annotate widgets/PluginParameterDialog.cpp @ 150:b1a3a9400284

* Add a bit of resistance to pane dragging so as to make it harder to inadvertently drag in the other axis from the one you intended
author Chris Cannam
date Fri, 22 Sep 2006 16:46:10 +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