annotate widgets/PluginParameterDialog.cpp @ 163:dd6dd983e8ef

* Tidy up plugin parameter dialog by switching it to a simple constructor with separate methods for passing in the additional options if necessary * Fix sizing problem on advanced pane toggle in plugin parameter dialog * Make a start on passing in list of candidate input models for transform
author Chris Cannam
date Wed, 11 Oct 2006 16:18:51 +0000
parents 8c730f49b9b3
children 11949d0b2739
rev   line source
Chris@62 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@62 2
Chris@62 3 /*
Chris@62 4 Sonic Visualiser
Chris@62 5 An audio file viewer and annotation editor.
Chris@62 6 Centre for Digital Music, Queen Mary, University of London.
Chris@62 7 This file copyright 2006 Chris Cannam.
Chris@62 8
Chris@62 9 This program is free software; you can redistribute it and/or
Chris@62 10 modify it under the terms of the GNU General Public License as
Chris@62 11 published by the Free Software Foundation; either version 2 of the
Chris@62 12 License, or (at your option) any later version. See the file
Chris@62 13 COPYING included with this distribution for more information.
Chris@62 14 */
Chris@62 15
Chris@62 16 #include "PluginParameterDialog.h"
Chris@62 17
Chris@62 18 #include "PluginParameterBox.h"
Chris@140 19 #include "WindowTypeSelector.h"
Chris@62 20
Chris@106 21 #include "vamp-sdk/Plugin.h"
Chris@147 22 #include "vamp-sdk/PluginHostAdapter.h"
Chris@106 23
Chris@62 24 #include <QGridLayout>
Chris@62 25 #include <QLabel>
Chris@62 26 #include <QGroupBox>
Chris@62 27 #include <QHBoxLayout>
Chris@143 28 #include <QVBoxLayout>
Chris@149 29 #include <QScrollArea>
Chris@62 30 #include <QPushButton>
Chris@69 31 #include <QMessageBox>
Chris@69 32 #include <QComboBox>
Chris@143 33 #include <QSettings>
Chris@62 34
Chris@71 35 PluginParameterDialog::PluginParameterDialog(Vamp::PluginBase *plugin,
Chris@62 36 QWidget *parent) :
Chris@62 37 QDialog(parent),
Chris@62 38 m_plugin(plugin),
Chris@163 39 m_channel(-1),
Chris@145 40 m_stepSize(0),
Chris@145 41 m_blockSize(0),
Chris@145 42 m_windowType(HanningWindow),
Chris@62 43 m_parameterBox(0)
Chris@62 44 {
Chris@122 45 setWindowTitle(tr("Plugin Parameters"));
Chris@122 46
Chris@62 47 QGridLayout *grid = new QGridLayout;
Chris@62 48 setLayout(grid);
Chris@62 49
Chris@62 50 QGroupBox *pluginBox = new QGroupBox;
Chris@62 51 pluginBox->setTitle(tr("Plugin"));
Chris@62 52 grid->addWidget(pluginBox, 0, 0);
Chris@62 53
Chris@62 54 QGridLayout *subgrid = new QGridLayout;
Chris@62 55 pluginBox->setLayout(subgrid);
Chris@62 56
Chris@63 57 subgrid->setSpacing(0);
Chris@63 58 subgrid->setMargin(10);
Chris@63 59
Chris@62 60 QFont font(pluginBox->font());
Chris@62 61 font.setBold(true);
Chris@62 62
Chris@62 63 QLabel *nameLabel = new QLabel(plugin->getDescription().c_str());
Chris@146 64 nameLabel->setWordWrap(true);
Chris@62 65 nameLabel->setFont(font);
Chris@62 66
Chris@62 67 QLabel *makerLabel = new QLabel(plugin->getMaker().c_str());
Chris@146 68 makerLabel->setWordWrap(true);
Chris@62 69
Chris@62 70 QLabel *versionLabel = new QLabel(QString("%1")
Chris@62 71 .arg(plugin->getPluginVersion()));
Chris@146 72 versionLabel->setWordWrap(true);
Chris@62 73
Chris@62 74 QLabel *copyrightLabel = new QLabel(plugin->getCopyright().c_str());
Chris@146 75 copyrightLabel->setWordWrap(true);
Chris@62 76
Chris@63 77 QLabel *typeLabel = new QLabel(plugin->getType().c_str());
Chris@146 78 typeLabel->setWordWrap(true);
Chris@63 79 typeLabel->setFont(font);
Chris@63 80
Chris@163 81 int row = 0;
Chris@163 82
Chris@147 83 QLabel *label = new QLabel(tr("Name:"));
Chris@147 84 label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
Chris@163 85 subgrid->addWidget(label, row, 0);
Chris@163 86 subgrid->addWidget(nameLabel, row, 1);
Chris@163 87 row++;
Chris@62 88
Chris@147 89 label = new QLabel(tr("Type:"));
Chris@147 90 label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
Chris@163 91 subgrid->addWidget(label, row, 0);
Chris@163 92 subgrid->addWidget(typeLabel, row, 1);
Chris@163 93 row++;
Chris@62 94
Chris@163 95 m_outputLabel = new QLabel(tr("Output:"));
Chris@163 96 m_outputLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
Chris@163 97 subgrid->addWidget(m_outputLabel, row, 0);
Chris@163 98 m_outputValue = new QLabel;
Chris@163 99 subgrid->addWidget(m_outputValue, row, 1);
Chris@163 100 m_outputLabel->hide();
Chris@163 101 m_outputValue->hide();
Chris@163 102 row++;
Chris@62 103
Chris@147 104 label = new QLabel(tr("Maker:"));
Chris@147 105 label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
Chris@163 106 subgrid->addWidget(label, row, 0);
Chris@163 107 subgrid->addWidget(makerLabel, row, 1);
Chris@163 108 row++;
Chris@63 109
Chris@147 110 label = new QLabel(tr("Copyright: "));
Chris@147 111 label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
Chris@163 112 subgrid->addWidget(label, row, 0);
Chris@163 113 subgrid->addWidget(copyrightLabel, row, 1);
Chris@163 114 row++;
Chris@106 115
Chris@147 116 label = new QLabel(tr("Version:"));
Chris@147 117 label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
Chris@163 118 subgrid->addWidget(label, row, 0);
Chris@163 119 subgrid->addWidget(versionLabel, row, 1);
Chris@163 120 row++;
Chris@62 121
Chris@62 122 subgrid->setColumnStretch(1, 2);
Chris@62 123
Chris@62 124 QGroupBox *paramBox = new QGroupBox;
Chris@62 125 paramBox->setTitle(tr("Plugin Parameters"));
Chris@62 126 grid->addWidget(paramBox, 1, 0);
Chris@62 127 grid->setRowStretch(1, 10);
Chris@62 128
Chris@62 129 QHBoxLayout *paramLayout = new QHBoxLayout;
Chris@63 130 paramLayout->setMargin(0);
Chris@62 131 paramBox->setLayout(paramLayout);
Chris@62 132
Chris@149 133 QScrollArea *scroll = new QScrollArea;
Chris@149 134 scroll->setWidgetResizable(true);
Chris@149 135 scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
Chris@149 136 scroll->setFrameShape(QFrame::NoFrame);
Chris@149 137 paramLayout->addWidget(scroll);
Chris@149 138
Chris@62 139 m_parameterBox = new PluginParameterBox(m_plugin);
Chris@64 140 connect(m_parameterBox, SIGNAL(pluginConfigurationChanged(QString)),
Chris@64 141 this, SIGNAL(pluginConfigurationChanged(QString)));
Chris@149 142 scroll->setWidget(m_parameterBox);
Chris@62 143
Chris@143 144 m_advanced = new QFrame;
Chris@143 145 QVBoxLayout *advancedLayout = new QVBoxLayout;
Chris@143 146 advancedLayout->setMargin(0);
Chris@143 147 m_advanced->setLayout(advancedLayout);
Chris@143 148 grid->addWidget(m_advanced, 2, 0);
Chris@143 149
Chris@143 150 bool haveAdvanced = false;
Chris@143 151
Chris@163 152 m_channelBox = new QGroupBox;
Chris@163 153 m_channelBox->setTitle(tr("Channels"));
Chris@163 154 advancedLayout->addWidget(m_channelBox);
Chris@163 155 m_channelBox->setVisible(false);
Chris@163 156 m_haveChannelBoxData = false;
Chris@163 157
Chris@163 158 m_windowBox = new QGroupBox;
Chris@163 159 m_windowBox->setTitle(tr("Processing"));
Chris@163 160 advancedLayout->addWidget(m_windowBox);
Chris@163 161 m_windowBox->setVisible(false);
Chris@163 162 m_haveWindowBoxData = false;
Chris@163 163
Chris@163 164 QHBoxLayout *hbox = new QHBoxLayout;
Chris@163 165 grid->addLayout(hbox, 4, 0);
Chris@163 166
Chris@163 167 m_advancedVisible = false;
Chris@163 168
Chris@163 169 m_advancedButton = new QPushButton(tr("Advanced >>"));
Chris@163 170 m_advancedButton->setCheckable(true);
Chris@163 171 connect(m_advancedButton, SIGNAL(clicked()), this, SLOT(advancedToggled()));
Chris@163 172
Chris@163 173 QSettings settings;
Chris@163 174 settings.beginGroup("PluginParameterDialog");
Chris@163 175 m_advancedVisible = settings.value("advancedvisible", false).toBool();
Chris@163 176 settings.endGroup();
Chris@163 177
Chris@163 178 m_advanced->setVisible(false);
Chris@163 179
Chris@163 180 hbox->addWidget(m_advancedButton);
Chris@163 181 m_advancedButton->hide();
Chris@163 182
Chris@163 183 QPushButton *ok = new QPushButton(tr("OK"));
Chris@163 184 QPushButton *cancel = new QPushButton(tr("Cancel"));
Chris@163 185 hbox->addStretch(10);
Chris@163 186 hbox->addWidget(ok);
Chris@163 187 hbox->addWidget(cancel);
Chris@163 188 connect(ok, SIGNAL(clicked()), this, SLOT(accept()));
Chris@163 189 connect(cancel, SIGNAL(clicked()), this, SLOT(reject()));
Chris@163 190
Chris@163 191 setAdvancedVisible(m_advancedVisible);
Chris@163 192 }
Chris@163 193
Chris@163 194 PluginParameterDialog::~PluginParameterDialog()
Chris@163 195 {
Chris@163 196 }
Chris@163 197
Chris@163 198
Chris@163 199 void
Chris@163 200 PluginParameterDialog::setOutputLabel(QString text)
Chris@163 201 {
Chris@163 202 if (text == "") {
Chris@163 203 m_outputLabel->hide();
Chris@163 204 m_outputValue->hide();
Chris@163 205 } else {
Chris@163 206 m_outputValue->setText(text);
Chris@163 207 m_outputValue->setWordWrap(true);
Chris@163 208 m_outputLabel->show();
Chris@163 209 m_outputValue->show();
Chris@163 210 }
Chris@163 211 /*
Chris@163 212 QLabel *outputLabel = 0;
Chris@163 213
Chris@163 214 if (output != "") {
Chris@163 215
Chris@163 216 Vamp::PluginHostAdapter *fePlugin = dynamic_cast<Vamp::PluginHostAdapter *>(m_plugin);
Chris@163 217
Chris@163 218 if (fePlugin) {
Chris@163 219
Chris@163 220 std::vector<Vamp::Plugin::OutputDescriptor> od =
Chris@163 221 fePlugin->getOutputDescriptors();
Chris@163 222
Chris@163 223 if (od.size() > 1) {
Chris@163 224
Chris@163 225 for (size_t i = 0; i < od.size(); ++i) {
Chris@163 226 if (od[i].name == output.toStdString()) {
Chris@163 227 outputLabel = new QLabel(od[i].description.c_str());
Chris@163 228 outputLabel->setWordWrap(true);
Chris@163 229 break;
Chris@163 230 }
Chris@163 231 }
Chris@163 232 }
Chris@163 233 }
Chris@163 234 }
Chris@163 235 */
Chris@163 236 }
Chris@163 237
Chris@163 238 void
Chris@163 239 PluginParameterDialog::setChannelArrangement(int sourceChannels,
Chris@163 240 int targetChannels,
Chris@163 241 int defaultChannel)
Chris@163 242 {
Chris@163 243 m_channel = defaultChannel;
Chris@163 244
Chris@69 245 if (sourceChannels != targetChannels) {
Chris@69 246
Chris@69 247 // At the moment we can only cope with the case where
Chris@69 248 // sourceChannels > targetChannels and targetChannels == 1
Chris@69 249
Chris@69 250 if (sourceChannels < targetChannels) {
Chris@69 251
Chris@69 252 QMessageBox::warning
Chris@163 253 (parentWidget(),
Chris@69 254 tr("Channel mismatch"),
Chris@69 255 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")),
Chris@69 256 QMessageBox::Ok,
Chris@69 257 QMessageBox::NoButton);
Chris@69 258
Chris@69 259 } else {
Chris@69 260
Chris@163 261 if (m_haveChannelBoxData) {
Chris@163 262 std::cerr << "WARNING: PluginParameterDialog::setChannelArrangement: Calling more than once on same dialog is not currently implemented" << std::endl;
Chris@163 263 return;
Chris@163 264 }
Chris@69 265
Chris@69 266 QVBoxLayout *channelLayout = new QVBoxLayout;
Chris@163 267 m_channelBox->setLayout(channelLayout);
Chris@69 268
Chris@69 269 if (targetChannels != 1) {
Chris@69 270
Chris@69 271 channelLayout->addWidget
Chris@69 272 (new QLabel(tr("This plugin accepts no more than %1 input channels,\nbut %2 are available. Only the first %3 will be used.\n")
Chris@69 273 .arg(targetChannels)
Chris@69 274 .arg(sourceChannels)
Chris@69 275 .arg(targetChannels)));
Chris@69 276
Chris@69 277 } else {
Chris@69 278
Chris@69 279 channelLayout->addWidget(new QLabel(tr("This plugin only has a single channel input,\nbut the source has %1 channels.").arg(sourceChannels)));
Chris@69 280
Chris@69 281 QComboBox *channelCombo = new QComboBox;
Chris@76 282 channelCombo->addItem(tr("Use mean of source channels"));
Chris@69 283 for (int i = 0; i < sourceChannels; ++i) {
Chris@69 284 channelCombo->addItem(tr("Use channel %1 only").arg(i + 1));
Chris@69 285 }
Chris@69 286
Chris@69 287 connect(channelCombo, SIGNAL(activated(int)),
Chris@69 288 this, SLOT(channelComboChanged(int)));
Chris@69 289
Chris@69 290 channelLayout->addWidget(channelCombo);
Chris@69 291 }
Chris@163 292
Chris@163 293 m_channelBox->setVisible(true);
Chris@163 294 m_haveChannelBoxData = true;
Chris@163 295 m_advancedButton->show();
Chris@69 296 }
Chris@69 297 }
Chris@69 298
Chris@163 299 setAdvancedVisible(m_advancedVisible);
Chris@163 300 }
Chris@163 301
Chris@163 302 void
Chris@163 303 PluginParameterDialog::setShowProcessingOptions(bool showWindowSize,
Chris@163 304 bool showFrequencyDomainOptions)
Chris@163 305 {
Chris@163 306 if (m_haveWindowBoxData) {
Chris@163 307 std::cerr << "WARNING: PluginParameterDialog::setShowProcessingOptions: Calling more than once on same dialog is not currently implemented" << std::endl;
Chris@163 308 return;
Chris@163 309 }
Chris@163 310
Chris@140 311 if (showWindowSize) {
Chris@140 312
Chris@147 313 Vamp::PluginHostAdapter *fePlugin = dynamic_cast<Vamp::PluginHostAdapter *>(m_plugin);
Chris@140 314 int size = 1024;
Chris@140 315 int increment = 1024;
Chris@140 316 if (fePlugin) {
Chris@140 317 size = fePlugin->getPreferredBlockSize();
Chris@146 318 std::cerr << "Feature extraction plugin \"" << fePlugin->getDescription() << "\" reports preferred block size as " << size << std::endl;
Chris@140 319 if (size == 0) size = 1024;
Chris@140 320 increment = fePlugin->getPreferredStepSize();
Chris@146 321 if (increment == 0) {
Chris@146 322 if (fePlugin->getInputDomain() == Vamp::Plugin::TimeDomain) {
Chris@146 323 increment = size;
Chris@146 324 } else {
Chris@146 325 increment = size/2;
Chris@146 326 }
Chris@146 327 }
Chris@140 328 }
Chris@140 329
Chris@140 330 QGridLayout *windowLayout = new QGridLayout;
Chris@163 331 m_windowBox->setLayout(windowLayout);
Chris@140 332
Chris@140 333 if (showFrequencyDomainOptions) {
Chris@140 334 windowLayout->addWidget(new QLabel(tr("Window size:")), 0, 0);
Chris@140 335 } else {
Chris@140 336 windowLayout->addWidget(new QLabel(tr("Audio frames per block:")), 0, 0);
Chris@140 337 }
Chris@140 338
Chris@143 339 std::cerr << "size: " << size << ", increment: " << increment << std::endl;
Chris@143 340
Chris@140 341 QComboBox *blockSizeCombo = new QComboBox;
Chris@140 342 blockSizeCombo->setEditable(true);
Chris@147 343 bool found = false;
Chris@143 344 for (int i = 0; i < 14; ++i) {
Chris@140 345 int val = pow(2, i + 3);
Chris@140 346 blockSizeCombo->addItem(QString("%1").arg(val));
Chris@147 347 if (val == size) {
Chris@147 348 blockSizeCombo->setCurrentIndex(i);
Chris@147 349 found = true;
Chris@147 350 }
Chris@147 351 }
Chris@147 352 if (!found) {
Chris@147 353 blockSizeCombo->addItem(QString("%1").arg(size));
Chris@147 354 blockSizeCombo->setCurrentIndex(blockSizeCombo->count() - 1);
Chris@140 355 }
Chris@143 356 blockSizeCombo->setValidator(new QIntValidator(1, pow(2, 18), this));
Chris@155 357 connect(blockSizeCombo, SIGNAL(editTextChanged(const QString &)),
Chris@155 358 this, SLOT(blockSizeComboChanged(const QString &)));
Chris@140 359 windowLayout->addWidget(blockSizeCombo, 0, 1);
Chris@140 360
Chris@148 361 windowLayout->addWidget(new QLabel(tr("Window increment:")), 1, 0);
Chris@148 362
Chris@148 363 QComboBox *incrementCombo = new QComboBox;
Chris@148 364 incrementCombo->setEditable(true);
Chris@148 365 found = false;
Chris@148 366 for (int i = 0; i < 14; ++i) {
Chris@148 367 int val = pow(2, i + 3);
Chris@148 368 incrementCombo->addItem(QString("%1").arg(val));
Chris@148 369 if (val == increment) {
Chris@148 370 incrementCombo->setCurrentIndex(i);
Chris@148 371 found = true;
Chris@148 372 }
Chris@148 373 }
Chris@148 374 if (!found) {
Chris@148 375 incrementCombo->addItem(QString("%1").arg(increment));
Chris@148 376 incrementCombo->setCurrentIndex(incrementCombo->count() - 1);
Chris@148 377 }
Chris@148 378 incrementCombo->setValidator(new QIntValidator(1, pow(2, 18), this));
Chris@155 379 connect(incrementCombo, SIGNAL(editTextChanged(const QString &)),
Chris@155 380 this, SLOT(incrementComboChanged(const QString &)));
Chris@148 381 windowLayout->addWidget(incrementCombo, 1, 1);
Chris@148 382
Chris@140 383 if (showFrequencyDomainOptions) {
Chris@140 384
Chris@140 385 windowLayout->addWidget(new QLabel(tr("Window shape:")), 2, 0);
Chris@140 386 WindowTypeSelector *windowTypeSelector = new WindowTypeSelector;
Chris@145 387 connect(windowTypeSelector, SIGNAL(windowTypeChanged(WindowType type)),
Chris@145 388 this, SLOT(windowTypeChanged(type)));
Chris@140 389 windowLayout->addWidget(windowTypeSelector, 2, 1);
Chris@140 390 }
Chris@163 391
Chris@163 392 m_windowBox->setVisible(true);
Chris@163 393 m_haveWindowBoxData = true;
Chris@163 394 m_advancedButton->show();
Chris@140 395 }
Chris@140 396
Chris@163 397 setAdvancedVisible(m_advancedVisible);
Chris@62 398 }
Chris@62 399
Chris@69 400 void
Chris@145 401 PluginParameterDialog::getProcessingParameters(size_t &blockSize) const
Chris@145 402 {
Chris@145 403 blockSize = m_blockSize;
Chris@145 404 return;
Chris@145 405 }
Chris@145 406
Chris@145 407 void
Chris@145 408 PluginParameterDialog::getProcessingParameters(size_t &stepSize,
Chris@145 409 size_t &blockSize,
Chris@145 410 WindowType &windowType) const
Chris@145 411 {
Chris@145 412 stepSize = m_stepSize;
Chris@145 413 blockSize = m_blockSize;
Chris@145 414 windowType = m_windowType;
Chris@146 415 return;
Chris@145 416 }
Chris@145 417
Chris@145 418 void
Chris@155 419 PluginParameterDialog::blockSizeComboChanged(const QString &text)
Chris@145 420 {
Chris@145 421 m_blockSize = text.toInt();
Chris@146 422 std::cerr << "Block size changed to " << m_blockSize << std::endl;
Chris@145 423 }
Chris@145 424
Chris@145 425 void
Chris@155 426 PluginParameterDialog::incrementComboChanged(const QString &text)
Chris@145 427 {
Chris@145 428 m_stepSize = text.toInt();
Chris@146 429 //!!! rename increment to step size throughout
Chris@147 430 std::cerr << "Increment changed to " << m_stepSize << std::endl;
Chris@145 431 }
Chris@145 432
Chris@145 433 void
Chris@145 434 PluginParameterDialog::windowTypeChanged(WindowType type)
Chris@145 435 {
Chris@145 436 m_windowType = type;
Chris@145 437 }
Chris@145 438
Chris@145 439 void
Chris@143 440 PluginParameterDialog::advancedToggled()
Chris@143 441 {
Chris@163 442 setAdvancedVisible(!m_advancedVisible);
Chris@163 443 }
Chris@143 444
Chris@163 445 void
Chris@163 446 PluginParameterDialog::setAdvancedVisible(bool visible)
Chris@163 447 {
Chris@143 448 m_advanced->setVisible(visible);
Chris@143 449
Chris@163 450 if (visible) {
Chris@163 451 m_advancedButton->setText(tr("Advanced <<"));
Chris@163 452 m_advancedButton->setChecked(true);
Chris@163 453 } else {
Chris@163 454 m_advancedButton->setText(tr("Advanced >>"));
Chris@163 455 m_advancedButton->setChecked(false);
Chris@163 456 }
Chris@143 457
Chris@143 458 QSettings settings;
Chris@143 459 settings.beginGroup("PluginParameterDialog");
Chris@143 460 settings.setValue("advancedvisible", visible);
Chris@143 461 settings.endGroup();
Chris@143 462
Chris@143 463 std::cerr << "resize to " << sizeHint().width() << " x " << sizeHint().height() << std::endl;
Chris@143 464
Chris@149 465 setMinimumHeight(sizeHint().height());
Chris@163 466 adjustSize();
Chris@163 467
Chris@163 468 m_advancedVisible = visible;
Chris@163 469
Chris@163 470 // if (visible) setMaximumHeight(sizeHint().height());
Chris@163 471 // adjustSize();
Chris@143 472 }
Chris@143 473
Chris@143 474 void
Chris@69 475 PluginParameterDialog::channelComboChanged(int index)
Chris@69 476 {
Chris@69 477 m_channel = index - 1;
Chris@69 478 }
Chris@69 479