summaryrefslogtreecommitdiffstats
path: root/src/gui/widgets
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 18:37:05 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-03-01 18:37:05 +0000
commit145364a8af6a1fec06556221e66d4b724a62fc9a (patch)
tree53bd71a544008c518034f208d64c932dc2883f50 /src/gui/widgets
downloadrosegarden-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')
-rw-r--r--src/gui/widgets/AudioFaderBox.cpp294
-rw-r--r--src/gui/widgets/AudioFaderBox.h114
-rw-r--r--src/gui/widgets/AudioListItem.h97
-rw-r--r--src/gui/widgets/AudioListView.cpp67
-rw-r--r--src/gui/widgets/AudioListView.h44
-rw-r--r--src/gui/widgets/AudioRouteMenu.cpp381
-rw-r--r--src/gui/widgets/AudioRouteMenu.h94
-rw-r--r--src/gui/widgets/AudioVUMeter.cpp103
-rw-r--r--src/gui/widgets/AudioVUMeter.h96
-rw-r--r--src/gui/widgets/BigArrowButton.h47
-rw-r--r--src/gui/widgets/CollapsingFrame.cpp148
-rw-r--r--src/gui/widgets/CollapsingFrame.h75
-rw-r--r--src/gui/widgets/ColourTable.cpp131
-rw-r--r--src/gui/widgets/ColourTable.h72
-rw-r--r--src/gui/widgets/ColourTableItem.cpp52
-rw-r--r--src/gui/widgets/ColourTableItem.h60
-rw-r--r--src/gui/widgets/CurrentProgressDialog.cpp84
-rw-r--r--src/gui/widgets/CurrentProgressDialog.h81
-rw-r--r--src/gui/widgets/DiatonicPitchChooser.cpp244
-rw-r--r--src/gui/widgets/DiatonicPitchChooser.h103
-rw-r--r--src/gui/widgets/Fader.cpp567
-rw-r--r--src/gui/widgets/Fader.h137
-rw-r--r--src/gui/widgets/HSpinBox.cpp81
-rw-r--r--src/gui/widgets/HSpinBox.h67
-rw-r--r--src/gui/widgets/Label.cpp2
-rw-r--r--src/gui/widgets/Label.h63
-rw-r--r--src/gui/widgets/MidiFaderWidget.cpp41
-rw-r--r--src/gui/widgets/MidiFaderWidget.h72
-rw-r--r--src/gui/widgets/PitchChooser.cpp113
-rw-r--r--src/gui/widgets/PitchChooser.h73
-rw-r--r--src/gui/widgets/PitchDragLabel.cpp269
-rw-r--r--src/gui/widgets/PitchDragLabel.h99
-rw-r--r--src/gui/widgets/PluginControl.cpp228
-rw-r--r--src/gui/widgets/PluginControl.h104
-rw-r--r--src/gui/widgets/ProgressBar.cpp44
-rw-r--r--src/gui/widgets/ProgressBar.h56
-rw-r--r--src/gui/widgets/ProgressDialog.cpp209
-rw-r--r--src/gui/widgets/ProgressDialog.h98
-rw-r--r--src/gui/widgets/QDeferScrollView.cpp52
-rw-r--r--src/gui/widgets/QDeferScrollView.h75
-rw-r--r--src/gui/widgets/QuantizeParameters.cpp497
-rw-r--r--src/gui/widgets/QuantizeParameters.h117
-rw-r--r--src/gui/widgets/RosegardenPopupMenu.h43
-rw-r--r--src/gui/widgets/Rotary.cpp560
-rw-r--r--src/gui/widgets/Rotary.h167
-rw-r--r--src/gui/widgets/ScrollBox.cpp159
-rw-r--r--src/gui/widgets/ScrollBox.h89
-rw-r--r--src/gui/widgets/ScrollBoxDialog.cpp68
-rw-r--r--src/gui/widgets/ScrollBoxDialog.h71
-rw-r--r--src/gui/widgets/SpinBox.cpp73
-rw-r--r--src/gui/widgets/SpinBox.h65
-rw-r--r--src/gui/widgets/TextFloat.cpp112
-rw-r--r--src/gui/widgets/TextFloat.h64
-rw-r--r--src/gui/widgets/TimeWidget.cpp668
-rw-r--r--src/gui/widgets/TimeWidget.h125
-rw-r--r--src/gui/widgets/TristateCheckBox.cpp43
-rw-r--r--src/gui/widgets/TristateCheckBox.h69
-rw-r--r--src/gui/widgets/VUMeter.cpp694
-rw-r--r--src/gui/widgets/VUMeter.h154
-rw-r--r--src/gui/widgets/WheelyButton.cpp35
-rw-r--r--src/gui/widgets/WheelyButton.h68
-rw-r--r--src/gui/widgets/ZoomSlider.cpp34
-rw-r--r--src/gui/widgets/ZoomSlider.h175
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