diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 18:37:05 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 18:37:05 +0000 |
commit | 145364a8af6a1fec06556221e66d4b724a62fc9a (patch) | |
tree | 53bd71a544008c518034f208d64c932dc2883f50 /src/gui/widgets | |
download | rosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.tar.gz rosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.zip |
Added old abandoned KDE3 version of the RoseGarden MIDI tool
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/rosegarden@1097595 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/gui/widgets')
63 files changed, 8987 insertions, 0 deletions
diff --git a/src/gui/widgets/AudioFaderBox.cpp b/src/gui/widgets/AudioFaderBox.cpp new file mode 100644 index 0000000..05789ff --- /dev/null +++ b/src/gui/widgets/AudioFaderBox.cpp @@ -0,0 +1,294 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "AudioFaderBox.h" +#include <qlayout.h> + +#include <klocale.h> +#include <kstddirs.h> +#include "misc/Debug.h" +#include "AudioRouteMenu.h" +#include "AudioVUMeter.h" +#include "base/AudioLevel.h" +#include "base/Instrument.h" +#include "base/Studio.h" +#include "Fader.h" +#include "gui/general/GUIPalette.h" +#include "gui/application/RosegardenGUIApp.h" +#include "gui/studio/AudioPluginOSCGUIManager.h" +#include "Rotary.h" +#include <kglobal.h> +#include <qframe.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qobject.h> +#include <qpixmap.h> +#include <qpushbutton.h> +#include <qsignalmapper.h> +#include <qstring.h> +#include <qtooltip.h> +#include <qvbox.h> +#include <qwidget.h> +#include "VUMeter.h" + + +namespace Rosegarden +{ + +AudioFaderBox::AudioFaderBox(QWidget *parent, + QString id, + bool haveInOut, + const char *name): + QFrame(parent, name), + m_signalMapper(new QSignalMapper(this)), + m_id(id), + m_isStereo(false) +{ + // Plugin box + // + QPushButton *plugin; + QVBox *pluginVbox = 0; + + pluginVbox = new QVBox(this); + pluginVbox->setSpacing(2); + + for (int i = 0; i < 5; i++) { + plugin = new QPushButton(pluginVbox); + plugin->setText(i18n("<no plugin>")); + + QToolTip::add + (plugin, i18n("Audio plugin button")); + + m_plugins.push_back(plugin); + m_signalMapper->setMapping(plugin, i); + connect(plugin, SIGNAL(clicked()), + m_signalMapper, SLOT(map())); + } + + m_synthButton = new QPushButton(this); + m_synthButton->setText(i18n("<no synth>")); + QToolTip::add + (m_synthButton, i18n("Synth plugin button")); + + // VU meter and fader + // + QHBox *faderHbox = new QHBox(this); + + m_vuMeter = new AudioVUMeter(faderHbox, VUMeter::AudioPeakHoldShort, + true, true); + + m_recordFader = new Fader(AudioLevel::ShortFader, + 20, m_vuMeter->height(), faderHbox); + + 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); + + m_fader = new Fader(AudioLevel::ShortFader, + 20, m_vuMeter->height(), faderHbox); + + m_fader->setOutlineColour(GUIPalette::getColour(GUIPalette::PlaybackFaderOutline)); + + QString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/"); + m_monoPixmap.load(QString("%1/misc/mono.xpm").arg(pixmapDir)); + m_stereoPixmap.load(QString("%1/misc/stereo.xpm").arg(pixmapDir)); + + 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->setPixmap(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(i18n("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; + } + + QToolTip::add + (m_pan, i18n("Set the audio pan position in the stereo field")); + QToolTip::add + (m_synthGUIButton, i18n("Open synth plugin's native editor")); + QToolTip::add + (m_stereoButton, i18n("Mono or Stereo Instrument")); + QToolTip::add + (m_recordFader, i18n("Record level")); + QToolTip::add + (m_fader, i18n("Playback level")); + QToolTip::add + (m_vuMeter, i18n("Audio level")); + + QGridLayout *grid = new QGridLayout(this, 3, 6, 4, 4); + + grid->addMultiCellWidget(m_synthButton, 0, 0, 0, 2); + + if (haveInOut) { + m_inputLabel = new QLabel(i18n("In:"), this); + grid->addWidget(m_inputLabel, 0, 0, AlignRight); + grid->addMultiCellWidget(m_audioInput->getWidget(), 0, 0, 1, 2); + m_outputLabel = new QLabel(i18n("Out:"), this); + grid->addWidget(m_outputLabel, 0, 3, AlignRight); + grid->addMultiCellWidget(m_audioOutput->getWidget(), 0, 0, 4, 5); + } + + grid->addMultiCellWidget(pluginVbox, 2, 2, 0, 2); + grid->addMultiCellWidget(faderHbox, 1, 2, 3, 5); + + 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]->width()); + } + m_synthButton->setFixedWidth(m_plugins[0]->width()); + + m_synthButton->hide(); + m_synthGUIButton->hide(); +} + +void +AudioFaderBox::setIsSynth(bool isSynth) +{ + if (isSynth) { + m_inputLabel->hide(); + m_synthButton->show(); + m_synthGUIButton->show(); + m_audioInput->getWidget()->hide(); + m_recordFader->hide(); + } else { + m_synthButton->hide(); + m_synthGUIButton->hide(); + m_inputLabel->show(); + m_audioInput->getWidget()->show(); + m_recordFader->show(); + } +} + +void +AudioFaderBox::slotSetInstrument(Studio *studio, + Instrument *instrument) +{ + if (m_audioInput) + m_audioInput->slotSetInstrument(studio, instrument); + if (m_audioOutput) + m_audioOutput->slotSetInstrument(studio, instrument); + if (instrument) + setAudioChannels(instrument->getAudioChannels()); + if (instrument) { + + RG_DEBUG << "AudioFaderBox::slotSetInstrument(" << instrument->getId() << ")" << endl; + + setIsSynth(instrument->getType() == Instrument::SoftSynth); + if (instrument->getType() == Instrument::SoftSynth) { + bool gui = false; + RG_DEBUG << "AudioFaderBox::slotSetInstrument(" << instrument->getId() << "): is soft synth" << endl; +#ifdef HAVE_LIBLO + + gui = RosegardenGUIApp::self()->getPluginGUIManager()->hasGUI + (instrument->getId(), Instrument::SYNTH_PLUGIN_POSITION); + RG_DEBUG << "AudioFaderBox::slotSetInstrument(" << instrument->getId() << "): has gui = " << gui << endl; +#endif + + m_synthGUIButton->setEnabled(gui); + } + } +} + +bool +AudioFaderBox::owns(const QObject *object) +{ + return (object && + ((object->parent() == this) || + (object->parent() && (object->parent()->parent() == this)))); +} + +void +AudioFaderBox::setAudioChannels(int channels) +{ + m_isStereo = (channels > 1); + + switch (channels) { + case 1: + if (m_stereoButton) + m_stereoButton->setPixmap(m_monoPixmap); + m_isStereo = false; + break; + + case 2: + if (m_stereoButton) + m_stereoButton->setPixmap(m_stereoPixmap); + m_isStereo = true; + break; + default: + RG_DEBUG << "AudioFaderBox::setAudioChannels - " + << "unsupported channel numbers (" << channels + << ")" << endl; + return ; + } + + if (m_audioInput) + m_audioInput->slotRepopulate(); + if (m_audioOutput) + m_audioOutput->slotRepopulate(); +} + +void +AudioFaderBox::slotChannelStateChanged() +{ + if (m_isStereo) { + setAudioChannels(1); + emit audioChannelsChanged(1); + } else { + setAudioChannels(2); + emit audioChannelsChanged(2); + } +} + +} +#include "AudioFaderBox.moc" diff --git a/src/gui/widgets/AudioFaderBox.h b/src/gui/widgets/AudioFaderBox.h new file mode 100644 index 0000000..060fc9c --- /dev/null +++ b/src/gui/widgets/AudioFaderBox.h @@ -0,0 +1,114 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_AUDIOFADERBOX_H_ +#define _RG_AUDIOFADERBOX_H_ + +#include <qframe.h> +#include <qpixmap.h> +#include <qstring.h> +#include <vector> + + +class QWidget; +class QSignalMapper; +class QPushButton; +class QObject; +class QLabel; + + +namespace Rosegarden +{ + +class Studio; +class Rotary; +class Instrument; +class Fader; +class AudioVUMeter; +class AudioRouteMenu; + + +class AudioFaderBox : public QFrame +{ + Q_OBJECT + +public: + AudioFaderBox(QWidget *parent, + QString id = "", + bool haveInOut = true, + const char *name = 0); + + void setAudioChannels(int); + + void setIsSynth(bool); + + bool owns(const QObject *object); + + QPushButton *m_synthButton; + std::vector<QPushButton*> m_plugins; + + AudioVUMeter *m_vuMeter; + + Fader *m_fader; + Fader *m_recordFader; + Rotary *m_pan; + + QPixmap m_monoPixmap; + QPixmap m_stereoPixmap; + + QSignalMapper *m_signalMapper; + + QLabel *m_inputLabel; + QLabel *m_outputLabel; + + AudioRouteMenu *m_audioInput; + AudioRouteMenu *m_audioOutput; + + QPushButton *m_synthGUIButton; + + QString m_id; + + bool isStereo() const { return m_isStereo; } + +signals: + void audioChannelsChanged(int); + +public slots: + void slotSetInstrument(Studio *studio, + Instrument *instrument); + +protected slots: + void slotChannelStateChanged(); + +protected: + QPushButton *m_stereoButton; + bool m_isStereo; +}; + + + +} + +#endif diff --git a/src/gui/widgets/AudioListItem.h b/src/gui/widgets/AudioListItem.h new file mode 100644 index 0000000..bbd8fc2 --- /dev/null +++ b/src/gui/widgets/AudioListItem.h @@ -0,0 +1,97 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_AUDIOLISTITEM_H_ +#define _RG_AUDIOLISTITEM_H_ + +#include <sound/AudioFile.h> +#include <klistview.h> + +namespace Rosegarden +{ + +class Segment; + +// Add an Id to a QListViewItem +// +class AudioListItem : public KListViewItem +{ + +public: + + AudioListItem(KListView *parent):KListViewItem(parent), + m_segment(0) {;} + + AudioListItem(KListViewItem *parent):KListViewItem(parent), + m_segment(0) {;} + + AudioListItem(KListView *parent, + QString label, + AudioFileId id): + KListViewItem(parent, + label, + "", "", "", "", "", "", ""), + m_id(id), + m_segment(0) {;} + + AudioListItem(KListViewItem *parent, + QString label, + AudioFileId id): + KListViewItem(parent, + label, + "", "", "", "", "", "", ""), + m_id(id), + m_segment(0) {;} + + + AudioFileId getId() { return m_id; } + + void setStartTime(const RealTime &time) + { m_startTime = time; } + RealTime getStartTime() { return m_startTime; } + + void setDuration(const RealTime &time) + { m_duration = time; } + RealTime getDuration() { return m_duration; } + + void setSegment(Segment *segment) + { m_segment = segment; } + Segment *getSegment() { return m_segment; } + +protected: + AudioFileId m_id; + + // for audio segments + RealTime m_startTime; + RealTime m_duration; + + // pointer to a segment + Segment *m_segment; + +}; + +} + + +#endif /*AUDIOLISTITEM_H_*/ diff --git a/src/gui/widgets/AudioListView.cpp b/src/gui/widgets/AudioListView.cpp new file mode 100644 index 0000000..45193a6 --- /dev/null +++ b/src/gui/widgets/AudioListView.cpp @@ -0,0 +1,67 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "AudioListView.h" + +#include "misc/Debug.h" +#include "gui/widgets/AudioListItem.h" +#include "qdragobject.h" + +namespace Rosegarden { + +AudioListView::AudioListView(QWidget *parent, const char *name) + : KListView(parent, name) +{ + setDragEnabled(true); + setAcceptDrops(true); + setDropVisualizer(false); +} + +bool AudioListView::acceptDrag(QDropEvent* e) const +{ + return QUriDrag::canDecode(e) || KListView::acceptDrag(e); +} + +QDragObject* AudioListView::dragObject() +{ + AudioListItem* item = dynamic_cast<AudioListItem*>(currentItem()); + + QString audioData; + QTextOStream ts(&audioData); + ts << "AudioFileManager\n" + << item->getId() << '\n' + << item->getStartTime().sec << '\n' + << item->getStartTime().nsec << '\n' + << item->getDuration().sec << '\n' + << item->getDuration().nsec << '\n'; + + RG_DEBUG << "AudioListView::dragObject - " + << "file id = " << item->getId() + << ", start time = " << item->getStartTime() << endl; + + return new QTextDrag(audioData, this); +} + +} diff --git a/src/gui/widgets/AudioListView.h b/src/gui/widgets/AudioListView.h new file mode 100644 index 0000000..477054a --- /dev/null +++ b/src/gui/widgets/AudioListView.h @@ -0,0 +1,44 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_AUDIOLISTVIEW_H_ +#define _RG_AUDIOLISTVIEW_H_ + +#include <klistview.h> + +namespace Rosegarden { + +class AudioListView : public KListView +{ +public: + AudioListView(QWidget *parent = 0, const char *name = 0); + +protected: + bool acceptDrag(QDropEvent* e) const; + virtual QDragObject* dragObject(); +}; + +} + +#endif /*AUDIOLISTVIEW_H_*/ diff --git a/src/gui/widgets/AudioRouteMenu.cpp b/src/gui/widgets/AudioRouteMenu.cpp new file mode 100644 index 0000000..6f4c93f --- /dev/null +++ b/src/gui/widgets/AudioRouteMenu.cpp @@ -0,0 +1,381 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "AudioRouteMenu.h" +#include "WheelyButton.h" + +#include "base/Instrument.h" +#include "base/Studio.h" +#include "gui/studio/StudioControl.h" +#include "gui/widgets/RosegardenPopupMenu.h" +#include "sound/MappedCommon.h" +#include "sound/MappedStudio.h" +#include <kcombobox.h> +#include <klocale.h> +#include <qcursor.h> +#include <qobject.h> +#include <qpoint.h> +#include <qstring.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +AudioRouteMenu::AudioRouteMenu(QWidget *par, + Direction direction, + Format format, + Studio *studio, + Instrument *instrument) : + QObject(par), + m_studio(studio), + m_instrument(instrument), + m_direction(direction), + m_format(format) +{ + switch (format) { + + case Compact: { + m_combo = 0; + m_button = new WheelyButton(par); + connect(m_button, SIGNAL(wheel(bool)), this, SLOT(slotWheel(bool))); + connect(m_button, SIGNAL(clicked()), this, SLOT(slotShowMenu())); + break; + } + + case Regular: { + m_button = 0; + m_combo = new KComboBox(par); + connect(m_combo, SIGNAL(activated(int)), this, SLOT(slotEntrySelected(int))); + break; + } + + } + + slotRepopulate(); +} + +QWidget * +AudioRouteMenu::getWidget() +{ + if (m_button) + return m_button; + else + return m_combo; +} + +void +AudioRouteMenu::slotRepopulate() +{ + switch (m_format) { + + case Compact: + m_button->setText(getEntryText(getCurrentEntry())); + break; + + case Regular: + m_combo->clear(); + for (int i = 0; i < getNumEntries(); ++i) { + m_combo->insertItem(getEntryText(i)); + } + m_combo->setCurrentItem(getCurrentEntry()); + break; + } +} + +void +AudioRouteMenu::slotSetInstrument(Studio *studio, + Instrument *instrument) +{ + m_studio = studio; + m_instrument = instrument; + slotRepopulate(); +} + +void +AudioRouteMenu::slotWheel(bool up) +{ + int current = getCurrentEntry(); + if (up) { // actually moves down the list + if (current > 0) + slotEntrySelected(current - 1); + } else { + if (current < getNumEntries() - 1) + slotEntrySelected(current + 1); + } +} + +void +AudioRouteMenu::slotShowMenu() +{ + if (getNumEntries() == 0) + return ; + + RosegardenPopupMenu *menu = new RosegardenPopupMenu((QWidget *)parent()); + + for (int i = 0; i < getNumEntries(); ++i) { + + menu->insertItem(getEntryText(i), this, SLOT(slotEntrySelected(int)), + 0, i); + menu->setItemParameter(i, i); + } + + int itemHeight = menu->itemHeight(0) + 2; + QPoint pos = QCursor::pos(); + + pos.rx() -= 10; + pos.ry() -= (itemHeight / 2 + getCurrentEntry() * itemHeight); + + menu->popup(pos); +} + +int +AudioRouteMenu::getNumEntries() +{ + if (!m_instrument) + return 0; + + switch (m_direction) { + + case In: { + int stereoIns = + m_studio->getRecordIns().size() + + m_studio->getBusses().size(); + + if (m_instrument->getAudioChannels() > 1) { + return stereoIns; + } else { + return stereoIns * 2; + } + + break; + } + + case Out: + return m_studio->getBusses().size(); + } + + return 0; +} + +int +AudioRouteMenu::getCurrentEntry() +{ + if (!m_instrument) + return 0; + + switch (m_direction) { + + case In: { + bool stereo = (m_instrument->getAudioChannels() > 1); + + bool isBuss; + int channel; + int input = m_instrument->getAudioInput(isBuss, channel); + + if (isBuss) { + int recordIns = m_studio->getRecordIns().size(); + if (stereo) { + return recordIns + input; + } else { + return recordIns * 2 + input * 2 + channel; + } + } else { + if (stereo) { + return input; + } else { + return input * 2 + channel; + } + } + + break; + } + + case Out: + return m_instrument->getAudioOutput(); + } + + return 0; +} + +QString +AudioRouteMenu::getEntryText(int entry) +{ + switch (m_direction) { + + case In: { + bool stereo = (m_instrument->getAudioChannels() > 1); + int recordIns = m_studio->getRecordIns().size(); + + if (stereo) { + if (entry < recordIns) { + return i18n("In %1").arg(entry + 1); + } else if (entry == recordIns) { + return i18n("Master"); + } else { + return i18n("Sub %1").arg(entry - recordIns); + } + } else { + int channel = entry % 2; + entry /= 2; + if (entry < recordIns) { + return (channel ? i18n("In %1 R") : + i18n("In %1 L")).arg(entry + 1); + } else if (entry == recordIns) { + return (channel ? i18n("Master R") : + i18n("Master L")); + } else { + return (channel ? i18n("Sub %1 R") : + i18n("Sub %1 L")).arg(entry - recordIns); + } + } + break; + } + + case Out: + if (entry == 0) + return i18n("Master"); + else + return i18n("Sub %1").arg(entry); + } + + return QString(); +} + +void +AudioRouteMenu::slotEntrySelected(int i) +{ + switch (m_direction) { + + case In: { + bool stereo = (m_instrument->getAudioChannels() > 1); + + bool oldIsBuss; + int oldChannel; + int oldInput = m_instrument->getAudioInput(oldIsBuss, oldChannel); + + bool newIsBuss; + int newChannel = 0; + int newInput; + + int recordIns = m_studio->getRecordIns().size(); + + if (stereo) { + newIsBuss = (i >= recordIns); + if (newIsBuss) { + newInput = i - recordIns; + } else { + newInput = i; + } + } else { + newIsBuss = (i >= recordIns * 2); + newChannel = i % 2; + if (newIsBuss) { + newInput = i / 2 - recordIns; + } else { + newInput = i / 2; + } + } + + MappedObjectId oldMappedId = 0, newMappedId = 0; + + if (oldIsBuss) { + Buss *buss = m_studio->getBussById(oldInput); + if (buss) + oldMappedId = buss->getMappedId(); + } else { + RecordIn *in = m_studio->getRecordIn(oldInput); + if (in) + oldMappedId = in->getMappedId(); + } + + if (newIsBuss) { + Buss *buss = m_studio->getBussById(newInput); + if (!buss) + return ; + newMappedId = buss->getMappedId(); + } else { + RecordIn *in = m_studio->getRecordIn(newInput); + if (!in) + return ; + newMappedId = in->getMappedId(); + } + + if (oldMappedId != 0) { + StudioControl::disconnectStudioObjects + (oldMappedId, m_instrument->getMappedId()); + } else { + StudioControl::disconnectStudioObject + (m_instrument->getMappedId()); + } + + StudioControl::setStudioObjectProperty + (m_instrument->getMappedId(), + MappedAudioFader::InputChannel, + MappedObjectValue(newChannel)); + + if (newMappedId != 0) { + StudioControl::connectStudioObjects + (newMappedId, m_instrument->getMappedId()); + } + + if (newIsBuss) { + m_instrument->setAudioInputToBuss(newInput, newChannel); + } else { + m_instrument->setAudioInputToRecord(newInput, newChannel); + } + + break; + } + + case Out: { + BussId bussId = m_instrument->getAudioOutput(); + Buss *oldBuss = m_studio->getBussById(bussId); + Buss *newBuss = m_studio->getBussById(i); + if (!newBuss) + return ; + + if (oldBuss) { + StudioControl::disconnectStudioObjects + (m_instrument->getMappedId(), oldBuss->getMappedId()); + } else { + StudioControl::disconnectStudioObject + (m_instrument->getMappedId()); + } + + StudioControl::connectStudioObjects + (m_instrument->getMappedId(), newBuss->getMappedId()); + + m_instrument->setAudioOutput(i); + break; + } + } + + slotRepopulate(); + emit changed(); +} + +} +#include "AudioRouteMenu.moc" diff --git a/src/gui/widgets/AudioRouteMenu.h b/src/gui/widgets/AudioRouteMenu.h new file mode 100644 index 0000000..259da68 --- /dev/null +++ b/src/gui/widgets/AudioRouteMenu.h @@ -0,0 +1,94 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_AUDIOROUTEMENU_H_ +#define _RG_AUDIOROUTEMENU_H_ + +#include <qobject.h> +#include <qstring.h> + + +class QWidget; +class KComboBox; + + +namespace Rosegarden +{ + +class WheelyButton; +class Studio; +class Instrument; + + +class AudioRouteMenu : public QObject +{ + Q_OBJECT + +public: + enum Direction { In, Out }; + enum Format { Compact, Regular }; + + AudioRouteMenu(QWidget *parent, + Direction direction, + Format format, + Studio *studio = 0, + Instrument *instrument = 0); + + QWidget *getWidget(); + +public slots: + void slotRepopulate(); + void slotSetInstrument(Studio *, Instrument *); + +protected slots: + void slotWheel(bool up); + void slotShowMenu(); + void slotEntrySelected(int); + +signals: + // The menu writes changes directly to the instrument, but it + // also emits this to let you know something has changed + void changed(); + +private: + Studio *m_studio; + Instrument *m_instrument; + Direction m_direction; + Format m_format; + + WheelyButton *m_button; + KComboBox *m_combo; + + int getNumEntries(); + int getCurrentEntry(); // for instrument + QString getEntryText(int n); +}; + + + + +} + +#endif diff --git a/src/gui/widgets/AudioVUMeter.cpp b/src/gui/widgets/AudioVUMeter.cpp new file mode 100644 index 0000000..4c15a07 --- /dev/null +++ b/src/gui/widgets/AudioVUMeter.cpp @@ -0,0 +1,103 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "AudioVUMeter.h" + +#include "gui/rulers/VelocityColour.h" +#include <qcolor.h> +#include <qlabel.h> +#include <qpainter.h> +#include <qtimer.h> +#include <qwidget.h> +#include "VUMeter.h" + + +namespace Rosegarden +{ + +AudioVUMeter::AudioVUMeter(QWidget *parent, + VUMeter::VUMeterType type, + bool stereo, + bool hasRecord, + int width, + int height, + const char *name) : + QWidget(parent, name), + m_stereo(stereo) +{ + setBackgroundMode(Qt::NoBackground); + setFixedSize(width, height); + + // This offset is intended to match that for the height of the + // button pixmap in Fader (in studiowidgets.cpp, which + // is probably where this class should be too) + + m_yoff = height / 7; + m_yoff /= 10; + ++m_yoff; + m_yoff *= 10; + ++m_yoff; + + // This one is _not_ intended to match that for the button width + + m_xoff = width / 4; + if (m_xoff % 2 == 1) + ++m_xoff; + + m_meter = new AudioVUMeterImpl(this, type, stereo, hasRecord, + width - m_xoff, height - m_yoff, name); + + m_meter->move(m_xoff / 2, m_yoff / 2); +} + +void +AudioVUMeter::paintEvent(QPaintEvent *e) +{ + QPainter paint(this); + paint.setPen(colorGroup().mid()); + paint.drawRect(0, 0, width(), height()); + + paint.setPen(colorGroup().background()); + paint.setBrush(colorGroup().background()); + paint.drawRect(1, 1, width() - 2, m_yoff / 2 - 1); + paint.drawRect(1, 1, m_xoff / 2 - 1, height() - 2); + paint.drawRect(width() - m_xoff / 2 - 1, 1, m_xoff / 2, height() - 2); + paint.drawRect(1, height() - m_yoff / 2 - 1, width() - 2, m_yoff / 2); + paint.end(); + + m_meter->paintEvent(e); +} + +AudioVUMeter::AudioVUMeterImpl::AudioVUMeterImpl(QWidget *parent, + VUMeterType type, + bool stereo, + bool hasRecord, + int width, + int height, + const char *name) : + VUMeter(parent, type, stereo, hasRecord, width, height, VUMeter::Vertical, name) +{} + +} diff --git a/src/gui/widgets/AudioVUMeter.h b/src/gui/widgets/AudioVUMeter.h new file mode 100644 index 0000000..cff7c27 --- /dev/null +++ b/src/gui/widgets/AudioVUMeter.h @@ -0,0 +1,96 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_AUDIOVUMETER_H_ +#define _RG_AUDIOVUMETER_H_ + +#include <qwidget.h> +#include "VUMeter.h" + + +class QPaintEvent; + + +namespace Rosegarden +{ + + + +class AudioVUMeter : public QWidget +{ +public: + AudioVUMeter(QWidget *parent = 0, + VUMeter::VUMeterType type = VUMeter::AudioPeakHoldShort, + bool stereo = true, + bool hasRecord = false, + int width = 12, + int height = 140, + const char *name = 0); + + void setLevel(double dB) { + m_meter->setLevel(dB); + } + void setLevel(double dBleft, double dBright) { + m_meter->setLevel(dBleft, dBright); + } + + void setRecordLevel(double dB) { + m_meter->setRecordLevel(dB); + } + void setRecordLevel(double dBleft, double dBright) { + m_meter->setRecordLevel(dBleft, dBright); + } + + virtual void paintEvent(QPaintEvent*); + +protected: + class AudioVUMeterImpl : public VUMeter + { + public: + AudioVUMeterImpl(QWidget *parent, + VUMeterType type, + bool stereo, + bool hasRecord, + int width, + int height, + const char *name); + protected: + virtual void meterStart() { } + virtual void meterStop() { } + }; + + AudioVUMeterImpl *m_meter; + bool m_stereo; + int m_yoff; + int m_xoff; +}; + + +// A push button that emits wheel events. Used by AudioRouteMenu. +// + +} + +#endif diff --git a/src/gui/widgets/BigArrowButton.h b/src/gui/widgets/BigArrowButton.h new file mode 100644 index 0000000..505e374 --- /dev/null +++ b/src/gui/widgets/BigArrowButton.h @@ -0,0 +1,47 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_BIGARROWBUTTON_H_ +#define _RG_BIGARROWBUTTON_H_ + +#include <karrowbutton.h> + +namespace Rosegarden { + +class BigArrowButton : public KArrowButton +{ +public: + BigArrowButton(QWidget *parent = 0, Qt::ArrowType arrow = Qt::UpArrow, + const char *name = 0) : + KArrowButton(parent, arrow, name) { } + virtual ~BigArrowButton() { } + + virtual QSize sizeHint() const { + return QSize(20, 20); + } +}; + +} + +#endif /*BIGARROWBUTTON_H_*/ diff --git a/src/gui/widgets/CollapsingFrame.cpp b/src/gui/widgets/CollapsingFrame.cpp new file mode 100644 index 0000000..1f71ebf --- /dev/null +++ b/src/gui/widgets/CollapsingFrame.cpp @@ -0,0 +1,148 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "CollapsingFrame.h" +#include <kapplication.h> +#include <kstddirs.h> +#include <kconfig.h> +#include <kglobal.h> +#include <qfont.h> +#include <qframe.h> +#include <qlayout.h> +#include <qpixmap.h> +#include <qstring.h> +#include <qtoolbutton.h> +#include <qwidget.h> +#include <cassert> + + +namespace Rosegarden +{ + +CollapsingFrame::CollapsingFrame(QString label, QWidget *parent, const char *n) : + QFrame(parent, n), + m_widget(0), + m_fill(false), + m_collapsed(false) +{ + m_layout = new QGridLayout(this, 3, 3, 0, 0); + + m_toggleButton = new QToolButton(this); + m_toggleButton->setTextLabel(label); + m_toggleButton->setUsesTextLabel(true); + m_toggleButton->setUsesBigPixmap(false); + m_toggleButton->setTextPosition(QToolButton::BesideIcon); + m_toggleButton->setAutoRaise(true); + + QFont font(m_toggleButton->font()); + font.setBold(true); + m_toggleButton->setFont(font); + + QString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/"); + QPixmap pixmap(pixmapDir + "/misc/arrow-expanded.png"); + m_toggleButton->setIconSet(pixmap); + + connect(m_toggleButton, SIGNAL(clicked()), this, SLOT(toggle())); + + m_layout->addMultiCellWidget(m_toggleButton, 0, 0, 0, 2); +} + +CollapsingFrame::~CollapsingFrame() +{} + +void +CollapsingFrame::setWidgetFill(bool fill) +{ + m_fill = fill; +} + +QFont +CollapsingFrame::font() const +{ + return m_toggleButton->font(); +} + +void +CollapsingFrame::setFont(QFont font) +{ + m_toggleButton->setFont(font); +} + +void +CollapsingFrame::setWidget(QWidget *widget) +{ + assert(!m_widget); + m_widget = widget; + if (m_fill) { + m_layout->addMultiCellWidget(widget, 1, 1, 0, 2); + } else { + m_layout->addWidget(widget, 1, 1); + } + + bool expanded = true; + if (name(0)) { + KConfig *config = kapp->config(); + QString groupTemp = config->group(); + config->setGroup("CollapsingFrame"); + expanded = config->readBoolEntry(name(), true); + config->setGroup(groupTemp); + } + if (expanded != !m_collapsed) + toggle(); +} + +void +CollapsingFrame::toggle() +{ + int h = m_toggleButton->height(); + + m_collapsed = !m_collapsed; + + m_widget->setShown(!m_collapsed); + + QString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/"); + QPixmap pixmap; + + if (m_collapsed) { + pixmap = QPixmap(pixmapDir + "/misc/arrow-contracted.png"); + } else { + pixmap = QPixmap(pixmapDir + "/misc/arrow-expanded.png"); + } + + if (name(0)) { + KConfig *config = kapp->config(); + QString groupTemp = config->group(); + config->setGroup("CollapsingFrame"); + config->writeEntry(name(), !m_collapsed); + config->setGroup(groupTemp); + } + + m_toggleButton->setIconSet(pixmap); + + m_toggleButton->setMaximumHeight(h); +} + +} +#include "CollapsingFrame.moc" diff --git a/src/gui/widgets/CollapsingFrame.h b/src/gui/widgets/CollapsingFrame.h new file mode 100644 index 0000000..780a8b1 --- /dev/null +++ b/src/gui/widgets/CollapsingFrame.h @@ -0,0 +1,75 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_COLLAPSINGFRAME_H_ +#define _RG_COLLAPSINGFRAME_H_ + +#include <qframe.h> +#include <qstring.h> + + +class QWidget; +class QToolButton; +class QGridLayout; + + +namespace Rosegarden +{ + + + +class CollapsingFrame : public QFrame +{ + Q_OBJECT + +public: + CollapsingFrame(QString label, QWidget *parent = 0, const char *name = 0); + virtual ~CollapsingFrame(); + + QFont font() const; + void setFont(QFont font); + + /// If true, the widget fills the available space. Call before setWidget + void setWidgetFill(bool fill); + + /// This frame contains a single other widget. Set it here. + void setWidget(QWidget *w); + +public slots: + void toggle(); + +protected: + QGridLayout *m_layout; + QToolButton *m_toggleButton; + QWidget *m_widget; + bool m_fill; + bool m_collapsed; +}; + + + +} + +#endif diff --git a/src/gui/widgets/ColourTable.cpp b/src/gui/widgets/ColourTable.cpp new file mode 100644 index 0000000..c5fcfc6 --- /dev/null +++ b/src/gui/widgets/ColourTable.cpp @@ -0,0 +1,131 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "ColourTable.h" + +#include <klocale.h> +#include "misc/Strings.h" +#include "base/ColourMap.h" +#include "ColourTableItem.h" +#include "gui/general/GUIPalette.h" +#include <kcolordialog.h> +#include <klineeditdlg.h> +#include <qcolor.h> +#include <qpoint.h> +#include <qstring.h> +#include <qtable.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +ColourTable::ColourTable +(QWidget *parent, ColourMap &input, ColourList &list) + : QTable(1, 2, parent, "RColourTable") +{ + setSorting(FALSE); + setSelectionMode(QTable::SingleRow); + horizontalHeader()->setLabel(0, i18n("Name")); + horizontalHeader()->setLabel(1, i18n("Color")); + populate_table(input, list); + connect(this, SIGNAL(doubleClicked(int, int, int, const QPoint&)), + SLOT(slotEditEntry(int, int))); + +} + +void +ColourTable::slotEditEntry(int row, int col) +{ + + switch (col) { + case 0: { + if (row == 0) + return ; + bool ok = false; + QString newName = KLineEditDlg::getText(i18n("Modify Color Name"), i18n("Enter new name"), + item(row, col)->text(), &ok); + + if ((ok == true) && (!newName.isEmpty())) { + emit entryTextChanged(row, newName); + return ; + } + } + break; + case 1: { + QColor temp = m_colours[row]; + KColorDialog box(this, "", true); + + int result = box.getColor(temp); + + if (result == KColorDialog::Accepted) { + emit entryColourChanged(row, temp); + return ; + } + } + break; + default: // Should never happen + break; + } + +} + +void +ColourTable::populate_table(ColourMap &input, ColourList &list) +{ + m_colours.reserve(input.size()); + setNumRows(input.size()); + + QString name; + + unsigned int i = 0; + + for (RCMap::const_iterator it = input.begin(); it != input.end(); ++it) { + if (it->second.second == std::string("")) + name = i18n("Default Color"); + else + name = strtoqstr(it->second.second); + + QTableItem *text = new QTableItem( + dynamic_cast<QTable*>(this), + QTableItem::Never, name); + + setItem(i, 0, text); + + list[i] = it->first; + m_colours[i] = GUIPalette::convertColour(it->second.first); + + ColourTableItem *temp = new ColourTableItem(this, m_colours[i]); + setItem(i, 1, temp); + + verticalHeader()->setLabel(i, QString::number(it->first)); + + ++i; + } + +} + +} +#include "ColourTable.moc" diff --git a/src/gui/widgets/ColourTable.h b/src/gui/widgets/ColourTable.h new file mode 100644 index 0000000..48e2309 --- /dev/null +++ b/src/gui/widgets/ColourTable.h @@ -0,0 +1,72 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + Portions of this file Copyright 2003 + Mark Hymers <markh@linuxfromscratch.org> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENCOLOURTABLE_H_ +#define _RG_ROSEGARDENCOLOURTABLE_H_ + +#include <map> +#include <qtable.h> +#include <vector> + + +class QWidget; +class ColourList; + + +namespace Rosegarden +{ + +class ColourMap; + + +class ColourTable : public QTable +{ + Q_OBJECT + +public: + typedef std::map<unsigned int, unsigned int, std::less<unsigned int> > ColourList; + ColourTable(QWidget *parent, ColourMap &input, ColourList &list); + void populate_table(ColourMap &input, ColourList &list); + + +signals: + void entryTextChanged(unsigned int, QString); + void entryColourChanged(unsigned int, QColor); + +public slots: + void slotEditEntry (int, int); + +protected: + std::vector<QColor> m_colours; + +}; + + +} + +#endif diff --git a/src/gui/widgets/ColourTableItem.cpp b/src/gui/widgets/ColourTableItem.cpp new file mode 100644 index 0000000..3dfbd87 --- /dev/null +++ b/src/gui/widgets/ColourTableItem.cpp @@ -0,0 +1,52 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "ColourTableItem.h" + +#include <qcolor.h> +#include <qpainter.h> +#include <qrect.h> +#include <qtable.h> + + +namespace Rosegarden +{ + +void +ColourTableItem::setColor(QColor &input) +{ + currentColour = input; +} + +void +ColourTableItem::paint(QPainter *p, const QColorGroup &cg, const QRect &cr, bool selected) +{ + QColorGroup g(cg); + g.setColor(QColorGroup::Base, currentColour); + selected = false; + QTableItem::paint(p, g, cr, selected); +} + +} diff --git a/src/gui/widgets/ColourTableItem.h b/src/gui/widgets/ColourTableItem.h new file mode 100644 index 0000000..a8c906e --- /dev/null +++ b/src/gui/widgets/ColourTableItem.h @@ -0,0 +1,60 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENCOLOURTABLEITEM_H_ +#define _RG_ROSEGARDENCOLOURTABLEITEM_H_ + +#include <qcolor.h> +#include <qtable.h> + +class QTable; +class QRect; +class QPainter; +class QColorGroup; + + +namespace Rosegarden +{ + + + +class ColourTableItem : public QTableItem +{ +public: + ColourTableItem(QTable *t, const QColor &input) + : QTableItem(t, QTableItem::Never, ""), + currentColour(input) {} + void setColor(QColor &input); + void paint(QPainter *p, const QColorGroup &cg, const QRect &cr, bool selected); + +protected: + QColor currentColour; +}; + + + +} + +#endif diff --git a/src/gui/widgets/CurrentProgressDialog.cpp b/src/gui/widgets/CurrentProgressDialog.cpp new file mode 100644 index 0000000..2e3735f --- /dev/null +++ b/src/gui/widgets/CurrentProgressDialog.cpp @@ -0,0 +1,84 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "CurrentProgressDialog.h" + +#include "ProgressDialog.h" +#include <qobject.h> + + +namespace Rosegarden +{ + +CurrentProgressDialog* CurrentProgressDialog::getInstance() +{ + if (!m_instance) + m_instance = new CurrentProgressDialog(0); + + return m_instance; +} + + +ProgressDialog* +CurrentProgressDialog::get() +{ + return m_currentProgressDialog; +} + +void +CurrentProgressDialog::set(ProgressDialog* d) +{ + if (m_currentProgressDialog) + m_currentProgressDialog->disconnect(getInstance()); + + m_currentProgressDialog = d; + + // this lets the progress dialog deregister itself when it's deleted + connect(d, SIGNAL(destroyed()), + getInstance(), SLOT(slotCurrentProgressDialogDestroyed())); +} + +void CurrentProgressDialog::freeze() +{ + if (m_currentProgressDialog) + m_currentProgressDialog->slotFreeze(); +} + +void CurrentProgressDialog::thaw() +{ + if (m_currentProgressDialog) + m_currentProgressDialog->slotThaw(); +} + +void CurrentProgressDialog::slotCurrentProgressDialogDestroyed() +{ + m_currentProgressDialog = 0; +} + +CurrentProgressDialog* CurrentProgressDialog::m_instance = 0; +ProgressDialog* CurrentProgressDialog::m_currentProgressDialog = 0; + +} +#include "CurrentProgressDialog.moc" diff --git a/src/gui/widgets/CurrentProgressDialog.h b/src/gui/widgets/CurrentProgressDialog.h new file mode 100644 index 0000000..d0eea2e --- /dev/null +++ b/src/gui/widgets/CurrentProgressDialog.h @@ -0,0 +1,81 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_CURRENTPROGRESSDIALOG_H_ +#define _RG_CURRENTPROGRESSDIALOG_H_ + +#include <qobject.h> + + + + +namespace Rosegarden +{ + +class ProgressDialog; + + +class CurrentProgressDialog : public QObject +{ + Q_OBJECT +public: + static CurrentProgressDialog* getInstance(); + + static ProgressDialog* get(); + static void set(ProgressDialog*); + + /** + * Block the current progress so that it won't appear + * regardless of passing time and occurring events. + * This is useful when you want to show another dialog + * and you want to make sure the progress dialog is out of the way + */ + static void freeze(); + + /** + * Restores the progress dialog to its normal state atfer a freeze() + */ + static void thaw(); + +public slots: + /// Called then the current progress dialog is being destroyed + void slotCurrentProgressDialogDestroyed(); + +protected: + CurrentProgressDialog(QObject* parent, const char* name = 0) + : QObject(parent, name) {} + + //--------------- Data members --------------------------------- + static CurrentProgressDialog* m_instance; + static ProgressDialog* m_currentProgressDialog; +}; + + +// A Text popup - a tooltip we can control. +// + +} + +#endif diff --git a/src/gui/widgets/DiatonicPitchChooser.cpp b/src/gui/widgets/DiatonicPitchChooser.cpp new file mode 100644 index 0000000..95b8b3a --- /dev/null +++ b/src/gui/widgets/DiatonicPitchChooser.cpp @@ -0,0 +1,244 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "DiatonicPitchChooser.h" + +#include <iostream> +#include <klocale.h> +#include "base/NotationRules.h" +#include "base/NotationTypes.h" +#include "gui/general/MidiPitchLabel.h" +#include "PitchDragLabel.h" +#include <kcombobox.h> +#include <qgroupbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qspinbox.h> +#include <qstring.h> +#include <qwidget.h> + +namespace Rosegarden +{ + +DiatonicPitchChooser::DiatonicPitchChooser(QString title, + QWidget *parent, + int defaultNote, + int defaultPitch, + int defaultOctave) : + QGroupBox(1, Horizontal, title, parent), + m_defaultPitch(defaultPitch) +{ + m_pitchDragLabel = new PitchDragLabel(this, defaultPitch); + + QHBox *hbox = new QHBox(this); + hbox->setSpacing(6); + + m_step = new KComboBox( hbox ); + m_step->setSizeLimit( 7 ); + m_step->insertItem(i18n("C")); + m_step->insertItem(i18n("D")); + m_step->insertItem(i18n("E")); + m_step->insertItem(i18n("F")); + m_step->insertItem(i18n("G")); + m_step->insertItem(i18n("A")); + m_step->insertItem(i18n("B")); + m_step->setCurrentItem(defaultNote); + + m_octave = new KComboBox( hbox ); + m_octave->insertItem(i18n("-2")); + m_octave->insertItem(i18n("-1")); + m_octave->insertItem(i18n("0")); + m_octave->insertItem(i18n("1")); + m_octave->insertItem(i18n("2")); + m_octave->insertItem(i18n("3")); + m_octave->insertItem(i18n("4")); + m_octave->insertItem(i18n("5")); + m_octave->insertItem(i18n("6")); + m_octave->insertItem(i18n("7")); + m_octave->setCurrentItem(defaultOctave); + + m_accidental = new KComboBox( hbox ); + m_accidental->insertItem(i18n("double flat")); + m_accidental->insertItem(i18n("flat")); + m_accidental->insertItem(i18n("natural")); + m_accidental->insertItem(i18n("sharp")); + m_accidental->insertItem(i18n("double sharp")); + m_accidental->setCurrentItem(2); // default: natural + + m_pitchLabel = new QLabel(QString("%1").arg(getPitch()), hbox); + + m_pitchLabel->setMinimumWidth(40); + + connect(m_accidental, SIGNAL(activated(int)), + this, SLOT(slotSetAccidental(int))); + + connect(m_octave, SIGNAL(activated(int)), + this, SLOT(slotSetOctave(int))); + + connect(m_step, SIGNAL(activated(int)), + this, SLOT(slotSetStep(int))); + + //connect(m_pitch, SIGNAL(valueChanged(int)), + // this, SIGNAL(pitchChanged(int))); + + //connect(m_pitch, SIGNAL(valueChanged(int)), + // this, SIGNAL(preview(int))); + + connect(m_pitchDragLabel, SIGNAL(pitchDragged(int,int,int)), + this, SLOT(slotSetNote(int,int,int))); + + //connect(m_pitchDragLabel, SIGNAL(pitchChanged(int)), + // this, SLOT(slotSetPitch(int))); + + connect(m_pitchDragLabel, SIGNAL(pitchChanged(int,int,int)), + this, SLOT(slotSetNote(int,int,int))); + + //connect(m_pitchDragLabel, SIGNAL(pitchChanged(int)), + // this, SIGNAL(pitchChanged(int))); + + connect(m_pitchDragLabel, SIGNAL(pitchDragged(int,int,int)), + this, SIGNAL(noteChanged(int,int,int))); + + connect(m_pitchDragLabel, SIGNAL(pitchChanged(int,int,int)), + this, SIGNAL(noteChanged(int,int,int))); + + connect(m_pitchDragLabel, SIGNAL(preview(int)), + this, SIGNAL(preview(int))); + +} + +int +DiatonicPitchChooser::getPitch() const +{ + return 12 * m_octave->currentItem() + scale_Cmajor[m_step->currentItem()] + + (m_accidental->currentItem() - 2); +} + +int +DiatonicPitchChooser::getAccidental() +{ + return m_accidental->currentItem() - 2; +} + +void +DiatonicPitchChooser::slotSetPitch(int pitch) +{ + if (m_pitchDragLabel->getPitch() != pitch) + m_pitchDragLabel->slotSetPitch(pitch); + + m_octave->setCurrentItem((int)(((long) pitch) / 12)); + + int step = steps_Cmajor[pitch % 12]; + m_step->setCurrentItem(step); + + int pitchChange = (pitch % 12) - scale_Cmajor[step]; + + m_accidental->setCurrentItem(pitchChange + 2); + + m_pitchLabel->setText(QString("%1").arg(pitch)); + + update(); +} + +void +DiatonicPitchChooser::slotSetStep(int step) +{ + if (m_step->currentItem() != step) + m_step->setCurrentItem(step); + std::cout << "slot_step called" << std::endl; + setLabelsIfNeeded(); + update(); +} + +void +DiatonicPitchChooser::slotSetOctave(int octave) +{ + if (m_octave->currentItem() != octave) + m_octave->setCurrentItem(octave); + setLabelsIfNeeded(); + update(); +} + +/** input 0..4: doubleflat .. doublesharp */ +void +DiatonicPitchChooser::slotSetAccidental(int accidental) +{ + if (m_accidental->currentItem() != accidental) + m_accidental->setCurrentItem(accidental); + setLabelsIfNeeded(); + update(); +} + +/** sets the m_pitchDragLabel and m_pitchLabel if needed */ +void +DiatonicPitchChooser::setLabelsIfNeeded() +{ + //if (m_pitchDragLabel->) + //{ + m_pitchDragLabel->slotSetPitch(getPitch(), m_octave->currentItem(), m_step->currentItem()); + //} + m_pitchLabel->setText(QString("%1").arg(getPitch())); +} + +void +DiatonicPitchChooser::slotSetNote(int pitch, int octave, int step) +{ + //if (m_pitch->value() != p) + // m_pitch->setValue(p); + if (m_pitchDragLabel->getPitch() != pitch) + m_pitchDragLabel->slotSetPitch(pitch, octave, step); + + m_octave->setCurrentItem(octave); + m_step->setCurrentItem(step); + + int pitchOffset = pitch - (octave * 12 + scale_Cmajor[step]); + m_accidental->setCurrentItem(pitchOffset + 2); + + //MidiPitchLabel pl(p); + m_pitchLabel->setText(QString("%1").arg(pitch)); + update(); +} + +void +DiatonicPitchChooser::slotResetToDefault() +{ + slotSetPitch(m_defaultPitch); +} + +int +DiatonicPitchChooser::getOctave() const +{ + return m_octave->currentItem(); +} + + +int +DiatonicPitchChooser::getStep() const +{ + return m_step->currentItem(); +} + +} +#include "DiatonicPitchChooser.moc" diff --git a/src/gui/widgets/DiatonicPitchChooser.h b/src/gui/widgets/DiatonicPitchChooser.h new file mode 100644 index 0000000..8e5b20d --- /dev/null +++ b/src/gui/widgets/DiatonicPitchChooser.h @@ -0,0 +1,103 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENDIATONICPITCHCHOOSER_H_ +#define _RG_ROSEGARDENDIATONICPITCHCHOOSER_H_ + +#include <qgroupbox.h> +#include <qstring.h> + + +class QWidget; +class QSpinBox; +class QComboBox; +class QLabel; + + +namespace Rosegarden +{ + +class PitchDragLabel; + + +class DiatonicPitchChooser : public QGroupBox +{ + Q_OBJECT +public: + DiatonicPitchChooser(QString title, + QWidget *parent, + int defaultNote = 0, + int defaultPitch = 60, + int defaultOctave = 5); + + // C0=0, D0=1, C1=12, etc. + int getPitch() const; + + // C=0, D=1, E=2, F=3, etc. + int getStep() const; + + // pitch 0 is the first C of octave 0. + int getOctave() const; + + // 0 = none, + // -x = x flats + // x = x sharps + int getAccidental(); + +signals: + void pitchChanged(int); + //pitch, octave, step + void noteChanged(int,int,int); + void preview(int); + +public slots: + void slotSetPitch(int); + //pitch, octave, step + void slotSetNote(int,int,int); + void slotSetStep(int); + void slotSetOctave(int); + void slotSetAccidental(int); + void slotResetToDefault(); + +protected: + int m_defaultPitch; + + PitchDragLabel *m_pitchDragLabel; + + QComboBox *m_step; + QComboBox *m_accidental; + QComboBox *m_octave; + + QLabel *m_pitchLabel; + +private: + void setLabelsIfNeeded(); +}; + + + +} + +#endif diff --git a/src/gui/widgets/Fader.cpp b/src/gui/widgets/Fader.cpp new file mode 100644 index 0000000..2413323 --- /dev/null +++ b/src/gui/widgets/Fader.cpp @@ -0,0 +1,567 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "Fader.h" +#include "TextFloat.h" + +#include "misc/Debug.h" +#include "base/AudioLevel.h" +#include <qcolor.h> +#include <qevent.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qpoint.h> +#include <qstring.h> +#include <qtimer.h> +#include <qwidget.h> +#include <cmath> + +namespace Rosegarden +{ + +Fader::PixmapCache Fader::m_pixmapCache; + + +Fader::Fader(AudioLevel::FaderType type, + int w, int h, QWidget *parent) : + QWidget(parent), + m_integral(false), + m_vertical(h > w), + m_min(0), + m_max(0), + m_type(type), + m_clickMousePos( -1), + m_float(new TextFloat(this)), + m_floatTimer(new QTimer()) +{ + setBackgroundMode(Qt::NoBackground); + setFixedSize(w, h); // provisional + calculateButtonPixmap(); + // if (m_vertical) { + // setFixedSize(w, h + m_buttonPixmap->height() + 4); + // } else { + // setFixedSize(w + m_buttonPixmap->width() + 4, h); + // } + + if (m_vertical) { + m_sliderMin = buttonPixmap()->height() / 2 + 2; + m_sliderMax = height() - m_sliderMin; + } else { + m_sliderMin = buttonPixmap()->width() / 2 + 2; + m_sliderMax = width() - m_sliderMin; + } + + m_outlineColour = colorGroup().mid(); + + calculateGroovePixmap(); + setFader(0.0); + + connect(m_floatTimer, SIGNAL(timeout()), this, SLOT(slotFloatTimeout())); + m_float->hide(); +} + +Fader::Fader(int min, int max, int deflt, + int w, int h, QWidget *parent) : + QWidget(parent), + m_integral(true), + m_vertical(h > w), + m_min(min), + m_max(max), + m_clickMousePos( -1), + m_float(new TextFloat(this)), + m_floatTimer(new QTimer()) +{ + setBackgroundMode(Qt::NoBackground); + setFixedSize(w, h); // provisional + calculateButtonPixmap(); + // if (m_vertical) { + // setFixedSize(w, h + m_buttonPixmap->height() + 4); + // } else { + // setFixedSize(w + m_buttonPixmap->width() + 4, h); + // } + + if (m_vertical) { + m_sliderMin = buttonPixmap()->height() / 2 + 2; + m_sliderMax = height() - m_sliderMin; + } else { + m_sliderMin = buttonPixmap()->width() / 2 + 2; + m_sliderMax = width() - m_sliderMin; + } + + m_outlineColour = colorGroup().mid(); + + calculateGroovePixmap(); + setFader(deflt); + + connect(m_floatTimer, SIGNAL(timeout()), this, SLOT(slotFloatTimeout())); + m_float->hide(); +} + +Fader::Fader(int min, int max, int deflt, + bool vertical, QWidget *parent) : + QWidget(parent), + m_integral(true), + m_vertical(vertical), + m_min(min), + m_max(max), + m_clickMousePos( -1), + m_float(new TextFloat(this)), + m_floatTimer(new QTimer()) +{ + setBackgroundMode(Qt::NoBackground); + calculateButtonPixmap(); + + if (m_vertical) { + m_sliderMin = buttonPixmap()->height() / 2 + 2; + m_sliderMax = height() - m_sliderMin; + } else { + m_sliderMin = buttonPixmap()->width() / 2 + 2; + m_sliderMax = width() - m_sliderMin; + } + + m_outlineColour = colorGroup().mid(); + + calculateGroovePixmap(); + setFader(deflt); + + connect(m_floatTimer, SIGNAL(timeout()), this, SLOT(slotFloatTimeout())); + m_float->hide(); +} + +Fader::~Fader() +{} + +void +Fader::setOutlineColour(QColor c) +{ + m_outlineColour = c; + calculateGroovePixmap(); +} + +QPixmap * +Fader::groovePixmap() +{ + PixmapCache::iterator i = m_pixmapCache.find(SizeRec(width(), height())); + if (i != m_pixmapCache.end()) { + ColourPixmapRec::iterator j = i->second.first.find(m_outlineColour.pixel()); + if (j != i->second.first.end()) { + return j->second; + } + } + return 0; +} + +QPixmap * +Fader::buttonPixmap() +{ + PixmapCache::iterator i = m_pixmapCache.find(SizeRec(width(), height())); + if (i != m_pixmapCache.end()) { + return i->second.second; + } else + return 0; +} + +float +Fader::getFaderLevel() const +{ + return m_value; +} + +void +Fader::setFader(float value) +{ + m_value = value; + emit faderChanged(value); + paintEvent(0); +} + +float +Fader::position_to_value(int position) +{ + float value; + + if (m_integral) { + float sliderLength = float(m_sliderMax) - float(m_sliderMin); + value = float(position) + * float(m_max - m_min) / sliderLength - float(m_min); + if (value > m_max) + value = float(m_max); + if (value < m_min) + value = float(m_min); + } else { + value = AudioLevel::fader_to_dB + (position, m_sliderMax - m_sliderMin, m_type); + } + /* + RG_DEBUG << "Fader::position_to_value - position = " << position + << ", new value = " << value << endl; + + if (m_min != m_max) // works for integral case + { + if (value > m_max) value = float(m_max); + if (value < m_min) value = float(m_min); + } + + RG_DEBUG << "Fader::position_to_value - limited value = " << value << endl; + */ + return value; +} + +int +Fader::value_to_position(float value) +{ + int position; + + if (m_integral) { + float sliderLength = float(m_sliderMax) - float(m_sliderMin); + position = + int(sliderLength * (value - float(m_min)) / float(m_max - m_min) + 0.1); + } else { + position = + AudioLevel::dB_to_fader + (value, m_sliderMax - m_sliderMin, m_type); + } + + return position; +} + +void +Fader::paintEvent(QPaintEvent *) +{ + QPainter paint(this); + int position = value_to_position(m_value); + + if (m_vertical) { + + int aboveButton = height() - position - m_sliderMin - buttonPixmap()->height() / 2; + int belowButton = position + m_sliderMin - buttonPixmap()->height() / 2; + + if (aboveButton > 0) { + paint.drawPixmap(0, 0, + *groovePixmap(), + 0, 0, + groovePixmap()->width(), aboveButton); + } + + if (belowButton > 0) { + paint.drawPixmap(0, aboveButton + buttonPixmap()->height(), + *groovePixmap(), + 0, aboveButton + buttonPixmap()->height(), + groovePixmap()->width(), belowButton); + } + + int buttonMargin = (width() - buttonPixmap()->width()) / 2; + + paint.drawPixmap(buttonMargin, aboveButton, *buttonPixmap()); + + paint.drawPixmap(0, aboveButton, + *groovePixmap(), + 0, aboveButton, + buttonMargin, buttonPixmap()->height()); + + paint.drawPixmap(buttonMargin + buttonPixmap()->width(), aboveButton, + *groovePixmap(), + buttonMargin + buttonPixmap()->width(), aboveButton, + width() - buttonMargin - buttonPixmap()->width(), + buttonPixmap()->height()); + + } else { + //... update + int leftOfButton = + (m_sliderMax - m_sliderMin) - position - buttonPixmap()->width() / 2; + + int rightOfButton = + position - buttonPixmap()->width() / 2; + + if (leftOfButton > 0) { + paint.drawPixmap(0, 0, + *groovePixmap(), + 0, 0, + leftOfButton, groovePixmap()->height()); + } + + if (rightOfButton > 0) { + paint.drawPixmap(rightOfButton + buttonPixmap()->width(), 0, + *groovePixmap(), + groovePixmap()->width() - rightOfButton, 0, + rightOfButton, groovePixmap()->height()); + } + + paint.drawPixmap(leftOfButton, 0, *buttonPixmap()); + } + + paint.end(); +} + +void +Fader::mousePressEvent(QMouseEvent *e) +{ + m_clickMousePos = -1; + + if (e->button() == LeftButton) { + + if (e->type() == QEvent::MouseButtonDblClick) { + setFader(0); + return ; + } + + if (m_vertical) { + int buttonPosition = value_to_position(m_value); + int clickPosition = height() - e->y() - m_sliderMin; + + if (clickPosition < buttonPosition + buttonPixmap()->height() / 2 && + clickPosition > buttonPosition - buttonPixmap()->height() / 2) { + m_clickMousePos = clickPosition; + m_clickButtonPos = value_to_position(m_value); + showFloatText(); + } + } + } +} + +void +Fader::mouseReleaseEvent(QMouseEvent *e) +{ + mouseMoveEvent(e); + m_clickMousePos = -1; +} + +void +Fader::mouseMoveEvent(QMouseEvent *e) +{ + if (m_clickMousePos >= 0) { + if (m_vertical) { + int mousePosition = height() - e->y() - m_sliderMin; + int delta = mousePosition - m_clickMousePos; + int buttonPosition = m_clickButtonPos + delta; + if (buttonPosition < 0) + buttonPosition = 0; + if (buttonPosition > m_sliderMax - m_sliderMin) { + buttonPosition = m_sliderMax - m_sliderMin; + } + setFader(position_to_value(buttonPosition)); + showFloatText(); + } + } +} + +void +Fader::wheelEvent(QWheelEvent *e) +{ + int buttonPosition = value_to_position(m_value); + if (e->state() & ShiftButton) { + if (e->delta() > 0) + buttonPosition += 10; + else + buttonPosition -= 10; + } else { + if (e->delta() > 0) + buttonPosition += 1; + else + buttonPosition -= 1; + } + RG_DEBUG << "Fader::wheelEvent - button position = " << buttonPosition << endl; + setFader(position_to_value(buttonPosition)); + RG_DEBUG << "Fader::wheelEvent - value = " << m_value << endl; + + showFloatText(); +} + +void +Fader::showFloatText() +{ + // draw on the float text + + QString text; + + if (m_integral) { + text = QString("%1").arg(int(m_value)); + } else if (m_value == AudioLevel::DB_FLOOR) { + text = "Off"; + } else { + float v = fabs(m_value); + text = QString("%1%2.%3%4%5 dB") + .arg(m_value < 0 ? '-' : '+') + .arg(int(v)) + .arg(int(v * 10) % 10) + .arg(int(v * 100) % 10) + .arg(int(v * 1000) % 10); + } + + m_float->setText(text); + + // Reposition - we need to sum the relative positions up to the + // topLevel or dialog to please move(). + // + QWidget *par = parentWidget(); + QPoint totalPos = this->pos(); + + while (par->parentWidget() && !par->isTopLevel() && !par->isDialog()) { + totalPos += par->pos(); + par = par->parentWidget(); + } + + // Move just top/right + // + m_float->move(totalPos + QPoint(width() + 2, 0)); + + // Show + m_float->show(); + + // one shot, 500ms + m_floatTimer->start(500, true); +} + +void +Fader::slotFloatTimeout() +{ + m_float->hide(); +} + +void +Fader::calculateGroovePixmap() +{ + QPixmap *& map = m_pixmapCache[SizeRec(width(), height())].first[m_outlineColour.pixel()]; + + delete map; + map = new QPixmap(width(), height()); + map->fill(colorGroup().background()); + QPainter paint(map); + paint.setBrush(colorGroup().background()); + + if (m_vertical) { + + paint.setPen(m_outlineColour); + paint.drawRect(0, 0, width(), height()); + + if (m_integral) { + //... + } else { + for (int dB = -70; dB <= 10; ) { + int position = value_to_position(float(dB)); + if (position >= 0 && + position < m_sliderMax - m_sliderMin) { + if (dB == 0) + paint.setPen(colorGroup().dark()); + else + paint.setPen(colorGroup().midlight()); + paint.drawLine(1, (m_sliderMax - position), + width() - 2, (m_sliderMax - position)); + } + if (dB < -10) + dB += 10; + else + dB += 2; + } + } + + paint.setPen(colorGroup().dark()); + paint.setBrush(colorGroup().mid()); + paint.drawRect(width() / 2 - 3, height() - m_sliderMax, + 6, m_sliderMax - m_sliderMin); + paint.end(); + } else { + //... + } +} + +void +Fader::calculateButtonPixmap() +{ + PixmapCache::iterator i = m_pixmapCache.find(SizeRec(width(), height())); + if (i != m_pixmapCache.end() && i->second.second) + return ; + + QPixmap *& map = m_pixmapCache[SizeRec(width(), height())].second; + + if (m_vertical) { + + int buttonHeight = height() / 7; + buttonHeight /= 10; + ++buttonHeight; + buttonHeight *= 10; + ++buttonHeight; + int buttonWidth = width() * 2 / 3; + buttonWidth /= 5; + ++buttonWidth; + buttonWidth *= 5; + if (buttonWidth > width() - 2) + buttonWidth = width() - 2; + + map = new QPixmap(buttonWidth, buttonHeight); + map->fill(colorGroup().background()); + + int x = 0; + int y = 0; + + QPainter paint(map); + + paint.setPen(colorGroup().light()); + paint.drawLine(x + 1, y, x + buttonWidth - 2, y); + paint.drawLine(x, y + 1, x, y + buttonHeight - 2); + + paint.setPen(colorGroup().midlight()); + paint.drawLine(x + 1, y + 1, x + buttonWidth - 2, y + 1); + paint.drawLine(x + 1, y + 1, x + 1, y + buttonHeight - 2); + + paint.setPen(colorGroup().mid()); + paint.drawLine(x + 2, y + buttonHeight - 2, x + buttonWidth - 2, + y + buttonHeight - 2); + paint.drawLine(x + buttonWidth - 2, y + 2, x + buttonWidth - 2, + y + buttonHeight - 2); + + paint.setPen(colorGroup().dark()); + paint.drawLine(x + 1, y + buttonHeight - 1, x + buttonWidth - 2, + y + buttonHeight - 1); + paint.drawLine(x + buttonWidth - 1, y + 1, x + buttonWidth - 1, + y + buttonHeight - 2); + + paint.setPen(colorGroup().shadow()); + paint.drawLine(x + 1, y + buttonHeight / 2, x + buttonWidth - 2, + y + buttonHeight / 2); + + paint.setPen(colorGroup().mid()); + paint.drawLine(x + 1, y + buttonHeight / 2 - 1, x + buttonWidth - 2, + y + buttonHeight / 2 - 1); + paint.drawPoint(x, y + buttonHeight / 2); + + paint.setPen(colorGroup().light()); + paint.drawLine(x + 1, y + buttonHeight / 2 + 1, x + buttonWidth - 2, + y + buttonHeight / 2 + 1); + + paint.setPen(colorGroup().button()); + paint.setBrush(colorGroup().button()); + paint.drawRect(x + 2, y + 2, buttonWidth - 4, buttonHeight / 2 - 4); + paint.drawRect(x + 2, y + buttonHeight / 2 + 2, + buttonWidth - 4, buttonHeight / 2 - 4); + + paint.end(); + } else { + //... + } +} + +} +#include "Fader.moc" diff --git a/src/gui/widgets/Fader.h b/src/gui/widgets/Fader.h new file mode 100644 index 0000000..f4afb24 --- /dev/null +++ b/src/gui/widgets/Fader.h @@ -0,0 +1,137 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENFADER_H_ +#define _RG_ROSEGARDENFADER_H_ + +#include "base/AudioLevel.h" +#include <map> +#include <qcolor.h> +#include <qwidget.h> +#include <utility> + + +class QWheelEvent; +class QTimer; +class QPixmap; +class QPaintEvent; +class QMouseEvent; + + +namespace Rosegarden +{ + +class TextFloat; + + +class Fader : public QWidget +{ + Q_OBJECT + +public: + /** + * Construct a dB fader. The fader calculates its orientation + * based on the given dimensions. + */ + Fader(AudioLevel::FaderType, + int width, int height, QWidget *parent); + + /** + * Construct a fader on an integral scale. The fader calculates + * its orientation based on the given dimensions. + */ + Fader(int min, int max, int deflt, + int width, int height, QWidget *parent); + + /** + * Construct a fader on an integral scale, with a 1:1 ratio of + * pixel positions and values. + */ + Fader(int min, int max, int deflt, + bool vertical, QWidget *parent); + + virtual ~Fader(); + + void setOutlineColour(QColor); + + float getFaderLevel() const; + +public slots: + void setFader(float value); + void slotFloatTimeout(); + +signals: + void faderChanged(float); + +protected: + virtual void paintEvent(QPaintEvent *); + virtual void mousePressEvent(QMouseEvent *); + virtual void mouseReleaseEvent(QMouseEvent *); + virtual void mouseMoveEvent(QMouseEvent *); + virtual void wheelEvent(QWheelEvent *); + + float position_to_value(int); + int value_to_position(float); + + void calculateGroovePixmap(); + void calculateButtonPixmap(); + void showFloatText(); + + bool m_integral; + bool m_vertical; + + int m_sliderMin; + int m_sliderMax; + float m_value; + + int m_min; + int m_max; + AudioLevel::FaderType m_type; + + int m_clickMousePos; + int m_clickButtonPos; + + TextFloat *m_float; + QTimer *m_floatTimer; + + QPixmap *groovePixmap(); + QPixmap *buttonPixmap(); + + QColor m_outlineColour; + + typedef std::pair<int, int> SizeRec; + typedef std::map<unsigned int, QPixmap *> ColourPixmapRec; // key is QColor::pixel() + typedef std::pair<ColourPixmapRec, QPixmap *> PixmapRec; + typedef std::map<SizeRec, PixmapRec> PixmapCache; + static PixmapCache m_pixmapCache; +}; + + +// AudioVUMeter - a vertical audio meter. Default is stereo. +// + +} + +#endif diff --git a/src/gui/widgets/HSpinBox.cpp b/src/gui/widgets/HSpinBox.cpp new file mode 100644 index 0000000..efdb9d1 --- /dev/null +++ b/src/gui/widgets/HSpinBox.cpp @@ -0,0 +1,81 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "HSpinBox.h" + +#include <qstring.h> +#include <cmath> +#include <algorithm> + +namespace Rosegarden +{ + +QString HSpinBox::mapValueToText(int j) +{ + QString str; + str.sprintf(m_format, float(j) / m_scaleFactor); + return str; +} + +int HSpinBox::mapTextToValue( bool* ok ) +{ + *ok = true; + float f = atof(text()); + return int(f * m_scaleFactor); +} + +HSpinBox::HSpinBox( int minV, int maxV, int step, QWidget* parent, + double bottom, double top, int decimals, float initialValue) + : QSpinBox(minV,maxV,step,parent) +{ + setValidator(new QDoubleValidator(bottom,top,decimals,this)); + initialize(decimals); + setValuef(initialValue); +} + + //constructor with default settings +HSpinBox::HSpinBox( QWidget* parent, float initialValue, int step, + double bottom, double top, int decimals, + const QObject* recv, const char* mem) + : QSpinBox((int)(bottom*pow(10.0, decimals)), + (int)(top*pow(10.0, decimals)), step, parent) +{ + setValidator(new QDoubleValidator(bottom,top,decimals,this)); + initialize(decimals); + setValuef(initialValue); + if (recv != NULL && mem != NULL) + QObject::connect(this, SIGNAL(valueChanged(int)), recv, mem); +} + +float HSpinBox::valuef() { return float(value()) / m_scaleFactor; } +void HSpinBox::setValuef(float v) { setValue(static_cast<int>(v * m_scaleFactor)); } + +void HSpinBox::initialize(int digits) { + m_scaleFactor = pow(10.0, digits); + sprintf(m_format, "%c%1i.%1if", '%', digits+3, digits); +} + + +} diff --git a/src/gui/widgets/HSpinBox.h b/src/gui/widgets/HSpinBox.h new file mode 100644 index 0000000..aa60b65 --- /dev/null +++ b/src/gui/widgets/HSpinBox.h @@ -0,0 +1,67 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_HSPINBOX_H_ +#define _RG_HSPINBOX_H_ + +#include <qobject.h> +#include <qspinbox.h> +#include <qstring.h> +#include <qvalidator.h> + + +namespace Rosegarden +{ + +class HSpinBox : public QSpinBox +{ + QString mapValueToText(int j); + + int mapTextToValue( bool* ok ); + +public: + HSpinBox( int minV, int maxV, int step, QWidget* parent, + double bottom, double top, int decimals, float initialValue); + + //constructor with default settings + HSpinBox( QWidget* parent, float initialValue = 0.2, int step=1, + double bottom=-25.0, double top=25.0, int decimals=3, + const QObject* recv=NULL, const char* mem=NULL); + + float valuef(); + void setValuef(float v); + void initialize(int digits); + +private: + + float m_scaleFactor; //scale of the value + char m_format[3]; //text format + +}; + + +} + +#endif diff --git a/src/gui/widgets/Label.cpp b/src/gui/widgets/Label.cpp new file mode 100644 index 0000000..69f504b --- /dev/null +++ b/src/gui/widgets/Label.cpp @@ -0,0 +1,2 @@ +#include "Label.h" +#include "Label.moc" diff --git a/src/gui/widgets/Label.h b/src/gui/widgets/Label.h new file mode 100644 index 0000000..e704c35 --- /dev/null +++ b/src/gui/widgets/Label.h @@ -0,0 +1,63 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENLABEL_H_ +#define _RG_ROSEGARDENLABEL_H_ + +#include <qlabel.h> + + +class QWidget; +class QWheelEvent; +class QMouseEvent; + + +namespace Rosegarden +{ + +class Label : public QLabel +{ + Q_OBJECT +public: + Label(QWidget *parent = 0, const char *name=0): + QLabel(parent, name) {;} + +protected: + virtual void mouseDoubleClickEvent(QMouseEvent * /*e*/) + { emit doubleClicked(); } + + virtual void wheelEvent(QWheelEvent * e) + { emit scrollWheel(e->delta()); } + +signals: + void doubleClicked(); + void scrollWheel(int); + +}; + + +} + +#endif diff --git a/src/gui/widgets/MidiFaderWidget.cpp b/src/gui/widgets/MidiFaderWidget.cpp new file mode 100644 index 0000000..a2ef7fc --- /dev/null +++ b/src/gui/widgets/MidiFaderWidget.cpp @@ -0,0 +1,41 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "MidiFaderWidget.h" + +#include "AudioVUMeter.h" +#include "Fader.h" +#include "Rotary.h" +#include <kcombobox.h> +#include <qframe.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qwidget.h> + + +namespace Rosegarden +{ +} +#include "MidiFaderWidget.moc" diff --git a/src/gui/widgets/MidiFaderWidget.h b/src/gui/widgets/MidiFaderWidget.h new file mode 100644 index 0000000..7bdf520 --- /dev/null +++ b/src/gui/widgets/MidiFaderWidget.h @@ -0,0 +1,72 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_MIDIFADERWIDGET_H_ +#define _RG_MIDIFADERWIDGET_H_ + +#include <qframe.h> +#include <qstring.h> + + +class QWidget; +class QPushButton; +class KComboBox; + + +namespace Rosegarden +{ + +class Rotary; +class Fader; +class AudioVUMeter; + + +class MidiFaderWidget : public QFrame +{ + Q_OBJECT + +public: + MidiFaderWidget(QWidget *parent, + QString id = ""); + + AudioVUMeter *m_vuMeter; + + Fader *m_fader; + + QPushButton *m_muteButton; + QPushButton *m_soloButton; + QPushButton *m_recordButton; + Rotary *m_pan; + + KComboBox *m_output; + + QString m_id; +}; + + + +} + +#endif diff --git a/src/gui/widgets/PitchChooser.cpp b/src/gui/widgets/PitchChooser.cpp new file mode 100644 index 0000000..e20647d --- /dev/null +++ b/src/gui/widgets/PitchChooser.cpp @@ -0,0 +1,113 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "PitchChooser.h" + +#include <klocale.h> +#include "gui/general/MidiPitchLabel.h" +#include "PitchDragLabel.h" +#include <qgroupbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qspinbox.h> +#include <qstring.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +PitchChooser::PitchChooser(QString title, + QWidget *parent, + int defaultPitch) : + QGroupBox(1, Horizontal, title, parent), + m_defaultPitch(defaultPitch) +{ + m_pitchDragLabel = new PitchDragLabel(this, defaultPitch); + + QHBox *hbox = new QHBox(this); + hbox->setSpacing(6); + + new QLabel(i18n("Pitch:"), hbox); + + m_pitch = new QSpinBox(hbox); + m_pitch->setMinValue(0); + m_pitch->setMaxValue(127); + m_pitch->setValue(defaultPitch); + + MidiPitchLabel pl(defaultPitch); + m_pitchLabel = new QLabel(pl.getQString(), hbox); + m_pitchLabel->setMinimumWidth(40); + + connect(m_pitch, SIGNAL(valueChanged(int)), + this, SLOT(slotSetPitch(int))); + + connect(m_pitch, SIGNAL(valueChanged(int)), + this, SIGNAL(pitchChanged(int))); + + connect(m_pitch, SIGNAL(valueChanged(int)), + this, SIGNAL(preview(int))); + + connect(m_pitchDragLabel, SIGNAL(pitchDragged(int)), + this, SLOT(slotSetPitch(int))); + + connect(m_pitchDragLabel, SIGNAL(pitchChanged(int)), + this, SLOT(slotSetPitch(int))); + + connect(m_pitchDragLabel, SIGNAL(pitchChanged(int)), + this, SIGNAL(pitchChanged(int))); + + connect(m_pitchDragLabel, SIGNAL(preview(int)), + this, SIGNAL(preview(int))); + +} + +int +PitchChooser::getPitch() const +{ + return m_pitch->value(); +} + +void +PitchChooser::slotSetPitch(int p) +{ + if (m_pitch->value() != p) + m_pitch->setValue(p); + if (m_pitchDragLabel->getPitch() != p) + m_pitchDragLabel->slotSetPitch(p); + + MidiPitchLabel pl(p); + m_pitchLabel->setText(pl.getQString()); + update(); +} + +void +PitchChooser::slotResetToDefault() +{ + slotSetPitch(m_defaultPitch); +} + +} +#include "PitchChooser.moc" diff --git a/src/gui/widgets/PitchChooser.h b/src/gui/widgets/PitchChooser.h new file mode 100644 index 0000000..df3b8ef --- /dev/null +++ b/src/gui/widgets/PitchChooser.h @@ -0,0 +1,73 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENPITCHCHOOSER_H_ +#define _RG_ROSEGARDENPITCHCHOOSER_H_ + +#include <qgroupbox.h> +#include <qstring.h> + + +class QWidget; +class QSpinBox; +class QLabel; + + +namespace Rosegarden +{ + +class PitchDragLabel; + + +class PitchChooser : public QGroupBox +{ + Q_OBJECT +public: + PitchChooser(QString title, + QWidget *parent, + int defaultPitch = 60); + + int getPitch() const; + +signals: + void pitchChanged(int); + void preview(int); + +public slots: + void slotSetPitch(int); + void slotResetToDefault(); + +protected: + int m_defaultPitch; + PitchDragLabel *m_pitchDragLabel; + QSpinBox *m_pitch; + QLabel *m_pitchLabel; +}; + + + +} + +#endif diff --git a/src/gui/widgets/PitchDragLabel.cpp b/src/gui/widgets/PitchDragLabel.cpp new file mode 100644 index 0000000..1d22a77 --- /dev/null +++ b/src/gui/widgets/PitchDragLabel.cpp @@ -0,0 +1,269 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "PitchDragLabel.h" + +#include "base/NotationRules.h" +#include "base/NotationTypes.h" +#include "gui/editors/notation/NotePixmapFactory.h" +#include <qcanvas.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qsize.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +PitchDragLabel::PitchDragLabel(QWidget *parent, + int defaultPitch, + bool defaultSharps) : + QWidget(parent), + m_pitch(defaultPitch), + m_usingSharps(defaultSharps), + m_clickedY(0), + m_clicked(false), + m_npf(new NotePixmapFactory()) +{ + calculatePixmap(); +} + +PitchDragLabel::~PitchDragLabel() +{ + delete m_npf; +} + +void +PitchDragLabel::slotSetPitch(int p) +{ + bool up = (p > m_pitch); + m_usingSharps = up; + if (m_pitch == p) + return ; + m_pitch = p; + calculatePixmap(); + emitPitchChange(); + paintEvent(0); +} + +void +PitchDragLabel::slotSetPitch(int pitch, int octave, int step) +{ + if (m_pitch == pitch) + return ; + m_pitch = pitch; + calculatePixmap(pitch, octave, step); + emit pitchChanged(pitch); + emit pitchChanged(pitch, octave, step); + paintEvent(0); +} + +void +PitchDragLabel::mousePressEvent(QMouseEvent *e) +{ + if (e->button() == LeftButton) { + m_clickedY = e->y(); + m_clickedPitch = m_pitch; + m_clicked = true; + emit preview(m_pitch); + } +} + +void +PitchDragLabel::mouseMoveEvent(QMouseEvent *e) +{ + if (m_clicked) { + + int y = e->y(); + int diff = y - m_clickedY; + int pitchDiff = diff * 4 / m_npf->getLineSpacing(); + + int newPitch = m_clickedPitch - pitchDiff; + if (newPitch < 0) + newPitch = 0; + if (newPitch > 127) + newPitch = 127; + + if (m_pitch != newPitch) { + bool up = (newPitch > m_pitch); + m_pitch = newPitch; + m_usingSharps = up; + calculatePixmap(); + emit pitchDragged(m_pitch); + if (up) + { + // use sharps + emit pitchDragged(m_pitch, (int)(((long)m_pitch) / 12), + steps_Cmajor_with_sharps[m_pitch % 12]); + } + else + { + // use flats + emit pitchDragged(m_pitch, (int)(((long)m_pitch) / 12), + steps_Cmajor_with_flats[m_pitch % 12]); + } + emit preview(m_pitch); + paintEvent(0); + } + } +} + +void +PitchDragLabel::mouseReleaseEvent(QMouseEvent *e) +{ + mouseMoveEvent(e); + emitPitchChange(); + m_clicked = false; +} + +void +PitchDragLabel::emitPitchChange() +{ + emit pitchChanged(m_pitch); + + Pitch newPitch(m_pitch); + + if (m_usingSharps) + { + Rosegarden::Key key = Rosegarden::Key("C major"); + emit pitchDragged(m_pitch, newPitch.getOctave(0), newPitch.getNoteInScale(key)); + } + else + { + Rosegarden::Key key = Rosegarden::Key("A minor"); + emit pitchDragged(m_pitch, newPitch.getOctave(0), (newPitch.getNoteInScale(key) + 5) % 7); + } +} + +void +PitchDragLabel::wheelEvent(QWheelEvent *e) +{ + if (e->delta() > 0) { + if (m_pitch < 127) { + ++m_pitch; + m_usingSharps = true; + calculatePixmap(); + emitPitchChange(); + emit preview(m_pitch); + paintEvent(0); + } + } else { + if (m_pitch > 0) { + --m_pitch; + m_usingSharps = false; + calculatePixmap(); + emitPitchChange(); + emit preview(m_pitch); + paintEvent(0); + } + } +} + +void +PitchDragLabel::paintEvent(QPaintEvent *) +{ + QPainter paint(this); + paint.fillRect(0, 0, width(), height(), paint.backgroundColor()); + + int x = width() / 2 - m_pixmap.width() / 2; + if (x < 0) + x = 0; + + int y = height() / 2 - m_pixmap.height() / 2; + if (y < 0) + y = 0; + + paint.drawPixmap(x, y, m_pixmap); + + +} + +QSize +PitchDragLabel::sizeHint() const +{ + return QSize(150, 135); +} + +void +PitchDragLabel::calculatePixmap(int pitch, int octave, int step) const +{ + std::string clefType = Clef::Treble; + int octaveOffset = 0; + + if (m_pitch > 94) { + octaveOffset = 2; + } else if (m_pitch > 82) { + octaveOffset = 1; + } else if (m_pitch < 60) { + clefType = Clef::Bass; + if (m_pitch < 24) { + octaveOffset = -2; + } else if (m_pitch < 36) { + octaveOffset = -1; + } + } + + QCanvasPixmap *pmap = m_npf->makePitchDisplayPixmap + (m_pitch, + Clef(clefType, octaveOffset), + octave, step); + + m_pixmap = *pmap; + + delete pmap; +} + +void +PitchDragLabel::calculatePixmap() const +{ + std::string clefType = Clef::Treble; + int octaveOffset = 0; + + if (m_pitch > 94) { + octaveOffset = 2; + } else if (m_pitch > 82) { + octaveOffset = 1; + } else if (m_pitch < 60) { + clefType = Clef::Bass; + if (m_pitch < 24) { + octaveOffset = -2; + } else if (m_pitch < 36) { + octaveOffset = -1; + } + } + + QCanvasPixmap *pmap = m_npf->makePitchDisplayPixmap + (m_pitch, + Clef(clefType, octaveOffset), + m_usingSharps); + + m_pixmap = *pmap; + + delete pmap; +} + +} +#include "PitchDragLabel.moc" diff --git a/src/gui/widgets/PitchDragLabel.h b/src/gui/widgets/PitchDragLabel.h new file mode 100644 index 0000000..7114611 --- /dev/null +++ b/src/gui/widgets/PitchDragLabel.h @@ -0,0 +1,99 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENPITCHDRAGLABEL_H_ +#define _RG_ROSEGARDENPITCHDRAGLABEL_H_ + +#include <qpixmap.h> +#include <qsize.h> +#include <qwidget.h> + + +class QWheelEvent; +class QPaintEvent; +class QMouseEvent; + + +namespace Rosegarden +{ + +class NotePixmapFactory; + + +class PitchDragLabel : public QWidget +{ + Q_OBJECT +public: + PitchDragLabel(QWidget *parent, + int defaultPitch = 60, bool defaultSharps = true); + ~PitchDragLabel(); + + int getPitch() const { return m_pitch; } + + virtual QSize sizeHint() const; + +signals: + void pitchDragged(int); + // pitch, octave, step + void pitchDragged(int,int,int); + void pitchChanged(int); // mouse release + // pitch, octave, step + void pitchChanged(int,int,int); // mouse release + void preview(int); + +public slots: + void slotSetPitch(int); + void slotSetPitch(int,int,int); + +protected: + virtual void paintEvent(QPaintEvent *); + virtual void mousePressEvent(QMouseEvent *e); + virtual void mouseReleaseEvent(QMouseEvent *e); + virtual void mouseMoveEvent(QMouseEvent *e); + virtual void wheelEvent(QWheelEvent *e); + + void calculatePixmap() const; + void calculatePixmap(int pitch, int octave, int step) const; + + /** emits 'pitchChanged' events, both diatonic and chromatic */ + void emitPitchChange(); + + mutable QPixmap m_pixmap; + + int m_pitch; + int m_clickedY; + int m_clickedPitch; + bool m_clicked; + + bool m_usingSharps; + + NotePixmapFactory *m_npf; +}; + + + +} + +#endif diff --git a/src/gui/widgets/PluginControl.cpp b/src/gui/widgets/PluginControl.cpp new file mode 100644 index 0000000..acf33ea --- /dev/null +++ b/src/gui/widgets/PluginControl.cpp @@ -0,0 +1,228 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "PluginControl.h" +#include "Rotary.h" +#include "misc/Strings.h" +#include "base/AudioPluginInstance.h" +#include "gui/general/GUIPalette.h" +#include "gui/studio/AudioPluginManager.h" +#include "gui/widgets/Rotary.h" +#include <qfont.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qobject.h> +#include <qstring.h> +#include <qwidget.h> +#include <cmath> + + +namespace Rosegarden +{ + +PluginControl::PluginControl(QWidget *parent, + QGridLayout *layout, + ControlType type, + PluginPort *port, + AudioPluginManager *aPM, + int index, + float initialValue, + bool showBounds, + bool hidden): + QObject(parent), + m_layout(layout), + m_type(type), + m_port(port), + m_pluginManager(aPM), + m_index(index) +{ + QFont plainFont; + plainFont.setPointSize((plainFont.pointSize() * 9 ) / 10); + + QLabel *controlTitle = + new QLabel(QString("%1 ").arg(strtoqstr(port->getName())), parent); + controlTitle->setFont(plainFont); + + if (type == Rotary) { + float lowerBound = port->getLowerBound(); + float upperBound = port->getUpperBound(); + // Default value was already handled when calling this constructor + + if (lowerBound > upperBound) { + float swap = upperBound; + upperBound = lowerBound; + lowerBound = swap; + } + + float step = (upperBound - lowerBound) / 100.0; + float pageStep = step * 10.f; + Rotary::TickMode ticks = Rotary::PageStepTicks; + bool snapToTicks = false; + + if (port->getDisplayHint() & PluginPort::Integer) { + step = 1.0; + ticks = Rotary::StepTicks; + if (upperBound - lowerBound > 30.0) + pageStep = 10.0; + snapToTicks = true; + } + if (port->getDisplayHint() & PluginPort::Toggled) { + lowerBound = -0.0001; + upperBound = 1.0001; + step = 1.0; + pageStep = 1.0; + ticks = Rotary::StepTicks; + snapToTicks = true; + } + + float displayLower = lowerBound, displayUpper = upperBound; + + bool logarithmic = (port->getDisplayHint() & PluginPort::Logarithmic); + + if (logarithmic) { + float logthresh = -10; + float thresh = powf(10, logthresh); + if (lowerBound > thresh) lowerBound = log10f(lowerBound); + else { + if (upperBound > 1) lowerBound = 0; + else lowerBound = logthresh; + } + if (upperBound > thresh) upperBound = log10f(upperBound); + else upperBound = logthresh; + + step = (upperBound - lowerBound) / 100.0; + pageStep = step * 10.f; + initialValue = log10f(initialValue); + } + + QLabel *low; + if (port->getDisplayHint() & + (PluginPort::Integer | PluginPort::Toggled)) { + low = new QLabel(QString("%1").arg(int(displayLower)), parent); + } else { + low = new QLabel(QString("%1").arg(displayLower), parent); + } + low->setFont(plainFont); + +// std::cerr << "port " << port->getName() << ": lower bound " +// << displayLower << ", upper bound " << displayUpper +// << ", logarithmic " << logarithmic << ", default " +// << initialValue << ", actual lower " << lowerBound +// << ", actual upper " << upperBound << ", step " +// << step << std::endl; + + m_dial = new ::Rosegarden::Rotary(parent, + lowerBound, // min + upperBound, // max + step, // step + pageStep, // page step + initialValue, // initial + 30, // size + ticks, + snapToTicks, + false, // centred + logarithmic); + + m_dial->setKnobColour(GUIPalette::getColour(GUIPalette::RotaryPlugin)); + + connect(m_dial, SIGNAL(valueChanged(float)), + this, SLOT(slotValueChanged(float))); + + QLabel *upp; + if (port->getDisplayHint() & + (PluginPort::Integer | PluginPort::Toggled)) { + upp = new QLabel(QString("%1").arg(int(displayUpper)), parent); + } else { + upp = new QLabel(QString("%1").arg(displayUpper), parent); + } + upp->setFont(plainFont); + + QWidgetItem *item; + + if (!hidden) { + controlTitle->show(); + item = new QWidgetItem(controlTitle); + item->setAlignment(Qt::AlignRight | Qt::AlignBottom); + m_layout->addItem(item); + } else { + controlTitle->hide(); + } + + if (showBounds && !hidden) { + low->show(); + item = new QWidgetItem(low); + item->setAlignment(Qt::AlignRight | Qt::AlignBottom); + m_layout->addItem(item); + } else { + low->hide(); + } + + if (!hidden) { + m_dial->show(); + item = new QWidgetItem(m_dial); + item->setAlignment(Qt::AlignCenter); + m_layout->addItem(item); + } else { + m_dial->hide(); + } + + if (showBounds && !hidden) { + upp->show(); + item = new QWidgetItem(upp); + item->setAlignment(Qt::AlignLeft | Qt::AlignBottom); + m_layout->addItem(item); + } else { + upp->hide(); + } + } +} + +void +PluginControl::setValue(float value, bool emitSignals) +{ + if (!emitSignals) + m_dial->blockSignals(true); + m_dial->setPosition(value); + if (!emitSignals) + m_dial->blockSignals(false); + else + emit valueChanged(value); +} + +float +PluginControl::getValue() const +{ + return m_dial == 0 ? 0 : m_dial->getPosition(); +} + +void +PluginControl::slotValueChanged(float value) +{ + emit valueChanged(value); +} + +} +#include "PluginControl.moc" diff --git a/src/gui/widgets/PluginControl.h b/src/gui/widgets/PluginControl.h new file mode 100644 index 0000000..83d2d33 --- /dev/null +++ b/src/gui/widgets/PluginControl.h @@ -0,0 +1,104 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_PLUGINCONTROL_H_ +#define _RG_PLUGINCONTROL_H_ + +#include <qobject.h> +#include <vector> + + +class QWidget; +class QHBox; +class QGridLayout; + + +namespace Rosegarden +{ + +class Rotary; +class PluginPort; +class AudioPluginManager; +class Studio; + +class PluginControl : public QObject +{ + Q_OBJECT +public: + + typedef enum + { + Rotary, + Slider, + NumericSlider + } ControlType; + + PluginControl(QWidget *parent, + QGridLayout *layout, + ControlType type, + PluginPort *port, + AudioPluginManager *pluginManager, + int index, + float initialValue, + bool showBounds, + bool hidden); + + void setValue(float value, bool emitSignals = true); + float getValue() const; + + int getIndex() const { return m_index; } + + void show(); + void hide(); + +public slots: + void slotValueChanged(float value); + +signals: + void valueChanged(float value); + +protected: + + //--------------- Data members --------------------------------- + + QGridLayout *m_layout; + + ControlType m_type; + PluginPort *m_port; + + ::Rosegarden::Rotary *m_dial; // we have to specify the namespace here otherwise gcc 4.1 thinks it's the enum value above + AudioPluginManager *m_pluginManager; + + int m_index; + +}; + +typedef std::vector<PluginControl*>::iterator ControlIterator; +typedef std::vector<QHBox*>::iterator ControlLineIterator; + + +} + +#endif diff --git a/src/gui/widgets/ProgressBar.cpp b/src/gui/widgets/ProgressBar.cpp new file mode 100644 index 0000000..c4cb88e --- /dev/null +++ b/src/gui/widgets/ProgressBar.cpp @@ -0,0 +1,44 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "ProgressBar.h" + +#include <kprogress.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +ProgressBar::ProgressBar(int totalSteps, + bool /*useDelay*/, + QWidget *creator, + const char *name, + WFlags f) : + KProgress(totalSteps, creator, name, f) +{} + +} +#include "ProgressBar.moc" diff --git a/src/gui/widgets/ProgressBar.h b/src/gui/widgets/ProgressBar.h new file mode 100644 index 0000000..3ce93e1 --- /dev/null +++ b/src/gui/widgets/ProgressBar.h @@ -0,0 +1,56 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENPROGRESSBAR_H_ +#define _RG_ROSEGARDENPROGRESSBAR_H_ + +#include <kprogress.h> + + +class QWidget; + + +namespace Rosegarden +{ + + + +class ProgressBar : public KProgress +{ + Q_OBJECT + +public: + ProgressBar(int totalSteps, + bool useDelay, + QWidget *creator = 0, + const char *name = 0, + WFlags f = 0); + +}; + + +} + +#endif diff --git a/src/gui/widgets/ProgressDialog.cpp b/src/gui/widgets/ProgressDialog.cpp new file mode 100644 index 0000000..1f6811f --- /dev/null +++ b/src/gui/widgets/ProgressDialog.cpp @@ -0,0 +1,209 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "ProgressDialog.h" +#include "CurrentProgressDialog.h" +#include "misc/Debug.h" +#include "gui/application/RosegardenApplication.h" +#include <klocale.h> +#include <qcursor.h> +#include <qprogressdialog.h> +#include <qstring.h> +#include <qtimer.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +bool ProgressDialog::m_modalVisible = false; + + +ProgressDialog::ProgressDialog(QWidget *creator, + const char *name, + bool modal): + KProgressDialog(creator, name, + i18n("Processing..."), QString::null, modal), + m_wasVisible(false), + m_frozen(false), + m_modal(modal) +{ + setCaption(i18n("Processing...")); + RG_DEBUG << "ProgressDialog::ProgressDialog type 1 - " + << labelText() << " - modal : " << modal << endl; + + connect(progressBar(), SIGNAL(percentageChanged (int)), + this, SLOT(slotCheckShow(int))); + + m_chrono.start(); + + CurrentProgressDialog::set + (this); + + setMinimumDuration(500); // set a default value for this +} + +ProgressDialog::ProgressDialog( + const QString &labelText, + int totalSteps, + QWidget *creator, + const char *name, + bool modal) : + KProgressDialog(creator, + name, + i18n("Processing..."), + labelText, + modal), + m_wasVisible(false), + m_frozen(false), + m_modal(modal) +{ + progressBar()->setTotalSteps(totalSteps); + + RG_DEBUG << "ProgressDialog::ProgressDialog type 2 - " + << labelText << " - modal : " << modal << endl; + + connect(progressBar(), SIGNAL(percentageChanged (int)), + this, SLOT(slotCheckShow(int))); + + m_chrono.start(); + + CurrentProgressDialog::set + (this); + + setMinimumDuration(500); // set a default value for this +} + +ProgressDialog::~ProgressDialog() +{ + m_modalVisible = false; +} + +void +ProgressDialog::polish() +{ + KProgressDialog::polish(); + + if (allowCancel()) + setCursor(Qt::ArrowCursor); + else + QApplication::setOverrideCursor(QCursor(Qt::waitCursor)); +} + +void ProgressDialog::hideEvent(QHideEvent* e) +{ + if (!allowCancel()) + QApplication::restoreOverrideCursor(); + + KProgressDialog::hideEvent(e); + m_modalVisible = false; +} + +void +ProgressDialog::slotSetOperationName(QString name) +{ + // RG_DEBUG << "ProgressDialog::slotSetOperationName(" + // << name << ") visible : " << isVisible() << endl; + + setLabel(name); + // Little trick stolen from QProgressDialog + // increase resize only, never shrink + int w = QMAX( isVisible() ? width() : 0, sizeHint().width() ); + int h = QMAX( isVisible() ? height() : 0, sizeHint().height() ); + resize( w, h ); +} + +void ProgressDialog::slotCancel() +{ + RG_DEBUG << "ProgressDialog::slotCancel()\n"; + KProgressDialog::slotCancel(); + slotFreeze(); +} + +void ProgressDialog::slotCheckShow(int) +{ + // RG_DEBUG << "ProgressDialog::slotCheckShow() : " + // << m_chrono.elapsed() << " - " << minimumDuration() + // << endl; + + if (!isVisible() && + !m_frozen && + m_chrono.elapsed() > minimumDuration()) { + RG_DEBUG << "ProgressDialog::slotCheckShow() : showing dialog\n"; + show(); + if (m_modal) + m_modalVisible = true; + processEvents(); + } +} + +void ProgressDialog::slotFreeze() +{ + RG_DEBUG << "ProgressDialog::slotFreeze()\n"; + + m_wasVisible = isVisible(); + if (isVisible()) { + m_modalVisible = false; + hide(); + } + + // This is also a convenient place to ensure the wait cursor (if + // currently shown) returns to the original cursor to ensure that + // the user can respond to whatever's freezing the progress dialog + QApplication::restoreOverrideCursor(); + + mShowTimer->stop(); + m_frozen = true; +} + +void ProgressDialog::slotThaw() +{ + RG_DEBUG << "ProgressDialog::slotThaw()\n"; + + if (m_wasVisible) { + if (m_modal) + m_modalVisible = true; + show(); + } + + // Restart timer + mShowTimer->start(minimumDuration()); + m_frozen = false; + m_chrono.restart(); +} + +void ProgressDialog::processEvents() +{ + // RG_DEBUG << "ProgressDialog::processEvents: modalVisible is " + // << m_modalVisible << endl; + if (m_modalVisible) { + kapp->processEvents(50); + } else { + rgapp->refreshGUI(50); + } +} + +} +#include "ProgressDialog.moc" diff --git a/src/gui/widgets/ProgressDialog.h b/src/gui/widgets/ProgressDialog.h new file mode 100644 index 0000000..b753493 --- /dev/null +++ b/src/gui/widgets/ProgressDialog.h @@ -0,0 +1,98 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENPROGRESSDIALOG_H_ +#define _RG_ROSEGARDENPROGRESSDIALOG_H_ + +#define private protected // fugly +#include <kprogress.h> +#undef private +#include <qdatetime.h> + +class QWidget; +class QString; +class QHideEvent; + + +namespace Rosegarden +{ + + + +class ProgressDialog : public KProgressDialog +{ + Q_OBJECT +public: + ProgressDialog(QWidget * creator = 0, + const char * name = 0, + bool modal = true); + + ProgressDialog(const QString &labelText, + int totalSteps, + QWidget *creator = 0, + const char *name = 0, + bool modal = true); + + ~ProgressDialog(); + + /** + * A "safe" way to process events without worrying about user + * input during the process. If there is a modal progress dialog + * visible, then this will permit user input so as to allow the + * user to hit Cancel; otherwise it will prevent all user input + */ + static void processEvents(); + + virtual void polish(); + +public slots: + void slotSetOperationName(QString); + void slotCancel(); + + /// Stop and hide (if it's shown) the progress dialog + void slotFreeze(); + + /// Restore the dialog to its normal state + void slotThaw(); + +protected slots: + void slotCheckShow(int); + +protected: + virtual void hideEvent(QHideEvent*); + + //--------------- Data members --------------------------------- + + QTime m_chrono; + bool m_wasVisible; + bool m_frozen; + bool m_modal; + static bool m_modalVisible; +}; + + +} + +#endif diff --git a/src/gui/widgets/QDeferScrollView.cpp b/src/gui/widgets/QDeferScrollView.cpp new file mode 100644 index 0000000..01864a3 --- /dev/null +++ b/src/gui/widgets/QDeferScrollView.cpp @@ -0,0 +1,52 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "QDeferScrollView.h" + +#include <qscrollview.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +QDeferScrollView::QDeferScrollView(QWidget* parent, const char *name, WFlags f) + : QScrollView(parent, name, f) +{ + setFocusPolicy(QWidget::WheelFocus); +} + +void QDeferScrollView::setBottomMargin(int m) +{ + setMargins(leftMargin(), topMargin(), rightMargin(), m); +} + +void QDeferScrollView::contentsWheelEvent(QWheelEvent* e) +{ + emit gotWheelEvent(e); +} + +} +#include "QDeferScrollView.moc" diff --git a/src/gui/widgets/QDeferScrollView.h b/src/gui/widgets/QDeferScrollView.h new file mode 100644 index 0000000..e4b2e3d --- /dev/null +++ b/src/gui/widgets/QDeferScrollView.h @@ -0,0 +1,75 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_QDEFERSCROLLVIEW_H_ +#define _RG_QDEFERSCROLLVIEW_H_ + +#include <qscrollview.h> + + +class QWidget; +class QWheelEvent; + + +namespace Rosegarden +{ + + + +/** + * A QScrollView which defers vertical scrolling (through mouse wheel) + * elsewhere, typically another QScrollView, so that both can be kept + * in sync. The master scrollview will connect its vertical scrollbar + * to the slave view so the scrollbar will act on both views. + * + * The slave scrollview will defer its scrolling to the master by + * having the gotWheelEvent() signal connected to a slot in the master + * scrollview, which will simply process the wheel event as if it had + * received it itself. + * + * @see TrackEditor + * @see SegmentCanvas + * @see TrackEditor::m_trackButtonScroll + */ +class QDeferScrollView : public QScrollView +{ + Q_OBJECT +public: + QDeferScrollView(QWidget* parent=0, const char *name=0, WFlags f=0); + + void setBottomMargin(int); + +signals: + void gotWheelEvent(QWheelEvent*); + +protected: + virtual void contentsWheelEvent(QWheelEvent*); + +}; + + +} + +#endif diff --git a/src/gui/widgets/QuantizeParameters.cpp b/src/gui/widgets/QuantizeParameters.cpp new file mode 100644 index 0000000..19ba96a --- /dev/null +++ b/src/gui/widgets/QuantizeParameters.cpp @@ -0,0 +1,497 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "QuantizeParameters.h" +#include <qlayout.h> +#include <kapplication.h> + +#include <klocale.h> +#include "base/NotationTypes.h" +#include "base/Quantizer.h" +#include "base/BasicQuantizer.h" +#include "base/LegatoQuantizer.h" +#include "base/NotationQuantizer.h" +#include "gui/editors/notation/NotationStrings.h" +#include "gui/editors/notation/NotePixmapFactory.h" +#include <kcombobox.h> +#include <kconfig.h> +#include <qcheckbox.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qobject.h> +#include <qpixmap.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +QuantizeParameters::QuantizeParameters(QWidget *parent, + QuantizerType defaultQuantizer, + bool showNotationOption, + bool showAdvancedButton, + QString configCategory, + QString preamble) : + QFrame(parent), + m_configCategory(configCategory), + m_standardQuantizations + (BasicQuantizer::getStandardQuantizations()) +{ + m_mainLayout = new QGridLayout(this, + preamble ? 3 : 4, 2, + preamble ? 10 : 0, + preamble ? 5 : 4); + + int zero = 0; + if (preamble) { + QLabel *label = new QLabel(preamble, this); + label->setAlignment(Qt::WordBreak); + m_mainLayout->addMultiCellWidget(label, 0, 0, 0, 1); + zero = 1; + } + + QGroupBox *quantizerBox = new QGroupBox + (1, Horizontal, i18n("Quantizer"), this); + + m_mainLayout->addWidget(quantizerBox, zero, 0); + QFrame *typeFrame = new QFrame(quantizerBox); + + QGridLayout *layout = new QGridLayout(typeFrame, 2, 2, 5, 3); + layout->addWidget(new QLabel(i18n("Quantizer type:"), typeFrame), 0, 0); + m_typeCombo = new KComboBox(typeFrame); + m_typeCombo->insertItem(i18n("Grid quantizer")); + m_typeCombo->insertItem(i18n("Legato quantizer")); + m_typeCombo->insertItem(i18n("Heuristic notation quantizer")); + layout->addWidget(m_typeCombo, 0, 1); + + m_notationTarget = new QCheckBox + (i18n("Quantize for notation only (leave performance unchanged)"), + typeFrame); + layout->addMultiCellWidget(m_notationTarget, 1, 1, 0, 1); + if (!showNotationOption) + m_notationTarget->hide(); + + QHBox *parameterBox = new QHBox(this); + m_mainLayout->addWidget(parameterBox, zero + 1, 0); + + m_notationBox = new QGroupBox + (1, Horizontal, i18n("Notation parameters"), parameterBox); + QFrame *notationFrame = new QFrame(m_notationBox); + + layout = new QGridLayout(notationFrame, 4, 2, 5, 3); + + layout->addWidget(new QLabel(i18n("Base grid unit:"), notationFrame), + 1, 0); + m_notationUnitCombo = new KComboBox(notationFrame); + layout->addWidget(m_notationUnitCombo, 1, 1); + + layout->addWidget(new QLabel(i18n("Complexity:"), + notationFrame), 0, 0); + + m_simplicityCombo = new KComboBox(notationFrame); + m_simplicityCombo->insertItem(i18n("Very high")); + m_simplicityCombo->insertItem(i18n("High")); + m_simplicityCombo->insertItem(i18n("Normal")); + m_simplicityCombo->insertItem(i18n("Low")); + m_simplicityCombo->insertItem(i18n("Very low")); + layout->addWidget(m_simplicityCombo, 0, 1); + + layout->addWidget(new QLabel(i18n("Tuplet level:"), + notationFrame), 2, 0); + m_maxTuplet = new KComboBox(notationFrame); + m_maxTuplet->insertItem(i18n("None")); + m_maxTuplet->insertItem(i18n("2-in-the-time-of-3")); + m_maxTuplet->insertItem(i18n("Triplet")); + /* + m_maxTuplet->insertItem(i18n("4-Tuplet")); + m_maxTuplet->insertItem(i18n("5-Tuplet")); + m_maxTuplet->insertItem(i18n("6-Tuplet")); + m_maxTuplet->insertItem(i18n("7-Tuplet")); + m_maxTuplet->insertItem(i18n("8-Tuplet")); + */ + m_maxTuplet->insertItem(i18n("Any")); + layout->addWidget(m_maxTuplet, 2, 1); + + m_counterpoint = new QCheckBox(i18n("Permit counterpoint"), notationFrame); + layout->addMultiCellWidget(m_counterpoint, 3, 3, 0, 1); + + m_gridBox = new QGroupBox + (1, Horizontal, i18n("Grid parameters"), parameterBox); + QFrame *gridFrame = new QFrame(m_gridBox); + + layout = new QGridLayout(gridFrame, 4, 2, 5, 3); + + layout->addWidget(new QLabel(i18n("Base grid unit:"), gridFrame), 0, 0); + m_gridUnitCombo = new KComboBox(gridFrame); + layout->addWidget(m_gridUnitCombo, 0, 1); + + m_swingLabel = new QLabel(i18n("Swing:"), gridFrame); + layout->addWidget(m_swingLabel, 1, 0); + m_swingCombo = new KComboBox(gridFrame); + layout->addWidget(m_swingCombo, 1, 1); + + m_iterativeLabel = new QLabel(i18n("Iterative amount:"), gridFrame); + layout->addWidget(m_iterativeLabel, 2, 0); + m_iterativeCombo = new KComboBox(gridFrame); + layout->addWidget(m_iterativeCombo, 2, 1); + + m_durationCheckBox = new QCheckBox + (i18n("Quantize durations as well as start times"), gridFrame); + layout->addMultiCellWidget(m_durationCheckBox, 3, 3, 0, 1); + + m_postProcessingBox = new QGroupBox + (1, Horizontal, i18n("After quantization"), this); + + if (preamble) { + m_mainLayout->addMultiCellWidget(m_postProcessingBox, + zero, zero + 1, + 1, 1); + } else { + m_mainLayout->addWidget(m_postProcessingBox, zero + 3, 0); + } + + bool advanced = true; + m_advancedButton = 0; + if (showAdvancedButton) { + m_advancedButton = + new QPushButton(i18n("Show advanced options"), this); + m_mainLayout->addWidget(m_advancedButton, zero + 2, 0, Qt::AlignLeft); + QObject::connect(m_advancedButton, SIGNAL(clicked()), + this, SLOT(slotAdvancedChanged())); + } + + QFrame *postFrame = new QFrame(m_postProcessingBox); + + layout = new QGridLayout(postFrame, 4, 1, 5, 3); + m_rebeam = new QCheckBox(i18n("Re-beam"), postFrame); + m_articulate = new QCheckBox + (i18n("Add articulations (staccato, tenuto, slurs)"), postFrame); + m_makeViable = new QCheckBox(i18n("Tie notes at barlines etc"), postFrame); + m_deCounterpoint = new QCheckBox(i18n("Split-and-tie overlapping chords"), postFrame); + + layout->addWidget(m_rebeam, 0, 0); + layout->addWidget(m_articulate, 1, 0); + layout->addWidget(m_makeViable, 2, 0); + layout->addWidget(m_deCounterpoint, 3, 0); + + QPixmap noMap = NotePixmapFactory::toQPixmap + (NotePixmapFactory::makeToolbarPixmap("menu-no-note")); + + int defaultType = 0; + timeT defaultUnit = + Note(Note::Demisemiquaver).getDuration(); + + if (!m_configCategory) { + if (defaultQuantizer == Notation) + m_configCategory = "Quantize Dialog Notation"; + else + m_configCategory = "Quantize Dialog Grid"; + } + + int defaultSwing = 0; + int defaultIterate = 100; + + if (m_configCategory) { + KConfig *config = kapp->config(); + config->setGroup(m_configCategory); + defaultType = + config->readNumEntry("quantizetype", + (defaultQuantizer == Notation) ? 2 : + (defaultQuantizer == Legato) ? 1 : + 0); + defaultUnit = + config->readNumEntry("quantizeunit", defaultUnit); + defaultSwing = + config->readNumEntry("quantizeswing", defaultSwing); + defaultIterate = + config->readNumEntry("quantizeiterate", defaultIterate); + m_notationTarget->setChecked + (config->readBoolEntry("quantizenotationonly", + defaultQuantizer == Notation)); + m_durationCheckBox->setChecked + (config->readBoolEntry("quantizedurations", false)); + m_simplicityCombo->setCurrentItem + (config->readNumEntry("quantizesimplicity", 13) - 11); + m_maxTuplet->setCurrentItem + (config->readNumEntry("quantizemaxtuplet", 3) - 1); + m_counterpoint->setChecked + (config->readBoolEntry("quantizecounterpoint", false)); + m_rebeam->setChecked + (config->readBoolEntry("quantizerebeam", true)); + m_makeViable->setChecked + (config->readBoolEntry("quantizemakeviable", false)); + m_deCounterpoint->setChecked + (config->readBoolEntry("quantizedecounterpoint", false)); + m_articulate->setChecked + (config->readBoolEntry("quantizearticulate", true)); + advanced = config->readBoolEntry("quantizeshowadvanced", false); + } else { + defaultType = + (defaultQuantizer == Notation) ? 2 : + (defaultQuantizer == Legato) ? 1 : 0; + m_notationTarget->setChecked(defaultQuantizer == Notation); + m_durationCheckBox->setChecked(false); + m_simplicityCombo->setCurrentItem(2); + m_maxTuplet->setCurrentItem(2); + m_counterpoint->setChecked(false); + m_rebeam->setChecked(true); + m_makeViable->setChecked(defaultQuantizer == Notation); + m_deCounterpoint->setChecked(defaultQuantizer == Notation); + m_articulate->setChecked(true); + advanced = false; + } + + if (preamble || advanced) { + m_postProcessingBox->show(); + } else { + m_postProcessingBox->hide(); + } + + for (unsigned int i = 0; i < m_standardQuantizations.size(); ++i) { + + timeT time = m_standardQuantizations[i]; + timeT error = 0; + + QPixmap pmap = NotePixmapFactory::toQPixmap + (NotePixmapFactory::makeNoteMenuPixmap(time, error)); + QString label = NotationStrings::makeNoteMenuLabel(time, false, error); + + if (error == 0) { + m_gridUnitCombo->insertItem(pmap, label); + m_notationUnitCombo->insertItem(pmap, label); + } else { + m_gridUnitCombo->insertItem(noMap, QString("%1").arg(time)); + m_notationUnitCombo->insertItem(noMap, QString("%1").arg(time)); + } + + if (m_standardQuantizations[i] == defaultUnit) { + m_gridUnitCombo->setCurrentItem(m_gridUnitCombo->count() - 1); + m_notationUnitCombo->setCurrentItem + (m_notationUnitCombo->count() - 1); + } + } + + for (int i = -100; i <= 200; i += 10) { + m_swingCombo->insertItem(i == 0 ? i18n("None") : QString("%1%").arg(i)); + if (i == defaultSwing) + m_swingCombo->setCurrentItem(m_swingCombo->count() - 1); + } + + for (int i = 10; i <= 100; i += 10) { + m_iterativeCombo->insertItem(i == 100 ? i18n("Full quantize") : + QString("%1%").arg(i)); + if (i == defaultIterate) + m_iterativeCombo->setCurrentItem(m_iterativeCombo->count() - 1); + } + + switch (defaultType) { + case 0: // grid + m_gridBox->show(); + m_swingLabel->show(); + m_swingCombo->show(); + m_iterativeLabel->show(); + m_iterativeCombo->show(); + m_notationBox->hide(); + m_durationCheckBox->show(); + m_typeCombo->setCurrentItem(0); + break; + case 1: // legato + m_gridBox->show(); + m_swingLabel->hide(); + m_swingCombo->hide(); + m_iterativeLabel->hide(); + m_iterativeCombo->hide(); + m_notationBox->hide(); + m_durationCheckBox->hide(); + m_typeCombo->setCurrentItem(1); + case 2: // notation + m_gridBox->hide(); + m_notationBox->show(); + m_typeCombo->setCurrentItem(2); + break; + } + + connect(m_typeCombo, SIGNAL(activated(int)), SLOT(slotTypeChanged(int))); +} + +Quantizer * +QuantizeParameters::getQuantizer() const +{ + //!!! Excessive duplication with + // EventQuantizeCommand::makeQuantizer in editcommands.cpp + + int type = m_typeCombo->currentItem(); + timeT unit = 0; + + if (type == 0 || type == 1) { + unit = m_standardQuantizations[m_gridUnitCombo->currentItem()]; + } else { + unit = m_standardQuantizations[m_notationUnitCombo->currentItem()]; + } + + Quantizer *quantizer = 0; + + int swing = m_swingCombo->currentItem(); + swing *= 10; + swing -= 100; + + int iterate = m_iterativeCombo->currentItem(); + iterate *= 10; + iterate += 10; + + if (type == 0) { + + if (m_notationTarget->isChecked()) { + quantizer = new BasicQuantizer + (Quantizer::RawEventData, + Quantizer::NotationPrefix, + unit, m_durationCheckBox->isChecked(), + swing, iterate); + } else { + quantizer = new BasicQuantizer + (Quantizer::RawEventData, + Quantizer::RawEventData, + unit, m_durationCheckBox->isChecked(), + swing, iterate); + } + } else if (type == 1) { + if (m_notationTarget->isChecked()) { + quantizer = new LegatoQuantizer + (Quantizer::RawEventData, + Quantizer::NotationPrefix, unit); + } else { + quantizer = new LegatoQuantizer + (Quantizer::RawEventData, + Quantizer::RawEventData, + unit); + } + } else { + + NotationQuantizer *nq; + + if (m_notationTarget->isChecked()) { + nq = new NotationQuantizer(); + } else { + nq = new NotationQuantizer + (Quantizer::RawEventData, + Quantizer::RawEventData); + } + + nq->setUnit(unit); + nq->setSimplicityFactor(m_simplicityCombo->currentItem() + 11); + nq->setMaxTuplet(m_maxTuplet->currentItem() + 1); + nq->setContrapuntal(m_counterpoint->isChecked()); + nq->setArticulate(m_articulate->isChecked()); + + quantizer = nq; + } + + if (m_configCategory) { + KConfig *config = kapp->config(); + config->setGroup(m_configCategory); + config->writeEntry("quantizetype", type); + config->writeEntry("quantizeunit", unit); + config->writeEntry("quantizeswing", swing); + config->writeEntry("quantizeiterate", iterate); + config->writeEntry("quantizenotationonly", + m_notationTarget->isChecked()); + if (type == 0) { + config->writeEntry("quantizedurations", + m_durationCheckBox->isChecked()); + } else { + config->writeEntry("quantizesimplicity", + m_simplicityCombo->currentItem() + 11); + config->writeEntry("quantizemaxtuplet", + m_maxTuplet->currentItem() + 1); + config->writeEntry("quantizecounterpoint", + m_counterpoint->isChecked()); + config->writeEntry("quantizearticulate", + m_articulate->isChecked()); + } + config->writeEntry("quantizerebeam", m_rebeam->isChecked()); + config->writeEntry("quantizemakeviable", m_makeViable->isChecked()); + config->writeEntry("quantizedecounterpoint", m_deCounterpoint->isChecked()); + } + + return quantizer; +} + +void +QuantizeParameters::slotAdvancedChanged() +{ + if (m_postProcessingBox->isVisible()) { + if (m_advancedButton) + m_advancedButton->setText(i18n("Show Advanced Options")); + m_postProcessingBox->hide(); + } else { + if (m_advancedButton) + m_advancedButton->setText(i18n("Hide Advanced Options")); + m_postProcessingBox->show(); + } + adjustSize(); +} + +void +QuantizeParameters::showAdvanced(bool show) +{ + if (show) { + m_postProcessingBox->show(); + } else { + m_postProcessingBox->hide(); + } + adjustSize(); +} + +void +QuantizeParameters::slotTypeChanged(int index) +{ + if (index == 0) { + m_gridBox->show(); + m_swingLabel->show(); + m_swingCombo->show(); + m_iterativeLabel->show(); + m_iterativeCombo->show(); + m_durationCheckBox->show(); + m_notationBox->hide(); + } else if (index == 1) { + m_gridBox->show(); + m_swingLabel->hide(); + m_swingCombo->hide(); + m_iterativeLabel->hide(); + m_iterativeCombo->hide(); + m_durationCheckBox->hide(); + m_notationBox->hide(); + } else { + m_gridBox->hide(); + m_notationBox->show(); + } +} + +} +#include "QuantizeParameters.moc" diff --git a/src/gui/widgets/QuantizeParameters.h b/src/gui/widgets/QuantizeParameters.h new file mode 100644 index 0000000..8eee7ff --- /dev/null +++ b/src/gui/widgets/QuantizeParameters.h @@ -0,0 +1,117 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENQUANTIZEPARAMETERS_H_ +#define _RG_ROSEGARDENQUANTIZEPARAMETERS_H_ + +#include <qframe.h> +#include <qstring.h> +#include <vector> +#include "base/Event.h" +#include <qgroupbox.h> + + +class QWidget; +class QPushButton; +class QLabel; +class QGridLayout; +class QCheckBox; +class KComboBox; + + +namespace Rosegarden +{ + +class Quantizer; + + +class QuantizeParameters : public QFrame +{ + Q_OBJECT +public: + enum QuantizerType { Grid, Legato, Notation }; + + QuantizeParameters(QWidget *parent, + QuantizerType defaultQuantizer, + bool showNotationOption, + bool showAdvancedButton, + QString configCategory, + QString preamble = 0); + + /** + * Returned quantizer object is on heap -- caller must delete. + * Also writes values to KConfig if so requested in constructor. + */ + Quantizer *getQuantizer() const; + + QWidget *getAdvancedWidget() { return m_postProcessingBox; } + + bool shouldRebeam() const { return m_rebeam; } + bool shouldDeCounterpoint() const { return m_deCounterpoint; } + bool shouldMakeViable() const { return m_makeViable; } + + void showAdvanced(bool show); + +public slots: + void slotTypeChanged(int); + void slotAdvancedChanged(); + +protected: + QString m_configCategory; + + std::vector<timeT> m_standardQuantizations; + + QGridLayout *m_mainLayout; + + KComboBox *m_typeCombo; + + QGroupBox *m_gridBox; + QCheckBox *m_durationCheckBox; + KComboBox *m_gridUnitCombo; + QLabel *m_swingLabel; + KComboBox *m_swingCombo; + QLabel *m_iterativeLabel; + KComboBox *m_iterativeCombo; + + QGroupBox *m_notationBox; + QCheckBox *m_notationTarget; + KComboBox *m_notationUnitCombo; + KComboBox *m_simplicityCombo; + KComboBox *m_maxTuplet; + QCheckBox *m_counterpoint; + + QPushButton *m_advancedButton; + QGroupBox *m_postProcessingBox; + QCheckBox *m_articulate; + QCheckBox *m_makeViable; + QCheckBox *m_deCounterpoint; + QCheckBox *m_rebeam; +}; + + + +} + +#endif diff --git a/src/gui/widgets/RosegardenPopupMenu.h b/src/gui/widgets/RosegardenPopupMenu.h new file mode 100644 index 0000000..aca82a9 --- /dev/null +++ b/src/gui/widgets/RosegardenPopupMenu.h @@ -0,0 +1,43 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENPOPUPMENU_H_ +#define _RG_ROSEGARDENPOPUPMENU_H_ + +#include <qpopupmenu.h> + +namespace Rosegarden { + +class RosegardenPopupMenu : public QPopupMenu +{ + // just to make itemHeight public +public: + RosegardenPopupMenu(QWidget *parent) : QPopupMenu(parent) { } + using QPopupMenu::itemHeight; +}; + + +} + +#endif /*ROSEGARDENPOPUPMENU_H_*/ diff --git a/src/gui/widgets/Rotary.cpp b/src/gui/widgets/Rotary.cpp new file mode 100644 index 0000000..36d5817 --- /dev/null +++ b/src/gui/widgets/Rotary.cpp @@ -0,0 +1,560 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "Rotary.h" + +#include "misc/Debug.h" +#include "gui/dialogs/FloatEdit.h" +#include "gui/general/GUIPalette.h" +#include "TextFloat.h" +#include <kapplication.h> +#include <klocale.h> +#include <qbrush.h> +#include <qcolor.h> +#include <qdialog.h> +#include <qimage.h> +#include <qpainter.h> +#include <qpalette.h> +#include <qpen.h> +#include <qpixmap.h> +#include <qpoint.h> +#include <qstring.h> +#include <qtimer.h> +#include <qtooltip.h> +#include <qwidget.h> +#include <cmath> + + +namespace Rosegarden +{ + +#define ROTARY_MIN (0.25 * M_PI) +#define ROTARY_MAX (1.75 * M_PI) +#define ROTARY_RANGE (ROTARY_MAX - ROTARY_MIN) + +static TextFloat* _float = 0; +static QTimer *_floatTimer = 0; + +Rotary::PixmapCache Rotary::m_pixmaps; + + +Rotary::Rotary(QWidget *parent, + float minValue, + float maxValue, + float step, + float pageStep, + float initialPosition, + int size, + TickMode ticks, + bool snapToTicks, + bool centred, + bool logarithmic) : + QWidget(parent), + m_minValue(minValue), + m_maxValue(maxValue), + m_step(step), + m_pageStep(pageStep), + m_size(size), + m_tickMode(ticks), + m_snapToTicks(snapToTicks), + m_centred(centred), + m_position(initialPosition), + m_snapPosition(m_position), + m_initialPosition(initialPosition), + m_buttonPressed(false), + m_lastY(0), + m_lastX(0), + m_knobColour(0, 0, 0), + m_logarithmic(logarithmic) +{ + setBackgroundMode(Qt::NoBackground); + + if (!_float) + _float = new TextFloat(this); + + if (!_floatTimer) { + _floatTimer = new QTimer(); + } + + // connect timer + connect(_floatTimer, SIGNAL(timeout()), this, + SLOT(slotFloatTimeout())); + _float->hide(); + + QToolTip::add + (this, + i18n("Click and drag up and down or left and right to modify.\nDouble click to edit value directly.")); + setFixedSize(size, size); + + emit valueChanged(m_snapPosition); +} + +Rotary::~Rotary() +{ + // Remove this connection + // + disconnect(_floatTimer, SIGNAL(timeout()), this, + SLOT(slotFloatTimeout())); + + delete _float; + _float = 0; +} + +void +Rotary::slotFloatTimeout() +{ + if (_float) + _float->hide(); +} + +void +Rotary::setKnobColour(const QColor &colour) +{ + m_knobColour = colour; + repaint(); +} + +void +Rotary::paintEvent(QPaintEvent *) +{ + QPainter paint; + + double angle = ROTARY_MIN // offset + + (ROTARY_RANGE * + (double(m_snapPosition - m_minValue) / + (double(m_maxValue) - double(m_minValue)))); + int degrees = int(angle * 180.0 / M_PI); + + // RG_DEBUG << "degrees: " << degrees << ", size " << m_size << ", pixel " << m_knobColour.pixel() << endl; + + int numTicks = 0; + switch (m_tickMode) { + case LimitTicks: + numTicks = 2; + break; + case IntervalTicks: + numTicks = 5; + break; + case PageStepTicks: + numTicks = 1 + (m_maxValue + 0.0001 - m_minValue) / m_pageStep; + break; + case StepTicks: + numTicks = 1 + (m_maxValue + 0.0001 - m_minValue) / m_step; + break; + default: + break; + } + + CacheIndex index(m_size, m_knobColour.pixel(), degrees, numTicks, m_centred); + + if (m_pixmaps.find(index) != m_pixmaps.end()) { + paint.begin(this); + paint.drawPixmap(0, 0, m_pixmaps[index]); + paint.end(); + return ; + } + + int scale = 4; + int width = m_size * scale; + QPixmap map(width, width); + map.fill(paletteBackgroundColor()); + paint.begin(&map); + + QPen pen; + pen.setColor(kapp->palette().color(QPalette::Active, QColorGroup::Dark)); + pen.setWidth(scale); + paint.setPen(pen); + + if (m_knobColour != Qt::black) { + paint.setBrush(m_knobColour); + } else { + paint.setBrush( + kapp->palette().color(QPalette::Active, QColorGroup::Base)); + } + + QColor c(m_knobColour); + pen.setColor(c); + paint.setPen(pen); + + int indent = width * 0.15 + 1; + + paint.drawEllipse(indent, indent, width - 2*indent, width - 2*indent); + + pen.setWidth(2 * scale); + int pos = indent + (width - 2 * indent) / 8; + int darkWidth = (width - 2 * indent) * 2 / 3; + int darkQuote = (130 * 2 / (darkWidth ? darkWidth : 1)) + 100; + while (darkWidth) { + c = c.light(101); + pen.setColor(c); + paint.setPen(pen); + paint.drawEllipse(pos, pos, darkWidth, darkWidth); + if (!--darkWidth) + break; + paint.drawEllipse(pos, pos, darkWidth, darkWidth); + if (!--darkWidth) + break; + paint.drawEllipse(pos, pos, darkWidth, darkWidth); + ++pos; + --darkWidth; + } + + paint.setBrush(QBrush::NoBrush); + + pen.setColor(colorGroup().dark()); + pen.setWidth(scale); + paint.setPen(pen); + + for (int i = 0; i < numTicks; ++i) { + int div = numTicks; + if (div > 1) + --div; + drawTick(paint, ROTARY_MIN + (ROTARY_MAX - ROTARY_MIN) * i / div, + width, i != 0 && i != numTicks - 1); + } + + // now the bright metering bit + + pen.setColor(GUIPalette::getColour(GUIPalette::RotaryMeter)); + pen.setWidth(indent); + paint.setPen(pen); + + if (m_centred) { + paint.drawArc(indent / 2, indent / 2, width - indent, width - indent, + 90 * 16, -(degrees - 180) * 16); + } else { + paint.drawArc(indent / 2, indent / 2, width - indent, width - indent, + (180 + 45) * 16, -(degrees - 45) * 16); + } + + pen.setWidth(scale); + paint.setPen(pen); + + int shadowAngle = -720; + c = colorGroup().dark(); + for (int arc = 120; arc < 2880; arc += 240) { + pen.setColor(c); + paint.setPen(pen); + paint.drawArc(indent, indent, width - 2*indent, width - 2*indent, shadowAngle + arc, 240); + paint.drawArc(indent, indent, width - 2*indent, width - 2*indent, shadowAngle - arc, 240); + c = c.light( 110 ); + } + + shadowAngle = 2160; + c = colorGroup().dark(); + for (int arc = 120; arc < 2880; arc += 240) { + pen.setColor(c); + paint.setPen(pen); + paint.drawArc(scale / 2, scale / 2, width - scale, width - scale, shadowAngle + arc, 240); + paint.drawArc(scale / 2, scale / 2, width - scale, width - scale, shadowAngle - arc, 240); + c = c.light( 109 ); + } + + // and un-draw the bottom part + pen.setColor(paletteBackgroundColor()); + paint.setPen(pen); + paint.drawArc(scale / 2, scale / 2, width - scale, width - scale, + -45 * 16, -90 * 16); + + double hyp = double(width) / 2.0; + double len = hyp - indent; + --len; + + double x0 = hyp; + double y0 = hyp; + + double x = hyp - len * sin(angle); + double y = hyp + len * cos(angle); + + pen.setWidth(scale * 2); + pen.setColor(colorGroup().dark()); + paint.setPen(pen); + + paint.drawLine(int(x0), int(y0), int(x), int(y)); + + paint.end(); + + QImage i = map.convertToImage().smoothScale(m_size, m_size); + m_pixmaps[index] = QPixmap(i); + paint.begin(this); + paint.drawPixmap(0, 0, m_pixmaps[index]); + paint.end(); +} + +void +Rotary::drawTick(QPainter &paint, double angle, int size, bool internal) +{ + double hyp = double(size) / 2.0; + double x0 = hyp - (hyp - 1) * sin(angle); + double y0 = hyp + (hyp - 1) * cos(angle); + + if (internal) { + + double len = hyp / 4; + double x1 = hyp - (hyp - len) * sin(angle); + double y1 = hyp + (hyp - len) * cos(angle); + + paint.drawLine(int(x0), int(y0), int(x1), int(y1)); + + } else { + + double len = hyp / 4; + double x1 = hyp - (hyp + len) * sin(angle); + double y1 = hyp + (hyp + len) * cos(angle); + + paint.drawLine(int(x0), int(y0), int(x1), int(y1)); + } +} + +void +Rotary::snapPosition() +{ + m_snapPosition = m_position; + + if (m_snapToTicks) { + + switch (m_tickMode) { + + case NoTicks: + break; // meaningless + + case LimitTicks: + if (m_position < (m_minValue + m_maxValue) / 2.0) { + m_snapPosition = m_minValue; + } else { + m_snapPosition = m_maxValue; + } + break; + + case IntervalTicks: + m_snapPosition = m_minValue + + (m_maxValue - m_minValue) / 4.0 * + int((m_snapPosition - m_minValue) / + ((m_maxValue - m_minValue) / 4.0)); + break; + + case PageStepTicks: + m_snapPosition = m_minValue + + m_pageStep * + int((m_snapPosition - m_minValue) / m_pageStep); + break; + + case StepTicks: + m_snapPosition = m_minValue + + m_step * + int((m_snapPosition - m_minValue) / m_step); + break; + } + } +} + +void +Rotary::mousePressEvent(QMouseEvent *e) +{ + if (e->button() == LeftButton) { + m_buttonPressed = true; + m_lastY = e->y(); + m_lastX = e->x(); + } else if (e->button() == MidButton) // reset to default + { + m_position = m_initialPosition; + snapPosition(); + update(); + emit valueChanged(m_snapPosition); + } else if (e->button() == RightButton) // reset to centre position + { + m_position = (m_maxValue + m_minValue) / 2.0; + snapPosition(); + update(); + emit valueChanged(m_snapPosition); + } + + QPoint totalPos = mapTo(topLevelWidget(), QPoint(0, 0)); + + if (!_float) + _float = new TextFloat(this); + _float->reparent(this); + _float->move(totalPos + QPoint(width() + 2, -height() / 2)); + if (m_logarithmic) { + _float->setText(QString("%1").arg(powf(10, m_position))); + } else { + _float->setText(QString("%1").arg(m_position)); + } + _float->show(); + +// std::cerr << "Rotary::mousePressEvent: logarithmic = " << m_logarithmic +// << ", position = " << m_position << std::endl; + + if (e->button() == RightButton || e->button() == MidButton) { + // one shot, 500ms + _floatTimer->start(500, true); + } +} + +void +Rotary::mouseDoubleClickEvent(QMouseEvent * /*e*/) +{ + float minv = m_minValue; + float maxv = m_maxValue; + float val = m_position; + float step = m_step; + + if (m_logarithmic) { + minv = powf(10, minv); + maxv = powf(10, maxv); + val = powf(10, val); + step = powf(10, step); + if (step > 0.001) step = 0.001; + } + + FloatEdit dialog(this, + i18n("Select a new value"), + i18n("Enter a new value"), + minv, + maxv, + val, + step); + + if (dialog.exec() == QDialog::Accepted) { + float newval = dialog.getValue(); + if (m_logarithmic) { + if (m_position < powf(10, -10)) m_position = -10; + else m_position = log10f(newval); + } else { + m_position = newval; + } + snapPosition(); + update(); + + emit valueChanged(m_snapPosition); + } +} + +void +Rotary::mouseReleaseEvent(QMouseEvent *e) +{ + if (e->button() == LeftButton) { + m_buttonPressed = false; + m_lastY = 0; + m_lastX = 0; + + // Hide the float text + // + if (_float) + _float->hide(); + } +} + +void +Rotary::mouseMoveEvent(QMouseEvent *e) +{ + if (m_buttonPressed) { + // Dragging by x or y axis when clicked modifies value + // + float newValue = m_position + + (m_lastY - float(e->y()) + float(e->x()) - m_lastX) * m_step; + + if (newValue > m_maxValue) + m_position = m_maxValue; + else + if (newValue < m_minValue) + m_position = m_minValue; + else + m_position = newValue; + + m_lastY = e->y(); + m_lastX = e->x(); + + snapPosition(); + + // don't update if there's nothing to update + // if (m_lastPosition == m_snapPosition) return; + + update(); + + emit valueChanged(m_snapPosition); + + // draw on the float text + if (m_logarithmic) { + _float->setText(QString("%1").arg(powf(10, m_snapPosition))); + } else { + _float->setText(QString("%1").arg(m_snapPosition)); + } + } +} + +void +Rotary::wheelEvent(QWheelEvent *e) +{ + if (e->delta() > 0) + m_position -= m_pageStep; + else + m_position += m_pageStep; + + if (m_position > m_maxValue) + m_position = m_maxValue; + + if (m_position < m_minValue) + m_position = m_minValue; + + snapPosition(); + update(); + + if (!_float) + _float = new TextFloat(this); + + // draw on the float text + if (m_logarithmic) { + _float->setText(QString("%1").arg(powf(10, m_snapPosition))); + } else { + _float->setText(QString("%1").arg(m_snapPosition)); + } + + // Reposition - we need to sum the relative positions up to the + // topLevel or dialog to please move(). Move just top/right of the rotary + // + QPoint totalPos = mapTo(topLevelWidget(), QPoint(0, 0)); + _float->reparent(this); + _float->move(totalPos + QPoint(width() + 2, -height() / 2)); + _float->show(); + + // one shot, 500ms + _floatTimer->start(500, true); + + // set it to show for a timeout value + emit valueChanged(m_snapPosition); +} + +void +Rotary::setPosition(float position) +{ + m_position = position; + + snapPosition(); + update(); +} + +} +#include "Rotary.moc" diff --git a/src/gui/widgets/Rotary.h b/src/gui/widgets/Rotary.h new file mode 100644 index 0000000..2efacf9 --- /dev/null +++ b/src/gui/widgets/Rotary.h @@ -0,0 +1,167 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENROTARY_H_ +#define _RG_ROSEGARDENROTARY_H_ + +#include <map> +#include <qcolor.h> +#include <qwidget.h> + + +class QWheelEvent; +class QPaintEvent; +class QPainter; +class QMouseEvent; + + +namespace Rosegarden +{ + + + +class Rotary : public QWidget +{ + Q_OBJECT +public: + + enum TickMode { + NoTicks, // plain circle with no marks for end points etc + LimitTicks, // marks at end points but not any intermediate points + IntervalTicks, // end points plus quarter, half, three-quarters + PageStepTicks, // end points plus every page-step interval + StepTicks // end points plus every step interval + }; + + Rotary(QWidget *parent, + float minValue = 0.0, + float maxValue = 100.0, + float step = 1.0, + float pageStep = 10.0, + float initialPosition = 50.0, + int size = 20, + TickMode ticks = NoTicks, + bool snapToTicks = false, + bool centred = false, + bool logarithmic = false); // extents are logs, exp for display + ~Rotary(); + + void setMinValue(float min) { m_minValue = min; } + float getMinValue() const { return m_minValue; } + + void setMaxValue(float max) { m_maxValue = max; } + float getMaxValue() const { return m_maxValue; } + + void setStep(float step) { m_step = step; } + float getStep() const { return m_step; } + + void setPageStep(float step) { m_pageStep = step; } + float getPageStep() const { return m_pageStep; } + + int getSize() const { return m_size; } + + // Position + // + float getPosition() const { return m_position; } + void setPosition(float position); + + // Set the colour of the knob + // + void setKnobColour(const QColor &colour); + QColor getKnobColour() const { return m_knobColour; } + +signals: + void valueChanged(float); + +protected slots: + void slotFloatTimeout(); + +protected: + virtual void paintEvent(QPaintEvent *e); + virtual void mousePressEvent(QMouseEvent *e); + virtual void mouseReleaseEvent(QMouseEvent *e); + virtual void mouseMoveEvent(QMouseEvent *e); + virtual void mouseDoubleClickEvent(QMouseEvent *e); + virtual void wheelEvent(QWheelEvent *e); + + void snapPosition(); + void drawPosition(); + void drawTick(QPainter &paint, double angle, int size, bool internal); + + float m_minValue; + float m_maxValue; + float m_step; + float m_pageStep; + int m_size; + TickMode m_tickMode; + bool m_snapToTicks; + bool m_centred; + bool m_logarithmic; + + float m_position; + float m_snapPosition; + float m_initialPosition; + bool m_buttonPressed; + int m_lastY; + int m_lastX; + + QColor m_knobColour; + + struct CacheIndex { + + CacheIndex(int _s, int _c, int _a, int _n, int _ct) : + size(_s), colour(_c), angle(_a), numTicks(_n), centred(_ct) { } + + bool operator<(const CacheIndex &i) const { + // woo! + if (size < i.size) return true; + else if (size > i.size) return false; + else if (colour < i.colour) return true; + else if (colour > i.colour) return false; + else if (angle < i.angle) return true; + else if (angle > i.angle) return false; + else if (numTicks < i.numTicks) return true; + else if (numTicks > i.numTicks) return false; + else if (centred == i.centred) return false; + else if (!centred) return true; + return false; + } + + int size; + unsigned int colour; + int angle; + int numTicks; + bool centred; + }; + + typedef std::map<CacheIndex, QPixmap> PixmapCache; + static PixmapCache m_pixmaps; +}; + + + +} + +#endif diff --git a/src/gui/widgets/ScrollBox.cpp b/src/gui/widgets/ScrollBox.cpp new file mode 100644 index 0000000..b409209 --- /dev/null +++ b/src/gui/widgets/ScrollBox.cpp @@ -0,0 +1,159 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + This file is based on code from KGhostView, Copyright 1997-2002 + Markkhu Hihnala <mah@ee.oulu.fi> + and the KGhostView authors. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "ScrollBox.h" + +#include <qapplication.h> +#include <qframe.h> +#include <qimage.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qpoint.h> +#include <qrect.h> +#include <qsize.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +ScrollBox::ScrollBox(QWidget* parent, SizeMode sizeMode, const char* name) : + QFrame(parent, name), + m_sizeMode(sizeMode) +{ + setFrameStyle(Panel | Sunken); +} + +void ScrollBox::mousePressEvent(QMouseEvent* e) +{ + m_mouse = e->pos(); + if (e->button() == RightButton) + emit button3Pressed(); + if (e->button() == MidButton) + emit button2Pressed(); +} + +void ScrollBox::mouseMoveEvent(QMouseEvent* e) +{ + if (e->state() != LeftButton) + return ; + + int dx = (e->pos().x() - m_mouse.x()) * m_pagesize.width() / width(); + int dy = (e->pos().y() - m_mouse.y()) * m_pagesize.height() / height(); + + emit valueChanged(QPoint(m_viewpos.x() + dx, m_viewpos.y() + dy)); + emit valueChangedRelative(dx, dy); + + m_mouse = e->pos(); +} + +void ScrollBox::drawContents(QPainter* paint) +{ + if (m_pagesize.isEmpty()) + return ; + + QRect c(contentsRect()); + + paint->setPen(Qt::red); + + int len = m_pagesize.width(); + int x = c.x() + c.width() * m_viewpos.x() / len; + int w = c.width() * m_viewsize.width() / len ; + if (w > c.width()) + w = c.width(); + + len = m_pagesize.height(); + int y = c.y() + c.height() * m_viewpos.y() / len; + int h = c.height() * m_viewsize.height() / len; + if (h > c.height()) + h = c.height(); + + paint->drawRect(x, y, w, h); +} + +void ScrollBox::setPageSize(const QSize& s) +{ + m_pagesize = s; + + setFixedWidth(100); + setFixedHeight(100); + + int maxWidth = int(QApplication::desktop()->width() * 0.75); + int maxHeight = int(QApplication::desktop()->height() * 0.75); + + if (m_sizeMode == FixWidth) { + int height = s.height() * width() / s.width(); + if (height > maxHeight) { + setFixedWidth(width() * maxHeight / height); + height = maxHeight; + } + setFixedHeight(height); + } else { + int width = s.width() * height() / s.height(); + if (width > maxWidth) { + setFixedHeight(height() * maxWidth / width); + width = maxWidth; + } + setFixedWidth(width); + } + + repaint(); +} + +void ScrollBox::setViewSize(const QSize& s) +{ + m_viewsize = s; + repaint(); +} + +void ScrollBox::setViewPos(const QPoint& pos) +{ + m_viewpos = pos; + repaint(); +} + +void ScrollBox::setViewX(int x) +{ + m_viewpos = QPoint(x, m_viewpos.y()); + repaint(); +} + +void ScrollBox::setViewY(int y) +{ + m_viewpos = QPoint(m_viewpos.x(), y); + repaint(); +} + +void ScrollBox::setThumbnail(QPixmap img) +{ + setPaletteBackgroundPixmap(img.convertToImage().smoothScale(size())); +} + +} +#include "ScrollBox.moc" diff --git a/src/gui/widgets/ScrollBox.h b/src/gui/widgets/ScrollBox.h new file mode 100644 index 0000000..3f8140e --- /dev/null +++ b/src/gui/widgets/ScrollBox.h @@ -0,0 +1,89 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + This file is based on code from KGhostView, Copyright 1997-2002 + Markkhu Hihnala <mah@ee.oulu.fi> + and the KGhostView authors. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_SCROLLBOX_H_ +#define _RG_SCROLLBOX_H_ + +#include <qframe.h> +#include <qpixmap.h> +#include <qpoint.h> +#include <qsize.h> + + +class QWidget; +class QPainter; +class QMouseEvent; + + +namespace Rosegarden +{ + +class ScrollBox: public QFrame +{ + Q_OBJECT + +public: + enum SizeMode { FixWidth, FixHeight }; + + ScrollBox(QWidget *parent = 0, + SizeMode mode = FixWidth, + const char *name = 0); + +public slots: + void setPageSize(const QSize&); + void setViewSize(const QSize&); + void setViewPos(const QPoint&); + void setViewPos(int x, int y) { setViewPos(QPoint(x, y)); } + void setViewX(int x); + void setViewY(int y); + void setThumbnail(QPixmap img); + +signals: + void valueChanged(const QPoint&); + void valueChangedRelative(int dx, int dy); + void button2Pressed(); + void button3Pressed(); + +protected: + void mousePressEvent(QMouseEvent *); + void mouseMoveEvent(QMouseEvent *); + void drawContents(QPainter *); + +private: + QPoint m_viewpos; + QPoint m_mouse; + QSize m_pagesize; + QSize m_viewsize; + SizeMode m_sizeMode; +}; + + +} + +#endif diff --git a/src/gui/widgets/ScrollBoxDialog.cpp b/src/gui/widgets/ScrollBoxDialog.cpp new file mode 100644 index 0000000..e442985 --- /dev/null +++ b/src/gui/widgets/ScrollBoxDialog.cpp @@ -0,0 +1,68 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "ScrollBoxDialog.h" + +#include "ScrollBox.h" +#include <kdialog.h> +#include <qframe.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qpoint.h> +#include <qsize.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +ScrollBoxDialog::ScrollBoxDialog(QWidget *parent, + ScrollBox::SizeMode sizeMode, + const char *name, + WFlags flags) : + KDialog(parent, name, flags), + m_scrollbox(new ScrollBox(this, sizeMode)) +{ } + + +ScrollBoxDialog::~ScrollBoxDialog() +{ } + + +void ScrollBoxDialog::closeEvent(QCloseEvent *e) +{ + e->accept(); + emit closed(); +} + +void ScrollBoxDialog::setPageSize(const QSize& s) +{ + m_scrollbox->setPageSize(s); + setFixedHeight(m_scrollbox->height()); + setFixedWidth(m_scrollbox->width()); +} + +} +#include "ScrollBoxDialog.moc" diff --git a/src/gui/widgets/ScrollBoxDialog.h b/src/gui/widgets/ScrollBoxDialog.h new file mode 100644 index 0000000..8da1771 --- /dev/null +++ b/src/gui/widgets/ScrollBoxDialog.h @@ -0,0 +1,71 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_SCROLLBOXDIALOG_H_ +#define _RG_SCROLLBOXDIALOG_H_ + +#include "ScrollBox.h" +#include <kdialog.h> + + +class QWidget; +class QSize; +class QCloseEvent; + + +namespace Rosegarden +{ + + + +class ScrollBoxDialog : public KDialog +{ + Q_OBJECT + +public: + ScrollBoxDialog(QWidget *parent = 0, + ScrollBox::SizeMode mode = ScrollBox::FixWidth, + const char *name = 0, + WFlags flags = 0); + ~ScrollBoxDialog(); + + ScrollBox *scrollbox() { return m_scrollbox; } + void setPageSize(const QSize&); + +protected: + virtual void closeEvent(QCloseEvent * e); + +signals: + void closed(); + +private: + ScrollBox *m_scrollbox; +}; + + + +} + +#endif diff --git a/src/gui/widgets/SpinBox.cpp b/src/gui/widgets/SpinBox.cpp new file mode 100644 index 0000000..10963c8 --- /dev/null +++ b/src/gui/widgets/SpinBox.cpp @@ -0,0 +1,73 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "SpinBox.h" +#include "misc/Strings.h" + +#include <qspinbox.h> +#include <qstring.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +SpinBox::SpinBox(QWidget *parent, const char *name): + QSpinBox(parent, name), m_doubleValue(0) +{} + +QString +SpinBox::mapValueToText(int value) +{ + QString doubleStr; + + // Assume we want to show the precision + // + if ((int)m_doubleValue != value) + m_doubleValue = (double) value; + + doubleStr.sprintf("%4.6f", m_doubleValue); + + // clear any special value + //setSpecialValueText(""); + + return doubleStr; +} + +int +SpinBox::mapTextToValue(bool * /*ok*/) +{ + double number = qstrtodouble(text()); + + if (number) { + m_doubleValue = number; + return ((int)number); + } + + return 120; // default +} + +} +#include "SpinBox.moc" diff --git a/src/gui/widgets/SpinBox.h b/src/gui/widgets/SpinBox.h new file mode 100644 index 0000000..a0dfffe --- /dev/null +++ b/src/gui/widgets/SpinBox.h @@ -0,0 +1,65 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENSPINBOX_H_ +#define _RG_ROSEGARDENSPINBOX_H_ + +#include <qspinbox.h> +#include <qstring.h> + + +class QWidget; + + +namespace Rosegarden +{ + + + +/** + * A Combobox that just about handles doubles - you have + * to set the precision outside of this class if you're + * using it with Qt designer. Urch. + */ +class SpinBox : public QSpinBox +{ + Q_OBJECT +public: + SpinBox(QWidget *parent = 0, const char *name=0); + + double getDoubleValue() const { return m_doubleValue; } + +protected: + virtual QString mapValueToText (int value); + virtual int mapTextToValue(bool *ok); + + double m_doubleValue; +}; + + + +} + +#endif diff --git a/src/gui/widgets/TextFloat.cpp b/src/gui/widgets/TextFloat.cpp new file mode 100644 index 0000000..5e3ddbc --- /dev/null +++ b/src/gui/widgets/TextFloat.cpp @@ -0,0 +1,112 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "TextFloat.h" +#include <kapplication.h> + +#include "gui/general/GUIPalette.h" +#include <qfontmetrics.h> +#include <qpainter.h> +#include <qpalette.h> +#include <qpoint.h> +#include <qrect.h> +#include <qstring.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +TextFloat::TextFloat(QWidget *parent): + QWidget(parent, "TextFloat", + WStyle_Customize | WStyle_NoBorder | WStyle_StaysOnTop), + m_text("") +{ + reparent(parentWidget()); + resize(20, 20); +} + +void +TextFloat::reparent(QWidget *newParent) +{ + QPoint position = newParent->pos(); + + // Get position and reparent to either top level or dialog + // + while (newParent->parentWidget() && !newParent->isTopLevel() + && !newParent->isDialog()) { + newParent = newParent->parentWidget(); + position += newParent->pos(); + } + + // Position this widget to the right of the parent + // + //move(pos + QPoint(parent->width() + 5, 5)); + + QWidget::reparent(newParent, + WStyle_Customize | WStyle_NoBorder | WStyle_StaysOnTop, + position + QPoint(20, 5)); +} + +void +TextFloat::paintEvent(QPaintEvent *e) +{ + QPainter paint(this); + + paint.setClipRegion(e->region()); + paint.setClipRect(e->rect().normalize()); + + paint.setPen(kapp->palette().color(QPalette::Active, QColorGroup::Dark)); + + paint.setPen(GUIPalette::getColour(GUIPalette::RotaryFloatForeground)); + paint.setBrush(GUIPalette::getColour(GUIPalette::RotaryFloatBackground)); + + QFontMetrics metrics(paint.fontMetrics()); + + QRect r = metrics.boundingRect(0, 0, 400, 400, Qt::AlignAuto, m_text); + resize(r.width() + 7, r.height() + 7); + paint.drawRect(0, 0, r.width() + 6, r.height() + 6); + paint.setPen(Qt::black); + paint.drawText(QRect(3, 3, r.width(), r.height()), Qt::AlignAuto, m_text); + + /* + QRect textBound = metrics.boundingRect(m_text); + + resize(textBound.width() + 7, textBound.height() + 7); + paint.drawRect(0, 0, textBound.width() + 6, textBound.height() + 6); + + paint.setPen(Qt::black); + paint.drawText(3, textBound.height() + 3, m_text); + */ +} + +void +TextFloat::setText(const QString &text) +{ + m_text = text; + repaint(); +} + +} diff --git a/src/gui/widgets/TextFloat.h b/src/gui/widgets/TextFloat.h new file mode 100644 index 0000000..d604a83 --- /dev/null +++ b/src/gui/widgets/TextFloat.h @@ -0,0 +1,64 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENTEXTFLOAT_H_ +#define _RG_ROSEGARDENTEXTFLOAT_H_ + +#include <qstring.h> +#include <qwidget.h> + + +class QPaintEvent; + + +namespace Rosegarden +{ + + + +class TextFloat : public QWidget +{ +public: + TextFloat(QWidget *parent); + virtual ~TextFloat() {;} + + void setText(const QString &text); + + // Reparent the float correctly by context + // + void reparent(QWidget *newParent); + +protected: + virtual void paintEvent(QPaintEvent *e); + + QString m_text; +}; + + + + +} + +#endif diff --git a/src/gui/widgets/TimeWidget.cpp b/src/gui/widgets/TimeWidget.cpp new file mode 100644 index 0000000..b9bad6f --- /dev/null +++ b/src/gui/widgets/TimeWidget.cpp @@ -0,0 +1,668 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "TimeWidget.h" +#include <qlayout.h> + +#include <klocale.h> +#include "misc/Debug.h" +#include "base/Composition.h" +#include "base/NotationTypes.h" +#include "base/RealTime.h" +#include "gui/editors/notation/NotationStrings.h" +#include "gui/editors/notation/NotePixmapFactory.h" +#include <qcombobox.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qpixmap.h> +#include <qspinbox.h> +#include <qstring.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +TimeWidget::TimeWidget(QString title, + QWidget *parent, + Composition *composition, + timeT absTime, + bool editable, + bool constrainToCompositionDuration) : + QGroupBox(1, Horizontal, title, parent), + m_composition(composition), + m_isDuration(false), + m_constrain(constrainToCompositionDuration), + m_time(absTime), + m_startTime(0), + m_defaultTime(absTime) +{ + init(editable); +} + +TimeWidget::TimeWidget(QString title, + QWidget *parent, + Composition *composition, + timeT startTime, + timeT duration, + bool editable, + bool constrainToCompositionDuration) : + QGroupBox(1, Horizontal, title, parent), + m_composition(composition), + m_isDuration(true), + m_constrain(constrainToCompositionDuration), + m_time(duration), + m_startTime(startTime), + m_defaultTime(duration) +{ + init(editable); +} + +void +TimeWidget::init(bool editable) +{ + int denoms[] = { + 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128 + }; + + bool savedEditable = editable; + editable = true; + + QFrame *frame = new QFrame(this); + QGridLayout *layout = new QGridLayout(frame, 7, 3, 5, 5); + QLabel *label = 0; + + if (m_isDuration) { + + label = new QLabel(i18n("Note:"), frame); + label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + layout->addWidget(label, 0, 0); + + if (editable) { + m_note = new QComboBox(frame); + m_noteDurations.push_back(0); + m_note->insertItem(i18n("<inexact>")); + for (size_t i = 0; i < sizeof(denoms) / sizeof(denoms[0]); ++i) { + + timeT duration = + Note(Note::Breve).getDuration() / denoms[i]; + + if (denoms[i] > 1 && denoms[i] < 128 && (denoms[i] % 3) != 0) { + // not breve or hemidemi, not a triplet + timeT dottedDuration = duration * 3 / 2; + m_noteDurations.push_back(dottedDuration); + timeT error = 0; + QString label = NotationStrings::makeNoteMenuLabel + (dottedDuration, false, error); + QPixmap pmap = NotePixmapFactory::toQPixmap + (NotePixmapFactory::makeNoteMenuPixmap(dottedDuration, error)); + m_note->insertItem(pmap, label); // ignore error + } + + m_noteDurations.push_back(duration); + timeT error = 0; + QString label = NotationStrings::makeNoteMenuLabel + (duration, false, error); + QPixmap pmap = NotePixmapFactory::toQPixmap + (NotePixmapFactory::makeNoteMenuPixmap(duration, error)); + m_note->insertItem(pmap, label); // ignore error + } + connect(m_note, SIGNAL(activated(int)), + this, SLOT(slotNoteChanged(int))); + layout->addMultiCellWidget(m_note, 0, 0, 1, 3); + + } else { + + m_note = 0; + timeT error = 0; + QString label = NotationStrings::makeNoteMenuLabel + (m_time, false, error); + if (error != 0) + label = i18n("<inexact>"); + QLineEdit *le = new QLineEdit(label, frame); + le->setReadOnly(true); + layout->addMultiCellWidget(le, 0, 0, 1, 3); + } + + label = new QLabel(i18n("Units:"), frame); + label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + layout->addWidget(label, 0, 4); + + if (editable) { + m_timeT = new QSpinBox(frame); + m_timeT->setLineStep + (Note(Note::Shortest).getDuration()); + connect(m_timeT, SIGNAL(valueChanged(int)), + this, SLOT(slotTimeTChanged(int))); + layout->addWidget(m_timeT, 0, 5); + } else { + m_timeT = 0; + QLineEdit *le = new QLineEdit(QString("%1").arg(m_time), frame); + le->setReadOnly(true); + layout->addWidget(le, 0, 5); + } + + } else { + + m_note = 0; + + label = new QLabel(i18n("Time:"), frame); + label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + layout->addWidget(label, 0, 0); + + if (editable) { + m_timeT = new QSpinBox(frame); + m_timeT->setLineStep + (Note(Note::Shortest).getDuration()); + connect(m_timeT, SIGNAL(valueChanged(int)), + this, SLOT(slotTimeTChanged(int))); + layout->addWidget(m_timeT, 0, 1); + layout->addWidget(new QLabel(i18n("units"), frame), 0, 2); + } else { + m_timeT = 0; + QLineEdit *le = new QLineEdit(QString("%1").arg(m_time), frame); + le->setReadOnly(true); + layout->addWidget(le, 0, 2); + } + } + + label = new QLabel(m_isDuration ? i18n("Measures:") : i18n("Measure:"), frame); + label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + layout->addWidget(label, 1, 0); + + if (editable) { + m_barLabel = 0; + m_bar = new QSpinBox(frame); + if (m_isDuration) + m_bar->setMinValue(0); + connect(m_bar, SIGNAL(valueChanged(int)), + this, SLOT(slotBarBeatOrFractionChanged(int))); + layout->addWidget(m_bar, 1, 1); + } else { + m_bar = 0; + m_barLabel = new QLineEdit(frame); + m_barLabel->setReadOnly(true); + layout->addWidget(m_barLabel, 1, 1); + } + + label = new QLabel(m_isDuration ? i18n("beats:") : i18n("beat:"), frame); + label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + layout->addWidget(label, 1, 2); + + if (editable) { + m_beatLabel = 0; + m_beat = new QSpinBox(frame); + m_beat->setMinValue(1); + connect(m_beat, SIGNAL(valueChanged(int)), + this, SLOT(slotBarBeatOrFractionChanged(int))); + layout->addWidget(m_beat, 1, 3); + } else { + m_beat = 0; + m_beatLabel = new QLineEdit(frame); + m_beatLabel->setReadOnly(true); + layout->addWidget(m_beatLabel, 1, 3); + } + + label = new QLabel(i18n("%1:").arg(NotationStrings::getShortNoteName + (Note + (Note::Shortest), true)), + frame); + label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + layout->addWidget(label, 1, 4); + + if (editable) { + m_fractionLabel = 0; + m_fraction = new QSpinBox(frame); + m_fraction->setMinValue(1); + connect(m_fraction, SIGNAL(valueChanged(int)), + this, SLOT(slotBarBeatOrFractionChanged(int))); + layout->addWidget(m_fraction, 1, 5); + } else { + m_fraction = 0; + m_fractionLabel = new QLineEdit(frame); + m_fractionLabel->setReadOnly(true); + layout->addWidget(m_fractionLabel, 1, 5); + } + + m_timeSig = new QLabel(frame); + layout->addWidget(m_timeSig, 1, 6); + + label = new QLabel(i18n("Seconds:"), frame); + label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + layout->addWidget(label, 2, 0); + + if (editable) { + m_secLabel = 0; + m_sec = new QSpinBox(frame); + if (m_isDuration) + m_sec->setMinValue(0); + connect(m_sec, SIGNAL(valueChanged(int)), + this, SLOT(slotSecOrMSecChanged(int))); + layout->addWidget(m_sec, 2, 1); + } else { + m_sec = 0; + m_secLabel = new QLineEdit(frame); + m_secLabel->setReadOnly(true); + layout->addWidget(m_secLabel, 2, 1); + } + + label = new QLabel(i18n("msec:"), frame); + label->setAlignment(Qt::AlignRight | Qt::AlignVCenter); + layout->addWidget(label, 2, 2); + + if (editable) { + m_msecLabel = 0; + m_msec = new QSpinBox(frame); + m_msec->setMinValue(0); + m_msec->setLineStep(10); + connect(m_msec, SIGNAL(valueChanged(int)), + this, SLOT(slotSecOrMSecChanged(int))); + layout->addWidget(m_msec, 2, 3); + } else { + m_msec = 0; + m_msecLabel = new QLineEdit(frame); + m_msecLabel->setReadOnly(true); + layout->addWidget(m_msecLabel, 2, 3); + } + + if (m_isDuration) { + m_tempo = new QLabel(frame); + layout->addWidget(m_tempo, 2, 6); + } else { + m_tempo = 0; + } + + if (!savedEditable) { + if (m_note) + m_note ->setEnabled(false); + if (m_timeT) + m_timeT ->setEnabled(false); + if (m_bar) + m_bar ->setEnabled(false); + if (m_beat) + m_beat ->setEnabled(false); + if (m_fraction) + m_fraction ->setEnabled(false); + if (m_sec) + m_sec ->setEnabled(false); + if (m_msec) + m_msec ->setEnabled(false); + } + + populate(); +} + +void +TimeWidget::populate() +{ + // populate everything from m_time and m_startTime + + if (m_note) + m_note ->blockSignals(true); + if (m_timeT) + m_timeT ->blockSignals(true); + if (m_bar) + m_bar ->blockSignals(true); + if (m_beat) + m_beat ->blockSignals(true); + if (m_fraction) + m_fraction ->blockSignals(true); + if (m_sec) + m_sec ->blockSignals(true); + if (m_msec) + m_msec ->blockSignals(true); + + if (m_isDuration) { + + if (m_time + m_startTime > m_composition->getEndMarker()) { + m_time = m_composition->getEndMarker() - m_startTime; + } + + if (m_timeT) { + m_timeT->setMinValue(0); + if (m_constrain) { + m_timeT->setMaxValue(m_composition->getEndMarker() - m_startTime); + } else { + m_timeT->setMaxValue(INT_MAX); + } + m_timeT->setValue(m_time); + } + + if (m_note) { + m_note->setCurrentItem(0); + for (size_t i = 0; i < m_noteDurations.size(); ++i) { + if (m_time == m_noteDurations[i]) { + m_note->setCurrentItem(i); + break; + } + } + } + + // the bar/beat etc timings are considered to be times of a note + // starting at the start of a bar, in the time signature in effect + // at m_startTime + + int bars = 0, beats = 0, hemidemis = 0, remainder = 0; + m_composition->getMusicalTimeForDuration(m_startTime, m_time, + bars, beats, hemidemis, remainder); + TimeSignature timeSig = + m_composition->getTimeSignatureAt(m_startTime); + + if (m_bar) { + m_bar->setMinValue(0); + if (m_constrain) { + m_bar->setMaxValue + (m_composition->getBarNumber(m_composition->getEndMarker()) - + m_composition->getBarNumber(m_startTime)); + } else { + m_bar->setMaxValue(9999); + } + m_bar->setValue(bars); + } else { + m_barLabel->setText(QString("%1").arg(bars)); + } + + if (m_beat) { + m_beat->setMinValue(0); + m_beat->setMaxValue(timeSig.getBeatsPerBar() - 1); + m_beat->setValue(beats); + } else { + m_beatLabel->setText(QString("%1").arg(beats)); + } + + if (m_fraction) { + m_fraction->setMinValue(0); + m_fraction->setMaxValue(timeSig.getBeatDuration() / + Note(Note::Shortest). + getDuration() - 1); + m_fraction->setValue(hemidemis); + } else { + m_fractionLabel->setText(QString("%1").arg(hemidemis)); + } + + m_timeSig->setText(i18n("(%1/%2 time)").arg(timeSig.getNumerator()). + arg(timeSig.getDenominator())); + + timeT endTime = m_startTime + m_time; + + RealTime rt = m_composition->getRealTimeDifference + (m_startTime, endTime); + + if (m_sec) { + m_sec->setMinValue(0); + if (m_constrain) { + m_sec->setMaxValue(m_composition->getRealTimeDifference + (m_startTime, m_composition->getEndMarker()).sec); + } else { + m_sec->setMaxValue(9999); + } + m_sec->setValue(rt.sec); + } else { + m_secLabel->setText(QString("%1").arg(rt.sec)); + } + + if (m_msec) { + m_msec->setMinValue(0); + m_msec->setMaxValue(999); + m_msec->setValue(rt.msec()); + } else { + m_msecLabel->setText(QString("%1").arg(rt.msec())); + } + + bool change = (m_composition->getTempoChangeNumberAt(endTime) != + m_composition->getTempoChangeNumberAt(m_startTime)); + + //!!! imprecise -- better to work from tempoT directly + double tempo = m_composition->getTempoQpm(m_composition->getTempoAtTime(m_startTime)); + + int qpmc = int(tempo * 100.0); + int bpmc = qpmc; + if (timeSig.getBeatDuration() + != Note(Note::Crotchet).getDuration()) { + bpmc = int(tempo * 100.0 * + Note(Note::Crotchet).getDuration() / + timeSig.getBeatDuration()); + } + if (change) { + if (bpmc != qpmc) { + m_tempo->setText(i18n("(starting %1.%2 qpm, %2.%3 bpm)"). + arg(qpmc / 100). + arg(qpmc % 100). + arg(bpmc / 100). + arg(bpmc % 100)); + } else { + m_tempo->setText(i18n("(starting %1.%2 bpm)"). + arg(bpmc / 100). + arg(bpmc % 100)); + } + } else { + if (bpmc != qpmc) { + m_tempo->setText(i18n("(%1.%2 qpm, %2.%3 bpm)"). + arg(qpmc / 100). + arg(qpmc % 100). + arg(bpmc / 100). + arg(bpmc % 100)); + } else { + m_tempo->setText(i18n("(%1.%2 bpm)"). + arg(bpmc / 100). + arg(bpmc % 100)); + } + } + + } else { + + if (m_time > m_composition->getEndMarker()) { + m_time = m_composition->getEndMarker(); + } + + if (m_timeT) { + if (m_constrain) { + m_timeT->setMinValue(m_composition->getStartMarker()); + m_timeT->setMaxValue(m_composition->getEndMarker()); + } else { + m_timeT->setMinValue(INT_MIN); + m_timeT->setMaxValue(INT_MAX); + } + m_timeT->setValue(m_time); + } + + int bar = 1, beat = 1, hemidemis = 0, remainder = 0; + m_composition->getMusicalTimeForAbsoluteTime + (m_time, bar, beat, hemidemis, remainder); + + TimeSignature timeSig = + m_composition->getTimeSignatureAt(m_time); + + if (m_bar) { + m_bar->setMinValue(INT_MIN); + if (m_constrain) { + m_bar->setMaxValue(m_composition->getBarNumber + (m_composition->getEndMarker())); + } else { + m_bar->setMaxValue(9999); + } + m_bar->setValue(bar + 1); + } else { + m_barLabel->setText(QString("%1").arg(bar + 1)); + } + + if (m_beat) { + m_beat->setMinValue(1); + m_beat->setMaxValue(timeSig.getBeatsPerBar()); + m_beat->setValue(beat); + } else { + m_beatLabel->setText(QString("%1").arg(beat)); + } + + if (m_fraction) { + m_fraction->setMinValue(0); + m_fraction->setMaxValue(timeSig.getBeatDuration() / + Note(Note::Shortest). + getDuration() - 1); + m_fraction->setValue(hemidemis); + } else { + m_fractionLabel->setText(QString("%1").arg(hemidemis)); + } + + m_timeSig->setText(i18n("(%1/%2 time)").arg(timeSig.getNumerator()). + arg(timeSig.getDenominator())); + + RealTime rt = m_composition->getElapsedRealTime(m_time); + + if (m_sec) { + m_sec->setMinValue(INT_MIN); + if (m_constrain) { + m_sec->setMaxValue(m_composition->getElapsedRealTime + (m_composition->getEndMarker()).sec); + } else { + m_sec->setMaxValue(9999); + } + m_sec->setValue(rt.sec); + } else { + m_secLabel->setText(QString("%1").arg(rt.sec)); + } + + if (m_msec) { + m_msec->setMinValue(0); + m_msec->setMaxValue(999); + m_msec->setValue(rt.msec()); + } else { + m_msecLabel->setText(QString("%1").arg(rt.msec())); + } + } + + if (m_note) + m_note ->blockSignals(false); + if (m_timeT) + m_timeT ->blockSignals(false); + if (m_bar) + m_bar ->blockSignals(false); + if (m_beat) + m_beat ->blockSignals(false); + if (m_fraction) + m_fraction ->blockSignals(false); + if (m_sec) + m_sec ->blockSignals(false); + if (m_msec) + m_msec ->blockSignals(false); +} + +timeT +TimeWidget::getTime() +{ + return m_time; +} + +RealTime +TimeWidget::getRealTime() +{ + if (m_isDuration) { + return m_composition->getRealTimeDifference(m_startTime, + m_startTime + m_time); + } else { + return m_composition->getElapsedRealTime(m_time); + } +} + +void +TimeWidget::slotSetTime(timeT t) +{ + bool change = (m_time != t); + if (!change) + return ; + m_time = t; + populate(); + emit timeChanged(getTime()); + emit realTimeChanged(getRealTime()); +} + +void +TimeWidget::slotSetRealTime(RealTime rt) +{ + if (m_isDuration) { + RealTime startRT = m_composition->getElapsedRealTime(m_startTime); + if (rt >= RealTime::zeroTime) { + slotSetTime(m_composition->getElapsedTimeForRealTime(startRT + rt) - + m_startTime); + } else { + RG_DEBUG << "WARNING: TimeWidget::slotSetRealTime: rt must be >0 for duration widget (was " << rt << ")" << endl; + } + } else { + slotSetTime(m_composition->getElapsedTimeForRealTime(rt)); + } +} + +void +TimeWidget::slotResetToDefault() +{ + slotSetTime(m_defaultTime); +} + +void +TimeWidget::slotNoteChanged(int n) +{ + if (n > 0) { + slotSetTime(m_noteDurations[n]); + } +} + +void +TimeWidget::slotTimeTChanged(int t) +{ + RG_DEBUG << "slotTimeTChanged: t is " << t << ", value is " << m_timeT->value() << endl; + + slotSetTime(t); +} + +void +TimeWidget::slotBarBeatOrFractionChanged(int) +{ + int bar = m_bar->value(); + int beat = m_beat->value(); + int fraction = m_fraction->value(); + + if (m_isDuration) { + slotSetTime(m_composition->getDurationForMusicalTime + (m_startTime, bar, beat, fraction, 0)); + + } else { + slotSetTime(m_composition->getAbsoluteTimeForMusicalTime + (bar, beat, fraction, 0)); + } +} + +void +TimeWidget::slotSecOrMSecChanged(int) +{ + int sec = m_sec->value(); + int msec = m_msec->value(); + + slotSetRealTime(RealTime(sec, msec * 1000000)); +} + +} +#include "TimeWidget.moc" diff --git a/src/gui/widgets/TimeWidget.h b/src/gui/widgets/TimeWidget.h new file mode 100644 index 0000000..5ffa17a --- /dev/null +++ b/src/gui/widgets/TimeWidget.h @@ -0,0 +1,125 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENTIMEWIDGET_H_ +#define _RG_ROSEGARDENTIMEWIDGET_H_ + +#include "base/RealTime.h" +#include <qgroupbox.h> +#include <qstring.h> +#include <vector> +#include "base/Event.h" + + +class QWidget; +class QSpinBox; +class QLineEdit; +class QLabel; +class QComboBox; + + +namespace Rosegarden +{ + +class Composition; + + +class TimeWidget : public QGroupBox +{ + Q_OBJECT +public: + /** + * Constructor for absolute time widget + */ + TimeWidget(QString title, + QWidget *parent, + Composition *composition, // for bar/beat/msec + timeT initialTime, + bool editable = true, + bool constrainToCompositionDuration = true); + + /** + * Constructor for duration widget. startTime is the absolute time + * at which this duration begins, necessary so that we can show the + * correct real-time (based on tempo at startTime) etc. + */ + TimeWidget(QString title, + QWidget *parent, + Composition *composition, // for bar/beat/msec + timeT startTime, + timeT initialDuration, + bool editable = true, + bool constrainToCompositionDuration = true); + + timeT getTime(); + RealTime getRealTime(); + +signals: + void timeChanged(timeT); + void realTimeChanged(RealTime); + +public slots: + void slotSetTime(timeT); + void slotSetRealTime(RealTime); + void slotResetToDefault(); + + void slotNoteChanged(int); + void slotTimeTChanged(int); + void slotBarBeatOrFractionChanged(int); + void slotSecOrMSecChanged(int); + +private: + Composition *m_composition; + bool m_isDuration; + bool m_constrain; + timeT m_time; + timeT m_startTime; + timeT m_defaultTime; + + QComboBox *m_note; + QSpinBox *m_timeT; + QSpinBox *m_bar; + QSpinBox *m_beat; + QSpinBox *m_fraction; + QLineEdit *m_barLabel; + QLineEdit *m_beatLabel; + QLineEdit *m_fractionLabel; + QLabel *m_timeSig; + QSpinBox *m_sec; + QSpinBox *m_msec; + QLineEdit *m_secLabel; + QLineEdit *m_msecLabel; + QLabel *m_tempo; + + void init(bool editable); + void populate(); + + std::vector<timeT> m_noteDurations; +}; + + +} + +#endif diff --git a/src/gui/widgets/TristateCheckBox.cpp b/src/gui/widgets/TristateCheckBox.cpp new file mode 100644 index 0000000..89ade5d --- /dev/null +++ b/src/gui/widgets/TristateCheckBox.cpp @@ -0,0 +1,43 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "TristateCheckBox.h" + +#include <qcheckbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +void +TristateCheckBox::mouseReleaseEvent(QMouseEvent *) +{} + +TristateCheckBox::~TristateCheckBox() +{} + +} +#include "TristateCheckBox.moc" diff --git a/src/gui/widgets/TristateCheckBox.h b/src/gui/widgets/TristateCheckBox.h new file mode 100644 index 0000000..699252a --- /dev/null +++ b/src/gui/widgets/TristateCheckBox.h @@ -0,0 +1,69 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ROSEGARDENTRISTATECHECKBOX_H_ +#define _RG_ROSEGARDENTRISTATECHECKBOX_H_ + +#include <qcheckbox.h> + + +class QWidget; +class QMouseEvent; + + +namespace Rosegarden +{ + + + +/** Create out own check box which is always Tristate + * and allows us to click only between on and off + * and only to _show_ the third ("Some") state + */ +class TristateCheckBox : public QCheckBox +{ +Q_OBJECT +public: + TristateCheckBox(QWidget *parent=0, + const char *name=0):QCheckBox(parent, name) + { setTristate(true) ;} + + virtual ~TristateCheckBox(); + +protected: + // don't emit when the button is released + virtual void mouseReleaseEvent(QMouseEvent *); + +private: +}; + + +// A label that emits a double click signal and provides scroll wheel information. +// +// + +} + +#endif diff --git a/src/gui/widgets/VUMeter.cpp b/src/gui/widgets/VUMeter.cpp new file mode 100644 index 0000000..ae9fe84 --- /dev/null +++ b/src/gui/widgets/VUMeter.cpp @@ -0,0 +1,694 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "VUMeter.h" + +#include "misc/Debug.h" +#include "base/AudioLevel.h" +#include "gui/general/GUIPalette.h" +#include "gui/rulers/VelocityColour.h" +#include <qbrush.h> +#include <qcolor.h> +#include <qlabel.h> +#include <qpainter.h> +#include <qtimer.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +VUMeter::VUMeter(QWidget *parent, + VUMeterType type, + bool stereo, + bool hasRecord, + int width, + int height, + VUAlignment alignment, + const char *name): + QLabel(parent, name), + m_originalHeight(height), + m_active(true), + m_type(type), + m_alignment(alignment), + m_levelLeft(0), + m_recordLevelLeft(0), + m_peakLevelLeft(0), + m_levelStepLeft(m_baseLevelStep), + m_recordLevelStepLeft(m_baseLevelStep), + m_fallTimerLeft(0), + m_peakTimerLeft(0), + m_levelRight(0), + m_recordLevelRight(0), + m_peakLevelRight(0), + m_levelStepRight(0), + m_recordLevelStepRight(0), + m_fallTimerRight(0), + m_peakTimerRight(0), + m_showPeakLevel(true), + m_baseLevelStep(3), + m_stereo(stereo), + m_hasRecord(hasRecord) +{ + // Work out if we need peak hold first + // + switch (m_type) { + case PeakHold: + case AudioPeakHoldShort: + case AudioPeakHoldLong: + case AudioPeakHoldIEC: + case AudioPeakHoldIECLong: + case FixedHeightVisiblePeakHold: + m_showPeakLevel = true; + break; + + default: + case Plain: + m_showPeakLevel = false; + break; + } + + // Always init the left fall timer + // + m_fallTimerLeft = new QTimer(); + + connect(m_fallTimerLeft, SIGNAL(timeout()), + this, SLOT(slotReduceLevelLeft())); + + if (m_showPeakLevel) { + m_peakTimerLeft = new QTimer(); + + connect(m_peakTimerLeft, SIGNAL(timeout()), + this, SLOT(slotStopShowingPeakLeft())); + } + + if (stereo) { + m_fallTimerRight = new QTimer(); + + connect(m_fallTimerRight, SIGNAL(timeout()), + this, SLOT(slotReduceLevelRight())); + + if (m_showPeakLevel) { + m_peakTimerRight = new QTimer(); + connect(m_peakTimerRight, SIGNAL(timeout()), + this, SLOT(slotStopShowingPeakRight())); + } + + } + + setMinimumSize(width, m_originalHeight); + setMaximumSize(width, m_originalHeight); + + if (m_alignment == Vertical) + m_maxLevel = height; + else + m_maxLevel = width; + + int max = m_maxLevel; + int red, orange, green; + + if (m_type == AudioPeakHoldShort) { + red = AudioLevel::dB_to_fader( 0.0, max, AudioLevel::ShortFader); + orange = AudioLevel::dB_to_fader( -2.0, max, AudioLevel::ShortFader); + green = AudioLevel::dB_to_fader( -10.0, max, AudioLevel::ShortFader); + m_background = QColor(50, 50, 50); + } else if (m_type == AudioPeakHoldLong) { + red = AudioLevel::dB_to_fader( 0.0, max, AudioLevel::LongFader); + orange = AudioLevel::dB_to_fader( -2.0, max, AudioLevel::LongFader); + green = AudioLevel::dB_to_fader( -10.0, max, AudioLevel::LongFader); + m_background = QColor(50, 50, 50); + } else if (m_type == AudioPeakHoldIEC) { + red = AudioLevel::dB_to_fader( -0.1, max, AudioLevel::IEC268Meter); + orange = AudioLevel::dB_to_fader( -6.0, max, AudioLevel::IEC268Meter); + green = AudioLevel::dB_to_fader( -10.0, max, AudioLevel::IEC268Meter); + m_background = QColor(50, 50, 50); + } else if (m_type == AudioPeakHoldIECLong) { + red = AudioLevel::dB_to_fader( 0.0, max, AudioLevel::IEC268LongMeter); + orange = AudioLevel::dB_to_fader( -6.0, max, AudioLevel::IEC268LongMeter); + green = AudioLevel::dB_to_fader( -10.0, max, AudioLevel::IEC268LongMeter); + m_background = QColor(50, 50, 50); + } else { + red = max * 92 / 100; + orange = max * 60 / 100; + green = max * 10 / 100; + m_background = Qt::black; + } + + if (m_type == AudioPeakHoldLong || + m_type == AudioPeakHoldShort || + m_type == AudioPeakHoldIEC || + m_type == AudioPeakHoldIECLong) { + m_velocityColour = + new VelocityColour(GUIPalette::getColour(GUIPalette::LevelMeterSolidRed), + GUIPalette::getColour(GUIPalette::LevelMeterSolidOrange), + GUIPalette::getColour(GUIPalette::LevelMeterSolidGreen), + max, red, orange, green); + } else { + m_velocityColour = + new VelocityColour(GUIPalette::getColour(GUIPalette::LevelMeterRed), + GUIPalette::getColour(GUIPalette::LevelMeterOrange), + GUIPalette::getColour(GUIPalette::LevelMeterGreen), + max, red, orange, green); + } +} + +VUMeter::~VUMeter() +{ + delete m_velocityColour; + delete m_peakTimerRight; + delete m_peakTimerLeft; + delete m_fallTimerRight; + delete m_fallTimerLeft; +} + +void +VUMeter::setLevel(double level) +{ + setLevel(level, level, false); +} + +void +VUMeter::setLevel(double leftLevel, double rightLevel) +{ + setLevel(leftLevel, rightLevel, false); +} + +void +VUMeter::setRecordLevel(double level) +{ + setLevel(level, level, true); +} + +void +VUMeter::setRecordLevel(double leftLevel, double rightLevel) +{ + setLevel(leftLevel, rightLevel, true); +} + +void +VUMeter::setLevel(double leftLevel, double rightLevel, bool record) +{ + if (!isVisible()) + return ; + + // RG_DEBUG << "setLevel(" << (void *)this << "): record=" << record << ", leftLevel=" << leftLevel << ", hasRecord=" << m_hasRecord << endl; + + if (record && !m_hasRecord) + return ; + + short &ll = (record ? m_recordLevelLeft : m_levelLeft); + short &lr = (record ? m_recordLevelRight : m_levelRight); + + switch (m_type) { + + case AudioPeakHoldShort: + ll = AudioLevel::dB_to_fader + (leftLevel, m_maxLevel, AudioLevel::ShortFader); + lr = AudioLevel::dB_to_fader + (rightLevel, m_maxLevel, AudioLevel::ShortFader); + break; + + case AudioPeakHoldLong: + ll = AudioLevel::dB_to_fader + (leftLevel, m_maxLevel, AudioLevel::LongFader); + lr = AudioLevel::dB_to_fader + (rightLevel, m_maxLevel, AudioLevel::LongFader); + break; + + case AudioPeakHoldIEC: + ll = AudioLevel::dB_to_fader + (leftLevel, m_maxLevel, AudioLevel::IEC268Meter); + lr = AudioLevel::dB_to_fader + (rightLevel, m_maxLevel, AudioLevel::IEC268Meter); + break; + + case AudioPeakHoldIECLong: + ll = AudioLevel::dB_to_fader + (leftLevel, m_maxLevel, AudioLevel::IEC268LongMeter); + lr = AudioLevel::dB_to_fader + (rightLevel, m_maxLevel, AudioLevel::IEC268LongMeter); + break; + + default: + ll = (int)(double(m_maxLevel) * leftLevel); + lr = (int)(double(m_maxLevel) * rightLevel); + }; + + if (ll < 0) + ll = 0; + if (ll > m_maxLevel) + ll = m_maxLevel; + if (lr < 0) + lr = 0; + if (lr > m_maxLevel) + lr = m_maxLevel; + + if (record) { + m_recordLevelStepLeft = m_baseLevelStep; + m_recordLevelStepRight = m_baseLevelStep; + } else { + m_levelStepLeft = m_baseLevelStep; + m_levelStepRight = m_baseLevelStep; + } + + // Only start the timer when we need it + if (ll > 0) { + if (m_fallTimerLeft->isActive() == false) { + m_fallTimerLeft->start(40); // 40 ms per level fall iteration + meterStart(); + } + } + + if (lr > 0) { + if (m_fallTimerRight && m_fallTimerRight->isActive() == false) { + m_fallTimerRight->start(40); // 40 ms per level fall iteration + meterStart(); + } + } + + if (!record) { + + // Reset level and reset timer if we're exceeding the + // current peak + // + if (ll >= m_peakLevelLeft && m_showPeakLevel) { + m_peakLevelLeft = ll; + + if (m_peakTimerLeft->isActive()) + m_peakTimerLeft->stop(); + + m_peakTimerLeft->start(1000); // milliseconds of peak hold + } + + if (lr >= m_peakLevelRight && m_showPeakLevel) { + m_peakLevelRight = lr; + + if (m_peakTimerRight) { + if (m_peakTimerRight->isActive()) + m_peakTimerRight->stop(); + + m_peakTimerRight->start(1000); // milliseconds of peak hold + } + } + } + + if (m_active) { + QPainter paint(this); + drawMeterLevel(&paint); + } +} + +void +VUMeter::paintEvent(QPaintEvent *e) +{ + // RG_DEBUG << "VUMeter::paintEvent - height = " << height() << endl; + QPainter paint(this); + + if (m_type == VUMeter::AudioPeakHoldShort || + m_type == VUMeter::AudioPeakHoldLong || + m_type == VUMeter::AudioPeakHoldIEC || + m_type == VUMeter::AudioPeakHoldIECLong) { + paint.setPen(m_background); + paint.setBrush(m_background); + paint.drawRect(0, 0, width(), height()); + + drawMeterLevel(&paint); + + paint.setPen(colorGroup().background()); + paint.drawPoint(0, 0); + paint.drawPoint(width() - 1, 0); + paint.drawPoint(0, height() - 1); + paint.drawPoint(width() - 1, height() - 1); + } else if (m_type == VUMeter::FixedHeightVisiblePeakHold) { + paint.setPen(m_background); + paint.setBrush(m_background); + paint.drawRect(0, 0, width(), height()); + + if (m_fallTimerLeft->isActive()) + drawMeterLevel(&paint); + else { + meterStop(); + drawFrame(&paint); + drawContents(&paint); + } + } else { + if (m_fallTimerLeft->isActive()) { + paint.setPen(m_background); + paint.setBrush(m_background); + paint.drawRect(0, 0, width(), height()); + drawMeterLevel(&paint); + } else { + meterStop(); + drawFrame(&paint); + drawContents(&paint); + } + } +} + +void +VUMeter::drawColouredBar(QPainter *paint, int channel, + int x, int y, int w, int h) +{ + if (m_type == AudioPeakHoldLong || + m_type == AudioPeakHoldShort || + m_type == AudioPeakHoldIEC || + m_type == AudioPeakHoldIECLong) { + + Qt::BrushStyle style = Qt::SolidPattern; + + int medium = m_velocityColour->getMediumKnee(), + loud = m_velocityColour->getLoudKnee(); + + if (m_alignment == Vertical) { + if (h > loud) { + paint->setPen(m_velocityColour->getLoudColour()); + paint->setBrush(QBrush(m_velocityColour->getLoudColour(), + style)); + paint->drawRect(x, y, w, h - loud); + } + } else { + if (w > loud) { + paint->setPen(m_velocityColour->getLoudColour()); + paint->setBrush(QBrush(m_velocityColour->getLoudColour(), + style)); + paint->drawRect(x + loud, y, w - loud, h); + } + } + + if (m_alignment == Vertical) { + if (h > medium) { + paint->setPen(m_velocityColour->getMediumColour()); + paint->setBrush(QBrush(m_velocityColour->getMediumColour(), + style)); + paint->drawRect(x, y + (h > loud ? (h - loud) : 0), + w, std::min(h - medium, loud - medium)); + } + } else { + if (w > medium) { + paint->setPen(m_velocityColour->getMediumColour()); + paint->setBrush(QBrush(m_velocityColour->getMediumColour(), + style)); + paint->drawRect(x + medium, y, + std::min(w - medium, loud - medium), h); + } + } + + if (m_alignment == Vertical) { + paint->setPen(m_velocityColour->getQuietColour()); + paint->setBrush(QBrush(m_velocityColour->getQuietColour(), + style)); + paint->drawRect(x, y + (h > medium ? (h - medium) : 0), + w, std::min(h, medium)); + } else { + paint->setPen(m_velocityColour->getQuietColour()); + paint->setBrush(QBrush(m_velocityColour->getQuietColour(), + style)); + paint->drawRect(x, y, std::min(w, medium), h); + } + + } else { + + if (channel == 0) { + + QColor mixedColour = m_velocityColour->getColour(m_levelLeft); + + paint->setPen(mixedColour); + paint->setBrush(mixedColour); + + } else { + + QColor mixedColour = m_velocityColour->getColour(m_levelRight); + + paint->setPen(mixedColour); + paint->setBrush(mixedColour); + } + + // RG_DEBUG << "VUMeter::drawColouredBar - level = " << m_levelLeft << endl; + + paint->drawRect(x, y, w, h); + } +} + +void +VUMeter::drawMeterLevel(QPainter* paint) +{ + int medium = m_velocityColour->getMediumKnee(), + loud = m_velocityColour->getLoudKnee(); + + if (m_stereo) { + if (m_alignment == VUMeter::Vertical) { + int hW = width() / 2; + + int midWidth = 1; + if (m_hasRecord) { + if (width() > 10) { + midWidth = 2; + } + } + + // Draw the left bar + // + int y = height() - (m_levelLeft * height()) / m_maxLevel; + int ry = height() - (m_recordLevelLeft * height()) / m_maxLevel; + + drawColouredBar(paint, 0, 0, y, hW - midWidth, height() - y); + + if (m_hasRecord) { + drawColouredBar(paint, 0, hW - midWidth, ry, midWidth + 1, height() - ry); + } + + paint->setPen(m_background); + paint->setBrush(m_background); + paint->drawRect(0, 0, hW - midWidth, y); + + if (m_hasRecord) { + paint->drawRect(hW - midWidth, 0, midWidth + 1, ry); + } + + if (m_showPeakLevel) { + int h = (m_peakLevelLeft * height()) / m_maxLevel; + y = height() - h; + + if (h > loud) { + paint->setPen(Qt::red); // brighter than the red meter bar + paint->drawLine(0, y - 1, hW - midWidth - 1, y - 1); + paint->drawLine(0, y + 1, hW - midWidth - 1, y + 1); + } + + paint->setPen(Qt::white); + paint->drawLine(0, y, hW - midWidth - 1, y); + } + + // Draw the right bar + // + y = height() - (m_levelRight * height()) / m_maxLevel; + ry = height() - (m_recordLevelRight * height()) / m_maxLevel; + drawColouredBar(paint, 1, hW + midWidth, y, hW - midWidth, height() - y); + + if (m_hasRecord) { + drawColouredBar(paint, 1, hW, ry, midWidth + 1, height() - ry); + } + + paint->setPen(m_background); + paint->setBrush(m_background); + paint->drawRect(hW + midWidth, 0, hW - midWidth + 1, y); + + if (m_hasRecord) { + paint->drawRect(hW, 0, midWidth, ry); + } + + if (m_showPeakLevel) { + int h = (m_peakLevelRight * height()) / m_maxLevel; + y = height() - h; + + if (h > loud) { + paint->setPen(Qt::red); // brighter than the red meter bar + paint->drawLine(hW + midWidth, y - 1, width(), y - 1); + paint->drawLine(hW + midWidth, y + 1, width(), y + 1); + } + + paint->setPen(Qt::white); + paint->setBrush(Qt::white); + + paint->drawLine(hW + midWidth, y, width(), y); + } + } else // horizontal + { + paint->setPen(m_background); + paint->setBrush(m_background); + paint->drawRect(0, 0, width(), height()); + + int x = (m_levelLeft * width()) / m_maxLevel; + if (x > 0) + paint->drawRect(0, 0, x, height()); + + if (m_showPeakLevel) { + paint->setPen(Qt::white); + paint->setBrush(Qt::white); + + // show peak level + x = m_peakLevelLeft * width() / m_maxLevel; + if (x < (width() - 1)) + x++; + else + x = width() - 1; + + paint->drawLine(x, 0, x, height()); + } + } + } else { + // Paint a vertical meter according to type + // + if (m_alignment == VUMeter::Vertical) { + int y = height() - (m_levelLeft * height()) / m_maxLevel; + drawColouredBar(paint, 0, 0, y, width(), height()); + + paint->setPen(m_background); + paint->setBrush(m_background); + paint->drawRect(0, 0, width(), y); + + /* + RG_DEBUG << "VUMeter::drawMeterLevel - height = " << height() + << ", vertical rect height = " << y << endl; + */ + + if (m_showPeakLevel) { + paint->setPen(Qt::white); + paint->setBrush(Qt::white); + + y = height() - (m_peakLevelLeft * height()) / m_maxLevel; + + paint->drawLine(0, y, width(), y); + } + } else { + int x = (m_levelLeft * width()) / m_maxLevel; + if (x > 0) + drawColouredBar(paint, 0, 0, 0, x, height()); + + paint->setPen(m_background); + paint->setBrush(m_background); + paint->drawRect(x, 0, width() - x, height()); + + if (m_showPeakLevel) { + paint->setPen(Qt::white); + paint->setBrush(Qt::white); + + // show peak level + x = (m_peakLevelLeft * width()) / m_maxLevel; + if (x < (width() - 1)) + x++; + else + x = width() - 1; + + paint->drawLine(x, 0, x, height()); + } + } + } +} + +void +VUMeter::slotReduceLevelRight() +{ + m_levelStepRight = int(m_levelRight) * m_baseLevelStep / 100 + 1; + if (m_levelStepRight < 1) + m_levelStepRight = 1; + + m_recordLevelStepRight = int(m_recordLevelRight) * m_baseLevelStep / 100 + 1; + if (m_recordLevelStepRight < 1) + m_recordLevelStepRight = 1; + + if (m_levelRight > 0) + m_levelRight -= m_levelStepRight; + if (m_recordLevelRight > 0) + m_recordLevelRight -= m_recordLevelStepRight; + + if (m_levelRight <= 0) { + m_levelRight = 0; + m_peakLevelRight = 0; + } + + if (m_recordLevelRight <= 0) + m_recordLevelRight = 0; + + if (m_levelRight == 0 && m_recordLevelRight == 0) { + // Always stop the timer when we don't need it + if (m_fallTimerRight) + m_fallTimerRight->stop(); + meterStop(); + } + + QPainter paint(this); + drawMeterLevel(&paint); +} + +void +VUMeter::slotReduceLevelLeft() +{ + m_levelStepLeft = int(m_levelLeft) * m_baseLevelStep / 100 + 1; + if (m_levelStepLeft < 1) + m_levelStepLeft = 1; + + m_recordLevelStepLeft = int(m_recordLevelLeft) * m_baseLevelStep / 100 + 1; + if (m_recordLevelStepLeft < 1) + m_recordLevelStepLeft = 1; + + if (m_levelLeft > 0) + m_levelLeft -= m_levelStepLeft; + if (m_recordLevelLeft > 0) + m_recordLevelLeft -= m_recordLevelStepLeft; + + if (m_levelLeft <= 0) { + m_levelLeft = 0; + m_peakLevelLeft = 0; + } + + if (m_recordLevelLeft <= 0) + m_recordLevelLeft = 0; + + if (m_levelLeft == 0 && m_recordLevelLeft == 0) { + // Always stop the timer when we don't need it + if (m_fallTimerLeft) + m_fallTimerLeft->stop(); + meterStop(); + } + + QPainter paint(this); + drawMeterLevel(&paint); +} + +void +VUMeter::slotStopShowingPeakRight() +{ + m_peakLevelRight = 0; +} + +void +VUMeter::slotStopShowingPeakLeft() +{ + m_peakLevelLeft = 0; +} + +} +#include "VUMeter.moc" diff --git a/src/gui/widgets/VUMeter.h b/src/gui/widgets/VUMeter.h new file mode 100644 index 0000000..0a06dfd --- /dev/null +++ b/src/gui/widgets/VUMeter.h @@ -0,0 +1,154 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_VUMETER_H_ +#define _RG_VUMETER_H_ + +#include <qcolor.h> +#include <qlabel.h> + + +class QWidget; +class QTimer; +class QPaintEvent; +class QPainter; + + +namespace Rosegarden +{ + +class VelocityColour; + + +class VUMeter : public QLabel +{ +Q_OBJECT + +public: + typedef enum + { + Plain, + PeakHold, + AudioPeakHoldShort, + AudioPeakHoldLong, + AudioPeakHoldIEC, + AudioPeakHoldIECLong, + FixedHeightVisiblePeakHold + } VUMeterType; + + typedef enum + { + Horizontal, + Vertical + } VUAlignment; + + // Mono and stereo level setting. The AudioPeakHold meter types + // expect levels in dB; other types expect levels between 0 and 1. + // + void setLevel(double level); + void setLevel(double leftLevel, double rightLevel); + + // Mono and stereo record level setting. Same units. Only + // applicable if hasRecord true in constructor. + // + void setRecordLevel(double level); + void setRecordLevel(double leftLevel, double rightLevel); + + virtual void paintEvent(QPaintEvent*); + +protected: + // Constructor is protected - we can only create an object + // from a sub-class of this type from a sub-class. + // + VUMeter(QWidget *parent = 0, + VUMeterType type = Plain, + bool stereo = false, + bool hasRecord = false, + int width = 0, + int height = 0, + VUAlignment alignment = Horizontal, + const char *name = 0); + ~VUMeter(); + + virtual void meterStart() = 0; + virtual void meterStop() = 0; + + int m_originalHeight; + bool m_active; + + void setLevel(double leftLevel, double rightLevel, bool record); + +private slots: + void slotReduceLevelLeft(); + void slotStopShowingPeakLeft(); + + void slotReduceLevelRight(); + void slotStopShowingPeakRight(); + +private: + + void drawMeterLevel(QPainter *paint); + void drawColouredBar(QPainter *paint, int channel, + int x, int y, int w, int h); + + VUMeterType m_type; + VUAlignment m_alignment; + QColor m_background; + + short m_maxLevel; + + short m_levelLeft; + short m_recordLevelLeft; + short m_peakLevelLeft; + short m_levelStepLeft; + short m_recordLevelStepLeft; + QTimer *m_fallTimerLeft; + QTimer *m_peakTimerLeft; + + short m_levelRight; + short m_recordLevelRight; + short m_peakLevelRight; + short m_levelStepRight; + short m_recordLevelStepRight; + QTimer *m_fallTimerRight; + QTimer *m_peakTimerRight; + + bool m_showPeakLevel; + short m_baseLevelStep; + + bool m_stereo; + bool m_hasRecord; + + // We use this to work out our colours + // + VelocityColour *m_velocityColour; + + +}; + + +} + +#endif diff --git a/src/gui/widgets/WheelyButton.cpp b/src/gui/widgets/WheelyButton.cpp new file mode 100644 index 0000000..e63cb3b --- /dev/null +++ b/src/gui/widgets/WheelyButton.cpp @@ -0,0 +1,35 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "WheelyButton.h" + +#include <qpushbutton.h> +#include <qwidget.h> + + +namespace Rosegarden +{ +} +#include "WheelyButton.moc" diff --git a/src/gui/widgets/WheelyButton.h b/src/gui/widgets/WheelyButton.h new file mode 100644 index 0000000..83de80d --- /dev/null +++ b/src/gui/widgets/WheelyButton.h @@ -0,0 +1,68 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_WHEELYBUTTON_H_ +#define _RG_WHEELYBUTTON_H_ + +#include <qpushbutton.h> + + +class QWidget; +class QWheelEvent; + + +namespace Rosegarden +{ + + + +class WheelyButton : public QPushButton +{ + Q_OBJECT + +public: + WheelyButton(QWidget *w) : QPushButton(w) { } + virtual ~WheelyButton() { } + +signals: + void wheel(bool up); + +protected: + void wheelEvent(QWheelEvent *e) { + emit wheel(e->delta() > 0); + } +}; + + + +// A specialised menu for selecting audio inputs or outputs, that +// queries the studio and instrument to find out what it should show. +// Available in a "compact" size, which is a push button with a popup +// menu attached, or a regular size which is a combobox. +// + +} + +#endif diff --git a/src/gui/widgets/ZoomSlider.cpp b/src/gui/widgets/ZoomSlider.cpp new file mode 100644 index 0000000..1986635 --- /dev/null +++ b/src/gui/widgets/ZoomSlider.cpp @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + + +#include "ZoomSlider.h" + +#include <qslider.h> +#include <qwidget.h> + + +namespace Rosegarden +{ +} diff --git a/src/gui/widgets/ZoomSlider.h b/src/gui/widgets/ZoomSlider.h new file mode 100644 index 0000000..635d074 --- /dev/null +++ b/src/gui/widgets/ZoomSlider.h @@ -0,0 +1,175 @@ + +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <glaurent@telegraph-road.org>, + Chris Cannam <cannam@all-day-breakfast.com>, + Richard Bown <richard.bown@ferventsoftware.com> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + Other copyrights also apply to some parts of this work. Please + see the AUTHORS file and individual file headers for details. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#ifndef _RG_ZOOMSLIDER_H_ +#define _RG_ZOOMSLIDER_H_ + +#include <qslider.h> +#include <vector> + + +class T; +class QWidget; + + +namespace Rosegarden +{ + + + +template <class T> +class ZoomSlider : public QSlider +{ +public: + + /** + * Construct a ZoomSlider offering a selection from the + * given set of sizes. + * + * A ZoomSlider is a not-very-well-named slider widget that + * offers the user an integral range of values (say, 1..3) + * but maps those values internally onto a list of "sizes", + * which may be any values of any type (for example the + * strings "small", "medium" or "large" or the doubles 1.0, + * 1.2 and 1.5). It may be useful where a GUI wants to + * offer a fairly limited range of sizes or options that + * may actually be arbitrary values chosen because they + * work well for some internal reason but that should appear + * to the user as a nice continuous range. + */ + ZoomSlider(const std::vector<T> &sizes, T defaultValue, + Orientation, QWidget * parent, const char * name=0); + + virtual ~ZoomSlider(); + + void reinitialise(const std::vector<T> &sizes, T defaultValue); + + const T &getCurrentSize() const; + const T &getDefault() const; + +public slots: + void setToDefault(); // restore the initial value + void setSize(T size); + void increment(); + void decrement(); + +protected: + static int getIndex(const std::vector<T> &, T size); + std::vector<T> m_sizes; + T m_defaultValue; +}; + + +template<class T> +ZoomSlider<T>::ZoomSlider(const std::vector<T> &sizes, + T initialSize, Orientation o, + QWidget *parent, const char *name) : + QSlider(0, sizes.size()-1, 1, + getIndex(sizes, initialSize), o, parent, name), + m_sizes(sizes), + m_defaultValue(initialSize) +{ + setTracking(false); + setFixedWidth(150); + setFixedHeight(15); + setLineStep(1); + setTickmarks(Below); +} + +template<class T> +ZoomSlider<T>::~ZoomSlider() { } + +template<class T> +int +ZoomSlider<T>::getIndex(const std::vector<T> &sizes, T size) +{ + for (unsigned int i = 0; i < sizes.size(); ++i) { + if (sizes[i] == size) return i; + } + return sizes.size()/2; +} + +template<class T> +void +ZoomSlider<T>::reinitialise(const std::vector<T> &sizes, T size) +{ + m_sizes = sizes; + setMinValue(0); + setMaxValue(sizes.size()-1); + setValue(getIndex(sizes, size)); + setLineStep(1); + setTickmarks(Below); +} + +template<class T> +void +ZoomSlider<T>::setToDefault() +{ + setValue(getIndex(m_sizes, m_defaultValue)); +} + +template <class T> +const T & +ZoomSlider<T>::getCurrentSize() const +{ + return m_sizes[value()]; +} + +template <class T> +void +ZoomSlider<T>::setSize(T size) +{ + setValue(getIndex(m_sizes, size)); +} + +template <class T> +void +ZoomSlider<T>::increment() +{ + if (value() + 1 >= m_sizes.size()) return; + setValue(value() + 1); +} + +template <class T> +void +ZoomSlider<T>::decrement() +{ + if (value() <= 0) return; + setValue(value() - 1); +} + +template <class T> +const T & +ZoomSlider<T>::getDefault() const +{ + return m_defaultValue; +} + + + + +} + +#endif |