summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/dialogs/dialogs.pri7
-rw-r--r--src/gui/dialogs/qdialog.cpp35
-rw-r--r--src/gui/dialogs/qfiledialog.cpp71
-rw-r--r--src/gui/dialogs/qfiledialog_embedded.ui (renamed from src/gui/dialogs/qfiledialog_wince.ui)0
-rw-r--r--src/gui/dialogs/qfiledialog_p.h59
-rw-r--r--src/gui/dialogs/qfileinfogatherer.cpp30
-rw-r--r--src/gui/dialogs/qfilesystemmodel.cpp35
-rw-r--r--src/gui/dialogs/qfscompleter_p.h82
-rw-r--r--src/gui/dialogs/qmessagebox.cpp2
-rw-r--r--src/gui/dialogs/qpagesetupdialog_win.cpp2
-rw-r--r--src/gui/dialogs/qprintdialog_unix.cpp4
-rw-r--r--src/gui/dialogs/qprintpreviewdialog.cpp13
-rw-r--r--src/gui/dialogs/qprintpreviewdialog.h2
-rw-r--r--src/gui/dialogs/qwizard.cpp2
-rw-r--r--src/gui/egl/qegl_p.h2
-rw-r--r--src/gui/embedded/qsoundqss_qws.cpp36
-rw-r--r--src/gui/embedded/qwindowsystem_qws.cpp44
-rw-r--r--src/gui/embedded/qwscursor_qws.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp136
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h3
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h2
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem.cpp1
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem.h3
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.h2
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicssceneevent.cpp1
-rw-r--r--src/gui/graphicsview/qgraphicssceneevent.h3
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp17
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicswidget.h2
-rw-r--r--src/gui/gui.pro7
-rw-r--r--src/gui/image/image.pri3
-rw-r--r--src/gui/image/qimage.cpp17
-rw-r--r--src/gui/image/qimageiohandler.cpp1
-rw-r--r--src/gui/image/qimageiohandler.h3
-rw-r--r--src/gui/image/qpicture.cpp29
-rw-r--r--src/gui/image/qpicture.h4
-rw-r--r--src/gui/image/qpicture_p.h4
-rw-r--r--src/gui/image/qpixmap.cpp7
-rw-r--r--src/gui/image/qpixmap.h10
-rw-r--r--src/gui/image/qpixmap_s60.cpp233
-rw-r--r--src/gui/image/qpixmapcache.cpp11
-rw-r--r--src/gui/image/qpixmapdatafactory.cpp4
-rw-r--r--src/gui/inputmethod/inputmethod.pri5
-rw-r--r--src/gui/inputmethod/qcoefepinputcontext_p.h153
-rw-r--r--src/gui/inputmethod/qcoefepinputcontext_s60.cpp747
-rw-r--r--src/gui/inputmethod/qinputcontext.cpp50
-rw-r--r--src/gui/inputmethod/qinputcontext.h8
-rw-r--r--src/gui/inputmethod/qinputcontextfactory.cpp23
-rw-r--r--src/gui/inputmethod/qwininputcontext_win.cpp7
-rw-r--r--src/gui/inputmethod/qximinputcontext_x11.cpp2
-rw-r--r--src/gui/itemviews/qabstractitemview.cpp8
-rw-r--r--src/gui/itemviews/qabstractitemview_p.h2
-rw-r--r--src/gui/itemviews/qcolumnview_p.h2
-rw-r--r--src/gui/itemviews/qdirmodel.cpp17
-rw-r--r--src/gui/itemviews/qfileiconprovider.cpp1
-rw-r--r--src/gui/itemviews/qfileiconprovider.h5
-rw-r--r--src/gui/itemviews/qheaderview.cpp8
-rw-r--r--src/gui/itemviews/qitemdelegate.cpp2
-rw-r--r--src/gui/itemviews/qstandarditemmodel.cpp6
-rw-r--r--src/gui/itemviews/qstandarditemmodel.h2
-rw-r--r--src/gui/itemviews/qstyleditemdelegate.cpp2
-rw-r--r--src/gui/itemviews/qtreewidget.cpp2
-rw-r--r--src/gui/itemviews/qtreewidgetitemiterator.cpp3
-rw-r--r--src/gui/itemviews/qtreewidgetitemiterator.h3
-rw-r--r--src/gui/kernel/kernel.pri21
-rw-r--r--src/gui/kernel/qaction.cpp29
-rw-r--r--src/gui/kernel/qaction.h9
-rw-r--r--src/gui/kernel/qaction_p.h1
-rw-r--r--src/gui/kernel/qapplication.cpp122
-rw-r--r--src/gui/kernel/qapplication.h20
-rw-r--r--src/gui/kernel/qapplication_p.h14
-rw-r--r--src/gui/kernel/qapplication_qws.cpp17
-rw-r--r--src/gui/kernel/qapplication_s60.cpp1182
-rw-r--r--src/gui/kernel/qclipboard_s60.cpp277
-rw-r--r--src/gui/kernel/qcursor.cpp3
-rw-r--r--src/gui/kernel/qcursor_qws.cpp6
-rw-r--r--src/gui/kernel/qcursor_s60.cpp60
-rw-r--r--src/gui/kernel/qdesktopwidget_s60.cpp202
-rw-r--r--src/gui/kernel/qdnd_s60.cpp395
-rw-r--r--src/gui/kernel/qevent.cpp11
-rw-r--r--src/gui/kernel/qevent.h5
-rw-r--r--src/gui/kernel/qeventdispatcher_s60.cpp130
-rw-r--r--src/gui/kernel/qeventdispatcher_s60_p.h96
-rw-r--r--src/gui/kernel/qkeymapper_p.h8
-rw-r--r--src/gui/kernel/qkeymapper_s60.cpp247
-rw-r--r--src/gui/kernel/qkeysequence.cpp158
-rw-r--r--src/gui/kernel/qlayout.cpp14
-rw-r--r--src/gui/kernel/qshortcutmap.cpp5
-rw-r--r--src/gui/kernel/qshortcutmap_p.h3
-rw-r--r--src/gui/kernel/qsound.cpp3
-rw-r--r--src/gui/kernel/qsound_s60.cpp206
-rw-r--r--src/gui/kernel/qt_s60_p.h292
-rw-r--r--src/gui/kernel/qwidget.cpp236
-rw-r--r--src/gui/kernel/qwidget.h13
-rw-r--r--src/gui/kernel/qwidget_p.h24
-rw-r--r--src/gui/kernel/qwidget_qws.cpp3
-rw-r--r--src/gui/kernel/qwidget_s60.cpp1174
-rw-r--r--src/gui/kernel/qwindowdefs.h5
-rw-r--r--src/gui/kernel/symbian.pri3
-rw-r--r--src/gui/painting/painting.pri27
-rw-r--r--src/gui/painting/qbackingstore.cpp4
-rw-r--r--src/gui/painting/qblendfunctions_armv6_rvct.s223
-rw-r--r--src/gui/painting/qbrush.cpp113
-rw-r--r--src/gui/painting/qbrush.h6
-rw-r--r--src/gui/painting/qcolormap_s60.cpp108
-rw-r--r--src/gui/painting/qdrawhelper.cpp292
-rw-r--r--src/gui/painting/qdrawhelper_armv6_p.h81
-rw-r--r--src/gui/painting/qdrawhelper_armv6_rvct.inc496
-rw-r--r--src/gui/painting/qdrawhelper_armv6_rvct.s178
-rw-r--r--src/gui/painting/qdrawhelper_p.h95
-rw-r--r--src/gui/painting/qgraphicssystem.cpp4
-rw-r--r--src/gui/painting/qgraphicssystemfactory.cpp2
-rw-r--r--src/gui/painting/qgrayraster.c5
-rw-r--r--src/gui/painting/qpaintdevice_s60.cpp72
-rw-r--r--src/gui/painting/qpaintengine.cpp1
-rw-r--r--src/gui/painting/qpaintengine.h3
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp188
-rw-r--r--src/gui/painting/qpaintengineex.cpp6
-rw-r--r--src/gui/painting/qpaintengineex_p.h8
-rw-r--r--src/gui/painting/qpainter.cpp65
-rw-r--r--src/gui/painting/qpainter.h5
-rw-r--r--src/gui/painting/qpainter_p.h2
-rw-r--r--src/gui/painting/qpainterpath.cpp39
-rw-r--r--src/gui/painting/qpainterpath.h9
-rw-r--r--src/gui/painting/qpathclipper_p.h7
-rw-r--r--src/gui/painting/qprinter.cpp1
-rw-r--r--src/gui/painting/qprinter.h5
-rw-r--r--src/gui/painting/qprinterinfo.h3
-rw-r--r--src/gui/painting/qprinterinfo_mac.cpp32
-rw-r--r--src/gui/painting/qprinterinfo_unix.cpp33
-rw-r--r--src/gui/painting/qprinterinfo_win.cpp30
-rw-r--r--src/gui/painting/qrasterizer.cpp7
-rw-r--r--src/gui/painting/qregion.cpp160
-rw-r--r--src/gui/painting/qregion.h4
-rw-r--r--src/gui/painting/qregion_s60.cpp52
-rw-r--r--src/gui/painting/qtessellator.cpp3
-rw-r--r--src/gui/painting/qvectorpath_p.h6
-rw-r--r--src/gui/painting/qwindowsurface_raster.cpp8
-rw-r--r--src/gui/painting/qwindowsurface_raster_p.h2
-rw-r--r--src/gui/painting/qwindowsurface_s60.cpp234
-rw-r--r--src/gui/painting/qwindowsurface_s60_p.h95
-rw-r--r--src/gui/styles/qs60style.cpp2880
-rw-r--r--src/gui/styles/qs60style.h113
-rw-r--r--src/gui/styles/qs60style_p.h501
-rw-r--r--src/gui/styles/qs60style_s60.cpp1372
-rw-r--r--src/gui/styles/qs60style_simulated.cpp449
-rw-r--r--src/gui/styles/qstyle_p.h2
-rw-r--r--src/gui/styles/qstyle_s60_simulated.qrc6
-rw-r--r--src/gui/styles/qstylefactory.cpp12
-rw-r--r--src/gui/styles/qstylesheetstyle_default.cpp7
-rw-r--r--src/gui/styles/qwindowsstyle.cpp5
-rw-r--r--src/gui/styles/styles.pri16
-rw-r--r--src/gui/text/qabstractfontengine_p.h2
-rw-r--r--src/gui/text/qcssparser.cpp5
-rw-r--r--src/gui/text/qfont.cpp73
-rw-r--r--src/gui/text/qfont.h3
-rw-r--r--src/gui/text/qfont_s60.cpp94
-rw-r--r--src/gui/text/qfontdatabase.cpp222
-rw-r--r--src/gui/text/qfontdatabase.h3
-rw-r--r--src/gui/text/qfontdatabase_qws.cpp190
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp414
-rw-r--r--src/gui/text/qfontengine.cpp39
-rw-r--r--src/gui/text/qfontengine_ft.cpp84
-rw-r--r--src/gui/text/qfontengine_ft_p.h3
-rw-r--r--src/gui/text/qfontengine_p.h19
-rw-r--r--src/gui/text/qfontengine_qpf.cpp21
-rw-r--r--src/gui/text/qfontengine_qpf_p.h1
-rw-r--r--src/gui/text/qfontengine_s60.cpp324
-rw-r--r--src/gui/text/qfontengine_s60_p.h146
-rw-r--r--src/gui/text/qfontmetrics.cpp8
-rw-r--r--src/gui/text/qfragmentmap_p.h8
-rw-r--r--src/gui/text/qtextcontrol.cpp34
-rw-r--r--src/gui/text/qtextengine.cpp10
-rw-r--r--src/gui/text/qtextlayout.cpp2
-rw-r--r--src/gui/text/qtextoption.cpp10
-rw-r--r--src/gui/text/qtexttable.cpp15
-rw-r--r--src/gui/text/qzip.cpp10
-rw-r--r--src/gui/text/text.pri33
-rw-r--r--src/gui/util/qcompleter.cpp15
-rw-r--r--src/gui/util/qdesktopservices.cpp7
-rw-r--r--src/gui/util/qdesktopservices_s60.cpp410
-rw-r--r--src/gui/util/util.pri5
-rw-r--r--src/gui/widgets/qabstractscrollarea.cpp23
-rw-r--r--src/gui/widgets/qabstractscrollarea_p.h2
-rw-r--r--src/gui/widgets/qabstractslider.cpp3
-rw-r--r--src/gui/widgets/qabstractspinbox.cpp13
-rw-r--r--src/gui/widgets/qabstractspinbox.h2
-rw-r--r--src/gui/widgets/qactiontokeyeventmapper.cpp103
-rw-r--r--src/gui/widgets/qactiontokeyeventmapper_p.h81
-rw-r--r--src/gui/widgets/qcalendarwidget.cpp11
-rw-r--r--src/gui/widgets/qcombobox.cpp11
-rw-r--r--src/gui/widgets/qdatetimeedit.cpp19
-rw-r--r--src/gui/widgets/qlineedit.cpp72
-rw-r--r--src/gui/widgets/qlineedit_p.h4
-rw-r--r--src/gui/widgets/qmacnativewidget_mac.h2
-rw-r--r--src/gui/widgets/qmainwindow.cpp16
-rw-r--r--src/gui/widgets/qmenu.cpp39
-rw-r--r--src/gui/widgets/qmenu.h9
-rw-r--r--src/gui/widgets/qmenu_p.h42
-rw-r--r--src/gui/widgets/qmenu_symbian.cpp423
-rw-r--r--src/gui/widgets/qmenubar.cpp38
-rw-r--r--src/gui/widgets/qmenubar_p.h45
-rw-r--r--src/gui/widgets/qmenudata.h2
-rw-r--r--src/gui/widgets/qplaintextedit.cpp20
-rw-r--r--src/gui/widgets/qplaintextedit_p.h6
-rw-r--r--src/gui/widgets/qprintpreviewwidget.cpp13
-rw-r--r--src/gui/widgets/qprintpreviewwidget.h2
-rw-r--r--src/gui/widgets/qspinbox.cpp9
-rw-r--r--src/gui/widgets/qtextedit.cpp18
-rw-r--r--src/gui/widgets/qtextedit_p.h1
-rw-r--r--src/gui/widgets/widgets.pri12
212 files changed, 17220 insertions, 1095 deletions
diff --git a/src/gui/dialogs/dialogs.pri b/src/gui/dialogs/dialogs.pri
index f1ec858..b9fad41 100644
--- a/src/gui/dialogs/dialogs.pri
+++ b/src/gui/dialogs/dialogs.pri
@@ -7,6 +7,7 @@ HEADERS += \
dialogs/qabstractpagesetupdialog_p.h \
dialogs/qcolordialog.h \
dialogs/qcolordialog_p.h \
+ dialogs/qfscompleter_p.h \
dialogs/qdialog.h \
dialogs/qdialog_p.h \
dialogs/qerrormessage.h \
@@ -45,7 +46,7 @@ win32 {
!win32-borland:!wince*: LIBS += -lshell32 # the filedialog needs this library
}
-!mac:!embedded:unix {
+!mac:!embedded:!symbian:unix {
HEADERS += dialogs/qpagesetupdialog_unix_p.h
SOURCES += dialogs/qprintdialog_unix.cpp \
dialogs/qpagesetupdialog_unix.cpp
@@ -70,7 +71,7 @@ embedded {
}
}
-wince*: FORMS += dialogs/qfiledialog_wince.ui
+wince*|symbian: FORMS += dialogs/qfiledialog_embedded.ui
else: FORMS += dialogs/qfiledialog.ui
INCLUDEPATH += $$PWD
@@ -94,4 +95,4 @@ SOURCES += \
FORMS += dialogs/qpagesetupwidget.ui
RESOURCES += dialogs/qprintdialog.qrc
-RESOURCES += dialogs/qmessagebox.qrc \ No newline at end of file
+RESOURCES += dialogs/qmessagebox.qrc
diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp
index bb6c6d6..3cb35bf 100644
--- a/src/gui/dialogs/qdialog.cpp
+++ b/src/gui/dialogs/qdialog.cpp
@@ -64,8 +64,10 @@ extern bool qt_wince_is_mobile(); //defined in qguifunctions_wce.cpp
extern bool qt_wince_is_smartphone(); //is defined in qguifunctions_wce.cpp
#elif defined(Q_WS_X11)
# include "../kernel/qt_x11_p.h"
+#elif defined(Q_OS_SYMBIAN)
+# include "qfiledialog.h"
+# include "qmenubar.h"
#endif
-
#ifndef SPI_GETSNAPTODEFBUTTON
# define SPI_GETSNAPTODEFBUTTON 95
#endif
@@ -292,9 +294,13 @@ QDialog::QDialog(QDialogPrivate &dd, QWidget *parent, Qt::WindowFlags f)
QDialog::~QDialog()
{
- // Need to hide() here, as our (to-be) overridden hide()
- // will not be called in ~QWidget.
- hide();
+ QT_TRY {
+ // Need to hide() here, as our (to-be) overridden hide()
+ // will not be called in ~QWidget.
+ hide();
+ } QT_CATCH(...) {
+ // we're in the destructor - just swallow the exception
+ }
}
/*!
@@ -486,7 +492,19 @@ int QDialog::exec()
#endif //QT_NO_MENUBAR
#endif //Q_WS_WINCE_WM
- show();
+#ifdef Q_OS_SYMBIAN
+#ifndef QT_NO_MENUBAR
+ QMenuBar *menuBar = 0;
+ if (!findChild<QMenuBar *>())
+ menuBar = new QMenuBar(this);
+#endif
+
+ if (qobject_cast<QFileDialog *>(this))
+ showFullScreen();
+ else
+#endif // Q_OS_SYMBIAN
+
+ show();
#ifdef Q_WS_MAC
d->mac_nativeDialogModalHelp();
@@ -511,6 +529,13 @@ int QDialog::exec()
delete menuBar;
#endif //QT_NO_MENUBAR
#endif //Q_WS_WINCE_WM
+#ifdef Q_OS_SYMBIAN
+#ifndef QT_NO_MENUBAR
+ else if (menuBar)
+ delete menuBar;
+#endif //QT_NO_MENUBAR
+#endif //Q_OS_SYMBIAN
+
return res;
}
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp
index 8b4e1b1..6198661 100644
--- a/src/gui/dialogs/qfiledialog.cpp
+++ b/src/gui/dialogs/qfiledialog.cpp
@@ -58,12 +58,15 @@
#include <qdebug.h>
#include <qapplication.h>
#include <qstylepainter.h>
-#ifndef Q_WS_WINCE
+#if !defined(Q_WS_WINCE) && !defined(Q_OS_SYMBIAN)
#include "ui_qfiledialog.h"
#else
-#include "ui_qfiledialog_wince.h"
+#define Q_EMBEDDED_SMALLSCREEN
+#include "ui_qfiledialog_embedded.h"
+#if defined(Q_OS_WINCE)
extern bool qt_priv_ptr_valid;
#endif
+#endif
QT_BEGIN_NAMESPACE
@@ -358,7 +361,6 @@ QFileDialog::~QFileDialog()
settings.beginGroup(QLatin1String("Qt"));
settings.setValue(QLatin1String("filedialog"), saveState());
#endif
- delete d->qFileDialogUi;
d->deleteNativeDialog_sys();
}
@@ -490,6 +492,38 @@ void QFileDialog::changeEvent(QEvent *e)
QDialog::changeEvent(e);
}
+QFileDialogPrivate::QFileDialogPrivate()
+ :
+#ifndef QT_NO_PROXYMODEL
+ proxyModel(0),
+#endif
+ model(0),
+ fileMode(QFileDialog::AnyFile),
+ acceptMode(QFileDialog::AcceptOpen),
+ currentHistoryLocation(-1),
+ renameAction(0),
+ deleteAction(0),
+ showHiddenAction(0),
+ useDefaultCaption(true),
+ defaultFileTypes(true),
+ fileNameLabelExplicitlySat(false),
+ nativeDialogInUse(false),
+#ifdef Q_WS_MAC
+ mDelegate(0),
+#ifndef QT_MAC_USE_COCOA
+ mDialog(0),
+ mDialogStarted(false),
+ mDialogClosed(true),
+#endif
+#endif
+ qFileDialogUi(0)
+{
+}
+
+QFileDialogPrivate::~QFileDialogPrivate()
+{
+}
+
void QFileDialogPrivate::retranslateWindowTitle()
{
Q_Q(QFileDialog);
@@ -2068,7 +2102,7 @@ void QFileDialogPrivate::init(const QString &directory, const QString &nameFilte
q->restoreState(settings.value(QLatin1String("filedialog")).toByteArray());
#endif
-#ifdef Q_WS_WINCE
+#if defined(Q_EMBEDDED_SMALLSCREEN)
qFileDialogUi->lookInLabel->setVisible(false);
qFileDialogUi->fileNameLabel->setVisible(false);
qFileDialogUi->fileTypeLabel->setVisible(false);
@@ -2108,7 +2142,7 @@ void QFileDialogPrivate::createWidgets()
q, SLOT(_q_rowsInserted(const QModelIndex &)));
model->setReadOnly(false);
- qFileDialogUi = new Ui_QFileDialog();
+ qFileDialogUi.reset(new Ui_QFileDialog());
qFileDialogUi->setupUi(q);
QList<QUrl> initialBookmarks;
@@ -2134,7 +2168,7 @@ void QFileDialogPrivate::createWidgets()
qFileDialogUi->fileNameLabel->setBuddy(qFileDialogUi->fileNameEdit);
#endif
#ifndef QT_NO_COMPLETER
- completer = new QFSCompletor(model, q);
+ completer = new QFSCompleter(model, q);
qFileDialogUi->fileNameEdit->setCompleter(completer);
QObject::connect(qFileDialogUi->fileNameEdit, SIGNAL(textChanged(QString)),
q, SLOT(_q_autoCompleteFileName(QString)));
@@ -2192,9 +2226,9 @@ void QFileDialogPrivate::createWidgets()
treeHeader->addAction(showHeader);
}
- QItemSelectionModel *selModel = qFileDialogUi->treeView->selectionModel();
+ QScopedPointer<QItemSelectionModel> selModel(qFileDialogUi->treeView->selectionModel());
qFileDialogUi->treeView->setSelectionModel(qFileDialogUi->listView->selectionModel());
- delete selModel;
+
QObject::connect(qFileDialogUi->treeView, SIGNAL(activated(QModelIndex)),
q, SLOT(_q_enterDirectory(QModelIndex)));
QObject::connect(qFileDialogUi->treeView, SIGNAL(customContextMenuRequested(QPoint)),
@@ -2276,9 +2310,9 @@ void QFileDialog::setProxyModel(QAbstractProxyModel *proxyModel)
connect(d->model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
this, SLOT(_q_rowsInserted(const QModelIndex &)));
}
- QItemSelectionModel *selModel = d->qFileDialogUi->treeView->selectionModel();
+ QScopedPointer<QItemSelectionModel> selModel(d->qFileDialogUi->treeView->selectionModel());
d->qFileDialogUi->treeView->setSelectionModel(d->qFileDialogUi->listView->selectionModel());
- delete selModel;
+
d->setRootIndex(idx);
// reconnect selection
@@ -3159,7 +3193,7 @@ void QFileDialogLineEdit::keyPressEvent(QKeyEvent *e)
#ifndef QT_NO_COMPLETER
-QString QFSCompletor::pathFromIndex(const QModelIndex &index) const
+QString QFSCompleter::pathFromIndex(const QModelIndex &index) const
{
const QFileSystemModel *dirModel;
if (proxyModel)
@@ -3174,14 +3208,17 @@ QString QFSCompletor::pathFromIndex(const QModelIndex &index) const
return index.data(QFileSystemModel::FilePathRole).toString();
}
-QStringList QFSCompletor::splitPath(const QString &path) const
+QStringList QFSCompleter::splitPath(const QString &path) const
{
if (path.isEmpty())
return QStringList(completionPrefix());
QString pathCopy = QDir::toNativeSeparators(path);
QString sep = QDir::separator();
-#ifdef Q_OS_WIN
+#if defined(Q_OS_SYMBIAN)
+ if (pathCopy == QLatin1String("\\"))
+ return QStringList(pathCopy);
+#elif defined(Q_OS_WIN)
if (pathCopy == QLatin1String("\\") || pathCopy == QLatin1String("\\\\"))
return QStringList(pathCopy);
QString doubleSlash(QLatin1String("\\\\"));
@@ -3193,7 +3230,11 @@ QStringList QFSCompletor::splitPath(const QString &path) const
QRegExp re(QLatin1Char('[') + QRegExp::escape(sep) + QLatin1Char(']'));
-#ifdef Q_OS_WIN
+#if defined(Q_OS_SYMBIAN)
+ QStringList parts = pathCopy.split(re, QString::SkipEmptyParts);
+ if (pathCopy.endsWith(sep))
+ parts.append(QString());
+#elif defined(Q_OS_WIN)
QStringList parts = pathCopy.split(re, QString::SkipEmptyParts);
if (!doubleSlash.isEmpty() && !parts.isEmpty())
parts[0].prepend(doubleSlash);
@@ -3205,7 +3246,7 @@ QStringList QFSCompletor::splitPath(const QString &path) const
parts[0] = sep[0];
#endif
-#ifdef Q_OS_WIN
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
bool startsFromRoot = !parts.isEmpty() && parts[0].endsWith(QLatin1Char(':'));
#else
bool startsFromRoot = path[0] == sep[0];
diff --git a/src/gui/dialogs/qfiledialog_wince.ui b/src/gui/dialogs/qfiledialog_embedded.ui
index 3f15458..3f15458 100644
--- a/src/gui/dialogs/qfiledialog_wince.ui
+++ b/src/gui/dialogs/qfiledialog_embedded.ui
diff --git a/src/gui/dialogs/qfiledialog_p.h b/src/gui/dialogs/qfiledialog_p.h
index 4c599cc..2da2b92 100644
--- a/src/gui/dialogs/qfiledialog_p.h
+++ b/src/gui/dialogs/qfiledialog_p.h
@@ -75,6 +75,7 @@
#include <qpointer.h>
#include <qdebug.h>
#include "qsidebar_p.h"
+#include "qfscompleter_p.h"
#if defined (Q_OS_UNIX)
#include <unistd.h>
@@ -90,25 +91,6 @@ class QCompleter;
class QHBoxLayout;
class Ui_QFileDialog;
-#ifndef QT_NO_COMPLETER
-/*!
- QCompleter that can deal with QFileSystemModel
- */
-class QFSCompletor : public QCompleter {
-public:
- QFSCompletor(QFileSystemModel *model, QObject *parent = 0) : QCompleter(model, parent), proxyModel(0), sourceModel(model)
- {
-#ifdef Q_OS_WIN
- setCaseSensitivity(Qt::CaseInsensitive);
-#endif
- }
- QString pathFromIndex(const QModelIndex &index) const;
- QStringList splitPath(const QString& path) const;
-
- QAbstractProxyModel *proxyModel;
- QFileSystemModel *sourceModel;
-};
-#endif // QT_NO_COMPLETER
struct QFileDialogArgs
{
@@ -130,31 +112,7 @@ class Q_AUTOTEST_EXPORT QFileDialogPrivate : public QDialogPrivate
Q_DECLARE_PUBLIC(QFileDialog)
public:
- QFileDialogPrivate() :
-#ifndef QT_NO_PROXYMODEL
- proxyModel(0),
-#endif
- model(0),
- fileMode(QFileDialog::AnyFile),
- acceptMode(QFileDialog::AcceptOpen),
- currentHistoryLocation(-1),
- renameAction(0),
- deleteAction(0),
- showHiddenAction(0),
- useDefaultCaption(true),
- defaultFileTypes(true),
- fileNameLabelExplicitlySat(false),
- nativeDialogInUse(false),
-#ifdef Q_WS_MAC
- mDelegate(0),
-#ifndef QT_MAC_USE_COCOA
- mDialog(0),
- mDialogStarted(false),
- mDialogClosed(true),
-#endif
-#endif
- qFileDialogUi(0)
- {}
+ QFileDialogPrivate();
void createToolButtons();
void createMenuActions();
@@ -222,7 +180,7 @@ public:
static inline QString toInternal(const QString &path)
{
-#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX)
+#if defined(Q_FS_FAT) || defined(Q_OS_OS2EMX) || defined(Q_OS_SYMBIAN)
QString n(path);
for (int i = 0; i < (int)n.length(); ++i)
if (n[i] == QLatin1Char('\\')) n[i] = QLatin1Char('/');
@@ -275,7 +233,7 @@ public:
QFileSystemModel *model;
#ifndef QT_NO_COMPLETER
- QFSCompletor *completer;
+ QFSCompleter *completer;
#endif //QT_NO_COMPLETER
QFileDialog::FileMode fileMode;
@@ -296,7 +254,7 @@ public:
bool defaultFileTypes;
bool fileNameLabelExplicitlySat;
QStringList nameFilters;
-
+
// Members for using native dialogs:
bool nativeDialogInUse;
// setVisible_sys returns true if it ends up showing a native
@@ -358,7 +316,7 @@ public:
void mac_nativeDialogModalHelp();
#endif
- Ui_QFileDialog *qFileDialogUi;
+ QScopedPointer<Ui_QFileDialog> qFileDialogUi;
QString acceptLabel;
@@ -367,6 +325,11 @@ public:
QByteArray signalToDisconnectOnClose;
QFileDialog::Options opts;
+
+ ~QFileDialogPrivate();
+
+private:
+ Q_DISABLE_COPY(QFileDialogPrivate)
};
class QFileDialogLineEdit : public QLineEdit
diff --git a/src/gui/dialogs/qfileinfogatherer.cpp b/src/gui/dialogs/qfileinfogatherer.cpp
index 887eb71..4d9a008 100644
--- a/src/gui/dialogs/qfileinfogatherer.cpp
+++ b/src/gui/dialogs/qfileinfogatherer.cpp
@@ -83,10 +83,10 @@ QFileInfoGatherer::QFileInfoGatherer(QObject *parent)
*/
QFileInfoGatherer::~QFileInfoGatherer()
{
- mutex.lock();
+ QMutexLocker locker(&mutex);
abort = true;
condition.wakeOne();
- mutex.unlock();
+ locker.unlock();
wait();
}
@@ -94,9 +94,8 @@ void QFileInfoGatherer::setResolveSymlinks(bool enable)
{
Q_UNUSED(enable);
#ifdef Q_OS_WIN
- mutex.lock();
+ QMutexLocker locker(&mutex);
m_resolveSymlinks = enable;
- mutex.unlock();
#endif
}
@@ -107,9 +106,8 @@ bool QFileInfoGatherer::resolveSymlinks() const
void QFileInfoGatherer::setIconProvider(QFileIconProvider *provider)
{
- mutex.lock();
+ QMutexLocker locker(&mutex);
m_iconProvider = provider;
- mutex.unlock();
}
QFileIconProvider *QFileInfoGatherer::iconProvider() const
@@ -124,12 +122,11 @@ QFileIconProvider *QFileInfoGatherer::iconProvider() const
*/
void QFileInfoGatherer::fetchExtendedInformation(const QString &path, const QStringList &files)
{
- mutex.lock();
+ QMutexLocker locker(&mutex);
// See if we already have this dir/file in our que
int loc = this->path.lastIndexOf(path);
while (loc > 0) {
if (this->files.at(loc) == files) {
- mutex.unlock();
return;
}
loc = this->path.lastIndexOf(path, loc - 1);
@@ -137,7 +134,6 @@ void QFileInfoGatherer::fetchExtendedInformation(const QString &path, const QStr
this->path.push(path);
this->files.push(files);
condition.wakeAll();
- mutex.unlock();
}
/*!
@@ -160,10 +156,9 @@ void QFileInfoGatherer::updateFile(const QString &filePath)
void QFileInfoGatherer::clear()
{
#ifndef QT_NO_FILESYSTEMWATCHER
- mutex.lock();
+ QMutexLocker locker(&mutex);
watcher->removePaths(watcher->files());
watcher->removePaths(watcher->directories());
- mutex.unlock();
#endif
}
@@ -175,9 +170,8 @@ void QFileInfoGatherer::clear()
void QFileInfoGatherer::removePath(const QString &path)
{
#ifndef QT_NO_FILESYSTEMWATCHER
- mutex.lock();
+ QMutexLocker locker(&mutex);
watcher->removePath(path);
- mutex.unlock();
#endif
}
@@ -198,9 +192,8 @@ void QFileInfoGatherer::run()
{
forever {
bool updateFiles = false;
- mutex.lock();
+ QMutexLocker locker(&mutex);
if (abort) {
- mutex.unlock();
return;
}
if (this->path.isEmpty())
@@ -214,8 +207,9 @@ void QFileInfoGatherer::run()
this->files.pop_front();
updateFiles = true;
}
- mutex.unlock();
- if (updateFiles) getFileInfos(path, list);
+ locker.unlock();
+ if (updateFiles)
+ getFileInfos(path, list);
}
}
@@ -287,6 +281,8 @@ QString QFileInfoGatherer::translateDriveName(const QFileInfo &drive) const
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
if (driveName.startsWith(QLatin1Char('/'))) // UNC host
return drive.fileName();
+#endif
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
if (driveName.endsWith(QLatin1Char('/')))
driveName.chop(1);
#endif
diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp
index 5a5d845..283bda6 100644
--- a/src/gui/dialogs/qfilesystemmodel.cpp
+++ b/src/gui/dialogs/qfilesystemmodel.cpp
@@ -347,7 +347,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
// ### TODO can we use bool QAbstractFileEngine::caseSensitive() const?
QStringList pathElements = absolutePath.split(QLatin1Char('/'), QString::SkipEmptyParts);
if ((pathElements.isEmpty())
-#if !defined(Q_OS_WIN) || defined(Q_OS_WINCE)
+#if (!defined(Q_OS_WIN) || defined(Q_OS_WINCE)) && !defined(Q_OS_SYMBIAN)
&& QDir::fromNativeSeparators(longPath) != QLatin1String("/")
#endif
)
@@ -376,9 +376,21 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
r = translateVisibleLocation(rootNode, r);
index = q->index(r, 0, QModelIndex());
pathElements.pop_front();
- } else {
+ } else
+#endif
+
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
+ {
if (!pathElements.at(0).contains(QLatin1String(":")))
+#if defined(Q_CC_NOKIAX86)
+ {
+ // Workaround for bizarre compiler crash.
+ QString rootPath = QDir(longPath).rootPath();
+ pathElements.prepend(rootPath);
+ }
+#else
pathElements.prepend(QDir(longPath).rootPath());
+#endif
if (pathElements.at(0).endsWith(QLatin1Char('/')))
pathElements[0].chop(1);
}
@@ -1588,12 +1600,25 @@ void QFileSystemModelPrivate::_q_directoryChanged(const QString &directory, cons
if (parentNode->children.count() == 0)
return;
QStringList toRemove;
+#if defined(Q_OS_SYMBIAN)
+ // Filename case must be exact in qBinaryFind below, so create a list of all lowercase names.
+ QStringList newFiles;
+ for(int i = 0; i < files.size(); i++) {
+ newFiles << files.at(i).toLower();
+ }
+#else
QStringList newFiles = files;
+#endif
qSort(newFiles.begin(), newFiles.end());
QHash<QString, QFileSystemNode*>::const_iterator i = parentNode->children.constBegin();
while (i != parentNode->children.constEnd()) {
QStringList::iterator iterator;
- iterator = qBinaryFind(newFiles.begin(), newFiles.end(), i.value()->fileName);
+ iterator = qBinaryFind(newFiles.begin(), newFiles.end(),
+#if defined(Q_OS_SYMBIAN)
+ i.value()->fileName.toLower());
+#else
+ i.value()->fileName);
+#endif
if (iterator == newFiles.end()) {
toRemove.append(i.value()->fileName);
}
@@ -1916,8 +1941,8 @@ bool QFileSystemModelPrivate::passNameFilters(const QFileSystemNode *node) const
return true;
}
+QT_END_NAMESPACE
+
#include "moc_qfilesystemmodel.cpp"
#endif // QT_NO_FILESYSTEMMODEL
-
-QT_END_NAMESPACE
diff --git a/src/gui/dialogs/qfscompleter_p.h b/src/gui/dialogs/qfscompleter_p.h
new file mode 100644
index 0000000..c65eeea
--- /dev/null
+++ b/src/gui/dialogs/qfscompleter_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOMPLETOR_P_H
+#define QCOMPLETOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qcompleter.h"
+#include <QtGui/qfilesystemmodel.h>
+QT_BEGIN_NAMESPACE
+#ifndef QT_NO_COMPLETER
+
+/*!
+ QCompleter that can deal with QFileSystemModel
+ */
+class QFSCompleter : public QCompleter {
+public:
+ QFSCompleter(QFileSystemModel *model, QObject *parent = 0)
+ : QCompleter(model, parent), proxyModel(0), sourceModel(model)
+ {
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ setCaseSensitivity(Qt::CaseInsensitive);
+#endif
+ }
+ QString pathFromIndex(const QModelIndex &index) const;
+ QStringList splitPath(const QString& path) const;
+
+ QAbstractProxyModel *proxyModel;
+ QFileSystemModel *sourceModel;
+};
+#endif // QT_NO_COMPLETER
+QT_END_NAMESPACE
+#endif // QCOMPLETOR_P_H
+
diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp
index 31f73b9..8a79759 100644
--- a/src/gui/dialogs/qmessagebox.cpp
+++ b/src/gui/dialogs/qmessagebox.cpp
@@ -269,7 +269,7 @@ void QMessageBoxPrivate::updateSize()
return;
QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size();
-#if defined(Q_WS_QWS) || defined(Q_WS_WINCE)
+#if defined(Q_WS_QWS) || defined(Q_WS_WINCE) || defined(Q_OS_SYMBIAN)
// the width of the screen, less the window border.
int hardLimit = screenSize.width() - (q->frameGeometry().width() - q->geometry().width());
#else
diff --git a/src/gui/dialogs/qpagesetupdialog_win.cpp b/src/gui/dialogs/qpagesetupdialog_win.cpp
index 3f2fb34..5f49aee 100644
--- a/src/gui/dialogs/qpagesetupdialog_win.cpp
+++ b/src/gui/dialogs/qpagesetupdialog_win.cpp
@@ -71,7 +71,7 @@ int QPageSetupDialog::exec()
return Rejected;
QWin32PrintEngine *engine = static_cast<QWin32PrintEngine*>(d->printer->paintEngine());
- QWin32PrintEnginePrivate *ep = static_cast<QWin32PrintEnginePrivate *>(engine->d_ptr);
+ QWin32PrintEnginePrivate *ep = static_cast<QWin32PrintEnginePrivate *>(engine->d_ptr.data());
PAGESETUPDLG psd;
memset(&psd, 0, sizeof(PAGESETUPDLG));
diff --git a/src/gui/dialogs/qprintdialog_unix.cpp b/src/gui/dialogs/qprintdialog_unix.cpp
index 5d64a67..3fb132d 100644
--- a/src/gui/dialogs/qprintdialog_unix.cpp
+++ b/src/gui/dialogs/qprintdialog_unix.cpp
@@ -44,7 +44,6 @@
#ifndef QT_NO_PRINTDIALOG
#include "private/qabstractprintdialog_p.h"
-#include "qfiledialog_p.h"
#include <QtGui/qmessagebox.h>
#include "qprintdialog.h"
#include "qfiledialog.h"
@@ -55,6 +54,7 @@
#include <QtGui/qdialogbuttonbox.h>
+#include "qfscompleter_p.h"
#include "ui_qprintpropertieswidget.h"
#include "ui_qprintsettingsoutput.h"
#include "ui_qprintwidget.h"
@@ -696,7 +696,7 @@ QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p)
QFileSystemModel *fsm = new QFileSystemModel(widget.filename);
fsm->setRootPath(QDir::homePath());
#if !defined(QT_NO_COMPLETER) && !defined(QT_NO_FILEDIALOG)
- widget.filename->setCompleter(new QFSCompletor(fsm, widget.filename));
+ widget.filename->setCompleter(new QFSCompleter(fsm, widget.filename));
#endif
#endif
_q_printerChanged(currentPrinterIndex);
diff --git a/src/gui/dialogs/qprintpreviewdialog.cpp b/src/gui/dialogs/qprintpreviewdialog.cpp
index eaae287..ef64056 100644
--- a/src/gui/dialogs/qprintpreviewdialog.cpp
+++ b/src/gui/dialogs/qprintpreviewdialog.cpp
@@ -42,6 +42,7 @@
#include "qprintpreviewdialog.h"
#include "qprintpreviewwidget.h"
#include <private/qprinter_p.h>
+#include "private/qdialog_p.h"
#include <QtGui/qaction.h>
#include <QtGui/qboxlayout.h>
@@ -138,12 +139,12 @@ private:
};
} // anonymous namespace
-class QPrintPreviewDialogPrivate
+class QPrintPreviewDialogPrivate : public QDialogPrivate
{
Q_DECLARE_PUBLIC(QPrintPreviewDialog)
public:
- QPrintPreviewDialogPrivate(QPrintPreviewDialog *q)
- : q_ptr(q), printDialog(0), ownPrinter(false),
+ QPrintPreviewDialogPrivate()
+ : printDialog(0), ownPrinter(false),
initialized(false) {}
// private slots
@@ -168,7 +169,6 @@ public:
void updatePageNumLabel();
void updateZoomFactor();
- QPrintPreviewDialog *q_ptr;
QPrintDialog *printDialog;
QPrintPreviewWidget *preview;
QPrinter *printer;
@@ -662,7 +662,7 @@ void QPrintPreviewDialogPrivate::_q_zoomFactorChanged()
\sa QWidget::setWindowFlags()
*/
QPrintPreviewDialog::QPrintPreviewDialog(QPrinter* printer, QWidget *parent, Qt::WindowFlags flags)
- : QDialog(parent, flags), d_ptr(new QPrintPreviewDialogPrivate(this))
+ : QDialog(*new QPrintPreviewDialogPrivate, parent, flags)
{
Q_D(QPrintPreviewDialog);
d->init(printer);
@@ -676,7 +676,7 @@ QPrintPreviewDialog::QPrintPreviewDialog(QPrinter* printer, QWidget *parent, Qt:
system default printer.
*/
QPrintPreviewDialog::QPrintPreviewDialog(QWidget *parent, Qt::WindowFlags f)
- : QDialog(parent, f), d_ptr(new QPrintPreviewDialogPrivate(this))
+ : QDialog(*new QPrintPreviewDialogPrivate, parent, f)
{
Q_D(QPrintPreviewDialog);
d->init();
@@ -691,7 +691,6 @@ QPrintPreviewDialog::~QPrintPreviewDialog()
if (d->ownPrinter)
delete d->printer;
delete d->printDialog;
- delete d_ptr;
}
/*!
diff --git a/src/gui/dialogs/qprintpreviewdialog.h b/src/gui/dialogs/qprintpreviewdialog.h
index 6c4c188..85ed517 100644
--- a/src/gui/dialogs/qprintpreviewdialog.h
+++ b/src/gui/dialogs/qprintpreviewdialog.h
@@ -94,7 +94,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_previewChanged())
Q_PRIVATE_SLOT(d_func(), void _q_zoomFactorChanged())
- QPrintPreviewDialogPrivate *d_ptr;
+ void *dummy; // ### Qt 5 - remove me
};
diff --git a/src/gui/dialogs/qwizard.cpp b/src/gui/dialogs/qwizard.cpp
index a97aedd..345c0f7 100644
--- a/src/gui/dialogs/qwizard.cpp
+++ b/src/gui/dialogs/qwizard.cpp
@@ -83,7 +83,7 @@ const int ModernHeaderTopMargin = 2;
const int ClassicHMargin = 4;
const int MacButtonTopMargin = 13;
const int MacLayoutLeftMargin = 20;
-const int MacLayoutTopMargin = 14;
+//const int MacLayoutTopMargin = 14; // Unused. Save some space and avoid warning.
const int MacLayoutRightMargin = 20;
const int MacLayoutBottomMargin = 17;
diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h
index ddf7d27..b457552 100644
--- a/src/gui/egl/qegl_p.h
+++ b/src/gui/egl/qegl_p.h
@@ -56,7 +56,7 @@
#include <QtCore/qsize.h>
#include <QtGui/qimage.h>
-#include "qeglproperties_p.h"
+#include <private/qeglproperties_p.h>
QT_BEGIN_INCLUDE_NAMESPACE
diff --git a/src/gui/embedded/qsoundqss_qws.cpp b/src/gui/embedded/qsoundqss_qws.cpp
index a45d0fe..e239e14 100644
--- a/src/gui/embedded/qsoundqss_qws.cpp
+++ b/src/gui/embedded/qsoundqss_qws.cpp
@@ -1037,24 +1037,28 @@ void QWSSoundServerPrivate::stopFile(int wid, int sid)
void QWSSoundServerPrivate::stopAll(int wid)
{
QWSSoundServerProvider *bucket;
- QList<QWSSoundServerProvider*>::Iterator it = active.begin();
- while (it != active.end()) {
- bucket = *it;
- if (bucket->groupId() == wid) {
- it = active.erase(it);
- delete bucket;
- } else {
- ++it;
+ if (!active.isEmpty()) {
+ QList<QWSSoundServerProvider*>::Iterator it = active.begin();
+ while (it != active.end()) {
+ bucket = *it;
+ if (bucket->groupId() == wid) {
+ it = active.erase(it);
+ delete bucket;
+ } else {
+ ++it;
+ }
}
}
- it = inactive.begin();
- while (it != inactive.end()) {
- bucket = *it;
- if (bucket->groupId() == wid) {
- it = inactive.erase(it);
- delete bucket;
- } else {
- ++it;
+ if (!inactive.isEmpty()) {
+ QList<QWSSoundServerProvider*>::Iterator it = inactive.begin();
+ while (it != inactive.end()) {
+ bucket = *it;
+ if (bucket->groupId() == wid) {
+ it = inactive.erase(it);
+ delete bucket;
+ } else {
+ ++it;
+ }
}
}
}
diff --git a/src/gui/embedded/qwindowsystem_qws.cpp b/src/gui/embedded/qwindowsystem_qws.cpp
index 0580198..a521319 100644
--- a/src/gui/embedded/qwindowsystem_qws.cpp
+++ b/src/gui/embedded/qwindowsystem_qws.cpp
@@ -1304,7 +1304,13 @@ QWSServer::QWSServer(int flags, QObject *parent) :
QObject(*new QWSServerPrivate, parent)
{
Q_D(QWSServer);
- d->initServer(flags);
+ QT_TRY {
+ d->initServer(flags);
+ } QT_CATCH(...) {
+ qwsServer = 0;
+ qwsServerPrivate = 0;
+ QT_RETHROW;
+ }
}
#ifdef QT3_SUPPORT
@@ -1750,21 +1756,23 @@ void QWSServerPrivate::cleanupFonts(bool force)
#if defined(QWS_DEBUG_FONTCLEANUP)
qDebug() << "cleanupFonts()";
#endif
- QMap<QByteArray, int>::Iterator it = fontReferenceCount.begin();
- while (it != fontReferenceCount.end()) {
- if (it.value() && !force) {
- ++it;
- continue;
- }
+ if (!fontReferenceCount.isEmpty()) {
+ QMap<QByteArray, int>::Iterator it = fontReferenceCount.begin();
+ while (it != fontReferenceCount.end()) {
+ if (it.value() && !force) {
+ ++it;
+ continue;
+ }
- const QByteArray &fontName = it.key();
+ const QByteArray &fontName = it.key();
#if defined(QWS_DEBUG_FONTCLEANUP)
- qDebug() << "removing unused font file" << fontName;
+ qDebug() << "removing unused font file" << fontName;
#endif
- QFile::remove(QFile::decodeName(fontName));
- sendFontRemovedEvent(fontName);
+ QFile::remove(QFile::decodeName(fontName));
+ sendFontRemovedEvent(fontName);
- it = fontReferenceCount.erase(it);
+ it = fontReferenceCount.erase(it);
+ }
}
if (crashedClientIds.isEmpty())
@@ -3966,7 +3974,8 @@ void QWSServerPrivate::openDisplay()
void QWSServerPrivate::closeDisplay()
{
- qt_screen->shutdownDevice();
+ if (qt_screen)
+ qt_screen->shutdownDevice();
}
/*!
@@ -4065,9 +4074,14 @@ void QWSServer::startup(int flags)
void QWSServer::closedown()
{
- unlink(qws_qtePipeFilename().toLatin1().constData());
- delete qwsServer;
+ QScopedPointer<QWSServer> server(qwsServer);
qwsServer = 0;
+ QT_TRY {
+ unlink(qws_qtePipeFilename().toLatin1().constData());
+ } QT_CATCH(const std::bad_alloc &) {
+ // ### TODO - what to do when we run out of memory
+ // when calling toLatin1?
+ }
}
void QWSServerPrivate::emergency_cleanup()
diff --git a/src/gui/embedded/qwscursor_qws.cpp b/src/gui/embedded/qwscursor_qws.cpp
index 1930944..e4474ac 100644
--- a/src/gui/embedded/qwscursor_qws.cpp
+++ b/src/gui/embedded/qwscursor_qws.cpp
@@ -531,7 +531,7 @@ void QWSCursor::set(const uchar *data, const uchar *mask,
cursor = QImage(width,height, QImage::Format_Indexed8);
- if (!width || !height || !data || !mask)
+ if (!width || !height || !data || !mask || cursor.isNull())
return;
cursor.setNumColors(3);
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 0ff3685..7e155e1 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -571,6 +571,7 @@
#include <QtGui/qpixmapcache.h>
#include <QtGui/qstyleoption.h>
#include <QtGui/qevent.h>
+#include <QInputContext>
#include <private/qgraphicsitem_p.h>
#include <private/qgraphicswidget_p.h>
@@ -1021,7 +1022,7 @@ void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rec
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *child = children.at(i);
- QGraphicsItemPrivate *childd = child->d_ptr;
+ QGraphicsItemPrivate *childd = child->d_ptr.data();
bool hasPos = !childd->pos.isNull();
if (hasPos || childd->transformData) {
// COMBINE
@@ -1178,7 +1179,6 @@ QGraphicsItem::~QGraphicsItem()
d_ptr->setParentItemHelper(0);
delete d_ptr->transformData;
- delete d_ptr;
qt_dataStore()->data.remove(this);
}
@@ -3507,7 +3507,7 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co
QTransform x;
const QGraphicsItem *p = child;
do {
- p->d_ptr->combineTransformToParent(&x);
+ p->d_ptr.data()->combineTransformToParent(&x);
} while ((p = p->d_ptr->parent) && p != root);
if (parentOfOther)
return x.inverted(ok);
@@ -3867,7 +3867,7 @@ QRectF QGraphicsItem::sceneBoundingRect() const
const QGraphicsItem *parentItem = this;
const QGraphicsItemPrivate *itemd;
do {
- itemd = parentItem->d_ptr;
+ itemd = parentItem->d_ptr.data();
if (itemd->transformData)
break;
offset += itemd->pos;
@@ -8623,7 +8623,7 @@ class QGraphicsTextItemPrivate
{
public:
QGraphicsTextItemPrivate()
- : control(0), pageNumber(0), useDefaultImpl(false), tabChangesFocus(false)
+ : control(0), pageNumber(0), useDefaultImpl(false), tabChangesFocus(false), clickCausedFocus(0)
{ }
mutable QTextControl *control;
@@ -8644,6 +8644,8 @@ public:
bool useDefaultImpl;
bool tabChangesFocus;
+ uint clickCausedFocus : 1;
+
QGraphicsTextItem *qq;
};
@@ -8973,7 +8975,13 @@ void QGraphicsTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
dd->useDefaultImpl = false;
return;
}
+
dd->sendControlEvent(event);
+ Q_ASSERT(event->widget());
+ QInputContext *qic = event->widget()->inputContext();
+ if(qic) {
+ qic->update();
+ }
}
/*!
@@ -8985,7 +8993,13 @@ void QGraphicsTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
QGraphicsItem::mouseMoveEvent(event);
return;
}
+
dd->sendControlEvent(event);
+ Q_ASSERT(event->widget());
+ QInputContext *qic = event->widget()->inputContext();
+ if(qic) {
+ qic->update();
+ }
}
/*!
@@ -9005,7 +9019,23 @@ void QGraphicsTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
}
return;
}
+
+ if (event->button() == Qt::LeftButton && qApp->autoSipEnabled()
+ && (!dd->clickCausedFocus || qApp->autoSipOnMouseFocus())) {
+ QEvent _event(QEvent::RequestSoftwareInputPanel);
+ QApplication::sendEvent(event->widget(), &_event);
+ } else {
+ QGraphicsItem::mouseReleaseEvent(event);
+ }
+ dd->clickCausedFocus = 0;
+
dd->sendControlEvent(event);
+
+ Q_ASSERT(event->widget());
+ QInputContext *qic = event->widget()->inputContext();
+ if(qic) {
+ qic->update();
+ }
}
/*!
@@ -9024,6 +9054,11 @@ void QGraphicsTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
}
dd->sendControlEvent(event);
+ Q_ASSERT(event->widget());
+ QInputContext *qic = event->widget()->inputContext();
+ if(qic) {
+ qic->update();
+ }
}
/*!
@@ -9032,6 +9067,11 @@ void QGraphicsTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
void QGraphicsTextItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
dd->sendControlEvent(event);
+ Q_ASSERT(event->widget());
+ QInputContext *qic = event->widget()->inputContext();
+ if(qic) {
+ qic->update();
+ }
}
/*!
@@ -9040,6 +9080,18 @@ void QGraphicsTextItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
void QGraphicsTextItem::keyPressEvent(QKeyEvent *event)
{
dd->sendControlEvent(event);
+ QList<QGraphicsView *> views = scene()->views();
+ for (int i = 0; i < views.size(); ++i) {
+ QGraphicsView *view = views.at(i);
+ Q_ASSERT(view->viewport());
+ if(view->viewport()->hasFocus()) {
+ QInputContext *qic = view->viewport()->inputContext();
+ if(qic){
+ qic->update();
+ }
+ break;
+ }
+ }
}
/*!
@@ -9048,6 +9100,18 @@ void QGraphicsTextItem::keyPressEvent(QKeyEvent *event)
void QGraphicsTextItem::keyReleaseEvent(QKeyEvent *event)
{
dd->sendControlEvent(event);
+ QList<QGraphicsView *> views = scene()->views();
+ for (int i = 0; i < views.size(); ++i) {
+ QGraphicsView *view = views.at(i);
+ Q_ASSERT(view->viewport());
+ if(view->viewport()->hasFocus()) {
+ QInputContext *qic = view->viewport()->inputContext();
+ if(qic){
+ qic->update();
+ }
+ break;
+ }
+ }
}
/*!
@@ -9056,7 +9120,22 @@ void QGraphicsTextItem::keyReleaseEvent(QKeyEvent *event)
void QGraphicsTextItem::focusInEvent(QFocusEvent *event)
{
dd->sendControlEvent(event);
+ if (event->reason() == Qt::MouseFocusReason) {
+ dd->clickCausedFocus = 1;
+ }
update();
+ QList<QGraphicsView *> views = scene()->views();
+ for (int i = 0; i < views.size(); ++i) {
+ QGraphicsView *view = views.at(i);
+ Q_ASSERT(view->viewport());
+ if(view->viewport()->hasFocus()) {
+ QInputContext *qic = view->viewport()->inputContext();
+ if(qic){
+ qic->reset();
+ }
+ break;
+ }
+ }
}
/*!
@@ -9066,6 +9145,18 @@ void QGraphicsTextItem::focusOutEvent(QFocusEvent *event)
{
dd->sendControlEvent(event);
update();
+ QList<QGraphicsView *> views = scene()->views();
+ for (int i = 0; i < views.size(); ++i) {
+ QGraphicsView *view = views.at(i);
+ Q_ASSERT(view->viewport());
+ if(view->viewport()->hasFocus()) {
+ QInputContext *qic = view->viewport()->inputContext();
+ if(qic){
+ qic->reset();
+ }
+ break;
+ }
+ }
}
/*!
@@ -9074,6 +9165,11 @@ void QGraphicsTextItem::focusOutEvent(QFocusEvent *event)
void QGraphicsTextItem::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
dd->sendControlEvent(event);
+ Q_ASSERT(event->widget());
+ QInputContext *qic = event->widget()->inputContext();
+ if(qic) {
+ qic->update();
+ }
}
/*!
@@ -9082,6 +9178,11 @@ void QGraphicsTextItem::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
void QGraphicsTextItem::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
{
dd->sendControlEvent(event);
+ Q_ASSERT(event->widget());
+ QInputContext *qic = event->widget()->inputContext();
+ if(qic) {
+ qic->update();
+ }
}
/*!
@@ -9090,6 +9191,11 @@ void QGraphicsTextItem::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
void QGraphicsTextItem::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
dd->sendControlEvent(event);
+ Q_ASSERT(event->widget());
+ QInputContext *qic = event->widget()->inputContext();
+ if(qic) {
+ qic->update();
+ }
}
/*!
@@ -9098,6 +9204,11 @@ void QGraphicsTextItem::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
void QGraphicsTextItem::dropEvent(QGraphicsSceneDragDropEvent *event)
{
dd->sendControlEvent(event);
+ Q_ASSERT(event->widget());
+ QInputContext *qic = event->widget()->inputContext();
+ if(qic) {
+ qic->update();
+ }
}
/*!
@@ -9114,6 +9225,11 @@ void QGraphicsTextItem::inputMethodEvent(QInputMethodEvent *event)
void QGraphicsTextItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
dd->sendControlEvent(event);
+ Q_ASSERT(event->widget());
+ QInputContext *qic = event->widget()->inputContext();
+ if(qic) {
+ qic->update();
+ }
}
/*!
@@ -9122,6 +9238,11 @@ void QGraphicsTextItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
void QGraphicsTextItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
dd->sendControlEvent(event);
+ Q_ASSERT(event->widget());
+ QInputContext *qic = event->widget()->inputContext();
+ if(qic) {
+ qic->update();
+ }
}
/*!
@@ -9130,6 +9251,11 @@ void QGraphicsTextItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
void QGraphicsTextItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
dd->sendControlEvent(event);
+ Q_ASSERT(event->widget());
+ QInputContext *qic = event->widget()->inputContext();
+ if(qic) {
+ qic->update();
+ }
}
/*!
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 5c9297f..fef09f0 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -46,6 +46,7 @@
#include <QtCore/qobject.h>
#include <QtCore/qvariant.h>
#include <QtCore/qrect.h>
+#include <QtCore/qscopedpointer.h>
#include <QtGui/qpainterpath.h>
#include <QtGui/qpixmap.h>
@@ -430,7 +431,7 @@ protected:
protected:
QGraphicsItem(QGraphicsItemPrivate &dd,
QGraphicsItem *parent, QGraphicsScene *scene);
- QGraphicsItemPrivate *d_ptr;
+ QScopedPointer<QGraphicsItemPrivate> d_ptr;
void addToIndex();
void removeFromIndex();
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 1cf188e..3d9f8a6 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -56,7 +56,7 @@
#include "qgraphicsitem.h"
#include "qset.h"
#include "qpixmapcache.h"
-#include "qgraphicsview_p.h"
+#include <private/qgraphicsview_p.h>
#include <QtCore/qpoint.h>
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp
index e280162..acf591a 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem.cpp
+++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp
@@ -369,7 +369,6 @@ QGraphicsLayoutItem::~QGraphicsLayoutItem()
}
}
}
- delete d_ptr;
}
/*!
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.h b/src/gui/graphicsview/qgraphicslayoutitem.h
index 85a5f07..60f894f 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem.h
+++ b/src/gui/graphicsview/qgraphicslayoutitem.h
@@ -42,6 +42,7 @@
#ifndef QGRAPHICSLAYOUTITEM_H
#define QGRAPHICSLAYOUTITEM_H
+#include <QtCore/qscopedpointer.h>
#include <QtGui/qsizepolicy.h>
#include <QtGui/qevent.h>
@@ -112,7 +113,7 @@ protected:
QGraphicsLayoutItem(QGraphicsLayoutItemPrivate &dd);
virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const = 0;
- QGraphicsLayoutItemPrivate *d_ptr;
+ QScopedPointer<QGraphicsLayoutItemPrivate> d_ptr;
private:
QSizeF *effectiveSizeHints(const QSizeF &constraint) const;
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.h b/src/gui/graphicsview/qgraphicsproxywidget.h
index 01b5033..ee314b9 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.h
+++ b/src/gui/graphicsview/qgraphicsproxywidget.h
@@ -129,7 +129,7 @@ protected Q_SLOTS:
private:
Q_DISABLE_COPY(QGraphicsProxyWidget)
- Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QGraphicsProxyWidget)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsProxyWidget)
Q_PRIVATE_SLOT(d_func(), void _q_removeWidgetSlot())
friend class QWidget;
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 4796436..d721d0d 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -3959,7 +3959,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
const QStyleOptionGraphicsItem *option, QWidget *widget,
bool painterStateProtection)
{
- QGraphicsItemPrivate *itemd = item->d_ptr;
+ QGraphicsItemPrivate *itemd = item->d_ptr.data();
QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode);
// Render directly, using no cache.
diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp
index 53019f2..97e8e46 100644
--- a/src/gui/graphicsview/qgraphicssceneevent.cpp
+++ b/src/gui/graphicsview/qgraphicssceneevent.cpp
@@ -317,7 +317,6 @@ QGraphicsSceneEvent::QGraphicsSceneEvent(QGraphicsSceneEventPrivate &dd, Type ty
*/
QGraphicsSceneEvent::~QGraphicsSceneEvent()
{
- delete d_ptr;
}
/*!
diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h
index b38e757..ea17f9d 100644
--- a/src/gui/graphicsview/qgraphicssceneevent.h
+++ b/src/gui/graphicsview/qgraphicssceneevent.h
@@ -44,6 +44,7 @@
#include <QtCore/qcoreevent.h>
#include <QtCore/qpoint.h>
+#include <QtCore/qscopedpointer.h>
#include <QtCore/qrect.h>
#include <QtGui/qpolygon.h>
#include <QtCore/qset.h>
@@ -74,7 +75,7 @@ public:
protected:
QGraphicsSceneEvent(QGraphicsSceneEventPrivate &dd, Type type = None);
- QGraphicsSceneEventPrivate *d_ptr;
+ QScopedPointer<QGraphicsSceneEventPrivate> d_ptr;
Q_DECLARE_PRIVATE(QGraphicsSceneEvent)
};
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 53b044c..a3005ae 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -776,7 +776,7 @@ QRect QGraphicsViewPrivate::mapToViewRect(const QGraphicsItem *item, const QRect
const QGraphicsItem *parentItem = item;
const QGraphicsItemPrivate *itemd;
do {
- itemd = parentItem->d_ptr;
+ itemd = parentItem->d_ptr.data();
if (itemd->transformData)
break;
offset += itemd->pos;
@@ -1028,6 +1028,11 @@ QGraphicsView::QGraphicsView(QWidget *parent)
// using a simple reference count. The same goes for acceptDrops and mouse
// tracking.
setAttribute(Qt::WA_InputMethodEnabled);
+
+ // viewport part of the graphics view has to be enabled
+ // as well, because when events come this widget is asked
+ // for input context and so on
+ viewport()->setAttribute(Qt::WA_InputMethodEnabled);
}
/*!
@@ -1042,6 +1047,11 @@ QGraphicsView::QGraphicsView(QGraphicsScene *scene, QWidget *parent)
setAcceptDrops(true);
setBackgroundRole(QPalette::Base);
setAttribute(Qt::WA_InputMethodEnabled);
+
+ // viewport part of the graphics view has to be enabled
+ // as well, because when events come this widget is asked
+ // for input context and so on
+ viewport()->setAttribute(Qt::WA_InputMethodEnabled);
}
/*!
@@ -1054,6 +1064,11 @@ QGraphicsView::QGraphicsView(QGraphicsViewPrivate &dd, QWidget *parent)
setAcceptDrops(true);
setBackgroundRole(QPalette::Base);
setAttribute(Qt::WA_InputMethodEnabled);
+
+ // viewport part of the graphics view has to be enabled
+ // as well, because when events come this widget is asked
+ // for input context and so on
+ viewport()->setAttribute(Qt::WA_InputMethodEnabled);
}
/*!
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 86c0b48..922db04 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -333,7 +333,7 @@ void QGraphicsWidget::resize(const QSizeF &size)
void QGraphicsWidget::setGeometry(const QRectF &rect)
{
QGraphicsWidgetPrivate *wd = QGraphicsWidget::d_func();
- QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr;
+ QGraphicsLayoutItemPrivate *d = QGraphicsLayoutItem::d_ptr.data();
QRectF newGeom;
QPointF oldPos = d->geom.topLeft();
if (!wd->inSetPos) {
diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h
index b72ec9f..9047310 100644
--- a/src/gui/graphicsview/qgraphicswidget.h
+++ b/src/gui/graphicsview/qgraphicswidget.h
@@ -228,7 +228,7 @@ protected:
private:
Q_DISABLE_COPY(QGraphicsWidget)
- Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr, QGraphicsWidget)
+ Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QGraphicsWidget)
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
friend class QGraphicsView;
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index b77bfdc..fdf4808 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -4,7 +4,7 @@ QT = core
DEFINES += QT_BUILD_GUI_LIB QT_NO_USING_NAMESPACE
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000
-!win32:!embedded:!mac:CONFIG += x11
+!win32:!embedded:!mac:!symbian:CONFIG += x11
unix:QMAKE_PKGCONFIG_REQUIRES = QtCore
@@ -17,6 +17,7 @@ x11:include(kernel/x11.pri)
mac:include(kernel/mac.pri)
win32:include(kernel/win.pri)
embedded:include(embedded/embedded.pri)
+symbian:include(kernel/symbian.pri)
#modules
include(animation/animation.pri)
@@ -47,3 +48,7 @@ QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtGui.dynlist
DEFINES += Q_INTERNAL_QAPP_SRC
+symbian:TARGET.UID3=0x2001B2DD
+
+# ro-section in gui can exceed default allocated space, so more rw-section little further
+symbian-sbsv2: MMP_RULES += "LINKEROPTION armcc --rw-base 0x800000"
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index bf348af..c15e8b6 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -62,6 +62,9 @@ mac {
HEADERS += image/qpixmap_mac_p.h
SOURCES += image/qpixmap_mac.cpp
}
+symbian {
+ SOURCES += image/qpixmap_s60.cpp
+}
# Built-in image format support
HEADERS += \
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 7d7dde1..d3a4855 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -185,6 +185,13 @@ static int depthForFormat(QImage::Format format)
return depth;
}
+/*! \fn QImageData * QImageData::create(const QSize &size, QImage::Format format, int numColors)
+
+ \internal
+
+ Creates a new image data.
+ Returns 0 if invalid parameters are give or anything else failed.
+*/
QImageData * QImageData::create(const QSize &size, QImage::Format format, int numColors)
{
if (!size.isValid() || numColors < 0 || format == QImage::Format_Invalid)
@@ -223,7 +230,7 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu
|| INT_MAX/sizeof(uchar *) < uint(height))
return 0;
- QImageData *d = new QImageData;
+ QScopedPointer<QImageData> d(new QImageData);
d->colortable.resize(numColors);
if (depth == 1) {
d->colortable[0] = QColor(Qt::black).rgba();
@@ -246,12 +253,11 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu
d->data = (uchar *)malloc(d->nbytes);
if (!d->data) {
- delete d;
return 0;
}
d->ref.ref();
- return d;
+ return d.take();
}
@@ -1618,6 +1624,7 @@ int QImage::numColors() const
/*!
Returns a pointer to the scanline pointer table. This is the
beginning of the data block for the image.
+ Returns 0 in case of an error.
Use the bits() or scanLine() function instead.
*/
@@ -1633,6 +1640,8 @@ uchar **QImage::jumpTable()
if (!d->jumptable) {
d->jumptable = (uchar **)malloc(d->height*sizeof(uchar *));
+ if (!d->jumptable)
+ return 0;
uchar *data = d->data;
int height = d->height;
uchar **p = d->jumptable;
@@ -1653,6 +1662,8 @@ const uchar * const *QImage::jumpTable() const
return 0;
if (!d->jumptable) {
d->jumptable = (uchar **)malloc(d->height*sizeof(uchar *));
+ if (!d->jumptable)
+ return 0;
uchar *data = d->data;
int height = d->height;
uchar **p = d->jumptable;
diff --git a/src/gui/image/qimageiohandler.cpp b/src/gui/image/qimageiohandler.cpp
index c64eef8..8248e42 100644
--- a/src/gui/image/qimageiohandler.cpp
+++ b/src/gui/image/qimageiohandler.cpp
@@ -272,7 +272,6 @@ QImageIOHandler::QImageIOHandler(QImageIOHandlerPrivate &dd)
*/
QImageIOHandler::~QImageIOHandler()
{
- delete d_ptr;
}
/*!
diff --git a/src/gui/image/qimageiohandler.h b/src/gui/image/qimageiohandler.h
index 94751f3..50508c0 100644
--- a/src/gui/image/qimageiohandler.h
+++ b/src/gui/image/qimageiohandler.h
@@ -44,6 +44,7 @@
#include <QtCore/qplugin.h>
#include <QtCore/qfactoryinterface.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
@@ -109,7 +110,7 @@ public:
protected:
QImageIOHandler(QImageIOHandlerPrivate &dd);
- QImageIOHandlerPrivate *d_ptr;
+ QScopedPointer<QImageIOHandlerPrivate> d_ptr;
private:
Q_DISABLE_COPY(QImageIOHandler)
};
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index ea1392b..ddb51d3 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -132,7 +132,6 @@ QPicture::QPicture(int formatVersion)
{
Q_D(QPicture);
d_ptr->q_ptr = this;
- d->paintEngine = 0;
if (formatVersion == 0)
qWarning("QPicture: invalid format version 0");
@@ -155,7 +154,7 @@ QPicture::QPicture(int formatVersion)
*/
QPicture::QPicture(const QPicture &pic)
- : QPaintDevice(), d_ptr(pic.d_ptr)
+ : QPaintDevice(), d_ptr(pic.d_ptr.data())
{
d_func()->ref.ref();
}
@@ -173,10 +172,6 @@ QPicture::QPicture(QPicturePrivate &dptr)
*/
QPicture::~QPicture()
{
- if (!d_func()->ref.deref()) {
- delete d_func()->paintEngine;
- delete d_func();
- }
}
/*!
@@ -1032,9 +1027,7 @@ void QPicture::detach_helper()
x->formatMinor = d->formatMinor;
x->brect = d->brect;
x->override_rect = d->override_rect;
- if (!d->ref.deref())
- delete d;
- d_ptr = x;
+ d_ptr.reset(x);
}
/*!
@@ -1043,13 +1036,25 @@ void QPicture::detach_helper()
*/
QPicture& QPicture::operator=(const QPicture &p)
{
- qAtomicAssign<QPicturePrivate>(d_ptr, p.d_ptr);
+ d_ptr.assign(p.d_ptr.data());
return *this;
}
/*!
\internal
+ Constructs a QPicturePrivate
+*/
+QPicturePrivate::QPicturePrivate()
+ : in_memory_only(false),
+ q_ptr(0)
+{
+ ref = 1;
+}
+
+/*!
+ \internal
+
Sets formatOk to false and resets the format version numbers to default
*/
@@ -1137,8 +1142,8 @@ bool QPicturePrivate::checkFormat()
QPaintEngine *QPicture::paintEngine() const
{
if (!d_func()->paintEngine)
- const_cast<QPicture*>(this)->d_func()->paintEngine = new QPicturePaintEngine;
- return d_func()->paintEngine;
+ const_cast<QPicture*>(this)->d_func()->paintEngine.reset(new QPicturePaintEngine);
+ return d_func()->paintEngine.data();
}
/*****************************************************************************
diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h
index 67e8db2..c323f0e 100644
--- a/src/gui/image/qpicture.h
+++ b/src/gui/image/qpicture.h
@@ -106,7 +106,7 @@ private:
bool exec(QPainter *p, QDataStream &ds, int i);
void detach_helper();
- QPicturePrivate *d_ptr;
+ QScopedSharedPointer<QPicturePrivate> d_ptr;
friend class QPicturePaintEngine;
friend class Q3Picture;
friend class QAlphaPaintEngine;
@@ -114,7 +114,7 @@ private:
public:
typedef QPicturePrivate* DataPtr;
- inline DataPtr &data_ptr() { return d_ptr; }
+ inline DataPtr &data_ptr() { return d_ptr.data_ptr(); }
};
Q_DECLARE_SHARED(QPicture)
diff --git a/src/gui/image/qpicture_p.h b/src/gui/image/qpicture_p.h
index 86b6365..6147019 100644
--- a/src/gui/image/qpicture_p.h
+++ b/src/gui/image/qpicture_p.h
@@ -143,7 +143,7 @@ public:
PdcReservedStop = 199 // for Qt
};
- inline QPicturePrivate() : in_memory_only(false), q_ptr(0) { ref = 1; }
+ QPicturePrivate();
QAtomicInt ref;
bool checkFormat();
@@ -156,7 +156,7 @@ public:
int formatMinor;
QRect brect;
QRect override_rect;
- QPaintEngine *paintEngine;
+ QScopedPointer<QPaintEngine> paintEngine;
bool in_memory_only;
QList<QImage> image_list;
QList<QPixmap> pixmap_list;
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 3e5c9b7..12287d3 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -76,6 +76,10 @@
# include <private/qpixmap_x11_p.h>
#endif
+#if defined(Q_OS_SYMBIAN)
+# include <private/qt_s60_p.h>
+#endif
+
#include "qpixmap_raster_p.h"
QT_BEGIN_NAMESPACE
@@ -1899,7 +1903,10 @@ int QPixmap::defaultDepth()
return 32; // XXX
#elif defined(Q_WS_MAC)
return 32;
+#elif defined(Q_OS_SYMBIAN)
+ return S60->screenDepth;
#endif
+
}
typedef void (*_qt_pixmap_cleanup_hook_64)(qint64);
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index d1e2ecb..279e1ef 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -51,6 +51,10 @@
QT_BEGIN_HEADER
+#if defined(Q_OS_SYMBIAN)
+class CFbsBitmap;
+#endif
+
QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
@@ -59,7 +63,6 @@ class QImageWriter;
class QColor;
class QVariant;
class QX11Info;
-
class QPixmapData;
class Q_GUI_EXPORT QPixmap : public QPaintDevice
@@ -152,6 +155,11 @@ public:
static QPixmap fromMacCGImageRef(CGImageRef image);
#endif
+#if defined(Q_OS_SYMBIAN)
+ CFbsBitmap *toSymbianCFbsBitmap() const;
+ static QPixmap fromSymbianCFbsBitmap(CFbsBitmap *bitmap);
+#endif
+
inline QPixmap copy(int x, int y, int width, int height) const;
QPixmap copy(const QRect &rect = QRect()) const;
diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp
new file mode 100644
index 0000000..132e26e
--- /dev/null
+++ b/src/gui/image/qpixmap_s60.cpp
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <exception>
+#include <w32std.h>
+#include <fbs.h>
+
+#include <private/qt_s60_p.h>
+#include "qpixmap.h"
+#include "qpixmap_raster_p.h"
+#include <qwidget.h>
+
+QT_BEGIN_NAMESPACE
+
+QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
+{
+ CWsScreenDevice* screenDevice = S60->screenDevice();
+ TSize screenSize = screenDevice->SizeInPixels();
+
+ TSize srcSize;
+ // Find out if this is one of our windows.
+ QSymbianControl *sControl;
+ sControl = winId->MopGetObject(sControl);
+ if (sControl && sControl->widget()->windowType() == Qt::Desktop) {
+ // Grabbing desktop widget
+ srcSize = screenSize;
+ } else {
+ TPoint relativePos = winId->PositionRelativeToScreen();
+ x += relativePos.iX;
+ y += relativePos.iY;
+ srcSize = winId->Size();
+ }
+
+ TRect srcRect(TPoint(x, y), srcSize);
+ // Clip to the screen
+ srcRect.Intersection(TRect(screenSize));
+
+ if (w > 0 && h > 0) {
+ TRect subRect(TPoint(x, y), TSize(w, h));
+ // Clip to the subRect
+ srcRect.Intersection(subRect);
+ }
+
+ if (srcRect.IsEmpty())
+ return QPixmap();
+
+ TDisplayMode displayMode = screenDevice->DisplayMode();
+ CFbsBitmap* temporary = new (ELeave) CFbsBitmap();
+ TInt error = temporary->Create(srcRect.Size(), displayMode);
+ if (error == KErrNone)
+ error = screenDevice->CopyScreenToBitmap(temporary, srcRect);
+
+ if (error != KErrNone) {
+ CBase::Delete(temporary);
+ return QPixmap();
+ }
+
+ QPixmap pixmap = QPixmap::fromSymbianCFbsBitmap(temporary);
+ CBase::Delete(temporary);
+ return pixmap;
+}
+
+/*!
+\since 4.6
+
+Returns a \c CFbsBitmap that is equivalent to the QPixmap by copying the data.
+
+It is the caller's responsibility to delete the \c CFbsBitmap after use.
+
+\warning This function is only available on Symbian OS.
+
+\sa fromSymbianCFbsBitmap()
+*/
+
+CFbsBitmap *QPixmap::toSymbianCFbsBitmap() const
+{
+ if (isNull())
+ return 0;
+
+ TDisplayMode mode;
+ const QImage img = toImage();
+ QImage::Format destFormat = img.format();
+ switch (img.format()) {
+ case QImage::Format_Mono:
+ destFormat = QImage::Format_MonoLSB;
+ // Fall through intended
+ case QImage::Format_MonoLSB:
+ mode = EGray2;
+ break;
+ case QImage::Format_Indexed8:
+ if (img.isGrayscale())
+ mode = EGray256;
+ else
+ mode = EColor256;
+ break;
+ case QImage::Format_RGB32:
+ mode = EColor16MU;
+ break;
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ destFormat = QImage::Format_ARGB32_Premultiplied;
+ // Fall through intended
+ case QImage::Format_ARGB32_Premultiplied:
+#if !defined(__SERIES60_31__) && !defined(__S60_32__)
+ // ### TODO: Add runtime detection as well?
+ mode = EColor16MAP;
+ break;
+#endif
+ destFormat = QImage::Format_ARGB32;
+ // Fall through intended
+ case QImage::Format_ARGB32:
+ mode = EColor16MA;
+ break;
+ case QImage::Format_RGB555:
+ destFormat = QImage::Format_RGB16;
+ // Fall through intended
+ case QImage::Format_RGB16:
+ mode = EColor64K;
+ break;
+ case QImage::Format_RGB666:
+ destFormat = QImage::Format_RGB888;
+ // Fall through intended
+ case QImage::Format_RGB888:
+ mode = EColor16M;
+ break;
+ case QImage::Format_RGB444:
+ mode = EColor4K;
+ break;
+ case QImage::Format_Invalid:
+ return 0;
+ default:
+ qWarning("Image format not supported: %d", img.format());
+ return 0;
+ }
+
+ CFbsBitmap* bitmap = new (ELeave) CFbsBitmap();
+ TSize size(width(), height());
+ if (bitmap->Create(size, mode) != KErrNone) {
+ CBase::Delete(bitmap);
+ return 0;
+ }
+
+ const QImage converted = img.convertToFormat(destFormat);
+
+ bitmap->LockHeap();
+ const uchar *sptr = converted.bits();
+ uchar *dptr = (uchar*)bitmap->DataAddress();
+ Mem::Copy(dptr, sptr, converted.numBytes());
+ bitmap->UnlockHeap();
+ return bitmap;
+}
+
+/*!
+\since 4.6
+
+Returns a QPixmap that is equivalent to the \c CFbsBitmap by copying the data.
+If the CFbsBitmap is not valid or is compressed in memory, this function will
+return a null QPixmap.
+
+\warning This function is only available on Symbian OS.
+
+\sa toSymbianCFbsBitmap(), {QPixmap#Pixmap Conversion}{Pixmap Conversion}
+*/
+
+QPixmap QPixmap::fromSymbianCFbsBitmap(CFbsBitmap *bitmap)
+{
+ int width = bitmap->SizeInPixels().iWidth;
+ int height = bitmap->SizeInPixels().iHeight;
+
+ if (!bitmap || width <= 0 || height <= 0 || bitmap->IsCompressedInRAM())
+ return QPixmap();
+
+ TDisplayMode displayMode = bitmap->DisplayMode();
+ QImage::Format format = qt_TDisplayMode2Format(displayMode);
+ int bytesPerLine = CFbsBitmap::ScanLineLength(width, displayMode);
+ bitmap->LockHeap();
+ QImage image = QImage((const uchar*)bitmap->DataAddress(), width, height, bytesPerLine, format);
+ if (displayMode == EGray2) {
+ image.setNumColors(2);
+ image.setColor(0, QColor(Qt::color0).rgba());
+ image.setColor(1, QColor(Qt::color1).rgba());
+ } else if (displayMode == EGray256) {
+ for (int i=0; i < 256; ++i)
+ image.setColor(i, qRgb(i, i, i));
+ }else if (displayMode == EColor256) {
+ const TColor256Util *palette = TColor256Util::Default();
+ for (int i=0; i < 256; ++i)
+ image.setColor(i, (QRgb)(palette->Color256(i).Value()));
+ }
+ QPixmap pixmap = QPixmap::fromImage(image.copy());
+ bitmap->UnlockHeap();
+ return pixmap;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp
index ecdcd8c..b4a3a49 100644
--- a/src/gui/image/qpixmapcache.cpp
+++ b/src/gui/image/qpixmapcache.cpp
@@ -86,7 +86,9 @@ QT_BEGIN_NAMESPACE
\sa QCache, QPixmap
*/
-#if defined(Q_WS_QWS) || defined(Q_WS_WINCE)
+#if defined(Q_OS_SYMBIAN)
+static int cache_limit = 1024; // 1048 KB cache limit for symbian
+#elif defined(Q_WS_QWS) || defined(Q_WS_WINCE)
static int cache_limit = 2048; // 2048 KB cache limit for embedded
#else
static int cache_limit = 10240; // 10 MB cache limit for desktop
@@ -608,7 +610,12 @@ void QPixmapCache::remove(const Key &key)
void QPixmapCache::clear()
{
- pm_cache()->clear();
+ QT_TRY {
+ pm_cache()->clear();
+ } QT_CATCH(const std::bad_alloc &) {
+ // if we ran out of memory during pm_cache(), it's no leak,
+ // so just ignore it.
+ }
}
QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmapdatafactory.cpp b/src/gui/image/qpixmapdatafactory.cpp
index e5bf414..852e875 100644
--- a/src/gui/image/qpixmapdatafactory.cpp
+++ b/src/gui/image/qpixmapdatafactory.cpp
@@ -47,7 +47,7 @@
#ifdef Q_WS_X11
# include <private/qpixmap_x11_p.h>
#endif
-#ifdef Q_WS_WIN
+#if defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
# include <private/qpixmap_raster_p.h>
#endif
#ifdef Q_WS_MAC
@@ -75,7 +75,7 @@ QPixmapData* QSimplePixmapDataFactory::create(QPixmapData::PixelType type)
#if defined(Q_WS_X11)
return new QX11PixmapData(type);
-#elif defined(Q_WS_WIN)
+#elif defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
return new QRasterPixmapData(type);
#elif defined(Q_WS_MAC)
return new QMacPixmapData(type);
diff --git a/src/gui/inputmethod/inputmethod.pri b/src/gui/inputmethod/inputmethod.pri
index d321cd4..6d9f748 100644
--- a/src/gui/inputmethod/inputmethod.pri
+++ b/src/gui/inputmethod/inputmethod.pri
@@ -23,4 +23,9 @@ mac:!embedded {
HEADERS += inputmethod/qmacinputcontext_p.h
SOURCES += inputmethod/qmacinputcontext_mac.cpp
}
+symbian:contains(QT_CONFIG, s60) {
+ HEADERS += inputmethod/qcoefepinputcontext_p.h
+ SOURCES += inputmethod/qcoefepinputcontext_s60.cpp
+ LIBS += -lfepbase
+}
diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h
new file mode 100644
index 0000000..d754763
--- /dev/null
+++ b/src/gui/inputmethod/qcoefepinputcontext_p.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOEFEPINPUTCONTEXT_P_H
+#define QCOEFEPINPUTCONTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QT_NO_IM
+
+#include "qinputcontext.h"
+#include <qhash.h>
+#include <private/qcore_symbian_p.h>
+#include <private/qt_s60_p.h>
+
+#include <fepbase.h>
+#include <aknedsts.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QCoeFepInputContext : public QInputContext,
+ public MCoeFepAwareTextEditor,
+ public MCoeFepAwareTextEditor_Extension1,
+ public MObjectProvider
+{
+ Q_OBJECT
+
+public:
+ QCoeFepInputContext(QObject *parent = 0);
+ ~QCoeFepInputContext();
+
+ QString identifierName() { return QLatin1String("coefep"); }
+ QString language();
+
+ void reset();
+ void update();
+
+ bool filterEvent(const QEvent *event);
+ void mouseHandler( int x, QMouseEvent *event);
+ bool isComposing() const { return m_isEditing; }
+
+ void setFocusWidget(QWidget * w);
+ void widgetDestroyed(QWidget *w);
+
+ TCoeInputCapabilities inputCapabilities();
+
+private:
+ void commitCurrentString(bool triggeredBySymbian);
+ void updateHints(bool mustUpdateInputCapabilities);
+ void applyHints(Qt::InputMethodHints hints);
+ void applyFormat(QList<QInputMethodEvent::Attribute> *attributes);
+ void queueInputCapabilitiesChanged();
+
+private Q_SLOTS:
+ void ensureInputCapabilitiesChanged();
+
+ // From MCoeFepAwareTextEditor
+public:
+ void StartFepInlineEditL(const TDesC& aInitialInlineText, TInt aPositionOfInsertionPointInInlineText,
+ TBool aCursorVisibility, const MFormCustomDraw* aCustomDraw,
+ MFepInlineTextFormatRetriever& aInlineTextFormatRetriever,
+ MFepPointerEventHandlerDuringInlineEdit& aPointerEventHandlerDuringInlineEdit);
+ void UpdateFepInlineTextL(const TDesC& aNewInlineText, TInt aPositionOfInsertionPointInInlineText);
+ void SetInlineEditingCursorVisibilityL(TBool aCursorVisibility);
+ void CancelFepInlineEdit();
+ TInt DocumentLengthForFep() const;
+ TInt DocumentMaximumLengthForFep() const;
+ void SetCursorSelectionForFepL(const TCursorSelection& aCursorSelection);
+ void GetCursorSelectionForFep(TCursorSelection& aCursorSelection) const;
+ void GetEditorContentForFep(TDes& aEditorContent, TInt aDocumentPosition, TInt aLengthToRetrieve) const;
+ void GetFormatForFep(TCharFormat& aFormat, TInt aDocumentPosition) const;
+ void GetScreenCoordinatesForFepL(TPoint& aLeftSideOfBaseLine, TInt& aHeight, TInt& aAscent,
+ TInt aDocumentPosition) const;
+private:
+ void DoCommitFepInlineEditL();
+ MCoeFepAwareTextEditor_Extension1* Extension1(TBool& aSetToTrue);
+
+ // From MCoeFepAwareTextEditor_Extension1
+public:
+ void SetStateTransferingOwnershipL(MCoeFepAwareTextEditor_Extension1::CState* aState, TUid aTypeSafetyUid);
+ MCoeFepAwareTextEditor_Extension1::CState* State(TUid aTypeSafetyUid);
+
+ // From MObjectProvider
+public:
+ TTypeUid::Ptr MopSupplyObject(TTypeUid id);
+
+private:
+ QSymbianControl *m_parent;
+ CAknEdwinState *m_fepState;
+ QString m_preeditString;
+ Qt::InputMethodHints m_lastImHints;
+ TUint m_textCapabilities;
+ bool m_isEditing;
+ bool m_inDestruction;
+ bool m_pendingInputCapabilitiesChanged;
+ int m_cursorVisibility;
+ int m_inlinePosition;
+ MFepInlineTextFormatRetriever *m_formatRetriever;
+ MFepPointerEventHandlerDuringInlineEdit *m_pointerHandler;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_IM
+
+#endif // QCOEFEPINPUTCONTEXT_P_H
diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
new file mode 100644
index 0000000..c03426f
--- /dev/null
+++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp
@@ -0,0 +1,747 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_IM
+
+#include "qcoefepinputcontext_p.h"
+#include <qapplication.h>
+#include <qtextformat.h>
+
+#include <fepitfr.h>
+
+#include <limits.h>
+// You only find these enumerations on SDK 5 onwards, so we need to provide our own
+// to remain compatible with older releases. They won't be called by pre-5.0 SDKs.
+
+// MAknEdStateObserver::EAknCursorPositionChanged
+#define QT_EAknCursorPositionChanged MAknEdStateObserver::EAknEdwinStateEvent(6)
+// MAknEdStateObserver::EAknActivatePenInputRequest
+#define QT_EAknActivatePenInputRequest MAknEdStateObserver::EAknEdwinStateEvent(7)
+
+QT_BEGIN_NAMESPACE
+
+QCoeFepInputContext::QCoeFepInputContext(QObject *parent)
+ : QInputContext(parent),
+ m_fepState(new (ELeave) CAknEdwinState),
+ m_lastImHints(Qt::ImhNone),
+ m_textCapabilities(TCoeInputCapabilities::EAllText),
+ m_isEditing(false),
+ m_inDestruction(false),
+ m_pendingInputCapabilitiesChanged(false),
+ m_cursorVisibility(1),
+ m_inlinePosition(0),
+ m_formatRetriever(0),
+ m_pointerHandler(0)
+{
+ m_fepState->SetObjectProvider(this);
+ m_fepState->SetFlags(EAknEditorFlagDefault);
+ m_fepState->SetDefaultInputMode( EAknEditorTextInputMode );
+ m_fepState->SetPermittedInputModes( EAknEditorAllInputModes );
+ m_fepState->SetDefaultCase( EAknEditorLowerCase );
+ m_fepState->SetPermittedCases( EAknEditorLowerCase|EAknEditorUpperCase );
+ m_fepState->SetSpecialCharacterTableResourceId( 0 );
+ m_fepState->SetNumericKeymap( EAknEditorStandardNumberModeKeymap );
+}
+
+QCoeFepInputContext::~QCoeFepInputContext()
+{
+ m_inDestruction = true;
+
+ // This is to make sure that the FEP manager "forgets" about us,
+ // otherwise we may get callbacks even after we're destroyed.
+ // The call below is essentially equivalent to InputCapabilitiesChanged(),
+ // but is synchronous, rather than asynchronous.
+ CCoeEnv::Static()->SyncNotifyFocusObserversOfChangeInFocus();
+
+ if (m_fepState)
+ delete m_fepState;
+}
+
+void QCoeFepInputContext::reset()
+{
+ CCoeEnv::Static()->Fep()->CancelTransaction();
+}
+
+void QCoeFepInputContext::update()
+{
+ updateHints(false);
+
+ // For pre-5.0 SDKs, we don't do text updates on S60 side.
+ if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) {
+ return;
+ }
+
+ // Don't be fooled (as I was) by the name of this enumeration.
+ // What it really does is tell the virtual keyboard UI that the text has been
+ // updated and it should be reflected in the internal display of the VK.
+ m_fepState->ReportAknEdStateEventL(QT_EAknCursorPositionChanged);
+}
+
+void QCoeFepInputContext::setFocusWidget(QWidget *w)
+{
+ commitCurrentString(false);
+
+ QInputContext::setFocusWidget(w);
+
+ updateHints(true);
+}
+
+void QCoeFepInputContext::widgetDestroyed(QWidget *w)
+{
+ // Make sure that the input capabilities of whatever new widget got focused are queried.
+ CCoeControl *ctrl = w->effectiveWinId();
+ if (ctrl->IsFocused()) {
+ ctrl->SetFocus(false);
+ ctrl->SetFocus(true);
+ }
+}
+
+/*!
+ Definition of struct for mapping Symbian to ISO locale
+ ### REMOVE
+ See below.
+*/
+struct symbianToISO {
+ int symbian_language;
+ char iso_name[8];
+};
+
+/*!
+ Mapping from Symbian to ISO locale
+ ### REMOVE
+ This was taken from the preliminary QLocale port to S60, and should be
+ removed once that is finished.
+*/
+static const symbianToISO symbian_to_iso_list[] = {
+ { ELangEnglish, "en_GB" },
+ { ELangFrench, "fr_FR" },
+ { ELangGerman, "de_DE" },
+ { ELangSpanish, "es_ES" },
+ { ELangItalian, "it_IT" },
+ { ELangSwedish, "sv_SE" },
+ { ELangDanish, "da_DK" },
+ { ELangNorwegian, "no_NO" },
+ { ELangFinnish, "fi_FI" },
+ { ELangAmerican, "en_US" },
+ { ELangPortuguese, "pt_PT" },
+ { ELangTurkish, "tr_TR" },
+ { ELangIcelandic, "is_IS" },
+ { ELangRussian, "ru_RU" },
+ { ELangHungarian, "hu_HU" },
+ { ELangDutch, "nl_NL" },
+ { ELangBelgianFlemish, "nl_BE" },
+ { ELangCzech, "cs_CZ" },
+ { ELangSlovak, "sk_SK" },
+ { ELangPolish, "pl_PL" },
+ { ELangSlovenian, "sl_SI" },
+ { ELangTaiwanChinese, "zh_TW" },
+ { ELangHongKongChinese, "zh_HK" },
+ { ELangPrcChinese, "zh_CN" },
+ { ELangJapanese, "ja_JP" },
+ { ELangThai, "th_TH" },
+ { ELangArabic, "ar_AE" },
+ { ELangTagalog, "tl_PH" },
+ { ELangBulgarian, "bg_BG" },
+ { ELangCatalan, "ca_ES" },
+ { ELangCroatian, "hr_HR" },
+ { ELangEstonian, "et_EE" },
+ { ELangFarsi, "fa_IR" },
+ { ELangCanadianFrench, "fr_CA" },
+ { ELangGreek, "el_GR" },
+ { ELangHebrew, "he_IL" },
+ { ELangHindi, "hi_IN" },
+ { ELangIndonesian, "id_ID" },
+ { ELangLatvian, "lv_LV" },
+ { ELangLithuanian, "lt_LT" },
+ { ELangMalay, "ms_MY" },
+ { ELangBrazilianPortuguese, "pt_BR" },
+ { ELangRomanian, "ro_RO" },
+ { ELangSerbian, "sr_YU" },
+ { ELangLatinAmericanSpanish, "es" },
+ { ELangUkrainian, "uk_UA" },
+ { ELangUrdu, "ur_PK" }, // India/Pakistan
+ { ELangVietnamese, "vi_VN" },
+#ifdef __E32LANG_H__
+// 5.0
+ { ELangBasque, "eu_ES" },
+ { ELangGalician, "gl_ES" },
+#endif
+ //{ ELangEnglish_Apac, "en" },
+ //{ ELangEnglish_Taiwan, "en_TW" },
+ //{ ELangEnglish_HongKong, "en_HK" },
+ //{ ELangEnglish_Prc, "en_CN" },
+ //{ ELangEnglish_Japan, "en_JP"},
+ //{ ELangEnglish_Thailand, "en_TH" },
+ //{ ELangMalay_Apac, "ms" }
+};
+
+/*!
+ Number of Symbian to ISO locale mappings
+ ### Remove.
+ See comment for array above.
+*/
+static const int symbian_to_iso_count
+ = sizeof(symbian_to_iso_list)/sizeof(symbianToISO);
+
+QString QCoeFepInputContext::language()
+{
+ TLanguage lang = m_fepState->LocalLanguage();
+ if (lang < symbian_to_iso_count) {
+ return QLatin1String(symbian_to_iso_list[lang].iso_name);
+ } else {
+ return QLatin1String("C");
+ }
+}
+
+bool QCoeFepInputContext::filterEvent(const QEvent *event)
+{
+ // The CloseSoftwareInputPanel event is not handled here, because the VK will automatically
+ // close when it discovers that the underlying widget does not have input capabilities.
+
+ if (!focusWidget())
+ return false;
+
+ if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) {
+ const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event);
+ Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints());
+ if (keyEvent->key() == Qt::Key_F20 && m_lastImHints & Qt::ImhHiddenText) {
+ // Special case in Symbian. On editors with secret text, F20 is for some reason
+ // considered to be a backspace.
+ QKeyEvent modifiedEvent(keyEvent->type(), Qt::Key_Backspace, keyEvent->modifiers(),
+ keyEvent->text(), keyEvent->isAutoRepeat(), keyEvent->count());
+ QApplication::sendEvent(focusWidget(), &modifiedEvent);
+ return true;
+ }
+ }
+
+ // For pre-5.0 SDKs, we don't launch the keyboard.
+ if (QSysInfo::s60Version() != QSysInfo::SV_S60_5_0) {
+ return false;
+ }
+
+ if (event->type() == QEvent::RequestSoftwareInputPanel) {
+ // Notify S60 that we want the virtual keyboard to show up.
+ QSymbianControl *sControl;
+ sControl = focusWidget()->effectiveWinId()->MopGetObject(sControl);
+ Q_ASSERT(sControl);
+
+ // The FEP UI temporarily steals focus when it shows up the first time, causing
+ // all sorts of weird effects on the focused widgets. Since it will immediately give
+ // back focus to us, we temporarily disable focus handling until the job's done.
+ if (sControl) {
+ sControl->setIgnoreFocusChanged(true);
+ }
+
+ ensureInputCapabilitiesChanged();
+ m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::QT_EAknActivatePenInputRequest);
+
+ if (sControl) {
+ sControl->setIgnoreFocusChanged(false);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event)
+{
+ Q_ASSERT(m_isEditing);
+ Q_ASSERT(focusWidget());
+
+ if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton) {
+ commitCurrentString(false);
+ int pos = focusWidget()->inputMethodQuery(Qt::ImCursorPosition).toInt();
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, pos + x, 0, QVariant());
+ QInputMethodEvent event("", attributes);
+ sendEvent(event);
+ }
+}
+
+TCoeInputCapabilities QCoeFepInputContext::inputCapabilities()
+{
+ if (m_inDestruction) {
+ return TCoeInputCapabilities(TCoeInputCapabilities::ENone, 0, 0);
+ }
+
+ return TCoeInputCapabilities(m_textCapabilities, this, 0);
+}
+
+static QTextCharFormat qt_TCharFormat2QTextCharFormat(const TCharFormat &cFormat)
+{
+ QTextCharFormat qFormat;
+
+ QBrush foreground(QColor(cFormat.iFontPresentation.iTextColor.Internal()));
+ qFormat.setForeground(foreground);
+
+ qFormat.setFontStrikeOut(cFormat.iFontPresentation.iStrikethrough == EStrikethroughOn);
+ qFormat.setFontUnderline(cFormat.iFontPresentation.iUnderline == EUnderlineOn);
+
+ return qFormat;
+}
+
+void QCoeFepInputContext::updateHints(bool mustUpdateInputCapabilities)
+{
+ QWidget *w = focusWidget();
+ if (w) {
+ Qt::InputMethodHints hints = w->inputMethodHints();
+ if (hints != m_lastImHints) {
+ m_lastImHints = hints;
+ applyHints(hints);
+ } else if (!mustUpdateInputCapabilities) {
+ // Optimization. Return immediately if there was no change.
+ return;
+ }
+ }
+ queueInputCapabilitiesChanged();
+}
+
+void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints)
+{
+ using namespace Qt;
+
+ bool numbersOnly = hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly
+ || hints & ImhDialableCharactersOnly;
+ bool noOnlys = !(numbersOnly || hints & ImhUppercaseOnly
+ || hints & ImhLowercaseOnly);
+ TInt flags;
+ Qt::InputMethodHints oldHints = hints;
+
+ // Some sanity checking. Make sure that only one preference is set.
+ InputMethodHints prefs = ImhPreferNumbers | ImhPreferUppercase | ImhPreferLowercase;
+ prefs &= hints;
+ if (prefs != ImhPreferNumbers && prefs != ImhPreferUppercase && prefs != ImhPreferLowercase) {
+ hints &= ~prefs;
+ }
+ if (!noOnlys) {
+ // Make sure that the preference is within the permitted set.
+ if (hints & ImhPreferNumbers && !(hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly
+ || hints & ImhDialableCharactersOnly)) {
+ hints &= ~ImhPreferNumbers;
+ } else if (hints & ImhPreferUppercase && !(hints & ImhUppercaseOnly)) {
+ hints &= ~ImhPreferUppercase;
+ } else if (hints & ImhPreferLowercase && !(hints & ImhLowercaseOnly)) {
+ hints &= ~ImhPreferLowercase;
+ }
+ // If there is no preference, set it to something within the permitted set.
+ if (!(hints & ImhPreferNumbers || hints & ImhPreferUppercase || hints & ImhPreferLowercase)) {
+ if (hints & ImhLowercaseOnly) {
+ hints |= ImhPreferLowercase;
+ } else if (hints & ImhUppercaseOnly) {
+ hints |= ImhPreferUppercase;
+ } else if (hints & ImhDigitsOnly || hints & ImhFormattedNumbersOnly
+ || hints & ImhDialableCharactersOnly) {
+ hints |= ImhPreferNumbers;
+ }
+ }
+ }
+
+ if (hints & ImhPreferNumbers) {
+ m_fepState->SetDefaultInputMode(EAknEditorNumericInputMode);
+ m_fepState->SetCurrentInputMode(EAknEditorNumericInputMode);
+ } else {
+ m_fepState->SetDefaultInputMode(EAknEditorTextInputMode);
+ m_fepState->SetCurrentInputMode(EAknEditorTextInputMode);
+ }
+ flags = 0;
+ if (numbersOnly) {
+ flags |= EAknEditorNumericInputMode;
+ }
+ if (hints & ImhUppercaseOnly || hints & ImhLowercaseOnly) {
+ flags |= EAknEditorTextInputMode;
+ }
+ if (flags == 0) {
+ flags = EAknEditorAllInputModes;
+ }
+ m_fepState->SetPermittedInputModes(flags);
+ m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateInputModeUpdate);
+
+ if (hints & ImhPreferLowercase) {
+ m_fepState->SetDefaultCase(EAknEditorLowerCase);
+ m_fepState->SetCurrentCase(EAknEditorLowerCase);
+ } else if (hints & ImhPreferUppercase) {
+ m_fepState->SetDefaultCase(EAknEditorUpperCase);
+ m_fepState->SetCurrentCase(EAknEditorUpperCase);
+ } else if (hints & ImhNoAutoUppercase) {
+ m_fepState->SetDefaultCase(EAknEditorLowerCase);
+ m_fepState->SetCurrentCase(EAknEditorLowerCase);
+ } else {
+ m_fepState->SetDefaultCase(EAknEditorTextCase);
+ m_fepState->SetCurrentCase(EAknEditorTextCase);
+ }
+ flags = 0;
+ if (hints & ImhUppercaseOnly) {
+ flags |= EAknEditorUpperCase;
+ }
+ if (hints & ImhLowercaseOnly) {
+ flags |= EAknEditorLowerCase;
+ }
+ if (flags == 0) {
+ flags = EAknEditorAllCaseModes;
+ if (hints & ImhNoAutoUppercase) {
+ flags &= ~EAknEditorTextCase;
+ }
+ }
+ m_fepState->SetPermittedCases(flags);
+ m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateCaseModeUpdate);
+
+ flags = 0;
+ if (hints & ImhUppercaseOnly && !(hints & ImhLowercaseOnly)
+ || hints & ImhLowercaseOnly && !(hints & ImhUppercaseOnly)) {
+ flags |= EAknEditorFlagFixedCase;
+ }
+ // Using T9 and hidden text together may actually crash the FEP, so check for hidden text too.
+ if (hints & ImhNoPredictiveText || hints & ImhHiddenText) {
+ flags |= EAknEditorFlagNoT9;
+ }
+ m_fepState->SetFlags(flags);
+ m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::EAknEdwinStateFlagsUpdate);
+
+ if (hints & ImhFormattedNumbersOnly) {
+ flags = EAknEditorCalculatorNumberModeKeymap;
+ } else if (hints & ImhDigitsOnly) {
+ flags = EAknEditorPlainNumberModeKeymap;
+ } else {
+ // ImhDialableCharactersOnly is the fallback as well, so we don't need to check for
+ // that flag.
+ flags = EAknEditorStandardNumberModeKeymap;
+ }
+ m_fepState->SetNumericKeymap(static_cast<TAknEditorNumericKeymap>(flags));
+
+ if (hints & ImhHiddenText) {
+ m_textCapabilities = TCoeInputCapabilities::EAllText | TCoeInputCapabilities::ESecretText;
+ } else {
+ m_textCapabilities = TCoeInputCapabilities::EAllText;
+ }
+}
+
+void QCoeFepInputContext::applyFormat(QList<QInputMethodEvent::Attribute> *attributes)
+{
+ TCharFormat cFormat;
+ TInt numChars = 0;
+ TInt charPos = 0;
+ int oldSize = attributes->size();
+ while (m_formatRetriever) {
+ m_formatRetriever->GetFormatOfFepInlineText(cFormat, numChars, charPos);
+ if (numChars <= 0) {
+ // This shouldn't happen according to S60 docs, but apparently does sometimes.
+ break;
+ }
+ attributes->append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
+ charPos,
+ numChars,
+ QVariant(qt_TCharFormat2QTextCharFormat(cFormat))));
+ charPos += numChars;
+ if (charPos >= m_preeditString.size()) {
+ break;
+ }
+ }
+
+ if (attributes->size() == oldSize) {
+ // S60 didn't provide any format, so let's give our own instead.
+ attributes->append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
+ 0,
+ m_preeditString.size(),
+ standardFormat(PreeditFormat)));
+ }
+}
+
+void QCoeFepInputContext::queueInputCapabilitiesChanged()
+{
+ if (m_pendingInputCapabilitiesChanged)
+ return;
+
+ // Call ensureInputCapabilitiesChanged asynchronously. This is done to improve performance
+ // by not updating input capabilities too often. The reason we don't call the Symbian
+ // asynchronous version of InputCapabilitiesChanged is because we need to ensure that it
+ // is synchronous in some specific cases. Those will call ensureInputCapabilitesChanged.
+ QMetaObject::invokeMethod(this, "ensureInputCapabilitiesChanged", Qt::QueuedConnection);
+ m_pendingInputCapabilitiesChanged = true;
+}
+
+void QCoeFepInputContext::ensureInputCapabilitiesChanged()
+{
+ if (!m_pendingInputCapabilitiesChanged)
+ return;
+
+ // The call below is essentially equivalent to InputCapabilitiesChanged(),
+ // but is synchronous, rather than asynchronous.
+ CCoeEnv::Static()->SyncNotifyFocusObserversOfChangeInFocus();
+ m_pendingInputCapabilitiesChanged = false;
+}
+
+void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText,
+ TInt aPositionOfInsertionPointInInlineText, TBool aCursorVisibility, const MFormCustomDraw* /*aCustomDraw*/,
+ MFepInlineTextFormatRetriever& aInlineTextFormatRetriever,
+ MFepPointerEventHandlerDuringInlineEdit& aPointerEventHandlerDuringInlineEdit)
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ m_isEditing = true;
+
+ QList<QInputMethodEvent::Attribute> attributes;
+
+ m_cursorVisibility = aCursorVisibility ? 1 : 0;
+ m_inlinePosition = aPositionOfInsertionPointInInlineText;
+ m_preeditString = qt_TDesC2QStringL(aInitialInlineText);
+
+ m_formatRetriever = &aInlineTextFormatRetriever;
+ m_pointerHandler = &aPointerEventHandlerDuringInlineEdit;
+
+ applyFormat(&attributes);
+
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
+ m_inlinePosition,
+ m_cursorVisibility,
+ QVariant()));
+ QInputMethodEvent event(m_preeditString, attributes);
+ sendEvent(event);
+}
+
+void QCoeFepInputContext::UpdateFepInlineTextL(const TDesC& aNewInlineText,
+ TInt aPositionOfInsertionPointInInlineText)
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ m_inlinePosition = aPositionOfInsertionPointInInlineText;
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ applyFormat(&attributes);
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
+ m_inlinePosition,
+ m_cursorVisibility,
+ QVariant()));
+ m_preeditString = qt_TDesC2QStringL(aNewInlineText);
+ QInputMethodEvent event(m_preeditString, attributes);
+ sendEvent(event);
+}
+
+void QCoeFepInputContext::SetInlineEditingCursorVisibilityL(TBool aCursorVisibility)
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ m_cursorVisibility = aCursorVisibility ? 1 : 0;
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
+ m_inlinePosition,
+ m_cursorVisibility,
+ QVariant()));
+ QInputMethodEvent event(m_preeditString, attributes);
+ sendEvent(event);
+}
+
+void QCoeFepInputContext::CancelFepInlineEdit()
+{
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ event.setCommitString("", 0, 0);
+ m_preeditString.clear();
+ sendEvent(event);
+
+ m_isEditing = false;
+}
+
+TInt QCoeFepInputContext::DocumentLengthForFep() const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return 0;
+
+ QVariant variant = w->inputMethodQuery(Qt::ImSurroundingText);
+ return variant.value<QString>().size() + m_preeditString.size();
+}
+
+TInt QCoeFepInputContext::DocumentMaximumLengthForFep() const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return 0;
+
+ QVariant variant = w->inputMethodQuery(Qt::ImMaximumTextLength);
+ int size;
+ if (variant.isValid()) {
+ size = variant.toInt();
+ } else {
+ size = INT_MAX; // Sensible default for S60.
+ }
+ return size;
+}
+
+void QCoeFepInputContext::SetCursorSelectionForFepL(const TCursorSelection& aCursorSelection)
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ int pos = aCursorSelection.iAnchorPos;
+ int length = aCursorSelection.iCursorPos - pos;
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, pos, length, QVariant());
+ QInputMethodEvent event(m_preeditString, attributes);
+ sendEvent(event);
+}
+
+void QCoeFepInputContext::GetCursorSelectionForFep(TCursorSelection& aCursorSelection) const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ int cursor = w->inputMethodQuery(Qt::ImCursorPosition).toInt() + m_preeditString.size();
+ int anchor = w->inputMethodQuery(Qt::ImAnchorPosition).toInt() + m_preeditString.size();
+ aCursorSelection.iAnchorPos = anchor;
+ aCursorSelection.iCursorPos = cursor;
+}
+
+void QCoeFepInputContext::GetEditorContentForFep(TDes& aEditorContent, TInt aDocumentPosition,
+ TInt aLengthToRetrieve) const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ QString text = w->inputMethodQuery(Qt::ImSurroundingText).value<QString>();
+ // FEP expects the preedit string to be part of the editor content, so let's mix it in.
+ int cursor = w->inputMethodQuery(Qt::ImCursorPosition).toInt();
+ text.insert(cursor, m_preeditString);
+ aEditorContent.Copy(qt_QString2TPtrC(text.mid(aDocumentPosition, aLengthToRetrieve)));
+}
+
+void QCoeFepInputContext::GetFormatForFep(TCharFormat& aFormat, TInt /* aDocumentPosition */) const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ QFont font = w->inputMethodQuery(Qt::ImFont).value<QFont>();
+ QFontMetrics metrics(font);
+ //QString name = font.rawName();
+ QString name = font.defaultFamily(); // TODO! FIXME! Should be the above.
+ QHBufC hBufC(name);
+ aFormat = TCharFormat(hBufC->Des(), metrics.height());
+}
+
+void QCoeFepInputContext::GetScreenCoordinatesForFepL(TPoint& aLeftSideOfBaseLine, TInt& aHeight,
+ TInt& aAscent, TInt /* aDocumentPosition */) const
+{
+ QWidget *w = focusWidget();
+ if (!w)
+ return;
+
+ QRect rect = w->inputMethodQuery(Qt::ImMicroFocus).value<QRect>();
+ aLeftSideOfBaseLine.iX = rect.left();
+ aLeftSideOfBaseLine.iY = rect.bottom();
+
+ QFont font = w->inputMethodQuery(Qt::ImFont).value<QFont>();
+ QFontMetrics metrics(font);
+ aHeight = metrics.height();
+ aAscent = metrics.ascent();
+}
+
+void QCoeFepInputContext::DoCommitFepInlineEditL()
+{
+ commitCurrentString(true);
+}
+
+void QCoeFepInputContext::commitCurrentString(bool triggeredBySymbian)
+{
+ if (m_preeditString.size() == 0) {
+ return;
+ }
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ QInputMethodEvent event("", attributes);
+ event.setCommitString(m_preeditString, 0, 0);//m_preeditString.size());
+ m_preeditString.clear();
+ sendEvent(event);
+
+ m_isEditing = false;
+
+ if (!triggeredBySymbian) {
+ CCoeEnv::Static()->Fep()->CancelTransaction();
+ }
+}
+
+MCoeFepAwareTextEditor_Extension1* QCoeFepInputContext::Extension1(TBool& aSetToTrue)
+{
+ aSetToTrue = ETrue;
+ return this;
+}
+
+void QCoeFepInputContext::SetStateTransferingOwnershipL(MCoeFepAwareTextEditor_Extension1::CState* aState,
+ TUid /*aTypeSafetyUid*/)
+{
+ // Note: The S60 docs are wrong! See the State() function.
+ if (m_fepState)
+ delete m_fepState;
+ m_fepState = static_cast<CAknEdwinState *>(aState);
+}
+
+MCoeFepAwareTextEditor_Extension1::CState* QCoeFepInputContext::State(TUid /*aTypeSafetyUid*/)
+{
+ // Note: The S60 docs are horribly wrong when describing the
+ // SetStateTransferingOwnershipL function and this function. They say that the former
+ // sets a CState object identified by the TUid, and the latter retrieves it.
+ // In reality, the CState is expected to always be a CAknEdwinState (even if it was not
+ // previously set), and the TUid is ignored. All in all, there is a single CAknEdwinState
+ // per QCoeFepInputContext, which should be deleted if the SetStateTransferingOwnershipL
+ // function is used to set a new one.
+ return m_fepState;
+}
+
+TTypeUid::Ptr QCoeFepInputContext::MopSupplyObject(TTypeUid /*id*/)
+{
+ return TTypeUid::Null();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_IM
diff --git a/src/gui/inputmethod/qinputcontext.cpp b/src/gui/inputmethod/qinputcontext.cpp
index 77b0cda..0747f76 100644
--- a/src/gui/inputmethod/qinputcontext.cpp
+++ b/src/gui/inputmethod/qinputcontext.cpp
@@ -209,9 +209,21 @@ void QInputContext::setFocusWidget(QWidget *widget)
way. Although the input events have accept() and ignore()
methods, leave it untouched.
- \a event is currently restricted to QKeyEvent. But some input
- method related events such as QWheelEvent or QTabletEvent may be
- added in future.
+ \a event is currently restricted to events of these types:
+
+ \list
+ \i CloseSoftwareInputPanel
+ \i KeyPress
+ \i KeyRelease
+ \i MouseButtonDblClick
+ \i MouseButtonPress
+ \i MouseButtonRelease
+ \i MouseMove
+ \i RequestSoftwareInputPanel
+ \endlist
+
+ But some input method related events such as QWheelEvent or
+ QTabletEvent may be added in future.
The filtering opportunity is always given to the input context as
soon as possible. It has to be taken place before any other key
@@ -415,13 +427,6 @@ QTextFormat QInputContext::standardFormat(StandardFormat s) const
switch (s) {
case QInputContext::PreeditFormat: {
fmt.setUnderlineStyle(QTextCharFormat::DashUnderline);
-#ifndef Q_WS_WIN
- int h1, s1, v1, h2, s2, v2;
- pal.color(QPalette::Base).getHsv(&h1, &s1, &v1);
- pal.color(QPalette::Background).getHsv(&h2, &s2, &v2);
- bg.setHsv(h1, s1, (v1 + v2) / 2);
- fmt.setBackground(QBrush(bg));
-#endif
break;
}
case QInputContext::SelectionFormat: {
@@ -459,6 +464,31 @@ bool QInputContext::x11FilterEvent(QWidget * /*keywidget*/, XEvent * /*event*/)
}
#endif // Q_WS_X11
+#ifdef Q_WS_S60
+/*!
+ This function may be overridden only if input method is depending
+ on Symbian and you need raw TWsEvent. Otherwise, this function must not.
+
+ This function is designed to filter raw key events on S60, but
+ other input methods may use this to implement some special
+ features.
+
+ Return true if the \a event has been consumed. Otherwise, the
+ unfiltered \a event will be translated into QEvent and forwarded
+ to filterEvent(). Filtering at both s60FilterEvent() and
+ filterEvent() in single input method is allowed.
+
+ \a keywidget is a client widget into which a text is inputted. \a
+ event is inputted TWsEvent.
+
+ \sa filterEvent()
+*/
+bool QInputContext::s60FilterEvent(QWidget * /*keywidget*/, TWsEvent * /*event*/)
+{
+ return false;
+}
+#endif // Q_WS_S60
+
QT_END_NAMESPACE
#endif //Q_NO_IM
diff --git a/src/gui/inputmethod/qinputcontext.h b/src/gui/inputmethod/qinputcontext.h
index 1270d26..e4e5f9d 100644
--- a/src/gui/inputmethod/qinputcontext.h
+++ b/src/gui/inputmethod/qinputcontext.h
@@ -67,6 +67,10 @@
QT_BEGIN_HEADER
+#ifdef Q_WS_S60
+class TWsEvent;
+#endif
+
QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
@@ -76,7 +80,6 @@ class QFont;
class QPopupMenu;
class QInputContextPrivate;
-
class Q_GUI_EXPORT QInputContext : public QObject
{
Q_OBJECT
@@ -105,6 +108,9 @@ public:
#if defined(Q_WS_X11)
virtual bool x11FilterEvent( QWidget *keywidget, XEvent *event );
#endif // Q_WS_X11
+#if defined(Q_WS_S60)
+ virtual bool s60FilterEvent( QWidget *keywidget, TWsEvent *event );
+#endif // Q_WS_S60
virtual bool filterEvent( const QEvent *event );
void sendEvent(const QInputMethodEvent &event);
diff --git a/src/gui/inputmethod/qinputcontextfactory.cpp b/src/gui/inputmethod/qinputcontextfactory.cpp
index f11c1b8..5133b54 100644
--- a/src/gui/inputmethod/qinputcontextfactory.cpp
+++ b/src/gui/inputmethod/qinputcontextfactory.cpp
@@ -71,6 +71,9 @@
#ifdef Q_WS_MAC
#include "qmacinputcontext_p.h"
#endif
+#ifdef Q_WS_S60
+#include "qcoefepinputcontext_p.h"
+#endif
#include "private/qfactoryloader_p.h"
#include "qmutex.h"
@@ -145,6 +148,11 @@ QInputContext *QInputContextFactory::create( const QString& key, QObject *parent
result = new QMacInputContext;
}
#endif
+#if defined(Q_WS_S60)
+ if (key == QLatin1String("coefep")) {
+ result = new QCoeFepInputContext;
+ }
+#endif
#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
Q_UNUSED(key);
#else
@@ -182,6 +190,9 @@ QStringList QInputContextFactory::keys()
#if defined(Q_WS_MAC)
result << QLatin1String("mac");
#endif
+#if defined(Q_WS_S60)
+ result << QLatin1String("coefep");
+#endif
#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
result += loader()->keys();
#endif // QT_NO_LIBRARY
@@ -217,6 +228,10 @@ QStringList QInputContextFactory::languages( const QString &key )
if (key == QLatin1String("mac"))
return QStringList(QString());
#endif
+#if defined(Q_WS_S60)
+ if (key == QLatin1String("coefep"))
+ return QStringList(QString());
+#endif
#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
Q_UNUSED(key);
#else
@@ -241,6 +256,10 @@ QString QInputContextFactory::displayName( const QString &key )
if (key == QLatin1String("xim"))
return QInputContext::tr( "XIM" );
#endif
+#ifdef Q_WS_S60
+ if (key == QLatin1String("coefep"))
+ return QInputContext::tr( "FEP" );
+#endif
#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
Q_UNUSED(key);
#else
@@ -272,6 +291,10 @@ QString QInputContextFactory::description( const QString &key )
if (key == QLatin1String("mac"))
return QInputContext::tr( "Mac OS X input method" );
#endif
+#if defined(Q_WS_S60)
+ if (key == QLatin1String("coefep"))
+ return QInputContext::tr( "S60 FEP input method" );
+#endif
#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
Q_UNUSED(key);
#else
diff --git a/src/gui/inputmethod/qwininputcontext_win.cpp b/src/gui/inputmethod/qwininputcontext_win.cpp
index 741d8da..da7e84f 100644
--- a/src/gui/inputmethod/qwininputcontext_win.cpp
+++ b/src/gui/inputmethod/qwininputcontext_win.cpp
@@ -695,7 +695,12 @@ void QWinInputContext::updateImeStatus(QWidget *w, bool hasFocus)
{
if (!w)
return;
- bool e = w->testAttribute(Qt::WA_InputMethodEnabled) && w->isEnabled();
+ // It's always the proxy that carries the hints.
+ QWidget *focusProxyWidget = w->focusProxy();
+ if (!focusProxyWidget)
+ focusProxyWidget = w;
+ bool e = w->testAttribute(Qt::WA_InputMethodEnabled) && w->isEnabled()
+ && !(focusProxyWidget->inputMethodHints() & Qt::ImhExclusiveInputMask);
bool hasIme = e && hasFocus;
#ifdef Q_IME_DEBUG
qDebug("%s HasFocus = %d hasIme = %d e = %d ", w->className(), hasFocus, hasIme, e);
diff --git a/src/gui/inputmethod/qximinputcontext_x11.cpp b/src/gui/inputmethod/qximinputcontext_x11.cpp
index 9b21163..edc6904 100644
--- a/src/gui/inputmethod/qximinputcontext_x11.cpp
+++ b/src/gui/inputmethod/qximinputcontext_x11.cpp
@@ -611,7 +611,7 @@ void QXIMInputContext::setFocusWidget(QWidget *w)
QInputContext::setFocusWidget(w);
- if (!w)
+ if (!w || w->inputMethodHints() & Qt::ImhExclusiveInputMask)
return;
ICData *data = ximData.value(w->effectiveWinId());
diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp
index 8887977..759ee1a 100644
--- a/src/gui/itemviews/qabstractitemview.cpp
+++ b/src/gui/itemviews/qabstractitemview.cpp
@@ -61,6 +61,7 @@
#ifndef QT_NO_ACCESSIBILITY
#include <qaccessible.h>
#endif
+#include <private/qactiontokeyeventmapper_p.h>
QT_BEGIN_NAMESPACE
@@ -2007,15 +2008,18 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
if (QApplication::keypadNavigationEnabled()) {
if (!hasEditFocus()) {
setEditFocus(true);
+ QActionToKeyEventMapper::addSoftKey(QAction::BackSoftKey, Qt::Key_Back, this);
return;
}
}
break;
case Qt::Key_Back:
- if (QApplication::keypadNavigationEnabled() && hasEditFocus())
+ if (QApplication::keypadNavigationEnabled() && hasEditFocus()) {
+ QActionToKeyEventMapper::removeSoftkey(this);
setEditFocus(false);
- else
+ } else {
event->ignore();
+ }
return;
default:
if (QApplication::keypadNavigationEnabled() && !hasEditFocus()) {
diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h
index 557e98b..f90e0fe 100644
--- a/src/gui/itemviews/qabstractitemview_p.h
+++ b/src/gui/itemviews/qabstractitemview_p.h
@@ -312,7 +312,7 @@ public:
*/
inline bool isPersistent(const QModelIndex &index) const
{
- return static_cast<QAbstractItemModelPrivate *>(model->d_ptr)->persistent.indexes.contains(index);
+ return static_cast<QAbstractItemModelPrivate *>(model->d_ptr.data())->persistent.indexes.contains(index);
}
QModelIndexList selectedDraggableIndexes() const;
diff --git a/src/gui/itemviews/qcolumnview_p.h b/src/gui/itemviews/qcolumnview_p.h
index 3f99220..7b4f774 100644
--- a/src/gui/itemviews/qcolumnview_p.h
+++ b/src/gui/itemviews/qcolumnview_p.h
@@ -55,7 +55,7 @@
#include "qcolumnview.h"
-#ifndef QT_NO_QCOlUMNVIEW
+#ifndef QT_NO_QCOLUMNVIEW
#include <private/qabstractitemview_p.h>
diff --git a/src/gui/itemviews/qdirmodel.cpp b/src/gui/itemviews/qdirmodel.cpp
index c5618b6..5d7d1ff 100644
--- a/src/gui/itemviews/qdirmodel.cpp
+++ b/src/gui/itemviews/qdirmodel.cpp
@@ -872,8 +872,10 @@ QModelIndex QDirModel::index(const QString &path, int column) const
return QModelIndex();
QString absolutePath = QDir(path).absolutePath();
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
absolutePath = absolutePath.toLower();
+#endif
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
// On Windows, "filename......." and "filename" are equivalent
if (absolutePath.endsWith(QLatin1Char('.'))) {
int i;
@@ -913,7 +915,10 @@ QModelIndex QDirModel::index(const QString &path, int column) const
pathElements.pop_front();
if (childAppended)
emit const_cast<QDirModel*>(this)->layoutChanged();
- } else if (pathElements.at(0).endsWith(QLatin1Char(':'))) {
+ } else
+#endif
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
+ if (pathElements.at(0).endsWith(QLatin1Char(':'))) {
pathElements[0] += QLatin1Char('/');
}
#else
@@ -935,11 +940,9 @@ QModelIndex QDirModel::index(const QString &path, int column) const
for (int j = parent->children.count() - 1; j >= 0; --j) {
const QFileInfo& fi = parent->children.at(j).info;
QString childFileName;
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
childFileName = idx.isValid() ? fi.fileName() : fi.absoluteFilePath();
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
childFileName = childFileName.toLower();
-#else
- childFileName = idx.isValid() ? fi.fileName() : fi.absoluteFilePath();
#endif
if (childFileName == element) {
if (i == pathElements.count() - 1)
@@ -956,7 +959,7 @@ QModelIndex QDirModel::index(const QString &path, int column) const
if (parent->info.isRoot())
newPath = parent->info.absoluteFilePath() + element;
else
- newPath= parent->info.absoluteFilePath() + QLatin1Char('/') + element;
+ newPath = parent->info.absoluteFilePath() + QLatin1Char('/') + element;
#else
QString newPath = parent->info.absoluteFilePath() + QLatin1Char('/') + element;
#endif
@@ -1308,6 +1311,8 @@ QString QDirModelPrivate::name(const QModelIndex &index) const
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
if (name.startsWith(QLatin1Char('/'))) // UNC host
return info.fileName();
+#endif
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
if (name.endsWith(QLatin1Char('/')))
name.chop(1);
#endif
diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp
index dd4341b..b9df4fc 100644
--- a/src/gui/itemviews/qfileiconprovider.cpp
+++ b/src/gui/itemviews/qfileiconprovider.cpp
@@ -179,7 +179,6 @@ QFileIconProvider::QFileIconProvider()
QFileIconProvider::~QFileIconProvider()
{
- delete d_ptr;
}
/*!
diff --git a/src/gui/itemviews/qfileiconprovider.h b/src/gui/itemviews/qfileiconprovider.h
index 7f587f4..165e30f 100644
--- a/src/gui/itemviews/qfileiconprovider.h
+++ b/src/gui/itemviews/qfileiconprovider.h
@@ -42,8 +42,9 @@
#ifndef QFILEICONPROVIDER_H
#define QFILEICONPROVIDER_H
-#include <QtGui/qicon.h>
#include <QtCore/qfileinfo.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtGui/qicon.h>
QT_BEGIN_HEADER
@@ -67,7 +68,7 @@ public:
private:
Q_DECLARE_PRIVATE(QFileIconProvider)
- QFileIconProviderPrivate *d_ptr;
+ QScopedPointer<QFileIconProviderPrivate> d_ptr;
Q_DISABLE_COPY(QFileIconProvider)
};
diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp
index 2419c18..750e20b 100644
--- a/src/gui/itemviews/qheaderview.cpp
+++ b/src/gui/itemviews/qheaderview.cpp
@@ -2821,16 +2821,12 @@ void QHeaderViewPrivate::setupSectionIndicator(int section, int position)
sectionIndicator = new QLabel(viewport);
}
- int x, y, w, h;
+ int w, h;
int p = q->sectionViewportPosition(section);
if (orientation == Qt::Horizontal) {
- x = p;
- y = 0;
w = q->sectionSize(section);
h = viewport->height();
} else {
- x = 0;
- y = p;
w = viewport->width();
h = q->sectionSize(section);
}
@@ -3561,7 +3557,7 @@ bool QHeaderViewPrivate::read(QDataStream &in)
in >> minimumSectionSize;
in >> align;
- defaultAlignment = (Qt::Alignment)align;
+ defaultAlignment = Qt::Alignment(align);
in >> global;
globalResizeMode = (QHeaderView::ResizeMode)global;
diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp
index 336ca79..6bcc153 100644
--- a/src/gui/itemviews/qitemdelegate.cpp
+++ b/src/gui/itemviews/qitemdelegate.cpp
@@ -1322,7 +1322,7 @@ QStyleOptionViewItem QItemDelegate::setOptions(const QModelIndex &index,
// set text alignment
value = index.data(Qt::TextAlignmentRole);
if (value.isValid())
- opt.displayAlignment = (Qt::Alignment)value.toInt();
+ opt.displayAlignment = Qt::Alignment(value.toInt());
// set foreground brush
value = index.data(Qt::ForegroundRole);
diff --git a/src/gui/itemviews/qstandarditemmodel.cpp b/src/gui/itemviews/qstandarditemmodel.cpp
index e71d8f9..b960fae 100644
--- a/src/gui/itemviews/qstandarditemmodel.cpp
+++ b/src/gui/itemviews/qstandarditemmodel.cpp
@@ -778,8 +778,6 @@ QStandardItem &QStandardItem::operator=(const QStandardItem &other)
*/
QStandardItem::~QStandardItem()
{
- Q_D(QStandardItem);
- delete d;
}
/*!
@@ -899,7 +897,7 @@ Qt::ItemFlags QStandardItem::flags() const
if (!v.isValid())
return (Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsEditable
|Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled);
- return ((Qt::ItemFlags)(v.toInt()));
+ return Qt::ItemFlags(v.toInt());
}
/*!
@@ -1896,7 +1894,7 @@ void QStandardItem::read(QDataStream &in)
in >> d->values;
qint32 flags;
in >> flags;
- setFlags((Qt::ItemFlags)flags);
+ setFlags(Qt::ItemFlags(flags));
}
/*!
diff --git a/src/gui/itemviews/qstandarditemmodel.h b/src/gui/itemviews/qstandarditemmodel.h
index c624615..c470b80 100644
--- a/src/gui/itemviews/qstandarditemmodel.h
+++ b/src/gui/itemviews/qstandarditemmodel.h
@@ -240,7 +240,7 @@ protected:
QStandardItem(const QStandardItem &other);
QStandardItem(QStandardItemPrivate &dd);
QStandardItem &operator=(const QStandardItem &other);
- QStandardItemPrivate *d_ptr;
+ QScopedPointer<QStandardItemPrivate> d_ptr;
void emitDataChanged();
diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp
index bd8fdac..df519ee 100644
--- a/src/gui/itemviews/qstyleditemdelegate.cpp
+++ b/src/gui/itemviews/qstyleditemdelegate.cpp
@@ -322,7 +322,7 @@ void QStyledItemDelegate::initStyleOption(QStyleOptionViewItem *option,
value = index.data(Qt::TextAlignmentRole);
if (value.isValid() && !value.isNull())
- option->displayAlignment = (Qt::Alignment)value.toInt();
+ option->displayAlignment = Qt::Alignment(value.toInt());
value = index.data(Qt::ForegroundRole);
if (qVariantCanConvert<QBrush>(value))
diff --git a/src/gui/itemviews/qtreewidget.cpp b/src/gui/itemviews/qtreewidget.cpp
index ccfa568..7dded8d 100644
--- a/src/gui/itemviews/qtreewidget.cpp
+++ b/src/gui/itemviews/qtreewidget.cpp
@@ -853,7 +853,7 @@ void QTreeModel::sortItems(QList<QTreeWidgetItem*> *items, int column, Qt::SortO
items->replace(r, item);
for (int c = 0; c < colCount; ++c) {
QModelIndex from = createIndex(oldRow, c, item);
- if (static_cast<QAbstractItemModelPrivate *>(d_ptr)->persistent.indexes.contains(from)) {
+ if (static_cast<QAbstractItemModelPrivate *>(d_ptr.data())->persistent.indexes.contains(from)) {
QModelIndex to = createIndex(r, c, item);
fromList << from;
toList << to;
diff --git a/src/gui/itemviews/qtreewidgetitemiterator.cpp b/src/gui/itemviews/qtreewidgetitemiterator.cpp
index 14aca3a..b6f56a0 100644
--- a/src/gui/itemviews/qtreewidgetitemiterator.cpp
+++ b/src/gui/itemviews/qtreewidgetitemiterator.cpp
@@ -97,7 +97,7 @@ QTreeWidgetItemIterator::QTreeWidgetItemIterator(QTreeWidget *widget, IteratorFl
Q_ASSERT(widget);
QTreeModel *model = qobject_cast<QTreeModel*>(widget->model());
Q_ASSERT(model);
- d_ptr = new QTreeWidgetItemIteratorPrivate(this, model);
+ d_ptr.reset(new QTreeWidgetItemIteratorPrivate(this, model));
model->iterators.append(this);
if (!model->rootItem->children.isEmpty()) current = model->rootItem->children.first();
if (current && !matchesFlags(current))
@@ -150,7 +150,6 @@ QTreeWidgetItemIterator::QTreeWidgetItemIterator(QTreeWidgetItem *item, Iterator
QTreeWidgetItemIterator::~QTreeWidgetItemIterator()
{
d_func()->m_model->iterators.removeAll(this);
- delete d_ptr;
}
/*!
diff --git a/src/gui/itemviews/qtreewidgetitemiterator.h b/src/gui/itemviews/qtreewidgetitemiterator.h
index 0c07284..eff9fdb 100644
--- a/src/gui/itemviews/qtreewidgetitemiterator.h
+++ b/src/gui/itemviews/qtreewidgetitemiterator.h
@@ -43,6 +43,7 @@
#define QTREEWIDGETITEMITERATOR_H
#include <QtCore/qglobal.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
@@ -105,7 +106,7 @@ public:
private:
bool matchesFlags(const QTreeWidgetItem *item) const;
- QTreeWidgetItemIteratorPrivate *d_ptr;
+ QScopedPointer<QTreeWidgetItemIteratorPrivate> d_ptr;
QTreeWidgetItem *current;
IteratorFlags flags;
Q_DECLARE_PRIVATE(QTreeWidgetItemIterator)
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index e6eff6e..530b146 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -96,6 +96,27 @@ win32 {
!contains(DEFINES, QT_NO_DIRECTDRAW):LIBS += ddraw.lib
}
+symbian {
+ SOURCES += \
+ kernel/qapplication_s60.cpp \
+ kernel/qeventdispatcher_s60.cpp \
+ kernel/qwidget_s60.cpp \
+ kernel/qcursor_s60.cpp \
+ kernel/qdesktopwidget_s60.cpp \
+ kernel/qkeymapper_s60.cpp\
+ kernel/qclipboard_s60.cpp\
+ kernel/qdnd_s60.cpp \
+ kernel/qsound_s60.cpp
+
+ HEADERS += \
+ kernel/qt_s60_p.h \
+ kernel/qeventdispatcher_s60_p.h
+ LIBS += -lbafl -lestor
+
+ INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE
+}
+
+
unix:x11 {
INCLUDEPATH += ../3rdparty/xorg
HEADERS += \
diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp
index e7cb5c2..afe6269 100644
--- a/src/gui/kernel/qaction.cpp
+++ b/src/gui/kernel/qaction.cpp
@@ -81,7 +81,8 @@ static QString qt_strippedText(QString s)
QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0),
visible(1), forceInvisible(0), checkable(0), checked(0), separator(0), fontSet(false),
- menuRole(QAction::TextHeuristicRole), priority(QAction::NormalPriority), iconVisibleInMenu(-1)
+ menuRole(QAction::TextHeuristicRole), softKeyRole(QAction::OptionsSoftKey),
+ priority(QAction::NormalPriority), iconVisibleInMenu(-1)
{
#ifdef QT3_SUPPORT
static int qt_static_action_id = -1;
@@ -1407,6 +1408,32 @@ QAction::MenuRole QAction::menuRole() const
}
/*!
+ \property QAction::softKeyRole
+ \brief the action's softkey role
+ \since 4.6
+
+ This indicates what softkey action this action is. Usually used on mobile
+ platforms to map QActions to hardware keys.
+
+ The softkey role can be changed any time.
+*/
+void QAction::setSoftKeyRole(SoftKeyRole softKeyRole)
+{
+ Q_D(QAction);
+ if (d->softKeyRole == softKeyRole)
+ return;
+
+ d->softKeyRole = softKeyRole;
+ d->sendDataChanged();
+}
+
+QAction::SoftKeyRole QAction::softKeyRole() const
+{
+ Q_D(const QAction);
+ return d->softKeyRole;
+}
+
+/*!
\property QAction::iconVisibleInMenu
\brief Whether or not an action should show an icon in a menu
\since 4.4
diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h
index 133fab4..3fd80b9 100644
--- a/src/gui/kernel/qaction.h
+++ b/src/gui/kernel/qaction.h
@@ -67,6 +67,7 @@ class Q_GUI_EXPORT QAction : public QObject
Q_DECLARE_PRIVATE(QAction)
Q_ENUMS(MenuRole)
+ Q_ENUMS(SoftKeyRole)
Q_ENUMS(Priority)
Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable)
Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled)
@@ -85,12 +86,17 @@ class Q_GUI_EXPORT QAction : public QObject
#endif
Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole)
+ Q_PROPERTY(SoftKeyRole softKeyRole READ softKeyRole WRITE setSoftKeyRole)
Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu)
Q_PROPERTY(Priority priority READ priority WRITE setPriority)
public:
enum MenuRole { NoRole, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole,
AboutRole, PreferencesRole, QuitRole };
+ enum SoftKeyRole { OptionsSoftKey, SelectSoftKey, BackSoftKey, NextSoftKey, PreviousSoftKey,
+ OkSoftKey, CancelSoftKey, EditSoftKey, ViewSoftKey, BackSpaceSoftKey,
+ EndEditSoftKey, RevertEditSoftKey, DeselectSoftKey, FinishSoftKey,
+ MenuSoftKey, ContextMenuSoftKey, ExitSoftKey };
enum Priority { LowPriority = 0,
NormalPriority = 128,
HighPriority = 256};
@@ -176,6 +182,9 @@ public:
void setMenuRole(MenuRole menuRole);
MenuRole menuRole() const;
+ void setSoftKeyRole(SoftKeyRole softKeyRole);
+ SoftKeyRole softKeyRole() const;
+
void setIconVisibleInMenu(bool visible);
bool isIconVisibleInMenu() const;
diff --git a/src/gui/kernel/qaction_p.h b/src/gui/kernel/qaction_p.h
index 4745ed1..4e3651e 100644
--- a/src/gui/kernel/qaction_p.h
+++ b/src/gui/kernel/qaction_p.h
@@ -102,6 +102,7 @@ public:
uint separator : 1;
uint fontSet : 1;
QAction::MenuRole menuRole;
+ QAction::SoftKeyRole softKeyRole;
QAction::Priority priority;
int iconVisibleInMenu : 3; // Only has values -1, 0, and 1
QList<QWidget *> widgets;
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 3453408..700af43 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -74,6 +74,9 @@
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
+#endif
+
+#if defined(Q_WS_X11) || defined(Q_WS_S60)
#include "qinputcontextfactory.h"
#endif
@@ -133,6 +136,8 @@ bool QApplicationPrivate::quitOnLastWindowClosed = true;
#ifdef Q_WS_WINCE
int QApplicationPrivate::autoMaximizeThreshold = -1;
bool QApplicationPrivate::autoSipEnabled = false;
+#else
+bool QApplicationPrivate::autoSipEnabled = true;
#endif
QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type)
@@ -431,7 +436,12 @@ bool Q_GUI_EXPORT qt_tab_all_widgets = true;
bool qt_in_tab_key_event = false;
int qt_antialiasing_threshold = -1;
static int drag_time = 500;
+#ifdef Q_OS_SYMBIAN
+// The screens are a bit too small to for your thumb when using only 4 pixels drag distance.
+static int drag_distance = 8;
+#else
static int drag_distance = 4;
+#endif
static Qt::LayoutDirection layout_direction = Qt::LeftToRight;
QSize QApplicationPrivate::app_strut = QSize(0,0); // no default application strut
bool QApplicationPrivate::animate_ui = true;
@@ -442,11 +452,16 @@ bool QApplicationPrivate::animate_tooltip = false;
bool QApplicationPrivate::fade_tooltip = false;
bool QApplicationPrivate::animate_toolbox = false;
bool QApplicationPrivate::widgetCount = false;
+bool QApplicationPrivate::auto_sip_on_mouse_focus = false;
#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
bool QApplicationPrivate::inSizeMove = false;
#endif
#ifdef QT_KEYPAD_NAVIGATION
+# if defined(Q_OS_SYMBIAN)
+bool QApplicationPrivate::keypadNavigation = true;
+# else
bool QApplicationPrivate::keypadNavigation = false;
+# endif
QWidget *QApplicationPrivate::oldEditFocus = 0;
#endif
@@ -982,7 +997,8 @@ QApplication::~QApplication()
if (QWidgetPrivate::mapper) {
QWidgetMapper * myMapper = QWidgetPrivate::mapper;
QWidgetPrivate::mapper = 0;
- for (QWidgetMapper::Iterator it = myMapper->begin(); it != myMapper->end(); ++it) {
+ for (QWidgetMapper::ConstIterator it = myMapper->constBegin();
+ it != myMapper->constEnd(); ++it) {
register QWidget *w = *it;
if (!w->parent()) // window
w->destroy(true, true);
@@ -994,7 +1010,7 @@ QApplication::~QApplication()
if (QWidgetPrivate::uncreatedWidgets) {
QWidgetSet *mySet = QWidgetPrivate::uncreatedWidgets;
QWidgetPrivate::uncreatedWidgets = 0;
- for (QWidgetSet::Iterator it = mySet->begin(); it != mySet->end(); ++it) {
+ for (QWidgetSet::ConstIterator it = mySet->constBegin(); it != mySet->constEnd(); ++it) {
register QWidget *w = *it;
if (!w->parent()) // window
w->destroy(true, true);
@@ -1061,6 +1077,7 @@ QApplication::~QApplication()
QApplicationPrivate::animate_tooltip = false;
QApplicationPrivate::fade_tooltip = false;
QApplicationPrivate::widgetCount = false;
+ QApplicationPrivate::auto_sip_on_mouse_focus = false;
#ifndef QT_NO_STATEMACHINE
// trigger unregistering of QStateMachine's GUI types
@@ -1216,11 +1233,15 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis
\since 4.5
\brief toggles automatic SIP (software input panel) visibility
- The auto SIP property is only available as part of Qt for Windows CE.
-
Set this property to true to automatically display the SIP when entering
widgets that accept keyboard input. This property only affects widgets with
- the WA_InputMethodEnabled attribute set.
+ the WA_InputMethodEnabled attribute set, and is typically used to launch
+ a virtual keyboard on devices which have very few or no keys.
+
+ The property only has an effect on platforms which use software input
+ panels, such as Windows CE and Symbian.
+
+ The default is platform dependent.
*/
#ifdef Q_WS_WINCE
@@ -1233,6 +1254,7 @@ int QApplication::autoMaximizeThreshold() const
{
return QApplicationPrivate::autoMaximizeThreshold;
}
+#endif
void QApplication::setAutoSipEnabled(const bool enabled)
{
@@ -1243,7 +1265,6 @@ bool QApplication::autoSipEnabled() const
{
return QApplicationPrivate::autoSipEnabled;
}
-#endif
#ifndef QT_NO_STYLE_STYLESHEET
@@ -1925,6 +1946,10 @@ QString desktopstyle;
desktopstyle = QLatin1String("Windows"); // default styles for Windows
#elif defined(Q_WS_X11) && defined(Q_OS_SOLARIS)
desktopstyle = QLatin1String("CDE"); // default style for X11 on Solaris
+#elif defined(Q_WS_S60)
+ desktopstyle = QLatin1String("S60"); // default style for Symbian with S60
+#elif defined(Q_OS_SYMBIAN)
+ desktopstyle = QLatin1String("Windows"); // default style for Symbian without S60
#elif defined(Q_WS_X11) && defined(Q_OS_IRIX)
desktopstyle = QLatin1String("SGI"); // default style for X11 on IRIX
#elif defined(Q_WS_QWS)
@@ -2079,6 +2104,16 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
prev->setEditFocus(false);
}
#endif
+#ifndef QT_NO_IM
+ if (focus) {
+ QInputContext *prevIc;
+ prevIc = prev->inputContext();
+ if (prevIc && prevIc != focus->inputContext()) {
+ QEvent closeSIPEvent(QEvent::CloseSoftwareInputPanel);
+ QApplication::sendEvent(prev, &closeSIPEvent);
+ }
+ }
+#endif
QFocusEvent out(QEvent::FocusOut, reason);
QPointer<QWidget> that = prev;
QApplication::sendEvent(prev, &out);
@@ -3436,6 +3471,39 @@ Qt::LayoutDirection QApplication::layoutDirection()
return layout_direction;
}
+/*!
+ \property autoSipOnMouseFocus
+ \since 4.6
+ \brief toggles SIP (software input panel) launch policy
+
+ This property holds whether widgets should request a software input
+ panel when it is focused with the mouse. This is typically used to
+ launch a virtual keyboard on devices which have very few or no keys.
+
+ If the property is set to true, the widget asks for an input panel
+ on the mouse click which causes the widget to be focused. If the
+ property is set to false, the user must click a second time before
+ the widget asks for an input panel.
+
+ \note If the widget is focused by other means than a mouse click,
+ the next click is will trigger an input panel request,
+ regardless of the value of this property.
+
+ The default is platform dependent.
+
+ \sa QEvent::RequestSoftwareInputPanel, QInputContext
+*/
+
+void QApplication::setAutoSipOnMouseFocus(bool enable)
+{
+ QApplicationPrivate::auto_sip_on_mouse_focus = enable;
+}
+
+bool QApplication::autoSipOnMouseFocus()
+{
+ return QApplicationPrivate::auto_sip_on_mouse_focus;
+}
+
/*!
\obsolete
@@ -3712,6 +3780,14 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QPoint relpos = mouse->pos();
if (e->spontaneous()) {
+#ifndef QT_NO_IM
+ QInputContext *ic = w->inputContext();
+ if (ic
+ && w->testAttribute(Qt::WA_InputMethodEnabled)
+ && ic->filterEvent(mouse))
+ return true;
+#endif
+
if (e->type() == QEvent::MouseButtonPress) {
QApplicationPrivate::giveFocusAccordingToFocusPolicy(w,
Qt::ClickFocus,
@@ -4050,6 +4126,20 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
touchEvent->setAccepted(eventAccepted);
break;
}
+ case QEvent::RequestSoftwareInputPanel:
+ case QEvent::CloseSoftwareInputPanel:
+#ifndef QT_NO_IM
+ if (receiver->isWidgetType()) {
+ QWidget *w = static_cast<QWidget *>(receiver);
+ QInputContext *ic = w->inputContext();
+ if (ic && ic->filterEvent(e)) {
+ break;
+ }
+ }
+#endif
+ res = d->notify_helper(receiver, e);
+ break;
+
case QEvent::WinGesture:
{
// only propagate the first gesture event (after the GID_BEGIN)
@@ -4724,7 +4814,7 @@ void QApplicationPrivate::emitLastWindowClosed()
If \a enable is true, Qt::Key_Up and Qt::Key_Down are used to change focus.
- This feature is available in Qt for Embedded Linux only.
+ This feature is available in Qt for Embedded Linux and Symbian only.
\sa keypadNavigationEnabled()
*/
@@ -4735,9 +4825,9 @@ void QApplication::setKeypadNavigationEnabled(bool enable)
/*!
Returns true if Qt is set to use keypad navigation; otherwise returns
- false. The default is false.
+ false. The default value is true on Symbian, but false on other platforms.
- This feature is available in Qt for Embedded Linux only.
+ This feature is available in Qt for Embedded Linux and Symbian only.
\sa setKeypadNavigationEnabled()
*/
@@ -4794,8 +4884,8 @@ bool QApplication::keypadNavigationEnabled()
The default value on X11 is 400 milliseconds. On Windows and Mac OS X, the
operating system's value is used.
- On Microsoft Windows, calling this function sets the double click interval
- for all applications.
+ On Microsoft Windows and Symbian, calling this function sets the
+ double click interval for all applications.
*/
/*!
@@ -4953,8 +5043,7 @@ void QApplication::setInputContext(QInputContext *inputContext)
qWarning("QApplication::setInputContext: called with 0 input context");
return;
}
- if (d->inputContext)
- delete d->inputContext;
+ delete d->inputContext;
d->inputContext = inputContext;
}
@@ -4978,6 +5067,11 @@ QInputContext *QApplication::inputContext() const
qic = QInputContextFactory::create(QLatin1String("xim"), that);
that->d_func()->inputContext = qic;
}
+#elif defined(Q_WS_S60)
+ if (!d->inputContext) {
+ QApplication *that = const_cast<QApplication *>(this);
+ that->d_func()->inputContext = QInputContextFactory::create(QString::fromLatin1("coefep"), that);
+ }
#endif
return d->inputContext;
}
@@ -4995,6 +5089,8 @@ uint QApplicationPrivate::currentPlatform(){
platform |= KB_Gnome;
if (X11->desktopEnvironment == DE_CDE)
platform |= KB_CDE;
+#elif defined(Q_OS_SYMBIAN)
+ platform = KB_S60;
#endif
return platform;
}
diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h
index 19ae085..fcb3a7c 100644
--- a/src/gui/kernel/qapplication.h
+++ b/src/gui/kernel/qapplication.h
@@ -61,6 +61,10 @@
QT_BEGIN_HEADER
+#if defined(Q_OS_SYMBIAN)
+class TWsEvent;
+#endif
+
QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
@@ -84,6 +88,7 @@ class QApplicationPrivate;
#endif
#define qApp (static_cast<QApplication *>(QCoreApplication::instance()))
+
class Q_GUI_EXPORT QApplication : public QCoreApplication
{
Q_OBJECT
@@ -92,6 +97,8 @@ class Q_GUI_EXPORT QApplication : public QCoreApplication
Q_PROPERTY(int cursorFlashTime READ cursorFlashTime WRITE setCursorFlashTime)
Q_PROPERTY(int doubleClickInterval READ doubleClickInterval WRITE setDoubleClickInterval)
Q_PROPERTY(int keyboardInputInterval READ keyboardInputInterval WRITE setKeyboardInputInterval)
+ Q_PROPERTY(bool autoSipOnMouseFocus READ autoSipOnMouseFocus
+ WRITE setAutoSipOnMouseFocus)
#ifndef QT_NO_WHEELEVENT
Q_PROPERTY(int wheelScrollLines READ wheelScrollLines WRITE setWheelScrollLines)
#endif
@@ -104,8 +111,8 @@ class Q_GUI_EXPORT QApplication : public QCoreApplication
#endif
#ifdef Q_WS_WINCE
Q_PROPERTY(int autoMaximizeThreshold READ autoMaximizeThreshold WRITE setAutoMaximizeThreshold)
- Q_PROPERTY(bool autoSipEnabled READ autoSipEnabled WRITE setAutoSipEnabled)
#endif
+ Q_PROPERTY(bool autoSipEnabled READ autoSipEnabled WRITE setAutoSipEnabled)
public:
enum Type { Tty, GuiClient, GuiServer };
@@ -223,6 +230,12 @@ public:
virtual int x11ClientMessage(QWidget*, XEvent*, bool passive_only);
int x11ProcessEvent(XEvent*);
#endif
+#if defined(Q_OS_SYMBIAN)
+ int s60ProcessEvent(TWsEvent *event);
+ virtual bool s60EventFilter(TWsEvent *aEvent);
+ void symbianHandleCommand(int command);
+ void symbianResourceChange(int type);
+#endif
#if defined(Q_WS_QWS)
virtual bool qwsEventFilter(QWSEvent *);
int qwsProcessEvent(QWSEvent*);
@@ -239,7 +252,6 @@ public:
void winFocus(QWidget *, bool);
static void winMouseButtonUp();
#endif
-
#ifndef QT_NO_SESSIONMANAGER
// session management
bool isSessionRestored() const;
@@ -284,9 +296,11 @@ public Q_SLOTS:
#ifdef Q_WS_WINCE
void setAutoMaximizeThreshold(const int threshold);
int autoMaximizeThreshold() const;
+#endif
void setAutoSipEnabled(const bool enabled);
bool autoSipEnabled() const;
-#endif
+ void setAutoSipOnMouseFocus(bool);
+ bool autoSipOnMouseFocus();
static void closeAllWindows();
static void aboutQt();
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 595f220..0cd93b9 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -100,6 +100,7 @@ extern QSysInfo::MacVersion qt_macver;
#if defined(Q_WS_QWS)
class QWSManager;
class QDirectPainter;
+struct QWSServerCleaner { ~QWSServerCleaner(); };
#endif
#ifndef QT_NO_TABLET
@@ -294,8 +295,8 @@ public:
static void emitLastWindowClosed();
#ifdef Q_WS_WINCE
static int autoMaximizeThreshold;
- static bool autoSipEnabled;
#endif
+ static bool autoSipEnabled;
static QString desktopStyleKey();
static QGraphicsSystem *graphicsSystem()
@@ -307,7 +308,6 @@ public:
void createEventDispatcher();
QString appName() const;
-
static void dispatchEnterLeave(QWidget *enter, QWidget *leave);
//modality
@@ -344,6 +344,7 @@ public:
KB_KDE = 8,
KB_Gnome = 16,
KB_CDE = 32,
+ KB_S60 = 64,
KB_All = 0xffff
};
@@ -429,6 +430,7 @@ public:
static bool fade_tooltip;
static bool animate_toolbox;
static bool widgetCount; // Coupled with -widgetcount switch
+ static bool auto_sip_on_mouse_focus;
#ifdef Q_WS_MAC
static bool native_modal_dialog_active;
#endif
@@ -456,6 +458,7 @@ public:
#ifdef Q_WS_QWS
QPointer<QWSManager> last_manager;
+ QWSServerCleaner qwsServerCleaner;
# ifndef QT_NO_DIRECTPAINTER
QMap<WId, QDirectPainter *> *directPainters;
# endif
@@ -495,6 +498,9 @@ public:
static bool sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget,
QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
bool spontaneous = true);
+#ifdef Q_OS_SYMBIAN
+ static TUint resolveS60ScanCode(TInt scanCode, TUint keysym);
+#endif
#if defined(Q_WS_WIN) || defined(Q_WS_X11)
void sendSyntheticEnterLeave(QWidget *widget);
#endif
@@ -559,6 +565,10 @@ private:
QMap<const QScreen*, QRect> maxWindowRects;
#endif
+#ifdef Q_OS_SYMBIAN
+ static QHash<TInt, TUint> scanCodeCache;
+#endif
+
static QApplicationPrivate *self;
static void giveFocusAccordingToFocusPolicy(QWidget *w,
diff --git a/src/gui/kernel/qapplication_qws.cpp b/src/gui/kernel/qapplication_qws.cpp
index 347afc8..83b2861 100644
--- a/src/gui/kernel/qapplication_qws.cpp
+++ b/src/gui/kernel/qapplication_qws.cpp
@@ -159,6 +159,8 @@ bool qws_overrideCursor = false;
#ifndef QT_NO_QWS_MANAGER
#include "qdecorationfactory_qws.h"
+extern Q_GUI_EXPORT QWSServer *qwsServer;
+
QT_BEGIN_NAMESPACE
QT_USE_NAMESPACE
@@ -485,8 +487,13 @@ QList<QWSCommand*> *qt_get_server_queue()
void qt_server_enqueue(const QWSCommand *command)
{
QWSCommand *copy = QWSCommand::factory(command->type);
- copy->copyFrom(command);
- outgoing.append(copy);
+ QT_TRY {
+ copy->copyFrom(command);
+ outgoing.append(copy);
+ } QT_CATCH(...) {
+ delete copy;
+ QT_RETHROW;
+ }
}
QWSDisplay::Data::Data(QObject* parent, bool singleProcess)
@@ -2300,7 +2307,7 @@ void qt_init(QApplicationPrivate *priv, int type)
qws_decoration = QApplication::qwsSetDecoration(decoration);
#endif // QT_NO_QWS_MANAGER
#ifndef QT_NO_QWS_INPUTMETHODS
- qApp->setInputContext(new QWSInputContext);
+ qApp->setInputContext(new QWSInputContext(qApp));
#endif
}
@@ -3547,10 +3554,10 @@ bool QETWidget::translateKeyEvent(const QWSKeyEvent *event, bool grab) /* grab i
#if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT)
if (type == QEvent::KeyPress && !grab
- && static_cast<QApplicationPrivate*>(qApp->d_ptr)->use_compat()) {
+ && static_cast<QApplicationPrivate*>(qApp->d_ptr.data())->use_compat()) {
// send accel events if the keyboard is not grabbed
QKeyEvent a(type, code, state, text, autor, int(text.length()));
- if (static_cast<QApplicationPrivate*>(qApp->d_ptr)->qt_tryAccelEvent(this, &a))
+ if (static_cast<QApplicationPrivate*>(qApp->d_ptr.data())->qt_tryAccelEvent(this, &a))
return true;
}
#else
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
new file mode 100644
index 0000000..d47747f
--- /dev/null
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -0,0 +1,1182 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication_p.h"
+#include "qsessionmanager.h"
+#include "qevent.h"
+#include "qeventdispatcher_s60_p.h"
+#include "qwidget.h"
+#include "qdesktopwidget.h"
+#include "private/qbackingstore_p.h"
+#include "qt_s60_p.h"
+#include "private/qevent_p.h"
+#include "qstring.h"
+#include "qdebug.h"
+#include "qimage.h"
+#include "private/qkeymapper_p.h"
+#include "private/qfont_p.h"
+#ifndef QT_NO_STYLE_S60
+#include "private/qs60style_p.h"
+#endif
+#include "private/qwindowsurface_s60_p.h"
+#include "qpaintengine.h"
+#include "private/qmenubar_p.h"
+
+#include "apgwgnam.h" // For CApaWindowGroupName
+#include <MdaAudioTonePlayer.h> // For CMdaAudioToneUtility
+
+#if !defined(QT_NO_IM) && defined(Q_WS_S60)
+#include "qinputcontext.h"
+#include <private/qcoefepinputcontext_p.h>
+#endif // !defined(QT_NO_IM) && defined(Q_WS_S60)
+
+#include "private/qstylesheetstyle_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#if defined(QT_DEBUG)
+static bool appNoGrab = false; // Grabbing enabled
+#endif
+
+Q_GUI_EXPORT QS60Data *qt_s60Data = 0;
+extern bool qt_sendSpontaneousEvent(QObject*,QEvent*);
+
+extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp
+
+QWidget *qt_button_down = 0; // widget got last button-down
+
+bool qt_nograb() // application no-grab option
+{
+#if defined(QT_DEBUG)
+ return appNoGrab;
+#else
+ return false;
+#endif
+}
+
+// Modified from http://www3.symbian.com/faq.nsf/0/0F1464EE96E737E780256D5E00503DD1?OpenDocument
+class QS60Beep : public CBase, public MMdaAudioToneObserver
+{
+public:
+ static QS60Beep* NewL(TInt aFrequency, TTimeIntervalMicroSeconds iDuration);
+ void Play();
+ ~QS60Beep();
+private:
+ void ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds iDuration);
+ void MatoPrepareComplete(TInt aError);
+ void MatoPlayComplete(TInt aError);
+private:
+ typedef enum
+ {
+ EBeepNotPrepared,
+ EBeepPrepared,
+ EBeepPlaying
+ } TBeepState;
+private:
+ CMdaAudioToneUtility* iToneUtil;
+ TBeepState iState;
+ TInt iFrequency;
+ TTimeIntervalMicroSeconds iDuration;
+};
+
+QS60Beep::~QS60Beep()
+{
+ delete iToneUtil;
+}
+
+QS60Beep* QS60Beep::NewL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
+{
+ QS60Beep* self=new (ELeave) QS60Beep();
+ CleanupStack::PushL(self);
+ self->ConstructL(aFrequency, aDuration);
+ CleanupStack::Pop();
+ return self;
+};
+
+void QS60Beep::ConstructL(TInt aFrequency, TTimeIntervalMicroSeconds aDuration)
+{
+ iToneUtil=CMdaAudioToneUtility::NewL(*this);
+ iState=EBeepNotPrepared;
+ iFrequency=aFrequency;
+ iDuration=aDuration;
+ iToneUtil->PrepareToPlayTone(iFrequency,iDuration);
+}
+
+void QS60Beep::Play()
+{
+ if(iState!=EBeepNotPrepared){
+ if(iState==EBeepPlaying) {
+ iToneUtil->CancelPlay();
+ iState=EBeepPrepared;
+ }
+ }
+
+ iToneUtil->Play();
+ iState=EBeepPlaying;
+}
+
+void QS60Beep::MatoPrepareComplete(TInt aError)
+{
+ if(aError==KErrNone) {
+ iState=EBeepPrepared;
+ }
+}
+
+void QS60Beep::MatoPlayComplete(TInt aError)
+{
+ Q_UNUSED(aError);
+ iState=EBeepPrepared;
+}
+
+
+QHash<TInt, TUint> QApplicationPrivate::scanCodeCache;
+
+static Qt::KeyboardModifiers mapToQtModifiers(TUint s60Modifiers)
+{
+ Qt::KeyboardModifiers result = Qt::NoModifier;
+
+ if (s60Modifiers & EModifierKeypad)
+ result |= Qt::KeypadModifier;
+ if (s60Modifiers & EModifierShift || s60Modifiers & EModifierLeftShift
+ || s60Modifiers & EModifierRightShift)
+ result |= Qt::ShiftModifier;
+ if (s60Modifiers & EModifierCtrl || s60Modifiers & EModifierLeftCtrl
+ || s60Modifiers & EModifierRightCtrl)
+ result |= Qt::ControlModifier;
+ if (s60Modifiers & EModifierAlt || s60Modifiers & EModifierLeftAlt
+ || s60Modifiers & EModifierRightAlt)
+ result |= Qt::AltModifier;
+
+ return result;
+}
+
+static void mapS60MouseEventTypeToQt(QEvent::Type *type, Qt::MouseButton *button, const TPointerEvent *pEvent)
+{
+ switch (pEvent->iType) {
+ case TPointerEvent::EButton1Down:
+ *type = QEvent::MouseButtonPress;
+ *button = Qt::LeftButton;
+ break;
+ case TPointerEvent::EButton1Up:
+ *type = QEvent::MouseButtonRelease;
+ *button = Qt::LeftButton;
+ break;
+ case TPointerEvent::EButton2Down:
+ *type = QEvent::MouseButtonPress;
+ *button = Qt::MidButton;
+ break;
+ case TPointerEvent::EButton2Up:
+ *type = QEvent::MouseButtonRelease;
+ *button = Qt::MidButton;
+ break;
+ case TPointerEvent::EButton3Down:
+ *type = QEvent::MouseButtonPress;
+ *button = Qt::RightButton;
+ break;
+ case TPointerEvent::EButton3Up:
+ *type = QEvent::MouseButtonRelease;
+ *button = Qt::RightButton;
+ break;
+ case TPointerEvent::EDrag:
+ *type = QEvent::MouseMove;
+ *button = Qt::NoButton;
+ break;
+ case TPointerEvent::EMove:
+ // Qt makes no distinction between move and drag
+ *type = QEvent::MouseMove;
+ *button = Qt::NoButton;
+ break;
+ default:
+ *type = QEvent::None;
+ *button = Qt::NoButton;
+ break;
+ }
+ if (pEvent->iModifiers & EModifierDoubleClick){
+ *type = QEvent::MouseButtonDblClick;
+ }
+
+ if (*type == QEvent::MouseButtonPress || *type == QEvent::MouseButtonDblClick)
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | (*button);
+ else if (*type == QEvent::MouseButtonRelease)
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~(*button));
+
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & Qt::MouseButtonMask;
+}
+
+//### Can be replaced with CAknLongTapDetector if animation is required.
+//NOTE: if CAknLongTapDetector is used make sure it gets variated out of 3.1 and 3.2,.
+//also MLongTapObserver needs to be changed to MAknLongTapDetectorCallBack if CAknLongTapDetector is used.
+class QLongTapTimer : public CTimer
+{
+public:
+ static QLongTapTimer* NewL(QAbstractLongTapObserver *observer);
+ QLongTapTimer(QAbstractLongTapObserver *observer);
+ void ConstructL();
+public:
+ void PointerEventL(const TPointerEvent &event);
+ void RunL();
+protected:
+private:
+ QAbstractLongTapObserver *m_observer;
+ TPointerEvent m_event;
+ QPoint m_pressedCoordinates;
+ int m_dragDistance;
+};
+
+QLongTapTimer* QLongTapTimer::NewL(QAbstractLongTapObserver *observer)
+{
+ QLongTapTimer* self = new QLongTapTimer(observer);
+ self->ConstructL();
+ return self;
+}
+void QLongTapTimer::ConstructL()
+{
+ CTimer::ConstructL();
+}
+
+QLongTapTimer::QLongTapTimer(QAbstractLongTapObserver *observer):CTimer(CActive::EPriorityHigh)
+{
+ m_observer = observer;
+ m_dragDistance = qApp->startDragDistance();
+ CActiveScheduler::Add(this);
+}
+
+void QLongTapTimer::PointerEventL(const TPointerEvent& event)
+{
+ if ( event.iType == TPointerEvent::EDrag || event.iType == TPointerEvent::EButtonRepeat)
+ {
+ QPoint diff(QPoint(event.iPosition.iX,event.iPosition.iY) - m_pressedCoordinates);
+ if (diff.manhattanLength() < m_dragDistance)
+ return;
+ }
+ Cancel();
+ m_event = event;
+ if (event.iType == TPointerEvent::EButton1Down)
+ {
+ m_pressedCoordinates = QPoint(event.iPosition.iX,event.iPosition.iY);
+ // must be same as KLongTapDelay in aknlongtapdetector.h
+ After(800000);
+ }
+}
+void QLongTapTimer::RunL()
+{
+ if (m_observer)
+ m_observer->HandleLongTapEventL(m_event.iPosition, m_event.iParentPosition);
+}
+
+QSymbianControl::QSymbianControl(QWidget *w)
+ : CCoeControl(), qwidget(w), m_ignoreFocusChanged(false)
+{
+}
+
+void QSymbianControl::ConstructL(bool topLevel, bool desktop)
+{
+ if (!desktop)
+ {
+ if (topLevel)
+ CreateWindowL(S60->windowGroup());
+
+ SetFocusing(true);
+ m_longTapDetector = QLongTapTimer::NewL(this);
+ }
+}
+
+QSymbianControl::~QSymbianControl()
+{
+ S60->appUi()->RemoveFromStack(this);
+ delete m_longTapDetector;
+}
+
+void QSymbianControl::setWidget(QWidget *w)
+{
+ qwidget = w;
+}
+void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation )
+{
+ QWidget *alienWidget;
+ QPoint widgetPos = QPoint(aPenEventLocation.iX, aPenEventLocation.iY);
+ QPoint globalPos = QPoint(aPenEventScreenLocation.iX,aPenEventScreenLocation.iY);
+ alienWidget = qwidget->childAt(widgetPos);
+ if (!alienWidget)
+ alienWidget = qwidget;
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons &(~Qt::LeftButton);
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons | Qt::RightButton;
+ QMouseEvent mEvent(QEvent::MouseButtonPress, alienWidget->mapFrom(qwidget, widgetPos), globalPos,
+ Qt::RightButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier);
+ sendMouseEvent(alienWidget, &mEvent);
+ m_previousEventLongTap = true;
+}
+
+void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent)
+{
+ //### refactor me, getting too complex
+ m_longTapDetector->PointerEventL(pEvent);
+ QMouseEvent::Type type;
+ Qt::MouseButton button;
+ mapS60MouseEventTypeToQt(&type, &button, &pEvent);
+
+ if (m_previousEventLongTap)
+ if (type == QEvent::MouseButtonRelease){
+ button = Qt::RightButton;
+ QApplicationPrivate::mouse_buttons = QApplicationPrivate::mouse_buttons & ~Qt::RightButton;
+ m_previousEventLongTap = false;
+ }
+ if (type == QMouseEvent::None)
+ return;
+
+ // store events for later sending/saving
+ QWidget *alienWidget;
+ typedef QPair<QWidget*,QMouseEvent> Event;
+ QList<Event > events;
+
+ QPoint widgetPos = QPoint(pEvent.iPosition.iX, pEvent.iPosition.iY);
+ TPoint controlScreenPos = PositionRelativeToScreen();
+ QPoint globalPos = QPoint(controlScreenPos.iX, controlScreenPos.iY) + widgetPos;
+
+ if (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick)
+ {
+ // get the button press target
+ alienWidget = qwidget->childAt(widgetPos);
+ if (!alienWidget)
+ alienWidget = qwidget;
+ S60->mousePressTarget = alienWidget;
+ //pointer grab
+ SetGloballyCapturing(ETrue);
+ SetPointerCapture(ETrue);
+ }
+ else if (type == QEvent::MouseButtonRelease)
+ {
+ //release pointer grab
+ SetGloballyCapturing(EFalse);
+ SetPointerCapture(EFalse);
+ }
+ alienWidget = S60->mousePressTarget;
+
+ if (alienWidget != S60->lastPointerEventTarget)
+ if (type == QEvent::MouseButtonPress || type == QEvent::MouseButtonDblClick || type == QEvent::MouseMove)
+ {
+ //moved to another widget, create enter and leave events
+ if (S60->lastPointerEventTarget)
+ {
+ QMouseEvent mEventLeave(QEvent::Leave, S60->lastPointerEventTarget->mapFromGlobal(S60->lastCursorPos), S60->lastCursorPos,
+ button, QApplicationPrivate::mouse_buttons, mapToQtModifiers(pEvent.iModifiers));
+ events.append(Event(S60->lastPointerEventTarget,mEventLeave));
+ }
+ QMouseEvent mEventEnter(QEvent::Enter, alienWidget->mapFromGlobal(globalPos), globalPos,
+ button, QApplicationPrivate::mouse_buttons, mapToQtModifiers(pEvent.iModifiers));
+
+ events.append(Event(alienWidget,mEventEnter));
+ }
+ S60->lastCursorPos = globalPos;
+ S60->lastPointerEventPos = widgetPos;
+ S60->lastPointerEventTarget = alienWidget;
+ if (alienWidget)
+ {
+ QMouseEvent mEvent(type, alienWidget->mapFromGlobal(globalPos), globalPos,
+ button, QApplicationPrivate::mouse_buttons, mapToQtModifiers(pEvent.iModifiers));
+ events.append(Event(alienWidget,mEvent));
+ QEventDispatcherS60 *dispatcher;
+ // It is theoretically possible for someone to install a different event dispatcher.
+ if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(alienWidget->d_func()->threadData->eventDispatcher)) != 0) {
+ if (dispatcher->excludeUserInputEvents()) {
+ for (int i=0;i < events.count();++i)
+ {
+ Event next = events[i];
+ dispatcher->saveInputEvent(this, next.first, new QMouseEvent(next.second));
+ }
+ return;
+ }
+ }
+ }
+ for (int i=0;i < events.count();++i)
+ {
+ Event next = events[i];
+ sendMouseEvent(next.first, &(next.second));
+ }
+}
+
+void QSymbianControl::sendMouseEvent(QWidget *widget, QMouseEvent *mEvent)
+{
+ qt_sendSpontaneousEvent(widget, mEvent);
+}
+
+TKeyResponse QSymbianControl::OfferKeyEventL(const TKeyEvent& keyEvent, TEventCode type)
+{
+ TKeyResponse r = EKeyWasNotConsumed;
+ QT_TRANSLATE_EXCEPTION_TO_SYMBIAN_LEAVE(r = OfferKeyEvent(keyEvent, type));
+ return r;
+}
+
+TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCode type)
+{
+ switch (type) {
+ //case EEventKeyDown: // <-- Intentionally left out. See below.
+ case EEventKeyUp:
+ case EEventKey:
+ {
+ // S60 has a confusing way of delivering key events. There are three types of
+ // events: EKeyEvent, EKeyEventDown and EKeyEventUp. When a key is pressed, the
+ // two first events are generated. When releasing the key, the last one is
+ // generated.
+ // Because S60 does not generate keysyms for EKeyEventDown and EKeyEventUp events,
+ // we need to do some special tricks to map it to the Qt way. First, we completely
+ // discard EKeyEventDown events, since they are redundant. Second, since
+ // EKeyEventUp does not give us a keysym, we need to cache the keysyms from
+ // the EKeyEvent events. This is what resolveS60ScanCode does.
+
+
+ // ### hackish way to send Qt application to background when pressing right softkey
+ /*
+ if( keyEvent.iScanCode == EStdKeyDevice1 ) {
+ S60->window_group->SetOrdinalPosition(-1);
+ qApp->setActiveWindow(0);
+ return EKeyWasNotConsumed;
+ }
+ */
+
+ TUint s60Keysym = QApplicationPrivate::resolveS60ScanCode(keyEvent.iScanCode,
+ keyEvent.iCode);
+ int keyCode;
+ if (s60Keysym >= 0x20 && s60Keysym < ENonCharacterKeyBase) {
+ // Normal characters keys.
+ keyCode = s60Keysym;
+ } else {
+ // Special S60 keys.
+ keyCode = qt_keymapper_private()->mapS60KeyToQt(s60Keysym);
+ }
+ Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers);
+ QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode,
+ mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
+ false, 1, keyEvent.iScanCode, s60Keysym, mods);
+// WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child();
+// if (!wid)
+// Could happen if window isn't shown yet.
+// return EKeyWasNotConsumed;
+ QWidget *widget;
+ widget = QWidget::keyboardGrabber();
+ if (!widget) {
+ if (QApplicationPrivate::popupWidgets != 0) {
+ widget = QApplication::activePopupWidget()->focusWidget();
+ if (!widget) {
+ widget = QApplication::activePopupWidget();
+ }
+ } else {
+ widget = QApplicationPrivate::focus_widget;
+ if (!widget) {
+ widget = qwidget;
+ }
+ }
+ }
+
+ QEventDispatcherS60 *dispatcher;
+ // It is theoretically possible for someone to install a different event dispatcher.
+ if ((dispatcher = qobject_cast<QEventDispatcherS60 *>(widget->d_func()->threadData->eventDispatcher)) != 0) {
+ if (dispatcher->excludeUserInputEvents()) {
+ dispatcher->saveInputEvent(this, widget, new QKeyEventEx(qKeyEvent));
+ return EKeyWasConsumed;
+ }
+ }
+ return sendKeyEvent(widget, &qKeyEvent);
+ }
+ }
+ return EKeyWasNotConsumed;
+}
+
+void QSymbianControl::sendInputEvent(QWidget *widget, QInputEvent *inputEvent)
+{
+ switch (inputEvent->type()) {
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ sendKeyEvent(widget, static_cast<QKeyEvent *>(inputEvent));
+ break;
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ sendMouseEvent(widget, static_cast<QMouseEvent *>(inputEvent));
+ break;
+ default:
+ // Shouldn't get here.
+ Q_ASSERT_X(0 == 1, "QSymbianControl::sendInputEvent()", "inputEvent->type() is unknown");
+ break;
+ }
+}
+
+TKeyResponse QSymbianControl::sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent)
+{
+#if !defined(QT_NO_IM) && defined(Q_WS_S60)
+ if (widget && widget->isEnabled() && widget->testAttribute(Qt::WA_InputMethodEnabled)) {
+ QInputContext *qic = widget->inputContext();
+ if(qic && qic->filterEvent(keyEvent))
+ return EKeyWasConsumed;
+ }
+#endif // !defined(QT_NO_IM) && defined(Q_WS_S60)
+
+ if (widget && qt_sendSpontaneousEvent(widget, keyEvent))
+ if (keyEvent->isAccepted())
+ return EKeyWasConsumed;
+
+ return EKeyWasNotConsumed;
+}
+
+#if !defined(QT_NO_IM) && defined(Q_WS_S60)
+TCoeInputCapabilities QSymbianControl::InputCapabilities() const
+{
+ QWidget *w = 0;
+
+ if(qwidget->hasFocus()) {
+ w = qwidget;
+ } else {
+ w = qwidget->focusWidget();
+ }
+
+ QCoeFepInputContext *ic;
+ if (w && w->isEnabled() && w->testAttribute(Qt::WA_InputMethodEnabled)
+ && (ic = qobject_cast<QCoeFepInputContext *>(w->inputContext()))) {
+ return ic->inputCapabilities();
+ } else {
+ return TCoeInputCapabilities(TCoeInputCapabilities::ENone, 0, 0);
+ }
+}
+#endif
+
+void QSymbianControl::Draw(const TRect& r) const
+{
+ QWindowSurface *surface = qwidget->windowSurface();
+ if (!surface)
+ return;
+
+ QPaintEngine *engine = surface->paintDevice()->paintEngine();
+ if (!engine)
+ return;
+ if (engine->type() == QPaintEngine::Raster) {
+ QS60WindowSurface *s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface());
+ CFbsBitmap *bitmap = s60Surface->symbianBitmap();
+ CWindowGc &gc = SystemGc();
+ if (qwidget->d_func()->isOpaque)
+ gc.SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha);
+ gc.BitBlt(r.iTl, bitmap, r);
+ } else {
+ surface->flush(qwidget, QRegion(qt_TRect2QRect(r)), QPoint());
+ }
+}
+
+void QSymbianControl::SizeChanged()
+{
+ CCoeControl::SizeChanged();
+
+ QSize oldSize = qwidget->size();
+ QSize newSize(Size().iWidth, Size().iHeight);
+
+ if (oldSize != newSize) {
+ QRect cr = qwidget->geometry();
+ cr.setSize(newSize);
+ qwidget->data->crect = cr;
+ if (qwidget->isVisible()) {
+ QTLWExtra *tlwExtra = qwidget->d_func()->maybeTopData();
+ bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
+ if (!slowResize && tlwExtra)
+ tlwExtra->inTopLevelResize = true;
+ QResizeEvent e(newSize, oldSize);
+ qt_sendSpontaneousEvent(qwidget, &e);
+ if (!qwidget->testAttribute(Qt::WA_StaticContents))
+ qwidget->d_func()->syncBackingStore();
+ if (!slowResize && tlwExtra)
+ tlwExtra->inTopLevelResize = false;
+ }
+ }
+}
+
+void QSymbianControl::PositionChanged()
+{
+ CCoeControl::PositionChanged();
+
+ QPoint oldPos = qwidget->geometry().topLeft();
+ QPoint newPos(Position().iX, Position().iY);
+
+ if (oldPos != newPos) {
+ QRect cr = qwidget->geometry();
+ cr.moveTopLeft(newPos);
+ qwidget->data->crect = cr;
+ QTLWExtra *top = qwidget->d_func()->maybeTopData();
+ if (top)
+ top->normalGeometry = cr;
+ if (qwidget->isVisible()) {
+ QMoveEvent e(newPos, oldPos);
+ qt_sendSpontaneousEvent(qwidget, &e);
+ } else {
+ QMoveEvent * e = new QMoveEvent(newPos, oldPos);
+ QApplication::postEvent(qwidget, e);
+ }
+ }
+}
+
+void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */)
+{
+ if (m_ignoreFocusChanged)
+ return;
+
+ // Popups never get focused, but still receive the FocusChanged when they are hidden.
+ if (QApplicationPrivate::popupWidgets != 0
+ || (qwidget->windowType() & Qt::Popup) == Qt::Popup)
+ return;
+
+ QEvent *deferredFocusEvent = new QEvent(QEvent::SymbianDeferredFocusChanged);
+ QApplication::postEvent(qwidget, deferredFocusEvent);
+}
+
+void QSymbianControl::HandleResourceChange(int resourceType)
+{
+ switch (resourceType) {
+ case KInternalStatusPaneChange:
+ qwidget->d_func()->setWindowIcon_sys(true);
+ break;
+ case KUidValueCoeFontChangeEvent:
+ // font change event
+ break;
+#ifdef Q_WS_S60
+ case KEikDynamicLayoutVariantSwitch:
+ {
+ if (qwidget->isFullScreen()) {
+ SetExtentToWholeScreen();
+ } else if (qwidget->isMaximized()) {
+ TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+ SetExtent(r.iTl, r.Size());
+ }
+ break;
+ }
+#endif
+ default:
+ break;
+ }
+
+ CCoeControl::HandleResourceChange(resourceType);
+
+}
+void QSymbianControl::CancelLongTapTimer()
+{
+ m_longTapDetector->Cancel();
+}
+
+TTypeUid::Ptr QSymbianControl::MopSupplyObject(TTypeUid id)
+{
+ if (id.iUid == ETypeId)
+ return id.MakePtr(this);
+
+ return CCoeControl::MopSupplyObject(id);
+}
+
+void qt_init(QApplicationPrivate * /* priv */, int)
+{
+ S60 = new QS60Data;
+
+#ifdef QT_NO_DEBUG
+ if (!qgetenv("QT_S60_AUTO_FLUSH_WSERV").isEmpty())
+#endif
+ S60->wsSession().SetAutoFlush(ETrue);
+
+ S60->updateScreenSize();
+
+
+ TDisplayMode mode = S60->screenDevice()->DisplayMode();
+ S60->screenDepth = TDisplayModeUtils::NumDisplayModeBitsPerPixel(mode);
+
+ RProcess me;
+ TSecureId securId = me.SecureId();
+ S60->uid = securId.operator TUid();
+
+ // New code to configure the window group name such that window server knows the associated application's UID
+ CApaWindowGroupName *wgn = CApaWindowGroupName::NewL(S60->wsSession());
+ wgn->SetAppUid(S60->uid);
+ User::LeaveIfError(wgn->SetWindowGroupName((S60->windowGroup())));
+ delete wgn;
+
+/*
+ ### Commented out for now as parameter handling not needed in SOS(yet). Code below will break testlib with -o flag
+ int argc = priv->argc;
+ char **argv = priv->argv;
+
+ // Get command line params
+ int j = argc ? 1 : 0;
+ for (int i=1; i<argc; i++) {
+ if (argv[i] && *argv[i] != '-') {
+ argv[j++] = argv[i];
+ continue;
+ }
+
+#if defined(QT_DEBUG)
+ if (qstrcmp(argv[i], "-nograb") == 0)
+ appNoGrab = !appNoGrab;
+ else
+#endif // QT_DEBUG
+ ;
+ }
+*/
+}
+
+/*****************************************************************************
+ qt_cleanup() - cleans up when the application is finished
+ *****************************************************************************/
+void qt_cleanup()
+{
+ QFontCache::cleanup(); // Has to happen now, since QFontEngineS60 has FBS handles
+// S60 structure and window server session are freed in eventdispatcher destructor as they are needed there
+
+ // It's important that this happens here, before the event dispatcher gets
+ // deleted, because the input context needs the event loop one last time before
+ // it dies.
+ delete QApplicationPrivate::inputContext;
+ QApplicationPrivate::inputContext = 0;
+}
+
+void QApplicationPrivate::initializeWidgetPaletteHash()
+{
+ // TODO: Implement QApplicationPrivate::initializeWidgetPaletteHash()
+ // Possibly a task fot the S60Style guys
+}
+
+void QApplicationPrivate::createEventDispatcher()
+{
+ Q_Q(QApplication);
+ eventDispatcher = new QEventDispatcherS60(q);
+}
+
+QString QApplicationPrivate::appName() const
+{
+ return QCoreApplicationPrivate::appName();
+}
+
+bool QApplicationPrivate::modalState()
+{
+ return false;
+}
+
+void QApplicationPrivate::enterModal_sys(QWidget * /* widget */)
+{
+ // TODO: Implement QApplicationPrivate::enterModal_sys(QWidget *widget)
+}
+
+void QApplicationPrivate::leaveModal_sys(QWidget * /* widget */)
+{
+ // TODO: Implement QApplicationPrivate::leaveModal_sys(QWidget *widget)
+}
+
+void QApplicationPrivate::openPopup(QWidget *popup)
+{
+ if (!QApplicationPrivate::popupWidgets)
+ QApplicationPrivate::popupWidgets = new QWidgetList;
+ QApplicationPrivate::popupWidgets->append(popup);
+
+ if (QApplicationPrivate::popupWidgets->count() == 1 && !qt_nograb()) {
+ Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
+ WId id = popup->effectiveWinId();
+ id->SetPointerCapture(true);
+ id->SetGloballyCapturing(true);
+ }
+
+ // popups are not focus-handled by the window system (the first
+ // popup grabbed the keyboard), so we have to do that manually: A
+ // new popup gets the focus
+ if (QApplication::focusWidget())
+ static_cast<QSymbianControl*>(QApplication::focusWidget()->effectiveWinId())->CancelLongTapTimer();
+ QWidget *fw = popup->focusWidget();
+ if (fw) {
+ fw->setFocus(Qt::PopupFocusReason);
+ } else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
+ fw = QApplication::focusWidget();
+ if (fw) {
+ QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
+ q_func()->sendEvent(fw, &e);
+ }
+ }
+}
+
+void QApplicationPrivate::closePopup(QWidget *popup)
+{
+ if (!QApplicationPrivate::popupWidgets)
+ return;
+ QApplicationPrivate::popupWidgets->removeAll(popup);
+
+ if (QApplicationPrivate::popupWidgets->isEmpty()) { // this was the last popup
+ delete QApplicationPrivate::popupWidgets;
+ QApplicationPrivate::popupWidgets = 0;
+ if (!qt_nograb()) { // grabbing not disabled
+ Q_ASSERT(popup->testAttribute(Qt::WA_WState_Created));
+ WId id = popup->effectiveWinId();
+ id->SetPointerCapture(false);
+ id->SetGloballyCapturing(false);
+ if (QWidgetPrivate::mouseGrabber != 0)
+ QWidgetPrivate::mouseGrabber->grabMouse();
+
+ if (QWidgetPrivate::keyboardGrabber != 0)
+ QWidgetPrivate::keyboardGrabber->grabKeyboard();
+
+ QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget()
+ : q_func()->focusWidget();
+ if (fw) {
+ if (fw != q_func()->focusWidget()) {
+ fw->setFocus(Qt::PopupFocusReason);
+ } else {
+ QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
+ q_func()->sendEvent(fw, &e);
+ }
+ }
+ }
+ } else {
+ // popups are not focus-handled by the window system (the
+ // first popup grabbed the keyboard), so we have to do that
+ // manually: A popup was closed, so the previous popup gets
+ // the focus.
+ QWidget* aw = QApplicationPrivate::popupWidgets->last();
+ if (QWidget *fw = QApplication::focusWidget()) {
+ QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
+ q_func()->sendEvent(fw, &e);
+ }
+ }
+}
+
+QWidget * QApplication::topLevelAt(QPoint const& point)
+{
+ QWidget *found = 0;
+ int lowestZ = INT_MAX;
+ QWidgetList list = QApplication::topLevelWidgets();
+ for (int i = 0; i < list.count(); ++i) {
+ QWidget *widget = list.at(i);
+ if (widget->isVisible() && !(widget->windowType() == Qt::Desktop)) {
+ Q_ASSERT(widget->testAttribute(Qt::WA_WState_Created));
+ if (widget->geometry().adjusted(0,0,1,1).contains(point)) {
+ // At this point we know there is a Qt widget under the point.
+ // Now we need to make sure it is the top most in the z-order.
+ RDrawableWindow* rw = widget->d_func()->topData()->rwindow;
+ int z = rw->OrdinalPosition();
+ if (z < lowestZ) {
+ lowestZ = z;
+ found = widget;
+ }
+ }
+ }
+ }
+ return found;
+}
+
+void QApplication::alert(QWidget * /* widget */, int /* duration */)
+{
+ // TODO: Implement QApplication::alert(QWidget *widget, int duration)
+}
+
+int QApplication::doubleClickInterval()
+{
+ TTimeIntervalMicroSeconds32 us;
+ TInt distance;
+ S60->wsSession().GetDoubleClickSettings(us, distance);
+ return (us.Int() / 1000);
+}
+
+void QApplication::setDoubleClickInterval(int ms)
+{
+ TTimeIntervalMicroSeconds32 newUs( ms * 1000);
+ TTimeIntervalMicroSeconds32 us;
+ TInt distance;
+ S60->wsSession().GetDoubleClickSettings(us, distance);
+ if (us != newUs)
+ S60->wsSession().SetDoubleClick(newUs, distance);
+}
+
+int QApplication::keyboardInputInterval()
+{
+ return QApplicationPrivate::keyboard_input_time;
+}
+
+void QApplication::setKeyboardInputInterval(int ms)
+{
+ QApplicationPrivate::keyboard_input_time = ms;
+}
+
+int QApplication::cursorFlashTime()
+{
+ return QApplicationPrivate::cursor_flash_time;
+}
+
+void QApplication::setCursorFlashTime(int msecs)
+{
+ QApplicationPrivate::cursor_flash_time = msecs;
+}
+
+void QApplication::beep()
+{
+ TInt frequency=440;
+ TTimeIntervalMicroSeconds duration(500000);
+ QS60Beep* beep=NULL;
+ TRAPD(err, beep=QS60Beep::NewL(frequency, duration));
+ if(!err) {
+ beep->Play();
+ }
+ delete beep;
+ beep=NULL;
+}
+
+int QApplication::s60ProcessEvent(TWsEvent *event)
+{
+ bool handled = s60EventFilter(event);
+ if (handled)
+ return 1;
+
+ // Qt event handling. Handle some events regardless of if the handle is in our
+ // widget map or not.
+ CCoeControl* control = reinterpret_cast<CCoeControl*>(event->Handle());
+ const bool controlInMap = QWidgetPrivate::mapper && QWidgetPrivate::mapper->contains(control);
+ switch (event->Type()) {
+#if !defined(QT_NO_IM) && defined(Q_WS_S60)
+ case EEventKey:
+ case EEventKeyUp:
+ case EEventKeyDown:
+ {
+ // The control doesn't seem to be any of our widgets, so rely on the focused
+ // widget instead. If the user needs the control, it can be found inside the
+ // event structure.
+ QWidget *w = qApp ? qApp->focusWidget() : 0;
+ if (w) {
+ QInputContext *ic = w->inputContext();
+ if (ic && ic->s60FilterEvent(w, event)) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ break;
+ }
+#endif
+ case EEventPointerEnter:
+ if (controlInMap)
+ return 1; // Qt::Enter will be generated in HandlePointerL
+ break;
+ case EEventPointerExit:
+ if (controlInMap) {
+ if (S60) {
+ // mouseEvent outside our window, send leave event to last focused widget
+ QMouseEvent mEvent(QEvent::Leave, S60->lastPointerEventPos, S60->lastCursorPos,
+ Qt::NoButton, QApplicationPrivate::mouse_buttons, Qt::NoModifier);
+ if (S60->lastPointerEventTarget)
+ qt_sendSpontaneousEvent(S60->lastPointerEventTarget,&mEvent);
+ S60->lastPointerEventTarget = 0;
+ }
+ return 1;
+ }
+ break;
+ case EEventScreenDeviceChanged:
+ if (S60)
+ S60->updateScreenSize();
+ if (qt_desktopWidget) {
+ QSize oldSize = qt_desktopWidget->size();
+ qt_desktopWidget->data->crect.setWidth(S60->screenWidthInPixels);
+ qt_desktopWidget->data->crect.setHeight(S60->screenHeightInPixels);
+ QResizeEvent e(qt_desktopWidget->size(), oldSize);
+ QApplication::sendEvent(qt_desktopWidget, &e);
+ }
+ return 0; // Propagate to CONE
+ case EEventWindowVisibilityChanged:
+ if (controlInMap) {
+ const TWsVisibilityChangedEvent *visChangedEvent = event->VisibilityChanged();
+ QWidget *w = QWidgetPrivate::mapper->value(control);
+ if (!w->d_func()->maybeTopData())
+ break;
+ if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) {
+ delete w->d_func()->topData()->backingStore;
+ w->d_func()->topData()->backingStore = 0;
+ } else if ((visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible)
+ && !w->d_func()->maybeBackingStore()) {
+ w->d_func()->topData()->backingStore = new QWidgetBackingStore(w);
+ w->update();
+ }
+ return 1;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!controlInMap)
+ return -1;
+
+ return 0;
+}
+
+bool QApplication::s60EventFilter(TWsEvent * /* aEvent */)
+{
+ return false;
+}
+
+/*!
+ Handles commands which are typically handled by CAknAppUi::HandleCommandL()
+ Qts Ui integration into Symbian is partially achieved by deriving from CAknAppUi.
+ Currently, exit, menu and softkey commands are handled
+
+ \sa s60EventFilter(), s60ProcessEvent()
+*/
+void QApplication::symbianHandleCommand(int command)
+{
+ switch (command) {
+ case EEikCmdExit:
+#ifdef Q_WS_S60
+ case EAknSoftkeyExit:
+#endif
+ exit();
+ break;
+ default:
+ if (command >= SOFTKEYSTART && command <= SOFTKEYEND) {
+ int index= command-SOFTKEYSTART;
+ QWidget *focused = QApplication::focusWidget();
+ QWidget *softKeySource = focused ? focused : QApplication::activeWindow();
+ const QList<QAction*>& softKeys = softKeySource->softKeys();
+ Q_ASSERT(index < softKeys.count());
+ softKeys.at(index)->activate(QAction::Trigger);
+ }
+#ifdef Q_WS_S60
+ else
+ QMenuBarPrivate::symbianCommands(command);
+#endif
+ break;
+ }
+}
+
+void QApplication::symbianResourceChange(int type)
+{
+ switch (type) {
+#ifdef Q_WS_S60
+ case KEikDynamicLayoutVariantSwitch:
+ {
+ if (S60)
+ S60->updateScreenSize();
+
+#ifndef QT_NO_STYLE_S60
+ QS60Style *s60Style = 0;
+
+#ifndef QT_NO_STYLE_STYLESHEET
+ QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle*>(QApplication::style());
+ if (proxy)
+ s60Style = qobject_cast<QS60Style*>(proxy->baseStyle());
+ else
+#endif
+ s60Style = qobject_cast<QS60Style*>(QApplication::style());
+
+ if (s60Style)
+ s60Style->handleDynamicLayoutVariantSwitch();
+#endif
+ }
+ break;
+
+#ifndef QT_NO_STYLE_S60
+ case KAknsMessageSkinChange:
+ if (QS60Style *s60Style = qobject_cast<QS60Style*>(QApplication::style()))
+ s60Style->handleSkinChange();
+ break;
+#endif
+#endif // Q_WS_S60
+ default:
+ break;
+ }
+}
+
+#ifndef QT_NO_WHEELEVENT
+int QApplication::wheelScrollLines()
+{
+ return QApplicationPrivate::wheel_scroll_lines;
+}
+
+void QApplication::setWheelScrollLines(int n)
+{
+ QApplicationPrivate::wheel_scroll_lines = n;
+}
+#endif //QT_NO_WHEELEVENT
+
+bool QApplication::isEffectEnabled(Qt::UIEffect /* effect */)
+{
+ // TODO: Implement QApplication::isEffectEnabled(Qt::UIEffect effect)
+ return false;
+}
+
+void QApplication::setEffectEnabled(Qt::UIEffect /* effect */, bool /* enable */)
+{
+ // TODO: Implement QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable)
+}
+
+TUint QApplicationPrivate::resolveS60ScanCode(TInt scanCode, TUint keysym)
+{
+ if (keysym) {
+ // If keysym is specified, cache it.
+ scanCodeCache.insert(scanCode, keysym);
+ return keysym;
+ } else {
+ // If not, retrieve the cached version.
+ return scanCodeCache[scanCode];
+ }
+}
+
+
+void QApplicationPrivate::initializeMultitouch_sys()
+{ }
+void QApplicationPrivate::cleanupMultitouch_sys()
+{ }
+
+#ifndef QT_NO_SESSIONMANAGER
+QSessionManager::QSessionManager(QApplication * /* app */, QString & /* id */, QString& /* key */)
+{
+
+}
+
+QSessionManager::~QSessionManager()
+{
+
+}
+
+bool QSessionManager::allowsInteraction()
+{
+ return false;
+}
+
+void QSessionManager::cancel()
+{
+
+}
+#endif //QT_NO_SESSIONMANAGER
+QT_END_NAMESPACE
+
+
diff --git a/src/gui/kernel/qclipboard_s60.cpp b/src/gui/kernel/qclipboard_s60.cpp
new file mode 100644
index 0000000..db5e7f3
--- /dev/null
+++ b/src/gui/kernel/qclipboard_s60.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qclipboard.h"
+
+#ifndef QT_NO_CLIPBOARD
+
+#include "qapplication.h"
+#include "qbitmap.h"
+#include "qdatetime.h"
+#include "qbuffer.h"
+#include "qwidget.h"
+#include "qevent.h"
+#include <QtDebug>
+
+// Symbian's clipboard
+#include <baclipb.h>
+QT_BEGIN_NAMESPACE
+
+//### Mime Type mapping to UIDs
+
+const TUid KQtCbDataStream = {0x666777};
+
+
+class QClipboardData
+{
+public:
+ QClipboardData();
+ ~QClipboardData();
+
+ void setSource(QMimeData* s)
+ {
+ if (s == src)
+ return;
+ delete src;
+ src = s;
+ }
+ QMimeData* source()
+ { return src; }
+ bool connected()
+ { return connection; }
+ void clear();
+ RFs fsSession();
+
+
+private:
+ QMimeData* src;
+ RFs iFs;
+ bool connection;
+};
+
+QClipboardData::QClipboardData():src(0),connection(true)
+{
+ clear();
+ if (KErrNone != iFs.Connect())
+ {
+ qWarning("QClipboardData::fileserver connnect failed");
+ connection = false;
+ }
+}
+
+QClipboardData::~QClipboardData()
+{
+ iFs.Close();
+ connection = false;
+ delete src;
+}
+
+void QClipboardData::clear()
+{
+ QMimeData* newSrc = new QMimeData;
+ delete src;
+ src = newSrc;
+}
+RFs QClipboardData::fsSession()
+{
+ return iFs;
+}
+
+static QClipboardData *internalCbData = 0;
+
+static void cleanupClipboardData()
+{
+ delete internalCbData;
+ internalCbData = 0;
+}
+
+static QClipboardData *clipboardData()
+{
+ if (internalCbData == 0) {
+ internalCbData = new QClipboardData;
+ if (internalCbData)
+ {
+ if (!internalCbData->connected())
+ {
+ delete internalCbData;
+ internalCbData = 0;
+ }
+ else
+ {
+ qAddPostRoutine(cleanupClipboardData);
+ }
+ }
+ }
+ return internalCbData;
+}
+
+void writeToStream(const QMimeData* aData, RWriteStream& aStream)
+{
+ QStringList headers = aData->formats();
+ aStream << TCardinality(headers.count());
+ for (QStringList::const_iterator iter= headers.constBegin();iter != headers.constEnd();iter++)
+ {
+ HBufC* stringData = TPtrC(reinterpret_cast<const TUint16*>((*iter).utf16())).AllocLC();
+ QByteArray ba = aData->data((*iter));
+ qDebug() << "copy to clipboard mime: " << *iter << " data: " << ba;
+ // mime type
+ aStream << TCardinality(stringData->Size());
+ aStream << *(stringData);
+ // mime data
+ aStream << TCardinality(ba.size());
+ aStream.WriteL(reinterpret_cast<const uchar*>(ba.constData()),ba.size());
+ CleanupStack::PopAndDestroy(stringData);
+ }
+}
+
+void readFromStream(QMimeData* aData,RReadStream& aStream)
+{
+ TCardinality mimeTypeCount;
+ aStream >> mimeTypeCount;
+ for (int i = 0; i< mimeTypeCount;i++)
+ {
+ // mime type
+ TCardinality mimeTypeSize;
+ aStream >> mimeTypeSize;
+ HBufC* mimeTypeBuf = HBufC::NewLC(aStream,mimeTypeSize);
+ QString mimeType = QString::fromUtf16(mimeTypeBuf->Des().Ptr(),mimeTypeBuf->Length());
+ // mime data
+ TCardinality dataSize;
+ aStream >> dataSize;
+ QByteArray ba;
+ ba.reserve(dataSize);
+ aStream.ReadL(reinterpret_cast<uchar*>(ba.data_ptr()->data),dataSize);
+ ba.data_ptr()->size = dataSize;
+ qDebug() << "paste from clipboard mime: " << mimeType << " data: " << ba;
+ aData->setData(mimeType,ba);
+ CleanupStack::PopAndDestroy(mimeTypeBuf);
+
+ }
+}
+
+
+/*****************************************************************************
+ QClipboard member functions
+ *****************************************************************************/
+
+void QClipboard::clear(Mode mode)
+{
+ setText(QString(), mode);
+}
+const QMimeData* QClipboard::mimeData(Mode mode) const
+{
+ if (mode != Clipboard) return 0;
+ QClipboardData *d = clipboardData();
+ if (d)
+ {
+ //###fixme when exceptions are added to Qt
+ TRAPD(err,{
+ RFs fs = d->fsSession();
+ CClipboard* cb = CClipboard::NewForReadingLC(fs);
+ Q_ASSERT(cb);
+ RStoreReadStream stream;
+ TStreamId stid = (cb->StreamDictionary()).At(KQtCbDataStream);
+ stream.OpenLC(cb->Store(),stid);
+ readFromStream(d->source(),stream);
+ CleanupStack::PopAndDestroy(2,cb);
+ return d->source();
+ });
+ if (err != KErrNone){
+ qDebug()<< "clipboard is empty/err: " << err;
+ }
+
+ }
+ return 0;
+}
+
+
+void QClipboard::setMimeData(QMimeData* src, Mode mode)
+{
+ if (mode != Clipboard) return;
+ QClipboardData *d = clipboardData();
+ if (d)
+ {
+ //###fixme when exceptions are added to Qt
+ TRAPD(err,{
+ RFs fs = d->fsSession();
+ CClipboard* cb = CClipboard::NewForWritingLC(fs);
+ RStoreWriteStream stream;
+ TStreamId stid = stream.CreateLC(cb->Store());
+ writeToStream(src,stream);
+ d->setSource(src);
+ stream.CommitL();
+ (cb->StreamDictionary()).AssignL(KQtCbDataStream,stid);
+ cb->CommitL();
+ CleanupStack::PopAndDestroy(2,cb);
+ });
+ if (err != KErrNone){
+ qDebug()<< "clipboard write err :" << err;
+ }
+ }
+ emitChanged(QClipboard::Clipboard);
+}
+
+bool QClipboard::supportsMode(Mode mode) const
+{
+ return (mode == Clipboard);
+}
+
+bool QClipboard::ownsMode(Mode mode) const
+{
+ if (mode == Clipboard)
+ qWarning("QClipboard::ownsClipboard: UNIMPLEMENTED!");
+ return false;
+}
+
+bool QClipboard::event(QEvent * /* e */)
+{
+ return true;
+}
+
+void QClipboard::connectNotify( const char * )
+{
+}
+
+void QClipboard::ownerDestroyed()
+{
+}
+QT_END_NAMESPACE
+#endif // QT_NO_CLIPBOARD
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index 9cca0d6..d665cc2 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -561,7 +561,6 @@ QCursor::operator QVariant() const
{
return QVariant(QVariant::Cursor, this);
}
-
+QT_END_NAMESPACE
#endif // QT_NO_CURSOR
-QT_END_NAMESPACE
diff --git a/src/gui/kernel/qcursor_qws.cpp b/src/gui/kernel/qcursor_qws.cpp
index 7553415..efbfcc5 100644
--- a/src/gui/kernel/qcursor_qws.cpp
+++ b/src/gui/kernel/qcursor_qws.cpp
@@ -66,7 +66,11 @@ QCursorData::~QCursorData()
{
delete bm;
delete bmm;
- QPaintDevice::qwsDisplay()->destroyCursor(id);
+ QT_TRY {
+ QPaintDevice::qwsDisplay()->destroyCursor(id);
+ } QT_CATCH(const std::bad_alloc &) {
+ // do nothing.
+ }
}
diff --git a/src/gui/kernel/qcursor_s60.cpp b/src/gui/kernel/qcursor_s60.cpp
new file mode 100644
index 0000000..a281130
--- /dev/null
+++ b/src/gui/kernel/qcursor_s60.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qcursor_p.h>
+#include <qcursor.h>
+#include <qt_s60_p.h>
+
+#ifdef QT_NO_CURSOR
+QT_BEGIN_NAMESPACE
+
+QPoint QCursor::pos()
+{
+ return S60->lastCursorPos;
+}
+
+void QCursor::setPos(int x, int y)
+{
+ S60->lastCursorPos = QPoint(x, y);
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_CURSOR
diff --git a/src/gui/kernel/qdesktopwidget_s60.cpp b/src/gui/kernel/qdesktopwidget_s60.cpp
new file mode 100644
index 0000000..a333d62
--- /dev/null
+++ b/src/gui/kernel/qdesktopwidget_s60.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdesktopwidget.h"
+#include "qapplication_p.h"
+#include "qwidget_p.h"
+#include "qt_s60_p.h"
+#include <w32std.h>
+
+#include "hal.h"
+#include "hal_data.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDesktopWidgetPrivate : public QWidgetPrivate
+{
+
+public:
+ QDesktopWidgetPrivate();
+ ~QDesktopWidgetPrivate();
+
+ static void init(QDesktopWidget *that);
+ static void cleanup();
+
+ static int screenCount;
+ static int primaryScreen;
+
+ static QVector<QRect> *rects;
+ static QVector<QRect> *workrects;
+
+ static int refcount;
+};
+
+int QDesktopWidgetPrivate::screenCount = 1;
+int QDesktopWidgetPrivate::primaryScreen = 0;
+QVector<QRect> *QDesktopWidgetPrivate::rects = 0;
+QVector<QRect> *QDesktopWidgetPrivate::workrects = 0;
+int QDesktopWidgetPrivate::refcount = 0;
+
+QDesktopWidgetPrivate::QDesktopWidgetPrivate()
+{
+ ++refcount;
+}
+
+QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
+{
+ if (!--refcount)
+ cleanup();
+}
+
+void QDesktopWidgetPrivate::init(QDesktopWidget *that)
+{
+ int screenCount=0;
+
+ if (HAL::Get(0, HALData::EDisplayNumberOfScreens, screenCount) == KErrNone)
+ QDesktopWidgetPrivate::screenCount = screenCount;
+ else
+ QDesktopWidgetPrivate::screenCount = 0;
+
+ rects = new QVector<QRect>();
+ workrects = new QVector<QRect>();
+
+ rects->resize(QDesktopWidgetPrivate::screenCount);
+ workrects->resize(QDesktopWidgetPrivate::screenCount);
+
+ // ### TODO: Implement proper multi-display support
+ rects->resize(1);
+ rects->replace(0, that->rect());
+ workrects->resize(1);
+ workrects->replace(0, that->rect());
+}
+
+void QDesktopWidgetPrivate::cleanup()
+{
+ delete rects;
+ rects = 0;
+ delete workrects;
+ workrects = 0;
+}
+
+
+QDesktopWidget::QDesktopWidget()
+ : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop)
+{
+ setObjectName(QLatin1String("desktop"));
+ QDesktopWidgetPrivate::init(this);
+}
+
+QDesktopWidget::~QDesktopWidget()
+{
+ QDesktopWidgetPrivate::cleanup();
+}
+
+bool QDesktopWidget::isVirtualDesktop() const
+{
+ return true;
+}
+
+int QDesktopWidget::primaryScreen() const
+{
+ return QDesktopWidgetPrivate::primaryScreen;
+}
+
+int QDesktopWidget::numScreens() const
+{
+ Q_D(const QDesktopWidget);
+ return QDesktopWidgetPrivate::screenCount;
+}
+
+QWidget *QDesktopWidget::screen(int /* screen */)
+{
+ return this;
+}
+
+const QRect QDesktopWidget::availableGeometry(int /* screen */) const
+{
+ TRect clientRect = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+ return qt_TRect2QRect(clientRect);
+}
+
+const QRect QDesktopWidget::screenGeometry(int /* screen */) const
+{
+ Q_D(const QDesktopWidget);
+ return QRect(0, 0, S60->screenWidthInPixels, S60->screenHeightInPixels);
+ }
+
+int QDesktopWidget::screenNumber(const QWidget * /* widget */) const
+{
+ return QDesktopWidgetPrivate::primaryScreen;
+}
+
+int QDesktopWidget::screenNumber(const QPoint & /* point */) const
+{
+ return QDesktopWidgetPrivate::primaryScreen;
+}
+
+void QDesktopWidget::resizeEvent(QResizeEvent *)
+{
+ Q_D(QDesktopWidget);
+ QVector<QRect> oldrects;
+ oldrects = *d->rects;
+ QVector<QRect> oldworkrects;
+ oldworkrects = *d->workrects;
+ int oldscreencount = d->screenCount;
+
+ QDesktopWidgetPrivate::cleanup();
+ QDesktopWidgetPrivate::init(this);
+
+ for (int i = 0; i < qMin(oldscreencount, d->screenCount); ++i) {
+ QRect oldrect = oldrects[i];
+ QRect newrect = d->rects->at(i);
+ if (oldrect != newrect)
+ emit resized(i);
+ }
+
+ for (int j = 0; j < qMin(oldscreencount, d->screenCount); ++j) {
+ QRect oldrect = oldworkrects[j];
+ QRect newrect = d->workrects->at(j);
+ if (oldrect != newrect)
+ emit workAreaResized(j);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdnd_s60.cpp b/src/gui/kernel/qdnd_s60.cpp
new file mode 100644
index 0000000..c459f8f
--- /dev/null
+++ b/src/gui/kernel/qdnd_s60.cpp
@@ -0,0 +1,395 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+
+#ifndef QT_NO_DRAGANDDROP
+
+#include "qwidget.h"
+#include "qdatetime.h"
+#include "qbitmap.h"
+#include "qcursor.h"
+#include "qevent.h"
+#include "qpainter.h"
+#include "qdnd_p.h"
+
+#include <COECNTRL.H>
+// pointer cursor
+#include <w32std.h>
+#include <gdi.h>
+QT_BEGIN_NAMESPACE
+//### artistic impression of Symbians default DnD cursor ?
+
+static QPixmap *defaultPm = 0;
+static const int default_pm_hotx = -50;
+static const int default_pm_hoty = -50;
+static const char *const default_pm[] = {
+"13 9 3 1",
+". c None",
+" c #000000",
+"X c #FFFFFF",
+"X X X X X X X",
+" X X X X X X ",
+"X ......... X",
+" X.........X ",
+"X ......... X",
+" X.........X ",
+"X ......... X",
+" X X X X X X ",
+"X X X X X X X",
+};
+//### actions need to be redefined for S60
+// Shift/Ctrl handling, and final drop status
+static Qt::DropAction global_accepted_action = Qt::MoveAction;
+static Qt::DropActions possible_actions = Qt::IgnoreAction;
+
+
+// static variables in place of a proper cross-process solution
+static QDrag *drag_object;
+static bool qt_symbian_dnd_dragging = false;
+
+
+static Qt::KeyboardModifiers oldstate;
+
+class QShapedPixmapWidget
+{
+public:
+ QShapedPixmapWidget(RWsSession aWsSession,RWindowTreeNode* aNode)
+ {
+ sprite = RWsSprite(aWsSession);
+ cursorSprite.iBitmap = 0;
+ cursorSprite.iMaskBitmap = 0;
+ cursorSprite.iInvertMask = EFalse;
+ cursorSprite.iOffset = TPoint(0,0);
+ cursorSprite.iInterval = TTimeIntervalMicroSeconds32(0);
+ cursorSprite.iDrawMode = CGraphicsContext::EDrawModePEN;
+ sprite.Construct(*aNode,TPoint(0,0), ESpriteNoShadows | ESpriteNoChildClip);
+ sprite.AppendMember(cursorSprite);
+ sprite.Activate();
+ }
+ ~QShapedPixmapWidget()
+ {
+ sprite.Close();
+ cursorSprite.iBitmap = 0;
+ delete cursorBitmap;
+ cursorBitmap = 0; //redundant...
+ }
+ void disableCursor()
+ {
+ cursorSprite.iBitmap = 0;
+ sprite.UpdateMember(0,cursorSprite);
+ }
+ void enableCursor()
+ {
+ cursorSprite.iBitmap = cursorBitmap;
+ sprite.UpdateMember(0,cursorSprite);
+ }
+ void setPixmap(QPixmap pm)
+ {
+ //### heaplock centralized.
+ QImage temp = pm.toImage();
+ QSize size = pm.size();
+ temp.bits();
+ CFbsBitmap *curbm = new (ELeave) CFbsBitmap();
+ curbm->Create(TSize(size.width(),size.height()),EColor16MA);
+ curbm->LockHeap(ETrue);
+ memcpy((uchar*)curbm->DataAddress(),temp.bits(),temp.numBytes());
+ curbm->UnlockHeap(ETrue);
+ delete cursorSprite.iBitmap;
+ cursorSprite.iBitmap = curbm;
+ cursorBitmap = curbm;
+ sprite.UpdateMember(0,cursorSprite);
+ }
+ CFbsBitmap *cursorBitmap;
+ RWsPointerCursor pointerCursor;
+ RWsSprite sprite;
+ TSpriteMember cursorSprite;
+
+};
+
+
+static QShapedPixmapWidget *qt_symbian_dnd_deco = 0;
+
+void QDragManager::updatePixmap()
+{
+ if (qt_symbian_dnd_deco) {
+ QPixmap pm;
+ QPoint pm_hot(default_pm_hotx,default_pm_hoty);
+ if (drag_object) {
+ pm = drag_object->pixmap();
+ if (!pm.isNull())
+ pm_hot = drag_object->hotSpot();
+ }
+ if (pm.isNull()) {
+ if (!defaultPm)
+ defaultPm = new QPixmap(default_pm);
+ pm = *defaultPm;
+ }
+ qt_symbian_dnd_deco->setPixmap(pm);
+ }
+}
+
+void QDragManager::timerEvent(QTimerEvent *) { }
+
+void QDragManager::move(const QPoint&) {
+}
+
+void QDragManager::updateCursor()
+{
+}
+
+
+bool QDragManager::eventFilter(QObject *o, QEvent *e)
+{
+ if (beingCancelled) {
+ return false;
+ }
+ if (!o->isWidgetType())
+ return false;
+
+ switch(e->type()) {
+ case QEvent::MouseButtonPress:
+ {
+ }
+ case QEvent::MouseMove:
+ {
+ if (!object) { //#### this should not happen
+ qWarning("QDragManager::eventFilter: No object");
+ return true;
+ }
+ QDragManager *manager = QDragManager::self();
+ QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData;
+ if (manager->object)
+ possible_actions = manager->dragPrivate()->possible_actions;
+ else
+ possible_actions = Qt::IgnoreAction;
+
+ QMouseEvent *me = (QMouseEvent *)e;
+
+ if (me->buttons()) {
+ Qt::DropAction prevAction = global_accepted_action;
+ QWidget *cw = QApplication::widgetAt(me->globalPos());
+ // map the Coords relative to the window.
+ if (!cw)
+ return true;
+ TPoint windowPos = cw->effectiveWinId()->PositionRelativeToScreen();
+ qt_symbian_dnd_deco->sprite.SetPosition(TPoint(me->globalX()- windowPos.iX,me->globalY()- windowPos.iY));
+
+ while (cw && !cw->acceptDrops() && !cw->isWindow())
+ cw = cw->parentWidget();
+
+ if (object->target() != cw) {
+ if (object->target()) {
+ QDragLeaveEvent dle;
+ QApplication::sendEvent(object->target(), &dle);
+ willDrop = false;
+ global_accepted_action = Qt::IgnoreAction;
+ updateCursor();
+ restoreCursor = true;
+ object->d_func()->target = 0;
+ }
+ if (cw && cw->acceptDrops()) {
+ object->d_func()->target = cw;
+ QDragEnterEvent dee(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData,
+ me->buttons(), me->modifiers());
+ QApplication::sendEvent(object->target(), &dee);
+ willDrop = dee.isAccepted() && dee.dropAction() != Qt::IgnoreAction;
+ global_accepted_action = willDrop ? dee.dropAction() : Qt::IgnoreAction;
+ updateCursor();
+ restoreCursor = true;
+ }
+ } else if (cw) {
+ QDragMoveEvent dme(cw->mapFromGlobal(me->globalPos()), possible_actions, dropData,
+ me->buttons(), me->modifiers());
+ if (global_accepted_action != Qt::IgnoreAction) {
+ dme.setDropAction(global_accepted_action);
+ dme.accept();
+ }
+ QApplication::sendEvent(cw, &dme);
+ willDrop = dme.isAccepted();
+ global_accepted_action = willDrop ? dme.dropAction() : Qt::IgnoreAction;
+ updatePixmap();
+ updateCursor();
+ }
+ if (global_accepted_action != prevAction)
+ emitActionChanged(global_accepted_action);
+ }
+ return true; // Eat all mouse events
+ }
+
+ case QEvent::MouseButtonRelease:
+ {
+ qApp->removeEventFilter(this);
+ if (restoreCursor) {
+ qt_symbian_dnd_deco->disableCursor();
+ willDrop = false;
+ restoreCursor = false;
+ }
+ if (object && object->target()) {
+
+ QMouseEvent *me = (QMouseEvent *)e;
+
+ QDragManager *manager = QDragManager::self();
+ QMimeData *dropData = manager->object ? manager->dragPrivate()->data : manager->dropData;
+
+ QDropEvent de(object->target()->mapFromGlobal(me->globalPos()), possible_actions, dropData,
+ me->buttons(), me->modifiers());
+ QApplication::sendEvent(object->target(), &de);
+ if (de.isAccepted())
+ global_accepted_action = de.dropAction();
+ else
+ global_accepted_action = Qt::IgnoreAction;
+
+ if (object)
+ object->deleteLater();
+ drag_object = object = 0;
+ }
+ eventLoop->exit();
+ return true; // Eat all mouse events
+ }
+
+ default:
+ break;
+ }
+ return false;
+}
+
+Qt::DropAction QDragManager::drag(QDrag *o)
+{
+ Q_ASSERT(!qt_symbian_dnd_dragging);
+ if (object == o || !o || !o->source())
+ return Qt::IgnoreAction;
+
+ if (object) {
+ cancel();
+ qApp->removeEventFilter(this);
+ beingCancelled = false;
+ }
+
+ object = drag_object = o;
+ RWsSession winSession = o->source()->effectiveWinId()->ControlEnv()->WsSession();
+ Q_ASSERT(!qt_symbian_dnd_deco);
+ qt_symbian_dnd_deco = new QShapedPixmapWidget(winSession, o->source()->effectiveWinId()->DrawableWindow());
+
+ oldstate = Qt::NoModifier; // #### Should use state that caused the drag
+ willDrop = false;
+ updatePixmap();
+ updateCursor();
+ restoreCursor = true;
+
+ object->d_func()->target = 0;
+ TPoint windowPos = source()->effectiveWinId()->PositionRelativeToScreen();
+ qt_symbian_dnd_deco->sprite.SetPosition(TPoint(QCursor::pos().x()- windowPos.iX ,QCursor::pos().y() - windowPos.iY));
+
+ QPoint hotspot = drag_object->hotSpot();
+ qt_symbian_dnd_deco->cursorSprite.iOffset = TPoint(- hotspot.x(),- hotspot.y());
+ qt_symbian_dnd_deco->sprite.UpdateMember(0,qt_symbian_dnd_deco->cursorSprite);
+
+ qApp->installEventFilter(this);
+
+ global_accepted_action = Qt::MoveAction;
+ qt_symbian_dnd_dragging = true;
+
+ eventLoop = new QEventLoop;
+ // block
+ (void) eventLoop->exec(QEventLoop::AllEvents);
+ delete eventLoop;
+ eventLoop = 0;
+
+ delete qt_symbian_dnd_deco;
+ qt_symbian_dnd_deco = 0;
+ qt_symbian_dnd_dragging = false;
+
+
+ return global_accepted_action;
+}
+
+
+void QDragManager::cancel(bool deleteSource)
+{
+ beingCancelled = true;
+
+ if (object->target()) {
+ QDragLeaveEvent dle;
+ QApplication::sendEvent(object->target(), &dle);
+ }
+
+ if (drag_object) {
+ if (deleteSource)
+ object->deleteLater();
+ drag_object = object = 0;
+ }
+
+ delete qt_symbian_dnd_deco;
+ qt_symbian_dnd_deco = 0;
+
+ global_accepted_action = Qt::IgnoreAction;
+}
+
+
+void QDragManager::drop()
+{
+}
+
+QVariant QDropData::retrieveData_sys(const QString &mimetype, QVariant::Type type) const
+{
+ if (!drag_object)
+ return QVariant();
+ QByteArray data = drag_object->mimeData()->data(mimetype);
+ if (type == QVariant::String)
+ return QString::fromUtf8(data);
+ return data;
+}
+
+bool QDropData::hasFormat_sys(const QString &format) const
+{
+ return formats().contains(format);
+}
+
+QStringList QDropData::formats_sys() const
+{
+ if (drag_object)
+ return drag_object->mimeData()->formats();
+ return QStringList();
+}
+
+QT_END_NAMESPACE
+#endif // QT_NO_DRAGANDDROP
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 328ba3d..a6a87b7 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -1688,6 +1688,17 @@ Qt::ButtonState QContextMenuEvent::state() const
several are specified for any character in the string the behaviour
is undefined.
+ \value Selection
+ If set, the edit cursor should be moved to the specified position
+ in the editor text contents. In contrast with \c Cursor, this
+ attribute does not work on the preedit text, but on the surrounding
+ text. The cursor will be moved after the commit string has been
+ committed, and the preedit string will be located at the new edit
+ position.
+ The start position specifies the new position and the length
+ variable can be used to set a selection starting from that point.
+ The value is unused.
+
\sa Attribute
*/
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 11843cb..a1cfbe5 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -245,7 +245,7 @@ public:
inline QT3_SUPPORT_CONSTRUCTOR QKeyEvent(Type type, int key, int /*ascii*/,
int modifiers, const QString& text = QString(),
bool autorep = false, ushort count = 1)
- : QInputEvent(type, (Qt::KeyboardModifiers)(modifiers & (int)Qt::KeyButtonMask)), txt(text), k(key),
+ : QInputEvent(type, Qt::KeyboardModifiers(modifiers & (int)Qt::KeyButtonMask)), txt(text), k(key),
c(count), autor(autorep)
{
if (key >= Qt::Key_Back && key <= Qt::Key_MediaLast)
@@ -428,7 +428,8 @@ public:
TextFormat,
Cursor,
Language,
- Ruby
+ Ruby,
+ Selection
};
class Attribute {
public:
diff --git a/src/gui/kernel/qeventdispatcher_s60.cpp b/src/gui/kernel/qeventdispatcher_s60.cpp
new file mode 100644
index 0000000..51878df
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_s60.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qwidget.h>
+
+#include "qeventdispatcher_s60_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QEventDispatcherS60::QEventDispatcherS60(QObject *parent)
+ : QEventDispatcherSymbian(parent),
+ m_noInputEvents(false)
+{
+}
+
+QEventDispatcherS60::~QEventDispatcherS60()
+{
+ for (int c = 0; c < m_deferredInputEvents.size(); ++c) {
+ delete m_deferredInputEvents[c].event;
+ }
+}
+
+bool QEventDispatcherS60::processEvents ( QEventLoop::ProcessEventsFlags flags )
+{
+ bool ret = false;
+
+ QT_TRY {
+ bool oldNoInputEventsValue = m_noInputEvents;
+ if (flags & QEventLoop::ExcludeUserInputEvents) {
+ m_noInputEvents = true;
+ } else {
+ m_noInputEvents = false;
+ ret = sendDeferredInputEvents() || ret;
+ }
+
+ ret = QEventDispatcherSymbian::processEvents(flags) || ret;
+
+ m_noInputEvents = oldNoInputEventsValue;
+ } QT_CATCH (const std::exception& ex) {
+#ifndef QT_NO_EXCEPTIONS
+ CActiveScheduler::Current()->Error(qt_translateExceptionToSymbianError(ex));
+#endif
+ }
+
+ return ret;
+}
+
+bool QEventDispatcherS60::hasPendingEvents()
+{
+ return !m_deferredInputEvents.isEmpty() || QEventDispatcherSymbian::hasPendingEvents();
+}
+
+void QEventDispatcherS60::saveInputEvent(QSymbianControl *control, QWidget *widget, QInputEvent *event)
+{
+ DeferredInputEvent inputEvent = {control, widget, event};
+ m_deferredInputEvents.append(inputEvent);
+ connect(widget, SIGNAL(destroyed(QObject *)), SLOT(removeInputEventsForWidget(QObject *)));
+}
+
+bool QEventDispatcherS60::sendDeferredInputEvents()
+{
+ bool eventsSent = false;
+ while (!m_deferredInputEvents.isEmpty()) {
+ DeferredInputEvent inputEvent = m_deferredInputEvents.takeFirst();
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+ inputEvent.control->sendInputEvent(inputEvent.widget, inputEvent.event);
+#ifndef QT_NO_EXCEPTIONS
+ } catch (...) {
+ delete inputEvent.event;
+ throw;
+ }
+#endif
+ delete inputEvent.event;
+ eventsSent = true;
+ }
+
+ return eventsSent;
+}
+
+void QEventDispatcherS60::removeInputEventsForWidget(QObject *object)
+{
+ for (int c = 0; c < m_deferredInputEvents.size(); ++c) {
+ if (m_deferredInputEvents[c].widget == object) {
+ delete m_deferredInputEvents[c].event;
+ m_deferredInputEvents.removeAt(c--);
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qeventdispatcher_s60_p.h b/src/gui/kernel/qeventdispatcher_s60_p.h
new file mode 100644
index 0000000..e42af95
--- /dev/null
+++ b/src/gui/kernel/qeventdispatcher_s60_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTDISPATCHER_S60_P_H
+#define QEVENTDISPATCHER_S60_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qeventdispatcher_symbian_p.h>
+#include "qt_s60_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QEventDispatcherS60 : public QEventDispatcherSymbian
+{
+ Q_OBJECT
+
+public:
+ QEventDispatcherS60(QObject *parent = 0);
+ ~QEventDispatcherS60();
+
+ bool processEvents ( QEventLoop::ProcessEventsFlags flags );
+ bool hasPendingEvents();
+
+ bool excludeUserInputEvents() { return m_noInputEvents; }
+
+ void saveInputEvent(QSymbianControl *control, QWidget *widget, QInputEvent *event);
+
+private:
+ bool sendDeferredInputEvents();
+
+private Q_SLOTS:
+ void removeInputEventsForWidget(QObject *object);
+
+private:
+ bool m_noInputEvents;
+
+ struct DeferredInputEvent
+ {
+ QSymbianControl *control;
+ QWidget *widget;
+ QInputEvent *event;
+ };
+ QList<DeferredInputEvent> m_deferredInputEvents;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_S60_P_H
diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h
index 5c06b4c..ba1fcfe 100644
--- a/src/gui/kernel/qkeymapper_p.h
+++ b/src/gui/kernel/qkeymapper_p.h
@@ -58,6 +58,7 @@
#include <qlist.h>
#include <qlocale.h>
#include <qevent.h>
+#include <qhash.h>
#if defined (Q_WS_MAC64)
# include <private/qt_mac_p.h>
@@ -203,6 +204,13 @@ public:
UInt32 keyboard_dead;
KeyboardLayoutItem *keyLayout[256];
#elif defined(Q_WS_QWS)
+#elif defined(Q_OS_SYMBIAN)
+private:
+ QHash<TUint, int> s60ToQtKeyMap;
+ void fillKeyMap();
+public:
+ QString translateKeyEvent(int keySym, Qt::KeyboardModifiers modifiers);
+ int mapS60KeyToQt(TUint s60key);
#endif
};
diff --git a/src/gui/kernel/qkeymapper_s60.cpp b/src/gui/kernel/qkeymapper_s60.cpp
new file mode 100644
index 0000000..c13dd51
--- /dev/null
+++ b/src/gui/kernel/qkeymapper_s60.cpp
@@ -0,0 +1,247 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qkeymapper_p.h"
+#include <e32keys.h>
+
+QT_BEGIN_NAMESPACE
+
+QKeyMapperPrivate::QKeyMapperPrivate()
+{
+ fillKeyMap();
+}
+
+QKeyMapperPrivate::~QKeyMapperPrivate()
+{
+}
+
+QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent * /* e */)
+{
+ QList<int> result;
+ return result;
+}
+
+void QKeyMapperPrivate::clearMappings()
+{
+ // stub
+}
+
+QString QKeyMapperPrivate::translateKeyEvent(int keySym, Qt::KeyboardModifiers /* modifiers */)
+{
+ if (keySym >= Qt::Key_Escape)
+ return QString();
+
+ // Symbian doesn't actually use modifiers, but gives us the character code directly.
+
+ return QString(QChar(keySym));
+}
+
+void QKeyMapperPrivate::fillKeyMap()
+{
+ using namespace Qt;
+ static const struct {
+ TUint s60Key;
+ int qtKey;
+ } map[] = {
+ {EKeyBell, Key_unknown},
+ {EKeyBackspace, Key_Backspace},
+ {EKeyTab, Key_Tab},
+ {EKeyLineFeed, Key_unknown},
+ {EKeyVerticalTab, Key_unknown},
+ {EKeyFormFeed, Key_unknown},
+ {EKeyEnter, Key_Enter},
+ {EKeyEscape, Key_Escape},
+ {EKeySpace, Key_Space},
+ {EKeyDelete, Key_Delete},
+ {EKeyPrintScreen, Key_SysReq},
+ {EKeyPause, Key_Pause},
+ {EKeyHome, Key_Home},
+ {EKeyEnd, Key_End},
+ {EKeyPageUp, Key_PageUp},
+ {EKeyPageDown, Key_PageDown},
+ {EKeyInsert, Key_Insert},
+ {EKeyLeftArrow, Key_Left},
+ {EKeyRightArrow, Key_Right},
+ {EKeyUpArrow, Key_Up},
+ {EKeyDownArrow, Key_Down},
+ {EKeyLeftShift, Key_Shift},
+ {EKeyRightShift, Key_Shift},
+ {EKeyLeftAlt, Key_Alt},
+ {EKeyRightAlt, Key_AltGr},
+ {EKeyLeftCtrl, Key_Control},
+ {EKeyRightCtrl, Key_Control},
+ {EKeyLeftFunc, Key_Super_L},
+ {EKeyRightFunc, Key_Super_R},
+ {EKeyCapsLock, Key_CapsLock},
+ {EKeyNumLock, Key_NumLock},
+ {EKeyScrollLock, Key_ScrollLock},
+ {EKeyF1, Key_F1},
+ {EKeyF2, Key_F2},
+ {EKeyF3, Key_F3},
+ {EKeyF4, Key_F4},
+ {EKeyF5, Key_F5},
+ {EKeyF6, Key_F6},
+ {EKeyF7, Key_F7},
+ {EKeyF8, Key_F8},
+ {EKeyF9, Key_F9},
+ {EKeyF10, Key_F10},
+ {EKeyF11, Key_F11},
+ {EKeyF12, Key_F12},
+ {EKeyF13, Key_F13},
+ {EKeyF14, Key_F14},
+ {EKeyF15, Key_F15},
+ {EKeyF16, Key_F16},
+ {EKeyF17, Key_F17},
+ {EKeyF18, Key_F18},
+ {EKeyF19, Key_F19},
+ {EKeyF20, Key_F20},
+ {EKeyF21, Key_F21},
+ {EKeyF22, Key_F22},
+ {EKeyF23, Key_F23},
+ {EKeyF24, Key_F24},
+ {EKeyOff, Key_unknown},
+ {EKeyIncContrast, Key_unknown},
+ {EKeyDecContrast, Key_unknown},
+ {EKeyBacklightOn, Key_unknown},
+ {EKeyBacklightOff, Key_unknown},
+ {EKeyBacklightToggle, Key_unknown},
+ {EKeySliderDown, Key_unknown},
+ {EKeySliderUp, Key_unknown},
+ {EKeyMenu, Key_Menu},
+ {EKeyDictaphonePlay, Key_unknown},
+ {EKeyDictaphoneStop, Key_unknown},
+ {EKeyDictaphoneRecord, Key_unknown},
+ {EKeyHelp, Key_unknown},
+ {EKeyDial, Key_Call},
+ {EKeyScreenDimension0, Key_unknown},
+ {EKeyScreenDimension1, Key_unknown},
+ {EKeyScreenDimension2, Key_unknown},
+ {EKeyScreenDimension3, Key_unknown},
+ {EKeyIncVolume, Key_unknown},
+ {EKeyDecVolume, Key_unknown},
+ {EKeyDevice0, Key_Context1}, // Found by manual testing, left softkey.
+ {EKeyDevice1, Key_Context2}, // Found by manual testing.
+ {EKeyDevice2, Key_unknown},
+ {EKeyDevice3, Key_Select}, // Found by manual testing.
+ {EKeyDevice4, Key_unknown},
+ {EKeyDevice5, Key_unknown},
+ {EKeyDevice6, Key_unknown},
+ {EKeyDevice7, Key_unknown},
+ {EKeyDevice8, Key_unknown},
+ {EKeyDevice9, Key_unknown},
+ {EKeyDeviceA, Key_unknown},
+ {EKeyDeviceB, Key_unknown},
+ {EKeyDeviceC, Key_unknown},
+ {EKeyDeviceD, Key_unknown},
+ {EKeyDeviceE, Key_unknown},
+ {EKeyDeviceF, Key_unknown},
+ {EKeyApplication0, Key_Launch0},
+ {EKeyApplication1, Key_Launch1},
+ {EKeyApplication2, Key_Launch2},
+ {EKeyApplication3, Key_Launch3},
+ {EKeyApplication4, Key_Launch4},
+ {EKeyApplication5, Key_Launch5},
+ {EKeyApplication6, Key_Launch6},
+ {EKeyApplication7, Key_Launch7},
+ {EKeyApplication8, Key_Launch8},
+ {EKeyApplication9, Key_Launch9},
+ {EKeyApplicationA, Key_LaunchA},
+ {EKeyApplicationB, Key_LaunchB},
+ {EKeyApplicationC, Key_LaunchC},
+ {EKeyApplicationD, Key_LaunchD},
+ {EKeyApplicationE, Key_LaunchE},
+ {EKeyApplicationF, Key_LaunchF},
+ {EKeyYes, Key_Yes},
+ {EKeyNo, Key_No},
+ {EKeyIncBrightness, Key_unknown},
+ {EKeyDecBrightness, Key_unknown},
+ {EKeyKeyboardExtend, Key_unknown},
+ {EKeyDevice10, Key_unknown},
+ {EKeyDevice11, Key_unknown},
+ {EKeyDevice12, Key_unknown},
+ {EKeyDevice13, Key_unknown},
+ {EKeyDevice14, Key_unknown},
+ {EKeyDevice15, Key_unknown},
+ {EKeyDevice16, Key_unknown},
+ {EKeyDevice17, Key_unknown},
+ {EKeyDevice18, Key_unknown},
+ {EKeyDevice19, Key_unknown},
+ {EKeyDevice1A, Key_unknown},
+ {EKeyDevice1B, Key_unknown},
+ {EKeyDevice1C, Key_unknown},
+ {EKeyDevice1D, Key_unknown},
+ {EKeyDevice1E, Key_unknown},
+ {EKeyDevice1F, Key_unknown},
+ {EKeyApplication10, Key_unknown},
+ {EKeyApplication11, Key_unknown},
+ {EKeyApplication12, Key_unknown},
+ {EKeyApplication13, Key_unknown},
+ {EKeyApplication14, Key_unknown},
+ {EKeyApplication15, Key_unknown},
+ {EKeyApplication16, Key_unknown},
+ {EKeyApplication17, Key_unknown},
+ {EKeyApplication18, Key_unknown},
+ {EKeyApplication19, Key_unknown},
+ {EKeyApplication1A, Key_unknown},
+ {EKeyApplication1B, Key_unknown},
+ {EKeyApplication1C, Key_unknown},
+ {EKeyApplication1D, Key_unknown},
+ {EKeyApplication1E, Key_unknown},
+ {EKeyApplication1F, Key_unknown}
+ };
+ const int mapSize = int(sizeof(map)/sizeof(map[0]));
+ s60ToQtKeyMap.reserve(mapSize + 5); // +5? docs: Ideally, slightly more than number of items
+ for (int i = 0; i < mapSize; ++i)
+ s60ToQtKeyMap.insert(map[i].s60Key, map[i].qtKey);
+}
+
+int QKeyMapperPrivate::mapS60KeyToQt(TUint s60key)
+{
+ QHash<TUint, int>::const_iterator mapping;
+ mapping = s60ToQtKeyMap.find(s60key);
+ if (mapping != s60ToQtKeyMap.end()) {
+ return *mapping;
+ } else {
+ return Qt::Key_unknown;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index d27eacd..6563dae 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -226,72 +226,72 @@ void Q_AUTOTEST_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mn
corresponds to the \key Control keys.
\table
- \header \i StandardKey \i Windows \i Mac OS X \i KDE \i GNOME
- \row \i HelpContents \i F1 \i Ctrl+? \i F1 \i F1
- \row \i WhatsThis \i Shift+F1 \i Shift+F1 \i Shift+F1 \i Shift+F1
- \row \i Open \i Ctrl+O \i Ctrl+O \i Ctrl+O \i Ctrl+O
- \row \i Close \i Ctrl+F4, Ctrl+W \i Ctrl+W, Ctrl+F4 \i Ctrl+W \i Ctrl+W
- \row \i Save \i Ctrl+S \i Ctrl+S \i Ctrl+S \i Ctrl+S
- \row \i Quit \i \i Ctrl+Q \i Qtrl+Q \i Qtrl+Q
- \row \i SaveAs \i \i Ctrl+Shift+S \i \i Ctrl+Shift+S
- \row \i New \i Ctrl+N \i Ctrl+N \i Ctrl+N \i Ctrl+N
- \row \i Delete \i Del \i Del, Meta+D \i Del, Ctrl+D \i Del, Ctrl+D
- \row \i Cut \i Ctrl+X, Shift+Del \i Ctrl+X \i Ctrl+X, F20, Shift+Del \i Ctrl+X, F20, Shift+Del
- \row \i Copy \i Ctrl+C, Ctrl+Ins \i Ctrl+C \i Ctrl+C, F16, Ctrl+Ins \i Ctrl+C, F16, Ctrl+Ins
- \row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins
- \row \i Preferences \i \i Ctrl+, \i \i
- \row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14
- \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z, Ctrl+Y \i Ctrl+Shift+Z \i Ctrl+Shift+Z
- \row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left
- \row \i Forward \i Alt+Right, Shift+Backspace \i Ctrl+] \i Alt+Right \i Alt+Right
- \row \i Refresh \i F5 \i F5 \i F5 \i Ctrl+R, F5
- \row \i ZoomIn \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus
- \row \i ZoomOut \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus
- \row \i Print \i Ctrl+P \i Ctrl+P \i Ctrl+P \i Ctrl+P
- \row \i AddTab \i Ctrl+T \i Ctrl+T \i Ctrl+Shift+N, Ctrl+T \i Ctrl+T
- \row \i NextChild \i Ctrl+Tab, Forward, Ctrl+F6 \i Ctrl+}, Forward, Ctrl+Tab \i Ctrl+Tab, Forward, Ctrl+Comma \i Ctrl+Tab, Forward
- \row \i PreviousChild \i Ctrl+Shift+Tab, Back, Ctrl+Shift+F6 \i Ctrl+{, Back, Ctrl+Shift+Tab \i Ctrl+Shift+Tab, Back, Ctrl+Period \i Ctrl+Shift+Tab, Back
- \row \i Find \i Ctrl+F \i Ctrl+F \i Ctrl+F \i Ctrl+F
- \row \i FindNext \i F3, Ctrl+G \i Ctrl+G \i F3 \i Ctrl+G, F3
- \row \i FindPrevious \i Shift+F3, Ctrl+Shift+G \i Ctrl+Shift+G \i Shift+F3 \i Ctrl+Shift+G, Shift+F3
- \row \i Replace \i Ctrl+H \i (none) \i Ctrl+R \i Ctrl+H
- \row \i SelectAll \i Ctrl+A \i Ctrl+A \i Ctrl+A \i Ctrl+A
- \row \i Bold \i Ctrl+B \i Ctrl+B \i Ctrl+B \i Ctrl+B
- \row \i Italic \i Ctrl+I \i Ctrl+I \i Ctrl+I \i Ctrl+I
- \row \i Underline \i Ctrl+U \i Ctrl+U \i Ctrl+U \i Ctrl+U
- \row \i MoveToNextChar \i Right \i Right \i Right \i Right
- \row \i MoveToPreviousChar \i Left \i Left \i Left \i Left
- \row \i MoveToNextWord \i Ctrl+Right \i Alt+Right \i Ctrl+Right \i Ctrl+Right
- \row \i MoveToPreviousWord \i Ctrl+Left \i Alt+Left \i Ctrl+Left \i Ctrl+Left
- \row \i MoveToNextLine \i Down \i Down \i Down \i Down
- \row \i MoveToPreviousLine \i Up \i Up \i Up \i Up
- \row \i MoveToNextPage \i PgDown \i PgDown, Alt+PgDown, Meta+Down, Meta+PgDown\i PgDown \i PgDown
- \row \i MoveToPreviousPage \i PgUp \i PgUp, Alt+PgUp, Meta+Up, Meta+PgUp \i PgUp \i PgUp
- \row \i MoveToStartOfLine \i Home \i Ctrl+Left, Meta+Left \i Home \i Home
- \row \i MoveToEndOfLine \i End \i Ctrl+Right, Meta+Right \i End \i End
- \row \i MoveToStartOfBlock \i (none) \i Alt+Up, Meta+A \i (none) \i (none)
- \row \i MoveToEndOfBlock \i (none) \i Alt+Down, Meta+E \i (none) \i (none)
- \row \i MoveToStartOfDocument\i Ctrl+Home \i Ctrl+Up, Home \i Ctrl+Home \i Ctrl+Home
- \row \i MoveToEndOfDocument \i Ctrl+End \i Ctrl+Down, End \i Ctrl+End \i Ctrl+End
- \row \i SelectNextChar \i Shift+Right \i Shift+Right \i Shift+Right \i Shift+Right
- \row \i SelectPreviousChar \i Shift+Left \i Shift+Left \i Shift+Left \i Shift?left
- \row \i SelectNextWord \i Ctrl+Shift+Right \i Alt+Shift+Right \i Ctrl+Shift+Right \i Ctrl+Shift+Right
- \row \i SelectPreviousWord \i Ctrl+Shift+Left \i Alt+Shift+Left \i Ctrl+Shift+Left \i Ctrl+Shift+Left
- \row \i SelectNextLine \i Shift+Down \i Shift+Down \i Shift+Down \i Shift+Down
- \row \i SelectPreviousLine \i Shift+Up \i Shift+Up \i Shift+Up \i Shift+Up
- \row \i SelectNextPage \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown
- \row \i SelectPreviousPage \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp
- \row \i SelectStartOfLine \i Shift+Home \i Ctrl+Shift+Left \i Shift+Home \i Shift+Home
- \row \i SelectEndOfLine \i Shift+End \i Ctrl+Shift+Right \i Shift+End \i Shift+End
- \row \i SelectStartOfBlock \i (none) \i Alt+Shift+Up \i (none) \i (none)
- \row \i SelectEndOfBlock \i (none) \i Alt+Shift+Down \i (none) \i (none)
- \row \i SelectStartOfDocument\i Ctrl+Shift+Home \i Ctrl+Shift+Up, Shift+Home \i Ctrl+Shift+Home\i Ctrl+Shift+Home
- \row \i SelectEndOfDocument \i Ctrl+Shift+End \i Ctrl+Shift+Down, Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End
- \row \i DeleteStartOfWord \i Ctrl+Backspace \i Alt+Backspace \i Ctrl+Backspace \i Ctrl+Backspace
- \row \i DeleteEndOfWord \i Ctrl+Del \i (none) \i Ctrl+Del \i Ctrl+Del
- \row \i DeleteEndOfLine \i (none) \i (none) \i Ctrl+K \i Ctrl+K
- \row \i InsertParagraphSeparator \i Enter \i Enter \i Enter \i Enter
- \row \i InsertLineSeparator \i Shift+Enter \i Meta+Enter \i Shift+Enter \i Shift+Enter
+ \header \i StandardKey \i Windows \i Mac OS X \i KDE \i GNOME \i S60
+ \row \i HelpContents \i F1 \i Ctrl+? \i F1 \i F1 \i F2
+ \row \i WhatsThis \i Shift+F1 \i Shift+F1 \i Shift+F1 \i Shift+F1 \i Shift+F1
+ \row \i Open \i Ctrl+O \i Ctrl+O \i Ctrl+O \i Ctrl+O \i (none)
+ \row \i Close \i Ctrl+F4, Ctrl+W \i Ctrl+W, Ctrl+F4 \i Ctrl+W \i Ctrl+W \i (none)
+ \row \i Save \i Ctrl+S \i Ctrl+S \i Ctrl+S \i Ctrl+S \i (none)
+ \row \i Quit \i \i Ctrl+Q \i Qtrl+Q \i Qtrl+Q \i (none)
+ \row \i SaveAs \i \i Ctrl+Shift+S \i \i Ctrl+Shift+S \i (none)
+ \row \i New \i Ctrl+N \i Ctrl+N \i Ctrl+N \i Ctrl+N \i (none)
+ \row \i Delete \i Del \i Del, Meta+D \i Del, Ctrl+D \i Del, Ctrl+D \i Del
+ \row \i Cut \i Ctrl+X, Shift+Del \i Ctrl+X \i Ctrl+X, F20, Shift+Del \i Ctrl+X, F20, Shift+Del \i Ctrl+X
+ \row \i Copy \i Ctrl+C, Ctrl+Ins \i Ctrl+C \i Ctrl+C, F16, Ctrl+Ins \i Ctrl+C, F16, Ctrl+Ins \i Ctrl+C
+ \row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins \i Ctrl+V
+ \row \i Preferences \i \i Ctrl+, \i \i \i (none)
+ \row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14 \i Ctrl+Z
+ \row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z, Ctrl+Y \i Ctrl+Shift+Z \i Ctrl+Shift+Z \i (none)
+ \row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left \i (none)
+ \row \i Forward \i Alt+Right, Shift+Backspace \i Ctrl+] \i Alt+Right \i Alt+Right \i (none)
+ \row \i Refresh \i F5 \i F5 \i F5 \i Ctrl+R, F5 \i (none)
+ \row \i ZoomIn \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus \i Ctrl+Plus \i (none)
+ \row \i ZoomOut \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus \i Ctrl+Minus \i (none)
+ \row \i Print \i Ctrl+P \i Ctrl+P \i Ctrl+P \i Ctrl+P \i (none)
+ \row \i AddTab \i Ctrl+T \i Ctrl+T \i Ctrl+Shift+N, Ctrl+T \i Ctrl+T \i (none)
+ \row \i NextChild \i Ctrl+Tab, Forward, Ctrl+F6 \i Ctrl+}, Forward, Ctrl+Tab \i Ctrl+Tab, Forward, Ctrl+Comma \i Ctrl+Tab, Forward \i (none)
+ \row \i PreviousChild \i Ctrl+Shift+Tab, Back, Ctrl+Shift+F6 \i Ctrl+{, Back, Ctrl+Shift+Tab \i Ctrl+Shift+Tab, Back, Ctrl+Period \i Ctrl+Shift+Tab, Back \i (none)
+ \row \i Find \i Ctrl+F \i Ctrl+F \i Ctrl+F \i Ctrl+F \i (none)
+ \row \i FindNext \i F3, Ctrl+G \i Ctrl+G \i F3 \i Ctrl+G, F3 \i (none)
+ \row \i FindPrevious \i Shift+F3, Ctrl+Shift+G \i Ctrl+Shift+G \i Shift+F3 \i Ctrl+Shift+G, Shift+F3 \i (none)
+ \row \i Replace \i Ctrl+H \i (none) \i Ctrl+R \i Ctrl+H \i (none)
+ \row \i SelectAll \i Ctrl+A \i Ctrl+A \i Ctrl+A \i Ctrl+A \i (none)
+ \row \i Bold \i Ctrl+B \i Ctrl+B \i Ctrl+B \i Ctrl+B \i (none)
+ \row \i Italic \i Ctrl+I \i Ctrl+I \i Ctrl+I \i Ctrl+I \i (none)
+ \row \i Underline \i Ctrl+U \i Ctrl+U \i Ctrl+U \i Ctrl+U \i (none)
+ \row \i MoveToNextChar \i Right \i Right \i Right \i Right \i Right
+ \row \i MoveToPreviousChar \i Left \i Left \i Left \i Left \i Left
+ \row \i MoveToNextWord \i Ctrl+Right \i Alt+Right \i Ctrl+Right \i Ctrl+Right \i Ctrl+Right
+ \row \i MoveToPreviousWord \i Ctrl+Left \i Alt+Left \i Ctrl+Left \i Ctrl+Left \i Ctrl+Left
+ \row \i MoveToNextLine \i Down \i Down \i Down \i Down \i Down
+ \row \i MoveToPreviousLine \i Up \i Up \i Up \i Up \i Up
+ \row \i MoveToNextPage \i PgDown \i PgDown, Alt+PgDown, Meta+Down, Meta+PgDown\i PgDown \i PgDown \i PgDown
+ \row \i MoveToPreviousPage \i PgUp \i PgUp, Alt+PgUp, Meta+Up, Meta+PgUp \i PgUp \i PgUp \i PgUp
+ \row \i MoveToStartOfLine \i Home \i Ctrl+Left, Meta+Left \i Home \i Home \i Home
+ \row \i MoveToEndOfLine \i End \i Ctrl+Right, Meta+Right \i End \i End \i End
+ \row \i MoveToStartOfBlock \i (none) \i Alt+Up, Meta+A \i (none) \i (none) \i (none)
+ \row \i MoveToEndOfBlock \i (none) \i Alt+Down, Meta+E \i (none) \i (none) \i (none)
+ \row \i MoveToStartOfDocument\i Ctrl+Home \i Ctrl+Up, Home \i Ctrl+Home \i Ctrl+Home \i Ctrl+Home
+ \row \i MoveToEndOfDocument \i Ctrl+End \i Ctrl+Down, End \i Ctrl+End \i Ctrl+End \i Ctrl+End
+ \row \i SelectNextChar \i Shift+Right \i Shift+Right \i Shift+Right \i Shift+Right \i Shift+Right
+ \row \i SelectPreviousChar \i Shift+Left \i Shift+Left \i Shift+Left \i Shift+Left \i Shift+Left
+ \row \i SelectNextWord \i Ctrl+Shift+Right \i Alt+Shift+Right \i Ctrl+Shift+Right \i Ctrl+Shift+Right \i Ctrl+Shift+Right
+ \row \i SelectPreviousWord \i Ctrl+Shift+Left \i Alt+Shift+Left \i Ctrl+Shift+Left \i Ctrl+Shift+Left \i Ctrl+Shift+Left
+ \row \i SelectNextLine \i Shift+Down \i Shift+Down \i Shift+Down \i Shift+Down \i Shift+Down
+ \row \i SelectPreviousLine \i Shift+Up \i Shift+Up \i Shift+Up \i Shift+Up \i Shift+Up
+ \row \i SelectNextPage \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown \i Shift+PgDown
+ \row \i SelectPreviousPage \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp \i Shift+PgUp
+ \row \i SelectStartOfLine \i Shift+Home \i Ctrl+Shift+Left \i Shift+Home \i Shift+Home \i Shift+Home
+ \row \i SelectEndOfLine \i Shift+End \i Ctrl+Shift+Right \i Shift+End \i Shift+End \i Shift+End
+ \row \i SelectStartOfBlock \i (none) \i Alt+Shift+Up \i (none) \i (none) \i (none)
+ \row \i SelectEndOfBlock \i (none) \i Alt+Shift+Down \i (none) \i (none) \i (none)
+ \row \i SelectStartOfDocument\i Ctrl+Shift+Home \i Ctrl+Shift+Up, Shift+Home \i Ctrl+Shift+Home\i Ctrl+Shift+Home \i Ctrl+Shift+Home
+ \row \i SelectEndOfDocument \i Ctrl+Shift+End \i Ctrl+Shift+Down, Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End \i Ctrl+Shift+End
+ \row \i DeleteStartOfWord \i Ctrl+Backspace \i Alt+Backspace \i Ctrl+Backspace \i Ctrl+Backspace \i (none)
+ \row \i DeleteEndOfWord \i Ctrl+Del \i (none) \i Ctrl+Del \i Ctrl+Del \i (none)
+ \row \i DeleteEndOfLine \i (none) \i (none) \i Ctrl+K \i Ctrl+K \i (none)
+ \row \i InsertParagraphSeparator \i Enter \i Enter \i Enter \i Enter \i (none)
+ \row \i InsertLineSeparator \i Shift+Enter \i Meta+Enter \i Shift+Enter \i Shift+Enter \i (none)
\endtable
Note that, since the key sequences used for the standard shortcuts differ
@@ -502,9 +502,9 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::InsertParagraphSeparator,0, Qt::Key_Return, QApplicationPrivate::KB_All},
{QKeySequence::InsertParagraphSeparator,0, Qt::Key_Enter, QApplicationPrivate::KB_All},
{QKeySequence::Delete, 1, Qt::Key_Delete, QApplicationPrivate::KB_All},
- {QKeySequence::MoveToStartOfLine, 0, Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToStartOfLine, 0, Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::MoveToStartOfDocument, 0, Qt::Key_Home, QApplicationPrivate::KB_Mac},
- {QKeySequence::MoveToEndOfLine, 0, Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToEndOfLine, 0, Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::MoveToEndOfDocument, 0, Qt::Key_End, QApplicationPrivate::KB_Mac},
{QKeySequence::MoveToPreviousChar, 0, Qt::Key_Left, QApplicationPrivate::KB_All},
{QKeySequence::MoveToPreviousLine, 0, Qt::Key_Up, QApplicationPrivate::KB_All},
@@ -513,6 +513,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::MoveToPreviousPage, 1, Qt::Key_PageUp, QApplicationPrivate::KB_All},
{QKeySequence::MoveToNextPage, 1, Qt::Key_PageDown, QApplicationPrivate::KB_All},
{QKeySequence::HelpContents, 0, Qt::Key_F1, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::HelpContents, 0, Qt::Key_F2, QApplicationPrivate::KB_S60},
{QKeySequence::FindNext, 0, Qt::Key_F3, QApplicationPrivate::KB_X11},
{QKeySequence::FindNext, 1, Qt::Key_F3, QApplicationPrivate::KB_Win},
{QKeySequence::Refresh, 0, Qt::Key_F5, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
@@ -523,13 +524,14 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::PreviousChild, 0, Qt::Key_Back, QApplicationPrivate::KB_All},
{QKeySequence::NextChild, 0, Qt::Key_Forward, QApplicationPrivate::KB_All},
{QKeySequence::Forward, 0, Qt::SHIFT | Qt::Key_Backspace, QApplicationPrivate::KB_Win},
+ {QKeySequence::Delete, 0, Qt::SHIFT | Qt::Key_Backspace, QApplicationPrivate::KB_S60},
{QKeySequence::InsertLineSeparator, 0, Qt::SHIFT | Qt::Key_Return, QApplicationPrivate::KB_All},
{QKeySequence::InsertLineSeparator, 0, Qt::SHIFT | Qt::Key_Enter, QApplicationPrivate::KB_All},
{QKeySequence::Paste, 0, Qt::SHIFT | Qt::Key_Insert, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
{QKeySequence::Cut, 0, Qt::SHIFT | Qt::Key_Delete, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, //## Check if this should work on mac
- {QKeySequence::SelectStartOfLine, 0, Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectStartOfLine, 0, Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::SelectStartOfDocument, 0, Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Mac},
- {QKeySequence::SelectEndOfLine, 0, Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectEndOfLine, 0, Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::SelectEndOfDocument, 0, Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Mac},
{QKeySequence::SelectPreviousChar, 0, Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_All},
{QKeySequence::SelectPreviousLine, 0, Qt::SHIFT | Qt::Key_Up, QApplicationPrivate::KB_All},
@@ -582,15 +584,15 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::DeleteStartOfWord, 0, Qt::CTRL | Qt::Key_Backspace, QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_Win},
{QKeySequence::Copy, 0, Qt::CTRL | Qt::Key_Insert, QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_Win},
{QKeySequence::DeleteEndOfWord, 0, Qt::CTRL | Qt::Key_Delete, QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_Win},
- {QKeySequence::MoveToStartOfDocument, 0, Qt::CTRL | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
- {QKeySequence::MoveToEndOfDocument, 0, Qt::CTRL | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToStartOfDocument, 0, Qt::CTRL | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
+ {QKeySequence::MoveToEndOfDocument, 0, Qt::CTRL | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::Back, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Mac},
- {QKeySequence::MoveToPreviousWord, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToPreviousWord, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::MoveToStartOfLine, 0, Qt::CTRL | Qt::Key_Left, QApplicationPrivate::KB_Mac },
{QKeySequence::MoveToStartOfDocument, 1, Qt::CTRL | Qt::Key_Up, QApplicationPrivate::KB_Mac},
{QKeySequence::Forward, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Mac},
{QKeySequence::MoveToEndOfLine, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Mac },
- {QKeySequence::MoveToNextWord, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::MoveToNextWord, 0, Qt::CTRL | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::MoveToEndOfDocument, 1, Qt::CTRL | Qt::Key_Down, QApplicationPrivate::KB_Mac},
{QKeySequence::Close, 1, Qt::CTRL | Qt::Key_F4, QApplicationPrivate::KB_Win},
{QKeySequence::Close, 0, Qt::CTRL | Qt::Key_F4, QApplicationPrivate::KB_Mac},
@@ -603,12 +605,12 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::Redo, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, //different priority from above
{QKeySequence::PreviousChild, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
{QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Mac },//different priority from above
- {QKeySequence::SelectStartOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
- {QKeySequence::SelectEndOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
- {QKeySequence::SelectPreviousWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectStartOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
+ {QKeySequence::SelectEndOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
+ {QKeySequence::SelectPreviousWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::SelectStartOfLine, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Mac },
{QKeySequence::SelectStartOfDocument, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Up, QApplicationPrivate::KB_Mac},
- {QKeySequence::SelectNextWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11},
+ {QKeySequence::SelectNextWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60},
{QKeySequence::SelectEndOfLine, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Right, QApplicationPrivate::KB_Mac },
{QKeySequence::SelectEndOfDocument, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Down, QApplicationPrivate::KB_Mac},
{QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_F6, QApplicationPrivate::KB_Win},
diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp
index e750088..921afce 100644
--- a/src/gui/kernel/qlayout.cpp
+++ b/src/gui/kernel/qlayout.cpp
@@ -148,7 +148,12 @@ QLayout::QLayout(QLayoutPrivate &dd, QLayout *lay, QWidget *w)
} else {
d->topLevel = true;
w->d_func()->layout = this;
- invalidate();
+ QT_TRY {
+ invalidate();
+ } QT_CATCH(...) {
+ w->d_func()->layout = 0;
+ QT_RETHROW;
+ }
}
}
}
@@ -233,7 +238,12 @@ QLayout::QLayout(QWidget *parent, int margin, int spacing, const char *name)
} else {
d->topLevel = true;
parent->d_func()->layout = this;
- invalidate();
+ QT_TRY {
+ invalidate();
+ } QT_CATCH(...) {
+ parent->d_func()->layout = 0;
+ QT_RETHROW;
+ }
}
}
}
diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp
index 5d56580..2b7c391 100644
--- a/src/gui/kernel/qshortcutmap.cpp
+++ b/src/gui/kernel/qshortcutmap.cpp
@@ -146,9 +146,8 @@ public:
QShortcutMap constructor.
*/
QShortcutMap::QShortcutMap()
+ : d_ptr(new QShortcutMapPrivate(this))
{
- d_ptr = new QShortcutMapPrivate(this);
- Q_ASSERT(d_ptr != 0);
resetState();
}
@@ -157,8 +156,6 @@ QShortcutMap::QShortcutMap()
*/
QShortcutMap::~QShortcutMap()
{
- delete d_ptr;
- d_ptr = 0;
}
/*! \internal
diff --git a/src/gui/kernel/qshortcutmap_p.h b/src/gui/kernel/qshortcutmap_p.h
index 9e7d92c..8962ac7 100644
--- a/src/gui/kernel/qshortcutmap_p.h
+++ b/src/gui/kernel/qshortcutmap_p.h
@@ -55,6 +55,7 @@
#include "QtGui/qkeysequence.h"
#include "QtCore/qvector.h"
+#include "QtCore/qscopedpointer.h"
QT_BEGIN_NAMESPACE
@@ -104,7 +105,7 @@ private:
#ifndef QT_NO_ACTION
bool correctContext(Qt::ShortcutContext context,QAction *a, QWidget *active_window) const;
#endif
- QShortcutMapPrivate *d_ptr;
+ QScopedPointer<QShortcutMapPrivate> d_ptr;
QKeySequence::SequenceMatch find(QKeyEvent *e);
QKeySequence::SequenceMatch matches(const QKeySequence &seq1, const QKeySequence &seq2) const;
diff --git a/src/gui/kernel/qsound.cpp b/src/gui/kernel/qsound.cpp
index 112a64e..73bad86 100644
--- a/src/gui/kernel/qsound.cpp
+++ b/src/gui/kernel/qsound.cpp
@@ -153,6 +153,9 @@ public:
\o Qt for Embedded Linux
\o A built-in mixing sound server is used, accessing \c /dev/dsp
directly. Only the WAVE format is supported.
+ \o Symbian
+ \o CMdaAudioPlayerUtility is used. All formats that Symbian OS or devices support
+ are supported also by Qt.
\endtable
Note that QSound does not support \l{resources.html}{resources}.
diff --git a/src/gui/kernel/qsound_s60.cpp b/src/gui/kernel/qsound_s60.cpp
new file mode 100644
index 0000000..c9eedf5
--- /dev/null
+++ b/src/gui/kernel/qsound_s60.cpp
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+
+#ifndef QT_NO_SOUND
+
+#include "qdir.h"
+#include "qapplication.h"
+#include "qsound.h"
+#include "qsound_p.h"
+#include "qfileinfo.h"
+#include <private/qcore_symbian_p.h>
+
+#include <e32std.h>
+#include <MdaAudioSamplePlayer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAuServerS60;
+
+class QAuBucketS60 : public QAuBucket, public MMdaAudioPlayerCallback
+{
+public:
+ QAuBucketS60( QAuServerS60 *server, QSound *sound);
+ ~QAuBucketS60();
+
+ void play();
+ void stop();
+
+ inline QSound* sound() const { return m_sound; }
+
+public: // from MMdaAudioPlayerCallback
+ void MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& aDuration);
+ void MapcPlayComplete(TInt aError);
+
+private:
+ QSound *m_sound;
+ QAuServerS60 *m_server;
+ bool m_prepared;
+ bool m_playCalled;
+ CMdaAudioPlayerUtility* m_playUtility;
+};
+
+
+class QAuServerS60 : public QAuServer
+{
+public:
+ QAuServerS60( QObject* parent );
+
+ void init( QSound* s )
+ {
+ QAuBucketS60 *bucket = new QAuBucketS60( this, s );
+ setBucket( s, bucket );
+ }
+
+ void play( QSound* s )
+ {
+ bucket( s )->play();
+ }
+
+ void stop( QSound* s )
+ {
+ bucket( s )->stop();
+ }
+
+ bool okay() { return true; }
+
+protected:
+ void playCompleted(QAuBucketS60* bucket, int error)
+ {
+ QSound *sound = bucket->sound();
+ if(!error) {
+ // We need to handle repeats by ourselves, since with Symbian API we don't
+ // know how many loops have been played when user asks it
+ if( decLoop( sound ) ) {
+ play( sound );
+ }
+ } else {
+ // We don't have a way to inform about errors -> just decrement loops
+ // in order that QSound::isFinished will return true;
+ while(decLoop(sound)) {}
+ }
+ }
+
+protected:
+ QAuBucketS60* bucket( QSound *s )
+ {
+ return (QAuBucketS60*)QAuServer::bucket( s );
+ }
+
+ friend class QAuBucketS60;
+
+};
+
+QAuServerS60::QAuServerS60(QObject* parent) :
+ QAuServer(parent)
+{
+ setObjectName(QLatin1String("QAuServerS60"));
+}
+
+
+QAuServer* qt_new_audio_server()
+{
+ return new QAuServerS60(qApp);
+}
+
+QAuBucketS60::QAuBucketS60( QAuServerS60 *server, QSound *sound )
+ : m_sound( sound ), m_server( server ), m_prepared(false), m_playCalled(false)
+{
+ QString filepath = QFileInfo( m_sound->fileName() ).absoluteFilePath();
+ filepath = QDir::toNativeSeparators(filepath);
+ TPtrC filepathPtr(qt_QString2TPtrC(filepath));
+ TRAPD(err, m_playUtility = CMdaAudioPlayerUtility::NewL(*this);
+ m_playUtility->OpenFileL(filepathPtr));
+ if(err){
+ m_server->playCompleted(this, err);
+ }
+}
+
+void QAuBucketS60::play()
+{
+ if(m_prepared) {
+ // OpenFileL call is completed we can start playing immediately
+ m_playUtility->Play();
+ } else {
+ m_playCalled = true;
+ }
+
+}
+
+void QAuBucketS60::stop()
+{
+ m_playCalled = false;
+ m_playUtility->Stop();
+}
+
+void QAuBucketS60::MapcPlayComplete(TInt aError)
+{
+ m_server->playCompleted(this, aError);
+}
+
+void QAuBucketS60::MapcInitComplete(TInt aError, const TTimeIntervalMicroSeconds& /*aDuration*/)
+{
+ if(aError) {
+ m_server->playCompleted(this, aError);
+ } else {
+ m_prepared = true;
+ if(m_playCalled){
+ play();
+ }
+ }
+}
+
+QAuBucketS60::~QAuBucketS60()
+{
+ if(m_playUtility){
+ m_playUtility->Stop();
+ m_playUtility->Close();
+ }
+
+ delete m_playUtility;
+}
+
+
+#endif // QT_NO_SOUND
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h
new file mode 100644
index 0000000..bcbe48f
--- /dev/null
+++ b/src/gui/kernel/qt_s60_p.h
@@ -0,0 +1,292 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_S60_P_H
+#define QT_S60_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtGui/qwindowdefs.h"
+#include "private/qcore_symbian_p.h"
+#include "qhash.h"
+#include "qpoint.h"
+#include "QtGui/qfont.h"
+#include "QtGui/qimage.h"
+#include "QtGui/qevent.h"
+#include "qpointer.h"
+#include <w32std.h>
+#include <coecntrl.h>
+#include <eikenv.h>
+#include <eikappui.h>
+
+#ifdef Q_WS_S60
+#include <aknutils.h> // AknLayoutUtils
+#include <avkon.hrh> // EEikStatusPaneUidTitle
+#include <akntitle.h> // CAknTitlePane
+#include <akncontext.h> // CAknContextPane
+#include <eikspane.h> // CEikStatusPane
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// Application internal HandleResourceChangeL events,
+// system evens seems to start with 0x10
+const TInt KInternalStatusPaneChange = 0x50000000;
+
+struct QS60Data;
+extern QS60Data *qt_s60Data;
+
+#define S60 qt_s60Data
+
+class QS60Data
+{
+public:
+ TUid uid;
+ int screenDepth;
+ QPoint lastCursorPos;
+ QPoint lastPointerEventPos;
+ QPointer<QWidget> lastPointerEventTarget;
+ QPointer<QWidget> mousePressTarget;
+ int screenWidthInPixels;
+ int screenHeightInPixels;
+ int screenWidthInTwips;
+ int screenHeightInTwips;
+ int defaultDpiX;
+ int defaultDpiY;
+ static inline void updateScreenSize();
+ static inline RWsSession& wsSession();
+ static inline RWindowGroup& windowGroup();
+ static inline CWsScreenDevice* screenDevice();
+ static inline CCoeAppUi* appUi();
+#ifdef Q_WS_S60
+ static inline CEikStatusPane* statusPane();
+ static inline CCoeControl* statusPaneSubPane(TInt aPaneId);
+ static inline CAknTitlePane* titlePane();
+ static inline CAknContextPane* contextPane();
+ static inline CEikButtonGroupContainer* buttonGroupContainer();
+#endif
+};
+
+class QAbstractLongTapObserver
+{
+public:
+ virtual void HandleLongTapEventL( const TPoint& aPenEventLocation,
+ const TPoint& aPenEventScreenLocation ) = 0;
+};
+class QLongTapTimer;
+
+class QSymbianControl : public CCoeControl, public QAbstractLongTapObserver
+{
+public:
+ DECLARE_TYPE_ID(0x51740000) // Fun fact: the two first values are "Qt" in ASCII.
+
+public:
+ QSymbianControl(QWidget *w);
+ void ConstructL(bool topLevel = false, bool desktop = false);
+ ~QSymbianControl();
+ void HandleResourceChange(int resourceType);
+ void HandlePointerEventL(const TPointerEvent& aPointerEvent);
+ TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
+#if !defined(QT_NO_IM) && defined(Q_WS_S60)
+ TCoeInputCapabilities InputCapabilities() const;
+#endif
+ TTypeUid::Ptr MopSupplyObject(TTypeUid id);
+
+ inline QWidget* widget() const { return qwidget; };
+ void setWidget(QWidget *w);
+ void sendInputEvent(QWidget *widget, QInputEvent *inputEvent);
+ void setIgnoreFocusChanged(bool enabled) { m_ignoreFocusChanged = enabled; }
+ void CancelLongTapTimer();
+
+protected:
+ void Draw(const TRect& aRect) const;
+ void SizeChanged();
+ void PositionChanged();
+ void FocusChanged(TDrawNow aDrawNow);
+
+private:
+ TKeyResponse OfferKeyEvent(const TKeyEvent& aKeyEvent,TEventCode aType);
+ TKeyResponse sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent);
+ void sendMouseEvent(QWidget *widget, QMouseEvent *mEvent);
+ void HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation );
+
+private:
+ QWidget *qwidget;
+ bool m_ignoreFocusChanged;
+ QLongTapTimer* m_longTapDetector;
+ bool m_previousEventLongTap;
+};
+
+inline void QS60Data::updateScreenSize()
+{
+ TPixelsTwipsAndRotation params;
+ int mode = S60->screenDevice()->CurrentScreenMode();
+ S60->screenDevice()->GetScreenModeSizeAndRotation(mode, params);
+ S60->screenWidthInPixels = params.iPixelSize.iWidth;
+ S60->screenHeightInPixels = params.iPixelSize.iHeight;
+ S60->screenWidthInTwips = params.iTwipsSize.iWidth;
+ S60->screenHeightInTwips = params.iTwipsSize.iHeight;
+
+ TReal inches = S60->screenHeightInTwips / (TReal)KTwipsPerInch;
+ S60->defaultDpiY = S60->screenHeightInPixels / inches;
+ inches = S60->screenWidthInTwips / (TReal)KTwipsPerInch;
+ S60->defaultDpiX = S60->screenWidthInPixels / inches;
+}
+
+inline RWsSession& QS60Data::wsSession()
+{
+ return CCoeEnv::Static()->WsSession();
+}
+
+inline RWindowGroup& QS60Data::windowGroup()
+{
+ return CCoeEnv::Static()->RootWin();
+}
+
+inline CWsScreenDevice* QS60Data::screenDevice()
+{
+ return CCoeEnv::Static()->ScreenDevice();
+}
+
+inline CCoeAppUi* QS60Data::appUi()
+{
+ return CCoeEnv::Static()-> AppUi();
+}
+
+#ifdef Q_WS_S60
+inline CEikStatusPane* QS60Data::statusPane()
+{
+ return CEikonEnv::Static()->AppUiFactory()->StatusPane();
+}
+
+// Returns the application's status pane control, if not present returns NULL.
+inline CCoeControl* QS60Data::statusPaneSubPane( TInt aPaneId )
+{
+ const TUid paneUid = { aPaneId };
+ CEikStatusPane* statusPane = S60->statusPane();
+ if (statusPane && statusPane->PaneCapabilities(paneUid).IsPresent()) {
+ CCoeControl* control = NULL;
+ // ControlL shouldn't leave because the pane is present
+ TRAPD(err, control = statusPane->ControlL(paneUid));
+ return err != KErrNone ? NULL : control;
+ }
+ return NULL;
+}
+
+// Returns the application's title pane, if not present returns NULL.
+inline CAknTitlePane* QS60Data::titlePane()
+{
+ return static_cast<CAknTitlePane*>(S60->statusPaneSubPane(EEikStatusPaneUidTitle));
+}
+
+// Returns the application's title pane, if not present returns NULL.
+inline CAknContextPane* QS60Data::contextPane()
+{
+ return static_cast<CAknContextPane*>(S60->statusPaneSubPane(EEikStatusPaneUidContext));
+}
+
+inline CEikButtonGroupContainer* QS60Data::buttonGroupContainer()
+{
+ return CEikonEnv::Static()->AppUiFactory()->Cba();
+}
+#endif // Q_WS_S60
+
+static inline QFont qt_TFontSpec2QFontL(const TFontSpec &fontSpec)
+{
+ return QFont(
+ qt_TDesC2QStringL(fontSpec.iTypeface.iName),
+ fontSpec.iHeight / KTwipsPerPoint,
+ fontSpec.iFontStyle.StrokeWeight() == EStrokeWeightNormal ? QFont::Normal : QFont::Bold,
+ fontSpec.iFontStyle.Posture() == EPostureItalic
+ );
+}
+
+static inline QImage::Format qt_TDisplayMode2Format(TDisplayMode mode)
+{
+ QImage::Format format;
+ switch(mode) {
+ case EGray2:
+ format = QImage::Format_MonoLSB;
+ break;
+ case EColor256:
+ case EGray256:
+ format = QImage::Format_Indexed8;
+ break;
+ case EColor4K:
+ format = QImage::Format_RGB444;
+ break;
+ case EColor64K:
+ format = QImage::Format_RGB16;
+ break;
+ case EColor16M:
+ format = QImage::Format_RGB666;
+ break;
+ case EColor16MU:
+ format = QImage::Format_RGB32;
+ break;
+ case EColor16MA:
+ format = QImage::Format_ARGB32;
+ break;
+#if !defined(__SERIES60_31__) && !defined(__S60_32__)
+ case EColor16MAP:
+ format = QImage::Format_ARGB32_Premultiplied;
+ break;
+#endif
+ default:
+ format = QImage::Format_Invalid;
+ break;
+ }
+ return format;
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_S60_P_H
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 7026525..334706d 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -101,6 +101,10 @@
#endif
#include <private/qpaintengine_raster_p.h>
+#if defined(Q_OS_SYMBIAN)
+#include "private/qt_s60_p.h"
+#endif
+
#include "qwidget_p.h"
#include "qaction_p.h"
#include "qlayout_p.h"
@@ -212,6 +216,7 @@ QWidgetPrivate::QWidgetPrivate(int version)
, window_event(0)
, qd_hd(0)
#endif
+ ,imHints(Qt::ImhNone)
{
if (!qApp) {
qFatal("QWidget: Must construct a QApplication before a QPaintDevice");
@@ -402,6 +407,7 @@ void QWidget::setEditFocus(bool on)
QApplication::sendEvent(f, &event);
QApplication::sendEvent(f->style(), &event);
}
+ f->repaint(); // Widget might want to repaint a focus indicator
}
#endif
@@ -890,6 +896,30 @@ void QWidget::setAutoFillBackground(bool enabled)
\endlist
\sa QEvent, QPainter, QGridLayout, QBoxLayout
+
+ \section1 SoftKeys
+ \since 4.6
+ \preliminary
+
+ Softkeys API is a platform independent way of mapping actions to (hardware)keys
+ and toolbars provided by the underlying platform.
+
+ There are three major use cases supported. First one is a mobile device
+ with keypad navigation and no touch ui. Second use case is a mobile
+ device with touch ui. Third use case is desktop. For now the softkey API is
+ only implemented for Series60.
+
+ QActions are set to widget(s) via softkey API. Actions in focused widget are
+ mapped to native toolbar or hardware keys. Even though the API allows to set
+ any amount of widgets there might be physical restrictions to amount of
+ softkeys that can be used by the device.
+
+ \o Series60: For series60 menu button is automatically mapped to left
+ soft key if there is QMainWindow with QMenuBar in widgets parent hierarchy.
+
+ \sa softKeys()
+ \sa setSoftKey()
+
*/
QWidgetMapper *QWidgetPrivate::mapper = 0; // widget with wid
@@ -933,6 +963,23 @@ QRegion qt_dirtyRegion(QWidget *widget)
\endlist
*/
+struct QWidgetExceptionCleaner
+{
+ /* this cleans up when the constructor throws an exception */
+ static inline void cleanup(QWidget *that, QWidgetPrivate *d)
+ {
+#ifndef QT_NO_EXCEPTIONS
+ QWidgetPrivate::uncreatedWidgets->remove(that);
+ if (d->focus_next != that) {
+ if (d->focus_next)
+ d->focus_next->d_func()->focus_prev = d->focus_prev;
+ if (d->focus_prev)
+ d->focus_prev->d_func()->focus_next = d->focus_next;
+ }
+#endif
+ }
+};
+
/*!
Constructs a widget which is a child of \a parent, with widget
flags set to \a f.
@@ -962,7 +1009,12 @@ QRegion qt_dirtyRegion(QWidget *widget)
QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
: QObject(*new QWidgetPrivate, 0), QPaintDevice()
{
- d_func()->init(parent, f);
+ QT_TRY {
+ d_func()->init(parent, f);
+ } QT_CATCH(...) {
+ QWidgetExceptionCleaner::cleanup(this, d_func());
+ QT_RETHROW;
+ }
}
#ifdef QT3_SUPPORT
@@ -973,8 +1025,13 @@ QWidget::QWidget(QWidget *parent, Qt::WindowFlags f)
QWidget::QWidget(QWidget *parent, const char *name, Qt::WindowFlags f)
: QObject(*new QWidgetPrivate, 0), QPaintDevice()
{
- d_func()->init(parent , f);
- setObjectName(QString::fromAscii(name));
+ QT_TRY {
+ d_func()->init(parent , f);
+ setObjectName(QString::fromAscii(name));
+ } QT_CATCH(...) {
+ QWidgetExceptionCleaner::cleanup(this, d_func());
+ QT_RETHROW;
+ }
}
#endif
@@ -983,7 +1040,13 @@ QWidget::QWidget(QWidget *parent, const char *name, Qt::WindowFlags f)
QWidget::QWidget(QWidgetPrivate &dd, QWidget* parent, Qt::WindowFlags f)
: QObject(dd, 0), QPaintDevice()
{
- d_func()->init(parent, f);
+ Q_D(QWidget);
+ QT_TRY {
+ d->init(parent, f);
+ } QT_CATCH(...) {
+ QWidgetExceptionCleaner::cleanup(this, d_func());
+ QT_RETHROW;
+ }
}
/*!
@@ -1265,7 +1328,7 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow)
d->create_sys(window, initializeWindow, destroyOldWindow);
// a real toplevel window needs a backing store
- if (isWindow()) {
+ if (isWindow() && windowType() != Qt::Desktop) {
delete d->topData()->backingStore;
// QWidgetBackingStore will check this variable, hence it must be 0
d->topData()->backingStore = 0;
@@ -1933,6 +1996,9 @@ void QWidgetPrivate::setOpaque(bool opaque)
#ifdef Q_WS_WIN
winUpdateIsOpaque();
#endif
+#ifdef Q_OS_SYMBIAN
+ s60UpdateIsOpaque();
+#endif
}
void QWidgetPrivate::updateIsTranslucent()
@@ -1946,6 +2012,9 @@ void QWidgetPrivate::updateIsTranslucent()
#ifdef Q_WS_WIN
winUpdateIsOpaque();
#endif
+#ifdef Q_OS_SYMBIAN
+ s60UpdateIsOpaque();
+#endif
}
/*!
@@ -1980,10 +2049,18 @@ static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrus
extern void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush);
qt_mac_fill_background(painter, rgn, brush);
#else
- const QRect rect(rgn.boundingRect());
- painter->setClipRegion(rgn);
- painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
-#endif
+#if !defined(QT_NO_STYLE_S60)
+ // Defined in qs60style.cpp
+ extern bool qt_s60_fill_background(QPainter *painter, const QRegion &rgn,
+ const QPoint &offset, const QBrush &brush);
+ if (!qt_s60_fill_background(painter, rgn, offset, brush))
+#endif // !defined(QT_NO_STYLE_S60)
+ {
+ const QRect rect(rgn.boundingRect());
+ painter->setClipRegion(rgn);
+ painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft());
+ }
+#endif // Q_WS_MAC
} else {
const QVector<QRect> &rects = rgn.rects();
for (int i = 0; i < rects.size(); ++i)
@@ -2576,7 +2653,7 @@ bool QWidget::isMaximized() const
*/
Qt::WindowStates QWidget::windowState() const
{
- return (Qt::WindowStates)data->window_state;
+ return Qt::WindowStates(data->window_state);
}
/*!\internal
@@ -2588,7 +2665,7 @@ Qt::WindowStates QWidget::windowState() const
*/
void QWidget::overrideWindowState(Qt::WindowStates newstate)
{
- QWindowStateChangeEvent e((Qt::WindowStates)data->window_state, true);
+ QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true);
data->window_state = newstate;
QApplication::sendEvent(this, &e);
}
@@ -4833,6 +4910,13 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
d->extra->inRenderWithPainter = false;
}
+#if !defined(Q_OS_SYMBIAN)
+void QWidgetPrivate::setSoftKeys_sys(const QList<QAction*> &softkeys)
+{
+ Q_UNUSED(softkeys)
+}
+#endif // !defined(Q_OS_SYMBIAN)
+
bool QWidgetPrivate::isAboutToShow() const
{
if (data.in_show)
@@ -5654,9 +5738,11 @@ bool QWidget::hasFocus() const
void QWidget::setFocus(Qt::FocusReason reason)
{
+ Q_D(QWidget);
+
if (!isEnabled())
return;
-
+
QWidget *f = this;
while (f->d_func()->extra && f->d_func()->extra->focus_proxy)
f = f->d_func()->extra->focus_proxy;
@@ -6712,7 +6798,7 @@ void QWidgetPrivate::show_helper()
// On Windows, show the popup now so that our own focus handling
// stores the correct old focus widget even if it's stolen in the
// showevent
-#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_OS_SYMBIAN)
if (!isEmbedded && q->windowType() == Qt::Popup)
qApp->d_func()->openPopup(q);
#endif
@@ -6729,7 +6815,7 @@ void QWidgetPrivate::show_helper()
show_sys();
-#if !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
+#if !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN)
if (!isEmbedded && q->windowType() == Qt::Popup)
qApp->d_func()->openPopup(q);
#endif
@@ -7299,7 +7385,7 @@ QSize QWidgetPrivate::adjustedSize() const
#else // all others
QRect screen = QApplication::desktop()->screenGeometry(q->pos());
#endif
-#if defined (Q_WS_WINCE)
+#if defined (Q_WS_WINCE) || defined (Q_OS_SYMBIAN)
s.setWidth(qMin(s.width(), screen.width()));
s.setHeight(qMin(s.height(), screen.height()));
#else
@@ -7610,6 +7696,7 @@ bool QWidget::event(QEvent *event)
}
break;
case QEvent::FocusIn:
+ d->setSoftKeys_sys(softKeys());
focusInEvent((QFocusEvent*)event);
break;
@@ -7759,6 +7846,10 @@ bool QWidget::event(QEvent *event)
if (w && w->isVisible() && !w->isWindow())
QApplication::sendEvent(w, event);
}
+
+ if (isWindow() && isActiveWindow())
+ d->setSoftKeys_sys(softKeys());
+
break; }
case QEvent::LanguageChange:
@@ -7925,6 +8016,12 @@ bool QWidget::event(QEvent *event)
(void) QApplication::sendEvent(this, &mouseEvent);
break;
}
+ case QEvent::SymbianDeferredFocusChanged: {
+#ifdef Q_OS_SYMBIAN
+ d->handleSymbianDeferredFocusChanged();
+#endif
+ break;
+ }
#ifdef Q_WS_WIN
case QEvent::WinGesture: {
QWinGestureEvent *ev = static_cast<QWinGestureEvent*>(event);
@@ -8524,7 +8621,7 @@ void QWidget::inputMethodEvent(QInputMethodEvent *event)
\a query specifies which property is queried.
- \sa inputMethodEvent(), QInputMethodEvent, QInputContext
+ \sa inputMethodEvent(), QInputMethodEvent, QInputContext, inputMethodHints
*/
QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
{
@@ -8533,11 +8630,54 @@ QVariant QWidget::inputMethodQuery(Qt::InputMethodQuery query) const
return QRect(width()/2, 0, 1, height());
case Qt::ImFont:
return font();
+ case Qt::ImAnchorPosition:
+ // Fallback.
+ return inputMethodQuery(Qt::ImCursorPosition);
default:
return QVariant();
}
}
+/*!
+ \property QWidget::inputMethodHints
+ \brief What input method specific hints the widget has.
+
+ This is only relevant for input widgets. It is used by
+ the input method to retrieve hints as to how the input method
+ should operate. For example, if the Qt::ImhFormattedNumbersOnly flag
+ is set, the input method may change its visual components to reflect
+ that only numbers can be entered.
+
+ \note The flags are only hints, so the particular input method
+ implementation is free to ignore them. If you want to be
+ sure that a certain type of characters are entered,
+ you should also set a QValidator on the widget.
+
+ The default value is Qt::ImhNone.
+
+ \since 4.6
+
+ \sa inputMethodQuery(), QInputContext
+*/
+Qt::InputMethodHints QWidget::inputMethodHints() const
+{
+ Q_D(const QWidget);
+ return d->imHints;
+}
+
+void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
+{
+ Q_D(QWidget);
+ d->imHints = hints;
+ // Optimisation to update input context only it has already been created.
+ if (d->ic || qApp->d_func()->inputContext) {
+ QInputContext *ic = inputContext();
+ if (ic)
+ ic->update();
+ }
+}
+
+
#ifndef QT_NO_DRAGANDDROP
/*!
@@ -10344,7 +10484,7 @@ void QWidget::setShortcutAutoRepeat(int id, bool enable)
*/
void QWidget::updateMicroFocus()
{
-#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS))
+#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN))
Q_D(QWidget);
// and optimisation to update input context only it has already been created.
if (d->ic || qApp->d_func()->inputContext) {
@@ -11478,6 +11618,68 @@ void QWidget::clearMask()
setMask(QRegion());
}
+/*!
+ \preliminary
+ \since 4.6
+
+ Returns the (possibly empty) list of this widget's softkeys.
+ Returned list cannot be changed. Softkeys should be added
+ and removed via method called setSoftKeys
+
+ \sa setSoftKey(), setSoftKeys()
+*/
+const QList<QAction*>& QWidget::softKeys() const
+{
+ Q_D(const QWidget);
+ if( d->softKeys.count() > 0)
+ return d->softKeys;
+ if (isWindow() || !parentWidget())
+ return d->softKeys;
+
+ return parentWidget()->softKeys();
+}
+
+/*!
+ \preliminary
+ \since 4.6
+
+ Sets the softkey \a softkey to this widget's list of softkeys,
+ Setting 0 as softkey will clear all the existing softkeys set
+ to the widget
+ A QWidget can have 0 or more softkeys
+
+ \sa softKeys(), setSoftKeys()
+*/
+void QWidget::setSoftKey(QAction *softKey)
+{
+ Q_D(QWidget);
+ qDeleteAll(d->softKeys);
+ d->softKeys.clear();
+ if (softKey)
+ d->softKeys.append(softKey);
+ if ((!QApplication::focusWidget() && this == QApplication::activeWindow())
+ || QApplication::focusWidget() == this)
+ d->setSoftKeys_sys(this->softKeys());
+}
+
+/*!
+ Sets the list of softkeys \a softkeys to this widget's list of softkeys,
+ A QWidget can have 0 or more softkeys
+
+ \sa softKeys(), setSoftKey()
+*/
+void QWidget::setSoftKeys(const QList<QAction*> &softKeys)
+{
+ Q_D(QWidget);
+ qDeleteAll(d->softKeys);
+ d->softKeys.clear();
+ d->softKeys = softKeys;
+
+ if ((!QApplication::focusWidget() && this == QApplication::activeWindow())
+ || QApplication::focusWidget() == this)
+ d->setSoftKeys_sys(this->softKeys());
+}
+
/*! \fn const QX11Info &QWidget::x11Info() const
Returns information about the configuration of the X display used to display
the widget.
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
index bc9952c..c73f633 100644
--- a/src/gui/kernel/qwidget.h
+++ b/src/gui/kernel/qwidget.h
@@ -213,6 +213,7 @@ class Q_GUI_EXPORT QWidget : public QObject, public QPaintDevice
#endif
Q_PROPERTY(QLocale locale READ locale WRITE setLocale RESET unsetLocale)
Q_PROPERTY(QString windowFilePath READ windowFilePath WRITE setWindowFilePath DESIGNABLE isWindow)
+ Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints)
public:
enum RenderFlag {
@@ -555,6 +556,9 @@ public:
void removeAction(QAction *action);
QList<QAction*> actions() const;
#endif
+ const QList<QAction*>& softKeys() const;
+ void setSoftKey(QAction *softKey);
+ void setSoftKeys(const QList<QAction*> &softKeys);
QWidget *parentWidget() const;
@@ -675,6 +679,10 @@ protected:
virtual void inputMethodEvent(QInputMethodEvent *);
public:
virtual QVariant inputMethodQuery(Qt::InputMethodQuery) const;
+
+ Qt::InputMethodHints inputMethodHints() const;
+ void setInputMethodHints(Qt::InputMethodHints hints);
+
protected:
void resetInputContext();
protected Q_SLOTS:
@@ -725,6 +733,7 @@ private:
friend class QGraphicsProxyWidget;
friend class QGraphicsProxyWidgetPrivate;
friend class QStyleSheetStyle;
+ friend struct QWidgetExceptionCleaner;
#ifdef Q_WS_MAC
friend class QCoreGraphicsPaintEnginePrivate;
@@ -746,6 +755,10 @@ private:
friend bool isWidgetOpaque(const QWidget *);
friend class QGLWidgetPrivate;
#endif
+#ifdef Q_OS_SYMBIAN
+ friend class QSymbianControl;
+ friend class QS60WindowSurface;
+#endif
#ifdef Q_WS_X11
friend void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
friend void qt_net_remove_user_time(QWidget *tlw);
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index 998181e..1d9689e 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -80,6 +80,14 @@
#include "QtGui/qscreen_qws.h"
#endif
+#if defined(Q_OS_SYMBIAN)
+class RDrawableWindow;
+class CCoeControl;
+// The following 2 defines may only be needed for s60. To be seen.
+const int SOFTKEYSTART=5000;
+const int SOFTKEYEND=5004;
+#endif
+
QT_BEGIN_NAMESPACE
// Extra QWidget data
@@ -162,6 +170,9 @@ struct QTLWExtra {
#ifndef QT_NO_QWS_MANAGER
QWSManager *qwsManager;
#endif
+#elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN
+ uint activated : 1; // RWindowBase::Activated has been called
+ RDrawableWindow *rwindow;
#endif
};
@@ -243,6 +254,7 @@ public:
explicit QWidgetPrivate(int version = QObjectPrivateVersion);
~QWidgetPrivate();
+ void setSoftKeys_sys(const QList<QAction*> &softkeys);
QWExtra *extraData() const;
QTLWExtra *topData() const;
QTLWExtra *maybeTopData() const;
@@ -269,6 +281,10 @@ public:
QPalette naturalWidgetPalette(uint inheritedMask) const;
void setMask_sys(const QRegion &);
+#ifdef Q_OS_SYMBIAN
+ void handleSymbianDeferredFocusChanged();
+#endif
+
void raise_sys();
void lower_sys();
void stackUnder_sys(QWidget *);
@@ -467,6 +483,7 @@ public:
QWidget *focus_next;
QWidget *focus_prev;
QWidget *focus_child;
+ QList<QAction*> softKeys;
QLayout *layout;
QRegion *needsFlush;
QPaintDevice *redirectDev;
@@ -479,6 +496,7 @@ public:
static QWidgetSet *uncreatedWidgets;
#if !defined(QT_NO_IM)
QPointer<QInputContext> ic;
+ Qt::InputMethodHints imHints;
#endif
#ifdef QT_KEYPAD_NAVIGATION
static QPointer<QWidget> editingWidget;
@@ -638,7 +656,13 @@ public:
void updateCursor() const;
#endif
QScreen* getScreen() const;
+#elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN
+ static QWidget *mouseGrabber;
+ static QWidget *keyboardGrabber;
+ void s60UpdateIsOpaque();
+ void reparentChildren();
#endif
+
};
inline QWExtra *QWidgetPrivate::extraData() const
diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp
index 299ed73..4ded5cf 100644
--- a/src/gui/kernel/qwidget_qws.cpp
+++ b/src/gui/kernel/qwidget_qws.cpp
@@ -638,7 +638,8 @@ void QWidgetPrivate::hide_sys()
q->releaseMouse();
// requestWindowRegion(QRegion());
- extra->topextra->backingStore->releaseBuffer();
+ if (extra->topextra->backingStore)
+ extra->topextra->backingStore->releaseBuffer();
QWidget::qwsDisplay()->requestFocus(data.winid,false);
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
new file mode 100644
index 0000000..5b05e55
--- /dev/null
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -0,0 +1,1174 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwidget_p.h"
+#include "qdesktopwidget.h"
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "private/qbackingstore_p.h"
+#include "qevent.h"
+#include "qt_s60_p.h"
+
+#include "qbitmap.h"
+#include "private/qwindowsurface_s60_p.h"
+
+#include <qinputcontext.h>
+
+#ifdef Q_WS_S60
+#include <aknappui.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+extern bool qt_nograb();
+
+QWidget *QWidgetPrivate::mouseGrabber = 0;
+QWidget *QWidgetPrivate::keyboardGrabber = 0;
+
+static bool isEqual(const QList<QAction*>& a, const QList<QAction*>& b)
+{
+ if ( a.count() != b.count())
+ return false;
+ int index=0;
+ while (index<a.count()) {
+ if (a.at(index)->softKeyRole() != b.at(index)->softKeyRole())
+ return false;
+ if (a.at(index)->text().compare(b.at(index)->text())!=0)
+ return false;
+ index++;
+ }
+ return true;
+}
+
+
+void QWidgetPrivate::setSoftKeys_sys(const QList<QAction*> &softkeys)
+{
+#ifdef Q_WS_S60
+ Q_Q(QWidget);
+ if (QApplication::focusWidget() && q!=QApplication::focusWidget()) {
+ QList<QAction *> old = QApplication::focusWidget()->softKeys();
+ if (isEqual(old, softkeys ))
+ return;
+ }
+ CEikButtonGroupContainer* nativeContainer = S60->buttonGroupContainer();
+ nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS);
+
+ int position = -1;
+ int command;
+ bool needsExitButton = true;
+
+ for (int index = 0; index < softkeys.count(); index++) {
+ const QAction* softKeyAction = softkeys.at(index);
+ switch (softKeyAction->softKeyRole()) {
+ // Positive Actions go on LSK
+ case QAction::OptionsSoftKey:
+ case QAction::MenuSoftKey:
+ case QAction::ContextMenuSoftKey:
+ command = EAknSoftkeyOptions; //Calls DynInitMenuPane in AppUI
+ position = 0;
+ break;
+ case QAction::SelectSoftKey:
+ case QAction::PreviousSoftKey:
+ case QAction::OkSoftKey:
+ case QAction::EditSoftKey:
+ case QAction::ViewSoftKey:
+ case QAction::EndEditSoftKey:
+ case QAction::FinishSoftKey:
+ command = SOFTKEYSTART + index;
+ position = 0;
+ break;
+ // Negative Actions on the RSK
+ case QAction::BackSoftKey:
+ case QAction::NextSoftKey:
+ case QAction::CancelSoftKey:
+ case QAction::BackSpaceSoftKey:
+ case QAction::RevertEditSoftKey:
+ case QAction::DeselectSoftKey:
+ needsExitButton = false;
+ command = SOFTKEYSTART + index;
+ position = 2;
+ break;
+ case QAction::ExitSoftKey:
+ needsExitButton = false;
+ command = EAknSoftkeyExit; //Calls HandleCommand in AppUI
+ position = 2;
+ break;
+ default:
+ break;
+ }
+
+ if (position != -1) {
+ TPtrC text = qt_QString2TPtrC(softKeyAction->text());
+ nativeContainer->SetCommandL(position, command, text);
+ }
+ }
+
+ if (needsExitButton)
+ nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QObject::tr("Exit")));
+
+ nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation
+#else
+ Q_UNUSED(softkeys)
+#endif
+}
+
+void QWidgetPrivate::setWSGeometry(bool /* dontShow */, const QRect & /* rect */)
+{
+
+}
+
+void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+
+ if ((q->windowType() == Qt::Desktop))
+ return;
+ if (extra) { // any size restrictions?
+ w = qMin(w,extra->maxw);
+ h = qMin(h,extra->maxh);
+ w = qMax(w,extra->minw);
+ h = qMax(h,extra->minh);
+ }
+
+ if (q->isWindow())
+ topData()->normalGeometry = QRect(0, 0, -1, -1);
+ else {
+ uint s = data.window_state;
+ s &= ~(Qt::WindowMaximized | Qt::WindowFullScreen);
+ data.window_state = s;
+ }
+
+ QPoint oldPos(q->pos());
+ QSize oldSize(q->size());
+ QRect oldGeom(data.crect);
+
+ bool isResize = w != oldSize.width() || h != oldSize.height();
+ if (!isMove && !isResize)
+ return;
+
+ if (isResize)
+ data.window_state &= ~Qt::WindowMaximized;
+
+ if(q->isWindow()) {
+ if (w == 0 || h == 0) {
+ q->setAttribute(Qt::WA_OutsideWSRange, true);
+ if (q->isVisible() && q->testAttribute(Qt::WA_Mapped))
+ hide_sys();
+ data.crect = QRect(x, y, w, h);
+ data.window_state &= ~Qt::WindowFullScreen;
+ } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) {
+ q->setAttribute(Qt::WA_OutsideWSRange, false);
+
+ // put the window in its place and show it
+ q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h)));
+ data.crect.setRect(x, y, w, h);
+
+ show_sys();
+ } else {
+ QRect r = QRect(x, y, w, h);
+ data.crect = r;
+ q->internalWinId()->SetRect(TRect(TPoint(x, y), TSize(w, h)));
+ topData()->normalGeometry = data.crect;
+ }
+ } else {
+ data.crect.setRect(x, y, w, h);
+
+ QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
+ const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false;
+
+ if (q->isVisible() && (!inTopLevelResize || q->internalWinId())) {
+ // Top-level resize optimization does not work for native child widgets;
+ // disable it for this particular widget.
+ if (inTopLevelResize)
+ tlwExtra->inTopLevelResize = false;
+ if (!isResize && maybeBackingStore())
+ moveRect(QRect(oldPos, oldSize), x - oldPos.x(), y - oldPos.y());
+ else
+ invalidateBuffer_resizeHelper(oldPos, oldSize);
+
+ if (inTopLevelResize)
+ tlwExtra->inTopLevelResize = true;
+ }
+ if (q->testAttribute(Qt::WA_WState_Created))
+ setWSGeometry();
+ }
+
+ if (q->isVisible()) {
+ if (isMove && q->pos() != oldPos) {
+ QMoveEvent e(q->pos(), oldPos);
+ QApplication::sendEvent(q, &e);
+ }
+ if (isResize) {
+ bool slowResize = qgetenv("QT_SLOW_TOPLEVEL_RESIZE").toInt();
+ const bool setTopLevelResize = !slowResize && q->isWindow() && extra && extra->topextra
+ && !extra->topextra->inTopLevelResize;
+ if (setTopLevelResize)
+ extra->topextra->inTopLevelResize = true;
+ QResizeEvent e(q->size(), oldSize);
+ QApplication::sendEvent(q, &e);
+ if (!q->testAttribute(Qt::WA_StaticContents) && q->internalWinId())
+ q->internalWinId()->DrawDeferred();
+ if (setTopLevelResize)
+ extra->topextra->inTopLevelResize = false;
+ }
+ } else {
+ if (isMove && q->pos() != oldPos)
+ q->setAttribute(Qt::WA_PendingMoveEvent, true);
+ if (isResize)
+ q->setAttribute(Qt::WA_PendingResizeEvent, true);
+ }
+}
+
+void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool destroyOldWindow)
+{
+ Q_Q(QWidget);
+
+ Qt::WindowType type = q->windowType();
+ Qt::WindowFlags &flags = data.window_flags;
+ QWidget *parentWidget = q->parentWidget();
+
+ bool topLevel = (flags & Qt::Window);
+ bool popup = (type == Qt::Popup);
+ bool dialog = (type == Qt::Dialog
+ || type == Qt::Sheet
+ || (flags & Qt::MSWindowsFixedSizeDialogHint));
+ bool desktop = (type == Qt::Desktop);
+ //bool tool = (type == Qt::Tool || type == Qt::Drawer);
+
+ WId id = 0;
+
+ if (popup)
+ flags |= Qt::WindowStaysOnTopHint; // a popup stays on top
+
+ TRect clientRect = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+ int sw = clientRect.Width();
+ int sh = clientRect.Height();
+
+ if (desktop) {
+ TSize screenSize = S60->screenDevice()->SizeInPixels();
+ data.crect.setRect(0, 0, screenSize.iWidth, screenSize.iHeight);
+ q->setAttribute(Qt::WA_DontShowOnScreen);
+ } else if(topLevel && !q->testAttribute(Qt::WA_Resized)){
+ int width = sw;
+ int height = sh;
+ if (extra) {
+ width = qMax(qMin(width, extra->maxw), extra->minw);
+ height = qMax(qMin(height, extra->maxh), extra->minh);
+ }
+ data.crect.setSize(QSize(width, height));
+ }
+
+ CCoeControl *destroyw = 0;
+
+ if(window) {
+ if (destroyOldWindow)
+ destroyw = data.winid;
+ id = window;
+ setWinId(window);
+ TRect tr = window->Rect();
+ data.crect.setRect(tr.iTl.iX, tr.iTl.iY, tr.Width(), tr.Height());
+
+ } else if (topLevel) {
+ if (!q->testAttribute(Qt::WA_Moved) && !q->testAttribute(Qt::WA_DontShowOnScreen))
+ data.crect.moveTopLeft(QPoint(clientRect.iTl.iX, clientRect.iTl.iY));
+ QSymbianControl *control= new QSymbianControl(q);
+ control->ConstructL(true,desktop);
+ if (!desktop) {
+ QTLWExtra *topExtra = topData();
+ topExtra->rwindow = control->DrawableWindow();
+ // Request mouse move events.
+ topExtra->rwindow->PointerFilter(EPointerFilterEnterExit
+ | EPointerFilterMove | EPointerFilterDrag, 0);
+ topExtra->rwindow->EnableVisibilityChangeEvents();
+
+ if (!isOpaque) {
+ RWindow *rwindow = static_cast<RWindow*>(topExtra->rwindow);
+ TDisplayMode gotDM = (TDisplayMode)rwindow->SetRequiredDisplayMode(EColor16MA);
+ if (rwindow->SetTransparencyAlphaChannel() == KErrNone)
+ rwindow->SetBackgroundColor(TRgb(255, 255, 255, 0));
+ }
+ }
+
+
+ id = (WId)control;
+
+ setWinId(id);
+
+ q->setAttribute(Qt::WA_WState_Created);
+
+ int x, y, w, h;
+ data.crect.getRect(&x, &y, &w, &h);
+ control->SetRect(TRect(TPoint(x, y), TSize(w, h)));
+ } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create native child widget
+ QSymbianControl *control = new QSymbianControl(q);
+ control->ConstructL(!parentWidget);
+ setWinId(control);
+ WId parentw = parentWidget->effectiveWinId();
+ control->SetContainerWindowL(*parentw);
+
+ q->setAttribute(Qt::WA_WState_Created);
+ int x, y, w, h;
+ data.crect.getRect(&x, &y, &w, &h);
+ control->SetRect(TRect(TPoint(x, y), TSize(w, h)));
+ }
+
+ if (destroyw) {
+ destroyw->ControlEnv()->AppUi()->RemoveFromStack(destroyw);
+ CBase::Delete(destroyw);
+ }
+}
+
+
+void QWidgetPrivate::show_sys()
+{
+ Q_Q(QWidget);
+
+ if (q->testAttribute(Qt::WA_OutsideWSRange))
+ return;
+
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+
+ q->setAttribute(Qt::WA_Mapped);
+
+ if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
+ invalidateBuffer(q->rect());
+ return;
+ }
+
+ if (q->isWindow() && q->internalWinId()) {
+
+ WId id = q->internalWinId();
+ if (!extra->topextra->activated) {
+ id->ActivateL();
+ extra->topextra->activated = 1;
+ }
+ TInt stackingFlags;
+ if ((q->windowType() & Qt::Popup) == Qt::Popup) {
+ stackingFlags = ECoeStackFlagRefusesAllKeys | ECoeStackFlagRefusesFocus;
+ } else {
+ stackingFlags = ECoeStackFlagStandard;
+ }
+ id->ControlEnv()->AppUi()->AddToStackL(id, ECoeStackPriorityDefault, stackingFlags);
+ id->MakeVisible(true);
+
+ // Force setting of the icon after window is made visible,
+ // this is needed even WA_SetWindowIcon is not set, as in that case we need
+ // to reset to the application level window icon
+ setWindowIcon_sys(true);
+ }
+
+ invalidateBuffer(q->rect());
+}
+
+void QWidgetPrivate::hide_sys()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ deactivateWidgetCleanup();
+ WId id = q->internalWinId();
+ if (q->isWindow() && id) {
+ if(id->IsFocused()) // Avoid unnecessry calls to FocusChanged()
+ id->SetFocus(false);
+ id->MakeVisible(false);
+ id->ControlEnv()->AppUi()->RemoveFromStack(id);
+ if (QWidgetBackingStore *bs = maybeBackingStore())
+ bs->releaseBuffer();
+ } else {
+ invalidateBuffer(q->rect());
+ }
+
+ q->setAttribute(Qt::WA_Mapped, false);
+}
+
+void QWidgetPrivate::setFocus_sys()
+{
+ Q_Q(QWidget);
+ if (q->testAttribute(Qt::WA_WState_Created) && q->window()->windowType() != Qt::Popup)
+ if(!q->effectiveWinId()->IsFocused()) // Avoid unnecessry calls to FocusChanged()
+ q->effectiveWinId()->SetFocus(true);
+}
+
+void QWidgetPrivate::handleSymbianDeferredFocusChanged()
+{
+ Q_Q(QWidget);
+ WId control = q->internalWinId();
+ if (!control) {
+ // This could happen if the widget was reparented, while the focuschange
+ // was in the event queue.
+ return;
+ }
+
+ if (control->IsFocused()) {
+ QApplication::setActiveWindow(q);
+#ifdef Q_WS_S60
+ // If widget is fullscreen, hide status pane and button container
+ // otherwise show them.
+ CEikStatusPane* statusPane = S60->statusPane();
+ CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
+ bool isFullscreen = q->windowState() & Qt::WindowFullScreen;
+ if (statusPane && (statusPane->IsVisible() == isFullscreen))
+ statusPane->MakeVisible(!isFullscreen);
+ if (buttonGroup && (buttonGroup->IsVisible() == isFullscreen))
+ buttonGroup->MakeVisible(!isFullscreen);
+#endif
+ } else {
+ QApplication::setActiveWindow(0);
+ }
+}
+
+void QWidgetPrivate::raise_sys()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ QTLWExtra *tlwExtra = maybeTopData();
+ if (q->internalWinId() && tlwExtra) {
+ tlwExtra->rwindow->SetOrdinalPosition(0);
+ }
+}
+
+void QWidgetPrivate::lower_sys()
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ QTLWExtra *tlwExtra = maybeTopData();
+ if (q->internalWinId() && tlwExtra) {
+ tlwExtra->rwindow->SetOrdinalPosition(-1);
+ }
+ if(!q->isWindow())
+ invalidateBuffer(q->rect());
+}
+
+void QWidgetPrivate::setModal_sys()
+{
+
+}
+
+void QWidgetPrivate::stackUnder_sys(QWidget* w)
+{
+ Q_Q(QWidget);
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ QTLWExtra *tlwExtra = maybeTopData();
+ QTLWExtra *tlwExtraSibling = w->d_func()->maybeTopData();
+ if (q->internalWinId() && tlwExtra && w->internalWinId() && tlwExtraSibling)
+ tlwExtra->rwindow->SetOrdinalPosition(tlwExtraSibling->rwindow->OrdinalPosition() + 1);
+ if(!q->isWindow() || !w->internalWinId())
+ invalidateBuffer(q->rect());
+}
+
+void QWidgetPrivate::reparentChildren()
+{
+ Q_Q(QWidget);
+ QObjectList chlist = q->children();
+ for (int i = 0; i < chlist.size(); ++i) { // reparent children
+ QObject *obj = chlist.at(i);
+ if (obj->isWidgetType()) {
+ QWidget *w = (QWidget *)obj;
+ if (!w->testAttribute(Qt::WA_WState_Created))
+ continue;
+ if (!w->isWindow()) {
+ w->d_func()->invalidateBuffer(w->rect());
+ WId parent = q->effectiveWinId();
+ WId child = w->effectiveWinId();
+ if (parent != child)
+ child->SetParent(parent);
+ // ### TODO: We probably also need to update the component array here
+ w->d_func()->reparentChildren();
+ } else {
+ bool showIt = w->isVisible();
+ QPoint old_pos = w->pos();
+ w->setParent(q, w->windowFlags());
+ w->move(old_pos);
+ if (showIt)
+ w->show();
+ }
+ }
+ }
+}
+
+void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
+{
+ Q_Q(QWidget);
+ bool wasCreated = q->testAttribute(Qt::WA_WState_Created);
+
+ if (q->isVisible() && q->parentWidget() && parent != q->parentWidget())
+ q->parentWidget()->d_func()->invalidateBuffer(q->geometry());
+
+ if (q->testAttribute(Qt::WA_DropSiteRegistered))
+ q->setAttribute(Qt::WA_DropSiteRegistered, false);
+
+ WId old_winid = wasCreated ? data.winid : 0;
+ if ((q->windowType() == Qt::Desktop))
+ old_winid = 0;
+ setWinId(0);
+
+ // hide and reparent our own window away. Otherwise we might get
+ // destroyed when emitting the child remove event below. See QWorkspace.
+ if (wasCreated && old_winid) {
+ old_winid->MakeVisible(false);
+ old_winid->ControlEnv()->AppUi()->RemoveFromStack(old_winid);
+ old_winid->SetParent(0);
+ }
+
+ QObjectPrivate::setParent_helper(parent);
+ bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide);
+
+ data.window_flags = f;
+ data.fstrut_dirty = true;
+ q->setAttribute(Qt::WA_WState_Created, false);
+ q->setAttribute(Qt::WA_WState_Visible, false);
+ q->setAttribute(Qt::WA_WState_Hidden, false);
+ adjustFlags(data.window_flags, q);
+ // keep compatibility with previous versions, we need to preserve the created state
+ // (but we recreate the winId for the widget being reparented, again for compatibility)
+ if (wasCreated || (!q->isWindow() && parent->testAttribute(Qt::WA_WState_Created)))
+ createWinId();
+ if (q->isWindow() || (!parent || parent->isVisible()) || explicitlyHidden)
+ q->setAttribute(Qt::WA_WState_Hidden);
+ q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden);
+
+ if (wasCreated)
+ reparentChildren();
+
+ if (old_winid) {
+ CBase::Delete(old_winid);
+ }
+
+ if (q->testAttribute(Qt::WA_AcceptDrops)
+ || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)))
+ q->setAttribute(Qt::WA_DropSiteRegistered, true);
+
+ invalidateBuffer(q->rect());
+}
+
+void QWidgetPrivate::setConstraints_sys()
+{
+
+}
+
+
+void QWidgetPrivate::s60UpdateIsOpaque()
+{
+ Q_Q(QWidget);
+
+ if (!q->testAttribute(Qt::WA_WState_Created) || !q->testAttribute(Qt::WA_TranslucentBackground))
+ return;
+
+ if ((data.window_flags & Qt::FramelessWindowHint) == 0)
+ return;
+
+ if (!isOpaque) {
+ QTLWExtra *topExtra = topData();
+ RWindow *rwindow = static_cast<RWindow*>(topExtra->rwindow);
+ TDisplayMode gotDM = (TDisplayMode)rwindow->SetRequiredDisplayMode(EColor16MA);
+ if (rwindow->SetTransparencyAlphaChannel() == KErrNone)
+ rwindow->SetBackgroundColor(TRgb(255, 255, 255, 0));
+ } else {
+ QTLWExtra *topExtra = topData();
+ RWindow *rwindow = static_cast<RWindow*>(topExtra->rwindow);
+ rwindow->SetTransparentRegion(TRegionFix<1>());
+ }
+}
+
+CFbsBitmap* qt_pixmapToNativeBitmapL(QPixmap pixmap, bool invert)
+{
+ CFbsBitmap* fbsBitmap = new(ELeave)CFbsBitmap;
+ TSize size(pixmap.size().width(), pixmap.size().height());
+ TDisplayMode mode(EColor16MU);
+
+ bool isNull = pixmap.isNull();
+ int depth = pixmap.depth();
+
+ // TODO: dummy assumptions from bit amounts for each color
+ // Will fix later on when native pixmap is implemented
+ switch(pixmap.depth()) {
+ case 1:
+ mode = EGray2;
+ break;
+ case 4:
+ mode = EColor16;
+ break;
+ case 8:
+ mode = EColor256;
+ break;
+ case 12:
+ mode = EColor4K;
+ break;
+ case 16:
+ mode = EColor64K;
+ break;
+ case 24:
+ mode = EColor16M;
+ break;
+ case 32:
+ case EColor16MU:
+ break;
+ default:
+ qFatal("Unsupported pixmap depth");
+ break;
+ }
+
+ User::LeaveIfError(fbsBitmap->Create(size, mode));
+ fbsBitmap->LockHeap();
+ QImage image = pixmap.toImage();
+
+ if(invert)
+ image.invertPixels();
+
+ int height = pixmap.size().height();
+ for(int i=0;i<height;i++ )
+ {
+ TPtr8 scanline(image.scanLine(i), image.bytesPerLine(), image.bytesPerLine());
+ fbsBitmap->SetScanLine( scanline, i );
+ }
+
+ fbsBitmap->UnlockHeap();
+ return fbsBitmap;
+}
+
+void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
+{
+#ifdef Q_WS_S60
+ Q_Q(QWidget);
+
+ if (!q->testAttribute(Qt::WA_WState_Created) || !q->isWindow() )
+ return;
+
+ QTLWExtra* topData = this->topData();
+ if (topData->iconPixmap && !forceReset)
+ // already been set
+ return;
+
+ TRect cPaneRect;
+ TBool found = AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EContextPane, cPaneRect );
+ CAknContextPane* contextPane = S60->contextPane();
+ if (found && contextPane) { // We have context pane with valid metrics
+ QIcon icon = q->windowIcon();
+ if (!icon.isNull()) {
+ // Valid icon -> set it as an context pane picture
+ QSize size = icon.actualSize(QSize(cPaneRect.Size().iWidth, cPaneRect.Size().iHeight));
+ QPixmap pm = icon.pixmap(size);
+ QBitmap mask = pm.mask();
+ if (mask.isNull()) {
+ mask = QBitmap(pm.size());
+ mask.fill(Qt::color1);
+ }
+
+ // Convert to CFbsBitmp
+ // TODO: When QPixmap is adapted to use native CFbsBitmap,
+ // it could be set directly to context pane
+ CFbsBitmap* nBitmap = qt_pixmapToNativeBitmapL(pm, false);
+ CFbsBitmap* nMask = qt_pixmapToNativeBitmapL(mask, true);
+
+ contextPane->SetPicture(nBitmap,nMask);
+ } else {
+ // Icon set to null -> set context pane picture to default
+ contextPane->SetPictureToDefaultL();
+ }
+ } else {
+ // Context pane does not exist, try setting small icon to title pane
+ TRect titlePaneRect;
+ TBool found = AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::ETitlePane, titlePaneRect );
+ CAknTitlePane* titlePane = S60->titlePane();
+ if (found && titlePane) { // We have title pane with valid metrics
+ // The API to get title_pane graphics size is not public -> assume square space based
+ // on titlebar font height. CAknBitmap would be optimum, wihtout setting the size, since
+ // then title pane would automatically scale the bitmap. Unfortunately it is not public API
+ const CFont * font = AknLayoutUtils::FontFromId(EAknLogicalFontTitleFont);
+ TSize iconSize(font->HeightInPixels(), font->HeightInPixels());
+
+ QIcon icon = q->windowIcon();
+ if (!icon.isNull()) {
+ // Valid icon -> set it as an title pane small picture
+ QSize size = icon.actualSize(QSize(iconSize.iWidth, iconSize.iHeight));
+ QPixmap pm = icon.pixmap(size);
+ QBitmap mask = pm.mask();
+ if (mask.isNull()) {
+ mask = QBitmap(pm.size());
+ mask.fill(Qt::color1);
+ }
+
+ // Convert to CFbsBitmp
+ // TODO: When QPixmap is adapted to use native CFbsBitmap,
+ // it could be set directly to context pane
+ CFbsBitmap* nBitmap = qt_pixmapToNativeBitmapL(pm, false);
+ CFbsBitmap* nMask = qt_pixmapToNativeBitmapL(mask, true);
+
+ titlePane->SetSmallPicture( nBitmap, nMask, ETrue );
+ } else {
+ // Icon set to null -> set context pane picture to default
+ titlePane->SetSmallPicture( NULL, NULL, EFalse );
+ }
+ }
+ }
+
+#else
+ Q_UNUSED(forceReset)
+#endif
+}
+
+void QWidgetPrivate::setWindowTitle_sys(const QString &caption)
+{
+#ifdef Q_WS_S60
+ Q_Q(QWidget);
+ if (q->isWindow()) {
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ CAknTitlePane* titlePane = S60->titlePane();
+ if(titlePane)
+ titlePane->SetTextL(qt_QString2TPtrC(caption));
+ }
+#else
+ Q_UNUSED(caption)
+#endif
+}
+
+void QWidgetPrivate::setWindowIconText_sys(const QString & /*iconText */)
+{
+
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy)
+{
+ Q_Q(QWidget);
+
+ scrollChildren(dx, dy);
+ if (!paintOnScreen() || !q->internalWinId() || !q->internalWinId()->OwnsWindow()) {
+ scrollRect(q->rect(), dx, dy);
+ } else {
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ RDrawableWindow* rw = topData()->rwindow;
+ rw->Scroll(TPoint(dx, dy));
+ }
+}
+
+void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r)
+{
+ Q_Q(QWidget);
+
+ if (!paintOnScreen() || !q->internalWinId() || !q->internalWinId()->OwnsWindow()) {
+ scrollRect(r, dx, dy);
+ } else {
+ Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
+ RDrawableWindow* rw = topData()->rwindow;
+ rw->Scroll(TPoint(dx, dy), qt_QRect2TRect(r));
+ }
+}
+
+/*!
+ For this function to work in the emulator, you must add:
+ TRANSPARENCY
+ To a line in the wsini.ini file.
+*/
+void QWidgetPrivate::setWindowOpacity_sys(qreal)
+{
+ // ### TODO: Implement uniform window transparency
+}
+
+void QWidgetPrivate::updateFrameStrut()
+{
+
+}
+
+void QWidgetPrivate::updateSystemBackground()
+{
+
+}
+
+void QWidgetPrivate::registerDropSite(bool /* on */)
+{
+
+}
+
+void QWidgetPrivate::createTLSysExtra()
+{
+ extra->topextra->backingStore = 0;
+ extra->topextra->activated = 0;
+ extra->topextra->rwindow = 0;
+}
+
+void QWidgetPrivate::deleteTLSysExtra()
+{
+ delete extra->topextra->backingStore;
+ extra->topextra->backingStore = 0;
+}
+
+void QWidgetPrivate::createSysExtra()
+{
+
+}
+
+void QWidgetPrivate::deleteSysExtra()
+{
+
+}
+
+QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
+{
+ return new QS60WindowSurface(q_func());
+}
+
+void QWidgetPrivate::setMask_sys(const QRegion& /* region */)
+{
+
+}
+
+int QWidget::metric(PaintDeviceMetric m) const
+{
+ Q_D(const QWidget);
+ int val;
+ if (m == PdmWidth) {
+ val = data->crect.width();
+ } else if (m == PdmHeight) {
+ val = data->crect.height();
+ } else {
+ CWsScreenDevice *scr = S60->screenDevice();
+ switch(m) {
+ case PdmDpiX:
+ case PdmPhysicalDpiX:
+ if (d->extra && d->extra->customDpiX) {
+ val = d->extra->customDpiX;
+ } else {
+ const QWidgetPrivate *p = d;
+ while (p->parent) {
+ p = static_cast<const QWidget *>(p->parent)->d_func();
+ if (p->extra && p->extra->customDpiX) {
+ val = p->extra->customDpiX;
+ break;
+ }
+ }
+ if (p == d || !(p->extra && p->extra->customDpiX))
+ val = S60->defaultDpiX;
+ }
+ break;
+ case PdmDpiY:
+ case PdmPhysicalDpiY:
+ if (d->extra && d->extra->customDpiY) {
+ val = d->extra->customDpiY;
+ } else {
+ const QWidgetPrivate *p = d;
+ while (p->parent) {
+ p = static_cast<const QWidget *>(p->parent)->d_func();
+ if (p->extra && p->extra->customDpiY) {
+ val = p->extra->customDpiY;
+ break;
+ }
+ }
+ if (p == d || !(p->extra && p->extra->customDpiY))
+ val = S60->defaultDpiY;
+ }
+ break;
+ case PdmWidthMM:
+ {
+ TInt twips = scr->HorizontalPixelsToTwips(data->crect.width());
+ val = (int)(twips * (25.4/KTwipsPerInch));
+ break;
+ }
+ case PdmHeightMM:
+ {
+ TInt twips = scr->VerticalPixelsToTwips(data->crect.height());
+ val = (int)(twips * (25.4/KTwipsPerInch));
+ break;
+ }
+ case PdmNumColors:
+ val = TDisplayModeUtils::NumDisplayModeColors(scr->DisplayMode());
+ break;
+ case PdmDepth:
+ val = TDisplayModeUtils::NumDisplayModeBitsPerPixel(scr->DisplayMode());
+ break;
+ default:
+ val = 0;
+ qWarning("QWidget::metric: Invalid metric command");
+ }
+ }
+ return val;
+}
+
+QPaintEngine *QWidget::paintEngine() const
+{
+ return 0;
+}
+
+QPoint QWidget::mapToGlobal(const QPoint &pos) const
+{
+ Q_D(const QWidget);
+ if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
+
+ QPoint p = pos + data->crect.topLeft();
+ return (isWindow() || !parentWidget()) ? p : parentWidget()->mapToGlobal(p);
+
+ } else if ((d->data.window_flags & Qt::Window) && internalWinId()) { //toplevel
+ QPoint tp = geometry().topLeft();
+ return pos + tp;
+ }
+
+ // This is the native window case. Consider using CCoeControl::PositionRelativeToScreen()
+ // if we decide to go with CCoeControl
+ return QPoint();
+}
+
+QPoint QWidget::mapFromGlobal(const QPoint &pos) const
+{
+ Q_D(const QWidget);
+ if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) {
+ QPoint p = (isWindow() || !parentWidget()) ? pos : parentWidget()->mapFromGlobal(pos);
+ return p - data->crect.topLeft();
+ } else if ((d->data.window_flags & Qt::Window) && internalWinId()) { //toplevel
+ QPoint tp = geometry().topLeft();
+ return pos - tp;
+ }
+
+ // ### TODO native window
+ return QPoint();
+}
+
+void QWidget::setWindowState(Qt::WindowStates newstate)
+{
+ Q_D(QWidget);
+ Qt::WindowStates oldstate = windowState();
+ if (oldstate == newstate)
+ return;
+
+ if (isWindow()) {
+ createWinId();
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ QTLWExtra *top = d->topData();
+
+ // Ensure the initial size is valid, since we store it as normalGeometry below.
+ if (!testAttribute(Qt::WA_Resized) && !isVisible())
+ adjustSize();
+
+ if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
+ if ((newstate & Qt::WindowMaximized)) {
+ const QRect normalGeometry = geometry();
+
+ const QRect r = top->normalGeometry;
+ setGeometry(qApp->desktop()->availableGeometry(this));
+ top->normalGeometry = r;
+
+ if (top->normalGeometry.width() < 0)
+ top->normalGeometry = normalGeometry;
+ } else {
+ // restore original geometry
+ setGeometry(top->normalGeometry);
+ }
+ }
+ if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
+#ifdef Q_WS_S60
+ CEikStatusPane* statusPane = S60->statusPane();
+ CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
+#endif
+ if (newstate & Qt::WindowFullScreen) {
+ const QRect normalGeometry = geometry();
+ const QRect r = top->normalGeometry;
+ setGeometry(qApp->desktop()->screenGeometry(this));
+#ifdef Q_WS_S60
+ if (statusPane)
+ statusPane->MakeVisible(false);
+ if (buttonGroup)
+ buttonGroup->MakeVisible(false);
+#endif
+ top->normalGeometry = r;
+ if (top->normalGeometry.width() < 0)
+ top->normalGeometry = normalGeometry;
+ } else {
+#ifdef Q_WS_S60
+ if (statusPane)
+ statusPane->MakeVisible(true);
+ if (buttonGroup)
+ buttonGroup->MakeVisible(true);
+#endif
+ if (newstate & Qt::WindowMaximized) {
+ const QRect r = top->normalGeometry;
+ setGeometry(qApp->desktop()->availableGeometry(this));
+ top->normalGeometry = r;
+ } else {
+ setGeometry(top->normalGeometry);
+ }
+ }
+ }
+ if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
+ if (newstate & Qt::WindowMinimized) {
+ if (isVisible()) {
+ WId id = effectiveWinId();
+ id->MakeVisible(false);
+ id->ControlEnv()->AppUi()->RemoveFromStack(id);
+ }
+ } else {
+ if (isVisible()) {
+ WId id = effectiveWinId();
+ id->MakeVisible(true);
+ id->ControlEnv()->AppUi()->AddToStackL(id);
+ }
+ const QRect normalGeometry = geometry();
+ const QRect r = top->normalGeometry;
+ top->normalGeometry = r;
+ if (top->normalGeometry.width() < 0)
+ top->normalGeometry = normalGeometry;
+ }
+ }
+ }
+
+ data->window_state = newstate;
+
+ if (newstate & Qt::WindowActive)
+ activateWindow();
+
+ QWindowStateChangeEvent e(oldstate);
+ QApplication::sendEvent(this, &e);
+}
+
+
+void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
+{
+ Q_D(QWidget);
+ if (!isWindow() && parentWidget())
+ parentWidget()->d_func()->invalidateBuffer(geometry());
+ d->deactivateWidgetCleanup();
+ if (testAttribute(Qt::WA_WState_Created)) {
+
+#ifndef QT_NO_IM
+ if (d->ic) {
+ delete d->ic;
+ } else {
+ QInputContext *ic = inputContext();
+ if (ic) {
+ ic->widgetDestroyed(this);
+ }
+ }
+#endif
+
+ setAttribute(Qt::WA_WState_Created, false);
+ QObjectList childList = children();
+ for (int i = 0; i < childList.size(); ++i) { // destroy all widget children
+ register QObject *obj = childList.at(i);
+ if (obj->isWidgetType())
+ static_cast<QWidget*>(obj)->destroy(destroySubWindows,
+ destroySubWindows);
+ }
+ if (QWidgetPrivate::mouseGrabber == this)
+ releaseMouse();
+ if (QWidgetPrivate::keyboardGrabber == this)
+ releaseKeyboard();
+ if (destroyWindow && !(windowType() == Qt::Desktop) && internalWinId()) {
+ WId id = internalWinId();
+ if(id->IsFocused()) // Avoid unnecessry calls to FocusChanged()
+ id->SetFocus(false);
+ id->ControlEnv()->AppUi()->RemoveFromStack(id);
+ CBase::Delete(id);
+
+ // Hack to activate window under destroyed one. With this activation
+ // the next visible window will get keyboard focus
+ WId wid = CEikonEnv::Static()->AppUi()->TopFocusedControl();
+ if (wid) {
+ QWidget *widget = QWidget::find(wid);
+ QApplication::setActiveWindow(widget);
+ }
+
+ }
+
+ d->setWinId(0);
+ }
+}
+
+QWidget *QWidget::mouseGrabber()
+{
+ return QWidgetPrivate::mouseGrabber;
+}
+
+QWidget *QWidget::keyboardGrabber()
+{
+ return QWidgetPrivate::keyboardGrabber;
+}
+
+void QWidget::grabKeyboard()
+{
+ if (!qt_nograb()) {
+ if (QWidgetPrivate::keyboardGrabber && QWidgetPrivate::keyboardGrabber != this)
+ QWidgetPrivate::keyboardGrabber->releaseKeyboard();
+
+ // ### TODO: Native keyboard grab
+
+ QWidgetPrivate::keyboardGrabber = this;
+ }
+}
+
+void QWidget::releaseKeyboard()
+{
+ if (!qt_nograb() && QWidgetPrivate::keyboardGrabber == this) {
+ // ### TODO: Native keyboard release
+ QWidgetPrivate::keyboardGrabber = 0;
+ }
+}
+
+void QWidget::grabMouse()
+{
+ if (!qt_nograb()) {
+ if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this)
+ QWidgetPrivate::mouseGrabber->releaseMouse();
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ WId id = effectiveWinId();
+ id->SetPointerCapture(true);
+ QWidgetPrivate::mouseGrabber = this;
+ }
+}
+
+void QWidget::releaseMouse()
+{
+ if (!qt_nograb() && QWidgetPrivate::mouseGrabber == this) {
+ Q_ASSERT(testAttribute(Qt::WA_WState_Created));
+ WId id = effectiveWinId();
+ id->SetPointerCapture(false);
+ QWidgetPrivate::mouseGrabber = 0;
+ }
+}
+
+void QWidget::activateWindow()
+{
+ Q_D(QWidget);
+ QWidget *tlw = window();
+ if (tlw->isVisible()) {
+ S60->windowGroup().SetOrdinalPosition(0);
+ window()->createWinId();
+ RDrawableWindow* rw = tlw->d_func()->topData()->rwindow;
+ rw->SetOrdinalPosition(0);
+ }
+}
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwindowdefs.h b/src/gui/kernel/qwindowdefs.h
index 7aa29b7..b1f4d1a 100644
--- a/src/gui/kernel/qwindowdefs.h
+++ b/src/gui/kernel/qwindowdefs.h
@@ -131,6 +131,11 @@ QT_END_HEADER
#endif // Q_WS_QWS
+#if defined(Q_OS_SYMBIAN)
+class CCoeControl;
+typedef CCoeControl * WId;
+#endif // Q_OS_SYMBIAN
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
diff --git a/src/gui/kernel/symbian.pri b/src/gui/kernel/symbian.pri
new file mode 100644
index 0000000..d267a53
--- /dev/null
+++ b/src/gui/kernel/symbian.pri
@@ -0,0 +1,3 @@
+symbian {
+ contains(QT_CONFIG, s60): LIBS+= $$QMAKE_LIBS_S60
+}
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 34d1779..d153215 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -82,6 +82,7 @@ SOURCES += \
DEFINES += QT_RASTER_IMAGEENGINE
win32:DEFINES += QT_RASTER_PAINTENGINE
embedded:DEFINES += QT_RASTER_PAINTENGINE
+ symbian:DEFINES += QT_RASTER_PAINTENGINE
SOURCES += \
painting/qpaintengine_raster.cpp \
painting/qdrawhelper.cpp \
@@ -156,14 +157,14 @@ unix:x11 {
painting/qprintengine_mac.mm \
}
-unix:!mac {
+unix:!mac:!symbian {
HEADERS += \
painting/qprinterinfo_unix_p.h
SOURCES += \
painting/qprinterinfo_unix.cpp
}
-win32|x11|mac|embedded {
+win32|x11|mac|embedded|symbian {
SOURCES += painting/qbackingstore.cpp
HEADERS += painting/qbackingstore_p.h
}
@@ -180,6 +181,13 @@ embedded {
painting/qpaintdevice_qws.cpp
}
+symbian {
+ SOURCES += \
+ painting/qpaintdevice_s60.cpp \
+ painting/qregion_s60.cpp \
+ painting/qcolormap_s60.cpp
+}
+
x11|embedded {
contains(QT_CONFIG,qtopia) {
DEFINES += QT_NO_CUPS QT_NO_LPR
@@ -357,3 +365,18 @@ embedded {
}
+symbian {
+ HEADERS += painting/qwindowsurface_s60_p.h
+ SOURCES += painting/qwindowsurface_s60.cpp
+ armccIfdefBlock = \
+ "$${LITERAL_HASH}if defined(ARMV6)" \
+ "MACRO QT_HAVE_ARMV6" \
+ "SOURCEPATH painting" \
+ "SOURCE qblendfunctions_armv6_rvct.s" \
+ "SOURCE qdrawhelper_armv6_rvct.s" \
+ "$${LITERAL_HASH}endif"
+
+ MMP_RULES += armccIfdefBlock
+ QMAKE_CXXFLAGS.ARMCC *= -O3
+}
+
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 34bc578..405acb7 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -829,6 +829,10 @@ QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
QWidgetBackingStore::~QWidgetBackingStore()
{
+ for (int c = 0; c < dirtyWidgets.size(); ++c) {
+ resetWidget(dirtyWidgets.at(c));
+ }
+
delete windowSurface;
windowSurface = 0;
delete dirtyOnScreenWidgets;
diff --git a/src/gui/painting/qblendfunctions_armv6_rvct.s b/src/gui/painting/qblendfunctions_armv6_rvct.s
new file mode 100644
index 0000000..312bd07
--- /dev/null
+++ b/src/gui/painting/qblendfunctions_armv6_rvct.s
@@ -0,0 +1,223 @@
+;/****************************************************************************
+;**
+;** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;** Contact: Qt Software Information (qt-info@nokia.com)
+;**
+;** This file is part of the QtGui module 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 either Technology Preview License Agreement or the
+;** Beta Release License Agreement.
+;**
+;** 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.0, included in the file LGPL_EXCEPTION.txt in this
+;** package.
+;**
+;** GNU General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU
+;** General Public License version 3.0 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.GPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU General Public License version 3.0 requirements will be
+;** met: http://www.gnu.org/copyleft/gpl.html.
+;**
+;** If you are unsure which license is appropriate for your use, please
+;** contact the sales department at qt-sales@nokia.com.
+;** $QT_END_LICENSE$
+;**
+;****************************************************************************/
+
+;
+; W A R N I N G
+; -------------
+;
+; This file is not part of the Qt API. It exists purely as an
+; implementation detail. This header file may change from version to
+; version without notice, or even be removed.
+;
+; We mean it.
+;
+
+
+ ARM
+ PRESERVE8
+
+ INCLUDE qdrawhelper_armv6_rvct.inc
+
+
+;-----------------------------------------------------------------------------
+; qt_blend_rgb32_on_rgb32_arm
+;
+; @brief
+;
+; @param dest Destination pixels (r0)
+; @param dbpl Destination bytes per line (r1)
+; @param src Source pixels (r2)
+; @param sbpl Source bytes per line (r3)
+; @param w Width (s0 -> r4)
+; @param h Height (s1 -> r5)
+; @param const_alpha Constant alpha (s2 -> r6)
+;
+;---------------------------------------------------------------------------
+qt_blend_rgb32_on_rgb32_armv6 Function
+ stmfd sp!, {r4-r12, r14}
+
+ ; read arguments off the stack
+ add r8, sp, #10 * 4
+ ldmia r8, {r9-r11}
+
+ ; Reorganize registers
+
+ mov r4, r10
+ mov r5, r1
+ mov r6, r3
+
+ mov r1, r2
+ mov r2, r9
+ mov r3, r11
+
+ ; Now we have registers
+ ; @param dest Destination pixels (r0)
+ ; @param src Source pixels (r1)
+ ; @param w Width (r2)
+ ; @param const_alpha Constant alpha (r3)
+ ; @param h Height (r4)
+ ; @param dbpl Destination bytes per line (r5)
+ ; @param sbpl Source bytes per line (r6)
+
+ cmp r3, #256 ; test if we have fully opaque constant alpha value
+ bne rgb32_blend_const_alpha ; branch if not
+
+rgb32_blend_loop
+
+ subs r4, r4, #1
+ bmi rgb32_blend_exit ; while(h--)
+
+rgb321 PixCpySafe r0, r1, r2
+
+ add r0, r0, r5 ; dest = dest + dbpl
+ add r1, r1, r6 ; src = src + sbpl
+
+ b rgb32_blend_loop
+
+
+rgb32_blend_const_alpha
+
+ ;ldr r14, =ComponentHalf ; load 0x800080 to r14
+ mov r14, #0x800000
+ add r14, r14, #0x80
+
+ sub r3, r3, #1 ; const_alpha -= 1;
+
+rgb32_blend_loop_const_alpha
+
+ subs r4, r4, #1
+ bmi rgb32_blend_exit ; while(h--)
+
+rgb322 BlendRowSafe PixelSourceOverConstAlpha
+
+ add r0, r0, r5 ; dest = dest + dbpl
+ add r1, r1, r6 ; src = src + sbpl
+
+ b rgb32_blend_loop_const_alpha
+
+rgb32_blend_exit
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+
+
+;-----------------------------------------------------------------------------
+; qt_blend_argb32_on_argb32_arm
+;
+; @brief
+;
+; @param dest Destination pixels (r0)
+; @param dbpl Destination bytes per line (r1)
+; @param src Source pixels (r2)
+; @param sbpl Source bytes per line (r3)
+; @param w Width (s0 -> r4)
+; @param h Height (s1 -> r5)
+; @param const_alpha Constant alpha (s2 -> r6)
+;
+;---------------------------------------------------------------------------
+qt_blend_argb32_on_argb32_armv6 Function
+ stmfd sp!, {r4-r12, r14}
+
+ ; read arguments off the stack
+ add r8, sp, #10 * 4
+ ldmia r8, {r9-r11}
+
+ ; Reorganize registers
+
+ mov r4, r10
+ mov r5, r1
+ mov r6, r3
+
+ mov r1, r2
+ mov r2, r9
+ mov r3, r11
+
+ ; Now we have registers
+ ; @param dest Destination pixels (r0)
+ ; @param src Source pixels (r1)
+ ; @param w Width (r2)
+ ; @param const_alpha Constant alpha (r3)
+ ; @param h Height (r4)
+ ; @param dbpl Destination bytes per line (r5)
+ ; @param sbpl Source bytes per line (r6)
+
+ ;ldr r14, =ComponentHalf ; load 0x800080 to r14
+ mov r14, #0x800000
+ add r14, r14, #0x80
+
+ cmp r3, #256 ; test if we have fully opaque constant alpha value
+ bne argb32_blend_const_alpha ; branch if not
+
+argb32_blend_loop
+
+ subs r4, r4, #1
+ bmi argb32_blend_exit ; while(h--)
+
+argb321 BlendRowSafe PixelSourceOver
+
+ add r0, r0, r5 ; dest = dest + dbpl
+ add r1, r1, r6 ; src = src + sbpl
+
+ b argb32_blend_loop
+
+argb32_blend_const_alpha
+
+ sub r3, r3, #1 ; const_alpha -= 1;
+
+argb32_blend_loop_const_alpha
+
+ subs r4, r4, #1
+ bmi argb32_blend_exit ; while(h--)
+
+argb322 BlendRowSafe PixelSourceOverConstAlpha
+
+ add r0, r0, r5 ; dest = dest + dbpl
+ add r1, r1, r6 ; src = src + sbpl
+
+ b argb32_blend_loop_const_alpha
+
+argb32_blend_exit
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+
+ END ; File end
+
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index f767bb3..519e02e 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -221,7 +221,7 @@ bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush)
{
if (brush.style() != Qt::TexturePattern)
return false;
- QTexturedBrushData *tx_data = static_cast<QTexturedBrushData *>(brush.d);
+ QTexturedBrushData *tx_data = static_cast<QTexturedBrushData *>(brush.d.data());
return tx_data->m_has_pixmap_texture;
}
@@ -230,6 +230,37 @@ struct QGradientBrushData : public QBrushData
QGradient gradient;
};
+struct QBrushDataPointerHandler
+{
+ static inline void deleteData(QBrushData *d)
+ {
+ switch (d->style) {
+ case Qt::TexturePattern:
+ delete static_cast<QTexturedBrushData*>(d);
+ break;
+ case Qt::LinearGradientPattern:
+ case Qt::RadialGradientPattern:
+ case Qt::ConicalGradientPattern:
+ delete static_cast<QGradientBrushData*>(d);
+ break;
+ default:
+ delete d;
+ }
+ }
+
+ static inline void cleanup(QBrushData *d)
+ {
+ if (d && !d->ref.deref()) {
+ deleteData(d);
+ }
+ }
+
+ static inline void reset(QBrushData *&d, QBrushData *other)
+ {
+ cleanup(d);
+ d = other;
+ }
+};
/*!
\class QBrush
@@ -364,20 +395,20 @@ void QBrush::init(const QColor &color, Qt::BrushStyle style)
{
switch(style) {
case Qt::NoBrush:
- d = nullBrushInstance();
+ d.data_ptr() = nullBrushInstance();
d->ref.ref();
if (d->color != color) setColor(color);
return;
case Qt::TexturePattern:
- d = new QTexturedBrushData;
+ d.data_ptr() = new QTexturedBrushData;
break;
case Qt::LinearGradientPattern:
case Qt::RadialGradientPattern:
case Qt::ConicalGradientPattern:
- d = new QGradientBrushData;
+ d.data_ptr() = new QGradientBrushData;
break;
default:
- d = new QBrushData;
+ d.data_ptr() = new QBrushData;
break;
}
d->ref = 1;
@@ -391,8 +422,8 @@ void QBrush::init(const QColor &color, Qt::BrushStyle style)
*/
QBrush::QBrush()
+ : d(nullBrushInstance())
{
- d = nullBrushInstance();
Q_ASSERT(d);
d->ref.ref();
}
@@ -435,7 +466,7 @@ QBrush::QBrush(Qt::BrushStyle style)
if (qbrush_check_type(style))
init(Qt::black, style);
else {
- d = nullBrushInstance();
+ d.data_ptr() = nullBrushInstance();
d->ref.ref();
}
}
@@ -451,7 +482,7 @@ QBrush::QBrush(const QColor &color, Qt::BrushStyle style)
if (qbrush_check_type(style))
init(color, style);
else {
- d = nullBrushInstance();
+ d.data_ptr() = nullBrushInstance();
d->ref.ref();
}
}
@@ -468,7 +499,7 @@ QBrush::QBrush(Qt::GlobalColor color, Qt::BrushStyle style)
if (qbrush_check_type(style))
init(color, style);
else {
- d = nullBrushInstance();
+ d.data_ptr() = nullBrushInstance();
d->ref.ref();
}
}
@@ -510,8 +541,8 @@ QBrush::QBrush(Qt::GlobalColor color, const QPixmap &pixmap)
*/
QBrush::QBrush(const QBrush &other)
+ : d(other.d.data())
{
- d = other.d;
d->ref.ref();
}
@@ -535,7 +566,7 @@ QBrush::QBrush(const QGradient &gradient)
};
init(QColor(), enum_table[gradient.type()]);
- QGradientBrushData *grad = static_cast<QGradientBrushData *>(d);
+ QGradientBrushData *grad = static_cast<QGradientBrushData *>(d.data());
grad->gradient = gradient;
}
@@ -545,24 +576,11 @@ QBrush::QBrush(const QGradient &gradient)
QBrush::~QBrush()
{
- if (!d->ref.deref())
- cleanUp(d);
}
void QBrush::cleanUp(QBrushData *x)
{
- switch (x->style) {
- case Qt::TexturePattern:
- delete static_cast<QTexturedBrushData*>(x);
- break;
- case Qt::LinearGradientPattern:
- case Qt::RadialGradientPattern:
- case Qt::ConicalGradientPattern:
- delete static_cast<QGradientBrushData*>(x);
- break;
- default:
- delete x;
- }
+ QBrushDataPointerHandler::deleteData(x);
}
@@ -571,38 +589,36 @@ void QBrush::detach(Qt::BrushStyle newStyle)
if (newStyle == d->style && d->ref == 1)
return;
- QBrushData *x;
+ QScopedPointer<QBrushData> x;
switch(newStyle) {
case Qt::TexturePattern: {
QTexturedBrushData *tbd = new QTexturedBrushData;
if (d->style == Qt::TexturePattern) {
- QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d);
+ QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
if (data->m_has_pixmap_texture)
tbd->setPixmap(data->pixmap());
else
tbd->setImage(data->image());
}
- x = tbd;
+ x.reset(tbd);
break;
}
case Qt::LinearGradientPattern:
case Qt::RadialGradientPattern:
case Qt::ConicalGradientPattern:
- x = new QGradientBrushData;
- static_cast<QGradientBrushData *>(x)->gradient =
- static_cast<QGradientBrushData *>(d)->gradient;
+ x.reset(new QGradientBrushData);
+ static_cast<QGradientBrushData *>(x.data())->gradient =
+ static_cast<QGradientBrushData *>(d.data())->gradient;
break;
default:
- x = new QBrushData;
+ x.reset(new QBrushData);
break;
}
x->ref = 1;
x->style = newStyle;
x->color = d->color;
x->transform = d->transform;
- if (!d->ref.deref())
- cleanUp(d);
- d = x;
+ d.reset(x.take());
}
@@ -615,10 +631,11 @@ void QBrush::detach(Qt::BrushStyle newStyle)
QBrush &QBrush::operator=(const QBrush &b)
{
+ if (this == &b)
+ return *this;
+
b.d->ref.ref();
- if (!d->ref.deref())
- cleanUp(d);
- d = b.d;
+ d.reset(b.d.data());
return *this;
}
@@ -713,7 +730,7 @@ QPixmap *QBrush::pixmap() const
{
if (d->style != Qt::TexturePattern)
return 0;
- QTexturedBrushData *data = static_cast<QTexturedBrushData*>(d);
+ QTexturedBrushData *data = static_cast<QTexturedBrushData*>(d.data());
QPixmap &pixmap = data->pixmap();
return pixmap.isNull() ? 0 : &pixmap;
}
@@ -730,7 +747,7 @@ QPixmap *QBrush::pixmap() const
QPixmap QBrush::texture() const
{
return d->style == Qt::TexturePattern
- ? ((QTexturedBrushData*) d)->pixmap()
+ ? (static_cast<QTexturedBrushData *>(d.data()))->pixmap()
: QPixmap();
}
@@ -748,7 +765,7 @@ void QBrush::setTexture(const QPixmap &pixmap)
{
if (!pixmap.isNull()) {
detach(Qt::TexturePattern);
- QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d);
+ QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
data->setPixmap(pixmap);
} else {
detach(Qt::NoBrush);
@@ -771,7 +788,7 @@ void QBrush::setTexture(const QPixmap &pixmap)
QImage QBrush::textureImage() const
{
return d->style == Qt::TexturePattern
- ? ((QTexturedBrushData *) d)->image()
+ ? (static_cast<QTexturedBrushData *>(d.data()))->image()
: QImage();
}
@@ -796,7 +813,7 @@ void QBrush::setTextureImage(const QImage &image)
{
if (!image.isNull()) {
detach(Qt::TexturePattern);
- QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d);
+ QTexturedBrushData *data = static_cast<QTexturedBrushData *>(d.data());
data->setImage(image);
} else {
detach(Qt::NoBrush);
@@ -812,7 +829,7 @@ const QGradient *QBrush::gradient() const
if (d->style == Qt::LinearGradientPattern
|| d->style == Qt::RadialGradientPattern
|| d->style == Qt::ConicalGradientPattern) {
- return &static_cast<const QGradientBrushData *>(d)->gradient;
+ return &static_cast<const QGradientBrushData *>(d.data())->gradient;
}
return 0;
}
@@ -925,16 +942,16 @@ bool QBrush::operator==(const QBrush &b) const
if (b.d->style == d->style && b.d->color == d->color) {
switch (d->style) {
case Qt::TexturePattern: {
- QPixmap &us = ((QTexturedBrushData *) d)->pixmap();
- QPixmap &them = ((QTexturedBrushData *) b.d)->pixmap();
+ QPixmap &us = (static_cast<QTexturedBrushData *>(d.data()))->pixmap();
+ QPixmap &them = (static_cast<QTexturedBrushData *>(b.d.data()))->pixmap();
return ((us.isNull() && them.isNull()) || us.cacheKey() == them.cacheKey());
}
case Qt::LinearGradientPattern:
case Qt::RadialGradientPattern:
case Qt::ConicalGradientPattern:
{
- QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d);
- QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d);
+ QGradientBrushData *d1 = static_cast<QGradientBrushData *>(d.data());
+ QGradientBrushData *d2 = static_cast<QGradientBrushData *>(b.d.data());
return d1->gradient == d2->gradient;
}
default:
diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h
index 6dbb94b..5479305 100644
--- a/src/gui/painting/qbrush.h
+++ b/src/gui/painting/qbrush.h
@@ -45,6 +45,7 @@
#include <QtCore/qpair.h>
#include <QtCore/qpoint.h>
#include <QtCore/qvector.h>
+#include <QtCore/qscopedpointer.h>
#include <QtGui/qcolor.h>
#include <QtGui/qmatrix.h>
#include <QtGui/qtransform.h>
@@ -61,6 +62,7 @@ struct QBrushData;
class QPixmap;
class QGradient;
class QVariant;
+struct QBrushDataPointerHandler;
class Q_GUI_EXPORT QBrush
{
@@ -126,13 +128,13 @@ private:
friend bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush);
void detach(Qt::BrushStyle newStyle);
void init(const QColor &color, Qt::BrushStyle bs);
- QBrushData *d;
+ QScopedCustomPointer<QBrushData, QBrushDataPointerHandler> d;
void cleanUp(QBrushData *x);
public:
inline bool isDetached() const;
typedef QBrushData * DataPtr;
- inline DataPtr &data_ptr() { return d; }
+ inline DataPtr &data_ptr() { return d.data_ptr(); }
};
inline void QBrush::setColor(Qt::GlobalColor acolor)
diff --git a/src/gui/painting/qcolormap_s60.cpp b/src/gui/painting/qcolormap_s60.cpp
new file mode 100644
index 0000000..1b58598
--- /dev/null
+++ b/src/gui/painting/qcolormap_s60.cpp
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcolormap.h"
+#include "qcolor.h"
+
+QT_BEGIN_NAMESPACE
+
+class QColormapPrivate
+{
+public:
+ inline QColormapPrivate()
+ : ref(1)
+ { }
+
+ QAtomicInt ref;
+};
+
+void QColormap::initialize()
+{
+}
+
+void QColormap::cleanup()
+{
+}
+
+QColormap QColormap::instance(int)
+{
+ return QColormap();
+}
+
+QColormap::QColormap() : d(new QColormapPrivate)
+{}
+
+QColormap::QColormap(const QColormap &colormap) :d (colormap.d)
+{ d->ref.ref(); }
+
+QColormap::~QColormap()
+{
+ if (!d->ref.deref())
+ delete d;
+}
+
+QColormap::Mode QColormap::mode() const
+{ return QColormap::Direct; }
+
+int QColormap::depth() const
+{
+ return 32;
+}
+
+int QColormap::size() const
+{
+ return -1;
+}
+
+uint QColormap::pixel(const QColor &color) const
+{ return color.rgba(); }
+
+const QColor QColormap::colorAt(uint pixel) const
+{ return QColor(pixel); }
+
+const QVector<QColor> QColormap::colormap() const
+{ return QVector<QColor>(); }
+
+QColormap &QColormap::operator=(const QColormap &colormap)
+{ qAtomicAssign(d, colormap.d); return *this; }
+
+QT_END_NAMESPACE
+
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 979390a..a70923d 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -38,15 +38,18 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+
#include <private/qdrawhelper_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qpainter_p.h>
#include <private/qdrawhelper_x86_p.h>
+#include <private/qdrawhelper_armv6_p.h>
#include <private/qmath_p.h>
#include <qmath.h>
QT_BEGIN_NAMESPACE
+
#define MASK(src, a) src = BYTE_MUL(src, a)
#if defined(Q_OS_IRIX) && defined(Q_CC_GNU) && __GNUC__ == 3 && __GNUC__ < 4 && QT_POINTER_SIZE == 8
@@ -654,7 +657,15 @@ Q_STATIC_TEMPLATE_FUNCTION
const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data,
int y, int x, int length)
{
+#ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2
+ FetchPixelProc fetch;
+ if (format != QImage::Format_Invalid)
+ fetch = qt_fetchPixel<format>;
+ else
+ fetch = fetchPixelProc[data->texture.format];
+#else
FetchPixelProc fetch = (format != QImage::Format_Invalid) ? FetchPixelProc(qt_fetchPixel<format>) : fetchPixelProc[data->texture.format];
+#endif
int image_width = data->texture.width;
int image_height = data->texture.height;
@@ -1203,7 +1214,35 @@ static const uint * QT_FASTCALL fetchConicalGradient(uint *buffer, const Operato
return b;
}
-
+#if defined(Q_CC_RVCT)
+// Force ARM code generation for comp_func_* -methods
+# pragma push
+# pragma arm
+# if defined(QT_HAVE_ARMV6)
+static __forceinline void preload(const uint *start)
+{
+ asm( "pld [start]" );
+}
+static const uint L2CacheLineLength = 32;
+static const uint L2CacheLineLengthInInts = L2CacheLineLength/sizeof(uint);
+# define PRELOAD_INIT(x) preload(x);
+# define PRELOAD_INIT2(x,y) PRELOAD_INIT(x) PRELOAD_INIT(y)
+# define PRELOAD_COND(x) if (((uint)&x[i])%L2CacheLineLength == 0) preload(&x[i] + L2CacheLineLengthInInts);
+// Two consecutive preloads stall, so space them out a bit by using different modulus.
+# define PRELOAD_COND2(x,y) if (((uint)&x[i])%L2CacheLineLength == 0) preload(&x[i] + L2CacheLineLengthInInts); \
+ if (((uint)&y[i])%L2CacheLineLength == 16) preload(&y[i] + L2CacheLineLengthInInts);
+# else
+# define PRELOAD_INIT(x)
+# define PRELOAD_INIT2(x,y)
+# define PRELOAD_COND(x)
+# define PRELOAD_COND2(x,y)
+# endif
+#else
+# define PRELOAD_INIT(x)
+# define PRELOAD_INIT2(x,y)
+# define PRELOAD_COND(x)
+# define PRELOAD_COND2(x,y)
+#endif
/* The constant alpha factor describes an alpha factor that gets applied
to the result of the composition operation combining it with the destination.
@@ -1236,8 +1275,11 @@ static void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint
QT_MEMFILL_UINT(dest, length, 0);
} else {
int ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = BYTE_MUL(dest[i], ialpha);
+ }
}
}
@@ -1247,8 +1289,11 @@ static void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, ui
QT_MEMFILL_UINT(dest, length, 0);
} else {
int ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = BYTE_MUL(dest[i], ialpha);
+ }
}
}
@@ -1263,8 +1308,11 @@ static void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint colo
} else {
int ialpha = 255 - const_alpha;
color = BYTE_MUL(color, const_alpha);
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = color + BYTE_MUL(dest[i], ialpha);
+ }
}
}
@@ -1274,8 +1322,11 @@ static void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length
::memcpy(dest, src, length * sizeof(uint));
} else {
int ialpha = 255 - const_alpha;
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT2(dest, src)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha);
+ }
}
}
@@ -1300,20 +1351,26 @@ static void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint
} else {
if (const_alpha != 255)
color = BYTE_MUL(color, const_alpha);
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = color + BYTE_MUL(dest[i], qAlpha(~color));
+ }
}
}
static void QT_FASTCALL comp_func_SourceOver(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = src[i];
dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s));
}
} else {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = BYTE_MUL(src[i], const_alpha);
dest[i] = s + BYTE_MUL(dest[i], qAlpha(~s));
}
@@ -1329,7 +1386,9 @@ static void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length,
{
if (const_alpha != 255)
color = BYTE_MUL(color, const_alpha);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
dest[i] = d + BYTE_MUL(color, qAlpha(~d));
}
@@ -1337,13 +1396,16 @@ static void QT_FASTCALL comp_func_solid_DestinationOver(uint *dest, int length,
static void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
dest[i] = d + BYTE_MUL(src[i], qAlpha(~d));
}
} else {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = BYTE_MUL(src[i], const_alpha);
dest[i] = d + BYTE_MUL(s, qAlpha(~d));
@@ -1357,13 +1419,17 @@ static void QT_FASTCALL comp_func_DestinationOver(uint *dest, const uint *src, i
*/
static void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint color, uint const_alpha)
{
+ PRELOAD_INIT(dest)
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = BYTE_MUL(color, qAlpha(dest[i]));
+ }
} else {
color = BYTE_MUL(color, const_alpha);
uint cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(d), d, cia);
}
@@ -1372,12 +1438,16 @@ static void QT_FASTCALL comp_func_solid_SourceIn(uint *dest, int length, uint co
static void QT_FASTCALL comp_func_SourceIn(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
dest[i] = BYTE_MUL(src[i], qAlpha(dest[i]));
+ }
} else {
uint cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = BYTE_MUL(src[i], const_alpha);
dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, cia);
@@ -1396,19 +1466,25 @@ static void QT_FASTCALL comp_func_solid_DestinationIn(uint *dest, int length, ui
if (const_alpha != 255) {
a = BYTE_MUL(a, const_alpha) + 255 - const_alpha;
}
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = BYTE_MUL(dest[i], a);
}
}
static void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
dest[i] = BYTE_MUL(dest[i], qAlpha(src[i]));
+ }
} else {
int cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint a = BYTE_MUL(qAlpha(src[i]), const_alpha) + cia;
dest[i] = BYTE_MUL(dest[i], a);
}
@@ -1422,13 +1498,17 @@ static void QT_FASTCALL comp_func_DestinationIn(uint *dest, const uint *src, int
static void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint color, uint const_alpha)
{
+ PRELOAD_INIT(dest)
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = BYTE_MUL(color, qAlpha(~dest[i]));
+ }
} else {
color = BYTE_MUL(color, const_alpha);
int cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, cia);
}
@@ -1437,12 +1517,16 @@ static void QT_FASTCALL comp_func_solid_SourceOut(uint *dest, int length, uint c
static void QT_FASTCALL comp_func_SourceOut(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
dest[i] = BYTE_MUL(src[i], qAlpha(~dest[i]));
+ }
} else {
int cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = BYTE_MUL(src[i], const_alpha);
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, cia);
@@ -1460,18 +1544,25 @@ static void QT_FASTCALL comp_func_solid_DestinationOut(uint *dest, int length, u
uint a = qAlpha(~color);
if (const_alpha != 255)
a = BYTE_MUL(a, const_alpha) + 255 - const_alpha;
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = BYTE_MUL(dest[i], a);
+ }
}
static void QT_FASTCALL comp_func_DestinationOut(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
- for (int i = 0; i < length; ++i)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
dest[i] = BYTE_MUL(dest[i], qAlpha(~src[i]));
+ }
} else {
int cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint sia = BYTE_MUL(qAlpha(~src[i]), const_alpha) + cia;
dest[i] = BYTE_MUL(dest[i], sia);
}
@@ -1490,20 +1581,26 @@ static void QT_FASTCALL comp_func_solid_SourceAtop(uint *dest, int length, uint
color = BYTE_MUL(color, const_alpha);
}
uint sia = qAlpha(~color);
- for (int i = 0; i < length; ++i)
+ PRELOAD_INIT(dest)
+ for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(dest[i]), dest[i], sia);
+ }
}
static void QT_FASTCALL comp_func_SourceAtop(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = src[i];
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s));
}
} else {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = BYTE_MUL(src[i], const_alpha);
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(d), d, qAlpha(~s));
@@ -1523,7 +1620,9 @@ static void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length,
color = BYTE_MUL(color, const_alpha);
a = qAlpha(color) + 255 - const_alpha;
}
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(d, a, color, qAlpha(~d));
}
@@ -1531,8 +1630,10 @@ static void QT_FASTCALL comp_func_solid_DestinationAtop(uint *dest, int length,
static void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = src[i];
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(d, qAlpha(s), s, qAlpha(~d));
@@ -1540,6 +1641,7 @@ static void QT_FASTCALL comp_func_DestinationAtop(uint *dest, const uint *src, i
} else {
int cia = 255 - const_alpha;
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint s = BYTE_MUL(src[i], const_alpha);
uint d = dest[i];
uint a = qAlpha(s) + cia;
@@ -1560,7 +1662,9 @@ static void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color,
color = BYTE_MUL(color, const_alpha);
uint sia = qAlpha(~color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
dest[i] = INTERPOLATE_PIXEL_255(color, qAlpha(~d), d, sia);
}
@@ -1568,14 +1672,17 @@ static void QT_FASTCALL comp_func_solid_XOR(uint *dest, int length, uint color,
static void QT_FASTCALL comp_func_XOR(uint *dest, const uint *src, int length, uint const_alpha)
{
+ PRELOAD_INIT2(dest, src)
if (const_alpha == 255) {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s));
}
} else {
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = BYTE_MUL(src[i], const_alpha);
dest[i] = INTERPOLATE_PIXEL_255(s, qAlpha(~d), d, qAlpha(~s));
@@ -1626,7 +1733,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl(uint *dest, int
{
uint s = color;
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
#define MIX(mask) (qMin(((qint64(s)&mask) + (qint64(d)&mask)), qint64(mask)))
d = (MIX(AMASK) | MIX(RMASK) | MIX(GMASK) | MIX(BMASK));
@@ -1646,7 +1755,9 @@ static void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color,
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Plus_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -1682,7 +1793,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest,
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -1708,7 +1821,9 @@ static void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint co
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -1746,7 +1861,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, i
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -1772,7 +1889,9 @@ static void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint colo
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -1821,7 +1940,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest,
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -1847,7 +1968,9 @@ static void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint col
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -1890,7 +2013,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, i
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -1916,7 +2041,9 @@ static void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint colo
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -1959,7 +2086,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest,
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -1985,7 +2114,9 @@ static void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint col
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2038,7 +2169,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *des
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2064,7 +2197,9 @@ static void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2117,7 +2252,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2143,7 +2280,9 @@ static void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint c
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2193,7 +2332,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2219,7 +2360,9 @@ static void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint c
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2278,7 +2421,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2304,7 +2449,9 @@ static void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint c
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2347,7 +2494,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *des
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2373,7 +2522,9 @@ static void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2410,7 +2561,9 @@ Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_imp
int sg = qGreen(color);
int sb = qBlue(color);
+ PRELOAD_INIT(dest)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND(dest)
uint d = dest[i];
int da = qAlpha(d);
@@ -2436,7 +2589,9 @@ static void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint c
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *dest, const uint *src, int length, const T &coverage)
{
+ PRELOAD_INIT2(dest, src)
for (int i = 0; i < length; ++i) {
+ PRELOAD_COND2(dest, src)
uint d = dest[i];
uint s = src[i];
@@ -2462,6 +2617,11 @@ static void QT_FASTCALL comp_func_Exclusion(uint *dest, const uint *src, int len
comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+#if defined(Q_CC_RVCT)
+// Restore pragma state from previous #pragma arm
+# pragma pop
+#endif
+
static void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest,
int length,
uint color,
@@ -7709,6 +7869,96 @@ static uint detectCPUFeatures()
#endif
}
+#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
+// Move these to qdrawhelper_arm.c when all
+// functions are implemented using arm assembly.
+static CompositionFunctionSolid qt_functionForModeSolid_ARMv6[numCompositionFunctions] = {
+ comp_func_solid_SourceOver,
+ comp_func_solid_DestinationOver,
+ comp_func_solid_Clear,
+ comp_func_solid_Source,
+ comp_func_solid_Destination,
+ comp_func_solid_SourceIn,
+ comp_func_solid_DestinationIn,
+ comp_func_solid_SourceOut,
+ comp_func_solid_DestinationOut,
+ comp_func_solid_SourceAtop,
+ comp_func_solid_DestinationAtop,
+ comp_func_solid_XOR,
+ comp_func_solid_Plus,
+ comp_func_solid_Multiply,
+ comp_func_solid_Screen,
+ comp_func_solid_Overlay,
+ comp_func_solid_Darken,
+ comp_func_solid_Lighten,
+ comp_func_solid_ColorDodge,
+ comp_func_solid_ColorBurn,
+ comp_func_solid_HardLight,
+ comp_func_solid_SoftLight,
+ comp_func_solid_Difference,
+ comp_func_solid_Exclusion,
+ rasterop_solid_SourceOrDestination,
+ rasterop_solid_SourceAndDestination,
+ rasterop_solid_SourceXorDestination,
+ rasterop_solid_NotSourceAndNotDestination,
+ rasterop_solid_NotSourceOrNotDestination,
+ rasterop_solid_NotSourceXorDestination,
+ rasterop_solid_NotSource,
+ rasterop_solid_NotSourceAndDestination,
+ rasterop_solid_SourceAndNotDestination
+};
+
+static CompositionFunction qt_functionForMode_ARMv6[numCompositionFunctions] = {
+ comp_func_SourceOver_armv6,
+ comp_func_DestinationOver,
+ comp_func_Clear,
+ comp_func_Source_armv6,
+ comp_func_Destination,
+ comp_func_SourceIn,
+ comp_func_DestinationIn,
+ comp_func_SourceOut,
+ comp_func_DestinationOut,
+ comp_func_SourceAtop,
+ comp_func_DestinationAtop,
+ comp_func_XOR,
+ comp_func_Plus,
+ comp_func_Multiply,
+ comp_func_Screen,
+ comp_func_Overlay,
+ comp_func_Darken,
+ comp_func_Lighten,
+ comp_func_ColorDodge,
+ comp_func_ColorBurn,
+ comp_func_HardLight,
+ comp_func_SoftLight,
+ comp_func_Difference,
+ comp_func_Exclusion,
+ rasterop_SourceOrDestination,
+ rasterop_SourceAndDestination,
+ rasterop_SourceXorDestination,
+ rasterop_NotSourceAndNotDestination,
+ rasterop_NotSourceOrNotDestination,
+ rasterop_NotSourceXorDestination,
+ rasterop_NotSource,
+ rasterop_NotSourceAndDestination,
+ rasterop_SourceAndNotDestination
+};
+
+static void qt_blend_color_argb_armv6(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+
+ CompositionFunctionSolid func = qt_functionForModeSolid_ARMv6[data->rasterBuffer->compositionMode];
+ while (count--) {
+ uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x;
+ func(target, spans->len, data->solid.color, spans->coverage);
+ ++spans;
+ }
+}
+
+#endif // Q_CC_RVCT && QT_HAVE_ARMV6
+
+
void qInitDrawhelperAsm()
{
static uint features = 0xffffffff;
@@ -7824,6 +8074,20 @@ void qInitDrawhelperAsm()
#endif // QT_NO_DEBUG
+#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
+ functionForModeAsm = qt_functionForMode_ARMv6;
+ functionForModeSolidAsm = qt_functionForModeSolid_ARMv6;
+
+ qt_memfill32 = qt_memfill32_armv6;
+
+ qDrawHelper[QImage::Format_ARGB32_Premultiplied].blendColor = qt_blend_color_argb_armv6;
+
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6;
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6;
+#endif // Q_CC_RVCT && QT_HAVE_ARMV6
+
if (functionForModeSolidAsm) {
const int destinationMode = QPainter::CompositionMode_Destination;
functionForModeSolidAsm[destinationMode] = functionForModeSolid_C[destinationMode];
diff --git a/src/gui/painting/qdrawhelper_armv6_p.h b/src/gui/painting/qdrawhelper_armv6_p.h
new file mode 100644
index 0000000..a4c1df2
--- /dev/null
+++ b/src/gui/painting/qdrawhelper_armv6_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDRAWHELPER_ARMV6_P_H
+#define QDRAWHELPER_ARMV6_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qdrawhelper_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
+
+extern "C" void qt_blend_rgb32_on_rgb32_armv6(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+extern "C" void qt_blend_argb32_on_argb32_armv6(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+extern "C" void qt_memfill32_armv6(quint32 *dest, quint32 value, int count);
+
+extern "C" void comp_func_Source_armv6(uint *dest, const uint *src, int length, uint const_alpha);
+extern "C" void comp_func_SourceOver_armv6(uint *dest, const uint *src, int length, uint const_alpha);
+
+#endif // QT_HAVE_ARMV6
+
+QT_END_NAMESPACE
+
+#endif // QDRAWHELPER_ARMV6_P_H
diff --git a/src/gui/painting/qdrawhelper_armv6_rvct.inc b/src/gui/painting/qdrawhelper_armv6_rvct.inc
new file mode 100644
index 0000000..b3e0605
--- /dev/null
+++ b/src/gui/painting/qdrawhelper_armv6_rvct.inc
@@ -0,0 +1,496 @@
+;/****************************************************************************
+;**
+;** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;** Contact: Qt Software Information (qt-info@nokia.com)
+;**
+;** This file is part of the QtGui module 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 either Technology Preview License Agreement or the
+;** Beta Release License Agreement.
+;**
+;** 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.0, included in the file LGPL_EXCEPTION.txt in this
+;** package.
+;**
+;** GNU General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU
+;** General Public License version 3.0 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.GPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU General Public License version 3.0 requirements will be
+;** met: http://www.gnu.org/copyleft/gpl.html.
+;**
+;** If you are unsure which license is appropriate for your use, please
+;** contact the sales department at qt-sales@nokia.com.
+;** $QT_END_LICENSE$
+;**
+;****************************************************************************/
+
+;
+; W A R N I N G
+; -------------
+;
+; This file is not part of the Qt API. It exists purely as an
+; implementation detail. This header file may change from version to
+; version without notice, or even be removed.
+;
+; We mean it.
+;
+
+;-----------------------------------------------------------------------------
+; Globals.
+; Earch marcro expects that caller has loaded 0x800080 to r14.
+;-----------------------------------------------------------------------------
+
+ComponentHalf EQU 0x800080
+
+;-----------------------------------------------------------------------------
+; ARM assembly implementations of accelerated graphics operations.
+;
+; Conventions:
+;
+; - r0 = Target buffer pointer
+; - r1 = Source buffer pointer
+; - r2 = Length of the buffer to blend
+; - r3 = Constant alpha for source buffer
+;
+;-----------------------------------------------------------------------------
+
+; A macro for transparently defining ARM functions
+ MACRO
+$func Function
+ AREA Function_$func, CODE
+ GLOBAL $func
+ ALIGN 4
+ CODE32
+$func
+ MEND
+
+
+;-----------------------------------------------------------------------------
+; Armv6 boosted implementation of BYTE_MUL(...) function found in qdrawhelper_p.h.
+;
+; @param dst Destination register where to store the result
+; @param x Value to multiply
+; @param a Multiplicator byte
+; @param r14 Component half 0x800080
+;
+; @note Trashes x, r8
+;-----------------------------------------------------------------------------
+ MACRO
+ ByteMul $dst, $x, $a
+
+ ; static inline uint BYTE_MUL(uint x, uint a)
+
+ ; uint r8 = (x & 0xff00ff) * a + 0x800080
+ uxtb16 r8, $x ; r8 = r8 & 0x00FF00FF
+ mla r8, r8, $a, r14
+
+ ; x = ((r >> 8) & 0xff00ff) * a + 0x800080
+ uxtb16 $x, $x, ror #8
+ mla $x, $x, $a, r14
+
+
+ ; r8 = (r8 + ((r8 >> 8) & 0xff00ff) ) >> 8
+ ; r8 &= 0xff00ff
+ uxtab16 r8, r8, r8, ror #8
+ uxtb16 r8, r8, ror #8
+
+ ; x = x + ((x >>8) & 0xff00ff)
+ uxtab16 $x, $x, $x, ror #8
+
+ ; x &= 0xff00ff00
+ ; x |= r8
+ uxtb16 $x, $x, ror #8
+ orr $dst, r8, $x, lsl #8
+
+ MEND
+
+;-----------------------------------------------------------------------------
+; Armv6 boosted implementation of INTERPOLATE_PIXEL_255(...) function found in
+; qdrawhelper_p.h.
+;
+; @param dst Destination register where to store the result
+; @param x First value to multiply
+; @param a Multiplicator byte for first value
+; @param y Second value to multiply
+; @param b Multiplicator byte for second value
+; @param r14 Component half 0x800080
+;
+;
+; @note Trashes x, r8, r14
+;-----------------------------------------------------------------------------
+ MACRO
+ InterpolatePixel255 $dst, $x, $a, $y, $b
+
+ ; static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b)
+
+ ; First calculate the parts where we need 0x800080
+
+ ; uint r8 = (((x & 0xff00ff) * a) + 0x800080)
+ uxtb16 r8, $x ; r8 = r8 & 0x00FF00FF
+ mla r8, r8, $a, r14
+
+ ; x = ((((x >> 8) & 0xff00ff) * a) + 0x800080)
+ uxtb16 $x, $x, ror #8
+ mla $x, $x, $a, r14
+
+ ; Now we are trashing r14 to free it for other purposes
+
+ ; uint r14 = (y & 0xff00ff) * b
+ uxtb16 r14, $y ; r14 = y & 0x00FF00FF
+ mul r14, r14, $b
+
+ ; r8 = r8 + r14
+ add r8, r8, r14
+
+ ; r8 = (r8 + ((r8 >> 8) & 0xff00ff) ) >> 8
+ ; r8 &= 0xff00ff
+ uxtab16 r8, r8, r8, ror #8
+ uxtb16 r8, r8, ror #8
+
+ ; r14 = ((y >> 8) & 0xff00ff) * b
+ uxtb16 r14, $y, ror #8 ; r14 = ((y >> 8) & 0xFF00FF)
+ mul r14, r14, $b
+
+ ; x = x + r14
+ add $x, $x, r14
+
+ ; x = x + ((x >>8) & 0xff00ff)
+ uxtab16 $x, $x, $x, ror #8
+
+ ; x &= 0xff00ff00
+ ; x |= r8
+ uxtb16 $x, $x, ror #8
+ orr $dst, r8, $x, lsl #8
+
+ MEND
+
+;-----------------------------------------------------------------------------
+;
+;-----------------------------------------------------------------------------
+ MACRO
+$label Blend4Pixels $BlendPixel
+
+ ; Blend first 4 pixels
+
+ ldmia r1!, {r4-r7}
+ ldm r0, {r9-r12}
+
+b4p1_$label $BlendPixel r9, r4, r3
+b4p2_$label $BlendPixel r10, r5, r3
+b4p3_$label $BlendPixel r11, r6, r3
+b4p4_$label $BlendPixel r12, r7, r3
+
+ stmia r0!, {r9-r12}
+
+ MEND
+
+;-----------------------------------------------------------------------------
+;
+;-----------------------------------------------------------------------------
+ MACRO
+$label Blend8Pixels $BlendPixel
+
+b8p1_$label Blend4Pixels $BlendPixel
+b8p2_$label Blend4Pixels $BlendPixel
+
+ MEND
+
+;-----------------------------------------------------------------------------
+;
+;-----------------------------------------------------------------------------
+ MACRO
+$label Blend16Pixels $BlendPixel
+
+b16p1_$label Blend8Pixels $BlendPixel
+b16p2_$label Blend8Pixels $BlendPixel
+
+ MEND
+
+;-----------------------------------------------------------------------------
+;
+;-----------------------------------------------------------------------------
+ MACRO
+$label Blend32Pixels $BlendPixel
+
+b32p1_$label Blend16Pixels $BlendPixel
+b32p2_$label Blend16Pixels $BlendPixel
+
+ MEND
+
+;-----------------------------------------------------------------------------
+; A macro for source over compositing one row of pixels and saving the results
+; to destination buffer.
+;
+; @param dest Destination buffer (r0)
+; @param src Source buffer (r1)
+; @param length Length (r2)
+; @param const_alpha Constant alpha (r3)
+; @param r14 Component Half (0x800080) (r14)
+;
+; @note Advances r0, r1
+; @note Trashes r2, r4-r12
+;-----------------------------------------------------------------------------
+ MACRO
+$label BlendRow $BlendPixel
+
+ pld [r1]
+
+bloop_$label
+ ; Blend 32 pixels per loop iteration
+ subs r2, r2, #32
+ bmi b_remaining_$label
+
+brp1_$label Blend32Pixels $BlendPixel
+
+ b bloop_$label
+
+b_remaining_$label
+
+ ; Remaining 31 pixels
+
+ addmi r2, r2, #32
+
+ ; Blend 16 pixels
+ tst r2, #16
+ beq b_remaining8_$label
+
+brp2_$label Blend16Pixels $BlendPixel
+
+b_remaining8_$label
+
+ ; Blend 8 pixels
+ tst r2, #8
+ beq b_remaining4_$label
+
+brp3_$label Blend8Pixels $BlendPixel
+
+b_remaining4_$label
+
+ ; Blend 4 pixels
+ tst r2, #4
+ beq b_remaining3_$label
+
+brp4_$label Blend4Pixels $BlendPixel
+
+b_remaining3_$label
+
+ ; Remaining 3 pixels
+
+ tst r2, #2
+ beq b_last_$label
+
+ ldmia r1!, {r4-r5}
+ ldm r0, {r9-r10}
+
+brp5_$label $BlendPixel r9, r4, r3
+brp6_$label $BlendPixel r10, r5, r3
+
+ stmia r0!, {r9-r10}
+
+b_last_$label
+
+ tst r2, #1
+ beq bexit_$label
+
+ ldr r4, [r1]
+ ldr r9, [r0]
+
+bpl_$label $BlendPixel r9, r4, r3
+
+ str r9, [r0]
+
+bexit_$label
+
+ MEND
+
+;-----------------------------------------------------------------------------
+; A macro for source over compositing one row of pixels and saving the results
+; to destination buffer. Restores all registers.
+;
+; @param dest Destination buffer (r0)
+; @param src Source buffer (r1)
+; @param length Length (r2)
+; @param const_alpha Constant alpha (r3)
+; @param r14 Component Half (0x800080) (r14)
+;
+; @note Advances r0, r1
+; @note Trashes r2, r4-r12
+;-----------------------------------------------------------------------------
+ MACRO
+$label BlendRowSafe $BlendPixel
+
+ stmfd sp!, {r0-r6} ; Preserves registers only up to r6
+
+brs_$label BlendRow $BlendPixel
+
+ ldmfd sp!, {r0-r6}
+
+ MEND
+
+
+;-----------------------------------------------------------------------------
+; Pix Copy.
+; NOTE! Cache line size of ARM1136JF-S and ARM1136J-S is 32 bytes (8 pixels).
+;
+; @param dst Destination pixels (r0)
+; @param src Source pixels (r1)
+; @param len Length (r2)
+;
+; @note Trashes r3-r10
+;-----------------------------------------------------------------------------
+ MACRO
+$label PixCpy $dst, $src, $len
+
+ pld [$src]
+
+pcpy_loop_$label
+ ; Copy 8 pixels per loop iteration
+ pld [$src, #96]
+ subs $len, $len, #8
+ ldmgeia $src!, {r3-r10}
+ stmgeia $dst!, {r3-r10}
+ bgt pcpy_loop_$label
+
+pcpy_remaining_$label
+
+ ; Copy up to 7 remaining pixels
+
+ ; Copy 4 pixels
+ tst $len, #4
+ ldmneia $src!, {r3-r6}
+ stmneia $dst!, {r3-r6}
+
+ tst $len, #2
+ ldmneia $src!, {r3-r4}
+ stmneia $dst!, {r3-r4}
+
+ tst $len, #1
+ ldrne r3, [$src]
+ strne r3, [$dst]
+
+ MEND
+
+;-----------------------------------------------------------------------------
+; General Pix Copy. Maximum 8 pixels at time. Restores all registers.
+;
+; @param dst Destination pixels (r0)
+; @param src Source pixels (r1)
+; @param len Length (r2)
+;
+; @note Trashes r3-r10
+;-----------------------------------------------------------------------------
+ MACRO
+$label PixCpySafe $dst, $src, $len
+
+ stmfd sp!, {r0-r6} ; Preserves registers only up to r6
+
+pcs_$label PixCpy $dst, $src, $len
+
+ ldmfd sp!, {r0-r6} ; pop
+
+ MEND
+
+
+;-----------------------------------------------------------------------------
+; A macro for source over compositing one pixel and saving the result to
+; dst register.
+;
+; @param dst Destination register, must contain destination pixel upon entry
+; @param src Source register, must contain source pixel upon entry
+; @param const_alpha Constant source alpha
+; @param r14 Component half 0x800080
+;
+; @note Trashes const_alpha, r8
+;-----------------------------------------------------------------------------
+ MACRO
+$label PixelSourceOver $dst, $src, $const_alpha
+
+ ; Negate src and extract alpha
+ mvn $const_alpha, $src ; bitwise not
+ uxtb $const_alpha, $const_alpha, ror #24 ; r3 = ((r3 & 0xFF000000) >> 24);
+
+ ;cmp $const_alpha, #255 ; test for full transparency ( negated )
+ ;beq exit_$label
+ cmp $const_alpha, #0 ; test for full opacity ( negated )
+ moveq $dst, $src
+ beq exit_$label
+
+ ByteMul $dst, $dst, $const_alpha
+ add $dst, $src, $dst
+
+exit_$label
+ MEND
+
+;-----------------------------------------------------------------------------
+; A macro for source over compositing one pixel and saving the result to
+; dst register.
+;
+; @param dst Destination register, must contain destination pixel upon entry
+; @param src Source register, must contain source pixel upon entry
+; @param const_alpha Constant source alpha
+; @param r14 Component half 0x800080
+;
+; @note Trashes src, const_alpha, r8
+;-----------------------------------------------------------------------------
+ MACRO
+$label PixelSourceOverConstAlpha $dst, $src, $const_alpha
+
+ ; store alpha because we are going to trash it
+ stmfd sp!, {$const_alpha}
+
+ ByteMul $src, $src, $const_alpha
+
+ ; Negate src and extract alpha
+ mvn $const_alpha, $src ; bitwise not
+ uxtb $const_alpha, $const_alpha, ror #24 ; r3 = ((r3 & 0xFF000000) >> 24);
+
+ ByteMul $dst, $dst, $const_alpha
+
+ add $dst, $src, $dst
+
+ ; recover alpha
+ ldmfd sp!, {$const_alpha}
+
+ MEND
+
+;-----------------------------------------------------------------------------
+; A macro for source over compositing one pixel and saving the result to
+; a register.
+;
+; @param dst Destination register, must contain destination pixel upon entry
+; @param src Source register, must contain source pixel upon entry
+; @param const_alpha Constant source alpha
+; @param r14 Component half 0x800080
+;
+; @note Trashes src, r8
+;-----------------------------------------------------------------------------
+ MACRO
+$label PixelSourceConstAlpha $dst, $src, $const_alpha
+
+ ; store r2 and r14 because we are going to trash them
+ stmfd sp!, {r2, r14}
+
+ rsb r2, $const_alpha, #255
+ InterpolatePixel255 $dst, $src, $const_alpha, $dst, r2
+
+ ; recover r2 and r14
+ ldmfd sp!, {r2, r14}
+
+ MEND
+
+ END ; File end
diff --git a/src/gui/painting/qdrawhelper_armv6_rvct.s b/src/gui/painting/qdrawhelper_armv6_rvct.s
new file mode 100644
index 0000000..3ffe48b
--- /dev/null
+++ b/src/gui/painting/qdrawhelper_armv6_rvct.s
@@ -0,0 +1,178 @@
+;/****************************************************************************
+;**
+;** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+;** Contact: Qt Software Information (qt-info@nokia.com)
+;**
+;** This file is part of the QtGui module 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 either Technology Preview License Agreement or the
+;** Beta Release License Agreement.
+;**
+;** 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.0, included in the file LGPL_EXCEPTION.txt in this
+;** package.
+;**
+;** GNU General Public License Usage
+;** Alternatively, this file may be used under the terms of the GNU
+;** General Public License version 3.0 as published by the Free Software
+;** Foundation and appearing in the file LICENSE.GPL included in the
+;** packaging of this file. Please review the following information to
+;** ensure the GNU General Public License version 3.0 requirements will be
+;** met: http://www.gnu.org/copyleft/gpl.html.
+;**
+;** If you are unsure which license is appropriate for your use, please
+;** contact the sales department at qt-sales@nokia.com.
+;** $QT_END_LICENSE$
+;**
+;****************************************************************************/
+
+;
+; W A R N I N G
+; -------------
+;
+; This file is not part of the Qt API. It exists purely as an
+; implementation detail. This header file may change from version to
+; version without notice, or even be removed.
+;
+; We mean it.
+;
+
+ ARM
+ PRESERVE8
+
+ INCLUDE qdrawhelper_armv6_rvct.inc
+
+;-----------------------------------------------------------------------------
+; qt_memfill32_armv6
+;
+; @brief Not yet in use!
+;
+; @param dest Destination buffer (r0)
+; @param value Value (r1)
+; @param count Count (r2)
+;
+;---------------------------------------------------------------------------
+qt_memfill32_armv6 Function
+ stmfd sp!, {r4-r12, r14}
+
+ mov r3, r1
+ mov r4, r1
+ mov r5, r1
+ mov r6, r1
+ mov r7, r1
+ mov r8, r1
+ mov r9, r1
+
+mfill_loop
+ ; Fill 32 pixels per loop iteration
+ subs r2, r2, #32
+ stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+ stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+ stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+ stmgeia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+ bgt mfill_loop
+
+mfill_remaining
+
+ ; Fill up to 31 remaining pixels
+
+ ; Fill 16 pixels
+ tst r2, #16
+ stmneia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+ stmneia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+
+ ; Fill 8 pixels
+ tst r2, #8
+ stmneia r0!, {r1, r3, r4, r5, r6, r7, r8, r9}
+
+ ; Fill 4 pixels
+ tst r2, #4
+ stmneia r0!, {r1, r3, r4, r5}
+
+ ; Fill 2 pixels
+ tst r2, #2
+ stmneia r0!, {r1, r3}
+
+ ; Fill last one
+ tst r2, #1
+ strne r1, [r0]
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+;-----------------------------------------------------------------------------
+; comp_func_Source_arm
+;
+; @brief
+;
+; @param dest Destination buffer (r0)
+; @param src Source buffer (r1)
+; @param length Length (r2)
+; @param const_alpha Constant alpha (r3)
+;
+;---------------------------------------------------------------------------
+comp_func_Source_armv6 Function
+ stmfd sp!, {r4-r12, r14}
+
+ cmp r3, #255 ; if(r3 == 255)
+ bne src2 ; branch if not
+
+src1 PixCpy r0, r1, r2
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+src2
+ ;ldr r14, =ComponentHalf ; load 0x800080 to r14
+ mov r14, #0x800000
+ add r14, r14, #0x80
+
+src22 BlendRow PixelSourceConstAlpha
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+;-----------------------------------------------------------------------------
+; comp_func_SourceOver_arm
+;
+; @brief
+;
+; @param dest Destination buffer (r0)
+; @param src Source buffer (r1)
+; @param length Length (r2)
+; @param const_alpha Constant alpha (r3)
+;
+;---------------------------------------------------------------------------
+comp_func_SourceOver_armv6 Function
+ stmfd sp!, {r4-r12, r14}
+
+ ;ldr r14, =ComponentHalf ; load 0x800080 to r14
+ mov r14, #0x800000
+ add r14, r14, #0x80
+
+ cmp r3, #255 ; if(r3 == 255)
+ bne srcovr2 ; branch if not
+
+srcovr1 BlendRow PixelSourceOver
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+srcovr2
+
+srcovr22 BlendRow PixelSourceOverConstAlpha
+
+ ldmfd sp!, {r4-r12, pc} ; pop and return
+
+
+ END ; File end
+
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 7979716..75b39b7 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -87,7 +87,7 @@ QT_BEGIN_NAMESPACE
#if defined(Q_CC_RVCT)
// RVCT doesn't like static template functions
# define Q_STATIC_TEMPLATE_FUNCTION
-# define Q_STATIC_INLINE_FUNCTION inline
+# define Q_STATIC_INLINE_FUNCTION static __forceinline
#else
# define Q_STATIC_TEMPLATE_FUNCTION static
# define Q_STATIC_INLINE_FUNCTION static inline
@@ -301,19 +301,23 @@ struct QSpanData
};
-static inline uint BYTE_MUL_RGB16(uint x, uint a) {
+Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16(uint x, uint a) {
a += 1;
uint t = (((x & 0x07e0)*a) >> 8) & 0x07e0;
t |= (((x & 0xf81f)*(a>>2)) >> 6) & 0xf81f;
return t;
}
-static inline uint BYTE_MUL_RGB16_32(uint x, uint a) {
+Q_STATIC_INLINE_FUNCTION uint BYTE_MUL_RGB16_32(uint x, uint a) {
uint t = (((x & 0xf81f07e0) >> 5)*a) & 0xf81f07e0;
t |= (((x & 0x07e0f81f)*a) >> 5) & 0x07e0f81f;
return t;
}
+#if defined(Q_CC_RVCT)
+# pragma push
+# pragma arm
+#endif
Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) {
uint t = (x & 0xff00ff) * a;
t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
@@ -325,8 +329,11 @@ Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) {
x |= t;
return x;
}
+#if defined(Q_CC_RVCT)
+# pragma pop
+#endif
-static inline uint PREMUL(uint x) {
+Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) {
uint a = x >> 24;
uint t = (x & 0xff00ff) * a;
t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
@@ -391,7 +398,7 @@ public:
return qt_colorConvert<quint16, quint32>(data, 0);
}
- static inline quint32p fromRawData(quint32 v)
+ Q_STATIC_INLINE_FUNCTION quint32p fromRawData(quint32 v)
{
quint32p p;
p.data = v;
@@ -422,7 +429,7 @@ class qrgb565;
class qargb8565
{
public:
- static inline bool hasAlpha() { return true; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; }
inline qargb8565() {}
inline qargb8565(quint32 v);
@@ -439,8 +446,8 @@ public:
data[1] &= 0xdf;
return *this;
}
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; }
- static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
inline qargb8565 byte_mul(quint8 a) const;
inline qargb8565 operator+(qargb8565 v) const;
@@ -458,7 +465,7 @@ private:
class qrgb565
{
public:
- static inline bool hasAlpha() { return false; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; }
qrgb565(int v = 0) : data(v) {}
@@ -473,8 +480,8 @@ public:
inline quint8 alpha() const { return 0xff; }
inline qrgb565 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; }
- static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
inline qrgb565 byte_mul(quint8 a) const;
@@ -654,7 +661,7 @@ class qrgb555;
class qargb8555
{
public:
- static inline bool hasAlpha() { return true; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; }
qargb8555() {}
inline qargb8555(quint32 v);
@@ -666,8 +673,8 @@ public:
inline quint8 alpha() const { return data[0]; }
inline qargb8555 truncedAlpha() { data[0] &= 0xf8; return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; }
- static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
inline qargb8555 operator+(qargb8555 v) const;
inline qargb8555 byte_mul(quint8 a) const;
@@ -684,7 +691,7 @@ private:
class qrgb555
{
public:
- static inline bool hasAlpha() { return false; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; }
inline qrgb555(int v = 0) : data(v) {}
@@ -733,8 +740,8 @@ public:
inline quint8 alpha() const { return 0xff; }
inline qrgb555 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 3; }
- static inline quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 3; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x20 - alpha(a); }
inline bool operator==(const qrgb555 &v) const { return v.data == data; }
inline bool operator!=(const qrgb555 &v) const { return v.data != data; }
@@ -882,7 +889,7 @@ class qrgb666;
class qargb6666
{
public:
- static inline bool hasAlpha() { return true; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; }
inline qargb6666() {}
inline qargb6666(quint32 v) { *this = qargb6666(quint32p(v)); }
@@ -894,8 +901,8 @@ public:
inline quint8 alpha() const;
inline qargb6666 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 2; }
- static inline quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 2; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; }
inline qargb6666 byte_mul(quint8 a) const;
inline qargb6666 operator+(qargb6666 v) const;
@@ -912,7 +919,7 @@ private:
class qrgb666
{
public:
- static inline bool hasAlpha() { return false; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; }
inline qrgb666() {}
inline qrgb666(quint32 v);
@@ -922,8 +929,8 @@ public:
inline quint8 alpha() const { return 0xff; }
inline qrgb666 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 2; }
- static inline quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 2; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return (255 - a + 1) >> 2; }
inline qrgb666 operator+(qrgb666 v) const;
inline qrgb666 byte_mul(quint8 a) const;
@@ -1080,7 +1087,7 @@ quint32 qargb6666::rawValue() const
class qrgb888
{
public:
- static inline bool hasAlpha() { return false; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; }
inline qrgb888() {}
inline qrgb888(quint32 v);
@@ -1089,8 +1096,8 @@ public:
inline quint8 alpha() const { return 0xff; }
inline qrgb888 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return a; }
- static inline quint8 ialpha(quint8 a) { return 255 - a; }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return a; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 255 - a; }
inline qrgb888 byte_mul(quint8 a) const;
inline qrgb888 operator+(qrgb888 v) const;
@@ -1269,7 +1276,7 @@ class qrgb444;
class qargb4444
{
public:
- static inline bool hasAlpha() { return true; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return true; }
inline qargb4444() {}
inline qargb4444(quint32 v) { *this = qargb4444(quint32p(v)); }
@@ -1283,8 +1290,8 @@ public:
inline quint8 alpha() const { return ((data & 0xf000) >> 8) | ((data & 0xf000) >> 12); }
inline qargb4444 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 4; }
- static inline quint8 ialpha(quint8 a) { return 0x10 - alpha(a); }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 4; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x10 - alpha(a); }
inline qargb4444 byte_mul(quint8 a) const;
inline bool operator==(const qargb4444 &v) const { return data == v.data; }
@@ -1300,7 +1307,7 @@ private:
class qrgb444
{
public:
- static inline bool hasAlpha() { return false; }
+ Q_STATIC_INLINE_FUNCTION bool hasAlpha() { return false; }
inline qrgb444() {}
inline qrgb444(quint32 v);
@@ -1312,8 +1319,8 @@ public:
inline qrgb444 operator+(qrgb444 v) const;
inline quint8 alpha() const { return 0xff; }
inline qrgb444 truncedAlpha() { return *this; }
- static inline quint8 alpha(quint8 a) { return (a + 1) >> 4; }
- static inline quint8 ialpha(quint8 a) { return 0x10 - alpha(a); }
+ Q_STATIC_INLINE_FUNCTION quint8 alpha(quint8 a) { return (a + 1) >> 4; }
+ Q_STATIC_INLINE_FUNCTION quint8 ialpha(quint8 a) { return 0x10 - alpha(a); }
inline qrgb444 byte_mul(quint8 a) const;
inline bool operator==(const qrgb444 &v) const { return data == v.data; }
@@ -1774,7 +1781,14 @@ do { \
} \
} while (0)
+#if defined(Q_CC_RVCT)
+# pragma push
+# pragma arm
+#endif
Q_STATIC_INLINE_FUNCTION int qt_div_255(int x) { return (x + (x>>8) + 0x80) >> 8; }
+#if defined(Q_CC_RVCT)
+# pragma pop
+#endif
inline ushort qConvertRgb32To16(uint c)
{
@@ -1817,7 +1831,7 @@ inline int qBlue565(quint16 rgb) {
}
#if 1
-static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
+Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
t >>= 8;
t &= 0xff00ff;
@@ -1828,7 +1842,11 @@ static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
return x;
}
-static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
+#if defined(Q_CC_RVCT)
+# pragma push
+# pragma arm
+#endif
+Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
uint t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
t &= 0xff00ff;
@@ -1839,9 +1857,12 @@ static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
x |= t;
return x;
}
+#if defined(Q_CC_RVCT)
+# pragma pop
+#endif
#else
// possible implementation for 64 bit
-static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
+Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
t += (((ulong(y)) | ((ulong(y)) << 24)) & 0x00ff00ff00ff00ff) * b;
t >>= 8;
@@ -1849,7 +1870,7 @@ static inline uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b) {
return (uint(t)) | (uint(t >> 24));
}
-static inline uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
+Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_255(uint x, uint a, uint y, uint b) {
ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
t += (((ulong(y)) | ((ulong(y)) << 24)) & 0x00ff00ff00ff00ff) * b;
t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080);
@@ -1864,7 +1885,7 @@ Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a) {
return (uint(t)) | (uint(t >> 24));
}
-static inline uint PREMUL(uint x) {
+Q_STATIC_INLINE_FUNCTION uint PREMUL(uint x) {
uint a = x >> 24;
ulong t = (((ulong(x)) | ((ulong(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080);
diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp
index 2a99f16..d4c7a65 100644
--- a/src/gui/painting/qgraphicssystem.cpp
+++ b/src/gui/painting/qgraphicssystem.cpp
@@ -44,7 +44,7 @@
#ifdef Q_WS_X11
# include <private/qpixmap_x11_p.h>
#endif
-#ifdef Q_WS_WIN
+#if defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
# include <private/qpixmap_raster_p.h>
#endif
#ifdef Q_WS_MAC
@@ -64,7 +64,7 @@ QPixmapData *QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixelType typ
#endif
#if defined(Q_WS_X11)
return new QX11PixmapData(type);
-#elif defined(Q_WS_WIN)
+#elif defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
return new QRasterPixmapData(type);
#elif defined(Q_WS_MAC)
return new QMacPixmapData(type);
diff --git a/src/gui/painting/qgraphicssystemfactory.cpp b/src/gui/painting/qgraphicssystemfactory.cpp
index ddc66f3..bf186e6 100644
--- a/src/gui/painting/qgraphicssystemfactory.cpp
+++ b/src/gui/painting/qgraphicssystemfactory.cpp
@@ -68,7 +68,7 @@ QGraphicsSystem *QGraphicsSystemFactory::create(const QString& key)
if (system.isEmpty()) {
system = QLatin1String("openvg");
}
-#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN)
+#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) && !defined(Q_OS_SYMBIAN)
if (system.isEmpty()) {
system = QLatin1String("raster");
}
diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c
index 7a9eda3..888fd9a 100644
--- a/src/gui/painting/qgrayraster.c
+++ b/src/gui/painting/qgrayraster.c
@@ -158,7 +158,12 @@
#include <private/qrasterdefs_p.h>
#include <private/qgrayraster_p.h>
+// Bug in stdlib.h, see more information from fixed_stdlib.h
+#if (defined __SYMBIAN32__ && !defined __cplusplus)
+#include <fixed_stdlib.h>
+#else
#include <stdlib.h>
+#endif // defined __SYMBIAN32__ && !defined __cplusplus
#include <stdio.h>
/* This macro is used to indicate that a function parameter is unused. */
diff --git a/src/gui/painting/qpaintdevice_s60.cpp b/src/gui/painting/qpaintdevice_s60.cpp
new file mode 100644
index 0000000..a2c4499
--- /dev/null
+++ b/src/gui/painting/qpaintdevice_s60.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpaintdevice.h"
+#include "qpainter.h"
+#include "qwidget.h"
+#include "qbitmap.h"
+#include "qapplication.h"
+#include <private/qapplication_p.h>
+#include "qprinter.h"
+
+QT_BEGIN_NAMESPACE
+
+QPaintDevice::QPaintDevice()
+{
+ painters = 0;
+}
+
+
+QPaintDevice::~QPaintDevice()
+{
+ if (paintingActive())
+ qWarning("QPaintDevice: Cannot destroy paint device that is being "
+ "painted. Be sure to QPainter::end() painters!");
+}
+
+int QPaintDevice::metric(PaintDeviceMetric) const
+{
+ qWarning("QPaintDevice::metrics: Device has no metric information");
+ return 0;
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index 4fb1832..5565146 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -717,7 +717,6 @@ QPaintEngine::QPaintEngine(QPaintEnginePrivate &dptr, PaintEngineFeatures caps)
*/
QPaintEngine::~QPaintEngine()
{
- delete d_ptr;
}
/*!
diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h
index 57c9e2d..92aa506 100644
--- a/src/gui/painting/qpaintengine.h
+++ b/src/gui/painting/qpaintengine.h
@@ -44,6 +44,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qobjectdefs.h>
+#include <QtCore/qscopedpointer.h>
#include <QtGui/qpainter.h>
QT_BEGIN_HEADER
@@ -239,7 +240,7 @@ protected:
uint selfDestruct : 1;
uint extended : 1;
- QPaintEnginePrivate *d_ptr;
+ QScopedPointer<QPaintEnginePrivate> d_ptr;
private:
void setAutoDestruct(bool autoDestr) { selfDestruct = autoDestr; }
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index e9ff752..2febdfa 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -91,6 +91,8 @@
# include <private/qfontengine_qpf_p.h>
# endif
# include <private/qabstractfontengine_p.h>
+#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
+# include <private/qfontengine_s60_p.h>
#endif
#if defined(Q_WS_WIN64)
@@ -342,6 +344,7 @@ void QRasterPaintEngine::init()
#else
(unsigned char *) malloc(d->rasterPoolSize);
#endif
+ Q_CHECK_PTR(d->rasterPoolBase);
// The antialiasing raster.
d->grayRaster = new QT_FT_Raster;
@@ -3224,7 +3227,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
ensurePen();
ensureState();
-#if defined (Q_WS_WIN) || defined(Q_WS_MAC)
+#if defined (Q_WS_WIN) || defined(Q_WS_MAC) || (defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE))
bool drawCached = true;
@@ -3257,7 +3260,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
return;
}
-#else // Q_WS_WIN || Q_WS_MAC
+#else // Q_WS_WIN || Q_WS_MAC || Q_OS_SYMBIAN && QT_NO_FREETYPE
QFontEngine *fontEngine = ti.fontEngine;
@@ -3277,7 +3280,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
}
#endif // Q_WS_QWS
-#if (defined(Q_WS_X11) || defined(Q_WS_QWS)) && !defined(QT_NO_FREETYPE)
+#if (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2)
if (fontEngine->type() == QFontEngine::QPF2) {
@@ -3942,7 +3945,7 @@ static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *r
// find required length
int max = qMax(c1_spans[c1_count - 1].x + c1_spans[c1_count - 1].len,
- c2_spans[c2_count - 1].x + c2_spans[c2_count - 1].len);
+ c2_spans[c2_count - 1].x + c2_spans[c2_count - 1].len);
buffer.resize(max);
memset(buffer.data(), 0, buffer.size() * sizeof(short));
@@ -4104,6 +4107,7 @@ void QRasterPaintEnginePrivate::rasterize(QT_FT_Outline *outline,
#else
(unsigned char *) malloc(rasterPoolSize);
#endif
+ Q_CHECK_PTR(rasterPoolBase); // note: we just freed the old rasterPoolBase. I hope it's not fatal.
qt_ft_grays_raster.raster_done(*grayRaster);
qt_ft_grays_raster.raster_new(0, grayRaster);
@@ -4226,8 +4230,14 @@ int QCustomRasterPaintDevice::bytesPerLine() const
{
return (width() * depth() + 7) / 8;
}
-#endif // Q_WS_QWS
+#elif defined(Q_OS_SYMBIAN)
+
+void QRasterBuffer::prepareBuffer(int /* width */, int /* height */)
+{
+}
+
+#endif // Q_OS_SYMBIAN
/*!
\class QCustomRasterPaintDevice
@@ -4335,95 +4345,109 @@ void QClipData::initialize()
if (!m_clipLines)
m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight);
- m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan));
- allocated = clipSpanHeight;
-
- if (hasRectClip) {
- int y = 0;
- while (y < ymin) {
- m_clipLines[y].spans = 0;
- m_clipLines[y].count = 0;
- ++y;
- }
-
- const int len = clipRect.width();
- count = 0;
- while (y < ymax) {
- QSpan *span = m_spans + count;
- span->x = xmin;
- span->len = len;
- span->y = y;
- span->coverage = 255;
- ++count;
-
- m_clipLines[y].spans = span;
- m_clipLines[y].count = 1;
- ++y;
- }
+ Q_CHECK_PTR(m_clipLines);
+ QT_TRY {
+ m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan));
+ allocated = clipSpanHeight;
+ Q_CHECK_PTR(m_spans);
+
+ QT_TRY {
+ if (hasRectClip) {
+ int y = 0;
+ while (y < ymin) {
+ m_clipLines[y].spans = 0;
+ m_clipLines[y].count = 0;
+ ++y;
+ }
- while (y < clipSpanHeight) {
- m_clipLines[y].spans = 0;
- m_clipLines[y].count = 0;
- ++y;
- }
- } else if (hasRegionClip) {
+ const int len = clipRect.width();
+ count = 0;
+ while (y < ymax) {
+ QSpan *span = m_spans + count;
+ span->x = xmin;
+ span->len = len;
+ span->y = y;
+ span->coverage = 255;
+ ++count;
- const QVector<QRect> rects = clipRegion.rects();
- const int numRects = rects.size();
+ m_clipLines[y].spans = span;
+ m_clipLines[y].count = 1;
+ ++y;
+ }
- { // resize
- const int maxSpans = (ymax - ymin) * numRects;
- if (maxSpans > allocated) {
- m_spans = (QSpan *)realloc(m_spans, maxSpans * sizeof(QSpan));
- allocated = maxSpans;
- }
- }
+ while (y < clipSpanHeight) {
+ m_clipLines[y].spans = 0;
+ m_clipLines[y].count = 0;
+ ++y;
+ }
+ } else if (hasRegionClip) {
+
+ const QVector<QRect> rects = clipRegion.rects();
+ const int numRects = rects.size();
+
+ { // resize
+ const int maxSpans = (ymax - ymin) * numRects;
+ if (maxSpans > allocated) {
+ QSpan *newSpans = (QSpan *)realloc(m_spans, maxSpans * sizeof(QSpan));
+ Q_CHECK_PTR(newSpans);
+ m_spans = newSpans;
+ allocated = maxSpans;
+ }
+ }
- int y = 0;
- int firstInBand = 0;
- count = 0;
- while (firstInBand < numRects) {
- const int currMinY = rects.at(firstInBand).y();
- const int currMaxY = currMinY + rects.at(firstInBand).height();
+ int y = 0;
+ int firstInBand = 0;
+ count = 0;
+ while (firstInBand < numRects) {
+ const int currMinY = rects.at(firstInBand).y();
+ const int currMaxY = currMinY + rects.at(firstInBand).height();
+
+ while (y < currMinY) {
+ m_clipLines[y].spans = 0;
+ m_clipLines[y].count = 0;
+ ++y;
+ }
- while (y < currMinY) {
- m_clipLines[y].spans = 0;
- m_clipLines[y].count = 0;
- ++y;
- }
+ int lastInBand = firstInBand;
+ while (lastInBand + 1 < numRects && rects.at(lastInBand+1).top() == y)
+ ++lastInBand;
- int lastInBand = firstInBand;
- while (lastInBand + 1 < numRects && rects.at(lastInBand+1).top() == y)
- ++lastInBand;
+ while (y < currMaxY) {
- while (y < currMaxY) {
+ m_clipLines[y].spans = m_spans + count;
+ m_clipLines[y].count = lastInBand - firstInBand + 1;
- m_clipLines[y].spans = m_spans + count;
- m_clipLines[y].count = lastInBand - firstInBand + 1;
+ for (int r = firstInBand; r <= lastInBand; ++r) {
+ const QRect &currRect = rects.at(r);
+ QSpan *span = m_spans + count;
+ span->x = currRect.x();
+ span->len = currRect.width();
+ span->y = y;
+ span->coverage = 255;
+ ++count;
+ }
+ ++y;
+ }
- for (int r = firstInBand; r <= lastInBand; ++r) {
- const QRect &currRect = rects.at(r);
- QSpan *span = m_spans + count;
- span->x = currRect.x();
- span->len = currRect.width();
- span->y = y;
- span->coverage = 255;
- ++count;
+ firstInBand = lastInBand + 1;
}
- ++y;
- }
- firstInBand = lastInBand + 1;
- }
+ Q_ASSERT(count <= allocated);
- Q_ASSERT(count <= allocated);
+ while (y < clipSpanHeight) {
+ m_clipLines[y].spans = 0;
+ m_clipLines[y].count = 0;
+ ++y;
+ }
- while (y < clipSpanHeight) {
- m_clipLines[y].spans = 0;
- m_clipLines[y].count = 0;
- ++y;
+ }
+ } QT_CATCH(...) {
+ free(m_spans);
+ QT_RETHROW;
}
-
+ } QT_CATCH(...) {
+ free(m_clipLines);
+ QT_RETHROW;
}
}
@@ -4698,8 +4722,10 @@ static void qt_span_clip(int count, const QSpan *spans, void *userData)
&newspans, newClip->allocated - newClip->count);
newClip->count = newspans - newClip->m_spans;
if (spans < end) {
+ QSpan *newSpan = (QSpan *)realloc(newClip->m_spans, newClip->allocated*2*sizeof(QSpan));
+ Q_CHECK_PTR(newSpan);
+ newClip->m_spans = newSpan;
newClip->allocated *= 2;
- newClip->m_spans = (QSpan *)realloc(newClip->m_spans, newClip->allocated*sizeof(QSpan));
}
}
}
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index a4db284..2fc23f9 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -144,8 +144,7 @@ void QPaintEngineExPrivate::replayClipOperations()
if (!p || !p->d_ptr)
return;
- QPainterPrivate *pp = p->d_ptr;
- QList<QPainterClipInfo> clipInfo = pp->state->clipInfo;
+ QList<QPainterClipInfo> clipInfo = p->d_ptr->state->clipInfo;
QTransform transform = q->state()->matrix;
@@ -196,8 +195,7 @@ bool QPaintEngineExPrivate::hasClipOperations() const
if (!p || !p->d_ptr)
return false;
- QPainterPrivate *pp = p->d_ptr;
- QList<QPainterClipInfo> clipInfo = pp->state->clipInfo;
+ QList<QPainterClipInfo> clipInfo = p->d_ptr->state->clipInfo;
return !clipInfo.isEmpty();
}
diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h
index d4e4862..2a50a51 100644
--- a/src/gui/painting/qpaintengineex_p.h
+++ b/src/gui/painting/qpaintengineex_p.h
@@ -55,10 +55,10 @@
#include <QtGui/qpaintengine.h>
-#include "qpaintengine_p.h"
-#include "qstroker_p.h"
-#include "qpainter_p.h"
-#include "qvectorpath_p.h"
+#include <private/qpaintengine_p.h>
+#include <private/qstroker_p.h>
+#include <private/qpainter_p.h>
+#include <private/qvectorpath_p.h>
QT_BEGIN_HEADER
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 34305c2..8738f54 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -75,14 +75,26 @@ QT_BEGIN_NAMESPACE
#define QGradient_StretchToDevice 0x10000000
#define QPaintEngine_OpaqueBackground 0x40000000
-// use the same rounding as in qrasterizer.cpp (6 bit fixed point)
-static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
-
// #define QT_DEBUG_DRAW
#ifdef QT_DEBUG_DRAW
bool qt_show_painter_debug_output = true;
#endif
+class QPainterPrivateCleaner
+{
+public:
+ static inline void cleanup(QPainterPrivate *d)
+ {
+ delete d;
+ }
+
+ static inline void reset(QPainterPrivate *&d, QPainterPrivate *other)
+ {
+ delete d;
+ d = other;
+ }
+};
+
extern QPixmap qt_pixmapForBrush(int style, bool invert);
void qt_format_text(const QFont &font,
@@ -259,14 +271,17 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
// in 99% of all cases). E.g: A renders B which renders C which renders D.
sp->d_ptr->d_ptrs_size = 4;
sp->d_ptr->d_ptrs = (QPainterPrivate **)malloc(4 * sizeof(QPainterPrivate *));
+ Q_CHECK_PTR(sp->d_ptr->d_ptrs);
} else if (sp->d_ptr->refcount - 1 == sp->d_ptr->d_ptrs_size) {
// However, to support corner cases we grow the array dynamically if needed.
sp->d_ptr->d_ptrs_size <<= 1;
const int newSize = sp->d_ptr->d_ptrs_size * sizeof(QPainterPrivate *);
- sp->d_ptr->d_ptrs = (QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize);
+ QPainterPrivate ** newPointers = (QPainterPrivate **)realloc(sp->d_ptr->d_ptrs, newSize);
+ Q_CHECK_PTR(newPointers);
+ sp->d_ptr->d_ptrs = newPointers;
}
- sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr;
- q->d_ptr = sp->d_ptr;
+ sp->d_ptr->d_ptrs[++sp->d_ptr->refcount - 2] = q->d_ptr.data();
+ q->d_ptr.data_ptr() = sp->d_ptr.data();
Q_ASSERT(q->d_ptr->state);
@@ -319,7 +334,7 @@ void QPainterPrivate::detachPainterPrivate(QPainter *q)
d_ptrs[refcount - 1] = 0;
q->restore();
- q->d_ptr = original;
+ q->d_ptr.data_ptr() = original;
if (emulationEngine) {
extended = emulationEngine->real_engine;
@@ -1354,8 +1369,8 @@ void QPainterPrivate::updateState(QPainterState *newState)
*/
QPainter::QPainter()
+ : d_ptr(new QPainterPrivate(this))
{
- d_ptr = new QPainterPrivate(this);
}
/*!
@@ -1387,7 +1402,7 @@ QPainter::QPainter(QPaintDevice *pd)
{
Q_ASSERT(pd != 0);
if (!QPainterPrivate::attachPainterPrivate(this, pd)) {
- d_ptr = new QPainterPrivate(this);
+ d_ptr.reset(new QPainterPrivate(this));
begin(pd);
}
Q_ASSERT(d_ptr);
@@ -1399,11 +1414,14 @@ QPainter::QPainter(QPaintDevice *pd)
QPainter::~QPainter()
{
d_ptr->inDestructor = true;
- if (isActive())
- end();
- else if (d_ptr->refcount > 1)
- d_ptr->detachPainterPrivate(this);
-
+ QT_TRY {
+ if (isActive())
+ end();
+ else if (d_ptr->refcount > 1)
+ d_ptr->detachPainterPrivate(this);
+ } QT_CATCH(...) {
+ // don't throw anything in the destructor.
+ }
if (d_ptr) {
// Make sure we haven't messed things up.
Q_ASSERT(d_ptr->inDestructor);
@@ -1411,7 +1429,6 @@ QPainter::~QPainter()
Q_ASSERT(d_ptr->refcount == 1);
if (d_ptr->d_ptrs)
free(d_ptr->d_ptrs);
- delete d_ptr;
}
}
@@ -5679,7 +5696,6 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif
engine.justify(line);
}
QFixed x = QFixed::fromReal(p.x());
- QFixed ox = x;
for (int i = 0; i < nItems; ++i) {
int item = visualOrder[i];
@@ -7398,8 +7414,21 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
void qt_painter_removePaintDevice(QPaintDevice *dev)
{
- QMutexLocker locker(globalRedirectionsMutex());
- if(QPaintDeviceRedirectionList *redirections = globalRedirections()) {
+ QMutex *mutex = 0;
+ QT_TRY {
+ mutex = globalRedirectionsMutex();
+ } QT_CATCH(...) {
+ // ignore the missing mutex, since we could be called from
+ // a destructor, and destructors shall not throw
+ }
+ QMutexLocker locker(mutex);
+ QPaintDeviceRedirectionList *redirections = 0;
+ QT_TRY {
+ redirections = globalRedirections();
+ } QT_CATCH(...) {
+ // do nothing - code below is safe with redirections being 0.
+ }
+ if (redirections) {
for (int i = 0; i < redirections->size(); ) {
if(redirections->at(i) == dev || redirections->at(i).replacement == dev)
redirections->removeAt(i);
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index e9c35ee..c81f5d4 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -45,6 +45,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qrect.h>
#include <QtCore/qpoint.h>
+#include <QtCore/qscopedpointer.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qimage.h>
#include <QtGui/qtextoption.h>
@@ -78,6 +79,8 @@ class QTextItem;
class QMatrix;
class QTransform;
+class QPainterPrivateCleaner;
+
class Q_GUI_EXPORT QPainter
{
Q_DECLARE_PRIVATE(QPainter)
@@ -497,7 +500,7 @@ private:
Q_DISABLE_COPY(QPainter)
friend class Q3Painter;
- QPainterPrivate *d_ptr;
+ QScopedCustomPointer<QPainterPrivate, QPainterPrivateCleaner> d_ptr;
friend class QFontEngine;
friend class QFontEngineBox;
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index 8e9d61e..4364772 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -63,7 +63,7 @@
#include "QtGui/qpaintengine.h"
#include <QtCore/qhash.h>
-#include "qpen_p.h"
+#include <private/qpen_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 027d5c8..ec8a46c 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -73,6 +73,24 @@
QT_BEGIN_NAMESPACE
+struct QPainterPathPrivateHandler
+{
+ static inline void cleanup(QPainterPathPrivate *d)
+ {
+ // note - we must up-cast to QPainterPathData since QPainterPathPrivate
+ // has a non-virtual destructor!
+ if (d && !d->ref.deref())
+ delete static_cast<QPainterPathData *>(d);
+ }
+
+ static inline void reset(QPainterPathPrivate *&d, QPainterPathPrivate *other)
+ {
+ QPainterPathPrivate *oldD = d;
+ d = other;
+ cleanup(oldD);
+ }
+};
+
// This value is used to determine the length of control point vectors
// when approximating arc segments as curves. The factor is multiplied
// with the radius of the circle.
@@ -506,10 +524,10 @@ QPainterPath::QPainterPath()
\sa operator=()
*/
QPainterPath::QPainterPath(const QPainterPath &other)
- : d_ptr(other.d_ptr)
+ : d_ptr(other.d_ptr.data())
{
- if (d_func())
- d_func()->ref.ref();
+ if (d_ptr)
+ d_ptr->ref.ref();
}
/*!
@@ -530,9 +548,7 @@ QPainterPath::QPainterPath(const QPointF &startPoint)
void QPainterPath::detach_helper()
{
QPainterPathPrivate *data = new QPainterPathData(*d_func());
- if (d_ptr && !d_ptr->ref.deref())
- delete d_ptr;
- d_ptr = data;
+ d_ptr.reset(data);
}
/*!
@@ -544,9 +560,7 @@ void QPainterPath::ensureData_helper()
data->elements.reserve(16);
QPainterPath::Element e = { 0, 0, QPainterPath::MoveToElement };
data->elements << e;
- if (d_ptr && !d_ptr->ref.deref())
- delete d_ptr;
- d_ptr = data;
+ d_ptr.reset(data);
Q_ASSERT(d_ptr != 0);
}
@@ -563,9 +577,7 @@ QPainterPath &QPainterPath::operator=(const QPainterPath &other)
QPainterPathPrivate *data = other.d_func();
if (data)
data->ref.ref();
- if (d_ptr && !d_ptr->ref.deref())
- delete d_ptr;
- d_ptr = data;
+ d_ptr.reset(data);
}
return *this;
}
@@ -575,8 +587,6 @@ QPainterPath &QPainterPath::operator=(const QPainterPath &other)
*/
QPainterPath::~QPainterPath()
{
- if (d_func() && !d_func()->ref.deref())
- delete d_func();
}
/*!
@@ -2464,7 +2474,6 @@ QPainterPathStroker::QPainterPathStroker()
*/
QPainterPathStroker::~QPainterPathStroker()
{
- delete d_ptr;
}
diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h
index 846bd8a..5068739 100644
--- a/src/gui/painting/qpainterpath.h
+++ b/src/gui/painting/qpainterpath.h
@@ -47,6 +47,7 @@
#include <QtCore/qrect.h>
#include <QtCore/qline.h>
#include <QtCore/qvector.h>
+#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
@@ -56,6 +57,7 @@ QT_MODULE(Gui)
class QFont;
class QPainterPathPrivate;
+struct QPainterPathPrivateHandler;
class QPainterPathData;
class QPainterPathStrokerPrivate;
class QPolygonF;
@@ -201,7 +203,7 @@ public:
QPainterPath &operator-=(const QPainterPath &other);
private:
- QPainterPathPrivate *d_ptr;
+ QScopedCustomPointer<QPainterPathPrivate, QPainterPathPrivateHandler> d_ptr;
inline void ensureData() { if (!d_ptr) ensureData_helper(); }
void ensureData_helper();
@@ -211,7 +213,7 @@ private:
void computeBoundingRect() const;
void computeControlPointRect() const;
- QPainterPathData *d_func() const { return reinterpret_cast<QPainterPathData *>(d_ptr); }
+ QPainterPathData *d_func() const { return reinterpret_cast<QPainterPathData *>(d_ptr.data()); }
friend class QPainterPathData;
friend class QPainterPathStroker;
@@ -235,6 +237,7 @@ public:
friend class QPainterPathStrokerPrivate;
friend class QMatrix;
friend class QTransform;
+ friend struct QPainterPathPrivateHandler;
#ifndef QT_NO_DATASTREAM
friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QPainterPath &);
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPainterPath &);
@@ -285,7 +288,7 @@ public:
private:
friend class QX11PaintEngine;
- QPainterPathStrokerPrivate *d_ptr;
+ QScopedPointer<QPainterPathStrokerPrivate> d_ptr;
};
inline void QPainterPath::moveTo(qreal x, qreal y)
diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h
index b2ab3b4..784b75d 100644
--- a/src/gui/painting/qpathclipper_p.h
+++ b/src/gui/painting/qpathclipper_p.h
@@ -160,8 +160,6 @@ public:
Direction directionTo(int vertex) const;
int vertex(Direction direction) const;
- bool isBezier() const;
-
private:
int m_next[2][2];
};
@@ -347,11 +345,6 @@ inline int QPathEdge::vertex(Direction direction) const
return direction == Backward ? first : second;
}
-inline bool QPathEdge::isBezier() const
-{
- return bezier >= 0;
-}
-
inline QPathVertex::QPathVertex(const QPointF &p, int e)
: edge(e)
, x(p.x())
diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp
index 411b74d..efaeb43 100644
--- a/src/gui/painting/qprinter.cpp
+++ b/src/gui/painting/qprinter.cpp
@@ -712,7 +712,6 @@ QPrinter::~QPrinter()
#ifndef QT_NO_PRINTPREVIEWWIDGET
delete d->previewEngine;
#endif
- delete d;
}
/*!
diff --git a/src/gui/painting/qprinter.h b/src/gui/painting/qprinter.h
index 90ed20d..25c2f0c 100644
--- a/src/gui/painting/qprinter.h
+++ b/src/gui/painting/qprinter.h
@@ -42,8 +42,9 @@
#ifndef QPRINTER_H
#define QPRINTER_H
-#include <QtGui/qpaintdevice.h>
#include <QtCore/qstring.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtGui/qpaintdevice.h>
QT_BEGIN_HEADER
@@ -288,7 +289,7 @@ private:
Q_DISABLE_COPY(QPrinter)
- QPrinterPrivate *d_ptr;
+ QScopedPointer<QPrinterPrivate> d_ptr;
friend class QPrintDialogPrivate;
friend class QAbstractPrintDialog;
diff --git a/src/gui/painting/qprinterinfo.h b/src/gui/painting/qprinterinfo.h
index eafdec5..c34e591 100644
--- a/src/gui/painting/qprinterinfo.h
+++ b/src/gui/painting/qprinterinfo.h
@@ -53,6 +53,7 @@ QT_MODULE(Gui)
#ifndef QT_NO_PRINTER
class QPrinterInfoPrivate;
+class QPrinterInfoPrivateCleanup;
class Q_GUI_EXPORT QPrinterInfo
{
Q_DECLARE_PRIVATE(QPrinterInfo)
@@ -76,7 +77,7 @@ public:
private:
QPrinterInfo(const QString& name);
- QPrinterInfoPrivate* d_ptr;
+ QScopedCustomPointer<QPrinterInfoPrivate, QPrinterInfoPrivateCleanup> d_ptr;
};
#endif // QT_NO_PRINTER
diff --git a/src/gui/painting/qprinterinfo_mac.cpp b/src/gui/painting/qprinterinfo_mac.cpp
index c84271c..6932015 100644
--- a/src/gui/painting/qprinterinfo_mac.cpp
+++ b/src/gui/painting/qprinterinfo_mac.cpp
@@ -65,6 +65,22 @@ private:
static QPrinterInfoPrivate nullQPrinterInfoPrivate;
+class QPrinterInfoPrivateCleanup
+{
+public:
+ static inline void cleanup(QPrinterInfoPrivate *d)
+ {
+ if (d != &nullQPrinterInfoPrivate)
+ delete d;
+ }
+
+ static inline void reset(QPrinterInfoPrivate *&d, QPrinterInfoPrivate *other)
+ {
+ cleanup(d);
+ d = other;
+ }
+};
+
extern QPrinter::PaperSize qSizeFTopaperSize(const QSizeF& size);
/////////////////////////////////////////////////////////////////////////////
@@ -106,8 +122,8 @@ QPrinterInfo QPrinterInfo::defaultPrinter(){
/////////////////////////////////////////////////////////////////////////////
QPrinterInfo::QPrinterInfo(const QPrinter& prn)
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
QList<QPrinterInfo> list = availablePrinters();
for (int c = 0; c < list.size(); ++c) {
if (prn.printerName() == list[c].printerName()) {
@@ -115,39 +131,33 @@ QPrinterInfo::QPrinterInfo(const QPrinter& prn)
return;
}
}
-
- *this = QPrinterInfo();
}
QPrinterInfo::~QPrinterInfo()
{
- if (d_ptr != &nullQPrinterInfoPrivate)
- delete d_ptr;
}
QPrinterInfo::QPrinterInfo()
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
}
QPrinterInfo::QPrinterInfo(const QString& name)
+ : d_ptr(new QPrinterInfoPrivate(name))
{
- d_ptr = new QPrinterInfoPrivate(name);
d_ptr->q_ptr = this;
}
QPrinterInfo::QPrinterInfo(const QPrinterInfo& src)
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
*this = src;
}
QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src)
{
Q_ASSERT(d_ptr);
- if (d_ptr != &nullQPrinterInfoPrivate)
- delete d_ptr;
- d_ptr = new QPrinterInfoPrivate(*src.d_ptr);
+ d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr));
d_ptr->q_ptr = this;
return *this;
}
diff --git a/src/gui/painting/qprinterinfo_unix.cpp b/src/gui/painting/qprinterinfo_unix.cpp
index 1ce5e1e..b9f1f3b 100644
--- a/src/gui/painting/qprinterinfo_unix.cpp
+++ b/src/gui/painting/qprinterinfo_unix.cpp
@@ -82,6 +82,22 @@ private:
static QPrinterInfoPrivate nullQPrinterInfoPrivate;
+class QPrinterInfoPrivateCleanup
+{
+public:
+ static inline void cleanup(QPrinterInfoPrivate *d)
+ {
+ if (d != &nullQPrinterInfoPrivate)
+ delete d;
+ }
+
+ static inline void reset(QPrinterInfoPrivate *&d, QPrinterInfoPrivate *other)
+ {
+ cleanup(d);
+ d = other;
+ }
+};
+
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
@@ -867,19 +883,19 @@ QPrinterInfo QPrinterInfo::defaultPrinter()
}
QPrinterInfo::QPrinterInfo()
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
}
QPrinterInfo::QPrinterInfo(const QPrinterInfo& src)
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
*this = src;
}
QPrinterInfo::QPrinterInfo(const QPrinter& printer)
+ : d_ptr(new QPrinterInfoPrivate(printer.printerName()))
{
- d_ptr = new QPrinterInfoPrivate(printer.printerName());
Q_D(QPrinterInfo);
d->q_ptr = this;
@@ -929,28 +945,23 @@ QPrinterInfo::QPrinterInfo(const QPrinter& printer)
#endif
// Printer not found.
- delete d;
- d_ptr = &nullQPrinterInfoPrivate;
+ d_ptr.reset(&nullQPrinterInfoPrivate);
}
QPrinterInfo::QPrinterInfo(const QString& name)
+ : d_ptr(new QPrinterInfoPrivate(name))
{
- d_ptr = new QPrinterInfoPrivate(name);
d_ptr->q_ptr = this;
}
QPrinterInfo::~QPrinterInfo()
{
- if (d_ptr != &nullQPrinterInfoPrivate)
- delete d_ptr;
}
QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src)
{
Q_ASSERT(d_ptr);
- if (d_ptr != &nullQPrinterInfoPrivate)
- delete d_ptr;
- d_ptr = new QPrinterInfoPrivate(*src.d_ptr);
+ d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr));
d_ptr->q_ptr = this;
return *this;
}
diff --git a/src/gui/painting/qprinterinfo_win.cpp b/src/gui/painting/qprinterinfo_win.cpp
index bea2e3a..4a92d30 100644
--- a/src/gui/painting/qprinterinfo_win.cpp
+++ b/src/gui/painting/qprinterinfo_win.cpp
@@ -69,6 +69,22 @@ private:
static QPrinterInfoPrivate nullQPrinterInfoPrivate;
+class QPrinterInfoPrivateCleanup
+{
+public:
+ static inline void cleanup(QPrinterInfoPrivate *d)
+ {
+ if (d != &nullQPrinterInfoPrivate)
+ delete d;
+ }
+
+ static inline void reset(QPrinterInfoPrivate *&d, QPrinterInfoPrivate *other)
+ {
+ cleanup(d);
+ d = other;
+ }
+};
+
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
@@ -125,25 +141,25 @@ QPrinterInfo QPrinterInfo::defaultPrinter()
/////////////////////////////////////////////////////////////////////////////
QPrinterInfo::QPrinterInfo()
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
}
QPrinterInfo::QPrinterInfo(const QString& name)
+ : d_ptr(new QPrinterInfoPrivate(name))
{
- d_ptr = new QPrinterInfoPrivate(name);
d_ptr->q_ptr = this;
}
QPrinterInfo::QPrinterInfo(const QPrinterInfo& src)
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
*this = src;
}
QPrinterInfo::QPrinterInfo(const QPrinter& prn)
+ : d_ptr(&nullQPrinterInfoPrivate)
{
- d_ptr = &nullQPrinterInfoPrivate;
QList<QPrinterInfo> list = availablePrinters();
for (int c = 0; c < list.size(); ++c) {
if (prn.printerName() == list[c].printerName()) {
@@ -157,16 +173,12 @@ QPrinterInfo::QPrinterInfo(const QPrinter& prn)
QPrinterInfo::~QPrinterInfo()
{
- if (d_ptr != &nullQPrinterInfoPrivate)
- delete d_ptr;
}
QPrinterInfo& QPrinterInfo::operator=(const QPrinterInfo& src)
{
Q_ASSERT(d_ptr);
- if (d_ptr != &nullQPrinterInfoPrivate)
- delete d_ptr;
- d_ptr = new QPrinterInfoPrivate(*src.d_ptr);
+ d_ptr.reset(new QPrinterInfoPrivate(*src.d_ptr));
d_ptr->q_ptr = this;
return *this;
}
diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp
index 58e4b4e..6d15271 100644
--- a/src/gui/painting/qrasterizer.cpp
+++ b/src/gui/painting/qrasterizer.cpp
@@ -436,8 +436,11 @@ void QScanConverter::end()
inline void QScanConverter::allocate(int size)
{
if (m_alloc < size) {
- m_alloc = qMax(size, 2 * m_alloc);
- m_intersections = (Intersection *)realloc(m_intersections, m_alloc * sizeof(Intersection));
+ int newAlloc = qMax(size, 2 * m_alloc);
+ Intersection *newIntersections = (Intersection *)realloc(m_intersections, newAlloc * sizeof(Intersection));
+ Q_CHECK_PTR(newIntersections);
+ m_alloc = newAlloc;
+ m_intersections = newIntersections;
}
}
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 762e9e0..7289a6b 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -3167,6 +3167,7 @@ static void InsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE, int scanline,
{
tmpSLLBlock =
(ScanLineListBlock *)malloc(sizeof(ScanLineListBlock));
+ Q_CHECK_PTR(tmpSLLBlock);
(*SLLBlock)->next = tmpSLLBlock;
tmpSLLBlock->next = (ScanLineListBlock *)NULL;
*SLLBlock = tmpSLLBlock;
@@ -3553,6 +3554,8 @@ static void PtsToRegion(register int numFullPtBlocks, register int iCurPtBlock,
* Scan converts a polygon by returning a run-length
* encoding of the resultant bitmap -- the run-length
* encoding is in the form of an array of rectangles.
+ *
+ * Can return 0 in case of errors.
*/
static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule)
//Point *Pts; /* the pts */
@@ -3624,75 +3627,28 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule)
}
- if (rule == EvenOddRule) {
- /*
- * for each scanline
- */
- for (y = ET.ymin; y < ET.ymax; ++y) {
-
- /*
- * Add a new edge to the active edge table when we
- * get to the next edge.
- */
- if (pSLL && y == pSLL->scanline) {
- loadAET(&AET, pSLL->edgelist);
- pSLL = pSLL->next;
- }
- pPrevAET = &AET;
- pAET = AET.next;
-
+ QT_TRY {
+ if (rule == EvenOddRule) {
/*
- * for each active edge
+ * for each scanline
*/
- while (pAET) {
- pts->setX(pAET->bres.minor_axis);
- pts->setY(y);
- ++pts;
- ++iPts;
+ for (y = ET.ymin; y < ET.ymax; ++y) {
/*
- * send out the buffer
+ * Add a new edge to the active edge table when we
+ * get to the next edge.
*/
- if (iPts == NUMPTSTOBUFFER) {
- tmpPtBlock = (POINTBLOCK *)malloc(sizeof(POINTBLOCK));
- tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data);
- curPtBlock->next = tmpPtBlock;
- curPtBlock = tmpPtBlock;
- pts = curPtBlock->pts;
- ++numFullPtBlocks;
- iPts = 0;
+ if (pSLL && y == pSLL->scanline) {
+ loadAET(&AET, pSLL->edgelist);
+ pSLL = pSLL->next;
}
- EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
- }
- InsertionSort(&AET);
- }
- } else {
- /*
- * for each scanline
- */
- for (y = ET.ymin; y < ET.ymax; ++y) {
- /*
- * Add a new edge to the active edge table when we
- * get to the next edge.
- */
- if (pSLL && y == pSLL->scanline) {
- loadAET(&AET, pSLL->edgelist);
- computeWAET(&AET);
- pSLL = pSLL->next;
- }
- pPrevAET = &AET;
- pAET = AET.next;
- pWETE = pAET;
+ pPrevAET = &AET;
+ pAET = AET.next;
- /*
- * for each active edge
- */
- while (pAET) {
/*
- * add to the buffer only those edges that
- * are in the Winding active edge table.
+ * for each active edge
*/
- if (pWETE == pAET) {
+ while (pAET) {
pts->setX(pAET->bres.minor_axis);
pts->setY(y);
++pts;
@@ -3702,7 +3658,8 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule)
* send out the buffer
*/
if (iPts == NUMPTSTOBUFFER) {
- tmpPtBlock = static_cast<POINTBLOCK *>(malloc(sizeof(POINTBLOCK)));
+ tmpPtBlock = (POINTBLOCK *)malloc(sizeof(POINTBLOCK));
+ Q_CHECK_PTR(tmpPtBlock);
tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data);
curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock;
@@ -3710,21 +3667,81 @@ static QRegionPrivate *PolygonRegion(const QPoint *Pts, int Count, int rule)
++numFullPtBlocks;
iPts = 0;
}
- pWETE = pWETE->nextWETE;
+ EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
}
- EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
+ InsertionSort(&AET);
}
-
+ } else {
/*
- * recompute the winding active edge table if
- * we just resorted or have exited an edge.
+ * for each scanline
*/
- if (InsertionSort(&AET) || fixWAET) {
- computeWAET(&AET);
- fixWAET = false;
+ for (y = ET.ymin; y < ET.ymax; ++y) {
+ /*
+ * Add a new edge to the active edge table when we
+ * get to the next edge.
+ */
+ if (pSLL && y == pSLL->scanline) {
+ loadAET(&AET, pSLL->edgelist);
+ computeWAET(&AET);
+ pSLL = pSLL->next;
+ }
+ pPrevAET = &AET;
+ pAET = AET.next;
+ pWETE = pAET;
+
+ /*
+ * for each active edge
+ */
+ while (pAET) {
+ /*
+ * add to the buffer only those edges that
+ * are in the Winding active edge table.
+ */
+ if (pWETE == pAET) {
+ pts->setX(pAET->bres.minor_axis);
+ pts->setY(y);
+ ++pts;
+ ++iPts;
+
+ /*
+ * send out the buffer
+ */
+ if (iPts == NUMPTSTOBUFFER) {
+ tmpPtBlock = static_cast<POINTBLOCK *>(malloc(sizeof(POINTBLOCK)));
+ tmpPtBlock->pts = reinterpret_cast<QPoint *>(tmpPtBlock->data);
+ curPtBlock->next = tmpPtBlock;
+ curPtBlock = tmpPtBlock;
+ pts = curPtBlock->pts;
+ ++numFullPtBlocks;
+ iPts = 0;
+ }
+ pWETE = pWETE->nextWETE;
+ }
+ EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
+ }
+
+ /*
+ * recompute the winding active edge table if
+ * we just resorted or have exited an edge.
+ */
+ if (InsertionSort(&AET) || fixWAET) {
+ computeWAET(&AET);
+ fixWAET = false;
+ }
}
}
+ } QT_CATCH(...) {
+ FreeStorage(SLLBlock.next);
+ PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
+ for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
+ tmpPtBlock = curPtBlock->next;
+ free(curPtBlock);
+ curPtBlock = tmpPtBlock;
+ }
+ free(pETEs);
+ return 0; // this function returns 0 in case of an error
}
+
FreeStorage(SLLBlock.next);
PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
@@ -3923,11 +3940,10 @@ QRegion &QRegion::operator=(const QRegion &r)
/*!
\internal
*/
-
QRegion QRegion::copy() const
{
QRegion r;
- QRegionData *x = new QRegionData;
+ QScopedPointer<QRegionData> x(new QRegionData);
x->ref = 1;
#if defined(Q_WS_X11)
x->rgn = 0;
@@ -3941,7 +3957,7 @@ QRegion QRegion::copy() const
x->qt_rgn = new QRegionPrivate;
if (!r.d->ref.deref())
cleanUp(r.d);
- r.d = x;
+ r.d = x.take();
return r;
}
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index bfedcb1..61a0623 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -59,7 +59,7 @@ QT_MODULE(Gui)
template <class T> class QVector;
class QVariant;
-#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE)
+#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
struct QRegionPrivate;
#endif
@@ -199,7 +199,7 @@ private:
#elif defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
mutable RgnHandle unused; // Here for binary compatability reasons. ### Qt 5 remove.
#endif
-#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE)
+#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
QRegionPrivate *qt_rgn;
#endif
};
diff --git a/src/gui/painting/qregion_s60.cpp b/src/gui/painting/qregion_s60.cpp
new file mode 100644
index 0000000..4d96910
--- /dev/null
+++ b/src/gui/painting/qregion_s60.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbitmap.h"
+#include "qbuffer.h"
+#include "qimage.h"
+#include "qpolygon.h"
+#include "qregion.h"
+
+QT_BEGIN_NAMESPACE
+
+QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0 };
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qtessellator.cpp b/src/gui/painting/qtessellator.cpp
index 31ee4f3..711f997 100644
--- a/src/gui/painting/qtessellator.cpp
+++ b/src/gui/painting/qtessellator.cpp
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
#ifdef DEBUG
#define QDEBUG qDebug
#else
-#define QDEBUG if (1); else qDebug
+#define QDEBUG if (1){} else qDebug
#endif
static const bool emit_clever = true;
@@ -703,7 +703,6 @@ struct QCoincidingEdge {
}
};
-
static void cancelEdges(QCoincidingEdge &e1, QCoincidingEdge &e2)
{
if (e1.before) {
diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h
index b6b85fa..e3cb333 100644
--- a/src/gui/painting/qvectorpath_p.h
+++ b/src/gui/painting/qvectorpath_p.h
@@ -55,9 +55,9 @@
#include <QtGui/qpaintengine.h>
-#include "qpaintengine_p.h"
-#include "qstroker_p.h"
-#include "qpainter_p.h"
+#include <private/qpaintengine_p.h>
+#include <private/qstroker_p.h>
+#include <private/qpainter_p.h>
QT_BEGIN_HEADER
diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp
index 22433dd..63b39b2 100644
--- a/src/gui/painting/qwindowsurface_raster.cpp
+++ b/src/gui/painting/qwindowsurface_raster.cpp
@@ -105,8 +105,6 @@ QRasterWindowSurface::~QRasterWindowSurface()
#endif
if (d_ptr->image)
delete d_ptr->image;
-
- delete d_ptr;
}
@@ -284,6 +282,12 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi
CGContextFlush(context);
#endif
#endif
+
+#ifdef Q_OS_SYMBIAN
+ Q_UNUSED(widget);
+ Q_UNUSED(rgn);
+ Q_UNUSED(offset);
+#endif
}
void QRasterWindowSurface::setGeometry(const QRect &rect)
diff --git a/src/gui/painting/qwindowsurface_raster_p.h b/src/gui/painting/qwindowsurface_raster_p.h
index 996aaef..b3256b3 100644
--- a/src/gui/painting/qwindowsurface_raster_p.h
+++ b/src/gui/painting/qwindowsurface_raster_p.h
@@ -109,7 +109,7 @@ public:
private:
void prepareBuffer(QImage::Format format, QWidget *widget);
Q_DECLARE_PRIVATE(QRasterWindowSurface)
- QRasterWindowSurfacePrivate *d_ptr;
+ QScopedPointer<QRasterWindowSurfacePrivate> d_ptr;
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp
new file mode 100644
index 0000000..e81adcc
--- /dev/null
+++ b/src/gui/painting/qwindowsurface_s60.cpp
@@ -0,0 +1,234 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qglobal.h> // for Q_WS_WIN define (non-PCH)
+
+#include <QtGui/qpaintdevice.h>
+#include <private/qwidget_p.h>
+#include "qwindowsurface_s60_p.h"
+#include "qt_s60_p.h"
+#include "private/qdrawhelper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+struct QS60WindowSurfacePrivate
+{
+ QImage device;
+ CFbsBitmap *bitmap;
+ uchar* bytes;
+
+ // Since only one CFbsBitmap is allowed to be locked at a time, this is static.
+ static QS60WindowSurface* lockedSurface;
+};
+QS60WindowSurface* QS60WindowSurfacePrivate::lockedSurface = NULL;
+
+QS60WindowSurface::QS60WindowSurface(QWidget* widget)
+ : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate)
+{
+ d_ptr->bytes = 0;
+ d_ptr->bitmap = 0;
+
+ TDisplayMode mode = S60->screenDevice()->DisplayMode();
+ bool isOpaque = qt_widget_private(widget)->isOpaque;
+ if (mode == EColor16MA && isOpaque)
+ mode = EColor16MU; // Faster since 16MU -> 16MA is typically accelerated
+ else if (mode == EColor16MU && !isOpaque)
+ mode = EColor16MA; // Try for transparency anyway
+
+
+ // We create empty CFbsBitmap here -> it will be resized in setGeometry
+ d_ptr->bitmap = new (ELeave) CFbsBitmap;
+ User::LeaveIfError( d_ptr->bitmap->Create(TSize(0, 0), mode ) );
+
+ updatePaintDeviceOnBitmap();
+
+ setStaticContentsSupport(true);
+}
+
+QS60WindowSurface::~QS60WindowSurface()
+{
+ // Ensure that locking and unlocking of this surface were symmetrical
+ Q_ASSERT(QS60WindowSurfacePrivate::lockedSurface != this);
+
+ delete d_ptr->bitmap;
+ delete d_ptr;
+}
+
+void QS60WindowSurface::beginPaint(const QRegion &rgn)
+{
+ if(!d_ptr->bitmap)
+ return;
+
+ Q_ASSERT(!QS60WindowSurfacePrivate::lockedSurface);
+ QS60WindowSurfacePrivate::lockedSurface = this;
+ lockBitmapHeap();
+
+ if (!qt_widget_private(window())->isOpaque) {
+ QRgb *data = reinterpret_cast<QRgb *>(d_ptr->device.bits());
+ const int row_stride = d_ptr->device.bytesPerLine() / 4;
+
+ const QVector<QRect> rects = rgn.rects();
+ for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
+ const int x_start = it->x();
+ const int width = it->width();
+
+ const int y_start = it->y();
+ const int height = it->height();
+
+ QRgb *row = data + row_stride * y_start;
+ for (int y = 0; y < height; ++y) {
+ qt_memfill(row + x_start, 0U, width);
+ row += row_stride;
+ }
+ }
+ }
+}
+
+void QS60WindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &)
+{
+ const QVector<QRect> subRects = region.rects();
+ for (int i = 0; i < subRects.count(); ++i) {
+ TRect tr = qt_QRect2TRect(subRects[i]);
+ widget->winId()->DrawNow(tr);
+ }
+}
+
+bool QS60WindowSurface::scroll(const QRegion &area, int dx, int dy)
+{
+ QRect rect = area.boundingRect();
+
+ if (dx == 0 && dy == 0)
+ return false;
+
+ if (d_ptr->device.isNull())
+ return false;
+
+ CFbsBitmapDevice *bitmapDevice = CFbsBitmapDevice::NewL(d_ptr->bitmap);
+ CBitmapContext *bitmapContext;
+ TInt err = bitmapDevice->CreateBitmapContext(bitmapContext);
+ if (err != KErrNone) {
+ CBase::Delete(bitmapDevice);
+ return false;
+ }
+ bitmapContext->CopyRect(TPoint(dx, dy), qt_QRect2TRect(rect));
+ CBase::Delete(bitmapContext);
+ CBase::Delete(bitmapDevice);
+ return true;
+}
+
+void QS60WindowSurface::endPaint(const QRegion & /* rgn */)
+{
+ if(!d_ptr->bitmap)
+ return;
+
+ Q_ASSERT(QS60WindowSurfacePrivate::lockedSurface);
+ unlockBitmapHeap();
+ QS60WindowSurfacePrivate::lockedSurface = NULL;
+}
+
+QPaintDevice* QS60WindowSurface::paintDevice()
+{
+ return &d_ptr->device;
+}
+
+void QS60WindowSurface::setGeometry(const QRect& rect)
+{
+ if (rect == geometry())
+ return;
+
+ QWindowSurface::setGeometry(rect);
+
+ TRect nativeRect(qt_QRect2TRect(rect));
+ User::LeaveIfError(d_ptr->bitmap->Resize(nativeRect.Size()));
+
+ if (!rect.isNull())
+ updatePaintDeviceOnBitmap();
+}
+
+void QS60WindowSurface::lockBitmapHeap()
+{
+ if (!QS60WindowSurfacePrivate::lockedSurface)
+ return;
+
+ // Get some local variables to make later code lines more clear to read
+ CFbsBitmap*& bitmap = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap;
+ QImage& device = QS60WindowSurfacePrivate::lockedSurface->d_ptr->device;
+ uchar*& bytes = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bytes;
+
+ bitmap->LockHeap();
+ uchar *newBytes = (uchar*)bitmap->DataAddress();
+ if (newBytes != bytes) {
+ bytes = newBytes;
+
+ // Get some values for QImage creation
+ TDisplayMode mode = bitmap->DisplayMode();
+ if (mode == EColor16MA
+ && qt_widget_private(QS60WindowSurfacePrivate::lockedSurface->window())->isOpaque)
+ mode = EColor16MU;
+ QImage::Format format = qt_TDisplayMode2Format( mode );
+ TSize bitmapSize = bitmap->SizeInPixels();
+ int bytesPerLine = CFbsBitmap::ScanLineLength( bitmapSize.iWidth, mode);
+
+ device = QImage( bytes, bitmapSize.iWidth, bitmapSize.iHeight, bytesPerLine, format );
+ }
+}
+
+void QS60WindowSurface::unlockBitmapHeap()
+{
+ if (!QS60WindowSurfacePrivate::lockedSurface)
+ return;
+
+ QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap->UnlockHeap();
+}
+
+void QS60WindowSurface::updatePaintDeviceOnBitmap()
+{
+ // This forces the actual device to be updated based on CFbsBitmap
+ beginPaint(QRegion());
+ endPaint(QRegion());
+}
+
+CFbsBitmap *QS60WindowSurface::symbianBitmap() const
+{
+ return d_ptr->bitmap;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qwindowsurface_s60_p.h b/src/gui/painting/qwindowsurface_s60_p.h
new file mode 100644
index 0000000..40a866d
--- /dev/null
+++ b/src/gui/painting/qwindowsurface_s60_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSURFACE_S60_P_H
+#define QWINDOWSURFACE_S60_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qglobal.h>
+#include "private/qwindowsurface_p.h"
+
+class CFbsBitmap;
+
+QT_BEGIN_NAMESPACE
+
+struct QS60WindowSurfacePrivate;
+
+class QS60WindowSurface : public QWindowSurface
+{
+public:
+ QS60WindowSurface(QWidget *widget);
+ ~QS60WindowSurface();
+
+ QPaintDevice *paintDevice();
+ void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
+ bool scroll(const QRegion &area, int dx, int dy);
+
+ void beginPaint(const QRegion &);
+ void endPaint(const QRegion &);
+
+ void setGeometry(const QRect &rect);
+
+ static void lockBitmapHeap();
+ static void unlockBitmapHeap();
+
+ CFbsBitmap *symbianBitmap() const;
+
+private:
+ void updatePaintDeviceOnBitmap();
+
+private:
+ QS60WindowSurfacePrivate* d_ptr;
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSURFACE_S60_P_H
diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp
new file mode 100644
index 0000000..b083f4b
--- /dev/null
+++ b/src/gui/styles/qs60style.cpp
@@ -0,0 +1,2880 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qs60style_p.h"
+
+#include "qapplication.h"
+#include "qpainter.h"
+#include "qstyleoption.h"
+#include "qevent.h"
+#include "qpixmapcache.h"
+
+#include "qcalendarwidget.h"
+#include "qdial.h"
+#include "qdialog.h"
+#include "qgroupbox.h"
+#include "qheaderview.h"
+#include "qlist.h"
+#include "qlistwidget.h"
+#include "qlistview.h"
+#include "qmenu.h"
+#include "qmenubar.h"
+#include "qpushbutton.h"
+#include "qscrollarea.h"
+#include "qscrollbar.h"
+#include "qtabbar.h"
+#include "qtablewidget.h"
+#include "qtableview.h"
+#include "qtextedit.h"
+#include "qtoolbar.h"
+#include "qtoolbutton.h"
+#include "qtreeview.h"
+
+#include "private/qtoolbarextension_p.h"
+#include "private/qcombobox_p.h"
+#include "private/qwidget_p.h"
+#include "private/qapplication_p.h"
+
+#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN)
+
+QT_BEGIN_NAMESPACE
+
+// from text/qfont.cpp
+extern Q_GUI_EXPORT int qt_defaultDpiY();
+
+const QS60StylePrivate::SkinElementFlags QS60StylePrivate::KDefaultSkinElementFlags =
+ SkinElementFlags(SF_PointNorth | SF_StateEnabled);
+
+static const QByteArray propertyKeyLayouts = "layouts";
+static const QByteArray propertyKeyCurrentlayout = "currentlayout";
+
+const layoutHeader QS60StylePrivate::m_layoutHeaders[] = {
+// *** generated layout data ***
+{240,320,1,14,true,QLatin1String("QVGA Landscape Mirrored")},
+{240,320,1,14,false,QLatin1String("QVGA Landscape")},
+{320,240,1,14,true,QLatin1String("QVGA Portrait Mirrored")},
+{320,240,1,14,false,QLatin1String("QVGA Portrait")},
+{360,640,1,14,true,QLatin1String("NHD Landscape Mirrored")},
+{360,640,1,14,false,QLatin1String("NHD Landscape")},
+{640,360,1,14,true,QLatin1String("NHD Portrait Mirrored")},
+{640,360,1,14,false,QLatin1String("NHD Portrait")},
+{352,800,1,12,true,QLatin1String("E90 Landscape Mirrored")},
+{352,800,1,12,false,QLatin1String("E90 Landscape")}
+// *** End of generated data ***
+};
+const int QS60StylePrivate::m_numberOfLayouts =
+ (int)sizeof(QS60StylePrivate::m_layoutHeaders)/sizeof(QS60StylePrivate::m_layoutHeaders[0]);
+
+const short QS60StylePrivate::data[][MAX_PIXELMETRICS] = {
+// *** generated pixel metrics ***
+{5,0,-909,0,0,1,0,0,-1,8,15,22,15,15,7,198,-909,-909,-909,19,15,2,0,0,21,-909,21,-909,4,4,1,-909,-909,0,2,0,0,13,23,17,17,21,21,2,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,51,27,51,4,4,5,10,15,-909,5,58,12,5,0,7,4,4,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1},
+{5,0,-909,0,0,1,0,0,-1,8,15,22,15,15,7,198,-909,-909,-909,19,15,2,0,0,21,-909,21,-909,4,4,1,-909,-909,0,2,0,0,13,23,17,17,21,21,2,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,51,27,51,4,4,5,10,15,-909,5,58,12,5,0,4,4,7,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1},
+{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,-909,27,-909,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,4,4,5,10,15,-909,5,58,13,5,0,7,4,4,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1},
+{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,-909,27,-909,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,4,4,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,1,-909,-909,-909,-909,4,4,3,1},
+{7,0,-909,0,0,2,0,0,-1,20,53,28,19,19,9,258,-909,-909,-909,29,19,26,0,0,32,-909,72,-909,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,5,5,6,8,19,-909,7,74,19,7,0,8,5,5,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1},
+{7,0,-909,0,0,2,0,0,-1,20,53,28,19,19,9,258,-909,-909,-909,29,19,26,0,0,32,-909,72,-909,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,5,5,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1},
+{7,0,-909,0,0,2,0,0,-1,20,52,28,19,19,9,258,-909,-909,-909,29,19,6,0,0,32,-909,60,-909,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,98,35,98,5,5,6,8,19,-909,7,74,22,7,0,8,5,5,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1},
+{7,0,-909,0,0,2,0,0,-1,20,52,28,19,19,9,258,-909,-909,-909,29,19,6,0,0,32,-909,60,-909,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,98,35,98,5,5,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,2,-909,-909,-909,-909,7,7,3,1},
+{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,-909,32,-909,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,5,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,8,6,5,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1},
+{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,-909,32,-909,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1}
+// *** End of generated data ***
+};
+
+const short *QS60StylePrivate::m_pmPointer = QS60StylePrivate::data[0];
+
+// theme background texture
+QPixmap *QS60StylePrivate::m_background = 0;
+
+// theme palette
+QPalette *QS60StylePrivate::m_themePalette = 0;
+
+const struct QS60StylePrivate::frameElementCenter QS60StylePrivate::m_frameElementsData[] = {
+ {SE_ButtonNormal, QS60StyleEnums::SP_QsnFrButtonTbCenter},
+ {SE_ButtonPressed, QS60StyleEnums::SP_QsnFrButtonTbCenterPressed},
+ {SE_FrameLineEdit, QS60StyleEnums::SP_QsnFrInputCenter},
+ {SE_ListHighlight, QS60StyleEnums::SP_QsnFrListCenter},
+ {SE_OptionsMenu, QS60StyleEnums::SP_QsnFrPopupCenter},
+ {SE_SettingsList, QS60StyleEnums::SP_QsnFrSetOptCenter},
+ {SE_TableItem, QS60StyleEnums::SP_QsnFrCaleCenter},
+ {SE_TableHeaderItem, QS60StyleEnums::SP_QsnFrCaleHeadingCenter},
+ {SE_ToolTip, QS60StyleEnums::SP_QsnFrPopupPreviewCenter},
+ {SE_ToolBar, QS60StyleEnums::SP_QsnFrPopupSubCenter},
+ {SE_ToolBarButton, QS60StyleEnums::SP_QsnFrSctrlButtonCenter},
+ {SE_ToolBarButtonPressed, QS60StyleEnums::SP_QsnFrSctrlButtonCenterPressed},
+ {SE_PanelBackground, QS60StyleEnums::SP_QsnFrSetOptCenter},
+ {SE_ButtonInactive, QS60StyleEnums::SP_QsnFrButtonCenterInactive},
+ {SE_Editor, QS60StyleEnums::SP_QsnFrNotepadCenter},
+};
+
+static const int frameElementsCount =
+ int(sizeof(QS60StylePrivate::m_frameElementsData)/sizeof(QS60StylePrivate::m_frameElementsData[0]));
+
+const int KNotFound = -909;
+const double KTabFontMul = 0.72;
+
+QS60StylePrivate::~QS60StylePrivate()
+{
+ clearCaches(); //deletes also background image
+ deleteThemePalette();
+}
+
+void QS60StylePrivate::drawSkinElement(SkinElements element, QPainter *painter,
+ const QRect &rect, SkinElementFlags flags)
+{
+ switch (element) {
+ case SE_ButtonNormal:
+ drawFrame(SF_ButtonNormal, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ButtonPressed:
+ drawFrame(SF_ButtonPressed, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_FrameLineEdit:
+ drawFrame(SF_FrameLineEdit, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ProgressBarGrooveHorizontal:
+ drawRow(QS60StyleEnums::SP_QgnGrafBarFrameSideL, QS60StyleEnums::SP_QgnGrafBarFrameCenter,
+ QS60StyleEnums::SP_QgnGrafBarFrameSideR, Qt::Horizontal, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ProgressBarGrooveVertical:
+ drawRow(QS60StyleEnums::SP_QgnGrafBarFrameSideL, QS60StyleEnums::SP_QgnGrafBarFrameCenter,
+ QS60StyleEnums::SP_QgnGrafBarFrameSideR, Qt::Vertical, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_ProgressBarIndicatorHorizontal:
+ drawPart(QS60StyleEnums::SP_QgnGrafBarProgress, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ProgressBarIndicatorVertical:
+ drawPart(QS60StyleEnums::SP_QgnGrafBarProgress, painter, rect, flags | SF_PointWest);
+ break;
+ case SE_ScrollBarGrooveHorizontal:
+ drawRow(QS60StyleEnums::SP_QsnCpScrollBgBottom, QS60StyleEnums::SP_QsnCpScrollBgMiddle,
+ QS60StyleEnums::SP_QsnCpScrollBgTop, Qt::Horizontal, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_ScrollBarGrooveVertical:
+ drawRow(QS60StyleEnums::SP_QsnCpScrollBgTop, QS60StyleEnums::SP_QsnCpScrollBgMiddle,
+ QS60StyleEnums::SP_QsnCpScrollBgBottom, Qt::Vertical, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ScrollBarHandleHorizontal:
+ drawRow(QS60StyleEnums::SP_QsnCpScrollHandleBottom, QS60StyleEnums::SP_QsnCpScrollHandleMiddle,
+ QS60StyleEnums::SP_QsnCpScrollHandleTop, Qt::Horizontal, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_ScrollBarHandleVertical:
+ drawRow(QS60StyleEnums::SP_QsnCpScrollHandleTop, QS60StyleEnums::SP_QsnCpScrollHandleMiddle,
+ QS60StyleEnums::SP_QsnCpScrollHandleBottom, Qt::Vertical, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_SliderHandleHorizontal:
+ drawPart(QS60StyleEnums::SP_QgnIndiSliderEdit, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_SliderHandleVertical:
+ drawPart(QS60StyleEnums::SP_QgnIndiSliderEdit, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_TabBarTabEastActive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabActiveL, QS60StyleEnums::SP_QgnGrafTabActiveM,
+ QS60StyleEnums::SP_QgnGrafTabActiveR, Qt::Vertical, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_TabBarTabEastInactive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveL, QS60StyleEnums::SP_QgnGrafTabPassiveM,
+ QS60StyleEnums::SP_QgnGrafTabPassiveR, Qt::Vertical, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_TabBarTabNorthActive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabActiveL, QS60StyleEnums::SP_QgnGrafTabActiveM,
+ QS60StyleEnums::SP_QgnGrafTabActiveR, Qt::Horizontal, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_TabBarTabNorthInactive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveL, QS60StyleEnums::SP_QgnGrafTabPassiveM,
+ QS60StyleEnums::SP_QgnGrafTabPassiveR, Qt::Horizontal, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_TabBarTabSouthActive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabActiveR, QS60StyleEnums::SP_QgnGrafTabActiveM,
+ QS60StyleEnums::SP_QgnGrafTabActiveL, Qt::Horizontal, painter, rect, flags | SF_PointSouth);
+ break;
+ case SE_TabBarTabSouthInactive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveR, QS60StyleEnums::SP_QgnGrafTabPassiveM,
+ QS60StyleEnums::SP_QgnGrafTabPassiveL, Qt::Horizontal, painter, rect, flags | SF_PointSouth);
+ break;
+ case SE_TabBarTabWestActive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabActiveR, QS60StyleEnums::SP_QgnGrafTabActiveM,
+ QS60StyleEnums::SP_QgnGrafTabActiveL, Qt::Vertical, painter, rect, flags | SF_PointWest);
+ break;
+ case SE_TabBarTabWestInactive:
+ drawRow(QS60StyleEnums::SP_QgnGrafTabPassiveR, QS60StyleEnums::SP_QgnGrafTabPassiveM,
+ QS60StyleEnums::SP_QgnGrafTabPassiveL, Qt::Vertical, painter, rect, flags | SF_PointWest);
+ break;
+ case SE_ListHighlight:
+ drawFrame(SF_ListHighlight, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_OptionsMenu:
+ drawFrame(SF_OptionsMenu, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_SettingsList:
+ drawFrame(SF_SettingsList, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_TableItem:
+ drawFrame(SF_TableItem, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_TableHeaderItem:
+ drawFrame(SF_TableHeaderItem, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ToolTip:
+ drawFrame(SF_ToolTip, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ToolBar:
+ drawFrame(SF_ToolBar, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ToolBarButton:
+ drawFrame(SF_ToolBarButton, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ToolBarButtonPressed:
+ drawFrame(SF_ToolBarButtonPressed, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_PanelBackground:
+ drawFrame(SF_PanelBackground, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ScrollBarHandlePressedHorizontal:
+ drawRow(QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed, QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed,
+ QS60StyleEnums::SP_QsnCpScrollHandleTopPressed, Qt::Horizontal, painter, rect, flags | SF_PointEast);
+ break;
+ case SE_ScrollBarHandlePressedVertical:
+ drawRow(QS60StyleEnums::SP_QsnCpScrollHandleTopPressed, QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed,
+ QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed, Qt::Vertical, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_ButtonInactive:
+ drawFrame(SF_ButtonInactive, painter, rect, flags | SF_PointNorth);
+ break;
+ case SE_Editor:
+ drawFrame(SF_Editor, painter, rect, flags | SF_PointNorth);
+ break;
+ default:
+ break;
+ }
+}
+
+void QS60StylePrivate::drawSkinPart(QS60StyleEnums::SkinParts part,
+ QPainter *painter, const QRect &rect, SkinElementFlags flags)
+{
+ drawPart(part, painter, rect, flags);
+}
+
+short QS60StylePrivate::pixelMetric(int metric)
+{
+ Q_ASSERT(metric < MAX_PIXELMETRICS);
+ const short returnValue = m_pmPointer[metric];
+ return returnValue;
+}
+
+void QS60StylePrivate::setStyleProperty(const char *name, const QVariant &value)
+{
+ if (name == propertyKeyCurrentlayout) {
+ static const QStringList layouts = styleProperty(propertyKeyLayouts).toStringList();
+ const QString layout = value.toString();
+ Q_ASSERT(layouts.contains(layout));
+ const int layoutIndex = layouts.indexOf(layout);
+ setCurrentLayout(layoutIndex);
+ QApplication::setLayoutDirection(m_layoutHeaders[layoutIndex].mirroring ? Qt::RightToLeft : Qt::LeftToRight);
+ clearCaches();
+ refreshUI();
+ }
+}
+
+QVariant QS60StylePrivate::styleProperty(const char *name) const
+{
+ if (name == propertyKeyLayouts) {
+ static QStringList layouts;
+ if (layouts.isEmpty())
+ for (int i = 0; i < m_numberOfLayouts; i++)
+ layouts.append(m_layoutHeaders[i].layoutName);
+ return layouts;
+ }
+ return QVariant();
+}
+
+QColor QS60StylePrivate::stateColor(const QColor &color, const QStyleOption *option)
+{
+ QColor retColor (color);
+ if (option && !(option->state & QStyle::State_Enabled)) {
+ QColor hsvColor = retColor.toHsv();
+ int colorSat = hsvColor.saturation();
+ int colorVal = hsvColor.value();
+ colorSat = (colorSat!=0) ? (colorSat>>1) : 128;
+ colorVal = (colorVal!=0) ? (colorVal>>1) : 128;
+ hsvColor.setHsv(hsvColor.hue(), colorSat, colorVal);
+ retColor = hsvColor.toRgb();
+ }
+ return retColor;
+}
+
+QColor QS60StylePrivate::lighterColor(const QColor &baseColor)
+{
+ QColor result(baseColor);
+ bool modifyColor = false;
+ if (result.saturation() == 0) {
+ result.setHsv(result.hue(), 128, result.value());
+ modifyColor = true;
+ }
+ if (result.value() == 0) {
+ result.setHsv(result.hue(), result.saturation(), 128);
+ modifyColor = true;
+ }
+ if (modifyColor)
+ result = result.lighter(175);
+ else
+ result = result.lighter(225);
+ return result;
+}
+
+bool QS60StylePrivate::drawsOwnThemeBackground(const QWidget *widget)
+{
+ return qobject_cast<const QDialog *> (widget);
+}
+
+QFont QS60StylePrivate::s60Font(
+ QS60StyleEnums::FontCategories fontCategory, int pointSize) const
+{
+ QFont result;
+ int actualPointSize = pointSize;
+ if (actualPointSize <= 0) {
+ const QFont appFont = QApplication::font();
+ actualPointSize = appFont.pointSize();
+ if (actualPointSize <= 0)
+ actualPointSize = appFont.pixelSize() * 72 / qt_defaultDpiY();
+ }
+ Q_ASSERT(actualPointSize > 0);
+ const QPair<QS60StyleEnums::FontCategories, int> key(fontCategory, actualPointSize);
+ if (!m_mappedFontsCache.contains(key)) {
+ result = s60Font_specific(fontCategory, actualPointSize);
+ m_mappedFontsCache.insert(key, result);
+ } else {
+ result = m_mappedFontsCache.value(key);
+ if (result.pointSize() != actualPointSize)
+ result.setPointSize(actualPointSize);
+ }
+ return result;
+}
+
+void QS60StylePrivate::clearCaches(CacheClearReason reason)
+{
+ switch(reason){
+ case CC_LayoutChange:
+ // when layout changes, the colors remain in cache, but graphics and fonts can change
+ m_mappedFontsCache.clear();
+ deleteBackground();
+ QPixmapCache::clear();
+ break;
+ case CC_ThemeChange:
+ m_colorCache.clear();
+ QPixmapCache::clear();
+ deleteBackground();
+ break;
+ case CC_UndefinedChange:
+ default:
+ m_colorCache.clear();
+ m_mappedFontsCache.clear();
+ QPixmapCache::clear();
+ deleteBackground();
+ break;
+ }
+}
+
+// Since S60Style has 'button' and 'tooltip' as a graphic, we don't have any native color which to use
+// for QPalette::Button and QPalette::ToolTipBase. Therefore S60Style needs to guesstimate
+// palette colors by calculating average rgb values for button pixels.
+// Returns Qt::black if there is an issue with the graphics (image is NULL, or no bits() found).
+QColor QS60StylePrivate::colorFromFrameGraphics(SkinFrameElements frame) const
+{
+ const bool cachedColorExists = m_colorCache.contains(frame);
+ if (!cachedColorExists) {
+ const int frameCornerWidth = pixelMetric(PM_Custom_FrameCornerWidth);
+ const int frameCornerHeight = pixelMetric(PM_Custom_FrameCornerHeight);
+ Q_ASSERT(2*frameCornerWidth<32);
+ Q_ASSERT(2*frameCornerHeight<32);
+
+ const QImage frameImage = QS60StylePrivate::frame(frame, QSize(32,32)).toImage();
+ if (frameImage.isNull())
+ return Qt::black;
+
+ const QRgb *pixelRgb = (const QRgb*)frameImage.bits();
+ const int pixels = frameImage.numBytes()/sizeof(QRgb);
+ const int bytesPerLine = frameImage.bytesPerLine();
+ Q_ASSERT(bytesPerLine);
+
+ int estimatedRed = 0;
+ int estimatedGreen = 0;
+ int estimatedBlue = 0;
+
+ int skips = 0;
+ int estimations = 0;
+
+ const int topBorderLastPixel = frameCornerHeight*frameImage.width()-1;
+ const int bottomBorderFirstPixel = frameImage.width()*frameImage.height()-frameCornerHeight*frameImage.width()-1;
+ const int rightBorderFirstPixel = frameImage.width()-frameCornerWidth;
+ const int leftBorderLastPixel = frameCornerWidth;
+
+ while ((skips + estimations) < pixels) {
+ if ((skips+estimations) > topBorderLastPixel &&
+ (skips+estimations) < bottomBorderFirstPixel) {
+ for (int rowIndex = 0; rowIndex < frameImage.width(); rowIndex++) {
+ if (rowIndex > leftBorderLastPixel &&
+ rowIndex < rightBorderFirstPixel) {
+ estimatedRed += qRed(*pixelRgb);
+ estimatedGreen += qGreen(*pixelRgb);
+ estimatedBlue += qBlue(*pixelRgb);
+ }
+ pixelRgb++;
+ estimations++;
+ }
+ } else {
+ pixelRgb++;
+ skips++;
+ }
+ }
+ QColor frameColor(estimatedRed/estimations, estimatedGreen/estimations, estimatedBlue/estimations);
+ m_colorCache.insert(frame, frameColor);
+ return !estimations ? Qt::black : frameColor;
+ } else {
+ return m_colorCache.value(frame);
+ }
+
+}
+
+void QS60StylePrivate::setThemePalette(QApplication *app) const
+{
+ Q_UNUSED(app)
+ QPalette widgetPalette = QPalette(Qt::white);
+ setThemePalette(&widgetPalette);
+ QApplication::setPalette(widgetPalette); //calling QApplication::setPalette clears palette hash
+ setThemePaletteHash(&widgetPalette);
+ storeThemePalette(&widgetPalette);
+}
+
+void QS60StylePrivate::setThemePalette(QStyleOption *option) const
+{
+ setThemePalette(&option->palette);
+}
+
+QPalette* QS60StylePrivate::themePalette()
+{
+ return m_themePalette;
+}
+
+void QS60StylePrivate::setBackgroundTexture(QApplication *app) const
+{
+ Q_UNUSED(app)
+ QPalette applicationPalette = QApplication::palette();
+ applicationPalette.setBrush(QPalette::Window, backgroundTexture());
+ QApplication::setPalette(applicationPalette);
+}
+
+void QS60StylePrivate::deleteBackground()
+{
+ if (m_background) {
+ delete m_background;
+ m_background = 0;
+ }
+}
+
+int QS60StylePrivate::focusRectPenWidth()
+{
+ return pixelMetric(QS60Style::PM_DefaultFrameWidth);
+}
+
+void QS60StylePrivate::setCurrentLayout(int index)
+{
+ m_pmPointer = data[index];
+}
+
+void QS60StylePrivate::drawPart(QS60StyleEnums::SkinParts skinPart,
+ QPainter *painter, const QRect &rect, SkinElementFlags flags)
+{
+ static const bool doCache =
+#if defined(Q_WS_S60)
+ // Freezes on 3.1. Anyways, caching is only really needed on touch UI
+ !(QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2);
+#else
+ true;
+#endif
+ const QPixmap skinPartPixMap((doCache ? cachedPart : part)(skinPart, rect.size(), flags));
+ if (!skinPartPixMap.isNull())
+ painter->drawPixmap(rect.topLeft(), skinPartPixMap);
+}
+
+void QS60StylePrivate::drawFrame(SkinFrameElements frameElement, QPainter *painter, const QRect &rect, SkinElementFlags flags)
+{
+ static const bool doCache =
+#if defined(Q_WS_S60)
+ // Freezes on 3.1. Anyways, caching is only really needed on touch UI
+ !(QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2);
+#else
+ true;
+#endif
+ const QPixmap frameElementPixMap((doCache ? cachedFrame : frame)(frameElement, rect.size(), flags));
+ if (!frameElementPixMap.isNull())
+ painter->drawPixmap(rect.topLeft(), frameElementPixMap);
+}
+
+void QS60StylePrivate::drawRow(QS60StyleEnums::SkinParts start,
+ QS60StyleEnums::SkinParts middle, QS60StyleEnums::SkinParts end,
+ Qt::Orientation orientation, QPainter *painter, const QRect &rect,
+ SkinElementFlags flags)
+{
+ QSize startEndSize(partSize(start, flags));
+ startEndSize.scale(rect.size(), Qt::KeepAspectRatio);
+
+ QRect startRect = QRect(rect.topLeft(), startEndSize);
+ QRect middleRect = rect;
+ QRect endRect;
+
+ if (orientation == Qt::Horizontal) {
+ startRect.setWidth(qMin((rect.width() >> 1) - 1, startRect.width()));
+ endRect = startRect.translated(rect.width() - startRect.width(), 0);
+ middleRect.adjust(startRect.width(), 0, -startRect.width(), 0);
+ if (startRect.bottomRight().x() > endRect.topLeft().x()) {
+ const int overlap = (startRect.bottomRight().x() - endRect.topLeft().x())>>1;
+ startRect.setWidth(startRect.width()-overlap);
+ endRect.adjust(overlap,0,0,0);
+ }
+ } else {
+ startRect.setHeight(qMin((rect.height() >> 1) - 1, startRect.height()));
+ endRect = startRect.translated(0, rect.height() - startRect.height());
+ middleRect.adjust(0, startRect.height(), 0, -startRect.height());
+ if (startRect.topRight().y() > endRect.bottomLeft().y()) {
+ const int overlap = (startRect.topRight().y() - endRect.bottomLeft().y())>>1;
+ startRect.setHeight(startRect.height()-overlap);
+ endRect.adjust(0,overlap,0,0);
+ }
+ }
+
+#if 0
+ painter->save();
+ painter->setOpacity(.3);
+ painter->fillRect(startRect, Qt::red);
+ painter->fillRect(middleRect, Qt::green);
+ painter->fillRect(endRect, Qt::blue);
+ painter->restore();
+#else
+ drawPart(start, painter, startRect, flags);
+ if (middleRect.isValid())
+ drawPart(middle, painter, middleRect, flags);
+ drawPart(end, painter, endRect, flags);
+#endif
+}
+
+QPixmap QS60StylePrivate::cachedPart(QS60StyleEnums::SkinParts part,
+ const QSize &size, SkinElementFlags flags)
+{
+ QPixmap result;
+ const QString cacheKey =
+ QString::fromLatin1("S60Style: SkinParts=%1 QSize=%2|%3 SkinPartFlags=%4")
+ .arg((int)part).arg(size.width()).arg(size.height()).arg((int)flags);
+ if (!QPixmapCache::find(cacheKey, result)) {
+ result = QS60StylePrivate::part(part, size, flags);
+ QPixmapCache::insert(cacheKey, result);
+ }
+ return result;
+}
+
+QPixmap QS60StylePrivate::cachedFrame(SkinFrameElements frame, const QSize &size, SkinElementFlags flags)
+{
+ QPixmap result;
+ const QString cacheKey =
+ QString::fromLatin1("S60Style: SkinFrameElements=%1 QSize=%2|%3 SkinElementFlags=%4")
+ .arg((int)frame).arg(size.width()).arg(size.height()).arg((int)flags);
+ if (!QPixmapCache::find(cacheKey, result)) {
+ result = QS60StylePrivate::frame(frame, size, flags);
+ QPixmapCache::insert(cacheKey, result);
+ }
+ return result;
+}
+
+void QS60StylePrivate::refreshUI()
+{
+ QList<QWidget *> widgets = QApplication::allWidgets();
+
+ for (int i = 0; i < widgets.size(); ++i) {
+ QWidget *widget = widgets.at(i);
+ if (widget == 0)
+ continue;
+
+ if (widget->style()) {
+ widget->style()->polish(widget);
+ QEvent event(QEvent::StyleChange);
+ qApp->sendEvent(widget, &event);
+ }
+ widget->update();
+ widget->updateGeometry();
+ }
+}
+
+void QS60StylePrivate::setFont(QWidget *widget) const
+{
+ QS60StyleEnums::FontCategories fontCategory = QS60StyleEnums::FC_Undefined;
+ if (!widget)
+ return;
+ if (qobject_cast<QPushButton *>(widget)){
+ fontCategory = QS60StyleEnums::FC_Primary;
+ } else if (qobject_cast<QToolButton *>(widget)){
+ fontCategory = QS60StyleEnums::FC_Primary;
+ } else if (qobject_cast<QHeaderView *>(widget)){
+ fontCategory = QS60StyleEnums::FC_Secondary;
+ } else if (qobject_cast<QGroupBox *>(widget)){
+ fontCategory = QS60StyleEnums::FC_Title;
+ }
+ if (fontCategory != QS60StyleEnums::FC_Undefined) {
+ const QFont suggestedFont =
+ s60Font(fontCategory, widget->font().pointSizeF());
+ widget->setFont(suggestedFont);
+ }
+}
+
+void QS60StylePrivate::setThemePalette(QWidget *widget) const
+{
+ if(!widget)
+ return;
+ QPalette widgetPalette = QApplication::palette(widget);
+
+ //header view and its viewport need to be set 100% transparent button color, since drawing code will
+ //draw transparent theme graphics to table column and row headers.
+ if (qobject_cast<QHeaderView *>(widget)){
+ widgetPalette.setColor(QPalette::Active, QPalette::ButtonText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 23, 0));
+ QHeaderView* header = qobject_cast<QHeaderView *>(widget);
+ widgetPalette.setColor(QPalette::Button, Qt::transparent );
+ if ( header->viewport() )
+ header->viewport()->setPalette(widgetPalette);
+ QApplication::setPalette(widgetPalette, "QHeaderView");
+ }
+}
+
+void QS60StylePrivate::setThemePalette(QPalette *palette) const
+{
+ if (!palette)
+ return;
+
+ // basic colors
+ palette->setColor(QPalette::WindowText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0));
+ palette->setColor(QPalette::ButtonText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0));
+ palette->setColor(QPalette::Text,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0));
+ palette->setColor(QPalette::ToolTipText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 55, 0));
+ palette->setColor(QPalette::BrightText, palette->color(QPalette::WindowText).lighter());
+ palette->setColor(QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0));
+ palette->setColor(QPalette::Link,
+ s60Color(QS60StyleEnums::CL_QsnHighlightColors, 3, 0));
+ palette->setColor(QPalette::LinkVisited, palette->color(QPalette::Link).darker());
+ palette->setColor(QPalette::Highlight,
+ s60Color(QS60StyleEnums::CL_QsnHighlightColors, 2, 0));
+ // set background image as a texture brush
+ palette->setBrush(QPalette::Window, backgroundTexture());
+ // set these as transparent so that styled full screen theme background is visible
+ palette->setColor(QPalette::AlternateBase, Qt::transparent);
+ palette->setBrush(QPalette::Base, Qt::transparent);
+ // set button and tooltipbase based on pixel colors
+ const QColor buttonColor = this->colorFromFrameGraphics(SF_ButtonNormal);
+ palette->setColor(QPalette::Button, buttonColor );
+ const QColor toolTipColor = this->colorFromFrameGraphics(SF_ToolTip);
+ palette->setColor(QPalette::ToolTipBase, toolTipColor );
+ palette->setColor(QPalette::Light, palette->color(QPalette::Button).lighter());
+ palette->setColor(QPalette::Dark, palette->color(QPalette::Button).darker());
+ palette->setColor(QPalette::Midlight, palette->color(QPalette::Button).lighter(125));
+ palette->setColor(QPalette::Mid, palette->color(QPalette::Button).darker(150));
+ palette->setColor(QPalette::Shadow, Qt::black);
+}
+
+void QS60StylePrivate::deleteThemePalette()
+{
+ if (m_themePalette) {
+ delete m_themePalette;
+ m_themePalette = 0;
+ }
+}
+
+void QS60StylePrivate::storeThemePalette(QPalette *palette)
+{
+ deleteThemePalette();
+ //store specified palette for latter use.
+ m_themePalette = new QPalette(*palette);
+}
+
+// set widget specific palettes
+void QS60StylePrivate::setThemePaletteHash(QPalette *palette) const
+{
+ if (!palette)
+ return;
+
+ //store the original palette
+ QPalette widgetPalette = *palette;
+ const QColor mainAreaTextColor =
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 6, 0);
+
+ widgetPalette.setColor(QPalette::All, QPalette::WindowText,
+ s60Color(QS60StyleEnums::CL_QsnLineColors, 8, 0));
+ QApplication::setPalette(widgetPalette, "QSlider");
+ // return to original palette after each widget
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::Active, QPalette::ButtonText, mainAreaTextColor);
+ widgetPalette.setColor(QPalette::Inactive, QPalette::ButtonText, mainAreaTextColor);
+ const QStyleOption opt;
+ widgetPalette.setColor(QPalette::Disabled, QPalette::ButtonText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 6, &opt));
+ QApplication::setPalette(widgetPalette, "QPushButton");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::Active, QPalette::ButtonText, mainAreaTextColor);
+ widgetPalette.setColor(QPalette::Inactive, QPalette::ButtonText, mainAreaTextColor);
+ QApplication::setPalette(widgetPalette, "QToolButton");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::Active, QPalette::ButtonText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 23, 0));
+ QApplication::setPalette(widgetPalette, "QHeaderView");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::All, QPalette::ButtonText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 8, 0));
+ QApplication::setPalette(widgetPalette, "QMenuBar");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::Active, QPalette::WindowText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 4, 0));
+ QApplication::setPalette(widgetPalette, "QTabBar");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::All, QPalette::Text,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 22, 0));
+ QApplication::setPalette(widgetPalette, "QTableView");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::All, QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0));
+ QApplication::setPalette(widgetPalette, "QLineEdit");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::All, QPalette::Text,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 34, 0));
+ widgetPalette.setColor(QPalette::All, QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0));
+ QApplication::setPalette(widgetPalette, "QTextEdit");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::All, QPalette::HighlightedText,
+ s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0));
+ QApplication::setPalette(widgetPalette, "QComboBox");
+ widgetPalette = *palette;
+
+ widgetPalette.setColor(QPalette::WindowText, mainAreaTextColor);
+ widgetPalette.setColor(QPalette::Button, QApplication::palette().color(QPalette::Button));
+ widgetPalette.setColor(QPalette::Dark, mainAreaTextColor.darker());
+ widgetPalette.setColor(QPalette::Light, mainAreaTextColor.lighter());
+ QApplication::setPalette(widgetPalette, "QDial");
+ widgetPalette = *palette;
+
+ widgetPalette.setBrush(QPalette::Window, QBrush());
+ QApplication::setPalette(widgetPalette, "QScrollArea");
+ widgetPalette = *palette;
+}
+
+QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlags flags)
+{
+ QSize result(20, 20);
+ switch (part)
+ {
+ case QS60StyleEnums::SP_QgnGrafBarProgress:
+ result.setWidth(pixelMetric(QStyle::PM_ProgressBarChunkWidth));
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabActiveM:
+ case QS60StyleEnums::SP_QgnGrafTabPassiveM:
+ case QS60StyleEnums::SP_QgnGrafTabActiveR:
+ case QS60StyleEnums::SP_QgnGrafTabPassiveR:
+ case QS60StyleEnums::SP_QgnGrafTabPassiveL:
+ case QS60StyleEnums::SP_QgnGrafTabActiveL:
+ break;
+ case QS60StyleEnums::SP_QgnIndiSliderEdit:
+ result.scale(pixelMetric(QStyle::PM_SliderLength),
+ pixelMetric(QStyle::PM_SliderControlThickness), Qt::IgnoreAspectRatio);
+ break;
+
+ case QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed:
+ case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed:
+ case QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed:
+ case QS60StyleEnums::SP_QsnCpScrollBgBottom:
+ case QS60StyleEnums::SP_QsnCpScrollBgMiddle:
+ case QS60StyleEnums::SP_QsnCpScrollBgTop:
+ case QS60StyleEnums::SP_QsnCpScrollHandleBottom:
+ case QS60StyleEnums::SP_QsnCpScrollHandleMiddle:
+ case QS60StyleEnums::SP_QsnCpScrollHandleTop:
+ result.setHeight(pixelMetric(QStyle::PM_ScrollBarExtent));
+ result.setWidth(pixelMetric(QStyle::PM_ScrollBarSliderMin));
+ break;
+ default:
+ // Generic frame part size gathering.
+ for (int i = 0; i < frameElementsCount; ++i)
+ {
+ switch (m_frameElementsData[i].center - part) {
+ case 8: /* CornerTl */
+ case 7: /* CornerTr */
+ case 6: /* CornerBl */
+ case 5: /* CornerBr */
+ result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth));
+ // Falltrough intended...
+ case 4: /* SideT */
+ case 3: /* SideB */
+ result.setHeight(pixelMetric(PM_Custom_FrameCornerHeight));
+ break;
+ case 2: /* SideL */
+ case 1: /* SideR */
+ result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth));
+ break;
+ case 0: /* center */
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ if (flags & (SF_PointEast | SF_PointWest)) {
+ const int temp = result.width();
+ result.setWidth(result.height());
+ result.setHeight(temp);
+ }
+ return result;
+}
+
+/*!
+ \class QS60Style
+ \brief The QS60Style class provides a look and feel suitable for applications on S60.
+ \since 4.6
+ \ingroup appearance
+
+ \sa QMacStyle, QWindowsStyle, QWindowsXPStyle, QWindowsVistaStyle, QPlastiqueStyle, QCleanlooksStyle, QMotifStyle
+*/
+
+QS60Style::~QS60Style()
+{
+}
+
+/*!
+ \reimp
+*/
+void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const
+{
+ const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled;
+ SubControls sub = option->subControls;
+
+ switch (control) {
+#ifndef QT_NO_SCROLLBAR
+ case CC_ScrollBar:
+ if (const QStyleOptionSlider *optionSlider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+ const bool horizontal = optionSlider->orientation == Qt::Horizontal;
+
+ const QRect scrollBarSlider = subControlRect(control, optionSlider, SC_ScrollBarSlider, widget);
+ const QRect grooveRect = subControlRect(control, optionSlider, SC_ScrollBarGroove, widget);
+
+ const QS60StylePrivate::SkinElements grooveElement =
+ horizontal ? QS60StylePrivate::SE_ScrollBarGrooveHorizontal : QS60StylePrivate::SE_ScrollBarGrooveVertical;
+ QS60StylePrivate::drawSkinElement(grooveElement, painter, grooveRect, flags);
+
+ const QStyle::SubControls subControls = optionSlider->subControls;
+
+ // select correct slider (horizontal/vertical/pressed)
+ const bool sliderPressed = ((optionSlider->state & QStyle::State_Sunken) && (subControls & SC_ScrollBarSlider));
+ const QS60StylePrivate::SkinElements handleElement =
+ horizontal ?
+ ( sliderPressed ?
+ QS60StylePrivate::SE_ScrollBarHandlePressedHorizontal :
+ QS60StylePrivate::SE_ScrollBarHandleHorizontal ) :
+ ( sliderPressed ?
+ QS60StylePrivate::SE_ScrollBarHandlePressedVertical :
+ QS60StylePrivate::SE_ScrollBarHandleVertical);
+ QS60StylePrivate::drawSkinElement(handleElement, painter, scrollBarSlider, flags);
+ }
+ break;
+#endif // QT_NO_SCROLLBAR
+#ifndef QT_NO_SLIDER
+ case CC_Slider:
+ if (const QStyleOptionSlider *optionSlider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+
+ // The groove is just a centered line. Maybe a qgn_graf_line_* at some point
+ const QRect sliderGroove = subControlRect(control, optionSlider, SC_SliderGroove, widget);
+ const QPoint sliderGrooveCenter = sliderGroove.center();
+ const bool horizontal = optionSlider->orientation == Qt::Horizontal;
+ painter->save();
+ if (widget)
+ painter->setPen(widget->palette().windowText().color());
+ if (horizontal)
+ painter->drawLine(0, sliderGrooveCenter.y(), sliderGroove.right(), sliderGrooveCenter.y());
+ else
+ painter->drawLine(sliderGrooveCenter.x(), 0, sliderGrooveCenter.x(), sliderGroove.bottom());
+ painter->restore();
+
+ const QRect sliderHandle = subControlRect(control, optionSlider, SC_SliderHandle, widget);
+ const QS60StylePrivate::SkinElements handleElement =
+ horizontal ? QS60StylePrivate::SE_SliderHandleHorizontal : QS60StylePrivate::SE_SliderHandleVertical;
+ QS60StylePrivate::drawSkinElement(handleElement, painter, sliderHandle, flags);
+
+ if (optionSlider->state & State_HasFocus) {
+ QStyleOptionFocusRect fropt;
+ fropt.QStyleOption::operator=(*optionSlider);
+ fropt.rect = subElementRect(SE_SliderFocusRect, optionSlider, widget);
+ drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ }
+ }
+ break;
+#endif // QT_NO_SLIDER
+#ifndef QT_NO_COMBOBOX
+ case CC_ComboBox:
+ if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
+ const QRect cmbxEditField = subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget);
+ const QRect cmbxFrame = subControlRect(CC_ComboBox, option, SC_ComboBoxFrame, widget);
+ const bool direction = cmb->direction == Qt::LeftToRight;
+
+ // Button frame
+ QStyleOptionFrame buttonOption;
+ buttonOption.QStyleOption::operator=(*cmb);
+ const int maxHeight = cmbxFrame.height();
+ const int maxWidth = cmbxFrame.width() - cmbxEditField.width();
+ const int topLeftPoint = direction ? cmbxEditField.right()+1 : cmbxEditField.left()+1-maxWidth;
+ const QRect buttonRect(topLeftPoint, cmbxEditField.top(), maxWidth, maxHeight);
+ buttonOption.rect = buttonRect;
+ buttonOption.state = cmb->state & (State_Enabled | State_MouseOver);
+ drawPrimitive(PE_PanelButtonCommand, &buttonOption, painter, widget);
+
+ // draw label background - label itself is drawn separately
+ const QS60StylePrivate::SkinElements skinElement = QS60StylePrivate::SE_FrameLineEdit;
+ QS60StylePrivate::drawSkinElement(skinElement, painter, cmbxEditField, flags);
+
+ // Draw the combobox arrow
+ if (sub & SC_ComboBoxArrow) {
+ // Make rect slightly smaller
+ buttonOption.rect.adjust(1, 1, -1, -1);
+ painter->save();
+ painter->setPen(option->palette.buttonText().color());
+ drawPrimitive(PE_IndicatorSpinDown, &buttonOption, painter, widget);
+ painter->restore();
+ }
+
+ if (cmb->subControls & SC_ComboBoxEditField) {
+ if (cmb->state & State_HasFocus && !cmb->editable) {
+ QStyleOptionFocusRect focus;
+ focus.QStyleOption::operator=(*cmb);
+ focus.rect = cmbxEditField;
+ focus.state |= State_FocusAtBorder;
+ focus.backgroundColor = cmb->palette.highlight().color();
+ drawPrimitive(PE_FrameFocusRect, &focus, painter, widget);
+ }
+ }
+ }
+ break;
+#endif // QT_NO_COMBOBOX
+#ifndef QT_NO_TOOLBUTTON
+ case CC_ToolButton:
+ if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
+ const State bflags = toolBtn->state;
+ const QRect button(subControlRect(control, toolBtn, SC_ToolButton, widget));
+ QStyleOptionToolButton toolButton = *toolBtn;
+
+ if (sub&SC_ToolButton) {
+ QStyleOption tool(0);
+ tool.palette = toolBtn->palette;
+
+ // Check if toolbutton is in toolbar.
+ QToolBar *toolBar = 0;
+ if (widget)
+ toolBar = qobject_cast<QToolBar *>(widget->parentWidget());
+
+ if (bflags & (State_Sunken | State_On | State_Raised)) {
+ tool.rect = button;
+ tool.state = bflags;
+
+ // todo: I'd like to move extension button next to where last button is
+ // however, the painter seems to want to clip the button rect even if I turn of the clipping.
+ if (toolBar && (qobject_cast<const QToolBarExtension *>(widget))){
+ /*QList<QAction *> actionList = toolBar->actions();
+ const int actionCount = actionList.count();
+ const int toolbarWidth = toolBar->width();
+ const int extButtonWidth = pixelMetric(PM_ToolBarExtensionExtent, option, widget);
+ const int toolBarButtonWidth = pixelMetric(PM_ToolBarIconSize, option, widget);
+ const int frame = pixelMetric(PM_ToolBarFrameWidth, option, widget);
+ const int margin = pixelMetric(PM_ToolBarItemMargin, option, widget);
+ const int border = frame + margin;
+ const int spacing = pixelMetric(PM_ToolBarItemSpacing, option, widget);
+ const int toolBarButtonArea = toolbarWidth - extButtonWidth - spacing - 2*border;
+ const int numberOfVisibleButtons = toolBarButtonArea / toolBarButtonWidth;
+ // new extension button place is after border and all the other visible buttons (with spacings)
+ const int newXForExtensionButton = numberOfVisibleButtons * toolBarButtonWidth + (numberOfVisibleButtons-1)*spacing + border;
+ painter->save();
+ painter->setClipping(false);
+ tool.rect.translate(-newXForExtensionButton,0);
+ painter->restore();*/
+ }
+
+ if (toolBar){
+ /*if (toolBar->orientation() == Qt::Vertical){
+ // todo: I'd like to make all vertical buttons the same size, but again the painter
+ // prefers to use clipping for button rects, even though clipping has been set off.
+ painter->save();
+ painter->setClipping(false);
+
+ const int origWidth = tool.rect.width();
+ const int newWidth = toolBar->width()-2*pixelMetric(PM_ToolBarFrameWidth, option, widget);
+ painter->translate(origWidth-newWidth,0);
+ tool.rect.translate(origWidth-tool.rect.width(),0);
+ tool.rect.setWidth(newWidth);
+
+ if (option->state & QStyle::State_Sunken)
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBarButtonPressed, painter, tool.rect, flags);
+ else
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBarButton, painter, tool.rect, flags);
+
+ }*/
+ if (option->state & QStyle::State_Sunken)
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBarButtonPressed, painter, tool.rect, flags);
+ else
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBarButton, painter, tool.rect, flags);
+ /*
+ if (toolBar->orientation() == Qt::Vertical)
+ painter->restore();
+ */
+ } else {
+ drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
+ }
+ }
+ }
+ if (toolBtn->state & State_HasFocus) {
+ QStyleOptionFocusRect fr;
+ fr.QStyleOption::operator=(*toolBtn);
+ const int frameWidth = pixelMetric(PM_DefaultFrameWidth, option, widget);
+ fr.rect.adjust(frameWidth, frameWidth, -frameWidth, -frameWidth);
+ drawPrimitive(PE_FrameFocusRect, &fr, painter, widget);
+ }
+
+ if (toolBtn->features & QStyleOptionToolButton::Arrow) {
+ QStyle::PrimitiveElement pe;
+ switch (toolBtn->arrowType) {
+ case Qt::LeftArrow:
+ pe = QStyle::PE_IndicatorArrowLeft;
+ break;
+ case Qt::RightArrow:
+ pe = QStyle::PE_IndicatorArrowRight;
+ break;
+ case Qt::UpArrow:
+ pe = QStyle::PE_IndicatorArrowUp;
+ break;
+ case Qt::DownArrow:
+ pe = QStyle::PE_IndicatorArrowDown;
+ break;
+ default:
+ break; }
+ toolButton.rect = button;
+ drawPrimitive(pe, &toolButton, painter, widget);
+ }
+
+ if (toolBtn->text.length()>0 ||
+ !toolBtn->icon.isNull()) {
+ const int frameWidth = pixelMetric(PM_DefaultFrameWidth, option, widget);
+ toolButton.rect = button.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth);
+ drawControl(CE_ToolButtonLabel, &toolButton, painter, widget);
+ }
+ }
+ break;
+#endif //QT_NO_TOOLBUTTON
+#ifndef QT_NO_SPINBOX
+ case CC_SpinBox:
+ if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
+ QStyleOptionSpinBox copy = *spinBox;
+ PrimitiveElement pe;
+
+ if (spinBox->subControls & SC_SpinBoxUp) {
+ copy.subControls = SC_SpinBoxUp;
+ QPalette spinBoxPal = spinBox->palette;
+ if (!(spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled)) {
+ spinBoxPal.setCurrentColorGroup(QPalette::Disabled);
+ copy.state &= ~State_Enabled;
+ copy.palette = spinBoxPal;
+ }
+
+ if (spinBox->activeSubControls == SC_SpinBoxUp && (spinBox->state & State_Sunken)) {
+ copy.state |= State_On;
+ copy.state |= State_Sunken;
+ } else {
+ copy.state |= State_Raised;
+ copy.state &= ~State_Sunken;
+ }
+ pe = (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) ?
+ PE_IndicatorSpinPlus :
+ PE_IndicatorSpinUp;
+
+ copy.rect = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxUp, widget);
+ drawPrimitive(PE_PanelButtonBevel, &copy, painter, widget);
+ copy.rect.adjust(1, 1, -1, -1);
+ drawPrimitive(pe, &copy, painter, widget);
+ }
+
+ if (spinBox->subControls & SC_SpinBoxDown) {
+ copy.subControls = SC_SpinBoxDown;
+ copy.state = spinBox->state;
+ QPalette spinBoxPal = spinBox->palette;
+ if (!(spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled)) {
+ spinBoxPal.setCurrentColorGroup(QPalette::Disabled);
+ copy.state &= ~State_Enabled;
+ copy.palette = spinBoxPal;
+ }
+
+ if (spinBox->activeSubControls == SC_SpinBoxDown && (spinBox->state & State_Sunken)) {
+ copy.state |= State_On;
+ copy.state |= State_Sunken;
+ } else {
+ copy.state |= State_Raised;
+ copy.state &= ~State_Sunken;
+ }
+ pe = (spinBox->buttonSymbols == QAbstractSpinBox::PlusMinus) ?
+ PE_IndicatorSpinMinus :
+ PE_IndicatorSpinDown;
+
+ copy.rect = subControlRect(CC_SpinBox, spinBox, SC_SpinBoxDown, widget);
+ drawPrimitive(PE_PanelButtonBevel, &copy, painter, widget);
+ copy.rect.adjust(1, 1, -1, -1);
+ drawPrimitive(pe, &copy, painter, widget);
+ }
+ }
+ break;
+#endif //QT_NO_SPINBOX
+#ifndef QT_NO_GROUPBOX
+ case CC_GroupBox:
+ if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
+ // Draw frame
+ const QRect textRect = subControlRect(CC_GroupBox, option, SC_GroupBoxLabel, widget);
+ const QRect checkBoxRect = subControlRect(CC_GroupBox, option, SC_GroupBoxCheckBox, widget);
+ if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
+ QStyleOptionFrameV2 frame;
+ frame.QStyleOption::operator=(*groupBox);
+ frame.features = groupBox->features;
+ frame.lineWidth = groupBox->lineWidth;
+ frame.midLineWidth = groupBox->midLineWidth;
+ frame.rect = subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget);
+ drawPrimitive(PE_FrameGroupBox, &frame, painter, widget);
+ }
+
+ // Draw title
+ if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
+ const QColor textColor = groupBox->textColor;
+ painter->save();
+
+ if (textColor.isValid())
+ painter->setPen(textColor);
+ int alignment = int(groupBox->textAlignment);
+ if (!styleHint(QStyle::SH_UnderlineShortcut, option, widget))
+ alignment |= Qt::TextHideMnemonic;
+
+ drawItemText(painter, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | Qt::AlignVCenter | alignment,
+ groupBox->palette, groupBox->state & State_Enabled, groupBox->text,
+ textColor.isValid() ? QPalette::NoRole : QPalette::WindowText);
+ painter->restore();
+
+ if (groupBox->state & State_HasFocus) {
+ QStyleOptionFocusRect fropt;
+ fropt.QStyleOption::operator=(*groupBox);
+ fropt.rect = textRect;
+ drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ }
+ }
+
+ // Draw checkbox
+ if (groupBox->subControls & SC_GroupBoxCheckBox) {
+ QStyleOptionButton box;
+ box.QStyleOption::operator=(*groupBox);
+ box.rect = checkBoxRect;
+ drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
+ }
+ }
+ break;
+#endif //QT_NO_GROUPBOX
+ default:
+ QCommonStyle::drawComplexControl(control, option, painter, widget);
+ }
+}
+
+/*!
+ \reimp
+*/
+void QS60Style::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
+{
+ Q_D(const QS60Style);
+ const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled;
+ switch (element) {
+ case CE_PushButton:
+ if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
+
+ drawControl(CE_PushButtonBevel, btn, painter, widget);
+ QStyleOptionButton subopt = *btn;
+ subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
+
+ drawControl(CE_PushButtonLabel, &subopt, painter, widget);
+ if (btn->state & State_HasFocus) {
+ QStyleOptionFocusRect fropt;
+ fropt.QStyleOption::operator=(*btn);
+ fropt.rect = subElementRect(SE_PushButtonFocusRect, btn, widget);
+ drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ }
+ }
+ break;
+ case CE_PushButtonBevel:
+ if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
+ const bool isDisabled = !(option->state & QStyle::State_Enabled);
+ const bool isFlat = button->features & QStyleOptionButton::Flat;
+ QS60StyleEnums::SkinParts skinPart;
+ QS60StylePrivate::SkinElements skinElement;
+ if (!isDisabled) {
+ const bool isPressed = (option->state & QStyle::State_Sunken) ||
+ (option->state & QStyle::State_On);
+ if (isFlat) {
+ skinPart =
+ isPressed ? QS60StyleEnums::SP_QsnFrButtonTbCenterPressed : QS60StyleEnums::SP_QsnFrButtonTbCenter;
+ } else {
+ skinElement =
+ isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal;
+ }
+ } else {
+ if (isFlat)
+ skinPart =QS60StyleEnums::SP_QsnFrButtonCenterInactive;
+ else
+ skinElement = QS60StylePrivate::SE_ButtonInactive;
+ }
+ if (isFlat)
+ QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags);
+ else
+ QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags);
+ }
+ break;
+#ifndef QT_NO_TOOLBUTTON
+ case CE_ToolButtonLabel:
+ if (const QStyleOptionToolButton *toolBtn = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
+ QStyleOptionToolButton optionToolButton = *toolBtn;
+
+ if (!optionToolButton.icon.isNull() && (optionToolButton.state & QStyle::State_Sunken)
+ && (optionToolButton.state & State_Enabled)) {
+
+ const QIcon::State state = optionToolButton.state & State_On ? QIcon::On : QIcon::Off;
+ const QPixmap pm(optionToolButton.icon.pixmap(optionToolButton.rect.size().boundedTo(optionToolButton.iconSize),
+ QIcon::Normal, state));
+ optionToolButton.icon = generatedIconPixmap(QIcon::Selected, pm, &optionToolButton);
+ }
+
+ QCommonStyle::drawControl(element, &optionToolButton, painter, widget);
+ }
+ break;
+#endif //QT_NO_TOOLBUTTON
+#ifndef QT_NO_COMBOBOX
+ case CE_ComboBoxLabel:
+ if (const QStyleOptionComboBox *comboBox = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
+ QStyleOption optionComboBox = *comboBox;
+ optionComboBox.palette.setColor(QPalette::Active, QPalette::WindowText,
+ optionComboBox.palette.text().color() );
+ optionComboBox.palette.setColor(QPalette::Inactive, QPalette::WindowText,
+ optionComboBox.palette.text().color() );
+ QRect editRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget);
+ painter->save();
+ painter->setClipRect(editRect);
+
+ if (!comboBox->currentIcon.isNull()) {
+ QIcon::Mode mode = comboBox->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
+ QPixmap pixmap = comboBox->currentIcon.pixmap(comboBox->iconSize, mode);
+ QRect iconRect(editRect);
+ iconRect.setWidth(comboBox->iconSize.width() + 4);
+ iconRect = alignedRect(comboBox->direction,
+ Qt::AlignLeft | Qt::AlignVCenter,
+ iconRect.size(), editRect);
+ if (comboBox->editable)
+ painter->fillRect(iconRect, optionComboBox.palette.brush(QPalette::Base));
+ drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
+
+ if (comboBox->direction == Qt::RightToLeft)
+ editRect.translate(-4 - comboBox->iconSize.width(), 0);
+ else
+ editRect.translate(comboBox->iconSize.width() + 4, 0);
+ }
+ if (!comboBox->currentText.isEmpty() && !comboBox->editable) {
+ QCommonStyle::drawItemText(painter,
+ editRect.adjusted(QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth), 0, -1, 0),
+ visualAlignment(comboBox->direction, Qt::AlignLeft | Qt::AlignVCenter),
+ comboBox->palette, comboBox->state & State_Enabled, comboBox->currentText);
+ }
+ painter->restore();
+ }
+ break;
+#endif //QT_NO_COMBOBOX
+#ifndef QT_NO_ITEMVIEWS
+ case CE_ItemViewItem:
+ if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
+ QStyleOptionViewItemV4 voptAdj = *vopt;
+ painter->save();
+
+ painter->setClipRect(voptAdj.rect);
+ const bool isSelected = (voptAdj.state & QStyle::State_HasFocus);
+
+ bool isVisible = false;
+ int scrollBarWidth = 0;
+ QList<QScrollBar *> scrollBars = qFindChildren<QScrollBar *>(widget);
+ for (int i = 0; i < scrollBars.size(); ++i) {
+ QScrollBar *scrollBar = scrollBars.at(i);
+ if (scrollBar && scrollBar->orientation() == Qt::Vertical) {
+ isVisible = scrollBar->isVisible();
+ scrollBarWidth = scrollBar->size().width();
+ break;
+ }
+ }
+
+ int rightValue = widget ? widget->contentsRect().right() : 0;
+
+ if (isVisible)
+ rightValue -= scrollBarWidth;
+
+ if (voptAdj.rect.right() > rightValue)
+ voptAdj.rect.setRight(rightValue);
+
+ const QRect iconRect = subElementRect(SE_ItemViewItemDecoration, &voptAdj, widget);
+ QRect textRect = subElementRect(SE_ItemViewItemText, &voptAdj, widget);
+
+ // draw themed background for table unless background brush has been defined.
+ if (vopt->backgroundBrush == Qt::NoBrush) {
+ const QStyleOptionViewItemV4 *tableOption = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option);
+ const QTableView *table = qobject_cast<const QTableView *>(widget);
+ if (table && tableOption) {
+ const QModelIndex index = tableOption->index;
+ //todo: Draw cell background only once - for the first cell.
+ QStyleOptionViewItemV4 voptAdj2 = voptAdj;
+ const QModelIndex indexFirst = table->model()->index(0,0);
+ const QModelIndex indexLast = table->model()->index(
+ table->model()->rowCount()-1,table->model()->columnCount()-1);
+ if (table->viewport())
+ voptAdj2.rect = QRect( table->visualRect(indexFirst).topLeft(),
+ table->visualRect(indexLast).bottomRight()).intersect(table->viewport()->rect());
+ drawPrimitive(PE_PanelItemViewItem, &voptAdj2, painter, widget);
+ }
+ } else { QCommonStyle::drawPrimitive(PE_PanelItemViewItem, option, painter, widget);}
+
+ // draw the focus rect
+ if (isSelected) {
+ const QRect highlightRect = option->rect.adjusted(1,1,-1,-1);
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, highlightRect, flags);
+ }
+
+ // draw the icon
+ const QIcon::Mode mode = (voptAdj.state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled;
+ const QIcon::State state = voptAdj.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
+ voptAdj.icon.paint(painter, iconRect, voptAdj.decorationAlignment, mode, state);
+
+ // Draw selection check mark. Show check mark only in multi selection modes.
+ if (const QListView *listView = (qobject_cast<const QListView *>(widget))) {
+ const bool singleSelection =
+ listView &&
+ (listView->selectionMode() == QAbstractItemView::SingleSelection ||
+ listView->selectionMode() == QAbstractItemView::NoSelection);
+ const QRect selectionRect = subElementRect(SE_ItemViewItemCheckIndicator, &voptAdj, widget);
+ if (voptAdj.state & QStyle::State_Selected && !singleSelection) {
+ QStyleOptionViewItemV4 option(voptAdj);
+ option.rect = selectionRect;
+ // Draw selection mark.
+ drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, painter, widget);
+ if ( textRect.right() > selectionRect.left() )
+ textRect.setRight(selectionRect.left());
+ } else if (singleSelection &&
+ voptAdj.features & QStyleOptionViewItemV2::HasCheckIndicator) {
+ // draw the check mark
+ if (selectionRect.isValid()) {
+ QStyleOptionViewItemV4 option(*vopt);
+ option.rect = selectionRect;
+ option.state = option.state & ~QStyle::State_HasFocus;
+
+ switch (vopt->checkState) {
+ case Qt::Unchecked:
+ option.state |= QStyle::State_Off;
+ break;
+ case Qt::PartiallyChecked:
+ option.state |= QStyle::State_NoChange;
+ break;
+ case Qt::Checked:
+ option.state |= QStyle::State_On;
+ break;
+ }
+ drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, painter, widget);
+ }
+ }
+ }
+
+ // draw the text
+ if (!voptAdj.text.isEmpty()) {
+ const QStyleOptionViewItemV4 *tableOption = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option);
+ if (isSelected) {
+ if (qobject_cast<const QTableView *>(widget) && tableOption)
+ voptAdj.palette.setColor(
+ QPalette::Text, QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 11, 0));
+ else
+ voptAdj.palette.setColor(
+ QPalette::Text, QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0));
+ }
+ painter->setPen(voptAdj.palette.text().color());
+ d->viewItemDrawText(painter, &voptAdj, textRect);
+ }
+ painter->restore();
+ }
+ break;
+#endif // QT_NO_ITEMVIEWS
+#ifndef QT_NO_TABBAR
+ case CE_TabBarTabShape:
+ if (const QStyleOptionTabV3 *optionTab = qstyleoption_cast<const QStyleOptionTabV3 *>(option)) {
+ QStyleOptionTabV3 optionTabAdj = *optionTab;
+ const bool isSelected = optionTab->state & QStyle::State_Selected;
+ const bool directionMirrored = (optionTab->direction == Qt::RightToLeft);
+ QS60StylePrivate::SkinElements skinElement;
+ switch (optionTab->shape) {
+ case QTabBar::TriangularEast:
+ case QTabBar::RoundedEast:
+ skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabEastActive:
+ QS60StylePrivate::SE_TabBarTabEastInactive;
+ break;
+ case QTabBar::TriangularSouth:
+ case QTabBar::RoundedSouth:
+ skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabSouthActive:
+ QS60StylePrivate::SE_TabBarTabSouthInactive;
+ break;
+ case QTabBar::TriangularWest:
+ case QTabBar::RoundedWest:
+ skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabWestActive:
+ QS60StylePrivate::SE_TabBarTabWestInactive;
+ break;
+ case QTabBar::TriangularNorth:
+ case QTabBar::RoundedNorth:
+ default:
+ skinElement = isSelected ? QS60StylePrivate::SE_TabBarTabNorthActive:
+ QS60StylePrivate::SE_TabBarTabNorthInactive;
+ break;
+ }
+ if (skinElement==QS60StylePrivate::SE_TabBarTabEastInactive||
+ skinElement==QS60StylePrivate::SE_TabBarTabNorthInactive||
+ skinElement==QS60StylePrivate::SE_TabBarTabSouthInactive||
+ skinElement==QS60StylePrivate::SE_TabBarTabWestInactive||
+ skinElement==QS60StylePrivate::SE_TabBarTabEastActive||
+ skinElement==QS60StylePrivate::SE_TabBarTabNorthActive||
+ skinElement==QS60StylePrivate::SE_TabBarTabSouthActive||
+ skinElement==QS60StylePrivate::SE_TabBarTabWestActive) {
+ const int borderThickness =
+ QS60StylePrivate::pixelMetric(QStyle::PM_DefaultFrameWidth);
+ const int tabOverlap =
+ QS60StylePrivate::pixelMetric(QStyle::PM_TabBarTabOverlap) - borderThickness;
+ //todo: draw navi wipe behind tabbar - must be drawn with first draw
+
+ if (skinElement==QS60StylePrivate::SE_TabBarTabEastInactive||
+ skinElement==QS60StylePrivate::SE_TabBarTabEastActive||
+ skinElement==QS60StylePrivate::SE_TabBarTabWestInactive||
+ skinElement==QS60StylePrivate::SE_TabBarTabWestActive){
+ optionTabAdj.rect.adjust(0, 0, 0, tabOverlap);
+ } else {
+ if (directionMirrored)
+ optionTabAdj.rect.adjust(-tabOverlap, 0, 0, 0);
+ else
+ optionTabAdj.rect.adjust(0, 0, tabOverlap, 0);
+ }
+ }
+ QS60StylePrivate::drawSkinElement(skinElement, painter, optionTabAdj.rect, flags);
+ }
+ break;
+ case CE_TabBarTabLabel:
+ if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(option)) {
+ QStyleOptionTabV3 optionTab = *tab;
+ QRect tr = optionTab.rect;
+ const bool directionMirrored = (optionTab.direction == Qt::RightToLeft);
+ const int borderThickness = QS60StylePrivate::pixelMetric(QStyle::PM_DefaultFrameWidth);
+ const int tabOverlap =
+ QS60StylePrivate::pixelMetric(QStyle::PM_TabBarTabOverlap) - borderThickness;
+ const QRect windowRect = painter->window();
+
+ switch (tab->shape) {
+ case QTabBar::TriangularWest:
+ case QTabBar::RoundedWest:
+ case QTabBar::TriangularEast:
+ case QTabBar::RoundedEast:
+ tr.adjust(0, 0, 0, tabOverlap);
+ break;
+ case QTabBar::TriangularSouth:
+ case QTabBar::RoundedSouth:
+ case QTabBar::TriangularNorth:
+ case QTabBar::RoundedNorth:
+ default:
+ if (directionMirrored)
+ tr.adjust(-tabOverlap, 0, 0, 0);
+ else
+ tr.adjust(0, 0, tabOverlap, 0);
+ break;
+ }
+ painter->save();
+ QFont f = painter->font();
+ f.setPointSizeF(f.pointSizeF() * KTabFontMul);
+ painter->setFont(f);
+
+ if (option->state & QStyle::State_Selected){
+ optionTab.palette.setColor(QPalette::Active, QPalette::WindowText,
+ QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors, 3, option));
+ }
+
+ const bool verticalTabs = optionTab.shape == QTabBar::RoundedEast
+ || optionTab.shape == QTabBar::RoundedWest
+ || optionTab.shape == QTabBar::TriangularEast
+ || optionTab.shape == QTabBar::TriangularWest;
+ const bool selected = optionTab.state & State_Selected;
+ if (verticalTabs) {
+ painter->save();
+ int newX, newY, newRotation;
+ if (optionTab.shape == QTabBar::RoundedEast || optionTab.shape == QTabBar::TriangularEast) {
+ newX = tr.width();
+ newY = tr.y();
+ newRotation = 90;
+ } else {
+ newX = 0;
+ newY = tr.y() + tr.height();
+ newRotation = -90;
+ }
+ tr.setRect(0, 0, tr.height(), tr.width());
+ QTransform m;
+ m.translate(newX, newY);
+ m.rotate(newRotation);
+ painter->setTransform(m, true);
+ }
+ tr.adjust(0, 0, pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget),
+ pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget));
+
+ if (selected) {
+ tr.setBottom(tr.bottom() - pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget));
+ tr.setRight(tr.right() - pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget));
+ }
+
+ int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
+ if (!styleHint(SH_UnderlineShortcut, &optionTab, widget))
+ alignment |= Qt::TextHideMnemonic;
+ if (!optionTab.icon.isNull()) {
+ QSize iconSize = optionTab.iconSize;
+ int iconExtent = pixelMetric(PM_TabBarIconSize);
+ if (iconSize.height() > iconExtent || iconSize.width() > iconExtent)
+ iconSize = QSize(iconExtent, iconExtent);
+ QPixmap tabIcon = optionTab.icon.pixmap(iconSize,
+ (optionTab.state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
+ if (tab->text.isEmpty())
+ painter->drawPixmap(tr.center().x() - (tabIcon.height() >>1),
+ tr.center().y() - (tabIcon.height() >>1),
+ tabIcon);
+ else
+ painter->drawPixmap(tr.left() + tabOverlap,
+ tr.center().y() - (tabIcon.height() >>1),
+ tabIcon);
+ tr.setLeft(tr.left() + iconSize.width() + 4);
+ }
+
+ QCommonStyle::drawItemText(painter, tr, alignment, optionTab.palette, tab->state & State_Enabled, tab->text, QPalette::WindowText);
+ if (verticalTabs)
+ painter->restore();
+
+ if (optionTab.state & State_HasFocus) {
+ const int OFFSET = 1 + pixelMetric(PM_DefaultFrameWidth);
+ const int leftBorder = optionTab.rect.left();
+ const int rightBorder = optionTab.rect.right() - 1;
+
+ QStyleOptionFocusRect fropt;
+ fropt.QStyleOption::operator=(*tab);
+ fropt.rect.setRect(leftBorder + 1 + OFFSET, optionTab.rect.y() + OFFSET,
+ rightBorder - leftBorder - 2*OFFSET, optionTab.rect.height() - 2*OFFSET);
+ drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ }
+
+ painter->restore();
+ }
+ break;
+#endif // QT_NO_TABBAR
+#ifndef QT_NO_PROGRESSBAR
+ case CE_ProgressBarContents:
+ if (const QStyleOptionProgressBarV2 *optionProgressBar = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
+ QRect progressRect = optionProgressBar->rect;
+
+ if (optionProgressBar->minimum == optionProgressBar->maximum && optionProgressBar->minimum == 0) {
+ // busy indicator
+ QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnGrafBarWait, painter, progressRect,flags);
+ } else {
+ const qreal progressFactor = (optionProgressBar->minimum == optionProgressBar->maximum) ? 1.0
+ : (qreal)optionProgressBar->progress / optionProgressBar->maximum;
+ if (optionProgressBar->orientation == Qt::Horizontal) {
+ progressRect.setWidth(int(progressRect.width() * progressFactor));
+ if(optionProgressBar->direction == Qt::RightToLeft)
+ progressRect.translate(optionProgressBar->rect.width()-progressRect.width(),0);
+ progressRect.adjust(1, 0, -1, 0);
+ } else {
+ progressRect.adjust(0, 1, 0, -1);
+ progressRect.setTop(progressRect.bottom() - int(progressRect.height() * progressFactor));
+ }
+
+ const QS60StylePrivate::SkinElements skinElement = optionProgressBar->orientation == Qt::Horizontal ?
+ QS60StylePrivate::SE_ProgressBarIndicatorHorizontal : QS60StylePrivate::SE_ProgressBarIndicatorVertical;
+ QS60StylePrivate::drawSkinElement(skinElement, painter, progressRect, flags);
+ }
+ }
+ break;
+ case CE_ProgressBarGroove:
+ if (const QStyleOptionProgressBarV2 *optionProgressBar = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
+ const QS60StylePrivate::SkinElements skinElement = optionProgressBar->orientation == Qt::Horizontal ?
+ QS60StylePrivate::SE_ProgressBarGrooveHorizontal : QS60StylePrivate::SE_ProgressBarGrooveVertical;
+ QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags);
+ }
+ break;
+ case CE_ProgressBarLabel:
+ if (const QStyleOptionProgressBarV2 *progressbar = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) {
+ QStyleOptionProgressBarV2 optionProgressBar = *progressbar;
+ QCommonStyle::drawItemText(painter, progressbar->rect, flags | Qt::AlignCenter | Qt::TextSingleLine, optionProgressBar.palette,
+ progressbar->state & State_Enabled, progressbar->text, QPalette::WindowText);
+ }
+ break;
+#endif // QT_NO_PROGRESSBAR
+#ifndef QT_NO_MENU
+ case CE_MenuItem:
+ if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
+ QStyleOptionMenuItem optionMenuItem = *menuItem;
+
+ bool drawSubMenuIndicator = false;
+ switch(menuItem->menuItemType) {
+ case QStyleOptionMenuItem::Scroller:
+ case QStyleOptionMenuItem::Separator:
+ return; // no separators or scrollers in S60 menus
+ case QStyleOptionMenuItem::SubMenu:
+ drawSubMenuIndicator = true;
+ break;
+ default:
+ break;
+ }
+ const bool enabled = optionMenuItem.state & State_Enabled;
+ const bool checkable = optionMenuItem.checkType != QStyleOptionMenuItem::NotCheckable;
+
+ uint text_flags = Qt::AlignLeading | Qt::TextShowMnemonic | Qt::TextDontClip
+ | Qt::TextSingleLine | Qt::AlignVCenter;
+ if (!styleHint(SH_UnderlineShortcut, menuItem, widget))
+ text_flags |= Qt::TextHideMnemonic;
+
+ QRect iconRect =
+ subElementRect(SE_ItemViewItemDecoration, &optionMenuItem, widget);
+ QRect textRect = subElementRect(SE_ItemViewItemText, &optionMenuItem, widget);
+
+ if ((option->state & State_Selected) && (option->state & State_Enabled))
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ListHighlight, painter, option->rect, flags);
+
+ //todo: move the vertical spacing stuff into subElementRect
+ const int vSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutVerticalSpacing);
+ if (checkable){
+ QStyleOptionMenuItem optionCheckBox;
+ optionCheckBox.QStyleOption::operator=(*menuItem);
+ optionCheckBox.rect.setWidth(pixelMetric(PM_IndicatorWidth));
+ optionCheckBox.rect.setHeight(pixelMetric(PM_IndicatorHeight));
+ const int moveByX = optionCheckBox.rect.width()+vSpacing;
+ if (optionMenuItem.direction == Qt::LeftToRight) {
+ textRect.translate(moveByX,0);
+ iconRect.translate(moveByX, 0);
+ iconRect.setWidth(iconRect.width()+vSpacing);
+ textRect.setWidth(textRect.width()-moveByX-vSpacing);
+ } else {
+ textRect.setWidth(textRect.width()-moveByX);
+ iconRect.setWidth(iconRect.width()+vSpacing);
+ iconRect.translate(-optionCheckBox.rect.width()-vSpacing, 0);
+ optionCheckBox.rect.translate(textRect.width()+iconRect.width(),0);
+ }
+ drawPrimitive(PE_IndicatorMenuCheckMark, &optionCheckBox, painter, widget);
+ }
+ //draw icon and/or checkState
+ QPixmap pix = menuItem->icon.pixmap(pixelMetric(PM_SmallIconSize),
+ enabled ? QIcon::Normal : QIcon::Disabled);
+ const bool itemWithIcon = !pix.isNull();
+ if (itemWithIcon) {
+ drawItemPixmap(painter, iconRect, text_flags, pix);
+ if (optionMenuItem.direction == Qt::LeftToRight)
+ textRect.translate(vSpacing,0);
+ else
+ textRect.translate(-vSpacing,0);
+ textRect.setWidth(textRect.width()-vSpacing);
+ }
+
+ //draw indicators
+ if (drawSubMenuIndicator) {
+ QStyleOptionMenuItem arrowOptions;
+ arrowOptions.QStyleOption::operator=(*menuItem);
+ const int indicatorWidth = (pixelMetric(PM_ListViewIconSize, option, widget)>>1) +
+ pixelMetric(QStyle::PM_LayoutVerticalSpacing, option, widget);
+ if (optionMenuItem.direction == Qt::LeftToRight)
+ arrowOptions.rect.setLeft(textRect.right());
+ arrowOptions.rect.setWidth(indicatorWidth);
+ //by default sub menu indicator in S60 points to east,so here icon
+ // direction is set to north (and south when in RightToLeft)
+ const QS60StylePrivate::SkinElementFlag arrowDirection = (arrowOptions.direction == Qt::LeftToRight) ?
+ QS60StylePrivate::SF_PointNorth : QS60StylePrivate::SF_PointSouth;
+ QS60StylePrivate::drawSkinPart(QS60StyleEnums::SP_QgnIndiSubMenu, painter, arrowOptions.rect,
+ (flags | QS60StylePrivate::SF_ColorSkinned | arrowDirection));
+ }
+
+ //draw text
+ if (!enabled){
+ //In s60, if something becomes disabled, it is removed from menu, so no native look-alike available.
+ optionMenuItem.palette.setColor(QPalette::Disabled, QPalette::Text, QS60StylePrivate::lighterColor(
+ optionMenuItem.palette.color(QPalette::Disabled, QPalette::Text)));
+ painter->save();
+ painter->setOpacity(0.5);
+ }
+ QCommonStyle::drawItemText(painter, textRect, text_flags,
+ optionMenuItem.palette, enabled,
+ optionMenuItem.text, QPalette::Text);
+ if (!enabled)
+ painter->restore();
+ }
+ break;
+ case CE_MenuEmptyArea:
+ break;
+#endif //QT_NO_MENU
+
+#ifndef QT_NO_MENUBAR
+ case CE_MenuBarEmptyArea:
+ break;
+#endif //QT_NO_MENUBAR
+
+ case CE_HeaderSection:
+ if ( const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
+ painter->save();
+ QPen linePen = QPen(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 1, header));
+ const int penWidth = (header->orientation == Qt::Horizontal) ?
+ linePen.width()+QS60StylePrivate::pixelMetric(PM_Custom_BoldLineWidth)
+ : linePen.width()+QS60StylePrivate::pixelMetric(PM_Custom_ThinLineWidth);
+ linePen.setWidth(penWidth);
+ painter->setPen(linePen);
+ if (header->orientation == Qt::Horizontal){
+ painter->drawLine(header->rect.bottomLeft(), header->rect.bottomRight());
+ } else {
+ if ( header->direction == Qt::LeftToRight ) {
+ painter->drawLine(header->rect.topRight(), header->rect.bottomRight());
+ } else {
+ painter->drawLine(header->rect.topLeft(), header->rect.bottomLeft());
+ }
+ }
+ painter->restore();
+ }
+ break;
+ case CE_HeaderEmptyArea: // no need to draw this
+ break;
+ case CE_Header:
+ if ( const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
+ drawControl(CE_HeaderSection, header, painter, widget);
+ QStyleOptionHeader subopt = *header;
+ subopt.rect = subElementRect(SE_HeaderLabel, header, widget);
+ if (subopt.rect.isValid())
+ drawControl(CE_HeaderLabel, &subopt, painter, widget);
+ if (header->sortIndicator != QStyleOptionHeader::None) {
+ subopt.rect = subElementRect(SE_HeaderArrow, option, widget);
+ drawPrimitive(PE_IndicatorHeaderArrow, &subopt, painter, widget);
+ }
+ }
+ break;
+#ifndef QT_NO_TOOLBAR
+ case CE_ToolBar:
+ if (const QStyleOptionToolBar *toolBar = qstyleoption_cast<const QStyleOptionToolBar *>(option)) {
+ const QToolBar *tbWidget = qobject_cast<const QToolBar *>(widget);
+
+ //toolbar within a toolbar, skip
+ if (!tbWidget || (widget && qobject_cast<QToolBar *>(widget->parentWidget())))
+ break;
+
+ // Normally in S60 5.0+ there is no background for toolbar, but in some cases with versatile QToolBar,
+ // it looks a bit strange. So, lets fillRect with Button.
+ if (!QS60StylePrivate::isToolBarBackground()) {
+ QList<QAction *> actions = tbWidget->actions();
+ bool justToolButtonsInToolBar = true;
+ for (int i = 0; i < actions.size(); ++i) {
+ QWidget *childWidget = tbWidget->widgetForAction(actions.at(i));
+ const QToolButton *button = qobject_cast<const QToolButton *>(childWidget);
+ if (!button){
+ justToolButtonsInToolBar = false;
+ }
+ }
+
+ // Draw frame background
+ // for vertical toolbars with text only and
+ // for toolbars with extension buttons and
+ // for toolbars with widgets in them.
+ if (!justToolButtonsInToolBar ||
+ (tbWidget &&
+ (tbWidget->orientation() == Qt::Vertical) &&
+ (tbWidget->toolButtonStyle() == Qt::ToolButtonTextOnly))) {
+ painter->save();
+ if (widget)
+ painter->setBrush(widget->palette().button());
+ painter->setOpacity(0.3);
+ painter->fillRect(toolBar->rect, painter->brush());
+ painter->restore();
+ }
+ } else {
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_ToolBar, painter, toolBar->rect, flags);
+ }
+ }
+ break;
+#endif //QT_NO_TOOLBAR
+ case CE_ShapedFrame:
+ if (qobject_cast<const QTextEdit *>(widget)) {
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_Editor, painter, option->rect, flags);
+ } else if (qobject_cast<const QTableView *>(widget)) {
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableItem, painter, option->rect, flags);
+ } else if (const QHeaderView *header = qobject_cast<const QHeaderView *>(widget)) {
+ if (header->orientation() == Qt::Horizontal) {
+ QRect headerRect = option->rect;
+ const int frameWidth = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
+ headerRect.adjust(0,frameWidth,-2*frameWidth,0);
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableHeaderItem, painter, headerRect, flags);
+ } else {
+ //todo: update to horizontal table graphic
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_TableHeaderItem, painter, option->rect, flags | QS60StylePrivate::SF_PointWest);
+ }
+ }
+ if (option->state & State_HasFocus)
+ drawPrimitive(PE_FrameFocusRect, option, painter, widget);
+ break;
+ case CE_MenuScroller:
+ break;
+ default:
+ QCommonStyle::drawControl(element, option, painter, widget);
+ }
+}
+
+/*!
+ \reimp
+*/
+void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
+{
+ const QS60StylePrivate::SkinElementFlags flags = (option->state & State_Enabled) ? QS60StylePrivate::SF_StateEnabled : QS60StylePrivate::SF_StateDisabled;
+ switch (element) {
+#ifndef QT_NO_LINEEDIT
+ case PE_PanelLineEdit:
+ if (const QStyleOptionFrame *lineEdit = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
+#ifndef QT_NO_COMBOBOX
+ if (widget && qobject_cast<const QComboBox *>(widget->parentWidget()))
+ break;
+#endif
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_FrameLineEdit,
+ painter, option->rect, flags);
+
+ if (lineEdit->state & State_HasFocus)
+ drawPrimitive(PE_FrameFocusRect, lineEdit, painter, widget);
+ }
+ break;
+#endif // QT_NO_LINEEDIT
+ case PE_IndicatorCheckBox:
+ {
+ const QRect indicatorRect = option->rect;
+ // Draw checkbox indicator as color skinned graphics.
+ const QS60StyleEnums::SkinParts skinPart = (option->state & QStyle::State_On) ?
+ QS60StyleEnums::SP_QgnIndiCheckboxOn : QS60StyleEnums::SP_QgnIndiCheckboxOff;
+ QS60StylePrivate::drawSkinPart(skinPart, painter, indicatorRect,
+ (flags | QS60StylePrivate::SF_ColorSkinned));
+ }
+ break;
+ case PE_IndicatorViewItemCheck:
+#ifndef QT_NO_ITEMVIEWS
+ if (const QListView *listItem = (qobject_cast<const QListView *>(widget))) {
+ if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) {
+ const bool checkBoxVisible = vopt->features & QStyleOptionViewItemV2::HasCheckIndicator;
+ const bool singleSelection = listItem->selectionMode() ==
+ QAbstractItemView::SingleSelection || listItem->selectionMode() == QAbstractItemView::NoSelection;
+ // draw either checkbox at the beginning
+ if (checkBoxVisible && singleSelection) {
+ drawPrimitive(PE_IndicatorCheckBox, option, painter, widget);
+ // ... or normal "tick" selection at the end.
+ } else if (option->state & QStyle::State_Selected) {
+ QRect tickRect = option->rect;
+ const int frameBorderWidth = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth);
+ // adjust tickmark rect to exclude frame border
+ tickRect.adjust(0,-frameBorderWidth,0,-frameBorderWidth);
+ QS60StyleEnums::SkinParts skinPart = QS60StyleEnums::SP_QgnIndiMarkedAdd;
+ QS60StylePrivate::drawSkinPart(skinPart, painter, tickRect,
+ (flags | QS60StylePrivate::SF_ColorSkinned));
+ }
+ }
+ }
+#endif //QT_NO_ITEMVIEWS
+ break;
+ case PE_IndicatorRadioButton: {
+ QRect buttonRect = option->rect;
+ //there is empty (a. 33%) space in svg graphics for radiobutton
+ const qreal reduceWidth = (qreal)buttonRect.width()/3.0;
+ const qreal rectWidth = (qreal)option->rect.width() != 0 ? option->rect.width() : 1.0;
+ // Try to occupy the full area
+ const qreal scaler = 1 + (reduceWidth/rectWidth);
+ buttonRect.setWidth((int)((buttonRect.width()-reduceWidth) * scaler));
+ buttonRect.setHeight((int)(buttonRect.height() * scaler));
+ // move the rect up for half of the new height-gain
+ const int newY = (buttonRect.bottomRight().y() - option->rect.bottomRight().y()) >> 1 ;
+ buttonRect.adjust(0,-newY,0,-newY);
+
+ // Draw radiobutton indicator as color skinned graphics.
+ QS60StyleEnums::SkinParts skinPart = (option->state & QStyle::State_On) ?
+ QS60StyleEnums::SP_QgnIndiRadiobuttOn : QS60StyleEnums::SP_QgnIndiRadiobuttOff;
+ QS60StylePrivate::drawSkinPart(skinPart, painter, buttonRect,
+ (flags | QS60StylePrivate::SF_ColorSkinned));
+ }
+ break;
+ case PE_PanelButtonCommand:
+ case PE_PanelButtonTool:
+ case PE_PanelButtonBevel:
+ case PE_FrameButtonBevel: {
+ const bool isPressed = option->state & QStyle::State_Sunken;
+ const QS60StylePrivate::SkinElements skinElement =
+ isPressed ? QS60StylePrivate::SE_ButtonPressed : QS60StylePrivate::SE_ButtonNormal;
+ QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags);
+ }
+ break;
+#ifndef QT_NO_TOOLBUTTON
+ case PE_IndicatorArrowDown:
+ case PE_IndicatorArrowLeft:
+ case PE_IndicatorArrowRight:
+ case PE_IndicatorArrowUp: {
+ QS60StyleEnums::SkinParts skinPart;
+ if (element==PE_IndicatorArrowDown)
+ skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowDown;
+ else if (element==PE_IndicatorArrowLeft)
+ skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowLeft;
+ else if (element==PE_IndicatorArrowRight)
+ skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowRight;
+ else if (element==PE_IndicatorArrowUp)
+ skinPart = QS60StyleEnums::SP_QgnGrafScrollArrowUp;
+
+ QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags);
+ }
+ break;
+#endif //QT_NO_TOOLBUTTON
+#ifndef QT_NO_SPINBOX
+ case PE_IndicatorSpinDown:
+ case PE_IndicatorSpinUp:
+ if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
+ QStyleOptionSpinBox optionSpinBox = *spinBox;
+ const QS60StyleEnums::SkinParts part = (element == PE_IndicatorSpinUp) ?
+ QS60StyleEnums::SP_QgnGrafScrollArrowUp :
+ QS60StyleEnums::SP_QgnGrafScrollArrowDown;
+ const int adjustment = qMin(optionSpinBox.rect.width(), optionSpinBox.rect.height())/6;
+ optionSpinBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? adjustment : -adjustment );
+ QS60StylePrivate::drawSkinPart(part, painter, optionSpinBox.rect,flags);
+ }
+#ifndef QT_NO_COMBOBOX
+ else if (const QStyleOptionFrame *cmb = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
+ // We want to draw down arrow here for comboboxes as well.
+ const QS60StyleEnums::SkinParts part = QS60StyleEnums::SP_QgnGrafScrollArrowDown;
+ QStyleOptionFrame comboBox = *cmb;
+ const int adjustment = qMin(comboBox.rect.width(), comboBox.rect.height())/6;
+ comboBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? adjustment : -adjustment );
+ QS60StylePrivate::drawSkinPart(part, painter, comboBox.rect,flags);
+ }
+#endif //QT_NO_COMBOBOX
+ break;
+ case PE_IndicatorSpinMinus:
+ case PE_IndicatorSpinPlus:
+ if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
+ QStyleOptionSpinBox optionSpinBox = *spinBox;
+ QCommonStyle::drawPrimitive(element, &optionSpinBox, painter, widget);
+ }
+#ifndef QT_NO_COMBOBOX
+ else if (const QStyleOptionFrame *cmb = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
+ // We want to draw down arrow here for comboboxes as well.
+ QStyleOptionFrame comboBox = *cmb;
+ const int frameWidth = QS60StylePrivate::pixelMetric(PM_DefaultFrameWidth);
+ comboBox.rect.adjust(0,frameWidth,0,-frameWidth);
+ QCommonStyle::drawPrimitive(element, &comboBox, painter, widget);
+ }
+#endif //QT_NO_COMBOBOX
+ break;
+#endif //QT_NO_SPINBOX
+ case PE_FrameFocusRect:
+// Calendar widget and combox both do not use styled itemDelegate
+ if (widget && !(false
+#ifndef QT_NO_CALENDARWIDGET
+ || qobject_cast<const QCalendarWidget *>(widget->parent())
+#endif //QT_NO_CALENDARWIDGET
+#ifndef QT_NO_COMBOBOX
+ || qobject_cast<const QComboBoxListView *>(widget)
+#endif //QT_NO_COMBOBOX
+ )) {
+ // no focus selection for touch
+ if (option->state & State_HasFocus && !QS60StylePrivate::isTouchSupported()) {
+ painter->save();
+ const int penWidth = QS60StylePrivate::focusRectPenWidth();
+#ifdef QT_KEYPAD_NAVIGATION
+ const Qt::PenStyle penStyle = widget->hasEditFocus() ? Qt::SolidLine :Qt::DotLine;
+ const qreal opacity = widget->hasEditFocus() ? 0.6 : 0.4;
+#else
+ const Qt::PenStyle penStyle = Qt::SolidLine;
+ const qreal opacity = 0.5;
+#endif
+ painter->setPen(QPen(option->palette.color(QPalette::Text), penWidth, penStyle));
+ painter->setRenderHint(QPainter::Antialiasing);
+ painter->setOpacity(opacity);
+ // Because of Qts coordinate system, we need to tweak the rect by .5 pixels, otherwise it gets blurred.
+ const qreal rectAdjustment = penWidth % 2?.5:0;
+ // Also we try to stay inside the option->rect, with penWidth > 1. Therefore these +1/-1
+ const QRectF adjustedRect = QRectF(option->rect).adjusted(
+ rectAdjustment + penWidth - 1,
+ rectAdjustment + penWidth - 1,
+ -rectAdjustment - penWidth + 1,
+ -rectAdjustment - penWidth + 1);
+ painter->drawRoundedRect(adjustedRect, penWidth * 1.5, penWidth * 1.5);
+ painter->restore();
+ }
+ }
+ break;
+ case PE_Widget:
+ if (QS60StylePrivate::drawsOwnThemeBackground(widget)
+#ifndef QT_NO_COMBOBOX
+ || qobject_cast<const QComboBoxListView *>(widget)
+#endif //QT_NO_COMBOBOX
+#ifndef QT_NO_MENU
+ || qobject_cast<const QMenu *> (widget)
+#endif //QT_NO_MENU
+ ) {
+ QS60StylePrivate::SkinElements skinElement = QS60StylePrivate::SE_OptionsMenu;
+ QS60StylePrivate::drawSkinElement(skinElement, painter, option->rect, flags);
+ }
+ break;
+ case PE_FrameWindow:
+ case PE_FrameTabWidget:
+ if (const QStyleOptionTabWidgetFrame *tabFrame = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) {
+ QStyleOptionTabWidgetFrame optionTabFrame = *tabFrame;
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_PanelBackground, painter, optionTabFrame.rect, flags);
+ }
+ break;
+ case PE_IndicatorHeaderArrow:
+ if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
+ if (header->sortIndicator & QStyleOptionHeader::SortUp)
+ drawPrimitive(PE_IndicatorArrowUp, header, painter, widget);
+ else if (header->sortIndicator & QStyleOptionHeader::SortDown)
+ drawPrimitive(PE_IndicatorArrowDown, header, painter, widget);
+ } // QStyleOptionHeader::None is not drawn => not needed
+ break;
+#ifndef QT_NO_GROUPBOX
+ case PE_FrameGroupBox:
+ if (const QStyleOptionFrameV2 *frame = qstyleoption_cast<const QStyleOptionFrameV2 *>(option))
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_SettingsList, painter, frame->rect, flags);
+ break;
+#endif //QT_NO_GROUPBOX
+
+ // Qt3 primitives are not supported
+ case PE_Q3CheckListController:
+ case PE_Q3CheckListExclusiveIndicator:
+ case PE_Q3CheckListIndicator:
+ case PE_Q3DockWindowSeparator:
+ case PE_Q3Separator:
+ Q_ASSERT(false);
+ break;
+ case PE_Frame:
+ if (const QStyleOptionFrameV3 *frame = qstyleoption_cast<const QStyleOptionFrameV3 *>(option))
+ drawPrimitive(PE_FrameFocusRect, frame, painter, widget);
+ break;
+#ifndef QT_NO_ITEMVIEWS
+ case PE_PanelItemViewItem:
+ case PE_PanelItemViewRow: // ### Qt 5: remove
+ break;
+#endif //QT_NO_ITEMVIEWS
+
+ case PE_IndicatorMenuCheckMark:
+ if (const QStyleOptionMenuItem *checkBox = qstyleoption_cast<const QStyleOptionMenuItem *>(option)){
+ QStyleOptionMenuItem optionCheckBox = *checkBox;
+ if (optionCheckBox.checked)
+ optionCheckBox.state = (optionCheckBox.state | State_On);
+ drawPrimitive(PE_IndicatorCheckBox, &optionCheckBox, painter, widget);
+ }
+ break;
+#ifndef QT_NO_TOOLBAR
+ case PE_IndicatorToolBarHandle:
+ // no toolbar handles in S60/AVKON UI
+ case PE_IndicatorToolBarSeparator:
+ // no separators in S60/AVKON UI
+ break;
+#endif //QT_NO_TOOLBAR
+
+ case PE_PanelMenuBar:
+ case PE_FrameMenu:
+ break; //disable frame in menu
+
+ case PE_IndicatorBranch:
+#if defined(Q_WS_S60)
+ // 3.1 AVKON UI does not have tree view component, use common style for drawing there
+ if (QSysInfo::s60Version() == QSysInfo::SV_S60_3_1) {
+#else
+ if (true) {
+#endif
+ QCommonStyle::drawPrimitive(element, option, painter, widget);
+ } else {
+ const bool rightLine = option->state & State_Item;
+ const bool downLine = option->state & State_Sibling;
+ const bool upLine = option->state & (State_Open | State_Children | State_Item | State_Sibling);
+
+ QS60StyleEnums::SkinParts skinPart;
+ bool drawSkinPart = false;
+ if (rightLine && downLine && upLine) {
+ skinPart = QS60StyleEnums::SP_QgnIndiHlLineBranch;
+ drawSkinPart = true;
+ } else if (rightLine && upLine) {
+ skinPart = QS60StyleEnums::SP_QgnIndiHlLineEnd;
+ drawSkinPart = true;
+ } else if (upLine && downLine) {
+ skinPart = QS60StyleEnums::SP_QgnIndiHlLineStraight;
+ drawSkinPart = true;
+ }
+
+ if ( drawSkinPart )
+ QS60StylePrivate::drawSkinPart(skinPart, painter, option->rect, flags);
+
+ if (option->state & State_Children) {
+ QS60StyleEnums::SkinParts skinPart =
+ (option->state & State_Open) ? QS60StyleEnums::SP_QgnIndiHlColSuper : QS60StyleEnums::SP_QgnIndiHlExpSuper;
+ int minDimension = qMin(option->rect.width(), option->rect.height());
+ const int resizeValue = minDimension >> 1;
+ minDimension += resizeValue; // Adjust the icon bigger because of empty space in svg icon.
+ QRect iconRect(option->rect.topLeft(), QSize(minDimension, minDimension));
+ int verticalMagic(0);
+ // magic values for positioning svg icon.
+ if (option->rect.width() <= option->rect.height())
+ verticalMagic = 3;
+ iconRect.translate(3, verticalMagic - resizeValue);
+ QS60StylePrivate::drawSkinPart(skinPart, painter, iconRect, flags);
+ }
+ }
+ break;
+
+ // todo: items are below with #ifdefs "just in case". in final version, remove all non-required cases
+ case PE_FrameLineEdit:
+ case PE_IndicatorButtonDropDown:
+ case PE_IndicatorDockWidgetResizeHandle:
+ case PE_PanelTipLabel:
+ case PE_PanelScrollAreaCorner:
+
+#ifndef QT_NO_TABBAR
+ case PE_IndicatorTabTear: // No tab tear in S60
+#endif // QT_NO_TABBAR
+ case PE_FrameDefaultButton:
+#ifndef QT_NO_DOCKWIDGET
+ case PE_FrameDockWidget:
+#endif //QT_NO_DOCKWIDGET
+#ifndef QT_NO_PROGRESSBAR
+ case PE_IndicatorProgressChunk:
+#endif //QT_NO_PROGRESSBAR
+#ifndef QT_NO_TOOLBAR
+ case PE_PanelToolBar:
+#endif //QT_NO_TOOLBAR
+#ifndef QT_NO_COLUMNVIEW
+ case PE_IndicatorColumnViewArrow:
+ case PE_IndicatorItemViewItemDrop:
+#endif //QT_NO_COLUMNVIEW
+ case PE_FrameTabBarBase: // since tabs are in S60 always in navipane, let's use common style for tab base in Qt.
+ default:
+ QCommonStyle::drawPrimitive(element, option, painter, widget);
+ }
+}
+
+/*! \reimp */
+int QS60Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
+{
+ int metricValue = QS60StylePrivate::pixelMetric(metric);
+ if (metricValue == KNotFound)
+ metricValue = QCommonStyle::pixelMetric(metric, option, widget);
+
+ if (metric == PM_SubMenuOverlap && widget){
+ const QMenu *menu = qobject_cast<const QMenu *>(widget);
+ if (menu && menu->activeAction() && menu->activeAction()->menu()) {
+ const int menuWidth = menu->activeAction()->menu()->sizeHint().width();
+ metricValue = -menuWidth;
+ }
+ }
+ return metricValue;
+}
+
+/*! \reimp */
+QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt,
+ const QSize &csz, const QWidget *widget) const
+{
+ QSize sz(csz);
+ switch (ct) {
+ case CT_PushButton:
+ sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget);
+ if (const QAbstractButton *buttonWidget = (qobject_cast<const QAbstractButton *>(widget)))
+ if (buttonWidget->isCheckable())
+ sz += QSize(pixelMetric(PM_IndicatorWidth) + pixelMetric(PM_CheckBoxLabelSpacing), 0);
+ break;
+ case CT_LineEdit:
+ if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(opt))
+ sz += QSize(2*f->lineWidth, 4*f->lineWidth);
+ break;
+ default:
+ sz = QCommonStyle::sizeFromContents( ct, opt, csz, widget);
+ break;
+ }
+ return sz;
+}
+
+/*! \reimp */
+int QS60Style::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *widget,
+ QStyleHintReturn *hret) const
+{
+ int retValue = -1;
+ switch (sh) {
+ case SH_Table_GridLineColor:
+ retValue = QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors,2,0).rgb();
+ break;
+ case SH_GroupBox_TextLabelColor:
+ retValue = QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnTextColors,6,0).rgb();
+ break;
+ case SH_ScrollBar_ScrollWhenPointerLeavesControl:
+ retValue = true;
+ break;
+ case SH_Slider_SnapToValue:
+ retValue = true;
+ break;
+ case SH_Slider_StopMouseOverSlider:
+ retValue = true;
+ break;
+ case SH_LineEdit_PasswordCharacter:
+ retValue = '*';
+ break;
+ case SH_ComboBox_PopupFrameStyle:
+ retValue = QFrame::NoFrame | QFrame::Plain;
+ break;
+ case SH_Dial_BackgroundRole:
+ retValue = QPalette::Base;
+ break;
+ case SH_ItemView_ActivateItemOnSingleClick:
+ retValue = true;
+ break;
+ case SH_ProgressDialog_TextLabelAlignment:
+ retValue = (QApplication::layoutDirection() == Qt::LeftToRight) ?
+ Qt::AlignLeft :
+ Qt::AlignRight;
+ break;
+ case SH_Menu_SubMenuPopupDelay:
+ retValue = 300;
+ break;
+ case SH_Menu_Scrollable:
+ retValue = true;
+ break;
+ case SH_Menu_SelectionWrap:
+ retValue = true;
+ break;
+ case SH_ItemView_ShowDecorationSelected:
+ retValue = true;
+ break;
+ case SH_ToolBar_Movable:
+ retValue = false;
+ break;
+ case SH_BlinkCursorWhenTextSelected:
+ retValue = true;
+ break;
+ case SH_UnderlineShortcut:
+ retValue = 0;
+ break;
+ default:
+ break;
+ }
+ if (retValue == -1)
+ retValue = QCommonStyle::styleHint(sh, opt, widget, hret);
+ return retValue;
+}
+
+/*! \reimp */
+QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl scontrol, const QWidget *widget) const
+{
+ QRect ret;
+ switch (control) {
+#ifndef QT_NO_SCROLLBAR
+ // This implementation of subControlRect(CC_ScrollBar..) basically just removes the SC_ScrollBarSubLine and SC_ScrollBarAddLine
+ case CC_ScrollBar:
+ if (const QStyleOptionSlider *scrollbarOption = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+ const QRect scrollBarRect = scrollbarOption->rect;
+ const bool isHorizontal = scrollbarOption->orientation == Qt::Horizontal;
+ const int maxlen = isHorizontal ? scrollBarRect.width() : scrollBarRect.height();
+ int sliderlen;
+
+ // calculate slider length
+ if (scrollbarOption->maximum != scrollbarOption->minimum) {
+ const uint range = scrollbarOption->maximum - scrollbarOption->minimum;
+ sliderlen = (qint64(scrollbarOption->pageStep) * maxlen) / (range + scrollbarOption->pageStep);
+
+ const int slidermin = pixelMetric(PM_ScrollBarSliderMin, scrollbarOption, widget);
+ if (sliderlen < slidermin || range > (INT_MAX>>1))
+ sliderlen = slidermin;
+ if (sliderlen > maxlen)
+ sliderlen = maxlen;
+ } else {
+ sliderlen = maxlen;
+ }
+
+ const int sliderstart = sliderPositionFromValue(scrollbarOption->minimum,
+ scrollbarOption->maximum,
+ scrollbarOption->sliderPosition,
+ maxlen - sliderlen,
+ scrollbarOption->upsideDown);
+
+ switch (scontrol) {
+ case SC_ScrollBarSubPage: // between top/left button and slider
+ if (isHorizontal)
+ ret.setRect(0, 0, sliderstart, scrollBarRect.height());
+ else
+ ret.setRect(0, 0, scrollBarRect.width(), sliderstart);
+ break;
+ case SC_ScrollBarAddPage: { // between bottom/right button and slider
+ const int addPageLength = sliderstart + sliderlen;
+ if (isHorizontal)
+ ret = scrollBarRect.adjusted(addPageLength, 0, 0, 0);
+ else
+ ret = scrollBarRect.adjusted(0, addPageLength, 0, 0);
+ }
+ break;
+ case SC_ScrollBarGroove:
+ ret = scrollBarRect;
+ break;
+ case SC_ScrollBarSlider:
+ if (scrollbarOption->orientation == Qt::Horizontal)
+ ret.setRect(sliderstart, 0, sliderlen, scrollBarRect.height());
+ else
+ ret.setRect(0, sliderstart, scrollBarRect.width(), sliderlen);
+ break;
+ case SC_ScrollBarSubLine: // top/left button
+ case SC_ScrollBarAddLine: // bottom/right button
+ default:
+ break;
+ }
+ ret = visualRect(scrollbarOption->direction, scrollBarRect, ret);
+ }
+ break;
+#endif // QT_NO_SCROLLBAR
+ case CC_SpinBox:
+ if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
+ const int frameThickness = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
+ const int buttonMargin = spinbox->frame ? 2 : 0;
+ const int buttonWidth = QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize) + 2*buttonMargin;
+ QSize buttonSize;
+ buttonSize.setHeight(qMax(8, spinbox->rect.height() - frameThickness));
+ buttonSize.setWidth(buttonWidth);
+ buttonSize = buttonSize.expandedTo(QApplication::globalStrut());
+
+ const int y = frameThickness + spinbox->rect.y();
+ const int x = spinbox->rect.x() + spinbox->rect.width() - frameThickness - 2*buttonSize.width();
+
+ switch (scontrol) {
+ case SC_SpinBoxUp:
+ if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
+ return QRect();
+ ret = QRect(x, y, buttonWidth, buttonSize.height());
+ break;
+ case SC_SpinBoxDown:
+ if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
+ return QRect();
+ ret = QRect(x+buttonSize.width(), y, buttonWidth, buttonSize.height());
+ break;
+ case SC_SpinBoxEditField:
+ if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
+ ret = QRect(
+ frameThickness,
+ frameThickness,
+ spinbox->rect.width() - 2*frameThickness,
+ spinbox->rect.height() - 2*frameThickness);
+ else
+ ret = QRect(
+ frameThickness,
+ frameThickness,
+ x - frameThickness,
+ spinbox->rect.height() - 2*frameThickness);
+ break;
+ case SC_SpinBoxFrame:
+ ret = spinbox->rect;
+ break;
+ default:
+ break;
+ }
+ ret = visualRect(spinbox->direction, spinbox->rect, ret);
+ }
+ break;
+ case CC_ComboBox:
+ if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
+ ret = cmb->rect;
+ const int width = cmb->rect.width();
+ const int height = cmb->rect.height();
+ const int buttonMargin = cmb->frame ? 2 : 0;
+ // lets use spinbox frame here as well, as no combobox specific value available.
+ const int frameThickness = cmb->frame ? pixelMetric(PM_SpinBoxFrameWidth, cmb, widget) : 0;
+ const int buttonWidth = QS60StylePrivate::pixelMetric(QStyle::PM_ButtonIconSize);
+ const int xposMod = (cmb->rect.x()) + width - buttonMargin - buttonWidth;
+ const int ypos = cmb->rect.y();
+
+ QSize buttonSize;
+ buttonSize.setHeight(qMax(8, (cmb->rect.height()>>1) - frameThickness)); //minimum of 8 pixels
+ buttonSize.setWidth(buttonWidth+2*buttonMargin);
+ buttonSize = buttonSize.expandedTo(QApplication::globalStrut());
+ switch (scontrol) {
+ case SC_ComboBoxArrow:
+ ret.setRect(xposMod, ypos + buttonMargin, buttonWidth, height - 2*buttonMargin);
+ break;
+ case SC_ComboBoxEditField: {
+ const int withFrameX = cmb->rect.x() + cmb->rect.width() - frameThickness - buttonSize.width();
+ ret = QRect(
+ frameThickness,
+ frameThickness,
+ withFrameX - frameThickness,
+ cmb->rect.height() - 2*frameThickness);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case CC_GroupBox:
+ if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
+ ret = QCommonStyle::subControlRect(control, option, scontrol, widget);
+ switch (scontrol) {
+ case SC_GroupBoxCheckBox: //fallthrough
+ case SC_GroupBoxLabel: {
+ //slightly indent text and boxes, so that dialog border does not mess with them.
+ const int horizontalSpacing =
+ QS60StylePrivate::pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
+ ret.adjust(2,horizontalSpacing-3,0,0);
+ }
+ break;
+ case SC_GroupBoxFrame: {
+ const QRect textBox = subControlRect(control, option, SC_GroupBoxLabel, widget);
+ const int tbHeight = textBox.height();
+ ret.translate(0, -ret.y());
+ // include title to within the groupBox frame
+ ret.setHeight(ret.height()+tbHeight);
+ if (widget && ret.bottom() > widget->rect().bottom())
+ ret.setBottom(widget->rect().bottom());
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ ret = QCommonStyle::subControlRect(control, option, scontrol, widget);
+ }
+ return ret;
+}
+
+QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, const QWidget *widget) const
+{
+ QRect ret;
+ switch (element) {
+ case SE_LineEditContents: {
+ // in S60 the input text box doesn't start from line Edit's TL, but
+ // a bit indented.
+ QRect lineEditRect = opt->rect;
+ const int adjustment = opt->rect.height()>>2;
+ lineEditRect.adjust(adjustment,0,0,0);
+ ret = lineEditRect;
+ }
+ break;
+ case SE_TabBarTearIndicator:
+ ret = QRect(0,0,0,0);
+ break;
+ case SE_TabWidgetTabBar:
+ if (const QStyleOptionTabWidgetFrame *optionTab = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
+ ret = QCommonStyle::subElementRect(element, opt, widget);
+
+ if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
+ const int tabOverlapNoBorder =
+ QS60StylePrivate::pixelMetric(QStyle::PM_TabBarTabOverlap);
+ const int tabOverlap =
+ tabOverlapNoBorder-QS60StylePrivate::pixelMetric(QStyle::PM_DefaultFrameWidth);
+ const QTabWidget *tab = qobject_cast<const QTabWidget *>(widget);
+ int gain = (tab) ? tabOverlap * tab->count() : 0;
+ switch (twf->shape) {
+ case QTabBar::RoundedNorth:
+ case QTabBar::TriangularNorth:
+ case QTabBar::RoundedSouth:
+ case QTabBar::TriangularSouth: {
+ if (widget) {
+ // make sure that gain does not set the rect outside of widget boundaries
+ if (twf->direction == Qt::RightToLeft) {
+ if ((ret.left() - gain) < widget->rect().left())
+ gain = widget->rect().left()-ret.left();
+ ret.adjust(-gain,0,0,0);
+ } else {
+ if ((ret.right() + gain) > widget->rect().right())
+ gain = widget->rect().right()-ret.right();
+ ret.adjust(0,0,gain,0);
+ }
+ }
+ break;
+ }
+ default: {
+ if (widget) {
+ if ((ret.bottom() + gain) > widget->rect().bottom())
+ gain = widget->rect().bottom()-ret.bottom();
+ ret.adjust(0,0,0,gain);
+ }
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case SE_ItemViewItemText:
+ case SE_ItemViewItemDecoration:
+ if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
+ const QListWidget *listItem = qobject_cast<const QListWidget *>(widget);
+ const bool multiSelection = !listItem ? false :
+ listItem->selectionMode() == QAbstractItemView::MultiSelection ||
+ listItem->selectionMode() == QAbstractItemView::ExtendedSelection ||
+ listItem->selectionMode() == QAbstractItemView::ContiguousSelection;
+ ret = QCommonStyle::subElementRect(element, opt, widget);
+ // If both multiselect & check-state, then remove checkbox and move
+ // text and decoration towards the beginning
+ if (listItem &&
+ multiSelection &&
+ (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator)) {
+ const int verticalSpacing =
+ QS60StylePrivate::pixelMetric(QStyle::PM_LayoutVerticalSpacing);
+ //const int horizontalSpacing = QS60StylePrivate::pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
+ const int checkBoxRectWidth = subElementRect(SE_ItemViewItemCheckIndicator, opt, widget).width();
+ ret.adjust(-checkBoxRectWidth-verticalSpacing,0,-checkBoxRectWidth-verticalSpacing,0);
+ }
+ } else if (const QStyleOptionMenuItem *menuItem = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
+ const bool checkable = menuItem->checkType != QStyleOptionMenuItem::NotCheckable;
+ const int indicatorWidth = checkable ?
+ pixelMetric(PM_ListViewIconSize, opt, widget) :
+ pixelMetric(PM_SmallIconSize, opt, widget);
+ ret = menuItem->rect;
+
+ if (element == SE_ItemViewItemDecoration) {
+ if (menuItem->direction == Qt::RightToLeft)
+ ret.translate(ret.width()-indicatorWidth, 0);
+ ret.setWidth(indicatorWidth);
+ } else {
+ ret = menuItem->rect;
+ if (!menuItem->icon.isNull())
+ if (menuItem->direction == Qt::LeftToRight)
+ ret.adjust(indicatorWidth, 0, 0, 0);
+ else
+ ret.adjust(0, 0, -indicatorWidth, 0);
+
+ // Make room for submenu indicator
+ if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu){
+ // submenu indicator is very small, so lets halve the rect
+ if (menuItem->direction == Qt::LeftToRight)
+ ret.adjust(0,0,-(indicatorWidth >> 1),0);
+ else
+ ret.adjust((indicatorWidth >> 1),0,0,0);
+ }
+ }
+ }
+ break;
+ case SE_ItemViewItemCheckIndicator:
+ if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(opt)) {
+ const QListWidget *listItem = qobject_cast<const QListWidget *>(widget);
+
+ const bool singleSelection = listItem &&
+ (listItem->selectionMode() == QAbstractItemView::SingleSelection ||
+ listItem->selectionMode() == QAbstractItemView::NoSelection);
+ const bool checkBoxOnly = (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator) &&
+ listItem &&
+ singleSelection;
+
+ // Selection check mark rect.
+ const int indicatorWidth = QS60StylePrivate::pixelMetric(QStyle::PM_IndicatorWidth);
+ const int indicatorHeight = QS60StylePrivate::pixelMetric(QStyle::PM_IndicatorHeight);
+ const int spacing = QS60StylePrivate::pixelMetric(QStyle::PM_CheckBoxLabelSpacing);
+
+ const int itemHeight = opt->rect.height();
+ int heightOffset = 0;
+ if (indicatorHeight < itemHeight)
+ heightOffset = ((itemHeight - indicatorHeight)>>1);
+ if (checkBoxOnly) {
+ // Move rect and make it slightly smaller, so that
+ // a) highlight border does not cross the rect
+ // b) in s60 list checkbox is smaller than normal checkbox
+ //todo; magic three
+ ret.setRect(opt->rect.left()+3, opt->rect.top() + heightOffset,
+ indicatorWidth-3, indicatorHeight-3);
+ } else {
+ ret.setRect(opt->rect.right() - indicatorWidth - spacing, opt->rect.top() + heightOffset,
+ indicatorWidth, indicatorHeight);
+ }
+ } else {
+ ret = QCommonStyle::subElementRect(element, opt, widget);
+ }
+ break;
+ case SE_HeaderLabel:
+ ret = QCommonStyle::subElementRect(element, opt, widget);
+ if (qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
+ // Subtract area needed for line
+ if (opt->state & State_Horizontal)
+ ret.setHeight(ret.height() - QS60StylePrivate::pixelMetric(PM_Custom_BoldLineWidth));
+ else
+ ret.setWidth(ret.width() - QS60StylePrivate::pixelMetric(PM_Custom_ThinLineWidth));
+ }
+ ret = visualRect(opt->direction, opt->rect, ret);
+ break;
+ case SE_FrameContents:
+ if (QS60StylePrivate::isTouchSupported()) {
+ return QCommonStyle::subElementRect(element, opt, widget);
+ } else if (const QStyleOptionFrameV2 *f = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt)) {
+ // We shrink the frame contents by focusFrameWidth, so that we can draw the frame around it in keypad navigation mode.
+ const int frameWidth = QS60StylePrivate::focusRectPenWidth();
+ ret = opt->rect.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth);
+ ret = visualRect(opt->direction, opt->rect, ret);
+ }
+ break;
+ default:
+ ret = QCommonStyle::subElementRect(element, opt, widget);
+ }
+ return ret;
+}
+
+void QS60Style::polish(QWidget *widget)
+{
+ Q_D(const QS60Style);
+ QCommonStyle::polish(widget);
+
+ if (!widget)
+ return;
+
+ if (false
+#ifndef QT_NO_SCROLLBAR
+ || qobject_cast<QScrollBar *>(widget)
+#endif
+ ) {
+ widget->setAttribute(Qt::WA_OpaquePaintEvent, false);
+ }
+
+ if (QS60StylePrivate::drawsOwnThemeBackground(widget)) {
+ widget->setAttribute(Qt::WA_StyledBackground);
+ } else if (false
+#ifndef QT_NO_MENU
+ || qobject_cast<const QMenu *> (widget)
+#endif // QT_NO_MENU
+ ) {
+ widget->setAttribute(Qt::WA_StyledBackground);
+ } else if (false
+#ifndef QT_NO_COMBOBOX
+ || qobject_cast<const QComboBoxListView *>(widget)
+#endif //QT_NO_COMBOBOX
+ ) {
+ widget->setAttribute(Qt::WA_StyledBackground);
+ }
+ d->setThemePalette(widget);
+ d->setFont(widget);
+}
+
+void QS60Style::unpolish(QWidget *widget)
+{
+ if (false
+ #ifndef QT_NO_SCROLLBAR
+ || qobject_cast<QScrollBar *>(widget)
+ #endif
+ )
+ widget->setAttribute(Qt::WA_OpaquePaintEvent);
+
+ if (QS60StylePrivate::drawsOwnThemeBackground(widget)) {
+ widget->setAttribute(Qt::WA_StyledBackground, false);
+ } else if (false
+#ifndef QT_NO_MENU
+ || qobject_cast<const QMenu *> (widget)
+#endif // QT_NO_MENU
+ ) {
+ widget->setAttribute(Qt::WA_StyledBackground, false);
+ } else if (false
+#ifndef QT_NO_COMBOBOX
+ || qobject_cast<const QComboBoxListView *>(widget)
+#endif //QT_NO_COMBOBOX
+ ) {
+ widget->setAttribute(Qt::WA_StyledBackground, false);
+ }
+
+ if (widget)
+ widget->setPalette(QPalette());
+
+ QCommonStyle::unpolish(widget);
+}
+
+void QS60Style::polish(QApplication *application)
+{
+ Q_D(QS60Style);
+ d->m_originalPalette = application->palette();
+ d->setThemePalette(application);
+}
+
+void QS60Style::unpolish(QApplication *application)
+{
+ Q_UNUSED(application)
+ Q_D(QS60Style);
+ const QPalette newPalette = QApplication::style()->standardPalette();
+ QApplication::setPalette(newPalette);
+ QApplicationPrivate::setSystemPalette(d->m_originalPalette);
+}
+
+void QS60Style::setStyleProperty(const char *name, const QVariant &value)
+{
+ Q_D(QS60Style);
+ d->setStyleProperty_specific(name, value);
+}
+
+QVariant QS60Style::styleProperty(const char *name) const
+{
+ Q_D(const QS60Style);
+ return d->styleProperty_specific(name);
+}
+
+QIcon QS60Style::standardIconImplementation(StandardPixmap standardIcon,
+ const QStyleOption *option, const QWidget *widget) const
+{
+ const int iconDimension = QS60StylePrivate::pixelMetric(QStyle::PM_ToolBarIconSize);
+ const QRect iconSize = (!option) ? QRect(0,0,iconDimension,iconDimension) : option->rect;
+ QS60StyleEnums::SkinParts part;
+ QS60StylePrivate::SkinElementFlags adjustedFlags;
+ if (option)
+ adjustedFlags = (option->state & State_Enabled) ?
+ QS60StylePrivate::SF_StateEnabled :
+ QS60StylePrivate::SF_StateDisabled;
+
+ switch(standardIcon) {
+ case QStyle::SP_MessageBoxWarning:
+ part = QS60StyleEnums::SP_QgnNoteWarning;
+ break;
+ case QStyle::SP_MessageBoxInformation:
+ part = QS60StyleEnums::SP_QgnNoteInfo;
+ break;
+ case QStyle::SP_MessageBoxCritical:
+ part = QS60StyleEnums::SP_QgnNoteError;
+ break;
+ case QStyle::SP_MessageBoxQuestion:
+ part = QS60StyleEnums::SP_QgnNoteQuery;
+ break;
+ case QStyle::SP_ArrowRight:
+ part = QS60StyleEnums::SP_QgnIndiNaviArrowRight;
+ break;
+ case QStyle::SP_ArrowLeft:
+ part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft;
+ break;
+ case QStyle::SP_ArrowUp:
+ part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft;
+ adjustedFlags |= QS60StylePrivate::SF_PointEast;
+ break;
+ case QStyle::SP_ArrowDown:
+ part = QS60StyleEnums::SP_QgnIndiNaviArrowLeft;
+ adjustedFlags |= QS60StylePrivate::SF_PointWest;
+ break;
+ case QStyle::SP_ArrowBack:
+ if (QApplication::layoutDirection() == Qt::RightToLeft)
+ return QS60Style::standardIcon(SP_ArrowRight, option, widget);
+ return QS60Style::standardIcon(SP_ArrowLeft, option, widget);
+ case QStyle::SP_ArrowForward:
+ if (QApplication::layoutDirection() == Qt::RightToLeft)
+ return QS60Style::standardIcon(SP_ArrowLeft, option, widget);
+ return QS60Style::standardIcon(SP_ArrowRight, option, widget);
+ case QStyle::SP_ComputerIcon:
+ part = QS60StyleEnums::SP_QgnPropPhoneMemcLarge;
+ break;
+ case QStyle::SP_DirClosedIcon:
+ part = QS60StyleEnums::SP_QgnPropFolderSmall;
+ break;
+ case QStyle::SP_DirOpenIcon:
+ part = QS60StyleEnums::SP_QgnPropFolderCurrent;
+ break;
+ case QStyle::SP_DirIcon:
+ part = QS60StyleEnums::SP_QgnPropFolderSmall;
+ break;
+ case QStyle::SP_FileDialogNewFolder:
+ part = QS60StyleEnums::SP_QgnPropFolderSmallNew;
+ break;
+ case QStyle::SP_FileIcon:
+ part = QS60StyleEnums::SP_QgnPropFileSmall;
+ break;
+ case QStyle::SP_TrashIcon:
+ part = QS60StyleEnums::SP_QgnNoteErased;
+ break;
+ case QStyle::SP_ToolBarHorizontalExtensionButton:
+ part = QS60StyleEnums::SP_QgnIndiSubMenu;
+ if (QApplication::layoutDirection() == Qt::RightToLeft)
+ adjustedFlags |= QS60StylePrivate::SF_PointSouth;
+ break;
+ case QStyle::SP_ToolBarVerticalExtensionButton:
+ adjustedFlags |= QS60StylePrivate::SF_PointEast;
+ part = QS60StyleEnums::SP_QgnIndiSubMenu;
+ break;
+
+ default:
+ return QCommonStyle::standardIconImplementation(standardIcon, option, widget);
+ }
+ const QS60StylePrivate::SkinElementFlags flags = adjustedFlags;
+ const QPixmap cachedPixMap(QS60StylePrivate::cachedPart(part, iconSize.size(), flags));
+ return cachedPixMap.isNull() ?
+ QCommonStyle::standardIconImplementation(standardIcon, option, widget) : QIcon(cachedPixMap);
+}
+
+extern QPoint qt_s60_fill_background_offset(const QWidget *targetWidget);
+
+bool qt_s60_fill_background(QPainter *painter, const QRegion &rgn, const QPoint &offset,
+ const QBrush &brush)
+{
+ const QPixmap backgroundTexture(QS60StylePrivate::backgroundTexture());
+ if (backgroundTexture.cacheKey() != brush.texture().cacheKey())
+ return false;
+
+ const QPaintDevice *target = painter->device();
+ if (target->devType() == QInternal::Widget) {
+ const QWidget *widget = static_cast<const QWidget *>(target);
+ const QRegion translated = rgn.translated(offset);
+ const QVector<QRect> &rects = translated.rects();
+ for (int i = 0; i < rects.size(); ++i) {
+ const QRect rect(rects.at(i));
+ painter->drawPixmap(rect.topLeft(), backgroundTexture,
+ rect.translated(qt_s60_fill_background_offset(widget)));
+ }
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STYLE_S60 || QT_PLUGIN
diff --git a/src/gui/styles/qs60style.h b/src/gui/styles/qs60style.h
new file mode 100644
index 0000000..d8e9a40
--- /dev/null
+++ b/src/gui/styles/qs60style.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QS60STYLE_H
+#define QS60STYLE_H
+
+#include <QtGui/qcommonstyle.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_STYLE_S60)
+
+class QS60StylePrivate;
+
+class Q_GUI_EXPORT QS60Style : public QCommonStyle
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QS60Style)
+
+public:
+ QS60Style();
+ ~QS60Style();
+
+ void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = 0) const;
+ void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const;
+ void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const;
+ int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const;
+ QSize sizeFromContents(ContentsType ct, const QStyleOption *opt, const QSize &contentsSize, const QWidget *w = 0) const;
+ int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0,
+ QStyleHintReturn *shret = 0) const;
+ QRect subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl scontrol, const QWidget *widget = 0) const;
+ QRect subElementRect(SubElement element, const QStyleOption *opt, const QWidget *widget = 0) const;
+ void polish(QWidget *widget);
+ void unpolish(QWidget *widget);
+ void polish(QApplication *application);
+ void unpolish(QApplication *application);
+
+ void setStyleProperty(const char *name, const QVariant &value);
+ QVariant styleProperty(const char *name) const;
+
+#ifndef Q_WS_S60
+ static QStringList partKeys();
+ static QStringList colorListKeys();
+ void setS60Theme(const QHash<QString, QPicture> &parts,
+ const QHash<QPair<QString , int>, QColor> &colors);
+ bool loadS60ThemeFromBlob(const QString &blobFile);
+ bool saveS60ThemeToBlob(const QString &blobFile) const;
+#endif // !Q_WS_S60
+
+#ifdef Q_WS_S60
+public Q_SLOTS:
+ void handleDynamicLayoutVariantSwitch();
+ void handleSkinChange();
+#endif // Q_WS_S60
+
+protected Q_SLOTS:
+ QIcon standardIconImplementation(
+ StandardPixmap standardIcon, const QStyleOption * option = 0, const QWidget * widget = 0 ) const;
+
+private:
+ Q_DISABLE_COPY(QS60Style)
+ friend class QStyleFactory;
+};
+
+#endif // QT_NO_STYLE_S60
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QS60STYLE_H
diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h
new file mode 100644
index 0000000..7240978
--- /dev/null
+++ b/src/gui/styles/qs60style_p.h
@@ -0,0 +1,501 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QS60STYLE_P_H
+#define QS60STYLE_P_H
+
+#include "qs60style.h"
+#include "qcommonstyle_p.h"
+#include <QtCore/qhash.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+const int MAX_NON_CUSTOM_PIXELMETRICS = 92;
+const int CUSTOMVALUESCOUNT = 4;
+enum {
+ PM_Custom_FrameCornerWidth = MAX_NON_CUSTOM_PIXELMETRICS,
+ PM_Custom_FrameCornerHeight,
+ PM_Custom_BoldLineWidth,
+ PM_Custom_ThinLineWidth
+ };
+const int MAX_PIXELMETRICS = MAX_NON_CUSTOM_PIXELMETRICS + CUSTOMVALUESCOUNT;
+
+typedef struct {
+ unsigned short height;
+ unsigned short width;
+ int major_version;
+ int minor_version;
+ bool mirroring; // TODO: (nice to have) Use Qt::LayoutDirection
+ QString layoutName;
+} layoutHeader;
+
+#ifdef Q_OS_SYMBIAN
+NONSHARABLE_CLASS (QS60StyleEnums)
+#else
+class QS60StyleEnums
+#endif
+: public QObject
+{
+#ifndef Q_WS_S60
+ Q_OBJECT
+ Q_ENUMS(FontCategories)
+ Q_ENUMS(SkinParts)
+ Q_ENUMS(ColorLists)
+#endif // !Q_WS_S60
+
+public:
+ // S60 look-and-feel font categories
+ enum FontCategories {
+ FC_Undefined,
+ FC_Primary,
+ FC_Secondary,
+ FC_Title,
+ FC_PrimarySmall,
+ FC_Digital
+ };
+
+ enum SkinParts {
+ SP_QgnGrafBarWait,
+ SP_QgnGrafBarFrameCenter,
+ SP_QgnGrafBarFrameSideL,
+ SP_QgnGrafBarFrameSideR,
+ SP_QgnGrafBarProgress,
+ SP_QgnGrafScrollArrowDown,
+ SP_QgnGrafScrollArrowLeft,
+ SP_QgnGrafScrollArrowRight,
+ SP_QgnGrafScrollArrowUp,
+ SP_QgnGrafTabActiveL,
+ SP_QgnGrafTabActiveM,
+ SP_QgnGrafTabActiveR,
+ SP_QgnGrafTabPassiveL,
+ SP_QgnGrafTabPassiveM,
+ SP_QgnGrafTabPassiveR,
+ SP_QgnIndiCheckboxOff,
+ SP_QgnIndiCheckboxOn,
+ SP_QgnIndiHlColSuper, // Available in S60 release 3.2 and later.
+ SP_QgnIndiHlExpSuper, // Available in S60 release 3.2 and later.
+ SP_QgnIndiHlLineBranch, // Available in S60 release 3.2 and later.
+ SP_QgnIndiHlLineEnd, // Available in S60 release 3.2 and later.
+ SP_QgnIndiHlLineStraight, // Available in S60 release 3.2 and later.
+ SP_QgnIndiMarkedAdd,
+ SP_QgnIndiNaviArrowLeft,
+ SP_QgnIndiNaviArrowRight,
+ SP_QgnIndiRadiobuttOff,
+ SP_QgnIndiRadiobuttOn,
+ SP_QgnIndiSliderEdit,
+ SP_QgnIndiSubMenu,
+ SP_QgnNoteErased,
+ SP_QgnNoteError,
+ SP_QgnNoteInfo,
+ SP_QgnNoteOk,
+ SP_QgnNoteQuery,
+ SP_QgnNoteWarning,
+ SP_QgnPropFileSmall,
+ SP_QgnPropFolderCurrent,
+ SP_QgnPropFolderSmall,
+ SP_QgnPropFolderSmallNew,
+ SP_QgnPropPhoneMemcLarge,
+ SP_QsnCpScrollHandleBottomPressed, //ScrollBar handle, pressed state
+ SP_QsnCpScrollHandleMiddlePressed,
+ SP_QsnCpScrollHandleTopPressed,
+ SP_QsnBgScreen,
+ SP_QsnCpScrollBgBottom,
+ SP_QsnCpScrollBgMiddle,
+ SP_QsnCpScrollBgTop,
+ SP_QsnCpScrollHandleBottom,
+ SP_QsnCpScrollHandleMiddle,
+ SP_QsnCpScrollHandleTop,
+ SP_QsnFrButtonTbCornerTl, // Button, normal state
+ SP_QsnFrButtonTbCornerTr,
+ SP_QsnFrButtonTbCornerBl,
+ SP_QsnFrButtonTbCornerBr,
+ SP_QsnFrButtonTbSideT,
+ SP_QsnFrButtonTbSideB,
+ SP_QsnFrButtonTbSideL,
+ SP_QsnFrButtonTbSideR,
+ SP_QsnFrButtonTbCenter,
+ SP_QsnFrButtonTbCornerTlPressed, // Button, pressed state
+ SP_QsnFrButtonTbCornerTrPressed,
+ SP_QsnFrButtonTbCornerBlPressed,
+ SP_QsnFrButtonTbCornerBrPressed,
+ SP_QsnFrButtonTbSideTPressed,
+ SP_QsnFrButtonTbSideBPressed,
+ SP_QsnFrButtonTbSideLPressed,
+ SP_QsnFrButtonTbSideRPressed,
+ SP_QsnFrButtonTbCenterPressed,
+ SP_QsnFrCaleCornerTl, // calendar grid item
+ SP_QsnFrCaleCornerTr,
+ SP_QsnFrCaleCornerBl,
+ SP_QsnFrCaleCornerBr,
+ SP_QsnFrCaleGSideT,
+ SP_QsnFrCaleGSideB,
+ SP_QsnFrCaleGSideL,
+ SP_QsnFrCaleGSideR,
+ SP_QsnFrCaleCenter,
+ SP_QsnFrCaleHeadingCornerTl, // calendar grid header
+ SP_QsnFrCaleHeadingCornerTr,
+ SP_QsnFrCaleHeadingCornerBl,
+ SP_QsnFrCaleHeadingCornerBr,
+ SP_QsnFrCaleHeadingSideT,
+ SP_QsnFrCaleHeadingSideB,
+ SP_QsnFrCaleHeadingSideL,
+ SP_QsnFrCaleHeadingSideR,
+ SP_QsnFrCaleHeadingCenter,
+ SP_QsnFrInputCornerTl, // Text input field
+ SP_QsnFrInputCornerTr,
+ SP_QsnFrInputCornerBl,
+ SP_QsnFrInputCornerBr,
+ SP_QsnFrInputSideT,
+ SP_QsnFrInputSideB,
+ SP_QsnFrInputSideL,
+ SP_QsnFrInputSideR,
+ SP_QsnFrInputCenter,
+ SP_QsnFrListCornerTl, // List background
+ SP_QsnFrListCornerTr,
+ SP_QsnFrListCornerBl,
+ SP_QsnFrListCornerBr,
+ SP_QsnFrListSideT,
+ SP_QsnFrListSideB,
+ SP_QsnFrListSideL,
+ SP_QsnFrListSideR,
+ SP_QsnFrListCenter,
+ SP_QsnFrPopupCornerTl, // Option menu background
+ SP_QsnFrPopupCornerTr,
+ SP_QsnFrPopupCornerBl,
+ SP_QsnFrPopupCornerBr,
+ SP_QsnFrPopupSideT,
+ SP_QsnFrPopupSideB,
+ SP_QsnFrPopupSideL,
+ SP_QsnFrPopupSideR,
+ SP_QsnFrPopupCenter,
+ SP_QsnFrPopupPreviewCornerTl, // tool tip background
+ SP_QsnFrPopupPreviewCornerTr,
+ SP_QsnFrPopupPreviewCornerBl,
+ SP_QsnFrPopupPreviewCornerBr,
+ SP_QsnFrPopupPreviewSideT,
+ SP_QsnFrPopupPreviewSideB,
+ SP_QsnFrPopupPreviewSideL,
+ SP_QsnFrPopupPreviewSideR,
+ SP_QsnFrPopupPreviewCenter,
+ SP_QsnFrSetOptCornerTl, // Settings list
+ SP_QsnFrSetOptCornerTr,
+ SP_QsnFrSetOptCornerBl,
+ SP_QsnFrSetOptCornerBr,
+ SP_QsnFrSetOptSideT,
+ SP_QsnFrSetOptSideB,
+ SP_QsnFrSetOptSideL,
+ SP_QsnFrSetOptSideR,
+ SP_QsnFrSetOptCenter,
+ SP_QsnFrPopupSubCornerTl, // Toolbar background
+ SP_QsnFrPopupSubCornerTr,
+ SP_QsnFrPopupSubCornerBl,
+ SP_QsnFrPopupSubCornerBr,
+ SP_QsnFrPopupSubSideT,
+ SP_QsnFrPopupSubSideB,
+ SP_QsnFrPopupSubSideL,
+ SP_QsnFrPopupSubSideR,
+ SP_QsnFrPopupSubCenter,
+ SP_QsnFrSctrlButtonCornerTl, // Toolbar button
+ SP_QsnFrSctrlButtonCornerTr,
+ SP_QsnFrSctrlButtonCornerBl,
+ SP_QsnFrSctrlButtonCornerBr,
+ SP_QsnFrSctrlButtonSideT,
+ SP_QsnFrSctrlButtonSideB,
+ SP_QsnFrSctrlButtonSideL,
+ SP_QsnFrSctrlButtonSideR,
+ SP_QsnFrSctrlButtonCenter,
+ SP_QsnFrSctrlButtonCornerTlPressed, // Toolbar button, pressed
+ SP_QsnFrSctrlButtonCornerTrPressed,
+ SP_QsnFrSctrlButtonCornerBlPressed,
+ SP_QsnFrSctrlButtonCornerBrPressed,
+ SP_QsnFrSctrlButtonSideTPressed,
+ SP_QsnFrSctrlButtonSideBPressed,
+ SP_QsnFrSctrlButtonSideLPressed,
+ SP_QsnFrSctrlButtonSideRPressed,
+ SP_QsnFrSctrlButtonCenterPressed,
+ SP_QsnFrButtonCornerTlInactive, // Inactive button
+ SP_QsnFrButtonCornerTrInactive,
+ SP_QsnFrButtonCornerBlInactive,
+ SP_QsnFrButtonCornerBrInactive,
+ SP_QsnFrButtonSideTInactive,
+ SP_QsnFrButtonSideBInactive,
+ SP_QsnFrButtonSideLInactive,
+ SP_QsnFrButtonSideRInactive,
+ SP_QsnFrButtonCenterInactive,
+ SP_QsnFrNotepadCornerTl,
+ SP_QsnFrNotepadCornerTr,
+ SP_QsnFrNotepadCornerBl,
+ SP_QsnFrNotepadCornerBr,
+ SP_QsnFrNotepadSideT,
+ SP_QsnFrNotepadSideB,
+ SP_QsnFrNotepadSideL,
+ SP_QsnFrNotepadSideR,
+ SP_QsnFrNotepadCenter
+ };
+
+ enum ColorLists {
+ CL_QsnHighlightColors,
+ CL_QsnIconColors,
+ CL_QsnLineColors,
+ CL_QsnOtherColors,
+ CL_QsnParentColors,
+ CL_QsnTextColors
+ };
+};
+
+// Private class
+#ifdef Q_OS_SYMBIAN
+NONSHARABLE_CLASS (QS60StylePrivate)
+#else
+class QS60StylePrivate
+#endif
+: public QCommonStylePrivate
+{
+ Q_DECLARE_PUBLIC(QS60Style)
+
+public:
+ QS60StylePrivate();
+ ~QS60StylePrivate();
+
+ enum SkinElements {
+ SE_ButtonNormal,
+ SE_ButtonPressed,
+ SE_FrameLineEdit,
+ SE_ProgressBarGrooveHorizontal,
+ SE_ProgressBarIndicatorHorizontal,
+ SE_ProgressBarGrooveVertical,
+ SE_ProgressBarIndicatorVertical,
+ SE_ScrollBarGrooveHorizontal,
+ SE_ScrollBarGrooveVertical,
+ SE_ScrollBarHandleHorizontal,
+ SE_ScrollBarHandleVertical,
+ SE_SliderHandleHorizontal,
+ SE_SliderHandleVertical,
+ SE_TabBarTabEastActive,
+ SE_TabBarTabEastInactive,
+ SE_TabBarTabNorthActive,
+ SE_TabBarTabNorthInactive,
+ SE_TabBarTabSouthActive,
+ SE_TabBarTabSouthInactive,
+ SE_TabBarTabWestActive,
+ SE_TabBarTabWestInactive,
+ SE_ListHighlight,
+ SE_OptionsMenu,
+ SE_SettingsList,
+ SE_TableItem,
+ SE_TableHeaderItem,
+ SE_ToolTip, //own graphic available on 3.2+ releases,
+ SE_ToolBar,
+ SE_ToolBarButton,
+ SE_ToolBarButtonPressed,
+ SE_PanelBackground,
+ SE_ScrollBarHandlePressedHorizontal, //only for 5.0+
+ SE_ScrollBarHandlePressedVertical,
+ SE_ButtonInactive,
+ SE_Editor,
+ };
+
+ enum SkinFrameElements {
+ SF_ButtonNormal,
+ SF_ButtonPressed,
+ SF_FrameLineEdit,
+ SF_ListHighlight,
+ SF_OptionsMenu,
+ SF_SettingsList,
+ SF_TableItem,
+ SF_TableHeaderItem,
+ SF_ToolTip,
+ SF_ToolBar,
+ SF_ToolBarButton,
+ SF_ToolBarButtonPressed,
+ SF_PanelBackground,
+ SF_ButtonInactive,
+ SF_Editor,
+ };
+
+ enum SkinElementFlag {
+ SF_PointNorth = 0x0001, // North = the default
+ SF_PointEast = 0x0002,
+ SF_PointSouth = 0x0004,
+ SF_PointWest = 0x0008,
+
+ SF_StateEnabled = 0x0010, // Enabled = the default
+ SF_StateDisabled = 0x0020,
+ SF_ColorSkinned = 0x0040,
+ };
+
+ enum CacheClearReason {
+ CC_UndefinedChange = 0,
+ CC_LayoutChange,
+ CC_ThemeChange
+ };
+
+ Q_DECLARE_FLAGS(SkinElementFlags, SkinElementFlag)
+
+ // draws skin element
+ static void drawSkinElement(SkinElements element, QPainter *painter,
+ const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags);
+ // draws a specific skin part
+ static void drawSkinPart(QS60StyleEnums::SkinParts part, QPainter *painter,
+ const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags);
+ // sets style property
+ void setStyleProperty(const char *name, const QVariant &value);
+ // sets specific style property
+ void setStyleProperty_specific(const char *name, const QVariant &value);
+ // gets style property
+ QVariant styleProperty(const char *name) const;
+ // gets specific style property
+ QVariant styleProperty_specific(const char *name) const;
+ // gets pixel metrics value
+ static short pixelMetric(int metric);
+ // gets color. 'index' is NOT 0-based.
+ // It corresponds to the enum key 1-based numbers of TAknsQsnXYZColorsIndex, not the values.
+ static QColor s60Color(QS60StyleEnums::ColorLists list,
+ int index, const QStyleOption *option);
+ // gets state specific color
+ static QColor stateColor(const QColor &color, const QStyleOption *option);
+ // gets lighter color than base color
+ static QColor lighterColor(const QColor &baseColor);
+ //deduces if the given widget should have separately themeable background
+ static bool drawsOwnThemeBackground(const QWidget *widget);
+
+ QFont s60Font(QS60StyleEnums::FontCategories fontCategory,
+ int pointSize = -1) const;
+ // clears all style caches (fonts, colors, pixmaps)
+ void clearCaches(CacheClearReason reason = CC_UndefinedChange);
+
+ // themed main background oprations
+ void setBackgroundTexture(QApplication *application) const;
+ static void deleteBackground();
+
+ static bool isTouchSupported();
+ static bool isToolBarBackground();
+
+ // calculates average color based on button skin graphics (minus borders).
+ QColor colorFromFrameGraphics(SkinFrameElements frame) const;
+
+ //set theme palette for application
+ void setThemePalette(QApplication *application) const;
+ //set theme palette for style option
+ void setThemePalette(QStyleOption *option) const;
+ //access to theme palette
+ static QPalette* themePalette();
+
+ static int focusRectPenWidth();
+
+ static const layoutHeader m_layoutHeaders[];
+ static const short data[][MAX_PIXELMETRICS];
+
+ void setCurrentLayout(int layoutIndex);
+ void setActiveLayout();
+ // Pointer
+ static short const *m_pmPointer;
+ // number of layouts supported by the style
+ static const int m_numberOfLayouts;
+
+ mutable QHash<QPair<QS60StyleEnums::FontCategories , int>, QFont> m_mappedFontsCache;
+ mutable QHash<SkinFrameElements, QColor> m_colorCache;
+
+ // Has one entry per SkinFrameElements
+ static const struct frameElementCenter {
+ SkinElements element;
+ QS60StyleEnums::SkinParts center;
+ } m_frameElementsData[];
+
+ static QPixmap frame(SkinFrameElements frame, const QSize &size,
+ SkinElementFlags flags = KDefaultSkinElementFlags);
+ static QPixmap backgroundTexture();
+
+private:
+ static void drawPart(QS60StyleEnums::SkinParts part, QPainter *painter,
+ const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags);
+ static void drawRow(QS60StyleEnums::SkinParts start, QS60StyleEnums::SkinParts middle,
+ QS60StyleEnums::SkinParts end, Qt::Orientation orientation, QPainter *painter,
+ const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags);
+ static void drawFrame(SkinFrameElements frame, QPainter *painter,
+ const QRect &rect, SkinElementFlags flags = KDefaultSkinElementFlags);
+
+ static QPixmap cachedPart(QS60StyleEnums::SkinParts part, const QSize &size,
+ SkinElementFlags flags = KDefaultSkinElementFlags);
+ static QPixmap cachedFrame(SkinFrameElements frame, const QSize &size,
+ SkinElementFlags flags = KDefaultSkinElementFlags);
+
+ static void refreshUI();
+
+ // set S60 font for widget
+ void setFont(QWidget *widget) const;
+ void setThemePalette(QWidget *widget) const;
+ void setThemePalette(QPalette *palette) const;
+ void setThemePaletteHash(QPalette *palette) const;
+ static void storeThemePalette(QPalette *palette);
+ static void deleteThemePalette();
+
+ static QSize partSize(QS60StyleEnums::SkinParts part,
+ SkinElementFlags flags = KDefaultSkinElementFlags);
+ static QPixmap part(QS60StyleEnums::SkinParts part, const QSize &size,
+ SkinElementFlags flags = KDefaultSkinElementFlags);
+
+ static QFont s60Font_specific(QS60StyleEnums::FontCategories fontCategory, int pointSize);
+
+ static QSize screenSize();
+
+ // Contains background texture.
+ static QPixmap *m_background;
+ const static SkinElementFlags KDefaultSkinElementFlags;
+ // defined theme palette
+ static QPalette *m_themePalette;
+ QPalette m_originalPalette;
+};
+
+QT_END_NAMESPACE
+
+#endif // QS60STYLE_P_H
diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp
new file mode 100644
index 0000000..63346da
--- /dev/null
+++ b/src/gui/styles/qs60style_s60.cpp
@@ -0,0 +1,1372 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qs60style.h"
+#include "qs60style_p.h"
+#include "qpainter.h"
+#include "qstyleoption.h"
+#include "qstyle.h"
+#include "private/qwindowsurface_s60_p.h"
+#include "private/qt_s60_p.h"
+#include "private/qcore_symbian_p.h"
+#include "qapplication.h"
+
+#include <w32std.h>
+#include <aknsconstants.h>
+#include <aknconsts.h>
+#include <aknsitemid.h>
+#include <aknsutils.h>
+#include <aknsdrawutils.h>
+#include <aknsskininstance.h>
+#include <aknsbasicbackgroundcontrolcontext.h>
+#include <avkon.mbg>
+#include <AknFontAccess.h>
+#include <AknLayoutFont.h>
+#include <aknutils.h>
+
+#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN)
+
+QT_BEGIN_NAMESPACE
+
+enum TDrawType {
+ EDrawIcon,
+ EDrawBackground,
+ ENoDraw
+};
+
+enum TSupportRelease {
+ ES60_None = 0x0000, //indicates that the commonstyle should draw the graphics
+ ES60_3_1 = 0x0001,
+ ES60_3_2 = 0x0002,
+ ES60_5_0 = 0x0004,
+ ES60_5_1 = 0x0008,
+ ES60_5_2 = 0x0010,
+ // Add all new releases here
+ ES60_AllReleases = ES60_3_1 | ES60_3_2 | ES60_5_0 | ES60_5_1 | ES60_5_2
+};
+
+typedef struct {
+ const TAknsItemID &skinID;
+ TDrawType drawType;
+ int supportInfo;
+ int newMajorSkinId;
+ int newMinorSkinId;
+} partMapEntry;
+
+class QS60StyleModeSpecifics
+{
+public:
+ static QPixmap skinnedGraphics(QS60StyleEnums::SkinParts stylepart,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static QPixmap skinnedGraphics(QS60StylePrivate::SkinFrameElements frameElement, const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static QPixmap colorSkinnedGraphics(const QS60StyleEnums::SkinParts &stylepart,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static QColor colorValue(const TAknsItemID &colorGroup, int colorIndex);
+ static QPixmap fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask, QS60StylePrivate::SkinElementFlags flags, QImage::Format format);
+ static bool disabledPartGraphic(QS60StyleEnums::SkinParts &part);
+ static bool disabledFrameGraphic(QS60StylePrivate::SkinFrameElements &frame);
+ static QPixmap generateMissingThemeGraphic(QS60StyleEnums::SkinParts &part, const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+
+private:
+ static QPixmap createSkinnedGraphicsL(QS60StyleEnums::SkinParts part,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static QPixmap createSkinnedGraphicsL(QS60StylePrivate::SkinFrameElements frameElement, const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static QPixmap colorSkinnedGraphicsL(const QS60StyleEnums::SkinParts &stylepart,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static void frameIdAndCenterId(QS60StylePrivate::SkinFrameElements frameElement, TAknsItemID &frameId, TAknsItemID &centerId);
+ static TRect innerRectFromElement(QS60StylePrivate::SkinFrameElements frameElement, const TRect &outerRect);
+ static void checkAndUnCompressBitmapL(CFbsBitmap*& aOriginalBitmap);
+ static void checkAndUnCompressBitmap(CFbsBitmap*& aOriginalBitmap);
+ static void unCompressBitmapL(const TRect& aTrgRect, CFbsBitmap* aTrgBitmap, CFbsBitmap* aSrcBitmap);
+ static void colorGroupAndIndex(QS60StyleEnums::SkinParts skinID,
+ TAknsItemID &colorGroup, int colorIndex);
+ static void fallbackInfo(const QS60StyleEnums::SkinParts &stylepart, TDes& fallbackFileName, TInt& fallbackIndex);
+ static bool checkSupport(const int supportedRelease);
+ static TAknsItemID checkAndUpdateReleaseSpecificGraphics(int part);
+ // Array to match the skin ID, fallback graphics and Qt widget graphics.
+ static const partMapEntry m_partMap[];
+};
+
+const partMapEntry QS60StyleModeSpecifics::m_partMap[] = {
+ /* SP_QgnGrafBarWait */ {KAknsIIDQgnGrafBarWaitAnim, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafBarFrameCenter */ {KAknsIIDQgnGrafBarFrameCenter, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafBarFrameSideL */ {KAknsIIDQgnGrafBarFrameSideL, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafBarFrameSideR */ {KAknsIIDQgnGrafBarFrameSideR, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafBarProgress */ {KAknsIIDQgnGrafBarProgress, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafScrollArrowDown */ {KAknsIIDQgnGrafScrollArrowDown, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafScrollArrowLeft */ {KAknsIIDQgnGrafScrollArrowLeft, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafScrollArrowRight */ {KAknsIIDQgnGrafScrollArrowRight, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafScrollArrowUp */ {KAknsIIDQgnGrafScrollArrowUp, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafTabActiveL */ {KAknsIIDQgnGrafTabActiveL, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafTabActiveM */ {KAknsIIDQgnGrafTabActiveM, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafTabActiveR */ {KAknsIIDQgnGrafTabActiveR, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafTabPassiveL */ {KAknsIIDQgnGrafTabPassiveL, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafTabPassiveM */ {KAknsIIDQgnGrafTabPassiveM, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnGrafTabPassiveR */ {KAknsIIDQgnGrafTabPassiveR, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiCheckboxOff */ {KAknsIIDQgnIndiCheckboxOff, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiCheckboxOn */ {KAknsIIDQgnIndiCheckboxOn, EDrawIcon, ES60_AllReleases, -1,-1},
+ // Following 5 items (SP_QgnIndiHlColSuper - SP_QgnIndiHlLineStraight) are available starting from S60 release 3.2.
+ // In 3.1 CommonStyle drawing is used for these QTreeView elements, since no similar icons in AVKON UI.
+ /* SP_QgnIndiHlColSuper */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d5 /* KAknsIIDQgnIndiHlColSuper */},
+ /* SP_QgnIndiHlExpSuper */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d6 /* KAknsIIDQgnIndiHlExpSuper */},
+ /* SP_QgnIndiHlLineBranch */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d7 /* KAknsIIDQgnIndiHlLineBranch */},
+ /* SP_QgnIndiHlLineEnd */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d8 /* KAknsIIDQgnIndiHlLineEnd */},
+ /* SP_QgnIndiHlLineStraight */ {KAknsIIDNone, EDrawIcon, ES60_3_1, EAknsMajorGeneric, 0x17d9 /* KAknsIIDQgnIndiHlLineStraight */},
+ /* SP_QgnIndiMarkedAdd */ {KAknsIIDQgnIndiMarkedAdd, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiNaviArrowLeft */ {KAknsIIDQgnGrafScrollArrowLeft, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiNaviArrowRight */ {KAknsIIDQgnGrafScrollArrowRight, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiRadiobuttOff */ {KAknsIIDQgnIndiRadiobuttOff, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiRadiobuttOn */ {KAknsIIDQgnIndiRadiobuttOn, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiSliderEdit */ {KAknsIIDQgnIndiSliderEdit, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnIndiSubMenu */ {KAknsIIDQgnIndiSubmenu, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnNoteErased */ {KAknsIIDQgnNoteErased, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnNoteError */ {KAknsIIDQgnNoteError, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnNoteInfo */ {KAknsIIDQgnNoteInfo, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnNoteOk */ {KAknsIIDQgnNoteOk, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnNoteQuery */ {KAknsIIDQgnNoteQuery, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnNoteWarning */ {KAknsIIDQgnNoteWarning, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnPropFileSmall */ {KAknsIIDQgnPropFileSmall, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnPropFolderCurrent */ {KAknsIIDQgnPropFolderCurrent, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnPropFolderSmall */ {KAknsIIDQgnPropFolderSmall, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnPropFolderSmallNew */ {KAknsIIDQgnPropFolderSmallNew, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QgnPropPhoneMemcLarge */ {KAknsIIDQgnPropPhoneMemcLarge, EDrawIcon, ES60_AllReleases, -1,-1},
+
+ // 3.1 & 3.2 do not have pressed state for scrollbar, so use normal scrollbar graphics instead.
+ /* SP_QsnCpScrollHandleBottomPressed*/ {KAknsIIDQsnCpScrollHandleBottom, EDrawIcon, ES60_3_1 | ES60_3_2, EAknsMajorGeneric, 0x20f8}, /*KAknsIIDQsnCpScrollHandleBottomPressed*/
+ /* SP_QsnCpScrollHandleMiddlePressed*/ {KAknsIIDQsnCpScrollHandleMiddle, EDrawIcon, ES60_3_1 | ES60_3_2, EAknsMajorGeneric, 0x20f9}, /*KAknsIIDQsnCpScrollHandleMiddlePressed*/
+ /* SP_QsnCpScrollHandleTopPressed*/ {KAknsIIDQsnCpScrollHandleTop, EDrawIcon, ES60_3_1 | ES60_3_2, EAknsMajorGeneric, 0x20fa}, /*KAknsIIDQsnCpScrollHandleTopPressed*/
+
+ /* SP_QsnBgScreen */ {KAknsIIDQsnBgScreen, EDrawBackground, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnCpScrollBgBottom */ {KAknsIIDQsnCpScrollBgBottom, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QsnCpScrollBgMiddle */ {KAknsIIDQsnCpScrollBgMiddle, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QsnCpScrollBgTop */ {KAknsIIDQsnCpScrollBgTop, EDrawIcon, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnCpScrollHandleBottom */ {KAknsIIDQsnCpScrollHandleBottom, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QsnCpScrollHandleMiddle */ {KAknsIIDQsnCpScrollHandleMiddle, EDrawIcon, ES60_AllReleases, -1,-1},
+ /* SP_QsnCpScrollHandleTop */ {KAknsIIDQsnCpScrollHandleTop, EDrawIcon, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrButtonTbCornerTl */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_AllReleases, -1,-1}, //todo: use "normal button" from 5.0 onwards
+ /* SP_QsnFrButtonTbCornerTr */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCornerBl */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCornerBr */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideT */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideB */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideL */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideR */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCenter */ {KAknsIIDQsnFrButtonTbCenter, EDrawIcon, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrButtonTbCornerTlPressed */{KAknsIIDQsnFrButtonTbCornerTlPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCornerTrPressed */{KAknsIIDQsnFrButtonTbCornerTrPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCornerBlPressed */{KAknsIIDQsnFrButtonTbCornerBlPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCornerBrPressed */{KAknsIIDQsnFrButtonTbCornerBrPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideTPressed */ {KAknsIIDQsnFrButtonTbSideTPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideBPressed */ {KAknsIIDQsnFrButtonTbSideBPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideLPressed */ {KAknsIIDQsnFrButtonTbSideLPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbSideRPressed */ {KAknsIIDQsnFrButtonTbSideRPressed, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrButtonTbCenterPressed */ {KAknsIIDQsnFrButtonTbCenterPressed, EDrawIcon, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrCaleCornerTl */ {KAknsIIDQsnFrCaleCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleCornerTr */ {KAknsIIDQsnFrCaleCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleCornerBl */ {KAknsIIDQsnFrCaleCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleCornerBr */ {KAknsIIDQsnFrCaleCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleGSideT */ {KAknsIIDQsnFrCaleSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleGSideB */ {KAknsIIDQsnFrCaleSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleGSideL */ {KAknsIIDQsnFrCaleSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleGSideR */ {KAknsIIDQsnFrCaleSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleCenter */ {KAknsIIDQsnFrCaleCenter, ENoDraw, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrCaleHeadingCornerTl */ {KAknsIIDQsnFrCaleHeadingCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingCornerTr */ {KAknsIIDQsnFrCaleHeadingCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingCornerBl */ {KAknsIIDQsnFrCaleHeadingCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingCornerBr */ {KAknsIIDQsnFrCaleHeadingCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingSideT */ {KAknsIIDQsnFrCaleHeadingSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingSideB */ {KAknsIIDQsnFrCaleHeadingSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingSideL */ {KAknsIIDQsnFrCaleHeadingSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingSideR */ {KAknsIIDQsnFrCaleHeadingSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrCaleHeadingCenter */ {KAknsIIDQsnFrCaleHeadingCenter, ENoDraw, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrInputCornerTl */ {KAknsIIDQsnFrInputCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputCornerTr */ {KAknsIIDQsnFrInputCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputCornerBl */ {KAknsIIDQsnFrInputCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputCornerBr */ {KAknsIIDQsnFrInputCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputSideT */ {KAknsIIDQsnFrInputSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputSideB */ {KAknsIIDQsnFrInputSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputSideL */ {KAknsIIDQsnFrInputSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputSideR */ {KAknsIIDQsnFrInputSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrInputCenter */ {KAknsIIDQsnFrInputCenter, ENoDraw, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrListCornerTl */ {KAknsIIDQsnFrListCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListCornerTr */ {KAknsIIDQsnFrListCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListCornerBl */ {KAknsIIDQsnFrListCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListCornerBr */ {KAknsIIDQsnFrListCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListSideT */ {KAknsIIDQsnFrListSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListSideB */ {KAknsIIDQsnFrListSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListSideL */ {KAknsIIDQsnFrListSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListSideR */ {KAknsIIDQsnFrListSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrListCenter */ {KAknsIIDQsnFrListCenter, ENoDraw, ES60_AllReleases, -1,-1},
+
+ /* SP_QsnFrPopupCornerTl */ {KAknsIIDQsnFrPopupCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupCornerTr */ {KAknsIIDQsnFrPopupCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupCornerBl */ {KAknsIIDQsnFrPopupCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupCornerBr */ {KAknsIIDQsnFrPopupCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupSideT */ {KAknsIIDQsnFrPopupSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupSideB */ {KAknsIIDQsnFrPopupSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupSideL */ {KAknsIIDQsnFrPopupSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupSideR */ {KAknsIIDQsnFrPopupSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrPopupCenter */ {KAknsIIDQsnFrPopupCenter, ENoDraw, ES60_AllReleases, -1,-1},
+
+ // ToolTip graphics different in 3.1 vs. 3.2+.
+ /* SP_QsnFrPopupPreviewCornerTl */ {KAknsIIDQsnFrPopupCornerTl, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c5}, /* KAknsIIDQsnFrPopupPreviewCornerTl */
+ /* SP_QsnFrPopupPreviewCornerTr */ {KAknsIIDQsnFrPopupCornerTr, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c6},
+ /* SP_QsnFrPopupPreviewCornerBl */ {KAknsIIDQsnFrPopupCornerBl, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c3},
+ /* SP_QsnFrPopupPreviewCornerBr */ {KAknsIIDQsnFrPopupCornerBr, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c4},
+ /* SP_QsnFrPopupPreviewSideT */ {KAknsIIDQsnFrPopupSideT, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19ca},
+ /* SP_QsnFrPopupPreviewSideB */ {KAknsIIDQsnFrPopupSideB, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c7},
+ /* SP_QsnFrPopupPreviewSideL */ {KAknsIIDQsnFrPopupSideL, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c8},
+ /* SP_QsnFrPopupPreviewSideR */ {KAknsIIDQsnFrPopupSideR, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c9},
+ /* SP_QsnFrPopupPreviewCenter */ {KAknsIIDQsnFrPopupCenter, ENoDraw, ES60_3_1, EAknsMajorSkin, 0x19c2},
+
+ /* SP_QsnFrSetOptCornerTl */ {KAknsIIDQsnFrSetOptCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptCornerTr */ {KAknsIIDQsnFrSetOptCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptCornerBl */ {KAknsIIDQsnFrSetOptCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptCornerBr */ {KAknsIIDQsnFrSetOptCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptSideT */ {KAknsIIDQsnFrSetOptSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptSideB */ {KAknsIIDQsnFrSetOptSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptSideL */ {KAknsIIDQsnFrSetOptSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptSideR */ {KAknsIIDQsnFrSetOptSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrSetOptCenter */ {KAknsIIDQsnFrSetOptCenter, ENoDraw, ES60_AllReleases, -1,-1},
+
+ // No toolbar frame for 5.0+ releases.
+ /* SP_QsnFrPopupSubCornerTl */ {KAknsIIDQsnFrPopupSubCornerTl, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubCornerTr */ {KAknsIIDQsnFrPopupSubCornerTr, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubCornerBl */ {KAknsIIDQsnFrPopupSubCornerBl, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubCornerBr */ {KAknsIIDQsnFrPopupSubCornerBr, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubSideT */ {KAknsIIDQsnFrPopupSubSideT, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubSideB */ {KAknsIIDQsnFrPopupSubSideB, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubSideL */ {KAknsIIDQsnFrPopupSubSideL, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubSideR */ {KAknsIIDQsnFrPopupSubSideR, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+ /* SP_QsnFrPopupSubCenter */ {KAknsIIDQsnFrPopupCenterSubmenu, ENoDraw, ES60_3_1 | ES60_3_2, -1,-1},
+
+ // Toolbar graphics is different in 3.1/3.2 vs. 5.0
+ /* SP_QsnFrSctrlButtonCornerTl */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2301}, /* KAknsIIDQgnFrSctrlButtonCornerTl*/
+ /* SP_QsnFrSctrlButtonCornerTr */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2302},
+ /* SP_QsnFrSctrlButtonCornerBl */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2303},
+ /* SP_QsnFrSctrlButtonCornerBr */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2304},
+ /* SP_QsnFrSctrlButtonSideT */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2305},
+ /* SP_QsnFrSctrlButtonSideB */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2306},
+ /* SP_QsnFrSctrlButtonSideL */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2307},
+ /* SP_QsnFrSctrlButtonSideR */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2308},
+ /* SP_QsnFrSctrlButtonCenter */ {KAknsIIDQsnFrButtonTbCenter, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2309}, /*KAknsIIDQgnFrSctrlButtonCenter*/
+
+ // No pressed state for toolbar button in 3.1/3.2.
+ /* SP_QsnFrSctrlButtonCornerTlPressed */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2621}, /*KAknsIIDQsnFrSctrlButtonCornerTlPressed*/
+ /* SP_QsnFrSctrlButtonCornerTrPressed */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2622},
+ /* SP_QsnFrSctrlButtonCornerBlPressed */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2623},
+ /* SP_QsnFrSctrlButtonCornerBrPressed */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2624},
+ /* SP_QsnFrSctrlButtonSideTPressed */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2625},
+ /* SP_QsnFrSctrlButtonSideBPressed */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2626},
+ /* SP_QsnFrSctrlButtonSideLPressed */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2627},
+ /* SP_QsnFrSctrlButtonSideRPressed */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2628},
+ /* SP_QsnFrSctrlButtonCenterPressed */ {KAknsIIDQsnFrButtonTbCenter, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x2629},
+
+ // No inactive button graphics in 3.1/3.2
+ /* SP_QsnFrButtonCornerTlInactive */ {KAknsIIDQsnFrButtonTbCornerTl, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b1}, /*KAknsIIDQsnFrButtonCornerTlInactive*/
+ /* SP_QsnFrButtonCornerTrInactive */ {KAknsIIDQsnFrButtonTbCornerTr, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b2},
+ /* SP_QsnFrButtonCornerBlInactive */ {KAknsIIDQsnFrButtonTbCornerBl, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b3},
+ /* SP_QsnFrButtonCornerTrInactive */ {KAknsIIDQsnFrButtonTbCornerBr, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b4},
+ /* SP_QsnFrButtonSideTInactive */ {KAknsIIDQsnFrButtonTbSideT, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b5},
+ /* SP_QsnFrButtonSideBInactive */ {KAknsIIDQsnFrButtonTbSideB, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b6},
+ /* SP_QsnFrButtonSideLInactive */ {KAknsIIDQsnFrButtonTbSideL, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b7},
+ /* SP_QsnFrButtonSideRInactive */ {KAknsIIDQsnFrButtonTbSideR, ENoDraw, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b8},
+ /* SP_QsnFrButtonCenterInactive */ {KAknsIIDQsnFrButtonTbCenter, EDrawIcon, ES60_3_1 | ES60_3_2, EAknsMajorSkin, 0x21b9},
+
+ /* SP_QsnFrNotepadCornerTl */ {KAknsIIDQsnFrNotepadContCornerTl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadCornerTr */ {KAknsIIDQsnFrNotepadContCornerTr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadCornerBl */ {KAknsIIDQsnFrNotepadCornerBl, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadCornerBr */ {KAknsIIDQsnFrNotepadCornerBr, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadSideT */ {KAknsIIDQsnFrNotepadContSideT, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadSideB */ {KAknsIIDQsnFrNotepadSideB, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadSideL */ {KAknsIIDQsnFrNotepadSideL, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadSideR */ {KAknsIIDQsnFrNotepadSideR, ENoDraw, ES60_AllReleases, -1,-1},
+ /* SP_QsnFrNotepadCenter */ {KAknsIIDQsnFrNotepadCenter, EDrawIcon, ES60_AllReleases, -1,-1},
+
+};
+
+QPixmap QS60StyleModeSpecifics::skinnedGraphics(
+ QS60StyleEnums::SkinParts stylepart, const QSize &size,
+ QS60StylePrivate::SkinElementFlags flags)
+{
+ QPixmap themedImage;
+ TRAPD( error, {
+ const QPixmap skinnedImage = createSkinnedGraphicsL(stylepart, size, flags);
+ themedImage = skinnedImage;
+ });
+ if (error)
+ return themedImage = QPixmap();
+ return themedImage;
+}
+
+QPixmap QS60StyleModeSpecifics::skinnedGraphics(
+ QS60StylePrivate::SkinFrameElements frame, const QSize &size, QS60StylePrivate::SkinElementFlags flags)
+{
+ QPixmap themedImage;
+ TRAPD( error, {
+ const QPixmap skinnedImage = createSkinnedGraphicsL(frame, size, flags);
+ themedImage = skinnedImage;
+ });
+ if (error)
+ return themedImage = QPixmap();
+ return themedImage;
+}
+
+QPixmap QS60StyleModeSpecifics::colorSkinnedGraphics(
+ const QS60StyleEnums::SkinParts &stylepart,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags)
+{
+ QPixmap colorGraphics;
+ TRAPD(error, colorGraphics = colorSkinnedGraphicsL(stylepart, size, flags));
+ return error ? QPixmap() : colorGraphics;
+}
+
+void QS60StyleModeSpecifics::fallbackInfo(const QS60StyleEnums::SkinParts &stylepart, TDes& fallbackFileName, TInt& fallbackIndex)
+{
+ switch(stylepart) {
+ case QS60StyleEnums::SP_QgnGrafBarWait:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_bar_wait_1;
+ break;
+ case QS60StyleEnums::SP_QgnGrafBarFrameCenter:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_bar_frame_center;
+ break;
+ case QS60StyleEnums::SP_QgnGrafBarFrameSideL:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_bar_frame_side_l;
+ break;
+ case QS60StyleEnums::SP_QgnGrafBarFrameSideR:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_bar_frame_side_r;
+ break;
+ case QS60StyleEnums::SP_QgnGrafBarProgress:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_bar_progress;
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabActiveL:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_tab_active_l;
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabActiveM:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_tab_active_m;
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabActiveR:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_tab_active_r;
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabPassiveL:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_tab_passive_l;
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabPassiveM:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_tab_passive_m;
+ break;
+ case QS60StyleEnums::SP_QgnGrafTabPassiveR:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_graf_tab_passive_r;
+ break;
+ case QS60StyleEnums::SP_QgnIndiCheckboxOff:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_checkbox_off;
+ break;
+ case QS60StyleEnums::SP_QgnIndiCheckboxOn:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_checkbox_on;
+ break;
+ case QS60StyleEnums::SP_QgnIndiHlColSuper:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = 0x4456; /* EMbmAvkonQgn_indi_hl_col_super */
+ break;
+ case QS60StyleEnums::SP_QgnIndiHlExpSuper:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = 0x4458; /* EMbmAvkonQgn_indi_hl_exp_super */
+ break;
+ case QS60StyleEnums::SP_QgnIndiHlLineBranch:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = 0x445A; /* EMbmAvkonQgn_indi_hl_line_branch */
+ break;
+ case QS60StyleEnums::SP_QgnIndiHlLineEnd:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = 0x445C; /* EMbmAvkonQgn_indi_hl_line_end */
+ break;
+ case QS60StyleEnums::SP_QgnIndiHlLineStraight:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = 0x445E; /* EMbmAvkonQgn_indi_hl_line_straight */
+ break;
+ case QS60StyleEnums::SP_QgnIndiMarkedAdd:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_marked_add;
+ break;
+ case QS60StyleEnums::SP_QgnIndiNaviArrowLeft:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_navi_arrow_left;
+ break;
+ case QS60StyleEnums::SP_QgnIndiNaviArrowRight:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_navi_arrow_right;
+ break;
+ case QS60StyleEnums::SP_QgnIndiRadiobuttOff:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_radiobutt_off;
+ break;
+ case QS60StyleEnums::SP_QgnIndiRadiobuttOn:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_radiobutt_on;
+ break;
+ case QS60StyleEnums::SP_QgnIndiSliderEdit:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_slider_edit;
+ break;
+ case QS60StyleEnums::SP_QgnIndiSubMenu:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_indi_submenu;
+ break;
+ case QS60StyleEnums::SP_QgnNoteErased:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_note_erased;
+ break;
+ case QS60StyleEnums::SP_QgnNoteError:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_note_error;
+ break;
+ case QS60StyleEnums::SP_QgnNoteInfo:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_note_info;
+ break;
+ case QS60StyleEnums::SP_QgnNoteOk:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_note_ok;
+ break;
+ case QS60StyleEnums::SP_QgnNoteQuery:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_note_query;
+ break;
+ case QS60StyleEnums::SP_QgnNoteWarning:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_note_warning;
+ break;
+ case QS60StyleEnums::SP_QgnPropFileSmall:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_prop_file_small;
+ break;
+ case QS60StyleEnums::SP_QgnPropFolderCurrent:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_prop_folder_current;
+ break;
+ case QS60StyleEnums::SP_QgnPropFolderSmall:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_prop_folder_small;
+ break;
+ case QS60StyleEnums::SP_QgnPropFolderSmallNew:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_prop_folder_small_new;
+ break;
+ case QS60StyleEnums::SP_QgnPropPhoneMemcLarge:
+ fallbackFileName = KAvkonBitmapFile();
+ fallbackIndex = EMbmAvkonQgn_prop_phone_memc_large;
+ break;
+ default:
+ fallbackFileName = KNullDesC();
+ fallbackIndex = -1;
+ break;
+ }
+}
+
+QPixmap QS60StyleModeSpecifics::colorSkinnedGraphicsL(
+ const QS60StyleEnums::SkinParts &stylepart,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags)
+{
+ const int stylepartIndex = (int)stylepart;
+ const TAknsItemID skinId = m_partMap[stylepartIndex].skinID;
+
+ TInt fallbackGraphicID = -1;
+ HBufC* iconFile = HBufC::NewLC( KMaxFileName );
+ TPtr fileNamePtr = iconFile->Des();
+ fallbackInfo(stylepart, fileNamePtr, fallbackGraphicID);
+
+ TAknsItemID colorGroup = KAknsIIDQsnIconColors;
+ int colorIndex = 0;
+ colorGroupAndIndex(stylepart, colorGroup, colorIndex);
+
+ const bool rotatedBy90or270 =
+ (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest));
+ const TSize targetSize =
+ rotatedBy90or270?TSize(size.height(), size.width()):TSize(size.width(), size.height());
+ CFbsBitmap *icon = 0;
+ CFbsBitmap *iconMask = 0;
+ const TInt fallbackGraphicsMaskID =
+ fallbackGraphicID == KErrNotFound?KErrNotFound:fallbackGraphicID+1; //masks are auto-generated as next in mif files
+ MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
+ AknsUtils::CreateColorIconLC(
+ skinInstance, skinId, colorGroup, colorIndex, icon, iconMask, fileNamePtr, fallbackGraphicID , fallbackGraphicsMaskID, KRgbBlack);
+ User::LeaveIfError(AknIconUtils::SetSize(icon, targetSize, EAspectRatioNotPreserved));
+ User::LeaveIfError(AknIconUtils::SetSize(iconMask, targetSize, EAspectRatioNotPreserved));
+ QPixmap result = fromFbsBitmap(icon, iconMask, flags, qt_TDisplayMode2Format(icon->DisplayMode()));
+ CleanupStack::PopAndDestroy(3); //icon, iconMask, iconFile
+ return result;
+}
+
+QColor QS60StyleModeSpecifics::colorValue(const TAknsItemID &colorGroup, int colorIndex)
+{
+ TRgb skinnedColor;
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ AknsUtils::GetCachedColor(skin, skinnedColor, colorGroup, colorIndex);
+ return QColor(skinnedColor.Red(),skinnedColor.Green(),skinnedColor.Blue());
+}
+
+QPixmap QS60StyleModeSpecifics::fromFbsBitmap(CFbsBitmap *icon, CFbsBitmap *mask, QS60StylePrivate::SkinElementFlags flags, QImage::Format format)
+{
+ Q_ASSERT(icon);
+ const TSize iconSize = icon->SizeInPixels();
+ const int iconBytesPerLine = CFbsBitmap::ScanLineLength(iconSize.iWidth, icon->DisplayMode());
+ const int iconBytesCount = iconBytesPerLine * iconSize.iHeight;
+
+ QImage iconImage(qt_TSize2QSize(iconSize), format);
+ if (iconImage.isNull())
+ return QPixmap();
+
+ checkAndUnCompressBitmap(icon);
+ if (!icon) //checkAndUnCompressBitmap might set icon to NULL
+ return QPixmap();
+
+ icon->LockHeap();
+ const uchar *const iconBytes = (uchar*)icon->DataAddress();
+ // The icon data needs to be copied, since the color format will be
+ // automatically converted to Format_ARGB32 when setAlphaChannel is called.
+ memcpy(iconImage.bits(), iconBytes, iconBytesCount);
+ icon->UnlockHeap();
+ if (mask) {
+ checkAndUnCompressBitmap(mask);
+ if (mask) { //checkAndUnCompressBitmap might set mask to NULL
+ const TSize maskSize = icon->SizeInPixels();
+ const int maskBytesPerLine = CFbsBitmap::ScanLineLength(maskSize.iWidth, mask->DisplayMode());
+ mask->LockHeap();
+ const uchar *const maskBytes = (uchar *)mask->DataAddress();
+ // Since no other bitmap should be locked, we can just "borrow" the mask data for setAlphaChannel
+ const QImage maskImage(maskBytes, maskSize.iWidth, maskSize.iHeight, maskBytesPerLine, QImage::Format_Indexed8);
+ if (!maskImage.isNull())
+ iconImage.setAlphaChannel(maskImage);
+ mask->UnlockHeap();
+ }
+ }
+
+ QTransform imageTransform;
+ if (flags & QS60StylePrivate::SF_PointEast) {
+ imageTransform.rotate(90);
+ } else if (flags & QS60StylePrivate::SF_PointSouth) {
+ imageTransform.rotate(180);
+ iconImage = iconImage.transformed(imageTransform);
+ } else if (flags & QS60StylePrivate::SF_PointWest) {
+ imageTransform.rotate(270);
+ }
+ if (imageTransform.isRotating())
+ iconImage = iconImage.transformed(imageTransform);
+
+ return QPixmap::fromImage(iconImage);
+}
+
+bool QS60StylePrivate::isTouchSupported()
+{
+ return bool(AknLayoutUtils::PenEnabled());
+}
+
+bool QS60StylePrivate::isToolBarBackground()
+{
+ return (QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2);
+}
+
+QPoint qt_s60_fill_background_offset(const QWidget *targetWidget)
+{
+ CCoeControl *control = targetWidget->effectiveWinId();
+ TPoint globalPos = control ? control->PositionRelativeToScreen() : TPoint(0,0);
+ return QPoint(globalPos.iX, globalPos.iY);
+}
+
+QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsL(
+ QS60StyleEnums::SkinParts part,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags)
+{
+ if (!size.isValid())
+ return QPixmap();
+
+ // Check release support and change part, if necessary.
+ const TAknsItemID skinId = checkAndUpdateReleaseSpecificGraphics((int)part);
+ const int stylepartIndex = (int)part;
+ const TDrawType drawType = m_partMap[stylepartIndex].drawType;
+ Q_ASSERT(drawType != ENoDraw);
+ const bool rotatedBy90or270 =
+ (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest));
+ const TSize targetSize =
+ rotatedBy90or270 ? TSize(size.height(), size.width()) : qt_QSize2TSize(size);
+
+ MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
+
+ QPixmap result;
+
+ switch (drawType) {
+ case EDrawIcon: {
+ TInt fallbackGraphicID = -1;
+ HBufC* iconFile = HBufC::NewLC( KMaxFileName );
+ TPtr fileNamePtr = iconFile->Des();
+ fallbackInfo(part, fileNamePtr, fallbackGraphicID);
+ // todo: could we instead use AknIconUtils::AvkonIconFileName(); to avoid allocating each time?
+
+ CFbsBitmap *icon = 0;
+ CFbsBitmap *iconMask = 0;
+ const TInt fallbackGraphicsMaskID =
+ fallbackGraphicID == KErrNotFound?KErrNotFound:fallbackGraphicID+1; //masks are auto-generated as next in mif files
+ // QS60WindowSurface::unlockBitmapHeap();
+ AknsUtils::CreateIconLC(skinInstance, skinId, icon, iconMask, fileNamePtr, fallbackGraphicID , fallbackGraphicsMaskID);
+ User::LeaveIfError(AknIconUtils::SetSize(icon, targetSize, EAspectRatioNotPreserved));
+ User::LeaveIfError(AknIconUtils::SetSize(iconMask, targetSize, EAspectRatioNotPreserved));
+ result = fromFbsBitmap(icon, iconMask, flags, qt_TDisplayMode2Format(icon->DisplayMode()));
+ CleanupStack::PopAndDestroy(3); // iconMask, icon, iconFile
+ // QS60WindowSurface::lockBitmapHeap();
+ break;
+ }
+ case EDrawBackground: {
+ // QS60WindowSurface::unlockBitmapHeap();
+ CFbsBitmap *background = new (ELeave) CFbsBitmap(); //offscreen
+ CleanupStack::PushL(background);
+ User::LeaveIfError(background->Create(targetSize, EColor16MA));
+
+ CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(background);
+ CleanupStack::PushL(dev);
+ CFbsBitGc* gc = NULL;
+ User::LeaveIfError(dev->CreateContext(gc));
+ CleanupStack::PushL(gc);
+
+ CAknsBasicBackgroundControlContext* bgContext = CAknsBasicBackgroundControlContext::NewL(
+ skinId,
+ targetSize,
+ EFalse);
+ CleanupStack::PushL(bgContext);
+
+ const TBool drawn = AknsDrawUtils::DrawBackground(
+ skinInstance,
+ bgContext,
+ NULL,
+ *gc,
+ TPoint(),
+ targetSize,
+ KAknsDrawParamDefault | KAknsDrawParamRGBOnly);
+
+ if (drawn)
+ result = fromFbsBitmap(background, NULL, flags, QImage::Format_RGB32);
+
+ CleanupStack::PopAndDestroy(4, background); //background, dev, gc, bgContext
+ // QS60WindowSurface::lockBitmapHeap();
+ break;
+ }
+ }
+
+ return result;
+}
+
+QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsL(QS60StylePrivate::SkinFrameElements frameElement,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags)
+{
+ if (!size.isValid())
+ return QPixmap();
+
+ const bool rotatedBy90or270 =
+ (flags & (QS60StylePrivate::SF_PointEast | QS60StylePrivate::SF_PointWest));
+ const TSize targetSize =
+ rotatedBy90or270 ? TSize(size.height(), size.width()) : qt_QSize2TSize(size);
+
+ MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
+ QPixmap result;
+
+// QS60WindowSurface::unlockBitmapHeap();
+ static const bool canDoEColor16MAP = !(QSysInfo::s60Version() == QSysInfo::SV_S60_3_1 || QSysInfo::s60Version() == QSysInfo::SV_S60_3_2);
+ static const TDisplayMode displayMode = canDoEColor16MAP ? TDisplayMode(13) : EColor16MA; // 13 = EColor16MAP
+ static const TInt drawParam = canDoEColor16MAP ? KAknsDrawParamDefault : KAknsDrawParamNoClearUnderImage|KAknsDrawParamRGBOnly;
+
+ CFbsBitmap *frame = new (ELeave) CFbsBitmap(); //offscreen
+ CleanupStack::PushL(frame);
+ User::LeaveIfError(frame->Create(targetSize, displayMode));
+
+ CFbsBitmapDevice* bitmapDev = CFbsBitmapDevice::NewL(frame);
+ CleanupStack::PushL(bitmapDev);
+ CFbsBitGc* bitmapGc = NULL;
+ User::LeaveIfError(bitmapDev->CreateContext(bitmapGc));
+ CleanupStack::PushL(bitmapGc);
+
+ frame->LockHeap();
+ memset(frame->DataAddress(), 0, frame->SizeInPixels().iWidth * frame->SizeInPixels().iHeight * 4); // 4: argb bytes
+ frame->UnlockHeap();
+
+ const TRect outerRect(TPoint(0, 0), targetSize);
+ const TRect innerRect = innerRectFromElement(frameElement, outerRect);
+
+ TAknsItemID frameSkinID, centerSkinID;
+ frameSkinID = centerSkinID = checkAndUpdateReleaseSpecificGraphics(QS60StylePrivate::m_frameElementsData[frameElement].center);
+ frameIdAndCenterId(frameElement, frameSkinID, centerSkinID);
+ const TBool drawn = AknsDrawUtils::DrawFrame( skinInstance,
+ *bitmapGc, outerRect, innerRect,
+ frameSkinID, centerSkinID,
+ drawParam );
+
+ if (canDoEColor16MAP) {
+ if (drawn)
+ result = fromFbsBitmap(frame, NULL, flags, QImage::Format_ARGB32_Premultiplied);
+ } else {
+ TDisplayMode maskDepth = EGray2;
+ // Query the skin item for possible frame graphics mask details.
+ if (skinInstance) {
+ CAknsMaskedBitmapItemData* skinMaskedBmp = static_cast<CAknsMaskedBitmapItemData*>(
+ skinInstance->GetCachedItemData(frameSkinID,EAknsITMaskedBitmap));
+ if (skinMaskedBmp && skinMaskedBmp->Mask())
+ maskDepth = skinMaskedBmp->Mask()->DisplayMode();
+ }
+ if (maskDepth != ENone) {
+ CFbsBitmap *frameMask = new (ELeave) CFbsBitmap(); //offscreen
+ CleanupStack::PushL(frameMask);
+ User::LeaveIfError(frameMask->Create(targetSize, maskDepth));
+
+ CFbsBitmapDevice* maskBitmapDevice = CFbsBitmapDevice::NewL(frameMask);
+ CleanupStack::PushL(maskBitmapDevice);
+ CFbsBitGc* maskBitGc = NULL;
+ User::LeaveIfError(maskBitmapDevice->CreateContext(maskBitGc));
+ CleanupStack::PushL(maskBitGc);
+
+ if (drawn) {
+ //ensure that the mask is really transparent
+ maskBitGc->Activate( maskBitmapDevice );
+ maskBitGc->SetPenStyle(CGraphicsContext::ENullPen);
+ maskBitGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+ maskBitGc->SetBrushColor(KRgbWhite);
+ maskBitGc->Clear();
+ maskBitGc->SetBrushStyle(CGraphicsContext::ENullBrush);
+
+ AknsDrawUtils::DrawFrame(skinInstance,
+ *maskBitGc, outerRect, innerRect,
+ frameSkinID, centerSkinID,
+ KAknsSDMAlphaOnly |KAknsDrawParamNoClearUnderImage);
+ result = fromFbsBitmap(frame, frameMask, flags, QImage::Format_ARGB32);
+ }
+ CleanupStack::PopAndDestroy(3, frameMask);
+ }
+ }
+ CleanupStack::PopAndDestroy(3, frame); //frame, bitmapDev, bitmapGc
+ return result;
+}
+
+void QS60StyleModeSpecifics::frameIdAndCenterId(QS60StylePrivate::SkinFrameElements frameElement, TAknsItemID &frameId, TAknsItemID &centerId)
+{
+// There are some major mix-ups in skin declarations for some frames.
+// First, the frames are not declared in sequence.
+// Second, the parts use different major than the frame-master.
+
+ switch(frameElement) {
+ case QS60StylePrivate::SF_ToolTip:
+ if (QSysInfo::s60Version()!=QSysInfo::SV_S60_3_1) {
+ centerId.Set(EAknsMajorGeneric, 0x19c2);
+ frameId.Set(EAknsMajorSkin, 0x5300);
+ } else {
+ centerId.Set(KAknsIIDQsnFrPopupCenter);
+ frameId.iMinor = centerId.iMinor - 9;
+ }
+ break;
+ case QS60StylePrivate::SF_ToolBar:
+ if (QSysInfo::s60Version()==QSysInfo::SV_S60_3_1 || QSysInfo::s60Version()==QSysInfo::SV_S60_3_2) {
+ centerId.Set(KAknsIIDQsnFrPopupCenterSubmenu);
+ frameId.Set(KAknsIIDQsnFrPopupSub);
+ }
+ break;
+ case QS60StylePrivate::SF_PanelBackground:
+ // remove center piece for panel graphics, so that only border is drawn
+ centerId.Set(KAknsIIDNone);
+ frameId.Set(KAknsIIDQsnFrSetOpt);
+ break;
+ case QS60StylePrivate::SF_Editor:
+ centerId.Set(KAknsIIDQsnFrNotepadCenter);
+ frameId.Set(KAknsIIDQsnFrNotepadCont);
+ break;
+ default:
+ // center should be correct here
+ frameId.iMinor = centerId.iMinor - 9;
+ break;
+ }
+}
+
+TRect QS60StyleModeSpecifics::innerRectFromElement(QS60StylePrivate::SkinFrameElements frameElement, const TRect &outerRect)
+{
+ TInt widthShrink = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth);
+ TInt heightShrink = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerHeight);
+ switch(frameElement) {
+ case QS60StylePrivate::SF_PanelBackground:
+ // panel should have slightly slimmer border to enable thin line of background graphics between closest component
+ widthShrink = widthShrink-2;
+ heightShrink = heightShrink-2;
+ break;
+ case QS60StylePrivate::SF_ToolTip:
+ widthShrink = widthShrink>>1;
+ heightShrink = heightShrink>>1;
+ break;
+ case QS60StylePrivate::SF_ListHighlight:
+ widthShrink = widthShrink-2;
+ heightShrink = heightShrink-2;
+ break;
+ default:
+ break;
+ }
+ TRect innerRect(outerRect);
+ innerRect.Shrink(widthShrink, heightShrink);
+ return innerRect;
+}
+
+bool QS60StyleModeSpecifics::checkSupport(const int supportedRelease)
+{
+ const QSysInfo::S60Version currentRelease = QSysInfo::s60Version();
+ return ( (currentRelease == QSysInfo::SV_S60_3_1 && supportedRelease & ES60_3_1) ||
+ (currentRelease == QSysInfo::SV_S60_3_2 && supportedRelease & ES60_3_2) ||
+ (currentRelease == QSysInfo::SV_S60_5_0 && supportedRelease & ES60_5_0));
+}
+
+TAknsItemID QS60StyleModeSpecifics::checkAndUpdateReleaseSpecificGraphics(int part)
+{
+ TAknsItemID newSkinId;
+ if (!checkSupport(m_partMap[(int)part].supportInfo))
+ newSkinId.Set(m_partMap[(int)part].newMajorSkinId, m_partMap[(int)part].newMinorSkinId);
+ else
+ newSkinId.Set(m_partMap[(int)part].skinID);
+ return newSkinId;
+}
+
+void QS60StyleModeSpecifics::checkAndUnCompressBitmap(CFbsBitmap*& aOriginalBitmap)
+{
+ TRAPD(error, checkAndUnCompressBitmapL(aOriginalBitmap));
+ if (error)
+ aOriginalBitmap = NULL;
+}
+
+void QS60StyleModeSpecifics::checkAndUnCompressBitmapL(CFbsBitmap*& aOriginalBitmap)
+{
+ if (aOriginalBitmap->IsCompressedInRAM()) {
+ const TSize iconSize(aOriginalBitmap->SizeInPixels().iWidth,
+ aOriginalBitmap->SizeInPixels().iHeight);
+ CFbsBitmap* uncompressedBitmap = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL(uncompressedBitmap);
+ User::LeaveIfError(uncompressedBitmap->Create(iconSize,
+ aOriginalBitmap->DisplayMode()));
+ unCompressBitmapL(iconSize, uncompressedBitmap, aOriginalBitmap);
+ CleanupStack::Pop(uncompressedBitmap);
+ User::LeaveIfError(aOriginalBitmap->Duplicate(
+ uncompressedBitmap->Handle()));
+ delete uncompressedBitmap;
+ }
+}
+
+QFont QS60StylePrivate::s60Font_specific(
+ QS60StyleEnums::FontCategories fontCategory, int pointSize)
+{
+ TAknFontCategory aknFontCategory = EAknFontCategoryUndefined;
+ switch (fontCategory) {
+ case QS60StyleEnums::FC_Primary:
+ aknFontCategory = EAknFontCategoryPrimary;
+ break;
+ case QS60StyleEnums::FC_Secondary:
+ aknFontCategory = EAknFontCategorySecondary;
+ break;
+ case QS60StyleEnums::FC_Title:
+ aknFontCategory = EAknFontCategoryTitle;
+ break;
+ case QS60StyleEnums::FC_PrimarySmall:
+ aknFontCategory = EAknFontCategoryPrimarySmall;
+ break;
+ case QS60StyleEnums::FC_Digital:
+ aknFontCategory = EAknFontCategoryDigital;
+ break;
+ case QS60StyleEnums::FC_Undefined:
+ default:
+ break;
+ }
+
+ // Create AVKON font according the given parameters
+ CWsScreenDevice* dev = CCoeEnv::Static()->ScreenDevice();
+ TAknFontSpecification spec(aknFontCategory, TFontSpec(), NULL);
+ if (pointSize > 0) {
+ const TInt pixelSize = dev->VerticalTwipsToPixels(pointSize * KTwipsPerPoint);
+ spec.SetTextPaneHeight(pixelSize + 4); // TODO: Is 4 a reasonable top+bottom margin?
+ }
+
+ QFont result;
+ TRAPD( error, {
+ const CAknLayoutFont* aknFont =
+ AknFontAccess::CreateLayoutFontFromSpecificationL(*dev, spec);
+
+ result = qt_TFontSpec2QFontL(aknFont->DoFontSpecInTwips());
+ if (result.pointSize() != pointSize)
+ result.setPointSize(pointSize); // Correct the font size returned by CreateLayoutFontFromSpecificationL()
+
+ delete aknFont;
+ });
+ if (error) result = QFont();
+ return result;
+}
+
+void QS60StylePrivate::setActiveLayout()
+{
+ const QSize activeScreenSize(screenSize());
+ int activeLayoutIndex = -1;
+ const bool mirrored = !QApplication::isLeftToRight();
+ const short screenHeight = (short)activeScreenSize.height();
+ const short screenWidth = (short)activeScreenSize.width();
+ for (int i=0; i<m_numberOfLayouts; i++) {
+ if (screenHeight==m_layoutHeaders[i].height &&
+ screenWidth==m_layoutHeaders[i].width &&
+ mirrored==m_layoutHeaders[i].mirroring) {
+ activeLayoutIndex = i;
+ break;
+ }
+ }
+
+ //not found, lets try without mirroring info
+ if (activeLayoutIndex==-1){
+ for (int i=0; i<m_numberOfLayouts; i++) {
+ if (screenHeight==m_layoutHeaders[i].height &&
+ screenWidth==m_layoutHeaders[i].width) {
+ activeLayoutIndex = i;
+ break;
+ }
+ }
+ }
+
+ //not found, lets try with either of dimensions
+ if (activeLayoutIndex==-1){
+ const QSysInfo::S60Version currentRelease = QSysInfo::s60Version();
+ const bool landscape = screenHeight < screenWidth;
+
+ activeLayoutIndex = (currentRelease == QSysInfo::SV_S60_3_1 || currentRelease == QSysInfo::SV_S60_3_2) ? 0 : 4;
+ activeLayoutIndex += (!landscape) ? 2 : 0;
+ activeLayoutIndex += (!mirrored) ? 1 : 0;
+ }
+
+ m_pmPointer = data[activeLayoutIndex];
+}
+
+QS60StylePrivate::QS60StylePrivate()
+{
+ // No need to set active layout, if dynamic metrics API is available
+ setActiveLayout();
+}
+
+void QS60StylePrivate::setStyleProperty_specific(const char *name, const QVariant &value)
+{
+ if (name == QLatin1String("foo")) {
+ // BaR
+ } else {
+ setStyleProperty(name, value);
+ }
+}
+
+QVariant QS60StylePrivate::styleProperty_specific(const char *name) const
+{
+ if (name == QLatin1String("foo"))
+ return QLatin1String("Bar");
+ else
+ return styleProperty(name);
+}
+
+QColor QS60StylePrivate::s60Color(QS60StyleEnums::ColorLists list,
+ int index, const QStyleOption *option)
+{
+ static const TAknsItemID *idMap[] = {
+ &KAknsIIDQsnHighlightColors,
+ &KAknsIIDQsnIconColors,
+ &KAknsIIDQsnLineColors,
+ &KAknsIIDQsnOtherColors,
+ &KAknsIIDQsnParentColors,
+ &KAknsIIDQsnTextColors
+ };
+ Q_ASSERT((int)list <= (int)sizeof(idMap)/sizeof(idMap[0]));
+ const QColor color = QS60StyleModeSpecifics::colorValue(*idMap[(int) list], index - 1);
+ return option ? QS60StylePrivate::stateColor(color, option) : color;
+}
+
+// In some cases, the AVKON UI themegraphic is already in 'disabled state'.
+// If so, return true for these parts.
+bool QS60StyleModeSpecifics::disabledPartGraphic(QS60StyleEnums::SkinParts &part)
+{
+ bool disabledGraphic = false;
+ switch(part){
+ // inactive button graphics are available from 5.0 onwards
+ case QS60StyleEnums::SP_QsnFrButtonCornerTlInactive:
+ case QS60StyleEnums::SP_QsnFrButtonCornerTrInactive:
+ case QS60StyleEnums::SP_QsnFrButtonCornerBlInactive:
+ case QS60StyleEnums::SP_QsnFrButtonCornerBrInactive:
+ case QS60StyleEnums::SP_QsnFrButtonSideTInactive:
+ case QS60StyleEnums::SP_QsnFrButtonSideBInactive:
+ case QS60StyleEnums::SP_QsnFrButtonSideLInactive:
+ case QS60StyleEnums::SP_QsnFrButtonSideRInactive:
+ case QS60StyleEnums::SP_QsnFrButtonCenterInactive:
+ if (!(QSysInfo::s60Version()==QSysInfo::SV_S60_3_1 ||
+ QSysInfo::s60Version()==QSysInfo::SV_S60_3_2))
+ disabledGraphic = true;
+ break;
+ default:
+ break;
+ }
+ return disabledGraphic;
+}
+
+// In some cases, the AVKON UI themegraphic is already in 'disabled state'.
+// If so, return true for these frames.
+bool QS60StyleModeSpecifics::disabledFrameGraphic(QS60StylePrivate::SkinFrameElements &frame)
+{
+ bool disabledGraphic = false;
+ switch(frame){
+ // inactive button graphics are available from 5.0 onwards
+ case QS60StylePrivate::SF_ButtonInactive:
+ if (!(QSysInfo::s60Version()==QSysInfo::SV_S60_3_1 ||
+ QSysInfo::s60Version()==QSysInfo::SV_S60_3_2))
+ disabledGraphic = true;
+ break;
+ default:
+ break;
+ }
+ return disabledGraphic;
+}
+
+QPixmap QS60StyleModeSpecifics::generateMissingThemeGraphic(QS60StyleEnums::SkinParts &part,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags)
+{
+ if (!QS60StylePrivate::isTouchSupported())
+ return QPixmap();
+
+ QS60StyleEnums::SkinParts updatedPart = part;
+ switch(part){
+ // AVKON UI has a abnormal handling for scrollbar graphics. It is possible that the root
+ // skin does not contain mandatory graphics for scrollbar pressed states. Therefore, AVKON UI
+ // creates dynamically these graphics by modifying the normal state scrollbar graphics slightly.
+ // S60Style needs to work similarly. Therefore if skingraphics call provides to be a miss
+ // (i.e. result is not valid), style needs to draw normal graphics instead and apply some
+ // modifications (similar to generatedIconPixmap()) to the result.
+ case QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed:
+ updatedPart = QS60StyleEnums::SP_QsnCpScrollHandleBottom;
+ break;
+ case QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed:
+ updatedPart = QS60StyleEnums::SP_QsnCpScrollHandleMiddle;
+ break;
+ case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed:
+ updatedPart = QS60StyleEnums::SP_QsnCpScrollHandleTop;
+ break;
+ default:
+ break;
+ }
+ if (part==updatedPart) {
+ return QPixmap();
+ } else {
+ QPixmap result = skinnedGraphics(updatedPart, size, flags);
+ QStyleOption opt;
+ QPalette *themePalette = QS60StylePrivate::themePalette();
+ if (themePalette)
+ opt.palette = *themePalette;
+
+ // For now, always generate new icon based on "selected". In the future possibly, expand
+ // this to consist other possibilities as well.
+ result = QApplication::style()->generatedIconPixmap(QIcon::Selected, result, &opt);
+ return result;
+ }
+}
+
+QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part,
+ const QSize &size, SkinElementFlags flags)
+{
+ QS60WindowSurface::unlockBitmapHeap();
+ QPixmap result = (flags & SF_ColorSkinned)?
+ QS60StyleModeSpecifics::colorSkinnedGraphics(part, size, flags)
+ : QS60StyleModeSpecifics::skinnedGraphics(part, size, flags);
+ QS60WindowSurface::lockBitmapHeap();
+
+ if (flags & SF_StateDisabled && !QS60StyleModeSpecifics::disabledPartGraphic(part)) {
+ QStyleOption opt;
+ QPalette *themePalette = QS60StylePrivate::themePalette();
+ if (themePalette)
+ opt.palette = *themePalette;
+ result = QApplication::style()->generatedIconPixmap(QIcon::Disabled, result, &opt);
+ }
+
+ if (!result)
+ result = QS60StyleModeSpecifics::generateMissingThemeGraphic(part, size, flags);
+
+ return result;
+}
+
+QPixmap QS60StylePrivate::frame(SkinFrameElements frame, const QSize &size, SkinElementFlags flags)
+{
+ QS60WindowSurface::unlockBitmapHeap();
+ QPixmap result = QS60StyleModeSpecifics::skinnedGraphics(frame, size, flags);
+ QS60WindowSurface::lockBitmapHeap();
+
+ if (flags & SF_StateDisabled && !QS60StyleModeSpecifics::disabledFrameGraphic(frame)) {
+ QStyleOption opt;
+ QPalette *themePalette = QS60StylePrivate::themePalette();
+ if (themePalette)
+ opt.palette = *themePalette;
+ result = QApplication::style()->generatedIconPixmap(QIcon::Disabled, result, &opt);
+ }
+ return result;
+}
+
+QPixmap QS60StylePrivate::backgroundTexture()
+{
+ if (!m_background) {
+ QPixmap background = part(QS60StyleEnums::SP_QsnBgScreen,
+ QSize(S60->screenWidthInPixels, S60->screenHeightInPixels), SkinElementFlags());
+ m_background = new QPixmap(background);
+ }
+ return *m_background;
+}
+
+// If the public SDK returns compressed images, please let us also uncompress those!
+void QS60StyleModeSpecifics::unCompressBitmapL(const TRect& aTrgRect, CFbsBitmap* aTrgBitmap, CFbsBitmap* aSrcBitmap)
+{
+ if (!aSrcBitmap)
+ User::Leave(KErrArgument);
+ if (!aTrgBitmap)
+ User::Leave(KErrArgument);
+
+ // Note! aSrcBitmap->IsCompressedInRAM() is always ETrue, since this method is called only if that applies!
+ ASSERT(aSrcBitmap->IsCompressedInRAM());
+
+ TDisplayMode displayMode = aSrcBitmap->DisplayMode();
+
+ if (displayMode != aTrgBitmap->DisplayMode())
+ User::Leave(KErrArgument);
+
+ const TSize trgSize = aTrgBitmap->SizeInPixels();
+ const TSize srcSize = aSrcBitmap->SizeInPixels();
+
+ // calculate the valid drawing area
+ TRect drawRect = aTrgRect;
+ drawRect.Intersection(TRect(TPoint(0, 0), trgSize));
+
+ if (drawRect.IsEmpty())
+ return;
+
+ CFbsBitmap* realSource = new (ELeave) CFbsBitmap();
+ CleanupStack::PushL(realSource);
+ User::LeaveIfError(realSource->Create(srcSize, displayMode));
+ CFbsBitmapDevice* dev = CFbsBitmapDevice::NewL(realSource);
+ CleanupStack::PushL(dev);
+ CFbsBitGc* gc = NULL;
+ User::LeaveIfError(dev->CreateContext(gc));
+ CleanupStack::PushL(gc);
+ gc->BitBlt(TPoint(0, 0), aSrcBitmap);
+ CleanupStack::PopAndDestroy(2); // dev, gc
+
+ // Heap lock for FBServ large chunk is only needed with large bitmaps.
+ if (realSource->IsLargeBitmap() || aTrgBitmap->IsLargeBitmap()) {
+ aTrgBitmap->LockHeapLC(ETrue); // fbsheaplock
+ } else {
+ CleanupStack::PushL((TAny*) NULL);
+ }
+
+ TUint32* srcAddress = realSource->DataAddress();
+ TUint32* trgAddress = aTrgBitmap->DataAddress();
+
+ const TInt xSkip = (srcSize.iWidth << 8) / aTrgRect.Width();
+ const TInt ySkip = (srcSize.iHeight << 8) / aTrgRect.Height();
+
+ const TInt drawWidth = drawRect.Width();
+ const TInt drawHeight = drawRect.Height();
+
+ const TRect offsetRect(aTrgRect.iTl, drawRect.iTl);
+ const TInt yPosOffset = ySkip * offsetRect.Height();
+ const TInt xPosOffset = xSkip * offsetRect.Width();
+
+ if ((displayMode == EGray256) || (displayMode == EColor256)) {
+ const TInt srcScanLen8 = CFbsBitmap::ScanLineLength(srcSize.iWidth,
+ displayMode);
+ const TInt trgScanLen8 = CFbsBitmap::ScanLineLength(trgSize.iWidth,
+ displayMode);
+
+ TUint8* trgAddress8 = reinterpret_cast<TUint8*> (trgAddress);
+
+ TInt yPos = yPosOffset;
+ // skip left and top margins in the beginning
+ trgAddress8 += trgScanLen8 * drawRect.iTl.iY + drawRect.iTl.iX;
+
+ for (TInt y = 0; y < drawHeight; y++) {
+ const TUint8* srcAddress8 = reinterpret_cast<const TUint8*> (srcAddress)
+ + (srcScanLen8 * (yPos >> 8));
+
+ TInt xPos = xPosOffset;
+ for (TInt x = 0; x < drawWidth; x++) {
+ *(trgAddress8++) = srcAddress8[xPos >> 8];
+ xPos += xSkip;
+ }
+
+ yPos += ySkip;
+
+ trgAddress8 += trgScanLen8 - drawWidth;
+ }
+ } else if (displayMode == EColor4K || displayMode == EColor64K) {
+ const TInt srcScanLen16 = CFbsBitmap::ScanLineLength(srcSize.iWidth,
+ displayMode) >>1;
+ const TInt trgScanLen16 = CFbsBitmap::ScanLineLength(trgSize.iWidth,
+ displayMode) >>1;
+
+ TUint16* trgAddress16 = reinterpret_cast<TUint16*> (trgAddress);
+
+ TInt yPos = yPosOffset;
+ // skip left and top margins in the beginning
+ trgAddress16 += trgScanLen16 * drawRect.iTl.iY + drawRect.iTl.iX;
+
+ for (TInt y = 0; y < drawHeight; y++) {
+ const TUint16* srcAddress16 = reinterpret_cast<const TUint16*> (srcAddress)
+ + (srcScanLen16 * (yPos >> 8));
+
+ TInt xPos = xPosOffset;
+ for (TInt x = 0; x < drawWidth; x++) {
+ *(trgAddress16++) = srcAddress16[xPos >> 8];
+ xPos += xSkip;
+ }
+
+ yPos += ySkip;
+
+ trgAddress16 += trgScanLen16 - drawWidth;
+ }
+ } else if (displayMode == EColor16MU || displayMode == EColor16MA) {
+ const TInt srcScanLen32 = CFbsBitmap::ScanLineLength(srcSize.iWidth,
+ displayMode) >>2;
+ const TInt trgScanLen32 = CFbsBitmap::ScanLineLength(trgSize.iWidth,
+ displayMode) >>2;
+
+ TUint32* trgAddress32 = reinterpret_cast<TUint32*> (trgAddress);
+
+ TInt yPos = yPosOffset;
+ // skip left and top margins in the beginning
+ trgAddress32 += trgScanLen32 * drawRect.iTl.iY + drawRect.iTl.iX;
+
+ for (TInt y = 0; y < drawHeight; y++) {
+ const TUint32* srcAddress32 = reinterpret_cast<const TUint32*> (srcAddress)
+ + (srcScanLen32 * (yPos >> 8));
+
+ TInt xPos = xPosOffset;
+ for (TInt x = 0; x < drawWidth; x++) {
+ *(trgAddress32++) = srcAddress32[xPos >> 8];
+ xPos += xSkip;
+ }
+
+ yPos += ySkip;
+
+ trgAddress32 += trgScanLen32 - drawWidth;
+ }
+ } else { User::Leave(KErrUnknown);}
+
+ CleanupStack::PopAndDestroy(2); // fbsheaplock, realSource
+}
+
+QSize QS60StylePrivate::screenSize()
+{
+ const TSize screenSize = QS60Data::screenDevice()->SizeInPixels();
+ return QSize(screenSize.iWidth, screenSize.iHeight);
+}
+
+void QS60StyleModeSpecifics::colorGroupAndIndex(
+ QS60StyleEnums::SkinParts skinID, TAknsItemID &colorGroup, int colorIndex)
+{
+ switch(skinID) {
+ case QS60StyleEnums::SP_QgnIndiSubMenu:
+ colorGroup = KAknsIIDQsnIconColors;
+ colorIndex = EAknsCIQsnIconColorsCG1;
+ break;
+ case QS60StyleEnums::SP_QgnIndiRadiobuttOff:
+ case QS60StyleEnums::SP_QgnIndiRadiobuttOn:
+ case QS60StyleEnums::SP_QgnIndiCheckboxOff:
+ case QS60StyleEnums::SP_QgnIndiCheckboxOn:
+ colorGroup = KAknsIIDQsnIconColors;
+ colorIndex = EAknsCIQsnIconColorsCG14;
+ break;
+ default:
+ break;
+ }
+}
+
+/*!
+ Constructs a QS60Style object.
+*/
+QS60Style::QS60Style()
+ : QCommonStyle(*new QS60StylePrivate)
+{
+}
+
+void QS60Style::handleDynamicLayoutVariantSwitch()
+{
+ Q_D(QS60Style);
+ d->clearCaches(QS60StylePrivate::CC_LayoutChange);
+ d->setActiveLayout();
+ d->refreshUI();
+ d->setBackgroundTexture(qApp);
+ foreach (QWidget *widget, QApplication::allWidgets())
+ widget->ensurePolished();
+}
+
+void QS60Style::handleSkinChange()
+{
+ Q_D(QS60Style);
+ d->clearCaches(QS60StylePrivate::CC_ThemeChange);
+ d->setThemePalette(qApp);
+ foreach (QWidget *topLevelWidget, QApplication::allWidgets()){
+ QEvent e(QEvent::StyleChange);
+ QApplication::sendEvent(topLevelWidget, &e);
+ d->setThemePalette(topLevelWidget);
+ topLevelWidget->ensurePolished();
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STYLE_S60 || QT_PLUGIN
diff --git a/src/gui/styles/qs60style_simulated.cpp b/src/gui/styles/qs60style_simulated.cpp
new file mode 100644
index 0000000..684f232
--- /dev/null
+++ b/src/gui/styles/qs60style_simulated.cpp
@@ -0,0 +1,449 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qs60style.h"
+#include "qs60style_p.h"
+#include "qfile.h"
+#include "qhash.h"
+#include "qapplication.h"
+#include "qpainter.h"
+#include "qpicture.h"
+#include "qstyleoption.h"
+#include "qtransform.h"
+#include "qlayout.h"
+#include "qpixmapcache.h"
+#include "qmetaobject.h"
+#include "qdebug.h"
+#include "qbuffer.h"
+#include "qdesktopwidget.h"
+
+#if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN)
+
+QT_BEGIN_NAMESPACE
+
+static const quint32 blobVersion = 1;
+static const int pictureSize = 256;
+
+#if defined(Q_CC_GNU)
+#if __GNUC__ >= 2
+#define __FUNCTION__ __func__
+#endif
+#endif
+
+
+bool saveThemeToBlob(const QString &themeBlob,
+ const QHash<QString, QPicture> &partPictures,
+ const QHash<QPair<QString, int>, QColor> &colors)
+{
+ QFile blob(themeBlob);
+ if (!blob.open(QIODevice::WriteOnly)) {
+ qWarning() << __FUNCTION__ << ": Could not create blob: " << themeBlob;
+ return false;
+ }
+
+ QByteArray data;
+ QBuffer dataBuffer(&data);
+ dataBuffer.open(QIODevice::WriteOnly);
+ QDataStream dataOut(&dataBuffer);
+
+ const int colorsCount = colors.count();
+ dataOut << colorsCount;
+ const QList<QPair<QString, int> > colorKeys = colors.keys();
+ for (int i = 0; i < colorsCount; ++i) {
+ const QPair<QString, int> &key = colorKeys.at(i);
+ dataOut << key;
+ const QColor color = colors.value(key);
+ dataOut << color;
+ }
+
+ const int picturesCount = partPictures.count();
+ dataOut << picturesCount;
+ foreach (const QString &key, partPictures.keys()) {
+ const QPicture picture = partPictures.value(key);
+ dataOut << key;
+ dataOut << picture;
+ }
+
+ QDataStream blobOut(&blob);
+ blobOut << blobVersion;
+ blobOut << qCompress(data);
+ return blobOut.status() == QDataStream::Ok;
+}
+
+bool loadThemeFromBlob(const QString &themeBlob,
+ QHash<QString, QPicture> &partPictures,
+ QHash<QPair<QString, int>, QColor> &colors)
+{
+ QFile blob(themeBlob);
+ if (!blob.open(QIODevice::ReadOnly)) {
+ qWarning() << __FUNCTION__ << ": Could not read blob: " << themeBlob;
+ return false;
+ }
+ QDataStream blobIn(&blob);
+
+ quint32 version;
+ blobIn >> version;
+
+ if (version != blobVersion) {
+ qWarning() << __FUNCTION__ << ": Invalid blob version: " << version << " ...expected: " << blobVersion;
+ return false;
+ }
+
+ QByteArray data;
+ blobIn >> data;
+ data = qUncompress(data);
+ QBuffer dataBuffer(&data);
+ dataBuffer.open(QIODevice::ReadOnly);
+ QDataStream dataIn(&dataBuffer);
+
+ int colorsCount;
+ dataIn >> colorsCount;
+ for (int i = 0; i < colorsCount; ++i) {
+ QPair<QString, int> key;
+ dataIn >> key;
+ QColor value;
+ dataIn >> value;
+ colors.insert(key, value);
+ }
+
+ int picturesCount;
+ dataIn >> picturesCount;
+ for (int i = 0; i < picturesCount; ++i) {
+ QString key;
+ dataIn >> key;
+ QPicture value;
+ dataIn >> value;
+ value.setBoundingRect(QRect(0, 0, pictureSize, pictureSize)); // Bug? The forced bounding rect was not deserialized.
+ partPictures.insert(key, value);
+ }
+
+ if (dataIn.status() != QDataStream::Ok) {
+ qWarning() << __FUNCTION__ << ": Invalid data blob: " << themeBlob;
+ return false;
+ }
+ return true;
+}
+
+class QS60StyleModeSpecifics
+{
+public:
+ static QPixmap skinnedGraphics(QS60StyleEnums::SkinParts stylepart,
+ const QSize &size, QS60StylePrivate::SkinElementFlags flags);
+ static QHash<QString, QPicture> m_partPictures;
+ static QHash<QPair<QString , int>, QColor> m_colors;
+};
+QHash<QString, QPicture> QS60StyleModeSpecifics::m_partPictures;
+QHash<QPair<QString , int>, QColor> QS60StyleModeSpecifics::m_colors;
+
+QS60StylePrivate::QS60StylePrivate()
+{
+ setCurrentLayout(0);
+}
+
+QColor QS60StylePrivate::s60Color(QS60StyleEnums::ColorLists list,
+ int index, const QStyleOption *option)
+{
+ const QString listKey = QS60Style::colorListKeys().at(list);
+ return QS60StylePrivate::stateColor(
+ QS60StyleModeSpecifics::m_colors.value(QPair<QString, int>(listKey, index)),
+ option
+ );
+}
+
+QPixmap QS60StylePrivate::part(QS60StyleEnums::SkinParts part, const QSize &size,
+ QS60StylePrivate::SkinElementFlags flags)
+{
+ const QString partKey = QS60Style::partKeys().at(part);
+ const QPicture partPicture = QS60StyleModeSpecifics::m_partPictures.value(partKey);
+ QSize partSize(partPicture.boundingRect().size());
+ if (flags & (SF_PointEast | SF_PointWest)) {
+ const int temp = partSize.width();
+ partSize.setWidth(partSize.height());
+ partSize.setHeight(temp);
+ }
+ const qreal scaleX = size.width() / (qreal)partSize.width();
+ const qreal scaleY = size.height() / (qreal)partSize.height();
+
+ QImage partImage(size, QImage::Format_ARGB32);
+ partImage.fill(Qt::transparent);
+ QPainter resultPainter(&partImage);
+ QTransform t;
+
+ if (flags & SF_PointEast)
+ t.translate(size.width(), 0);
+ else if (flags & SF_PointSouth)
+ t.translate(size.width(), size.height());
+ else if (flags & SF_PointWest)
+ t.translate(0, size.height());
+
+ t.scale(scaleX, scaleY);
+
+ if (flags & SF_PointEast)
+ t.rotate(90);
+ else if (flags & SF_PointSouth)
+ t.rotate(180);
+ else if (flags & SF_PointWest)
+ t.rotate(270);
+
+ resultPainter.setTransform(t, true);
+ const_cast<QPicture *>(&partPicture)->play(&resultPainter);
+ resultPainter.end();
+
+ QPixmap result = QPixmap::fromImage(partImage);
+ if (flags & SF_StateDisabled) {
+ QStyleOption opt;
+ QPalette *themePalette = QS60StylePrivate::themePalette();
+ if (themePalette)
+ opt.palette = *themePalette;
+ result = QApplication::style()->generatedIconPixmap(QIcon::Disabled, result, &opt);
+ }
+
+ return result;
+}
+
+QPixmap QS60StylePrivate::frame(SkinFrameElements frame, const QSize &size,
+ SkinElementFlags flags)
+{
+ const QS60StyleEnums::SkinParts center = m_frameElementsData[frame].center;
+ const QS60StyleEnums::SkinParts topLeft = QS60StyleEnums::SkinParts(center - 8);
+ const QS60StyleEnums::SkinParts topRight = QS60StyleEnums::SkinParts(center - 7);
+ const QS60StyleEnums::SkinParts bottomLeft = QS60StyleEnums::SkinParts(center - 6);
+ const QS60StyleEnums::SkinParts bottomRight = QS60StyleEnums::SkinParts(center - 5);
+ const QS60StyleEnums::SkinParts top = QS60StyleEnums::SkinParts(center - 4);
+ const QS60StyleEnums::SkinParts bottom = QS60StyleEnums::SkinParts(center - 3);
+ const QS60StyleEnums::SkinParts left = QS60StyleEnums::SkinParts(center - 2);
+ const QS60StyleEnums::SkinParts right = QS60StyleEnums::SkinParts(center - 1);
+
+ // The size of topLeft defines all other sizes
+ const QSize cornerSize(partSize(topLeft));
+ // if frame is so small that corners would cover it completely, draw only center piece
+ const bool drawOnlyCenter =
+ 2 * cornerSize.width() + 1 >= size.width() || 2 * cornerSize.height() + 1 >= size.height();
+
+ const int cornerWidth = cornerSize.width();
+ const int cornerHeight = cornerSize.height();
+ const int rectWidth = size.width();
+ const int rectHeight = size.height();
+ const QRect rect(QPoint(), size);
+
+ const QRect topLeftRect = QRect(rect.topLeft(), cornerSize);
+ const QRect topRect = rect.adjusted(cornerWidth, 0, -cornerWidth, -(rectHeight - cornerHeight));
+ const QRect topRightRect = topLeftRect.translated(rectWidth - cornerWidth, 0);
+ const QRect rightRect = rect.adjusted(rectWidth - cornerWidth, cornerHeight, 0, -cornerHeight);
+ const QRect bottomRightRect = topRightRect.translated(0, rectHeight - cornerHeight);
+ const QRect bottomRect = topRect.translated(0, rectHeight - cornerHeight);
+ const QRect bottomLeftRect = topLeftRect.translated(0, rectHeight - cornerHeight);
+ const QRect leftRect = rightRect.translated(cornerWidth - rectWidth, 0);
+ const QRect centerRect = drawOnlyCenter ? rect : rect.adjusted(cornerWidth, cornerWidth, -cornerWidth, -cornerWidth);
+
+ QPixmap result(size);
+ result.fill(Qt::transparent);
+ QPainter painter(&result);
+
+#if 0
+ painter.save();
+ painter.setOpacity(.3);
+ painter.fillRect(topLeftRect, Qt::red);
+ painter.fillRect(topRect, Qt::green);
+ painter.fillRect(topRightRect, Qt::blue);
+ painter.fillRect(rightRect, Qt::green);
+ painter.fillRect(bottomRightRect, Qt::red);
+ painter.fillRect(bottomRect, Qt::blue);
+ painter.fillRect(bottomLeftRect, Qt::green);
+ painter.fillRect(leftRect, Qt::blue);
+ painter.fillRect(centerRect, Qt::red);
+ painter.restore();
+#else
+ drawPart(topLeft, &painter, topLeftRect, flags);
+ drawPart(top, &painter, topRect, flags);
+ drawPart(topRight, &painter, topRightRect, flags);
+ drawPart(right, &painter, rightRect, flags);
+ drawPart(bottomRight, &painter, bottomRightRect, flags);
+ drawPart(bottom, &painter, bottomRect, flags);
+ drawPart(bottomLeft, &painter, bottomLeftRect, flags);
+ drawPart(left, &painter, leftRect, flags);
+ drawPart(center, &painter, centerRect, flags);
+#endif
+
+ return result;
+}
+
+void QS60StylePrivate::setStyleProperty_specific(const char *name, const QVariant &value)
+{
+ setStyleProperty(name, value);
+}
+
+QVariant QS60StylePrivate::styleProperty_specific(const char *name) const
+{
+ return styleProperty(name);
+}
+
+QPixmap QS60StylePrivate::backgroundTexture()
+{
+ if (!m_background) {
+ const QSize size = QApplication::desktop()->screen()->size();
+ QPixmap background = part(QS60StyleEnums::SP_QsnBgScreen, size);
+ m_background = new QPixmap(background);
+ }
+ return *m_background;
+}
+
+
+bool QS60StylePrivate::isTouchSupported()
+{
+#ifdef QT_KEYPAD_NAVIGATION
+ return !QApplication::keypadNavigationEnabled();
+#else
+ return true;
+#endif
+}
+
+bool QS60StylePrivate::isToolBarBackground()
+{
+ return true;
+}
+
+QFont QS60StylePrivate::s60Font_specific(QS60StyleEnums::FontCategories fontCategory, int pointSize)
+{
+ QFont result;
+ result.setPointSize(pointSize);
+ switch (fontCategory) {
+ case QS60StyleEnums::FC_Primary:
+ result.setBold(true);
+ break;
+ case QS60StyleEnums::FC_Secondary:
+ case QS60StyleEnums::FC_Title:
+ case QS60StyleEnums::FC_PrimarySmall:
+ case QS60StyleEnums::FC_Digital:
+ case QS60StyleEnums::FC_Undefined:
+ default:
+ break;
+ }
+ return result;
+}
+
+/*!
+ Constructs a QS60Style object.
+*/
+QS60Style::QS60Style()
+ : QCommonStyle(*new QS60StylePrivate)
+{
+ // Assume, that the resource system has a ':/s60Stylethemes/Default.blob'
+ const QString defaultBlob = QString::fromLatin1(":/s60Stylethemes/Default.blob");
+ if (QFile::exists(defaultBlob))
+ loadS60ThemeFromBlob(defaultBlob);
+}
+
+Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, enumPartKeys, {
+ const int enumIndex = QS60StyleEnums::staticMetaObject.indexOfEnumerator("SkinParts");
+ Q_ASSERT(enumIndex >= 0);
+ const QMetaEnum metaEnum = QS60StyleEnums::staticMetaObject.enumerator(enumIndex);
+ for (int i = 0; i < metaEnum.keyCount(); ++i) {
+ const QString enumKey = QString::fromLatin1(metaEnum.key(i));
+ QString partKey;
+ // Following loop does following conversions: "SP_QgnNoteInfo" to "qgn_note_info"...
+ for (int charPosition = 3; charPosition < enumKey.length(); charPosition++) {
+ if (charPosition > 3 && enumKey[charPosition].isUpper())
+ partKey.append(QChar::fromLatin1('_'));
+ partKey.append(enumKey[charPosition].toLower());
+ }
+ x->append(partKey);
+ }
+})
+
+QStringList QS60Style::partKeys()
+{
+ return *enumPartKeys();
+}
+
+Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, enumColorListKeys, {
+ const int enumIndex = QS60StyleEnums::staticMetaObject.indexOfEnumerator("ColorLists");
+ Q_ASSERT(enumIndex >= 0);
+ const QMetaEnum metaEnum = QS60StyleEnums::staticMetaObject.enumerator(enumIndex);
+ for (int i = 0; i < metaEnum.keyCount(); i++) {
+ const QString enumKey = QString::fromLatin1(metaEnum.key(i));
+ // Following line does following conversions: CL_QsnTextColors to "text"...
+ x->append(enumKey.mid(6, enumKey.length() - 12).toLower());
+ }
+})
+
+QStringList QS60Style::colorListKeys()
+{
+ return *enumColorListKeys();
+}
+
+void QS60Style::setS60Theme(const QHash<QString, QPicture> &parts,
+ const QHash<QPair<QString , int>, QColor> &colors)
+{
+ Q_D(QS60Style);
+ QS60StyleModeSpecifics::m_partPictures = parts;
+ QS60StyleModeSpecifics::m_colors = colors;
+ d->clearCaches(QS60StylePrivate::CC_ThemeChange);
+ d->setBackgroundTexture(qApp);
+ d->setThemePalette(qApp);
+}
+
+bool QS60Style::loadS60ThemeFromBlob(const QString &blobFile)
+{
+ QHash<QString, QPicture> partPictures;
+ QHash<QPair<QString, int>, QColor> colors;
+
+ if (!loadThemeFromBlob(blobFile, partPictures, colors))
+ return false;
+ setS60Theme(partPictures, colors);
+ return true;
+}
+
+bool QS60Style::saveS60ThemeToBlob(const QString &blobFile) const
+{
+ return saveThemeToBlob(blobFile,
+ QS60StyleModeSpecifics::m_partPictures, QS60StyleModeSpecifics::m_colors);
+}
+
+QPoint qt_s60_fill_background_offset(const QWidget *targetWidget)
+{
+ Q_UNUSED(targetWidget)
+ return QPoint();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STYLE_S60 || QT_PLUGIN
diff --git a/src/gui/styles/qstyle_p.h b/src/gui/styles/qstyle_p.h
index 2d6ef22..11be2f8 100644
--- a/src/gui/styles/qstyle_p.h
+++ b/src/gui/styles/qstyle_p.h
@@ -65,7 +65,7 @@ class QStyle;
class QStylePrivate: public QObjectPrivate
{
- Q_DECLARE_PUBLIC(QStyle);
+ Q_DECLARE_PUBLIC(QStyle)
public:
inline QStylePrivate()
: layoutSpacingIndex(-1), proxyStyle(0) {}
diff --git a/src/gui/styles/qstyle_s60_simulated.qrc b/src/gui/styles/qstyle_s60_simulated.qrc
new file mode 100644
index 0000000..72aab9e
--- /dev/null
+++ b/src/gui/styles/qstyle_s60_simulated.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource prefix="/trolltech/styles/s60style">
+ <file>images/s60themes.dat</file>
+ </qresource>
+</RCC>
diff --git a/src/gui/styles/qstylefactory.cpp b/src/gui/styles/qstylefactory.cpp
index 36f405c..a1d585d 100644
--- a/src/gui/styles/qstylefactory.cpp
+++ b/src/gui/styles/qstylefactory.cpp
@@ -69,6 +69,9 @@
#ifndef QT_NO_STYLE_WINDOWSMOBILE
#include "qwindowsmobilestyle.h"
#endif
+#ifndef QT_NO_STYLE_S60
+#include "qs60style.h"
+#endif
QT_BEGIN_NAMESPACE
@@ -154,6 +157,11 @@ QStyle *QStyleFactory::create(const QString& key)
ret = new QCDEStyle;
else
#endif
+#ifndef QT_NO_STYLE_S60
+ if (style == QLatin1String("s60"))
+ ret = new QS60Style;
+ else
+#endif
#ifndef QT_NO_STYLE_PLASTIQUE
if (style == QLatin1String("plastique"))
ret = new QPlastiqueStyle;
@@ -233,6 +241,10 @@ QStringList QStyleFactory::keys()
if (!list.contains(QLatin1String("CDE")))
list << QLatin1String("CDE");
#endif
+#ifndef QT_NO_STYLE_S60
+ if (!list.contains(QLatin1String("S60")))
+ list << QLatin1String("S60");
+#endif
#ifndef QT_NO_STYLE_PLASTIQUE
if (!list.contains(QLatin1String("Plastique")))
list << QLatin1String("Plastique");
diff --git a/src/gui/styles/qstylesheetstyle_default.cpp b/src/gui/styles/qstylesheetstyle_default.cpp
index b008c12..91464f7 100644
--- a/src/gui/styles/qstylesheetstyle_default.cpp
+++ b/src/gui/styles/qstylesheetstyle_default.cpp
@@ -154,11 +154,12 @@ StyleSheet QStyleSheetStyle::getDefaultStyleSheet() const
Value value;
Pseudo pseudo;
AttributeSelector attr;
-
+
// pixmap based style doesn't support any features
bool styleIsPixmapBased = baseStyle()->inherits("QMacStyle")
|| baseStyle()->inherits("QWindowsXPStyle")
- || baseStyle()->inherits("QGtkStyle");
+ || baseStyle()->inherits("QGtkStyle")
+ || baseStyle()->inherits("QS60Style");
/*QLineEdit {
@@ -212,7 +213,7 @@ StyleSheet QStyleSheetStyle::getDefaultStyleSheet() const
ADD_BASIC_SELECTOR;
ADD_SELECTOR;
-
+
SET_PROPERTY(QLatin1String("padding-top"), PaddingTop);
ADD_VALUE(Value::Identifier, QString::fromLatin1("2px"));
ADD_DECLARATION;
diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp
index 4c66bbb..bc1df9d 100644
--- a/src/gui/styles/qwindowsstyle.cpp
+++ b/src/gui/styles/qwindowsstyle.cpp
@@ -122,7 +122,8 @@ static const int windowsItemHMargin = 3; // menu item hor text margin
static const int windowsItemVMargin = 2; // menu item ver text margin
static const int windowsArrowHMargin = 6; // arrow horizontal margin
static const int windowsTabSpacing = 12; // space between text and tab
-static const int windowsCheckMarkHMargin = 2; // horiz. margins of check mark
+// Save some space and avoid warning.
+//static const int windowsCheckMarkHMargin = 2; // horiz. margins of check mark
static const int windowsRightBorder = 15; // right border on windows
static const int windowsCheckMarkWidth = 12; // checkmarks width on windows
@@ -2485,7 +2486,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
bool floating = false;
bool active = dwOpt->state & State_Active;
- int menuOffset = 0; //used to center text when floated
QColor inactiveCaptionTextColor = d->inactiveCaptionText;
if (dwOpt->movable) {
QColor left, right;
@@ -2500,7 +2500,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
left = d->inactiveCaptionColor;
right = d->inactiveGradientCaptionColor;
}
- menuOffset = 2;
QBrush fillBrush(left);
if (left != right) {
QPoint p1(r.x(), r.top() + r.height()/2);
diff --git a/src/gui/styles/styles.pri b/src/gui/styles/styles.pri
index d255f80..277be76 100644
--- a/src/gui/styles/styles.pri
+++ b/src/gui/styles/styles.pri
@@ -161,3 +161,19 @@ contains( styles, windowsmobile ) {
DEFINES += QT_NO_STYLE_WINDOWSMOBILE
}
+contains( styles, s60 ):contains(QT_CONFIG, s60) {
+ HEADERS += \
+ styles/qs60style.h \
+ styles/qs60style_p.h
+ SOURCES += styles/qs60style.cpp
+ symbian {
+ SOURCES += styles/qs60style_s60.cpp
+ # TODO: fix the following LIBS hack. Line 1 is for armv5, 2 for winscw
+ LIBS += aknicon aknskins aknskinsrv fontutils
+ LIBS += -laknicon -laknskins -laknskinsrv -lfontutils
+ } else {
+ SOURCES += styles/qs60style_simulated.cpp
+ }
+} else {
+ DEFINES += QT_NO_STYLE_S60
+}
diff --git a/src/gui/text/qabstractfontengine_p.h b/src/gui/text/qabstractfontengine_p.h
index 3d0f348..4401173 100644
--- a/src/gui/text/qabstractfontengine_p.h
+++ b/src/gui/text/qabstractfontengine_p.h
@@ -91,7 +91,7 @@ public:
virtual Type type() const { return Proxy; }
virtual const char *name() const { return "proxy engine"; }
-#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
+#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN)
virtual void draw(QPaintEngine *, qreal, qreal, const QTextItemInt &);
#endif
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index db5ed7c..99374b5 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -48,6 +48,7 @@
#include <qfontmetrics.h>
#include <qbrush.h>
#include <qimagereader.h>
+#include "private/qfunctions_p.h"
#ifndef QT_NO_CSSPARSER
@@ -340,12 +341,12 @@ static const QCssKnownValue styleFeatures[NumKnownStyleFeatures - 1] = {
{ "none", StyleFeature_None }
};
-static bool operator<(const QString &name, const QCssKnownValue &prop)
+Q_STATIC_GLOBAL_OPERATOR bool operator<(const QString &name, const QCssKnownValue &prop)
{
return QString::compare(name, QLatin1String(prop.name), Qt::CaseInsensitive) < 0;
}
-static bool operator<(const QCssKnownValue &prop, const QString &name)
+Q_STATIC_GLOBAL_OPERATOR bool operator<(const QCssKnownValue &prop, const QString &name)
{
return QString::compare(QLatin1String(prop.name), name, Qt::CaseInsensitive) < 0;
}
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index dfd5f24..a575199 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -72,6 +72,9 @@
#include "qfontengine_qpf_p.h"
#endif
#endif
+#ifdef Q_OS_SYMBIAN
+#include "qt_s60_p.h"
+#endif
#include <QMutexLocker>
@@ -169,6 +172,8 @@ Q_GUI_EXPORT int qt_defaultDpiX()
if (!subScreens.isEmpty())
screen = subScreens.at(0);
dpi = qRound(screen->width() / (screen->physicalWidth() / qreal(25.4)));
+#elif defined(Q_OS_SYMBIAN)
+ dpi = S60->defaultDpiX;
#endif // Q_WS_X11
return dpi;
@@ -195,6 +200,8 @@ Q_GUI_EXPORT int qt_defaultDpiY()
if (!subScreens.isEmpty())
screen = subScreens.at(0);
dpi = qRound(screen->height() / (screen->physicalHeight() / qreal(25.4)));
+#elif defined(Q_OS_SYMBIAN)
+ dpi = S60->defaultDpiY;
#endif // Q_WS_X11
return dpi;
@@ -307,7 +314,7 @@ QFontPrivate *QFontPrivate::smallCapsFontPrivate() const
font.setPointSizeF(pointSize * .7);
else
font.setPixelSize((font.pixelSize() * 7 + 5) / 10);
- scFont = font.d;
+ scFont = font.d.data();
if (scFont != this)
scFont->ref.ref();
return scFont;
@@ -714,12 +721,11 @@ QFont::QFont(const QFont &font, QPaintDevice *pd)
const int screen = 0;
#endif
if (font.d->dpi != dpi || font.d->screen != screen ) {
- d = new QFontPrivate(*font.d);
+ d.reset(new QFontPrivate(*font.d));
d->dpi = dpi;
d->screen = screen;
} else {
- d = font.d;
- d->ref.ref();
+ d.assign(font.d.data());
}
#ifdef Q_WS_WIN
if (pd->devType() == QInternal::Printer && pd->getDC())
@@ -733,8 +739,7 @@ QFont::QFont(const QFont &font, QPaintDevice *pd)
QFont::QFont(QFontPrivate *data)
: resolve_mask(QFont::AllPropertiesResolved)
{
- d = data;
- d->ref.ref();
+ d.assign(data);
}
/*! \internal
@@ -746,13 +751,13 @@ void QFont::detach()
if (d->engineData)
d->engineData->ref.deref();
d->engineData = 0;
- if (d->scFont && d->scFont != d)
+ if (d->scFont && d->scFont != d.data())
d->scFont->ref.deref();
d->scFont = 0;
return;
}
- qAtomicDetach(d);
+ d.detach();
}
/*!
@@ -761,9 +766,9 @@ void QFont::detach()
\sa QApplication::setFont(), QApplication::font()
*/
QFont::QFont()
- :d(QApplication::font().d), resolve_mask(0)
+ :resolve_mask(0)
{
- d->ref.ref();
+ d.assign(QApplication::font().d.data());
}
/*!
@@ -783,12 +788,16 @@ QFont::QFont()
setStyleHint() QApplication::font()
*/
QFont::QFont(const QString &family, int pointSize, int weight, bool italic)
- :d(new QFontPrivate)
{
+ d.reset(new QFontPrivate());
resolve_mask = QFont::FamilyResolved;
if (pointSize <= 0) {
+#ifdef Q_OS_SYMBIAN
+ pointSize = 7;
+#else
pointSize = 12;
+#endif
} else {
resolve_mask |= QFont::SizeResolved;
}
@@ -811,8 +820,7 @@ QFont::QFont(const QString &family, int pointSize, int weight, bool italic)
*/
QFont::QFont(const QFont &font)
{
- d = font.d;
- d->ref.ref();
+ d.assign(font.d.data());
resolve_mask = font.resolve_mask;
}
@@ -821,8 +829,6 @@ QFont::QFont(const QFont &font)
*/
QFont::~QFont()
{
- if (!d->ref.deref())
- delete d;
}
/*!
@@ -830,7 +836,7 @@ QFont::~QFont()
*/
QFont &QFont::operator=(const QFont &font)
{
- qAtomicAssign(d, font.d);
+ d.assign(font.d.data());
resolve_mask = font.resolve_mask;
return *this;
}
@@ -1713,7 +1719,7 @@ QFont QFont::resolve(const QFont &other) const
QFont font(*this);
font.detach();
- font.d->resolve(resolve_mask, other.d);
+ font.d->resolve(resolve_mask, other.d.data());
return font;
}
@@ -2166,11 +2172,11 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
s << (quint8) font.d->request.styleStrategy;
s << (quint8) 0
<< (quint8) font.d->request.weight
- << get_font_bits(s.version(), font.d);
+ << get_font_bits(s.version(), font.d.data());
if (s.version() >= QDataStream::Qt_4_3)
s << (quint16)font.d->request.stretch;
if (s.version() >= QDataStream::Qt_4_4)
- s << get_extended_font_bits(font.d);
+ s << get_extended_font_bits(font.d.data());
if (s.version() >= QDataStream::Qt_4_5) {
s << font.d->letterSpacing.value();
s << font.d->wordSpacing.value();
@@ -2189,10 +2195,8 @@ QDataStream &operator<<(QDataStream &s, const QFont &font)
*/
QDataStream &operator>>(QDataStream &s, QFont &font)
{
- if (!font.d->ref.deref())
- delete font.d;
-
- font.d = new QFontPrivate;
+ font.d.assign(0);
+ font.d.reset(new QFontPrivate);
font.resolve_mask = QFont::AllPropertiesResolved;
quint8 styleHint, styleStrategy = QFont::PreferDefault, charSet, weight, bits;
@@ -2233,7 +2237,7 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
font.d->request.styleStrategy = styleStrategy;
font.d->request.weight = weight;
- set_font_bits(s.version(), bits, font.d);
+ set_font_bits(s.version(), bits, font.d.data());
if (s.version() >= QDataStream::Qt_4_3) {
quint16 stretch;
@@ -2244,7 +2248,7 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
if (s.version() >= QDataStream::Qt_4_4) {
quint8 extendedBits;
s >> extendedBits;
- set_extended_font_bits(extendedBits, font.d);
+ set_extended_font_bits(extendedBits, font.d.data());
}
if (s.version() >= QDataStream::Qt_4_5) {
int value;
@@ -2326,7 +2330,7 @@ QDataStream &operator>>(QDataStream &s, QFont &font)
that is not screen-compatible.
*/
QFontInfo::QFontInfo(const QFont &font)
- : d(font.d)
+ : d(font.d.data())
{ d->ref.ref(); }
/*!
@@ -2599,7 +2603,14 @@ QFontCache *QFontCache::instance()
void QFontCache::cleanup()
{
- theFontCache()->setLocalData(0);
+ QThreadStorage<QFontCache *> *cache = 0;
+ QT_TRY {
+ cache = theFontCache();
+ } QT_CATCH (const std::bad_alloc &) {
+ // no cache - just ignore
+ }
+ if (cache && cache->hasLocalData())
+ cache->setLocalData(0);
}
#endif // QT_NO_THREAD
@@ -2612,8 +2623,8 @@ QFontCache::QFontCache()
QFontCache::~QFontCache()
{
{
- EngineDataCache::Iterator it = engineDataCache.begin(),
- end = engineDataCache.end();
+ EngineDataCache::ConstIterator it = engineDataCache.constBegin(),
+ end = engineDataCache.constEnd();
while (it != end) {
if (it.value()->ref == 0)
delete it.value();
@@ -2623,8 +2634,8 @@ QFontCache::~QFontCache()
++it;
}
}
- EngineCache::Iterator it = engineCache.begin(),
- end = engineCache.end();
+ EngineCache::ConstIterator it = engineCache.constBegin(),
+ end = engineCache.constEnd();
while (it != end) {
if (--it.value().data->cache_count == 0) {
if (it.value().data->ref == 0) {
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index cf67891..69abe05 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -44,6 +44,7 @@
#include <QtGui/qwindowdefs.h>
#include <QtCore/qstring.h>
+#include <QtCore/qscopedpointer.h>
#if defined(Q_WS_X11) || defined(Q_WS_QWS)
typedef struct FT_FaceRec_* FT_Face;
@@ -312,7 +313,7 @@ private:
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QFont &);
#endif
- QFontPrivate *d;
+ QScopedSharedPointer<QFontPrivate> d;
uint resolve_mask;
};
diff --git a/src/gui/text/qfont_s60.cpp b/src/gui/text/qfont_s60.cpp
new file mode 100644
index 0000000..533e51f
--- /dev/null
+++ b/src/gui/text/qfont_s60.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfont.h"
+#include "qt_s60_p.h"
+#include <private/qwindowsurface_s60_p.h>
+#include "qmutex.h"
+
+QT_BEGIN_NAMESPACE
+
+#if 1
+#ifdef QT_NO_FREETYPE
+Q_GLOBAL_STATIC(QMutex, lastResortFamilyMutex);
+#endif // QT_NO_FREETYPE
+
+QString QFont::lastResortFamily() const
+{
+#ifdef QT_NO_FREETYPE
+ QMutexLocker locker(lastResortFamilyMutex());
+ static QString family;
+ if (family.isEmpty()) {
+ QS60WindowSurface::unlockBitmapHeap();
+ CFont *font;
+ const TInt err = S60->screenDevice()->GetNearestFontInTwips(font, TFontSpec());
+ Q_ASSERT(err == KErrNone);
+ const TFontSpec spec = font->FontSpecInTwips();
+ family = QString((const QChar *)spec.iTypeface.iName.Ptr(), spec.iTypeface.iName.Length());
+ S60->screenDevice()->ReleaseFont(font);
+ QS60WindowSurface::lockBitmapHeap();
+ }
+ return family;
+#else
+ // For the FreeType case we just hard code the face name, since otherwise on
+ // East Asian systems we may get a name for a stroke based (non-ttf) font.
+
+ // TODO: Get the type face name in a proper way
+
+ const bool isJapaneseOrChineseSystem =
+ User::Language() == ELangJapanese || User::Language() == ELangPrcChinese;
+
+ return QLatin1String(isJapaneseOrChineseSystem?"Heisei Kaku Gothic S60":"Series 60 Sans");
+#endif // QT_NO_FREETYPE
+}
+#else // 0
+QString QFont::lastResortFamily() const
+{
+ return QLatin1String("Series 60 Sans");
+}
+#endif // 0
+
+QString QFont::defaultFamily() const
+{
+ return lastResortFamily();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 8d5b460..844c3f9 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -56,6 +56,11 @@
#include <stdlib.h>
#include <limits.h>
+#if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
+# include <ft2build.h>
+# include FT_TRUETYPE_TABLES_H
+#endif
+
// #define QFONTDATABASE_DEBUG
#ifdef QFONTDATABASE_DEBUG
# define FD_DEBUG qDebug
@@ -76,6 +81,8 @@
QT_BEGIN_NAMESPACE
+#define SMOOTH_SCALABLE 0xffff
+
extern int qt_defaultDpiY(); // in qfont.cpp
Q_GUI_EXPORT bool qt_enable_test_font = false;
@@ -141,10 +148,10 @@ struct QtFontSize
QtFontEncoding *encodingID(int id, uint xpoint = 0, uint xres = 0,
uint yres = 0, uint avgwidth = 0, bool add = false);
#endif // Q_WS_X11
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
QByteArray fileName;
int fileIndex;
-#endif
+#endif // defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
};
@@ -160,10 +167,13 @@ QtFontEncoding *QtFontSize::encodingID(int id, uint xpoint, uint xres,
if (!add) return 0;
- if (!(count % 4))
- encodings = (QtFontEncoding *)
+ if (!(count % 4)) {
+ QtFontEncoding *newEncodings = (QtFontEncoding *)
realloc(encodings,
(((count+4) >> 2) << 2) * sizeof(QtFontEncoding));
+ Q_CHECK_PTR(newEncodings);
+ encodings = newEncodings;
+ }
encodings[count].encoding = id;
encodings[count].xpoint = xpoint;
encodings[count].xres = xres;
@@ -215,12 +225,12 @@ struct QtFontStyle
delete [] weightName;
delete [] setwidthName;
#endif
-#if defined(Q_WS_X11) || defined(Q_WS_QWS)
+#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
while (count--) {
#ifdef Q_WS_X11
free(pixelSizes[count].encodings);
#endif
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
pixelSizes[count].fileName.~QByteArray();
#endif
}
@@ -238,7 +248,7 @@ struct QtFontStyle
const char *weightName;
const char *setwidthName;
#endif // Q_WS_X11
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
bool antialiased;
#endif
@@ -267,16 +277,19 @@ QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add)
if (!add)
return 0;
- if (!(count % 8))
- pixelSizes = (QtFontSize *)
+ if (!(count % 8)) {
+ QtFontSize *newPixelSizes = (QtFontSize *)
realloc(pixelSizes,
(((count+8) >> 3) << 3) * sizeof(QtFontSize));
+ Q_CHECK_PTR(newPixelSizes);
+ pixelSizes = newPixelSizes;
+ }
pixelSizes[count].pixelSize = size;
#ifdef Q_WS_X11
pixelSizes[count].count = 0;
pixelSizes[count].encodings = 0;
#endif
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
new (&pixelSizes[count].fileName) QByteArray;
pixelSizes[count].fileIndex = 0;
#endif
@@ -321,12 +334,16 @@ QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create)
return 0;
// qDebug("adding key (weight=%d, style=%d, oblique=%d stretch=%d) at %d", key.weight, key.style, key.oblique, key.stretch, pos);
- if (!(count % 8))
- styles = (QtFontStyle **)
+ if (!(count % 8)) {
+ QtFontStyle **newStyles = (QtFontStyle **)
realloc(styles, (((count+8) >> 3) << 3) * sizeof(QtFontStyle *));
+ Q_CHECK_PTR(newStyles);
+ styles = newStyles;
+ }
+ QtFontStyle *style = new QtFontStyle(key);
memmove(styles + pos + 1, styles + pos, (count-pos)*sizeof(QtFontStyle *));
- styles[pos] = new QtFontStyle(key);
+ styles[pos] = style;
count++;
return styles[pos];
}
@@ -358,7 +375,7 @@ struct QtFontFamily
fixedPitchComputed(false),
#endif
name(n), count(0), foundries(0)
-#if defined(Q_WS_QWS)
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
, bogusWritingSystems(false)
#endif
{
@@ -388,7 +405,7 @@ struct QtFontFamily
#endif
QString name;
-#ifdef Q_WS_X11
+#if defined(Q_WS_X11) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
QByteArray fontFilename;
int fontFileIndex;
#endif
@@ -398,7 +415,7 @@ struct QtFontFamily
int count;
QtFontFoundry **foundries;
-#ifdef Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
bool bogusWritingSystems;
QStringList fallbackFamilies;
#endif
@@ -431,10 +448,13 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create)
if (!create)
return 0;
- if (!(count % 8))
- foundries = (QtFontFoundry **)
+ if (!(count % 8)) {
+ QtFontFoundry **newFoundries = (QtFontFoundry **)
realloc(foundries,
(((count+8) >> 3) << 3) * sizeof(QtFontFoundry *));
+ Q_CHECK_PTR(newFoundries);
+ foundries = newFoundries;
+ }
foundries[count] = new QtFontFoundry(f);
return foundries[count++];
@@ -442,7 +462,7 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create)
// ### copied to tools/makeqpf/qpf2.cpp
-#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA))
+#if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA))
// see the Unicode subset bitfields in the MSDN docs
static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = {
// Any,
@@ -563,6 +583,15 @@ static QList<QFontDatabase::WritingSystem> determineWritingSystemsFromTrueTypeBi
}
#endif
+#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
+// class with virtual destructor, derived in qfontdatabase_s60.cpp
+class QFontDatabaseS60Store
+{
+public:
+ virtual ~QFontDatabaseS60Store() {};
+};
+#endif
+
class QFontDatabasePrivate
{
public:
@@ -571,6 +600,9 @@ public:
#if defined(Q_WS_QWS)
, stream(0)
#endif
+#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
+ , s60Store(0)
+#endif
{ }
~QFontDatabasePrivate() {
free();
@@ -582,6 +614,12 @@ public:
::free(families);
families = 0;
count = 0;
+#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
+ if (s60Store) {
+ delete s60Store;
+ s60Store = 0;
+ }
+#endif
// don't clear the memory fonts!
}
@@ -609,17 +647,22 @@ public:
#if defined(Q_WS_QWS)
bool loadFromCache(const QString &fontPath);
+ void addQPF2File(const QByteArray &file);
+#endif // Q_WS_QWS
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
void addFont(const QString &familyname, const char *foundryname, int weight,
bool italic, int pixelSize, const QByteArray &file, int fileIndex,
bool antialiased,
const QList<QFontDatabase::WritingSystem> &writingSystems = QList<QFontDatabase::WritingSystem>());
- void addQPF2File(const QByteArray &file);
#ifndef QT_NO_FREETYPE
QStringList addTTFile(const QByteArray &file, const QByteArray &fontData = QByteArray());
+#endif // QT_NO_FREETYPE
#endif
-
+#if defined(Q_WS_QWS)
QDataStream *stream;
QStringList fallbackFamilies;
+#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE)
+ const QFontDatabaseS60Store *s60Store;
#endif
};
@@ -654,17 +697,133 @@ QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create)
pos++;
// qDebug("adding family %s at %d total=%d", f.latin1(), pos, count);
- if (!(count % 8))
- families = (QtFontFamily **)
+ if (!(count % 8)) {
+ QtFontFamily **newFamilies = (QtFontFamily **)
realloc(families,
(((count+8) >> 3) << 3) * sizeof(QtFontFamily *));
+ Q_CHECK_PTR(newFamilies);
+ families = newFamilies;
+ }
+ QtFontFamily *family = new QtFontFamily(f);
memmove(families + pos + 1, families + pos, (count-pos)*sizeof(QtFontFamily *));
- families[pos] = new QtFontFamily(f);
+ families[pos] = family;
count++;
return families[pos];
}
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
+void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize,
+ const QByteArray &file, int fileIndex, bool antialiased,
+ const QList<QFontDatabase::WritingSystem> &writingSystems)
+{
+// qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased;
+ QtFontStyle::Key styleKey;
+ styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
+ styleKey.weight = weight;
+ styleKey.stretch = 100;
+ QtFontFamily *f = family(familyname, true);
+
+ if (writingSystems.isEmpty()) {
+ for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) {
+ f->writingSystems[ws] = QtFontFamily::Supported;
+ }
+ f->bogusWritingSystems = true;
+ } else {
+ for (int i = 0; i < writingSystems.count(); ++i) {
+ f->writingSystems[writingSystems.at(i)] = QtFontFamily::Supported;
+ }
+ }
+
+ QtFontFoundry *foundry = f->foundry(QString::fromLatin1(foundryname), true);
+ QtFontStyle *style = foundry->style(styleKey, true);
+ style->smoothScalable = (pixelSize == 0);
+ style->antialiased = antialiased;
+ QtFontSize *size = style->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true);
+ size->fileName = file;
+ size->fileIndex = fileIndex;
+
+#if defined(Q_WS_QWS)
+ if (stream) {
+ *stream << familyname << foundry->name << weight << quint8(italic) << pixelSize
+ << file << fileIndex << quint8(antialiased);
+ *stream << quint8(writingSystems.count());
+ for (int i = 0; i < writingSystems.count(); ++i)
+ *stream << quint8(writingSystems.at(i));
+ }
+#else // ..in case of defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
+ f->fontFilename = file;
+ f->fontFileIndex = fileIndex;
+#endif
+}
+#endif
+
+#if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE)
+QStringList QFontDatabasePrivate::addTTFile(const QByteArray &file, const QByteArray &fontData)
+{
+ QStringList families;
+ extern FT_Library qt_getFreetype();
+ FT_Library library = qt_getFreetype();
+
+ int index = 0;
+ int numFaces = 0;
+ do {
+ FT_Face face;
+ FT_Error error;
+ if (!fontData.isEmpty()) {
+ error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face);
+ } else {
+ error = FT_New_Face(library, file, index, &face);
+ }
+ if (error != FT_Err_Ok) {
+ qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error;
+ break;
+ }
+ numFaces = face->num_faces;
+
+ int weight = QFont::Normal;
+ bool italic = face->style_flags & FT_STYLE_FLAG_ITALIC;
+
+ if (face->style_flags & FT_STYLE_FLAG_BOLD)
+ weight = QFont::Bold;
+
+ QList<QFontDatabase::WritingSystem> writingSystems;
+ // detect symbol fonts
+ for (int i = 0; i < face->num_charmaps; ++i) {
+ FT_CharMap cm = face->charmaps[i];
+ if (cm->encoding == ft_encoding_adobe_custom
+ || cm->encoding == ft_encoding_symbol) {
+ writingSystems.append(QFontDatabase::Symbol);
+ break;
+ }
+ }
+ if (writingSystems.isEmpty()) {
+ TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
+ if (os2) {
+ quint32 unicodeRange[4] = {
+ os2->ulUnicodeRange1, os2->ulUnicodeRange2, os2->ulUnicodeRange3, os2->ulUnicodeRange4
+ };
+ quint32 codePageRange[2] = {
+ os2->ulCodePageRange1, os2->ulCodePageRange2
+ };
+
+ writingSystems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+ //for (int i = 0; i < writingSystems.count(); ++i)
+ // qDebug() << QFontDatabase::writingSystemName(writingSystems.at(i));
+ }
+ }
+
+ QString family = QString::fromAscii(face->family_name);
+ families.append(family);
+ addFont(family, /*foundry*/ "", weight, italic,
+ /*pixelsize*/ 0, file, index, /*antialias*/ true, writingSystems);
+
+ FT_Done_Face(face);
+ ++index;
+ } while (index < numFaces);
+ return families;
+}
+#endif
static const int scriptForWritingSystem[] = {
QUnicodeTables::Common, // Any
@@ -814,7 +973,7 @@ static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDe
#endif
#endif
-#if defined(Q_WS_X11) || defined(Q_WS_WIN)
+#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN)
static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key)
{
// look for the requested font in the engine data cache
@@ -866,8 +1025,6 @@ QMutex *qt_fontdatabase_mutex()
return fontDatabaseMutex();
}
-#define SMOOTH_SCALABLE 0xffff
-
QT_BEGIN_INCLUDE_NAMESPACE
#if defined(Q_WS_X11)
# include "qfontdatabase_x11.cpp"
@@ -877,6 +1034,8 @@ QT_BEGIN_INCLUDE_NAMESPACE
# include "qfontdatabase_win.cpp"
#elif defined(Q_WS_QWS)
# include "qfontdatabase_qws.cpp"
+#elif defined(Q_OS_SYMBIAN)
+# include "qfontdatabase_s60.cpp"
#endif
QT_END_INCLUDE_NAMESPACE
@@ -2254,7 +2413,16 @@ QString QFontDatabase::writingSystemSample(WritingSystem writingSystem)
sample += QChar(0xac2f);
break;
case Vietnamese:
+ {
+ static const char vietnameseUtf8[] = {
+ char(0xef), char(0xbb), char(0xbf), char(0xe1), char(0xbb), char(0x97),
+ char(0xe1), char(0xbb), char(0x99),
+ char(0xe1), char(0xbb), char(0x91),
+ char(0xe1), char(0xbb), char(0x93),
+ };
+ sample += QString::fromUtf8(vietnameseUtf8, sizeof(vietnameseUtf8));
break;
+ }
case Ogham:
sample += QChar(0x1681);
sample += QChar(0x1682);
diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h
index 4fffc33..e0a7c41 100644
--- a/src/gui/text/qfontdatabase.h
+++ b/src/gui/text/qfontdatabase.h
@@ -151,7 +151,7 @@ public:
private:
static void createDatabase();
static void parseFontName(const QString &name, QString &foundry, QString &family);
-#if defined(Q_WS_QWS)
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request);
#endif
static void load(const QFontPrivate *d, int script);
@@ -165,6 +165,7 @@ private:
friend class QFontDialogPrivate;
friend class QFontEngineMultiXLFD;
friend class QFontEngineMultiQWS;
+ friend class QFontEngineMultiS60;
QFontDatabasePrivate *d;
};
diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp
index d348e1b..ff6af98 100644
--- a/src/gui/text/qfontdatabase_qws.cpp
+++ b/src/gui/text/qfontdatabase_qws.cpp
@@ -50,7 +50,6 @@
#include <ft2build.h>
#include FT_FREETYPE_H
-#include FT_TRUETYPE_TABLES_H
#endif
#include "qfontengine_qpf_p.h"
@@ -83,44 +82,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
const quint8 DatabaseVersion = 4;
-void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize,
- const QByteArray &file, int fileIndex, bool antialiased,
- const QList<QFontDatabase::WritingSystem> &writingSystems)
-{
-// qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased;
- QtFontStyle::Key styleKey;
- styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal;
- styleKey.weight = weight;
- styleKey.stretch = 100;
- QtFontFamily *f = family(familyname, true);
-
- if (writingSystems.isEmpty()) {
- for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) {
- f->writingSystems[ws] = QtFontFamily::Supported;
- }
- f->bogusWritingSystems = true;
- } else {
- for (int i = 0; i < writingSystems.count(); ++i) {
- f->writingSystems[writingSystems.at(i)] = QtFontFamily::Supported;
- }
- }
-
- QtFontFoundry *foundry = f->foundry(QString::fromLatin1(foundryname), true);
- QtFontStyle *style = foundry->style(styleKey, true);
- style->smoothScalable = (pixelSize == 0);
- style->antialiased = antialiased;
- QtFontSize *size = style->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true);
- size->fileName = file;
- size->fileIndex = fileIndex;
-
- if (stream) {
- *stream << familyname << foundry->name << weight << quint8(italic) << pixelSize
- << file << fileIndex << quint8(antialiased);
- *stream << quint8(writingSystems.count());
- for (int i = 0; i < writingSystems.count(); ++i)
- *stream << quint8(writingSystems.at(i));
- }
-}
+// QFontDatabasePrivate::addFont() went into qfontdatabase.cpp
#ifndef QT_NO_QWS_QPF2
void QFontDatabasePrivate::addQPF2File(const QByteArray &file)
@@ -180,74 +142,9 @@ void QFontDatabasePrivate::addQPF2File(const QByteArray &file)
QT_CLOSE(f);
#endif
}
-#endif
-
-#ifndef QT_NO_FREETYPE
-QStringList QFontDatabasePrivate::addTTFile(const QByteArray &file, const QByteArray &fontData)
-{
- QStringList families;
- extern FT_Library qt_getFreetype();
- FT_Library library = qt_getFreetype();
-
- int index = 0;
- int numFaces = 0;
- do {
- FT_Face face;
- FT_Error error;
- if (!fontData.isEmpty()) {
- error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face);
- } else {
- error = FT_New_Face(library, file, index, &face);
- }
- if (error != FT_Err_Ok) {
- qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error;
- break;
- }
- numFaces = face->num_faces;
-
- int weight = QFont::Normal;
- bool italic = face->style_flags & FT_STYLE_FLAG_ITALIC;
-
- if (face->style_flags & FT_STYLE_FLAG_BOLD)
- weight = QFont::Bold;
-
- QList<QFontDatabase::WritingSystem> writingSystems;
- // detect symbol fonts
- for (int i = 0; i < face->num_charmaps; ++i) {
- FT_CharMap cm = face->charmaps[i];
- if (cm->encoding == ft_encoding_adobe_custom
- || cm->encoding == ft_encoding_symbol) {
- writingSystems.append(QFontDatabase::Symbol);
- break;
- }
- }
- if (writingSystems.isEmpty()) {
- TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
- if (os2) {
- quint32 unicodeRange[4] = {
- os2->ulUnicodeRange1, os2->ulUnicodeRange2, os2->ulUnicodeRange3, os2->ulUnicodeRange4
- };
- quint32 codePageRange[2] = {
- os2->ulCodePageRange1, os2->ulCodePageRange2
- };
-
- writingSystems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
- //for (int i = 0; i < writingSystems.count(); ++i)
- // qDebug() << QFontDatabase::writingSystemName(writingSystems.at(i));
- }
- }
+#endif // QT_NO_QWS_QPF2
- QString family = QString::fromAscii(face->family_name);
- families.append(family);
- addFont(family, /*foundry*/ "", weight, italic,
- /*pixelsize*/ 0, file, index, /*antialias*/ true, writingSystems);
-
- FT_Done_Face(face);
- ++index;
- } while (index < numFaces);
- return families;
-}
-#endif
+// QFontDatabasePrivate::addTTFile() went into qfontdatabase.cpp
static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt);
@@ -671,8 +568,8 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp,
QFontEngineQPF *fe = new QFontEngineQPF(request, res.data(), res.size());
if (fe->isValid())
return fe;
- qDebug() << "fontengine is not valid! " << size->fileName;
delete fe;
+ qDebug() << "fontengine is not valid! " << size->fileName;
} else {
qDebug() << "Resource not valid" << size->fileName;
}
@@ -682,8 +579,8 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp,
QFontEngineQPF *fe = new QFontEngineQPF(request, f);
if (fe->isValid())
return fe;
- qDebug() << "fontengine is not valid!";
delete fe; // will close f
+ qDebug() << "fontengine is not valid!";
}
#endif
} else
@@ -697,70 +594,67 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp,
static bool dontShareFonts = !qgetenv("QWS_NO_SHARE_FONTS").isEmpty();
bool shareFonts = !dontShareFonts;
- QFontEngine *engine = 0;
+ QScopedPointer<QFontEngine> engine;
#ifndef QT_NO_LIBRARY
QFontEngineFactoryInterface *factory = qobject_cast<QFontEngineFactoryInterface *>(loader()->instance(foundry->name));
- if (factory) {
- QFontEngineInfo info;
- info.setFamily(request.family);
- info.setPixelSize(request.pixelSize);
- info.setStyle(QFont::Style(request.style));
- info.setWeight(request.weight);
- // #### antialiased
-
- QAbstractFontEngine *customEngine = factory->create(info);
- if (customEngine) {
- engine = new QProxyFontEngine(customEngine, def);
-
- if (shareFonts) {
- QVariant hint = customEngine->fontProperty(QAbstractFontEngine::CacheGlyphsHint);
- if (hint.isValid())
- shareFonts = hint.toBool();
- else
- shareFonts = (pixelSize < 64);
- }
+ if (factory) {
+ QFontEngineInfo info;
+ info.setFamily(request.family);
+ info.setPixelSize(request.pixelSize);
+ info.setStyle(QFont::Style(request.style));
+ info.setWeight(request.weight);
+ // #### antialiased
+
+ QAbstractFontEngine *customEngine = factory->create(info);
+ if (customEngine) {
+ engine.reset(new QProxyFontEngine(customEngine, def));
+
+ if (shareFonts) {
+ QVariant hint = customEngine->fontProperty(QAbstractFontEngine::CacheGlyphsHint);
+ if (hint.isValid())
+ shareFonts = hint.toBool();
+ else
+ shareFonts = (pixelSize < 64);
}
+ }
}
#endif // QT_NO_LIBRARY
- if (!engine && !file.isEmpty() && QFile::exists(file) || privateDb()->isApplicationFont(file)) {
+ if ((engine.isNull() && !file.isEmpty() && QFile::exists(file)) || privateDb()->isApplicationFont(file)) {
QFontEngine::FaceId faceId;
faceId.filename = file.toLocal8Bit();
faceId.index = size->fileIndex;
#ifndef QT_NO_FREETYPE
- QFontEngineFT *fte = new QFontEngineFT(def);
+ QScopedPointer<QFontEngineFT> fte(new QFontEngineFT(def));
if (fte->init(faceId, style->antialiased,
style->antialiased ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono)) {
#ifdef QT_NO_QWS_QPF2
- return fte;
+ return fte.take();
#else
- engine = fte;
// try to distinguish between bdf and ttf fonts we can pre-render
// and don't try to share outline fonts
shareFonts = shareFonts
&& !fte->defaultGlyphs()->outline_drawing
&& !fte->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd')).isEmpty();
+ engine.reset(fte.take());
#endif
- } else {
- delete fte;
}
#endif // QT_NO_FREETYPE
}
- if (engine) {
+ if (!engine.isNull()) {
#if !defined(QT_NO_QWS_QPF2) && !defined(QT_FONTS_ARE_RESOURCES)
if (shareFonts) {
- QFontEngineQPF *fe = new QFontEngineQPF(def, -1, engine);
- engine = 0;
+ QScopedPointer<QFontEngineQPF> fe(new QFontEngineQPF(def, -1, engine.data()));
+ engine.take();
if (fe->isValid())
- return fe;
+ return fe.take();
qWarning("Initializing QFontEngineQPF failed for %s", qPrintable(file));
- engine = fe->takeRenderingEngine();
- delete fe;
+ engine.reset(fe->takeRenderingEngine());
}
#endif
- return engine;
+ return engine.take();
}
} else
{
@@ -787,20 +681,22 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp,
QtFontFamily *family, QtFontFoundry *foundry,
QtFontStyle *style, QtFontSize *size)
{
- QFontEngine *fe = loadSingleEngine(script, fp, request, family, foundry,
- style, size);
- if (fe
+ QScopedPointer<QFontEngine> engine(loadSingleEngine(script, fp, request, family, foundry,
+ style, size));
+ if (!engine.isNull()
&& script == QUnicodeTables::Common
- && !(request.styleStrategy & QFont::NoFontMerging) && !fe->symbol) {
+ && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) {
QStringList fallbacks = privateDb()->fallbackFamilies;
if (family && !family->fallbackFamilies.isEmpty())
fallbacks = family->fallbackFamilies;
- fe = new QFontEngineMultiQWS(fe, script, fallbacks);
+ QFontEngine *fe = new QFontEngineMultiQWS(engine.data(), script, fallbacks);
+ engine.take();
+ engine.reset(fe);
}
- return fe;
+ return engine.take();
}
static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp
new file mode 100644
index 0000000..416c3d1
--- /dev/null
+++ b/src/gui/text/qfontdatabase_s60.cpp
@@ -0,0 +1,414 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qapplication_p.h>
+#include "qdir.h"
+#include "qfont_p.h"
+#include "qfontengine_s60_p.h"
+#include "qabstractfileengine.h"
+#include "qdesktopservices.h"
+#include "qt_s60_p.h"
+#include "qendian.h"
+#include <private/qwindowsurface_s60_p.h>
+#include <private/qcore_symbian_p.h>
+#if defined(QT_NO_FREETYPE)
+#include <OPENFONT.H>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QFileInfoList alternativeFilePaths(const QString &path, const QStringList &nameFilters,
+ QDir::Filters filters = QDir::NoFilter, QDir::SortFlags sort = QDir::NoSort,
+ bool uniqueFileNames = true)
+{
+ QFileInfoList result;
+
+ // Prepare a 'soft to hard' drive list: W:, X: ... A:, Z:
+ QStringList driveStrings;
+ foreach (const QFileInfo &drive, QDir::drives())
+ driveStrings.append(drive.absolutePath());
+ driveStrings.sort();
+ const QString zDriveString("Z:/");
+ driveStrings.removeAll(zDriveString);
+ driveStrings.prepend(zDriveString);
+
+ QStringList uniqueFileNameList;
+ for (int i = driveStrings.count() - 1; i >= 0; --i) {
+ const QDir dirOnDrive(driveStrings.at(i) + path);
+ const QFileInfoList entriesOnDrive = dirOnDrive.entryInfoList(nameFilters, filters, sort);
+ if (uniqueFileNames) {
+ foreach(const QFileInfo &entry, entriesOnDrive) {
+ if (!uniqueFileNameList.contains(entry.fileName())) {
+ uniqueFileNameList.append(entry.fileName());
+ result.append(entry);
+ }
+ }
+ } else {
+ result.append(entriesOnDrive);
+ }
+ }
+ return result;
+}
+
+#if defined(QT_NO_FREETYPE)
+class QFontDatabaseS60StoreImplementation : public QFontDatabaseS60Store
+{
+public:
+ QFontDatabaseS60StoreImplementation();
+ ~QFontDatabaseS60StoreImplementation();
+
+ const QFontEngineS60Extensions *extension(const QString &typeface) const;
+
+private:
+ RHeap* m_heap;
+ CFontStore *m_store;
+ COpenFontRasterizer *m_rasterizer;
+ mutable QHash<QString, const QFontEngineS60Extensions *> m_extensions;
+};
+
+QFontDatabaseS60StoreImplementation::QFontDatabaseS60StoreImplementation()
+{
+ m_heap = User::ChunkHeap(NULL, 0x1000, 0x100000);
+ m_store = CFontStore::NewL(m_heap);
+ m_rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E));
+ m_store->InstallRasterizerL(m_rasterizer);
+
+ QStringList filters;
+ filters.append(QString::fromLatin1("*.ttf"));
+ filters.append(QString::fromLatin1("*.ccc"));
+ const QFileInfoList fontFiles = alternativeFilePaths(QString::fromLatin1("resource\\Fonts"), filters);
+ foreach (const QFileInfo &fontFileInfo, fontFiles) {
+ const QString fontFile = QDir::toNativeSeparators(fontFileInfo.absoluteFilePath());
+ m_store->AddFileL(qt_QString2TPtrC(fontFile));
+ }
+}
+QFontDatabaseS60StoreImplementation::~QFontDatabaseS60StoreImplementation()
+{
+ qDeleteAll(m_extensions);
+ delete m_rasterizer;
+ delete m_store;
+ m_heap->Close();
+}
+
+const QFontEngineS60Extensions *QFontDatabaseS60StoreImplementation::extension(const QString &typeface) const
+{
+ if (!m_extensions.contains(typeface)) {
+ CFont* font = NULL;
+ TFontSpec spec(qt_QString2TPtrC(typeface), 1);
+ spec.iHeight = 1;
+ const TInt err = m_store->GetNearestFontToDesignHeightInPixels(font, spec);
+ Q_ASSERT(err == KErrNone && font);
+ CBitmapFont *bitmapFont = static_cast<CBitmapFont*>(font);
+ m_extensions.insert(typeface, new QFontEngineS60Extensions(bitmapFont->OpenFont()));
+ }
+ return m_extensions.value(typeface);
+}
+#else
+class QFontEngineFTS60 : public QFontEngineFT
+{
+public:
+ QFontEngineFTS60(const QFontDef &fd);
+};
+
+QFontEngineFTS60::QFontEngineFTS60(const QFontDef &fd)
+ : QFontEngineFT(fd)
+{
+ default_hint_style = HintFull;
+}
+#endif // defined(QT_NO_FREETYPE)
+
+/*
+ QFontEngineS60::pixelsToPoints, QFontEngineS60::pointsToPixels, QFontEngineMultiS60::QFontEngineMultiS60
+ and QFontEngineMultiS60::QFontEngineMultiS60 should be in qfontengine_s60.cpp. But since also the
+ Freetype based font rendering need them, they are here.
+*/
+qreal QFontEngineS60::pixelsToPoints(qreal pixels, Qt::Orientation orientation)
+{
+ return (orientation == Qt::Horizontal?
+ S60->screenDevice()->HorizontalPixelsToTwips(pixels)
+ :S60->screenDevice()->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint;
+}
+
+qreal QFontEngineS60::pointsToPixels(qreal points, Qt::Orientation orientation)
+{
+ const int twips = points * KTwipsPerPoint;
+ return orientation == Qt::Horizontal?
+ S60->screenDevice()->HorizontalTwipsToPixels(twips)
+ :S60->screenDevice()->VerticalTwipsToPixels(twips);
+}
+
+QFontEngineMultiS60::QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies)
+ : QFontEngineMulti(fallbackFamilies.size() + 1)
+ , m_script(script)
+ , m_fallbackFamilies(fallbackFamilies)
+{
+ engines[0] = first;
+ first->ref.ref();
+ fontDef = engines[0]->fontDef;
+}
+
+void QFontEngineMultiS60::loadEngine(int at)
+{
+ Q_ASSERT(at < engines.size());
+ Q_ASSERT(engines.at(at) == 0);
+
+ QFontDef request = fontDef;
+ request.styleStrategy |= QFont::NoFontMerging;
+ request.family = m_fallbackFamilies.at(at-1);
+ engines[at] = QFontDatabase::findFont(m_script,
+ /*fontprivate*/0,
+ request);
+ Q_ASSERT(engines[at]);
+}
+
+static void initializeDb()
+{
+ QFontDatabasePrivate *db = privateDb();
+ if(!db || db->count)
+ return;
+
+#if defined(QT_NO_FREETYPE)
+ if (!db->s60Store)
+ db->s60Store = new QFontDatabaseS60StoreImplementation;
+
+ QS60WindowSurface::unlockBitmapHeap();
+ const int numTypeFaces = QS60Data::screenDevice()->NumTypefaces();
+ const QFontDatabaseS60StoreImplementation *store = dynamic_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store);
+ Q_ASSERT(store);
+ for (int i = 0; i < numTypeFaces; i++) {
+ TTypefaceSupport typefaceSupport;
+ QS60Data::screenDevice()->TypefaceSupport(typefaceSupport, i);
+ CFont *font; // We have to get a font instance in order to know all the details
+ TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11);
+ QS60Data::screenDevice()->GetNearestFontInPixels(font, fontSpec);
+ if (font->TypeUid() == KCFbsFontUid) {
+ TOpenFontFaceAttrib faceAttrib;
+ const CFbsFont *cfbsFont = dynamic_cast<const CFbsFont *>(font);
+ Q_ASSERT(cfbsFont);
+ cfbsFont->GetFaceAttrib(faceAttrib);
+
+ QtFontStyle::Key styleKey;
+ styleKey.style = faceAttrib.IsItalic()?QFont::StyleItalic:QFont::StyleNormal;
+ styleKey.weight = faceAttrib.IsBold()?QFont::Bold:QFont::Normal;
+
+ QString familyName((const QChar *)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length());
+ QtFontFamily *family = db->family(familyName, true);
+ family->fixedPitch = faceAttrib.IsMonoWidth();
+ QtFontFoundry *foundry = family->foundry(QString(), true);
+ QtFontStyle *style = foundry->style(styleKey, true);
+ style->smoothScalable = typefaceSupport.iIsScalable;
+ style->pixelSize(0, true);
+
+ const QFontEngineS60Extensions *extension = store->extension(familyName);
+ const QByteArray os2Table = extension->getSfntTable(MAKE_TAG('O', 'S', '/', '2'));
+ const unsigned char* data = reinterpret_cast<const unsigned char*>(os2Table.constData());
+ const unsigned char* ulUnicodeRange = data + 42;
+ quint32 unicodeRange[4] = {
+ qFromBigEndian<quint32>(ulUnicodeRange),
+ qFromBigEndian<quint32>(ulUnicodeRange + 4),
+ qFromBigEndian<quint32>(ulUnicodeRange + 8),
+ qFromBigEndian<quint32>(ulUnicodeRange + 12)
+ };
+ const unsigned char* ulCodePageRange = data + 78;
+ quint32 codePageRange[2] = {
+ qFromBigEndian<quint32>(ulCodePageRange),
+ qFromBigEndian<quint32>(ulCodePageRange + 4)
+ };
+ const QList<QFontDatabase::WritingSystem> writingSystems =
+ determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange);
+ foreach (const QFontDatabase::WritingSystem system, writingSystems)
+ family->writingSystems[system] = QtFontFamily::Supported;
+ }
+ QS60Data::screenDevice()->ReleaseFont(font);
+ }
+ QS60WindowSurface::lockBitmapHeap();
+#else // defined(QT_NO_FREETYPE)
+ QDir dir(QDesktopServices::storageLocation(QDesktopServices::FontsLocation));
+ dir.setNameFilters(QStringList() << QLatin1String("*.ttf")
+ << QLatin1String("*.ttc") << QLatin1String("*.pfa")
+ << QLatin1String("*.pfb"));
+ for (int i = 0; i < int(dir.count()); ++i) {
+ const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i]));
+ db->addTTFile(file);
+ }
+#endif // defined(QT_NO_FREETYPE)
+}
+
+static inline void load(const QString &family = QString(), int script = -1)
+{
+ Q_UNUSED(family)
+ Q_UNUSED(script)
+ initializeDb();
+}
+
+static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt)
+{
+ Q_UNUSED(fnt);
+}
+
+bool QFontDatabase::supportsThreadedFontRendering()
+{
+ return false;
+}
+
+static
+QFontDef cleanedFontDef(const QFontDef &req)
+{
+ QFontDef result = req;
+ if (result.pixelSize <= 0) {
+ result.pixelSize = QFontEngineS60::pointsToPixels(qMax(qreal(1.0), result.pointSize));
+ result.pointSize = 0;
+ }
+ return result;
+}
+
+QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate *, const QFontDef &req)
+{
+ const QFontCache::Key key(cleanedFontDef(req), script);
+
+ if (!privateDb()->count)
+ initializeDb();
+
+ QFontEngine *fe = QFontCache::instance()->findEngine(key);
+ if (!fe) {
+ // Making sure that fe->fontDef.family will be an existing font.
+ initializeDb();
+ QFontDatabasePrivate *db = privateDb();
+ QtFontDesc desc;
+ QList<int> blacklistedFamilies;
+ match(script, req, req.family, QString(), -1, &desc, blacklistedFamilies);
+ if (!desc.family) // falling back to application font
+ desc.family = db->family(QApplication::font().defaultFamily());
+ Q_ASSERT(desc.family);
+
+ // Making sure that desc.family supports the requested script
+ QtFontDesc mappedDesc;
+ bool supportsScript = false;
+ do {
+ match(script, req, QString(), QString(), -1, &mappedDesc, blacklistedFamilies);
+ if (mappedDesc.family == desc.family) {
+ supportsScript = true;
+ break;
+ }
+ blacklistedFamilies.append(mappedDesc.familyIndex);
+ } while (mappedDesc.family);
+ if (!supportsScript) {
+ blacklistedFamilies.clear();
+ match(script, req, QString(), QString(), -1, &mappedDesc, blacklistedFamilies);
+ if (mappedDesc.family)
+ desc = mappedDesc;
+ }
+
+ const QString fontFamily = desc.family->name;
+ QFontDef request = req;
+ request.family = fontFamily;
+#if defined(QT_NO_FREETYPE)
+ const QFontDatabaseS60StoreImplementation *store = dynamic_cast<const QFontDatabaseS60StoreImplementation*>(db->s60Store);
+ Q_ASSERT(store);
+ const QFontEngineS60Extensions *extension = store->extension(fontFamily);
+ fe = new QFontEngineS60(request, extension);
+#else
+ QFontEngine::FaceId faceId;
+ const QtFontFamily * const reqQtFontFamily = db->family(fontFamily);
+ faceId.filename = reqQtFontFamily->fontFilename;
+ faceId.index = reqQtFontFamily->fontFileIndex;
+
+ QFontEngineFTS60 *fte = new QFontEngineFTS60(cleanedFontDef(request));
+ if (fte->init(faceId, true, QFontEngineFT::Format_A8))
+ fe = fte;
+ else
+ delete fte;
+#endif
+
+ Q_ASSERT(fe);
+ if (script == QUnicodeTables::Common
+ && !(req.styleStrategy & QFont::NoFontMerging)
+ && !fe->symbol) {
+
+ QStringList commonFonts;
+ for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) {
+ if (scriptForWritingSystem[ws] != script)
+ continue;
+ for (int i = 0; i < db->count; ++i) {
+ if (db->families[i]->writingSystems[ws] & QtFontFamily::Supported)
+ commonFonts.append(db->families[i]->name);
+ }
+ }
+
+ // Hack: Prioritize .ccc fonts
+ const QString niceEastAsianFont(QLatin1String("Sans MT 936_S60"));
+ if (commonFonts.removeAll(niceEastAsianFont) > 0)
+ commonFonts.prepend(niceEastAsianFont);
+
+ fe = new QFontEngineMultiS60(fe, script, commonFonts);
+ }
+ }
+ fe->ref.ref();
+ QFontCache::instance()->insertEngine(key, fe);
+ return fe;
+}
+
+void QFontDatabase::load(const QFontPrivate *d, int script)
+{
+ QFontEngine *fe = 0;
+ QFontDef req = d->request;
+
+ if (!d->engineData) {
+ const QFontCache::Key key(cleanedFontDef(req), script);
+ getEngineData(d, key);
+ }
+
+ // the cached engineData could have already loaded the engine we want
+ if (d->engineData->engines[script])
+ fe = d->engineData->engines[script];
+
+ if (!fe) {
+ if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) {
+ fe = new QTestFontEngine(req.pixelSize);
+ fe->fontDef = req;
+ } else {
+ fe = findFont(script, d, req);
+ }
+ d->engineData->engines[script] = fe;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 05b3695..730137e 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -185,18 +185,20 @@ QFontEngine::QFontEngine()
QFontEngine::~QFontEngine()
{
- for (GlyphPointerHash::iterator it = m_glyphPointerHash.begin(), end = m_glyphPointerHash.end();
- it != end; ++it) {
- for (QList<QFontEngineGlyphCache*>::iterator it2 = it.value().begin(), end2 = it.value().end();
- it2 != end2; ++it2)
- delete *it2;
+ for (GlyphPointerHash::const_iterator it = m_glyphPointerHash.constBegin(),
+ end = m_glyphPointerHash.constEnd(); it != end; ++it) {
+ for (QList<QFontEngineGlyphCache*>::const_iterator it2 = it.value().constBegin(),
+ end2 = it.value().constEnd(); it2 != end2; ++it2) {
+ delete *it2;
+ }
}
m_glyphPointerHash.clear();
- for (GlyphIntHash::iterator it = m_glyphIntHash.begin(), end = m_glyphIntHash.end();
- it != end; ++it) {
- for (QList<QFontEngineGlyphCache*>::iterator it2 = it.value().begin(), end2 = it.value().end();
- it2 != end2; ++it2)
- delete *it2;
+ for (GlyphIntHash::const_iterator it = m_glyphIntHash.constBegin(),
+ end = m_glyphIntHash.constEnd(); it != end; ++it) {
+ for (QList<QFontEngineGlyphCache*>::const_iterator it2 = it.value().constBegin(),
+ end2 = it.value().constEnd(); it2 != end2; ++it2) {
+ delete *it2;
+ }
}
m_glyphIntHash.clear();
qHBFreeFace(hbFace);
@@ -812,7 +814,7 @@ QFontEngineGlyphCache *QFontEngine::glyphCache(QFontEngineGlyphCache::Type key,
return 0;
}
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs)
{
uint left_right = (left << 16) + right;
@@ -1034,9 +1036,8 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
return 0;
quint16 segCountX2 = qFromBigEndian<quint16>(cmap + 6);
const unsigned char *ends = cmap + 14;
- quint16 endIndex = 0;
int i = 0;
- for (; i < segCountX2/2 && (endIndex = qFromBigEndian<quint16>(ends + 2*i)) < unicode; i++) {}
+ for (; i < segCountX2/2 && qFromBigEndian<quint16>(ends + 2*i) < unicode; i++) {}
const unsigned char *idx = ends + segCountX2 + 2 + 2*i;
quint16 startIndex = qFromBigEndian<quint16>(idx);
@@ -1103,6 +1104,18 @@ quint32 QFontEngine::getTrueTypeGlyphIndex(const uchar *cmap, uint unicode)
return 0;
}
+Q_GLOBAL_STATIC_WITH_INITIALIZER(QVector<QRgb>, qt_grayPalette, {
+ x->resize(256);
+ QRgb *it = x->data();
+ for (int i = 0; i < x->size(); ++i, ++it)
+ *it = 0xff000000 | i | (i<<8) | (i<<16);
+});
+
+const QVector<QRgb> &QFontEngine::grayPalette()
+{
+ return *qt_grayPalette();
+}
+
// ------------------------------------------------------------------
// The box font engine
// ------------------------------------------------------------------
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index a0b6f0c..ab04dc7 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -191,6 +191,9 @@ HB_Error QFreetypeFace::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 p
/*
* One font file can contain more than one font (bold/italic for example)
* find the right one and return it.
+ *
+ * Returns the freetype face or 0 in case of an empty file or any other problems
+ * (like not being able to open the file)
*/
QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id)
{
@@ -203,7 +206,7 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id)
QFreetypeFace *freetype = freetypeData->faces.value(face_id, 0);
if (!freetype) {
- freetype = new QFreetypeFace;
+ QScopedPointer<QFreetypeFace> newFreetype(new QFreetypeFace);
FT_Face face;
QFile file(QString::fromUtf8(face_id.filename));
if (face_id.filename.startsWith(":qmemoryfonts/")) {
@@ -212,84 +215,82 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id)
QByteArray idx = face_id.filename;
idx.remove(0, 14); // remove ':qmemoryfonts/'
bool ok = false;
- freetype->fontData = qt_fontdata_from_index(idx.toInt(&ok));
+ newFreetype->fontData = qt_fontdata_from_index(idx.toInt(&ok));
if (!ok)
- freetype->fontData = QByteArray();
+ newFreetype->fontData = QByteArray();
} else if (!(file.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
if (!file.open(QIODevice::ReadOnly)) {
- delete freetype;
return 0;
}
- freetype->fontData = file.readAll();
+ newFreetype->fontData = file.readAll();
}
- if (!freetype->fontData.isEmpty()) {
- if (FT_New_Memory_Face(freetypeData->library, (const FT_Byte *)freetype->fontData.constData(), freetype->fontData.size(), face_id.index, &face)) {
- delete freetype;
+ if (!newFreetype->fontData.isEmpty()) {
+ if (FT_New_Memory_Face(freetypeData->library, (const FT_Byte *)newFreetype->fontData.constData(), newFreetype->fontData.size(), face_id.index, &face)) {
return 0;
}
} else if (FT_New_Face(freetypeData->library, face_id.filename, face_id.index, &face)) {
- delete freetype;
return 0;
}
- freetype->face = face;
-
- freetype->hbFace = qHBNewFace(face, hb_getSFntTable);
- freetype->ref = 0;
- freetype->xsize = 0;
- freetype->ysize = 0;
- freetype->matrix.xx = 0x10000;
- freetype->matrix.yy = 0x10000;
- freetype->matrix.xy = 0;
- freetype->matrix.yx = 0;
- freetype->unicode_map = 0;
- freetype->symbol_map = 0;
+ newFreetype->face = face;
+
+ newFreetype->hbFace = qHBNewFace(face, hb_getSFntTable);
+ newFreetype->ref = 0;
+ newFreetype->xsize = 0;
+ newFreetype->ysize = 0;
+ newFreetype->matrix.xx = 0x10000;
+ newFreetype->matrix.yy = 0x10000;
+ newFreetype->matrix.xy = 0;
+ newFreetype->matrix.yx = 0;
+ newFreetype->unicode_map = 0;
+ newFreetype->symbol_map = 0;
#ifndef QT_NO_FONTCONFIG
- freetype->charset = 0;
+ newFreetype->charset = 0;
#endif
- memset(freetype->cmapCache, 0, sizeof(freetype->cmapCache));
+ memset(newFreetype->cmapCache, 0, sizeof(newFreetype->cmapCache));
- for (int i = 0; i < freetype->face->num_charmaps; ++i) {
- FT_CharMap cm = freetype->face->charmaps[i];
+ for (int i = 0; i < newFreetype->face->num_charmaps; ++i) {
+ FT_CharMap cm = newFreetype->face->charmaps[i];
switch(cm->encoding) {
case FT_ENCODING_UNICODE:
- freetype->unicode_map = cm;
+ newFreetype->unicode_map = cm;
break;
case FT_ENCODING_APPLE_ROMAN:
case FT_ENCODING_ADOBE_LATIN_1:
- if (!freetype->unicode_map || freetype->unicode_map->encoding != FT_ENCODING_UNICODE)
- freetype->unicode_map = cm;
+ if (!newFreetype->unicode_map || newFreetype->unicode_map->encoding != FT_ENCODING_UNICODE)
+ newFreetype->unicode_map = cm;
break;
case FT_ENCODING_ADOBE_CUSTOM:
case FT_ENCODING_MS_SYMBOL:
- if (!freetype->symbol_map)
- freetype->symbol_map = cm;
+ if (!newFreetype->symbol_map)
+ newFreetype->symbol_map = cm;
break;
default:
break;
}
}
- if (!FT_IS_SCALABLE(freetype->face) && freetype->face->num_fixed_sizes == 1)
- FT_Set_Char_Size (face, X_SIZE(freetype->face, 0), Y_SIZE(freetype->face, 0), 0, 0);
+ if (!FT_IS_SCALABLE(newFreetype->face) && newFreetype->face->num_fixed_sizes == 1)
+ FT_Set_Char_Size (face, X_SIZE(newFreetype->face, 0), Y_SIZE(newFreetype->face, 0), 0, 0);
# if 0
FcChar8 *name;
FcPatternGetString(pattern, FC_FAMILY, 0, &name);
qDebug("%s: using maps: default: %x unicode: %x, symbol: %x", name,
- freetype->face->charmap ? freetype->face->charmap->encoding : 0,
- freetype->unicode_map ? freetype->unicode_map->encoding : 0,
- freetype->symbol_map ? freetype->symbol_map->encoding : 0);
+ newFreetype->face->charmap ? newFreetype->face->charmap->encoding : 0,
+ newFreetype->unicode_map ? newFreetype->unicode_map->encoding : 0,
+ newFreetype->symbol_map ? newFreetype->symbol_map->encoding : 0);
for (int i = 0; i < 256; i += 8)
qDebug(" %x: %d %d %d %d %d %d %d %d", i,
- FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i),
- FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i),
- FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i),
- FcCharSetHasChar(freetype->charset, i), FcCharSetHasChar(freetype->charset, i));
+ FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
+ FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
+ FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i),
+ FcCharSetHasChar(newFreetype->charset, i), FcCharSetHasChar(newFreetype->charset, i));
#endif
- FT_Set_Charmap(freetype->face, freetype->unicode_map);
- freetypeData->faces.insert(face_id, freetype);
+ FT_Set_Charmap(newFreetype->face, newFreetype->unicode_map);
+ freetypeData->faces.insert(face_id, newFreetype.data());
+ freetype = newFreetype.take();
}
freetype->ref.ref();
return freetype;
@@ -606,6 +607,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
kerning_pairs_loaded = false;
transform = false;
antialias = true;
+ freetype = 0;
default_load_flags = 0;
default_hint_style = HintNone;
subpixelType = Subpixel_None;
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index fa7a6c2..aa1cd0a 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -119,6 +119,7 @@ struct QFreetypeFace
static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path, bool = false);
private:
+ friend class QScopedPointer<QFreetypeFace>;
QFreetypeFace() : _lock(QMutex::Recursive) {}
~QFreetypeFace() {}
QAtomicInt ref;
@@ -255,7 +256,7 @@ public:
QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
bool loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, GlyphFormat format = Format_Render);
-#if defined(Q_WS_QWS)
+#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
virtual void draw(QPaintEngine * /*p*/, qreal /*x*/, qreal /*y*/, const QTextItemInt & /*si*/) {}
#endif
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 2113fff..2b27d41 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -70,7 +70,7 @@
# include "private/qcore_mac_p.h"
#endif
-#include "qfontengineglyphcache_p.h"
+#include <private/qfontengineglyphcache_p.h>
struct glyph_metrics_t;
typedef unsigned int glyph_t;
@@ -112,6 +112,10 @@ public:
QPF1,
QPF2,
Proxy,
+
+ // S60 types
+ S60FontEngine, // Cannot be simply called "S60". Reason is qt_s60Data.h
+
TestFontEngine = 0x1000
};
@@ -163,7 +167,7 @@ public:
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const {}
virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const;
-#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
+#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN)
virtual void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si) = 0;
#endif
virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
@@ -230,7 +234,7 @@ public:
bool symbol;
mutable HB_FontRec hbFont;
mutable HB_Face hbFace;
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS)
+#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
struct KernPair {
uint left_right;
QFixed adjust;
@@ -246,6 +250,9 @@ public:
int glyphFormat;
+protected:
+ static const QVector<QRgb> &grayPalette();
+
private:
/// remove old entries from the glyph cache. Helper method for the setGlyphCache ones.
void expireGlyphCache();
@@ -321,7 +328,7 @@ public:
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const;
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const;
-#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC)
+#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN)
void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si);
#endif
virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags);
@@ -618,4 +625,8 @@ QT_END_NAMESPACE
# include "private/qfontengine_win_p.h"
#endif
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE)
+# include "private/qfontengine_ft_p.h"
+#endif
+
#endif // QFONTENGINE_P_H
diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp
index b255694..232f839 100644
--- a/src/gui/text/qfontengine_qpf.cpp
+++ b/src/gui/text/qfontengine_qpf.cpp
@@ -326,8 +326,8 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
fileName.replace(QLatin1Char(' '), QLatin1Char('_'));
fileName.prepend(qws_fontCacheDir());
- const QByteArray encodedName = QFile::encodeName(fileName);
- if (::access(encodedName, F_OK) == 0) {
+ encodedFileName = QFile::encodeName(fileName);
+ if (::access(encodedFileName, F_OK) == 0) {
#if defined(DEBUG_FONTENGINE)
qDebug() << "found existing qpf:" << fileName;
#endif
@@ -475,15 +475,21 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
#endif
#if defined(Q_WS_QWS)
if (isValid() && renderingFontEngine)
- qt_fbdpy->sendFontCommand(QWSFontCommand::StartedUsingFont, QFile::encodeName(fileName));
+ qt_fbdpy->sendFontCommand(QWSFontCommand::StartedUsingFont, encodedFileName);
#endif
}
QFontEngineQPF::~QFontEngineQPF()
{
#if defined(Q_WS_QWS)
- if (isValid() && renderingFontEngine)
- qt_fbdpy->sendFontCommand(QWSFontCommand::StoppedUsingFont, QFile::encodeName(fileName));
+ if (isValid() && renderingFontEngine) {
+ QT_TRY {
+ qt_fbdpy->sendFontCommand(QWSFontCommand::StoppedUsingFont, encodedFileName);
+ } QT_CATCH(...) {
+ qDebug("QFontEngineQPF::~QFontEngineQPF: Out of memory");
+ // ignore.
+ }
+ }
#endif
delete renderingFontEngine;
if (fontData)
@@ -1129,6 +1135,11 @@ void QPFGenerator::writeTaggedQFixed(QFontEngineQPF::HeaderTag tag, QFixed value
#endif // QT_NO_QWS_QPF2
+/*
+ Creates a new multi qws engine.
+
+ This function takes ownership of the QFontEngine, increasing it's refcount.
+*/
QFontEngineMultiQWS::QFontEngineMultiQWS(QFontEngine *fe, int _script, const QStringList &fallbacks)
: QFontEngineMulti(fallbacks.size() + 1),
fallbackFamilies(fallbacks), script(_script)
diff --git a/src/gui/text/qfontengine_qpf_p.h b/src/gui/text/qfontengine_qpf_p.h
index bf6862a..0fc0730 100644
--- a/src/gui/text/qfontengine_qpf_p.h
+++ b/src/gui/text/qfontengine_qpf_p.h
@@ -243,6 +243,7 @@ private:
quint32 glyphDataOffset;
quint32 glyphDataSize;
QString fileName;
+ QByteArray encodedFileName;
bool readOnly;
QFreetypeFace *freetype;
diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp
new file mode 100644
index 0000000..f485afb
--- /dev/null
+++ b/src/gui/text/qfontengine_s60.cpp
@@ -0,0 +1,324 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfontengine_s60_p.h"
+#include "qtextengine_p.h"
+#include "qglobal.h"
+#include <private/qapplication_p.h>
+#include <private/qwindowsurface_s60_p.h>
+#include "qimage.h"
+#include "qt_s60_p.h"
+
+#include <e32base.h>
+#include <e32std.h>
+#include <EIKENV.H>
+#include <GDI.H>
+
+QT_BEGIN_NAMESPACE
+
+QFontEngineS60Extensions::QFontEngineS60Extensions(COpenFont *font)
+ : m_font(font)
+ , m_cmap(0)
+ , m_symbolCMap(false)
+{
+ TAny *shapingExtension = NULL;
+ m_font->ExtendedInterface(KUidOpenFontShapingExtension, shapingExtension);
+ m_shapingExtension = static_cast<MOpenFontShapingExtension*>(shapingExtension);
+ TAny *trueTypeExtension = NULL;
+ m_font->ExtendedInterface(KUidOpenFontTrueTypeExtension, trueTypeExtension);
+ m_trueTypeExtension = static_cast<MOpenFontTrueTypeExtension*>(trueTypeExtension);
+ Q_ASSERT(m_shapingExtension && m_trueTypeExtension);
+}
+
+QByteArray QFontEngineS60Extensions::getSfntTable(uint tag) const
+{
+ Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag));
+ TInt error = KErrNone;
+ TInt tableByteLength = 0;
+ TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength);
+ QByteArray result(static_cast<const char*>(table), tableByteLength);
+ m_trueTypeExtension->ReleaseTrueTypeTable(table);
+ return result;
+}
+
+const unsigned char *QFontEngineS60Extensions::cmap() const
+{
+ if (!m_cmap) {
+ m_cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p'));
+ int size = 0;
+ m_cmap = QFontEngineS60::getCMap(reinterpret_cast<const uchar *>(m_cmapTable.constData()), m_cmapTable.size(), &m_symbolCMap, &size);
+ }
+ return m_cmap;
+}
+
+QPainterPath QFontEngineS60Extensions::glyphOutline(glyph_t glyph) const
+{
+ QPainterPath result;
+ QPolygonF polygon;
+ TInt glyphIndex = glyph;
+ TInt pointNumber = 0;
+ TInt x, y;
+ while (m_shapingExtension->GlyphPointInFontUnits(glyphIndex, pointNumber++, x, y)) {
+ const QPointF point(qreal(x) / 0xffff, qreal(y) / 0xffff);
+ if (polygon.contains(point)) {
+ result.addPolygon(polygon);
+ result.closeSubpath();
+ polygon.clear();
+ } else {
+ polygon.append(point);
+ }
+ }
+ return result;
+}
+
+// duplicated from qfontengine_xyz.cpp
+static inline unsigned int getChar(const QChar *str, int &i, const int len)
+{
+ unsigned int uc = str[i].unicode();
+ if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) {
+ uint low = str[i+1].unicode();
+ if (low >= 0xdc00 && low < 0xe000) {
+ uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000;
+ ++i;
+ }
+ }
+ return uc;
+}
+
+QFontEngineS60::QFontEngineS60(const QFontDef &request, const QFontEngineS60Extensions *extensions)
+ : m_extensions(extensions)
+{
+ QFontEngine::fontDef = request;
+ m_fontSizeInPixels = (request.pixelSize >= 0)?
+ request.pixelSize:pointsToPixels(request.pointSize);
+ QS60WindowSurface::unlockBitmapHeap();
+ m_textRenderBitmap = new (ELeave) CFbsBitmap();
+ const TSize bitmapSize(1, 1); // It is just a dummy bitmap that I need to keep the font alive (or maybe not)
+ User::LeaveIfError(m_textRenderBitmap->Create(bitmapSize, EGray256));
+ m_textRenderBitmapDevice = CFbsBitmapDevice::NewL(m_textRenderBitmap);
+ User::LeaveIfError(m_textRenderBitmapDevice->CreateContext(m_textRenderBitmapGc));
+ cache_cost = sizeof(QFontEngineS60) + bitmapSize.iHeight * bitmapSize.iWidth * 4;
+
+ TFontSpec fontSpec(qt_QString2TPtrC(request.family), m_fontSizeInPixels);
+ fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap);
+ fontSpec.iFontStyle.SetPosture(request.style == QFont::StyleNormal?EPostureUpright:EPostureItalic);
+ fontSpec.iFontStyle.SetStrokeWeight(request.weight > QFont::Normal?EStrokeWeightBold:EStrokeWeightNormal);
+ const TInt errorCode = m_textRenderBitmapDevice->GetNearestFontInPixels(m_font, fontSpec);
+ Q_ASSERT(errorCode == 0);
+ m_textRenderBitmapGc->UseFont(m_font);
+ QS60WindowSurface::lockBitmapHeap();
+}
+
+QFontEngineS60::~QFontEngineS60()
+{
+ QS60WindowSurface::unlockBitmapHeap();
+ m_textRenderBitmapGc->DiscardFont();
+ delete m_textRenderBitmapGc;
+ m_textRenderBitmapGc = NULL;
+ m_textRenderBitmapDevice->ReleaseFont(m_font);
+ delete m_textRenderBitmapDevice;
+ m_textRenderBitmapDevice = NULL;
+ delete m_textRenderBitmap;
+ m_textRenderBitmap = NULL;
+ QS60WindowSurface::lockBitmapHeap();
+}
+
+bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const
+{
+ if (*nglyphs < len) {
+ *nglyphs = len;
+ return false;
+ }
+
+ HB_Glyph *g = glyphs->glyphs;
+ const unsigned char* cmap = m_extensions->cmap();
+ for (int i = 0; i < len; ++i) {
+ const unsigned int uc = getChar(characters, i, len);
+ *g++ = QFontEngine::getTrueTypeGlyphIndex(cmap, uc);
+ }
+
+ glyphs->numGlyphs = g - glyphs->glyphs;
+ *nglyphs = glyphs->numGlyphs;
+
+ if (flags & QTextEngine::GlyphIndicesOnly)
+ return true;
+
+ recalcAdvances(glyphs, flags);
+ return true;
+}
+
+void QFontEngineS60::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
+{
+ Q_UNUSED(flags);
+ for (int i = 0; i < glyphs->numGlyphs; i++) {
+ const glyph_metrics_t bbox = boundingBox_const(glyphs->glyphs[i]);
+ glyphs->advances_x[i] = glyphs->offsets[i].x = bbox.xoff;
+ glyphs->advances_y[i] = glyphs->offsets[i].y = bbox.yoff;
+ }
+}
+
+QImage QFontEngineS60::alphaMapForGlyph(glyph_t glyph)
+{
+ TOpenFontCharMetrics metrics;
+ const TUint8 *glyphBitmapBytes;
+ TSize glyphBitmapSize;
+ getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize);
+ QImage result(glyphBitmapBytes, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight, glyphBitmapSize.iWidth, QImage::Format_Indexed8);
+ result.setColorTable(grayPalette());
+
+ // The above setColorTable() call detached the image data anyway, so why not shape tha data a bit, while we can.
+ // CFont::GetCharacterData() returns 8-bit data that obviously was 4-bit data before, and converted to 8-bit incorrectly.
+ // The data values are 0x00, 0x10 ... 0xe0, 0xf0. So, a real opaque 0xff is never reached, which we get punished
+ // for every time we want to blit this glyph in the raster paint engine.
+ // "Fix" is to convert all 0xf0 to 0xff. Is fine, quality wise, and I assume faster than correcting all values.
+ // Blitting is however, evidentially faster now.
+ const int bpl = result.bytesPerLine();
+ for (int row = 0; row < result.height(); ++row) {
+ uchar *scanLine = result.scanLine(row);
+ for (int column = 0; column < bpl; ++column) {
+ if (*scanLine == 0xf0)
+ *scanLine = 0xff;
+ scanLine++;
+ }
+ }
+
+ return result;
+}
+
+glyph_metrics_t QFontEngineS60::boundingBox(const QGlyphLayout &glyphs)
+{
+ if (glyphs.numGlyphs == 0)
+ return glyph_metrics_t();
+
+ QFixed w = 0;
+ for (int i = 0; i < glyphs.numGlyphs; ++i)
+ w += glyphs.effectiveAdvance(i);
+
+ return glyph_metrics_t(0, -ascent(), w, ascent()+descent()+1, w, 0);
+}
+
+glyph_metrics_t QFontEngineS60::boundingBox_const(glyph_t glyph) const
+{
+ TOpenFontCharMetrics metrics;
+ const TUint8 *glyphBitmapBytes;
+ TSize glyphBitmapSize;
+ getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize);
+ TRect glyphBounds;
+ metrics.GetHorizBounds(glyphBounds);
+ const glyph_metrics_t result(
+ glyphBounds.iTl.iX,
+ glyphBounds.iTl.iY,
+ glyphBounds.Width(),
+ glyphBounds.Height(),
+ metrics.HorizAdvance(),
+ 0
+ );
+ return result;
+}
+
+glyph_metrics_t QFontEngineS60::boundingBox(glyph_t glyph)
+{
+ return boundingBox_const(glyph);
+}
+
+QFixed QFontEngineS60::ascent() const
+{
+ return m_font->FontMaxAscent();
+}
+
+QFixed QFontEngineS60::descent() const
+{
+ return m_font->FontMaxDescent();
+}
+
+QFixed QFontEngineS60::leading() const
+{
+ return 0;
+}
+
+qreal QFontEngineS60::maxCharWidth() const
+{
+ return m_font->MaxCharWidthInPixels();
+}
+
+const char *QFontEngineS60::name() const
+{
+ return "QFontEngineS60";
+}
+
+bool QFontEngineS60::canRender(const QChar *string, int len)
+{
+ const unsigned char *cmap = m_extensions->cmap();
+ for (int i = 0; i < len; ++i) {
+ const unsigned int uc = getChar(string, i, len);
+ if (QFontEngine::getTrueTypeGlyphIndex(cmap, uc) == 0)
+ return false;
+ }
+ return true;
+}
+
+QByteArray QFontEngineS60::getSfntTable(uint tag) const
+{
+ return m_extensions->getSfntTable(tag);
+}
+
+QFontEngine::Type QFontEngineS60::type() const
+{
+ return QFontEngine::S60FontEngine;
+}
+
+void QFontEngineS60::getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const
+{
+ // Setting the most significant bit tells GetCharacterData
+ // that 'code' is a Glyph ID, rather than a UTF-16 value
+ const TUint specialCode = (TUint)glyph | 0x80000000;
+
+ const CFont::TCharacterDataAvailability availability =
+ m_font->GetCharacterData(specialCode, metrics, bitmap, bitmapSize);
+ const glyph_t fallbackGlyph = '?';
+ if (availability != CFont::EAllCharacterData) {
+ const CFont::TCharacterDataAvailability fallbackAvailability =
+ m_font->GetCharacterData(fallbackGlyph, metrics, bitmap, bitmapSize);
+ Q_ASSERT(fallbackAvailability == CFont::EAllCharacterData);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h
new file mode 100644
index 0000000..2998de8
--- /dev/null
+++ b/src/gui/text/qfontengine_s60_p.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFONTENGINE_S60_P_H
+#define QFONTENGINE_S60_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qconfig.h"
+#include "qfontengine_p.h"
+#include "qsize.h"
+#include <OPENFONT.H>
+
+class CFbsBitmap;
+class CFbsBitmapDevice;
+class CFbsBitGc;
+class CFont;
+
+QT_BEGIN_NAMESPACE
+
+// ..gives us access to truetype tables, UTF-16<->GlyphID mapping, and glyph outlines
+class QFontEngineS60Extensions
+{
+public:
+ QFontEngineS60Extensions(COpenFont *font);
+
+ QByteArray getSfntTable(uint tag) const;
+ const unsigned char *cmap() const;
+ QPainterPath glyphOutline(glyph_t glyph) const;
+
+private:
+ COpenFont *m_font;
+ const MOpenFontShapingExtension *m_shapingExtension;
+ mutable MOpenFontTrueTypeExtension *m_trueTypeExtension;
+ mutable const unsigned char *m_cmap;
+ mutable bool m_symbolCMap;
+ mutable QByteArray m_cmapTable;
+};
+
+class QFontEngineS60 : public QFontEngine
+{
+public:
+ QFontEngineS60(const QFontDef &fontDef, const QFontEngineS60Extensions *extensions);
+ ~QFontEngineS60();
+
+ bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const;
+ void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const;
+
+ QImage alphaMapForGlyph(glyph_t glyph);
+
+ glyph_metrics_t boundingBox(const QGlyphLayout &glyphs);
+ glyph_metrics_t boundingBox_const(glyph_t glyph) const; // Const correctnes quirk.
+ glyph_metrics_t boundingBox(glyph_t glyph);
+
+ QFixed ascent() const;
+ QFixed descent() const;
+ QFixed leading() const;
+ qreal maxCharWidth() const;
+ qreal minLeftBearing() const { return 0; }
+ qreal minRightBearing() const { return 0; }
+
+ QByteArray getSfntTable(uint tag) const;
+
+ static qreal pixelsToPoints(qreal pixels, Qt::Orientation orientation = Qt::Horizontal);
+ static qreal pointsToPixels(qreal points, Qt::Orientation orientation = Qt::Horizontal);
+
+ const char *name() const;
+
+ bool canRender(const QChar *string, int len);
+
+ Type type() const;
+
+private:
+ friend class QFontPrivate;
+
+ QFixed glyphAdvance(HB_Glyph glyph) const;
+ void getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const;
+
+ CFbsBitmap *m_textRenderBitmap;
+ CFbsBitmapDevice *m_textRenderBitmapDevice;
+ CFbsBitGc *m_textRenderBitmapGc;
+ CFont* m_font;
+ const QFontEngineS60Extensions *m_extensions;
+ qreal m_fontSizeInPixels;
+};
+
+class QFontEngineMultiS60 : public QFontEngineMulti
+{
+public:
+ QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies);
+ void loadEngine(int at);
+
+ int m_script;
+ QStringList m_fallbackFamilies;
+};
+
+QT_END_NAMESPACE
+
+#endif // QFONTENGINE_S60_P_H
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index abab91c..9f19fd9 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -164,7 +164,7 @@ extern int qt_defaultDpi();
metrics that are compatible with a certain paint device.
*/
QFontMetrics::QFontMetrics(const QFont &font)
- : d(font.d)
+ : d(font.d.data())
{
d->ref.ref();
}
@@ -196,7 +196,7 @@ QFontMetrics::QFontMetrics(const QFont &font, QPaintDevice *paintdevice)
d->dpi = dpi;
d->screen = screen;
} else {
- d = font.d;
+ d = font.d.data();
d->ref.ref();
}
@@ -1006,7 +1006,7 @@ QFontMetricsF &QFontMetricsF::operator=(const QFontMetrics &other)
metrics that are compatible with a certain paint device.
*/
QFontMetricsF::QFontMetricsF(const QFont &font)
- : d(font.d)
+ : d(font.d.data())
{
d->ref.ref();
}
@@ -1038,7 +1038,7 @@ QFontMetricsF::QFontMetricsF(const QFont &font, QPaintDevice *paintdevice)
d->dpi = dpi;
d->screen = screen;
} else {
- d = font.d;
+ d = font.d.data();
d->ref.ref();
}
diff --git a/src/gui/text/qfragmentmap_p.h b/src/gui/text/qfragmentmap_p.h
index c780845..c2ba2b4 100644
--- a/src/gui/text/qfragmentmap_p.h
+++ b/src/gui/text/qfragmentmap_p.h
@@ -214,6 +214,7 @@ private:
template <class Fragment>
QFragmentMapData<Fragment>::QFragmentMapData()
+ : fragments(0)
{
init();
}
@@ -222,6 +223,7 @@ template <class Fragment>
void QFragmentMapData<Fragment>::init()
{
fragments = (Fragment *)malloc(64*fragmentSize);
+ Q_CHECK_PTR(fragments);
head->tag = (((quint32)'p') << 24) | (((quint32)'m') << 16) | (((quint32)'a') << 8) | 'p'; //TAG('p', 'm', 'a', 'p');
head->root = 0;
head->freelist = 1;
@@ -247,7 +249,9 @@ uint QFragmentMapData<Fragment>::createFragment()
// need to create some free space
uint needed = qAllocMore((freePos+1)*fragmentSize, 0);
Q_ASSERT(needed/fragmentSize > head->allocated);
- fragments = (Fragment *)realloc(fragments, needed);
+ Fragment *newFragments = (Fragment *)realloc(fragments, needed);
+ Q_CHECK_PTR(newFragments);
+ fragments = newFragments;
head->allocated = needed/fragmentSize;
F(freePos).right = 0;
}
@@ -787,6 +791,8 @@ public:
QFragmentMap() {}
~QFragmentMap()
{
+ if (!data.fragments)
+ return; // in case of out-of-memory, we won't have fragments
for (Iterator it = begin(); !it.atEnd(); ++it)
it.value()->free();
}
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index 2a590fd..78fd13b 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -1612,6 +1612,9 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF
if (cursor.position() != oldCursorPos)
emit q->cursorPositionChanged();
_q_updateCurrentCharFormatAndSelection();
+ if (QInputContext *ic = inputContext()) {
+ ic->update();
+ }
} else {
//emit q->visibilityRequest(QRectF(mousePos, QSizeF(1, 1)));
if (cursor.position() != oldCursorPos)
@@ -1814,13 +1817,18 @@ bool QTextControlPrivate::dropEvent(const QMimeData *mimeData, const QPointF &po
void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
{
+ Q_Q(QTextControl);
if (!(interactionFlags & Qt::TextEditable) || cursor.isNull()) {
e->ignore();
return;
}
- cursor.beginEditBlock();
+ bool isGettingInput = !e->commitString().isEmpty() || !e->preeditString().isEmpty()
+ || e->replacementLength() > 0;
- cursor.removeSelectedText();
+ if (isGettingInput) {
+ cursor.beginEditBlock();
+ cursor.removeSelectedText();
+ }
// insert commit string
if (!e->commitString().isEmpty() || e->replacementLength()) {
@@ -1830,6 +1838,18 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
c.insertText(e->commitString());
}
+ for (int i = 0; i < e->attributes().size(); ++i) {
+ const QInputMethodEvent::Attribute &a = e->attributes().at(i);
+ if (a.type == QInputMethodEvent::Selection) {
+ QTextCursor oldCursor = cursor;
+ int blockStart = a.start + cursor.block().position();
+ cursor.setPosition(blockStart, QTextCursor::MoveAnchor);
+ cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor);
+ q->ensureCursorVisible();
+ repaintOldAndNewSelection(oldCursor);
+ }
+ }
+
QTextBlock block = cursor.block();
QTextLayout *layout = block.layout();
layout->setPreeditArea(cursor.position() - block.position(), e->preeditString());
@@ -1853,7 +1873,9 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
}
}
layout->setAdditionalFormats(overrides);
- cursor.endEditBlock();
+
+ if (isGettingInput)
+ cursor.endEditBlock();
}
QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const
@@ -1866,11 +1888,15 @@ QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const
case Qt::ImFont:
return QVariant(d->cursor.charFormat().font());
case Qt::ImCursorPosition:
- return QVariant(d->cursor.selectionEnd() - block.position());
+ return QVariant(d->cursor.position() - block.position());
case Qt::ImSurroundingText:
return QVariant(block.text());
case Qt::ImCurrentSelection:
return QVariant(d->cursor.selectedText());
+ case Qt::ImMaximumTextLength:
+ return QVariant(); // No limit.
+ case Qt::ImAnchorPosition:
+ return QVariant(qBound(0, d->cursor.anchor() - block.position(), block.length()));
default:
return QVariant();
}
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 407fcb6..b00d2da 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -2069,10 +2069,12 @@ void QTextEngine::LayoutData::reallocate(int totalGlyphs)
int newAllocated = space_charAttributes + space_glyphs + space_logClusters;
Q_ASSERT(newAllocated >= allocated);
- void **old_mem = memory;
- memory = (void **)::realloc(memory_on_stack ? 0 : old_mem, newAllocated*sizeof(void *));
- if (memory_on_stack && memory)
- memcpy(memory, old_mem, allocated*sizeof(void *));
+ void **newMem = memory;
+ newMem = (void **)::realloc(memory_on_stack ? 0 : memory, newAllocated*sizeof(void *));
+ Q_CHECK_PTR(newMem);
+ if (memory_on_stack && newMem)
+ memcpy(newMem, memory, allocated*sizeof(void *));
+ memory = newMem;
memory_on_stack = false;
void **m = memory;
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 5efbbe9..699c41a 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -367,7 +367,7 @@ QTextLayout::QTextLayout(const QString& text, const QFont &font, QPaintDevice *p
QFont f(font);
if (paintdevice)
f = QFont(font, paintdevice);
- d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f.d);
+ d = new QTextEngine((text.isNull() ? (const QString&)QString::fromLatin1("") : text), f.d.data());
}
/*!
diff --git a/src/gui/text/qtextoption.cpp b/src/gui/text/qtextoption.cpp
index 524db4f..6709f87 100644
--- a/src/gui/text/qtextoption.cpp
+++ b/src/gui/text/qtextoption.cpp
@@ -117,7 +117,13 @@ QTextOption &QTextOption::operator=(const QTextOption &o)
{
if (this == &o)
return *this;
- delete d; d = 0;
+
+ QTextOptionPrivate* dNew = 0;
+ if (o.d)
+ dNew = new QTextOptionPrivate(*o.d);
+ delete d;
+ d = dNew;
+
align = o.align;
wordWrap = o.wordWrap;
design = o.design;
@@ -125,8 +131,6 @@ QTextOption &QTextOption::operator=(const QTextOption &o)
unused = o.unused;
f = o.f;
tab = o.tab;
- if (o.d)
- d = new QTextOptionPrivate(*o.d);
return *this;
}
diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp
index 2b6c894..11ea2a7 100644
--- a/src/gui/text/qtexttable.cpp
+++ b/src/gui/text/qtexttable.cpp
@@ -432,6 +432,13 @@ void QTextTablePrivate::fragmentRemoved(const QChar &type, uint fragment)
QTextFramePrivate::fragmentRemoved(type, fragment);
}
+/*!
+ /fn void QTextTablePrivate::update() const
+
+ This function is usually called when the table is "dirty".
+ It seems to update all kind of table information.
+
+*/
void QTextTablePrivate::update() const
{
Q_Q(const QTextTable);
@@ -439,7 +446,9 @@ void QTextTablePrivate::update() const
nRows = (cells.size() + nCols-1)/nCols;
// qDebug(">>>> QTextTablePrivate::update, nRows=%d, nCols=%d", nRows, nCols);
- grid = (int *)realloc(grid, nRows*nCols*sizeof(int));
+ int* newGrid = (int *)realloc(grid, nRows*nCols*sizeof(int));
+ Q_CHECK_PTR(newGrid);
+ grid = newGrid;
memset(grid, 0, nRows*nCols*sizeof(int));
QTextDocumentPrivate *p = pieceTable;
@@ -463,7 +472,9 @@ void QTextTablePrivate::update() const
cellIndices[i] = cell;
if (r + rowspan > nRows) {
- grid = (int *)realloc(grid, sizeof(int)*(r + rowspan)*nCols);
+ newGrid = (int *)realloc(grid, sizeof(int)*(r + rowspan)*nCols);
+ Q_CHECK_PTR(newGrid);
+ grid = newGrid;
memset(grid + (nRows*nCols), 0, sizeof(int)*(r+rowspan-nRows)*nCols);
nRows = r + rowspan;
}
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
index ccb4e6b..e4e54cf 100644
--- a/src/gui/text/qzip.cpp
+++ b/src/gui/text/qzip.cpp
@@ -705,7 +705,7 @@ void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const
*/
QZipReader::QZipReader(const QString &archive, QIODevice::OpenMode mode)
{
- QFile *f = new QFile(archive);
+ QScopedPointer<QFile> f(new QFile(archive));
f->open(mode);
QZipReader::Status status;
if (f->error() == QFile::NoError)
@@ -721,7 +721,8 @@ QZipReader::QZipReader(const QString &archive, QIODevice::OpenMode mode)
status = FileError;
}
- d = new QZipReaderPrivate(f, /*ownDevice=*/true);
+ d = new QZipReaderPrivate(f.data(), /*ownDevice=*/true);
+ f.take();
d->status = status;
}
@@ -979,7 +980,7 @@ void QZipReader::close()
*/
QZipWriter::QZipWriter(const QString &fileName, QIODevice::OpenMode mode)
{
- QFile *f = new QFile(fileName);
+ QScopedPointer<QFile> f(new QFile(fileName));
f->open(mode);
QZipWriter::Status status;
if (f->error() == QFile::NoError)
@@ -995,7 +996,8 @@ QZipWriter::QZipWriter(const QString &fileName, QIODevice::OpenMode mode)
status = QZipWriter::FileError;
}
- d = new QZipWriterPrivate(f, /*ownDevice=*/true);
+ d = new QZipWriterPrivate(f.data(), /*ownDevice=*/true);
+ f.take();
d->status = status;
}
diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri
index fc33d43..e4d24ff 100644
--- a/src/gui/text/text.pri
+++ b/src/gui/text/text.pri
@@ -106,9 +106,27 @@ embedded {
DEFINES += QT_NO_FONTCONFIG
}
+symbian {
+ SOURCES += \
+ text/qfont_s60.cpp
+ contains(QT_CONFIG, freetype) {
+ SOURCES += \
+ text/qfontengine_ft.cpp
+ HEADERS += \
+ text/qfontengine_ft_p.h
+ DEFINES += \
+ QT_NO_FONTCONFIG
+ } else {
+ SOURCES += \
+ text/qfontengine_s60.cpp
+ HEADERS += \
+ text/qfontengine_s60_p.h
+ LIBS += -lfntstr -lecom
+ }
+}
+
contains(QT_CONFIG, freetype) {
SOURCES += \
- ../3rdparty/freetype/builds/unix/ftsystem.c \
../3rdparty/freetype/src/base/ftbase.c \
../3rdparty/freetype/src/base/ftbbox.c \
../3rdparty/freetype/src/base/ftdebug.c \
@@ -152,10 +170,19 @@ contains(QT_CONFIG, freetype) {
../3rdparty/freetype/src/autofit/afloader.c\
../3rdparty/freetype/src/autofit/autofit.c
+ symbian {
+ SOURCES += \
+ ../3rdparty/freetype/src/base/ftsystem.c
+ } else {
+ SOURCES += \
+ ../3rdparty/freetype/builds/unix/ftsystem.c
+ INCLUDEPATH += \
+ ../3rdparty/freetype/builds/unix
+ }
+
INCLUDEPATH += \
../3rdparty/freetype/src \
- ../3rdparty/freetype/include \
- ../3rdparty/freetype/builds/unix
+ ../3rdparty/freetype/include
DEFINES += FT2_BUILD_LIBRARY FT_CONFIG_OPTION_SYSTEM_ZLIB
diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp
index bf1fa6a..0ce3b3c 100644
--- a/src/gui/util/qcompleter.cpp
+++ b/src/gui/util/qcompleter.cpp
@@ -482,7 +482,7 @@ QMatchData QCompletionEngine::filterHistory()
for (int i = 0; i < source->rowCount(); i++) {
QString str = source->index(i, c->column).data().toString();
if (str.startsWith(c->prefix, c->cs)
-#if !defined(Q_OS_WIN) || defined(Q_OS_WINCE)
+#if (!defined(Q_OS_WIN) || defined(Q_OS_WINCE)) && !defined(Q_OS_SYMBIAN)
&& (!dirModel || QDir::toNativeSeparators(str) != QDir::separator())
#endif
)
@@ -987,7 +987,7 @@ void QCompleter::setModel(QAbstractItemModel *model)
delete oldModel;
#ifndef QT_NO_DIRMODEL
if (qobject_cast<QDirModel *>(model)) {
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if (defined(Q_OS_WIN) && !defined(Q_OS_WINCE)) || defined(Q_OS_SYMBIAN)
setCaseSensitivity(Qt::CaseInsensitive);
#else
setCaseSensitivity(Qt::CaseSensitive);
@@ -1652,7 +1652,7 @@ QString QCompleter::pathFromIndex(const QModelIndex& index) const
idx = parent.sibling(parent.row(), index.column());
} while (idx.isValid());
-#if !defined(Q_OS_WIN) || defined(Q_OS_WINCE)
+#if (!defined(Q_OS_WIN) || defined(Q_OS_WINCE)) && !defined(Q_OS_SYMBIAN)
if (list.count() == 1) // only the separator or some other text
return list[0];
list[0].clear() ; // the join below will provide the separator
@@ -1686,7 +1686,10 @@ QStringList QCompleter::splitPath(const QString& path) const
QString pathCopy = QDir::toNativeSeparators(path);
QString sep = QDir::separator();
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_OS_SYMBIAN)
+ if (pathCopy == QLatin1String("\\"))
+ return QStringList(pathCopy);
+#elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
if (pathCopy == QLatin1String("\\") || pathCopy == QLatin1String("\\\\"))
return QStringList(pathCopy);
QString doubleSlash(QLatin1String("\\\\"));
@@ -1699,7 +1702,9 @@ QStringList QCompleter::splitPath(const QString& path) const
QRegExp re(QLatin1Char('[') + QRegExp::escape(sep) + QLatin1Char(']'));
QStringList parts = pathCopy.split(re);
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_OS_SYMBIAN)
+ // Do nothing
+#elif defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
if (!doubleSlash.isEmpty())
parts[0].prepend(doubleSlash);
#else
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index 8177fb7..eb2d92e 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -53,6 +53,8 @@
#include "qdesktopservices_win.cpp"
#elif defined(Q_WS_MAC)
#include "qdesktopservices_mac.cpp"
+#elif defined(Q_OS_SYMBIAN)
+#include "qdesktopservices_s60.cpp"
#endif
#include <qhash.h>
@@ -285,6 +287,11 @@ void QDesktopServices::unsetUrlHandler(const QString &scheme)
\note The storage location returned can be a directory that does not exist; i.e., it
may need to be created by the system or the user.
+
+ \note On Symbian OS, DataLocation and ApplicationsLocation always point to appropriate
+ folder on same drive with executable. FontsLocation always points to folder on ROM drive.
+ Rest of the standard locations point to folder on same drive with executable, except
+ that if executable is in ROM the folder from C drive is returned.
\note On Mac OS X, DataLocation does not include QCoreApplication::organizationName.
Use code like this to add it:
diff --git a/src/gui/util/qdesktopservices_s60.cpp b/src/gui/util/qdesktopservices_s60.cpp
new file mode 100644
index 0000000..77cf254
--- /dev/null
+++ b/src/gui/util/qdesktopservices_s60.cpp
@@ -0,0 +1,410 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This flag changes the implementation to use S60 CDcoumentHandler
+// instead of apparch when opening the files
+#undef USE_DOCUMENTHANDLER
+
+#include <qcoreapplication.h>
+#include <qdir.h>
+#include <qurl.h>
+#include <private/qcore_symbian_p.h>
+
+#include <miutset.h> // KUidMsgTypeSMTP
+#include <txtrich.h> // CRichText
+#include <f32file.h> // TDriveUnit etc
+#include <eikenv.h> // CEikonEnv
+#include <apgcli.h> // RApaLsSession
+#include <apgtask.h> // TApaTaskList, TApaTask
+#include <rsendas.h> // RSendAs
+#include <rsendasmessage.h> // RSendAsMessage
+
+#ifdef Q_WS_S60
+# include <pathinfo.h> // PathInfo
+# ifdef USE_DOCUMENTHANDLER
+# include <documenthandler.h> // CDocumentHandler
+# endif
+#elif defined(USE_DOCUMENTHANDLER)
+# error CDocumentHandler requires support for S60
+#endif
+
+QT_BEGIN_NAMESPACE
+
+_LIT(KSysBin, "\\Sys\\Bin\\");
+_LIT(KTempDir, "\\System\\Temp\\");
+_LIT(KBrowserPrefix, "4 " );
+_LIT(KFontsDir, "z:\\resource\\Fonts\\");
+const TUid KUidBrowser = { 0x10008D39 };
+
+static void handleMailtoSchemeL(const QUrl &url)
+{
+ QString recipient = url.path();
+ QString subject = url.queryItemValue("subject");
+ QString body = url.queryItemValue("body");
+ QString to = url.queryItemValue("to");
+ QString cc = url.queryItemValue("cc");
+ QString bcc = url.queryItemValue("bcc");
+
+ // these fields might have comma separated addresses
+ QStringList recipients = recipient.split(",");
+ QStringList tos = to.split(",");
+ QStringList ccs = cc.split(",");
+ QStringList bccs = bcc.split(",");
+
+
+ RSendAs sendAs;
+ User::LeaveIfError(sendAs.Connect());
+ CleanupClosePushL(sendAs);
+
+
+ CSendAsAccounts* accounts = CSendAsAccounts::NewL();
+ CleanupStack::PushL(accounts);
+ sendAs.AvailableAccountsL(KUidMsgTypeSMTP, *accounts);
+ TInt count = accounts->Count();
+ CleanupStack::PopAndDestroy(accounts);
+
+ if(!count) {
+ // TODO: we should try to create account if count == 0
+ // CSendUi would provide account creation service for us, but it requires ridicilous
+ // capabilities: LocalServices NetworkServices ReadDeviceData ReadUserData WriteDeviceData WriteUserData
+ User::Leave(KErrNotSupported);
+ } else {
+ RSendAsMessage sendAsMessage;
+ sendAsMessage.CreateL(sendAs, KUidMsgTypeSMTP);
+ CleanupClosePushL(sendAsMessage);
+
+
+ // Subject
+ sendAsMessage.SetSubjectL(qt_QString2TPtrC(subject));
+
+ // Body
+ sendAsMessage.SetBodyTextL(qt_QString2TPtrC(body));
+
+ // To
+ foreach(QString item, recipients)
+ sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo );
+
+ foreach(QString item, tos)
+ sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientTo );
+
+ // Cc
+ foreach(QString item, ccs)
+ sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientCc );
+
+ // Bcc
+ foreach(QString item, bccs)
+ sendAsMessage.AddRecipientL(qt_QString2TPtrC(item), RSendAsMessage::ESendAsRecipientBcc );
+
+ // send the message
+ sendAsMessage.LaunchEditorAndCloseL();
+
+ // sendAsMessage (already closed)
+ CleanupStack::Pop();
+ }
+ // sendAs
+ CleanupStack::PopAndDestroy();
+}
+
+static bool handleMailtoScheme(const QUrl &url)
+{
+ TRAPD(err, handleMailtoSchemeL(url));
+ return err ? false : true;
+}
+
+static void handleOtherSchemesL(const TDesC& aUrl)
+{
+ // Other schemes are at the moment passed to WEB browser
+ HBufC* buf16 = HBufC::NewLC( aUrl.Length() + KBrowserPrefix.iTypeLength );
+ buf16->Des().Copy( KBrowserPrefix ); // Prefix used to launch correct browser view
+ buf16->Des().Append( aUrl );
+
+ TApaTaskList taskList( CEikonEnv::Static()->WsSession() );
+ TApaTask task = taskList.FindApp( KUidBrowser );
+ if ( task.Exists() )
+ {
+ // Switch to existing browser instance
+ HBufC8* param8 = HBufC8::NewLC( buf16->Length() );
+ param8->Des().Append( buf16->Des() );
+ task.SendMessage( TUid::Uid( 0 ), *param8 ); // Uid is not used
+ CleanupStack::PopAndDestroy( param8 );
+ }
+ else
+ {
+ // Start a new browser instance
+ RApaLsSession appArcSession;
+ User::LeaveIfError( appArcSession.Connect() );
+ CleanupClosePushL<RApaLsSession>( appArcSession );
+ TThreadId id;
+ appArcSession.StartDocument( *buf16, KUidBrowser , id );
+ CleanupStack::PopAndDestroy(); // appArcSession
+ }
+
+ CleanupStack::PopAndDestroy( buf16 );
+}
+
+static bool handleOtherSchemes(const QUrl &url)
+{
+ TRAPD( err, handleOtherSchemesL(qt_QString2TPtrC(url.toEncoded())));
+ return err ? false : true;
+}
+
+static TDriveUnit exeDrive()
+{
+ RProcess me;
+ TFileName processFileName = me.FileName();
+ TDriveUnit drive(processFileName);
+ return drive;
+}
+
+static TDriveUnit writableExeDrive()
+{
+ TDriveUnit drive = exeDrive();
+ if( drive.operator TInt() == EDriveZ )
+ return TDriveUnit( EDriveC );
+ return drive;
+}
+
+static TPtrC writableDataRoot()
+{
+ TDriveUnit drive = exeDrive();
+#ifdef Q_WS_S60
+ switch( drive.operator TInt() ){
+ case EDriveC:
+ return PathInfo::PhoneMemoryRootPath();
+ break;
+ case EDriveE:
+ return PathInfo::MemoryCardRootPath();
+ break;
+ case EDriveZ:
+ // It is not possible to write on ROM drive ->
+ // return phone mem root path instead
+ return PathInfo::PhoneMemoryRootPath();
+ break;
+ default:
+ // TODO: Should we return drive root similar to MemoryCardRootPath
+ return PathInfo::PhoneMemoryRootPath();
+ break;
+ }
+#else
+#warning No fallback implementation of writableDataRoot()
+ return 0;
+#endif
+}
+
+static void openDocumentL(const TDesC& aUrl)
+{
+#ifndef USE_DOCUMENTHANDLER
+ // Start app associated to file MIME type by using RApaLsSession
+ // Apparc base method cannot be used to open app in embedded mode,
+ // but seems to be most stable way at the moment
+ RApaLsSession appArcSession;
+ User::LeaveIfError( appArcSession.Connect() );
+ CleanupClosePushL<RApaLsSession>( appArcSession );
+ TThreadId id;
+ // ESwitchFiles means do not start another instance
+ // Leaves if file does not exist, leave is trapped in openDocument and false returned to user.
+ User::LeaveIfError( appArcSession.StartDocument( aUrl, id,
+ RApaLsSession::ESwitchFiles ) ); // ELaunchNewApp
+ CleanupStack::PopAndDestroy(); // appArcSession
+#else
+ // This is an alternative way to launch app associated to MIME type
+ // CDocumentHandler would support opening apps in embedded mode,
+ // but our Qt application window group seems to always get switched on top of embedded one
+ // -> Cannot use menus etc of embedded app -> used
+
+ CDocumentHandler* docHandler = CDocumentHandler::NewLC();
+ TDataType temp;
+ //Standalone file opening fails for some file-types at least in S60 3.1 emulator
+ //For example .txt file fails with KErrAlreadyInUse and music files with KERN-EXEC 0
+ //Workaround is to use OpenFileEmbeddedL
+ //docHandler->OpenFileL(aUrl, temp);
+
+ // Opening file with CDocumentHandler will leave if file does not exist
+ // Leave is trapped in openDocument and false returned to user.
+ docHandler->OpenFileEmbeddedL(aUrl, temp);
+ CleanupStack::PopAndDestroy(docHandler);
+#endif
+}
+
+#ifdef USE_SCHEMEHANDLER
+// The schemehandler component only exist in private SDK. This implementation
+// exist here just for convenience in case that we need to use it later on
+// The schemehandle based implementation is not yet tested.
+
+// The biggest advantage of schemehandler is that it can handle
+// wide range of schemes and is extensible by plugins
+static bool handleUrl(const QUrl &url)
+{
+ if (!url.isValid())
+ return false;
+
+ TRAPD( err, handleUrlL(qt_QString2TPtrC(url.toString())));
+ return err ? false : true;
+}
+
+static void handleUrlL(const TDesC& aUrl)
+{
+ CSchemeHandler* schemeHandler = CSchemeHandler::NewL( aUrl );
+ CleanupStack::PushL( schemeHandler );
+ schemeHandler->HandleUrlStandaloneL(); // Process the Url in standalone mode
+ CleanupStack::PopAndDestroy();
+}
+static bool launchWebBrowser(const QUrl &url)
+{
+ return handleUrl(url);
+}
+
+static bool openDocument(const QUrl &file)
+{
+ return handleUrl(url);
+}
+#endif
+
+static bool launchWebBrowser(const QUrl &url)
+{
+ if (!url.isValid())
+ return false;
+
+ if (url.scheme() == QLatin1String("mailto")) {
+ return handleMailtoScheme(url);
+ }
+ return handleOtherSchemes( url );
+}
+
+static bool openDocument(const QUrl &file)
+{
+ if (!file.isValid())
+ return false;
+
+ QString filePath = file.toLocalFile();
+ filePath = QDir::toNativeSeparators(filePath);
+ TRAPD(err, openDocumentL(qt_QString2TPtrC(filePath)));
+ return err ? false : true;
+}
+
+QString QDesktopServices::storageLocation(StandardLocation type)
+{
+ TFileName path;
+
+ switch (type) {
+ case DesktopLocation:
+ qWarning("QDesktopServices::storageLocation %d not implemented", type);
+ break;
+ case DocumentsLocation:
+ path.Append(writableDataRoot());
+ break;
+ case FontsLocation:
+ path.Append(KFontsDir);
+ break;
+ case ApplicationsLocation:
+ path.Append(exeDrive().Name());
+ path.Append(KSysBin);
+ break;
+ case MusicLocation:
+ path.Append(writableDataRoot());
+#ifdef Q_WS_S60
+ path.Append(PathInfo::SoundsPath());
+#endif
+ break;
+ case MoviesLocation:
+ path.Append(writableDataRoot());
+#ifdef Q_WS_S60
+ path.Append(PathInfo::VideosPath());
+#endif
+ break;
+ case PicturesLocation:
+ path.Append(writableDataRoot());
+#ifdef Q_WS_S60
+ path.Append(PathInfo::ImagesPath());
+#endif
+ break;
+ case TempLocation:
+ path.Append(writableExeDrive().Name());
+ path.Append(KTempDir);
+ //return QDir::tempPath(); break;
+ break;
+ case HomeLocation:
+ path.Append(writableDataRoot());
+ //return QDir::homePath(); break;
+ break;
+ case DataLocation:
+ CEikonEnv::Static()->FsSession().PrivatePath( path );
+ // TODO: Should we actually return phone mem if data is on ROM?
+ path.Insert( 0, exeDrive().Name() );
+ break;
+ default:
+ break;
+ }
+
+ // Convert to cross-platform format and clean the path
+ QString nativePath = QString::fromUtf16(path.Ptr(), path.Length());
+ QString qtPath = QDir::fromNativeSeparators(nativePath);
+ qtPath = QDir::cleanPath(qtPath);
+
+ // Note: The storage location returned can be a directory that does not exist;
+ // i.e., it may need to be created by the system or the user.
+ return qtPath;
+}
+
+typedef QString (*LocalizerFunc)(QString&);
+
+static QString defaultLocalizedDirectoryName(QString&)
+{
+ return QString();
+}
+
+QString QDesktopServices::displayName(StandardLocation type)
+{
+ static LocalizerFunc ptrLocalizerFunc = NULL;
+
+ if (!ptrLocalizerFunc) {
+ ptrLocalizerFunc = reinterpret_cast<LocalizerFunc>
+ (qt_resolveS60PluginFunc(S60Plugin_LocalizedDirectoryName));
+ if (!ptrLocalizerFunc)
+ ptrLocalizerFunc = &defaultLocalizedDirectoryName;
+ }
+
+ QString rawPath = storageLocation(type);
+ return ptrLocalizerFunc(rawPath);
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri
index e628229..cdbb7cc 100644
--- a/src/gui/util/util.pri
+++ b/src/gui/util/util.pri
@@ -38,3 +38,8 @@ embedded {
!embedded:!x11:mac {
OBJECTIVE_SOURCES += util/qsystemtrayicon_mac.mm
}
+
+symbian {
+ LIBS += -lsendas2 -letext -lapmime
+ contains(QT_CONFIG, s60): LIBS += -lplatformenv -lcommonui
+}
diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp
index dd92e17..391e095 100644
--- a/src/gui/widgets/qabstractscrollarea.cpp
+++ b/src/gui/widgets/qabstractscrollarea.cpp
@@ -287,8 +287,8 @@ void QAbstractScrollAreaPrivate::init()
scrollBarContainers[Qt::Vertical]->setVisible(false);
QObject::connect(vbar, SIGNAL(valueChanged(int)), q, SLOT(_q_vslide(int)));
QObject::connect(vbar, SIGNAL(rangeChanged(int,int)), q, SLOT(_q_showOrHideScrollBars()), Qt::QueuedConnection);
- viewportFilter = new QAbstractScrollAreaFilter(this);
- viewport->installEventFilter(viewportFilter);
+ viewportFilter.reset(new QAbstractScrollAreaFilter(this));
+ viewport->installEventFilter(viewportFilter.data());
viewport->setFocusProxy(q);
q->setFocusPolicy(Qt::WheelFocus);
q->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
@@ -500,7 +500,12 @@ QAbstractScrollArea::QAbstractScrollArea(QAbstractScrollAreaPrivate &dd, QWidget
:QFrame(dd, parent)
{
Q_D(QAbstractScrollArea);
- d->init();
+ QT_TRY {
+ d->init();
+ } QT_CATCH(...) {
+ d->viewportFilter.reset();
+ QT_RETHROW;
+ }
}
/*!
@@ -512,7 +517,12 @@ QAbstractScrollArea::QAbstractScrollArea(QWidget *parent)
:QFrame(*new QAbstractScrollAreaPrivate, parent)
{
Q_D(QAbstractScrollArea);
- d->init();
+ QT_TRY {
+ d->init();
+ } QT_CATCH(...) {
+ d->viewportFilter.reset();
+ QT_RETHROW;
+ }
}
@@ -522,7 +532,8 @@ QAbstractScrollArea::QAbstractScrollArea(QWidget *parent)
QAbstractScrollArea::~QAbstractScrollArea()
{
Q_D(QAbstractScrollArea);
- delete d->viewportFilter;
+ // reset it here, otherwise we'll have a dangling pointer in ~QWidget
+ d->viewportFilter.reset();
}
@@ -546,7 +557,7 @@ void QAbstractScrollArea::setViewport(QWidget *widget)
d->viewport = widget;
d->viewport->setParent(this);
d->viewport->setFocusProxy(this);
- d->viewport->installEventFilter(d->viewportFilter);
+ d->viewport->installEventFilter(d->viewportFilter.data());
d->layoutChildren();
if (isVisible())
d->viewport->show();
diff --git a/src/gui/widgets/qabstractscrollarea_p.h b/src/gui/widgets/qabstractscrollarea_p.h
index aef8ac5..f8ea843 100644
--- a/src/gui/widgets/qabstractscrollarea_p.h
+++ b/src/gui/widgets/qabstractscrollarea_p.h
@@ -98,7 +98,7 @@ public:
inline bool viewportEvent(QEvent *event)
{ return q_func()->viewportEvent(event); }
- QObject *viewportFilter;
+ QScopedPointer<QObject> viewportFilter;
#ifdef Q_WS_WIN
bool singleFingerPanEnabled;
diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp
index 6865a56..19712d3 100644
--- a/src/gui/widgets/qabstractslider.cpp
+++ b/src/gui/widgets/qabstractslider.cpp
@@ -687,8 +687,9 @@ void QAbstractSlider::wheelEvent(QWheelEvent * e)
Q_D(QAbstractSlider);
e->ignore();
if (e->orientation() != d->orientation && !rect().contains(e->pos()))
+ {
return;
-
+ }
static qreal offset = 0;
static QAbstractSlider *offset_owner = 0;
if (offset_owner != this){
diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp
index 433406c..8027f9e 100644
--- a/src/gui/widgets/qabstractspinbox.cpp
+++ b/src/gui/widgets/qabstractspinbox.cpp
@@ -663,7 +663,6 @@ void QAbstractSpinBox::setLineEdit(QLineEdit *lineEdit)
d->edit->setParent(this);
d->edit->setFrame(false);
- d->edit->setAttribute(Qt::WA_InputMethodEnabled, false);
d->edit->setFocusProxy(this);
d->edit->setAcceptDrops(false);
@@ -694,6 +693,18 @@ void QAbstractSpinBox::interpretText()
d->interpret(EmitIfChanged);
}
+/*
+ Reimplemented in 4.6, so be careful.
+ */
+/*!
+ \reimp
+*/
+QVariant QAbstractSpinBox::inputMethodQuery(Qt::InputMethodQuery query) const
+{
+ Q_D(const QAbstractSpinBox);
+ return d->edit->inputMethodQuery(query);
+}
+
/*!
\reimp
*/
diff --git a/src/gui/widgets/qabstractspinbox.h b/src/gui/widgets/qabstractspinbox.h
index d8b9757..e65f27b 100644
--- a/src/gui/widgets/qabstractspinbox.h
+++ b/src/gui/widgets/qabstractspinbox.h
@@ -122,6 +122,8 @@ public:
void interpretText();
bool event(QEvent *event);
+ QVariant inputMethodQuery(Qt::InputMethodQuery) const;
+
virtual QValidator::State validate(QString &input, int &pos) const;
virtual void fixup(QString &input) const;
diff --git a/src/gui/widgets/qactiontokeyeventmapper.cpp b/src/gui/widgets/qactiontokeyeventmapper.cpp
new file mode 100644
index 0000000..280b1c6
--- /dev/null
+++ b/src/gui/widgets/qactiontokeyeventmapper.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qapplication.h"
+#include "qevent.h"
+#include "qactiontokeyeventmapper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QActionToKeyEventMapper::QActionToKeyEventMapper(QAction *softKeyAction, Qt::Key key, QObject *parent)
+ : QObject(parent)
+ , m_softKeyAction(softKeyAction)
+ , m_key(key)
+{
+
+}
+
+QString QActionToKeyEventMapper::roleText(QAction::SoftKeyRole role)
+{
+ switch (role) {
+ case QAction::OptionsSoftKey:
+ return QAction::tr("Options");
+ case QAction::SelectSoftKey:
+ return QAction::tr("Select");
+ case QAction::BackSoftKey:
+ return QAction::tr("Back");
+ case QAction::NextSoftKey:
+ return QAction::tr("Next");
+ case QAction::PreviousSoftKey:
+ return QAction::tr("Previous");
+ case QAction::OkSoftKey:
+ return QAction::tr("Ok");
+ case QAction::CancelSoftKey:
+ return QAction::tr("Cancel");
+ case QAction::EditSoftKey:
+ return QAction::tr("Edit");
+ case QAction::ViewSoftKey:
+ return QAction::tr("View");
+ default:
+ return QString();
+ };
+}
+void QActionToKeyEventMapper::addSoftKey(QAction::SoftKeyRole standardRole, Qt::Key key, QWidget *actionWidget)
+{
+ QAction *action = new QAction(actionWidget);
+ action->setSoftKeyRole(standardRole);
+ action->setText(roleText(standardRole));
+ QActionToKeyEventMapper *softKey = new QActionToKeyEventMapper(action, key, actionWidget);
+ connect(action, SIGNAL(triggered()), softKey, SLOT(sendKeyEvent()));
+ connect(action, SIGNAL(destroyed()), softKey, SLOT(deleteLater()));
+ actionWidget->setSoftKey(action);
+}
+
+void QActionToKeyEventMapper::removeSoftkey(QWidget *focussedWidget)
+{
+ focussedWidget->setSoftKey(0);
+}
+
+void QActionToKeyEventMapper::sendKeyEvent()
+{
+ QApplication::postEvent(parent(), new QKeyEvent(QEvent::KeyPress, m_key, Qt::NoModifier));
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/gui/widgets/qactiontokeyeventmapper_p.h b/src/gui/widgets/qactiontokeyeventmapper_p.h
new file mode 100644
index 0000000..c54e612
--- /dev/null
+++ b/src/gui/widgets/qactiontokeyeventmapper_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module 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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACTIONTOKEYEVENTMAPPER_P_H
+#define QACTIONTOKEYEVENTMAPPER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+#include "QtGui/qaction.h"
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QActionToKeyEventMapper : public QObject
+{
+ Q_OBJECT
+public:
+ QActionToKeyEventMapper(QAction *softKeyAction, Qt::Key key, QObject *parent);
+ static QString roleText(QAction::SoftKeyRole role);
+ static void addSoftKey(QAction::SoftKeyRole standardRole, Qt::Key key, QWidget *actionWidget);
+ static void removeSoftkey(QWidget *focussedWidget);
+private:
+ QAction *m_softKeyAction;
+ Qt::Key m_key;
+private Q_SLOTS:
+ void sendKeyEvent();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QACTIONTOKEYEVENTMAPPER_P_H
diff --git a/src/gui/widgets/qcalendarwidget.cpp b/src/gui/widgets/qcalendarwidget.cpp
index 2586c56..7f29ec7 100644
--- a/src/gui/widgets/qcalendarwidget.cpp
+++ b/src/gui/widgets/qcalendarwidget.cpp
@@ -2142,14 +2142,11 @@ QSize QCalendarWidget::minimumSizeHint() const
int end = 53;
int rows = 7;
int cols = 8;
- int startRow = 0;
- int startCol = 0;
const int marginH = (style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1) * 2;
if (horizontalHeaderFormat() == QCalendarWidget::NoHorizontalHeader) {
rows = 6;
- startRow = 1;
} else {
for (int i = 1; i <= 7; i++) {
QFontMetrics fm(d->m_model->formatForCell(0, i).font());
@@ -2160,7 +2157,6 @@ QSize QCalendarWidget::minimumSizeHint() const
if (verticalHeaderFormat() == QCalendarWidget::NoVerticalHeader) {
cols = 7;
- startCol = 1;
} else {
for (int i = 1; i <= 6; i++) {
QFontMetrics fm(d->m_model->formatForCell(i, 0).font());
@@ -2527,13 +2523,6 @@ void QCalendarWidget::setDateRange(const QDate &min, const QDate &max)
if (!min.isValid() || !max.isValid())
return;
- QDate minimum = min;
- QDate maximum = max;
- if (min > max) {
- minimum = max;
- maximum = min;
- }
-
QDate oldDate = d->m_model->m_date;
d->m_model->setRange(min, max);
d->yearEdit->setMinimum(d->m_model->m_minimumDate.year());
diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp
index 097f3d0..b6fae10 100644
--- a/src/gui/widgets/qcombobox.cpp
+++ b/src/gui/widgets/qcombobox.cpp
@@ -64,7 +64,7 @@
#include <private/qabstractitemmodel_p.h>
#include <private/qabstractscrollarea_p.h>
#include <qdebug.h>
-
+#include <private/qactiontokeyeventmapper_p.h>
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
#endif
@@ -629,6 +629,9 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
case Qt::Key_Select:
#endif
if (view->currentIndex().isValid() && (view->currentIndex().flags() & Qt::ItemIsEnabled) ) {
+#ifdef QT_KEYPAD_NAVIGATION
+ QActionToKeyEventMapper::removeSoftkey(this);
+#endif
combo->hidePopup();
emit itemSelected(view->currentIndex());
}
@@ -641,6 +644,7 @@ bool QComboBoxPrivateContainer::eventFilter(QObject *o, QEvent *e)
case Qt::Key_Escape:
#ifdef QT_KEYPAD_NAVIGATION
case Qt::Key_Back:
+ QActionToKeyEventMapper::removeSoftkey(this);
#endif
combo->hidePopup();
return true;
@@ -2454,6 +2458,11 @@ void QComboBox::showPopup()
container->setUpdatesEnabled(updatesEnabled);
container->update();
+#ifdef QT_KEYPAD_NAVIGATION
+ if (QApplication::keypadNavigationEnabled())
+ view()->setEditFocus(true);
+ QActionToKeyEventMapper::addSoftKey(QAction::CancelSoftKey, Qt::Key_Back, view());
+#endif
}
/*!
diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp
index 5ddf7f7..db57b43 100644
--- a/src/gui/widgets/qdatetimeedit.cpp
+++ b/src/gui/widgets/qdatetimeedit.cpp
@@ -1126,23 +1126,25 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event)
case Qt::Key_Left:
case Qt::Key_Right:
if (event->key() == Qt::Key_Left || event->key() == Qt::Key_Right) {
+ if (
#ifdef QT_KEYPAD_NAVIGATION
- if (!QApplication::keypadNavigationEnabled() || !hasEditFocus()) {
- select = false;
- break;
- }
-#else
- if (!(event->modifiers() & Qt::ControlModifier)) {
+ QApplication::keypadNavigationEnabled() && !hasEditFocus()
+ || !QApplication::keypadNavigationEnabled() &&
+#endif
+ !(event->modifiers() & Qt::ControlModifier)) {
select = false;
break;
}
#ifdef Q_WS_MAC
- else {
+ else
+#ifdef QT_KEYPAD_NAVIGATION
+ if (!QApplication::keypadNavigationEnabled())
+#endif
+ {
select = (event->modifiers() & Qt::ShiftModifier);
break;
}
#endif
-#endif // QT_KEYPAD_NAVIGATION
}
// else fall through
case Qt::Key_Backtab:
@@ -2386,6 +2388,7 @@ void QDateTimeEditPrivate::init(const QVariant &var)
q->setCalendarPopup(true);
#endif
updateTimeSpec();
+ q->setInputMethodHints(Qt::ImhPreferNumbers);
setLayoutItemMargins(QStyle::SE_DateTimeEditLayoutItem);
}
diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp
index d1067a8..01d5711 100644
--- a/src/gui/widgets/qlineedit.cpp
+++ b/src/gui/widgets/qlineedit.cpp
@@ -97,8 +97,7 @@ extern void qt_mac_secure_keyboard(bool); //qapplication_mac.cpp
static inline bool shouldEnableInputMethod(QLineEdit *lineedit)
{
- const QLineEdit::EchoMode mode = lineedit->echoMode();
- return !lineedit->isReadOnly() && (mode == QLineEdit::Normal || mode == QLineEdit::PasswordEchoOnEdit);
+ return !lineedit->isReadOnly();
}
/*!
@@ -544,7 +543,13 @@ void QLineEdit::setEchoMode(EchoMode mode)
Q_D(QLineEdit);
if (mode == (EchoMode)d->echoMode)
return;
- setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
+ Qt::InputMethodHints imHints = inputMethodHints();
+ if (mode == Password) {
+ imHints |= Qt::ImhHiddenText;
+ } else {
+ imHints &= ~Qt::ImhHiddenText;
+ }
+ setInputMethodHints(imHints);
d->echoMode = mode;
d->passwordEchoEditing = false;
d->updateTextLayout();
@@ -1765,6 +1770,13 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e)
}
}
#endif
+
+ if (e->button() == Qt::LeftButton && qApp->autoSipEnabled()
+ && (!d->clickCausedFocus || qApp->autoSipOnMouseFocus())) {
+ QEvent event(QEvent::RequestSoftwareInputPanel);
+ QApplication::sendEvent(this, &event);
+ }
+ d->clickCausedFocus = 0;
}
/*! \reimp
@@ -2260,8 +2272,16 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e)
}
#endif
- int priorState = d->undoState;
- d->removeSelectedText();
+ int priorState = 0;
+ bool isGettingInput = !e->commitString().isEmpty() || !e->preeditString().isEmpty()
+ || e->replacementLength() > 0;
+ bool cursorPositionChanged = false;
+
+ if (isGettingInput) {
+ // If any text is being input, remove selected text.
+ priorState = d->undoState;
+ d->removeSelectedText();
+ }
int c = d->cursor; // cursor position after insertion of commit string
if (e->replacementStart() <= 0)
@@ -2275,11 +2295,30 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e)
d->selend = d->selstart + e->replacementLength();
d->removeSelectedText();
}
- if (!e->commitString().isEmpty())
+ if (!e->commitString().isEmpty()) {
d->insert(e->commitString());
+ cursorPositionChanged = true;
+ }
d->cursor = qMin(c, d->text.length());
+ for (int i = 0; i < e->attributes().size(); ++i) {
+ const QInputMethodEvent::Attribute &a = e->attributes().at(i);
+ if (a.type == QInputMethodEvent::Selection) {
+ d->cursor = qBound(0, a.start + a.length, d->text.length());
+ if (a.length) {
+ d->selstart = qMax(0, qMin(a.start, d->text.length()));
+ d->selend = d->cursor;
+ if (d->selend < d->selstart) {
+ qSwap(d->selstart, d->selend);
+ }
+ } else {
+ d->selstart = d->selend = 0;
+ }
+ cursorPositionChanged = true;
+ }
+ }
+
d->textLayout.setPreeditArea(d->cursor, e->preeditString());
d->preeditCursor = e->preeditString().length();
d->hideCursor = false;
@@ -2303,9 +2342,12 @@ void QLineEdit::inputMethodEvent(QInputMethodEvent *e)
d->textLayout.setAdditionalFormats(formats);
d->updateTextLayout();
update();
- if (!e->commitString().isEmpty())
+ if (cursorPositionChanged)
d->emitCursorPositionChanged();
- d->finishChange(priorState);
+
+ if (isGettingInput)
+ d->finishChange(priorState);
+
#ifndef QT_NO_COMPLETER
if (!e->commitString().isEmpty())
d->complete(Qt::Key_unknown);
@@ -2323,11 +2365,20 @@ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const
case Qt::ImFont:
return font();
case Qt::ImCursorPosition:
- return QVariant((d->selend - d->selstart == 0) ? d->cursor : d->selend);
+ return QVariant(d->cursor);
case Qt::ImSurroundingText:
return QVariant(d->text);
case Qt::ImCurrentSelection:
return QVariant(selectedText());
+ case Qt::ImMaximumTextLength:
+ return QVariant(maxLength());
+ case Qt::ImAnchorPosition:
+ if (d->selstart == d->selend)
+ return QVariant(d->cursor);
+ else if (d->selstart == d->cursor)
+ return QVariant(d->selend);
+ else
+ return QVariant(d->selstart);
default:
return QVariant();
}
@@ -2346,6 +2397,8 @@ void QLineEdit::focusInEvent(QFocusEvent *e)
d->moveCursor(d->nextMaskBlank(0));
else if (!d->hasSelectedText())
selectAll();
+ } else if (e->reason() == Qt::MouseFocusReason) {
+ d->clickCausedFocus = 1;
}
#ifdef QT_KEYPAD_NAVIGATION
if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && e->reason() == Qt::PopupFocusReason))
@@ -2920,6 +2973,7 @@ void QLineEditPrivate::moveCursor(int pos, bool mark)
selDirty = false;
emit q->selectionChanged();
}
+ q->updateMicroFocus();
emitCursorPositionChanged();
}
diff --git a/src/gui/widgets/qlineedit_p.h b/src/gui/widgets/qlineedit_p.h
index 7a4ff26..03029f9 100644
--- a/src/gui/widgets/qlineedit_p.h
+++ b/src/gui/widgets/qlineedit_p.h
@@ -76,7 +76,8 @@ public:
: cursor(0), preeditCursor(0), cursorTimer(0), frame(1),
cursorVisible(0), hideCursor(false), separator(0), readOnly(0),
dragEnabled(0), contextMenuEnabled(1), echoMode(0), textDirty(0),
- selDirty(0), validInput(1), alignment(Qt::AlignLeading | Qt::AlignVCenter), ascent(0),
+ selDirty(0), validInput(1), clickCausedFocus(0),
+ alignment(Qt::AlignLeading | Qt::AlignVCenter), ascent(0),
maxLength(32767), hscroll(0), vscroll(0), lastCursorPos(-1), maskData(0),
modifiedState(0), undoState(0), selstart(0), selend(0), userInput(false),
emitingEditingFinished(false), passwordEchoEditing(false)
@@ -110,6 +111,7 @@ public:
uint textDirty : 1;
uint selDirty : 1;
uint validInput : 1;
+ uint clickCausedFocus : 1;
uint alignment;
int ascent;
int maxLength;
diff --git a/src/gui/widgets/qmacnativewidget_mac.h b/src/gui/widgets/qmacnativewidget_mac.h
index 6b6bee1..5c654b5 100644
--- a/src/gui/widgets/qmacnativewidget_mac.h
+++ b/src/gui/widgets/qmacnativewidget_mac.h
@@ -64,7 +64,7 @@ protected:
bool event(QEvent *ev);
private:
- Q_DECLARE_PRIVATE_D(QWidget::d_ptr, QMacNativeWidget)
+ Q_DECLARE_PRIVATE(QMacNativeWidget)
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp
index c51bed9..b75b5ea 100644
--- a/src/gui/widgets/qmainwindow.cpp
+++ b/src/gui/widgets/qmainwindow.cpp
@@ -481,6 +481,11 @@ void QMainWindow::setMenuBar(QMenuBar *menuBar)
oldMenuBar->deleteLater();
}
d->layout->setMenuBar(menuBar);
+ if (menuBar) {
+ QAction* menu = new QAction(QString::fromLatin1("Options"), this);
+ menu->setSoftKeyRole(QAction::MenuSoftKey);
+ setSoftKey(menu);
+ }
}
/*!
@@ -1396,7 +1401,16 @@ bool QMainWindow::event(QEvent *event)
}
break;
#endif
-
+#ifndef QT_NO_MENUBAR
+ case QEvent::WindowActivate:
+ if (d->layout->menuBar()) {
+ // ### TODO: This is evil, there is no need to create a new action every time
+ QAction* menu = new QAction(QString::fromLatin1("Options"), this);
+ menu->setSoftKeyRole(QAction::MenuSoftKey);
+ setSoftKey(menu);
+ }
+ break;
+#endif
default:
break;
}
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index 99f3880..b69e8bb 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -60,6 +60,7 @@
#ifndef QT_NO_WHATSTHIS
# include <qwhatsthis.h>
#endif
+#include <private/qactiontokeyeventmapper_p.h>
#include "qmenu_p.h"
#include "qmenubar_p.h"
@@ -556,8 +557,14 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
//when the action has no QWidget, the QMenu itself should
// get the focus
// Since the menu is a pop-up, it uses the popup reason.
- if (!q->hasFocus())
+ if (!q->hasFocus()) {
q->setFocus(Qt::PopupFocusReason);
+#ifdef QT_KEYPAD_NAVIGATION
+ // TODO: aportale, remove KEYPAD_NAVIGATION_HACK when softkey stack
+ // handles focus related and user related actions separately...
+ QActionToKeyEventMapper::addSoftKey(QAction::CancelSoftKey, Qt::Key_Back, q);
+#endif
+ }
}
}
} else { //action is a separator
@@ -1774,6 +1781,22 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
QRect screen = d->popupGeometry(QApplication::desktop()->screenNumber(p));
const int desktopFrame = style()->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, this);
bool adjustToDesktop = !window()->testAttribute(Qt::WA_DontShowOnScreen);
+#ifdef QT_KEYPAD_NAVIGATION
+ if (!atAction && QApplication::keypadNavigationEnabled()) {
+ // Try to have one item activated
+ if (d->defaultAction && d->defaultAction->isEnabled()) {
+ atAction = d->defaultAction;
+ // TODO: This works for first level menus, not yet sub menus
+ } else {
+ foreach (QAction *action, d->actions)
+ if (action->isEnabled()) {
+ atAction = action;
+ break;
+ }
+ }
+ d->currentAction = atAction;
+ }
+#endif
if (d->ncols > 1) {
pos.setY(screen.top()+desktopFrame);
} else if (atAction) {
@@ -1901,6 +1924,9 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
#ifndef QT_NO_ACCESSIBILITY
QAccessible::updateAccessibility(this, 0, QAccessible::PopupMenuStart);
#endif
+#ifdef QT_KEYPAD_NAVIGATION
+ QActionToKeyEventMapper::addSoftKey(QAction::CancelSoftKey, Qt::Key_Back, this);
+#endif
}
/*!
@@ -2559,6 +2585,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
case Qt::Key_Escape:
#ifdef QT_KEYPAD_NAVIGATION
case Qt::Key_Back:
+ QActionToKeyEventMapper::removeSoftkey(this);
#endif
key_consumed = true;
if (d->tornoff) {
@@ -2834,6 +2861,16 @@ void QMenu::actionEvent(QActionEvent *e)
d->wce_menu->syncAction(e->action());
#endif
+#ifdef Q_WS_S60
+ if (!d->symbian_menu)
+ d->symbian_menu = new QMenuPrivate::QSymbianMenuPrivate;
+ if (e->type() == QEvent::ActionAdded)
+ d->symbian_menu->addAction(e->action(), d->symbian_menu->findAction(e->before()));
+ else if (e->type() == QEvent::ActionRemoved)
+ d->symbian_menu->removeAction(e->action());
+ else if (e->type() == QEvent::ActionChanged)
+ d->symbian_menu->syncAction(e->action());
+#endif
if (isVisible()) {
d->updateActionRects();
resize(sizeHint());
diff --git a/src/gui/widgets/qmenu.h b/src/gui/widgets/qmenu.h
index c8be540..41890c4 100644
--- a/src/gui/widgets/qmenu.h
+++ b/src/gui/widgets/qmenu.h
@@ -52,11 +52,19 @@
#endif
QT_BEGIN_HEADER
+#ifdef Q_WS_S60
+ class CEikMenuPane;
+#endif
QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
+#ifdef Q_WS_S60
+ IMPORT_C void qt_symbian_show_toplevel(CEikMenuPane* menuPane);
+ IMPORT_C void qt_symbian_show_submenu(CEikMenuPane* menuPane, int id);
+#endif
+
#ifndef QT_NO_MENU
class QMenuPrivate;
@@ -145,7 +153,6 @@ public:
HMENU wceMenu(bool create = false);
#endif
-
bool separatorsCollapsible() const;
void setSeparatorsCollapsible(bool collapse);
diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h
index 4e428fe..355ecb4 100644
--- a/src/gui/widgets/qmenu_p.h
+++ b/src/gui/widgets/qmenu_p.h
@@ -61,6 +61,9 @@
#include "QtCore/qbasictimer.h"
#include "private/qwidget_p.h"
+#ifdef Q_WS_S60
+class CEikMenuPane;
+#endif
QT_BEGIN_NAMESPACE
#ifndef QT_NO_MENU
@@ -120,6 +123,15 @@ struct QWceMenuAction {
QWceMenuAction() : menuHandle(0), command(0) {}
};
#endif
+#ifdef Q_WS_S60
+struct QSymbianMenuAction {
+ uint command;
+ int parent;
+ CEikMenuPane* menuPane;
+ QPointer<QAction> action;
+ QSymbianMenuAction() : command(0) {}
+};
+#endif
class QMenuPrivate : public QWidgetPrivate
{
@@ -135,6 +147,9 @@ public:
#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
,wce_menu(0)
#endif
+#ifdef Q_WS_S60
+ ,symbian_menu(0)
+#endif
#ifdef QT3_SUPPORT
,emitHighlighted(false)
#endif
@@ -148,6 +163,10 @@ public:
#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
delete wce_menu;
#endif
+#ifdef Q_WS_S60
+ delete symbian_menu;
+#endif
+
}
void init();
@@ -319,7 +338,28 @@ public:
HMENU wceMenu(bool create = false);
QAction* wceCommands(uint command);
#endif
-
+#if defined(Q_WS_S60)
+ struct QSymbianMenuPrivate {
+ QList<QSymbianMenuAction*> actionItems;
+ QSymbianMenuPrivate();
+ ~QSymbianMenuPrivate();
+ void addAction(QAction *, QSymbianMenuAction* =0);
+ void addAction(QSymbianMenuAction *, QSymbianMenuAction* =0);
+ void syncAction(QSymbianMenuAction *);
+ inline void syncAction(QAction *a) { syncAction(findAction(a)); }
+ void removeAction(QSymbianMenuAction *);
+ void rebuild(bool reCreate = false);
+ inline void removeAction(QAction *a) { removeAction(findAction(a)); }
+ inline QSymbianMenuAction *findAction(QAction *a) {
+ for(int i = 0; i < actionItems.size(); i++) {
+ QSymbianMenuAction *act = actionItems[i];
+ if(a == act->action)
+ return act;
+ }
+ return 0;
+ }
+ } *symbian_menu;
+#endif
QPointer<QWidget> noReplayFor;
};
diff --git a/src/gui/widgets/qmenu_symbian.cpp b/src/gui/widgets/qmenu_symbian.cpp
new file mode 100644
index 0000000..76057e7
--- /dev/null
+++ b/src/gui/widgets/qmenu_symbian.cpp
@@ -0,0 +1,423 @@
+/****************************************************************************
+**
+** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+**
+** $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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmenu.h"
+#include "qapplication.h"
+#include "qevent.h"
+#include "qstyle.h"
+#include "qdebug.h"
+#include "qwidgetaction.h"
+#include <private/qapplication_p.h>
+#include <private/qmenu_p.h>
+#include <private/qmenubar_p.h>
+#include <qt_s60_p.h>
+#include <QtCore/qlibrary.h>
+
+#ifdef Q_WS_S60
+#include <eikmenub.h>
+#include <eikmenup.h>
+#include <eikaufty.h>
+#include <eikbtgpc.h>
+#include <avkon.rsg>
+#endif
+
+#if !defined(QT_NO_MENUBAR) && defined(Q_WS_S60)
+
+QT_BEGIN_NAMESPACE
+
+typedef QMultiHash<QWidget *, QMenuBarPrivate *> MenuBarHash;
+Q_GLOBAL_STATIC(MenuBarHash, menubars)
+
+#define QT_FIRST_MENU_ITEM 32000
+
+struct SymbianMenuItem
+{
+ int id;
+ CEikMenuPaneItem::SData menuItemData;
+ QList<SymbianMenuItem*> children;
+ QAction* action;
+};
+
+static QList<SymbianMenuItem*> symbianMenus;
+static QList<QMenuBar*> nativeMenuBars;
+static uint qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM;
+static QPointer<QWidget> widgetWithContextMenu;
+static QList<QAction*> contextMenuActionList;
+static QAction contextAction(0);
+static int contexMenuCommand=0;
+
+bool menuExists()
+{
+ QWidget *w = qApp->activeWindow();
+ QMenuBarPrivate *mb = menubars()->value(w);
+ if ((!mb) && !menubars()->count())
+ return false;
+ return true;
+}
+
+static bool hasContextMenu(QWidget* widget)
+{
+ if (!widget)
+ return false;
+ const Qt::ContextMenuPolicy policy = widget->contextMenuPolicy();
+ if (policy != Qt::NoContextMenu && policy != Qt::PreventContextMenu ) {
+ return true;
+ }
+ return false;
+}
+// ### FIX THIS, copy/paste of original (faulty) stripped text implementation.
+// Implementation should be removed from QAction implementation to some generic place
+static QString qt_strippedText_copy_from_qaction(QString s)
+{
+ s.remove(QString::fromLatin1("..."));
+ int i = 0;
+ while (i < s.size()) {
+ ++i;
+ if (s.at(i-1) != QLatin1Char('&'))
+ continue;
+ if (i < s.size() && s.at(i) == QLatin1Char('&'))
+ ++i;
+ s.remove(i-1,1);
+ }
+ return s.trimmed();
+};
+
+static SymbianMenuItem* qt_symbian_find_menu(int id, const QList<SymbianMenuItem*> &parent)
+{
+ int index=0;
+ while (index < parent.count()) {
+ SymbianMenuItem* temp = parent[index];
+ if (temp->menuItemData.iCascadeId == id)
+ return temp;
+ else if (temp->menuItemData.iCascadeId != 0) {
+ SymbianMenuItem* result = qt_symbian_find_menu( id, temp->children);
+ if (result)
+ return result;
+ }
+ index++;
+ }
+ return 0;
+}
+
+static SymbianMenuItem* qt_symbian_find_menu_item(int id, const QList<SymbianMenuItem*> &parent)
+{
+ int index=0;
+ while (index < parent.count()) {
+ SymbianMenuItem* temp = parent[index];
+ if (temp->menuItemData.iCascadeId != 0) {
+ SymbianMenuItem* result = qt_symbian_find_menu_item( id, temp->children);
+ if (result)
+ return result;
+ }
+ else if (temp->menuItemData.iCommandId == id)
+ return temp;
+ index++;
+
+ }
+ return 0;
+}
+
+static void qt_symbian_insert_action(QSymbianMenuAction* action, QList<SymbianMenuItem*>* parent)
+{
+ if (action->action->isVisible()) {
+ if (action->action->isSeparator())
+ return;
+
+// ### FIX THIS, the qt_strippedText2 doesn't work perfectly for stripping & marks. Same bug is in QAction
+// New really working method is needed in a place where the implementation isn't copy/pasted
+ QString text = qt_strippedText_copy_from_qaction(action->action->text());
+ TPtrC menuItemText(qt_QString2TPtrC(text));
+
+ if (action->action->menu()) {
+ SymbianMenuItem* menuItem = new SymbianMenuItem();
+ menuItem->menuItemData.iCascadeId = action->command;
+ menuItem->menuItemData.iCommandId = action->command;
+ menuItem->menuItemData.iFlags = 0;
+ menuItem->menuItemData.iText = menuItemText;
+ menuItem->action = action->action;
+ if (action->action->menu()->actions().size() == 0 || !action->action->isEnabled() )
+ menuItem->menuItemData.iFlags |= EEikMenuItemDimmed;
+ parent->append(menuItem);
+
+ if (action->action->menu()->actions().size() > 0) {
+ for (int c2= 0; c2 < action->action->menu()->actions().size(); ++c2) {
+ QSymbianMenuAction *symbianAction2 = new QSymbianMenuAction;
+ symbianAction2->action = action->action->menu()->actions().at(c2);
+ QMenu * menu = symbianAction2->action->menu();
+ symbianAction2->command = qt_symbian_menu_static_cmd_id++;
+ qt_symbian_insert_action(symbianAction2, &(menuItem->children));
+ }
+ }
+
+ } else {
+ SymbianMenuItem* menuItem = new SymbianMenuItem();
+ menuItem->menuItemData.iCascadeId = 0;
+ menuItem->menuItemData.iCommandId = action->command;
+ menuItem->menuItemData.iFlags = 0;
+ menuItem->menuItemData.iText = menuItemText;
+ menuItem->action = action->action;
+ if (!action->action->isEnabled()){
+ menuItem->menuItemData.iFlags += EEikMenuItemDimmed;
+ }
+
+ if (action->action->isCheckable()) {
+ if (action->action->isChecked())
+ menuItem->menuItemData.iFlags += EEikMenuItemCheckBox | EEikMenuItemSymbolOn;
+ else
+ menuItem->menuItemData.iFlags += EEikMenuItemCheckBox;
+ }
+ parent->append(menuItem);
+ }
+ }
+}
+
+void deleteAll(QList<SymbianMenuItem*> *items)
+{
+ while (!items->isEmpty()) {
+ SymbianMenuItem* temp = items->takeFirst();
+ deleteAll(&temp->children);
+ delete temp;
+ }
+}
+
+static void rebuildMenu()
+{
+ widgetWithContextMenu = 0;
+ QMenuBarPrivate *mb = 0;
+ QWidget *w = qApp->activeWindow();
+ QWidget* focusWidget = QApplication::focusWidget();
+ if (focusWidget) {
+ if (hasContextMenu(focusWidget))
+ widgetWithContextMenu = focusWidget;
+ }
+
+ if (w) {
+ mb = menubars()->value(w);
+ qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM;
+ deleteAll( &symbianMenus );
+ if (!mb)
+ return;
+ mb->symbian_menubar->rebuild();
+ }
+}
+
+Q_GUI_EXPORT void qt_symbian_show_toplevel( CEikMenuPane* menuPane)
+{
+ if (!menuExists())
+ return;
+ rebuildMenu();
+ for (int i = 0; i < symbianMenus.count(); ++i)
+ menuPane->AddMenuItemL(symbianMenus.at(i)->menuItemData);
+}
+
+Q_GUI_EXPORT void qt_symbian_show_submenu( CEikMenuPane* menuPane, int id)
+{
+ SymbianMenuItem* menu = qt_symbian_find_menu(id, symbianMenus);
+ if (menu) {
+ for (int i = 0; i < menu->children.count(); ++i)
+ menuPane->AddMenuItemL(menu->children.at(i)->menuItemData);
+ }
+}
+
+void QMenuBarPrivate::symbianCommands(int command)
+{
+ if (command == contexMenuCommand && !widgetWithContextMenu.isNull()) {
+ QContextMenuEvent* event = new QContextMenuEvent(QContextMenuEvent::Keyboard, QPoint(0,0));
+ QCoreApplication::postEvent(widgetWithContextMenu, event);
+ }
+
+ int size = nativeMenuBars.size();
+ for (int i = 0; i < nativeMenuBars.size(); ++i) {
+ SymbianMenuItem* menu = qt_symbian_find_menu_item(command, symbianMenus);
+ if (!menu)
+ continue;
+
+ emit nativeMenuBars.at(i)->triggered(menu->action);
+ menu->action->activate(QAction::Trigger);
+ break;
+ }
+}
+
+void QMenuBarPrivate::symbianCreateMenuBar(QWidget *parent)
+{
+ Q_Q(QMenuBar);
+ if (parent && parent->isWindow()){
+ menubars()->insert(q->window(), this);
+ symbian_menubar = new QSymbianMenuBarPrivate(this);
+ nativeMenuBars.append(q);
+ }
+}
+
+void QMenuBarPrivate::symbianDestroyMenuBar()
+{
+ Q_Q(QMenuBar);
+ int index = nativeMenuBars.indexOf(q);
+ nativeMenuBars.removeAt(index);
+ menubars()->remove(q->window(), this);
+ rebuildMenu();
+ if (symbian_menubar)
+ delete symbian_menubar;
+ symbian_menubar = 0;
+}
+
+QMenuBarPrivate::QSymbianMenuBarPrivate::QSymbianMenuBarPrivate(QMenuBarPrivate *menubar)
+{
+ d = menubar;
+}
+
+QMenuBarPrivate::QSymbianMenuBarPrivate::~QSymbianMenuBarPrivate()
+{
+ deleteAll( &symbianMenus );
+ symbianMenus.clear();
+ d = 0;
+ rebuild();
+}
+
+QMenuPrivate::QSymbianMenuPrivate::QSymbianMenuPrivate()
+{
+}
+
+QMenuPrivate::QSymbianMenuPrivate::~QSymbianMenuPrivate()
+{
+
+}
+
+void QMenuPrivate::QSymbianMenuPrivate::addAction(QAction *a, QSymbianMenuAction *before)
+{
+ QSymbianMenuAction *action = new QSymbianMenuAction;
+ action->action = a;
+ action->command = qt_symbian_menu_static_cmd_id++;
+ addAction(action, before);
+}
+
+void QMenuPrivate::QSymbianMenuPrivate::addAction(QSymbianMenuAction *action, QSymbianMenuAction *before)
+{
+ if (!action)
+ return;
+ int before_index = actionItems.indexOf(before);
+ if (before_index < 0) {
+ before = 0;
+ before_index = actionItems.size();
+ }
+ actionItems.insert(before_index, action);
+}
+
+
+void QMenuPrivate::QSymbianMenuPrivate::syncAction(QSymbianMenuAction *)
+{
+ rebuild();
+}
+
+void QMenuPrivate::QSymbianMenuPrivate::removeAction(QSymbianMenuAction *action)
+{
+ actionItems.removeAll(action);
+ delete action;
+ action = 0;
+ rebuild();
+}
+
+void QMenuPrivate::QSymbianMenuPrivate::rebuild(bool)
+{
+}
+
+void QMenuBarPrivate::QSymbianMenuBarPrivate::addAction(QAction *a, QSymbianMenuAction *before)
+{
+ QSymbianMenuAction *action = new QSymbianMenuAction;
+ action->action = a;
+ action->command = qt_symbian_menu_static_cmd_id++;
+ addAction(action, before);
+}
+
+void QMenuBarPrivate::QSymbianMenuBarPrivate::addAction(QSymbianMenuAction *action, QSymbianMenuAction *before)
+{
+ if (!action)
+ return;
+ int before_index = actionItems.indexOf(before);
+ if (before_index < 0) {
+ before = 0;
+ before_index = actionItems.size();
+ }
+ actionItems.insert(before_index, action);
+}
+
+void QMenuBarPrivate::QSymbianMenuBarPrivate::syncAction(QSymbianMenuAction*)
+{
+ rebuild();
+}
+
+void QMenuBarPrivate::QSymbianMenuBarPrivate::removeAction(QSymbianMenuAction *action)
+{
+ actionItems.removeAll(action);
+ delete action;
+ rebuild();
+}
+
+void QMenuBarPrivate::QSymbianMenuBarPrivate::insertNativeMenuItems(const QList<QAction*> &actions)
+{
+ for (int i = 0; i <actions.size(); ++i) {
+ QSymbianMenuAction *symbianActionTopLevel = new QSymbianMenuAction;
+ symbianActionTopLevel->action = actions.at(i);
+ symbianActionTopLevel->parent = 0;
+ symbianActionTopLevel->command = qt_symbian_menu_static_cmd_id++;
+ qt_symbian_insert_action(symbianActionTopLevel, &symbianMenus);
+ }
+}
+
+
+
+void QMenuBarPrivate::QSymbianMenuBarPrivate::rebuild()
+{
+ contexMenuCommand = 0;
+ qt_symbian_menu_static_cmd_id = QT_FIRST_MENU_ITEM;
+ deleteAll( &symbianMenus );
+ if (d)
+ insertNativeMenuItems(d->actions);
+
+ contextMenuActionList.clear();
+ if (widgetWithContextMenu) {
+ contexMenuCommand = qt_symbian_menu_static_cmd_id;
+ contextAction.setText(QMenuBar::tr("Actions"));
+ contextMenuActionList.append(&contextAction);
+ insertNativeMenuItems(contextMenuActionList);
+ }
+}
+QT_END_NAMESPACE
+
+#endif //QT_NO_MENUBAR
diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp
index 6b93879..bb1dd29 100644
--- a/src/gui/widgets/qmenubar.cpp
+++ b/src/gui/widgets/qmenubar.cpp
@@ -739,6 +739,12 @@ void QMenuBarPrivate::init()
q->hide();
}
#endif
+#ifdef Q_WS_S60
+ symbianCreateMenuBar(q->parentWidget());
+ if(symbian_menubar)
+ q->hide();
+#endif
+
q->setBackgroundRole(QPalette::Button);
oldWindow = oldParent = 0;
#ifdef QT3_SUPPORT
@@ -810,6 +816,10 @@ QMenuBar::~QMenuBar()
if (qt_wince_is_mobile())
d->wceDestroyMenuBar();
#endif
+#ifdef Q_WS_S60
+ Q_D(QMenuBar);
+ d->symbianDestroyMenuBar();
+#endif
}
/*!
@@ -1065,6 +1075,12 @@ void QMenuBar::setVisible(bool visible)
if (isNativeMenuBar())
return;
#endif
+#ifdef Q_WS_S60
+ Q_D(QMenuBar);
+ if(d->symbian_menubar)
+ return;
+#endif
+
QWidget::setVisible(visible);
}
@@ -1277,6 +1293,17 @@ void QMenuBar::actionEvent(QActionEvent *e)
nativeMenuBar->syncAction(e->action());
}
#endif
+#ifdef Q_WS_S60
+ if(d->symbian_menubar) {
+ if(e->type() == QEvent::ActionAdded)
+ d->symbian_menubar->addAction(e->action(), d->symbian_menubar->findAction(e->before()));
+ else if(e->type() == QEvent::ActionRemoved)
+ d->symbian_menubar->removeAction(e->action());
+ else if(e->type() == QEvent::ActionChanged)
+ d->symbian_menubar->syncAction(e->action());
+ }
+#endif
+
if(e->type() == QEvent::ActionAdded) {
connect(e->action(), SIGNAL(triggered()), this, SLOT(_q_actionTriggered()));
connect(e->action(), SIGNAL(hovered()), this, SLOT(_q_actionHovered()));
@@ -1363,6 +1390,11 @@ void QMenuBarPrivate::handleReparent()
if (qt_wince_is_mobile() && wce_menubar)
wce_menubar->rebuild();
#endif
+#ifdef Q_WS_S60
+ if (symbian_menubar)
+ symbian_menubar->rebuild();
+#endif
+
}
#ifdef QT3_SUPPORT
@@ -1597,7 +1629,7 @@ QRect QMenuBar::actionGeometry(QAction *act) const
QSize QMenuBar::minimumSizeHint() const
{
Q_D(const QMenuBar);
-#if defined(Q_WS_MAC) || defined(Q_WS_WINCE)
+#if defined(Q_WS_MAC) || defined(Q_WS_WINCE) || defined(Q_WS_S60)
const bool as_gui_menubar = !isNativeMenuBar();
#else
const bool as_gui_menubar = true;
@@ -1653,7 +1685,7 @@ QSize QMenuBar::minimumSizeHint() const
QSize QMenuBar::sizeHint() const
{
Q_D(const QMenuBar);
-#if defined(Q_WS_MAC) || defined(Q_WS_WINCE)
+#if defined(Q_WS_MAC) || defined(Q_WS_WINCE) || defined(Q_WS_S60)
const bool as_gui_menubar = !isNativeMenuBar();
#else
const bool as_gui_menubar = true;
@@ -1711,7 +1743,7 @@ QSize QMenuBar::sizeHint() const
int QMenuBar::heightForWidth(int) const
{
Q_D(const QMenuBar);
-#if defined(Q_WS_MAC) || defined(Q_WS_WINCE)
+#if defined(Q_WS_MAC) || defined(Q_WS_WINCE) || defined(Q_WS_S60)
const bool as_gui_menubar = !isNativeMenuBar();
#else
const bool as_gui_menubar = true;
diff --git a/src/gui/widgets/qmenubar_p.h b/src/gui/widgets/qmenubar_p.h
index b890b7b..004562f 100644
--- a/src/gui/widgets/qmenubar_p.h
+++ b/src/gui/widgets/qmenubar_p.h
@@ -61,6 +61,13 @@
#include "qguifunctions_wince.h"
#endif
+#ifndef QT_NO_MENUBAR
+#ifdef Q_WS_S60
+class CCoeControl;
+class CEikMenuBar;
+#endif
+#endif
+
QT_BEGIN_NAMESPACE
#ifndef QT_NO_MENUBAR
@@ -82,7 +89,11 @@ public:
#ifdef Q_WS_WINCE
, wce_menubar(0), wceClassicMenu(false)
#endif
- { }
+#ifdef Q_WS_S60
+ , symbian_menubar(0)
+#endif
+
+ { }
~QMenuBarPrivate()
{
#ifdef Q_WS_MAC
@@ -91,6 +102,9 @@ public:
#ifdef Q_WS_WINCE
delete wce_menubar;
#endif
+#ifdef Q_WS_S60
+ delete symbian_menubar;
+#endif
}
void init();
@@ -225,6 +239,35 @@ public:
void wceRefresh();
bool wceEmitSignals(QList<QWceMenuAction*> actions, uint command);
#endif
+#ifdef Q_WS_S60
+ void symbianCreateMenuBar(QWidget *);
+ void symbianDestroyMenuBar();
+ struct QSymbianMenuBarPrivate {
+ QList<QSymbianMenuAction*> actionItems;
+ QMenuBarPrivate *d;
+ QSymbianMenuBarPrivate(QMenuBarPrivate *menubar);
+ ~QSymbianMenuBarPrivate();
+ void addAction(QAction *, QSymbianMenuAction* =0);
+ void addAction(QSymbianMenuAction *, QSymbianMenuAction* =0);
+ void syncAction(QSymbianMenuAction *);
+ inline void syncAction(QAction *a) { syncAction(findAction(a)); }
+ void removeAction(QSymbianMenuAction *);
+ void rebuild();
+ inline void removeAction(QAction *a) { removeAction(findAction(a)); }
+ inline QSymbianMenuAction *findAction(QAction *a) {
+ for(int i = 0; i < actionItems.size(); i++) {
+ QSymbianMenuAction *act = actionItems[i];
+ if(a == act->action)
+ return act;
+ }
+ return 0;
+ }
+ void insertNativeMenuItems(const QList<QAction*> &actions);
+
+ } *symbian_menubar;
+ static void symbianCommands(int command);
+
+#endif
};
#endif
diff --git a/src/gui/widgets/qmenudata.h b/src/gui/widgets/qmenudata.h
index 7d0228f..521b5fc 100644
--- a/src/gui/widgets/qmenudata.h
+++ b/src/gui/widgets/qmenudata.h
@@ -67,6 +67,8 @@ private:
friend class QMenuBar;
void setId(int);
void setSignalValue(int);
+
+ Q_DISABLE_COPY(QMenuItem);
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp
index 82026d4..7d9d2b5 100644
--- a/src/gui/widgets/qplaintextedit.cpp
+++ b/src/gui/widgets/qplaintextedit.cpp
@@ -74,6 +74,11 @@
QT_BEGIN_NAMESPACE
+static inline bool shouldEnableInputMethod(QPlainTextEdit *plaintextedit)
+{
+ return !plaintextedit->isReadOnly();
+}
+
class QPlainTextDocumentLayoutPrivate : public QAbstractTextDocumentLayoutPrivate
{
Q_DECLARE_PUBLIC(QPlainTextDocumentLayout)
@@ -721,7 +726,8 @@ QPlainTextEditPrivate::QPlainTextEditPrivate()
tabChangesFocus(false),
lineWrap(QPlainTextEdit::WidgetWidth),
wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere),
- topLine(0), pageUpDownLastCursorYIsValid(false)
+ clickCausedFocus(0),topLine(0),
+ pageUpDownLastCursorYIsValid(false)
{
showCursorOnInitialShow = true;
backgroundVisible = false;
@@ -1925,6 +1931,13 @@ void QPlainTextEdit::mouseReleaseEvent(QMouseEvent *e)
d->autoScrollTimer.stop();
d->ensureCursorVisible();
}
+
+ if (e->button() == Qt::LeftButton && qApp->autoSipEnabled()
+ && (!d->clickCausedFocus || qApp->autoSipOnMouseFocus())) {
+ QEvent event(QEvent::RequestSoftwareInputPanel);
+ QApplication::sendEvent(this, &event);
+ }
+ d->clickCausedFocus = 0;
}
/*! \reimp
@@ -2059,6 +2072,9 @@ QVariant QPlainTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
void QPlainTextEdit::focusInEvent(QFocusEvent *e)
{
Q_D(QPlainTextEdit);
+ if (e->reason() == Qt::MouseFocusReason) {
+ d->clickCausedFocus = 1;
+ }
QAbstractScrollArea::focusInEvent(e);
d->sendControlEvent(e);
}
@@ -2325,7 +2341,7 @@ void QPlainTextEdit::setReadOnly(bool ro)
} else {
flags = Qt::TextEditorInteraction;
}
- setAttribute(Qt::WA_InputMethodEnabled, !ro);
+ setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
d->control->setTextInteractionFlags(flags);
}
diff --git a/src/gui/widgets/qplaintextedit_p.h b/src/gui/widgets/qplaintextedit_p.h
index ae584e0..739fd89 100644
--- a/src/gui/widgets/qplaintextedit_p.h
+++ b/src/gui/widgets/qplaintextedit_p.h
@@ -92,7 +92,10 @@ public:
return r;
}
inline QRectF cursorRect() { return cursorRect(textCursor()); }
- void ensureCursorVisible() { textEdit->ensureCursorVisible(); }
+ void ensureCursorVisible() {
+ textEdit->ensureCursorVisible();
+ emit microFocusChanged();
+ }
QPlainTextEdit *textEdit;
@@ -149,6 +152,7 @@ public:
uint backgroundVisible : 1;
uint centerOnScroll : 1;
uint inDrag : 1;
+ uint clickCausedFocus : 1;
int topLine;
diff --git a/src/gui/widgets/qprintpreviewwidget.cpp b/src/gui/widgets/qprintpreviewwidget.cpp
index fb1b6ea..f5f7e73 100644
--- a/src/gui/widgets/qprintpreviewwidget.cpp
+++ b/src/gui/widgets/qprintpreviewwidget.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qprintpreviewwidget.h"
+#include "private/qwidget_p.h"
#include <private/qprinter_p.h>
#include <QtCore/qmath.h>
@@ -170,12 +171,12 @@ protected:
} // anonymous namespace
-class QPrintPreviewWidgetPrivate
+class QPrintPreviewWidgetPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QPrintPreviewWidget)
public:
- QPrintPreviewWidgetPrivate(QPrintPreviewWidget *q)
- : q_ptr(q), scene(0), curPage(1),
+ QPrintPreviewWidgetPrivate()
+ : scene(0), curPage(1),
viewMode(QPrintPreviewWidget::SinglePageView),
zoomMode(QPrintPreviewWidget::FitInView),
zoomFactor(1), initialized(false), fitting(true)
@@ -194,7 +195,6 @@ public:
void setZoomFactor(qreal zoomFactor);
int calcCurrentPage();
- QPrintPreviewWidget *q_ptr;
GraphicsView *graphicsView;
QGraphicsScene *scene;
@@ -518,7 +518,7 @@ void QPrintPreviewWidgetPrivate::setZoomFactor(qreal _zoomFactor)
\sa QWidget::setWindowFlags()
*/
QPrintPreviewWidget::QPrintPreviewWidget(QPrinter *printer, QWidget *parent, Qt::WindowFlags flags)
- : QWidget(parent, flags), d_ptr(new QPrintPreviewWidgetPrivate(this))
+ : QWidget(*new QPrintPreviewWidgetPrivate, parent, flags)
{
Q_D(QPrintPreviewWidget);
d->printer = printer;
@@ -534,7 +534,7 @@ QPrintPreviewWidget::QPrintPreviewWidget(QPrinter *printer, QWidget *parent, Qt:
preview.
*/
QPrintPreviewWidget::QPrintPreviewWidget(QWidget *parent, Qt::WindowFlags flags)
- : QWidget(parent, flags), d_ptr(new QPrintPreviewWidgetPrivate(this))
+ : QWidget(*new QPrintPreviewWidgetPrivate, parent, flags)
{
Q_D(QPrintPreviewWidget);
d->printer = new QPrinter;
@@ -551,7 +551,6 @@ QPrintPreviewWidget::~QPrintPreviewWidget()
Q_D(QPrintPreviewWidget);
if (d->ownPrinter)
delete d->printer;
- delete d_ptr;
}
/*!
diff --git a/src/gui/widgets/qprintpreviewwidget.h b/src/gui/widgets/qprintpreviewwidget.h
index 99b14bf..d74bf93 100644
--- a/src/gui/widgets/qprintpreviewwidget.h
+++ b/src/gui/widgets/qprintpreviewwidget.h
@@ -111,7 +111,7 @@ Q_SIGNALS:
void previewChanged();
private:
- QPrintPreviewWidgetPrivate *d_ptr;
+ void *dummy; // ### remove in Qt 5.0
Q_PRIVATE_SLOT(d_func(), void _q_fit())
Q_PRIVATE_SLOT(d_func(), void _q_updateCurrentPage())
};
diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp
index 7441df4..193b15c 100644
--- a/src/gui/widgets/qspinbox.cpp
+++ b/src/gui/widgets/qspinbox.cpp
@@ -78,6 +78,8 @@ public:
QChar thousand;
inline void init() {
+ Q_Q(QSpinBox);
+ q->setInputMethodHints(Qt::ImhDigitsOnly);
setLayoutItemMargins(QStyle::SE_SpinBoxLayoutItem);
}
};
@@ -98,6 +100,11 @@ public:
// variables
int decimals;
QChar delimiter, thousand;
+
+ inline void init() {
+ Q_Q(QDoubleSpinBox);
+ q->setInputMethodHints(Qt::ImhFormattedNumbersOnly);
+ }
};
@@ -599,6 +606,8 @@ void QSpinBox::fixup(QString &input) const
QDoubleSpinBox::QDoubleSpinBox(QWidget *parent)
: QAbstractSpinBox(*new QDoubleSpinBoxPrivate(parent), parent)
{
+ Q_D(QDoubleSpinBox);
+ d->init();
}
/*!
diff --git a/src/gui/widgets/qtextedit.cpp b/src/gui/widgets/qtextedit.cpp
index e80df92..2de661a 100644
--- a/src/gui/widgets/qtextedit.cpp
+++ b/src/gui/widgets/qtextedit.cpp
@@ -76,6 +76,10 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_TEXTEDIT
+static inline bool shouldEnableInputMethod(QTextEdit *textedit)
+{
+ return !textedit->isReadOnly();
+}
class QTextEditControl : public QTextControl
{
@@ -107,7 +111,8 @@ QTextEditPrivate::QTextEditPrivate()
: control(0),
autoFormatting(QTextEdit::AutoNone), tabChangesFocus(false),
lineWrap(QTextEdit::WidgetWidth), lineWrapColumnOrWidth(0),
- wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere), textFormat(Qt::AutoText)
+ wordWrap(QTextOption::WrapAtWordBoundaryOrAnywhere), clickCausedFocus(0),
+ textFormat(Qt::AutoText)
{
ignoreAutomaticScrollbarAdjustment = false;
preferRichText = false;
@@ -1566,6 +1571,12 @@ void QTextEdit::mouseReleaseEvent(QMouseEvent *e)
d->autoScrollTimer.stop();
ensureCursorVisible();
}
+ if (e->button() == Qt::LeftButton && qApp->autoSipEnabled()
+ && (!d->clickCausedFocus || qApp->autoSipOnMouseFocus())) {
+ QEvent event(QEvent::RequestSoftwareInputPanel);
+ QApplication::sendEvent(this, &event);
+ }
+ d->clickCausedFocus = 0;
}
/*! \reimp
@@ -1702,6 +1713,9 @@ QVariant QTextEdit::inputMethodQuery(Qt::InputMethodQuery property) const
void QTextEdit::focusInEvent(QFocusEvent *e)
{
Q_D(QTextEdit);
+ if (e->reason() == Qt::MouseFocusReason) {
+ d->clickCausedFocus = 1;
+ }
QAbstractScrollArea::focusInEvent(e);
d->sendControlEvent(e);
}
@@ -2066,7 +2080,7 @@ void QTextEdit::setReadOnly(bool ro)
} else {
flags = Qt::TextEditorInteraction;
}
- setAttribute(Qt::WA_InputMethodEnabled, !ro);
+ setAttribute(Qt::WA_InputMethodEnabled, shouldEnableInputMethod(this));
d->control->setTextInteractionFlags(flags);
}
diff --git a/src/gui/widgets/qtextedit_p.h b/src/gui/widgets/qtextedit_p.h
index 249331e..cf87a86 100644
--- a/src/gui/widgets/qtextedit_p.h
+++ b/src/gui/widgets/qtextedit_p.h
@@ -123,6 +123,7 @@ public:
uint preferRichText : 1;
uint showCursorOnInitialShow : 1;
uint inDrag : 1;
+ uint clickCausedFocus : 1;
// Qt3 COMPAT only, for setText
Qt::TextFormat textFormat;
diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri
index 2d809a1..cc03513 100644
--- a/src/gui/widgets/widgets.pri
+++ b/src/gui/widgets/widgets.pri
@@ -80,8 +80,8 @@ HEADERS += \
widgets/qtoolbararealayout_p.h \
widgets/qplaintextedit.h \
widgets/qplaintextedit_p.h \
- widgets/qprintpreviewwidget.h
-
+ widgets/qprintpreviewwidget.h \
+ widgets/qactiontokeyeventmapper_p.h
SOURCES += \
widgets/qabstractbutton.cpp \
widgets/qabstractslider.cpp \
@@ -140,8 +140,8 @@ SOURCES += \
widgets/qwidgetanimator.cpp \
widgets/qtoolbararealayout.cpp \
widgets/qplaintextedit.cpp \
- widgets/qprintpreviewwidget.cpp
-
+ widgets/qprintpreviewwidget.cpp \
+ widgets/qactiontokeyeventmapper.cpp
!embedded:mac {
HEADERS += widgets/qmacnativewidget_mac.h \
@@ -162,3 +162,7 @@ wince*: {
RC_FILE = widgets/qmenu_wince.rc
!static: QMAKE_WRITE_DEFAULT_RC = 1
}
+
+symbian*: {
+ SOURCES += widgets/qmenu_symbian.cpp
+}