diff options
author | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2011-03-01 07:57:03 (GMT) |
---|---|---|
committer | Laszlo Agocs <laszlo.p.agocs@nokia.com> | 2011-03-01 07:57:03 (GMT) |
commit | e538957c77f71b1cc38a3c43c9f3157f65a3ff11 (patch) | |
tree | 3d013b12ba28668d127fe5532de5fc588fe63cb0 /src/gui | |
parent | 67d5513b5aca096dfc33952cf81219087b0e41b0 (diff) | |
parent | 2653c4fcf42ec93db16a299c29c9fe0f98680c75 (diff) | |
download | Qt-e538957c77f71b1cc38a3c43c9f3157f65a3ff11.zip Qt-e538957c77f71b1cc38a3c43c9f3157f65a3ff11.tar.gz Qt-e538957c77f71b1cc38a3c43c9f3157f65a3ff11.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt into 4.7
Conflicts:
src/s60installs/bwins/QtGuiu.def
src/s60installs/eabi/QtGuiu.def
Diffstat (limited to 'src/gui')
41 files changed, 347 insertions, 189 deletions
diff --git a/src/gui/dialogs/qpagesetupdialog.cpp b/src/gui/dialogs/qpagesetupdialog.cpp index 2a7847e..4037e1c 100644 --- a/src/gui/dialogs/qpagesetupdialog.cpp +++ b/src/gui/dialogs/qpagesetupdialog.cpp @@ -107,10 +107,10 @@ class QPageSetupDialogPrivate : public QAbstractPageSetupDialogPrivate This value is obsolete and does nothing since Qt 4.5: - \value DontUseSheet In previous versions of Qt, exec() the page setup dialog - would create a sheet by default if the dialog was given a parent. - This is no longer supported in Qt 4.5. If you want to use sheets, use - QPageSetupDialog::open() instead. + \value DontUseSheet In previous versions of QDialog::exec() the + page setup dialog would create a sheet by default if the dialog + was given a parent. This is no longer supported from Qt 4.5. If + you want to use sheets, use QPageSetupDialog::open() instead. \omitvalue None \omitvalue OwnsPrinter diff --git a/src/gui/embedded/qscreen_qws.cpp b/src/gui/embedded/qscreen_qws.cpp index 4656af8..e207ed1 100644 --- a/src/gui/embedded/qscreen_qws.cpp +++ b/src/gui/embedded/qscreen_qws.cpp @@ -1768,7 +1768,7 @@ QImage::Format QScreenPrivate::preferredImageFormat() const This function is called by every \l{Qt for Embedded Linux} application on startup, and must be implemented to map in the framebuffer and the accelerated drivers that the graphics card - control registers. Note that coonnect must be called \e before + control registers. Note that connect must be called \e before the initDevice() function. Ensure that true is returned if a connection to the screen device diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp index b059bd2..014b61b 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -56,9 +56,9 @@ Items that are anchored are automatically added to the layout, and if items are removed, all their anchors will be automatically removed. - \beginfloatleft + \div {float-left} \inlineimage simpleanchorlayout-example.png Using an anchor layout to align simple colored widgets. - \endfloat + \enddiv Anchors are always set up between edges of an item, where the "center" is also considered to be an edge. Consider the following example: diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 52e4d79..f463887 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -7689,11 +7689,13 @@ void QGraphicsObject::updateMicroFocus() void QGraphicsItemPrivate::children_append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item) { - QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(list->object); - if (QGraphicsItemPrivate::get(graphicsObject)->sendParentChangeNotification) { - item->setParentItem(graphicsObject); - } else { - QGraphicsItemPrivate::get(item)->setParentItemHelper(graphicsObject, 0, 0); + if (item) { + QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(list->object); + if (QGraphicsItemPrivate::get(graphicsObject)->sendParentChangeNotification) { + item->setParentItem(graphicsObject); + } else { + QGraphicsItemPrivate::get(item)->setParentItemHelper(graphicsObject, 0, 0); + } } } diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 5e5077b..f997fc2 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -130,7 +130,7 @@ item on the scene gains focus, the scene automatically gains focus. If the scene has focus, hasFocus() will return true, and key events will be forwarded to the focus item, if any. If the scene loses focus, (i.e., - someone calls clearFocus(),) while an item has focus, the scene will + someone calls clearFocus()) while an item has focus, the scene will maintain its item focus information, and once the scene regains focus, it will make sure the last focus item regains focus. @@ -806,28 +806,23 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, } if (focusItem) { - QFocusEvent event(QEvent::FocusOut, focusReason); lastFocusItem = focusItem; - focusItem = 0; - sendEvent(lastFocusItem, &event); #ifndef QT_NO_IM if (lastFocusItem && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { - // Reset any visible preedit text - QInputMethodEvent imEvent; - sendEvent(lastFocusItem, &imEvent); - // Close any external input method panel. This happens // automatically by removing WA_InputMethodEnabled on // the views, but if we are changing focus, we have to // do it ourselves. - if (item) { - for (int i = 0; i < views.size(); ++i) - if (views.at(i)->inputContext()) - views.at(i)->inputContext()->reset(); - } + for (int i = 0; i < views.size(); ++i) + if (views.at(i)->inputContext()) + views.at(i)->inputContext()->reset(); } + + focusItem = 0; + QFocusEvent event(QEvent::FocusOut, focusReason); + sendEvent(lastFocusItem, &event); #endif //QT_NO_IM } @@ -3104,8 +3099,8 @@ bool QGraphicsScene::stickyFocus() const \list \o If the item receives a mouse release event when there are no other buttons pressed, it loses the mouse grab. - \o If the item becomes invisible (i.e., someone calls \c {item->setVisible(false))}, - or if it becomes disabled (i.e., someone calls \c {item->setEnabled(false))}, + \o If the item becomes invisible (i.e., someone calls \c {item->setVisible(false)}), + or if it becomes disabled (i.e., someone calls \c {item->setEnabled(false)}), it loses the mouse grab. \o If the item is removed from the scene, it loses the mouse grab. \endlist @@ -5941,6 +5936,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve } if (item->isPanel()) break; + if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation) + break; } // If nobody could take focus, clear it. @@ -5973,6 +5970,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve } if (item && item->isPanel()) break; + if (item && (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)) + break; } touchEvent->setAccepted(eventAccepted); diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index 09c086a..6dea9d9 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -246,6 +246,8 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int if (depth != 32) { ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits; + if (ncols > 256) // sanity check - don't run out of mem if color table is broken + return false; image.setColorCount(ncols); } diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 9028de4..168c518 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -513,12 +513,12 @@ bool QImageData::checkForAlphaPixels() const function. For example: \table + \header + \o {2,1}32-bit \row \o \inlineimage qimage-32bit_scaled.png \o \snippet doc/src/snippets/code/src_gui_image_qimage.cpp 0 - \header - \o {2,1}32-bit \endtable In case of a 8-bit and monchrome images, the pixel value is only @@ -534,12 +534,12 @@ bool QImageData::checkForAlphaPixels() const example: \table + \header + \o {2,1} 8-bit \row \o \inlineimage qimage-8bit_scaled.png \o \snippet doc/src/snippets/code/src_gui_image_qimage.cpp 1 - \header - \o {2,1} 8-bit \endtable QImage also provide the scanLine() function which returns a diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index a02b3ff..76cd813 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -882,7 +882,7 @@ static bool read_xpm_body( QByteArray buf(200, 0); int i; - if (cpp > 15) + if (cpp < 0 || cpp > 15) return false; // For > 256 colors, we delay creation of the image until diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 37507dd..081a6d9 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -622,9 +622,9 @@ QAbstractItemView::~QAbstractItemView() deleteLater() functions to explicitly delete them. The view \e{does not} take ownership of the model unless it is the model's - parent object because the view may be shared between many different views. + parent object because the model may be shared between many different views. - \sa selectionModel(), setSelectionModel() + \sa selectionModel(), setSelectionModel() */ void QAbstractItemView::setModel(QAbstractItemModel *model) { diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp index e54cbd2..9f89bf5 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.cpp +++ b/src/gui/itemviews/qsortfilterproxymodel.cpp @@ -227,7 +227,7 @@ public: void _q_sourceColumnsRemoved(const QModelIndex &source_parent, int start, int end); - void clear_mapping(); + void _q_clearMapping(); void sort(); bool update_source_sort_column(); @@ -281,7 +281,7 @@ typedef QHash<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap; void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed() { QAbstractProxyModelPrivate::_q_sourceModelDestroyed(); - clear_mapping(); + _q_clearMapping(); } void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source_parent) @@ -293,7 +293,7 @@ void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source } } -void QSortFilterProxyModelPrivate::clear_mapping() +void QSortFilterProxyModelPrivate::_q_clearMapping() { // store the persistent indexes QModelIndexPairList source_indexes = store_persistent_indexes(); @@ -1223,7 +1223,7 @@ void QSortFilterProxyModelPrivate::_q_sourceReset() { Q_Q(QSortFilterProxyModel); invalidatePersistentIndexes(); - clear_mapping(); + _q_clearMapping(); // All internal structures are deleted in clear() q->endResetModel(); update_source_sort_column(); @@ -1519,6 +1519,7 @@ QSortFilterProxyModel::QSortFilterProxyModel(QObject *parent) d->filter_column = 0; d->filter_role = Qt::DisplayRole; d->dynamic_sortfilter = false; + connect(this, SIGNAL(modelReset()), this, SLOT(_q_clearMapping())); } /*! @@ -1620,7 +1621,7 @@ void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel) connect(d->model, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_sourceAboutToBeReset())); connect(d->model, SIGNAL(modelReset()), this, SLOT(_q_sourceReset())); - d->clear_mapping(); + d->_q_clearMapping(); endResetModel(); if (d->update_source_sort_column() && d->dynamic_sortfilter) d->sort(); @@ -2311,7 +2312,7 @@ void QSortFilterProxyModel::clear() { Q_D(QSortFilterProxyModel); emit layoutAboutToBeChanged(); - d->clear_mapping(); + d->_q_clearMapping(); emit layoutChanged(); } @@ -2326,7 +2327,7 @@ void QSortFilterProxyModel::invalidate() { Q_D(QSortFilterProxyModel); emit layoutAboutToBeChanged(); - d->clear_mapping(); + d->_q_clearMapping(); emit layoutChanged(); } diff --git a/src/gui/itemviews/qsortfilterproxymodel.h b/src/gui/itemviews/qsortfilterproxymodel.h index 09fd20f..afeaa69 100644 --- a/src/gui/itemviews/qsortfilterproxymodel.h +++ b/src/gui/itemviews/qsortfilterproxymodel.h @@ -189,6 +189,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsInserted(const QModelIndex &source_parent, int start, int end)) Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end)) Q_PRIVATE_SLOT(d_func(), void _q_sourceColumnsRemoved(const QModelIndex &source_parent, int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_clearMapping()) }; QT_END_NAMESPACE diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index f1f3236..c0573bb 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -2753,6 +2753,7 @@ int QTreeView::indexRowSizeHint(const QModelIndex &index) const int start = -1; int end = -1; + int indexRow = index.row(); int count = d->header->count(); bool emptyHeader = (count == 0); QModelIndex parent = index.parent(); @@ -2789,7 +2790,7 @@ int QTreeView::indexRowSizeHint(const QModelIndex &index) const int logicalColumn = emptyHeader ? column : d->header->logicalIndex(column); if (d->header->isSectionHidden(logicalColumn)) continue; - QModelIndex idx = d->model->index(index.row(), logicalColumn, parent); + QModelIndex idx = d->model->index(indexRow, logicalColumn, parent); if (idx.isValid()) { QWidget *editor = d->editorForIndex(idx).editor; if (editor && d->persistent.contains(editor)) { @@ -3224,14 +3225,14 @@ int QTreeViewPrivate::itemHeight(int item) const if (viewItems.isEmpty()) return 0; const QModelIndex &index = viewItems.at(item).index; + if (!index.isValid()) + return 0; int height = viewItems.at(item).height; - if (height <= 0 && index.isValid()) { + if (height <= 0) { height = q_func()->indexRowSizeHint(index); viewItems[item].height = height; } - if (!index.isValid() || height < 0) - return 0; - return height; + return qMax(height, 0); } diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index f28868c..e0447cc 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -5656,10 +5656,21 @@ static void sm_performSaveYourself(QSessionManagerPrivate* smd) sm_setProperty(QString::fromLatin1(SmProgram), argument0); // tell the session manager about our user as well. struct passwd *entryPtr = 0; -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) - QVarLengthArray<char, 1024> buf(sysconf(_SC_GETPW_R_SIZE_MAX)); +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) + QVarLengthArray<char, 1024> buf(qMax<long>(sysconf(_SC_GETPW_R_SIZE_MAX), 1024L)); struct passwd entry; - getpwuid_r(geteuid(), &entry, buf.data(), buf.size(), &entryPtr); + while (getpwuid_r(geteuid(), &entry, buf.data(), buf.size(), &entryPtr) == ERANGE) { + if (buf.size() >= 32768) { + // too big already, fail + static char badusername[] = ""; + entryPtr = &entry; + entry.pw_name = badusername; + break; + } + + // retry with a bigger buffer + buf.resize(buf.size() * 2); + } #else entryPtr = getpwuid(geteuid()); #endif diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h index 9c110fd..6254061 100644 --- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h +++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h @@ -89,6 +89,8 @@ QT_END_NAMESPACE QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; if (!widget) return NO; // This should happen only for qt_root_win + if (QApplicationPrivate::isBlockedByModal(widget)) + return NO; bool isToolTip = (widget->windowType() == Qt::ToolTip); bool isPopup = (widget->windowType() == Qt::Popup); @@ -100,6 +102,8 @@ QT_END_NAMESPACE QWidget *widget = [self QT_MANGLE_NAMESPACE(qt_qwidget)]; if (!widget) return NO; // This should happen only for qt_root_win + if ([self isSheet]) + return NO; bool isToolTip = (widget->windowType() == Qt::ToolTip); bool isPopup = (widget->windowType() == Qt::Popup); diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 749472a..d9f428c 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -1115,7 +1115,7 @@ static int qCocoaViewCount = 0; - (BOOL)resignFirstResponder { if (!qwidget) - return NO; + return YES; // Seems like the following test only triggers if this // view is inside a QMacNativeWidget: if (qwidget == QApplication::focusWidget()) diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index 17ede02..56daba2 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -332,7 +332,7 @@ void QPanGesture::setAcceleration(qreal value) /*! \class QPinchGesture \since 4.6 - \brief The QPinchGesture class describes a pinch gesture made my the user. + \brief The QPinchGesture class describes a pinch gesture made by the user. \ingroup touch \ingroup gestures diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp index 1eeaf8e..e014ec8 100644 --- a/src/gui/kernel/qlayout.cpp +++ b/src/gui/kernel/qlayout.cpp @@ -980,10 +980,10 @@ void QLayoutPrivate::reparentChildWidgets(QWidget *mw) /*! This function is called from \c addWidget() functions in - subclasses to add \a w as a child widget. + subclasses to add \a w as a managed widget of a layout. - If \a w is already in a layout, this function will give a warning - and remove \a w from the layout. This function must therefore be + If \a w is already managed by a layout, this function will give a warning + and remove \a w from that layout. This function must therefore be called before adding \a w to the layout's data structure. */ void QLayout::addChildWidget(QWidget *w) diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 3820bfc..20c1ddb 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -1391,6 +1391,7 @@ void qt_mac_constructQIconFromIconRef(const IconRef icon, const IconRef overlayI void qt_mac_menu_collapseSeparators(void */*NSMenu **/ theMenu, bool collapse) { + QMacCocoaAutoReleasePool pool; OSMenuRef menu = static_cast<OSMenuRef>(theMenu); if (collapse) { bool previousIsSeparator = true; // setting to true kills all the separators placed at the top. diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index e542a59..7065e85 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -393,11 +393,24 @@ void QWidgetPrivate::scrollChildren(int dx, int dy) } } +QInputContext *QWidgetPrivate::assignedInputContext() const +{ +#ifndef QT_NO_IM + const QWidget *widget = q_func(); + while (widget) { + if (QInputContext *qic = widget->d_func()->ic) + return qic; + widget = widget->parentWidget(); + } +#endif + return 0; +} + QInputContext *QWidgetPrivate::inputContext() const { #ifndef QT_NO_IM - if (ic) - return ic; + if (QInputContext *qic = assignedInputContext()) + return qic; return qApp->inputContext(); #else return 0; @@ -10721,7 +10734,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) case Qt::WA_InputMethodEnabled: { #ifndef QT_NO_IM QWidget *focusWidget = d->effectiveFocusWidget(); - QInputContext *ic = focusWidget->d_func()->ic; + QInputContext *ic = focusWidget->d_func()->assignedInputContext(); if (!ic && (!on || hasFocus())) ic = focusWidget->d_func()->inputContext(); if (ic) { @@ -11208,7 +11221,7 @@ void QWidget::updateMicroFocus() #if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) Q_D(QWidget); // and optimization to update input context only it has already been created. - if (d->ic || qApp->d_func()->inputContext) { + if (d->assignedInputContext() || qApp->d_func()->inputContext) { QInputContext *ic = inputContext(); if (ic) ic->update(); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 3759dd1..9f6ba6f 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -559,6 +559,7 @@ public: // sub-classes that their internals are about to be released. virtual void aboutToDestroy() {} + QInputContext *assignedInputContext() const; QInputContext *inputContext() const; inline QWidget *effectiveFocusWidget() { QWidget *w = q_func(); diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 9893478..b0375ef 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -444,6 +444,7 @@ static QVector<Atom> getNetWmState(QWidget *w) && actualType == XA_ATOM && actualFormat == 32) { returnValue.resize(bytesLeft / 4); XFree((char*) propertyData); + propertyData = 0; // fetch all data if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0, @@ -458,7 +459,8 @@ static QVector<Atom> getNetWmState(QWidget *w) if (!returnValue.isEmpty()) { memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom)); } - XFree((char*) propertyData); + if (propertyData) + XFree((char*) propertyData); } return returnValue; @@ -1316,40 +1318,12 @@ QPoint QWidgetPrivate::mapFromGlobal(const QPoint &pos) const QPoint QWidget::mapToGlobal(const QPoint &pos) const { Q_D(const QWidget); - QPoint offset = data->crect.topLeft(); - const QWidget *w = this; - const QWidget *p = w->parentWidget(); - while (!w->isWindow() && p) { - w = p; - p = p->parentWidget(); - offset += w->data->crect.topLeft(); - } - - const QWidgetPrivate *wd = w->d_func(); - QTLWExtra *tlw = wd->topData(); - if (!tlw->embedded) - return pos + offset; - return d->mapToGlobal(pos); } QPoint QWidget::mapFromGlobal(const QPoint &pos) const { Q_D(const QWidget); - QPoint offset = data->crect.topLeft(); - const QWidget *w = this; - const QWidget *p = w->parentWidget(); - while (!w->isWindow() && p) { - w = p; - p = p->parentWidget(); - offset += w->data->crect.topLeft(); - } - - const QWidgetPrivate *wd = w->d_func(); - QTLWExtra *tlw = wd->topData(); - if (!tlw->embedded) - return pos - offset; - return d->mapFromGlobal(pos); } diff --git a/src/gui/kernel/qx11embed_x11.cpp b/src/gui/kernel/qx11embed_x11.cpp index aba42f2..710f607 100644 --- a/src/gui/kernel/qx11embed_x11.cpp +++ b/src/gui/kernel/qx11embed_x11.cpp @@ -415,8 +415,9 @@ static Bool functor(Display *display, XEvent *event, XPointer arg) status = XGetWindowProperty(display, data->id, ATOM(WM_STATE), 0, 2, False, ATOM(WM_STATE), &ret, &format, &nitems, &after, &retval ); if (status == Success && ret == ATOM(WM_STATE) && format == 32 && nitems > 0) { - long *state = (long *)retval; - if (state[0] == WithdrawnState) { + long state = *(long *)retval; + XFree(retval); + if (state == WithdrawnState) { data->clearedWmState = true; return true; } @@ -833,6 +834,8 @@ bool QX11EmbedWidget::x11Event(XEvent *event) XUnmapWindow(x11Info().display(), internalWinId()); } } + if (prop_return) + XFree(prop_return); } } diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 81a62b0..dc61e34 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -1208,14 +1208,14 @@ QDataStream &operator>>(QDataStream &s, QBrush &b) Each of the types is represented by a subclass of QGradient: \table - \row - \o \inlineimage qgradient-linear.png - \o \inlineimage qgradient-radial.png - \o \inlineimage qgradient-conical.png \header \o QLinearGradient \o QRadialGradient \o QConicalGradient + \row + \o \inlineimage qgradient-linear.png + \o \inlineimage qgradient-radial.png + \o \inlineimage qgradient-conical.png \endtable The colors in a gradient are defined using stop points of the diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index dea3a72..8ebbe35 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -78,12 +78,12 @@ QT_BEGIN_NAMESPACE names. \table + \header + \o RGB \o HSV \o CMYK \row \o \inlineimage qcolor-rgb.png \o \inlineimage qcolor-hsv.png \o \inlineimage qcolor-cmyk.png - \header - \o RGB \o HSV \o CMYK \endtable The QColor constructor creates the color based on RGB values. To diff --git a/src/gui/painting/qgraphicssystem_runtime.cpp b/src/gui/painting/qgraphicssystem_runtime.cpp index 0294c4b..5841d40 100644 --- a/src/gui/painting/qgraphicssystem_runtime.cpp +++ b/src/gui/painting/qgraphicssystem_runtime.cpp @@ -285,6 +285,7 @@ void QRuntimeWindowSurface::flush(QWidget *widget, const QRegion ®ion, void QRuntimeWindowSurface::setGeometry(const QRect &rect) { + QWindowSurface::setGeometry(rect); m_windowSurface->setGeometry(rect); } diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 682731a..ba618ea 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -3706,6 +3706,13 @@ void QRasterPaintEnginePrivate::rasterizeLine_dashed(QLineF line, const bool squareCap = (pen.capStyle() == Qt::SquareCap); const QVector<qreal> pattern = pen.dashPattern(); + qreal patternLength = 0; + for (int i = 0; i < pattern.size(); ++i) + patternLength += pattern.at(i); + + if (patternLength <= 0) + return; + qreal length = line.length(); Q_ASSERT(length > 0); while (length > 0) { diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index a32443f..76ac7db 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1113,14 +1113,14 @@ void QPainterPrivate::updateState(QPainterState *newState) the range of available patterns. \table - \row - \o \inlineimage qpainter-vectordeformation.png - \o \inlineimage qpainter-gradients.png - \o \inlineimage qpainter-pathstroking.png \header \o \l {demos/deform}{Vector Deformation} \o \l {demos/gradients}{Gradients} \o \l {demos/pathstroke}{Path Stroking} + \row + \o \inlineimage qpainter-vectordeformation.png + \o \inlineimage qpainter-gradients.png + \o \inlineimage qpainter-pathstroking.png \endtable @@ -1193,13 +1193,13 @@ void QPainterPrivate::updateState(QPainterState *newState) coordinate transformations. \table + \header + \o nop \o rotate() \o scale() \o translate() \row \o \inlineimage qpainter-clock.png \o \inlineimage qpainter-rotation.png \o \inlineimage qpainter-scale.png \o \inlineimage qpainter-translation.png - \header - \o nop \o rotate() \o scale() \o translate() \endtable The most commonly used transformations are scaling, rotation, diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 7ecf10a..9ef6955 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -240,12 +240,12 @@ static void qt_debug_path(const QPainterPath &path) provides two methods for filling paths: \table - \row - \o \inlineimage qt-fillrule-oddeven.png - \o \inlineimage qt-fillrule-winding.png \header \o Qt::OddEvenFill \o Qt::WindingFill + \row + \o \inlineimage qt-fillrule-oddeven.png + \o \inlineimage qt-fillrule-winding.png \endtable See the Qt::FillRule documentation for the definition of the @@ -315,12 +315,12 @@ static void qt_debug_path(const QPainterPath &path) QPainterPath to draw text. \table - \row - \o \inlineimage qpainterpath-example.png - \o \inlineimage qpainterpath-demo.png \header \o \l {painting/painterpaths}{Painter Paths Example} \o \l {demos/deform}{Vector Deformation Demo} + \row + \o \inlineimage qpainterpath-example.png + \o \inlineimage qpainterpath-demo.png \endtable \sa QPainterPathStroker, QPainter, QRegion, {Painter Paths Example} @@ -1245,12 +1245,12 @@ Qt::FillRule QPainterPath::fillRule() const fillRule. Qt provides two methods for filling paths: \table - \row - \o \inlineimage qt-fillrule-oddeven.png - \o \inlineimage qt-fillrule-winding.png \header \o Qt::OddEvenFill (default) \o Qt::WindingFill + \row + \o \inlineimage qt-fillrule-oddeven.png + \o \inlineimage qt-fillrule-winding.png \endtable \sa fillRule() diff --git a/src/gui/statemachine/qguistatemachine.cpp b/src/gui/statemachine/qguistatemachine.cpp index eadb8ff..2a0de3c 100644 --- a/src/gui/statemachine/qguistatemachine.cpp +++ b/src/gui/statemachine/qguistatemachine.cpp @@ -404,6 +404,7 @@ static QEvent *cloneEvent(QEvent *e) we2->setButtons(we->buttons()); we2->setModifiers(we->modifiers()); we2->setOrientation(we->orientation()); + we2->setDelta(we->delta()); return we2; } #endif diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 2b3dffc..a4e7c38 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -4248,7 +4248,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op return; case PE_Widget: - if (!rule.hasDrawable()) { + if (w && !rule.hasDrawable()) { QWidget *container = containerWidget(w); if (autoFillDisabledWidgets->contains(container) && (container == w || !renderRule(container, opt).hasBackground())) { diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 1c21f91..42b9402 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -59,6 +59,8 @@ QT_BEGIN_NAMESPACE +static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90); + /***************************************************************************** QFontEngine debug facilities *****************************************************************************/ @@ -467,6 +469,9 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph) glyph_metrics_t ret; CGGlyph g = glyph; CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, 0, 1); + if (synthesisFlags & QFontEngine::SynthesizedItalic) { + rect.size.width += rect.size.height * SYNTHETIC_ITALIC_SKEW; + } ret.width = QFixed::fromReal(rect.size.width); ret.height = QFixed::fromReal(rect.size.height); ret.x = QFixed::fromReal(rect.origin.x); @@ -558,7 +563,7 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt CGAffineTransformConcat(cgMatrix, oldTextMatrix); if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0)); + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); cgMatrix = CGAffineTransformConcat(cgMatrix, transform); @@ -646,7 +651,7 @@ void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *position cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1); if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0)); + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); for (int i = 0; i < nGlyphs; ++i) { @@ -681,7 +686,7 @@ QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, int margin, bool aa) CGAffineTransformConcat(cgMatrix, oldTextMatrix); if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, tanf(14 * acosf(0) / 90), 1, 0, 0)); + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); cgMatrix = CGAffineTransformConcat(cgMatrix, transform); @@ -1625,7 +1630,7 @@ QImage QFontEngineMac::imageForGlyph(glyph_t glyph, int margin, bool colorful) CGAffineTransformConcat(cgMatrix, oldTextMatrix); if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, tanf(14 * acosf(0) / 90), 1, 0, 0)); + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); cgMatrix = CGAffineTransformConcat(cgMatrix, transform); @@ -1718,7 +1723,7 @@ void QFontEngineMac::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt CGAffineTransformConcat(cgMatrix, oldTextMatrix); if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0)); + cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); cgMatrix = CGAffineTransformConcat(cgMatrix, transform); diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 58bfbc6..b25588d 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -114,6 +114,7 @@ static QTextLine currentTextLine(const QTextCursor &cursor) QTextControlPrivate::QTextControlPrivate() : doc(0), cursorOn(false), cursorIsFocusIndicator(false), interactionFlags(Qt::TextEditorInteraction), + dragEnabled(true), #ifndef QT_NO_DRAGANDDROP mousePressed(false), mightStartDrag(false), #endif @@ -128,7 +129,8 @@ QTextControlPrivate::QTextControlPrivate() isEnabled(true), hadSelectionOnMousePress(false), ignoreUnusedNavigationEvents(false), - openExternalLinks(false) + openExternalLinks(false), + wordSelectionEnabled(false) {} bool QTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) @@ -930,15 +932,18 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte break; } case QEvent::MouseMove: { QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseMoveEvent(ev->buttons(), matrix.map(ev->pos())); + d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), + ev->buttons(), ev->globalPos()); break; } case QEvent::MouseButtonRelease: { QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseReleaseEvent(ev->button(), matrix.map(ev->pos())); + d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), + ev->buttons(), ev->globalPos()); break; } case QEvent::MouseButtonDblClick: { QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseDoubleClickEvent(e, ev->button(), matrix.map(ev->pos())); + d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), + ev->buttons(), ev->globalPos()); break; } case QEvent::InputMethod: d->inputMethodEvent(static_cast<QInputMethodEvent *>(e)); @@ -998,15 +1003,18 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte break; } case QEvent::GraphicsSceneMouseMove: { QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseMoveEvent(ev->buttons(), matrix.map(ev->pos())); + d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + ev->screenPos()); break; } case QEvent::GraphicsSceneMouseRelease: { QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseReleaseEvent(ev->button(), matrix.map(ev->pos())); + d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + ev->screenPos()); break; } case QEvent::GraphicsSceneMouseDoubleClick: { QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseDoubleClickEvent(e, ev->button(), matrix.map(ev->pos())); + d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), + ev->screenPos()); break; } case QEvent::GraphicsSceneContextMenu: { QGraphicsSceneContextMenuEvent *ev = static_cast<QGraphicsSceneContextMenuEvent *>(e); @@ -1015,7 +1023,8 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte case QEvent::GraphicsSceneHoverMove: { QGraphicsSceneHoverEvent *ev = static_cast<QGraphicsSceneHoverEvent *>(e); - d->mouseMoveEvent(Qt::NoButton, matrix.map(ev->pos())); + d->mouseMoveEvent(ev, Qt::NoButton, matrix.map(ev->pos()), ev->modifiers(),Qt::NoButton, + ev->screenPos()); break; } case QEvent::GraphicsSceneDragEnter: { @@ -1485,6 +1494,11 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con { Q_Q(QTextControl); + if (sendMouseEventToInputContext( + e, QEvent::MouseButtonPress, button, pos, modifiers, buttons, globalPos)) { + return; + } + if (interactionFlags & Qt::LinksAccessibleByMouse) { anchorOnMousePress = q->anchorAt(pos); @@ -1527,31 +1541,22 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con return; } -#if !defined(QT_NO_IM) - QTextLayout *layout = cursor.block().layout(); - if (contextWidget && layout && !layout->preeditAreaText().isEmpty()) { - QInputContext *ctx = inputContext(); - if (ctx) { - QMouseEvent ev(QEvent::MouseButtonPress, contextWidget->mapFromGlobal(globalPos), globalPos, - button, buttons, modifiers); - ctx->mouseHandler(cursorPos - cursor.position(), &ev); + if (modifiers == Qt::ShiftModifier && (interactionFlags & Qt::TextSelectableByMouse)) { + if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { + selectedWordOnDoubleClick = cursor; + selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); } - if (!layout->preeditAreaText().isEmpty()) { - e->ignore(); - return; - } - } -#endif - if (modifiers == Qt::ShiftModifier) { + if (selectedBlockOnTrippleClick.hasSelection()) extendBlockwiseSelection(cursorPos); else if (selectedWordOnDoubleClick.hasSelection()) extendWordwiseSelection(cursorPos, pos.x()); - else + else if (wordSelectionEnabled) setCursorPosition(cursorPos, QTextCursor::KeepAnchor); } else { - if (cursor.hasSelection() + if (dragEnabled + && cursor.hasSelection() && !cursorIsFocusIndicator && cursorPos >= cursor.selectionStart() && cursorPos <= cursor.selectionEnd() @@ -1581,10 +1586,16 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con hadSelectionOnMousePress = cursor.hasSelection(); } -void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF &mousePos) +void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, const QPointF &mousePos, Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); + if (sendMouseEventToInputContext( + e, QEvent::MouseMove, button, mousePos, modifiers, buttons, globalPos)) { + return; + } + if (interactionFlags & Qt::LinksAccessibleByMouse) { QString anchor = q->anchorAt(mousePos); if (anchor != highlightedAnchor) { @@ -1614,21 +1625,20 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF } const qreal mouseX = qreal(mousePos.x()); -#if !defined(QT_NO_IM) - QTextLayout *layout = cursor.block().layout(); - if (layout && !layout->preeditAreaText().isEmpty()) - return; -#endif - int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit); if (newCursorPos == -1) return; + if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { + selectedWordOnDoubleClick = cursor; + selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); + } + if (selectedBlockOnTrippleClick.hasSelection()) extendBlockwiseSelection(newCursorPos); else if (selectedWordOnDoubleClick.hasSelection()) extendWordwiseSelection(newCursorPos, mouseX); - else + else if (interactionFlags & Qt::TextSelectableByMouse) setCursorPosition(newCursorPos, QTextCursor::KeepAnchor); if (interactionFlags & Qt::TextEditable) { @@ -1652,10 +1662,16 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF repaintOldAndNewSelection(oldSelection); } -void QTextControlPrivate::mouseReleaseEvent(Qt::MouseButton button, const QPointF &pos) +void QTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); + if (sendMouseEventToInputContext( + e, QEvent::MouseButtonRelease, button, pos, modifiers, buttons, globalPos)) { + return; + } + const QTextCursor oldSelection = cursor; const int oldCursorPos = cursor.position(); @@ -1713,19 +1729,21 @@ void QTextControlPrivate::mouseReleaseEvent(Qt::MouseButton button, const QPoint } } -void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos) +void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, const QPoint &globalPos) { Q_Q(QTextControl); + + if (sendMouseEventToInputContext( + e, QEvent::MouseButtonDblClick, button, pos, modifiers, buttons, globalPos)) { + return; + } + if (button != Qt::LeftButton || !(interactionFlags & Qt::TextSelectableByMouse)) { e->ignore(); return; } -#if !defined(QT_NO_IM) - QTextLayout *layout = cursor.block().layout(); - if (layout && !layout->preeditAreaText().isEmpty()) - return; -#endif #ifndef QT_NO_DRAGANDDROP mightStartDrag = false; @@ -1754,6 +1772,45 @@ void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton butto } } +bool QTextControlPrivate::sendMouseEventToInputContext( + QEvent *e, QEvent::Type eventType, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint &globalPos) +{ +#if !defined(QT_NO_IM) + Q_Q(QTextControl); + + QTextLayout *layout = cursor.block().layout(); + if (contextWidget && layout && !layout->preeditAreaText().isEmpty()) { + QInputContext *ctx = inputContext(); + int cursorPos = q->hitTest(pos, Qt::FuzzyHit) - cursor.position(); + + if (cursorPos < 0 || cursorPos > layout->preeditAreaText().length()) { + cursorPos = -1; + // don't send move events outside the preedit area + if (eventType == QEvent::MouseMove) + return true; + } + if (ctx) { + QMouseEvent ev(eventType, contextWidget->mapFromGlobal(globalPos), globalPos, + button, buttons, modifiers); + ctx->mouseHandler(cursorPos, &ev); + e->setAccepted(ev.isAccepted()); + } + if (!layout->preeditAreaText().isEmpty()) + return true; + } +#else + Q_UNUSED(e); + Q_UNUSED(eventType); + Q_UNUSED(button); + Q_UNUSED(pos); + Q_UNUSED(modifiers); + Q_UNUSED(buttons); + Q_UNUSED(globalPos); +#endif + return false; +} + void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPointF &docPos, QWidget *contextWidget) { #ifdef QT_NO_CONTEXTMENU @@ -2328,6 +2385,31 @@ bool QTextControl::cursorIsFocusIndicator() const return d->cursorIsFocusIndicator; } + +void QTextControl::setDragEnabled(bool enabled) +{ + Q_D(QTextControl); + d->dragEnabled = enabled; +} + +bool QTextControl::isDragEnabled() const +{ + Q_D(const QTextControl); + return d->dragEnabled; +} + +void QTextControl::setWordSelectionEnabled(bool enabled) +{ + Q_D(QTextControl); + d->wordSelectionEnabled = enabled; +} + +bool QTextControl::isWordSelectionEnabled() const +{ + Q_D(const QTextControl); + return d->wordSelectionEnabled; +} + #ifndef QT_NO_PRINTER void QTextControl::print(QPrinter *printer) const { diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h index 6540f4f..31fa843 100644 --- a/src/gui/text/qtextcontrol_p.h +++ b/src/gui/text/qtextcontrol_p.h @@ -175,6 +175,12 @@ public: void setCursorIsFocusIndicator(bool b); bool cursorIsFocusIndicator() const; + void setDragEnabled(bool enabled); + bool isDragEnabled() const; + + bool isWordSelectionEnabled() const; + void setWordSelectionEnabled(bool enabled); + #ifndef QT_NO_PRINTER void print(QPrinter *printer) const; #endif @@ -183,8 +189,6 @@ public: virtual QRectF blockBoundingRect(const QTextBlock &block) const; QAbstractTextDocumentLayout::PaintContext getPaintContext(QWidget *widget) const; - - public Q_SLOTS: void setPlainText(const QString &text); void setHtml(const QString &text); diff --git a/src/gui/text/qtextcontrol_p_p.h b/src/gui/text/qtextcontrol_p_p.h index 04f4c75..94670e2 100644 --- a/src/gui/text/qtextcontrol_p_p.h +++ b/src/gui/text/qtextcontrol_p_p.h @@ -135,9 +135,23 @@ public: Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint &globalPos); - void mouseMoveEvent(Qt::MouseButtons buttons, const QPointF &pos); - void mouseReleaseEvent(Qt::MouseButton button, const QPointF &pos); - void mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos); + void mouseMoveEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); + void mouseReleaseEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); + void mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); + bool sendMouseEventToInputContext(QEvent *e, QEvent::Type eventType, Qt::MouseButton button, + const QPointF &pos, + Qt::KeyboardModifiers modifiers, + Qt::MouseButtons buttons, + const QPoint &globalPos); void contextMenuEvent(const QPoint &screenPos, const QPointF &docPos, QWidget *contextWidget); void focusEvent(QFocusEvent *e); #ifdef QT_KEYPAD_NAVIGATION @@ -174,6 +188,8 @@ public: QBasicTimer trippleClickTimer; QPointF trippleClickPoint; + bool dragEnabled; + bool mousePressed; bool mightStartDrag; @@ -209,6 +225,8 @@ public: bool ignoreUnusedNavigationEvents; bool openExternalLinks; + bool wordSelectionEnabled; + QString linkToCopy; void _q_copyLink(); void _q_updateBlock(const QTextBlock &); diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index d721c91..a1dcb63 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -513,6 +513,9 @@ public: qreal scaleToDevice(qreal value) const; QFixed scaleToDevice(QFixed value) const; + + qreal lineH; + QTextDocumentLayout::LineHeightMode lineHeightMode; }; QTextDocumentLayoutPrivate::QTextDocumentLayoutPrivate() @@ -520,7 +523,9 @@ QTextDocumentLayoutPrivate::QTextDocumentLayoutPrivate() cursorWidth(1), currentLazyLayoutPosition(-1), lazyLayoutStepSize(1000), - lastPageCount(-1) + lastPageCount(-1), + lineH(1), + lineHeightMode(QTextDocumentLayout::ProportionalHeight) { showLayoutProgress = true; insideDocumentChange = false; @@ -2639,7 +2644,10 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi } - QFixed lineHeight = QFixed::fromReal(line.height()); + // TODO: replace with proper line height support in 4.8 + QFixed lineHeight = (lineHeightMode == QTextDocumentLayout::FixedHeight) + ? QFixed::fromReal(lineH) : QFixed::fromReal(line.height() * lineH); + if (layoutStruct->pageHeight > 0 && layoutStruct->absoluteY() + lineHeight > layoutStruct->pageBottom) { layoutStruct->newPage(); @@ -2714,6 +2722,13 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi } } +void QTextDocumentLayout::setLineHeight(qreal lineH, QTextDocumentLayout::LineHeightMode mode = QTextDocumentLayout::ProportionalHeight) +{ + Q_D(QTextDocumentLayout); + d->lineH = lineH; + d->lineHeightMode = mode; +} + void QTextDocumentLayoutPrivate::floatMargins(const QFixed &y, const QTextLayoutStruct *layoutStruct, QFixed *left, QFixed *right) const { diff --git a/src/gui/text/qtextdocumentlayout_p.h b/src/gui/text/qtextdocumentlayout_p.h index 3c0383c..3e3e485 100644 --- a/src/gui/text/qtextdocumentlayout_p.h +++ b/src/gui/text/qtextdocumentlayout_p.h @@ -63,7 +63,7 @@ class QTextListFormat; class QTextDocumentLayoutPrivate; -class Q_AUTOTEST_EXPORT QTextDocumentLayout : public QAbstractTextDocumentLayout +class Q_GUI_EXPORT QTextDocumentLayout : public QAbstractTextDocumentLayout { Q_DECLARE_PRIVATE(QTextDocumentLayout) Q_OBJECT @@ -109,6 +109,11 @@ protected: void drawInlineObject(QPainter *p, const QRectF &rect, QTextInlineObject item, int posInDocument, const QTextFormat &format); virtual void timerEvent(QTimerEvent *e); + + // TODO: remove when we support line height properly in 4.8 + enum LineHeightMode { ProportionalHeight, FixedHeight }; + void setLineHeight(qreal lineHeight, QTextDocumentLayout::LineHeightMode mode); + private: QRectF doLayout(int from, int oldLength, int length); void layoutFinished(); diff --git a/src/gui/text/qtextengine_mac.cpp b/src/gui/text/qtextengine_mac.cpp index ce42241..c34bdb3 100644 --- a/src/gui/text/qtextengine_mac.cpp +++ b/src/gui/text/qtextengine_mac.cpp @@ -604,8 +604,9 @@ void QTextEngine::shapeTextMac(int item) const bool stringToCMapFailed = false; if (!fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, attributes())) { ensureSpace(num_glyphs); - stringToCMapFailed = fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, - attributes()); + g = availableGlyphs(&si); + stringToCMapFailed = !fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, + attributes()); } if (!stringToCMapFailed) { diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 0da4f6a..d108ad9 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -456,6 +456,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) #ifndef QT_NO_IM setPreeditArea(m_cursor, event->preeditString()); #endif //QT_NO_IM + const int oldPreeditCursor = m_preeditCursor; m_preeditCursor = event->preeditString().length(); m_hideCursor = false; QList<QTextLayout::FormatRange> formats; @@ -479,6 +480,8 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) updateDisplayText(/*force*/ true); if (cursorPositionChanged) emitCursorPositionChanged(); + else if (m_preeditCursor != oldPreeditCursor) + emit updateMicroFocus(); if (isGettingInput) finishChange(priorState); } @@ -541,10 +544,13 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl */ void QLineControl::selectWordAtPos(int cursor) { - int c = m_textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords); + int next = cursor + 1; + if(next > end()) + --next; + int c = m_textLayout.previousCursorPosition(next, QTextLayout::SkipWords); moveCursor(c, false); // ## text layout should support end of words. - int end = m_textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords); + int end = m_textLayout.nextCursorPosition(c, QTextLayout::SkipWords); while (end > cursor && m_text[end-1].isSpace()) --end; moveCursor(end, true); diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index bfe50fe..3c505c8 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -425,6 +425,7 @@ Q_SIGNALS: void textEdited(const QString &); void resetInputContext(); + void updateMicroFocus(); void accepted(); void editingFinished(); diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp index d3af9e1..7435691 100644 --- a/src/gui/widgets/qplaintextedit.cpp +++ b/src/gui/widgets/qplaintextedit.cpp @@ -967,7 +967,7 @@ void QPlainTextEditPrivate::_q_adjustScrollbars() ++lineNumber; } if (lineNumber < layoutLineCount) - visibleFromBottom += (layoutLineCount - lineNumber - 1); + visibleFromBottom += (layoutLineCount - lineNumber); break; } diff --git a/src/gui/widgets/qscrollbar.cpp b/src/gui/widgets/qscrollbar.cpp index 67f34eb..c895b1b 100644 --- a/src/gui/widgets/qscrollbar.cpp +++ b/src/gui/widgets/qscrollbar.cpp @@ -82,21 +82,21 @@ QT_BEGIN_NAMESPACE needs. \table - \row \i \image qscrollbar-picture.png - \i Scroll bars typically include four separate controls: a slider, + \row \o \image qscrollbar-picture.png + \o Scroll bars typically include four separate controls: a slider, scroll arrows, and a page control. \list - \i a. The slider provides a way to quickly go to any part of the + \o a. The slider provides a way to quickly go to any part of the document, but does not support accurate navigation within large documents. - \i b. The scroll arrows are push buttons which can be used to accurately + \o b. The scroll arrows are push buttons which can be used to accurately navigate to a particular place in a document. For a vertical scroll bar connected to a text editor, these typically move the current position one "line" up or down, and adjust the position of the slider by a small amount. In editors and list boxes a "line" might mean one line of text; in an image viewer it might mean 20 pixels. - \i c. The page control is the area over which the slider is dragged (the + \o c. The page control is the area over which the slider is dragged (the scroll bar's background). Clicking here moves the scroll bar towards the click by one "page". This value is usually the same as the length of the slider. @@ -134,13 +134,12 @@ QT_BEGIN_NAMESPACE value of 80. This would give us a scroll bar with five "pages". \table - \row \i \inlineimage qscrollbar-values.png - \i The relationship between a document length, the range of values used + \row \o \inlineimage qscrollbar-values.png + \o The relationship between a document length, the range of values used in a scroll bar, and the page step is simple in many common situations. The scroll bar's range of values is determined by subtracting a chosen page step from some value representing the length of the document. In such cases, the following equation is useful: - \e{document length} = maximum() - minimum() + pageStep(). \endtable @@ -153,18 +152,18 @@ QT_BEGIN_NAMESPACE ScrollBar inherits a comprehensive set of signals from QAbstractSlider: \list - \i \l{QAbstractSlider::valueChanged()}{valueChanged()} is emitted when the + \o \l{QAbstractSlider::valueChanged()}{valueChanged()} is emitted when the scroll bar's value has changed. The tracking() determines whether this signal is emitted during user interaction. - \i \l{QAbstractSlider::rangeChanged()}{rangeChanged()} is emitted when the + \o \l{QAbstractSlider::rangeChanged()}{rangeChanged()} is emitted when the scroll bar's range of values has changed. - \i \l{QAbstractSlider::sliderPressed()}{sliderPressed()} is emitted when + \o \l{QAbstractSlider::sliderPressed()}{sliderPressed()} is emitted when the user starts to drag the slider. - \i \l{QAbstractSlider::sliderMoved()}{sliderMoved()} is emitted when the user + \o \l{QAbstractSlider::sliderMoved()}{sliderMoved()} is emitted when the user drags the slider. - \i \l{QAbstractSlider::sliderReleased()}{sliderReleased()} is emitted when + \o \l{QAbstractSlider::sliderReleased()}{sliderReleased()} is emitted when the user releases the slider. - \i \l{QAbstractSlider::actionTriggered()}{actionTriggered()} is emitted + \o \l{QAbstractSlider::actionTriggered()}{actionTriggered()} is emitted when the scroll bar is changed by user interaction or via the \l{QAbstractSlider::triggerAction()}{triggerAction()} function. \endlist @@ -173,12 +172,12 @@ QT_BEGIN_NAMESPACE default focusPolicy() of Qt::NoFocus. Use setFocusPolicy() to enable keyboard interaction with the scroll bar: \list - \i Left/Right move a horizontal scroll bar by one single step. - \i Up/Down move a vertical scroll bar by one single step. - \i PageUp moves up one page. - \i PageDown moves down one page. - \i Home moves to the start (mininum). - \i End moves to the end (maximum). + \o Left/Right move a horizontal scroll bar by one single step. + \o Up/Down move a vertical scroll bar by one single step. + \o PageUp moves up one page. + \o PageDown moves down one page. + \o Home moves to the start (mininum). + \o End moves to the end (maximum). \endlist The slider itself can be controlled by using the |