forked from qt-creator/qt-creator
QmlDesigner: Implement transient scrollbar for widgets in studiostyle
Task-number: QDS-9556 Task-number: QDS-10368 Task-number: QDS-10385 Change-Id: Idcbc70db3075f7741a754376580f48d7df40e67a Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
This commit is contained in:
committed by
Ali Kianian
parent
98a28d30bc
commit
c78e0965c0
@@ -50,6 +50,7 @@ public:
|
||||
DockAreaWidget *m_dockArea = nullptr;
|
||||
QAction *m_toggleViewAction = nullptr;
|
||||
bool m_closed = false;
|
||||
bool m_focused = false;
|
||||
QScrollArea *m_scrollArea = nullptr;
|
||||
QToolBar *m_toolBar = nullptr;
|
||||
Qt::ToolButtonStyle m_toolBarStyleDocked = Qt::ToolButtonIconOnly;
|
||||
@@ -219,6 +220,7 @@ void DockWidgetPrivate::setupScrollArea()
|
||||
m_scrollArea = new QScrollArea(q);
|
||||
m_scrollArea->setObjectName("dockWidgetScrollArea");
|
||||
m_scrollArea->setWidgetResizable(true);
|
||||
m_scrollArea->setProperty("focused", q->isFocused());
|
||||
m_layout->addWidget(m_scrollArea);
|
||||
}
|
||||
|
||||
@@ -439,6 +441,21 @@ bool DockWidget::isClosed() const
|
||||
return d->m_closed;
|
||||
}
|
||||
|
||||
void DockWidget::setFocused(bool focused)
|
||||
{
|
||||
if (d->m_focused == focused)
|
||||
return;
|
||||
|
||||
d->m_focused = focused;
|
||||
if (d->m_scrollArea)
|
||||
d->m_scrollArea->setProperty("focused", focused);
|
||||
}
|
||||
|
||||
bool DockWidget::isFocused() const
|
||||
{
|
||||
return d->m_focused;
|
||||
}
|
||||
|
||||
QAction *DockWidget::toggleViewAction() const
|
||||
{
|
||||
return d->m_toggleViewAction;
|
||||
|
||||
@@ -32,6 +32,8 @@ class AutoHideSideBar;
|
||||
class ADS_EXPORT DockWidget : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool focused READ isFocused WRITE setFocused)
|
||||
|
||||
private:
|
||||
DockWidgetPrivate *d; ///< private data (pimpl)
|
||||
friend class DockWidgetPrivate;
|
||||
@@ -367,6 +369,16 @@ public:
|
||||
*/
|
||||
bool isClosed() const;
|
||||
|
||||
/**
|
||||
* Sets the focus property for widget
|
||||
*/
|
||||
void setFocused(bool focused);
|
||||
|
||||
/**
|
||||
* Returns true if this dock widget is focused.
|
||||
*/
|
||||
bool isFocused() const;
|
||||
|
||||
/**
|
||||
* Returns a checkable action that can be used to show or close this dock widget.
|
||||
* The action's text is set to the dock widget's window title.
|
||||
|
||||
@@ -5,12 +5,17 @@
|
||||
|
||||
#include "algorithm.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QEvent>
|
||||
#include <QPainter>
|
||||
#include <QStyleOption>
|
||||
#include <QWidget>
|
||||
|
||||
using namespace Utils;
|
||||
|
||||
static const qreal ScrollBarFadeOutDuration = 200.0;
|
||||
static const qreal ScrollBarFadeOutDelay = 450.0;
|
||||
|
||||
Animation * StyleAnimator::widgetAnimation(const QWidget *widget) const
|
||||
{
|
||||
if (!widget)
|
||||
@@ -125,3 +130,187 @@ void StyleAnimator::startAnimation(Animation *t)
|
||||
if (animations.size() > 0 && !animationTimer.isActive())
|
||||
animationTimer.start(35, this);
|
||||
}
|
||||
|
||||
QStyleAnimation::QStyleAnimation(QObject *target)
|
||||
: QAbstractAnimation(target)
|
||||
, m_delay(0)
|
||||
, m_duration(-1)
|
||||
, m_startTime(QTime::currentTime())
|
||||
, m_fps(ThirtyFps)
|
||||
, m_skip(0)
|
||||
{}
|
||||
|
||||
QStyleAnimation::~QStyleAnimation() {}
|
||||
|
||||
QObject *QStyleAnimation::target() const
|
||||
{
|
||||
return parent();
|
||||
}
|
||||
|
||||
int QStyleAnimation::duration() const
|
||||
{
|
||||
return m_duration;
|
||||
}
|
||||
|
||||
void QStyleAnimation::setDuration(int duration)
|
||||
{
|
||||
m_duration = duration;
|
||||
}
|
||||
|
||||
int QStyleAnimation::delay() const
|
||||
{
|
||||
return m_delay;
|
||||
}
|
||||
|
||||
void QStyleAnimation::setDelay(int delay)
|
||||
{
|
||||
m_delay = delay;
|
||||
}
|
||||
|
||||
QTime QStyleAnimation::startTime() const
|
||||
{
|
||||
return m_startTime;
|
||||
}
|
||||
|
||||
void QStyleAnimation::setStartTime(const QTime &time)
|
||||
{
|
||||
m_startTime = time;
|
||||
}
|
||||
|
||||
QStyleAnimation::FrameRate QStyleAnimation::frameRate() const
|
||||
{
|
||||
return m_fps;
|
||||
}
|
||||
|
||||
void QStyleAnimation::setFrameRate(FrameRate fps)
|
||||
{
|
||||
m_fps = fps;
|
||||
}
|
||||
|
||||
void QStyleAnimation::updateTarget()
|
||||
{
|
||||
QEvent event(QEvent::StyleAnimationUpdate);
|
||||
event.setAccepted(false);
|
||||
QCoreApplication::sendEvent(target(), &event);
|
||||
if (!event.isAccepted())
|
||||
stop();
|
||||
}
|
||||
|
||||
void QStyleAnimation::start()
|
||||
{
|
||||
m_skip = 0;
|
||||
QAbstractAnimation::start(DeleteWhenStopped);
|
||||
}
|
||||
|
||||
bool QStyleAnimation::isUpdateNeeded() const
|
||||
{
|
||||
return currentTime() > m_delay;
|
||||
}
|
||||
|
||||
void QStyleAnimation::updateCurrentTime(int)
|
||||
{
|
||||
if (++m_skip >= m_fps) {
|
||||
m_skip = 0;
|
||||
if (target() && isUpdateNeeded())
|
||||
updateTarget();
|
||||
}
|
||||
}
|
||||
|
||||
QNumberStyleAnimation::QNumberStyleAnimation(QObject *target)
|
||||
: QStyleAnimation(target)
|
||||
, m_start(0.0)
|
||||
, m_end(1.0)
|
||||
, m_prev(0.0)
|
||||
{
|
||||
setDuration(250);
|
||||
}
|
||||
|
||||
qreal QNumberStyleAnimation::startValue() const
|
||||
{
|
||||
return m_start;
|
||||
}
|
||||
|
||||
void QNumberStyleAnimation::setStartValue(qreal value)
|
||||
{
|
||||
m_start = value;
|
||||
}
|
||||
|
||||
qreal QNumberStyleAnimation::endValue() const
|
||||
{
|
||||
return m_end;
|
||||
}
|
||||
|
||||
void QNumberStyleAnimation::setEndValue(qreal value)
|
||||
{
|
||||
m_end = value;
|
||||
}
|
||||
|
||||
qreal QNumberStyleAnimation::currentValue() const
|
||||
{
|
||||
qreal step = qreal(currentTime() - delay()) / (duration() - delay());
|
||||
return m_start + qMax(qreal(0), step) * (m_end - m_start);
|
||||
}
|
||||
|
||||
bool QNumberStyleAnimation::isUpdateNeeded() const
|
||||
{
|
||||
if (QStyleAnimation::isUpdateNeeded()) {
|
||||
qreal current = currentValue();
|
||||
if (!qFuzzyCompare(m_prev, current)) {
|
||||
m_prev = current;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QScrollbarStyleAnimation::QScrollbarStyleAnimation(Mode mode, QObject *target)
|
||||
: QNumberStyleAnimation(target)
|
||||
, m_mode(mode)
|
||||
, m_active(false)
|
||||
{
|
||||
switch (mode) {
|
||||
case Activating:
|
||||
setDuration(ScrollBarFadeOutDuration);
|
||||
setStartValue(0.0);
|
||||
setEndValue(1.0);
|
||||
break;
|
||||
case Deactivating:
|
||||
setDuration(ScrollBarFadeOutDelay + ScrollBarFadeOutDuration);
|
||||
setDelay(ScrollBarFadeOutDelay);
|
||||
setStartValue(1.0);
|
||||
setEndValue(0.0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QScrollbarStyleAnimation::Mode QScrollbarStyleAnimation::mode() const
|
||||
{
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
bool QScrollbarStyleAnimation::wasActive() const
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
|
||||
bool QScrollbarStyleAnimation::wasAdjacent() const
|
||||
{
|
||||
return m_adjacent;
|
||||
}
|
||||
|
||||
void QScrollbarStyleAnimation::setActive(bool active)
|
||||
{
|
||||
m_active = active;
|
||||
}
|
||||
|
||||
void QScrollbarStyleAnimation::setAdjacent(bool adjacent)
|
||||
{
|
||||
m_adjacent = adjacent;
|
||||
}
|
||||
|
||||
void QScrollbarStyleAnimation::updateCurrentTime(int time)
|
||||
{
|
||||
QNumberStyleAnimation::updateCurrentTime(time);
|
||||
if (m_mode == Deactivating && qFuzzyIsNull(currentValue()))
|
||||
target()->setProperty("visible", false);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "utils_global.h"
|
||||
|
||||
#include <QAbstractAnimation>
|
||||
#include <QBasicTimer>
|
||||
#include <QPointer>
|
||||
#include <QTime>
|
||||
@@ -13,6 +14,7 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QPainter;
|
||||
class QStyleOption;
|
||||
class QTimerEvent;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Utils {
|
||||
@@ -76,4 +78,78 @@ private:
|
||||
QBasicTimer animationTimer;
|
||||
QList <Animation*> animations;
|
||||
};
|
||||
}
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT QStyleAnimation : public QAbstractAnimation
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QStyleAnimation(QObject *target);
|
||||
virtual ~QStyleAnimation();
|
||||
QObject *target() const;
|
||||
int duration() const override;
|
||||
void setDuration(int duration);
|
||||
int delay() const;
|
||||
void setDelay(int delay);
|
||||
QTime startTime() const;
|
||||
void setStartTime(const QTime &time);
|
||||
enum FrameRate { DefaultFps, SixtyFps, ThirtyFps, TwentyFps, FifteenFps };
|
||||
FrameRate frameRate() const;
|
||||
void setFrameRate(FrameRate fps);
|
||||
void updateTarget();
|
||||
public Q_SLOTS:
|
||||
void start();
|
||||
|
||||
protected:
|
||||
virtual bool isUpdateNeeded() const;
|
||||
virtual void updateCurrentTime(int time) override;
|
||||
|
||||
private:
|
||||
int m_delay;
|
||||
int m_duration;
|
||||
QTime m_startTime;
|
||||
FrameRate m_fps;
|
||||
int m_skip;
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT QNumberStyleAnimation : public QStyleAnimation
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QNumberStyleAnimation(QObject *target);
|
||||
qreal startValue() const;
|
||||
void setStartValue(qreal value);
|
||||
qreal endValue() const;
|
||||
void setEndValue(qreal value);
|
||||
qreal currentValue() const;
|
||||
|
||||
protected:
|
||||
bool isUpdateNeeded() const override;
|
||||
|
||||
private:
|
||||
qreal m_start;
|
||||
qreal m_end;
|
||||
mutable qreal m_prev;
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT QScrollbarStyleAnimation : public QNumberStyleAnimation
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Mode { Activating, Deactivating };
|
||||
QScrollbarStyleAnimation(Mode mode, QObject *target);
|
||||
Mode mode() const;
|
||||
bool wasActive() const;
|
||||
bool wasAdjacent() const;
|
||||
void setActive(bool active);
|
||||
void setAdjacent(bool adjacent);
|
||||
|
||||
private slots:
|
||||
void updateCurrentTime(int time) override;
|
||||
|
||||
private:
|
||||
Mode m_mode;
|
||||
bool m_active;
|
||||
bool m_adjacent;
|
||||
};
|
||||
|
||||
} // namespace Utils
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
using namespace Utils;
|
||||
|
||||
static constexpr char transientScrollAreaSupportName[] = "transientScrollAreSupport";
|
||||
static constexpr char focusedPropertyName[] = "focused";
|
||||
static constexpr char skipChildPropertyName[] = "qds_transient_skipChildArea";
|
||||
|
||||
class Utils::ScrollAreaPrivate
|
||||
{
|
||||
@@ -19,13 +21,22 @@ public:
|
||||
ScrollAreaPrivate(QAbstractScrollArea *area)
|
||||
: area(area)
|
||||
{
|
||||
verticalScrollBar = dynamic_cast<ScrollBar *>(area->verticalScrollBar());
|
||||
if (!verticalScrollBar) {
|
||||
verticalScrollBar = new ScrollBar(area);
|
||||
area->setVerticalScrollBar(verticalScrollBar);
|
||||
}
|
||||
|
||||
horizontalScrollBar = dynamic_cast<ScrollBar *>(area->horizontalScrollBar());
|
||||
if (!horizontalScrollBar) {
|
||||
horizontalScrollBar = new ScrollBar(area);
|
||||
area->setHorizontalScrollBar(horizontalScrollBar);
|
||||
}
|
||||
|
||||
if (area->verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff)
|
||||
area->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
|
||||
if (area->horizontalScrollBarPolicy() != Qt::ScrollBarAlwaysOff)
|
||||
area->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
}
|
||||
|
||||
@@ -40,15 +51,30 @@ public:
|
||||
return rect.adjusted(0, mDiff, 0, mDiff);
|
||||
}
|
||||
}
|
||||
inline QPointer<ScrollBar> adjacentScrollBar(QPointer<ScrollBar> scrollBar)
|
||||
{
|
||||
if (scrollBar == verticalScrollBar)
|
||||
return horizontalScrollBar;
|
||||
|
||||
if (scrollBar == horizontalScrollBar)
|
||||
return verticalScrollBar;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline bool checkToFlashScroll(QPointer<ScrollBar> scrollBar, const QPoint &pos)
|
||||
{
|
||||
if (scrollBar.isNull())
|
||||
return false;
|
||||
|
||||
if (!scrollBar->style()->styleHint(
|
||||
QStyle::SH_ScrollBar_Transient,
|
||||
nullptr, scrollBar))
|
||||
if (!scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, scrollBar))
|
||||
return false;
|
||||
|
||||
Qt::ScrollBarPolicy policy = (scrollBar->orientation() == Qt::Horizontal)
|
||||
? area->horizontalScrollBarPolicy()
|
||||
: area->verticalScrollBarPolicy();
|
||||
|
||||
if (policy == Qt::ScrollBarAlwaysOff)
|
||||
return false;
|
||||
|
||||
if (scrollBarRect(scrollBar).contains(pos)) {
|
||||
@@ -59,16 +85,120 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool setAdjacentHovered(QObject *w, bool setHovered)
|
||||
{
|
||||
if (!w)
|
||||
return false;
|
||||
|
||||
QPointer<ScrollBar> scrollBar;
|
||||
if (w == verticalScrollBar)
|
||||
scrollBar = verticalScrollBar;
|
||||
else if (w == horizontalScrollBar)
|
||||
scrollBar = horizontalScrollBar;
|
||||
|
||||
if (!scrollBar)
|
||||
return false;
|
||||
|
||||
QPointer<ScrollBar> adjacent = adjacentScrollBar(scrollBar);
|
||||
if (!adjacent)
|
||||
return false;
|
||||
|
||||
return adjacent->setAdjacentHovered(setHovered);
|
||||
}
|
||||
|
||||
inline bool setAdjacentVisible(QObject *changedObject, bool setVisible)
|
||||
{
|
||||
if (!changedObject)
|
||||
return false;
|
||||
|
||||
QPointer<ScrollBar> scrollBar;
|
||||
if (changedObject == verticalScrollBar) {
|
||||
scrollBar = verticalScrollBar;
|
||||
} else if (changedObject == horizontalScrollBar) {
|
||||
scrollBar = horizontalScrollBar;
|
||||
} else if (changedObject == area) {
|
||||
if (setVisible && verticalScrollBar && horizontalScrollBar) {
|
||||
bool anyChange = false;
|
||||
anyChange |= verticalScrollBar->setAdjacentVisible(horizontalScrollBar->isVisible());
|
||||
anyChange |= horizontalScrollBar->setAdjacentVisible(verticalScrollBar->isVisible());
|
||||
return anyChange;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scrollBar)
|
||||
return false;
|
||||
|
||||
QPointer<ScrollBar> adjacent = adjacentScrollBar(scrollBar);
|
||||
if (!adjacent)
|
||||
return false;
|
||||
|
||||
return adjacent->setAdjacentVisible(setVisible);
|
||||
}
|
||||
|
||||
inline bool checkToFlashScroll(const QPoint &pos)
|
||||
{
|
||||
bool coversScroll = checkToFlashScroll(verticalScrollBar, pos);
|
||||
|
||||
if (!coversScroll)
|
||||
coversScroll |= checkToFlashScroll(horizontalScrollBar, pos);
|
||||
|
||||
return coversScroll;
|
||||
}
|
||||
|
||||
inline void installViewPort(QObject *eventHandler) {
|
||||
inline bool canSetTransientProperty(QPointer<ScrollBar> scrollBar) const
|
||||
{
|
||||
if (scrollBar.isNull())
|
||||
return false;
|
||||
|
||||
if (!scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, scrollBar))
|
||||
return false;
|
||||
|
||||
Qt::ScrollBarPolicy policy = (scrollBar->orientation() == Qt::Horizontal)
|
||||
? area->horizontalScrollBarPolicy()
|
||||
: area->verticalScrollBarPolicy();
|
||||
|
||||
if (policy == Qt::ScrollBarAlwaysOff)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool setFocus(QPointer<ScrollBar> scrollBar, const bool &focus)
|
||||
{
|
||||
if (!canSetTransientProperty(scrollBar))
|
||||
return false;
|
||||
|
||||
return scrollBar->setFocused(focus);
|
||||
}
|
||||
|
||||
inline bool setFocus(const bool &focus)
|
||||
{
|
||||
bool flashChanged = false;
|
||||
flashChanged |= setFocus(verticalScrollBar, focus);
|
||||
flashChanged |= setFocus(horizontalScrollBar, focus);
|
||||
|
||||
return flashChanged;
|
||||
}
|
||||
|
||||
inline bool setViewPortIntraction(QPointer<ScrollBar> scrollBar, const bool &hovered)
|
||||
{
|
||||
if (!canSetTransientProperty(scrollBar))
|
||||
return false;
|
||||
|
||||
return scrollBar->setViewPortInteraction(hovered);
|
||||
}
|
||||
|
||||
inline bool setViewPortIntraction(const bool &hovered)
|
||||
{
|
||||
bool interactionChanged = false;
|
||||
interactionChanged |= setViewPortIntraction(verticalScrollBar, hovered);
|
||||
interactionChanged |= setViewPortIntraction(horizontalScrollBar, hovered);
|
||||
|
||||
return interactionChanged;
|
||||
}
|
||||
|
||||
inline void installViewPort(QObject *eventHandler)
|
||||
{
|
||||
QWidget *viewPort = area->viewport();
|
||||
if (viewPort
|
||||
&& viewPort != this->viewPort
|
||||
@@ -76,14 +206,30 @@ public:
|
||||
&& (area->verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOff
|
||||
|| area->horizontalScrollBarPolicy() != Qt::ScrollBarAlwaysOff)) {
|
||||
viewPort->installEventFilter(eventHandler);
|
||||
|
||||
if (verticalScrollBar)
|
||||
verticalScrollBar->installEventFilter(eventHandler);
|
||||
|
||||
if (horizontalScrollBar)
|
||||
horizontalScrollBar->installEventFilter(eventHandler);
|
||||
|
||||
this->viewPort = viewPort;
|
||||
setViewPortIntraction(true);
|
||||
}
|
||||
}
|
||||
|
||||
inline void uninstallViewPort(QObject *eventHandler) {
|
||||
if (viewPort) {
|
||||
viewPort->removeEventFilter(eventHandler);
|
||||
|
||||
if (verticalScrollBar)
|
||||
verticalScrollBar->removeEventFilter(eventHandler);
|
||||
|
||||
if (horizontalScrollBar)
|
||||
horizontalScrollBar->removeEventFilter(eventHandler);
|
||||
|
||||
this->viewPort = nullptr;
|
||||
setViewPortIntraction(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +257,13 @@ void TransientScrollAreaSupport::support(QAbstractScrollArea *scrollArea)
|
||||
);
|
||||
}
|
||||
|
||||
void TransientScrollAreaSupport::supportWidget(QWidget *widget)
|
||||
{
|
||||
for (QAbstractScrollArea *area : widget->findChildren<QAbstractScrollArea *>()) {
|
||||
support(area);
|
||||
}
|
||||
}
|
||||
|
||||
TransientScrollAreaSupport::~TransientScrollAreaSupport()
|
||||
{
|
||||
delete d;
|
||||
@@ -122,23 +275,65 @@ bool TransientScrollAreaSupport::eventFilter(QObject *watched, QEvent *event)
|
||||
case QEvent::Enter: {
|
||||
if (watched == d->area)
|
||||
d->installViewPort(this);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
case QEvent::Leave: {
|
||||
if (watched == d->area)
|
||||
d->uninstallViewPort(this);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
case QEvent::MouseMove: {
|
||||
if (watched == d->viewPort){
|
||||
if (watched == d->viewPort) {
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
if (mouseEvent) {
|
||||
if (d->checkToFlashScroll(mouseEvent->pos()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case QEvent::HoverEnter:
|
||||
case QEvent::HoverMove: {
|
||||
QHoverEvent *hoverEvent = static_cast<QHoverEvent *>(event);
|
||||
if (watched == d->horizontalScrollBar || watched == d->verticalScrollBar) {
|
||||
if (hoverEvent)
|
||||
d->setAdjacentHovered(watched, true);
|
||||
}
|
||||
} break;
|
||||
case QEvent::HoverLeave: {
|
||||
QHoverEvent *hoverEvent = static_cast<QHoverEvent *>(event);
|
||||
if (watched == d->horizontalScrollBar || watched == d->verticalScrollBar) {
|
||||
if (hoverEvent)
|
||||
d->setAdjacentHovered(watched, false);
|
||||
}
|
||||
} break;
|
||||
case QEvent::DynamicPropertyChange: {
|
||||
if (watched == d->area) {
|
||||
auto *pEvent = static_cast<QDynamicPropertyChangeEvent *>(event);
|
||||
if (!pEvent || pEvent->propertyName() != focusedPropertyName)
|
||||
break;
|
||||
|
||||
bool focused = d->area->property(focusedPropertyName).toBool();
|
||||
d->setFocus(focused);
|
||||
|
||||
if (!d->area->property(skipChildPropertyName).toBool() && d->area->viewport()) {
|
||||
const QList<QAbstractScrollArea *> scrollChildren
|
||||
= d->area->viewport()->findChildren<QAbstractScrollArea *>();
|
||||
for (QAbstractScrollArea *area : scrollChildren) {
|
||||
area->setProperty(skipChildPropertyName, true);
|
||||
area->setProperty(focusedPropertyName, focused);
|
||||
area->setProperty(skipChildPropertyName, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case QEvent::Hide:
|
||||
d->setAdjacentVisible(watched, false);
|
||||
break;
|
||||
case QEvent::Show:
|
||||
d->setAdjacentVisible(watched, true);
|
||||
break;
|
||||
case QEvent::Resize: {
|
||||
if (watched == d->area)
|
||||
d->setAdjacentVisible(watched, true);
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -149,6 +344,12 @@ class Utils::ScrollBarPrivate {
|
||||
public:
|
||||
bool flashed = false;
|
||||
int flashTimer = 0;
|
||||
bool focused = false;
|
||||
bool viewPortIntraction = false;
|
||||
bool adjacentHovered = false;
|
||||
bool adjacentVisible = false;
|
||||
bool isHandleUnderCursor = false;
|
||||
bool isGrooveUnderCursor = false;
|
||||
};
|
||||
|
||||
ScrollBar::ScrollBar(QWidget *parent)
|
||||
@@ -162,25 +363,6 @@ ScrollBar::~ScrollBar()
|
||||
delete d;
|
||||
}
|
||||
|
||||
QSize ScrollBar::sizeHint() const
|
||||
{
|
||||
QSize sh = QScrollBar::sizeHint();
|
||||
if (style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, this)) {
|
||||
constexpr int thickness = 10;
|
||||
if (orientation() == Qt::Horizontal)
|
||||
sh.setHeight(thickness);
|
||||
else
|
||||
sh.setWidth(thickness);
|
||||
} else {
|
||||
constexpr int thickness = 12;
|
||||
if (orientation() == Qt::Horizontal)
|
||||
sh.setHeight(thickness);
|
||||
else
|
||||
sh.setWidth(thickness);
|
||||
}
|
||||
return sh;
|
||||
}
|
||||
|
||||
void ScrollBar::flash()
|
||||
{
|
||||
if (!d->flashed && style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, this)) {
|
||||
@@ -197,14 +379,57 @@ void ScrollBar::flash()
|
||||
void ScrollBar::initStyleOption(QStyleOptionSlider *option) const
|
||||
{
|
||||
QScrollBar::initStyleOption(option);
|
||||
|
||||
if (d->flashed && style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, this))
|
||||
if (style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, this)) {
|
||||
if (d->flashed || d->focused || d->viewPortIntraction)
|
||||
option->state |= QStyle::State_On;
|
||||
|
||||
if (d->isGrooveUnderCursor || d->isHandleUnderCursor || d->adjacentHovered)
|
||||
option->subControls |= QStyle::SC_ScrollBarGroove;
|
||||
|
||||
option->styleObject->setProperty("adjacentScroll", d->adjacentHovered);
|
||||
|
||||
if (d->isHandleUnderCursor)
|
||||
option->activeSubControls |= QStyle::SC_ScrollBarSlider;
|
||||
|
||||
if (d->adjacentVisible) {
|
||||
int scrollExtent = style()->pixelMetric(QStyle::PM_ScrollBarExtent, option, this);
|
||||
if (option->orientation == Qt::Horizontal)
|
||||
option->rect.adjust(0, 0, -scrollExtent, 0);
|
||||
else
|
||||
option->rect.adjust(0, 0, 0, -scrollExtent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ScrollBar::event(QEvent *event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::HoverEnter:
|
||||
case QEvent::HoverMove: {
|
||||
QHoverEvent *hoverEvent = static_cast<QHoverEvent *>(event);
|
||||
if (hoverEvent) {
|
||||
QStyleOptionSlider option;
|
||||
option.initFrom(this);
|
||||
d->isHandleUnderCursor = style()
|
||||
->subControlRect(QStyle::CC_ScrollBar,
|
||||
&option,
|
||||
QStyle::SC_ScrollBarSlider,
|
||||
this)
|
||||
.contains(hoverEvent->pos());
|
||||
|
||||
d->isGrooveUnderCursor = !d->isHandleUnderCursor
|
||||
&& style()
|
||||
->subControlRect(QStyle::CC_ScrollBar,
|
||||
&option,
|
||||
QStyle::SC_ScrollBarGroove,
|
||||
this)
|
||||
.contains(hoverEvent->pos());
|
||||
}
|
||||
} break;
|
||||
case QEvent::HoverLeave:
|
||||
d->isHandleUnderCursor = false;
|
||||
d->isGrooveUnderCursor = false;
|
||||
break;
|
||||
case QEvent::Timer:
|
||||
if (static_cast<QTimerEvent *>(event)->timerId() == d->flashTimer) {
|
||||
if (d->flashed && style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, this)) {
|
||||
@@ -213,6 +438,7 @@ bool ScrollBar::event(QEvent *event)
|
||||
}
|
||||
killTimer(d->flashTimer);
|
||||
d->flashTimer = 0;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -220,3 +446,99 @@ bool ScrollBar::event(QEvent *event)
|
||||
}
|
||||
return QScrollBar::event(event);
|
||||
}
|
||||
|
||||
bool ScrollBar::setFocused(const bool &focused)
|
||||
{
|
||||
if (d->focused == focused)
|
||||
return false;
|
||||
|
||||
d->focused = focused;
|
||||
|
||||
if (d->focused)
|
||||
flash();
|
||||
else
|
||||
update();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScrollBar::setAdjacentVisible(const bool &visible)
|
||||
{
|
||||
if (d->adjacentVisible == visible)
|
||||
return false;
|
||||
|
||||
d->adjacentVisible = visible;
|
||||
update();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScrollBar::setAdjacentHovered(const bool &hovered)
|
||||
{
|
||||
if (d->adjacentHovered == hovered)
|
||||
return false;
|
||||
|
||||
d->adjacentHovered = hovered;
|
||||
update();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScrollBar::setViewPortInteraction(const bool &hovered)
|
||||
{
|
||||
if (d->viewPortIntraction == hovered)
|
||||
return false;
|
||||
|
||||
d->viewPortIntraction = hovered;
|
||||
|
||||
if (d->viewPortIntraction)
|
||||
flash();
|
||||
else
|
||||
update();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GlobalTransientSupport::support(QWidget *widget)
|
||||
{
|
||||
if (!widget)
|
||||
return;
|
||||
|
||||
widget->installEventFilter(instance());
|
||||
QAbstractScrollArea *area = dynamic_cast<QAbstractScrollArea *>(widget);
|
||||
if (area)
|
||||
TransientScrollAreaSupport::support(area);
|
||||
|
||||
for (QWidget *childWidget : widget->findChildren<QWidget *>(Qt::FindChildOption::FindDirectChildrenOnly))
|
||||
support(childWidget);
|
||||
}
|
||||
|
||||
GlobalTransientSupport::GlobalTransientSupport()
|
||||
: QObject(nullptr)
|
||||
{}
|
||||
|
||||
GlobalTransientSupport *GlobalTransientSupport::instance()
|
||||
{
|
||||
static GlobalTransientSupport *gVal = nullptr;
|
||||
if (!gVal)
|
||||
gVal = new GlobalTransientSupport;
|
||||
|
||||
return gVal;
|
||||
}
|
||||
|
||||
bool GlobalTransientSupport::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::ChildAdded: {
|
||||
QChildEvent *childEvent = static_cast<QChildEvent *>(event);
|
||||
|
||||
if (!childEvent || !childEvent->child() || !childEvent->child()->isWidgetType())
|
||||
break;
|
||||
|
||||
QWidget *widget = dynamic_cast<QWidget *>(childEvent->child());
|
||||
if (widget)
|
||||
support(widget);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ class QTCREATOR_UTILS_EXPORT TransientScrollAreaSupport : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
static void support(QAbstractScrollArea *scrollArea);
|
||||
static void supportWidget(QWidget *widget);
|
||||
virtual ~TransientScrollAreaSupport();
|
||||
|
||||
protected:
|
||||
@@ -35,20 +36,38 @@ private:
|
||||
class QTCREATOR_UTILS_EXPORT ScrollBar : public QScrollBar
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class ScrollAreaPrivate;
|
||||
|
||||
public:
|
||||
explicit ScrollBar(QWidget *parent = nullptr);
|
||||
virtual ~ScrollBar();
|
||||
|
||||
QSize sizeHint() const override;
|
||||
|
||||
virtual void flash();
|
||||
|
||||
bool setFocused(const bool &focused);
|
||||
|
||||
protected:
|
||||
virtual void initStyleOption(QStyleOptionSlider *option) const override;
|
||||
void initStyleOption(QStyleOptionSlider *option) const override;
|
||||
bool event(QEvent *event) override;
|
||||
|
||||
private:
|
||||
bool setAdjacentVisible(const bool &visible);
|
||||
bool setAdjacentHovered(const bool &hovered);
|
||||
bool setViewPortInteraction(const bool &hovered);
|
||||
|
||||
ScrollBarPrivate *d = nullptr;
|
||||
};
|
||||
|
||||
class QTCREATOR_UTILS_EXPORT GlobalTransientSupport : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static void support(QWidget *widget);
|
||||
|
||||
private:
|
||||
GlobalTransientSupport();
|
||||
static GlobalTransientSupport *instance();
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -31,11 +31,10 @@ class HighlightScrollBarOverlay : public QWidget
|
||||
public:
|
||||
HighlightScrollBarOverlay(HighlightScrollBarController *scrollBarController)
|
||||
: QWidget(scrollBarController->scrollArea())
|
||||
, m_scrollBar(scrollBarController->scrollBar())
|
||||
, m_highlightController(scrollBarController)
|
||||
{
|
||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
m_scrollBar->parentWidget()->installEventFilter(this);
|
||||
scrollBar()->parentWidget()->installEventFilter(this);
|
||||
doResize();
|
||||
doMove();
|
||||
show();
|
||||
@@ -43,12 +42,12 @@ public:
|
||||
|
||||
void doResize()
|
||||
{
|
||||
resize(m_scrollBar->size());
|
||||
resize(scrollBar()->size());
|
||||
}
|
||||
|
||||
void doMove()
|
||||
{
|
||||
move(parentWidget()->mapFromGlobal(m_scrollBar->mapToGlobal(m_scrollBar->pos())));
|
||||
move(parentWidget()->mapFromGlobal(scrollBar()->mapToGlobal(scrollBar()->pos())));
|
||||
}
|
||||
|
||||
void scheduleUpdate();
|
||||
@@ -71,7 +70,7 @@ private:
|
||||
// line start to line end
|
||||
QMap<Highlight::Priority, QMap<Utils::Theme::Color, QMap<int, int>>> m_highlightCache;
|
||||
|
||||
QScrollBar *m_scrollBar;
|
||||
inline QScrollBar *scrollBar() const { return m_highlightController->scrollBar(); }
|
||||
HighlightScrollBarController *m_highlightController;
|
||||
bool m_isCacheUpdateScheduled = true;
|
||||
};
|
||||
@@ -115,8 +114,8 @@ void HighlightScrollBarOverlay::paintEvent(QPaintEvent *paintEvent)
|
||||
gRect.width() + marginH,
|
||||
gRect.height() - hRect.height() + gRect.y() - hRect.y());
|
||||
|
||||
const int aboveValue = m_scrollBar->value();
|
||||
const int belowValue = m_scrollBar->maximum() - m_scrollBar->value();
|
||||
const int aboveValue = scrollBar()->value();
|
||||
const int belowValue = scrollBar()->maximum() - scrollBar()->value();
|
||||
const int sizeDocAbove = int(aboveValue * m_highlightController->lineHeight());
|
||||
const int sizeDocBelow = int(belowValue * m_highlightController->lineHeight());
|
||||
const int sizeDocVisible = int(m_highlightController->visibleRange());
|
||||
@@ -303,14 +302,14 @@ void HighlightScrollBarOverlay::updateCache()
|
||||
|
||||
QRect HighlightScrollBarOverlay::overlayRect() const
|
||||
{
|
||||
QStyleOptionSlider opt = qt_qscrollbarStyleOption(m_scrollBar);
|
||||
return m_scrollBar->style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarGroove, m_scrollBar);
|
||||
QStyleOptionSlider opt = qt_qscrollbarStyleOption(scrollBar());
|
||||
return scrollBar()->style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarGroove, scrollBar());
|
||||
}
|
||||
|
||||
QRect HighlightScrollBarOverlay::handleRect() const
|
||||
{
|
||||
QStyleOptionSlider opt = qt_qscrollbarStyleOption(m_scrollBar);
|
||||
return m_scrollBar->style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarSlider, m_scrollBar);
|
||||
QStyleOptionSlider opt = qt_qscrollbarStyleOption(scrollBar());
|
||||
return scrollBar()->style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarSlider, scrollBar());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -80,7 +80,6 @@ ConnectionViewWidget::ConnectionViewWidget(QWidget *parent) :
|
||||
ui->tabBar->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
|
||||
|
||||
QByteArray sheet = Utils::FileReader::fetchQrc(":/connectionview/stylesheet.css");
|
||||
sheet += Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css");
|
||||
setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(sheet)));
|
||||
|
||||
connect(ui->tabBar, &QTabBar::currentChanged,
|
||||
|
||||
@@ -87,11 +87,6 @@ GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
|
||||
|
||||
applyZoom(m_zoomX, m_zoomY);
|
||||
update();
|
||||
|
||||
const QString css = Theme::replaceCssColors(
|
||||
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css")));
|
||||
horizontalScrollBar()->setStyleSheet(css);
|
||||
verticalScrollBar()->setStyleSheet(css);
|
||||
}
|
||||
|
||||
GraphicsView::~GraphicsView()
|
||||
|
||||
@@ -74,7 +74,6 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view)
|
||||
setAcceptDrops(true);
|
||||
|
||||
QByteArray sheet = Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css");
|
||||
sheet += Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css");
|
||||
setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(sheet)));
|
||||
|
||||
Core::Context context(Constants::C_QMLEDITOR3D);
|
||||
|
||||
@@ -291,7 +291,6 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view)
|
||||
fillLayout->addWidget(m_graphicsView.data());
|
||||
|
||||
QByteArray sheet = Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css");
|
||||
sheet += Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css");
|
||||
setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(sheet)));
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "qproxystyle.h"
|
||||
#include "previewtooltip.h"
|
||||
|
||||
#include <qmldesignerbase/studio/studiostyle.h>
|
||||
|
||||
#include <metainfo.h>
|
||||
#include <theme.h>
|
||||
|
||||
@@ -35,7 +37,8 @@ namespace {
|
||||
class TableViewStyle : public QProxyStyle
|
||||
{
|
||||
public:
|
||||
TableViewStyle(QObject *parent) : QProxyStyle(QStyleFactory::create("fusion"))
|
||||
TableViewStyle(QObject *parent)
|
||||
: QProxyStyle(new StudioStyle("fusion"))
|
||||
{
|
||||
setParent(parent);
|
||||
baseStyle()->setParent(parent);
|
||||
|
||||
@@ -62,7 +62,6 @@ NavigatorWidget::NavigatorWidget(NavigatorView *view)
|
||||
setWindowTitle(tr("Navigator", "Title of navigator view"));
|
||||
|
||||
QByteArray sheet = Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css");
|
||||
sheet += Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css");
|
||||
setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(sheet)));
|
||||
|
||||
QmlDesignerPlugin::trackWidgetFocusTime(this, Constants::EVENT_NAVIGATORVIEW_TIME);
|
||||
|
||||
@@ -70,11 +70,6 @@ void TextEditorWidget::setTextEditor(Utils::UniqueObjectLatePtr<TextEditor::Base
|
||||
});
|
||||
|
||||
m_textEditor->editorWidget()->installEventFilter(this);
|
||||
|
||||
static QString styleSheet = Theme::replaceCssColors(
|
||||
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css")));
|
||||
m_textEditor->editorWidget()->verticalScrollBar()->setStyleSheet(styleSheet);
|
||||
m_textEditor->editorWidget()->horizontalScrollBar()->setStyleSheet(styleSheet);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <theme.h>
|
||||
#include <utils/algorithm.h>
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/transientscroll.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QComboBox>
|
||||
@@ -97,7 +98,7 @@ TimelineWidget::TimelineWidget(TimelineView *view)
|
||||
, m_toolbar(new TimelineToolBar(this))
|
||||
, m_rulerView(new QGraphicsView(this))
|
||||
, m_graphicsView(new QGraphicsView(this))
|
||||
, m_scrollbar(new QScrollBar(this))
|
||||
, m_scrollbar(new Utils::ScrollBar(this))
|
||||
, m_statusBar(new QLabel(this))
|
||||
, m_timelineView(view)
|
||||
, m_graphicsScene(new TimelineGraphicsScene(this, view->externalDependencies()))
|
||||
@@ -112,11 +113,6 @@ TimelineWidget::TimelineWidget(TimelineView *view)
|
||||
|
||||
m_toolbar->setStyleSheet(Theme::replaceCssColors(
|
||||
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css"))));
|
||||
|
||||
const QString css = Theme::replaceCssColors(
|
||||
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css")));
|
||||
|
||||
m_scrollbar->setStyleSheet(css);
|
||||
m_scrollbar->setOrientation(Qt::Horizontal);
|
||||
|
||||
QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
@@ -129,7 +125,6 @@ TimelineWidget::TimelineWidget(TimelineView *view)
|
||||
m_rulerView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
m_rulerView->viewport()->installEventFilter(new Eventfilter(this));
|
||||
m_rulerView->viewport()->setFocusPolicy(Qt::NoFocus);
|
||||
m_rulerView->setStyleSheet(css);
|
||||
m_rulerView->setFrameShape(QFrame::NoFrame);
|
||||
m_rulerView->setFrameShadow(QFrame::Plain);
|
||||
m_rulerView->setLineWidth(0);
|
||||
@@ -137,12 +132,11 @@ TimelineWidget::TimelineWidget(TimelineView *view)
|
||||
m_rulerView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
m_rulerView->setScene(graphicsScene());
|
||||
|
||||
m_graphicsView->setStyleSheet(css);
|
||||
m_graphicsView->setObjectName("SceneView");
|
||||
m_graphicsView->setFrameShape(QFrame::NoFrame);
|
||||
m_graphicsView->setFrameShadow(QFrame::Plain);
|
||||
m_graphicsView->setLineWidth(0);
|
||||
m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
m_graphicsView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
m_graphicsView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
||||
m_graphicsView->setSizePolicy(sizePolicy1);
|
||||
@@ -286,6 +280,8 @@ TimelineWidget::TimelineWidget(TimelineView *view)
|
||||
|
||||
auto onFinish = [this]() { graphicsScene()->setCurrentFrame(m_playbackAnimation->startValue().toInt()); };
|
||||
connect(m_playbackAnimation, &QVariantAnimation::finished, onFinish);
|
||||
|
||||
TimeLineNS::TimelineScrollAreaSupport::support(m_graphicsView, m_scrollbar);
|
||||
}
|
||||
|
||||
void TimelineWidget::connectToolbar()
|
||||
@@ -541,11 +537,11 @@ void TimelineWidget::invalidateTimelinePosition(const QmlTimeline &timeline)
|
||||
void TimelineWidget::setupScrollbar(int min, int max, int current)
|
||||
{
|
||||
bool b = m_scrollbar->blockSignals(true);
|
||||
m_scrollbar->setMinimum(min);
|
||||
m_scrollbar->setMaximum(max);
|
||||
m_scrollbar->setRange(min, max);
|
||||
m_scrollbar->setValue(current);
|
||||
m_scrollbar->setSingleStep((max - min) / 10);
|
||||
m_scrollbar->blockSignals(b);
|
||||
m_scrollbar->flash();
|
||||
}
|
||||
|
||||
void TimelineWidget::setTimelineId(const QString &id)
|
||||
@@ -634,4 +630,145 @@ TimelineView *TimelineWidget::timelineView() const
|
||||
return m_timelineView;
|
||||
}
|
||||
|
||||
namespace TimeLineNS {
|
||||
|
||||
using ScrollBar = Utils::ScrollBar;
|
||||
static constexpr char timelineScrollAreaSupportName[] = "timelinetransientScrollAreSupport";
|
||||
static constexpr char focusedPropertyName[] = "focused";
|
||||
|
||||
class TimelineScrollAreaPrivate
|
||||
{
|
||||
public:
|
||||
TimelineScrollAreaPrivate(QAbstractScrollArea *area, ScrollBar *scrollbar)
|
||||
: area(area)
|
||||
, scrollbar(scrollbar)
|
||||
{}
|
||||
|
||||
inline QRect scrollBarRect(ScrollBar *scrollBar)
|
||||
{
|
||||
QRect rect = viewPort ? viewPort->rect() : area->rect();
|
||||
if (scrollBar->orientation() == Qt::Vertical) {
|
||||
int mDiff = rect.width() - scrollBar->sizeHint().width();
|
||||
return rect.adjusted(mDiff, 0, mDiff, 0);
|
||||
} else {
|
||||
int mDiff = rect.height() - scrollBar->sizeHint().height();
|
||||
return rect.adjusted(0, mDiff, 0, mDiff);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool checkToFlashScroll(QPointer<ScrollBar> scrollBar, const QPoint &pos)
|
||||
{
|
||||
if (scrollBar.isNull())
|
||||
return false;
|
||||
|
||||
if (!scrollBar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, scrollBar))
|
||||
return false;
|
||||
|
||||
if (scrollBarRect(scrollBar).contains(pos)) {
|
||||
scrollBar->flash();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool checkToFlashScroll(const QPoint &pos)
|
||||
{
|
||||
bool coversScroll = checkToFlashScroll(scrollbar, pos);
|
||||
|
||||
return coversScroll;
|
||||
}
|
||||
|
||||
inline bool setFocus(const bool &focus)
|
||||
{
|
||||
if (scrollbar.isNull())
|
||||
return false;
|
||||
|
||||
if (!scrollbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, scrollbar))
|
||||
return false;
|
||||
|
||||
return scrollbar->setFocused(focus);
|
||||
}
|
||||
|
||||
inline void installViewPort(QObject *eventHandler)
|
||||
{
|
||||
QWidget *viewPort = area->viewport();
|
||||
if (viewPort && viewPort != this->viewPort
|
||||
&& viewPort->style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, viewPort)) {
|
||||
viewPort->installEventFilter(eventHandler);
|
||||
this->viewPort = viewPort;
|
||||
}
|
||||
}
|
||||
|
||||
inline void uninstallViewPort(QObject *eventHandler)
|
||||
{
|
||||
if (viewPort) {
|
||||
viewPort->removeEventFilter(eventHandler);
|
||||
this->viewPort = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QAbstractScrollArea *area = nullptr;
|
||||
QPointer<QWidget> viewPort = nullptr;
|
||||
QPointer<ScrollBar> scrollbar;
|
||||
};
|
||||
|
||||
TimelineScrollAreaSupport::TimelineScrollAreaSupport(QAbstractScrollArea *scrollArea,
|
||||
Utils::ScrollBar *scrollbar)
|
||||
: QObject(scrollArea)
|
||||
, d(new TimelineScrollAreaPrivate(scrollArea, scrollbar))
|
||||
{
|
||||
scrollArea->installEventFilter(this);
|
||||
}
|
||||
|
||||
void TimelineScrollAreaSupport::support(QAbstractScrollArea *scrollArea, Utils::ScrollBar *scrollbar)
|
||||
{
|
||||
QObject *prevSupport = scrollArea->property(timelineScrollAreaSupportName).value<QObject *>();
|
||||
if (!prevSupport)
|
||||
scrollArea->setProperty(timelineScrollAreaSupportName,
|
||||
QVariant::fromValue(
|
||||
new TimelineScrollAreaSupport(scrollArea, scrollbar)));
|
||||
}
|
||||
|
||||
TimelineScrollAreaSupport::~TimelineScrollAreaSupport()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool TimelineScrollAreaSupport::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
switch (event->type()) {
|
||||
case QEvent::Enter: {
|
||||
if (watched == d->area)
|
||||
d->installViewPort(this);
|
||||
} break;
|
||||
case QEvent::Leave: {
|
||||
if (watched == d->area)
|
||||
d->uninstallViewPort(this);
|
||||
} break;
|
||||
case QEvent::MouseMove: {
|
||||
if (watched == d->viewPort) {
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
if (mouseEvent) {
|
||||
if (d->checkToFlashScroll(mouseEvent->pos()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case QEvent::DynamicPropertyChange: {
|
||||
if (watched == d->area) {
|
||||
auto *pEvent = static_cast<QDynamicPropertyChangeEvent *>(event);
|
||||
if (!pEvent || pEvent->propertyName() != focusedPropertyName)
|
||||
break;
|
||||
|
||||
bool focused = d->area->property(focusedPropertyName).toBool();
|
||||
d->setFocus(focused);
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
} // namespace TimeLineNS
|
||||
} // namespace QmlDesigner
|
||||
|
||||
@@ -19,15 +19,44 @@ QT_FORWARD_DECLARE_CLASS(QString)
|
||||
QT_FORWARD_DECLARE_CLASS(QPushButton)
|
||||
QT_FORWARD_DECLARE_CLASS(QVariantAnimation)
|
||||
QT_FORWARD_DECLARE_CLASS(QScrollBar)
|
||||
QT_FORWARD_DECLARE_CLASS(QAbstractScrollArea)
|
||||
|
||||
namespace Utils {
|
||||
QT_FORWARD_DECLARE_CLASS(ScrollBar)
|
||||
}
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class TimelineToolBar;
|
||||
class TimelineView;
|
||||
class TimelineGraphicsScene;
|
||||
class TimelineWidget;
|
||||
class QmlTimeline;
|
||||
class Navigation2dScrollBar;
|
||||
|
||||
namespace TimeLineNS {
|
||||
|
||||
class TimelineScrollAreaPrivate;
|
||||
class ScrollBarPrivate;
|
||||
|
||||
class TimelineScrollAreaSupport : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static void support(QAbstractScrollArea *scrollArea, Utils::ScrollBar *scrollbar);
|
||||
virtual ~TimelineScrollAreaSupport();
|
||||
|
||||
protected:
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
private:
|
||||
explicit TimelineScrollAreaSupport(QAbstractScrollArea *scrollArea, Utils::ScrollBar *scrollbar);
|
||||
|
||||
TimelineScrollAreaPrivate *d = nullptr;
|
||||
};
|
||||
|
||||
} // namespace TimeLineNS
|
||||
|
||||
class TimelineWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -76,7 +105,7 @@ private:
|
||||
|
||||
QGraphicsView *m_graphicsView = nullptr;
|
||||
|
||||
QScrollBar *m_scrollbar = nullptr;
|
||||
Utils::ScrollBar *m_scrollbar = nullptr;
|
||||
|
||||
QLabel *m_statusBar = nullptr;
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ TransitionEditorWidget::TransitionEditorWidget(TransitionEditorView *view)
|
||||
, m_toolbar(new TransitionEditorToolBar(this))
|
||||
, m_rulerView(new QGraphicsView(this))
|
||||
, m_graphicsView(new QGraphicsView(this))
|
||||
, m_scrollbar(new QScrollBar(this))
|
||||
, m_scrollbar(new Utils::ScrollBar(this))
|
||||
, m_statusBar(new QLabel(this))
|
||||
, m_transitionEditorView(view)
|
||||
, m_graphicsScene(new TransitionEditorGraphicsScene(this))
|
||||
@@ -94,11 +94,6 @@ TransitionEditorWidget::TransitionEditorWidget(TransitionEditorView *view)
|
||||
|
||||
m_toolbar->setStyleSheet(Theme::replaceCssColors(
|
||||
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css"))));
|
||||
|
||||
const QString css = Theme::replaceCssColors(
|
||||
QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css")));
|
||||
|
||||
m_scrollbar->setStyleSheet(css);
|
||||
m_scrollbar->setOrientation(Qt::Horizontal);
|
||||
|
||||
QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
@@ -111,7 +106,6 @@ TransitionEditorWidget::TransitionEditorWidget(TransitionEditorView *view)
|
||||
m_rulerView->setAlignment(Qt::AlignLeft | Qt::AlignTop);
|
||||
m_rulerView->viewport()->installEventFilter(new Eventfilter(this));
|
||||
m_rulerView->viewport()->setFocusPolicy(Qt::NoFocus);
|
||||
m_rulerView->setStyleSheet(css);
|
||||
m_rulerView->setFrameShape(QFrame::NoFrame);
|
||||
m_rulerView->setFrameShadow(QFrame::Plain);
|
||||
m_rulerView->setLineWidth(0);
|
||||
@@ -119,7 +113,6 @@ TransitionEditorWidget::TransitionEditorWidget(TransitionEditorView *view)
|
||||
m_rulerView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
m_rulerView->setScene(graphicsScene());
|
||||
|
||||
m_graphicsView->setStyleSheet(css);
|
||||
m_graphicsView->setObjectName("SceneView");
|
||||
m_graphicsView->setFrameShape(QFrame::NoFrame);
|
||||
m_graphicsView->setFrameShadow(QFrame::Plain);
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <coreplugin/icontext.h>
|
||||
|
||||
#include <utils/transientscroll.h>
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include <functional>
|
||||
@@ -75,7 +77,7 @@ private:
|
||||
|
||||
QGraphicsView *m_graphicsView = nullptr;
|
||||
|
||||
QScrollBar *m_scrollbar = nullptr;
|
||||
Utils::ScrollBar *m_scrollbar = nullptr;
|
||||
|
||||
QLabel *m_statusBar = nullptr;
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <utils/fileutils.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/stylehelper.h>
|
||||
#include <utils/transientscroll.h>
|
||||
|
||||
#include <QActionGroup>
|
||||
#include <QApplication>
|
||||
@@ -125,7 +126,6 @@ QWidget *DesignModeWidget::createProjectExplorerWidget(QWidget *parent)
|
||||
|
||||
if (navigationView.widget) {
|
||||
QByteArray sheet = Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css");
|
||||
sheet += Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css");
|
||||
sheet += "QLabel { background-color: #4f4f4f; }";
|
||||
navigationView.widget->setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(sheet)));
|
||||
navigationView.widget->setParent(parent);
|
||||
@@ -190,7 +190,6 @@ void DesignModeWidget::setup()
|
||||
Core::ICore::resourcePath("qmldesigner/workspacePresets/").toString());
|
||||
|
||||
QString sheet = QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/dockwidgets.css"));
|
||||
sheet += QString::fromUtf8(Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css"));
|
||||
m_dockManager->setStyleSheet(Theme::replaceCssColors(sheet));
|
||||
|
||||
// Setup icons
|
||||
@@ -300,7 +299,6 @@ void DesignModeWidget::setup()
|
||||
|
||||
// Apply stylesheet to QWidget
|
||||
QByteArray sheet = Utils::FileReader::fetchQrc(":/qmldesigner/stylesheet.css");
|
||||
sheet += Utils::FileReader::fetchQrc(":/qmldesigner/scrollbar.css");
|
||||
sheet += "QLabel { background-color: creatorTheme.DSsectionHeadBackground; }";
|
||||
navigationView.widget->setStyleSheet(Theme::replaceCssColors(QString::fromUtf8(sheet)));
|
||||
|
||||
@@ -428,6 +426,8 @@ void DesignModeWidget::setup()
|
||||
setupNavigatorHistory(currentDesignDocument()->textEditor());
|
||||
|
||||
m_dockManager->initialize();
|
||||
if (style()->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, this))
|
||||
Utils::GlobalTransientSupport::support(m_dockManager);
|
||||
|
||||
// Hide all floating widgets if the initial mode isn't design mode
|
||||
if (Core::ModeManager::instance()->currentModeId() != Core::Constants::MODE_DESIGN) {
|
||||
|
||||
@@ -36,6 +36,7 @@ extend_qtc_plugin(QmlDesignerBase
|
||||
SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/studio
|
||||
SOURCES
|
||||
studiostyle.cpp studiostyle.h
|
||||
studiostyle_p.cpp studiostyle_p.h
|
||||
studioquickwidget.cpp studioquickwidget.h
|
||||
studiosettingspage.cpp studiosettingspage.h
|
||||
)
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
#include "studiostyle.h"
|
||||
#include "studiostyle_p.h"
|
||||
|
||||
#include <utils/hostosinfo.h>
|
||||
#include <utils/styleanimator.h>
|
||||
#include <utils/stylehelper.h>
|
||||
#include <utils/theme/theme.h>
|
||||
|
||||
@@ -9,7 +12,9 @@
|
||||
#include <QPainter>
|
||||
#include <QStyleOption>
|
||||
|
||||
#define ANIMATE_SCROLLBARS QT_CONFIG(animation)
|
||||
using namespace Utils;
|
||||
using namespace QmlDesigner;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -65,6 +70,17 @@ inline QColor studioButtonOutlineColor(bool enabled,
|
||||
return creatorTheme()->color(themePenColorId);
|
||||
}
|
||||
|
||||
inline bool anyParentsFocused(const QWidget *widget)
|
||||
{
|
||||
const QWidget *p = widget;
|
||||
while (p) {
|
||||
if (p->property("focused").toBool())
|
||||
return true;
|
||||
p = p->parentWidget();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool styleEnabled(const QWidget *widget)
|
||||
{
|
||||
const QWidget *p = widget;
|
||||
@@ -93,221 +109,43 @@ bool isQmlEditorMenu(const QWidget *widget)
|
||||
return false;
|
||||
}
|
||||
|
||||
QPixmap getPixmapFromIcon(const QIcon &icon, const QSize &size, bool enabled, bool active, bool checked)
|
||||
inline QPixmap getPixmapFromIcon(
|
||||
const QIcon &icon, const QSize &size, bool enabled, bool active, bool checked)
|
||||
{
|
||||
QIcon::Mode mode = enabled ? ((active) ? QIcon::Active : QIcon::Normal) : QIcon::Disabled;
|
||||
QIcon::State state = (checked) ? QIcon::On : QIcon::Off;
|
||||
return icon.pixmap(size, mode, state);
|
||||
}
|
||||
|
||||
struct StudioShortcut {
|
||||
StudioShortcut(const QStyleOptionMenuItem *option,
|
||||
const QString &shortcutText)
|
||||
: shortcutText(shortcutText)
|
||||
, enabled(option->state & QStyle::State_Enabled)
|
||||
, active(option->state & QStyle::State_Selected)
|
||||
, font(option->font)
|
||||
, fm(font)
|
||||
, defaultHeight(fm.height())
|
||||
, spaceConst(fm.boundingRect(".").width())
|
||||
{
|
||||
reset();
|
||||
|
||||
if (backspaceMatch(shortcutText).hasMatch())
|
||||
backspaceIcon = option->styleObject->property("backspaceIcon").value<QIcon>();
|
||||
}
|
||||
|
||||
QSize getSize()
|
||||
{
|
||||
if (isFirstParticle)
|
||||
calcResult();
|
||||
return _size;
|
||||
}
|
||||
|
||||
QPixmap getPixmap()
|
||||
{
|
||||
if (!isFirstParticle && !_pixmap.isNull())
|
||||
return _pixmap;
|
||||
|
||||
_pixmap = QPixmap(getSize());
|
||||
_pixmap.fill(Qt::transparent);
|
||||
QPainter painter(&_pixmap);
|
||||
painter.setFont(font);
|
||||
QPen pPen = painter.pen();
|
||||
pPen.setColor(studioTextColor(enabled, active, false));
|
||||
painter.setPen(pPen);
|
||||
calcResult(&painter);
|
||||
painter.end();
|
||||
|
||||
return _pixmap;
|
||||
}
|
||||
|
||||
private:
|
||||
void applySize(const QSize &itemSize) {
|
||||
width += itemSize.width();
|
||||
height = std::max(height, itemSize.height());
|
||||
if (isFirstParticle)
|
||||
isFirstParticle = false;
|
||||
else
|
||||
width += spaceConst;
|
||||
};
|
||||
|
||||
void addText(const QString &txt, QPainter *painter = nullptr)
|
||||
{
|
||||
if (txt.size()) {
|
||||
int textWidth = fm.horizontalAdvance(txt);
|
||||
QSize itemSize = {textWidth, defaultHeight};
|
||||
if (painter) {
|
||||
static const QTextOption textOption(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
QRect placeRect({width, 0}, itemSize);
|
||||
painter->drawText(placeRect, txt, textOption);
|
||||
}
|
||||
applySize(itemSize);
|
||||
}
|
||||
};
|
||||
|
||||
void addPixmap(const QPixmap &pixmap, QPainter *painter = nullptr)
|
||||
{
|
||||
if (painter)
|
||||
painter->drawPixmap(QRect({width, 0}, pixmap.size()), pixmap);
|
||||
|
||||
applySize(pixmap.size());
|
||||
};
|
||||
|
||||
void calcResult(QPainter *painter = nullptr)
|
||||
{
|
||||
reset();
|
||||
#ifndef QT_NO_SHORTCUT
|
||||
if (!shortcutText.isEmpty()) {
|
||||
int fwdIndex = 0;
|
||||
|
||||
QRegularExpressionMatch mMatch = backspaceMatch(shortcutText);
|
||||
int matchCount = mMatch.lastCapturedIndex();
|
||||
|
||||
for (int i = 0; i <= matchCount; ++i) {
|
||||
QString mStr = mMatch.captured(i);
|
||||
QSize iconSize(defaultHeight * 3, defaultHeight);
|
||||
const QList<QSize> iconSizes = backspaceIcon.availableSizes();
|
||||
if (iconSizes.size())
|
||||
iconSize = iconSizes.last();
|
||||
double aspectRatio = (defaultHeight + .0) / iconSize.height();
|
||||
int newWidth = iconSize.width() * aspectRatio;
|
||||
|
||||
QPixmap pixmap = getPixmapFromIcon(backspaceIcon,
|
||||
{newWidth, defaultHeight},
|
||||
enabled, active, false);
|
||||
|
||||
int lIndex = shortcutText.indexOf(mStr, fwdIndex);
|
||||
int diffChars = lIndex - fwdIndex;
|
||||
addText(shortcutText.mid(fwdIndex, diffChars), painter);
|
||||
addPixmap(pixmap, painter);
|
||||
fwdIndex = lIndex + mStr.size();
|
||||
}
|
||||
addText(shortcutText.mid(fwdIndex), painter);
|
||||
}
|
||||
#endif
|
||||
_size = {width, height};
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
isFirstParticle = true;
|
||||
width = 0;
|
||||
height = 0;
|
||||
}
|
||||
|
||||
inline QRegularExpressionMatch backspaceMatch(const QString &str) const
|
||||
{
|
||||
static const QRegularExpression backspaceDetect(
|
||||
"\\+*backspace\\+*",
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
return backspaceDetect.match(str);
|
||||
}
|
||||
|
||||
const QString shortcutText;
|
||||
const bool enabled;
|
||||
const bool active;
|
||||
const QFont font;
|
||||
const QFontMetrics fm;
|
||||
const int defaultHeight;
|
||||
const int spaceConst;
|
||||
QIcon backspaceIcon;
|
||||
bool isFirstParticle = true;
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
QSize _size;
|
||||
QPixmap _pixmap;
|
||||
};
|
||||
|
||||
} // blank namespace
|
||||
|
||||
class StudioStylePrivate
|
||||
inline QRect expandScrollRect(const QRect &ref,
|
||||
const qreal &factor,
|
||||
const Qt::Orientation &orientation)
|
||||
{
|
||||
public:
|
||||
explicit StudioStylePrivate();
|
||||
if (qFuzzyCompare(factor, 1))
|
||||
return ref;
|
||||
|
||||
public:
|
||||
QPalette stdPalette;
|
||||
};
|
||||
|
||||
StudioStylePrivate::StudioStylePrivate()
|
||||
{
|
||||
auto color = [] (Theme::Color c) {
|
||||
return creatorTheme()->color(c);
|
||||
};
|
||||
|
||||
{
|
||||
stdPalette.setColorGroup(
|
||||
QPalette::Disabled, // group
|
||||
color(Theme::DStextColorDisabled), // windowText
|
||||
color(Theme::DScontrolBackgroundDisabled), // button
|
||||
color(Theme::DScontrolOutlineDisabled), // light
|
||||
color(Theme::DStextSelectedTextColor), // dark
|
||||
color(Theme::DSstatusbarBackground), // mid
|
||||
color(Theme::DStextColorDisabled), // text
|
||||
color(Theme::DStextColorDisabled), // brightText
|
||||
color(Theme::DStoolbarIcon_blocked), // base
|
||||
color(Theme::DStoolbarIcon_blocked) // window
|
||||
);
|
||||
|
||||
stdPalette.setColorGroup(
|
||||
QPalette::Inactive, // group
|
||||
color(Theme::DStextColor), // windowText
|
||||
color(Theme::DScontrolBackground), // button
|
||||
color(Theme::DStoolbarBackground), // light
|
||||
color(Theme::DSstatusbarBackground), // dark
|
||||
color(Theme::DScontrolBackground), // mid
|
||||
color(Theme::DStextColor), // text
|
||||
color(Theme::DStextColor), // brightText
|
||||
color(Theme::DStoolbarBackground), // base
|
||||
color(Theme::DStoolbarBackground) // window
|
||||
);
|
||||
|
||||
stdPalette.setColorGroup(
|
||||
QPalette::Active, // group
|
||||
color(Theme::DStextSelectedTextColor), // windowText
|
||||
color(Theme::DSnavigatorItemBackgroundHover), // button
|
||||
color(Theme::DSstateBackgroundColor_hover), // light
|
||||
color(Theme::DSpanelBackground), // dark
|
||||
color(Theme::DSnavigatorItemBackgroundHover), // mid
|
||||
color(Theme::DStextSelectedTextColor), // text
|
||||
color(Theme::DStextSelectedTextColor), // brightText
|
||||
color(Theme::DStoolbarBackground), // base
|
||||
color(Theme::DStoolbarBackground) // window
|
||||
);
|
||||
if (orientation == Qt::Horizontal) {
|
||||
qreal newExp = ref.height() * factor;
|
||||
qreal newDiff = ref.height() - newExp;
|
||||
return ref.adjusted(0, newDiff, 0, 0);
|
||||
} else {
|
||||
qreal newExp = ref.width() * factor;
|
||||
qreal newDiff = ref.width() - newExp;
|
||||
return ref.adjusted(newDiff, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
StudioStyle::StudioStyle(QStyle *style)
|
||||
: QProxyStyle(style)
|
||||
, d(new StudioStylePrivate)
|
||||
, d(new StudioStylePrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
StudioStyle::StudioStyle(const QString &key)
|
||||
: QProxyStyle(key)
|
||||
, d(new StudioStylePrivate)
|
||||
, d(new StudioStylePrivate(this))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -358,8 +196,7 @@ void StudioStyle::drawPrimitive(
|
||||
if (!isQmlEditorMenu(widget))
|
||||
Super::drawPrimitive(element, option, painter, widget);
|
||||
break;
|
||||
case PE_FrameDefaultButton:
|
||||
{
|
||||
case PE_FrameDefaultButton: {
|
||||
if (const auto button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
|
||||
bool enabled = button->state & QStyle::State_Enabled;
|
||||
bool hovered = enabled && button->state & QStyle::State_MouseOver;
|
||||
@@ -385,30 +222,29 @@ void StudioStyle::drawPrimitive(
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case PE_IndicatorToolBarSeparator:
|
||||
{
|
||||
case PE_IndicatorToolBarSeparator: {
|
||||
bool horizontal = option->state & State_Horizontal;
|
||||
int thickness = pixelMetric(PM_ToolBarSeparatorExtent, option, widget);
|
||||
QRect colorRect;
|
||||
if (horizontal) {
|
||||
colorRect = {option->rect.center().x() - thickness / 2 , option->rect.top() + 2,
|
||||
thickness , option->rect.height() - 4};
|
||||
colorRect = {option->rect.center().x() - thickness / 2,
|
||||
option->rect.top() + 2,
|
||||
thickness,
|
||||
option->rect.height() - 4};
|
||||
} else {
|
||||
colorRect = {option->rect.left() + 2, option->rect.center().y() - thickness / 2,
|
||||
option->rect.width() - 4, thickness};
|
||||
colorRect = {option->rect.left() + 2,
|
||||
option->rect.center().y() - thickness / 2,
|
||||
option->rect.width() - 4,
|
||||
thickness};
|
||||
}
|
||||
|
||||
// The separator color is currently the same as toolbar bg
|
||||
painter->fillRect(colorRect,
|
||||
creatorTheme()->color(Theme::DStoolbarBackground));
|
||||
}
|
||||
break;
|
||||
painter->fillRect(colorRect, creatorTheme()->color(Theme::DStoolbarBackground));
|
||||
} break;
|
||||
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
Super::drawPrimitive(element, option, painter, widget);
|
||||
break;
|
||||
}
|
||||
@@ -452,7 +288,7 @@ void StudioStyle::drawControl(
|
||||
|
||||
if (item.menuItemType == QStyleOptionMenuItem::Separator) {
|
||||
int commonHeight = item.rect.center().y();
|
||||
int additionalMargin = forwardX /*hmargin*/;
|
||||
int additionalMargin = forwardX;
|
||||
QLineF separatorLine (item.rect.left() + additionalMargin,
|
||||
commonHeight,
|
||||
item.rect.right() - additionalMargin,
|
||||
@@ -764,6 +600,295 @@ void StudioStyle::drawComplexControl(
|
||||
}
|
||||
Super::drawComplexControl(control, option, painter, widget);
|
||||
} break;
|
||||
|
||||
#if QT_CONFIG(slider)
|
||||
case CC_ScrollBar: {
|
||||
painter->save();
|
||||
if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(
|
||||
option)) {
|
||||
bool wasActive = false;
|
||||
bool wasAdjacent = false;
|
||||
bool isFocused = anyParentsFocused(widget);
|
||||
bool isAdjacent = false;
|
||||
qreal scaleCoFactor = 1.0;
|
||||
QObject *styleObject = option->styleObject;
|
||||
bool hasTransientStyle = proxy()->styleHint(SH_ScrollBar_Transient, option, widget);
|
||||
if (styleObject && hasTransientStyle) {
|
||||
#if ANIMATE_SCROLLBARS
|
||||
qreal opacity = 0.0;
|
||||
bool shouldExpand = false;
|
||||
const qreal minExpandScale = 0.7;
|
||||
const qreal maxExpandScale = 1.0;
|
||||
#endif
|
||||
isAdjacent = styleObject->property("adjacentScroll").toBool();
|
||||
int oldPos = styleObject->property("_qdss_stylepos").toInt();
|
||||
int oldMin = styleObject->property("_qdss_stylemin").toInt();
|
||||
int oldMax = styleObject->property("_qdss_stylemax").toInt();
|
||||
QRect oldRect = styleObject->property("_qdss_stylerect").toRect();
|
||||
QStyle::State oldState = static_cast<QStyle::State>(
|
||||
qvariant_cast<QStyle::State::Int>(styleObject->property("_qdss_stylestate")));
|
||||
uint oldActiveControls = styleObject->property("_qdss_stylecontrols").toUInt();
|
||||
bool oldFocus = styleObject->property("_qdss_focused").toBool();
|
||||
bool oldAdjacent = styleObject->property("_qdss_adjacentScroll").toBool();
|
||||
// a scrollbar is transient when the scrollbar itself and
|
||||
// its sibling are both inactive (ie. not pressed/hovered/moved)
|
||||
bool transient = !option->activeSubControls && !(option->state & State_On);
|
||||
if (!transient || oldPos != scrollBar->sliderPosition
|
||||
|| oldMin != scrollBar->minimum || oldMax != scrollBar->maximum
|
||||
|| oldRect != scrollBar->rect || oldState != scrollBar->state
|
||||
|| oldActiveControls != scrollBar->activeSubControls || oldFocus != isFocused
|
||||
|| oldAdjacent != isAdjacent) {
|
||||
styleObject->setProperty("_qdss_stylepos", scrollBar->sliderPosition);
|
||||
styleObject->setProperty("_qdss_stylemin", scrollBar->minimum);
|
||||
styleObject->setProperty("_qdss_stylemax", scrollBar->maximum);
|
||||
styleObject->setProperty("_qdss_stylerect", scrollBar->rect);
|
||||
styleObject->setProperty("_qdss_stylestate",
|
||||
static_cast<QStyle::State::Int>(scrollBar->state));
|
||||
styleObject->setProperty("_qdss_stylecontrols",
|
||||
static_cast<uint>(scrollBar->activeSubControls));
|
||||
styleObject->setProperty("_qdss_focused", isFocused);
|
||||
styleObject->setProperty("_qdss_adjacentScroll", isAdjacent);
|
||||
#if ANIMATE_SCROLLBARS
|
||||
// if the scrollbar is transient or its attributes, geometry or
|
||||
// state has changed, the opacity is reset back to 100% opaque
|
||||
opacity = 1.0;
|
||||
QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(
|
||||
d->animation(styleObject));
|
||||
if (transient) {
|
||||
if (anim && anim->mode() != QScrollbarStyleAnimation::Deactivating) {
|
||||
d->stopAnimation(styleObject);
|
||||
anim = nullptr;
|
||||
}
|
||||
if (!anim) {
|
||||
anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Deactivating,
|
||||
styleObject);
|
||||
d->startAnimation(anim);
|
||||
} else if (anim->mode() == QScrollbarStyleAnimation::Deactivating) {
|
||||
// the scrollbar was already fading out while the
|
||||
// state changed -> restart the fade out animation
|
||||
anim->setCurrentTime(0);
|
||||
}
|
||||
} else if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) {
|
||||
d->stopAnimation(styleObject);
|
||||
}
|
||||
#endif // animation
|
||||
}
|
||||
#if ANIMATE_SCROLLBARS
|
||||
QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(
|
||||
d->animation(styleObject));
|
||||
if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) {
|
||||
// once a scrollbar was active (hovered/pressed), it retains
|
||||
// the active look even if it's no longer active while fading out
|
||||
if (oldActiveControls)
|
||||
anim->setActive(true);
|
||||
|
||||
if (oldAdjacent)
|
||||
anim->setAdjacent(true);
|
||||
|
||||
wasActive = anim->wasActive();
|
||||
wasAdjacent = anim->wasAdjacent();
|
||||
opacity = anim->currentValue();
|
||||
}
|
||||
shouldExpand = (option->activeSubControls || wasActive);
|
||||
if (shouldExpand) {
|
||||
if (!anim && !oldActiveControls) {
|
||||
// Start expand animation only once and when entering
|
||||
anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Activating,
|
||||
styleObject);
|
||||
d->startAnimation(anim);
|
||||
}
|
||||
if (anim && anim->mode() == QScrollbarStyleAnimation::Activating) {
|
||||
scaleCoFactor = (1.0 - anim->currentValue()) * minExpandScale
|
||||
+ anim->currentValue() * maxExpandScale;
|
||||
} else {
|
||||
// Keep expanded state after the animation ends, and when fading out
|
||||
scaleCoFactor = maxExpandScale;
|
||||
}
|
||||
}
|
||||
painter->setOpacity(opacity);
|
||||
#endif // animation
|
||||
}
|
||||
bool horizontal = scrollBar->orientation == Qt::Horizontal;
|
||||
bool sunken = scrollBar->state & State_Sunken;
|
||||
QRect scrollBarSubLine = proxy()->subControlRect(control,
|
||||
scrollBar,
|
||||
SC_ScrollBarSubLine,
|
||||
widget);
|
||||
QRect scrollBarAddLine = proxy()->subControlRect(control,
|
||||
scrollBar,
|
||||
SC_ScrollBarAddLine,
|
||||
widget);
|
||||
QRect scrollBarSlider = proxy()->subControlRect(control,
|
||||
scrollBar,
|
||||
SC_ScrollBarSlider,
|
||||
widget);
|
||||
QRect scrollBarGroove = proxy()->subControlRect(control,
|
||||
scrollBar,
|
||||
SC_ScrollBarGroove,
|
||||
widget);
|
||||
QRect rect = option->rect;
|
||||
|
||||
QColor alphaOutline = StyleHelper::borderColor();
|
||||
alphaOutline.setAlpha(180);
|
||||
QColor arrowColor = option->palette.windowText().color();
|
||||
arrowColor.setAlpha(160);
|
||||
|
||||
bool enabled = scrollBar->state & QStyle::State_Enabled;
|
||||
bool hovered = enabled && scrollBar->state & QStyle::State_MouseOver;
|
||||
|
||||
QColor buttonColor = hovered ? "#D9D9D9" : "#9B9B9B";
|
||||
QColor gradientStartColor = buttonColor.lighter(118);
|
||||
QColor gradientStopColor = buttonColor;
|
||||
if (hasTransientStyle) {
|
||||
rect = expandScrollRect(rect, scaleCoFactor, scrollBar->orientation);
|
||||
scrollBarSlider = expandScrollRect(scrollBarSlider,
|
||||
scaleCoFactor,
|
||||
scrollBar->orientation);
|
||||
scrollBarGroove = expandScrollRect(scrollBarGroove,
|
||||
scaleCoFactor,
|
||||
scrollBar->orientation);
|
||||
}
|
||||
// Paint groove
|
||||
if ((!hasTransientStyle || scrollBar->activeSubControls || wasActive || isAdjacent
|
||||
|| wasAdjacent)
|
||||
&& scrollBar->subControls & SC_ScrollBarGroove) {
|
||||
painter->save();
|
||||
painter->setPen(Qt::NoPen);
|
||||
if (hasTransientStyle) {
|
||||
QColor brushColor("#D9D9D9");
|
||||
brushColor.setAlpha(0.3 * 255);
|
||||
painter->setBrush(QBrush(brushColor));
|
||||
painter->drawRoundedRect(scrollBarGroove, 4, 4);
|
||||
} else {
|
||||
painter->setBrush(QBrush("#773E3E"));
|
||||
painter->drawRect(rect);
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
QRect pixmapRect = scrollBarSlider;
|
||||
QLinearGradient gradient(pixmapRect.center().x(),
|
||||
pixmapRect.top(),
|
||||
pixmapRect.center().x(),
|
||||
pixmapRect.bottom());
|
||||
if (!horizontal)
|
||||
gradient = QLinearGradient(pixmapRect.left(),
|
||||
pixmapRect.center().y(),
|
||||
pixmapRect.right(),
|
||||
pixmapRect.center().y());
|
||||
QLinearGradient highlightedGradient = gradient;
|
||||
QColor midColor2 = StyleHelper::mergedColors(gradientStartColor, gradientStopColor, 40);
|
||||
gradient.setColorAt(0, buttonColor.lighter(108));
|
||||
gradient.setColorAt(1, buttonColor);
|
||||
QColor innerContrastLine = StyleHelper::highlightColor();
|
||||
highlightedGradient.setColorAt(0, gradientStartColor.darker(102));
|
||||
highlightedGradient.setColorAt(1, gradientStopColor.lighter(102));
|
||||
// Paint slider
|
||||
if (scrollBar->subControls & SC_ScrollBarSlider) {
|
||||
if (hasTransientStyle) {
|
||||
QRect rect = scrollBarSlider;
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(highlightedGradient);
|
||||
int r = qMin(rect.width(), rect.height()) / 2;
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
painter->drawRoundedRect(rect, r, r);
|
||||
painter->restore();
|
||||
} else {
|
||||
QRect pixmapRect = scrollBarSlider;
|
||||
painter->setPen(QPen(alphaOutline));
|
||||
if (option->state & State_Sunken
|
||||
&& scrollBar->activeSubControls & SC_ScrollBarSlider)
|
||||
painter->setBrush(midColor2);
|
||||
else if (option->state & State_MouseOver
|
||||
&& scrollBar->activeSubControls & SC_ScrollBarSlider)
|
||||
painter->setBrush(highlightedGradient);
|
||||
else
|
||||
painter->setBrush(gradient);
|
||||
painter->drawRect(pixmapRect.adjusted(horizontal ? -1 : 0,
|
||||
horizontal ? 0 : -1,
|
||||
horizontal ? 0 : 1,
|
||||
horizontal ? 1 : 0));
|
||||
painter->setPen(innerContrastLine);
|
||||
painter->drawRect(
|
||||
scrollBarSlider.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, -1, -1));
|
||||
}
|
||||
}
|
||||
// The SubLine (up/left) buttons
|
||||
if (!hasTransientStyle && scrollBar->subControls & SC_ScrollBarSubLine) {
|
||||
if ((scrollBar->activeSubControls & SC_ScrollBarSubLine) && sunken)
|
||||
painter->setBrush(gradientStopColor);
|
||||
else if ((scrollBar->activeSubControls & SC_ScrollBarSubLine))
|
||||
painter->setBrush(highlightedGradient);
|
||||
else
|
||||
painter->setBrush(gradient);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->drawRect(
|
||||
scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, 0, 0));
|
||||
painter->setPen(QPen(alphaOutline));
|
||||
if (option->state & State_Horizontal) {
|
||||
if (option->direction == Qt::RightToLeft) {
|
||||
pixmapRect.setLeft(scrollBarSubLine.left());
|
||||
painter->drawLine(pixmapRect.topLeft(), pixmapRect.bottomLeft());
|
||||
} else {
|
||||
pixmapRect.setRight(scrollBarSubLine.right());
|
||||
painter->drawLine(pixmapRect.topRight(), pixmapRect.bottomRight());
|
||||
}
|
||||
} else {
|
||||
pixmapRect.setBottom(scrollBarSubLine.bottom());
|
||||
painter->drawLine(pixmapRect.bottomLeft(), pixmapRect.bottomRight());
|
||||
}
|
||||
QRect upRect = scrollBarSubLine.adjusted(horizontal ? 0 : 1,
|
||||
horizontal ? 1 : 0,
|
||||
horizontal ? -2 : -1,
|
||||
horizontal ? -1 : -2);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->setPen(innerContrastLine);
|
||||
painter->drawRect(upRect);
|
||||
// Arrows
|
||||
PrimitiveElement arrowType = PE_IndicatorArrowUp;
|
||||
if (option->state & State_Horizontal)
|
||||
arrowType = option->direction == Qt::LeftToRight ? PE_IndicatorArrowLeft
|
||||
: PE_IndicatorArrowRight;
|
||||
StyleHelper::drawArrow(arrowType, painter, option);
|
||||
}
|
||||
// The AddLine (down/right) button
|
||||
if (!hasTransientStyle && scrollBar->subControls & SC_ScrollBarAddLine) {
|
||||
if ((scrollBar->activeSubControls & SC_ScrollBarAddLine) && sunken)
|
||||
painter->setBrush(gradientStopColor);
|
||||
else if ((scrollBar->activeSubControls & SC_ScrollBarAddLine))
|
||||
painter->setBrush(midColor2);
|
||||
else
|
||||
painter->setBrush(gradient);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->drawRect(
|
||||
scrollBarAddLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, 0, 0));
|
||||
painter->setPen(QPen(alphaOutline, 1));
|
||||
if (option->state & State_Horizontal) {
|
||||
if (option->direction == Qt::LeftToRight) {
|
||||
pixmapRect.setLeft(scrollBarAddLine.left());
|
||||
painter->drawLine(pixmapRect.topLeft(), pixmapRect.bottomLeft());
|
||||
} else {
|
||||
pixmapRect.setRight(scrollBarAddLine.right());
|
||||
painter->drawLine(pixmapRect.topRight(), pixmapRect.bottomRight());
|
||||
}
|
||||
} else {
|
||||
pixmapRect.setTop(scrollBarAddLine.top());
|
||||
painter->drawLine(pixmapRect.topLeft(), pixmapRect.topRight());
|
||||
}
|
||||
QRect downRect = scrollBarAddLine.adjusted(1, 1, -1, -1);
|
||||
painter->setPen(innerContrastLine);
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawRect(downRect);
|
||||
PrimitiveElement arrowType = PE_IndicatorArrowDown;
|
||||
if (option->state & State_Horizontal)
|
||||
arrowType = option->direction == Qt::LeftToRight ? PE_IndicatorArrowRight
|
||||
: PE_IndicatorArrowLeft;
|
||||
StyleHelper::drawArrow(arrowType, painter, option);
|
||||
}
|
||||
}
|
||||
painter->restore();
|
||||
} break;
|
||||
#endif // QT_CONFIG(slider)
|
||||
default:
|
||||
Super::drawComplexControl(control, option, painter, widget);
|
||||
break;
|
||||
@@ -779,7 +904,7 @@ QSize StudioStyle::sizeFromContents(
|
||||
QSize newSize;
|
||||
|
||||
switch (type) {
|
||||
case CT_MenuItem:
|
||||
case CT_MenuItem: {
|
||||
if (const auto mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
|
||||
if (!isQmlEditorMenu(widget)) {
|
||||
newSize = Super::sizeFromContents(type, option, size, widget);
|
||||
@@ -835,8 +960,7 @@ QSize StudioStyle::sizeFromContents(
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
} break;
|
||||
default:
|
||||
newSize = Super::sizeFromContents(type, option, size, widget);
|
||||
break;
|
||||
@@ -860,26 +984,56 @@ QRect StudioStyle::subControlRect(
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (control)
|
||||
{
|
||||
case CC_Slider:
|
||||
switch (control) {
|
||||
case CC_Slider: {
|
||||
if (const auto slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
|
||||
switch (subControl) {
|
||||
case SubControl::SC_SliderGroove:
|
||||
return slider->rect;
|
||||
case SubControl::SC_SliderHandle:
|
||||
{
|
||||
case SubControl::SC_SliderHandle: {
|
||||
QRect retval = Super::subControlRect(control, option, subControl, widget);
|
||||
return (slider->orientation == Qt::Horizontal)
|
||||
? retval.adjusted(0, 1, 0, 0)
|
||||
return (slider->orientation == Qt::Horizontal) ? retval.adjusted(0, 1, 0, 0)
|
||||
: retval.adjusted(1, 0, 0, 0);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case CC_ScrollBar: {
|
||||
if (!styleHint(SH_ScrollBar_Transient, option, widget))
|
||||
break;
|
||||
|
||||
if (const auto scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
|
||||
QRect newRect = Super::subControlRect(control, option, subControl, widget);
|
||||
if (Utils::HostOsInfo::isMacHost()) {
|
||||
if (scrollbar->orientation == Qt::Horizontal) {
|
||||
const int halfThickness = newRect.height() / 2;
|
||||
newRect.adjust(0, halfThickness, 0, 0);
|
||||
} else {
|
||||
const int halfThickness = newRect.width() / 2;
|
||||
newRect.adjust(halfThickness, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
if (subControl == SC_ScrollBarSlider) {
|
||||
bool hasGroove
|
||||
= (scrollbar->activeSubControls.testFlag(SC_SliderGroove)
|
||||
|| (scrollbar->styleObject
|
||||
&& scrollbar->styleObject->property("adjacentScrollBar").toBool()))
|
||||
&& scrollbar->subControls.testFlag(SC_ScrollBarGroove);
|
||||
bool interacted = scrollbar->activeSubControls.testFlag(SC_ScrollBarSlider);
|
||||
|
||||
if (hasGroove || interacted)
|
||||
return newRect;
|
||||
|
||||
if (scrollbar->orientation == Qt::Horizontal)
|
||||
newRect.adjust(0, 1, 0, -1);
|
||||
else
|
||||
newRect.adjust(1, 0, -1, 0);
|
||||
}
|
||||
return newRect;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -893,6 +1047,12 @@ int StudioStyle::styleHint(
|
||||
const QWidget *widget,
|
||||
QStyleHintReturn *returnData) const
|
||||
{
|
||||
switch (hint) {
|
||||
case SH_ScrollBar_Transient:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return Super::styleHint(hint, option, widget, returnData);
|
||||
}
|
||||
|
||||
@@ -946,19 +1106,22 @@ int StudioStyle::pixelMetric(
|
||||
return 4;
|
||||
case PM_ToolBarExtensionExtent:
|
||||
return 29;
|
||||
case PM_ScrollBarExtent:
|
||||
return 20;
|
||||
case PM_ScrollBarExtent: {
|
||||
if (styleHint(SH_ScrollBar_Transient, option, widget))
|
||||
return 10;
|
||||
return 14;
|
||||
} break;
|
||||
case PM_ScrollBarSliderMin:
|
||||
return 30;
|
||||
case PM_SliderLength:
|
||||
return 5;
|
||||
case PM_SliderThickness:
|
||||
case PM_SliderThickness: {
|
||||
if (const auto *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
|
||||
return (slider->orientation == Qt::Horizontal
|
||||
? slider->rect.height()
|
||||
: slider->rect.width()) - 1;
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
case PM_SliderControlThickness:
|
||||
return 2;
|
||||
default:
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include <QProxyStyle>
|
||||
|
||||
namespace QmlDesigner {
|
||||
class StudioStylePrivate;
|
||||
|
||||
class QMLDESIGNERBASE_EXPORT StudioStyle : public QProxyStyle
|
||||
@@ -20,53 +21,45 @@ public:
|
||||
virtual ~StudioStyle() override;
|
||||
|
||||
// Drawing Methods
|
||||
void drawPrimitive(
|
||||
PrimitiveElement element,
|
||||
void drawPrimitive(PrimitiveElement element,
|
||||
const QStyleOption *option,
|
||||
QPainter *painter,
|
||||
const QWidget *widget = nullptr) const override;
|
||||
|
||||
void drawControl(
|
||||
ControlElement element,
|
||||
void drawControl(ControlElement element,
|
||||
const QStyleOption *option,
|
||||
QPainter *painter,
|
||||
const QWidget *widget = nullptr) const override;
|
||||
|
||||
void drawComplexControl(
|
||||
ComplexControl control,
|
||||
void drawComplexControl(ComplexControl control,
|
||||
const QStyleOptionComplex *option,
|
||||
QPainter *painter,
|
||||
const QWidget *widget = nullptr) const override;
|
||||
|
||||
// Topology
|
||||
QSize sizeFromContents(
|
||||
ContentsType type,
|
||||
QSize sizeFromContents(ContentsType type,
|
||||
const QStyleOption *option,
|
||||
const QSize &size,
|
||||
const QWidget *widget) const override;
|
||||
|
||||
QRect subControlRect(
|
||||
ComplexControl control,
|
||||
QRect subControlRect(ComplexControl control,
|
||||
const QStyleOptionComplex *option,
|
||||
SubControl subControl,
|
||||
const QWidget *widget) const override;
|
||||
|
||||
int styleHint(
|
||||
StyleHint hint,
|
||||
const QStyleOption *option,
|
||||
const QWidget *widget,
|
||||
QStyleHintReturn *returnData) const override;
|
||||
int styleHint(StyleHint hint,
|
||||
const QStyleOption *option = nullptr,
|
||||
const QWidget *widget = nullptr,
|
||||
QStyleHintReturn *returnData = nullptr) const override;
|
||||
|
||||
int pixelMetric(
|
||||
PixelMetric metric,
|
||||
int pixelMetric(PixelMetric metric,
|
||||
const QStyleOption *option = nullptr,
|
||||
const QWidget *widget = nullptr) const override;
|
||||
|
||||
QPalette standardPalette() const override;
|
||||
|
||||
private:
|
||||
void drawQmlEditorIcon(
|
||||
PrimitiveElement element,
|
||||
void drawQmlEditorIcon(PrimitiveElement element,
|
||||
const QStyleOption *option,
|
||||
const char *propertyName,
|
||||
QPainter *painter,
|
||||
@@ -74,3 +67,5 @@ private:
|
||||
|
||||
StudioStylePrivate *d = nullptr;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
||||
240
src/plugins/qmldesignerbase/studio/studiostyle_p.cpp
Normal file
240
src/plugins/qmldesignerbase/studio/studiostyle_p.cpp
Normal file
@@ -0,0 +1,240 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "studiostyle_p.h"
|
||||
|
||||
#include "studiostyle.h"
|
||||
|
||||
#include <utils/styleanimator.h>
|
||||
#include <utils/theme/theme.h>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QStyleOption>
|
||||
|
||||
using namespace Utils;
|
||||
using namespace QmlDesigner;
|
||||
|
||||
namespace {
|
||||
inline QPixmap getPixmapFromIcon(
|
||||
const QIcon &icon, const QSize &size, bool enabled, bool active, bool checked)
|
||||
{
|
||||
QIcon::Mode mode = enabled ? ((active) ? QIcon::Active : QIcon::Normal) : QIcon::Disabled;
|
||||
QIcon::State state = (checked) ? QIcon::On : QIcon::Off;
|
||||
return icon.pixmap(size, mode, state);
|
||||
}
|
||||
|
||||
inline QColor studioTextColor(bool enabled, bool active, bool checked)
|
||||
{
|
||||
Theme::Color themePenColorId = enabled ? (active ? (checked ? Theme::DSsubPanelBackground
|
||||
: Theme::DSpanelBackground)
|
||||
: Theme::DStextColor)
|
||||
: Theme::DStextColorDisabled;
|
||||
|
||||
return creatorTheme()->color(themePenColorId);
|
||||
}
|
||||
}; // namespace
|
||||
|
||||
StudioStylePrivate::StudioStylePrivate(StudioStyle *q)
|
||||
: QObject(q)
|
||||
, q(q)
|
||||
{
|
||||
auto color = [](Theme::Color c) { return creatorTheme()->color(c); };
|
||||
|
||||
{
|
||||
stdPalette.setColorGroup(QPalette::Disabled, // group
|
||||
color(Theme::DStextColorDisabled), // windowText
|
||||
color(Theme::DScontrolBackgroundDisabled), // button
|
||||
color(Theme::DScontrolOutlineDisabled), // light
|
||||
color(Theme::DStextSelectedTextColor), // dark
|
||||
color(Theme::DSstatusbarBackground), // mid
|
||||
color(Theme::DStextColorDisabled), // text
|
||||
color(Theme::DStextColorDisabled), // brightText
|
||||
color(Theme::DStoolbarIcon_blocked), // base
|
||||
color(Theme::DStoolbarIcon_blocked) // window
|
||||
);
|
||||
|
||||
stdPalette.setColorGroup(QPalette::Inactive, // group
|
||||
color(Theme::DStextColor), // windowText
|
||||
color(Theme::DScontrolBackground), // button
|
||||
color(Theme::DStoolbarBackground), // light
|
||||
color(Theme::DSstatusbarBackground), // dark
|
||||
color(Theme::DScontrolBackground), // mid
|
||||
color(Theme::DStextColor), // text
|
||||
color(Theme::DStextColor), // brightText
|
||||
color(Theme::DStoolbarBackground), // base
|
||||
color(Theme::DStoolbarBackground) // window
|
||||
);
|
||||
|
||||
stdPalette.setColorGroup(QPalette::Active, // group
|
||||
color(Theme::DStextSelectedTextColor), // windowText
|
||||
color(Theme::DSnavigatorItemBackgroundHover), // button
|
||||
color(Theme::DSstateBackgroundColor_hover), // light
|
||||
color(Theme::DSpanelBackground), // dark
|
||||
color(Theme::DSnavigatorItemBackgroundHover), // mid
|
||||
color(Theme::DStextSelectedTextColor), // text
|
||||
color(Theme::DStextSelectedTextColor), // brightText
|
||||
color(Theme::DStoolbarBackground), // base
|
||||
color(Theme::DStoolbarBackground) // window
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
QList<const QObject *> StudioStylePrivate::animationTargets() const
|
||||
{
|
||||
return m_animations.keys();
|
||||
}
|
||||
|
||||
QStyleAnimation *StudioStylePrivate::animation(const QObject *target) const
|
||||
{
|
||||
return m_animations.value(target, nullptr);
|
||||
}
|
||||
|
||||
void StudioStylePrivate::startAnimation(QStyleAnimation *animation) const
|
||||
{
|
||||
stopAnimation(animation->target());
|
||||
QObject::connect(animation,
|
||||
&QObject::destroyed,
|
||||
this,
|
||||
&StudioStylePrivate::removeAnimation,
|
||||
Qt::UniqueConnection);
|
||||
m_animations.insert(animation->target(), animation);
|
||||
animation->start();
|
||||
}
|
||||
|
||||
void StudioStylePrivate::stopAnimation(const QObject *target) const
|
||||
{
|
||||
QStyleAnimation *animation = m_animations.take(target);
|
||||
if (animation) {
|
||||
animation->stop();
|
||||
delete animation;
|
||||
}
|
||||
}
|
||||
|
||||
void StudioStylePrivate::removeAnimation(const QObject *animationObject)
|
||||
{
|
||||
if (animationObject)
|
||||
m_animations.remove(animationObject->parent());
|
||||
}
|
||||
|
||||
StudioShortcut::StudioShortcut(const QStyleOptionMenuItem *option, const QString &shortcutText)
|
||||
: m_shortcutText(shortcutText)
|
||||
, m_enabled(option->state & QStyle::State_Enabled)
|
||||
, m_active(option->state & QStyle::State_Selected)
|
||||
, m_font(option->font)
|
||||
, m_fontMetrics(m_font)
|
||||
, m_defaultHeight(m_fontMetrics.height())
|
||||
, m_spaceConst(m_fontMetrics.boundingRect(".").width())
|
||||
{
|
||||
reset();
|
||||
|
||||
if (backspaceMatch(shortcutText).hasMatch() && option->styleObject)
|
||||
m_backspaceIcon = option->styleObject->property("backspaceIcon").value<QIcon>();
|
||||
}
|
||||
|
||||
QSize StudioShortcut::getSize()
|
||||
{
|
||||
if (m_isFirstParticle)
|
||||
calcResult();
|
||||
return m_size;
|
||||
}
|
||||
|
||||
QPixmap StudioShortcut::getPixmap()
|
||||
{
|
||||
if (!m_isFirstParticle && !m_pixmap.isNull())
|
||||
return m_pixmap;
|
||||
|
||||
m_pixmap = QPixmap(getSize());
|
||||
m_pixmap.fill(Qt::transparent);
|
||||
QPainter painter(&m_pixmap);
|
||||
painter.setFont(m_font);
|
||||
QPen pPen = painter.pen();
|
||||
pPen.setColor(studioTextColor(m_enabled, m_active, false));
|
||||
painter.setPen(pPen);
|
||||
calcResult(&painter);
|
||||
painter.end();
|
||||
|
||||
return m_pixmap;
|
||||
}
|
||||
|
||||
void StudioShortcut::applySize(const QSize &itemSize)
|
||||
{
|
||||
m_width += itemSize.width();
|
||||
m_height = std::max(m_height, itemSize.height());
|
||||
if (m_isFirstParticle)
|
||||
m_isFirstParticle = false;
|
||||
else
|
||||
m_width += m_spaceConst;
|
||||
}
|
||||
|
||||
void StudioShortcut::addText(const QString &txt, QPainter *painter)
|
||||
{
|
||||
if (txt.size()) {
|
||||
int textWidth = m_fontMetrics.horizontalAdvance(txt);
|
||||
QSize itemSize = {textWidth, m_defaultHeight};
|
||||
if (painter) {
|
||||
static const QTextOption textOption(Qt::AlignLeft | Qt::AlignVCenter);
|
||||
QRect placeRect({m_width, 0}, itemSize);
|
||||
painter->drawText(placeRect, txt, textOption);
|
||||
}
|
||||
applySize(itemSize);
|
||||
}
|
||||
}
|
||||
|
||||
void StudioShortcut::addPixmap(const QPixmap &pixmap, QPainter *painter)
|
||||
{
|
||||
if (painter)
|
||||
painter->drawPixmap(QRect({m_width, 0}, pixmap.size()), pixmap);
|
||||
|
||||
applySize(pixmap.size());
|
||||
}
|
||||
|
||||
void StudioShortcut::calcResult(QPainter *painter)
|
||||
{
|
||||
reset();
|
||||
#ifndef QT_NO_SHORTCUT
|
||||
if (!m_shortcutText.isEmpty()) {
|
||||
int fwdIndex = 0;
|
||||
|
||||
QRegularExpressionMatch mMatch = backspaceMatch(m_shortcutText);
|
||||
int matchCount = mMatch.lastCapturedIndex();
|
||||
|
||||
for (int i = 0; i <= matchCount; ++i) {
|
||||
QString mStr = mMatch.captured(i);
|
||||
QSize iconSize(m_defaultHeight * 3, m_defaultHeight);
|
||||
const QList<QSize> iconSizes = m_backspaceIcon.availableSizes();
|
||||
if (iconSizes.size())
|
||||
iconSize = iconSizes.last();
|
||||
double aspectRatio = (m_defaultHeight + .0) / iconSize.height();
|
||||
int newWidth = iconSize.width() * aspectRatio;
|
||||
|
||||
QPixmap pixmap = getPixmapFromIcon(m_backspaceIcon,
|
||||
{newWidth, m_defaultHeight},
|
||||
m_enabled,
|
||||
m_active,
|
||||
false);
|
||||
|
||||
int lIndex = m_shortcutText.indexOf(mStr, fwdIndex);
|
||||
int diffChars = lIndex - fwdIndex;
|
||||
addText(m_shortcutText.mid(fwdIndex, diffChars), painter);
|
||||
addPixmap(pixmap, painter);
|
||||
fwdIndex = lIndex + mStr.size();
|
||||
}
|
||||
addText(m_shortcutText.mid(fwdIndex), painter);
|
||||
}
|
||||
#endif
|
||||
m_size = {m_width, m_height};
|
||||
}
|
||||
|
||||
void StudioShortcut::reset()
|
||||
{
|
||||
m_isFirstParticle = true;
|
||||
m_width = 0;
|
||||
m_height = 0;
|
||||
}
|
||||
|
||||
QRegularExpressionMatch StudioShortcut::backspaceMatch(const QString &str) const
|
||||
{
|
||||
static const QRegularExpression backspaceDetect("\\+*backspace\\+*",
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
return backspaceDetect.match(str);
|
||||
}
|
||||
84
src/plugins/qmldesignerbase/studio/studiostyle_p.h
Normal file
84
src/plugins/qmldesignerbase/studio/studiostyle_p.h
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QFont>
|
||||
#include <QFontMetrics>
|
||||
#include <QHash>
|
||||
#include <QIcon>
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QPalette>
|
||||
#include <QPixmap>
|
||||
#include <QProxyStyle>
|
||||
#include <QRegularExpressionMatch>
|
||||
#include <QSize>
|
||||
|
||||
class QStyleOptionMenuItem;
|
||||
class QPainter;
|
||||
|
||||
namespace Utils {
|
||||
class StyleAnimation;
|
||||
class QStyleAnimation;
|
||||
} // namespace Utils
|
||||
|
||||
namespace QmlDesigner {
|
||||
class StudioStyle;
|
||||
|
||||
class StudioStylePrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
using StyleAnimation = Utils::StyleAnimation;
|
||||
using QStyleAnimation = Utils::QStyleAnimation;
|
||||
|
||||
public:
|
||||
explicit StudioStylePrivate(StudioStyle *q);
|
||||
|
||||
QList<const QObject *> animationTargets() const;
|
||||
QStyleAnimation *animation(const QObject *target) const;
|
||||
void startAnimation(QStyleAnimation *animation) const;
|
||||
void stopAnimation(const QObject *target) const;
|
||||
|
||||
QPalette stdPalette;
|
||||
|
||||
private:
|
||||
StudioStyle *q = nullptr;
|
||||
mutable QHash<const QObject *, QStyleAnimation *> m_animations;
|
||||
|
||||
private slots:
|
||||
void removeAnimation(const QObject *animationObject);
|
||||
};
|
||||
|
||||
struct StudioShortcut
|
||||
{
|
||||
StudioShortcut(const QStyleOptionMenuItem *option, const QString &shortcutText);
|
||||
QSize getSize();
|
||||
QPixmap getPixmap();
|
||||
|
||||
private:
|
||||
void applySize(const QSize &itemSize);
|
||||
void addText(const QString &txt, QPainter *painter = nullptr);
|
||||
void addPixmap(const QPixmap &pixmap, QPainter *painter = nullptr);
|
||||
void calcResult(QPainter *painter = nullptr);
|
||||
void reset();
|
||||
QRegularExpressionMatch backspaceMatch(const QString &str) const;
|
||||
|
||||
const QString m_shortcutText;
|
||||
const bool m_enabled;
|
||||
const bool m_active;
|
||||
const QFont m_font;
|
||||
const QFontMetrics m_fontMetrics;
|
||||
const int m_defaultHeight;
|
||||
const int m_spaceConst;
|
||||
|
||||
QIcon m_backspaceIcon;
|
||||
bool m_isFirstParticle = true;
|
||||
|
||||
int m_width = 0;
|
||||
int m_height = 0;
|
||||
QSize m_size;
|
||||
QPixmap m_pixmap;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
Reference in New Issue
Block a user