| Chris@1285 | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */ | 
| Chris@1285 | 2 | 
| Chris@1285 | 3 /* | 
| Chris@1285 | 4     Sonic Visualiser | 
| Chris@1285 | 5     An audio file viewer and annotation editor. | 
| Chris@1285 | 6     Centre for Digital Music, Queen Mary, University of London. | 
| Chris@1285 | 7 | 
| Chris@1285 | 8     This program is free software; you can redistribute it and/or | 
| Chris@1285 | 9     modify it under the terms of the GNU General Public License as | 
| Chris@1285 | 10     published by the Free Software Foundation; either version 2 of the | 
| Chris@1285 | 11     License, or (at your option) any later version.  See the file | 
| Chris@1285 | 12     COPYING included with this distribution for more information. | 
| Chris@1285 | 13 */ | 
| Chris@1285 | 14 | 
| Chris@1285 | 15 #include "PluginPathConfigurator.h" | 
| Chris@1292 | 16 #include "PluginReviewDialog.h" | 
| Chris@1285 | 17 | 
| Chris@1285 | 18 #include <QPushButton> | 
| Chris@1287 | 19 #include <QListWidget> | 
| Chris@1288 | 20 #include <QGridLayout> | 
| Chris@1289 | 21 #include <QComboBox> | 
| Chris@1285 | 22 #include <QLabel> | 
| Chris@1290 | 23 #include <QCheckBox> | 
| Chris@1291 | 24 #include <QFileDialog> | 
| Chris@1285 | 25 | 
| Chris@1285 | 26 #include "IconLoader.h" | 
| Chris@1285 | 27 #include "WidgetScale.h" | 
| Chris@1285 | 28 | 
| Chris@1293 | 29 #include "plugin/PluginPathSetter.h" | 
| Chris@1293 | 30 | 
| Chris@1285 | 31 PluginPathConfigurator::PluginPathConfigurator(QWidget *parent) : | 
| Chris@1287 | 32     QFrame(parent) | 
| Chris@1285 | 33 { | 
| Chris@1285 | 34     m_layout = new QGridLayout; | 
| Chris@1285 | 35     setLayout(m_layout); | 
| Chris@1292 | 36 | 
| Chris@1291 | 37     QHBoxLayout *buttons = new QHBoxLayout; | 
| Chris@1291 | 38 | 
| Chris@1291 | 39     m_down = new QPushButton; | 
| Chris@1291 | 40     m_down->setIcon(IconLoader().load("down")); | 
| Chris@1291 | 41     m_down->setToolTip(tr("Move the selected location later in the list")); | 
| Chris@1291 | 42     connect(m_down, SIGNAL(clicked()), this, SLOT(downClicked())); | 
| Chris@1291 | 43     buttons->addWidget(m_down); | 
| Chris@1291 | 44 | 
| Chris@1291 | 45     m_up = new QPushButton; | 
| Chris@1291 | 46     m_up->setIcon(IconLoader().load("up")); | 
| Chris@1291 | 47     m_up->setToolTip(tr("Move the selected location earlier in the list")); | 
| Chris@1291 | 48     connect(m_up, SIGNAL(clicked()), this, SLOT(upClicked())); | 
| Chris@1291 | 49     buttons->addWidget(m_up); | 
| Chris@1291 | 50 | 
| Chris@1291 | 51     m_add = new QPushButton; | 
| Chris@1291 | 52     m_add->setIcon(IconLoader().load("plus")); | 
| Chris@1295 | 53     m_add->setToolTip(tr("Add a new location to the list")); | 
| Chris@1291 | 54     connect(m_add, SIGNAL(clicked()), this, SLOT(addClicked())); | 
| Chris@1291 | 55     buttons->addWidget(m_add); | 
| Chris@1291 | 56 | 
| Chris@1291 | 57     m_delete = new QPushButton; | 
| Chris@1291 | 58     m_delete->setIcon(IconLoader().load("datadelete")); | 
| Chris@1291 | 59     m_delete->setToolTip(tr("Remove the selected location from the list")); | 
| Chris@1291 | 60     connect(m_delete, SIGNAL(clicked()), this, SLOT(deleteClicked())); | 
| Chris@1291 | 61     buttons->addWidget(m_delete); | 
| Chris@1291 | 62 | 
| Chris@1291 | 63     m_reset = new QPushButton; | 
| Chris@1293 | 64     m_reset->setText(tr("Reset to Default")); | 
| Chris@1291 | 65     m_reset->setToolTip(tr("Reset the list for this plugin type to its default")); | 
| Chris@1291 | 66     connect(m_reset, SIGNAL(clicked()), this, SLOT(resetClicked())); | 
| Chris@1291 | 67     buttons->addWidget(m_reset); | 
| Chris@1287 | 68 | 
| Chris@1297 | 69     buttons->addStretch(50); | 
| Chris@1297 | 70 | 
| Chris@1297 | 71     m_seePlugins = new QPushButton; | 
| Chris@1297 | 72     m_seePlugins->setText(tr("Review plugins...")); | 
| Chris@1297 | 73     connect(m_seePlugins, SIGNAL(clicked()), this, SLOT(seePluginsClicked())); | 
| Chris@1297 | 74     buttons->addWidget(m_seePlugins); | 
| Chris@1297 | 75 | 
| Chris@1287 | 76     int row = 0; | 
| Chris@1287 | 77 | 
| Chris@1289 | 78     m_header = new QLabel; | 
| Chris@1290 | 79     m_header->setText(tr("Plugin locations for plugin type:")); | 
| Chris@1289 | 80     m_layout->addWidget(m_header, row, 0); | 
| Chris@1289 | 81 | 
| Chris@1289 | 82     m_pluginTypeSelector = new QComboBox; | 
| Chris@1290 | 83     m_layout->addWidget(m_pluginTypeSelector, row, 1, Qt::AlignLeft); | 
| Chris@1289 | 84     connect(m_pluginTypeSelector, SIGNAL(currentTextChanged(QString)), | 
| Chris@1289 | 85             this, SLOT(currentTypeChanged(QString))); | 
| Chris@1289 | 86 | 
| Chris@1290 | 87     m_layout->setColumnStretch(1, 10); | 
| Chris@1287 | 88     ++row; | 
| Chris@1287 | 89 | 
| Chris@1287 | 90     m_list = new QListWidget; | 
| Chris@1290 | 91     m_layout->addWidget(m_list, row, 0, 1, 3); | 
| Chris@1290 | 92     m_layout->setRowStretch(row, 20); | 
| Chris@1288 | 93     connect(m_list, SIGNAL(currentRowChanged(int)), | 
| Chris@1288 | 94             this, SLOT(currentLocationChanged(int))); | 
| Chris@1287 | 95     ++row; | 
| Chris@1290 | 96 | 
| Chris@1297 | 97     m_layout->addLayout(buttons, row, 0, 1, 3); | 
| Chris@1292 | 98 | 
| Chris@1287 | 99     ++row; | 
| Chris@1291 | 100 | 
| Chris@1290 | 101     m_envOverride = new QCheckBox; | 
| Chris@1290 | 102     connect(m_envOverride, SIGNAL(stateChanged(int)), | 
| Chris@1290 | 103             this, SLOT(envOverrideChanged(int))); | 
| Chris@1290 | 104     m_layout->addWidget(m_envOverride, row, 0, 1, 3); | 
| Chris@1291 | 105     ++row; | 
| Chris@1285 | 106 } | 
| Chris@1285 | 107 | 
| Chris@1285 | 108 PluginPathConfigurator::~PluginPathConfigurator() | 
| Chris@1285 | 109 { | 
| Chris@1285 | 110 } | 
| Chris@1285 | 111 | 
| Chris@1296 | 112 QString | 
| Chris@1296 | 113 PluginPathConfigurator::getLabelFor(PluginPathSetter::TypeKey key) | 
| Chris@1296 | 114 { | 
| Chris@1296 | 115     if (key.second == KnownPlugins::FormatNative) { | 
| Chris@1296 | 116         switch (key.first) { | 
| Chris@1296 | 117         case KnownPlugins::VampPlugin: | 
| Chris@1296 | 118             return tr("Vamp"); | 
| Chris@1296 | 119         case KnownPlugins::LADSPAPlugin: | 
| Chris@1296 | 120             return tr("LADSPA"); | 
| Chris@1296 | 121         case KnownPlugins::DSSIPlugin: | 
| Chris@1296 | 122             return tr("DSSI"); | 
| Chris@1296 | 123         } | 
| Chris@1296 | 124     } else if (key.second == KnownPlugins::FormatNonNative32Bit) { | 
| Chris@1296 | 125         switch (key.first) { | 
| Chris@1296 | 126         case KnownPlugins::VampPlugin: | 
| Chris@1296 | 127             return tr("Vamp (32-bit)"); | 
| Chris@1296 | 128         case KnownPlugins::LADSPAPlugin: | 
| Chris@1296 | 129             return tr("LADSPA (32-bit)"); | 
| Chris@1296 | 130         case KnownPlugins::DSSIPlugin: | 
| Chris@1296 | 131             return tr("DSSI (32-bit)"); | 
| Chris@1296 | 132         } | 
| Chris@1296 | 133     } else { | 
| Chris@1296 | 134         SVCERR << "PluginPathConfigurator::getLabelFor: WARNING: " | 
| Chris@1296 | 135                << "Unknown format value " << key.second << endl; | 
| Chris@1296 | 136         return "<unknown>"; | 
| Chris@1296 | 137     } | 
| Chris@1296 | 138 } | 
| Chris@1296 | 139 | 
| Chris@1296 | 140 PluginPathSetter::TypeKey | 
| Chris@1296 | 141 PluginPathConfigurator::getKeyForLabel(QString label) | 
| Chris@1296 | 142 { | 
| Chris@1296 | 143     for (const auto &p: m_paths) { | 
| Chris@1296 | 144         auto key = p.first; | 
| Chris@1296 | 145         if (getLabelFor(key) == label) { | 
| Chris@1296 | 146             return key; | 
| Chris@1296 | 147         } | 
| Chris@1296 | 148     } | 
| Chris@1296 | 149     SVCERR << "PluginPathConfigurator::getKeyForLabel: WARNING: " | 
| Chris@1296 | 150            << "Unrecognised label \"" << label << "\"" << endl; | 
| Chris@1296 | 151     return { KnownPlugins::VampPlugin, KnownPlugins::FormatNative }; | 
| Chris@1296 | 152 } | 
| Chris@1296 | 153 | 
| Chris@1285 | 154 void | 
| Chris@1293 | 155 PluginPathConfigurator::setPaths(PluginPathSetter::Paths paths) | 
| Chris@1285 | 156 { | 
| Chris@1289 | 157     m_paths = paths; | 
| Chris@1293 | 158 | 
| Chris@1293 | 159     m_defaultPaths = PluginPathSetter::getDefaultPaths(); | 
| Chris@1289 | 160 | 
| Chris@1289 | 161     m_pluginTypeSelector->clear(); | 
| Chris@1289 | 162     for (const auto &p: paths) { | 
| Chris@1296 | 163         m_pluginTypeSelector->addItem(getLabelFor(p.first)); | 
| Chris@1289 | 164     } | 
| Chris@1289 | 165 | 
| Chris@1285 | 166     populate(); | 
| Chris@1285 | 167 } | 
| Chris@1285 | 168 | 
| Chris@1285 | 169 void | 
| Chris@1289 | 170 PluginPathConfigurator::populate() | 
| Chris@1285 | 171 { | 
| Chris@1287 | 172     m_list->clear(); | 
| Chris@1286 | 173 | 
| Chris@1289 | 174     if (m_paths.empty()) return; | 
| Chris@1289 | 175 | 
| Chris@1296 | 176     populateFor(m_paths.begin()->first, -1); | 
| Chris@1289 | 177 } | 
| Chris@1289 | 178 | 
| Chris@1289 | 179 void | 
| Chris@1296 | 180 PluginPathConfigurator::populateFor(PluginPathSetter::TypeKey key, | 
| Chris@1296 | 181                                     int makeCurrent) | 
| Chris@1289 | 182 { | 
| Chris@1296 | 183     QString envVariable = m_paths.at(key).envVariable; | 
| Chris@1296 | 184     bool useEnvVariable = m_paths.at(key).useEnvVariable; | 
| Chris@1294 | 185     QString envVarValue = | 
| Chris@1294 | 186         PluginPathSetter::getOriginalEnvironmentValue(envVariable); | 
| Chris@1294 | 187     QString currentValueRubric; | 
| Chris@1294 | 188     if (envVarValue == QString()) { | 
| Chris@1294 | 189         currentValueRubric = tr("(Variable is currently unset)"); | 
| Chris@1294 | 190     } else { | 
| Chris@1294 | 191         if (envVarValue.length() > 100) { | 
| Chris@1294 | 192             QString envVarStart = envVarValue.left(95); | 
| Chris@1294 | 193             currentValueRubric = tr("(Current value begins: \"%1 ...\")") | 
| Chris@1294 | 194                 .arg(envVarStart); | 
| Chris@1294 | 195         } else { | 
| Chris@1294 | 196             currentValueRubric = tr("(Currently set to: \"%1\")") | 
| Chris@1294 | 197                 .arg(envVarValue); | 
| Chris@1294 | 198         } | 
| Chris@1294 | 199     } | 
| Chris@1290 | 200     m_envOverride->setText | 
| Chris@1294 | 201         (tr("Allow the %1 environment variable to take priority over this\n%2") | 
| Chris@1294 | 202          .arg(envVariable) | 
| Chris@1294 | 203          .arg(currentValueRubric)); | 
| Chris@1290 | 204     m_envOverride->setCheckState(useEnvVariable ? Qt::Checked : Qt::Unchecked); | 
| Chris@1294 | 205 | 
| Chris@1289 | 206     m_list->clear(); | 
| Chris@1289 | 207 | 
| Chris@1289 | 208     for (int i = 0; i < m_pluginTypeSelector->count(); ++i) { | 
| Chris@1296 | 209         if (getLabelFor(key) == m_pluginTypeSelector->itemText(i)) { | 
| Chris@1294 | 210             m_pluginTypeSelector->blockSignals(true); | 
| Chris@1289 | 211             m_pluginTypeSelector->setCurrentIndex(i); | 
| Chris@1294 | 212             m_pluginTypeSelector->blockSignals(false); | 
| Chris@1289 | 213         } | 
| Chris@1289 | 214     } | 
| Chris@1289 | 215 | 
| Chris@1296 | 216     QStringList path = m_paths.at(key).directories; | 
| Chris@1289 | 217 | 
| Chris@1289 | 218     for (int i = 0; i < path.size(); ++i) { | 
| Chris@1289 | 219         m_list->addItem(path[i]); | 
| Chris@1287 | 220     } | 
| Chris@1285 | 221 | 
| Chris@1290 | 222     if (makeCurrent < path.size()) { | 
| Chris@1287 | 223         m_list->setCurrentRow(makeCurrent); | 
| Chris@1290 | 224         currentLocationChanged(makeCurrent); | 
| Chris@1286 | 225     } | 
| Chris@1285 | 226 } | 
| Chris@1285 | 227 | 
| Chris@1285 | 228 void | 
| Chris@1288 | 229 PluginPathConfigurator::currentLocationChanged(int i) | 
| Chris@1288 | 230 { | 
| Chris@1296 | 231     QString label = m_pluginTypeSelector->currentText(); | 
| Chris@1296 | 232     PluginPathSetter::TypeKey key = getKeyForLabel(label); | 
| Chris@1296 | 233     QStringList path = m_paths.at(key).directories; | 
| Chris@1288 | 234     m_up->setEnabled(i > 0); | 
| Chris@1290 | 235     m_down->setEnabled(i >= 0 && i + 1 < path.size()); | 
| Chris@1290 | 236     m_delete->setEnabled(i >= 0 && i < path.size()); | 
| Chris@1296 | 237     m_reset->setEnabled(path != m_defaultPaths.at(key).directories); | 
| Chris@1289 | 238 } | 
| Chris@1289 | 239 | 
| Chris@1289 | 240 void | 
| Chris@1296 | 241 PluginPathConfigurator::currentTypeChanged(QString label) | 
| Chris@1289 | 242 { | 
| Chris@1296 | 243     populateFor(getKeyForLabel(label), -1); | 
| Chris@1290 | 244 } | 
| Chris@1290 | 245 | 
| Chris@1290 | 246 void | 
| Chris@1292 | 247 PluginPathConfigurator::envOverrideChanged(int state) | 
| Chris@1290 | 248 { | 
| Chris@1292 | 249     bool useEnvVariable = (state == Qt::Checked); | 
| Chris@1292 | 250 | 
| Chris@1296 | 251     QString label = m_pluginTypeSelector->currentText(); | 
| Chris@1296 | 252     PluginPathSetter::TypeKey key = getKeyForLabel(label); | 
| Chris@1292 | 253 | 
| Chris@1296 | 254     auto newEntry = m_paths.at(key); | 
| Chris@1292 | 255     newEntry.useEnvVariable = useEnvVariable; | 
| Chris@1296 | 256     m_paths[key] = newEntry; | 
| Chris@1292 | 257 | 
| Chris@1293 | 258     emit pathsChanged(); | 
| Chris@1288 | 259 } | 
| Chris@1288 | 260 | 
| Chris@1288 | 261 void | 
| Chris@1285 | 262 PluginPathConfigurator::upClicked() | 
| Chris@1285 | 263 { | 
| Chris@1296 | 264     QString label = m_pluginTypeSelector->currentText(); | 
| Chris@1296 | 265     PluginPathSetter::TypeKey key = getKeyForLabel(label); | 
| Chris@1296 | 266     QStringList path = m_paths.at(key).directories; | 
| Chris@1289 | 267 | 
| Chris@1287 | 268     int current = m_list->currentRow(); | 
| Chris@1287 | 269     if (current <= 0) return; | 
| Chris@1287 | 270 | 
| Chris@1286 | 271     QStringList newPath; | 
| Chris@1289 | 272     for (int i = 0; i < path.size(); ++i) { | 
| Chris@1287 | 273         if (i + 1 == current) { | 
| Chris@1289 | 274             newPath.push_back(path[i+1]); | 
| Chris@1289 | 275             newPath.push_back(path[i]); | 
| Chris@1286 | 276             ++i; | 
| Chris@1286 | 277         } else { | 
| Chris@1289 | 278             newPath.push_back(path[i]); | 
| Chris@1286 | 279         } | 
| Chris@1286 | 280     } | 
| Chris@1290 | 281 | 
| Chris@1296 | 282     auto newEntry = m_paths.at(key); | 
| Chris@1290 | 283     newEntry.directories = newPath; | 
| Chris@1296 | 284     m_paths[key] = newEntry; | 
| Chris@1287 | 285 | 
| Chris@1296 | 286     populateFor(key, current - 1); | 
| Chris@1292 | 287 | 
| Chris@1293 | 288     emit pathsChanged(); | 
| Chris@1285 | 289 } | 
| Chris@1285 | 290 | 
| Chris@1285 | 291 void | 
| Chris@1285 | 292 PluginPathConfigurator::downClicked() | 
| Chris@1285 | 293 { | 
| Chris@1296 | 294     QString label = m_pluginTypeSelector->currentText(); | 
| Chris@1296 | 295     PluginPathSetter::TypeKey key = getKeyForLabel(label); | 
| Chris@1296 | 296     QStringList path = m_paths.at(key).directories; | 
| Chris@1289 | 297 | 
| Chris@1287 | 298     int current = m_list->currentRow(); | 
| Chris@1289 | 299     if (current < 0 || current + 1 >= path.size()) return; | 
| Chris@1289 | 300 | 
| Chris@1286 | 301     QStringList newPath; | 
| Chris@1289 | 302     for (int i = 0; i < path.size(); ++i) { | 
| Chris@1287 | 303         if (i == current) { | 
| Chris@1289 | 304             newPath.push_back(path[i+1]); | 
| Chris@1289 | 305             newPath.push_back(path[i]); | 
| Chris@1286 | 306             ++i; | 
| Chris@1286 | 307         } else { | 
| Chris@1289 | 308             newPath.push_back(path[i]); | 
| Chris@1286 | 309         } | 
| Chris@1286 | 310     } | 
| Chris@1290 | 311 | 
| Chris@1296 | 312     auto newEntry = m_paths.at(key); | 
| Chris@1290 | 313     newEntry.directories = newPath; | 
| Chris@1296 | 314     m_paths[key] = newEntry; | 
| Chris@1287 | 315 | 
| Chris@1296 | 316     populateFor(key, current + 1); | 
| Chris@1292 | 317 | 
| Chris@1293 | 318     emit pathsChanged(); | 
| Chris@1285 | 319 } | 
| Chris@1285 | 320 | 
| Chris@1285 | 321 void | 
| Chris@1291 | 322 PluginPathConfigurator::addClicked() | 
| Chris@1291 | 323 { | 
| Chris@1296 | 324     QString label = m_pluginTypeSelector->currentText(); | 
| Chris@1296 | 325     PluginPathSetter::TypeKey key = getKeyForLabel(label); | 
| Chris@1291 | 326 | 
| Chris@1291 | 327     QString newDir = QFileDialog::getExistingDirectory | 
| Chris@1291 | 328         (this, tr("Choose directory to add")); | 
| Chris@1291 | 329 | 
| Chris@1291 | 330     if (newDir == QString()) return; | 
| Chris@1291 | 331 | 
| Chris@1296 | 332     auto newEntry = m_paths.at(key); | 
| Chris@1291 | 333     newEntry.directories.push_back(newDir); | 
| Chris@1296 | 334     m_paths[key] = newEntry; | 
| Chris@1291 | 335 | 
| Chris@1296 | 336     populateFor(key, newEntry.directories.size() - 1); | 
| Chris@1292 | 337 | 
| Chris@1293 | 338     emit pathsChanged(); | 
| Chris@1291 | 339 } | 
| Chris@1291 | 340 | 
| Chris@1291 | 341 void | 
| Chris@1285 | 342 PluginPathConfigurator::deleteClicked() | 
| Chris@1285 | 343 { | 
| Chris@1296 | 344     QString label = m_pluginTypeSelector->currentText(); | 
| Chris@1296 | 345     PluginPathSetter::TypeKey key = getKeyForLabel(label); | 
| Chris@1296 | 346     QStringList path = m_paths.at(key).directories; | 
| Chris@1289 | 347 | 
| Chris@1287 | 348     int current = m_list->currentRow(); | 
| Chris@1290 | 349     if (current < 0) return; | 
| Chris@1289 | 350 | 
| Chris@1286 | 351     QStringList newPath; | 
| Chris@1289 | 352     for (int i = 0; i < path.size(); ++i) { | 
| Chris@1287 | 353         if (i != current) { | 
| Chris@1289 | 354             newPath.push_back(path[i]); | 
| Chris@1286 | 355         } | 
| Chris@1286 | 356     } | 
| Chris@1290 | 357 | 
| Chris@1296 | 358     auto newEntry = m_paths.at(key); | 
| Chris@1290 | 359     newEntry.directories = newPath; | 
| Chris@1296 | 360     m_paths[key] = newEntry; | 
| Chris@1287 | 361 | 
| Chris@1296 | 362     populateFor(key, current < newPath.size() ? current : current-1); | 
| Chris@1292 | 363 | 
| Chris@1293 | 364     emit pathsChanged(); | 
| Chris@1285 | 365 } | 
| Chris@1290 | 366 | 
| Chris@1290 | 367 void | 
| Chris@1290 | 368 PluginPathConfigurator::resetClicked() | 
| Chris@1290 | 369 { | 
| Chris@1296 | 370     QString label = m_pluginTypeSelector->currentText(); | 
| Chris@1296 | 371     PluginPathSetter::TypeKey key = getKeyForLabel(label); | 
| Chris@1296 | 372     m_paths[key] = m_defaultPaths[key]; | 
| Chris@1296 | 373     populateFor(key, -1); | 
| Chris@1292 | 374 | 
| Chris@1293 | 375     emit pathsChanged(); | 
| Chris@1290 | 376 } | 
| Chris@1292 | 377 | 
| Chris@1292 | 378 void | 
| Chris@1292 | 379 PluginPathConfigurator::seePluginsClicked() | 
| Chris@1292 | 380 { | 
| Chris@1292 | 381     PluginReviewDialog dialog(this); | 
| Chris@1292 | 382     dialog.populate(); | 
| Chris@1292 | 383     dialog.exec(); | 
| Chris@1292 | 384 } | 
| Chris@1292 | 385 |