Loading [MathJax]/extensions/TeX/AMSmath.js
Radium Engine  1.6.2
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 button->setObjectName( name.c_str() );
179 auto srgbColor = Ra::Core::Utils::Color::linearRGBTosRGB( color );
180 auto clrBttn = QColor::fromRgbF( srgbColor[0], srgbColor[1], srgbColor[2], srgbColor[3] );
181 auto clrDlg = [callback, clrBttn, withAlpha, button, name]() mutable {
182 clrBttn = QColorDialog::getColor(
183 clrBttn,
184 nullptr,
185 name.c_str(),
186 ( withAlpha ? QColorDialog::ShowAlphaChannel : QColorDialog::ColorDialogOptions() )
187#ifndef OS_MACOS
188 | QColorDialog::DontUseNativeDialog
189#endif
190 );
191 if ( clrBttn.isValid() ) {
192 // update the background color of the viewer
193 auto lum = 0.2126_ra * Scalar( clrBttn.redF() ) +
194 0.7151_ra * Scalar( clrBttn.greenF() ) +
195 0.0721_ra * Scalar( clrBttn.blueF() );
197 Ra::Core::Utils::Color( Scalar( clrBttn.redF() ),
198 Scalar( clrBttn.greenF() ),
199 Scalar( clrBttn.blueF() ),
200 Scalar( clrBttn.alphaF() ) ) );
201 callback( bgk );
202 QString qss = QString( "background-color: %1" ).arg( clrBttn.name() );
203 if ( lum > 1_ra / 3_ra ) { qss += QString( "; color: #000000" ); }
204 else { qss += QString( "; color: #FFFFFF" ); }
205 button->setStyleSheet( qss );
206 }
207 };
208
209 if ( !tooltip.empty() ) {
210 button->setToolTip(
211 QString( "<qt>%1</qt>" ).arg( QString( tooltip.c_str() ).toHtmlEscaped() ) );
212 }
213 // for contrast computation : see
214 // https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html
215 auto lum = 0.2126_ra * srgbColor[0] + 0.7151_ra * srgbColor[1] + 0.0721_ra * srgbColor[2];
216 QString qss = QString( "background-color: %1" ).arg( clrBttn.name() );
217 if ( lum > 1_ra / 3_ra ) { qss += QString( "; color: #000000" ); }
218 else { qss += QString( "; color: #FFFFFF" ); }
219 button->setStyleSheet( qss );
220
221 connect( button, &QPushButton::clicked, clrDlg );
222
223 auto index = m_contentLayout->rowCount();
224 m_contentLayout->addWidget( button, index, 0, 1, -1 );
225}
226
227void ControlPanel::addFileInput( const std::string& name,
228 std::function<void( std::string )> callback,
229 const std::string& rootDirectory,
230 const std::string& filters,
231 const std::string& tooltip ) {
232
233 auto openFile = [this, callback, rootDirectory, filters]() {
234 auto fltrs = QString::fromStdString( filters );
235 auto pathList = QFileDialog::getOpenFileNames(
236 this, "Open files", QString::fromStdString( rootDirectory ), fltrs );
237 if ( !pathList.empty() ) {
238 std::string fileList;
239 for ( const auto& file : pathList ) {
240 fileList += file.toStdString() + ";";
241 }
242 fileList.erase( fileList.size() - 1 );
243 callback( fileList );
244 }
245 else { callback( "" ); }
246 };
247
248 addButton( name, openFile, tooltip );
249}
250
251void ControlPanel::addFileOutput( const std::string& name,
252 std::function<void( std::string )> callback,
253 const std::string& rootDirectory,
254 const std::string& filters,
255 const std::string& tooltip ) {
256
257 auto saveFile = [this, callback, rootDirectory, filters]() {
258 auto fltrs = QString::fromStdString( filters );
259 auto filename = QFileDialog::getSaveFileName(
260 this, "Save file", QString::fromStdString( rootDirectory ), fltrs );
261 if ( !filename.isEmpty() ) { callback( filename.toStdString() ); }
262 };
263 addButton( name, saveFile, tooltip );
264}
265
266void ControlPanel::addSeparator() {
267 QFrame* line = new QFrame();
268 line->setFrameShape( QFrame::HLine );
269 line->setFrameShadow( QFrame::Sunken );
270 m_mainLayout->addWidget( line );
271 m_contentLayout = new QGridLayout();
272 m_mainLayout->addLayout( m_contentLayout );
273}
274
275void ControlPanel::addComboBox( const std::string& name,
276 std::function<void( int )> callback,
277 int initial,
278 const std::vector<std::string>& items,
279 const std::string& tooltip ) {
280 auto inputLabel = new QLabel( tr( name.c_str() ) );
281 auto inputField = new QComboBox();
282 for ( auto v : items ) {
283 inputField->addItem( QString::fromStdString( v ) );
284 }
285 if ( !tooltip.empty() ) {
286 inputLabel->setToolTip(
287 QString( "<qt>%1</qt>" ).arg( QString( tooltip.c_str() ).toHtmlEscaped() ) );
288 }
289 inputField->setCurrentIndex( initial );
290 connect(
291 inputField, QOverload<int>::of( &QComboBox::currentIndexChanged ), std::move( callback ) );
292
293 auto index = m_contentLayout->rowCount();
294 m_contentLayout->addWidget( inputLabel, index, 0 );
295 m_contentLayout->addWidget( inputField, index, 1 );
296}
297
298void ControlPanel::addComboBox( const std::string& name,
299 std::function<void( const QString& )> callback,
300 const std::string& initial,
301 const std::vector<std::string>& items,
302 const std::string& tooltip ) {
303 auto inputLabel = new QLabel( tr( name.c_str() ) );
304 auto inputField = new QComboBox();
305 for ( auto v : items ) {
306 inputField->addItem( QString::fromStdString( v ) );
307 }
308 if ( !tooltip.empty() ) {
309 inputLabel->setToolTip(
310 QString( "<qt>%1</qt>" ).arg( QString( tooltip.c_str() ).toHtmlEscaped() ) );
311 }
312 inputField->setCurrentText( QString::fromStdString( initial ) );
313 connect( inputField,
314 QOverload<const QString&>::of( &QComboBox::currentTextChanged ),
315 std::move( callback ) );
316
317 auto index = m_contentLayout->rowCount();
318 m_contentLayout->addWidget( inputLabel, index, 0 );
319 m_contentLayout->addWidget( inputField, index, 1 );
320}
321
322void ControlPanel::addStretch( int stretch ) {
323 m_mainLayout->addStretch( stretch );
324 m_contentLayout = new QGridLayout();
325 m_contentLayout->setObjectName( "stretch layout" );
326 m_mainLayout->addLayout( m_contentLayout );
327}
328
329void ControlPanel::addWidget( QWidget* newWidget ) {
330 m_mainLayout->addWidget( newWidget );
331 m_contentLayout = new QGridLayout();
332 m_contentLayout->setObjectName( "Widget content layout" );
333 m_mainLayout->addLayout( m_contentLayout );
334}
335
336} // 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)