annotate widgets/PluginParameterDialog.cpp @ 151:8f51db2434dc

* Pull alphabetical categorisation code out into a SubdividingMenu class
author Chris Cannam
date Mon, 25 Sep 2006 11:21:12 +0000
parents 3dade4b025b7
children 8c730f49b9b3
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@69 36 int sourceChannels,
Chris@69 37 int targetChannels,
Chris@69 38 int defaultChannel,
Chris@106 39 QString output,
Chris@140 40 bool showWindowSize,
Chris@140 41 bool showFrequencyDomainOptions,
Chris@62 42 QWidget *parent) :
Chris@62 43 QDialog(parent),
Chris@62 44 m_plugin(plugin),
Chris@69 45 m_channel(defaultChannel),
Chris@145 46 m_stepSize(0),
Chris@145 47 m_blockSize(0),
Chris@145 48 m_windowType(HanningWindow),
Chris@62 49 m_parameterBox(0)
Chris@62 50 {
Chris@122 51 setWindowTitle(tr("Plugin Parameters"));
Chris@122 52
Chris@62 53 QGridLayout *grid = new QGridLayout;
Chris@62 54 setLayout(grid);
Chris@62 55
Chris@62 56 QGroupBox *pluginBox = new QGroupBox;
Chris@62 57 pluginBox->setTitle(tr("Plugin"));
Chris@62 58 grid->addWidget(pluginBox, 0, 0);
Chris@62 59
Chris@62 60 QGridLayout *subgrid = new QGridLayout;
Chris@62 61 pluginBox->setLayout(subgrid);
Chris@62 62
Chris@63 63 subgrid->setSpacing(0);
Chris@63 64 subgrid->setMargin(10);
Chris@63 65
Chris@62 66 QFont font(pluginBox->font());
Chris@62 67 font.setBold(true);
Chris@62 68
Chris@62 69 QLabel *nameLabel = new QLabel(plugin->getDescription().c_str());
Chris@146 70 nameLabel->setWordWrap(true);
Chris@62 71 nameLabel->setFont(font);
Chris@62 72
Chris@62 73 QLabel *makerLabel = new QLabel(plugin->getMaker().c_str());
Chris@146 74 makerLabel->setWordWrap(true);
Chris@62 75
Chris@106 76 QLabel *outputLabel = 0;
Chris@106 77
Chris@106 78 if (output != "") {
Chris@106 79
Chris@147 80 Vamp::PluginHostAdapter *fePlugin = dynamic_cast<Vamp::PluginHostAdapter *>(m_plugin);
Chris@106 81
Chris@106 82 if (fePlugin) {
Chris@106 83
Chris@106 84 std::vector<Vamp::Plugin::OutputDescriptor> od =
Chris@106 85 fePlugin->getOutputDescriptors();
Chris@106 86
Chris@106 87 if (od.size() > 1) {
Chris@106 88
Chris@106 89 for (size_t i = 0; i < od.size(); ++i) {
Chris@106 90 if (od[i].name == output.toStdString()) {
Chris@106 91 outputLabel = new QLabel(od[i].description.c_str());
Chris@146 92 outputLabel->setWordWrap(true);
Chris@106 93 break;
Chris@106 94 }
Chris@106 95 }
Chris@106 96 }
Chris@106 97 }
Chris@106 98 }
Chris@106 99
Chris@62 100 QLabel *versionLabel = new QLabel(QString("%1")
Chris@62 101 .arg(plugin->getPluginVersion()));
Chris@146 102 versionLabel->setWordWrap(true);
Chris@62 103
Chris@62 104 QLabel *copyrightLabel = new QLabel(plugin->getCopyright().c_str());
Chris@146 105 copyrightLabel->setWordWrap(true);
Chris@62 106
Chris@63 107 QLabel *typeLabel = new QLabel(plugin->getType().c_str());
Chris@146 108 typeLabel->setWordWrap(true);
Chris@63 109 typeLabel->setFont(font);
Chris@63 110
Chris@147 111 QLabel *label = new QLabel(tr("Name:"));
Chris@147 112 label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
Chris@147 113 subgrid->addWidget(label, 0, 0);
Chris@62 114 subgrid->addWidget(nameLabel, 0, 1);
Chris@62 115
Chris@147 116 label = new QLabel(tr("Type:"));
Chris@147 117 label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
Chris@147 118 subgrid->addWidget(label, 1, 0);
Chris@63 119 subgrid->addWidget(typeLabel, 1, 1);
Chris@62 120
Chris@106 121 int outputOffset = 0;
Chris@106 122 if (outputLabel) {
Chris@147 123 label = new QLabel(tr("Output:"));
Chris@147 124 label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
Chris@147 125 subgrid->addWidget(label, 2, 0);
Chris@106 126 subgrid->addWidget(outputLabel, 2, 1);
Chris@106 127 outputOffset = 1;
Chris@106 128 }
Chris@62 129
Chris@147 130 label = new QLabel(tr("Maker:"));
Chris@147 131 label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
Chris@147 132 subgrid->addWidget(label, 2 + outputOffset, 0);
Chris@106 133 subgrid->addWidget(makerLabel, 2 + outputOffset, 1);
Chris@63 134
Chris@147 135 label = new QLabel(tr("Copyright: "));
Chris@147 136 label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
Chris@147 137 subgrid->addWidget(label, 3 + outputOffset, 0);
Chris@106 138 subgrid->addWidget(copyrightLabel, 3 + outputOffset, 1);
Chris@106 139
Chris@147 140 label = new QLabel(tr("Version:"));
Chris@147 141 label->setAlignment(Qt::AlignTop | Qt::AlignLeft);
Chris@147 142 subgrid->addWidget(label, 4 + outputOffset, 0);
Chris@106 143 subgrid->addWidget(versionLabel, 4 + outputOffset, 1);
Chris@62 144
Chris@62 145 subgrid->setColumnStretch(1, 2);
Chris@62 146
Chris@62 147 QGroupBox *paramBox = new QGroupBox;
Chris@62 148 paramBox->setTitle(tr("Plugin Parameters"));
Chris@62 149 grid->addWidget(paramBox, 1, 0);
Chris@62 150 grid->setRowStretch(1, 10);
Chris@62 151
Chris@62 152 QHBoxLayout *paramLayout = new QHBoxLayout;
Chris@63 153 paramLayout->setMargin(0);
Chris@62 154 paramBox->setLayout(paramLayout);
Chris@62 155
Chris@149 156 QScrollArea *scroll = new QScrollArea;
Chris@149 157 scroll->setWidgetResizable(true);
Chris@149 158 scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
Chris@149 159 scroll->setFrameShape(QFrame::NoFrame);
Chris@149 160 paramLayout->addWidget(scroll);
Chris@149 161
Chris@62 162 m_parameterBox = new PluginParameterBox(m_plugin);
Chris@64 163 connect(m_parameterBox, SIGNAL(pluginConfigurationChanged(QString)),
Chris@64 164 this, SIGNAL(pluginConfigurationChanged(QString)));
Chris@149 165 scroll->setWidget(m_parameterBox);
Chris@62 166
Chris@143 167 m_advanced = new QFrame;
Chris@143 168 QVBoxLayout *advancedLayout = new QVBoxLayout;
Chris@143 169 advancedLayout->setMargin(0);
Chris@143 170 m_advanced->setLayout(advancedLayout);
Chris@143 171 grid->addWidget(m_advanced, 2, 0);
Chris@143 172
Chris@143 173 bool haveAdvanced = false;
Chris@143 174
Chris@69 175 if (sourceChannels != targetChannels) {
Chris@69 176
Chris@69 177 // At the moment we can only cope with the case where
Chris@69 178 // sourceChannels > targetChannels and targetChannels == 1
Chris@69 179
Chris@69 180 if (sourceChannels < targetChannels) {
Chris@69 181
Chris@69 182 QMessageBox::warning
Chris@69 183 (parent,
Chris@69 184 tr("Channel mismatch"),
Chris@69 185 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 186 QMessageBox::Ok,
Chris@69 187 QMessageBox::NoButton);
Chris@69 188
Chris@69 189 } else {
Chris@69 190
Chris@69 191 QGroupBox *channelBox = new QGroupBox;
Chris@69 192 channelBox->setTitle(tr("Channels"));
Chris@143 193 advancedLayout->addWidget(channelBox);
Chris@143 194 haveAdvanced = true;
Chris@69 195
Chris@69 196 QVBoxLayout *channelLayout = new QVBoxLayout;
Chris@69 197 channelBox->setLayout(channelLayout);
Chris@69 198
Chris@69 199 if (targetChannels != 1) {
Chris@69 200
Chris@69 201 channelLayout->addWidget
Chris@69 202 (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 203 .arg(targetChannels)
Chris@69 204 .arg(sourceChannels)
Chris@69 205 .arg(targetChannels)));
Chris@69 206
Chris@69 207 } else {
Chris@69 208
Chris@69 209 channelLayout->addWidget(new QLabel(tr("This plugin only has a single channel input,\nbut the source has %1 channels.").arg(sourceChannels)));
Chris@69 210
Chris@69 211 QComboBox *channelCombo = new QComboBox;
Chris@76 212 channelCombo->addItem(tr("Use mean of source channels"));
Chris@69 213 for (int i = 0; i < sourceChannels; ++i) {
Chris@69 214 channelCombo->addItem(tr("Use channel %1 only").arg(i + 1));
Chris@69 215 }
Chris@69 216
Chris@69 217 connect(channelCombo, SIGNAL(activated(int)),
Chris@69 218 this, SLOT(channelComboChanged(int)));
Chris@69 219
Chris@69 220 channelLayout->addWidget(channelCombo);
Chris@69 221 }
Chris@69 222 }
Chris@69 223 }
Chris@69 224
Chris@140 225 if (showWindowSize) {
Chris@140 226
Chris@147 227 Vamp::PluginHostAdapter *fePlugin = dynamic_cast<Vamp::PluginHostAdapter *>(m_plugin);
Chris@140 228 int size = 1024;
Chris@140 229 int increment = 1024;
Chris@140 230 if (fePlugin) {
Chris@140 231 size = fePlugin->getPreferredBlockSize();
Chris@146 232 std::cerr << "Feature extraction plugin \"" << fePlugin->getDescription() << "\" reports preferred block size as " << size << std::endl;
Chris@140 233 if (size == 0) size = 1024;
Chris@140 234 increment = fePlugin->getPreferredStepSize();
Chris@146 235 if (increment == 0) {
Chris@146 236 if (fePlugin->getInputDomain() == Vamp::Plugin::TimeDomain) {
Chris@146 237 increment = size;
Chris@146 238 } else {
Chris@146 239 increment = size/2;
Chris@146 240 }
Chris@146 241 }
Chris@146 242 } else {
Chris@147 243 std::cerr << "Plugin " << plugin << " is not a feature extraction plugin (it's a " << typeid(*plugin).name() << ")" << std::endl;//!!!
Chris@140 244 }
Chris@140 245
Chris@140 246 QGroupBox *windowBox = new QGroupBox;
Chris@140 247 windowBox->setTitle(tr("Processing"));
Chris@143 248 advancedLayout->addWidget(windowBox);
Chris@143 249 haveAdvanced = true;
Chris@140 250
Chris@140 251 QGridLayout *windowLayout = new QGridLayout;
Chris@140 252 windowBox->setLayout(windowLayout);
Chris@140 253
Chris@140 254 if (showFrequencyDomainOptions) {
Chris@140 255 windowLayout->addWidget(new QLabel(tr("Window size:")), 0, 0);
Chris@140 256 } else {
Chris@140 257 windowLayout->addWidget(new QLabel(tr("Audio frames per block:")), 0, 0);
Chris@140 258 }
Chris@140 259
Chris@143 260 std::cerr << "size: " << size << ", increment: " << increment << std::endl;
Chris@143 261
Chris@145 262 //!!! deal with block and step sizes (coming from the plugin's
Chris@145 263 // preferences) that don't fit into the default list
Chris@145 264
Chris@140 265 QComboBox *blockSizeCombo = new QComboBox;
Chris@140 266 blockSizeCombo->setEditable(true);
Chris@147 267 bool found = false;
Chris@143 268 for (int i = 0; i < 14; ++i) {
Chris@140 269 int val = pow(2, i + 3);
Chris@140 270 blockSizeCombo->addItem(QString("%1").arg(val));
Chris@147 271 if (val == size) {
Chris@147 272 blockSizeCombo->setCurrentIndex(i);
Chris@147 273 found = true;
Chris@147 274 }
Chris@147 275 }
Chris@147 276 if (!found) {
Chris@147 277 blockSizeCombo->addItem(QString("%1").arg(size));
Chris@147 278 blockSizeCombo->setCurrentIndex(blockSizeCombo->count() - 1);
Chris@140 279 }
Chris@143 280 blockSizeCombo->setValidator(new QIntValidator(1, pow(2, 18), this));
Chris@146 281 connect(blockSizeCombo, SIGNAL(textChanged(QString)),
Chris@145 282 this, SLOT(blockSizeComboChanged(QString)));
Chris@140 283 windowLayout->addWidget(blockSizeCombo, 0, 1);
Chris@140 284
Chris@148 285 windowLayout->addWidget(new QLabel(tr("Window increment:")), 1, 0);
Chris@148 286
Chris@148 287 QComboBox *incrementCombo = new QComboBox;
Chris@148 288 incrementCombo->setEditable(true);
Chris@148 289 found = false;
Chris@148 290 for (int i = 0; i < 14; ++i) {
Chris@148 291 int val = pow(2, i + 3);
Chris@148 292 incrementCombo->addItem(QString("%1").arg(val));
Chris@148 293 if (val == increment) {
Chris@148 294 incrementCombo->setCurrentIndex(i);
Chris@148 295 found = true;
Chris@148 296 }
Chris@148 297 }
Chris@148 298 if (!found) {
Chris@148 299 incrementCombo->addItem(QString("%1").arg(increment));
Chris@148 300 incrementCombo->setCurrentIndex(incrementCombo->count() - 1);
Chris@148 301 }
Chris@148 302 incrementCombo->setValidator(new QIntValidator(1, pow(2, 18), this));
Chris@148 303 connect(incrementCombo, SIGNAL(textChanged(QString)),
Chris@148 304 this, SLOT(incrementComboChanged(QString)));
Chris@148 305 windowLayout->addWidget(incrementCombo, 1, 1);
Chris@148 306
Chris@140 307 if (showFrequencyDomainOptions) {
Chris@140 308
Chris@140 309 windowLayout->addWidget(new QLabel(tr("Window shape:")), 2, 0);
Chris@140 310 WindowTypeSelector *windowTypeSelector = new WindowTypeSelector;
Chris@145 311 connect(windowTypeSelector, SIGNAL(windowTypeChanged(WindowType type)),
Chris@145 312 this, SLOT(windowTypeChanged(type)));
Chris@140 313 windowLayout->addWidget(windowTypeSelector, 2, 1);
Chris@140 314 }
Chris@140 315 }
Chris@140 316
Chris@62 317 QHBoxLayout *hbox = new QHBoxLayout;
Chris@140 318 grid->addLayout(hbox, 4, 0);
Chris@143 319
Chris@143 320 bool advancedVisible = false;
Chris@143 321
Chris@143 322 if (haveAdvanced) {
Chris@143 323
Chris@143 324 m_advancedButton = new QPushButton(tr("Advanced >>"));
Chris@143 325 m_advancedButton->setCheckable(true);
Chris@143 326 connect(m_advancedButton, SIGNAL(clicked()), this, SLOT(advancedToggled()));
Chris@143 327
Chris@143 328 QSettings settings;
Chris@143 329 settings.beginGroup("PluginParameterDialog");
Chris@143 330 advancedVisible = settings.value("advancedvisible", false).toBool();
Chris@143 331 settings.endGroup();
Chris@143 332
Chris@143 333 m_advanced->setVisible(false);
Chris@143 334
Chris@143 335 hbox->addWidget(m_advancedButton);
Chris@143 336 }
Chris@143 337
Chris@62 338 QPushButton *ok = new QPushButton(tr("OK"));
Chris@62 339 QPushButton *cancel = new QPushButton(tr("Cancel"));
Chris@62 340 hbox->addStretch(10);
Chris@62 341 hbox->addWidget(ok);
Chris@62 342 hbox->addWidget(cancel);
Chris@62 343 connect(ok, SIGNAL(clicked()), this, SLOT(accept()));
Chris@62 344 connect(cancel, SIGNAL(clicked()), this, SLOT(reject()));
Chris@143 345
Chris@143 346 if (advancedVisible) {
Chris@143 347 m_advancedButton->setChecked(true);
Chris@143 348 advancedToggled();
Chris@143 349 }
Chris@62 350 }
Chris@62 351
Chris@62 352 PluginParameterDialog::~PluginParameterDialog()
Chris@62 353 {
Chris@62 354 }
Chris@62 355
Chris@69 356 void
Chris@145 357 PluginParameterDialog::getProcessingParameters(size_t &blockSize) const
Chris@145 358 {
Chris@145 359 blockSize = m_blockSize;
Chris@145 360 return;
Chris@145 361 }
Chris@145 362
Chris@145 363 void
Chris@145 364 PluginParameterDialog::getProcessingParameters(size_t &stepSize,
Chris@145 365 size_t &blockSize,
Chris@145 366 WindowType &windowType) const
Chris@145 367 {
Chris@145 368 stepSize = m_stepSize;
Chris@145 369 blockSize = m_blockSize;
Chris@145 370 windowType = m_windowType;
Chris@146 371 return;
Chris@145 372 }
Chris@145 373
Chris@145 374 void
Chris@145 375 PluginParameterDialog::blockSizeComboChanged(QString text)
Chris@145 376 {
Chris@145 377 m_blockSize = text.toInt();
Chris@146 378 std::cerr << "Block size changed to " << m_blockSize << std::endl;
Chris@145 379 }
Chris@145 380
Chris@145 381 void
Chris@145 382 PluginParameterDialog::incrementComboChanged(QString text)
Chris@145 383 {
Chris@145 384 m_stepSize = text.toInt();
Chris@146 385 //!!! rename increment to step size throughout
Chris@147 386 std::cerr << "Increment changed to " << m_stepSize << std::endl;
Chris@145 387 }
Chris@145 388
Chris@145 389 void
Chris@145 390 PluginParameterDialog::windowTypeChanged(WindowType type)
Chris@145 391 {
Chris@145 392 m_windowType = type;
Chris@145 393 }
Chris@145 394
Chris@145 395 void
Chris@143 396 PluginParameterDialog::advancedToggled()
Chris@143 397 {
Chris@143 398 bool visible = !m_advanced->isVisible();
Chris@143 399
Chris@143 400 m_advanced->setVisible(visible);
Chris@143 401
Chris@143 402 if (visible) m_advancedButton->setText(tr("Advanced <<"));
Chris@143 403 else m_advancedButton->setText(tr("Advanced >>"));
Chris@143 404
Chris@143 405 QSettings settings;
Chris@143 406 settings.beginGroup("PluginParameterDialog");
Chris@143 407 settings.setValue("advancedvisible", visible);
Chris@143 408 settings.endGroup();
Chris@143 409
Chris@143 410 std::cerr << "resize to " << sizeHint().width() << " x " << sizeHint().height() << std::endl;
Chris@143 411
Chris@149 412 setMinimumHeight(sizeHint().height());
Chris@149 413 if (visible) setMaximumHeight(sizeHint().height());
Chris@143 414 }
Chris@143 415
Chris@143 416 void
Chris@69 417 PluginParameterDialog::channelComboChanged(int index)
Chris@69 418 {
Chris@69 419 m_channel = index - 1;
Chris@69 420 }
Chris@69 421