svgui  1.9
PluginParameterDialog.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006 Chris Cannam and QMUL.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "PluginParameterDialog.h"
17 
18 #include "PluginParameterBox.h"
19 #include "WindowTypeSelector.h"
20 
21 #include "TextAbbrev.h"
22 #include "IconLoader.h"
23 
24 #include <vamp-hostsdk/Plugin.h>
25 #include <vamp-hostsdk/PluginHostAdapter.h>
26 #include <vamp-hostsdk/PluginWrapper.h>
27 
28 #include <QGridLayout>
29 #include <QLabel>
30 #include <QGroupBox>
31 #include <QHBoxLayout>
32 #include <QVBoxLayout>
33 #include <QScrollArea>
34 #include <QPushButton>
35 #include <QMessageBox>
36 #include <QComboBox>
37 #include <QCheckBox>
38 #include <QSettings>
39 #include <QDialogButtonBox>
40 #include <QDesktopServices>
41 #include <QUrl>
42 
43 #include "base/Debug.h"
44 
46  QWidget *parent) :
47  QDialog(parent),
48  m_plugin(plugin),
49  m_channel(-1),
50  m_stepSize(0),
51  m_blockSize(0),
52  m_windowType(HanningWindow),
53  m_parameterBox(0),
54  m_currentSelectionOnly(false)
55 {
56  setWindowTitle(tr("Plugin Parameters"));
57 
58  QGridLayout *grid = new QGridLayout;
59  setLayout(grid);
60 
61  QGroupBox *pluginBox = new QGroupBox;
62  pluginBox->setTitle(plugin->getType().c_str());
63  grid->addWidget(pluginBox, 0, 0);
64 
65  QGridLayout *subgrid = new QGridLayout;
66  pluginBox->setLayout(subgrid);
67 
68  subgrid->setSpacing(0);
69  subgrid->setMargin(10);
70 
71  QFont boldFont(pluginBox->font());
72  boldFont.setBold(true);
73 
74  QFont italicFont(pluginBox->font());
75  italicFont.setItalic(true);
76 
77  QLabel *nameLabel = new QLabel(plugin->getName().c_str());
78  nameLabel->setWordWrap(true);
79  nameLabel->setFont(boldFont);
80 
81  QLabel *makerLabel = new QLabel(plugin->getMaker().c_str());
82  makerLabel->setWordWrap(true);
83 
84  int version = plugin->getPluginVersion();
85  QLabel *versionLabel = new QLabel(QString("%1").arg(version));
86  versionLabel->setWordWrap(true);
87 
88  QLabel *copyrightLabel = new QLabel(plugin->getCopyright().c_str());
89  copyrightLabel->setWordWrap(true);
90 
91 // QLabel *typeLabel = new QLabel(plugin->getType().c_str());
92 // typeLabel->setWordWrap(true);
93 // typeLabel->setFont(boldFont);
94 
95  QLabel *descriptionLabel = 0;
96  if (plugin->getDescription() != "") {
97  descriptionLabel = new QLabel(plugin->getDescription().c_str());
98  descriptionLabel->setWordWrap(true);
99  descriptionLabel->setFont(italicFont);
100  }
101 
102  int row = 0;
103 
104  QLabel *label = new QLabel(tr("Name:"));
105  label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
106  subgrid->addWidget(label, row, 0);
107  subgrid->addWidget(nameLabel, row, 1);
108 
109  m_moreInfo = new QPushButton;
110  m_moreInfo->setIcon(IconLoader().load("info"));
111  m_moreInfo->setFixedSize(QSize(16, 16));
112  connect(m_moreInfo, SIGNAL(clicked()), this, SLOT(moreInfo()));
113  subgrid->addWidget(m_moreInfo, row, 2, Qt::AlignTop | Qt::AlignRight);
114  m_moreInfo->hide();
115 
116  row++;
117 
118  if (descriptionLabel) {
119 // label = new QLabel(tr("Description:"));
120 // label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
121 // subgrid->addWidget(label, row, 0);
122  subgrid->addWidget(descriptionLabel, row, 1, 1, 2);
123  row++;
124  }
125 
126  if (version >= 0) {
127  label = new QLabel(tr("Version:"));
128  label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
129  subgrid->addWidget(label, row, 0);
130  subgrid->addWidget(versionLabel, row, 1);
131  row++;
132  }
133 
134 // label = new QLabel(tr("Type:"));
135 // label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
136 // subgrid->addWidget(label, row, 0);
137 // subgrid->addWidget(typeLabel, row, 1);
138 // row++;
139 
140  label = new QLabel(tr("Maker:"));
141  label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
142  subgrid->addWidget(label, row, 0);
143  subgrid->addWidget(makerLabel, row, 1);
144  row++;
145 
146  label = new QLabel(tr("Copyright: "));
147  label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
148  subgrid->addWidget(label, row, 0);
149  subgrid->addWidget(copyrightLabel, row, 1);
150  row++;
151 
152  m_outputSpacer = new QLabel;
153  subgrid->addWidget(m_outputSpacer, row, 0);
154  m_outputSpacer->setFixedHeight(7);
155  m_outputSpacer->hide();
156  row++;
157 
158  m_outputLabel = new QLabel(tr("Output:"));
159  m_outputLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
160  subgrid->addWidget(m_outputLabel, row, 0);
161  m_outputValue = new QLabel;
162  m_outputValue->setFont(boldFont);
163  subgrid->addWidget(m_outputValue, row, 1);
164  m_outputLabel->hide();
165  m_outputValue->hide();
166  row++;
167 
168  m_outputDescription = new QLabel;
169  m_outputDescription->setFont(italicFont);
170  subgrid->addWidget(m_outputDescription, row, 1);
171  m_outputDescription->hide();
172  row++;
173 
174  subgrid->setColumnStretch(1, 2);
175 
176  m_inputModelBox = new QGroupBox;
177  m_inputModelBox->setTitle(tr("Input Material"));
178  grid->addWidget(m_inputModelBox, 1, 0);
179 
180  m_inputModels = new QComboBox;
181  QVBoxLayout *inputLayout = new QVBoxLayout;
182  m_inputModelBox->setLayout(inputLayout);
183  inputLayout->addWidget(m_inputModels);
184  m_inputModels->hide();
185 
186  m_selectionOnly = new QCheckBox(tr("Restrict to selection extents"));
187  inputLayout->addWidget(m_selectionOnly);
188  m_selectionOnly->hide();
189 
190  m_inputModelBox->hide();
191 
192  QGroupBox *paramBox = new QGroupBox;
193  paramBox->setTitle(tr("Plugin Parameters"));
194  grid->addWidget(paramBox, 2, 0);
195  grid->setRowStretch(2, 10);
196 
197  QHBoxLayout *paramLayout = new QHBoxLayout;
198  paramLayout->setMargin(0);
199  paramBox->setLayout(paramLayout);
200 
201  QScrollArea *scroll = new QScrollArea;
202  scroll->setWidgetResizable(true);
203  scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
204  scroll->setFrameShape(QFrame::NoFrame);
205  paramLayout->addWidget(scroll);
206 
208  connect(m_parameterBox, SIGNAL(pluginConfigurationChanged(QString)),
209  this, SIGNAL(pluginConfigurationChanged(QString)));
210  scroll->setWidget(m_parameterBox);
211 
212  m_advanced = new QFrame;
213  QVBoxLayout *advancedLayout = new QVBoxLayout;
214  advancedLayout->setMargin(0);
215  m_advanced->setLayout(advancedLayout);
216  grid->addWidget(m_advanced, 3, 0);
217 
218  m_channelBox = new QGroupBox;
219  m_channelBox->setTitle(tr("Channels"));
220  advancedLayout->addWidget(m_channelBox);
221  m_channelBox->setVisible(false);
222  m_haveChannelBoxData = false;
223 
224  m_windowBox = new QGroupBox;
225  m_windowBox->setTitle(tr("Processing"));
226  advancedLayout->addWidget(m_windowBox);
227  m_windowBox->setVisible(false);
228  m_haveWindowBoxData = false;
229 
230  QHBoxLayout *hbox = new QHBoxLayout;
231  grid->addLayout(hbox, 4, 0);
232 
233  m_advancedVisible = false;
234 
235  m_advancedButton = new QPushButton(tr("Advanced >>"));
236  m_advancedButton->setCheckable(true);
237  connect(m_advancedButton, SIGNAL(clicked()), this, SLOT(advancedToggled()));
238 
239  QSettings settings;
240  settings.beginGroup("PluginParameterDialog");
241  m_advancedVisible = settings.value("advancedvisible", false).toBool();
242  settings.endGroup();
243 
244  m_advanced->hide();
245 
246  hbox->addWidget(m_advancedButton);
247  m_advancedButton->hide();
248 
249  QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok |
250  QDialogButtonBox::Cancel);
251  hbox->addWidget(bb);
252  connect(bb, SIGNAL(accepted()), this, SLOT(dialogAccepted()));
253  connect(bb, SIGNAL(rejected()), this, SLOT(reject()));
254  bb->button(QDialogButtonBox::Ok)->setDefault(true);
255 
257 }
258 
260 {
261 }
262 
263 int
265 {
266  show();
268  return QDialog::exec();
269 }
270 
271 
272 void
274  QString description)
275 {
276  if (text == "") {
277  m_outputSpacer->hide();
278  m_outputLabel->hide();
279  m_outputValue->hide();
280  m_outputDescription->hide();
281  } else {
282  m_outputSpacer->show();
283  m_outputValue->setText(text);
284  m_outputValue->setWordWrap(true);
285  m_outputDescription->setText(description);
286  m_outputDescription->setWordWrap(true);
287  m_outputLabel->show();
288  m_outputValue->show();
289  if (description != "") {
290  m_outputDescription->show();
291  } else {
292  m_outputDescription->hide();
293  }
294  }
295 }
296 
297 void
299 {
300  m_moreInfoUrl = moreInfoUrl;
301  if (m_moreInfoUrl != "") {
302  m_moreInfo->show();
303  } else {
304  m_moreInfo->hide();
305  }
306 }
307 
308 void
310  int targetChannels,
311  int defaultChannel)
312 {
313  m_channel = defaultChannel;
314 
315  if (sourceChannels != targetChannels) {
316 
317  // At the moment we can only cope with the case where
318  // sourceChannels > targetChannels and targetChannels == 1
319 
320  if (sourceChannels < targetChannels) {
321 
322  QMessageBox::warning
323  (parentWidget(),
324  tr("Channel mismatch"),
325  tr("This plugin requires at least %1 input channels, but only %2 %3 available. The plugin probably will not work correctly.").arg(targetChannels).arg(sourceChannels).arg(sourceChannels != 1 ? tr("are") : tr("is")),
326  QMessageBox::Ok,
327  QMessageBox::NoButton);
328 
329  } else {
330 
331  if (m_haveChannelBoxData) {
332  cerr << "WARNING: PluginParameterDialog::setChannelArrangement: Calling more than once on same dialog is not currently implemented" << endl;
333  return;
334  }
335 
336  QVBoxLayout *channelLayout = new QVBoxLayout;
337  m_channelBox->setLayout(channelLayout);
338 
339  if (targetChannels != 1) {
340 
341  channelLayout->addWidget
342  (new QLabel(tr("This plugin accepts no more than %1 input channels,\nbut %2 are available. Only the first %3 will be used.\n")
343  .arg(targetChannels)
344  .arg(sourceChannels)
345  .arg(targetChannels)));
346 
347  } else {
348 
349  channelLayout->addWidget(new QLabel(tr("This plugin only has a single channel input,\nbut the source has %1 channels.").arg(sourceChannels)));
350 
351  QComboBox *channelCombo = new QComboBox;
352  channelCombo->addItem(tr("Use mean of source channels"));
353  for (int i = 0; i < sourceChannels; ++i) {
354  channelCombo->addItem(tr("Use channel %1 only").arg(i + 1));
355  }
356 
357  connect(channelCombo, SIGNAL(activated(int)),
358  this, SLOT(channelComboChanged(int)));
359 
360  channelLayout->addWidget(channelCombo);
361  }
362 
363  m_channelBox->setVisible(true);
364  m_haveChannelBoxData = true;
365  m_advancedButton->show();
366  }
367  }
368 
370 }
371 
372 void
374  bool showFrequencyDomainOptions)
375 {
376  if (m_haveWindowBoxData) {
377  cerr << "WARNING: PluginParameterDialog::setShowProcessingOptions: Calling more than once on same dialog is not currently implemented" << endl;
378  return;
379  }
380 
381  if (showWindowSize) {
382 
383  Vamp::Plugin *fePlugin = dynamic_cast<Vamp::Plugin *>(m_plugin);
384  if (!fePlugin) fePlugin = dynamic_cast<Vamp::PluginHostAdapter *>(m_plugin);
385  if (!fePlugin) fePlugin = dynamic_cast<Vamp::HostExt::PluginWrapper *>(m_plugin);
386  int size = 1024;
387  int increment = 1024;
388  if (fePlugin) {
389  size = fePlugin->getPreferredBlockSize();
390  cerr << "Feature extraction plugin \"" << fePlugin->getName() << "\" reports preferred block size as " << size << endl;
391  if (size == 0) size = 1024;
392  increment = fePlugin->getPreferredStepSize();
393  if (increment == 0) {
394  if (fePlugin->getInputDomain() == Vamp::Plugin::TimeDomain) {
395  increment = size;
396  } else {
397  increment = size/2;
398  }
399  }
400  }
401 
402  QGridLayout *windowLayout = new QGridLayout;
403  m_windowBox->setLayout(windowLayout);
404 
405  if (showFrequencyDomainOptions) {
406  windowLayout->addWidget(new QLabel(tr("Window size:")), 0, 0);
407  } else {
408  windowLayout->addWidget(new QLabel(tr("Audio frames per block:")), 0, 0);
409  }
410 
411  cerr << "size: " << size << ", increment: " << increment << endl;
412 
413  QComboBox *blockSizeCombo = new QComboBox;
414  blockSizeCombo->setEditable(true);
415  bool found = false;
416  for (int i = 0; i < 14; ++i) {
417  int val = 1 << (i + 3);
418  blockSizeCombo->addItem(QString("%1").arg(val));
419  if (val == size) {
420  blockSizeCombo->setCurrentIndex(i);
421  found = true;
422  }
423  }
424  if (!found) {
425  blockSizeCombo->addItem(QString("%1").arg(size));
426  blockSizeCombo->setCurrentIndex(blockSizeCombo->count() - 1);
427  }
428  blockSizeCombo->setValidator(new QIntValidator(1, int(pow(2., 18)), this));
429  connect(blockSizeCombo, SIGNAL(editTextChanged(const QString &)),
430  this, SLOT(blockSizeComboChanged(const QString &)));
431  windowLayout->addWidget(blockSizeCombo, 0, 1);
432 
433  windowLayout->addWidget(new QLabel(tr("Window increment:")), 1, 0);
434 
435  QComboBox *incrementCombo = new QComboBox;
436  incrementCombo->setEditable(true);
437  found = false;
438  for (int i = 0; i < 14; ++i) {
439  int val = 1 << (i + 3);
440  incrementCombo->addItem(QString("%1").arg(val));
441  if (val == increment) {
442  incrementCombo->setCurrentIndex(i);
443  found = true;
444  }
445  }
446  if (!found) {
447  incrementCombo->addItem(QString("%1").arg(increment));
448  incrementCombo->setCurrentIndex(incrementCombo->count() - 1);
449  }
450  incrementCombo->setValidator(new QIntValidator(1, int(pow(2., 18)), this));
451  connect(incrementCombo, SIGNAL(editTextChanged(const QString &)),
452  this, SLOT(incrementComboChanged(const QString &)));
453  windowLayout->addWidget(incrementCombo, 1, 1);
454 
455  if (showFrequencyDomainOptions) {
456 
457  windowLayout->addWidget(new QLabel(tr("Window shape:")), 2, 0);
458  WindowTypeSelector *windowTypeSelector = new WindowTypeSelector;
459  connect(windowTypeSelector, SIGNAL(windowTypeChanged(WindowType)),
460  this, SLOT(windowTypeChanged(WindowType)));
461  windowLayout->addWidget(windowTypeSelector, 2, 1);
462  }
463 
464  m_windowBox->setVisible(true);
465  m_haveWindowBoxData = true;
466  m_advancedButton->show();
467  }
468 
470 }
471 
472 void
474  QString defaultModel)
475 {
476  m_inputModels->clear();
477 
478  QSettings settings;
479  settings.beginGroup("PluginParameterDialog");
480  QString lastModel = settings.value("lastinputmodel").toString();
481  settings.endGroup();
482 
483  if (defaultModel == "") defaultModel = lastModel;
484 
485  m_inputModels->show();
486 
487  m_inputModelList = models;
488  m_inputModels->addItems(TextAbbrev::abbreviate(models, 80));
489  m_inputModels->setCurrentIndex(0);
490 
491  if (defaultModel != "") {
492  for (int i = 0; i < models.size(); ++i) {
493  if (defaultModel == models[i]) {
494  m_inputModels->setCurrentIndex(i);
495  m_currentInputModel = models[i];
496  break;
497  }
498  }
499  }
500 
501  connect(m_inputModels, SIGNAL(activated(int)),
502  this, SLOT(inputModelComboChanged(int)));
503  m_inputModelBox->show();
504 }
505 
506 void
508 {
509  if (!show) {
510  m_selectionOnly->hide();
511  if (!m_inputModels->isVisible()) m_inputModelBox->hide();
512  return;
513  }
514 
515  QSettings settings;
516  settings.beginGroup("PluginParameterDialog");
517  bool lastSelectionOnly = settings.value("lastselectiononly", false).toBool();
518  settings.endGroup();
519 
520  m_selectionOnly->setChecked(lastSelectionOnly);
521  m_currentSelectionOnly = lastSelectionOnly;
522 
523  connect(m_selectionOnly, SIGNAL(stateChanged(int)),
524  this, SLOT(selectionOnlyChanged(int)));
525 
526  m_selectionOnly->show();
527  m_inputModelBox->show();
528 }
529 
530 QString
532 {
533  return m_currentInputModel;
534 }
535 
536 bool
538 {
539  return m_currentSelectionOnly;
540 }
541 
542 void
544 {
545  blockSize = m_blockSize;
546  return;
547 }
548 
549 void
551  int &blockSize,
552  WindowType &windowType) const
553 {
554  stepSize = m_stepSize;
555  blockSize = m_blockSize;
556  windowType = m_windowType;
557  return;
558 }
559 
560 void
562 {
563  m_blockSize = text.toInt();
564  cerr << "Block size changed to " << m_blockSize << endl;
565 }
566 
567 void
569 {
570  m_stepSize = text.toInt();
572  cerr << "Increment changed to " << m_stepSize << endl;
573 }
574 
575 void
577 {
578  m_windowType = type;
579 }
580 
581 void
583 {
584  if (m_moreInfoUrl != "") {
585  QDesktopServices::openUrl(QUrl(m_moreInfoUrl));
586  }
587 }
588 
589 void
591 {
593 }
594 
595 void
597 {
598 // m_advanced->setVisible(visible);
599 
600  if (visible) {
601  m_advancedButton->setText(tr("Advanced <<"));
602  m_advancedButton->setChecked(true);
603  m_advanced->show();
604  } else {
605  m_advanced->hide();
606  m_advancedButton->setText(tr("Advanced >>"));
607  m_advancedButton->setChecked(false);
608  }
609 
610 // cerr << "resize to " << sizeHint().width() << " x " << sizeHint().height() << endl;
611 
612 // setMinimumHeight(sizeHint().height());
613  adjustSize();
614 
615 // (sizeHint());
616 
617  m_advancedVisible = visible;
618 
619  QSettings settings;
620  settings.beginGroup("PluginParameterDialog");
621  settings.setValue("advancedvisible", visible);
622  settings.endGroup();
623 
624 // if (visible) setMaximumHeight(sizeHint().height());
625 // adjustSize();
626 }
627 
628 void
630 {
631  m_channel = index - 1;
632 }
633 
634 void
636 {
637  if (index >= m_inputModelList.size()) return;
640 }
641 
642 void
644 {
645  if (state == Qt::Checked) {
646  m_currentSelectionOnly = true;
647  } else {
648  m_currentSelectionOnly = false;
649  }
650 }
651 
652 void
654 {
655  QSettings settings;
656  settings.beginGroup("PluginParameterDialog");
657 
658  if (m_inputModels->isVisible()) {
659  settings.setValue("lastinputmodel", getInputModel());
660  }
661 
662  if (m_selectionOnly->isVisible()) {
663  settings.setValue("lastselectiononly", getSelectionOnly());
664  }
665 
666  settings.endGroup();
667 
668  accept();
669 }
670 
void setChannelArrangement(int sourceChannels, int targetChannels, int defaultChannel)
static QString abbreviate(QString text, int maxLength, Policy policy=ElideEnd, bool fuzzy=true, QString ellipsis="")
Abbreviate the given text to the given maximum length (including ellipsis), using the given abbreviat...
Definition: TextAbbrev.cpp:74
void pluginConfigurationChanged(QString)
void inputModelChanged(QString)
void windowTypeChanged(WindowType type)
void setCandidateInputModels(const QStringList &names, QString defaultName)
void setShowSelectionOnlyOption(bool show)
void setOutputLabel(QString output, QString description)
PluginParameterBox * m_parameterBox
void setShowProcessingOptions(bool showWindowSize, bool showFrequencyDomainOptions)
void getProcessingParameters(int &blockSize) const
!! merge with PluginTransform::ExecutionContext
Vamp::PluginBase * m_plugin
void blockSizeComboChanged(const QString &)
void setMoreInfoUrl(QString url)
void incrementComboChanged(const QString &)
PluginParameterDialog(Vamp::PluginBase *, QWidget *parent=0)