diff options
Diffstat (limited to 'src/gui')
33 files changed, 1028 insertions, 901 deletions
diff --git a/src/gui/accessible/accessible.pri b/src/gui/accessible/accessible.pri index 76b6687..ad2fb4c 100644 --- a/src/gui/accessible/accessible.pri +++ b/src/gui/accessible/accessible.pri @@ -14,7 +14,8 @@ contains(QT_CONFIG, accessibility) { mac:!embedded { HEADERS += accessible/qaccessible_mac_p.h - OBJECTIVE_SOURCES += accessible/qaccessible_mac.mm + OBJECTIVE_SOURCES += accessible/qaccessible_mac.mm \ + accessible/qaccessible_mac_cocoa.mm } else:win32 { SOURCES += accessible/qaccessible_win.cpp } else { diff --git a/src/gui/accessible/qaccessible_mac_cocoa.mm b/src/gui/accessible/qaccessible_mac_cocoa.mm index e69de29..1cb2ffa 100644 --- a/src/gui/accessible/qaccessible_mac_cocoa.mm +++ b/src/gui/accessible/qaccessible_mac_cocoa.mm @@ -0,0 +1,234 @@ + +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qaccessible.h" +#include "qaccessible_mac_p.h" +#include "qdebug.h" +#include "qtabwidget.h" + +#include <private/qt_mac_p.h> +#include <private/qcocoaview_mac_p.h> +#include <private/qwidget_p.h> + + +#ifndef QT_NO_ACCESSIBILITY + +#ifdef QT_MAC_USE_COCOA + +QT_BEGIN_NAMESPACE + +//#define MAC_ACCESSIBILTY_DEVELOPER_MODE + +#ifdef MAC_ACCESSIBILTY_DEVELOPER_MODE +#define MAC_ACCESSIBILTY_DEBUG qDebug +#else +#define MAC_ACCESSIBILTY_DEBUG if (0) qDebug +#endif + +typedef QMap<QAccessible::Role, NSString *> QMacAccessibiltyRoleMap; +Q_GLOBAL_STATIC(QMacAccessibiltyRoleMap, qMacAccessibiltyRoleMap); + +static QAInterface interfaceForView(QT_MANGLE_NAMESPACE(QCocoaView) *view) +{ + return QAInterface(QAccessible::queryAccessibleInterface([view qt_qwidget])); +} + +/* + Set up mappings from Qt accessibilty roles to Mac accessibilty roles. +*/ +static void populateRoleMap() +{ + QMacAccessibiltyRoleMap &roleMap = *qMacAccessibiltyRoleMap(); + roleMap[QAccessible::MenuItem] = NSAccessibilityMenuItemRole; + roleMap[QAccessible::MenuBar] = NSAccessibilityMenuBarRole; + roleMap[QAccessible::ScrollBar] = NSAccessibilityScrollBarRole; + roleMap[QAccessible::Grip] = NSAccessibilityGrowAreaRole; + roleMap[QAccessible::Window] = NSAccessibilityWindowRole; + roleMap[QAccessible::Dialog] = NSAccessibilityWindowRole; + roleMap[QAccessible::AlertMessage] = NSAccessibilityWindowRole; + roleMap[QAccessible::ToolTip] = NSAccessibilityWindowRole; + roleMap[QAccessible::HelpBalloon] = NSAccessibilityWindowRole; + roleMap[QAccessible::PopupMenu] = NSAccessibilityMenuRole; + roleMap[QAccessible::Application] = NSAccessibilityApplicationRole; + roleMap[QAccessible::Pane] = NSAccessibilityGroupRole; + roleMap[QAccessible::Grouping] = NSAccessibilityGroupRole; + roleMap[QAccessible::Separator] = NSAccessibilitySplitterRole; + roleMap[QAccessible::ToolBar] = NSAccessibilityToolbarRole; + roleMap[QAccessible::PageTab] = NSAccessibilityRadioButtonRole; + roleMap[QAccessible::ButtonMenu] = NSAccessibilityMenuButtonRole; + roleMap[QAccessible::ButtonDropDown] = NSAccessibilityPopUpButtonRole; + roleMap[QAccessible::SpinBox] = NSAccessibilityIncrementorRole; + roleMap[QAccessible::Slider] = NSAccessibilitySliderRole; + roleMap[QAccessible::ProgressBar] = NSAccessibilityProgressIndicatorRole; + roleMap[QAccessible::ComboBox] = NSAccessibilityPopUpButtonRole; + roleMap[QAccessible::RadioButton] = NSAccessibilityRadioButtonRole; + roleMap[QAccessible::CheckBox] = NSAccessibilityCheckBoxRole; + roleMap[QAccessible::StaticText] = NSAccessibilityStaticTextRole; + roleMap[QAccessible::Table] = NSAccessibilityTableRole; + roleMap[QAccessible::StatusBar] = NSAccessibilityStaticTextRole; + roleMap[QAccessible::Column] = NSAccessibilityColumnRole; + roleMap[QAccessible::ColumnHeader] = NSAccessibilityColumnRole; + roleMap[QAccessible::Row] = NSAccessibilityRowRole; + roleMap[QAccessible::RowHeader] = NSAccessibilityRowRole; + roleMap[QAccessible::Cell] = NSAccessibilityTextFieldRole; + roleMap[QAccessible::PushButton] = NSAccessibilityButtonRole; + roleMap[QAccessible::EditableText] = NSAccessibilityTextFieldRole; + roleMap[QAccessible::Link] = NSAccessibilityTextFieldRole; + roleMap[QAccessible::Indicator] = NSAccessibilityValueIndicatorRole; + roleMap[QAccessible::Splitter] = NSAccessibilitySplitGroupRole; + roleMap[QAccessible::List] = NSAccessibilityListRole; + roleMap[QAccessible::ListItem] = NSAccessibilityStaticTextRole; + roleMap[QAccessible::Cell] = NSAccessibilityStaticTextRole; +} + +/* + Returns a Mac accessibility role for the given interface, or + NSAccessibilityUnknownRole if no role mapping is found. +*/ +static NSString *macRoleForInterface(QAInterface interface) +{ + const QAccessible::Role qtRole = interface.role(); + QMacAccessibiltyRoleMap &roleMap = *qMacAccessibiltyRoleMap(); + + if (roleMap.isEmpty()) + populateRoleMap(); + + MAC_ACCESSIBILTY_DEBUG() << "role for" << interface.object() << "interface role" << hex << qtRole; + + if (roleMap.contains(qtRole)) { + MAC_ACCESSIBILTY_DEBUG() << "return" << roleMap[qtRole]; + return roleMap[qtRole]; + } + + MAC_ACCESSIBILTY_DEBUG() << "return NSAccessibilityUnknownRole"; + return NSAccessibilityUnknownRole; +} + +/* + Is the interface a QTabBar embedded in a QTabWidget? + (as opposed to a stand-alone tab bar) +*/ +static bool isEmbeddedTabBar(const QAInterface &interface) +{ + QObject *object = interface.object(); + if (interface.role() == QAccessible::PageTabList && object) + return (qobject_cast<QTabWidget *>(object->parent())); + + return false; +} + +static bool isInterfaceIgnored(QAInterface interface) +{ + // Mac accessibility does not have an attribute that corresponds to the + // Invisible/Offscreen state. Use the ignore facility to disable them. + const QAccessible::State state = interface.state(); + if (state & QAccessible::Invisible || + state & QAccessible::Offscreen ) + return false; + + // Hide QTabBars that has a QTabWidget parent (the QTabWidget handles the accessibility) + if (isEmbeddedTabBar(interface)) + return false; + + if (QObject * const object = interface.object()) { + const QString className = QLatin1String(object->metaObject()->className()); + + // Prevent VoiceOver from focusing on tool tips by ignoring those + // interfaces. Shifting VoiceOver focus to the tool tip is confusing + // and the contents of the tool tip is avalible through the description + // attribute anyway. + if (className == QLatin1String("QTipLabel")) + return false; + } + + // Hide interfaces with an unknown role. When developing it's often useful to disable + // this check to see all interfaces in the hierarchy. +#ifndef MAC_ACCESSIBILTY_DEVELOPER_MODE + return [macRoleForInterface(interface) isEqualToString: NSAccessibilityUnknownRole]; +#else + return NO; +#endif +} + +QT_END_NAMESPACE + +@implementation QT_MANGLE_NAMESPACE(QCocoaView) (Accessibility) + +- (BOOL)accessibilityIsIgnored +{ + QAInterface interface = interfaceForView(self); + return isInterfaceIgnored(interface); +} + +- (NSArray *)accessibilityAttributeNames +{ + QAInterface interface = interfaceForView(self); + + static NSArray *attributes = nil; + if (attributes == nil) { + attributes = [super accessibilityAttributeNames]; + + } + return attributes; +} + +- (id)accessibilityAttributeValue:(NSString *)attribute +{ + MAC_ACCESSIBILTY_DEBUG() << "accessibilityAttributeValue" << self << QCFString::toQString(reinterpret_cast<CFStringRef>(attribute)); + + QAInterface interface = interfaceForView(self); + + // Switch on the attribute name and call the appropriate handler function. + // Pass the call on to the NSView class for attributes we don't handle. + if ([attribute isEqualToString:@"AXRole"]) { + return macRoleForInterface(interface); + } else { + return [super accessibilityAttributeValue:attribute]; + } +} + +@end + +#endif // QT_MAC_USE_COCOA + +#endif // QT_NO_ACCESSIBILITY + diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 89d9d1b..ebdac9a 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -400,4 +400,15 @@ void QEglContext::dumpAllConfigs() delete [] configs; } +QString QEglContext::extensions() +{ + const char* exts = eglQueryString(dpy, EGL_EXTENSIONS); + return QString(QLatin1String(exts)); +} + +bool QEglContext::hasExtension(const char* extensionName) +{ + return extensions().contains(QLatin1String(extensionName)); +} + QT_END_NAMESPACE diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index ddf7d27..3ae1489 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -122,6 +122,9 @@ public: void dumpAllConfigs(); + QString extensions(); + bool hasExtension(const char* extensionName); + private: QEgl::API apiType; EGLDisplay dpy; diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 3884af9..eaf9896 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -135,38 +135,39 @@ \section1 Transformation - QGraphicsItem supports affine transformations in addition to its base - position, pos(). To change the item's transformation, you can pass - a transformation matrix to setTransform() - - Item transformations accumulate from parent to child, so if both a - parent and child item are rotated 90 degrees, the child's total - transformation will be 180 degrees. Similarly, if the item's - parent is scaled to 2x its original size, its children will also - be twice as large. An item's transformation does not affect its - own local geometry; all geometry functions (e.g., contains(), - update(), and all the mapping functions) still operate in local - coordinates. For convenience, QGraphicsItem provides the functions - sceneTransform(), which returns the item's total transformation + QGraphicsItem supports projective transformations in addition to its base + position, pos(). There are several ways to change an item's transformation. + For simple transformations, you can call either of the convenience + functions setRotation() or setScale(), or you can pass any transformation + matrix to setTransform(). For advanced transformation control you also have + the option of setting several combined transformations by calling + setTransformations(). + + Item transformations accumulate from parent to child, so if both a parent + and child item are rotated 90 degrees, the child's total transformation + will be 180 degrees. Similarly, if the item's parent is scaled to 2x its + original size, its children will also be twice as large. An item's + transformation does not affect its own local geometry; all geometry + functions (e.g., contains(), update(), and all the mapping functions) still + operate in local coordinates. For convenience, QGraphicsItem provides the + functions sceneTransform(), which returns the item's total transformation matrix (including its position and all parents' positions and - transformations), and scenePos(), which returns its position in - scene coordinates. To reset an item's matrix, call - resetTransform(). + transformations), and scenePos(), which returns its position in scene + coordinates. To reset an item's matrix, call resetTransform(). - Another way to apply transformation to an item is to use the , or - set the different transformation properties (transformOrigin, - x/y/zRotation, x/yScale, horizontal/verticalShear). Those - properties come in addition to the base transformation + Certain transformation operations produce a different outcome depending on + the order in which they are applied. For example, if you scale an + transform, and then rotate it, you may get a different result than if the + transform was rotated first. However, the order you set the transformation + properties on QGraphicsItem does not affect the resulting transformation; + QGraphicsItem always applies the properties in a fixed, defined order: - The order you set the transformation properties does not affect - the resulting transformation The resulting transformation is - always computed in the following order - - \code - [Origin] [Base] [RotateX] [RotateY] [RotateZ] [Shear] [Scale] [-Origin] - \endcode - - Where [Base] is the stransformation set by setTransform + \list + \o The item's base transform is applied (transform()) + \o The item's transformations list is applied in order (transformations()) + \o The item is rotated relative to its transform origin point (rotation(), transformOriginPoint()) + \o The item is scaled relative to its transform origin point (scale(), transformOriginPoint()) + \endlist \section1 Painting @@ -2969,11 +2970,10 @@ QMatrix QGraphicsItem::matrix() const Returns this item's transformation matrix. - Either the one set by setTransform, or the resulting transformation from - all the transfmation properties - - If no matrix or transformation property has been set, the - identity matrix is returned. + The transformation matrix is combined with the item's rotation(), scale() + and transformations() into a combined transformations for the item. + + The default transformation matrix is an identity matrix. \sa setTransform(), sceneTransform() */ @@ -2987,13 +2987,13 @@ QTransform QGraphicsItem::transform() const /*! \since 4.6 - Returns the rotation around the Z axis. - - The default is 0 + Returns the clockwise rotation, in degrees, around the Z axis. The default + value is 0 (i.e., the item is not rotated). - \warning The value doesn't take in account any rotation set with the setTransform() method. + The rotation is combined with the item's scale(), transform() and + transformations() to map the item's coordinate system to the parent item. - \sa setRotation(), {Transformations} + \sa setRotation(), transformOriginPoint(), {Transformations} */ qreal QGraphicsItem::rotation() const { @@ -3005,9 +3005,19 @@ qreal QGraphicsItem::rotation() const /*! \since 4.6 - Sets the rotation around the Z axis to \a angle degrees. + Sets the clockwise rotation \a angle, in degrees, around the Z axis. The + default value is 0 (i.e., the item is not rotated). Assigning a negative + value will rotate the item counter-clockwise. Normally the rotation angle + is in the range (-360, 360), but it's also possible to assign values + outside of this range (e.g., a rotation of 370 degrees is the same as a + rotation of 10 degrees). + + The item is rotated around its transform origin point, which by default + is (0, 0). You can select a different transformation origin by calling + setTransformOriginPoint(). - \warning The value doesn't take in account any rotation set with the setTransform() method. + The rotation is combined with the item's scale(), transform() and + transformations() to map the item's coordinate system to the parent item. \sa rotation(), setTransformOriginPoint(), {Transformations} */ @@ -3027,13 +3037,13 @@ void QGraphicsItem::setRotation(qreal angle) /*! \since 4.6 - Returns the scale factor of the item. + Returns the scale factor of the item. The default scale factor is 1.0 + (i.e., the item is not scaled). - The default is 1 + The scale is combined with the item's rotation(), transform() and + transformations() to map the item's coordinate system to the parent item. - \warning The value doesn't take in account any scaling set with the setTransform() method. - - \sa setScale(), {Transformations} + \sa setScale(), rotation(), {Transformations} */ qreal QGraphicsItem::scale() const { @@ -3045,9 +3055,17 @@ qreal QGraphicsItem::scale() const /*! \since 4.6 - Sets the scale factor of the item to \a factor. + Sets the scale \a factor of the item. The default scale factor is 1.0 + (i.e., the item is not scaled). A scale factor of 0.0 will collapse the + item to a single point. If you provide a negative scale factor, the + item will be flipped and mirrored (i.e., rotated 180 degrees). + + The item is scaled around its transform origin point, which by default + is (0, 0). You can select a different transformation origin by calling + setTransformOriginPoint(). - \warning The value doesn't take in account any scaling set with the setTransform() method. + The scale is combined with the item's rotation(), transform() and + transformations() to map the item's coordinate system to the parent item. \sa scale(), setTransformOriginPoint(), {Transformations} */ @@ -3068,9 +3086,17 @@ void QGraphicsItem::setScale(qreal factor) /*! \since 4.6 - returns list of graphics transformations on the item. + Returns a list of graphics transforms that currently apply to this item. - \sa scale(), setTransformOriginPoint(), {Transformations} + QGraphicsTransform is for applying and controlling a chain of individual + transformation operations on an item. It's particularily useful in + animations, where each transform operation needs to be interpolated + independently, or differently. + + The transformations are combined with the item's rotation(), scale() and + transform() to map the item's coordinate system to the parent item. + + \sa scale(), rotation(), transformOriginPoint(), {Transformations} */ QList<QGraphicsTransform *> QGraphicsItem::transformations() const { @@ -3082,7 +3108,20 @@ QList<QGraphicsTransform *> QGraphicsItem::transformations() const /*! \since 4.6 - Sets a list of graphics transformations on the item to \a transformations. + Sets a list of graphics \a transformations (QGraphicsTransform) that + currently apply to this item. + + If all you want is to rotate or scale an item, you should call setRotation() + or setScale() instead. If you want to set an arbitrary transformation on + an item, you can call setTransform(). + + QGraphicsTransform is for applying and controlling a chain of individual + transformation operations on an item. It's particularily useful in + animations, where each transform operation needs to be interpolated + independently, or differently. + + The transformations are combined with the item's rotation(), scale() and + transform() to map the item's coordinate system to the parent item. \sa scale(), setTransformOriginPoint(), {Transformations} */ @@ -3098,7 +3137,9 @@ void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transf d_ptr->dirtySceneTransform = 1; } - +/*! + \internal +*/ void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t) { if (!transformData) @@ -3432,7 +3473,9 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine) to map an item coordiate to a scene coordinate, or mapFromScene() to map from scene coordinates to item coordinates. - \warning using this function doesnt affect the value of the transformation properties + The transformation matrix is combined with the item's rotation(), scale() + and transformations() into a combined transformation that maps the item's + coordinate system to its parent. \sa transform(), setRotation(), setScale(), setTransformOriginPoint(), {The Graphics View Coordinate System}, {Transformations} */ @@ -3491,7 +3534,8 @@ void QGraphicsItem::resetTransform() /*! \obsolete - Use setZRotation() instead + + Use setRotation() instead Rotates the current item transformation \a angle degrees clockwise around its origin. To translate around an arbitrary point (x, y), you need to @@ -3501,8 +3545,6 @@ void QGraphicsItem::resetTransform() \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 6 - \warning using this functionhas no effect on the zRotation value - \sa setTransform(), transform(), scale(), shear(), translate() */ void QGraphicsItem::rotate(qreal angle) @@ -3512,6 +3554,7 @@ void QGraphicsItem::rotate(qreal angle) /*! \obsolete + Use setScale() instead Scales the current item transformation by (\a sx, \a sy) around its @@ -3522,8 +3565,6 @@ void QGraphicsItem::rotate(qreal angle) \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 7 - \warning using this function has no effect on the xScale or yScale value - \sa setTransform(), transform() */ void QGraphicsItem::scale(qreal sx, qreal sy) @@ -3533,11 +3574,10 @@ void QGraphicsItem::scale(qreal sx, qreal sy) /*! \obsolete - Use setShear instead. - Shears the current item transformation by (\a sh, \a sv). + Use setTransform() instead. - \warning using this function has no effect on the horizontalShear or verticalShear value + Shears the current item transformation by (\a sh, \a sv). \sa setTransform(), transform() */ @@ -3548,6 +3588,7 @@ void QGraphicsItem::shear(qreal sh, qreal sv) /*! \obsolete + Use setPos() or setTransformOriginPoint() instead. Translates the current item transformation by (\a dx, \a dy). diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index b8d98c1..5c3622b 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -468,7 +468,8 @@ public: QGraphicsItem *q_ptr; }; -struct QGraphicsItemPrivate::TransformData { +struct QGraphicsItemPrivate::TransformData +{ QTransform transform; qreal scale; qreal rotation; @@ -481,7 +482,7 @@ struct QGraphicsItemPrivate::TransformData { scale(1.0), rotation(0.0), xOrigin(0.0), yOrigin(0.0), onlyTransform(true) - {} + { } QTransform computedFullTransform(QTransform *postmultiplyTransform = 0) const { diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 3cb33d1..07d23b7 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -525,7 +525,7 @@ QGraphicsSceneBspTreeIndex::~QGraphicsSceneBspTreeIndex() } /*! - \reimp + \internal Clear the all the BSP index. */ void QGraphicsSceneBspTreeIndex::clear() @@ -566,7 +566,7 @@ void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) } /*! - \reimp + \internal Update the BSP when the \a item 's bounding rect has changed. */ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) @@ -682,7 +682,7 @@ void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) } /*! - \reimp + \internal This method react to the \a rect change of the scene and reset the BSP tree index. @@ -695,11 +695,10 @@ void QGraphicsSceneBspTreeIndex::updateSceneRect(const QRectF &rect) } /*! - \reimp + \internal This method react to the \a change of the \a item and use the \a value to update the BSP tree if necessary. - */ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) { diff --git a/src/gui/graphicsview/qgraphicstransform.cpp b/src/gui/graphicsview/qgraphicstransform.cpp index b55d78e..890aff7 100644 --- a/src/gui/graphicsview/qgraphicstransform.cpp +++ b/src/gui/graphicsview/qgraphicstransform.cpp @@ -39,6 +39,43 @@ ** ****************************************************************************/ +/*! + \class QGraphicsTransform + \brief The QGraphicsTransform class is an abstract base class for building + advanced transformations on QGraphicsItems. + \since 4.6 + + As an alternative to QGraphicsItem::transform, QGraphicsTransform lets you + create and control advanced transformations that can be configured + independently using specialized properties. + + QGraphicsItem allows you to assign any number of QGraphicsTransform + instances to one QGraphicsItem. Each QGraphicsTransform is applied in + order, one at a time, to the QGraphicsItem it's assigned to. + + QGraphicsTransform is particularily useful for animations. Whereas + QGraphicsItem::setTransform() lets you assign any transform directly to an + item, there is no direct way to interpolate between two different + transformations (e.g., when transitioning between two states, each for + which the item has a different arbitrary transform assigned). Using + QGraphicsTransform you can interpolate the property values of each + independent transformation. The resulting operation is then combined into a + single transform which is applied to QGraphicsItem. + + If you want to create your own configurable transformation, you can create + a subclass of QGraphicsTransform (or any or the existing subclasses), and + reimplement the pure virtual applyTo() function, which takes a pointer to a + QTransform. Each operation you would like to apply should be exposed as + properties (e.g., customTransform->setVerticalShear(2.5)). Inside you + reimplementation of applyTo(), you can modify the provided transform + respectively. + + QGraphicsTransform can be used together with QGraphicsItem::setTransform(), + QGraphicsItem::setRotation(), and QGraphicsItem::setScale(). + + \sa QGraphicsItem::transform(), QGraphicsScale, QGraphicsRotation, QGraphicsRotation3D +*/ + #include "qgraphicstransform.h" #include "qgraphicsitem_p.h" #include "qgraphicstransform_p.h" @@ -51,7 +88,6 @@ QT_BEGIN_NAMESPACE - void QGraphicsTransformPrivate::setItem(QGraphicsItem *i) { if (item == i) @@ -77,15 +113,38 @@ void QGraphicsTransformPrivate::updateItem(QGraphicsItem *item) item->d_ptr->dirtySceneTransform = 1; } -void QGraphicsTransform::update() +/*! + Constructs a new QGraphicsTransform with the given \a parent. +*/ +QGraphicsTransform::QGraphicsTransform(QObject *parent) + : QObject(*new QGraphicsTransformPrivate, parent) +{ +} + +/*! + Destroys the graphics transform. +*/ +QGraphicsTransform::~QGraphicsTransform() { Q_D(QGraphicsTransform); - if (d->item) - d->updateItem(d->item); + d->setItem(0); +} + +/*! + \internal +*/ +QGraphicsTransform::QGraphicsTransform(QGraphicsTransformPrivate &p, QObject *parent) + : QObject(p, parent) +{ } /*! - returns this object as a QTransform. + Applies this transformation to an identity transform, and returns the + resulting transform. + + This is equivalent to passing an identity transform to applyTo(). + + \sa applyTo() */ QTransform QGraphicsTransform::transform() const { @@ -95,76 +154,65 @@ QTransform QGraphicsTransform::transform() const } /*! - \class QGraphicsTransform - \brief The QGraphicsTransform class is an abstract base class for tranformations on QGraphicsItems. - \since 4.6 - - The classes that inherit QGraphicsTransform express different types of transformations - that can be applied to graphics items. + \fn void QGraphicsTransform::applyTo(QTransform *transform) const - A list of these transformations can be applied to any graphics item. These - transformations are then easily modifyable and usable from e.g. within animations. + This pure virtual method has to be reimplemented in derived classes. - QGraphicsTransform is an abstract base class that is implemented by QGraphicsScale, - QGraphicsRotation and QGraphicsRotation3D. Subclasses have to implement the applyTo method. + It applies this transformation to \a transform. - \sa QGraphicsItem::transform(), QGraphicsScale, QGraphicsRotation, QGraphicsRotation3D + \sa QGraphicsItem::transform() */ /*! - Constructs a new QGraphicsTransform with \a parent. -*/ -QGraphicsTransform::QGraphicsTransform(QObject *parent) : - QObject(*new QGraphicsTransformPrivate, parent) -{ -} + Notifies that this transform operation has changed its parameters in such a + way that applyTo() will return a different result than before. -/*! - Destructs the graphics transform. + When implementing you own custom graphics transform, you must call this + function every time you change a parameter, to let QGraphicsItem know that + its transformation needs to be updated. + + \sa applyTo() */ -QGraphicsTransform::~QGraphicsTransform() +void QGraphicsTransform::update() { Q_D(QGraphicsTransform); - d->setItem(0); + if (d->item) + d->updateItem(d->item); } /*! - \internal -*/ -QGraphicsTransform::QGraphicsTransform(QGraphicsTransformPrivate &p, QObject *parent) - : QObject(p, parent) -{ -} - -/*! \fn void QGraphicsTransform::applyTo(QTransform *transform) const + \class QGraphicsScale + \brief The QGraphicsScale class provides a scale transformation. + \since 4.6 - This pure virtual method has to be reimplemented in derived classes. + QGraphicsScene provides certain parameters to help control how the scale + should be applied. - It applies this transformation to \a transform. -*/ + The origin is the point that the item is scaled from (i.e., it stays fixed + relative to the parent as the rest of the item grows). By default the + origin is QPointF(0, 0). + The two parameters xScale and yScale describe the scale factors to apply in + horizontal and vertical direction. They can take on any value, including 0 + (to collapse the item to a point) or negativate value. A negative xScale + value will mirror the item horizontally. A negative yScale value will flip + the item vertically. -/*! - \class QGraphicsScale - \brief The QGraphicsScale class provides a way to scale a graphics item in 2 dimensions. - \since 4.6 - - QGraphicsScale contains an \a origin around which the scaling happens, and two - scale factors, xScale and yScale, the x and one for the y axis. + \sa QGraphicsTransform, QGraphicsItem::setScale(), QTransform::scale() */ class QGraphicsScalePrivate : public QGraphicsTransformPrivate { public: QGraphicsScalePrivate() - : xScale(1), yScale(1) {} + : xScale(1), yScale(1) {} QPointF origin; qreal xScale; qreal yScale; }; /*! - Constructs a new graphics scale object with \a parent. + Constructs an empty QGraphicsScale object with the given \a parent. */ QGraphicsScale::QGraphicsScale(QObject *parent) : QGraphicsTransform(*new QGraphicsScalePrivate, parent) @@ -172,24 +220,26 @@ QGraphicsScale::QGraphicsScale(QObject *parent) } /*! - Destroys the object + Destroys the graphics scale. */ QGraphicsScale::~QGraphicsScale() { } /*! - \property QGraphicsScale::origin - The origin of the scale. All scaling will be done relative to this point. + \property QGraphicsScale::origin + \brief The QGraphicsScene class provides the origin of the scale. + + All scaling will be done relative to this point (i.e., this point + will stay fixed, relative to the parent, when the item is scaled). - The \a origin is in other words the fixed point for the transformation. + \sa xScale, yScale */ QPointF QGraphicsScale::origin() const { Q_D(const QGraphicsScale); return d->origin; } - void QGraphicsScale::setOrigin(const QPointF &point) { Q_D(QGraphicsScale); @@ -199,26 +249,21 @@ void QGraphicsScale::setOrigin(const QPointF &point) } /*! - \fn QGraphicsScale::originChanged() - - This signal is emitted whenever the origin of the object - changes. -*/ - -/*! - \property QGraphicsScale::xScale + \property QGraphicsScale::xScale + \brief the horizontal scale factor. - The scale factor in x direction. The x direction is - in the graphics items logical coordinates. + The scale factor can be any real number; the default value is 1.0. If you + set the factor to 0.0, the item will be collapsed to a single point. If you + provide a negative value, the item will be mirrored horizontally around its + origin. - \sa yScale + \sa yScale, origin */ qreal QGraphicsScale::xScale() const { Q_D(const QGraphicsScale); return d->xScale; } - void QGraphicsScale::setXScale(qreal scale) { Q_D(QGraphicsScale); @@ -230,19 +275,21 @@ void QGraphicsScale::setXScale(qreal scale) } /*! - \property QGraphicsScale::yScale + \property QGraphicsScale::yScale + \brief the vertical scale factor. - The scale factor in y direction. The y direction is - in the graphics items logical coordinates. + The scale factor can be any real number; the default value is 1.0. If you + set the factor to 0.0, the item will be collapsed to a single point. If you + provide a negative value, the item will be flipped vertically around its + origin. - \sa xScale + \sa xScale, origin */ qreal QGraphicsScale::yScale() const { Q_D(const QGraphicsScale); return d->yScale; } - void QGraphicsScale::setYScale(qreal scale) { Q_D(QGraphicsScale); @@ -254,14 +301,7 @@ void QGraphicsScale::setYScale(qreal scale) } /*! - \fn QGraphicsScale::scaleChanged() - - This signal is emitted whenever the xScale or yScale of the object - changes. -*/ - -/*! - \reimp + \reimp */ void QGraphicsScale::applyTo(QTransform *transform) const { @@ -272,12 +312,41 @@ void QGraphicsScale::applyTo(QTransform *transform) const } /*! - \class QGraphicsRotation - \brief The QGraphicsRotation class provides a way to rotate a graphics item in 2 dimensions. - \since 4.6 + \fn QGraphicsScale::originChanged() + + QGraphicsScale emits this signal when its origin changes. + + \sa QGraphicsScale::origin +*/ + +/*! + \fn QGraphicsScale::scaleChanged() + + This signal is emitted whenever the xScale or yScale of the object + changes. - QGraphicsRotation contains an \a origin around which the rotation happens, and one - angle in degrees describing the amount of the rotation. + \sa QGraphicsScale::xScale, QGraphicsScale::yScale +*/ + +/*! + \class QGraphicsRotation + \brief The QGraphicsRotation class provides a rotation transformation. + \since 4.6 + + QGraphicsRotation provides certain parameters to help control how the + rotation should be applied. + + The origin is the point that the item is rotated around (i.e., it stays + fixed relative to the parent as the rest of the item is rotated). By + default the origin is QPointF(0, 0). + + The angle property provides the number of degrees to rotate the item + clockwise around the origin. This value also be negative, indicating a + counter-clockwise rotation. For animation purposes it may also be useful to + provide rotation angles exceeding (-360, 360) degrees, for instance to + animate how an item rotates several times. + + \sa QGraphicsTransform, QGraphicsItem::setRotation(), QTransform::rotate() */ class QGraphicsRotationPrivate : public QGraphicsTransformPrivate @@ -291,7 +360,7 @@ public: }; /*! - Constructs a new graphics rotation with \a parent. + Constructs a new QGraphicsRotation with the given \a parent. */ QGraphicsRotation::QGraphicsRotation(QObject *parent) : QGraphicsTransform(*new QGraphicsRotationPrivate, parent) @@ -299,7 +368,7 @@ QGraphicsRotation::QGraphicsRotation(QObject *parent) } /*! - \internal + \internal */ QGraphicsRotation::QGraphicsRotation(QGraphicsRotationPrivate &p, QObject *parent) : QGraphicsTransform(p, parent) @@ -307,24 +376,26 @@ QGraphicsRotation::QGraphicsRotation(QGraphicsRotationPrivate &p, QObject *paren } /*! - Destructs the object + Destroys the graphics rotation. */ QGraphicsRotation::~QGraphicsRotation() { } /*! - \property QGraphicsRotation::origin - The origin around which this object will rotate the graphics item. + \property QGraphicsRotation::origin + \brief the origin of the rotation. - The \a origin is in other words the fixed point for the transformation. + All rotations will be done relative to this point (i.e., this point + will stay fixed, relative to the parent, when the item is rotated). + + \sa angle */ QPointF QGraphicsRotation::origin() const { Q_D(const QGraphicsRotation); return d->origin; } - void QGraphicsRotation::setOrigin(const QPointF &point) { Q_D(QGraphicsRotation); @@ -334,22 +405,22 @@ void QGraphicsRotation::setOrigin(const QPointF &point) } /*! - \fn QGraphicsRotation::originChanged() + \property QGraphicsRotation::angle + \brief the angle for clockwise rotation, in degrees. - This signal is emitted whenever the origin of the object - changes. -*/ + The angle can be any real number; the default value is 0.0. A value of 180 + will rotate 180 degrees, clockwise. If you provide a negative number, the + item will be rotated counter-clockwise. Normally the rotation angle will be + in the range (-360, 360), but you can also provide numbers outside of this + range (e.g., a angle of 370 degrees gives the same result as 10 degrees). -/*! - \property QGraphicsRotation::angle - The angle, in degrees, of the rotation. + \sa origin */ qreal QGraphicsRotation::angle() const { Q_D(const QGraphicsRotation); return d->angle; } - void QGraphicsRotation::setAngle(qreal angle) { Q_D(QGraphicsRotation); @@ -361,33 +432,50 @@ void QGraphicsRotation::setAngle(qreal angle) } /*! - \fn void QGraphicsRotation::angleChanged() - - This signal is emitted whenever the angle of the object - changes. -*/ - -/*! - \reimp + \reimp */ void QGraphicsRotation::applyTo(QTransform *t) const { Q_D(const QGraphicsRotation); - if(d->angle) { + if (d->angle) { t->translate(d->origin.x(), d->origin.y()); t->rotate(d->angle); t->translate(-d->origin.x(), -d->origin.y()); } } +/*! + \fn QGraphicsRotation::originChanged() + + This signal is emitted whenever the origin has changed. + + \sa QGraphicsRotation::origin +*/ /*! - \class QGraphicsRotation3D - \brief The QGraphicsRotation3D class provides a way to rotate a graphics item in 3 dimensions. - \since 4.6 + \fn void QGraphicsRotation::angleChanged() - In addition to the origin and angle of a simple QGraphicsRotation, QGraphicsRotation3D contains - also an axis that describes around which axis in space the rotation is supposed to happen. + This signal is emitted whenever the angle has changed. + + \sa QGraphicsRotation::angle +*/ + +/*! + \class QGraphicsRotation3D + \brief The QGraphicsRotation3D class provides rotation in 3 dimensions. + \since 4.6 + + QGraphicsRotation3D extends QGraphicsRotation with the ability to rotate + around a given axis. + + You can provide the desired axis by assigning a QVector3D to the axis + property. The angle property, which is provided by QGraphicsRotation, now + describes the number of degrees to rotate around this axis. + + By default the axis is (0, 0, 1), giving QGraphicsRotation3D the same + default behavior as QGraphicsRotation (i.e., rotation around the Z axis). + + \sa QGraphicsTransform, QGraphicsItem::setRotation(), QTransform::rotate() */ class QGraphicsRotation3DPrivate : public QGraphicsRotationPrivate @@ -399,7 +487,7 @@ public: }; /*! - Constructs a new 3D rotation with \a parent. + Constructs a new QGraphicsRotation3D with the given \a parent. */ QGraphicsRotation3D::QGraphicsRotation3D(QObject *parent) : QGraphicsRotation(*new QGraphicsRotation3DPrivate, parent) @@ -407,7 +495,7 @@ QGraphicsRotation3D::QGraphicsRotation3D(QObject *parent) } /*! - Destroys the object + Destroys the 3D graphics rotation. */ QGraphicsRotation3D::~QGraphicsRotation3D() { @@ -415,15 +503,22 @@ QGraphicsRotation3D::~QGraphicsRotation3D() /*! \property QGraphicsRotation3D::axis + \brief a rotation axis, specified by a vector in 3D space. + + This can be any axis in 3D space. By default the axis is (0, 0, 1), + which is aligned with the Z axis and provides the same behavior + for the rotation angle as QGraphicsRotation. If you provide another + axis, QGraphicsRotation3D will provide a transformation that rotates + around this axis. For example, if you would like to rotate an item + around its X axis, you could pass (1, 0, 0) as the axis. - A rotation axis is specified by a vector in 3D space. + \sa QTransform, QGraphicsRotation::angle */ QVector3D QGraphicsRotation3D::axis() { Q_D(QGraphicsRotation3D); return d->axis; } - void QGraphicsRotation3D::setAxis(const QVector3D &axis) { Q_D(QGraphicsRotation3D); @@ -431,17 +526,10 @@ void QGraphicsRotation3D::setAxis(const QVector3D &axis) update(); } -/*! - \fn void QGraphicsRotation3D::axisChanged() - - This signal is emitted whenever the axis of the object - changes. -*/ - -const qreal inv_dist_to_plane = 1. / 1024.; +static const qreal inv_dist_to_plane = 1. / 1024.; /*! - \reimp + \reimp */ void QGraphicsRotation3D::applyTo(QTransform *t) const { @@ -474,6 +562,12 @@ void QGraphicsRotation3D::applyTo(QTransform *t) const t->translate(-d->origin.x(), -d->origin.y()); } +/*! + \fn void QGraphicsRotation3D::axisChanged() + + This signal is emitted whenever the axis of the object changes. +*/ + #include "moc_qgraphicstransform.cpp" QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicstransform.h b/src/gui/graphicsview/qgraphicstransform.h index b5d8d84..d7c07d0 100644 --- a/src/gui/graphicsview/qgraphicstransform.h +++ b/src/gui/graphicsview/qgraphicstransform.h @@ -70,6 +70,7 @@ protected Q_SLOTS: protected: QGraphicsTransform(QGraphicsTransformPrivate &p, QObject *parent); + private: friend class QGraphicsItem; friend class QGraphicsItemPrivate; diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index bf348af..b9c36dc 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -25,7 +25,9 @@ HEADERS += \ image/qpixmapcache_p.h \ image/qpixmapdata_p.h \ image/qpixmapdatafactory_p.h \ - image/qpixmapfilter_p.h + image/qpixmapfilter_p.h \ + image/qimagepixmapcleanuphooks_p.h \ + SOURCES += \ image/qbitmap.cpp \ @@ -47,6 +49,8 @@ SOURCES += \ image/qmovie.cpp \ image/qpixmap_raster.cpp \ image/qnativeimage.cpp \ + image/qimagepixmapcleanuphooks.cpp \ + win32 { SOURCES += image/qpixmap_win.cpp diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index e8ca7a9..bb77fb5 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -49,6 +49,7 @@ #include "qimagewriter.h" #include "qstringlist.h" #include "qvariant.h" +#include "qimagepixmapcleanuphooks_p.h" #include <ctype.h> #include <stdlib.h> #include <limits.h> @@ -106,14 +107,6 @@ static inline bool checkPixelSize(const QImage::Format format) } -// ### Qt 5: remove -typedef void (*_qt_image_cleanup_hook)(int); -Q_GUI_EXPORT _qt_image_cleanup_hook qt_image_cleanup_hook = 0; - -// ### Qt 5: rename -typedef void (*_qt_image_cleanup_hook_64)(qint64); -Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64 = 0; - static QImage rotated90(const QImage &src); static QImage rotated180(const QImage &src); static QImage rotated270(const QImage &src); @@ -257,8 +250,8 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu QImageData::~QImageData() { - if (is_cached && qt_image_cleanup_hook_64) - qt_image_cleanup_hook_64((((qint64) ser_no) << 32) | ((qint64) detach_no)); + if (is_cached) + QImagePixmapCleanupHooks::executeImageHooks((((qint64) ser_no) << 32) | ((qint64) detach_no)); delete paintEngine; if (data && own_data) free(data); @@ -1342,8 +1335,8 @@ QImage::operator QVariant() const void QImage::detach() { if (d) { - if (d->is_cached && qt_image_cleanup_hook_64 && d->ref == 1) - qt_image_cleanup_hook_64(cacheKey()); + if (d->is_cached && d->ref == 1) + QImagePixmapCleanupHooks::executeImageHooks(cacheKey()); if (d->ref != 1 || d->ro_data) *this = copy(); diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp new file mode 100644 index 0000000..7d1c5fb --- /dev/null +++ b/src/gui/image/qimagepixmapcleanuphooks.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qimagepixmapcleanuphooks_p.h" +#include "qpixmapdata_p.h" + + +// Legacy, single instance hooks: ### Qt 5: remove +typedef void (*_qt_pixmap_cleanup_hook)(int); +typedef void (*_qt_pixmap_cleanup_hook_64)(qint64); +typedef void (*_qt_image_cleanup_hook)(int); +Q_GUI_EXPORT _qt_pixmap_cleanup_hook qt_pixmap_cleanup_hook = 0; +Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64 = 0; +Q_GUI_EXPORT _qt_image_cleanup_hook qt_image_cleanup_hook = 0; +Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64 = 0; + + +QImagePixmapCleanupHooks* qt_image_and_pixmap_cleanup_hooks = 0; + + +QImagePixmapCleanupHooks::QImagePixmapCleanupHooks() +{ + qt_image_and_pixmap_cleanup_hooks = this; +} + +QImagePixmapCleanupHooks *QImagePixmapCleanupHooks::instance() +{ + if (!qt_image_and_pixmap_cleanup_hooks) + qt_image_and_pixmap_cleanup_hooks = new QImagePixmapCleanupHooks; + return qt_image_and_pixmap_cleanup_hooks; +} + +void QImagePixmapCleanupHooks::addPixmapHook(_qt_pixmap_cleanup_hook_pm hook) +{ + pixmapHooks.append(hook); +} + +void QImagePixmapCleanupHooks::addImageHook(_qt_image_cleanup_hook_64 hook) +{ + imageHooks.append(hook); +} + +void QImagePixmapCleanupHooks::removePixmapHook(_qt_pixmap_cleanup_hook_pm hook) +{ + pixmapHooks.removeAll(hook); +} + +void QImagePixmapCleanupHooks::removeImageHook(_qt_image_cleanup_hook_64 hook) +{ + imageHooks.removeAll(hook); +} + + +void QImagePixmapCleanupHooks::executePixmapHooks(QPixmap* pm) +{ + for (int i = 0; i < qt_image_and_pixmap_cleanup_hooks->pixmapHooks.count(); ++i) + qt_image_and_pixmap_cleanup_hooks->pixmapHooks[i](pm); + + if (qt_pixmap_cleanup_hook_64) + qt_pixmap_cleanup_hook_64(pm->cacheKey()); +} + + +void QImagePixmapCleanupHooks::executeImageHooks(qint64 key) +{ + for (int i = 0; i < qt_image_and_pixmap_cleanup_hooks->imageHooks.count(); ++i) + qt_image_and_pixmap_cleanup_hooks->imageHooks[i](key); + + if (qt_image_cleanup_hook_64) + qt_image_cleanup_hook_64(key); +} + diff --git a/src/gui/painting/qregion_wince.cpp b/src/gui/image/qimagepixmapcleanuphooks_p.h index 9c33123..e765e69 100644 --- a/src/gui/painting/qregion_wince.cpp +++ b/src/gui/image/qimagepixmapcleanuphooks_p.h @@ -39,81 +39,51 @@ ** ****************************************************************************/ -#include "qatomic.h" -#include "qbitmap.h" -#include "qbuffer.h" -#include "qimage.h" -#include "qpolygon.h" -#include "qregion.h" -#include "qt_windows.h" -#include "qpainterpath.h" -#include "qguifunctions_wince.h" +#ifndef QIMAGEPIXMAP_CLEANUPHOOKS_P_H +#define QIMAGEPIXMAP_CLEANUPHOOKS_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/qpixmap.h> QT_BEGIN_NAMESPACE -QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 }; +typedef void (*_qt_image_cleanup_hook_64)(qint64); +typedef void (*_qt_pixmap_cleanup_hook_pm)(QPixmap*); -HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom) -{ - const int tries = 10; - for (int i = 0; i < tries; ++i) { - HRGN region; - switch (type) { - case QRegion::Rectangle: - region = CreateRectRgn(left, top, right, bottom); - break; - case QRegion::Ellipse: -#ifndef Q_OS_WINCE - region = CreateEllipticRgn(left, top, right, bottom); -#endif - break; - } - if (region) { - if (GetRegionData(region, 0, 0)) - return region; - else - DeleteObject(region); - } - } - return 0; -} +class QImagePixmapCleanupHooks; +extern QImagePixmapCleanupHooks* qt_image_and_pixmap_cleanup_hooks; -void qt_win_dispose_rgn(HRGN r) +class Q_GUI_EXPORT QImagePixmapCleanupHooks { - if (r) - DeleteObject(r); -} +public: + QImagePixmapCleanupHooks(); -static void qt_add_rect(HRGN &winRegion, QRect r) -{ - HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); - if (rgn) { - HRGN dest = CreateRectRgn(0,0,0,0); - int result = CombineRgn(dest, winRegion, rgn, RGN_OR); - if (result) { - DeleteObject(winRegion); - winRegion = dest; - } - } -} + static QImagePixmapCleanupHooks *instance(); -void QRegion::ensureHandle() const -{ - if (d->rgn) - DeleteObject(d->rgn); - d->rgn = CreateRectRgn(0,0,0,0); - if (d->qt_rgn) { - if (d->qt_rgn->numRects == 1) { - QRect r = d->qt_rgn->extents; - qt_add_rect(d->rgn, r); - return; - } - for (int i = 0;i < d->qt_rgn->numRects;i++) { - QRect r = d->qt_rgn->rects.at(i); - qt_add_rect(d->rgn, r); - } - } -} + void addPixmapHook(_qt_pixmap_cleanup_hook_pm); + void addImageHook(_qt_image_cleanup_hook_64); + + void removePixmapHook(_qt_pixmap_cleanup_hook_pm); + void removeImageHook(_qt_image_cleanup_hook_64); + static void executePixmapHooks(QPixmap*); + static void executeImageHooks(qint64 key); + +private: + QList<_qt_image_cleanup_hook_64> imageHooks; + QList<_qt_pixmap_cleanup_hook_pm> pixmapHooks; +}; QT_END_NAMESPACE + +#endif // QIMAGEPIXMAP_CLEANUPHOOKS_P_H diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 18829f4..82835d5 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -43,6 +43,7 @@ #include "qpixmap.h" #include "qpixmapdata_p.h" +#include "qimagepixmapcleanuphooks_p.h" #include "qbitmap.h" #include "qcolormap.h" @@ -81,14 +82,6 @@ QT_BEGIN_NAMESPACE // ### Qt 5: remove -typedef void (*_qt_pixmap_cleanup_hook)(int); -Q_GUI_EXPORT _qt_pixmap_cleanup_hook qt_pixmap_cleanup_hook = 0; - -// ### Qt 5: rename -typedef void (*_qt_pixmap_cleanup_hook_64)(qint64); -Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64 = 0; - -// ### Qt 5: remove Q_GUI_EXPORT qint64 qt_pixmap_id(const QPixmap &pixmap) { return pixmap.cacheKey(); @@ -656,7 +649,7 @@ void QPixmap::resize_helper(const QSize &s) QX11PixmapData *x11Data = data->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(data) : 0; if (x11Data) { pm.x11SetScreen(x11Data->xinfo.screen()); - uninit = x11Data->uninit; + uninit = x11Data->flags & QX11PixmapData::Uninitialized; } #elif defined(Q_WS_MAC) QMacPixmapData *macData = data->classId() == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data) : 0; @@ -1357,8 +1350,8 @@ bool QPixmap::isDetached() const void QPixmap::deref() { if (data && !data->ref.deref()) { // Destroy image if last ref - if (data->is_cached && qt_pixmap_cleanup_hook_64) - qt_pixmap_cleanup_hook_64(cacheKey()); + if (data->is_cached) + QImagePixmapCleanupHooks::executePixmapHooks(this); delete data; data = 0; } @@ -1897,9 +1890,6 @@ int QPixmap::defaultDepth() #endif } -typedef void (*_qt_pixmap_cleanup_hook_64)(qint64); -extern _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64; - /*! Detaches the pixmap from shared pixmap data. @@ -1925,8 +1915,8 @@ void QPixmap::detach() rasterData->image.detach(); } - if (data->is_cached && qt_pixmap_cleanup_hook_64 && data->ref == 1) - qt_pixmap_cleanup_hook_64(cacheKey()); + if (data->is_cached && data->ref == 1) + QImagePixmapCleanupHooks::executePixmapHooks(this); #if defined(Q_WS_MAC) QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data) : 0; @@ -1946,7 +1936,7 @@ void QPixmap::detach() #if defined(Q_WS_X11) if (data->classId() == QPixmapData::X11Class) { QX11PixmapData *d = static_cast<QX11PixmapData*>(data); - d->uninit = false; + d->flags &= ~QX11PixmapData::Uninitialized; // reset the cache data if (d->hd2) { diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp index 86cf515..be3d070 100644 --- a/src/gui/image/qpixmap_x11.cpp +++ b/src/gui/image/qpixmap_x11.cpp @@ -313,7 +313,7 @@ int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0; QX11PixmapData::QX11PixmapData(PixelType type) : QPixmapData(type, X11Class), hd(0), - uninit(true), read_only(false), x11_mask(0), picture(0), mask_picture(0), hd2(0), + flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0), gl_surface(0), share_mode(QPixmap::ImplicitlyShared), pengine(0) { } @@ -1217,7 +1217,7 @@ void QX11PixmapData::release() XFreePixmap(xinfo.display(), hd2); hd2 = 0; } - if (!read_only) + if (!(flags & Readonly)) XFreePixmap(xinfo.display(), hd); hd = 0; } @@ -1876,7 +1876,7 @@ QPixmap QX11PixmapData::transformed(const QTransform &transform, } else { // color pixmap QPixmap pm; QX11PixmapData *x11Data = static_cast<QX11PixmapData*>(pm.data); - x11Data->uninit = false; + x11Data->flags &= ~QX11PixmapData::Uninitialized; x11Data->xinfo = xinfo; x11Data->d = d; x11Data->w = w; @@ -2018,7 +2018,7 @@ QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h) QPixmap pm(data); - data->uninit = false; + data->flags &= ~QX11PixmapData::Uninitialized; pm.x11SetScreen(scr); GC gc = XCreateGC(dpy, pm.handle(), 0, 0); @@ -2060,7 +2060,7 @@ QPaintEngine* QX11PixmapData::paintEngine() const { QX11PixmapData *that = const_cast<QX11PixmapData*>(this); - if (read_only && share_mode == QPixmap::ImplicitlyShared) { + if ((flags & Readonly) && share_mode == QPixmap::ImplicitlyShared) { // if someone wants to draw onto us, copy the shared contents // and turn it into a fully fledged QPixmap ::Pixmap hd_copy = XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()), @@ -2082,7 +2082,7 @@ QPaintEngine* QX11PixmapData::paintEngine() const XFreeGC(X11->display, gc); } that->hd = hd_copy; - that->read_only = false; + that->flags &= ~QX11PixmapData::Readonly; } if (!that->pengine) @@ -2133,7 +2133,7 @@ void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect) setSerialNumber(++qt_pixmap_serial); - uninit = false; + flags &= ~Uninitialized; xinfo = x11Data->xinfo; d = x11Data->d; w = rect.width(); @@ -2201,7 +2201,7 @@ void QX11PixmapData::convertToARGB32(bool preserveContents) return; // Q_ASSERT(count == 1); - if (read_only && share_mode == QPixmap::ExplicitlyShared) + if ((flags & Readonly) && share_mode == QPixmap::ExplicitlyShared) return; Pixmap pm = XCreatePixmap(X11->display, RootWindow(X11->display, xinfo.screen()), @@ -2211,10 +2211,10 @@ void QX11PixmapData::convertToARGB32(bool preserveContents) if (picture) { if (preserveContents) XRenderComposite(X11->display, PictOpSrc, picture, 0, p, 0, 0, 0, 0, 0, 0, w, h); - if (!read_only) + if (!(flags & Readonly)) XRenderFreePicture(X11->display, picture); } - if (hd && !read_only) + if (hd && !(flags & Readonly)) XFreePixmap(X11->display, hd); if (x11_mask) { XFreePixmap(X11->display, x11_mask); @@ -2252,9 +2252,8 @@ QPixmap QPixmap::fromX11Pixmap(Qt::HANDLE pixmap, QPixmap::ShareMode mode) QX11PixmapData *data = new QX11PixmapData(depth == 1 ? QPixmapData::BitmapType : QPixmapData::PixmapType); data->setSerialNumber(++qt_pixmap_serial); - data->read_only = true; + data->flags = QX11PixmapData::Readonly; data->share_mode = mode; - data->uninit = false; data->w = width; data->h = height; data->is_null = (width <= 0 || height <= 0); diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h index 3de9a0f..835fea4 100644 --- a/src/gui/image/qpixmap_x11_p.h +++ b/src/gui/image/qpixmap_x11_p.h @@ -99,6 +99,7 @@ private: friend class QX11PaintEngine; friend class QX11WindowSurface; friend class QRasterWindowSurface; + friend class QGLContextPrivate; // Needs to access xinfo, gl_surface & flags void release(); @@ -108,14 +109,21 @@ private: Qt::HANDLE hd; - uint uninit : 1; - uint read_only : 1; + enum Flag { + NoFlags = 0x0, + Uninitialized = 0x1, + Readonly = 0x2, + InvertedWhenBoundToTexture = 0x4, + GlSurfaceCreatedWithAlpha = 0x8 + }; + uint flags; QX11Info xinfo; Qt::HANDLE x11_mask; Qt::HANDLE picture; Qt::HANDLE mask_picture; Qt::HANDLE hd2; // sorted in the default display depth + Qt::HANDLE gl_surface; #ifndef QT_NO_XRENDER void convertToARGB32(bool preserveContents = true); #endif diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index 29dafaf..32b419e 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -116,6 +116,7 @@ private: friend class QPixmap; friend class QGLContextPrivate; friend class QX11PixmapData; + friend class QGLTextureCache; //Needs to check the reference count QAtomicInt ref; int detach_no; diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 5181689..e210556 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -179,11 +179,11 @@ QApplicationPrivate::~QApplicationPrivate() QApplication contains the main event loop, where all events from the window system and other sources are processed and dispatched. It also handles the - application's initialization and finalization, and provides session - management. In addition, it handles most system-wide and application-wide - settings. + application's initialization, finalization, and provides session + management. In addition, QApplication handles most of the system-wide and + application-wide settings. - For any GUI application using Qt, there is precisely one QApplication + For any GUI application using Qt, there is precisely \bold one QApplication object, no matter whether the application has 0, 1, 2 or more windows at any given time. For non-GUI Qt applications, use QCoreApplication instead, as it does not depend on the \l QtGui library. @@ -239,9 +239,9 @@ QApplicationPrivate::~QApplicationPrivate() saveState() for details. \endlist - The QApplication object does so much initialization. Hence, it \e{must} be + Since the QApplication object does so much initialization, it \e{must} be created before any other objects related to the user interface are created. - Since QApplication also deals with common command line arguments, it is + QApplication also deals with common command line arguments. Hence, it is usually a good idea to create it \e before any interpretation or modification of \c argv is done in the application itself. @@ -673,9 +673,9 @@ QApplication::QApplication(int &argc, char **argv, int _internal) On X11, the window system is initialized if \a GUIenabled is true. If \a GUIenabled is false, the application does not connect to the X server. - On Windows and Macintosh, currently the window system is always - initialized, regardless of the value of GUIenabled. This may change in - future versions of Qt. + On Windows and Mac OS, currently the window system is always initialized, + regardless of the value of GUIenabled. This may change in future versions + of Qt. The following example shows how to create an application that uses a graphical interface when available. @@ -1194,21 +1194,22 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis \since 4.4 \brief defines a threshold for auto maximizing widgets - The auto maximize threshold is only available as part of Qt for Windows CE. + \bold{The auto maximize threshold is only available as part of Qt for + Windows CE.} This property defines a threshold for the size of a window as a percentage of the screen size. If the minimum size hint of a window exceeds the - threshold, calling show() will then cause the window to be maximized + threshold, calling show() will cause the window to be maximized automatically. - Setting the threshold to be 100 or greater means that it will cause it to - always be maximized. Setting it to be 50 means that the widget is maximized - if the vertical minimum size hint is at least 50% of the vertical screen - size. + Setting the threshold to 100 or greater means that the widget will always + be maximized. Alternatively, setting the threshold to 50 means that the + widget will be maximized only if the vertical minimum size hint is at least + 50% of the vertical screen size. - If -1 is specified then this will disable the feature. + Setting the threshold to -1 disables the feature. - On Windows CE the default is -1 (i.e. it is disabled). + On Windows CE the default is -1 (i.e., it is disabled). On Windows Mobile the default is 40. */ @@ -1217,9 +1218,9 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis \since 4.5 \brief toggles automatic SIP (software input panel) visibility - The auto SIP property is only available as part of Qt for Windows CE. + \bold{The auto SIP property is only available as part of Qt for Windows CE.} - Set this property to true to automatically display the SIP when entering + Set this property to \c true to automatically display the SIP when entering widgets that accept keyboard input. This property only affects widgets with the WA_InputMethodEnabled attribute set. */ @@ -1517,7 +1518,7 @@ int QApplication::colorSpec() strategy. Use this option if your application uses buttons, menus, texts and pixmaps with few colors. With this option, the application uses system global colors. This works fine for most - applications under X11, but on Windows machines it may cause + applications under X11, but on the Windows platform, it may cause dithering of non-standard colors. \o QApplication::CustomColor. Use this option if your application needs a small number of custom colors. On X11, this option is the @@ -3513,12 +3514,12 @@ void QApplication::changeOverrideCursor(const QCursor &cursor) We recommend that you connect clean-up code to the \l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in your - application's \c{main()} function because on some platforms the - QApplication::exec() call may not return. For example, on Windows when the - user logs off, the system terminates the process after Qt closes all - top-level windows. Hence, there is no guarantee that the application will - have time to exit its event loop and execute code at the end of the - \c{main()} function after the QApplication::exec() call. + application's \c{main()} function. This is because, on some platforms the + QApplication::exec() call may not return. For example, on the Windows + platform, when the user logs off, the system terminates the process after Qt + closes all top-level windows. Hence, there is \e{no guarantee} that the + application will have time to exit its event loop and execute code at the + end of the \c{main()} function, after the QApplication::exec() call. \sa quitOnLastWindowClosed, quit(), exit(), processEvents(), QCoreApplication::exec() @@ -4762,7 +4763,7 @@ bool QApplication::keypadNavigationEnabled() On Mac OS X, this works more at the application level and will cause the application icon to bounce in the dock. - On Windows this causes the window's taskbar entry to flash for a time. If + On Windows, this causes the window's taskbar entry to flash for a time. If \a msec is zero, the flashing will stop and the taskbar entry will turn a different color (currently orange). @@ -4779,24 +4780,22 @@ bool QApplication::keypadNavigationEnabled() caret display. Usually the text cursor is displayed for half the cursor flash time, then hidden for the same amount of time, but this may vary. - The default value on X11 is 1000 milliseconds. On Windows, the control - panel value is used. Widgets should not cache this value since it may be - changed at any time by the user changing the global desktop settings. + The default value on X11 is 1000 milliseconds. On Windows, the + \gui{Control Panel} value is used and setting this property sets the cursor + flash time for all applications. - \note On Microsoft Windows, setting this property sets the cursor flash - time for all applications. + We recommend that widgets do not cache this value as it may change at any + time if the user changes the global desktop settings. */ /*! \property QApplication::doubleClickInterval - \brief the time limit in milliseconds that distinguishes a double click from two - consecutive mouse clicks - - The default value on X11 is 400 milliseconds. On Windows and Mac OS X, the - operating system's value is used. + \brief the time limit in milliseconds that distinguishes a double click + from two consecutive mouse clicks - On Microsoft Windows, calling this function sets the double click interval - for all applications. + The default value on X11 is 400 milliseconds. On Windows and Mac OS, the + operating system's value is used. However, on Windows, calling this + function sets the double click interval for all applications. */ /*! @@ -4805,7 +4804,7 @@ bool QApplication::keypadNavigationEnabled() from two consecutive key presses \since 4.2 - The default value on X11 is 400 milliseconds. On Windows and Mac OS X, the + The default value on X11 is 400 milliseconds. On Windows and Mac OS, the operating system's value is used. */ @@ -4870,7 +4869,7 @@ bool QApplication::keypadNavigationEnabled() You need not have a main widget; connecting lastWindowClosed() to quit() is an alternative. - For X11, this function also resizes and moves the main widget according + On X11, this function also resizes and moves the main widget according to the \e -geometry command-line option, so you should set the default geometry (using \l QWidget::setGeometry()) before calling setMainWidget(). @@ -4899,9 +4898,10 @@ bool QApplication::keypadNavigationEnabled() Application cursors are stored on an internal stack. setOverrideCursor() pushes the cursor onto the stack, and restoreOverrideCursor() pops the active cursor off the stack. changeOverrideCursor() changes the curently - active application override cursor. Every setOverrideCursor() must - eventually be followed by a corresponding restoreOverrideCursor(), - otherwise the stack will never be emptied. + active application override cursor. + + Every setOverrideCursor() must eventually be followed by a corresponding + restoreOverrideCursor(), otherwise the stack will never be emptied. Example: \snippet doc/src/snippets/code/src_gui_kernel_qapplication_x11.cpp 0 @@ -5082,19 +5082,19 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) */ /*! \fn QDecoration* QApplication::qwsSetDecoration(const QString &decoration) - \overload + \overload - Requests a QDecoration object for \a decoration from the QDecorationFactory. + Requests a QDecoration object for \a decoration from the + QDecorationFactory. - The string must be one of the QDecorationFactory::keys(). Keys are - case insensitive. + The string must be one of the QDecorationFactory::keys(). Keys are case + insensitive. - A later call to the QApplication constructor will override the - requested style when a "-style" option is passed in as a commandline - parameter. + A later call to the QApplication constructor will override the requested + style when a "-style" option is passed in as a commandline parameter. - Returns 0 if an unknown \a decoration is passed, otherwise the QStyle object - returned is set as the application's GUI style. + Returns 0 if an unknown \a decoration is passed, otherwise the QStyle object + returned is set as the application's GUI style. */ /*! diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index d53b419..1f98013 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -153,7 +153,7 @@ QGesture::QGesture(QObject *parent) : QObject(*new QGesturePrivate, parent) { if (parent) - installEventFilter(parent); + parent->installEventFilter(this); } /*! \internal @@ -162,7 +162,7 @@ QGesture::QGesture(QGesturePrivate &dd, QObject *parent) : QObject(dd, parent) { if (parent) - installEventFilter(parent); + parent->installEventFilter(this); } /*! diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index e24b7cb..6ee229a 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -3497,11 +3497,16 @@ bool QWidgetPrivate::setMinimumSize_helper(int &minw, int &minh) minh = qMax(minh, 0); } createExtra(); - if (extra->minw == minw && extra->minh == minh) + int mw = minw, mh = minh; + if (mw == QWIDGETSIZE_MAX) + mw = 0; + if (mh == QWIDGETSIZE_MAX) + mh = 0; + if (extra->minw == mw && extra->minh == mh) return false; - extra->minw = minw; - extra->minh = minh; - extra->explicitMinSize = (minw ? Qt::Horizontal : 0) | (minh ? Qt::Vertical : 0); + extra->minw = mw; + extra->minh = mh; + extra->explicitMinSize = (mw ? Qt::Horizontal : 0) | (mh ? Qt::Vertical : 0); return true; } @@ -3561,7 +3566,8 @@ bool QWidgetPrivate::setMaximumSize_helper(int &maxw, int &maxh) return false; extra->maxw = maxw; extra->maxh = maxh; - extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) | (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0); + extra->explicitMaxSize = (maxw != QWIDGETSIZE_MAX ? Qt::Horizontal : 0) | + (maxh != QWIDGETSIZE_MAX ? Qt::Vertical : 0); return true; } @@ -3640,6 +3646,8 @@ void QWidget::setBaseSize(int basew, int baseh) This will override the default size constraints set by QLayout. + To remove constraints, set the size to QWIDGETSIZE_MAX. + Alternatively, if you want the widget to have a fixed size based on its contents, you can call QLayout::setSizeConstraint(QLayout::SetFixedSize); @@ -3681,7 +3689,8 @@ void QWidget::setFixedSize(int w, int h) else d->updateGeometry_helper(true); - resize(w, h); + if (w != QWIDGETSIZE_MAX || h != QWIDGETSIZE_MAX) + resize(w, h); } void QWidget::setMinimumWidth(int w) diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 70eea3a..3bbf5d4 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -3100,7 +3100,12 @@ void QWidgetPrivate::update_sys(const QRegion &rgn) return; dirtyOnWidget += rgn; #ifndef QT_MAC_USE_COCOA - HIViewSetNeedsDisplayInRegion(qt_mac_nativeview_for(q), QMacSmartQuickDrawRegion(rgn.toQDRgn()), true); + RgnHandle rgnHandle = rgn.toQDRgnForUpdate_sys(); + if (rgnHandle) + HIViewSetNeedsDisplayInRegion(qt_mac_nativeview_for(q), QMacSmartQuickDrawRegion(rgnHandle), true); + else { + HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); // do a complete repaint on overflow. + } #else // Cocoa doesn't do regions, it seems more efficient to just update the bounding rect instead of a potential number of message passes for each rect. const QRect &boundingRect = rgn.boundingRect(); diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 46fa3be..2f230d7 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -467,6 +467,17 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } } + if (topLevel) { + if (data.window_flags & Qt::CustomizeWindowHint + && data.window_flags & Qt::WindowTitleHint) { + HMENU systemMenu = GetSystemMenu((HWND)q->internalWinId(), FALSE); + if (data.window_flags & Qt::WindowCloseButtonHint) + EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED); + else + EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); + } + } + q->setAttribute(Qt::WA_WState_Created); // accept move/resize events hd = 0; // no display context @@ -638,16 +649,6 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) || (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) q->setAttribute(Qt::WA_DropSiteRegistered, true); - - if (data.window_flags & Qt::CustomizeWindowHint - && data.window_flags & Qt::WindowTitleHint) { - HMENU systemMenu = GetSystemMenu((HWND)q->internalWinId(), FALSE); - if (data.window_flags & Qt::WindowCloseButtonHint) - EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_ENABLED); - else - EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); - } - #ifdef Q_WS_WINCE // Show borderless toplevel windows in tasklist & NavBar if (!parent) { @@ -1524,6 +1525,11 @@ bool QWidgetPrivate::shouldShowMaximizeButton() { if (data.window_flags & Qt::MSWindowsFixedSizeDialogHint) return false; + // if the user explicitely asked for the maximize button, we try to add + // it even if the window has fixed size. + if (data.window_flags & Qt::CustomizeWindowHint && + data.window_flags & Qt::WindowMaximizeButtonHint) + return true; if (extra) { if ((extra->maxw && extra->maxw != QWIDGETSIZE_MAX && extra->maxw != QLAYOUTSIZE_MAX) || (extra->maxh && extra->maxh != QWIDGETSIZE_MAX && extra->maxh != QLAYOUTSIZE_MAX)) diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 34d1779..d226be2 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -100,8 +100,8 @@ win32 { painting/qcolormap_win.cpp \ painting/qpaintdevice_win.cpp \ painting/qprintengine_win.cpp \ - painting/qprinterinfo_win.cpp \ - painting/qregion_win.cpp + painting/qprinterinfo_win.cpp + !win32-borland:!wince*:LIBS += -lmsimg32 } @@ -126,10 +126,6 @@ embedded { painting/qwindowsurface_raster.cpp \ } -wince* { - SOURCES -= painting/qregion_win.cpp -} - unix:x11 { HEADERS += \ painting/qpaintengine_x11_p.h diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 979390a..b6603e4 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -4794,30 +4794,60 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void * if (sy < 0) sy += image_height; - while (length) { - int l = qMin(image_width - sx, length); - if (buffer_size < l) - l = buffer_size; - - DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; - const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; - if (modeSource && coverage == 255) { + if (modeSource && coverage == 255) { + // Copy the first texture block + length = image_width; + while (length) { + int l = qMin(image_width - sx, length); + if (buffer_size < l) + l = buffer_size; + DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; + const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; qt_memconvert<DST, SRC>(dest, src, l); - } else if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && - (quintptr(dest) & 3) == (quintptr(src) & 3)) - { - blendUntransformed_dest24(dest, src, coverage, l); - } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && - (quintptr(dest) & 3) == (quintptr(src) & 3)) - { - blendUntransformed_dest16(dest, src, coverage, l); - } else { - blendUntransformed_unaligned(dest, src, coverage, l); + length -= l; + sx = 0; } - x += l; - length -= l; - sx = 0; + // Now use the rasterBuffer as the source of the texture, + // We can now progressively copy larger blocks + // - Less cpu time in code figuring out what to copy + // We are dealing with one block of data + // - More likely to fit in the cache + // - can use memcpy + int copy_image_width = image_width; + length = spans->len - image_width; + DST *src = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; + DST *dest = src + copy_image_width; + while (copy_image_width < length) { + qt_memconvert(dest, src, copy_image_width); + dest += copy_image_width; + length -= copy_image_width; + copy_image_width *= 2; + } + qt_memconvert(dest, src, length); + } else { + while (length) { + int l = qMin(image_width - sx, length); + if (buffer_size < l) + l = buffer_size; + DST *dest = ((DST*)data->rasterBuffer->scanLine(spans->y)) + x; + const SRC *src = (SRC*)data->texture.scanLine(sy) + sx; + if (sizeof(DST) == 3 && sizeof(SRC) == 3 && l >= 4 && + (quintptr(dest) & 3) == (quintptr(src) & 3)) + { + blendUntransformed_dest24(dest, src, coverage, l); + } else if (sizeof(DST) == 2 && sizeof(SRC) == 2 && l >= 2 && + (quintptr(dest) & 3) == (quintptr(src) & 3)) + { + blendUntransformed_dest16(dest, src, coverage, l); + } else { + blendUntransformed_unaligned(dest, src, coverage, l); + } + + x += l; + length -= l; + sx = 0; + } } ++spans; } diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index 762e9e0..d59f3ff 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -49,7 +49,7 @@ #include <qdebug.h> -#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE) +#if defined(Q_OS_UNIX) || defined(Q_WS_WIN) #include "qimage.h" #include "qbitmap.h" #include <stdlib.h> @@ -545,7 +545,7 @@ QRegion& QRegion::operator|=(const QRegion &r) \sa intersected() */ -#if !defined (Q_OS_UNIX) && !defined (Q_OS_WINCE) +#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN) QRegion& QRegion::operator+=(const QRect &r) { return operator+=(QRegion(r)); @@ -561,16 +561,14 @@ QRegion& QRegion::operator+=(const QRect &r) \sa intersected() */ -#if !defined(Q_WS_WIN) || defined(Q_OS_WINCE) QRegion& QRegion::operator&=(const QRegion &r) { return *this = *this & r; } -#endif /*! \overload \since 4.4 */ -#if defined (Q_OS_UNIX) || defined (Q_OS_WINCE) +#if defined (Q_OS_UNIX) || defined (Q_WS_WIN) QRegion& QRegion::operator&=(const QRect &r) { return *this = *this & r; @@ -591,10 +589,8 @@ QRegion& QRegion::operator&=(const QRect &r) \sa subtracted() */ -#if !defined(Q_WS_WIN) || defined(Q_OS_WINCE) QRegion& QRegion::operator-=(const QRegion &r) { return *this = *this - r; } -#endif /*! Applies the xored() function to this region and \a r and @@ -731,7 +727,7 @@ bool QRegion::intersects(const QRect &rect) const return false; } -#if !defined (Q_OS_UNIX) && !defined (Q_OS_WINCE) +#if !defined (Q_OS_UNIX) && !defined (Q_WS_WIN) /*! \overload \since 4.4 @@ -1086,7 +1082,7 @@ Q_AUTOTEST_EXPORT QPainterPath qt_regionToPath(const QRegion ®ion) return result; } -#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE) +#if defined(Q_OS_UNIX) || defined(Q_WS_WIN) //#define QT_REGION_DEBUG /* @@ -1627,9 +1623,9 @@ QT_END_INCLUDE_NAMESPACE QT_BEGIN_INCLUDE_NAMESPACE # include "qregion_mac.cpp" QT_END_INCLUDE_NAMESPACE -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) QT_BEGIN_INCLUDE_NAMESPACE -# include "qregion_wince.cpp" +# include "qregion_win.cpp" QT_END_INCLUDE_NAMESPACE #elif defined(Q_WS_QWS) static QRegionPrivate qrp; @@ -3829,7 +3825,7 @@ QRegion::QRegion(const QRect &r, RegionType t) #if defined(Q_WS_X11) d->rgn = 0; d->xrectangles = 0; -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) d->rgn = 0; #endif if (t == Rectangle) { @@ -3851,7 +3847,7 @@ QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule) #if defined(Q_WS_X11) d->rgn = 0; d->xrectangles = 0; -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) d->rgn = 0; #endif d->qt_rgn = PolygonRegion(a.constData(), a.size(), @@ -3881,7 +3877,7 @@ QRegion::QRegion(const QBitmap &bm) #if defined(Q_WS_X11) d->rgn = 0; d->xrectangles = 0; -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) d->rgn = 0; #endif d->qt_rgn = qt_bitmapToRegion(bm); @@ -3896,7 +3892,7 @@ void QRegion::cleanUp(QRegion::QRegionData *x) XDestroyRegion(x->rgn); if (x->xrectangles) free(x->xrectangles); -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) if (x->rgn) qt_win_dispose_rgn(x->rgn); #endif @@ -3932,7 +3928,7 @@ QRegion QRegion::copy() const #if defined(Q_WS_X11) x->rgn = 0; x->xrectangles = 0; -#elif defined(Q_OS_WINCE) +#elif defined(Q_WS_WIN) x->rgn = 0; #endif if (d->qt_rgn) diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index bfedcb1..84024ce 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -59,7 +59,7 @@ QT_MODULE(Gui) template <class T> class QVector; class QVariant; -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE) +#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) struct QRegionPrivate; #endif @@ -148,6 +148,7 @@ public: #elif defined(Q_WS_MAC) #if defined Q_WS_MAC32 RgnHandle toQDRgn() const; + RgnHandle toQDRgnForUpdate_sys() const; static QRegion fromQDRgn(RgnHandle shape); #endif #ifdef QT_MAC_USE_COCOA @@ -199,7 +200,7 @@ private: #elif defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) mutable RgnHandle unused; // Here for binary compatability reasons. ### Qt 5 remove. #endif -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_OS_WINCE) +#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) QRegionPrivate *qt_rgn; #endif }; diff --git a/src/gui/painting/qregion_mac.cpp b/src/gui/painting/qregion_mac.cpp index b57f234..9b0e99f 100644 --- a/src/gui/painting/qregion_mac.cpp +++ b/src/gui/painting/qregion_mac.cpp @@ -155,6 +155,44 @@ RgnHandle QRegion::toQDRgn() const } return rgnHandle; } + +/*! + \internal + Create's a RegionHandle, it's the caller's responsibility to release. + Returns 0 if the QRegion overflows. +*/ +RgnHandle QRegion::toQDRgnForUpdate_sys() const +{ + RgnHandle rgnHandle = qt_mac_get_rgn(); + if(d->qt_rgn && d->qt_rgn->numRects) { + RgnHandle tmp_rgn = qt_mac_get_rgn(); + int n = d->qt_rgn->numRects; + const QRect *qt_r = (n == 1) ? &d->qt_rgn->extents : d->qt_rgn->rects.constData(); + while (n--) { + + // detect overflow. Tested for use with HIViewSetNeedsDisplayInRegion + // in QWidgetPrivate::update_sys(). + enum { HIViewSetNeedsDisplayInRegionOverflow = 10000 }; // empirically determined conservative value + qDebug() << qt_r->x() << qt_r->y() << qt_r->right() << qt_r->bottom(); + if (qt_r->right() > HIViewSetNeedsDisplayInRegionOverflow || qt_r->bottom() > HIViewSetNeedsDisplayInRegionOverflow) { + qt_mac_dispose_rgn(tmp_rgn); + qt_mac_dispose_rgn(rgnHandle); + return 0; + } + + SetRectRgn(tmp_rgn, + qMax(SHRT_MIN, qt_r->x()), + qMax(SHRT_MIN, qt_r->y()), + qMin(SHRT_MAX, qt_r->right() + 1), + qMin(SHRT_MAX, qt_r->bottom() + 1)); + UnionRgn(rgnHandle, tmp_rgn, rgnHandle); + ++qt_r; + } + qt_mac_dispose_rgn(tmp_rgn); + } + return rgnHandle; +} + #endif #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) diff --git a/src/gui/painting/qregion_win.cpp b/src/gui/painting/qregion_win.cpp index 249b1a6..2d5e76b 100644 --- a/src/gui/painting/qregion_win.cpp +++ b/src/gui/painting/qregion_win.cpp @@ -39,27 +39,25 @@ ** ****************************************************************************/ +#include "qatomic.h" #include "qbitmap.h" #include "qbuffer.h" #include "qimage.h" #include "qpolygon.h" #include "qregion.h" #include "qt_windows.h" +#include "qpainterpath.h" +#include "qguifunctions_wince.h" QT_BEGIN_NAMESPACE +QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 }; -/* - In Windows versions before Windows Vista CreateRectRgn - when called in a multi-threaded - environment - might return an invalid handle. This function works around this limitation - by verifying the handle with a quick GetRegionData() call and re-creates the region - if necessary. -*/ HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom) { const int tries = 10; for (int i = 0; i < tries; ++i) { - HRGN region = 0; + HRGN region; switch (type) { case QRegion::Rectangle: region = CreateRectRgn(left, top, right, bottom); @@ -80,497 +78,73 @@ HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, return 0; } -#ifndef Q_OS_WINCE -HRGN qt_tryCreatePolygonRegion(const QPolygon &a, Qt::FillRule fillRule) -{ - const int tries = 10; - for (int i = 0; i < tries; ++i) { - HRGN region = CreatePolygonRgn(reinterpret_cast<const POINT*>(a.data()), a.size(), - fillRule == Qt::OddEvenFill ? ALTERNATE : WINDING); - if (region) { - if (GetRegionData(region, 0, 0)) - return region; - else - DeleteObject(region); - } - } - return 0; -} -#endif - -QRegion::QRegionData QRegion::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1), 0 }; - -QRegion::QRegion() - : d(&shared_empty) -{ - d->ref.ref(); -} - -#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp -QRegion::QRegion(const QRect &r, RegionType t) -{ - if (r.isEmpty()) { - d = &shared_empty; - d->ref.ref(); - } else { - d = new QRegionData; - d->ref = 1; - if (t == Rectangle) - d->rgn = qt_tryCreateRegion(t, r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); - else if (t == Ellipse) { - // need to add 1 to width/height for the ellipse to have correct boundingrect. - d->rgn = qt_tryCreateRegion(t, r.x(), r.y(), r.x() + r.width() + 1, r.y() + r.height() + 1); - } - } -} -#endif - -#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp -QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule) -{ - if (a.size() < 3) { - d = &shared_empty; - d->ref.ref(); - } else { - d = new QRegionData; - d->ref = 1; - d->rgn = qt_tryCreatePolygonRegion(a, fillRule); - } -} -#endif - -QRegion::QRegion(const QRegion &r) -{ - d = r.d; - d->ref.ref(); -} - -HRGN qt_win_bitmapToRegion(const QBitmap& bitmap) -{ - HRGN region=0; - QImage image = bitmap.toImage(); - const int MAXRECT = 256; - struct RData { - RGNDATAHEADER header; - RECT rect[MAXRECT]; - }; - RData data; - -#define FlushSpans \ - { \ - data.header.dwSize = sizeof(RGNDATAHEADER); \ - data.header.iType = RDH_RECTANGLES; \ - data.header.nCount = n; \ - data.header.nRgnSize = 0; \ - data.header.rcBound.bottom = y; \ - HRGN r = ExtCreateRegion(0, \ - sizeof(RGNDATAHEADER)+n*sizeof(RECT),(RGNDATA*)&data); \ - if (region) { \ - CombineRgn(region, region, r, RGN_OR); \ - DeleteObject(r); \ - } else { \ - region = r; \ - } \ - data.header.rcBound.top = y; \ - } - -#define AddSpan \ - { \ - data.rect[n].left=prev1; \ - data.rect[n].top=y; \ - data.rect[n].right=x-1+1; \ - data.rect[n].bottom=y+1; \ - n++; \ - if (n == MAXRECT) { \ - FlushSpans \ - n=0; \ - } \ - } - - data.header.rcBound.top = 0; - data.header.rcBound.left = 0; - data.header.rcBound.right = image.width()-1; - int n = 0; - - int zero = 0x00; - - int x, y; - for (y = 0; y < image.height(); ++y) { - uchar *line = image.scanLine(y); - int w = image.width(); - uchar all=zero; - int prev1 = -1; - for (x = 0; x < w;) { - uchar byte = line[x/8]; - if (x > w - 8 || byte != all) { - for (int b = 8; b > 0 && x < w; --b) { - if (!(byte & 0x01) == !all) { - // More of the same - } else { - // A change. - if (all != zero) { - AddSpan; - all = zero; - } else { - prev1 = x; - all = ~zero; - } - } - byte >>= 1; - ++x; - } - } else { - x += 8; - } - } - if (all != zero) { - AddSpan; - } - } - if (n) { - FlushSpans; - } - - if (!region) { - // Surely there is some better way. - region = qt_tryCreateRegion(QRegion::Rectangle, 0,0,1,1); - CombineRgn(region, region, region, RGN_XOR); - } - return region; -} - -#ifndef Q_OS_WINCE //implementation for WindowsCE in qregion_wce.cpp -QRegion::QRegion(const QBitmap &bm) -{ - if (bm.isNull()) { - d = &shared_empty; - d->ref.ref(); - } else { - d = new QRegionData; - d->ref = 1; - d->rgn = qt_win_bitmapToRegion(bm); - } -} -#endif - -void QRegion::cleanUp(QRegion::QRegionData *x) -{ - if (x->rgn) - DeleteObject(x->rgn); - delete x; -} - -QRegion::~QRegion() -{ - if (!d->ref.deref()) - cleanUp(d); -} - -QRegion &QRegion::operator=(const QRegion &r) -{ - r.d->ref.ref(); - if (!d->ref.deref()) - cleanUp(d); - d = r.d; - return *this; -} - - -QRegion QRegion::copy() const -{ - QRegion r; - QRegionData *x = new QRegionData; - x->ref = 1; - if (d->rgn) { - x->rgn = qt_tryCreateRegion(QRegion::Rectangle, 0, 0, 2, 2); - CombineRgn(x->rgn, d->rgn, 0, RGN_COPY); - } else { - x->rgn = 0; - } - if (!r.d->ref.deref()) - cleanUp(r.d); - r.d = x; - return r; -} - -bool QRegion::isEmpty() const -{ - return (d == &shared_empty || boundingRect().isEmpty()); -} - - -bool QRegion::contains(const QPoint &p) const -{ - return d->rgn ? PtInRegion(d->rgn, p.x(), p.y()) : false; -} - -bool QRegion::contains(const QRect &r) const -{ - if (!d->rgn) - return false; - RECT rect; - SetRect(&rect, r.left(), r.top(), r.right(), r.bottom()); - return RectInRegion(d->rgn, &rect); -} - - -void QRegion::translate(int dx, int dy) -{ - if (!d->rgn || (dx == 0 && dy == 0)) - return; - detach(); - OffsetRgn(d->rgn, dx, dy); -} - - -#define RGN_NOP -1 - -// Duplicates of those in qregion.cpp -#define QRGN_OR 6 -#define QRGN_AND 7 -#define QRGN_SUB 8 -#define QRGN_XOR 9 - -/* - Performs the actual OR, AND, SUB and XOR operation between regions. - Sets the resulting region handle to 0 to indicate an empty region. -*/ - -QRegion QRegion::winCombine(const QRegion &r, int op) const +QRegion qt_region_from_HRGN(HRGN rgn) { - int both=RGN_NOP, - left=RGN_NOP, - right=RGN_NOP; - switch (op) { - case QRGN_OR: - both = RGN_OR; - left = right = RGN_COPY; - break; - case QRGN_AND: - both = RGN_AND; - break; - case QRGN_SUB: - both = RGN_DIFF; - left = RGN_COPY; - break; - case QRGN_XOR: - both = RGN_XOR; - left = right = RGN_COPY; - break; - default: - qWarning("QRegion: Internal error in winCombine"); - } - - int allCombineRgnResults = NULLREGION; - QRegion result; - result.detach(); - result.d->rgn = qt_tryCreateRegion(QRegion::Rectangle, 0, 0, 0, 0); - if (d->rgn && r.d->rgn) - allCombineRgnResults = CombineRgn(result.d->rgn, d->rgn, r.d->rgn, both); - else if (d->rgn && left != RGN_NOP) - allCombineRgnResults = CombineRgn(result.d->rgn, d->rgn, d->rgn, left); - else if (r.d->rgn && right != RGN_NOP) - allCombineRgnResults = CombineRgn(result.d->rgn, r.d->rgn, r.d->rgn, right); - - if (allCombineRgnResults == NULLREGION || allCombineRgnResults == ERROR) - result = QRegion(); - - //##### do not delete this. A null pointer is different from an empty region in SelectClipRgn in qpainter_win! (M) -// if (allCombineRgnResults == NULLREGION) { -// if (result.data->rgn) -// DeleteObject(result.data->rgn); -// result.data->rgn = 0; // empty region -// } - return result; -} - -QRegion QRegion::unite(const QRegion &r) const -{ - if (!d->rgn) - return r; - if (!r.d->rgn) - return *this; - return winCombine(r, QRGN_OR); -} - -QRegion QRegion::unite(const QRect &r) const -{ - return unite(QRegion(r)); -} - -QRegion QRegion::intersect(const QRegion &r) const -{ - if (!r.d->rgn || !d->rgn) - return QRegion(); - return winCombine(r, QRGN_AND); -} - -QRegion QRegion::subtract(const QRegion &r) const -{ - if (!r.d->rgn || !d->rgn) - return *this; - return winCombine(r, QRGN_SUB); -} - -QRegion QRegion::eor(const QRegion &r) const -{ - if (!d->rgn) - return r; - if (!r.d->rgn) - return *this; - return winCombine(r, QRGN_XOR); -} - - -QRect QRegion::boundingRect() const -{ - if (!d->rgn) - return QRect(); - RECT r; - if (GetRgnBox(d->rgn, &r) == NULLREGION) - return QRect(); - else - return QRect(r.left, r.top, r.right - r.left, r.bottom - r.top); -} - -QVector<QRect> QRegion::rects() const -{ - if (d->rgn == 0) - return QVector<QRect>(); - - int numBytes = GetRegionData(d->rgn, 0, 0); + int numBytes = GetRegionData(rgn, 0, 0); if (numBytes == 0) - return QVector<QRect>(); + return QRegion(); char *buf = new char[numBytes]; if (buf == 0) - return QVector<QRect>(); + return QRegion(); RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf); - if (GetRegionData(d->rgn, numBytes, rd) == 0) { + if (GetRegionData(rgn, numBytes, rd) == 0) { delete [] buf; - return QVector<QRect>(); + return QRegion(); } - QVector<QRect> a(rd->rdh.nCount); + QRegion region; RECT *r = reinterpret_cast<RECT*>(rd->Buffer); - for (int i = 0; i < a.size(); ++i) { - a[i].setCoords(r->left, r->top, r->right - 1, r->bottom - 1); + for (int i = 0; i < rd->rdh.nCount; ++i) { + QRect rect; + rect.setCoords(r->left, r->top, r->right - 1, r->bottom - 1); ++r; + region |= rect; } delete [] buf; - return a; -} - -void QRegion::setRects(const QRect *rects, int num) -{ - *this = QRegion(); - if (!rects || num == 0 || (num == 1 && rects->isEmpty())) - return; - for (int i = 0; i < num; ++i) - *this |= rects[i]; -} - -int QRegion::numRects() const -{ - if (d->rgn == 0) - return 0; - - const int numBytes = GetRegionData(d->rgn, 0, 0); - if (numBytes == 0) - return 0; - - char *buf = new char[numBytes]; - if (buf == 0) - return 0; - - RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf); - if (GetRegionData(d->rgn, numBytes, rd) == 0) { - delete[] buf; - return 0; - } - - const int n = rd->rdh.nCount; - delete[] buf; - return n; + return region; } -bool QRegion::operator==(const QRegion &r) const +void qt_win_dispose_rgn(HRGN r) { - if (d == r.d) - return true; - if ((d->rgn == 0) ^ (r.d->rgn == 0)) // one is empty, not both - return false; - return d->rgn == 0 ? true // both empty - : EqualRgn(d->rgn, r.d->rgn); // both non-empty + if (r) + DeleteObject(r); } -QRegion& QRegion::operator+=(const QRegion &r) +static void qt_add_rect(HRGN &winRegion, QRect r) { - if (!r.d->rgn) - return *this; - - if (!d->rgn) { - *this = r; - return *this; + HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height()); + if (rgn) { + HRGN dest = CreateRectRgn(0,0,0,0); + int result = CombineRgn(dest, winRegion, rgn, RGN_OR); + if (result) { + DeleteObject(winRegion); + winRegion = dest; + } + DeleteObject(rgn); } - - detach(); - - int result; - result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_OR); - if (result == NULLREGION || result == ERROR) - *this = QRegion(); - - return *this; -} - -QRegion& QRegion::operator-=(const QRegion &r) -{ - if (!r.d->rgn || !d->rgn) - return *this; - - detach(); - - int result; - result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_DIFF); - if (result == NULLREGION || result == ERROR) - *this = QRegion(); - - return *this; } -QRegion& QRegion::operator&=(const QRegion &r) +void QRegion::ensureHandle() const { - if (!d->rgn) - return *this; - - if (!r.d->rgn) { - *this = QRegion(); - return *this; + if (d->rgn) + DeleteObject(d->rgn); + d->rgn = CreateRectRgn(0,0,0,0); + if (d->qt_rgn) { + if (d->qt_rgn->numRects == 1) { + QRect r = d->qt_rgn->extents; + qt_add_rect(d->rgn, r); + return; + } + for (int i = 0;i < d->qt_rgn->numRects;i++) { + QRect r = d->qt_rgn->rects.at(i); + qt_add_rect(d->rgn, r); + } } - - detach(); - - int result; - result = CombineRgn(d->rgn, d->rgn, r.d->rgn, RGN_AND); - if (result == NULLREGION || result == ERROR) - *this = QRegion(); - - return *this; -} - -bool qt_region_strictContains(const QRegion ®ion, const QRect &rect) -{ - Q_UNUSED(region); - Q_UNUSED(rect); - return false; } -void QRegion::ensureHandle() const -{ -} QT_END_NAMESPACE diff --git a/src/gui/painting/qwindowsurface_x11.cpp b/src/gui/painting/qwindowsurface_x11.cpp index d8b0d9e..95f6ce3 100644 --- a/src/gui/painting/qwindowsurface_x11.cpp +++ b/src/gui/painting/qwindowsurface_x11.cpp @@ -154,7 +154,7 @@ void QX11WindowSurface::setGeometry(const QRect &rect) QX11PixmapData *oldData = static_cast<QX11PixmapData *>(d_ptr->device.pixmapData()); Q_ASSERT(oldData); - if (!oldData->uninit && hasStaticContents()) { + if (!(oldData->flags & QX11PixmapData::Uninitialized) && hasStaticContents()) { // Copy the content of the old pixmap into the new one. QX11PixmapData *newData = new QX11PixmapData(QPixmapData::PixmapType); newData->resize(size.width(), size.height()); @@ -175,7 +175,7 @@ void QX11WindowSurface::setGeometry(const QRect &rect) dx, dy, qMin(boundingRect.width(), size.width()), qMin(boundingRect.height(), size.height()), dx, dy); XFreeGC(X11->display, tmpGc); - newData->uninit = false; + newData->flags &= ~QX11PixmapData::Uninitialized; d_ptr->device = QPixmap(newData); } else { diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index 9560c4b..ad87354 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -134,6 +134,7 @@ static const int windowsRightBorder = 12; // right border on windows // External function calls extern Q_GUI_EXPORT HDC qt_win_display_dc(); +extern QRegion qt_region_from_HRGN(HRGN rgn); @@ -445,6 +446,7 @@ bool QWindowsXPStylePrivate::isTransparent(XPThemeData &themeData) themeData.stateId); } + /*! \internal Returns a QRegion of the region of the part */ @@ -456,12 +458,18 @@ QRegion QWindowsXPStylePrivate::region(XPThemeData &themeData) themeData.stateId, &rect, &hRgn))) return QRegion(); - QRegion rgn = QRegion(0,0,1,1); - const bool success = CombineRgn(rgn.handle(), hRgn, 0, RGN_COPY) != ERROR; - DeleteObject(hRgn); + HRGN dest = CreateRectRgn(0, 0, 0, 0); + const bool success = CombineRgn(dest, hRgn, 0, RGN_COPY) != ERROR; + + QRegion region; + if (success) - return rgn; - return QRegion(); + region = qt_region_from_HRGN(dest); + + DeleteObject(hRgn); + DeleteObject(dest); + + return region; } /*! \internal diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index a0b6f0c..d210cb4 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -1378,8 +1378,8 @@ bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, G FT_Face face = 0; for (int i = 0; i < num_glyphs; ++i) { - if (!gs->glyph_data.contains(glyphs[i]) - || gs->glyph_data.value(glyphs[i])->format != format) { + Glyph *glyph = gs->glyph_data.value(glyphs[i]); + if (glyph == 0 || glyph->format != format) { if (!face) { face = lockFace(); FT_Matrix m = matrix; diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp index bf1fa6a..a0a3756 100644 --- a/src/gui/util/qcompleter.cpp +++ b/src/gui/util/qcompleter.cpp @@ -824,6 +824,9 @@ void QCompleterPrivate::_q_complete(QModelIndex index, bool highlighted) Q_Q(QCompleter); QString completion; + if (!(index.flags() & Qt::ItemIsEnabled)) + return; + if (!index.isValid() || (!proxy->showAll && (index.row() >= proxy->engine->matchCount()))) { completion = prefix; } else { @@ -1102,7 +1105,8 @@ void QCompleter::setPopup(QAbstractItemView *popup) QObject::connect(popup, SIGNAL(clicked(QModelIndex)), this, SLOT(_q_complete(QModelIndex))); - QObject::connect(popup, SIGNAL(clicked(QModelIndex)), popup, SLOT(hide())); + QObject::connect(this, SIGNAL(activated(QModelIndex)), + popup, SLOT(hide())); QObject::connect(popup->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(_q_completionSelected(QItemSelection))); diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index a3964f7..4a900d6 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -716,7 +716,7 @@ void QMenuBar::initStyleOption(QStyleOptionMenuItem *option, const QAction *acti application examples} also provide menus using these classes. \sa QMenu, QShortcut, QAction, - {http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/index.html}{Introduction to Apple Human Interface Guidelines}, + {http://developer.apple.com/documentation/UserExperience/Conceptual/AppleHIGuidelines/XHIGIntro/XHIGIntro.html}{Introduction to Apple Human Interface Guidelines}, {fowler}{GUI Design Handbook: Menu Bar}, {Menus Example} */ |