Radium Engine  1.5.20
Loading...
Searching...
No Matches
ControlPanel.cpp
1#include <Gui/Widgets/ControlPanel.hpp>
2
3#include <Gui/Widgets/MatrixEditor.hpp>
4
5#include <PowerSlider/PowerSlider.hpp>
6
7#include <QCheckBox>
8#include <QColorDialog>
9#include <QComboBox>
10#include <QDialog>
11#include <QFileDialog>
12#include <QLabel>
13#include <QPlainTextEdit>
14#include <QPushButton>
15#include <QSlider>
16#include <QVBoxLayout>
17
18namespace Ra::Gui::Widgets {
19
20ControlPanel::ControlPanel( const std::string& name, bool hline, QWidget* parent ) :
21 QFrame( parent ) {
22 setObjectName( name.c_str() );
23 m_mainLayout = new QVBoxLayout();
24 m_mainLayout->setObjectName( "main layout" );
25 m_contentLayout = new QGridLayout();
26 m_contentLayout->setObjectName( "first content layout" );
27
28 if ( !name.empty() ) {
29 auto panelName = new QLabel();
30 panelName->setText( name.c_str() );
31 m_mainLayout->addWidget( panelName );
32 }
33 if ( hline ) {
34 QFrame* line;
35 line = new QFrame();
36 line->setFrameShape( QFrame::HLine );
37 line->setFrameShadow( QFrame::Sunken );
38 m_mainLayout->addWidget( line );
39 }
40
41 m_mainLayout->addLayout( m_contentLayout );
42
43 setLayout( m_mainLayout );
44}
45
46// Method to populate the panel
47void ControlPanel::addOption( const std::string& name,
48 std::function<void( bool )> callback,
49 bool set,
50 const std::string& tooltip ) {
51 auto label = new QLabel( name.c_str() );
52 auto button = new QCheckBox();
53 button->setAutoExclusive( false );
54 button->setChecked( set );
55 if ( !tooltip.empty() ) {
56 auto tooltipString =
57 QString( "<qt>%1</qt>" ).arg( QString( tooltip.c_str() ).toHtmlEscaped() );
58 label->setToolTip( tooltipString );
59 button->setToolTip( tooltipString );
60 }
61 connect( button, &QCheckBox::stateChanged, std::move( callback ) );
62
63 auto index = m_contentLayout->rowCount();
64 m_contentLayout->addWidget( label, index, 0 );
65 m_contentLayout->addWidget( button, index, 1 );
66}
67
68void ControlPanel::addLabel( const std::string& text ) {
69 auto label = new QLabel( text.c_str() );
70 auto index = m_contentLayout->rowCount();
71 m_contentLayout->addWidget( label, index, 0, 1, -1 );
72}
73
74void ControlPanel::addButton( const std::string& name,
75 std::function<void()> callback,
76 const std::string& tooltip ) {
77 auto button = new QPushButton( name.c_str(), nullptr );
78 if ( !tooltip.empty() ) {
79 button->setToolTip(
80 QString( "<qt>%1</qt>" ).arg( QString( tooltip.c_str() ).toHtmlEscaped() ) );
81 }
82
83 connect( button, &QPushButton::clicked, std::move( callback ) );
84
85 auto index = m_contentLayout->rowCount();
86 m_contentLayout->addWidget( button, index, 1, 1, -1 );
87}
88
89void ControlPanel::addSliderInput( const std::string& name,
90 std::function<void( int )> callback,
91 int initial,
92 int min,
93 int max,
94 const std::string& tooltip ) {
95 auto inputLabel = new QLabel( tr( name.c_str() ) );
96 auto sliderLayout = new QHBoxLayout();
97 auto inputField = new QSlider( Qt::Horizontal );
98 if ( !tooltip.empty() ) {
99 auto tooltipString =
100 QString( "<qt>%1</qt>" ).arg( QString( tooltip.c_str() ).toHtmlEscaped() );
101 inputLabel->setToolTip( tooltipString );
102 inputField->setToolTip( tooltipString );
103 }
104 auto spinbox = new QSpinBox();
105 inputField->setRange( min, max );
106 inputField->setValue( initial );
107 inputField->setTickPosition( QSlider::TicksAbove );
108 inputField->setTickInterval( 1 );
109 inputField->setFocusPolicy( Qt::StrongFocus );
110 spinbox->setRange( min, max );
111 spinbox->setValue( initial );
112 connect( inputField, &QSlider::valueChanged, spinbox, &QSpinBox::setValue );
113 connect( spinbox, &QSpinBox::valueChanged, inputField, &QSlider::setValue );
114 connect( inputField, &QSlider::valueChanged, std::move( callback ) );
115 sliderLayout->addWidget( inputField );
116 sliderLayout->addWidget( spinbox );
117
118 auto index = m_contentLayout->rowCount();
119 m_contentLayout->addWidget( inputLabel, index, 0 );
120 m_contentLayout->addLayout( sliderLayout, index, 1 );
121}
122
123void ControlPanel::addPowerSliderInput( const std::string& name,
124 std::function<void( double )> callback,
125 double initial,
126 double min,
127 double max,
128 const std::string& tooltip ) {
129 auto inputLabel = new QLabel( tr( name.c_str() ) );
130 auto inputField = new PowerSlider();
131 if ( !tooltip.empty() ) {
132 auto tooltipString =
133 QString( "<qt>%1</qt>" ).arg( QString( tooltip.c_str() ).toHtmlEscaped() );
134 inputLabel->setToolTip( tooltipString );
135 inputField->setToolTip( tooltipString );
136 }
137 inputField->setObjectName( name.c_str() );
138 inputField->setRange( min, max );
139 inputField->setValue( initial );
140 inputField->setSingleStep( 0.01 );
141 connect( inputField, &PowerSlider::valueChanged, std::move( callback ) );
142
143 auto index = m_contentLayout->rowCount();
144 m_contentLayout->addWidget( inputLabel, index, 0 );
145 m_contentLayout->addWidget( inputField, index, 1 );
146}
147
148void ControlPanel::addMatrixInput( const std::string& name,
149 std::function<void( const Ra::Core::MatrixN& )> callback,
150 const Ra::Core::MatrixN& initial,
151 int dec,
152 const std::string& tooltip ) {
153
154 auto inputLabel = new QLabel( tr( name.c_str() ) );
155 auto inputField = new MatrixEditor( initial, dec );
156
157 if ( !tooltip.empty() ) {
158 auto tooltipString =
159 QString( "<qt>%1</qt>" ).arg( QString( tooltip.c_str() ).toHtmlEscaped() );
160 inputLabel->setToolTip( tooltipString );
161 inputField->setToolTip( tooltipString );
162 }
163 connect( inputField, &MatrixEditor::valueChanged, std::move( callback ) );
164
165 auto index = m_contentLayout->rowCount();
166 m_contentLayout->addWidget( inputLabel, index, 0 );
167 m_contentLayout->addWidget( inputField, index, 1 );
168}
169
170void ControlPanel::addColorInput(
171 const std::string& name,
172 const std::function<void( const Ra::Core::Utils::Color& clr )>& callback,
174 bool withAlpha,
175 const std::string& tooltip ) {
176
177 auto button = new QPushButton( name.c_str() );
178 auto srgbColor = Ra::Core::Utils::Color::linearRGBTosRGB( color );
179 auto clrBttn = QColor::fromRgbF( srgbColor[0], srgbColor[1], srgbColor[2], srgbColor[3] );
180 auto clrDlg = [callback, clrBttn, withAlpha, button, name]() mutable {
181 clrBttn = QColorDialog::getColor(
182 clrBttn,
183 nullptr,
184 name.c_str(),
185 ( withAlpha ? QColorDialog::ShowAlphaChannel : QColorDialog::ColorDialogOptions() )
186#ifndef OS_MACOS
187 | QColorDialog::DontUseNativeDialog
188#endif
189 );
190 if ( clrBttn.isValid() ) {
191 // update the background color of the viewer
192 auto lum = 0.2126_ra * Scalar( clrBttn.redF() ) +
193 0.7151_ra * Scalar( clrBttn.greenF() ) +
194 0.0721_ra * Scalar( clrBttn.blueF() );
196 Ra::Core::Utils::Color( Scalar( clrBttn.redF() ),
197 Scalar( clrBttn.greenF() ),
198 Scalar( clrBttn.blueF() ),
199 Scalar( clrBttn.alphaF() ) ) );
200 callback( bgk );
201 QString qss = QString( "background-color: %1" ).arg( clrBttn.name() );
202 if ( lum > 1_ra / 3_ra ) { qss += QString( "; color: #000000" ); }
203 else { qss += QString( "; color: #FFFFFF" ); }
204 button->setStyleSheet( qss );
205 }
206 };
207
208 if ( !tooltip.empty() ) {
209 button->setToolTip(
210 QString( "<qt>%1</qt>" ).arg( QString( tooltip.c_str() ).toHtmlEscaped() ) );
211 }
212 // for contrast computation : see
213 // https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
214 auto lum = 0.2126_ra * srgbColor[0] + 0.7151_ra * srgbColor[1] + 0.0721_ra * srgbColor[2];
215 QString qss = QString( "background-color: %1" ).arg( clrBttn.name() );
216 if ( lum > 1_ra / 3_ra ) { qss += QString( "; color: #000000" ); }
217 else { qss += QString( "; color: #FFFFFF" ); }
218 button->setStyleSheet( qss );
219
220 connect( button, &QPushButton::clicked, clrDlg );
221
222 auto index = m_contentLayout->rowCount();
223 m_contentLayout->addWidget( button, index, 0, 1, -1 );
224}
225
226void ControlPanel::addFileInput( const std::string& name,
227 std::function<void( std::string )> callback,
228 const std::string& rootDirectory,
229 const std::string& filters,
230 const std::string& tooltip ) {
231
232 auto openFile = [this, callback, rootDirectory, filters]() {
233 auto fltrs = QString::fromStdString( filters );
234 auto pathList = QFileDialog::getOpenFileNames(
235 this, "Open files", QString::fromStdString( rootDirectory ), fltrs );
236 if ( !pathList.empty() ) {
237 std::string fileList;
238 for ( const auto& file : pathList ) {
239 fileList += file.toStdString() + ";";
240 }
241 fileList.erase( fileList.size() - 1 );
242 callback( fileList );
243 }
244 else { callback( "" ); }
245 };
246
247 addButton( name, openFile, tooltip );
248}
249
250void ControlPanel::addFileOutput( const std::string& name,
251 std::function<void( std::string )> callback,
252 const std::string& rootDirectory,
253 const std::string& filters,
254 const std::string& tooltip ) {
255
256 auto saveFile = [this, callback, rootDirectory, filters]() {
257 auto fltrs = QString::fromStdString( filters );
258 auto filename = QFileDialog::getSaveFileName(
259 this, "Save file", QString::fromStdString( rootDirectory ), fltrs );
260 if ( !filename.isEmpty() ) { callback( filename.toStdString() ); }
261 };
262 addButton( name, saveFile, tooltip );
263}
264
265void ControlPanel::addSeparator() {
266 QFrame* line = new QFrame();
267 line->setFrameShape( QFrame::HLine );
268 line->setFrameShadow( QFrame::Sunken );
269 m_mainLayout->addWidget( line );
270 m_contentLayout = new QGridLayout();
271 m_mainLayout->addLayout( m_contentLayout );
272}
273
274void ControlPanel::addComboBox( const std::string& name,
275 std::function<void( int )> callback,
276 int initial,
277 const std::vector<std::string>& items,
278 const std::string& tooltip ) {
279 auto inputLabel = new QLabel( tr( name.c_str() ) );
280 auto inputField = new QComboBox();
281 for ( auto v : items ) {
282 inputField->addItem( QString::fromStdString( v ) );
283 }
284 if ( !tooltip.empty() ) {
285 inputLabel->setToolTip(
286 QString( "<qt>%1</qt>" ).arg( QString( tooltip.c_str() ).toHtmlEscaped() ) );
287 }
288 inputField->setCurrentIndex( initial );
289 connect(
290 inputField, QOverload<int>::of( &QComboBox::currentIndexChanged ), std::move( callback ) );
291
292 auto index = m_contentLayout->rowCount();
293 m_contentLayout->addWidget( inputLabel, index, 0 );
294 m_contentLayout->addWidget( inputField, index, 1 );
295}
296
297void ControlPanel::addComboBox( const std::string& name,
298 std::function<void( const QString& )> callback,
299 const std::string& initial,
300 const std::vector<std::string>& items,
301 const std::string& tooltip ) {
302 auto inputLabel = new QLabel( tr( name.c_str() ) );
303 auto inputField = new QComboBox();
304 for ( auto v : items ) {
305 inputField->addItem( QString::fromStdString( v ) );
306 }
307 if ( !tooltip.empty() ) {
308 inputLabel->setToolTip(
309 QString( "<qt>%1</qt>" ).arg( QString( tooltip.c_str() ).toHtmlEscaped() ) );
310 }
311 inputField->setCurrentText( QString::fromStdString( initial ) );
312 connect( inputField,
313 QOverload<const QString&>::of( &QComboBox::currentTextChanged ),
314 std::move( callback ) );
315
316 auto index = m_contentLayout->rowCount();
317 m_contentLayout->addWidget( inputLabel, index, 0 );
318 m_contentLayout->addWidget( inputField, index, 1 );
319}
320
321void ControlPanel::addStretch( int stretch ) {
322 m_mainLayout->addStretch( stretch );
323 m_contentLayout = new QGridLayout();
324 m_contentLayout->setObjectName( "stretch layout" );
325 m_mainLayout->addLayout( m_contentLayout );
326}
327
328void ControlPanel::addWidget( QWidget* newWidget ) {
329 m_mainLayout->addWidget( newWidget );
330 m_contentLayout = new QGridLayout();
331 m_contentLayout->setObjectName( "Widget content layout" );
332 m_mainLayout->addLayout( m_contentLayout );
333}
334
335} // namespace Ra::Gui::Widgets
T c_str(T... args)
static ColorBase sRGBToLinearRGB(const ColorBase &srgb)
Definition Color.hpp:62
static ColorBase linearRGBTosRGB(const ColorBase &lrgb)
Definition Color.hpp:72
T empty(T... args)
T erase(T... args)
T move(T... args)
T size(T... args)