Example #1
0
void
CollapsingFrame::toggle()
{
    int h = m_toggleButton->height();

    m_collapsed = !m_collapsed;

    m_widget->setVisible(!m_collapsed);

    QPixmap pixmap;

    if (m_collapsed) {
        pixmap = IconLoader().loadPixmap("style/arrow-right-small-inverted");
    } else {
        pixmap = IconLoader().loadPixmap("style/arrow-down-small-inverted");
    }

    if (!objectName().isEmpty()) {
        QSettings settings;
        settings.beginGroup(CollapsingFrameConfigGroup);
        settings.setValue(objectName(), !m_collapsed);
        settings.endGroup();
    }

    m_toggleButton->setIcon(pixmap);

    m_toggleButton->setMaximumHeight(h);
}
Example #2
0
StartupLogo::StartupLogo(QWidget * parent) :
    QWidget(parent, Qt::SplashScreen),
    m_readyToHide(false),
    m_showTip(true)
{

#ifdef STABLE
    m_pixmap = IconLoader().loadPixmap("splash");
#else
    m_pixmap = IconLoader().loadPixmap("splash-devel");
#endif

    setGeometry(QApplication::desktop()->width() / 2 - m_pixmap.width() / 2,
                QApplication::desktop()->height() / 2 - m_pixmap.height() / 2,
                m_pixmap.width(), m_pixmap.height());
}
Example #3
0
void
WarningDialog::addWarning(Message message)
{
    QWidget *tab = new QWidget;
    QVBoxLayout *layout = new QVBoxLayout;
    layout->setAlignment(Qt::AlignTop);
    tab->setLayout(layout);

    QLabel *text = new QLabel(message.first.first);
    text->setWordWrap(true);
    layout->addWidget(text);

    QLabel *informativeText = new QLabel(message.first.second);
    informativeText->setWordWrap(true);
    layout->addWidget(informativeText);

    informativeText->setOpenExternalLinks(true);

    QIcon icon = IconLoader().load("warning");
    QString headline(tr("Warning"));

    switch (message.second) {
    case Midi:
        icon = IconLoader().load("midi-nok");
        headline = tr("MIDI");
        break;
    case Audio:
        icon = IconLoader().load("audio-nok");
        headline = tr("Audio");
        break;
    case Timer:
        icon = IconLoader().load("timer-nok");
        headline = tr("System timer");
        break;
    case Info:
        icon = IconLoader().load("messagebox-information");
        headline = tr("Information");
        break;
    case Other:
    default:
        // icon and text were initialized suitable for this case, so there's
        // nothing to do here
        break;
    }

    m_tabWidget->addTab(tab, icon, headline);
}
Example #4
0
WarningDialog::WarningDialog(QWidget *parent) : 
    QDialog(parent)
{
    QVBoxLayout *layout = new QVBoxLayout;
    setLayout(layout);

    m_tabWidget = new QTabWidget;
    layout->addWidget(m_tabWidget);

    QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
    layout->addWidget(buttonBox);
    connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));

    setWindowTitle(tr("Performance Problems Detected"));
    setWindowIcon(IconLoader().load("warning"));
}
Example #5
0
CollapsingFrame::CollapsingFrame(
        QString label, QWidget *parent, const QString &name,
        bool defaultExpanded) :
    QFrame(parent),
    m_widget(0),
    m_fill(false),
    m_collapsed(false)
{
    setObjectName(name);

    // Set up the initial default state if needed.
    QSettings settings;
    settings.beginGroup(CollapsingFrameConfigGroup);
    bool expanded = qStrToBool(settings.value(
            name, defaultExpanded ? "true" : "false"));
    settings.setValue(name, expanded);

    setContentsMargins(0, 0, 0, 0);
    m_layout = new QGridLayout(this);
    m_layout->setMargin(0);
    m_layout->setSpacing(0);

    m_toggleButton = new QToolButton(this);
    m_toggleButton->setText(label);
    m_toggleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    m_toggleButton->setAutoRaise(true);

    QFont font(m_toggleButton->font());
    font.setBold(true);
    m_toggleButton->setFont(font);

    m_toggleButton->setIcon(IconLoader().load("style/arrow-down-small-inverted"));

    connect(m_toggleButton, SIGNAL(clicked()), this, SLOT(toggle()));

    m_layout->addWidget(m_toggleButton, 0, 0, 1, 3);
}
Example #6
0
void
MidiMixerWindow::setupTabs()
{
    DeviceListConstIterator it;
    MidiDevice *dev = 0;
    InstrumentList instruments;
    InstrumentList::const_iterator iIt;
    int faderCount = 0, deviceCount = 1;

    if (m_tabFrame)
        delete m_tabFrame;

    // Setup m_tabFrame
    //

    QWidget *blackWidget = new QWidget(this);
    setCentralWidget(blackWidget);
    QVBoxLayout *centralLayout = new QVBoxLayout;
    blackWidget->setLayout(centralLayout);

    m_tabWidget = new QTabWidget;
    centralLayout->addWidget(m_tabWidget);

    connect(m_tabWidget, SIGNAL(currentChanged(QWidget *)),
            this, SLOT(slotCurrentTabChanged(QWidget *)));
    m_tabWidget->setTabPosition(QTabWidget::South);
    setWindowTitle(tr("MIDI Mixer"));
    setWindowIcon(IconLoader().loadPixmap("window-midimixer"));


    for (it = m_studio->begin(); it != m_studio->end(); ++it) {
        dev = dynamic_cast<MidiDevice*>(*it);

        if (dev) {
            // Get the control parameters that are on the IPB (and hence can
            // be shown here too).
            //
            ControlList controls = getIPBForMidiMixer(dev);

            instruments = dev->getPresentationInstruments();

            // Don't add a frame for empty devices
            //
            if (!instruments.size())
                continue;

            m_tabFrame = new QFrame(m_tabWidget);
            m_tabFrame->setContentsMargins(10, 10, 10, 10);

            // m_tabFrame->setContentsMargins(5, 5, 5, 5); ???
            QGridLayout *mainLayout = new QGridLayout(m_tabFrame);

            // MIDI Mixer label
            QLabel *label = new QLabel("", m_tabFrame);
            mainLayout->addWidget(label, 0, 0, 0, 16, Qt::AlignCenter);

            // control labels
            for (size_t i = 0; i < controls.size(); ++i) {
                label = new QLabel(QObject::tr(controls[i].getName().c_str()), m_tabFrame);
                mainLayout->addWidget(label, i + 1, 0, Qt::AlignCenter);
            }

            // meter label
            // (obsolete abandoned code deleted here)

            // volume label
            label = new QLabel(tr("Volume"), m_tabFrame);
            mainLayout->addWidget(label, controls.size() + 2, 0,
                                  Qt::AlignCenter);

            // instrument label
            label = new QLabel(tr("Instrument"), m_tabFrame);
            label->setFixedWidth(80); //!!! this should come from metrics
            mainLayout->addWidget(label, controls.size() + 3, 0,
                                  Qt::AlignLeft);

            int posCount = 1;
            int firstInstrument = -1;

            for (iIt = instruments.begin(); iIt != instruments.end(); ++iIt) {

                // Add new fader struct
                //
                m_faders.push_back(new FaderStruct());

                // Store the first ID
                //
                if (firstInstrument == -1)
                    firstInstrument = (*iIt)->getId();


                // Add the controls
                //
                for (size_t i = 0; i < controls.size(); ++i) {
                    QColor knobColour = QColor(Qt::white);

                    if (controls[i].getColourIndex() > 0) {
                        Colour c =
                            m_document->getComposition().getGeneralColourMap().
                            getColourByIndex(controls[i].getColourIndex());

                        knobColour = QColor(c.getRed(),
                                            c.getGreen(), c.getBlue());
                    }

                    Rotary *controller =
                        new Rotary(m_tabFrame,
                                   controls[i].getMin(),
                                   controls[i].getMax(),
                                   1.0,
                                   5.0,
                                   controls[i].getDefault(),
                                   20,
                                   Rotary::NoTicks,
                                   false,
                                   controls[i].getDefault() == 64); //!!! hacky

                    controller->setKnobColour(knobColour);

                    connect(controller, SIGNAL(valueChanged(float)),
                            this, SLOT(slotControllerChanged(float)));

                    mainLayout->addWidget(controller, i + 1, posCount,
                                          Qt::AlignCenter);

                    // Store the rotary
                    //
                    m_faders[faderCount]->m_controllerRotaries.push_back(
                        std::pair<MidiByte, Rotary*>
                        (controls[i].getControllerValue(), controller));
                }

                // VU meter
                //
                MidiMixerVUMeter *meter =
                    new MidiMixerVUMeter(m_tabFrame,
                                         VUMeter::FixedHeightVisiblePeakHold, 6, 30);
                mainLayout->addWidget(meter, controls.size() + 1,
                                      posCount, Qt::AlignCenter);
                m_faders[faderCount]->m_vuMeter = meter;

                // Volume fader
                //
                Fader *fader =
                    new Fader(0, 127, 100, 20, 80, m_tabFrame);
                mainLayout->addWidget(fader, controls.size() + 2,
                                      posCount, Qt::AlignCenter);
                m_faders[faderCount]->m_volumeFader = fader;

                // Label
                //
                QLabel *idLabel = new QLabel(QString("%1").
                                             arg((*iIt)->getId() - firstInstrument + 1),
                                             m_tabFrame);
                idLabel->setObjectName("idLabel");

                mainLayout->addWidget(idLabel, controls.size() + 3,
                                      posCount, Qt::AlignCenter);

                // store id in struct
                m_faders[faderCount]->m_id = (*iIt)->getId();

                // Connect them up
                //
                connect(fader, SIGNAL(faderChanged(float)),
                        this, SLOT(slotFaderLevelChanged(float)));

                // Update all the faders and controllers
                //
                slotUpdateInstrument((*iIt)->getId());

                // Increment counters
                //
                posCount++;
                faderCount++;
            }

            QString name = QString("%1 (%2)")
                           .arg(QObject::tr(dev->getName().c_str()))
                           .arg(deviceCount++);

            addTab(m_tabFrame, name);
        }
    }
}
GuitarChordSelectorDialog::GuitarChordSelectorDialog(QWidget *parent)
    : QDialog(parent)
{
    QString localStyle = "QListView {background-color: #FFFFFF; alternate-background-color: #EEEEFF; color: #000000; selection-background-color: #80AFFF; selection-color: #FFFFFF;}";
    // we'll use "localStyle" as a future search point, but switch over to a
    // more meaningful variable name for the actual style assignment
    //
    // Note that I'm just slapping another local stylesheet on these damn
    // QListView objects, because they're stubbornly refusing to be touched from
    // the external stylesheet, and I'm beyond losing patience with dicking
    // around to solve problems like this.  Our stylesheet and style code are a
    // complete mess, and I will probably have to rewrite all of this one day,
    // but not before Thorn/Abraham Darby releases.
    QString listStyle = localStyle;

    setModal(true);
    setWindowTitle(tr("Guitar Chord Selector"));
    setWindowIcon(IconLoader().loadPixmap("window-guitar"));

    QGridLayout *metagrid = new QGridLayout;
    setLayout(metagrid);
    QGroupBox *page = new QGroupBox(this);
    QGridLayout *topLayout = new QGridLayout(page);
    metagrid->addWidget(page, 0, 0);
    
    topLayout->addWidget(new QLabel(tr("Root"), page), 0, 0);
    m_rootNotesList = new QListWidget(page);
    m_rootNotesList->setStyleSheet(listStyle);
    topLayout->addWidget(m_rootNotesList, 1, 0);
    
    topLayout->addWidget(new QLabel(tr("Extension"), page), 0, 1);
    m_chordExtList = new QListWidget(page);
    m_chordExtList->setStyleSheet(listStyle);
    topLayout->addWidget(m_chordExtList, 1, 1);
    
    m_newFingeringButton = new QPushButton(tr("New"), page);
    m_deleteFingeringButton = new QPushButton(tr("Delete"), page);
    m_editFingeringButton = new QPushButton(tr("Edit"), page);
    
    m_chordComplexityCombo = new QComboBox(page);
    m_chordComplexityCombo->addItem(tr("beginner"));
    m_chordComplexityCombo->addItem(tr("common"));
    m_chordComplexityCombo->addItem(tr("all"));
    //m_chordComplexityCombo->setMinimumContentsLength(20);
    
    connect(m_chordComplexityCombo, SIGNAL(activated(int)),
            this, SLOT(slotComplexityChanged(int)));

    page->setContentsMargins(5, 5, 5, 5);
    QVBoxLayout* vboxLayout = new QVBoxLayout();
    //topLayout->addLayout(vboxLayout, 1, 2, 3, 1);
    topLayout->addLayout(vboxLayout, 2, 1);
    vboxLayout->addWidget(m_chordComplexityCombo);
    vboxLayout->addStretch(10);
    vboxLayout->addWidget(m_newFingeringButton); 
    vboxLayout->addWidget(m_deleteFingeringButton); 
    vboxLayout->addWidget(m_editFingeringButton); 
    
    connect(m_newFingeringButton, SIGNAL(clicked()),
            this, SLOT(slotNewFingering()));
    connect(m_deleteFingeringButton, SIGNAL(clicked()),
            this, SLOT(slotDeleteFingering()));
    connect(m_editFingeringButton, SIGNAL(clicked()),
            this, SLOT(slotEditFingering()));
    
    topLayout->addWidget(new QLabel(tr("Fingerings"), page), 0, 3);
    m_fingeringsList = new QListWidget(page);
    m_fingeringsList->setStyleSheet(listStyle);

    // try setting size to something 200 can be divided into evenly, in the hope
    // of avoiding fuzzy half pixel scaling problems (50 was no good, but 100
    // works well for grid lines here; dots still look awful, but who cares)
    m_fingeringsList->setIconSize(QSize(100, 100));

    topLayout->addWidget(m_fingeringsList, 1, 3, 2, 1);
    
    m_fingeringBox = new FingeringBox(false, page, true);
    topLayout->addWidget(m_fingeringBox, 2, 0, 1, 2);
    
    connect(m_rootNotesList, SIGNAL(currentRowChanged(int)),
            this, SLOT(slotRootHighlighted(int)));
    connect(m_chordExtList, SIGNAL(currentRowChanged(int)),
            this, SLOT(slotChordExtHighlighted(int)));

    // connect itemClicked() so it will fire if a user clicks directly on the
    // fingering list doodad thingummy (and comments like "fingering list doodad
    // thingummy" are what you get when you abandon half-finished code the core
    // developers don't really understand, and expect them to keep it alive for
    // you in perpetuity)
    //
    connect(m_fingeringsList, SIGNAL(itemClicked(QListWidgetItem*)),
            this, SLOT(slotFingeringHighlighted(QListWidgetItem*)));

    // connect currentRowChanged() so this can be fired when other widgets are
    // manipulated, which will cause this one to pop back up to the top.  This
    // slot triggers other updates in a leg bone connected to the thigh bone
    // fashion, so we have to wire it to some input to get those updates to
    // happen, and overloading this to fire two different ways was quick and
    // cheap
    //
    connect(m_fingeringsList, SIGNAL(currentRowChanged(int)),
            this, SLOT(slotFingeringHighlighted(int)));

    QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok |
                                                       QDialogButtonBox::Cancel);
    metagrid->addWidget(buttonBox, 1, 0);
    metagrid->setRowStretch(0, 10);
    connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
    connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
}
Example #8
0
AudioFaderBox::AudioFaderBox(QWidget *parent,
                             QString id,
                             bool haveInOut,
                             const char *name):
        QFrame(parent),
        m_signalMapper(new QSignalMapper(this)),
        m_id(id),
        m_isStereo(false)
{
    setObjectName(name);

    // Plugin box
    //
    PluginPushButton *plugin;
    QWidget *pluginVbox = 0;

    pluginVbox = new QWidget(this);
    QVBoxLayout *pluginVboxLayout = new QVBoxLayout;
    pluginVboxLayout->setSpacing(2);
    pluginVboxLayout->setMargin(0);

    for (int i = 0; i < 5; i++) {
        plugin = new PluginPushButton(pluginVbox);
        pluginVboxLayout->addWidget(plugin);
        plugin->setText(tr("<no plugin>"));

        plugin->setToolTip(tr("Click to load an audio plugin"));

        m_plugins.push_back(plugin);
        m_signalMapper->setMapping(plugin, i);
        connect(plugin, SIGNAL(clicked()),
                m_signalMapper, SLOT(map()));
    }
    pluginVbox->setLayout(pluginVboxLayout);

    m_synthButton = new PluginPushButton(this);
    m_synthButton->setText(tr("<no synth>"));
    m_synthButton->setToolTip(tr("Click to load a synth plugin for playing MIDI"));

    // VU meter and fader
    //
    QWidget *faderHbox = new QWidget(this);
    QHBoxLayout *faderHboxLayout = new QHBoxLayout;
    faderHboxLayout->setMargin(0);

    //@@@ Testing m_vuMeter->height() doesn't work until the meter has
    //actually been shown, in Qt4 -- hardcode this for now
    int vuHeight = 140;

/*@@@
    m_vuMeter = new AudioVUMeter( faderHbox, VUMeter::AudioPeakHoldShort,
            true, true);

    faderHboxLayout->addWidget(m_vuMeter);
*/
    m_recordFader = new Fader(AudioLevel::ShortFader, 20,
                              vuHeight, faderHbox);

    faderHboxLayout->addWidget(m_recordFader);

    m_recordFader->setOutlineColour(GUIPalette::getColour(GUIPalette::RecordFaderOutline));
/*@@@
    delete m_vuMeter; // only used the first one to establish height,
    // actually want it after the record fader in
    // hbox
    */
    m_vuMeter = new AudioVUMeter(faderHbox, VUMeter::AudioPeakHoldShort,
            true, true);

    faderHboxLayout->addWidget(m_vuMeter);

    m_fader = new Fader(AudioLevel::ShortFader, 20,
                        vuHeight, faderHbox);

    faderHboxLayout->addWidget(m_fader);
    faderHbox->setLayout(faderHboxLayout);

    m_fader->setOutlineColour(GUIPalette::getColour(GUIPalette::PlaybackFaderOutline));

    m_monoPixmap = IconLoader().loadPixmap("mono");
    m_stereoPixmap = IconLoader().loadPixmap("stereo");

    m_pan = new Rotary(this, -100.0, 100.0, 1.0, 5.0, 0.0, 22,
                       Rotary::NoTicks, false, true);

    // same as the knob colour on the MIDI pan
    m_pan->setKnobColour(GUIPalette::getColour(GUIPalette::RotaryPastelGreen));

    m_stereoButton = new QPushButton(this);
    m_stereoButton->setIcon(QIcon(m_monoPixmap)); // default is mono
    m_stereoButton->setFixedSize(24, 24);

    connect(m_stereoButton, SIGNAL(clicked()),
            this, SLOT(slotChannelStateChanged()));

    m_synthGUIButton = new QPushButton(this);
    m_synthGUIButton->setText(tr("Editor"));

    if (haveInOut) {
        m_audioInput = new AudioRouteMenu(this,
                                          AudioRouteMenu::In,
                                          AudioRouteMenu::Regular);
        m_audioOutput = new AudioRouteMenu(this,
                                           AudioRouteMenu::Out,
                                           AudioRouteMenu::Regular);

    } else {
        m_pan->setKnobColour(GUIPalette::getColour(GUIPalette::RotaryPastelOrange));

        m_audioInput = 0;
        m_audioOutput = 0;
    }

    m_pan->setToolTip(tr("Set the audio pan position in the stereo field"));
    m_synthGUIButton->setToolTip(tr("Open the synth plugin's native editor"));
    m_stereoButton->setToolTip(tr("Mono or Stereo Instrument"));
    m_recordFader->setToolTip(tr("Record level"));
    m_fader->setToolTip(tr("Playback level"));
    m_vuMeter->setToolTip(tr("Audio level"));

    setContentsMargins(4, 4, 4, 4);
    QGridLayout *grid = new QGridLayout(this);
    setLayout(grid);
    grid->setMargin(0);
    grid->setSpacing(4);

    grid->addWidget(m_synthButton, 0, 0, 1, 3);

    if (haveInOut) {
        m_inputLabel = new QLabel(tr("In:"), this);
        grid->addWidget(m_inputLabel, 0, 0, Qt::AlignRight);
        grid->addWidget(m_audioInput->getWidget(), 0, 1, 1, 2);
        // force "In 1 L" to show full width:
        grid->setColumnStretch(1, 40);
        m_outputLabel = new QLabel(tr("Out:"), this);
        grid->addWidget(m_outputLabel, 0, 3, Qt::AlignRight);
        grid->addWidget(m_audioOutput->getWidget(), 0, 4, 1, 2);
    }
    grid->addWidget(pluginVbox, 2, 0, 0+1, 2- 0+1);
    grid->addWidget(faderHbox, 1, 3, 1+1, 5- 3+1);

    grid->addWidget(m_synthGUIButton, 1, 0);
    grid->addWidget(m_pan, 1, 2);
    grid->addWidget(m_stereoButton, 1, 1);
/*&&&
    for (int i = 0; i < 5; ++i) {
        // Force width
        m_plugins[i]->setFixedWidth(m_plugins[i]->sizeHint().width());
    }
    m_synthButton->setFixedWidth(m_plugins[0]->sizeHint().width());
*/
    m_synthButton->hide();
    m_synthGUIButton->hide();
}
Example #9
0
ControlRulerTabBar::ControlRulerTabBar():QTabBar()
{
    m_closeIcon = QPixmap(IconLoader().loadPixmap("tab-close"));
}
Example #10
0
PreferencesDialog::PreferencesDialog(QWidget *parent, Qt::WFlags flags) :
    QDialog(parent, flags),
    m_audioDevice(0),
    m_changesOnRestart(false)
{
    setWindowTitle(tr("Sonic Visualiser: Application Preferences"));

    Preferences *prefs = Preferences::getInstance();

    QGridLayout *grid = new QGridLayout;
    setLayout(grid);

    QTabWidget *tab = new QTabWidget;
    grid->addWidget(tab, 0, 0);
    
    tab->setTabPosition(QTabWidget::North);

    // Create this first, as slots that get called from the ctor will
    // refer to it
    m_applyButton = new QPushButton(tr("Apply"));

    // Create all the preference widgets first, then create the
    // individual tab widgets and place the preferences in their
    // appropriate places in one go afterwards

    int min, max, deflt, i;

    m_windowType = WindowType(prefs->getPropertyRangeAndValue
                              ("Window Type", &min, &max, &deflt));
    m_windowTypeSelector = new WindowTypeSelector(m_windowType);

    connect(m_windowTypeSelector, SIGNAL(windowTypeChanged(WindowType)),
            this, SLOT(windowTypeChanged(WindowType)));

    QComboBox *smoothing = new QComboBox;
    
    int sm = prefs->getPropertyRangeAndValue("Spectrogram Y Smoothing", &min, &max,
                                             &deflt);
    m_spectrogramSmoothing = sm;

    for (i = min; i <= max; ++i) {
        smoothing->addItem(prefs->getPropertyValueLabel("Spectrogram Y Smoothing", i));
    }

    smoothing->setCurrentIndex(sm);

    connect(smoothing, SIGNAL(currentIndexChanged(int)),
            this, SLOT(spectrogramSmoothingChanged(int)));

    QComboBox *xsmoothing = new QComboBox;
    
    int xsm = prefs->getPropertyRangeAndValue("Spectrogram X Smoothing", &min, &max,
                                             &deflt);
    m_spectrogramXSmoothing = xsm;

    for (i = min; i <= max; ++i) {
        xsmoothing->addItem(prefs->getPropertyValueLabel("Spectrogram X Smoothing", i));
    }

    xsmoothing->setCurrentIndex(xsm);

    connect(xsmoothing, SIGNAL(currentIndexChanged(int)),
            this, SLOT(spectrogramXSmoothingChanged(int)));

    QComboBox *propertyLayout = new QComboBox;
    int pl = prefs->getPropertyRangeAndValue("Property Box Layout", &min, &max,
                                         &deflt);
    m_propertyLayout = pl;

    for (i = min; i <= max; ++i) {
        propertyLayout->addItem(prefs->getPropertyValueLabel("Property Box Layout", i));
    }

    propertyLayout->setCurrentIndex(pl);

    connect(propertyLayout, SIGNAL(currentIndexChanged(int)),
            this, SLOT(propertyLayoutChanged(int)));

    m_tuningFrequency = prefs->getTuningFrequency();

    QDoubleSpinBox *frequency = new QDoubleSpinBox;
    frequency->setMinimum(100.0);
    frequency->setMaximum(5000.0);
    frequency->setSuffix(" Hz");
    frequency->setSingleStep(1);
    frequency->setValue(m_tuningFrequency);
    frequency->setDecimals(2);

    connect(frequency, SIGNAL(valueChanged(double)),
            this, SLOT(tuningFrequencyChanged(double)));

    QComboBox *audioDevice = new QComboBox;
    std::vector<QString> devices =
        AudioTargetFactory::getInstance()->getCallbackTargetNames();
    
    QSettings settings;
    settings.beginGroup("Preferences");
    QString targetName = settings.value("audio-target", "").toString();
    settings.endGroup();

    for (int i = 0; i < devices.size(); ++i) {
        audioDevice->addItem(AudioTargetFactory::getInstance()
                             ->getCallbackTargetDescription(devices[i]));
        if (targetName == devices[i]) audioDevice->setCurrentIndex(i);
    }

    connect(audioDevice, SIGNAL(currentIndexChanged(int)),
            this, SLOT(audioDeviceChanged(int)));

    QComboBox *resampleQuality = new QComboBox;

    int rsq = prefs->getPropertyRangeAndValue("Resample Quality", &min, &max,
                                              &deflt);
    m_resampleQuality = rsq;

    for (i = min; i <= max; ++i) {
        resampleQuality->addItem(prefs->getPropertyValueLabel("Resample Quality", i));
    }

    resampleQuality->setCurrentIndex(rsq);

    connect(resampleQuality, SIGNAL(currentIndexChanged(int)),
            this, SLOT(resampleQualityChanged(int)));

    QCheckBox *resampleOnLoad = new QCheckBox;
    m_resampleOnLoad = prefs->getResampleOnLoad();
    resampleOnLoad->setCheckState(m_resampleOnLoad ? Qt::Checked :
                                  Qt::Unchecked);
    connect(resampleOnLoad, SIGNAL(stateChanged(int)),
            this, SLOT(resampleOnLoadChanged(int)));

    m_tempDirRootEdit = new QLineEdit;
    QString dir = prefs->getTemporaryDirectoryRoot();
    m_tempDirRoot = dir;
    dir.replace("$HOME", tr("<home directory>"));
    m_tempDirRootEdit->setText(dir);
    m_tempDirRootEdit->setReadOnly(true);
    QPushButton *tempDirButton = new QPushButton;
    tempDirButton->setIcon(IconLoader().load("fileopen"));
    connect(tempDirButton, SIGNAL(clicked()),
            this, SLOT(tempDirButtonClicked()));
    tempDirButton->setFixedSize(QSize(24, 24));

    QCheckBox *showSplash = new QCheckBox;
    m_showSplash = prefs->getShowSplash();
    showSplash->setCheckState(m_showSplash ? Qt::Checked : Qt::Unchecked);
    connect(showSplash, SIGNAL(stateChanged(int)),
            this, SLOT(showSplashChanged(int)));

#ifndef Q_WS_MAC
    QComboBox *bgMode = new QComboBox;
    int bg = prefs->getPropertyRangeAndValue("Background Mode", &min, &max,
                                             &deflt);
    m_backgroundMode = bg;
    for (i = min; i <= max; ++i) {
        bgMode->addItem(prefs->getPropertyValueLabel("Background Mode", i));
    }
    bgMode->setCurrentIndex(bg);

    connect(bgMode, SIGNAL(currentIndexChanged(int)),
            this, SLOT(backgroundModeChanged(int)));
#endif

    QSpinBox *fontSize = new QSpinBox;
    int fs = prefs->getPropertyRangeAndValue("View Font Size", &min, &max,
                                             &deflt);
    m_viewFontSize = fs;
    fontSize->setMinimum(min);
    fontSize->setMaximum(max);
    fontSize->setSuffix(" pt");
    fontSize->setSingleStep(1);
    fontSize->setValue(fs);

    connect(fontSize, SIGNAL(valueChanged(int)),
            this, SLOT(viewFontSizeChanged(int)));

    QComboBox *ttMode = new QComboBox;
    int tt = prefs->getPropertyRangeAndValue("Time To Text Mode", &min, &max,
                                             &deflt);
    m_timeToTextMode = tt;
    for (i = min; i <= max; ++i) {
        ttMode->addItem(prefs->getPropertyValueLabel("Time To Text Mode", i));
    }
    ttMode->setCurrentIndex(tt);

    connect(ttMode, SIGNAL(currentIndexChanged(int)),
            this, SLOT(timeToTextModeChanged(int)));

    // General tab

    QFrame *frame = new QFrame;
    
    QGridLayout *subgrid = new QGridLayout;
    frame->setLayout(subgrid);

    int row = 0;

    subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel
                                                ("Temporary Directory Root"))),
                       row, 0);
    subgrid->addWidget(m_tempDirRootEdit, row, 1, 1, 1);
    subgrid->addWidget(tempDirButton, row, 2, 1, 1);
    row++;

    subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel
                                                ("Resample On Load"))),
                       row, 0);
    subgrid->addWidget(resampleOnLoad, row++, 1, 1, 1);

    subgrid->addWidget(new QLabel(tr("Playback audio device:")), row, 0);
    subgrid->addWidget(audioDevice, row++, 1, 1, 2);

    subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel
                                                ("Resample Quality"))),
                       row, 0);
    subgrid->addWidget(resampleQuality, row++, 1, 1, 2);

    subgrid->setRowStretch(row, 10);
    
    tab->addTab(frame, tr("&General"));

    // Appearance tab

    frame = new QFrame;
    subgrid = new QGridLayout;
    frame->setLayout(subgrid);
    row = 0;

    subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel
                                                ("Property Box Layout"))),
                       row, 0);
    subgrid->addWidget(propertyLayout, row++, 1, 1, 2);

#ifndef Q_WS_MAC
    subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel
                                                ("Background Mode"))),
                       row, 0);
    subgrid->addWidget(bgMode, row++, 1, 1, 2);
#endif

    subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel
                                                ("View Font Size"))),
                       row, 0);
    subgrid->addWidget(fontSize, row++, 1, 1, 2);

    subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel
                                                ("Time To Text Mode"))),
                       row, 0);
    subgrid->addWidget(ttMode, row++, 1, 1, 2);

    subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel
                                                ("Show Splash Screen"))),
                       row, 0);
    subgrid->addWidget(showSplash, row++, 1, 1, 1);

    subgrid->setRowStretch(row, 10);
    
    tab->addTab(frame, tr("&Appearance"));

    // Analysis tab

    frame = new QFrame;
    subgrid = new QGridLayout;
    frame->setLayout(subgrid);
    row = 0;

    subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel
                                                ("Tuning Frequency"))),
                       row, 0);
    subgrid->addWidget(frequency, row++, 1, 1, 2);

    subgrid->addWidget(new QLabel(prefs->getPropertyLabel
                                  ("Spectrogram Y Smoothing")),
                       row, 0);
    subgrid->addWidget(smoothing, row++, 1, 1, 2);

    subgrid->addWidget(new QLabel(prefs->getPropertyLabel
                                  ("Spectrogram X Smoothing")),
                       row, 0);
    subgrid->addWidget(xsmoothing, row++, 1, 1, 2);

    subgrid->addWidget(new QLabel(tr("%1:").arg(prefs->getPropertyLabel
                                                ("Window Type"))),
                       row, 0);
    subgrid->addWidget(m_windowTypeSelector, row++, 1, 2, 2);
    subgrid->setRowStretch(row, 10);
    row++;
    
    subgrid->setRowStretch(row, 10);
    
    tab->addTab(frame, tr("Anal&ysis"));

    QDialogButtonBox *bb = new QDialogButtonBox(Qt::Horizontal);
    grid->addWidget(bb, 1, 0);
    
    QPushButton *ok = new QPushButton(tr("OK"));
    QPushButton *cancel = new QPushButton(tr("Cancel"));
    bb->addButton(ok, QDialogButtonBox::AcceptRole);
    bb->addButton(m_applyButton, QDialogButtonBox::ApplyRole);
    bb->addButton(cancel, QDialogButtonBox::RejectRole);
    connect(ok, SIGNAL(clicked()), this, SLOT(okClicked()));
    connect(m_applyButton, SIGNAL(clicked()), this, SLOT(applyClicked()));
    connect(cancel, SIGNAL(clicked()), this, SLOT(cancelClicked()));

    m_applyButton->setEnabled(false);
}