mirror of
https://github.com/crystalidea/qt-build-tools.git
synced 2024-11-26 12:37:11 +08:00
5.5.14 original files
This commit is contained in:
parent
617e91d13a
commit
446a887d34
392
5.15.14/qtbase/src/plugins/platforms/cocoa/qnsview.mm
Normal file
392
5.15.14/qtbase/src/plugins/platforms/cocoa/qnsview.mm
Normal file
@ -0,0 +1,392 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the plugins of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:COMM$
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <QtGui/qtguiglobal.h>
|
||||||
|
|
||||||
|
#include "qnsview.h"
|
||||||
|
#include "qcocoawindow.h"
|
||||||
|
#include "qcocoahelpers.h"
|
||||||
|
#include "qcocoascreen.h"
|
||||||
|
#include "qmultitouch_mac_p.h"
|
||||||
|
#include "qcocoadrag.h"
|
||||||
|
#include "qcocoainputcontext.h"
|
||||||
|
#include <qpa/qplatformintegration.h>
|
||||||
|
|
||||||
|
#include <qpa/qwindowsysteminterface.h>
|
||||||
|
#include <QtGui/QTextFormat>
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QPointer>
|
||||||
|
#include <QtCore/QSet>
|
||||||
|
#include <QtCore/qsysinfo.h>
|
||||||
|
#include <QtGui/QAccessible>
|
||||||
|
#include <QtGui/QImage>
|
||||||
|
#include <private/qguiapplication_p.h>
|
||||||
|
#include <private/qcoregraphics_p.h>
|
||||||
|
#include <private/qwindow_p.h>
|
||||||
|
#include "qcocoabackingstore.h"
|
||||||
|
#ifndef QT_NO_OPENGL
|
||||||
|
#include "qcocoaglcontext.h"
|
||||||
|
#endif
|
||||||
|
#include "qcocoaintegration.h"
|
||||||
|
|
||||||
|
// Private interface
|
||||||
|
@interface QNSView ()
|
||||||
|
- (BOOL)isTransparentForUserInput;
|
||||||
|
@property (assign) NSView* previousSuperview;
|
||||||
|
@property (assign) NSWindow* previousWindow;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface QNSView (Drawing) <CALayerDelegate>
|
||||||
|
- (void)initDrawing;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) : NSObject
|
||||||
|
- (instancetype)initWithView:(QNSView *)theView;
|
||||||
|
- (void)mouseMoved:(NSEvent *)theEvent;
|
||||||
|
- (void)mouseEntered:(NSEvent *)theEvent;
|
||||||
|
- (void)mouseExited:(NSEvent *)theEvent;
|
||||||
|
- (void)cursorUpdate:(NSEvent *)theEvent;
|
||||||
|
@end
|
||||||
|
|
||||||
|
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSViewMouseMoveHelper);
|
||||||
|
|
||||||
|
@interface QNSView (Mouse)
|
||||||
|
- (void)initMouse;
|
||||||
|
- (NSPoint)screenMousePoint:(NSEvent *)theEvent;
|
||||||
|
- (void)mouseMovedImpl:(NSEvent *)theEvent;
|
||||||
|
- (void)mouseEnteredImpl:(NSEvent *)theEvent;
|
||||||
|
- (void)mouseExitedImpl:(NSEvent *)theEvent;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface QNSView (Touch)
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface QNSView (Tablet)
|
||||||
|
- (bool)handleTabletEvent:(NSEvent *)theEvent;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface QNSView (Gestures)
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface QNSView (Dragging)
|
||||||
|
-(void)registerDragTypes;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface QNSView (Keys)
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface QNSView (ComplexText) <NSTextInputClient>
|
||||||
|
- (void)textInputContextKeyboardSelectionDidChangeNotification:(NSNotification *)textInputContextKeyboardSelectionDidChangeNotification;
|
||||||
|
@property (readonly) QObject* focusObject;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation QNSView {
|
||||||
|
QPointer<QCocoaWindow> m_platformWindow;
|
||||||
|
Qt::MouseButtons m_buttons;
|
||||||
|
Qt::MouseButtons m_acceptedMouseDowns;
|
||||||
|
Qt::MouseButtons m_frameStrutButtons;
|
||||||
|
QString m_composingText;
|
||||||
|
QPointer<QObject> m_composingFocusObject;
|
||||||
|
bool m_sendKeyEvent;
|
||||||
|
bool m_dontOverrideCtrlLMB;
|
||||||
|
bool m_sendUpAsRightButton;
|
||||||
|
Qt::KeyboardModifiers m_currentWheelModifiers;
|
||||||
|
NSString *m_inputSource;
|
||||||
|
QNSViewMouseMoveHelper *m_mouseMoveHelper;
|
||||||
|
bool m_resendKeyEvent;
|
||||||
|
bool m_scrolling;
|
||||||
|
bool m_updatingDrag;
|
||||||
|
NSEvent *m_currentlyInterpretedKeyEvent;
|
||||||
|
QSet<quint32> m_acceptedKeyDowns;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithCocoaWindow:(QCocoaWindow *)platformWindow
|
||||||
|
{
|
||||||
|
if ((self = [super initWithFrame:NSZeroRect])) {
|
||||||
|
m_platformWindow = platformWindow;
|
||||||
|
m_sendKeyEvent = false;
|
||||||
|
m_inputSource = nil;
|
||||||
|
m_resendKeyEvent = false;
|
||||||
|
m_updatingDrag = false;
|
||||||
|
m_currentlyInterpretedKeyEvent = nil;
|
||||||
|
|
||||||
|
self.focusRingType = NSFocusRingTypeNone;
|
||||||
|
|
||||||
|
self.previousSuperview = nil;
|
||||||
|
self.previousWindow = nil;
|
||||||
|
|
||||||
|
[self initDrawing];
|
||||||
|
[self initMouse];
|
||||||
|
[self registerDragTypes];
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(textInputContextKeyboardSelectionDidChangeNotification:)
|
||||||
|
name:NSTextInputContextKeyboardSelectionDidChangeNotification
|
||||||
|
object:nil];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
qCDebug(lcQpaWindow) << "Deallocating" << self;
|
||||||
|
|
||||||
|
[m_inputSource release];
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
[m_mouseMoveHelper release];
|
||||||
|
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)description
|
||||||
|
{
|
||||||
|
NSMutableString *description = [NSMutableString stringWithString:[super description]];
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
|
QString platformWindowDescription;
|
||||||
|
QDebug debug(&platformWindowDescription);
|
||||||
|
debug.nospace() << "; " << m_platformWindow << ">";
|
||||||
|
|
||||||
|
NSRange lastCharacter = [description rangeOfComposedCharacterSequenceAtIndex:description.length - 1];
|
||||||
|
[description replaceCharactersInRange:lastCharacter withString:platformWindowDescription.toNSString()];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------- Re-parenting ---------------------------------
|
||||||
|
|
||||||
|
- (void)removeFromSuperview
|
||||||
|
{
|
||||||
|
QMacAutoReleasePool pool;
|
||||||
|
[super removeFromSuperview];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewWillMoveToSuperview:(NSView *)newSuperview
|
||||||
|
{
|
||||||
|
Q_ASSERT(!self.previousSuperview);
|
||||||
|
self.previousSuperview = self.superview;
|
||||||
|
|
||||||
|
if (newSuperview == self.superview)
|
||||||
|
qCDebug(lcQpaWindow) << "Re-ordering" << self << "inside" << self.superview;
|
||||||
|
else
|
||||||
|
qCDebug(lcQpaWindow) << "Re-parenting" << self << "from" << self.superview << "to" << newSuperview;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewDidMoveToSuperview
|
||||||
|
{
|
||||||
|
auto cleanup = qScopeGuard([&] { self.previousSuperview = nil; });
|
||||||
|
|
||||||
|
if (self.superview == self.previousSuperview) {
|
||||||
|
qCDebug(lcQpaWindow) << "Done re-ordering" << self << "new index:"
|
||||||
|
<< [self.superview.subviews indexOfObject:self];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(lcQpaWindow) << "Done re-parenting" << self << "into" << self.superview;
|
||||||
|
|
||||||
|
// Note: at this point the view's window property hasn't been updated to match the window
|
||||||
|
// of the new superview. We have to wait for viewDidMoveToWindow for that to be reflected.
|
||||||
|
|
||||||
|
if (!m_platformWindow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_platformWindow->isEmbedded())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ([self superview]) {
|
||||||
|
QWindowSystemInterface::handleGeometryChange(m_platformWindow->window(), m_platformWindow->geometry());
|
||||||
|
[self setNeedsDisplay:YES];
|
||||||
|
QWindowSystemInterface::flushWindowSystemEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewWillMoveToWindow:(NSWindow *)newWindow
|
||||||
|
{
|
||||||
|
Q_ASSERT(!self.previousWindow);
|
||||||
|
self.previousWindow = self.window;
|
||||||
|
|
||||||
|
// This callback is documented to be called also when a view is just moved between
|
||||||
|
// subviews in the same NSWindow, so we're not necessarily moving between NSWindows.
|
||||||
|
if (newWindow == self.window)
|
||||||
|
return;
|
||||||
|
|
||||||
|
qCDebug(lcQpaWindow) << "Moving" << self << "from" << self.window << "to" << newWindow;
|
||||||
|
|
||||||
|
// Note: at this point the superview has already been updated, so we know which view inside
|
||||||
|
// the new window the view will be a child of.
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewDidMoveToWindow
|
||||||
|
{
|
||||||
|
auto cleanup = qScopeGuard([&] { self.previousWindow = nil; });
|
||||||
|
|
||||||
|
// This callback is documented to be called also when a view is just moved between
|
||||||
|
// subviews in the same NSWindow, so we're not necessarily moving between NSWindows.
|
||||||
|
if (self.window == self.previousWindow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
qCDebug(lcQpaWindow) << "Done moving" << self << "to" << self.window;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
- (QWindow *)topLevelWindow
|
||||||
|
{
|
||||||
|
if (!m_platformWindow)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
QWindow *focusWindow = m_platformWindow->window();
|
||||||
|
|
||||||
|
// For widgets we need to do a bit of trickery as the window
|
||||||
|
// to activate is the window of the top-level widget.
|
||||||
|
if (qstrcmp(focusWindow->metaObject()->className(), "QWidgetWindow") == 0) {
|
||||||
|
while (focusWindow->parent()) {
|
||||||
|
focusWindow = focusWindow->parent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return focusWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)viewDidHide
|
||||||
|
{
|
||||||
|
if (!m_platformWindow->isExposed())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_platformWindow->handleExposeEvent(QRegion());
|
||||||
|
|
||||||
|
// Note: setNeedsDisplay is automatically called for
|
||||||
|
// viewDidUnhide so no reason to override it here.
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isTransparentForUserInput
|
||||||
|
{
|
||||||
|
return m_platformWindow->window() &&
|
||||||
|
m_platformWindow->window()->flags() & Qt::WindowTransparentForInput;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)becomeFirstResponder
|
||||||
|
{
|
||||||
|
if (!m_platformWindow)
|
||||||
|
return NO;
|
||||||
|
if ([self isTransparentForUserInput])
|
||||||
|
return NO;
|
||||||
|
if (!m_platformWindow->windowIsPopupType())
|
||||||
|
QWindowSystemInterface::handleWindowActivated([self topLevelWindow]);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)acceptsFirstResponder
|
||||||
|
{
|
||||||
|
if (!m_platformWindow)
|
||||||
|
return NO;
|
||||||
|
if (m_platformWindow->shouldRefuseKeyWindowAndFirstResponder())
|
||||||
|
return NO;
|
||||||
|
if ([self isTransparentForUserInput])
|
||||||
|
return NO;
|
||||||
|
if ((m_platformWindow->window()->flags() & Qt::ToolTip) == Qt::ToolTip)
|
||||||
|
return NO;
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSView *)hitTest:(NSPoint)aPoint
|
||||||
|
{
|
||||||
|
NSView *candidate = [super hitTest:aPoint];
|
||||||
|
if (candidate == self) {
|
||||||
|
if ([self isTransparentForUserInput])
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)convertFromScreen:(NSPoint)mouseLocation toWindowPoint:(QPointF *)qtWindowPoint andScreenPoint:(QPointF *)qtScreenPoint
|
||||||
|
{
|
||||||
|
// Calculate the mouse position in the QWindow and Qt screen coordinate system,
|
||||||
|
// starting from coordinates in the NSWindow coordinate system.
|
||||||
|
//
|
||||||
|
// This involves translating according to the window location on screen,
|
||||||
|
// as well as inverting the y coordinate due to the origin change.
|
||||||
|
//
|
||||||
|
// Coordinate system overview, outer to innermost:
|
||||||
|
//
|
||||||
|
// Name Origin
|
||||||
|
//
|
||||||
|
// OS X screen bottom-left
|
||||||
|
// Qt screen top-left
|
||||||
|
// NSWindow bottom-left
|
||||||
|
// NSView/QWindow top-left
|
||||||
|
//
|
||||||
|
// NSView and QWindow are equal coordinate systems: the QWindow covers the
|
||||||
|
// entire NSView, and we've set the NSView's isFlipped property to true.
|
||||||
|
|
||||||
|
NSWindow *window = [self window];
|
||||||
|
NSPoint nsWindowPoint;
|
||||||
|
NSRect windowRect = [window convertRectFromScreen:NSMakeRect(mouseLocation.x, mouseLocation.y, 1, 1)];
|
||||||
|
nsWindowPoint = windowRect.origin; // NSWindow coordinates
|
||||||
|
NSPoint nsViewPoint = [self convertPoint: nsWindowPoint fromView: nil]; // NSView/QWindow coordinates
|
||||||
|
*qtWindowPoint = QPointF(nsViewPoint.x, nsViewPoint.y); // NSView/QWindow coordinates
|
||||||
|
*qtScreenPoint = QCocoaScreen::mapFromNative(mouseLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
#include "qnsview_drawing.mm"
|
||||||
|
#include "qnsview_mouse.mm"
|
||||||
|
#include "qnsview_touch.mm"
|
||||||
|
#include "qnsview_gestures.mm"
|
||||||
|
#include "qnsview_tablet.mm"
|
||||||
|
#include "qnsview_dragging.mm"
|
||||||
|
#include "qnsview_keys.mm"
|
||||||
|
#include "qnsview_complextext.mm"
|
||||||
|
#include "qnsview_menus.mm"
|
||||||
|
#ifndef QT_NO_ACCESSIBILITY
|
||||||
|
#include "qnsview_accessibility.mm"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// -----------------------------------------------------
|
||||||
|
|
||||||
|
@implementation QNSView (QtExtras)
|
||||||
|
|
||||||
|
- (QCocoaWindow*)platformWindow
|
||||||
|
{
|
||||||
|
return m_platformWindow.data();;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
6740
5.15.14/qtbase/src/plugins/styles/mac/qmacstyle_mac.mm
Normal file
6740
5.15.14/qtbase/src/plugins/styles/mac/qmacstyle_mac.mm
Normal file
File diff suppressed because it is too large
Load Diff
552
5.15.14/qtbase/src/widgets/widgets/qslider.cpp
Normal file
552
5.15.14/qtbase/src/widgets/widgets/qslider.cpp
Normal file
@ -0,0 +1,552 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the QtWidgets module of the Qt Toolkit.
|
||||||
|
**
|
||||||
|
** $QT_BEGIN_LICENSE:COMM$
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** $QT_END_LICENSE$
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "qslider.h"
|
||||||
|
#ifndef QT_NO_ACCESSIBILITY
|
||||||
|
#include "qaccessible.h"
|
||||||
|
#endif
|
||||||
|
#include "qapplication.h"
|
||||||
|
#include "qevent.h"
|
||||||
|
#include "qpainter.h"
|
||||||
|
#include "qstyle.h"
|
||||||
|
#include "qstyleoption.h"
|
||||||
|
#include "private/qapplication_p.h"
|
||||||
|
#include "private/qabstractslider_p.h"
|
||||||
|
#include "qdebug.h"
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QSliderPrivate : public QAbstractSliderPrivate
|
||||||
|
{
|
||||||
|
Q_DECLARE_PUBLIC(QSlider)
|
||||||
|
public:
|
||||||
|
QStyle::SubControl pressedControl;
|
||||||
|
int tickInterval;
|
||||||
|
QSlider::TickPosition tickPosition;
|
||||||
|
int clickOffset;
|
||||||
|
void init();
|
||||||
|
void resetLayoutItemMargins();
|
||||||
|
int pixelPosToRangeValue(int pos) const;
|
||||||
|
inline int pick(const QPoint &pt) const;
|
||||||
|
|
||||||
|
QStyle::SubControl newHoverControl(const QPoint &pos);
|
||||||
|
bool updateHoverControl(const QPoint &pos);
|
||||||
|
QStyle::SubControl hoverControl;
|
||||||
|
QRect hoverRect;
|
||||||
|
};
|
||||||
|
|
||||||
|
void QSliderPrivate::init()
|
||||||
|
{
|
||||||
|
Q_Q(QSlider);
|
||||||
|
pressedControl = QStyle::SC_None;
|
||||||
|
tickInterval = 0;
|
||||||
|
tickPosition = QSlider::NoTicks;
|
||||||
|
hoverControl = QStyle::SC_None;
|
||||||
|
q->setFocusPolicy(Qt::FocusPolicy(q->style()->styleHint(QStyle::SH_Button_FocusPolicy)));
|
||||||
|
QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Fixed, QSizePolicy::Slider);
|
||||||
|
if (orientation == Qt::Vertical)
|
||||||
|
sp.transpose();
|
||||||
|
q->setSizePolicy(sp);
|
||||||
|
q->setAttribute(Qt::WA_WState_OwnSizePolicy, false);
|
||||||
|
resetLayoutItemMargins();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QSliderPrivate::resetLayoutItemMargins()
|
||||||
|
{
|
||||||
|
Q_Q(QSlider);
|
||||||
|
QStyleOptionSlider opt;
|
||||||
|
q->initStyleOption(&opt);
|
||||||
|
setLayoutItemMargins(QStyle::SE_SliderLayoutItem, &opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
int QSliderPrivate::pixelPosToRangeValue(int pos) const
|
||||||
|
{
|
||||||
|
Q_Q(const QSlider);
|
||||||
|
QStyleOptionSlider opt;
|
||||||
|
q->initStyleOption(&opt);
|
||||||
|
QRect gr = q->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, q);
|
||||||
|
QRect sr = q->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, q);
|
||||||
|
int sliderMin, sliderMax, sliderLength;
|
||||||
|
|
||||||
|
if (orientation == Qt::Horizontal) {
|
||||||
|
sliderLength = sr.width();
|
||||||
|
sliderMin = gr.x();
|
||||||
|
sliderMax = gr.right() - sliderLength + 1;
|
||||||
|
} else {
|
||||||
|
sliderLength = sr.height();
|
||||||
|
sliderMin = gr.y();
|
||||||
|
sliderMax = gr.bottom() - sliderLength + 1;
|
||||||
|
}
|
||||||
|
return QStyle::sliderValueFromPosition(minimum, maximum, pos - sliderMin,
|
||||||
|
sliderMax - sliderMin, opt.upsideDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int QSliderPrivate::pick(const QPoint &pt) const
|
||||||
|
{
|
||||||
|
return orientation == Qt::Horizontal ? pt.x() : pt.y();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Initialize \a option with the values from this QSlider. This method
|
||||||
|
is useful for subclasses when they need a QStyleOptionSlider, but don't want
|
||||||
|
to fill in all the information themselves.
|
||||||
|
|
||||||
|
\sa QStyleOption::initFrom()
|
||||||
|
*/
|
||||||
|
void QSlider::initStyleOption(QStyleOptionSlider *option) const
|
||||||
|
{
|
||||||
|
if (!option)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Q_D(const QSlider);
|
||||||
|
option->initFrom(this);
|
||||||
|
option->subControls = QStyle::SC_None;
|
||||||
|
option->activeSubControls = QStyle::SC_None;
|
||||||
|
option->orientation = d->orientation;
|
||||||
|
option->maximum = d->maximum;
|
||||||
|
option->minimum = d->minimum;
|
||||||
|
option->tickPosition = (QSlider::TickPosition)d->tickPosition;
|
||||||
|
option->tickInterval = d->tickInterval;
|
||||||
|
option->upsideDown = (d->orientation == Qt::Horizontal) ?
|
||||||
|
(d->invertedAppearance != (option->direction == Qt::RightToLeft))
|
||||||
|
: (!d->invertedAppearance);
|
||||||
|
option->direction = Qt::LeftToRight; // we use the upsideDown option instead
|
||||||
|
option->sliderPosition = d->position;
|
||||||
|
option->sliderValue = d->value;
|
||||||
|
option->singleStep = d->singleStep;
|
||||||
|
option->pageStep = d->pageStep;
|
||||||
|
if (d->orientation == Qt::Horizontal)
|
||||||
|
option->state |= QStyle::State_Horizontal;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QSliderPrivate::updateHoverControl(const QPoint &pos)
|
||||||
|
{
|
||||||
|
Q_Q(QSlider);
|
||||||
|
QRect lastHoverRect = hoverRect;
|
||||||
|
QStyle::SubControl lastHoverControl = hoverControl;
|
||||||
|
bool doesHover = q->testAttribute(Qt::WA_Hover);
|
||||||
|
if (lastHoverControl != newHoverControl(pos) && doesHover) {
|
||||||
|
q->update(lastHoverRect);
|
||||||
|
q->update(hoverRect);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return !doesHover;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStyle::SubControl QSliderPrivate::newHoverControl(const QPoint &pos)
|
||||||
|
{
|
||||||
|
Q_Q(QSlider);
|
||||||
|
QStyleOptionSlider opt;
|
||||||
|
q->initStyleOption(&opt);
|
||||||
|
opt.subControls = QStyle::SC_All;
|
||||||
|
QRect handleRect = q->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, q);
|
||||||
|
QRect grooveRect = q->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, q);
|
||||||
|
QRect tickmarksRect = q->style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderTickmarks, q);
|
||||||
|
|
||||||
|
if (handleRect.contains(pos)) {
|
||||||
|
hoverRect = handleRect;
|
||||||
|
hoverControl = QStyle::SC_SliderHandle;
|
||||||
|
} else if (grooveRect.contains(pos)) {
|
||||||
|
hoverRect = grooveRect;
|
||||||
|
hoverControl = QStyle::SC_SliderGroove;
|
||||||
|
} else if (tickmarksRect.contains(pos)) {
|
||||||
|
hoverRect = tickmarksRect;
|
||||||
|
hoverControl = QStyle::SC_SliderTickmarks;
|
||||||
|
} else {
|
||||||
|
hoverRect = QRect();
|
||||||
|
hoverControl = QStyle::SC_None;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hoverControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QSlider
|
||||||
|
\brief The QSlider widget provides a vertical or horizontal slider.
|
||||||
|
|
||||||
|
\ingroup basicwidgets
|
||||||
|
\inmodule QtWidgets
|
||||||
|
|
||||||
|
\image windows-slider.png
|
||||||
|
|
||||||
|
The slider is the classic widget for controlling a bounded value.
|
||||||
|
It lets the user move a slider handle along a horizontal or vertical
|
||||||
|
groove and translates the handle's position into an integer value
|
||||||
|
within the legal range.
|
||||||
|
|
||||||
|
QSlider has very few of its own functions; most of the functionality is in
|
||||||
|
QAbstractSlider. The most useful functions are setValue() to set
|
||||||
|
the slider directly to some value; triggerAction() to simulate
|
||||||
|
the effects of clicking (useful for shortcut keys);
|
||||||
|
setSingleStep(), setPageStep() to set the steps; and setMinimum()
|
||||||
|
and setMaximum() to define the range of the scroll bar.
|
||||||
|
|
||||||
|
QSlider provides methods for controlling tickmarks. You can use
|
||||||
|
setTickPosition() to indicate where you want the tickmarks to be,
|
||||||
|
setTickInterval() to indicate how many of them you want. the
|
||||||
|
currently set tick position and interval can be queried using the
|
||||||
|
tickPosition() and tickInterval() functions, respectively.
|
||||||
|
|
||||||
|
QSlider inherits a comprehensive set of signals:
|
||||||
|
\table
|
||||||
|
\header \li Signal \li Description
|
||||||
|
\row \li \l valueChanged()
|
||||||
|
\li Emitted when the slider's value has changed. The tracking()
|
||||||
|
determines whether this signal is emitted during user
|
||||||
|
interaction.
|
||||||
|
\row \li \l sliderPressed()
|
||||||
|
\li Emitted when the user starts to drag the slider.
|
||||||
|
\row \li \l sliderMoved()
|
||||||
|
\li Emitted when the user drags the slider.
|
||||||
|
\row \li \l sliderReleased()
|
||||||
|
\li Emitted when the user releases the slider.
|
||||||
|
\endtable
|
||||||
|
|
||||||
|
QSlider only provides integer ranges. Note that although
|
||||||
|
QSlider handles very large numbers, it becomes difficult for users
|
||||||
|
to use a slider accurately for very large ranges.
|
||||||
|
|
||||||
|
A slider accepts focus on Tab and provides both a mouse wheel and a
|
||||||
|
keyboard interface. The keyboard interface is the following:
|
||||||
|
|
||||||
|
\list
|
||||||
|
\li Left/Right move a horizontal slider by one single step.
|
||||||
|
\li Up/Down move a vertical slider by one single step.
|
||||||
|
\li PageUp moves up one page.
|
||||||
|
\li PageDown moves down one page.
|
||||||
|
\li Home moves to the start (minimum).
|
||||||
|
\li End moves to the end (maximum).
|
||||||
|
\endlist
|
||||||
|
|
||||||
|
\sa QScrollBar, QSpinBox, QDial, {fowler}{GUI Design Handbook: Slider}, {Sliders Example}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\enum QSlider::TickPosition
|
||||||
|
|
||||||
|
This enum specifies where the tick marks are to be drawn relative
|
||||||
|
to the slider's groove and the handle the user moves.
|
||||||
|
|
||||||
|
\value NoTicks Do not draw any tick marks.
|
||||||
|
\value TicksBothSides Draw tick marks on both sides of the groove.
|
||||||
|
\value TicksAbove Draw tick marks above the (horizontal) slider
|
||||||
|
\value TicksBelow Draw tick marks below the (horizontal) slider
|
||||||
|
\value TicksLeft Draw tick marks to the left of the (vertical) slider
|
||||||
|
\value TicksRight Draw tick marks to the right of the (vertical) slider
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs a vertical slider with the given \a parent.
|
||||||
|
*/
|
||||||
|
QSlider::QSlider(QWidget *parent)
|
||||||
|
: QSlider(Qt::Vertical, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Constructs a slider with the given \a parent. The \a orientation
|
||||||
|
parameter determines whether the slider is horizontal or vertical;
|
||||||
|
the valid values are Qt::Vertical and Qt::Horizontal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
QSlider::QSlider(Qt::Orientation orientation, QWidget *parent)
|
||||||
|
: QAbstractSlider(*new QSliderPrivate, parent)
|
||||||
|
{
|
||||||
|
d_func()->orientation = orientation;
|
||||||
|
d_func()->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Destroys this slider.
|
||||||
|
*/
|
||||||
|
QSlider::~QSlider()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
void QSlider::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
Q_D(QSlider);
|
||||||
|
QPainter p(this);
|
||||||
|
QStyleOptionSlider opt;
|
||||||
|
initStyleOption(&opt);
|
||||||
|
|
||||||
|
opt.subControls = QStyle::SC_SliderGroove | QStyle::SC_SliderHandle;
|
||||||
|
if (d->tickPosition != NoTicks)
|
||||||
|
opt.subControls |= QStyle::SC_SliderTickmarks;
|
||||||
|
if (d->pressedControl) {
|
||||||
|
opt.activeSubControls = d->pressedControl;
|
||||||
|
opt.state |= QStyle::State_Sunken;
|
||||||
|
} else {
|
||||||
|
opt.activeSubControls = d->hoverControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
style()->drawComplexControl(QStyle::CC_Slider, &opt, &p, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool QSlider::event(QEvent *event)
|
||||||
|
{
|
||||||
|
Q_D(QSlider);
|
||||||
|
|
||||||
|
switch(event->type()) {
|
||||||
|
case QEvent::HoverEnter:
|
||||||
|
case QEvent::HoverLeave:
|
||||||
|
case QEvent::HoverMove:
|
||||||
|
if (const QHoverEvent *he = static_cast<const QHoverEvent *>(event))
|
||||||
|
d->updateHoverControl(he->pos());
|
||||||
|
break;
|
||||||
|
case QEvent::StyleChange:
|
||||||
|
case QEvent::MacSizeChange:
|
||||||
|
d->resetLayoutItemMargins();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return QAbstractSlider::event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
void QSlider::mousePressEvent(QMouseEvent *ev)
|
||||||
|
{
|
||||||
|
Q_D(QSlider);
|
||||||
|
if (d->maximum == d->minimum || (ev->buttons() ^ ev->button())) {
|
||||||
|
ev->ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef QT_KEYPAD_NAVIGATION
|
||||||
|
if (QApplicationPrivate::keypadNavigationEnabled())
|
||||||
|
setEditFocus(true);
|
||||||
|
#endif
|
||||||
|
ev->accept();
|
||||||
|
if ((ev->button() & style()->styleHint(QStyle::SH_Slider_AbsoluteSetButtons)) == ev->button()) {
|
||||||
|
QStyleOptionSlider opt;
|
||||||
|
initStyleOption(&opt);
|
||||||
|
const QRect sliderRect = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
|
||||||
|
const QPoint center = sliderRect.center() - sliderRect.topLeft();
|
||||||
|
// to take half of the slider off for the setSliderPosition call we use the center - topLeft
|
||||||
|
|
||||||
|
setSliderPosition(d->pixelPosToRangeValue(d->pick(ev->pos() - center)));
|
||||||
|
triggerAction(SliderMove);
|
||||||
|
setRepeatAction(SliderNoAction);
|
||||||
|
d->pressedControl = QStyle::SC_SliderHandle;
|
||||||
|
update();
|
||||||
|
} else if ((ev->button() & style()->styleHint(QStyle::SH_Slider_PageSetButtons)) == ev->button()) {
|
||||||
|
QStyleOptionSlider opt;
|
||||||
|
initStyleOption(&opt);
|
||||||
|
d->pressedControl = style()->hitTestComplexControl(QStyle::CC_Slider,
|
||||||
|
&opt, ev->pos(), this);
|
||||||
|
SliderAction action = SliderNoAction;
|
||||||
|
if (d->pressedControl == QStyle::SC_SliderGroove) {
|
||||||
|
const QRect sliderRect = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
|
||||||
|
int pressValue = d->pixelPosToRangeValue(d->pick(ev->pos() - sliderRect.center() + sliderRect.topLeft()));
|
||||||
|
d->pressValue = pressValue;
|
||||||
|
if (pressValue > d->value)
|
||||||
|
action = SliderPageStepAdd;
|
||||||
|
else if (pressValue < d->value)
|
||||||
|
action = SliderPageStepSub;
|
||||||
|
if (action) {
|
||||||
|
triggerAction(action);
|
||||||
|
setRepeatAction(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ev->ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->pressedControl == QStyle::SC_SliderHandle) {
|
||||||
|
QStyleOptionSlider opt;
|
||||||
|
initStyleOption(&opt);
|
||||||
|
setRepeatAction(SliderNoAction);
|
||||||
|
QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
|
||||||
|
d->clickOffset = d->pick(ev->pos() - sr.topLeft());
|
||||||
|
update(sr);
|
||||||
|
setSliderDown(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
void QSlider::mouseMoveEvent(QMouseEvent *ev)
|
||||||
|
{
|
||||||
|
Q_D(QSlider);
|
||||||
|
if (d->pressedControl != QStyle::SC_SliderHandle) {
|
||||||
|
ev->ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ev->accept();
|
||||||
|
int newPosition = d->pixelPosToRangeValue(d->pick(ev->pos()) - d->clickOffset);
|
||||||
|
QStyleOptionSlider opt;
|
||||||
|
initStyleOption(&opt);
|
||||||
|
setSliderPosition(newPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
void QSlider::mouseReleaseEvent(QMouseEvent *ev)
|
||||||
|
{
|
||||||
|
Q_D(QSlider);
|
||||||
|
if (d->pressedControl == QStyle::SC_None || ev->buttons()) {
|
||||||
|
ev->ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ev->accept();
|
||||||
|
QStyle::SubControl oldPressed = QStyle::SubControl(d->pressedControl);
|
||||||
|
d->pressedControl = QStyle::SC_None;
|
||||||
|
setRepeatAction(SliderNoAction);
|
||||||
|
if (oldPressed == QStyle::SC_SliderHandle)
|
||||||
|
setSliderDown(false);
|
||||||
|
QStyleOptionSlider opt;
|
||||||
|
initStyleOption(&opt);
|
||||||
|
opt.subControls = oldPressed;
|
||||||
|
update(style()->subControlRect(QStyle::CC_Slider, &opt, oldPressed, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
QSize QSlider::sizeHint() const
|
||||||
|
{
|
||||||
|
Q_D(const QSlider);
|
||||||
|
ensurePolished();
|
||||||
|
const int SliderLength = 84, TickSpace = 5;
|
||||||
|
QStyleOptionSlider opt;
|
||||||
|
initStyleOption(&opt);
|
||||||
|
int thick = style()->pixelMetric(QStyle::PM_SliderThickness, &opt, this);
|
||||||
|
if (d->tickPosition & TicksAbove)
|
||||||
|
thick += TickSpace;
|
||||||
|
if (d->tickPosition & TicksBelow)
|
||||||
|
thick += TickSpace;
|
||||||
|
int w = thick, h = SliderLength;
|
||||||
|
if (d->orientation == Qt::Horizontal) {
|
||||||
|
w = SliderLength;
|
||||||
|
h = thick;
|
||||||
|
}
|
||||||
|
return style()->sizeFromContents(QStyle::CT_Slider, &opt, QSize(w, h), this).expandedTo(QApplication::globalStrut());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
QSize QSlider::minimumSizeHint() const
|
||||||
|
{
|
||||||
|
Q_D(const QSlider);
|
||||||
|
QSize s = sizeHint();
|
||||||
|
QStyleOptionSlider opt;
|
||||||
|
initStyleOption(&opt);
|
||||||
|
int length = style()->pixelMetric(QStyle::PM_SliderLength, &opt, this);
|
||||||
|
if (d->orientation == Qt::Horizontal)
|
||||||
|
s.setWidth(length);
|
||||||
|
else
|
||||||
|
s.setHeight(length);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\property QSlider::tickPosition
|
||||||
|
\brief the tickmark position for this slider
|
||||||
|
|
||||||
|
The valid values are described by the QSlider::TickPosition enum.
|
||||||
|
|
||||||
|
The default value is \l QSlider::NoTicks.
|
||||||
|
|
||||||
|
\sa tickInterval
|
||||||
|
*/
|
||||||
|
|
||||||
|
void QSlider::setTickPosition(TickPosition position)
|
||||||
|
{
|
||||||
|
Q_D(QSlider);
|
||||||
|
d->tickPosition = position;
|
||||||
|
d->resetLayoutItemMargins();
|
||||||
|
update();
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSlider::TickPosition QSlider::tickPosition() const
|
||||||
|
{
|
||||||
|
return d_func()->tickPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\property QSlider::tickInterval
|
||||||
|
\brief the interval between tickmarks
|
||||||
|
|
||||||
|
This is a value interval, not a pixel interval. If it is 0, the
|
||||||
|
slider will choose between singleStep and pageStep.
|
||||||
|
|
||||||
|
The default value is 0.
|
||||||
|
|
||||||
|
\sa tickPosition, singleStep, pageStep
|
||||||
|
*/
|
||||||
|
|
||||||
|
void QSlider::setTickInterval(int ts)
|
||||||
|
{
|
||||||
|
d_func()->tickInterval = qMax(0, ts);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
int QSlider::tickInterval() const
|
||||||
|
{
|
||||||
|
return d_func()->tickInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_WIDGETS_EXPORT QStyleOptionSlider qt_qsliderStyleOption(QSlider *slider)
|
||||||
|
{
|
||||||
|
QStyleOptionSlider sliderOption;
|
||||||
|
slider->initStyleOption(&sliderOption);
|
||||||
|
return sliderOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#include "moc_qslider.cpp"
|
Loading…
Reference in New Issue
Block a user