diff options
author | Peter Hartmann <peter.hartmann@trolltech.com> | 2009-07-15 10:30:21 (GMT) |
---|---|---|
committer | Peter Hartmann <peter.hartmann@trolltech.com> | 2009-07-15 10:30:21 (GMT) |
commit | 97f82b2344334fa158f20e4ed059984fd3c43162 (patch) | |
tree | 05a38900c0409a904f45ad35b7447baef13623ed /src/gui/widgets | |
parent | 2567ec486d5d95dc4ca06874cf75bf03bd7502b9 (diff) | |
parent | 28d0930593c6c04a7ef538353f8bee55df00a0e8 (diff) | |
download | Qt-97f82b2344334fa158f20e4ed059984fd3c43162.zip Qt-97f82b2344334fa158f20e4ed059984fd3c43162.tar.gz Qt-97f82b2344334fa158f20e4ed059984fd3c43162.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt
Diffstat (limited to 'src/gui/widgets')
25 files changed, 427 insertions, 420 deletions
diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp index 66572b8..dd92e17 100644 --- a/src/gui/widgets/qabstractscrollarea.cpp +++ b/src/gui/widgets/qabstractscrollarea.cpp @@ -301,6 +301,7 @@ void QAbstractScrollAreaPrivate::setupGestures() #ifdef Q_OS_WIN if (!viewport) return; + QApplicationPrivate* getQApplicationPrivateInternal(); QApplicationPrivate *qAppPriv = getQApplicationPrivateInternal(); bool needh = (hbarpolicy == Qt::ScrollBarAlwaysOn || (hbarpolicy == Qt::ScrollBarAsNeeded && hbar->minimum() < hbar->maximum())); @@ -490,9 +491,6 @@ void QAbstractScrollAreaPrivate::layoutChildren() viewport->setGeometry(QStyle::visualRect(opt.direction, opt.rect, viewportRect)); // resize the viewport last } -// ### Fix for 4.4, talk to Bjoern E or Girish. -void QAbstractScrollAreaPrivate::scrollBarPolicyChanged(Qt::Orientation, Qt::ScrollBarPolicy) {} - /*! \internal @@ -940,6 +938,7 @@ bool QAbstractScrollArea::event(QEvent *e) case QEvent::DragMove: case QEvent::DragLeave: #endif + return false; case QEvent::StyleChange: case QEvent::LayoutDirectionChange: case QEvent::ApplicationLayoutDirectionChange: diff --git a/src/gui/widgets/qabstractscrollarea_p.h b/src/gui/widgets/qabstractscrollarea_p.h index 5d3494b..aef8ac5 100644 --- a/src/gui/widgets/qabstractscrollarea_p.h +++ b/src/gui/widgets/qabstractscrollarea_p.h @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE class QScrollBar; class QAbstractScrollAreaScrollBarContainer; -class QAbstractScrollAreaPrivate: public QFramePrivate +class Q_AUTOTEST_EXPORT QAbstractScrollAreaPrivate: public QFramePrivate { Q_DECLARE_PUBLIC(QAbstractScrollArea) @@ -88,7 +88,7 @@ public: void init(); void layoutChildren(); // ### Fix for 4.4, talk to Bjoern E or Girish. - virtual void scrollBarPolicyChanged(Qt::Orientation, Qt::ScrollBarPolicy); + virtual void scrollBarPolicyChanged(Qt::Orientation, Qt::ScrollBarPolicy) {} void _q_hslide(int); void _q_vslide(int); diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp index 25acd6e..433406c 100644 --- a/src/gui/widgets/qabstractspinbox.cpp +++ b/src/gui/widgets/qabstractspinbox.cpp @@ -57,6 +57,9 @@ #include <qpalette.h> #include <qstylepainter.h> #include <qdebug.h> +#ifndef QT_NO_ACCESSIBILITY +# include <qaccessible.h> +#endif #if defined(Q_WS_X11) #include <limits.h> @@ -951,6 +954,9 @@ void QAbstractSpinBox::keyPressEvent(QKeyEvent *event) d->buttonState = (Keyboard | (up ? Up : Down)); } stepBy(steps); +#ifndef QT_NO_ACCESSIBILITY + QAccessible::updateAccessibility(this, 0, QAccessible::ValueChanged); +#endif return; } #ifdef QT_KEYPAD_NAVIGATION @@ -1548,6 +1554,9 @@ void QAbstractSpinBoxPrivate::updateState(bool up) spinClickThresholdTimerId = q->startTimer(spinClickThresholdTimerInterval); buttonState = (up ? (Mouse | Up) : (Mouse | Down)); q->stepBy(up ? 1 : -1); +#ifndef QT_NO_ACCESSIBILITY + QAccessible::updateAccessibility(q, 0, QAccessible::ValueChanged); +#endif } } @@ -1568,7 +1577,7 @@ void QAbstractSpinBox::initStyleOption(QStyleOptionSpinBox *option) const option->initFrom(this); option->activeSubControls = QStyle::SC_None; option->buttonSymbols = d->buttonSymbols; - option->subControls = QStyle::SC_SpinBoxFrame; + option->subControls = QStyle::SC_SpinBoxFrame | QStyle::SC_SpinBoxEditField; if (d->buttonSymbols != QAbstractSpinBox::NoButtons) { option->subControls |= QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown; if (d->buttonState & Up) { diff --git a/src/gui/widgets/qcocoatoolbardelegate_mac.mm b/src/gui/widgets/qcocoatoolbardelegate_mac.mm index 894028e..10fe9b0 100644 --- a/src/gui/widgets/qcocoatoolbardelegate_mac.mm +++ b/src/gui/widgets/qcocoatoolbardelegate_mac.mm @@ -43,6 +43,7 @@ #ifdef QT_MAC_USE_COCOA #include <private/qmainwindowlayout_p.h> #include <private/qt_mac_p.h> +#include <private/qt_cocoa_helpers_mac_p.h> #include <private/qcocoaview_mac_p.h> #include <private/qwidget_p.h> #include <qtoolbar.h> @@ -99,7 +100,7 @@ QT_FORWARD_DECLARE_CLASS(QCFString); { Q_UNUSED(flag); Q_UNUSED(nstoolbar); - QToolBar *tb = mainWindowLayout->cocoaItemIDToToolbarHash.value(QCFString::toQString(CFStringRef(itemIdentifier))); + QToolBar *tb = mainWindowLayout->cocoaItemIDToToolbarHash.value(qt_mac_NSStringToQString(itemIdentifier)); NSToolbarItem *item = nil; if (tb) { item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier]; @@ -111,7 +112,7 @@ QT_FORWARD_DECLARE_CLASS(QCFString); - (void)toolbarWillAddItem:(NSNotification *)notification { NSToolbarItem *item = [[notification userInfo] valueForKey:@"item"]; - QToolBar *tb = mainWindowLayout->cocoaItemIDToToolbarHash.value(QCFString::toQString(CFStringRef([item itemIdentifier]))); + QToolBar *tb = mainWindowLayout->cocoaItemIDToToolbarHash.value(qt_mac_NSStringToQString([item itemIdentifier])); if (!tb) return; // I can't really do anything about this. [item retain]; @@ -119,12 +120,9 @@ QT_FORWARD_DECLARE_CLASS(QCFString); NSArray *items = [[qt_mac_window_for(mainWindowLayout->layoutState.mainWindow->window()) toolbar] items]; int someIndex = 0; - bool foundItem = false; for (NSToolbarItem *i in items) { - if (i == item) { - foundItem = true; + if (i == item) break; - } ++someIndex; } mainWindowLayout->toolbarItemsCopy.insert(someIndex, item); diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 1ca878d..097f3d0 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -148,8 +148,10 @@ QStyleOptionMenuItem QComboMenuDelegate::getStyleOption(const QStyleOptionViewIt menuOption.rect = option.rect; // Make sure fonts set on the combo box also overrides the font for the popup menu. - if (mCombo->testAttribute(Qt::WA_SetFont) || mCombo->testAttribute(Qt::WA_MacSmallSize) - || mCombo->testAttribute(Qt::WA_MacMiniSize)) + if (mCombo->testAttribute(Qt::WA_SetFont) + || mCombo->testAttribute(Qt::WA_MacSmallSize) + || mCombo->testAttribute(Qt::WA_MacMiniSize) + || mCombo->font() != qt_app_fonts_hash()->value("QComboBox", QFont())) menuOption.font = mCombo->font(); else menuOption.font = qt_app_fonts_hash()->value("QComboMenuItem", mCombo->font()); diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp index b905ccd..ee29b55 100644 --- a/src/gui/widgets/qdockarealayout.cpp +++ b/src/gui/widgets/qdockarealayout.cpp @@ -1707,7 +1707,7 @@ QDockAreaLayoutItem &QDockAreaLayoutInfo::item(const QList<int> &path) Q_ASSERT(!path.isEmpty()); const int index = path.first(); if (path.count() > 1) { - const QDockAreaLayoutItem &item = item_list.at(index); + const QDockAreaLayoutItem &item = item_list[index]; Q_ASSERT(item.subinfo != 0); return item.subinfo->item(path.mid(1)); } diff --git a/src/gui/widgets/qeffects.cpp b/src/gui/widgets/qeffects.cpp index d6d0a16..f3b1b76 100644 --- a/src/gui/widgets/qeffects.cpp +++ b/src/gui/widgets/qeffects.cpp @@ -128,7 +128,8 @@ QAlphaWidget::~QAlphaWidget() { #if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) // Restore user-defined opacity value - widget->setWindowOpacity(windowOpacity); + if (widget) + widget->setWindowOpacity(windowOpacity); #endif } diff --git a/src/gui/widgets/qfontcombobox.cpp b/src/gui/widgets/qfontcombobox.cpp index 9660399..f87ccd3 100644 --- a/src/gui/widgets/qfontcombobox.cpp +++ b/src/gui/widgets/qfontcombobox.cpp @@ -263,7 +263,7 @@ void QFontComboBoxPrivate::_q_currentChanged(const QString &text) { Q_Q(QFontComboBox); QFont newFont(text); - if (currentFont != newFont) { + if (currentFont.family() != newFont.family()) { currentFont = newFont; emit q->currentFontChanged(currentFont); } diff --git a/src/gui/widgets/qgroupbox.cpp b/src/gui/widgets/qgroupbox.cpp index 2380e78..5758b6a 100644 --- a/src/gui/widgets/qgroupbox.cpp +++ b/src/gui/widgets/qgroupbox.cpp @@ -478,11 +478,7 @@ void QGroupBox::focusInEvent(QFocusEvent *fe) if (focusPolicy() == Qt::NoFocus) { d->_q_fixFocus(fe->reason()); } else { - QStyleOptionGroupBox box; - initStyleOption(&box); - QRect rect = style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxCheckBox, this) - | style()->subControlRect(QStyle::CC_GroupBox, &box, QStyle::SC_GroupBoxLabel, this); - update(rect); + QWidget::focusInEvent(fe); } } diff --git a/src/gui/widgets/qmainwindow.cpp b/src/gui/widgets/qmainwindow.cpp index 0c841eb..c51bed9 100644 --- a/src/gui/widgets/qmainwindow.cpp +++ b/src/gui/widgets/qmainwindow.cpp @@ -1369,20 +1369,25 @@ bool QMainWindow::event(QEvent *event) #ifdef Q_WS_MAC case QEvent::Show: if (unifiedTitleAndToolBarOnMac()) - macWindowToolbarShow(this, true); + d->layout->syncUnifiedToolbarVisibility(); + d->layout->blockVisiblityCheck = false; break; -# ifdef QT_MAC_USE_COCOA case QEvent::WindowStateChange: { + if (isHidden()) { + // We are coming out of a minimize, leave things as is. + d->layout->blockVisiblityCheck = true; + } +# ifdef QT_MAC_USE_COCOA // We need to update the HIToolbar status when we go out of or into fullscreen. QWindowStateChangeEvent *wce = static_cast<QWindowStateChangeEvent *>(event); if ((windowState() & Qt::WindowFullScreen) || (wce->oldState() & Qt::WindowFullScreen)) { d->layout->updateHIToolBarStatus(); } +# endif // Cocoa } break; -# endif // Cocoa -#endif +#endif // Q_WS_MAC #if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR) case QEvent::CursorChange: if (d->cursorAdjusted) { diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp index 0318f53..3936a67 100644 --- a/src/gui/widgets/qmainwindowlayout.cpp +++ b/src/gui/widgets/qmainwindowlayout.cpp @@ -237,7 +237,7 @@ void QMainWindowLayoutState::apply(bool animated) if (centralWidgetItem != 0) { QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(mainWindow->layout()); Q_ASSERT(layout != 0); - layout->widgetAnimator->animate(centralWidgetItem->widget(), centralWidgetRect, animated); + layout->widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, animated); } #endif } @@ -426,42 +426,42 @@ QList<int> QMainWindowLayoutState::gapIndex(QWidget *widget, return result; } -bool QMainWindowLayoutState::insertGap(QList<int> path, QLayoutItem *item) +bool QMainWindowLayoutState::insertGap(const QList<int> &path, QLayoutItem *item) { if (path.isEmpty()) return false; - int i = path.takeFirst(); + int i = path.first(); #ifndef QT_NO_TOOLBAR if (i == 0) { Q_ASSERT(qobject_cast<QToolBar*>(item->widget()) != 0); - return toolBarAreaLayout.insertGap(path, item); + return toolBarAreaLayout.insertGap(path.mid(1), item); } #endif #ifndef QT_NO_DOCKWIDGET if (i == 1) { Q_ASSERT(qobject_cast<QDockWidget*>(item->widget()) != 0); - return dockAreaLayout.insertGap(path, item); + return dockAreaLayout.insertGap(path.mid(1), item); } #endif //QT_NO_DOCKWIDGET return false; } -void QMainWindowLayoutState::remove(QList<int> path) +void QMainWindowLayoutState::remove(const QList<int> &path) { - int i = path.takeFirst(); + int i = path.first(); #ifndef QT_NO_TOOLBAR if (i == 0) - toolBarAreaLayout.remove(path); + toolBarAreaLayout.remove(path.mid(1)); #endif #ifndef QT_NO_DOCKWIDGET if (i == 1) - dockAreaLayout.remove(path); + dockAreaLayout.remove(path.mid(1)); #endif //QT_NO_DOCKWIDGET } @@ -501,88 +501,88 @@ bool QMainWindowLayoutState::isValid() const return rect.isValid(); } -QLayoutItem *QMainWindowLayoutState::item(QList<int> path) +QLayoutItem *QMainWindowLayoutState::item(const QList<int> &path) { - int i = path.takeFirst(); + int i = path.first(); #ifndef QT_NO_TOOLBAR if (i == 0) - return toolBarAreaLayout.item(path).widgetItem; + return toolBarAreaLayout.item(path.mid(1)).widgetItem; #endif #ifndef QT_NO_DOCKWIDGET if (i == 1) - return dockAreaLayout.item(path).widgetItem; + return dockAreaLayout.item(path.mid(1)).widgetItem; #endif //QT_NO_DOCKWIDGET return 0; } -QRect QMainWindowLayoutState::itemRect(QList<int> path) const +QRect QMainWindowLayoutState::itemRect(const QList<int> &path) const { - int i = path.takeFirst(); + int i = path.first(); #ifndef QT_NO_TOOLBAR if (i == 0) - return toolBarAreaLayout.itemRect(path); + return toolBarAreaLayout.itemRect(path.mid(1)); #endif #ifndef QT_NO_DOCKWIDGET if (i == 1) - return dockAreaLayout.itemRect(path); + return dockAreaLayout.itemRect(path.mid(1)); #endif //QT_NO_DOCKWIDGET return QRect(); } -QRect QMainWindowLayoutState::gapRect(QList<int> path) const +QRect QMainWindowLayoutState::gapRect(const QList<int> &path) const { - int i = path.takeFirst(); + int i = path.first(); #ifndef QT_NO_TOOLBAR if (i == 0) - return toolBarAreaLayout.itemRect(path); + return toolBarAreaLayout.itemRect(path.mid(1)); #endif #ifndef QT_NO_DOCKWIDGET if (i == 1) - return dockAreaLayout.gapRect(path); + return dockAreaLayout.gapRect(path.mid(1)); #endif //QT_NO_DOCKWIDGET return QRect(); } -QLayoutItem *QMainWindowLayoutState::plug(QList<int> path) +QLayoutItem *QMainWindowLayoutState::plug(const QList<int> &path) { - int i = path.takeFirst(); + int i = path.first(); #ifndef QT_NO_TOOLBAR if (i == 0) - return toolBarAreaLayout.plug(path); + return toolBarAreaLayout.plug(path.mid(1)); #endif #ifndef QT_NO_DOCKWIDGET if (i == 1) - return dockAreaLayout.plug(path); + return dockAreaLayout.plug(path.mid(1)); #endif //QT_NO_DOCKWIDGET return 0; } -QLayoutItem *QMainWindowLayoutState::unplug(QList<int> path, QMainWindowLayoutState *other) +QLayoutItem *QMainWindowLayoutState::unplug(const QList<int> &path, QMainWindowLayoutState *other) { - int i = path.takeFirst(); + int i = path.first(); #ifdef QT_NO_TOOLBAR Q_UNUSED(other); #else if (i == 0) - return toolBarAreaLayout.unplug(path, other ? &other->toolBarAreaLayout : 0); + return toolBarAreaLayout.unplug(path.mid(1), other ? &other->toolBarAreaLayout : 0); #endif #ifndef QT_NO_DOCKWIDGET if (i == 1) - return dockAreaLayout.unplug(path); + return dockAreaLayout.unplug(path.mid(1)); #endif //QT_NO_DOCKWIDGET return 0; @@ -939,16 +939,70 @@ void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar void QMainWindowLayout::toggleToolBarsVisible() { - layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible; - if (!layoutState.mainWindow->isMaximized()){ - QPoint topLeft = parentWidget()->geometry().topLeft(); - QRect r = parentWidget()->geometry(); - r = layoutState.toolBarAreaLayout.rectHint(r); - r.moveTo(topLeft); - parentWidget()->setGeometry(r); -// widgetAnimator->animate(parentWidget(), r, true); - } else{ - update(); + bool updateNonUnifiedParts = true; +#ifdef Q_WS_MAC + if (layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) { + // If we hit this case, someone has pressed the "toolbar button" which will + // toggle the unified toolbar visiblity, because that's what the user wants. + // We might be in a situation where someone has hidden all the toolbars + // beforehand (maybe in construction), but now they've hit this button and + // and are expecting the items to show. What do we do? + // 1) Check the visibility of all the toolbars, if one is visible, do nothing, this + // preserves what people would expect (these toolbars were visible when I clicked last time). + // 2) If NONE are visible, then show them all. Again, this preserves the user expectation + // of, "I want to see the toolbars." The user may get more toolbars than expected, but this + // is better seeing nothing. + // Don't worry about any of this if we are going invisible. This does mean we may get + // into issues when switching into and out of fullscreen mode, but this is probably minor. + // If we ever need to do hiding, that would have to be taken care of after the unified toolbar + // has finished hiding. + // People can of course handle the QEvent::ToolBarChange event themselves and do + // WHATEVER they want if they don't like what we are doing (though the unified toolbar + // will fire regardless). + + // Check if we REALLY need to update the geometry below. If we only have items in the + // unified toolbar, all the docks will be empty, so there's very little point + // in doing the geometry as Apple will do it (we also avoid flicker in Cocoa as well). + // FWIW, layoutState.toolBarAreaLayout.visible and the state of the unified toolbar + // visibility can get out of sync. I really don't think it's a big issue. It is kept + // to a minimum because we only change the visibility if we absolutely must. + // update the "non unified parts." + updateNonUnifiedParts = !layoutState.toolBarAreaLayout.isEmpty(); + + // We get this function before the unified toolbar does its thing. + // So, the value will be opposite of what we expect. + bool goingVisible = !macWindowToolbarIsVisible(qt_mac_window_for(layoutState.mainWindow)); + if (goingVisible) { + const int ToolBarCount = qtoolbarsInUnifiedToolbarList.size(); + bool needAllVisible = true; + for (int i = 0; i < ToolBarCount; ++i) { + if (!qtoolbarsInUnifiedToolbarList.at(i)->isHidden()) { + needAllVisible = false; + break; + } + } + if (needAllVisible) { + QBoolBlocker blocker(blockVisiblityCheck); // Disable the visibilty check because + // the toggle has already happened. + for (int i = 0; i < ToolBarCount; ++i) + qtoolbarsInUnifiedToolbarList.at(i)->setVisible(true); + } + } + if (!updateNonUnifiedParts) + layoutState.toolBarAreaLayout.visible = goingVisible; + } +#endif + if (updateNonUnifiedParts) { + layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible; + if (!layoutState.mainWindow->isMaximized()) { + QPoint topLeft = parentWidget()->geometry().topLeft(); + QRect r = parentWidget()->geometry(); + r = layoutState.toolBarAreaLayout.rectHint(r); + r.moveTo(topLeft); + parentWidget()->setGeometry(r); + } else { + update(); + } } } @@ -1528,59 +1582,28 @@ bool QMainWindowLayout::plug(QLayoutItem *widgetItem) layoutState.remove(previousPath); pluggingWidget = widget; - if (dockOptions & QMainWindow::AnimatedDocks) { - QRect globalRect = currentGapRect; - globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft())); + QRect globalRect = currentGapRect; + globalRect.moveTopLeft(parentWidget()->mapToGlobal(globalRect.topLeft())); #ifndef QT_NO_DOCKWIDGET - if (qobject_cast<QDockWidget*>(widget) != 0) { - QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout()); - if (layout->nativeWindowDeco()) { - globalRect.adjust(0, layout->titleHeight(), 0, 0); - } else { - int fw = widget->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, widget); - globalRect.adjust(-fw, -fw, fw, fw); - } + if (qobject_cast<QDockWidget*>(widget) != 0) { + QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(widget->layout()); + if (layout->nativeWindowDeco()) { + globalRect.adjust(0, layout->titleHeight(), 0, 0); + } else { + int fw = widget->style()->pixelMetric(QStyle::PM_DockWidgetFrameWidth, 0, widget); + globalRect.adjust(-fw, -fw, fw, fw); } -#endif - widgetAnimator.animate(widget, globalRect, true); - } else { - animationFinished(widget); } +#endif + widgetAnimator.animate(widget, globalRect, dockOptions & QMainWindow::AnimatedDocks); return true; } -void QMainWindowLayout::allAnimationsFinished() -{ -#ifndef QT_NO_DOCKWIDGET - parentWidget()->update(layoutState.dockAreaLayout.separatorRegion()); - -#ifndef QT_NO_TABBAR - foreach (QTabBar *tab_bar, usedTabBars) - tab_bar->show(); -#endif // QT_NO_TABBAR -#endif // QT_NO_DOCKWIDGET - - updateGapIndicator(); -} - void QMainWindowLayout::animationFinished(QWidget *widget) { - - /* This signal is delivered from QWidgetAnimator over a qeued connection. The problem is that - the widget can be deleted. This is handled as follows: - - The animator only ever animates widgets that have been added to this layout. If a widget - is deleted during animation, the widget's destructor removes the widget form this layout. - This in turn aborts the animation (see takeAt()) and this signal will never be delivered. - - If the widget is deleted after the animation is finished but before this qeued signal - is delivered, the widget is no longer in the layout and we catch it here. The key is that - QMainWindowLayoutState::contains() never dereferences the pointer. */ - - if (!layoutState.contains(widget)) - return; - + //this function is called from within the Widget Animator whenever an animation is finished + //on a certain widget #ifndef QT_NO_TOOLBAR if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) { QToolBarLayout *tbl = qobject_cast<QToolBarLayout*>(tb->layout()); @@ -1593,32 +1616,44 @@ void QMainWindowLayout::animationFinished(QWidget *widget) } #endif - if (widget != pluggingWidget) - return; + if (widget == pluggingWidget) { #ifndef QT_NO_DOCKWIDGET - if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) - dw->d_func()->plug(currentGapRect); + if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) + dw->d_func()->plug(currentGapRect); #endif #ifndef QT_NO_TOOLBAR - if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) - tb->d_func()->plug(currentGapRect); + if (QToolBar *tb = qobject_cast<QToolBar*>(widget)) + tb->d_func()->plug(currentGapRect); #endif - applyState(layoutState, false); #ifndef QT_NO_DOCKWIDGET #ifndef QT_NO_TABBAR - if (qobject_cast<QDockWidget*>(widget) != 0) { - // info() might return null if the widget is destroyed while - // animating but before the animationFinished signal is received. - if (QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget)) - info->setCurrentTab(widget); - } + if (qobject_cast<QDockWidget*>(widget) != 0) { + // info() might return null if the widget is destroyed while + // animating but before the animationFinished signal is received. + if (QDockAreaLayoutInfo *info = layoutState.dockAreaLayout.info(widget)) + info->setCurrentTab(widget); + } #endif #endif - savedState.clear(); - currentGapPos.clear(); - pluggingWidget = 0; + + savedState.clear(); + currentGapPos.clear(); + pluggingWidget = 0; + } + + if (!widgetAnimator.animating()) { + //all animations are finished +#ifndef QT_NO_DOCKWIDGET + parentWidget()->update(layoutState.dockAreaLayout.separatorRegion()); +#ifndef QT_NO_TABBAR + foreach (QTabBar *tab_bar, usedTabBars) + tab_bar->show(); +#endif // QT_NO_TABBAR +#endif // QT_NO_DOCKWIDGET + } + updateGapIndicator(); } @@ -1654,8 +1689,11 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow) , widgetAnimator(this) , pluggingWidget(0) #ifndef QT_NO_RUBBERBAND - , gapIndicator(QRubberBand::Rectangle, mainwindow) + , gapIndicator(new QRubberBand(QRubberBand::Rectangle, mainwindow)) #endif //QT_NO_RUBBERBAND +#ifdef Q_WS_MAC + , blockVisiblityCheck(false) +#endif { #ifndef QT_NO_DOCKWIDGET #ifndef QT_NO_TABBAR @@ -1670,8 +1708,8 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow) #ifndef QT_NO_RUBBERBAND // For accessibility to identify this special widget. - gapIndicator.setObjectName(QLatin1String("qt_rubberband")); - gapIndicator.hide(); + gapIndicator->setObjectName(QLatin1String("qt_rubberband")); + gapIndicator->hide(); #endif pluggingWidget = 0; @@ -1777,14 +1815,8 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget) void QMainWindowLayout::updateGapIndicator() { #ifndef QT_NO_RUBBERBAND - if (widgetAnimator.animating() || currentGapPos.isEmpty()) { - gapIndicator.hide(); - } else { - if (gapIndicator.geometry() != currentGapRect) - gapIndicator.setGeometry(currentGapRect); - if (!gapIndicator.isVisible()) - gapIndicator.show(); - } + gapIndicator->setVisible(!widgetAnimator.animating() && !currentGapPos.isEmpty()); + gapIndicator->setGeometry(currentGapRect); #endif } diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm index 6632be7..61719c2 100644 --- a/src/gui/widgets/qmainwindowlayout_mac.mm +++ b/src/gui/widgets/qmainwindowlayout_mac.mm @@ -338,18 +338,16 @@ void QMainWindowLayout::updateHIToolBarStatus() 0, kWindowUnifiedTitleAndToolbarAttribute); } #endif - macWindowToolbarShow(layoutState.mainWindow, useMacToolbar); layoutState.mainWindow->setUpdatesEnabled(false); // reduces a little bit of flicker, not all though if (!useMacToolbar) { - OSWindowRef windowRef = qt_mac_window_for(parentWidget()); - macWindowToolbarShow(parentWidget(), false); + macWindowToolbarShow(layoutState.mainWindow, false); // Move everything out of the HIToolbar into the main toolbar. while (!qtoolbarsInUnifiedToolbarList.isEmpty()) { // Should shrink the list by one every time. layoutState.mainWindow->addToolBar(Qt::TopToolBarArea, qtoolbarsInUnifiedToolbarList.first()); } - macWindowToolbarSet(windowRef, NULL); + macWindowToolbarSet(qt_mac_window_for(layoutState.mainWindow), 0); } else { QList<QToolBar *> toolbars = layoutState.mainWindow->findChildren<QToolBar *>(); for (int i = 0; i < toolbars.size(); ++i) { @@ -359,6 +357,7 @@ void QMainWindowLayout::updateHIToolBarStatus() layoutState.mainWindow->addToolBar(Qt::TopToolBarArea, toolbar); } } + syncUnifiedToolbarVisibility(); } layoutState.mainWindow->setUpdatesEnabled(true); } @@ -439,7 +438,7 @@ void QMainWindowLayout::insertIntoMacToolbar(QToolBar *before, QToolBar *toolbar #else NSString *toolbarID = kQToolBarNSToolbarIdentifier; toolbarID = [toolbarID stringByAppendingFormat:@"%p", toolbar]; - cocoaItemIDToToolbarHash.insert(QCFString::toQString(CFStringRef(toolbarID)), toolbar); + cocoaItemIDToToolbarHash.insert(qt_mac_NSStringToQString(toolbarID), toolbar); [macToolbar insertItemWithItemIdentifier:toolbarID atIndex:beforeIndex]; #endif } @@ -487,6 +486,7 @@ void QMainWindowLayout::cleanUpMacToolbarItems() void QMainWindowLayout::fixSizeInUnifiedToolbar(QToolBar *tb) const { +#ifdef QT_MAC_USE_COCOA QHash<void *, QToolBar *>::const_iterator it = unifiedToolbarHash.constBegin(); NSToolbarItem *item = nil; while (it != unifiedToolbarHash.constEnd()) { @@ -507,5 +507,26 @@ void QMainWindowLayout::fixSizeInUnifiedToolbar(QToolBar *tb) const nssize.height = size.height() - 2; [item setMinSize:nssize]; } +#else + Q_UNUSED(tb); +#endif } + +void QMainWindowLayout::syncUnifiedToolbarVisibility() +{ + if (blockVisiblityCheck) + return; + + Q_ASSERT(layoutState.mainWindow->unifiedTitleAndToolBarOnMac()); + bool show = false; + const int ToolBarCount = qtoolbarsInUnifiedToolbarList.count(); + for (int i = 0; i < ToolBarCount; ++i) { + if (qtoolbarsInUnifiedToolbarList.at(i)->isVisible()) { + show = true; + break; + } + } + macWindowToolbarShow(layoutState.mainWindow, show); +} + QT_END_NAMESPACE diff --git a/src/gui/widgets/qmainwindowlayout_p.h b/src/gui/widgets/qmainwindowlayout_p.h index 5c5965a..524fdbf 100644 --- a/src/gui/widgets/qmainwindowlayout_p.h +++ b/src/gui/widgets/qmainwindowlayout_p.h @@ -59,7 +59,6 @@ #include "QtGui/qlayout.h" #include "QtGui/qtabbar.h" -#include "QtGui/qrubberband.h" #include "QtCore/qvector.h" #include "QtCore/qset.h" #include "QtCore/qbasictimer.h" @@ -129,9 +128,9 @@ public: QLayoutItem *itemAt(int index, int *x) const; QLayoutItem *takeAt(int index, int *x); QList<int> indexOf(QWidget *widget) const; - QLayoutItem *item(QList<int> path); - QRect itemRect(QList<int> path) const; - QRect gapRect(QList<int> path) const; // ### get rid of this, use itemRect() instead + QLayoutItem *item(const QList<int> &path); + QRect itemRect(const QList<int> &path) const; + QRect gapRect(const QList<int> &path) const; // ### get rid of this, use itemRect() instead bool contains(QWidget *widget) const; @@ -139,14 +138,14 @@ public: QWidget *centralWidget() const; QList<int> gapIndex(QWidget *widget, const QPoint &pos) const; - bool insertGap(QList<int> path, QLayoutItem *item); - void remove(QList<int> path); + bool insertGap(const QList<int> &path, QLayoutItem *item); + void remove(const QList<int> &path); void remove(QLayoutItem *item); void clear(); bool isValid() const; - QLayoutItem *plug(QList<int> path); - QLayoutItem *unplug(QList<int> path, QMainWindowLayoutState *savedState = 0); + QLayoutItem *plug(const QList<int> &path); + QLayoutItem *unplug(const QList<int> &path, QMainWindowLayoutState *savedState = 0); void saveState(QDataStream &stream) const; bool checkFormat(QDataStream &stream, bool pre43); @@ -284,7 +283,7 @@ public: QRect currentGapRect; QWidget *pluggingWidget; #ifndef QT_NO_RUBBERBAND - QRubberBand gapIndicator; + QRubberBand *gapIndicator; #endif QList<int> hover(QLayoutItem *widgetItem, const QPoint &mousePos); @@ -297,9 +296,8 @@ public: void restore(bool keepSavedState = false); void updateHIToolBarStatus(); void animationFinished(QWidget *widget); - void allAnimationsFinished(); -private slots: +private Q_SLOTS: #ifndef QT_NO_DOCKWIDGET #ifndef QT_NO_TABBAR void tabChanged(); @@ -337,6 +335,8 @@ public: void cleanUpMacToolbarItems(); void fixSizeInUnifiedToolbar(QToolBar *tb) const; bool useHIToolBar; + void syncUnifiedToolbarVisibility(); + bool blockVisiblityCheck; #endif }; QT_END_NAMESPACE diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index d3f5bc5..99f3880 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -163,6 +163,12 @@ void QMenuPrivate::init() } } +int QMenuPrivate::scrollerHeight() const +{ + Q_Q(const QMenu); + return qMax(QApplication::globalStrut().height(), q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q)); +} + //Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't QRect QMenuPrivate::popupGeometry(int screen) const { @@ -257,7 +263,6 @@ void QMenuPrivate::updateActionRects() const //let the style modify the above size.. QStyleOptionMenuItem opt; q->initStyleOption(&opt, action); - opt.rect = q->rect(); const QFontMetrics &fm = opt.fontMetrics; QSize sz; @@ -280,10 +285,7 @@ void QMenuPrivate::updateActionRects() const tabWidth = qMax(int(tabWidth), qfm.width(seq)); #endif } - int w = fm.boundingRect(QRect(), Qt::TextSingleLine, s).width(); - w -= s.count(QLatin1Char('&')) * fm.width(QLatin1Char('&')); - w += s.count(QLatin1String("&&")) * fm.width(QLatin1Char('&')); - sz.setWidth(w); + sz.setWidth(fm.boundingRect(QRect(), Qt::TextSingleLine | Qt::TextShowMnemonic, s).width()); sz.setHeight(qMax(fm.height(), qfm.height())); QIcon is = action->icon(); @@ -484,14 +486,13 @@ void QMenuPrivate::setFirstActionActive() { Q_Q(QMenu); updateActionRects(); - const int scrollerHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q); for(int i = 0, saccum = 0; i < actions.count(); i++) { const QRect &rect = actionRects.at(i); if (rect.isNull()) continue; if (scroll && scroll->scrollFlags & QMenuScroller::ScrollUp) { saccum -= rect.height(); - if (saccum > scroll->scrollOffset-scrollerHeight) + if (saccum > scroll->scrollOffset - scrollerHeight()) continue; } QAction *act = actions.at(i); @@ -669,16 +670,14 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc return; updateActionRects(); int newOffset = 0; - const int scrollHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q); - const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollHeight : 0; - const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollHeight : 0; + const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollerHeight() : 0; + const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollerHeight() : 0; const int vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, 0, q); const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q); if (location == QMenuScroller::ScrollTop) { for(int i = 0, saccum = 0; i < actions.count(); i++) { - QAction *act = actions.at(i); - if (act == action) { + if (actions.at(i) == action) { newOffset = topScroll - saccum; break; } @@ -686,9 +685,8 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc } } else { for(int i = 0, saccum = 0; i < actions.count(); i++) { - QAction *act = actions.at(i); saccum += actionRects.at(i).height(); - if (act == action) { + if (actions.at(i) == action) { if (location == QMenuScroller::ScrollCenter) newOffset = ((q->height() / 2) - botScroll) - (saccum - topScroll); else @@ -757,9 +755,19 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc } //actually update flags - scroll->scrollOffset = newOffset; - if (scroll->scrollOffset > 0) - scroll->scrollOffset = 0; + const int delta = qMin(0, newOffset) - scroll->scrollOffset; //make sure the new offset is always negative + if (!itemsDirty && delta) { + //we've scrolled so we need to update the action rects + for (int i = 0; i < actionRects.count(); ++i) { + QRect ¤t = actionRects[i]; + current.moveTop(current.top() + delta); + + //we need to update the widgets geometry + if (QWidget *w = widgetItems.at(i)) + w->setGeometry(current); + } + } + scroll->scrollOffset += delta; scroll->scrollFlags = newScrollFlags; if (active) setCurrentAction(action); @@ -811,9 +819,8 @@ void QMenuPrivate::scrollMenu(QMenuScroller::ScrollDirection direction, bool pag if (!scroll || !(scroll->scrollFlags & direction)) //not really possible... return; updateActionRects(); - const int scrollHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q); - const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollHeight : 0; - const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollHeight : 0; + const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollerHeight() : 0; + const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollerHeight() : 0; const int vmargin = q->style()->pixelMetric(QStyle::PM_MenuVMargin, 0, q); const int fw = q->style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, q); const int offset = topScroll ? topScroll-vmargin : 0; @@ -860,13 +867,12 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e) if (scroll && !activeMenu) { //let the scroller "steal" the event bool isScroll = false; if (pos.x() >= 0 && pos.x() < q->width()) { - const int scrollerHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q); for(int dir = QMenuScroller::ScrollUp; dir <= QMenuScroller::ScrollDown; dir = dir << 1) { if (scroll->scrollFlags & dir) { if (dir == QMenuScroller::ScrollUp) - isScroll = (pos.y() <= scrollerHeight); + isScroll = (pos.y() <= scrollerHeight()); else if (dir == QMenuScroller::ScrollDown) - isScroll = (pos.y() >= q->height()-scrollerHeight); + isScroll = (pos.y() >= q->height() - scrollerHeight()); if (isScroll) { scroll->scrollDirection = dir; break; @@ -875,19 +881,17 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e) } } if (isScroll) { - if (!scroll->scrollTimer) - scroll->scrollTimer = new QBasicTimer; - scroll->scrollTimer->start(50, q); + scroll->scrollTimer.start(50, q); return true; - } else if (scroll->scrollTimer && scroll->scrollTimer->isActive()) { - scroll->scrollTimer->stop(); + } else { + scroll->scrollTimer.stop(); } } if (tearoff) { //let the tear off thingie "steal" the event.. QRect tearRect(0, 0, q->width(), q->style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, q)); if (scroll && scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp) - tearRect.translate(0, q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q)); + tearRect.translate(0, scrollerHeight()); q->update(tearRect); if (tearRect.contains(pos) && hasMouseMoved(e->globalPos())) { setCurrentAction(0); @@ -1348,8 +1352,7 @@ QMenu::~QMenu() if (d->eventLoop) d->eventLoop->exit(); - if (d->tornPopup) - d->tornPopup->close(); + hideTearOffMenu(); } /*! @@ -1560,8 +1563,8 @@ void QMenu::setTearOffEnabled(bool b) Q_D(QMenu); if (d->tearoff == b) return; - if (!b && d->tornPopup) - d->tornPopup->close(); + if (!b) + hideTearOffMenu(); d->tearoff = b; d->itemsDirty = true; @@ -1596,8 +1599,8 @@ bool QMenu::isTearOffMenuVisible() const */ void QMenu::hideTearOffMenu() { - if (d_func()->tornPopup) - d_func()->tornPopup->close(); + if (QWidget *w = d_func()->tornPopup) + w->close(); } @@ -1712,8 +1715,6 @@ QSize QMenu::sizeHint() const if (rect.right() >= s.width()) s.setWidth(rect.x() + rect.width()); } - if (d->tearoff) - s.rheight() += style()->pixelMetric(QStyle::PM_MenuTearoffHeight, &opt, this); // Note that the action rects calculated above already include // the top and left margins, so we only need to add margins for // the bottom and right. @@ -2054,6 +2055,8 @@ void QMenu::hideEvent(QHideEvent *) d->hasHadMouse = false; d->causedPopup.widget = 0; d->causedPopup.action = 0; + if (d->scroll) + d->scroll->scrollTimer.stop(); //make sure the timer stops } /*! @@ -2095,18 +2098,17 @@ void QMenu::paintEvent(QPaintEvent *e) const int fw = style()->pixelMetric(QStyle::PM_MenuPanelWidth, 0, this); //draw the scroller regions.. if (d->scroll) { - const int scrollerHeight = style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, this); menuOpt.menuItemType = QStyleOptionMenuItem::Scroller; menuOpt.state |= QStyle::State_Enabled; if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp) { - menuOpt.rect.setRect(fw, fw, width() - (fw * 2), scrollerHeight); + menuOpt.rect.setRect(fw, fw, width() - (fw * 2), d->scrollerHeight()); emptyArea -= QRegion(menuOpt.rect); p.setClipRect(menuOpt.rect); style()->drawControl(QStyle::CE_MenuScroller, &menuOpt, &p, this); } if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown) { - menuOpt.rect.setRect(fw, height() - scrollerHeight - fw, width() - (fw * 2), - scrollerHeight); + menuOpt.rect.setRect(fw, height() - d->scrollerHeight() - fw, width() - (fw * 2), + d->scrollerHeight()); emptyArea -= QRegion(menuOpt.rect); menuOpt.state |= QStyle::State_DownArrow; p.setClipRect(menuOpt.rect); @@ -2119,7 +2121,7 @@ void QMenu::paintEvent(QPaintEvent *e) menuOpt.rect.setRect(fw, fw, width() - (fw * 2), style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this)); if (d->scroll && d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp) - menuOpt.rect.translate(0, style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, this)); + menuOpt.rect.translate(0, d->scrollerHeight()); emptyArea -= QRegion(menuOpt.rect); p.setClipRect(menuOpt.rect); menuOpt.state = QStyle::State_None; @@ -2449,7 +2451,7 @@ void QMenu::keyPressEvent(QKeyEvent *e) continue; nextAction = next; if (d->scroll && (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp)) { - int topVisible = style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, this); + int topVisible = d->scrollerHeight(); if (d->tearoff) topVisible += style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this); if (((y + d->scroll->scrollOffset) - topVisible) <= d->actionRects.at(next_i).height()) @@ -2480,10 +2482,9 @@ void QMenu::keyPressEvent(QKeyEvent *e) continue; nextAction = next; if (d->scroll && (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollDown)) { - const int scrollerHeight = style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, this); - int bottomVisible = height()-scrollerHeight; + int bottomVisible = height() - d->scrollerHeight(); if (d->scroll->scrollFlags & QMenuPrivate::QMenuScroller::ScrollUp) - bottomVisible -= scrollerHeight; + bottomVisible -= d->scrollerHeight(); if (d->tearoff) bottomVisible -= style()->pixelMetric(QStyle::PM_MenuTearoffHeight, 0, this); if ((y + d->scroll->scrollOffset + d->actionRects.at(next_i).height()) > bottomVisible) @@ -2499,8 +2500,7 @@ void QMenu::keyPressEvent(QKeyEvent *e) } if (nextAction) { if (d->scroll && scroll_loc != QMenuPrivate::QMenuScroller::ScrollStay) { - if (d->scroll->scrollTimer) - d->scroll->scrollTimer->stop(); + d->scroll->scrollTimer.stop(); d->scrollMenu(nextAction, scroll_loc); } d->setCurrentAction(nextAction, /*popup*/-1, QMenuPrivate::SelectedFromKeyboard); @@ -2761,10 +2761,10 @@ void QMenu::timerEvent(QTimerEvent *e) { Q_D(QMenu); - if (d->scroll && d->scroll->scrollTimer && d->scroll->scrollTimer->timerId() == e->timerId()) { + if (d->scroll && d->scroll->scrollTimer.timerId() == e->timerId()) { d->scrollMenu((QMenuPrivate::QMenuScroller::ScrollDirection)d->scroll->scrollDirection); if (d->scroll->scrollFlags == QMenuPrivate::QMenuScroller::ScrollNone) - d->scroll->scrollTimer->stop(); + d->scroll->scrollTimer.stop(); } else if(QMenuPrivate::menuDelayTimer.timerId() == e->timerId()) { QMenuPrivate::menuDelayTimer.stop(); internalDelayedPopup(); diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h index 50a9f2f..4e428fe 100644 --- a/src/gui/widgets/qmenu_p.h +++ b/src/gui/widgets/qmenu_p.h @@ -151,6 +151,8 @@ public: } void init(); + int scrollerHeight() const; + //item calculations mutable uint itemsDirty : 1; mutable uint maxIconWidth, tabWidth; @@ -189,10 +191,10 @@ public: enum ScrollDirection { ScrollNone=0, ScrollUp=0x01, ScrollDown=0x02 }; uint scrollFlags : 2, scrollDirection : 2; int scrollOffset; - QBasicTimer *scrollTimer; + QBasicTimer scrollTimer; - QMenuScroller() : scrollFlags(ScrollNone), scrollDirection(ScrollNone), scrollOffset(0), scrollTimer(0) { } - ~QMenuScroller() { delete scrollTimer; } + QMenuScroller() : scrollFlags(ScrollNone), scrollDirection(ScrollNone), scrollOffset(0) { } + ~QMenuScroller() { } } *scroll; void scrollMenu(QMenuScroller::ScrollLocation location, bool active=false); void scrollMenu(QMenuScroller::ScrollDirection direction, bool page=false, bool active=false); diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index e1d41de..6b93879 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -218,7 +218,7 @@ void QMenuBarPrivate::updateGeometries() bool hasHiddenActions = false; for (int i = 0; i < actions.count(); ++i) { const QRect &rect = actionRects.at(i); - if (!menuRect.contains(rect)) { + if (rect.isValid() && !menuRect.contains(rect)) { hasHiddenActions = true; break; } @@ -229,7 +229,7 @@ void QMenuBarPrivate::updateGeometries() menuRect = this->menuRect(true); for (int i = 0; i < actions.count(); ++i) { const QRect &rect = actionRects.at(i); - if (!menuRect.contains(rect)) { + if (rect.isValid() && !menuRect.contains(rect)) { hiddenActions.append(actions.at(i)); } } @@ -447,10 +447,7 @@ void QMenuBarPrivate::calcActionRects(int max_width, int start) const } else { const QString s = action->text(); if(!s.isEmpty()) { - const int w = fm.width(s) - - s.count(QLatin1Char('&')) * fm.width(QLatin1Char('&')) - + s.count(QLatin1String("&&")) * fm.width(QLatin1Char('&')); - sz = QSize(w, fm.height()); + sz = fm.size(Qt::TextShowMnemonic, s); } QIcon is = action->icon(); @@ -956,6 +953,13 @@ void QMenuBar::setActiveAction(QAction *act) /*! Removes all the actions from the menu bar. + \note On Mac OS X, menu items that have been merged to the system + menu bar are not removed by this function. One way to handle this + would be to remove the extra actions yourself. You can set the + \l{QAction::MenuRole}{menu role} on the different menus, so that + you know ahead of time which menu items get merged and which do + not. Then decide what to recreate or remove yourself. + \sa removeAction() */ void QMenuBar::clear() diff --git a/src/gui/widgets/qprogressbar.cpp b/src/gui/widgets/qprogressbar.cpp index ac3338b..d168028 100644 --- a/src/gui/widgets/qprogressbar.cpp +++ b/src/gui/widgets/qprogressbar.cpp @@ -204,7 +204,7 @@ bool QProgressBarPrivate::repaintRequired() const \o A progress bar shown in the Plastique widget style. \endtable - \sa QTimeLine, QProgressDialog, {fowler}{GUI Design Handbook: Progress Indicator} + \sa QProgressDialog, {fowler}{GUI Design Handbook: Progress Indicator} */ /*! diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp index e069a21..3933272 100644 --- a/src/gui/widgets/qspinbox.cpp +++ b/src/gui/widgets/qspinbox.cpp @@ -50,6 +50,7 @@ #include <qdebug.h> #include <math.h> +#include <float.h> QT_BEGIN_NAMESPACE @@ -823,8 +824,8 @@ void QDoubleSpinBox::setRange(double minimum, double maximum) Sets how many decimals the spinbox will use for displaying and interpreting doubles. - \warning The results might not be reliable with very high values - for \a decimals. + \warning The maximum value for \a decimals is DBL_MAX_10_EXP + + DBL_DIG (ie. 323) because of the limitations of the double type. Note: The maximum, minimum and value might change as a result of changing this property. @@ -840,7 +841,7 @@ int QDoubleSpinBox::decimals() const void QDoubleSpinBox::setDecimals(int decimals) { Q_D(QDoubleSpinBox); - d->decimals = qMax(0, decimals); + d->decimals = qBound(0, decimals, DBL_MAX_10_EXP + DBL_DIG); setRange(minimum(), maximum()); // make sure values are rounded setValue(value()); diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp index 11cb6a1..690e624 100644 --- a/src/gui/widgets/qtabbar.cpp +++ b/src/gui/widgets/qtabbar.cpp @@ -663,7 +663,7 @@ void QTabBarPrivate::refresh() if (pressedIndex != -1 && movable && QApplication::mouseButtons() == Qt::NoButton) { - _q_moveTabFinished(pressedIndex); + moveTabFinished(pressedIndex); if (!validIndex(pressedIndex)) pressedIndex = -1; } @@ -1662,26 +1662,17 @@ void QTabBarPrivate::slide(int from, int to) q->setUpdatesEnabled(true); int postLocation = vertical ? q->tabRect(to).y() : q->tabRect(to).x(); int length = postLocation - preLocation; - tabList[to].makeTimeLine(q); - tabList[to].dragOffset += -1 * length; - tabList[to].timeLine->setFrameRange(tabList[to].dragOffset, 0); - animations[tabList[to].timeLine] = to; - tabList[to].timeLine->setDuration(ANIMATION_DURATION); - if (tabList[to].timeLine->state() != QTimeLine::Running) - tabList[to].timeLine->start(); + tabList[to].dragOffset -= length; + tabList[to].startAnimation(this, ANIMATION_DURATION); } -void QTabBarPrivate::_q_moveTab(int offset) +void QTabBarPrivate::moveTab(int index, int offset) { - Q_Q(QTabBar); - if (QTimeLine *timeLine = qobject_cast<QTimeLine *>(q->sender())) { - int index = animations[timeLine]; - if (!validIndex(index)) - return; - tabList[index].dragOffset = offset; - layoutTab(index); // Make buttons follow tab - q->update(); - } + if (!validIndex(index)) + return; + tabList[index].dragOffset = offset; + layoutTab(index); // Make buttons follow tab + q_func()->update(); } /*!\reimp @@ -1695,7 +1686,7 @@ void QTabBar::mousePressEvent(QMouseEvent *event) } // Be safe! if (d->pressedIndex != -1 && d->movable) - d->_q_moveTabFinished(d->pressedIndex); + d->moveTabFinished(d->pressedIndex); d->pressedIndex = d->indexAtPos(event->pos()); if (d->validIndex(d->pressedIndex)) { @@ -1721,7 +1712,7 @@ void QTabBar::mouseMoveEvent(QMouseEvent *event) // Be safe! if (d->pressedIndex != -1 && event->buttons() == Qt::NoButton) - d->_q_moveTabFinished(d->pressedIndex); + d->moveTabFinished(d->pressedIndex); // Start drag if (!d->dragInProgress && d->pressedIndex != -1) { @@ -1789,16 +1780,6 @@ void QTabBar::mouseMoveEvent(QMouseEvent *event) optTabBase.documentMode = d->documentMode; } -void QTabBarPrivate::_q_moveTabFinished() -{ - Q_Q(QTabBar); - if (QTimeLine *timeLine = qobject_cast<QTimeLine *>(q->sender())) { - int index = animations[timeLine]; - animations.remove(timeLine); - _q_moveTabFinished(index); - } -} - void QTabBarPrivate::setupMovableTab() { Q_Q(QTabBar); @@ -1838,11 +1819,19 @@ void QTabBarPrivate::setupMovableTab() movingTab->setVisible(true); } -void QTabBarPrivate::_q_moveTabFinished(int index) +void QTabBarPrivate::moveTabFinished(int index) { Q_Q(QTabBar); bool cleanup = (pressedIndex == index) || (pressedIndex == -1) || !validIndex(index); - if (animations.isEmpty() && cleanup) { + bool allAnimationsFinished = true; +#ifndef QT_NO_ANIMATION + for(int i = 0; allAnimationsFinished && i < tabList.count(); ++i) { + const Tab &t = tabList.at(i); + if (t.animation && t.animation->state() == QAbstractAnimation::Running) + allAnimationsFinished = false; + } +#endif //QT_NO_ANIMATION + if (allAnimationsFinished && cleanup) { movingTab->setVisible(false); // We might not get a mouse release for (int i = 0; i < tabList.count(); ++i) { tabList[i].dragOffset = 0; @@ -1877,17 +1866,8 @@ void QTabBar::mouseReleaseEvent(QMouseEvent *event) ? tabRect(d->pressedIndex).height() : tabRect(d->pressedIndex).width(); int duration = qMin(ANIMATION_DURATION, - ((length < 0 ? (-1 * length) : length) * ANIMATION_DURATION) / width); - if (duration > 0) { - d->tabList[d->pressedIndex].makeTimeLine(this); - d->tabList[d->pressedIndex].timeLine->setFrameRange(length, 0); - d->animations[d->tabList[d->pressedIndex].timeLine] = d->pressedIndex; - d->tabList[d->pressedIndex].timeLine->setDuration(duration); - if (d->tabList[d->pressedIndex].timeLine->state() != QTimeLine::Running) - d->tabList[d->pressedIndex].timeLine->start(); - } else { - d->_q_moveTabFinished(d->pressedIndex); - } + (qAbs(length) * ANIMATION_DURATION) / width); + d->tabList[d->pressedIndex].startAnimation(d, duration); d->dragInProgress = false; d->movingTab->setVisible(false); d->dragStartPosition = QPoint(); diff --git a/src/gui/widgets/qtabbar.h b/src/gui/widgets/qtabbar.h index 7514486..402f54b 100644 --- a/src/gui/widgets/qtabbar.h +++ b/src/gui/widgets/qtabbar.h @@ -215,8 +215,6 @@ private: Q_DECLARE_PRIVATE(QTabBar) Q_PRIVATE_SLOT(d_func(), void _q_scrollTabs()) Q_PRIVATE_SLOT(d_func(), void _q_closeTab()) - Q_PRIVATE_SLOT(d_func(), void _q_moveTab(int)) - Q_PRIVATE_SLOT(d_func(), void _q_moveTabFinished()) }; #endif // QT_NO_TABBAR diff --git a/src/gui/widgets/qtabbar_p.h b/src/gui/widgets/qtabbar_p.h index dbae055..b9b9fba 100644 --- a/src/gui/widgets/qtabbar_p.h +++ b/src/gui/widgets/qtabbar_p.h @@ -58,9 +58,8 @@ #include <qicon.h> #include <qtoolbutton.h> -#include <qtimeline.h> -#include <qhash.h> #include <qdebug.h> +#include <qvariantanimation.h> #ifndef QT_NO_TABBAR @@ -75,9 +74,10 @@ class QTabBarPrivate : public QWidgetPrivate Q_DECLARE_PUBLIC(QTabBar) public: QTabBarPrivate() - :currentIndex(-1), pressedIndex(-1), - shape(QTabBar::RoundedNorth), - layoutDirty(false), drawBase(true), scrollOffset(0), expanding(true), closeButtonOnTabs(false), selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false), dragInProgress(false), documentMode(false), movingTab(0) {} + :currentIndex(-1), pressedIndex(-1), shape(QTabBar::RoundedNorth), layoutDirty(false), + drawBase(true), scrollOffset(0), expanding(true), closeButtonOnTabs(false), + selectionBehaviorOnRemove(QTabBar::SelectRightTab), paintWithOffsets(true), movable(false), + dragInProgress(false), documentMode(false), movingTab(0) {} int currentIndex; int pressedIndex; @@ -88,16 +88,13 @@ public: struct Tab { inline Tab(const QIcon &ico, const QString &txt) - : enabled(true) - , shortcutId(0) - , text(txt) - , icon(ico) - , leftWidget(0) - , rightWidget(0) - , lastTab(-1) - , timeLine(0) - , dragOffset(0) + : enabled(true) , shortcutId(0), text(txt), icon(ico), + leftWidget(0), rightWidget(0), lastTab(-1), dragOffset(0) +#ifndef QT_NO_ANIMATION + , animation(0) +#endif //QT_NO_ANIMATION {} + bool operator==(const Tab &other) const { return &other == this; } bool enabled; int shortcutId; QString text; @@ -117,21 +114,39 @@ public: QWidget *leftWidget; QWidget *rightWidget; int lastTab; - - QTimeLine *timeLine; int dragOffset; - void makeTimeLine(QWidget *q) { - if (timeLine) - return; - timeLine = new QTimeLine(ANIMATION_DURATION, q); - q->connect(timeLine, SIGNAL(frameChanged(int)), q, SLOT(_q_moveTab(int))); - q->connect(timeLine, SIGNAL(finished()), q, SLOT(_q_moveTabFinished())); +#ifndef QT_NO_ANIMATION + ~Tab() { delete animation; } + struct TabBarAnimation : public QVariantAnimation { + TabBarAnimation(Tab *t, QTabBarPrivate *_priv) : tab(t), priv(_priv) + { setEasingCurve(QEasingCurve::InOutQuad); } + + void updateCurrentValue(const QVariant ¤t) + { priv->moveTab(priv->tabList.indexOf(*tab), current.toInt()); } + + void updateState(State, State newState) + { if (newState == Stopped) priv->moveTabFinished(priv->tabList.indexOf(*tab)); } + private: + //these are needed for the callbacks + Tab *tab; + QTabBarPrivate *priv; + } *animation; + + void startAnimation(QTabBarPrivate *priv, int duration) { + if (!animation) + animation = new TabBarAnimation(this, priv); + animation->setStartValue(dragOffset); + animation->setEndValue(0); + animation->setDuration(duration); + animation->start(); } - +#else + void startAnimation(QTabBarPrivate *priv, int duration) + { Q_UNUSED(duration); priv->moveTabFinished(priv->tabList.indexOf(*this)); } +#endif //QT_NO_ANIMATION }; QList<Tab> tabList; - QHash<QTimeLine*, int> animations; int calculateNewPosition(int from, int to, int index) const; void slide(int from, int to); @@ -152,9 +167,8 @@ public: void _q_scrollTabs(); void _q_closeTab(); - void _q_moveTab(int); - void _q_moveTabFinished(); - void _q_moveTabFinished(int offset); + void moveTab(int index, int offset); + void moveTabFinished(int index); QRect hoverRect; void refresh(); diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp index b249915..b65f1ba 100644 --- a/src/gui/widgets/qtoolbar.cpp +++ b/src/gui/widgets/qtoolbar.cpp @@ -1074,6 +1074,15 @@ static bool waitForPopup(QToolBar *tb, QWidget *popup) return false; } +#if defined(Q_WS_MAC) +static bool toolbarInUnifiedToolBar(QToolBar *toolbar) +{ + const QMainWindow *mainWindow = qobject_cast<const QMainWindow *>(toolbar->parentWidget()); + return mainWindow && mainWindow->unifiedTitleAndToolBarOnMac() + && mainWindow->toolBarArea(toolbar) == Qt::TopToolBarArea; +} +#endif + /*! \reimp */ bool QToolBar::event(QEvent *event) { @@ -1096,7 +1105,15 @@ bool QToolBar::event(QEvent *event) // fallthrough intended case QEvent::Show: d->toggleViewAction->setChecked(event->type() == QEvent::Show); -#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) +#if defined(Q_WS_MAC) + if (toolbarInUnifiedToolBar(this)) { + // I can static_cast because I did the qobject_cast in the if above, therefore + // we must have a QMainWindowLayout here. + QMainWindowLayout *mwLayout = static_cast<QMainWindowLayout *>(parentWidget()->layout()); + mwLayout->fixSizeInUnifiedToolbar(this); + mwLayout->syncUnifiedToolbarVisibility(); + } +# if !defined(QT_MAC_USE_COCOA) // Fall through case QEvent::LayoutRequest: { // There's currently no way to invalidate the size and let @@ -1111,10 +1128,9 @@ bool QToolBar::event(QEvent *event) } if (needUpdate) { - OSWindowRef windowRef = qt_mac_window_for(this); - if (mainWindow->unifiedTitleAndToolBarOnMac() - && mainWindow->toolBarArea(this) == Qt::TopToolBarArea - && macWindowToolbarVisible(windowRef)) { + OSWindowRef windowRef = qt_mac_window_for(mainWindow); + if (toolbarInUnifiedToolBar(this) + && macWindowToolbarIsVisible(windowRef)) { DisableScreenUpdates(); macWindowToolbarShow(this, false); macWindowToolbarShow(this, true); @@ -1126,7 +1142,8 @@ bool QToolBar::event(QEvent *event) return earlyResult; } } -#endif +# endif // !QT_MAC_USE_COCOA +#endif // Q_WS_MAC break; case QEvent::ParentChange: d->layout->checkUsePopupMenu(); diff --git a/src/gui/widgets/qtoolbararealayout.cpp b/src/gui/widgets/qtoolbararealayout.cpp index 0c11700..b4a0ef0 100644 --- a/src/gui/widgets/qtoolbararealayout.cpp +++ b/src/gui/widgets/qtoolbararealayout.cpp @@ -156,21 +156,15 @@ void QToolBarAreaLayoutLine::fitLayout() if (item.skip()) continue; - QToolBarLayout *tblayout = qobject_cast<QToolBarLayout*>(item.widgetItem->widget()->layout()); - if (tblayout) + if (QToolBarLayout *tblayout = qobject_cast<QToolBarLayout*>(item.widgetItem->widget()->layout())) tblayout->checkUsePopupMenu(); - int itemMin = pick(o, item.minimumSize()); - int itemHint = pick(o, item.sizeHint()); - //we ensure the extraspace is not too low - item.size = qMax(item.size, itemHint); - if (item.preferredSize > 0) { - //preferredSize would be the default size - item.size = item.preferredSize; - } + const int itemMin = pick(o, item.minimumSize()); + //preferredSize is the default if it is set, otherwise, we take the sizehint + item.size = item.preferredSize > 0 ? item.preferredSize : pick(o, item.sizeHint()); //the extraspace is the space above the item minimum sizehint - int extraSpace = qMin(item.size - itemMin, extra); + const int extraSpace = qMin(item.size - itemMin, extra); item.size = itemMin + extraSpace; //that is the real size extra -= extraSpace; diff --git a/src/gui/widgets/qwidgetanimator.cpp b/src/gui/widgets/qwidgetanimator.cpp index 56b3f43..1a93b51 100644 --- a/src/gui/widgets/qwidgetanimator.cpp +++ b/src/gui/widgets/qwidgetanimator.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#include <QtCore/qpropertyanimation.h> #include <QtGui/qwidget.h> #include <QtGui/private/qmainwindowlayout_p.h> @@ -46,130 +47,72 @@ QT_BEGIN_NAMESPACE -static const int g_animation_steps = 12; -static const int g_animation_interval = 16; - -// 1000 * (x/(1 + x*x) + 0.5) on interval [-1, 1] -static const int g_animate_function[] = -{ - 0, 1, 5, 12, 23, 38, 58, 84, 116, 155, 199, 251, 307, 368, - 433, 500, 566, 631, 692, 748, 799, 844, 883, 915, 941, 961, - 976, 987, 994, 998, 1000 -}; -static const int g_animate_function_points = sizeof(g_animate_function)/sizeof(int); - -static inline int animateHelper(int start, int stop, int step, int steps) -{ - if (start == stop) - return start; - if (step == 0) - return start; - if (step == steps) - return stop; - - int x = g_animate_function_points*step/(steps + 1); - return start + g_animate_function[x]*(stop - start)/1000; -} - QWidgetAnimator::QWidgetAnimator(QMainWindowLayout *layout) : m_mainWindowLayout(layout) { } -QWidgetAnimator::~QWidgetAnimator() +void QWidgetAnimator::abort(QWidget *w) { +#ifndef QT_NO_ANIMATION + AnimationMap::iterator it = m_animation_map.find(w); + if (it == m_animation_map.end()) + return; + QPropertyAnimation *anim = *it; + m_animation_map.erase(it); + anim->stop(); + m_mainWindowLayout->animationFinished(w); +#else + Q_UNUSED(w); //there is no animation to abort +#endif //QT_NO_ANIMATION } -void QWidgetAnimator::abort(QWidget *w) +#ifndef QT_NO_ANIMATION +void QWidgetAnimator::animationFinished() { - if (m_animation_map.remove(w) == 0) - return; - if (m_animation_map.isEmpty()) { - m_timer.stop(); - m_mainWindowLayout->allAnimationsFinished(); - } + QPropertyAnimation *anim = qobject_cast<QPropertyAnimation*>(sender()); + abort(static_cast<QWidget*>(anim->targetObject())); } +#endif //QT_NO_ANIMATION void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, bool animate) { - QRect final_geometry = _final_geometry; - QRect r = widget->geometry(); if (r.right() < 0 || r.bottom() < 0) r = QRect(); - if (r.isNull() || final_geometry.isNull() || r == final_geometry) - animate = false; + animate = animate && !r.isNull() && !_final_geometry.isNull(); + + // might make the wigdet go away by sending it to negative space + const QRect final_geometry = _final_geometry.isValid() || widget->isWindow() ? _final_geometry : + QRect(QPoint(-500 - widget->width(), -500 - widget->height()), widget->size()); + if (r == final_geometry) + return; //the widget is already where it should be +#ifndef QT_NO_ANIMATION AnimationMap::const_iterator it = m_animation_map.constFind(widget); - if (it != m_animation_map.constEnd() && (*it).r2 == final_geometry) + if (it != m_animation_map.constEnd() && (*it)->endValue().toRect() == final_geometry) return; - if (animate) { - AnimationItem item(widget, r, final_geometry); - m_animation_map[widget] = item; - if (!m_timer.isActive()) { - m_timer.start(g_animation_interval, this); - m_time.start(); - } - } else { - if (!final_geometry.isValid() && !widget->isWindow()) { - // Make the wigdet go away by sending it to negative space - QSize s = widget->size(); - final_geometry = QRect(-500 - s.width(), -500 - s.height(), s.width(), s.height()); - } - widget->setGeometry(final_geometry); - - if (m_animation_map.remove(widget)) { - m_mainWindowLayout->animationFinished(widget); - if (m_animation_map.isEmpty()) { - m_timer.stop(); - m_mainWindowLayout->allAnimationsFinished(); - } - } - } -} - -void QWidgetAnimator::timerEvent(QTimerEvent *) -{ - int steps = (1 + m_time.restart())/g_animation_interval; - AnimationMap::iterator it = m_animation_map.begin(); - while (it != m_animation_map.end()) { - AnimationItem &item = *it; - - item.step = qMin(item.step + steps, g_animation_steps); - - int x = animateHelper(item.r1.left(), item.r2.left(), - item.step, g_animation_steps); - int y = animateHelper(item.r1.top(), item.r2.top(), - item.step, g_animation_steps); - int w = animateHelper(item.r1.width(), item.r2.width(), - item.step, g_animation_steps); - int h = animateHelper(item.r1.height(), item.r2.height(), - item.step, g_animation_steps); - - item.widget->setGeometry(x, y, w, h); - - if (item.step == g_animation_steps) { - QWidget *widget = item.widget; - it = m_animation_map.erase(it); - m_mainWindowLayout->animationFinished(widget); - } else { - ++it; - } - } - - if (m_animation_map.isEmpty()) { - m_timer.stop(); - m_mainWindowLayout->allAnimationsFinished(); - } + QPropertyAnimation *anim = new QPropertyAnimation(widget, "geometry"); + anim->setDuration(animate ? 200 : 0); + anim->setEasingCurve(QEasingCurve::InOutQuad); + anim->setEndValue(final_geometry); + m_animation_map[widget] = anim; + connect(anim, SIGNAL(finished()), SLOT(animationFinished())); + anim->start(QPropertyAnimation::DeleteWhenStopped); +#else + //we do it in one shot + widget->setGeometry(final_geometry); + m_mainWindowLayout->animationFinished(widget); +#endif //QT_NO_ANIMATION } bool QWidgetAnimator::animating() const { - return m_timer.isActive(); + return !m_animation_map.isEmpty(); } -bool QWidgetAnimator::animating(QWidget *widget) +bool QWidgetAnimator::animating(QWidget *widget) const { return m_animation_map.contains(widget); } diff --git a/src/gui/widgets/qwidgetanimator_p.h b/src/gui/widgets/qwidgetanimator_p.h index 0c68e00..5a3e39d 100644 --- a/src/gui/widgets/qwidgetanimator_p.h +++ b/src/gui/widgets/qwidgetanimator_p.h @@ -54,43 +54,34 @@ // #include <qobject.h> -#include <qrect.h> #include <qmap.h> -#include <qbasictimer.h> -#include <qdatetime.h> QT_BEGIN_NAMESPACE class QWidget; class QMainWindowLayout; +class QPropertyAnimation; +class QRect; class QWidgetAnimator : public QObject { + Q_OBJECT public: QWidgetAnimator(QMainWindowLayout *layout); - ~QWidgetAnimator(); void animate(QWidget *widget, const QRect &final_geometry, bool animate); bool animating() const; - bool animating(QWidget *widget); + bool animating(QWidget *widget) const; void abort(QWidget *widget); -protected: - void timerEvent(QTimerEvent *e); +#ifndef QT_NO_ANIMATION +private Q_SLOTS: + void animationFinished(); +#endif private: - struct AnimationItem { - AnimationItem(QWidget *_widget = 0, const QRect &_r1 = QRect(), - const QRect &_r2 = QRect()) - : widget(_widget), r1(_r1), r2(_r2), step(0) {} - QWidget *widget; - QRect r1, r2; - int step; - }; - typedef QMap<QWidget*, AnimationItem> AnimationMap; + typedef QMap<QWidget*, QPropertyAnimation*> AnimationMap; AnimationMap m_animation_map; - QBasicTimer m_timer; - QTime m_time; QMainWindowLayout *m_mainWindowLayout; }; |