forked from qt-creator/qt-creator
QmlDesigner: Style particle slider for new theme
The style for slider is overridden in ManhattanStyle. SeekSlider is modified. Task-number: QDS-9134 Change-Id: Ib96413f2bb7918d611adf4fc19c184efae1c4f4c Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -89,6 +89,11 @@ bool panelWidget(const QWidget *widget)
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isDSSlider(const QWidget *widget)
|
||||
{
|
||||
return (widget && widget->property("DSSlider").toBool());
|
||||
}
|
||||
|
||||
// Consider making this a QStyle state
|
||||
static bool isQmlEditorMenu(const QWidget *widget)
|
||||
{
|
||||
@@ -489,7 +494,30 @@ QRect ManhattanStyle::subControlRect(ComplexControl control, const QStyleOptionC
|
||||
return QRect(); // breaks the scrollbar, but avoids the crash
|
||||
}
|
||||
#endif
|
||||
return QProxyStyle::subControlRect(control, option, subControl, widget);
|
||||
|
||||
QRect retval = QProxyStyle::subControlRect(control, option, subControl, widget);;
|
||||
if (isDSSlider(widget)) {
|
||||
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
|
||||
switch (subControl) {
|
||||
case SubControl::SC_SliderGroove:
|
||||
return option->rect;
|
||||
case SubControl::SC_SliderHandle:
|
||||
{
|
||||
int thickness = 2;
|
||||
QPoint center = retval.center();
|
||||
const QRect &rect = slider->rect;
|
||||
if (slider->orientation == Qt::Horizontal)
|
||||
return QRect(center.x() - thickness, rect.top(), (thickness * 2) + 1, rect.height());
|
||||
else
|
||||
return QRect(rect.left(), center.y() - thickness, rect.width(), (thickness * 2) + 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
QStyle::SubControl ManhattanStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
|
||||
@@ -1758,7 +1786,156 @@ void ManhattanStyle::drawComplexControl(ComplexControl control, const QStyleOpti
|
||||
painter->restore();
|
||||
}
|
||||
break;
|
||||
case CC_Slider:
|
||||
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
|
||||
if (!isDSSlider(widget)) {
|
||||
QProxyStyle::drawComplexControl(control, option, painter, widget);
|
||||
break;
|
||||
}
|
||||
|
||||
QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
|
||||
QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
|
||||
|
||||
bool horizontal = slider->orientation == Qt::Horizontal;
|
||||
bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
|
||||
bool ticksBelow = slider->tickPosition & QSlider::TicksBelow;
|
||||
bool enabled = option->state & QStyle::State_Enabled;
|
||||
bool activeFocus = option->state & State_HasFocus && option->state & State_KeyboardFocusChange;
|
||||
|
||||
int sliderPaintingOffset = horizontal
|
||||
? handle.center().x()
|
||||
: handle.center().y();
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::RenderHint::Antialiasing);
|
||||
|
||||
int lineWidth = pixelMetric(QStyle::PM_DefaultFrameWidth, option, widget);
|
||||
Theme::Color themeframeColor = enabled
|
||||
? activeFocus
|
||||
? Theme::DSstateBackgroundColor_hover
|
||||
: Theme::DSBackgroundColorAlternate
|
||||
: Theme::DScontrolBackgroundDisabled;
|
||||
QColor frameColor = creatorTheme()->color(themeframeColor);
|
||||
|
||||
if ((option->subControls & SC_SliderGroove) && groove.isValid()) {
|
||||
Theme::Color bgPlusColor = enabled ? Theme::DSBackgroundColorAlternate : Theme::DScontrolOutlineDisabled;
|
||||
Theme::Color bgMinusColor = enabled ? Theme::DScontrolBackground : Theme::DScontrolOutlineDisabled;
|
||||
|
||||
QRect minusRect(groove);
|
||||
QRect plusRect(groove);
|
||||
|
||||
if (horizontal) {
|
||||
if (slider->upsideDown) {
|
||||
minusRect.setLeft(sliderPaintingOffset);
|
||||
plusRect.setRight(sliderPaintingOffset);
|
||||
} else {
|
||||
minusRect.setRight(sliderPaintingOffset);
|
||||
plusRect.setLeft(sliderPaintingOffset);
|
||||
}
|
||||
} else {
|
||||
if (slider->upsideDown) {
|
||||
minusRect.setBottom(sliderPaintingOffset);
|
||||
plusRect.setTop(sliderPaintingOffset);
|
||||
} else {
|
||||
minusRect.setTop(sliderPaintingOffset);
|
||||
plusRect.setBottom(sliderPaintingOffset);
|
||||
}
|
||||
}
|
||||
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->fillRect(plusRect, creatorTheme()->color(bgPlusColor));
|
||||
painter->fillRect(minusRect, creatorTheme()->color(bgMinusColor));
|
||||
}
|
||||
|
||||
if (option->subControls & SC_SliderTickmarks) {
|
||||
Theme::Color tickPen = enabled
|
||||
? activeFocus
|
||||
? Theme::DSstateBackgroundColor_hover
|
||||
: Theme::DSBackgroundColorAlternate
|
||||
: Theme::DScontrolBackgroundDisabled;
|
||||
|
||||
painter->setPen(tickPen);
|
||||
int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
|
||||
int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
|
||||
int interval = slider->tickInterval;
|
||||
if (interval <= 0) {
|
||||
interval = slider->singleStep;
|
||||
if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval,
|
||||
available)
|
||||
- QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
|
||||
0, available) < 3)
|
||||
interval = slider->pageStep;
|
||||
}
|
||||
if (interval <= 0)
|
||||
interval = 1;
|
||||
|
||||
int v = slider->minimum;
|
||||
int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
|
||||
while (v <= slider->maximum + 1) {
|
||||
if (v == slider->maximum + 1 && interval == 1)
|
||||
break;
|
||||
const int v_ = qMin(v, slider->maximum);
|
||||
int pos = sliderPositionFromValue(slider->minimum, slider->maximum,
|
||||
v_, (horizontal
|
||||
? slider->rect.width()
|
||||
: slider->rect.height()) - len,
|
||||
slider->upsideDown) + len / 2;
|
||||
int extra = 2 - ((v_ == slider->minimum || v_ == slider->maximum) ? 1 : 0);
|
||||
|
||||
if (horizontal) {
|
||||
if (ticksAbove) {
|
||||
painter->drawLine(pos, slider->rect.top() + extra,
|
||||
pos, slider->rect.top() + tickSize);
|
||||
}
|
||||
if (ticksBelow) {
|
||||
painter->drawLine(pos, slider->rect.bottom() - extra,
|
||||
pos, slider->rect.bottom() - tickSize);
|
||||
}
|
||||
} else {
|
||||
if (ticksAbove) {
|
||||
painter->drawLine(slider->rect.left() + extra, pos,
|
||||
slider->rect.left() + tickSize, pos);
|
||||
}
|
||||
if (ticksBelow) {
|
||||
painter->drawLine(slider->rect.right() - extra, pos,
|
||||
slider->rect.right() - tickSize, pos);
|
||||
}
|
||||
}
|
||||
// in the case where maximum is max int
|
||||
int nextInterval = v + interval;
|
||||
if (nextInterval < v)
|
||||
break;
|
||||
v = nextInterval;
|
||||
}
|
||||
}
|
||||
|
||||
// draw handle
|
||||
if ((option->subControls & SC_SliderHandle) ) {
|
||||
Theme::Color handleColor = enabled
|
||||
? slider->state & QStyle::State_Editing
|
||||
? Theme::DSsliderHandleInteraction
|
||||
: slider->activeSubControls & SC_SliderHandle
|
||||
? Theme::DSsliderHandleHover
|
||||
: Theme::DSsliderHandle
|
||||
: Theme::DSiconColorDisabled;
|
||||
|
||||
int halfSliderThickness = horizontal
|
||||
? handle.width() / 2
|
||||
: handle.height() / 2;
|
||||
painter->setBrush(creatorTheme()->color(handleColor));
|
||||
painter->drawRoundedRect(handle,
|
||||
halfSliderThickness,
|
||||
halfSliderThickness);
|
||||
}
|
||||
|
||||
if (groove.isValid()) {
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->setPen(QPen(frameColor, lineWidth));
|
||||
painter->drawRect(groove);
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
QProxyStyle::drawComplexControl(control, option, painter, widget);
|
||||
break;
|
||||
|
@@ -167,8 +167,8 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view)
|
||||
view->setSeeker(seeker);
|
||||
seeker->setToolTip(QLatin1String("Seek particle system time when paused."));
|
||||
|
||||
QObject::connect(seeker, &SeekerSlider::positionChanged, [seeker, view]() {
|
||||
view->emitView3DAction(View3DActionType::ParticlesSeek, seeker->position());
|
||||
QObject::connect(seeker, &SeekerSlider::valueChanged, [view](int value) {
|
||||
view->emitView3DAction(View3DActionType::ParticlesSeek, value);
|
||||
});
|
||||
|
||||
// Onboarding label contains instructions for new users how to get 3D content into the project
|
||||
|
@@ -5,112 +5,66 @@
|
||||
|
||||
#include <utils/icon.h>
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <QStyleOption>
|
||||
#include <QSlider>
|
||||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
SeekerSlider::SeekerSlider(QWidget *parentWidget)
|
||||
: QWidget(parentWidget),
|
||||
m_bgIcon(QLatin1String(":/icon/layout/scrubbg.png"))
|
||||
SeekerSlider::SeekerSlider(QWidget *parent)
|
||||
: QSlider(parent)
|
||||
{
|
||||
m_handleIcon.addFile(QLatin1String(":/icon/layout/scrubhandle-24.png"), QSize(24, 24));
|
||||
m_handleIcon.addFile(QLatin1String(":/icon/layout/scrubhandle-48.png"), QSize(48, 48));
|
||||
m_handleIcon.addFile(QLatin1String(":/icon/layout/scrubhandle-disabled-24.png"), QSize(24, 24), QIcon::Disabled);
|
||||
m_handleIcon.addFile(QLatin1String(":/icon/layout/scrubhandle-disabled-48.png"), QSize(48, 48), QIcon::Disabled);
|
||||
const Utils::Icon bg({{":/icon/layout/scrubbg.png", Utils::Theme::IconsBaseColor}});
|
||||
m_bgWidth = bg.pixmap().width();
|
||||
m_bgHeight = bg.pixmap().height();
|
||||
m_handleWidth = m_bgHeight;
|
||||
m_handleHeight = m_bgHeight;
|
||||
int width = m_bgWidth + m_handleWidth * 2;
|
||||
m_sliderHalfWidth = m_bgWidth / 2;
|
||||
setMinimumWidth(width);
|
||||
setMaximumWidth(width);
|
||||
setProperty("panelwidget", true);
|
||||
setProperty("panelwidget_singlerow", true);
|
||||
setProperty("DSSlider", true);
|
||||
setOrientation(Qt::Horizontal);
|
||||
setFixedWidth(120);
|
||||
setMaxValue(30);
|
||||
}
|
||||
|
||||
void SeekerSlider::paintEvent([[maybe_unused]] QPaintEvent *event)
|
||||
int SeekerSlider::maxValue() const
|
||||
{
|
||||
QPainter painter(this);
|
||||
return maximum();
|
||||
}
|
||||
|
||||
void SeekerSlider::setMaxValue(int maxValue)
|
||||
{
|
||||
QStyleOptionToolBar option;
|
||||
option.rect = rect();
|
||||
option.state = QStyle::State_Horizontal;
|
||||
style()->drawControl(QStyle::CE_ToolBar, &option, &painter, this);
|
||||
}
|
||||
|
||||
int x = rect().width() / 2;
|
||||
int y = rect().height() / 2;
|
||||
|
||||
const QPixmap bg = m_bgIcon.pixmap(QSize(m_bgWidth, m_bgHeight), isEnabled() ? QIcon::Normal : QIcon::Disabled, QIcon::On);
|
||||
painter.drawPixmap(x - m_bgWidth / 2, y - m_bgHeight / 2, bg);
|
||||
|
||||
if (m_moving) {
|
||||
const QPixmap handle = m_handleIcon.pixmap(QSize(m_handleWidth, m_handleHeight), QIcon::Active, QIcon::On);
|
||||
painter.drawPixmap(x - m_handleWidth / 2 + m_sliderPos, y - m_handleHeight / 2, handle);
|
||||
} else {
|
||||
const QPixmap handle = m_handleIcon.pixmap(QSize(m_handleWidth, m_handleHeight), isEnabled() ? QIcon::Normal : QIcon::Disabled, QIcon::On);
|
||||
painter.drawPixmap(x - m_handleWidth / 2, y - m_handleHeight / 2, handle);
|
||||
}
|
||||
maxValue = std::abs(maxValue);
|
||||
setRange(-maxValue, +maxValue);
|
||||
}
|
||||
|
||||
void SeekerSlider::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() != Qt::LeftButton) {
|
||||
QWidget::mousePressEvent(event);
|
||||
if (event->button() != Qt::LeftButton)
|
||||
return;
|
||||
}
|
||||
|
||||
int x = rect().width() / 2;
|
||||
int y = rect().height() / 2;
|
||||
auto pos = event->localPos();
|
||||
if (pos.x() >= x - m_handleWidth / 2 && pos.x() <= x + m_handleWidth / 2
|
||||
&& pos.y() >= y - m_handleHeight / 2 && pos.y() <= y + m_handleHeight / 2) {
|
||||
m_moving = true;
|
||||
m_startPos = pos.x();
|
||||
}
|
||||
QStyleOptionSlider os;
|
||||
initStyleOption(&os);
|
||||
QRect handleRect = style()->subControlRect(QStyle::CC_Slider, &os, QStyle::SC_SliderHandle, this);
|
||||
m_moving = handleRect.contains(event->localPos().toPoint());
|
||||
if (m_moving)
|
||||
QSlider::mousePressEvent(event);
|
||||
else
|
||||
event->setAccepted(false);
|
||||
}
|
||||
|
||||
void SeekerSlider::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (!m_moving) {
|
||||
QWidget::mouseMoveEvent(event);
|
||||
if (!m_moving)
|
||||
return;
|
||||
}
|
||||
|
||||
auto pos = event->localPos();
|
||||
int delta = pos.x() - m_startPos;
|
||||
m_sliderPos = qBound(-m_sliderHalfWidth, delta, m_sliderHalfWidth);
|
||||
delta = m_maxPosition * m_sliderPos / m_sliderHalfWidth;
|
||||
if (delta != m_position) {
|
||||
m_position = delta;
|
||||
Q_EMIT positionChanged();
|
||||
update();
|
||||
}
|
||||
QSlider::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
void SeekerSlider::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (!m_moving) {
|
||||
QWidget::mouseReleaseEvent(event);
|
||||
if (!m_moving)
|
||||
return;
|
||||
}
|
||||
|
||||
setValue(0);
|
||||
m_moving = false;
|
||||
m_position = 0;
|
||||
m_startPos = 0;
|
||||
m_sliderPos = 0;
|
||||
Q_EMIT positionChanged();
|
||||
update();
|
||||
}
|
||||
|
||||
int SeekerSlider::position() const
|
||||
{
|
||||
return m_position;
|
||||
QSlider::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -2,50 +2,30 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QMouseEvent>
|
||||
#include <QIcon>
|
||||
#include <QSlider>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class SeekerSlider : public QWidget
|
||||
class SeekerSlider : public QSlider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SeekerSlider(QWidget *parentWidget);
|
||||
int position() const;
|
||||
int maxPosition() const
|
||||
{
|
||||
return m_maxPosition;
|
||||
}
|
||||
explicit SeekerSlider(QWidget *parent = nullptr);
|
||||
|
||||
void setMaxPosition(int pos)
|
||||
{
|
||||
m_maxPosition = qMax(0, pos);
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void positionChanged();
|
||||
int maxValue() const;
|
||||
void setMaxValue(int maxValue);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event) override;
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
int m_position = 0;
|
||||
int m_startPos = 0;
|
||||
int m_sliderPos = 0;
|
||||
int m_sliderHalfWidth = 0;
|
||||
int m_maxPosition = 30;
|
||||
using QSlider::setMinimum;
|
||||
using QSlider::setMaximum;
|
||||
using QSlider::setRange;
|
||||
|
||||
bool m_moving = false;
|
||||
int m_bgWidth;
|
||||
int m_bgHeight;
|
||||
int m_handleWidth;
|
||||
int m_handleHeight;
|
||||
QIcon m_bgIcon;
|
||||
QIcon m_handleIcon;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -48,7 +48,7 @@ ToolBox::ToolBox(SeekerSlider *seeker, QWidget *parentWidget)
|
||||
m_rightToolBar->setOrientation(Qt::Horizontal);
|
||||
horizontalLayout->addWidget(m_leftToolBar);
|
||||
horizontalLayout->addWidget(stretchToolbar);
|
||||
if (seeker)
|
||||
if (m_seeker)
|
||||
horizontalLayout->addWidget(m_seeker);
|
||||
horizontalLayout->addWidget(m_rightToolBar);
|
||||
}
|
||||
|
@@ -429,6 +429,9 @@ void TimelineToolBar::createRightControls()
|
||||
|
||||
m_scale = new QSlider(this);
|
||||
m_scale->setOrientation(Qt::Horizontal);
|
||||
m_scale->setProperty("DSSlider", true);
|
||||
m_scale->setProperty("panelwidget", true);
|
||||
m_scale->setProperty("panelwidget_singlerow", true);
|
||||
m_scale->setMaximumWidth(200);
|
||||
m_scale->setMinimumWidth(100);
|
||||
m_scale->setMinimum(0);
|
||||
|
Reference in New Issue
Block a user