summaryrefslogtreecommitdiffstats
path: root/src/gui/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/widgets')
-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.cpp26
-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
28 files changed, 935 insertions, 56 deletions
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 7fa26ae..bcc5c92 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 e0f5bc9..01d4890 100644
--- a/src/gui/widgets/qlineedit.cpp
+++ b/src/gui/widgets/qlineedit.cpp
@@ -509,7 +509,13 @@ void QLineEdit::setEchoMode(EchoMode mode)
Q_D(QLineEdit);
if (mode == (EchoMode)d->control->echoMode())
return;
- setAttribute(Qt::WA_InputMethodEnabled, d->shouldEnableInputMethod());
+ Qt::InputMethodHints imHints = inputMethodHints();
+ if (mode == Password) {
+ imHints |= Qt::ImhHiddenText;
+ } else {
+ imHints &= ~Qt::ImhHiddenText;
+ }
+ setInputMethodHints(imHints);
d->control->setEchoMode(mode);
update();
#ifdef Q_WS_MAC
@@ -1487,6 +1493,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
@@ -1649,6 +1662,15 @@ QVariant QLineEdit::inputMethodQuery(Qt::InputMethodQuery property) const
return QVariant(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();
}
@@ -1667,6 +1689,8 @@ void QLineEdit::focusInEvent(QFocusEvent *e)
d->control->moveCursor(d->control->nextMaskBlank(0));
else if (!d->control->hasSelectedText())
selectAll();
+ } else if (e->reason() == Qt::MouseFocusReason) {
+ d->clickCausedFocus = 1;
}
#ifdef QT_KEYPAD_NAVIGATION
if (!QApplication::keypadNavigationEnabled() || (hasEditFocus() && e->reason() == Qt::PopupFocusReason))
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 0b85eec..d0620af 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 8697771..0218dc7 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 4a900d6..eaf03b3 100644
--- a/src/gui/widgets/qmenubar.cpp
+++ b/src/gui/widgets/qmenubar.cpp
@@ -738,6 +738,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
@@ -809,6 +815,10 @@ QMenuBar::~QMenuBar()
if (qt_wince_is_mobile())
d->wceDestroyMenuBar();
#endif
+#ifdef Q_WS_S60
+ Q_D(QMenuBar);
+ d->symbianDestroyMenuBar();
+#endif
}
/*!
@@ -1064,6 +1074,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);
}
@@ -1276,6 +1292,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()));
@@ -1362,6 +1389,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
@@ -1596,7 +1628,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;
@@ -1652,7 +1684,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;
@@ -1710,7 +1742,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 8f24fac..4567902 100644
--- a/src/gui/widgets/widgets.pri
+++ b/src/gui/widgets/widgets.pri
@@ -81,8 +81,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 \
@@ -143,8 +143,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 \
@@ -165,3 +165,7 @@ wince*: {
RC_FILE = widgets/qmenu_wince.rc
!static: QMAKE_WRITE_DEFAULT_RC = 1
}
+
+symbian*: {
+ SOURCES += widgets/qmenu_symbian.cpp
+}