Initial version of FloatModelEditorBase
Create an initial version of `FloatModelEditorBase`. It is intended to become the base widget for all widgets that manipulate a float model and provides some base functionalities like context menus, edit dialogs, mouse handling, etc. The initial version is a copy of `Knob`. The enum and its values have been suffixed with "Temp" as they will be removed later anyway. Same applies for the function `convertPixmapToGrayScaleTemp`.
This commit is contained in:
217
include/FloatModelEditorBase.h
Normal file
217
include/FloatModelEditorBase.h
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* FloatModelEditorBase.h - Base editor for float models
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2023 Michael Gregorius
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LMMS_GUI_FLOAT_MODEL_EDITOR_BASE_H
|
||||
#define LMMS_GUI_FLOAT_MODEL_EDITOR_BASE_H
|
||||
|
||||
#include <memory>
|
||||
#include <QPixmap>
|
||||
#include <QWidget>
|
||||
#include <QPoint>
|
||||
#include <QTextDocument>
|
||||
|
||||
#include "AutomatableModelView.h"
|
||||
|
||||
|
||||
class QPixmap;
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
|
||||
class SimpleTextFloat;
|
||||
|
||||
enum knobTypesTemp
|
||||
{
|
||||
knobDark_28Temp, knobBright_26Temp, knobSmall_17Temp, knobVintage_32Temp, knobStyledTemp
|
||||
} ;
|
||||
|
||||
|
||||
void convertPixmapToGrayScaleTemp(QPixmap &pixMap);
|
||||
|
||||
class LMMS_EXPORT FloatModelEditorBase : public QWidget, public FloatModelView
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS( knobTypesTemp )
|
||||
|
||||
Q_PROPERTY(float innerRadius READ innerRadius WRITE setInnerRadius)
|
||||
Q_PROPERTY(float outerRadius READ outerRadius WRITE setOuterRadius)
|
||||
|
||||
Q_PROPERTY(float centerPointX READ centerPointX WRITE setCenterPointX)
|
||||
Q_PROPERTY(float centerPointY READ centerPointY WRITE setCenterPointY)
|
||||
|
||||
Q_PROPERTY(float lineWidth READ lineWidth WRITE setLineWidth)
|
||||
|
||||
// Unfortunately, the gradient syntax doesn't create our gradient
|
||||
// correctly so we need to do this:
|
||||
Q_PROPERTY(QColor outerColor READ outerColor WRITE setOuterColor)
|
||||
|
||||
Q_PROPERTY(QColor lineActiveColor MEMBER m_lineActiveColor)
|
||||
Q_PROPERTY(QColor lineInactiveColor MEMBER m_lineInactiveColor)
|
||||
Q_PROPERTY(QColor arcActiveColor MEMBER m_arcActiveColor)
|
||||
Q_PROPERTY(QColor arcInactiveColor MEMBER m_arcInactiveColor)
|
||||
|
||||
mapPropertyFromModel(bool,isVolumeKnob,setVolumeKnob,m_volumeKnob);
|
||||
mapPropertyFromModel(float,volumeRatio,setVolumeRatio,m_volumeRatio);
|
||||
|
||||
Q_PROPERTY(knobTypesTemp knobNum READ knobNum WRITE setknobNum)
|
||||
|
||||
Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor)
|
||||
|
||||
void initUi( const QString & _name ); //!< to be called by ctors
|
||||
void onKnobNumUpdated(); //!< to be called when you updated @a m_knobNum
|
||||
|
||||
public:
|
||||
FloatModelEditorBase( knobTypesTemp _knob_num, QWidget * _parent = nullptr, const QString & _name = QString() );
|
||||
FloatModelEditorBase( QWidget * _parent = nullptr, const QString & _name = QString() ); //!< default ctor
|
||||
FloatModelEditorBase( const FloatModelEditorBase& other ) = delete;
|
||||
|
||||
// TODO: remove
|
||||
inline void setHintText( const QString & _txt_before,
|
||||
const QString & _txt_after )
|
||||
{
|
||||
setDescription( _txt_before );
|
||||
setUnit( _txt_after );
|
||||
}
|
||||
void setLabel( const QString & txt );
|
||||
void setHtmlLabel( const QString &htmltxt );
|
||||
|
||||
void setTotalAngle( float angle );
|
||||
|
||||
// Begin styled knob accessors
|
||||
float innerRadius() const;
|
||||
void setInnerRadius( float r );
|
||||
|
||||
float outerRadius() const;
|
||||
void setOuterRadius( float r );
|
||||
|
||||
knobTypesTemp knobNum() const;
|
||||
void setknobNum( knobTypesTemp k );
|
||||
|
||||
QPointF centerPoint() const;
|
||||
float centerPointX() const;
|
||||
void setCenterPointX( float c );
|
||||
float centerPointY() const;
|
||||
void setCenterPointY( float c );
|
||||
|
||||
float lineWidth() const;
|
||||
void setLineWidth( float w );
|
||||
|
||||
QColor outerColor() const;
|
||||
void setOuterColor( const QColor & c );
|
||||
|
||||
QColor textColor() const;
|
||||
void setTextColor( const QColor & c );
|
||||
|
||||
|
||||
signals:
|
||||
void sliderPressed();
|
||||
void sliderReleased();
|
||||
void sliderMoved( float value );
|
||||
|
||||
|
||||
protected:
|
||||
void contextMenuEvent( QContextMenuEvent * _me ) override;
|
||||
void dragEnterEvent( QDragEnterEvent * _dee ) override;
|
||||
void dropEvent( QDropEvent * _de ) override;
|
||||
void focusOutEvent( QFocusEvent * _fe ) override;
|
||||
void mousePressEvent( QMouseEvent * _me ) override;
|
||||
void mouseReleaseEvent( QMouseEvent * _me ) override;
|
||||
void mouseMoveEvent( QMouseEvent * _me ) override;
|
||||
void mouseDoubleClickEvent( QMouseEvent * _me ) override;
|
||||
void paintEvent( QPaintEvent * _me ) override;
|
||||
void wheelEvent( QWheelEvent * _me ) override;
|
||||
void changeEvent(QEvent * ev) override;
|
||||
|
||||
virtual float getValue( const QPoint & _p );
|
||||
|
||||
private slots:
|
||||
virtual void enterValue();
|
||||
void friendlyUpdate();
|
||||
void toggleScale();
|
||||
|
||||
private:
|
||||
virtual QString displayValue() const;
|
||||
|
||||
void doConnections() override;
|
||||
|
||||
QLineF calculateLine( const QPointF & _mid, float _radius,
|
||||
float _innerRadius = 1) const;
|
||||
|
||||
void drawKnob( QPainter * _p );
|
||||
void setPosition( const QPoint & _p );
|
||||
bool updateAngle();
|
||||
|
||||
int angleFromValue( float value, float minValue, float maxValue, float totalAngle ) const
|
||||
{
|
||||
return static_cast<int>( ( value - 0.5 * ( minValue + maxValue ) ) / ( maxValue - minValue ) * m_totalAngle ) % 360;
|
||||
}
|
||||
|
||||
inline float pageSize() const
|
||||
{
|
||||
return ( model()->maxValue() - model()->minValue() ) / 100.0f;
|
||||
}
|
||||
|
||||
|
||||
static SimpleTextFloat * s_textFloat;
|
||||
|
||||
QString m_label;
|
||||
bool m_isHtmlLabel;
|
||||
QTextDocument* m_tdRenderer;
|
||||
|
||||
std::unique_ptr<QPixmap> m_knobPixmap;
|
||||
BoolModel m_volumeKnob;
|
||||
FloatModel m_volumeRatio;
|
||||
|
||||
QPoint m_lastMousePos; //!< mouse position in last mouseMoveEvent
|
||||
float m_leftOver;
|
||||
bool m_buttonPressed;
|
||||
|
||||
float m_totalAngle;
|
||||
int m_angle;
|
||||
QImage m_cache;
|
||||
|
||||
// Styled knob stuff, could break out
|
||||
QPointF m_centerPoint;
|
||||
float m_innerRadius;
|
||||
float m_outerRadius;
|
||||
float m_lineWidth;
|
||||
QColor m_outerColor;
|
||||
|
||||
QColor m_lineActiveColor;
|
||||
QColor m_lineInactiveColor;
|
||||
QColor m_arcActiveColor;
|
||||
QColor m_arcInactiveColor;
|
||||
|
||||
QColor m_textColor;
|
||||
|
||||
knobTypesTemp m_knobNum;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
|
||||
#endif // LMMS_GUI_FLOAT_MODEL_EDITOR_BASE_H
|
||||
@@ -101,6 +101,7 @@ SET(LMMS_SRCS
|
||||
gui/widgets/ComboBox.cpp
|
||||
gui/widgets/CustomTextKnob.cpp
|
||||
gui/widgets/Fader.cpp
|
||||
gui/widgets/FloatModelEditorBase.cpp
|
||||
gui/widgets/Graph.cpp
|
||||
gui/widgets/GroupBox.cpp
|
||||
gui/widgets/Knob.cpp
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include "LadspaBase.h"
|
||||
|
||||
#include "BarModelEditor.h"
|
||||
// TODO Only for testing! Remove!
|
||||
#include "FloatModelEditorBase.h"
|
||||
#include "LedCheckBox.h"
|
||||
#include "TempoSyncKnob.h"
|
||||
|
||||
@@ -65,7 +67,15 @@ QWidget * LadspaWidgetFactory::createWidget(LadspaControl * ladspaControl, QWidg
|
||||
knob->setModel(ladspaControl->knobModel());
|
||||
knob->setLabel(name);
|
||||
break;*/
|
||||
return new BarModelEditor(name, ladspaControl->knobModel(), parent);
|
||||
{
|
||||
FloatModelEditorBase * fme = new FloatModelEditorBase(knobBright_26Temp, parent, name);
|
||||
fme->setModel(ladspaControl->knobModel());
|
||||
fme->setLabel(name);
|
||||
fme->setHintText(QObject::tr("Value:"), "");
|
||||
return fme;
|
||||
}
|
||||
// FloatModelEditorBase
|
||||
//return new BarModelEditor(name, ladspaControl->knobModel(), parent);
|
||||
|
||||
case TIME:
|
||||
knob = new TempoSyncKnob(knobBright_26, parent, name);
|
||||
|
||||
873
src/gui/widgets/FloatModelEditorBase.cpp
Normal file
873
src/gui/widgets/FloatModelEditorBase.cpp
Normal file
@@ -0,0 +1,873 @@
|
||||
/*
|
||||
* FloatModelEditorBase.cpp - Base editor for float models
|
||||
*
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2023 Michael Gregorius
|
||||
*
|
||||
* This file is part of LMMS - https://lmms.io
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public
|
||||
* License along with this program (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "FloatModelEditorBase.h"
|
||||
|
||||
#include <memory>
|
||||
#include <QApplication>
|
||||
#include <QFontMetrics>
|
||||
#include <QInputDialog>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
|
||||
#ifndef __USE_XOPEN
|
||||
#define __USE_XOPEN
|
||||
#endif
|
||||
|
||||
#include "lmms_math.h"
|
||||
#include "CaptionMenu.h"
|
||||
#include "ConfigManager.h"
|
||||
#include "ControllerConnection.h"
|
||||
#include "DeprecationHelper.h"
|
||||
#include "embed.h"
|
||||
#include "gui_templates.h"
|
||||
#include "GuiApplication.h"
|
||||
#include "LocaleHelper.h"
|
||||
#include "MainWindow.h"
|
||||
#include "ProjectJournal.h"
|
||||
#include "SimpleTextFloat.h"
|
||||
#include "StringPairDrag.h"
|
||||
|
||||
|
||||
namespace lmms::gui
|
||||
{
|
||||
|
||||
SimpleTextFloat * FloatModelEditorBase::s_textFloat = nullptr;
|
||||
|
||||
|
||||
|
||||
|
||||
FloatModelEditorBase::FloatModelEditorBase( knobTypesTemp _knob_num, QWidget * _parent, const QString & _name ) :
|
||||
QWidget( _parent ),
|
||||
FloatModelView( new FloatModel( 0, 0, 0, 1, nullptr, _name, true ), this ),
|
||||
m_label( "" ),
|
||||
m_isHtmlLabel(false),
|
||||
m_tdRenderer(nullptr),
|
||||
m_volumeKnob( false ),
|
||||
m_volumeRatio( 100.0, 0.0, 1000000.0 ),
|
||||
m_buttonPressed( false ),
|
||||
m_angle( -10 ),
|
||||
m_lineWidth( 0 ),
|
||||
m_textColor( 255, 255, 255 ),
|
||||
m_knobNum( _knob_num )
|
||||
{
|
||||
initUi( _name );
|
||||
}
|
||||
|
||||
FloatModelEditorBase::FloatModelEditorBase( QWidget * _parent, const QString & _name ) :
|
||||
FloatModelEditorBase( knobBright_26Temp, _parent, _name )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::initUi( const QString & _name )
|
||||
{
|
||||
if( s_textFloat == nullptr )
|
||||
{
|
||||
s_textFloat = new SimpleTextFloat;
|
||||
}
|
||||
|
||||
setWindowTitle( _name );
|
||||
|
||||
onKnobNumUpdated();
|
||||
setTotalAngle( 270.0f );
|
||||
setInnerRadius( 1.0f );
|
||||
setOuterRadius( 10.0f );
|
||||
setFocusPolicy( Qt::ClickFocus );
|
||||
|
||||
// This is a workaround to enable style sheets for knobs which are not styled knobs.
|
||||
//
|
||||
// It works as follows: the palette colors that are assigned as the line color previously
|
||||
// had been hard coded in the drawKnob method for the different knob types. Now the
|
||||
// drawKnob method uses the line color to draw the lines. By assigning the palette colors
|
||||
// as the line colors here the knob lines will be drawn in this color unless the stylesheet
|
||||
// overrides that color.
|
||||
switch (knobNum())
|
||||
{
|
||||
case knobSmall_17Temp:
|
||||
case knobBright_26Temp:
|
||||
case knobDark_28Temp:
|
||||
m_lineActiveColor = QApplication::palette().color(QPalette::Active, QPalette::WindowText);
|
||||
m_arcActiveColor = QColor(QApplication::palette().color(
|
||||
QPalette::Active, QPalette::WindowText));
|
||||
m_arcActiveColor.setAlpha(70);
|
||||
break;
|
||||
case knobVintage_32Temp:
|
||||
m_lineActiveColor = QApplication::palette().color(QPalette::Active, QPalette::Shadow);
|
||||
m_arcActiveColor = QColor(QApplication::palette().color(
|
||||
QPalette::Active, QPalette::Shadow));
|
||||
m_arcActiveColor.setAlpha(70);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
doConnections();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::onKnobNumUpdated()
|
||||
{
|
||||
if( m_knobNum != knobStyledTemp )
|
||||
{
|
||||
QString knobFilename;
|
||||
switch (m_knobNum)
|
||||
{
|
||||
case knobDark_28Temp:
|
||||
knobFilename = "knob01";
|
||||
break;
|
||||
case knobBright_26Temp:
|
||||
knobFilename = "knob02";
|
||||
break;
|
||||
case knobSmall_17Temp:
|
||||
knobFilename = "knob03";
|
||||
break;
|
||||
case knobVintage_32Temp:
|
||||
knobFilename = "knob05";
|
||||
break;
|
||||
case knobStyledTemp: // only here to stop the compiler from complaining
|
||||
break;
|
||||
}
|
||||
|
||||
// If knobFilename is still empty here we should get the fallback pixmap of size 1x1
|
||||
m_knobPixmap = std::make_unique<QPixmap>(QPixmap(embed::getIconPixmap(knobFilename.toUtf8().constData())));
|
||||
if (!this->isEnabled())
|
||||
{
|
||||
convertPixmapToGrayScaleTemp(*m_knobPixmap.get());
|
||||
}
|
||||
setFixedSize( m_knobPixmap->width(), m_knobPixmap->height() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::setLabel( const QString & txt )
|
||||
{
|
||||
m_label = txt;
|
||||
m_isHtmlLabel = false;
|
||||
if( m_knobPixmap )
|
||||
{
|
||||
setFixedSize(qMax<int>( m_knobPixmap->width(),
|
||||
horizontalAdvance(QFontMetrics(pointSizeF(font(), 6.5)), m_label)),
|
||||
m_knobPixmap->height() + 10);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
void FloatModelEditorBase::setHtmlLabel(const QString &htmltxt)
|
||||
{
|
||||
m_label = htmltxt;
|
||||
m_isHtmlLabel = true;
|
||||
// Put the rendered HTML content into cache
|
||||
if (!m_tdRenderer)
|
||||
{
|
||||
m_tdRenderer = new QTextDocument(this);
|
||||
}
|
||||
|
||||
m_tdRenderer->setHtml(QString("<span style=\"color:%1;\">%2</span>").arg(textColor().name(), m_label));
|
||||
|
||||
if (m_knobPixmap)
|
||||
{
|
||||
setFixedSize(m_knobPixmap->width(),
|
||||
m_knobPixmap->height() + 15);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::setTotalAngle( float angle )
|
||||
{
|
||||
if( angle < 10.0 )
|
||||
{
|
||||
m_totalAngle = 10.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_totalAngle = angle;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float FloatModelEditorBase::innerRadius() const
|
||||
{
|
||||
return m_innerRadius;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::setInnerRadius( float r )
|
||||
{
|
||||
m_innerRadius = r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
float FloatModelEditorBase::outerRadius() const
|
||||
{
|
||||
return m_outerRadius;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::setOuterRadius( float r )
|
||||
{
|
||||
m_outerRadius = r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
knobTypesTemp FloatModelEditorBase::knobNum() const
|
||||
{
|
||||
return m_knobNum;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::setknobNum( knobTypesTemp k )
|
||||
{
|
||||
if( m_knobNum != k )
|
||||
{
|
||||
m_knobNum = k;
|
||||
onKnobNumUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QPointF FloatModelEditorBase::centerPoint() const
|
||||
{
|
||||
return m_centerPoint;
|
||||
}
|
||||
|
||||
|
||||
|
||||
float FloatModelEditorBase::centerPointX() const
|
||||
{
|
||||
return m_centerPoint.x();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::setCenterPointX( float c )
|
||||
{
|
||||
m_centerPoint.setX( c );
|
||||
}
|
||||
|
||||
|
||||
|
||||
float FloatModelEditorBase::centerPointY() const
|
||||
{
|
||||
return m_centerPoint.y();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::setCenterPointY( float c )
|
||||
{
|
||||
m_centerPoint.setY( c );
|
||||
}
|
||||
|
||||
|
||||
|
||||
float FloatModelEditorBase::lineWidth() const
|
||||
{
|
||||
return m_lineWidth;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::setLineWidth( float w )
|
||||
{
|
||||
m_lineWidth = w;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QColor FloatModelEditorBase::outerColor() const
|
||||
{
|
||||
return m_outerColor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::setOuterColor( const QColor & c )
|
||||
{
|
||||
m_outerColor = c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QColor FloatModelEditorBase::textColor() const
|
||||
{
|
||||
return m_textColor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::setTextColor( const QColor & c )
|
||||
{
|
||||
m_textColor = c;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QLineF FloatModelEditorBase::calculateLine( const QPointF & _mid, float _radius, float _innerRadius ) const
|
||||
{
|
||||
const float rarc = m_angle * F_PI / 180.0;
|
||||
const float ca = cos( rarc );
|
||||
const float sa = -sin( rarc );
|
||||
|
||||
return QLineF( _mid.x() - sa*_innerRadius, _mid.y() - ca*_innerRadius,
|
||||
_mid.x() - sa*_radius, _mid.y() - ca*_radius );
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool FloatModelEditorBase::updateAngle()
|
||||
{
|
||||
int angle = 0;
|
||||
if( model() && model()->maxValue() != model()->minValue() )
|
||||
{
|
||||
angle = angleFromValue( model()->inverseScaledValue( model()->value() ), model()->minValue(), model()->maxValue(), m_totalAngle );
|
||||
}
|
||||
if( qAbs( angle - m_angle ) > 0 )
|
||||
{
|
||||
m_angle = angle;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::drawKnob( QPainter * _p )
|
||||
{
|
||||
bool enabled = this->isEnabled();
|
||||
QColor currentArcColor = enabled ? m_arcActiveColor : m_arcInactiveColor;
|
||||
QColor currentLineColor = enabled ? m_lineActiveColor : m_lineInactiveColor;
|
||||
|
||||
if( updateAngle() == false && !m_cache.isNull() )
|
||||
{
|
||||
_p->drawImage( 0, 0, m_cache );
|
||||
return;
|
||||
}
|
||||
|
||||
m_cache = QImage( size(), QImage::Format_ARGB32 );
|
||||
m_cache.fill( qRgba( 0, 0, 0, 0 ) );
|
||||
|
||||
QPainter p( &m_cache );
|
||||
|
||||
QPoint mid;
|
||||
|
||||
if( m_knobNum == knobStyledTemp )
|
||||
{
|
||||
p.setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
// Perhaps this can move to setOuterRadius()
|
||||
if( m_outerColor.isValid() )
|
||||
{
|
||||
QRadialGradient gradient( centerPoint(), outerRadius() );
|
||||
gradient.setColorAt( 0.4, _p->pen().brush().color() );
|
||||
gradient.setColorAt( 1, m_outerColor );
|
||||
|
||||
p.setPen( QPen( gradient, lineWidth(),
|
||||
Qt::SolidLine, Qt::RoundCap ) );
|
||||
}
|
||||
else {
|
||||
QPen pen = p.pen();
|
||||
pen.setWidth( (int) lineWidth() );
|
||||
pen.setCapStyle( Qt::RoundCap );
|
||||
|
||||
p.setPen( pen );
|
||||
}
|
||||
|
||||
p.drawLine( calculateLine( centerPoint(), outerRadius(),
|
||||
innerRadius() ) );
|
||||
p.end();
|
||||
_p->drawImage( 0, 0, m_cache );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Old-skool knobs
|
||||
const float radius = m_knobPixmap->width() / 2.0f - 1;
|
||||
mid = QPoint( width() / 2, m_knobPixmap->height() / 2 );
|
||||
|
||||
p.drawPixmap( static_cast<int>(
|
||||
width() / 2 - m_knobPixmap->width() / 2 ), 0,
|
||||
*m_knobPixmap );
|
||||
|
||||
p.setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
const int centerAngle = angleFromValue( model()->inverseScaledValue( model()->centerValue() ), model()->minValue(), model()->maxValue(), m_totalAngle );
|
||||
|
||||
const int arcLineWidth = 2;
|
||||
const int arcRectSize = m_knobPixmap->width() - arcLineWidth;
|
||||
|
||||
p.setPen(QPen(currentArcColor, 2));
|
||||
p.drawArc( mid.x() - arcRectSize/2, 1, arcRectSize, arcRectSize, 315*16, 16*m_totalAngle );
|
||||
|
||||
p.setPen(QPen(currentLineColor, 2));
|
||||
switch( m_knobNum )
|
||||
{
|
||||
case knobSmall_17Temp:
|
||||
{
|
||||
p.drawLine( calculateLine( mid, radius-2 ) );
|
||||
break;
|
||||
}
|
||||
case knobBright_26Temp:
|
||||
{
|
||||
p.drawLine( calculateLine( mid, radius-5 ) );
|
||||
break;
|
||||
}
|
||||
case knobDark_28Temp:
|
||||
{
|
||||
const float rb = qMax<float>( ( radius - 10 ) / 3.0,
|
||||
0.0 );
|
||||
const float re = qMax<float>( ( radius - 4 ), 0.0 );
|
||||
QLineF ln = calculateLine( mid, re, rb );
|
||||
ln.translate( 1, 1 );
|
||||
p.drawLine( ln );
|
||||
break;
|
||||
}
|
||||
case knobVintage_32Temp:
|
||||
{
|
||||
p.drawLine( calculateLine( mid, radius-2, 2 ) );
|
||||
break;
|
||||
}
|
||||
case knobStyledTemp:
|
||||
break;
|
||||
}
|
||||
|
||||
p.drawArc( mid.x() - arcRectSize/2, 1, arcRectSize, arcRectSize, (90-centerAngle)*16, -16*(m_angle-centerAngle) );
|
||||
|
||||
p.end();
|
||||
|
||||
_p->drawImage( 0, 0, m_cache );
|
||||
}
|
||||
|
||||
float FloatModelEditorBase::getValue( const QPoint & _p )
|
||||
{
|
||||
float value;
|
||||
|
||||
// knob value increase is linear to mouse movement
|
||||
value = .4f * _p.y();
|
||||
|
||||
// if shift pressed we want slower movement
|
||||
if( getGUI()->mainWindow()->isShiftPressed() )
|
||||
{
|
||||
value /= 4.0f;
|
||||
value = qBound( -4.0f, value, 4.0f );
|
||||
}
|
||||
return value * pageSize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::contextMenuEvent( QContextMenuEvent * )
|
||||
{
|
||||
// for the case, the user clicked right while pressing left mouse-
|
||||
// button, the context-menu appears while mouse-cursor is still hidden
|
||||
// and it isn't shown again until user does something which causes
|
||||
// an QApplication::restoreOverrideCursor()-call...
|
||||
mouseReleaseEvent( nullptr );
|
||||
|
||||
CaptionMenu contextMenu( model()->displayName(), this );
|
||||
addDefaultActions( &contextMenu );
|
||||
contextMenu.addAction( QPixmap(),
|
||||
model()->isScaleLogarithmic() ? tr( "Set linear" ) : tr( "Set logarithmic" ),
|
||||
this, SLOT(toggleScale()));
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.exec( QCursor::pos() );
|
||||
}
|
||||
|
||||
|
||||
void FloatModelEditorBase::toggleScale()
|
||||
{
|
||||
model()->setScaleLogarithmic( ! model()->isScaleLogarithmic() );
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::dragEnterEvent( QDragEnterEvent * _dee )
|
||||
{
|
||||
StringPairDrag::processDragEnterEvent( _dee, "float_value,"
|
||||
"automatable_model" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::dropEvent( QDropEvent * _de )
|
||||
{
|
||||
QString type = StringPairDrag::decodeKey( _de );
|
||||
QString val = StringPairDrag::decodeValue( _de );
|
||||
if( type == "float_value" )
|
||||
{
|
||||
model()->setValue( LocaleHelper::toFloat(val) );
|
||||
_de->accept();
|
||||
}
|
||||
else if( type == "automatable_model" )
|
||||
{
|
||||
auto mod = dynamic_cast<AutomatableModel*>(Engine::projectJournal()->journallingObject(val.toInt()));
|
||||
if( mod != nullptr )
|
||||
{
|
||||
AutomatableModel::linkModels( model(), mod );
|
||||
mod->setValue( model()->value() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton &&
|
||||
! ( _me->modifiers() & Qt::ControlModifier ) &&
|
||||
! ( _me->modifiers() & Qt::ShiftModifier ) )
|
||||
{
|
||||
AutomatableModel *thisModel = model();
|
||||
if( thisModel )
|
||||
{
|
||||
thisModel->addJournalCheckPoint();
|
||||
thisModel->saveJournallingState( false );
|
||||
}
|
||||
|
||||
const QPoint & p = _me->pos();
|
||||
m_lastMousePos = p;
|
||||
m_leftOver = 0.0f;
|
||||
|
||||
emit sliderPressed();
|
||||
|
||||
s_textFloat->setText( displayValue() );
|
||||
s_textFloat->moveGlobal( this,
|
||||
QPoint( width() + 2, 0 ) );
|
||||
s_textFloat->show();
|
||||
m_buttonPressed = true;
|
||||
}
|
||||
else if( _me->button() == Qt::LeftButton &&
|
||||
(_me->modifiers() & Qt::ShiftModifier) )
|
||||
{
|
||||
new StringPairDrag( "float_value",
|
||||
QString::number( model()->value() ),
|
||||
QPixmap(), this );
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatModelView::mousePressEvent( _me );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( m_buttonPressed && _me->pos() != m_lastMousePos )
|
||||
{
|
||||
// knob position is changed depending on last mouse position
|
||||
setPosition( _me->pos() - m_lastMousePos );
|
||||
emit sliderMoved( model()->value() );
|
||||
// original position for next time is current position
|
||||
m_lastMousePos = _me->pos();
|
||||
}
|
||||
s_textFloat->setText( displayValue() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::mouseReleaseEvent( QMouseEvent* event )
|
||||
{
|
||||
if( event && event->button() == Qt::LeftButton )
|
||||
{
|
||||
AutomatableModel *thisModel = model();
|
||||
if( thisModel )
|
||||
{
|
||||
thisModel->restoreJournallingState();
|
||||
}
|
||||
}
|
||||
|
||||
m_buttonPressed = false;
|
||||
|
||||
emit sliderReleased();
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
s_textFloat->hide();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::focusOutEvent( QFocusEvent * _fe )
|
||||
{
|
||||
// make sure we don't loose mouse release event
|
||||
mouseReleaseEvent( nullptr );
|
||||
QWidget::focusOutEvent( _fe );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::mouseDoubleClickEvent( QMouseEvent * )
|
||||
{
|
||||
enterValue();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::paintEvent( QPaintEvent * _me )
|
||||
{
|
||||
QPainter p( this );
|
||||
|
||||
drawKnob( &p );
|
||||
if( !m_label.isEmpty() )
|
||||
{
|
||||
if (!m_isHtmlLabel)
|
||||
{
|
||||
p.setFont(pointSizeF(p.font(), 6.5));
|
||||
p.setPen(textColor());
|
||||
p.drawText(width() / 2 -
|
||||
horizontalAdvance(p.fontMetrics(), m_label) / 2,
|
||||
height() - 2, m_label);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tdRenderer->setDefaultFont(pointSizeF(p.font(), 6.5));
|
||||
p.translate((width() - m_tdRenderer->idealWidth()) / 2, (height() - m_tdRenderer->pageSize().height()) / 2);
|
||||
m_tdRenderer->drawContents(&p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::wheelEvent(QWheelEvent * we)
|
||||
{
|
||||
we->accept();
|
||||
const float stepMult = model()->range() / 2000 / model()->step<float>();
|
||||
const int inc = ((we->angleDelta().y() > 0 ) ? 1 : -1) * ((stepMult < 1 ) ? 1 : stepMult);
|
||||
model()->incValue( inc );
|
||||
|
||||
|
||||
s_textFloat->setText( displayValue() );
|
||||
s_textFloat->moveGlobal( this, QPoint( width() + 2, 0 ) );
|
||||
s_textFloat->setVisibilityTimeOut( 1000 );
|
||||
|
||||
emit sliderMoved( model()->value() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::setPosition( const QPoint & _p )
|
||||
{
|
||||
const float value = getValue( _p ) + m_leftOver;
|
||||
const auto step = model()->step<float>();
|
||||
const float oldValue = model()->value();
|
||||
|
||||
|
||||
|
||||
if( model()->isScaleLogarithmic() ) // logarithmic code
|
||||
{
|
||||
const float pos = model()->minValue() < 0
|
||||
? oldValue / qMax( qAbs( model()->maxValue() ), qAbs( model()->minValue() ) )
|
||||
: ( oldValue - model()->minValue() ) / model()->range();
|
||||
const float ratio = 0.1f + qAbs( pos ) * 15.f;
|
||||
float newValue = value * ratio;
|
||||
if( qAbs( newValue ) >= step )
|
||||
{
|
||||
float roundedValue = qRound( ( oldValue - value ) / step ) * step;
|
||||
model()->setValue( roundedValue );
|
||||
m_leftOver = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_leftOver = value;
|
||||
}
|
||||
}
|
||||
|
||||
else // linear code
|
||||
{
|
||||
if( qAbs( value ) >= step )
|
||||
{
|
||||
float roundedValue = qRound( ( oldValue - value ) / step ) * step;
|
||||
model()->setValue( roundedValue );
|
||||
m_leftOver = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_leftOver = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::enterValue()
|
||||
{
|
||||
bool ok;
|
||||
float new_val;
|
||||
|
||||
if( isVolumeKnob() &&
|
||||
ConfigManager::inst()->value( "app", "displaydbfs" ).toInt() )
|
||||
{
|
||||
new_val = QInputDialog::getDouble(
|
||||
this, tr( "Set value" ),
|
||||
tr( "Please enter a new value between "
|
||||
"-96.0 dBFS and 6.0 dBFS:" ),
|
||||
ampToDbfs( model()->getRoundedValue() / 100.0 ),
|
||||
-96.0, 6.0, model()->getDigitCount(), &ok );
|
||||
if( new_val <= -96.0 )
|
||||
{
|
||||
new_val = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_val = dbfsToAmp( new_val ) * 100.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
new_val = QInputDialog::getDouble(
|
||||
this, tr( "Set value" ),
|
||||
tr( "Please enter a new value between "
|
||||
"%1 and %2:" ).
|
||||
arg( model()->minValue() ).
|
||||
arg( model()->maxValue() ),
|
||||
model()->getRoundedValue(),
|
||||
model()->minValue(),
|
||||
model()->maxValue(), model()->getDigitCount(), &ok );
|
||||
}
|
||||
|
||||
if( ok )
|
||||
{
|
||||
model()->setValue( new_val );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::friendlyUpdate()
|
||||
{
|
||||
if (model() && (model()->controllerConnection() == nullptr ||
|
||||
model()->controllerConnection()->getController()->frequentUpdates() == false ||
|
||||
Controller::runningFrames() % (256*4) == 0))
|
||||
{
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QString FloatModelEditorBase::displayValue() const
|
||||
{
|
||||
if( isVolumeKnob() &&
|
||||
ConfigManager::inst()->value( "app", "displaydbfs" ).toInt() )
|
||||
{
|
||||
return m_description.trimmed() + QString( " %1 dBFS" ).
|
||||
arg( ampToDbfs( model()->getRoundedValue() / volumeRatio() ),
|
||||
3, 'f', 2 );
|
||||
}
|
||||
return m_description.trimmed() + QString( " %1" ).
|
||||
arg( model()->getRoundedValue() ) + m_unit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FloatModelEditorBase::doConnections()
|
||||
{
|
||||
if( model() != nullptr )
|
||||
{
|
||||
QObject::connect( model(), SIGNAL(dataChanged()),
|
||||
this, SLOT(friendlyUpdate()));
|
||||
|
||||
QObject::connect( model(), SIGNAL(propertiesChanged()),
|
||||
this, SLOT(update()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FloatModelEditorBase::changeEvent(QEvent * ev)
|
||||
{
|
||||
if (ev->type() == QEvent::EnabledChange)
|
||||
{
|
||||
onKnobNumUpdated();
|
||||
if (!m_label.isEmpty())
|
||||
{
|
||||
setLabel(m_label);
|
||||
}
|
||||
m_cache = QImage();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void convertPixmapToGrayScaleTemp(QPixmap& pixMap)
|
||||
{
|
||||
QImage temp = pixMap.toImage().convertToFormat(QImage::Format_ARGB32);
|
||||
for (int i = 0; i < temp.height(); ++i)
|
||||
{
|
||||
for (int j = 0; j < temp.width(); ++j)
|
||||
{
|
||||
const auto pix = temp.pixelColor(i, j);
|
||||
const auto gscale = 0.2126 * pix.redF() + 0.7152 * pix.greenF() + 0.0722 * pix.blueF();
|
||||
const auto pixGray = QColor::fromRgbF(gscale, gscale, gscale, pix.alphaF());
|
||||
temp.setPixelColor(i, j, pixGray);
|
||||
}
|
||||
}
|
||||
pixMap.convertFromImage(temp);
|
||||
}
|
||||
|
||||
|
||||
} // namespace lmms::gui
|
||||
Reference in New Issue
Block a user