diff options
author | Kent Hansen <khansen@trolltech.com> | 2009-08-05 14:10:47 (GMT) |
---|---|---|
committer | Kent Hansen <khansen@trolltech.com> | 2009-08-05 14:10:47 (GMT) |
commit | 1d7d5436eea09a232187836e59d2a937a752dee4 (patch) | |
tree | 6bd9ae61abb1467aceddc5a828fc2e65d93b2534 /src/gui | |
parent | 791bddfcd5cc7540219835ef5d91486acd833c4b (diff) | |
parent | fb8bb148affec842e8fa1a70616c64c7d3066ee8 (diff) | |
download | Qt-1d7d5436eea09a232187836e59d2a937a752dee4.zip Qt-1d7d5436eea09a232187836e59d2a937a752dee4.tar.gz Qt-1d7d5436eea09a232187836e59d2a937a752dee4.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt into qtscript-jsc-backend
Conflicts:
src/script/qscriptextqobject.cpp
Diffstat (limited to 'src/gui')
91 files changed, 1780 insertions, 1695 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/dialogs/qcolordialog.cpp b/src/gui/dialogs/qcolordialog.cpp index 42d3a9a..aee592c 100644 --- a/src/gui/dialogs/qcolordialog.cpp +++ b/src/gui/dialogs/qcolordialog.cpp @@ -1583,8 +1583,7 @@ void QColorDialog::setCurrentColor(const QColor &color) #ifdef Q_WS_MAC d->setCurrentQColor(color); - if (d->delegate) - QColorDialogPrivate::setColor(d->delegate, color); + d->setCocoaPanelColor(color); #endif } @@ -1725,19 +1724,16 @@ void QColorDialog::setVisible(bool visible) #if defined(Q_WS_MAC) if (visible) { - if (!d->delegate && QColorDialogPrivate::sharedColorPanelAvailable && - !(testAttribute(Qt::WA_DontShowOnScreen) || (d->opts & DontUseNativeDialog))){ - d->delegate = QColorDialogPrivate::openCocoaColorPanel( - currentColor(), parentWidget(), windowTitle(), options(), d); + if (d->delegate || (QColorDialogPrivate::sharedColorPanelAvailable && + !(testAttribute(Qt::WA_DontShowOnScreen) || (d->opts & DontUseNativeDialog)))){ + d->openCocoaColorPanel(currentColor(), parentWidget(), windowTitle(), options()); QColorDialogPrivate::sharedColorPanelAvailable = false; setAttribute(Qt::WA_DontShowOnScreen); } setWindowFlags(windowModality() == Qt::WindowModal ? Qt::Sheet : DefaultWindowFlags); } else { if (d->delegate) { - QColorDialogPrivate::closeCocoaColorPanel(d->delegate); - d->delegate = 0; - QColorDialogPrivate::sharedColorPanelAvailable = true; + d->closeCocoaColorPanel(); setAttribute(Qt::WA_DontShowOnScreen, false); } } @@ -1840,6 +1836,14 @@ QRgb QColorDialog::getRgba(QRgb initial, bool *ok, QWidget *parent) QColorDialog::~QColorDialog() { + Q_D(QColorDialog); +#if defined(Q_WS_MAC) + if (d->delegate) { + d->releaseCocoaColorPanelDelegate(); + QColorDialogPrivate::sharedColorPanelAvailable = true; + } +#endif + #ifndef QT_NO_SETTINGS if (!customSet) { QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); diff --git a/src/gui/dialogs/qcolordialog_mac.mm b/src/gui/dialogs/qcolordialog_mac.mm index 1936de5..6cdb7ee 100644 --- a/src/gui/dialogs/qcolordialog_mac.mm +++ b/src/gui/dialogs/qcolordialog_mac.mm @@ -76,6 +76,8 @@ QT_USE_NAMESPACE CGFloat mMinWidth; // currently unused CGFloat mExtraHeight; // currently unused BOOL mHackedPanel; + NSInteger mResultCode; + BOOL mDialogIsExecuting; } - (id)initWithColorPanel:(NSColorPanel *)panel stolenContentView:(NSView *)stolenContentView @@ -90,7 +92,8 @@ QT_USE_NAMESPACE - (NSColorPanel *)colorPanel; - (QColor)qtColor; - (void)finishOffWithCode:(NSInteger)result; -- (void)cleanUpAfterMyself; +- (void)showColorPanel; +- (void)exec; @end @implementation QCocoaColorPanelDelegate @@ -110,6 +113,8 @@ QT_USE_NAMESPACE mMinWidth = 0.0; mExtraHeight = 0.0; mHackedPanel = (okButton != 0); + mResultCode = NSCancelButton; + mDialogIsExecuting = false; if (mHackedPanel) { [self relayout]; @@ -121,19 +126,31 @@ QT_USE_NAMESPACE [cancelButton setTarget:self]; } - if (mPriv) - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(colorChanged:) - name:NSColorPanelColorDidChangeNotification - object:mColorPanel]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(colorChanged:) + name:NSColorPanelColorDidChangeNotification + object:mColorPanel]; + mQtColor = new QColor(); return self; } - (void)dealloc { - if (mPriv) - [[NSNotificationCenter defaultCenter] removeObserver:self]; + QMacCocoaAutoReleasePool pool; + if (mHackedPanel) { + NSView *ourContentView = [mColorPanel contentView]; + + // return stolen stuff to its rightful owner + [mStolenContentView removeFromSuperview]; + [mColorPanel setContentView:mStolenContentView]; + + [mOkButton release]; + [mCancelButton release]; + [ourContentView release]; + } + [mColorPanel setDelegate:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; delete mQtColor; [super dealloc]; } @@ -160,8 +177,7 @@ QT_USE_NAMESPACE - (void)colorChanged:(NSNotification *)notification; { Q_UNUSED(notification); - if (mPriv) - [self updateQtColor]; + [self updateQtColor]; } - (void)relayout @@ -258,8 +274,7 @@ QT_USE_NAMESPACE } } - if (mPriv) - mPriv->setCurrentQColor(*mQtColor); + mPriv->setCurrentQColor(*mQtColor); } - (NSColorPanel *)colorPanel @@ -274,36 +289,42 @@ QT_USE_NAMESPACE - (void)finishOffWithCode:(NSInteger)code { - if (mPriv) { - // Finish the QColorDialog as well. But since a call to accept or reject will - // close down the QEventLoop found in QDialog, we need to make sure that the - // current thread has exited the native dialogs modal session/run loop first. - // We ensure this by posting the call: + mResultCode = code; + if (mDialogIsExecuting) { + // We stop the current modal event loop. The control + // will then return inside -(void)exec below. + // It's important that the modal event loop is stopped before + // we accept/reject QColorDialog, since QColorDialog has its + // own event loop that needs to be stopped last. [NSApp stopModalWithCode:code]; - if (code == NSOKButton) - QMetaObject::invokeMethod(mPriv->colorDialog(), "accept", Qt::QueuedConnection); - else - QMetaObject::invokeMethod(mPriv->colorDialog(), "reject", Qt::QueuedConnection); } else { - [NSApp stopModalWithCode:code]; + // Since we are not in a modal event loop, we can safely close + // down QColorDialog + if (mResultCode == NSCancelButton) + mPriv->colorDialog()->reject(); + else + mPriv->colorDialog()->accept(); } } -- (void)cleanUpAfterMyself +- (void)showColorPanel { - if (mHackedPanel) { - NSView *ourContentView = [mColorPanel contentView]; - - // return stolen stuff to its rightful owner - [mStolenContentView removeFromSuperview]; - [mColorPanel setContentView:mStolenContentView]; + mDialogIsExecuting = false; + [mColorPanel makeKeyAndOrderFront:mColorPanel]; +} - [mOkButton release]; - [mCancelButton release]; - [ourContentView release]; - } - [mColorPanel setDelegate:nil]; +- (void)exec +{ + QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active); + QMacCocoaAutoReleasePool pool; + mDialogIsExecuting = true; + [NSApp runModalForWindow:mColorPanel]; + if (mResultCode == NSCancelButton) + mPriv->colorDialog()->reject(); + else + mPriv->colorDialog()->accept(); } + @end QT_BEGIN_NAMESPACE @@ -312,91 +333,90 @@ extern void macStartInterceptNSPanelCtor(); extern void macStopInterceptNSPanelCtor(); extern NSButton *macCreateButton(const char *text, NSView *superview); -void *QColorDialogPrivate::openCocoaColorPanel(const QColor &initial, - QWidget *parent, const QString &title, QColorDialog::ColorDialogOptions options, - QColorDialogPrivate *priv) +void QColorDialogPrivate::openCocoaColorPanel(const QColor &initial, + QWidget *parent, const QString &title, QColorDialog::ColorDialogOptions options) { Q_UNUSED(parent); // we would use the parent if only NSColorPanel could be a sheet QMacCocoaAutoReleasePool pool; - /* - The standard Cocoa color panel has no OK or Cancel button and - is created as a utility window, whereas we want something like - the Carbon color panel. We need to take the following steps: + if (!delegate) { + /* + The standard Cocoa color panel has no OK or Cancel button and + is created as a utility window, whereas we want something like + the Carbon color panel. We need to take the following steps: + + 1. Intercept the color panel constructor to turn off the + NSUtilityWindowMask flag. This is done by temporarily + replacing initWithContentRect:styleMask:backing:defer: + in NSPanel by our own method. - 1. Intercept the color panel constructor to turn off the - NSUtilityWindowMask flag. This is done by temporarily - replacing initWithContentRect:styleMask:backing:defer: - in NSPanel by our own method. + 2. Modify the color panel so that its content view is part + of a new content view that contains it as well as two + buttons (OK and Cancel). - 2. Modify the color panel so that its content view is part - of a new content view that contains it as well as two - buttons (OK and Cancel). + 3. Lay out the original content view and the buttons when + the color panel is shown and whenever it is resized. - 3. Lay out the original content view and the buttons when - the color panel is shown and whenever it is resized. + 4. Clean up after ourselves. + */ - 4. Clean up after ourselves. - */ + bool hackColorPanel = !(options & QColorDialog::NoButtons); - bool hackColorPanel = !(options & QColorDialog::NoButtons); + if (hackColorPanel) + macStartInterceptNSPanelCtor(); + NSColorPanel *colorPanel = [NSColorPanel sharedColorPanel]; + if (hackColorPanel) + macStopInterceptNSPanelCtor(); - if (hackColorPanel) - macStartInterceptNSPanelCtor(); - NSColorPanel *colorPanel = [NSColorPanel sharedColorPanel]; - if (hackColorPanel) - macStopInterceptNSPanelCtor(); + [colorPanel setHidesOnDeactivate:false]; - [colorPanel setHidesOnDeactivate:false]; + // set up the Cocoa color panel + [colorPanel setShowsAlpha:options & QColorDialog::ShowAlphaChannel]; + [colorPanel setTitle:(NSString*)(CFStringRef)QCFString(title)]; - // set up the Cocoa color panel - [colorPanel setShowsAlpha:options & QColorDialog::ShowAlphaChannel]; - [colorPanel setTitle:(NSString*)(CFStringRef)QCFString(title)]; + NSView *stolenContentView = 0; + NSButton *okButton = 0; + NSButton *cancelButton = 0; - NSView *stolenContentView = 0; - NSButton *okButton = 0; - NSButton *cancelButton = 0; + if (hackColorPanel) { + // steal the color panel's contents view + stolenContentView = [colorPanel contentView]; + [stolenContentView retain]; + [colorPanel setContentView:0]; - if (hackColorPanel) { - // steal the color panel's contents view - stolenContentView = [colorPanel contentView]; - [stolenContentView retain]; - [colorPanel setContentView:0]; + // create a new content view and add the stolen one as a subview + NSRect frameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } }; + NSView *ourContentView = [[NSView alloc] initWithFrame:frameRect]; + [ourContentView addSubview:stolenContentView]; - // create a new content view and add the stolen one as a subview - NSRect frameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } }; - NSView *ourContentView = [[NSView alloc] initWithFrame:frameRect]; - [ourContentView addSubview:stolenContentView]; + // create OK and Cancel buttons and add these as subviews + okButton = macCreateButton("&OK", ourContentView); + cancelButton = macCreateButton("Cancel", ourContentView); - // create OK and Cancel buttons and add these as subviews - okButton = macCreateButton("&OK", ourContentView); - cancelButton = macCreateButton("Cancel", ourContentView); + [colorPanel setContentView:ourContentView]; + [colorPanel setDefaultButtonCell:[okButton cell]]; + } - [colorPanel setContentView:ourContentView]; - [colorPanel setDefaultButtonCell:[okButton cell]]; + delegate = [[QCocoaColorPanelDelegate alloc] initWithColorPanel:colorPanel + stolenContentView:stolenContentView + okButton:okButton + cancelButton:cancelButton + priv:this]; + [colorPanel setDelegate:static_cast<QCocoaColorPanelDelegate *>(delegate)]; } - // create a delegate and set it - QCocoaColorPanelDelegate *delegate = - [[QCocoaColorPanelDelegate alloc] initWithColorPanel:colorPanel - stolenContentView:stolenContentView - okButton:okButton - cancelButton:cancelButton - priv:priv]; - [colorPanel setDelegate:delegate]; - setColor(delegate, initial); - [colorPanel makeKeyAndOrderFront:colorPanel]; - - return delegate; + setCocoaPanelColor(initial); + [static_cast<QCocoaColorPanelDelegate *>(delegate) showColorPanel]; } -void QColorDialogPrivate::closeCocoaColorPanel(void *delegate) +void QColorDialogPrivate::closeCocoaColorPanel() { - QMacCocoaAutoReleasePool pool; - QCocoaColorPanelDelegate *theDelegate = static_cast<QCocoaColorPanelDelegate *>(delegate); - [[theDelegate colorPanel] close]; - [theDelegate cleanUpAfterMyself]; - [theDelegate autorelease]; + [[static_cast<QCocoaColorPanelDelegate *>(delegate) colorPanel] close]; +} + +void QColorDialogPrivate::releaseCocoaColorPanelDelegate() +{ + [static_cast<QCocoaColorPanelDelegate *>(delegate) release]; } void QColorDialogPrivate::mac_nativeDialogModalHelp() @@ -416,13 +436,10 @@ void QColorDialogPrivate::mac_nativeDialogModalHelp() void QColorDialogPrivate::_q_macRunNativeAppModalPanel() { - QBoolBlocker nativeDialogOnTop(QApplicationPrivate::native_modal_dialog_active); - QMacCocoaAutoReleasePool pool; - QCocoaColorPanelDelegate *delegateCasted = static_cast<QCocoaColorPanelDelegate *>(delegate); - [NSApp runModalForWindow:[delegateCasted colorPanel]]; + [static_cast<QCocoaColorPanelDelegate *>(delegate) exec]; } -void QColorDialogPrivate::setColor(void *delegate, const QColor &color) +void QColorDialogPrivate::setCocoaPanelColor(const QColor &color) { QMacCocoaAutoReleasePool pool; QCocoaColorPanelDelegate *theDelegate = static_cast<QCocoaColorPanelDelegate *>(delegate); diff --git a/src/gui/dialogs/qcolordialog_p.h b/src/gui/dialogs/qcolordialog_p.h index ea66d4a..00d40b6 100644 --- a/src/gui/dialogs/qcolordialog_p.h +++ b/src/gui/dialogs/qcolordialog_p.h @@ -116,14 +116,11 @@ public: QByteArray memberToDisconnectOnClose; #ifdef Q_WS_MAC - static void *openCocoaColorPanel(const QColor &initial, - QWidget *parent, const QString &title, - QColorDialog::ColorDialogOptions options, - QColorDialogPrivate *priv = 0); - static void closeCocoaColorPanel(void *delegate); - static QColor execCocoaColorPanel(const QColor &initial, QWidget *parent, - const QString &title, QColorDialog::ColorDialogOptions options); - static void setColor(void *delegate, const QColor &color); + void openCocoaColorPanel(const QColor &initial, + QWidget *parent, const QString &title, QColorDialog::ColorDialogOptions options); + void closeCocoaColorPanel(); + void releaseCocoaColorPanelDelegate(); + void setCocoaPanelColor(const QColor &color); inline void done(int result) { q_func()->done(result); } inline QColorDialog *colorDialog() { return q_func(); } diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index 8b4e1b1..f000033 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -394,6 +394,9 @@ QList<QUrl> QFileDialog::sidebarUrls() const static const qint32 QFileDialogMagic = 0xbe; +const char *qt_file_dialog_filter_reg_exp = +"^(.*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$"; + /*! \since 4.3 Saves the state of the dialog's layout, history and current directory. @@ -984,8 +987,13 @@ void QFileDialog::setNameFilters(const QStringList &filters) if (testOption(HideNameFilterDetails)) { QStringList strippedFilters; + QRegExp r(QString::fromLatin1(qt_file_dialog_filter_reg_exp)); for (int i = 0; i < cleanedFilters.count(); ++i) { - strippedFilters.append(cleanedFilters[i].mid(0, cleanedFilters[i].indexOf(QLatin1String(" (")))); + QString filterName; + int index = r.indexIn(cleanedFilters[i]); + if (index >= 0) + filterName = r.cap(1); + strippedFilters.append(filterName.simplified()); } d->qFileDialogUi->fileTypeCombo->addItems(strippedFilters); } else { @@ -2837,9 +2845,6 @@ void QFileDialogPrivate::_q_goToDirectory(const QString &path) } } -const char *qt_file_dialog_filter_reg_exp = - "^([^()]*)\\(([a-zA-Z0-9_.*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$"; - // Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)" QStringList qt_clean_filter_list(const QString &filter) { diff --git a/src/gui/dialogs/qfiledialog_win.cpp b/src/gui/dialogs/qfiledialog_win.cpp index 9bf82c3..02469b2 100644 --- a/src/gui/dialogs/qfiledialog_win.cpp +++ b/src/gui/dialogs/qfiledialog_win.cpp @@ -59,7 +59,9 @@ #endif #include <shlobj.h> - +#if !defined(Q_WS_WINCE) +#include <shobjidl.h> +#endif #include <objbase.h> #if defined(__IFileDialog_INTERFACE_DEFINED__) \ @@ -441,6 +443,8 @@ static bool qt_win_set_IFileDialogOptions(IFileDialog *pfd, QString subfilter = *it; if (!subfilter.isEmpty()) { offsets<<currentOffset; + //Here the COMMON_ITEM_DIALOG API always add the details for the filter (e.g. *.txt) + //so we don't need to handle the flag HideNameFilterDetails. winfilters += subfilter; // The name of the filter. winfilters += QChar(); currentOffset += subfilter.size()+1; diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp index 5a5d845..b8e12b4 100644 --- a/src/gui/dialogs/qfilesystemmodel.cpp +++ b/src/gui/dialogs/qfilesystemmodel.cpp @@ -872,6 +872,7 @@ QVariant QFileSystemModel::headerData(int section, Qt::Orientation orientation, pixmap.setAlphaChannel(pixmap.createAlphaMask()); return pixmap; } + break; case Qt::TextAlignmentRole: return Qt::AlignLeft; } 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/egl/qegl_x11.cpp b/src/gui/egl/qegl_x11.cpp index be89efe..6772592 100644 --- a/src/gui/egl/qegl_x11.cpp +++ b/src/gui/egl/qegl_x11.cpp @@ -39,15 +39,18 @@ ** ****************************************************************************/ +#include <QtCore/qdebug.h> + +#include <private/qt_x11_p.h> +#include <QtGui/qx11info_x11.h> +#include <private/qpixmapdata_p.h> +#include <private/qpixmap_x11_p.h> + #include <QtGui/qpaintdevice.h> #include <QtGui/qpixmap.h> #include <QtGui/qwidget.h> -#include <QtCore/qdebug.h> #include "qegl_p.h" -#include <QtGui/qx11info_x11.h> -#include <X11/Xlib.h> -#include <X11/Xutil.h> QT_BEGIN_NAMESPACE @@ -125,7 +128,17 @@ void QEglProperties::setVisualFormat(const QX11Info *xinfo) setValue(EGL_RED_SIZE, countBits(visual->red_mask)); setValue(EGL_GREEN_SIZE, countBits(visual->green_mask)); setValue(EGL_BLUE_SIZE, countBits(visual->blue_mask)); - setValue(EGL_ALPHA_SIZE, 0); // XXX + + EGLint alphaBits = 0; +#if !defined(QT_NO_XRENDER) + XRenderPictFormat *format; + format = XRenderFindVisualFormat(xinfo->display(), visual); + if (format && (format->type == PictTypeDirect) && format->direct.alphaMask) { + alphaBits = countBits(format->direct.alphaMask); + qDebug("QEglProperties::setVisualFormat() - visual's alphaMask is %d", alphaBits); + } +#endif + setValue(EGL_ALPHA_SIZE, alphaBits); } extern const QX11Info *qt_x11Info(const QPaintDevice *pd); diff --git a/src/gui/egl/qeglproperties.cpp b/src/gui/egl/qeglproperties.cpp index e0ae8a6..358ebcc 100644 --- a/src/gui/egl/qeglproperties.cpp +++ b/src/gui/egl/qeglproperties.cpp @@ -46,12 +46,26 @@ QT_BEGIN_NAMESPACE #include <QtCore/qdebug.h> #include <QtCore/qstringlist.h> +#include "qegl_p.h" + + // Initialize a property block. QEglProperties::QEglProperties() { props.append(EGL_NONE); } +QEglProperties::QEglProperties(EGLConfig cfg) +{ + props.append(EGL_NONE); + for (int name = 0x3020; name <= 0x304F; ++name) { + EGLint value; + if (name != EGL_NONE && eglGetConfigAttrib(QEglContext::defaultDisplay(0), cfg, name, &value)) + setValue(name, value); + } + eglGetError(); // Clear the error state. +} + // Fetch the current value associated with a property. int QEglProperties::value(int name) const { @@ -215,12 +229,21 @@ bool QEglProperties::reduceConfiguration() removeValue(EGL_SAMPLES); return true; } - if (removeValue(EGL_ALPHA_SIZE)) + if (removeValue(EGL_ALPHA_SIZE)) { +#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB) + if (removeValue(EGL_BIND_TO_TEXTURE_RGBA)) + setValue(EGL_BIND_TO_TEXTURE_RGB, TRUE); +#endif return true; + } if (removeValue(EGL_STENCIL_SIZE)) return true; if (removeValue(EGL_DEPTH_SIZE)) return true; +#if defined(EGL_BIND_TO_TEXTURE_RGB) + if (removeValue(EGL_BIND_TO_TEXTURE_RGB)) + return true; +#endif return false; } diff --git a/src/gui/egl/qeglproperties_p.h b/src/gui/egl/qeglproperties_p.h index 81af4cd..bcdc657 100644 --- a/src/gui/egl/qeglproperties_p.h +++ b/src/gui/egl/qeglproperties_p.h @@ -107,6 +107,7 @@ class Q_GUI_EXPORT QEglProperties { public: QEglProperties(); + QEglProperties(EGLConfig); QEglProperties(const QEglProperties& other) : props(other.props) {} ~QEglProperties() {} diff --git a/src/gui/embedded/qkbdqnx_qws.cpp b/src/gui/embedded/qkbdqnx_qws.cpp index 06163c7..089b868 100644 --- a/src/gui/embedded/qkbdqnx_qws.cpp +++ b/src/gui/embedded/qkbdqnx_qws.cpp @@ -6,11 +6,11 @@ ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** 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 diff --git a/src/gui/embedded/qkbdqnx_qws.h b/src/gui/embedded/qkbdqnx_qws.h index c046c8d..fa3ae56 100644 --- a/src/gui/embedded/qkbdqnx_qws.h +++ b/src/gui/embedded/qkbdqnx_qws.h @@ -6,11 +6,11 @@ ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** 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 diff --git a/src/gui/embedded/qmouseqnx_qws.cpp b/src/gui/embedded/qmouseqnx_qws.cpp index 98f8f06..59cd5be 100644 --- a/src/gui/embedded/qmouseqnx_qws.cpp +++ b/src/gui/embedded/qmouseqnx_qws.cpp @@ -6,11 +6,11 @@ ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** 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 diff --git a/src/gui/embedded/qmouseqnx_qws.h b/src/gui/embedded/qmouseqnx_qws.h index a61562e..f8cad4a 100644 --- a/src/gui/embedded/qmouseqnx_qws.h +++ b/src/gui/embedded/qmouseqnx_qws.h @@ -6,11 +6,11 @@ ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** 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 diff --git a/src/gui/embedded/qscreenqnx_qws.cpp b/src/gui/embedded/qscreenqnx_qws.cpp index 7101bc7..c79ee59 100644 --- a/src/gui/embedded/qscreenqnx_qws.cpp +++ b/src/gui/embedded/qscreenqnx_qws.cpp @@ -6,11 +6,11 @@ ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** 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 diff --git a/src/gui/embedded/qscreenqnx_qws.h b/src/gui/embedded/qscreenqnx_qws.h index 837c061..30312fe 100644 --- a/src/gui/embedded/qscreenqnx_qws.h +++ b/src/gui/embedded/qscreenqnx_qws.h @@ -6,11 +6,11 @@ ** This file is part of the QtGui module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. +** 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 diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 5aae93e..beaf42b 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 @@ -674,19 +675,22 @@ void QGraphicsItemPrivate::updateAncestorFlag(QGraphicsItem::GraphicsItemFlag ch return; } - // Inherit the enabled-state from our parents. - if ((parent && ((parent->d_ptr->ancestorFlags & flag) - || (int(parent->d_ptr->flags & childFlag) == childFlag) + if (parent) { + // Inherit the enabled-state from our parents. + if ((parent->d_ptr->ancestorFlags & flag) + || (int(parent->d_ptr->flags & childFlag) == childFlag) || (childFlag == -1 && parent->d_ptr->handlesChildEvents) - || (childFlag == -2 && parent->d_ptr->filtersDescendantEvents)))) { - enabled = true; - ancestorFlags |= flag; - } - - // Top-level root items don't have any ancestors, so there are no - // ancestor flags either. - if (!parent) + || (childFlag == -2 && parent->d_ptr->filtersDescendantEvents)) { + enabled = true; + ancestorFlags |= flag; + } else { + ancestorFlags &= ~flag; + } + } else { + // Top-level root items don't have any ancestors, so there are no + // ancestor flags either. ancestorFlags = 0; + } } else { // Don't set or propagate the ancestor flag if it's already correct. if (((ancestorFlags & flag) && enabled) || (!(ancestorFlags & flag) && !enabled)) @@ -2969,11 +2973,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 +2990,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 +3008,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). - \warning The value doesn't take in account any rotation set with the setTransform() method. + 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(). + + 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 +3040,13 @@ void QGraphicsItem::setRotation(qreal angle) /*! \since 4.6 - Returns the scale factor of the item. - - The default is 1 + Returns the scale factor of the item. The default scale factor is 1.0 + (i.e., the item is not scaled). - \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 setScale(), {Transformations} + \sa setScale(), rotation(), {Transformations} */ qreal QGraphicsItem::scale() const { @@ -3045,9 +3058,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). - \warning The value doesn't take in account any scaling set with the setTransform() method. + 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(). + + 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 +3089,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 +3111,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 +3140,9 @@ void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transf d_ptr->dirtySceneTransform = 1; } - +/*! + \internal +*/ void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t) { if (!transformData) @@ -3432,7 +3476,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 +3537,14 @@ void QGraphicsItem::resetTransform() /*! \obsolete - Use setZRotation() instead + + Use + + \code + setRotation(rotation() + angle); + \endcode + + 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 +3554,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,7 +3563,14 @@ void QGraphicsItem::rotate(qreal angle) /*! \obsolete - Use setScale() instead + + Use + + \code + setTransform(QTransform::fromScale(sx, sy), true); + \endcode + + instead. Scales the current item transformation by (\a sx, \a sy) around its origin. To scale from an arbitrary point (x, y), you need to combine @@ -3522,8 +3580,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 +3589,16 @@ void QGraphicsItem::scale(qreal sx, qreal sy) /*! \obsolete - Use setShear instead. - Shears the current item transformation by (\a sh, \a sv). + Use - \warning using this function has no effect on the horizontalShear or verticalShear value + \code + setTransform(QTransform().shear(sh, sv), true); + \endcode + + instead. + + Shears the current item transformation by (\a sh, \a sv). \sa setTransform(), transform() */ @@ -3548,7 +3609,13 @@ void QGraphicsItem::shear(qreal sh, qreal sv) /*! \obsolete - Use setPos() or setTransformOriginPoint() instead. + + Use setPos() or setTransformOriginPoint() instead. For identical + behavior, use + + \code + setTransform(QTransform::fromTranslate(dx, dy), true); + \endcode Translates the current item transformation by (\a dx, \a dy). @@ -6320,7 +6387,7 @@ void QGraphicsItem::inputMethodEvent(QInputMethodEvent *event) surrounding text and reconversions. \a query specifies which property is queried. - \sa inputMethodEvent() + \sa inputMethodEvent(), QInputMethodEvent, QInputContext */ QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const { @@ -6336,6 +6403,39 @@ QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const } /*! + Returns the current input method hints of this item. + + Input method hints are only relevant for input items. + The hints are used by the input method to indicate how it should operate. + For example, if the Qt::ImhNumbersOnly flag is set, the input method may change + its visual components to reflect that only numbers can be entered. + + The effect may vary between input method implementations. + + \since 4.6 + + \sa setInputMethodHints(), inputMethodQuery(), QInputContext +*/ +Qt::InputMethodHints QGraphicsItem::inputMethodHints() const +{ + Q_D(const QGraphicsItem); + return d->imHints; +} + +/*! + Sets the current input method hints of this item to \a hints. + + \since 4.6 + + \sa inputMethodHints(), inputMethodQuery(), QInputContext +*/ +void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints) +{ + Q_D(QGraphicsItem); + d->imHints = hints; +} + +/*! This virtual function is called by QGraphicsItem to notify custom items that some part of the item's state changes. By reimplementing this function, your can react to a change, and in some cases, (depending on \a @@ -6462,7 +6562,7 @@ void QGraphicsItem::prepareGeometryChange() // if someone is connected to the changed signal or the scene has no views. // Note that this has to be done *after* markDirty to ensure that // _q_processDirtyItems is called before _q_emitUpdated. - if ((scenePrivate->connectedSignals & scenePrivate->changedSignalMask) + if ((scenePrivate->connectedSignals[0] & scenePrivate->changedSignalMask) || scenePrivate->views.isEmpty()) { if (d_ptr->hasTranslateOnlySceneTransform()) { d_ptr->scene->update(boundingRect().translated(d_ptr->sceneTransform.dx(), diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index b94fb97..f142b0f 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -375,6 +375,9 @@ public: QVariant data(int key) const; void setData(int key, const QVariant &value); + Qt::InputMethodHints inputMethodHints() const; + void setInputMethodHints(Qt::InputMethodHints hints); + enum { Type = 1, UserType = 65536 diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index b8d98c1..805b554 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -126,6 +126,7 @@ public: depth(0), focusProxy(0), subFocusItem(0), + imHints(Qt::ImhNone), acceptedMouseButtons(0x1f), visible(1), explicitlyHidden(0), @@ -419,8 +420,9 @@ public: int depth; QGraphicsItem *focusProxy; QGraphicsItem *subFocusItem; + Qt::InputMethodHints imHints; - // Packed 32 bytes + // Packed 32 bits quint32 acceptedMouseButtons : 5; quint32 visible : 1; quint32 explicitlyHidden : 1; @@ -468,7 +470,8 @@ public: QGraphicsItem *q_ptr; }; -struct QGraphicsItemPrivate::TransformData { +struct QGraphicsItemPrivate::TransformData +{ QTransform transform; qreal scale; qreal rotation; @@ -481,7 +484,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/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index a846cf6..da4a347 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -344,7 +344,7 @@ void QGraphicsScenePrivate::_q_emitUpdated() // the optimization that items send updates directly to the views, but it // needs to happen in order to keep compatibility with the behavior from // Qt 4.4 and backward. - if (connectedSignals & changedSignalMask) { + if (connectedSignals[0] & changedSignalMask) { for (int i = 0; i < views.size(); ++i) { QGraphicsView *view = views.at(i); if (!view->d_func()->connectedToScene) { @@ -2899,7 +2899,7 @@ void QGraphicsScene::update(const QRectF &rect) // Check if anyone's connected; if not, we can send updates directly to // the views. Otherwise or if there are no views, use old behavior. - bool directUpdates = !(d->connectedSignals & d->changedSignalMask) && !d->views.isEmpty(); + bool directUpdates = !(d->connectedSignals[0] & d->changedSignalMask) && !d->views.isEmpty(); if (rect.isNull()) { d->updateAll = true; d->updatedRects.clear(); @@ -4477,7 +4477,7 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b if (removingItemFromScene) { // Note that this function can be called from the item's destructor, so // do NOT call any virtual functions on it within this block. - if ((connectedSignals & changedSignalMask) || views.isEmpty()) { + if ((connectedSignals[0] & changedSignalMask) || views.isEmpty()) { // This block of code is kept for compatibility. Since 4.5, by default // QGraphicsView does not connect the signal and we use the below // method of delivering updates. @@ -4623,7 +4623,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool // Process item. if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) { - const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); + const bool useCompatUpdate = views.isEmpty() || (connectedSignals[0] & changedSignalMask); const QRectF itemBoundingRect = adjustedItemBoundingRect(item); if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) { 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..778cd94 100644 --- a/src/gui/graphicsview/qgraphicstransform.cpp +++ b/src/gui/graphicsview/qgraphicstransform.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtDeclarative module of the Qt Toolkit. ** @@ -34,11 +34,48 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ +/*! + \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_mac.cpp b/src/gui/image/qpixmap_mac.cpp index 45392f1..5568898 100644 --- a/src/gui/image/qpixmap_mac.cpp +++ b/src/gui/image/qpixmap_mac.cpp @@ -1178,6 +1178,7 @@ QPixmap QPixmap::fromMacCGImageRef(CGImageRef image) const size_t w = CGImageGetWidth(image), h = CGImageGetHeight(image); QPixmap ret(w, h); + ret.fill(Qt::transparent); CGRect rect = CGRectMake(0, 0, w, h); CGContextRef ctx = qt_mac_cg_context(&ret); qt_mac_drawCGImage(ctx, &rect, image); 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/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 8b6b5cb..94569ec 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -960,6 +960,7 @@ void QAbstractItemView::reset() d->currentIndexSet = false; setState(NoState); setRootIndex(QModelIndex()); + d->selectionModel->reset(); } /*! diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp index 336ca79..bd6dc62 100644 --- a/src/gui/itemviews/qitemdelegate.cpp +++ b/src/gui/itemviews/qitemdelegate.cpp @@ -1226,21 +1226,19 @@ bool QItemDelegate::eventFilter(QObject *object, QEvent *event) } else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) { //the Hide event will take care of he editors that are in fact complete dialogs if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) { - if (editor->isAncestorOf(QApplication::focusWidget())) - return false; // don't worry about focus changes internally in the editor - + QWidget *w = QApplication::focusWidget(); + while (w) { // don't worry about focus changes internally in the editor + if (w == editor) + return false; + w = w->parentWidget(); + } #ifndef QT_NO_DRAGANDDROP // The window may lose focus during an drag operation. // i.e when dragging involves the taskbar on Windows. if (QDragManager::self() && QDragManager::self()->object != 0) return false; #endif - // Opening a modal dialog will start a new eventloop - // that will process the deleteLater event. - if (QApplication::activeModalWidget() - && !QApplication::activeModalWidget()->isAncestorOf(editor) - && qobject_cast<QDialog*>(QApplication::activeModalWidget())) - return false; + emit commitData(editor); emit closeEditor(editor, NoHint); } @@ -1298,8 +1296,14 @@ bool QItemDelegate::editorEvent(QEvent *event, return false; } - Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked + Qt::CheckState state; + if ( flags & Qt::ItemIsTristate ) { + state = static_cast<Qt::CheckState>( (value.toInt() + 1) % 3 ); + } else { + state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked ? Qt::Unchecked : Qt::Checked); + } + return model->setData(index, state, Qt::CheckStateRole); } diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp index bd8fdac..34667ee 100644 --- a/src/gui/itemviews/qstyleditemdelegate.cpp +++ b/src/gui/itemviews/qstyleditemdelegate.cpp @@ -674,22 +674,19 @@ bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event) } else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) { //the Hide event will take care of he editors that are in fact complete dialogs if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) { - if (editor->isAncestorOf(QApplication::focusWidget())) - return false; // don't worry about focus changes internally in the editor - + QWidget *w = QApplication::focusWidget(); + while (w) { // don't worry about focus changes internally in the editor + if (w == editor) + return false; + w = w->parentWidget(); + } #ifndef QT_NO_DRAGANDDROP // The window may lose focus during an drag operation. // i.e when dragging involves the taskbar on Windows. if (QDragManager::self() && QDragManager::self()->object != 0) return false; #endif - // Opening a modal dialog will start a new eventloop - // that will process the deleteLater event. - QWidget *activeModalWidget = QApplication::activeModalWidget(); - if (activeModalWidget - && !activeModalWidget->isAncestorOf(editor) - && qobject_cast<QDialog*>(activeModalWidget)) - return false; + emit commitData(editor); emit closeEditor(editor, NoHint); } @@ -749,8 +746,13 @@ bool QStyledItemDelegate::editorEvent(QEvent *event, return false; } - Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked + Qt::CheckState state; + if ( flags & Qt::ItemIsTristate ) { + state = static_cast<Qt::CheckState>( (value.toInt() + 1) % 3 ); + } else { + state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked ? Qt::Unchecked : Qt::Checked); + } return model->setData(index, state, Qt::CheckStateRole); } diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h index 133fab4..cb681c4 100644 --- a/src/gui/kernel/qaction.h +++ b/src/gui/kernel/qaction.h @@ -68,24 +68,24 @@ class Q_GUI_EXPORT QAction : public QObject Q_ENUMS(MenuRole) Q_ENUMS(Priority) - Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable) + Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY changed) Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled) - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) - Q_PROPERTY(QIcon icon READ icon WRITE setIcon) - Q_PROPERTY(QString text READ text WRITE setText) - Q_PROPERTY(QString iconText READ iconText WRITE setIconText) - Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip) - Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip) - Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis) - Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY changed) + Q_PROPERTY(QIcon icon READ icon WRITE setIcon NOTIFY changed) + Q_PROPERTY(QString text READ text WRITE setText NOTIFY changed) + Q_PROPERTY(QString iconText READ iconText WRITE setIconText NOTIFY changed) + Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY changed) + Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip NOTIFY changed) + Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis NOTIFY changed) + Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed) #ifndef QT_NO_SHORTCUT - Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) - Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext) - Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat) + Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut NOTIFY changed) + Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext NOTIFY changed) + Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY changed) #endif - Q_PROPERTY(bool visible READ isVisible WRITE setVisible) - Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole) - Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu) + Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed) + Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed) + Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed) Q_PROPERTY(Priority priority READ priority WRITE setPriority) public: diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 5181689..c24ff49 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() @@ -4051,7 +4052,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) touchEvent->setAccepted(eventAccepted); break; } - case QEvent::WinGesture: + case QEvent::NativeGesture: { // only propagate the first gesture event (after the GID_BEGIN) QWidget *w = static_cast<QWidget *>(receiver); @@ -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/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index beccfb0..ac132aa 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1480,6 +1480,7 @@ QWidget *QApplicationPrivate::tryModalHelper_sys(QWidget *top) return top; } +#ifndef QT_MAC_USE_COCOA static bool qt_try_modal(QWidget *widget, EventRef event) { QWidget * top = 0; @@ -1513,6 +1514,7 @@ static bool qt_try_modal(QWidget *widget, EventRef event) #endif return !block_event; } +#endif OSStatus QApplicationPrivate::tabletProximityCallback(EventHandlerCallRef, EventRef carbonEvent, void *) @@ -2890,52 +2892,25 @@ bool QApplicationPrivate::canQuit() #endif } -void onApplicationWindowChangedActivation( QWidget*widget, bool activated ) +void onApplicationWindowChangedActivation(QWidget *widget, bool activated) { #if QT_MAC_USE_COCOA - QApplication *app = qApp; + if (!widget) + return; - if ( activated ) - { - if (QApplicationPrivate::app_style) - { + if (activated) { + if (QApplicationPrivate::app_style) { QEvent ev(QEvent::Style); qt_sendSpontaneousEvent(QApplicationPrivate::app_style, &ev); } - - if (widget && app_do_modal && !qt_try_modal(widget, NULL)) - return; - - if (widget && widget->window()->isVisible()) - { - QWidget *tlw = widget->window(); - - if (tlw->isWindow() && !(tlw->windowType() == Qt::Popup) - && !qt_mac_is_macdrawer(tlw) - && (!tlw->parentWidget() || tlw->isModal() || !(tlw->windowType() == Qt::Tool))) { - bool just_send_event = false; -#if 0 - WindowActivationScope scope; - if ( GetWindowActivationScope((OSWindowRef)wid, &scope) == noErr && - scope == kWindowActivationScopeIndependent) - { - if ( GetFrontWindowOfClass(kAllWindowClasses, true) != wid ) - just_send_event = true; - } -#endif - if (just_send_event) { - QEvent e(QEvent::WindowActivate); - qt_sendSpontaneousEvent(widget, &e); - } else { - app->setActiveWindow(tlw); - } - } - } + qApp->setActiveWindow(widget); } else { // deactivated - if (widget && QApplicationPrivate::active_window == widget) - app->setActiveWindow(0); + if (QApplicationPrivate::active_window == widget) + qApp->setActiveWindow(0); } + QMenuBar::macUpdateMenuBar(); + #else Q_UNUSED(widget); Q_UNUSED(activated); diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index d5c820c..2bded5c 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -3735,22 +3735,22 @@ bool QETWidget::translateGestureEvent(const MSG &msg) alienWidget = 0; QWidget *widget = alienWidget ? alienWidget : this; - QWinGestureEvent event; + QNativeGestureEvent event; event.sequenceId = gi.dwSequenceID; event.position = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); if (bResult) { switch (gi.dwID) { case GID_BEGIN: - // we are not interested in this type of event. + event.gestureType = QNativeGestureEvent::GestureBegin; break; case GID_END: - event.gestureType = QWinGestureEvent::GestureEnd; + event.gestureType = QNativeGestureEvent::GestureEnd; break; case GID_ZOOM: - event.gestureType = QWinGestureEvent::Pinch; + event.gestureType = QNativeGestureEvent::Pinch; break; case GID_PAN: - event.gestureType = QWinGestureEvent::Pan; + event.gestureType = QNativeGestureEvent::Pan; break; case GID_ROTATE: case GID_TWOFINGERTAP: @@ -3758,7 +3758,7 @@ bool QETWidget::translateGestureEvent(const MSG &msg) default: break; } - if (event.gestureType != QWinGestureEvent::None) + if (event.gestureType != QNativeGestureEvent::None) qt_sendSpontaneousEvent(widget, &event); } else { DWORD dwErr = GetLastError(); diff --git a/src/gui/kernel/qboxlayout.cpp b/src/gui/kernel/qboxlayout.cpp index 770f5bb..23d20ff 100644 --- a/src/gui/kernel/qboxlayout.cpp +++ b/src/gui/kernel/qboxlayout.cpp @@ -527,7 +527,7 @@ void QBoxLayoutPrivate::calcHfw(int w) You will almost always want to use QVBoxLayout and QHBoxLayout rather than QBoxLayout because of their convenient constructors. - \sa QGridLayout, QStackedLayout, {Layout Classes} + \sa QGridLayout, QStackedLayout, {Layout Management} */ /*! @@ -1295,7 +1295,7 @@ QBoxLayout::Direction QBoxLayout::direction() const \image qhboxlayout-with-5-children.png Horizontal box layout with five child widgets - \sa QVBoxLayout, QGridLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example} + \sa QVBoxLayout, QGridLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example} */ @@ -1413,7 +1413,7 @@ QHBoxLayout::~QHBoxLayout() \image qvboxlayout-with-5-children.png Horizontal box layout with five child widgets - \sa QHBoxLayout, QGridLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example} + \sa QHBoxLayout, QGridLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example} */ /*! diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 57c9117..1d352cb 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -327,7 +327,7 @@ extern "C" { return NSDragOperationNone; } else { // save the mouse position, used by draggingExited handler. - DnDParams *dndParams = [QCocoaView currentMouseEvent]; + DnDParams *dndParams = [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]; dndParams->activeDragEnterPos = windowPoint; // send a drag move event immediately after a drag enter event (as per documentation). QDragMoveEvent qDMEvent(posDrag, qtAllowed, mimeData, QApplication::mouseButtons(), modifiers); @@ -406,7 +406,7 @@ extern "C" { dragEnterSequence = -1; if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) { // try sending the leave event to the last view which accepted drag enter. - DnDParams *dndParams = [QCocoaView currentMouseEvent]; + DnDParams *dndParams = [QT_MANGLE_NAMESPACE(QCocoaView) currentMouseEvent]; NSView *candidateView = [[[self window] contentView] hitTest:dndParams->activeDragEnterPos]; if (candidateView && candidateView != self) return [candidateView draggingExited:sender]; diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp index 9cca0d6..0b47b6f 100644 --- a/src/gui/kernel/qcursor.cpp +++ b/src/gui/kernel/qcursor.cpp @@ -127,11 +127,11 @@ QT_BEGIN_NAMESPACE \o Qt::SizeAllCursor \o \c size_all \row \o \inlineimage cursor-busy.png \o Qt::BusyCursor \o \c left_ptr_watch - \o \inlineimage cursor-hsplit.png + \o \inlineimage cursor-vsplit.png \o Qt::SplitVCursor \o \c split_v \row \o \inlineimage cursor-forbidden.png \o Qt::ForbiddenCursor \o \c forbidden - \o \inlineimage cursor-vsplit.png + \o \inlineimage cursor-hsplit.png \o Qt::SplitHCursor \o \c split_h \row \o \inlineimage cursor-hand.png \o Qt::PointingHandCursor \o \c pointing_hand diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index bc3633c..0fc36e7 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -49,7 +49,6 @@ #include "qmime.h" #include "qdnd_p.h" #include "qevent_p.h" -#include "qgesture.h" QT_BEGIN_NAMESPACE diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index 67441ea..92c4fc1 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -119,20 +119,30 @@ public: qreal pressure; }; -class QWinGestureEvent : public QEvent +class QNativeGestureEvent : public QEvent { public: enum Type { None, + GestureBegin, GestureEnd, Pan, Pinch }; - QWinGestureEvent() : QEvent(QEvent::WinGesture), gestureType(None), sequenceId(0) { } + QNativeGestureEvent() + : QEvent(QEvent::NativeGesture), gestureType(None) +#ifdef Q_WS_WIN + , sequenceId(0) +#endif + { + } + Type gestureType; +#ifdef Q_WS_WIN QPoint position; ulong sequenceId; +#endif }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qformlayout.cpp b/src/gui/kernel/qformlayout.cpp index 0b7656f..de33f93 100644 --- a/src/gui/kernel/qformlayout.cpp +++ b/src/gui/kernel/qformlayout.cpp @@ -689,16 +689,12 @@ void QFormLayoutPrivate::setupVerticalLayoutData(int width) // are split. maxLabelWidth = 0; if (!wrapAllRows) { - int maxFieldMinWidth = 0; //the maximum minimum size of the field for (int i = 0; i < rr; ++i) { const QFormLayoutItem *label = m_matrix(i, 0); const QFormLayoutItem *field = m_matrix(i, 1); - if (label && field && label->sideBySide) + if (label && (label->sizeHint.width() + (field ? field->minSize.width() : 0) <= width)) maxLabelWidth = qMax(maxLabelWidth, label->sizeHint.width()); - if (field) - maxFieldMinWidth = qMax(maxFieldMinWidth, field->minSize.width() + field->sbsHSpace); } - maxLabelWidth = qMin(maxLabelWidth, width - maxFieldMinWidth); } else { maxLabelWidth = width; } diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index d53b419..8075ad9 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -97,7 +97,7 @@ private: This is a base class, to create a custom gesture type, you should subclass it and implement its pure virtual functions. - \sa QPanGesture, QTapAndHoldGesture + \sa QPanGesture */ /*! \fn bool QGesture::filterEvent(QEvent *event) @@ -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); } /*! @@ -205,51 +205,6 @@ void QGesture::setState(Qt::GestureState state) } /*! - \property QGesture::startPos - - \brief The start position of the gesture (if relevant). -*/ -QPoint QGesture::startPos() const -{ - return d_func()->startPos; -} - -void QGesture::setStartPos(const QPoint &point) -{ - d_func()->startPos = point; -} - -/*! - \property QGesture::lastPos - - \brief The last recorded position of the gesture (if relevant). -*/ -QPoint QGesture::lastPos() const -{ - return d_func()->lastPos; -} - -void QGesture::setLastPos(const QPoint &point) -{ - d_func()->lastPos = point; -} - -/*! - \property QGesture::pos - - \brief The current position of the gesture (if relevant). -*/ -QPoint QGesture::pos() const -{ - return d_func()->pos; -} - -void QGesture::setPos(const QPoint &point) -{ - d_func()->pos = point; -} - -/*! Sets the \a graphicsItem the gesture is filtering events for. The gesture will install an event filter to the \a graphicsItem and diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index 1cd9cae..0735160 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -64,10 +64,6 @@ class Q_GUI_EXPORT QGesture : public QObject Q_PROPERTY(Qt::GestureState state READ state) - Q_PROPERTY(QPoint startPos READ startPos WRITE setStartPos) - Q_PROPERTY(QPoint lastPos READ lastPos WRITE setLastPos) - Q_PROPERTY(QPoint pos READ pos WRITE setPos) - public: explicit QGesture(QObject *parent = 0); ~QGesture(); @@ -80,19 +76,13 @@ public: virtual void reset(); Qt::GestureState state() const; - void setState(Qt::GestureState state); - - QPoint startPos() const; - void setStartPos(const QPoint &point); - QPoint lastPos() const; - void setLastPos(const QPoint &point); - QPoint pos() const; - void setPos(const QPoint &point); protected: QGesture(QGesturePrivate &dd, QObject *parent); bool eventFilter(QObject*, QEvent*); + void setState(Qt::GestureState state); + Q_SIGNALS: void started(); void triggered(); diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index 99f572f..56eaee7 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -73,22 +73,11 @@ public: { } - void init(const QPoint &startPos, const QPoint &lastPos, - const QPoint &pos) - { - this->startPos = startPos; - this->lastPos = lastPos; - this->pos = pos; - } QGraphicsItem *graphicsItem; QGraphicsItem *eventFilterProxyGraphicsItem; Qt::GestureState state; - - QPoint startPos; - QPoint lastPos; - QPoint pos; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qgridlayout.cpp b/src/gui/kernel/qgridlayout.cpp index 7ac874e..558f570 100644 --- a/src/gui/kernel/qgridlayout.cpp +++ b/src/gui/kernel/qgridlayout.cpp @@ -1046,7 +1046,7 @@ QRect QGridLayoutPrivate::cellRect(int row, int col) const the margin width for a top-level layout, or to the same as the parent layout. - \sa QBoxLayout, QStackedLayout, {Layout Classes}, {Basic Layouts Example} + \sa QBoxLayout, QStackedLayout, {Layout Management}, {Basic Layouts Example} */ diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp index e750088..941db8f 100644 --- a/src/gui/kernel/qlayout.cpp +++ b/src/gui/kernel/qlayout.cpp @@ -83,7 +83,7 @@ static int menuBarHeightForWidth(QWidget *menubar, int w) For users of QLayout subclasses or of QMainWindow there is seldom any need to use the basic functions provided by QLayout, such as - setSizeConstraint() or setMenuBar(). See \l{Layout Classes} + setSizeConstraint() or setMenuBar(). See \l{Layout Management} for more information. To make your own layout manager, implement the functions @@ -98,7 +98,7 @@ static int menuBarHeightForWidth(QWidget *menubar, int w) Geometry management stops when the layout manager is deleted. - \sa QLayoutItem, {Layout Classes}, {Basic Layouts Example}, + \sa QLayoutItem, {Layout Management}, {Basic Layouts Example}, {Border Layout Example}, {Flow Layout Example} */ diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp index c8b11c5..4753416 100644 --- a/src/gui/kernel/qstandardgestures.cpp +++ b/src/gui/kernel/qstandardgestures.cpp @@ -45,9 +45,14 @@ #include <qabstractscrollarea.h> #include <qscrollbar.h> #include <private/qapplication_p.h> +#include <private/qevent_p.h> QT_BEGIN_NAMESPACE +#ifdef Q_WS_WIN +QApplicationPrivate* getQApplicationPrivateInternal(); +#endif + /*! \class QPanGesture \since 4.6 @@ -68,7 +73,6 @@ QPanGesture::QPanGesture(QWidget *parent) { #ifdef Q_WS_WIN if (parent) { - QApplicationPrivate* getQApplicationPrivateInternal(); QApplicationPrivate *qAppPriv = getQApplicationPrivateInternal(); qAppPriv->widgetGestures[parent].pan = this; } @@ -93,9 +97,81 @@ bool QPanGesture::event(QEvent *event) break; } #endif + +#if defined(Q_OS_MAC) && !defined(QT_MAC_USE_COCOA) + Q_D(QPanGesture); + if (event->type() == QEvent::Timer) { + const QTimerEvent *te = static_cast<QTimerEvent *>(event); + if (te->timerId() == d->panFinishedTimer) { + killTimer(d->panFinishedTimer); + d->panFinishedTimer = 0; + d->lastOffset = QSize(0, 0); + setState(Qt::GestureFinished); + emit triggered(); + setState(Qt::NoGesture); + } + } +#endif + return QObject::event(event); } +bool QPanGesture::eventFilter(QObject *receiver, QEvent *event) +{ +#ifdef Q_WS_WIN + if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) { + QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); + QApplicationPrivate *qAppPriv = getQApplicationPrivateInternal(); + QApplicationPrivate::WidgetStandardGesturesMap::iterator it; + it = qAppPriv->widgetGestures.find(static_cast<QWidget*>(receiver)); + if (it == qAppPriv->widgetGestures.end()) + return false; + QPanGesture *gesture = it.value().pan; + if (!gesture) + return false; + Qt::GestureState nextState = state(); + switch(ev->gestureType) { + case QNativeGestureEvent::GestureBegin: + // next we might receive the first gesture update event, so we + // prepare for it. + setState(Qt::GestureStarted); + return false; + case QNativeGestureEvent::Pan: + nextState = Qt::GestureUpdated; + break; + case QNativeGestureEvent::GestureEnd: + if (state() != QNativeGestureEvent::Pan) + return false; // some other gesture has ended + setState(Qt::GestureFinished); + nextState = Qt::GestureFinished; + break; + default: + return false; + } + QPanGesturePrivate *d = gesture->d_func(); + if (state() == Qt::GestureStarted) { + d->lastPosition = ev->position; + d->lastOffset = d->totalOffset = QSize(); + } else { + d->lastOffset = QSize(ev->position.x() - d->lastPosition.x(), + ev->position.y() - d->lastPosition.y()); + d->totalOffset += d->lastOffset; + } + d->lastPosition = ev->position; + + if (state() == Qt::GestureStarted) + emit gesture->started(); + emit gesture->triggered(); + if (state() == Qt::GestureFinished) + emit gesture->finished(); + event->accept(); + gesture->setState(nextState); + return true; + } +#endif + return QGesture::eventFilter(receiver, event); +} + /*! \internal */ bool QPanGesture::filterEvent(QEvent *event) { @@ -104,28 +180,34 @@ bool QPanGesture::filterEvent(QEvent *event) return false; const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); if (event->type() == QEvent::TouchBegin) { - d->touchPoints = ev->touchPoints(); - const QPoint p = ev->touchPoints().at(0).pos().toPoint(); - setStartPos(p); - setLastPos(p); - setPos(p); - return false; + QTouchEvent::TouchPoint p = ev->touchPoints().at(0); + d->lastPosition = p.pos().toPoint(); + d->lastOffset = d->totalOffset = QSize(); } else if (event->type() == QEvent::TouchEnd) { if (state() != Qt::NoGesture) { setState(Qt::GestureFinished); - setLastPos(pos()); - setPos(ev->touchPoints().at(0).pos().toPoint()); + if (!ev->touchPoints().isEmpty()) { + QTouchEvent::TouchPoint p = ev->touchPoints().at(0); + const QPoint pos = p.pos().toPoint(); + const QPoint lastPos = p.lastPos().toPoint(); + const QPoint startPos = p.startPos().toPoint(); + d->lastOffset = QSize(pos.x() - lastPos.x(), pos.y() - lastPos.y()); + d->totalOffset = QSize(pos.x() - startPos.x(), pos.y() - startPos.y()); + } emit triggered(); emit finished(); } setState(Qt::NoGesture); reset(); } else if (event->type() == QEvent::TouchUpdate) { - d->touchPoints = ev->touchPoints(); - QPointF pt = d->touchPoints.at(0).pos() - d->touchPoints.at(0).startPos(); - setLastPos(pos()); - setPos(ev->touchPoints().at(0).pos().toPoint()); - if (pt.x() > 10 || pt.y() > 10 || pt.x() < -10 || pt.y() < -10) { + QTouchEvent::TouchPoint p = ev->touchPoints().at(0); + const QPoint pos = p.pos().toPoint(); + const QPoint lastPos = p.lastPos().toPoint(); + const QPoint startPos = p.startPos().toPoint(); + d->lastOffset = QSize(pos.x() - lastPos.x(), pos.y() - lastPos.y()); + d->totalOffset = QSize(pos.x() - startPos.x(), pos.y() - startPos.y()); + if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 || + d->totalOffset.width() < -10 || d->totalOffset.height() < -10) { if (state() == Qt::NoGesture) setState(Qt::GestureStarted); else @@ -133,6 +215,36 @@ bool QPanGesture::filterEvent(QEvent *event) emit triggered(); } } +#ifdef Q_OS_MAC + else if (event->type() == QEvent::Wheel) { + // On Mac, there is really no native panning gesture. Instead, a two + // finger pan is delivered as mouse wheel events. Otoh, on Windows, you + // either get mouse wheel events or pan events. We have decided to make this + // the Qt behaviour as well, meaning that on Mac, wheel + // events will be masked away when listening for pan events. +#ifndef QT_MAC_USE_COCOA + // In Carbon we receive neither touch-, nor pan gesture events. + // So we create pan gestures by converting wheel events. After all, this + // is how things are supposed to work on mac in the first place. + const QWheelEvent *wev = static_cast<const QWheelEvent*>(event); + int offset = wev->delta() / -120; + d->lastOffset = wev->orientation() == Qt::Horizontal ? QSize(offset, 0) : QSize(0, offset); + + if (state() == Qt::NoGesture) { + setState(Qt::GestureStarted); + d->totalOffset = d->lastOffset; + } else { + setState(Qt::GestureUpdated); + d->totalOffset += d->lastOffset; + } + + killTimer(d->panFinishedTimer); + d->panFinishedTimer = startTimer(200); + emit triggered(); +#endif + return true; + } +#endif return false; } @@ -140,7 +252,14 @@ bool QPanGesture::filterEvent(QEvent *event) void QPanGesture::reset() { Q_D(QPanGesture); - d->touchPoints.clear(); + d->lastOffset = d->totalOffset = QSize(); + d->lastPosition = QPoint(); +#if defined(Q_OS_MAC) && !defined(QT_MAC_USE_COCOA) + if (d->panFinishedTimer) { + killTimer(d->panFinishedTimer); + d->panFinishedTimer = 0; + } +#endif } /*! @@ -150,8 +269,8 @@ void QPanGesture::reset() */ QSize QPanGesture::totalOffset() const { - QPoint pt = pos() - startPos(); - return QSize(pt.x(), pt.y()); + Q_D(const QPanGesture); + return d->totalOffset; } /*! @@ -162,93 +281,11 @@ QSize QPanGesture::totalOffset() const */ QSize QPanGesture::lastOffset() const { - QPoint pt = pos() - lastPos(); - return QSize(pt.x(), pt.y()); -} - -/*! - \class QTapAndHoldGesture - \since 4.6 - - \brief The QTapAndHoldGesture class represents a Tap-and-Hold gesture, - providing additional information. -*/ - -const int QTapAndHoldGesturePrivate::iterationCount = 40; -const int QTapAndHoldGesturePrivate::iterationTimeout = 50; - -/*! - Creates a new Tap and Hold gesture handler object and marks it as a child - of \a parent. - - On some platforms like Windows there is a system-wide tap and hold gesture - that cannot be overriden, hence the gesture might never trigger and default - context menu will be shown instead. -*/ -QTapAndHoldGesture::QTapAndHoldGesture(QWidget *parent) - : QGesture(*new QTapAndHoldGesturePrivate, parent) -{ -} - -/*! \internal */ -bool QTapAndHoldGesture::filterEvent(QEvent *event) -{ - Q_D(QTapAndHoldGesture); - if (!event->spontaneous()) - return false; - const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); - switch (event->type()) { - case QEvent::TouchBegin: { - if (d->timer.isActive()) - d->timer.stop(); - d->timer.start(QTapAndHoldGesturePrivate::iterationTimeout, this); - const QPoint p = ev->touchPoints().at(0).pos().toPoint(); - setStartPos(p); - setLastPos(p); - setPos(p); - break; - } - case QEvent::TouchUpdate: - if (ev->touchPoints().size() != 1) - reset(); - else if ((startPos() - ev->touchPoints().at(0).pos().toPoint()).manhattanLength() > 15) - reset(); - break; - case QEvent::TouchEnd: - reset(); - break; - default: - break; - } - return false; + Q_D(const QPanGesture); + return d->lastOffset; } -/*! \internal */ -void QTapAndHoldGesture::timerEvent(QTimerEvent *event) -{ - Q_D(QTapAndHoldGesture); - if (event->timerId() != d->timer.timerId()) - return; - if (d->iteration == QTapAndHoldGesturePrivate::iterationCount) { - d->timer.stop(); - setState(Qt::GestureFinished); - emit triggered(); - } else { - setState(Qt::GestureStarted); - emit triggered(); - } - ++d->iteration; -} +QT_END_NAMESPACE -/*! \internal */ -void QTapAndHoldGesture::reset() -{ - Q_D(QTapAndHoldGesture); - if (state() != Qt::NoGesture) - emit cancelled(); - setState(Qt::NoGesture); - d->timer.stop(); - d->iteration = 0; -} +#include "moc_qstandardgestures.cpp" -QT_END_NAMESPACE diff --git a/src/gui/kernel/qstandardgestures.h b/src/gui/kernel/qstandardgestures.h index 2234702..c734fba 100644 --- a/src/gui/kernel/qstandardgestures.h +++ b/src/gui/kernel/qstandardgestures.h @@ -71,29 +71,13 @@ public: QSize totalOffset() const; QSize lastOffset() const; -protected: +private: bool event(QEvent *event); + bool eventFilter(QObject *receiver, QEvent *event); -private: friend class QWidget; }; -class QTapAndHoldGesturePrivate; -class Q_GUI_EXPORT QTapAndHoldGesture : public QGesture -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QTapAndHoldGesture) - -public: - QTapAndHoldGesture(QWidget *parent); - - bool filterEvent(QEvent *event); - void reset(); - -protected: - void timerEvent(QTimerEvent *event); -}; - QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/kernel/qstandardgestures_p.h b/src/gui/kernel/qstandardgestures_p.h index bb11c9f..0fe24ee 100644 --- a/src/gui/kernel/qstandardgestures_p.h +++ b/src/gui/kernel/qstandardgestures_p.h @@ -60,6 +60,8 @@ #include "qgesture.h" #include "qgesture_p.h" +#include "qstandardgestures.h" + QT_BEGIN_NAMESPACE class QPanGesturePrivate : public QGesturePrivate @@ -67,23 +69,20 @@ class QPanGesturePrivate : public QGesturePrivate Q_DECLARE_PUBLIC(QPanGesture) public: - QPanGesturePrivate() { } - - QList<QTouchEvent::TouchPoint> touchPoints; -}; + QPanGesturePrivate() + { +#if defined(Q_OS_MAC) && !defined(QT_MAC_USE_COCOA) + panFinishedTimer = 0; +#endif + } -class QTapAndHoldGesturePrivate : public QGesturePrivate -{ - Q_DECLARE_PUBLIC(QTapAndHoldGesture) - -public: - QTapAndHoldGesturePrivate() - : iteration(0) { } + QSize totalOffset; + QSize lastOffset; + QPoint lastPosition; - QBasicTimer timer; - int iteration; - static const int iterationCount; - static const int iterationTimeout; +#if defined(Q_OS_MAC) && !defined(QT_MAC_USE_COCOA) + int panFinishedTimer; +#endif }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 7026525..a827967 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -505,7 +505,7 @@ void QWidget::setAutoFillBackground(bool enabled) been outlined to indicate their full sizes. If you want to use a QWidget to hold child widgets you will usually want to - add a layout to the parent QWidget. See \l{Layout Classes} for more + add a layout to the parent QWidget. See \l{Layout Management} for more information. @@ -1375,6 +1375,11 @@ QWidget::~QWidget() // set all QPointers for this object to zero QObjectPrivate::clearGuards(this); + if (d->declarativeData) { + d->declarativeData->destroyed(this); + d->declarativeData = 0; // don't activate again in ~QObject + } + if (!d->children.isEmpty()) d->deleteChildren(); @@ -3491,11 +3496,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; } @@ -3555,7 +3565,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; } @@ -3634,6 +3645,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); @@ -3675,7 +3688,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) @@ -7925,59 +7939,6 @@ bool QWidget::event(QEvent *event) (void) QApplication::sendEvent(this, &mouseEvent); break; } -#ifdef Q_WS_WIN - case QEvent::WinGesture: { - QWinGestureEvent *ev = static_cast<QWinGestureEvent*>(event); - QApplicationPrivate *qAppPriv = qApp->d_func(); - QApplicationPrivate::WidgetStandardGesturesMap::iterator it; - it = qAppPriv->widgetGestures.find(this); - if (it != qAppPriv->widgetGestures.end()) { - Qt::GestureState state = Qt::GestureUpdated; - if (qAppPriv->lastGestureId == 0) - state = Qt::GestureStarted; - QWinGestureEvent::Type type = ev->gestureType; - if (ev->gestureType == QWinGestureEvent::GestureEnd) { - type = (QWinGestureEvent::Type)qAppPriv->lastGestureId; - state = Qt::GestureFinished; - } - - QGesture *gesture = 0; - switch (type) { - case QWinGestureEvent::Pan: { - QPanGesture *pan = it.value().pan; - gesture = pan; - if (state == Qt::GestureStarted) { - gesture->setStartPos(ev->position); - gesture->setLastPos(ev->position); - } else { - gesture->setLastPos(gesture->pos()); - } - gesture->setPos(ev->position); - break; - } - case QWinGestureEvent::Pinch: - break; - default: - break; - } - if (gesture) { - gesture->setState(state); - if (state == Qt::GestureStarted) - emit gesture->started(); - emit gesture->triggered(); - if (state == Qt::GestureFinished) - emit gesture->finished(); - event->accept(); - } - if (ev->gestureType == QWinGestureEvent::GestureEnd) { - qAppPriv->lastGestureId = 0; - } else { - qAppPriv->lastGestureId = type; - } - } - break; - } -#endif #ifndef QT_NO_PROPERTIES case QEvent::DynamicPropertyChange: { const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName(); @@ -8854,7 +8815,7 @@ QRegion QWidget::mask() const The layout manager sets the geometry of the widget's children that have been added to the layout. - \sa setLayout(), sizePolicy(), {Layout Classes} + \sa setLayout(), sizePolicy(), {Layout Management} */ QLayout *QWidget::layout() const { @@ -8884,7 +8845,7 @@ QLayout *QWidget::layout() const The QWidget will take ownership of \a layout. - \sa layout(), {Layout Classes} + \sa layout(), {Layout Management} */ void QWidget::setLayout(QLayout *l) @@ -9850,6 +9811,10 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) data->window_modality = (w && w->testAttribute(Qt::WA_GroupLeader)) ? Qt::WindowModal : Qt::ApplicationModal; + // Some window managers does not allow us to enter modal after the + // window is showing. Therefore, to be consistent, we cannot call + // QApplicationPrivate::enterModal(this) here. The window must be + // hidden before changing modality. } if (testAttribute(Qt::WA_WState_Created)) { // don't call setModal_sys() before create_sys() diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 70eea3a..78df09d 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(); @@ -4584,6 +4589,7 @@ void QWidgetPrivate::setModal_sys() OSWindowRef windowRef = qt_mac_window_for(q); #ifdef QT_MAC_USE_COCOA + QMacCocoaAutoReleasePool pool; bool alreadySheet = [windowRef styleMask] & NSDocModalWindowMask; if (windowParent && q->windowModality() == Qt::WindowModal){ @@ -4660,31 +4666,40 @@ void QWidgetPrivate::setModal_sys() || (primaryWindow && primaryWindow->windowModality() == Qt::WindowModal)){ // Window should be window-modal (which implies a sheet). if (old_wclass != kSheetWindowClass){ - // We cannot convert a created window to a sheet. So we recreate the window: + // We cannot convert a created window to a sheet. + // So we recreate the window: recreateMacWindow(); return; } - } else if (!(q->data->window_flags & Qt::CustomizeWindowHint)) { - if (old_wclass == kDocumentWindowClass || old_wclass == kFloatingWindowClass || old_wclass == kUtilityWindowClass){ - // Only change the class to kMovableModalWindowClass if the no explicit jewels - // are set (kMovableModalWindowClass can't contain them), and the current window class - // can be converted to modal (according to carbon doc). Mind the order of - // HIWindowChangeClass and ChangeWindowAttributes. - WindowGroupRef group = GetWindowGroup(windowRef); - HIWindowChangeClass(windowRef, kMovableModalWindowClass); - quint32 tmpWattr = kWindowCloseBoxAttribute | kWindowHorizontalZoomAttribute; - ChangeWindowAttributes(windowRef, tmpWattr, kWindowNoAttributes); - ChangeWindowAttributes(windowRef, kWindowNoAttributes, tmpWattr); - // If the window belongs to a qt-created group, set that group once more: - if (data.window_flags & Qt::WindowStaysOnTopHint - || q->windowType() == Qt::Popup - || q->windowType() == Qt::ToolTip) - SetWindowGroup(windowRef, group); + } else { + // Window should be application-modal (which implies NOT using a sheet). + if (old_wclass == kSheetWindowClass){ + // We cannot convert a sheet to a window. + // So we recreate the window: + recreateMacWindow(); + return; + } else if (!(q->data->window_flags & Qt::CustomizeWindowHint)) { + if (old_wclass == kDocumentWindowClass || old_wclass == kFloatingWindowClass || old_wclass == kUtilityWindowClass){ + // Only change the class to kMovableModalWindowClass if the no explicit jewels + // are set (kMovableModalWindowClass can't contain them), and the current window class + // can be converted to modal (according to carbon doc). Mind the order of + // HIWindowChangeClass and ChangeWindowAttributes. + WindowGroupRef group = GetWindowGroup(windowRef); + HIWindowChangeClass(windowRef, kMovableModalWindowClass); + quint32 tmpWattr = kWindowCloseBoxAttribute | kWindowHorizontalZoomAttribute; + ChangeWindowAttributes(windowRef, tmpWattr, kWindowNoAttributes); + ChangeWindowAttributes(windowRef, kWindowNoAttributes, tmpWattr); + // If the window belongs to a qt-created group, set that group once more: + if (data.window_flags & Qt::WindowStaysOnTopHint + || q->windowType() == Qt::Popup + || q->windowType() == Qt::ToolTip) + SetWindowGroup(windowRef, group); + } + // Popups are usually handled "special" and are never modal. + Qt::WindowType winType = q->windowType(); + if (winType != Qt::Popup && winType != Qt::ToolTip) + SetWindowModality(windowRef, kWindowModalityAppModal, 0); } - // Popups are usually handled "special" and are never modal. - Qt::WindowType winType = q->windowType(); - if (winType != Qt::Popup && winType != Qt::ToolTip) - SetWindowModality(windowRef, kWindowModalityAppModal, 0); } } else if (windowRef) { if (old_wclass == kSheetWindowClass){ diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 46fa3be..b11b661 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) { @@ -1431,10 +1432,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) qt_wince_maximize(q); } else { #endif - if (!isTranslucentWindow) - MoveWindow(q->internalWinId(), fs.x(), fs.y(), fs.width(), fs.height(), true); - else if (isMove && !isResize) - SetWindowPos(q->internalWinId(), 0, fs.x(), fs.y(), 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER); + MoveWindow(q->internalWinId(), fs.x(), fs.y(), fs.width(), fs.height(), true); } if (!q->isVisible()) InvalidateRect(q->internalWinId(), 0, FALSE); @@ -1524,6 +1522,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/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index 831d389..fc2eb60 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -223,8 +223,8 @@ void qt_scale_image_16bit(uchar *destPixels, int dbpl, int h = ty2 - ty1; int w = tx2 - tx1; - const int dstx = int((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix); - const int dsty = int((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy); + const int dstx = qCeil((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix) - 1; + const int dsty = qCeil((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy) - 1; quint32 basex = quint32((sx < 0 ? srcRect.right() : srcRect.left()) * 65536) + dstx; quint32 srcy = quint32((sy < 0 ? srcRect.bottom() : srcRect.top()) * 65536) + dsty; @@ -723,8 +723,8 @@ template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl, int h = ty2 - ty1; int w = tx2 - tx1; - const int dstx = int((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix); - const int dsty = int((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy); + const int dstx = qCeil((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix) - 1; + const int dsty = qCeil((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy) - 1; quint32 basex = quint32((sx < 0 ? srcRect.right() : srcRect.left()) * 65536) + dstx; quint32 srcy = quint32((sy < 0 ? srcRect.bottom() : srcRect.top()) * 65536) + dsty; diff --git a/src/gui/painting/qdatabuffer_p.h b/src/gui/painting/qdatabuffer_p.h index b568f43..275ec13 100644 --- a/src/gui/painting/qdatabuffer_p.h +++ b/src/gui/painting/qdatabuffer_p.h @@ -114,23 +114,6 @@ public: qSwap(buffer, other.buffer); } - inline void insertBlank(int pos, int count) { - Q_ASSERT(pos >= 0); - Q_ASSERT(pos < siz); - reserve(siz + count); - for (int i = siz - pos - 1; i >= 0; --i) - buffer[pos + count + i] = buffer[pos + i]; - siz += count; - } - - inline void removeAndShift(int pos, int count) { - Q_ASSERT(pos >= 0); - Q_ASSERT(pos < siz); - for (int i=pos; i<siz-count; ++i) - buffer[i] = buffer[i+count]; - siz -= count; - } - inline QDataBuffer &operator<<(const Type &t) { add(t); return *this; } private: 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/qoutlinemapper.cpp b/src/gui/painting/qoutlinemapper.cpp index 9c073f2..1287672 100644 --- a/src/gui/painting/qoutlinemapper.cpp +++ b/src/gui/painting/qoutlinemapper.cpp @@ -40,7 +40,6 @@ ****************************************************************************/ #include "qoutlinemapper_p.h" -#include "qbezier_p.h" #include "qmath.h" @@ -199,70 +198,30 @@ void QOutlineMapper::endOutline() m_m22 * e.y() + m_m12 * e.x() + m_dy); } } else { - // ## TODO: this case needs to be plain code polygonal paths - QTransform matrix(m_m11, m_m12, m_m13, m_m21, m_m22, m_m23, m_dx, m_dy, m_m33); - - if (m_element_types.isEmpty()) { - if (!m_elements.isEmpty()) - m_elements_dev << m_elements.at(0) * matrix; - for (int i=1; i<m_elements.size(); ++i) - m_elements_dev << m_elements.at(i) * matrix; - - } else { - for (int i=0, t=0; i<m_elements.size(); ++i) { - switch (m_element_types.at(t)) { - case QPainterPath::MoveToElement: - m_elements_dev << m_elements.at(i) * matrix; - ++t; - break; - case QPainterPath::LineToElement: - m_elements_dev << m_elements.at(i) * matrix; - ++t; - break; - case QPainterPath::CurveToElement: { - QPolygonF segment = QBezier::fromPoints(m_elements.at(i-1), - m_elements.at(i), - m_elements.at(i+1), - m_elements.at(i+2)).toPolygon(); - if (segment.size() > 3) - m_element_types.insertBlank(t, segment.size() - 3); - else if (segment.size() < 3) - m_element_types.removeAndShift(t, 3 - segment.size()); - - for (QPolygonF::const_iterator it = segment.constBegin(); - it < segment.constEnd(); ++it, ++t) { - m_elements_dev << *it * matrix; - m_element_types.at(t) = QPainterPath::LineToElement; - } - i += 2; - } break; - default: - Q_ASSERT(false); - break; - } - } - element_count = m_elements_dev.size(); - } + const QVectorPath vp((qreal *)m_elements.data(), m_elements.size(), m_element_types.data()); + QPainterPath path = vp.convertToPainterPath(); + path = QTransform(m_m11, m_m12, m_m13, m_m21, m_m22, m_m23, m_dx, m_dy, m_m33).map(path); + if (!(m_outline.flags & QT_FT_OUTLINE_EVEN_ODD_FILL)) + path.setFillRule(Qt::WindingFill); + uint old_txop = m_txop; + m_txop = QTransform::TxNone; + if (path.isEmpty()) + m_valid = false; + else + convertPath(path); + m_txop = old_txop; + return; } elements = m_elements_dev.data(); } if (m_round_coords) { // round coordinates to match outlines drawn with drawLine_midpoint_i - for (int i = 0; i < element_count; ++i) + for (int i = 0; i < m_elements.size(); ++i) elements[i] = QPointF(qFloor(elements[i].x() + aliasedCoordinateDelta), qFloor(elements[i].y() + aliasedCoordinateDelta)); } -#ifdef QT_DEBUG_CONVERT - for (int i=0; i<element_count; ++i) { - printf("%d: (%.2f, %.2f)\n", - !m_element_types.isEmpty() ? m_element_types.at(i) : -1, - elements[i].x(), - elements[i].y()); - } -#endif - controlPointRect = boundingRect(elements, element_count); #ifdef QT_DEBUG_CONVERT diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 69e490a..74456dd 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1736,6 +1736,8 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) const QLineF *lines = reinterpret_cast<const QLineF *>(path.points()); for (int i = 0; i < lineCount; ++i) { + if (path.shape() == QVectorPath::LinesHint) + dashOffset = s->lastPen.dashOffset(); if (lines[i].p1() == lines[i].p2()) { if (s->lastPen.capStyle() != Qt::FlatCap) { QPointF p = lines[i].p1(); @@ -3454,8 +3456,8 @@ void QRasterPaintEngine::drawLines(const QLine *lines, int lineCount) int m22 = int(s->matrix.m22()); int dx = qFloor(s->matrix.dx() + aliasedCoordinateDelta); int dy = qFloor(s->matrix.dy() + aliasedCoordinateDelta); - int dashOffset = int(s->lastPen.dashOffset()); for (int i=0; i<lineCount; ++i) { + int dashOffset = int(s->lastPen.dashOffset()); if (s->flags.int_xform) { const QLine &l = lines[i]; int x1 = l.x1() * m11 + dx; @@ -3554,8 +3556,8 @@ void QRasterPaintEngine::drawLines(const QLineF *lines, int lineCount) ? LineDrawNormal : LineDrawIncludeLastPixel; - int dashOffset = int(s->lastPen.dashOffset()); for (int i=0; i<lineCount; ++i) { + int dashOffset = int(s->lastPen.dashOffset()); QLineF line = (lines[i] * s->matrix).translated(aliasedCoordinateDelta, aliasedCoordinateDelta); const QRectF brect(QPointF(line.x1(), line.y1()), QPointF(line.x2(), line.y2())); diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 8ec881e..ed9b858 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -421,7 +421,6 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) const qreal *lastPoint = points + (pointCount<<1); - d->activeStroker->begin(d->strokeHandler); d->strokeHandler->types.reset(); d->strokeHandler->pts.reset(); @@ -430,13 +429,13 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) if (d->stroker.capStyle() == Qt::RoundCap || d->stroker.joinStyle() == Qt::RoundJoin) flags |= QVectorPath::CurvedShapeHint; - // ### Perspective Xforms are currently not supported... qreal txscale = 1; if (!(pen.isCosmetic() || (qt_scaleForTransform(state()->matrix, &txscale) && txscale != 1))) { // We include cosmetic pens in this case to avoid having to // change the current transform. Normal transformed, // non-cosmetic pens will be transformed as part of fill // later, so they are also covered here.. + d->activeStroker->begin(d->strokeHandler); if (types) { while (points < lastPoint) { switch (*types) { @@ -491,79 +490,64 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) const qreal strokeWidth = d->stroker.strokeWidth(); d->stroker.setStrokeWidth(strokeWidth * txscale); // For cosmetic pens we need a bit of trickery... We to process xform the input points - if (types) { - bool isProject = state()->matrix.type() >= QTransform::TxProject; - while (points < lastPoint) { - switch (*types) { - case QPainterPath::MoveToElement: { - QPointF pt = (*(QPointF *) points) * state()->matrix; - d->activeStroker->moveTo(pt.x(), pt.y()); - points += 2; - ++types; - break; - } - case QPainterPath::LineToElement: { - QPointF pt = (*(QPointF *) points) * state()->matrix; - d->activeStroker->lineTo(pt.x(), pt.y()); - points += 2; - ++types; - break; - } - case QPainterPath::CurveToElement: { - // Convert projective xformed curves to line - // segments so they can be transformed more - // accurately - if (isProject) { - // -1 access here is safe because there is - // always an element prior to the cubicTo, we - // just need the value.. - QPolygonF segment = - QBezier::fromPoints(*(((QPointF *) points) - 1), - *((QPointF *) points), - *(((QPointF *) points) + 1), - *(((QPointF *) points) + 2)).toPolygon(); - - for (QPolygonF::const_iterator it = segment.constBegin(); - it < segment.constEnd(); ++it) { - const QPointF pt = *it * state()->matrix; - d->activeStroker->lineTo(pt.x(), pt.y()); - } - } else { + if (state()->matrix.type() >= QTransform::TxProject) { + QPainterPath painterPath = state()->matrix.map(path.convertToPainterPath()); + d->activeStroker->strokePath(painterPath, d->strokeHandler, QTransform()); + } else { + d->activeStroker->begin(d->strokeHandler); + if (types) { + while (points < lastPoint) { + switch (*types) { + case QPainterPath::MoveToElement: { + QPointF pt = (*(QPointF *) points) * state()->matrix; + d->activeStroker->moveTo(pt.x(), pt.y()); + points += 2; + ++types; + break; + } + case QPainterPath::LineToElement: { + QPointF pt = (*(QPointF *) points) * state()->matrix; + d->activeStroker->lineTo(pt.x(), pt.y()); + points += 2; + ++types; + break; + } + case QPainterPath::CurveToElement: { QPointF c1 = ((QPointF *) points)[0] * state()->matrix; QPointF c2 = ((QPointF *) points)[1] * state()->matrix; QPointF e = ((QPointF *) points)[2] * state()->matrix; d->activeStroker->cubicTo(c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y()); + points += 6; + types += 3; + flags |= QVectorPath::CurvedShapeHint; + break; + } + default: + break; } - points += 6; - types += 3; - flags |= QVectorPath::CurvedShapeHint; - break; } - default: - break; + if (path.hasImplicitClose()) { + QPointF pt = * ((QPointF *) path.points()) * state()->matrix; + d->activeStroker->lineTo(pt.x(), pt.y()); } - } - if (path.hasImplicitClose()) { - QPointF pt = * ((QPointF *) path.points()) * state()->matrix; - d->activeStroker->lineTo(pt.x(), pt.y()); - } - } else { - QPointF p = ((QPointF *)points)[0] * state()->matrix; - d->activeStroker->moveTo(p.x(), p.y()); - points += 2; - ++types; - while (points < lastPoint) { + } else { QPointF p = ((QPointF *)points)[0] * state()->matrix; - d->activeStroker->lineTo(p.x(), p.y()); + d->activeStroker->moveTo(p.x(), p.y()); points += 2; ++types; + while (points < lastPoint) { + QPointF p = ((QPointF *)points)[0] * state()->matrix; + d->activeStroker->lineTo(p.x(), p.y()); + points += 2; + ++types; + } + if (path.hasImplicitClose()) + d->activeStroker->lineTo(p.x(), p.y()); } - if (path.hasImplicitClose()) - d->activeStroker->lineTo(p.x(), p.y()); + d->activeStroker->end(); } - d->activeStroker->end(); d->stroker.setStrokeWidth(strokeWidth); QVectorPath strokePath(d->strokeHandler->pts.data(), d->strokeHandler->types.size(), diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 9c7a7fa..8192fb7 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1672,7 +1672,7 @@ bool QPainter::begin(QPaintDevice *pd) if (!d->engine) { qWarning("QPainter::begin: Paint device returned engine == 0, type: %d", pd->devType()); - return true; + return false; } // Slip a painter state into the engine before we do any other operations 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..6fe7805 100644 --- a/src/gui/painting/qregion_mac.cpp +++ b/src/gui/painting/qregion_mac.cpp @@ -155,6 +155,43 @@ 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 + 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..8708461 100644 --- a/src/gui/painting/qregion_win.cpp +++ b/src/gui/painting/qregion_win.cpp @@ -39,22 +39,20 @@ ** ****************************************************************************/ +#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; @@ -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 (uint 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/qtransform.cpp b/src/gui/painting/qtransform.cpp index a322fe4..a13b494 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -48,6 +48,8 @@ #include "qvariant.h" #include <qmath.h> +#include <private/qbezier_p.h> + QT_BEGIN_NAMESPACE #define Q_NEAR_CLIP 0.000001 @@ -1492,27 +1494,12 @@ static inline bool lineTo_clipped(QPainterPath &path, const QTransform &transfor static inline bool cubicTo_clipped(QPainterPath &path, const QTransform &transform, const QPointF &a, const QPointF &b, const QPointF &c, const QPointF &d, bool needsMoveTo) { - const QHomogeneousCoordinate ha = mapHomogeneous(transform, a); - const QHomogeneousCoordinate hb = mapHomogeneous(transform, b); - const QHomogeneousCoordinate hc = mapHomogeneous(transform, c); - const QHomogeneousCoordinate hd = mapHomogeneous(transform, d); - - if (ha.w < Q_NEAR_CLIP && hb.w < Q_NEAR_CLIP && hc.w < Q_NEAR_CLIP && hd.w < Q_NEAR_CLIP) - return false; + // Convert projective xformed curves to line + // segments so they can be transformed more accurately + QPolygonF segment = QBezier::fromPoints(a, b, c, d).toPolygon(); - if (ha.w >= Q_NEAR_CLIP && hb.w >= Q_NEAR_CLIP && hc.w >= Q_NEAR_CLIP && hd.w >= Q_NEAR_CLIP) { - if (needsMoveTo) - path.moveTo(ha.toPoint()); - - path.cubicTo(hb.toPoint(), hc.toPoint(), hd.toPoint()); - return true; - } - - if (lineTo_clipped(path, transform, a, b, needsMoveTo)) - needsMoveTo = false; - if (lineTo_clipped(path, transform, b, c, needsMoveTo)) - needsMoveTo = false; - if (lineTo_clipped(path, transform, c, d, needsMoveTo)) + for (int i = 0; i < segment.size() - 1; ++i) + if (lineTo_clipped(path, transform, segment.at(i), segment.at(i+1), needsMoveTo)) needsMoveTo = false; return !needsMoveTo; @@ -1554,6 +1541,7 @@ static QPainterPath mapProjective(const QTransform &transform, const QPainterPat if (path.elementCount() > 0 && lastMoveTo != last) lineTo_clipped(result, transform, last, lastMoveTo, needsMoveTo, false); + result.setFillRule(path.fillRule()); return result; } @@ -1793,6 +1781,14 @@ void QTransform::setMatrix(qreal m11, qreal m12, qreal m13, m_dirty = TxProject; } +static inline bool needsPerspectiveClipping(const QRectF &rect, const QTransform &transform) +{ + const qreal wx = qMin(transform.m13() * rect.left(), transform.m13() * rect.right()); + const qreal wy = qMin(transform.m23() * rect.top(), transform.m23() * rect.bottom()); + + return wx + wy + transform.m33() < Q_NEAR_CLIP; +} + QRect QTransform::mapRect(const QRect &rect) const { TransformationType t = inline_type(); @@ -1813,7 +1809,7 @@ QRect QTransform::mapRect(const QRect &rect) const y -= h; } return QRect(x, y, w, h); - } else { + } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) { // see mapToPolygon for explanations of the algorithm. qreal x = 0, y = 0; MAP(rect.left(), rect.top(), x, y); @@ -1837,6 +1833,10 @@ QRect QTransform::mapRect(const QRect &rect) const xmax = qMax(xmax, x); ymax = qMax(ymax, y); return QRect(qRound(xmin), qRound(ymin), qRound(xmax)-qRound(xmin), qRound(ymax)-qRound(ymin)); + } else { + QPainterPath path; + path.addRect(rect); + return map(path).boundingRect().toRect(); } } @@ -1879,7 +1879,7 @@ QRectF QTransform::mapRect(const QRectF &rect) const y -= h; } return QRectF(x, y, w, h); - } else { + } else if (t < TxProject || !needsPerspectiveClipping(rect, *this)) { qreal x = 0, y = 0; MAP(rect.x(), rect.y(), x, y); qreal xmin = x; @@ -1902,6 +1902,10 @@ QRectF QTransform::mapRect(const QRectF &rect) const xmax = qMax(xmax, x); ymax = qMax(ymax, y); return QRectF(xmin, ymin, xmax-xmin, ymax - ymin); + } else { + QPainterPath path; + path.addRect(rect); + return map(path).boundingRect(); } } diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index 22433dd..eddbfd2 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -118,7 +118,7 @@ QPaintDevice *QRasterWindowSurface::paintDevice() void QRasterWindowSurface::beginPaint(const QRegion &rgn) { #if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_WS_WINCE)) - if (!qt_widget_private(window())->isOpaque) { + if (!qt_widget_private(window())->isOpaque && window()->testAttribute(Qt::WA_TranslucentBackground)) { #if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) if (d_ptr->image->image.format() != QImage::Format_ARGB32_Premultiplied) prepareBuffer(QImage::Format_ARGB32_Premultiplied, window()); @@ -149,7 +149,7 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi QRect br = rgn.boundingRect(); #ifndef Q_WS_WINCE - if (!qt_widget_private(window())->isOpaque) { + if (!qt_widget_private(window())->isOpaque && window()->testAttribute(Qt::WA_TranslucentBackground)) { QRect r = window()->frameGeometry(); QPoint frameOffset = qt_widget_private(window())->frameStrut().topLeft(); QRect dirtyRect = br.translated(offset + frameOffset); 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/statemachine/qkeyeventtransition.cpp b/src/gui/statemachine/qkeyeventtransition.cpp index 51b3ccc..21a0736 100644 --- a/src/gui/statemachine/qkeyeventtransition.cpp +++ b/src/gui/statemachine/qkeyeventtransition.cpp @@ -106,19 +106,6 @@ QKeyEventTransition::QKeyEventTransition(QObject *object, QEvent::Type type, } /*! - Constructs a new key event transition for events of the given \a type for - the given \a object, with the given \a key, \a targets and \a sourceState. -*/ -QKeyEventTransition::QKeyEventTransition(QObject *object, QEvent::Type type, - int key, const QList<QAbstractState*> &targets, - QState *sourceState) - : QEventTransition(*new QKeyEventTransitionPrivate, object, type, targets, sourceState) -{ - Q_D(QKeyEventTransition); - d->transition = new QBasicKeyEventTransition(type, key); -} - -/*! Destroys this key event transition. */ QKeyEventTransition::~QKeyEventTransition() diff --git a/src/gui/statemachine/qkeyeventtransition.h b/src/gui/statemachine/qkeyeventtransition.h index f5e8de3..45ae684 100644 --- a/src/gui/statemachine/qkeyeventtransition.h +++ b/src/gui/statemachine/qkeyeventtransition.h @@ -62,9 +62,6 @@ public: QKeyEventTransition(QState *sourceState = 0); QKeyEventTransition(QObject *object, QEvent::Type type, int key, QState *sourceState = 0); - QKeyEventTransition(QObject *object, QEvent::Type type, int key, - const QList<QAbstractState*> &targets, - QState *sourceState = 0); ~QKeyEventTransition(); int key() const; diff --git a/src/gui/statemachine/qmouseeventtransition.cpp b/src/gui/statemachine/qmouseeventtransition.cpp index 0cd096a..dbe50b3 100644 --- a/src/gui/statemachine/qmouseeventtransition.cpp +++ b/src/gui/statemachine/qmouseeventtransition.cpp @@ -112,21 +112,6 @@ QMouseEventTransition::QMouseEventTransition(QObject *object, QEvent::Type type, } /*! - Constructs a new mouse event transition for events of the given \a type for - the given \a object, with the given \a button, \a targets and \a - sourceState. -*/ -QMouseEventTransition::QMouseEventTransition(QObject *object, QEvent::Type type, - Qt::MouseButton button, - const QList<QAbstractState*> &targets, - QState *sourceState) - : QEventTransition(*new QMouseEventTransitionPrivate, object, type, targets, sourceState) -{ - Q_D(QMouseEventTransition); - d->transition = new QBasicMouseEventTransition(type, button); -} - -/*! Destroys this mouse event transition. */ QMouseEventTransition::~QMouseEventTransition() diff --git a/src/gui/statemachine/qmouseeventtransition.h b/src/gui/statemachine/qmouseeventtransition.h index 73ae6c9..a56a554 100644 --- a/src/gui/statemachine/qmouseeventtransition.h +++ b/src/gui/statemachine/qmouseeventtransition.h @@ -63,10 +63,6 @@ public: QMouseEventTransition(QState *sourceState = 0); QMouseEventTransition(QObject *object, QEvent::Type type, Qt::MouseButton button, QState *sourceState = 0); - QMouseEventTransition(QObject *object, QEvent::Type type, - Qt::MouseButton button, - const QList<QAbstractState*> &targets, - QState *sourceState = 0); ~QMouseEventTransition(); Qt::MouseButton button() const; diff --git a/src/gui/styles/gtksymbols.cpp b/src/gui/styles/gtksymbols.cpp index c2c7876..f947ac1 100644 --- a/src/gui/styles/gtksymbols.cpp +++ b/src/gui/styles/gtksymbols.cpp @@ -752,7 +752,24 @@ static void setupGtkFileChooser(GtkWidget* gtkFileChooser, QWidget *parent, QGtk::gtk_file_filter_set_name(gtkFilter, qPrintable(name.isEmpty() ? extensions.join(QLS(", ")) : name)); foreach (const QString &fileExtension, extensions) { - QGtk::gtk_file_filter_add_pattern (gtkFilter, qPrintable(fileExtension)); + // Note Gtk file dialogs are by default case sensitive + // and only supports basic glob syntax so we + // rewrite .xyz to .[xX][yY][zZ] + QString caseInsensitive; + for (int i = 0 ; i < fileExtension.length() ; ++i) { + QChar ch = fileExtension.at(i); + if (ch.isLetter()) { + caseInsensitive.append( + QLatin1Char('[') + + ch.toLower() + + ch.toUpper() + + QLatin1Char(']')); + } else { + caseInsensitive.append(ch); + } + } + QGtk::gtk_file_filter_add_pattern (gtkFilter, qPrintable(caseInsensitive)); + } if (filterMap) filterMap->insert(gtkFilter, rawfilter); diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 2efa4a7..5f6d4ab 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -2891,8 +2891,8 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC bool customUp = true, customDown = true; QRenderRule upRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton); QRenderRule downRule = renderRule(w, opt, PseudoElement_SpinBoxDownButton); - bool upRuleMatch = upRule.hasGeometry(); - bool downRuleMatch = downRule.hasGeometry(); + bool upRuleMatch = upRule.hasGeometry() || upRule.hasPosition(); + bool downRuleMatch = downRule.hasGeometry() || downRule.hasPosition(); if (rule.hasNativeBorder() && !upRuleMatch && !downRuleMatch) { rule.drawBackgroundImage(p, spinOpt.rect); customUp = (opt->subControls & QStyle::SC_SpinBoxUp) @@ -5167,8 +5167,8 @@ QRect QStyleSheetStyle::subControlRect(ComplexControl cc, const QStyleOptionComp QRenderRule upRule = renderRule(w, opt, PseudoElement_SpinBoxUpButton); QRenderRule downRule = renderRule(w, opt, PseudoElement_SpinBoxDownButton); bool ruleMatch = rule.hasBox() || !rule.hasNativeBorder(); - bool upRuleMatch = upRule.hasGeometry(); - bool downRuleMatch = downRule.hasGeometry(); + bool upRuleMatch = upRule.hasGeometry() || upRule.hasPosition(); + bool downRuleMatch = downRule.hasGeometry() || upRule.hasPosition(); if (ruleMatch || upRuleMatch || downRuleMatch) { switch (sc) { case SC_SpinBoxFrame: 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/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 76132df..dbf3015 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -156,7 +156,7 @@ QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, con if (!kerning) { float zero = 0.0; QCFType<CFNumberRef> noKern = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &zero); - CFDictionaryAddValue(attributeDict, kCTKernAttributeName, &noKern); + CFDictionaryAddValue(attributeDict, kCTKernAttributeName, noKern); } QCoreTextFontEngine *fe = new QCoreTextFontEngine(ctfont, fontDef, this); @@ -1588,6 +1588,7 @@ QFontEngine::FaceId QFontEngineMac::faceId() const { FaceId ret; #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) +if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { // CTFontGetPlatformFont FSRef ref; if (ATSFontGetFileReference(FMGetATSFontRefFromFont(fontID), &ref) != noErr) @@ -1595,7 +1596,9 @@ QFontEngine::FaceId QFontEngineMac::faceId() const ret.filename = QByteArray(128, 0); ret.index = fontID; FSRefMakePath(&ref, (UInt8 *)ret.filename.data(), ret.filename.size()); -#else +}else +#endif +{ FSSpec spec; if (ATSFontGetFileSpecification(FMGetATSFontRefFromFont(fontID), &spec) != noErr) return ret; @@ -1605,7 +1608,7 @@ QFontEngine::FaceId QFontEngineMac::faceId() const ret.filename = QByteArray(128, 0); ret.index = fontID; FSRefMakePath(&ref, (UInt8 *)ret.filename.data(), ret.filename.size()); -#endif +} return ret; } diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h index 872bcd5..eb0d749 100644 --- a/src/gui/text/qtextcontrol_p.h +++ b/src/gui/text/qtextcontrol_p.h @@ -83,7 +83,7 @@ class QAbstractScrollArea; class QEvent; class QTimerEvent; -class Q_AUTOTEST_EXPORT QTextControl : public QObject +class Q_GUI_EXPORT QTextControl : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QTextControl) diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp index bf1fa6a..f4dd87c 100644 --- a/src/gui/util/qcompleter.cpp +++ b/src/gui/util/qcompleter.cpp @@ -772,7 +772,7 @@ QMatchData QUnsortedModelEngine::filter(const QString& part, const QModelIndex& /////////////////////////////////////////////////////////////////////////////// QCompleterPrivate::QCompleterPrivate() : widget(0), proxy(0), popup(0), cs(Qt::CaseSensitive), role(Qt::EditRole), column(0), - sorting(QCompleter::UnsortedModel), wrap(true), maxVisibleItems(7), eatFocusOut(true) + maxVisibleItems(7), sorting(QCompleter::UnsortedModel), wrap(true), eatFocusOut(true) { } @@ -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/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 106d8f2..f68d287 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtGui module of the Qt Toolkit. ** @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/gui/widgets/qlineedit_p.cpp b/src/gui/widgets/qlineedit_p.cpp index 0e39304..f0ec8ad 100644 --- a/src/gui/widgets/qlineedit_p.cpp +++ b/src/gui/widgets/qlineedit_p.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtGui module of the Qt Toolkit. ** @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp index 3936a67..55afa70 100644 --- a/src/gui/widgets/qmainwindowlayout.cpp +++ b/src/gui/widgets/qmainwindowlayout.cpp @@ -1988,6 +1988,9 @@ void QMainWindowLayout::timerEvent(QTimerEvent *e) if (movingSeparatorOrigin == movingSeparatorPos) return; + //when moving the separator, we need to update the previous position + parentWidget()->update(layoutState.dockAreaLayout.separatorRegion()); + layoutState = savedState; layoutState.dockAreaLayout.separatorMove(movingSeparator, movingSeparatorOrigin, movingSeparatorPos); diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 8eec0fc..05426a0 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -225,9 +225,17 @@ void QMenuPrivate::updateActionRects() const dh = popupGeometry(QApplication::desktop()->screenNumber(q)).height(), y = 0; QStyle *style = q->style(); - const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, 0, q), - vmargin = style->pixelMetric(QStyle::PM_MenuVMargin, 0, q), - icone = style->pixelMetric(QStyle::PM_SmallIconSize, 0, q); + QStyleOption opt; + opt.init(q); + const int hmargin = style->pixelMetric(QStyle::PM_MenuHMargin, &opt, q), + vmargin = style->pixelMetric(QStyle::PM_MenuVMargin, &opt, q), + icone = style->pixelMetric(QStyle::PM_SmallIconSize, &opt, q); + const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, &opt, q); + const int deskFw = style->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, &opt, q); + + const int sfcMargin = style->sizeFromContents(QStyle::CT_Menu, &opt, QApplication::globalStrut(), q).width() - QApplication::globalStrut().width(); + const int min_column_width = q->minimumWidth() - (sfcMargin + leftmargin + rightmargin + 2 * (fw + hmargin)); + const int tearoffHeight = tearoff ? style->pixelMetric(QStyle::PM_MenuTearoffHeight, &opt, q) : 0; //for compatability now - will have to refactor this away.. tabWidth = 0; @@ -300,10 +308,10 @@ void QMenuPrivate::updateActionRects() const if (!sz.isEmpty()) { - max_column_width = qMax(max_column_width, sz.width()); + max_column_width = qMax(min_column_width, qMax(max_column_width, sz.width())); //wrapping if (!scroll && - y+sz.height()+vmargin > dh - (style->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, q) * 2)) { + y+sz.height()+vmargin > dh - (deskFw * 2)) { ncols++; y = vmargin; } @@ -316,10 +324,9 @@ void QMenuPrivate::updateActionRects() const max_column_width += tabWidth; //finally add in the tab width //calculate position - const int fw = style->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q); const int base_y = vmargin + fw + topmargin + (scroll ? scroll->scrollOffset : 0) + - (tearoff ? style->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, q) : 0); + tearoffHeight; int x = hmargin + fw + leftmargin; y = base_y; @@ -328,7 +335,7 @@ void QMenuPrivate::updateActionRects() const if (rect.isNull()) continue; if (!scroll && - y+rect.height() > dh - (style->pixelMetric(QStyle::PM_MenuDesktopFrameWidth, 0, q) * 2)) { + y+rect.height() > dh - deskFw * 2) { x += max_column_width + hmargin; y = base_y; } @@ -1703,9 +1710,7 @@ QSize QMenu::sizeHint() const QSize s; QStyleOption opt(0); - opt.rect = rect(); - opt.palette = palette(); - opt.state = QStyle::State_None; + opt.init(this); for (int i = 0; i < d->actionRects.count(); ++i) { const QRect &rect = d->actionRects.at(i); if (rect.isNull()) @@ -2721,7 +2726,7 @@ void QMenu::mouseMoveEvent(QMouseEvent *e) QAction *action = d->actionAt(e->pos()); if (!action) { - if (d->hasHadMouse && !rect().contains(e->pos())) + if (d->hasHadMouse) d->setCurrentAction(0); return; } else if(e->buttons()) { 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} */ diff --git a/src/gui/widgets/qtextedit.cpp b/src/gui/widgets/qtextedit.cpp index e80df92..c095f5c 100644 --- a/src/gui/widgets/qtextedit.cpp +++ b/src/gui/widgets/qtextedit.cpp @@ -2625,12 +2625,12 @@ void QTextEditPrivate::_q_gestureTriggered() return; QScrollBar *hBar = q->horizontalScrollBar(); QScrollBar *vBar = q->verticalScrollBar(); - QPoint delta = g->pos() - (g->lastPos().isNull() ? g->pos() : g->lastPos()); + QSize delta = g->lastOffset(); if (!delta.isNull()) { if (QApplication::isRightToLeft()) - delta.rx() *= -1; - int newX = hBar->value() - delta.x(); - int newY = vBar->value() - delta.y(); + delta.rwidth() *= -1; + int newX = hBar->value() - delta.width(); + int newY = vBar->value() - delta.height(); hbar->setValue(newX); vbar->setValue(newY); } |