diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 18:37:05 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 18:37:05 +0000 |
commit | 145364a8af6a1fec06556221e66d4b724a62fc9a (patch) | |
tree | 53bd71a544008c518034f208d64c932dc2883f50 /src/gui/dialogs | |
download | rosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.tar.gz rosegarden-145364a8af6a1fec06556221e66d4b724a62fc9a.zip |
Added old abandoned KDE3 version of the RoseGarden MIDI tool
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/rosegarden@1097595 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/gui/dialogs')
96 files changed, 17470 insertions, 0 deletions
diff --git a/src/gui/dialogs/AddTracksDialog.cpp b/src/gui/dialogs/AddTracksDialog.cpp new file mode 100644 index 0000000..67e5412 --- /dev/null +++ b/src/gui/dialogs/AddTracksDialog.cpp @@ -0,0 +1,110 @@ +/* -*- 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 "AddTracksDialog.h" + +#include <klocale.h> +#include <kdialogbase.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qspinbox.h> +#include <kcombobox.h> +#include <qvbox.h> +#include <qwidget.h> +#include <kapp.h> +#include <kconfig.h> + +#include "document/ConfigGroups.h" + + +namespace Rosegarden +{ + +AddTracksDialog::AddTracksDialog(QWidget *parent, int currentTrack) : + KDialogBase(parent, 0, true, i18n("Add Tracks"), + Ok | Cancel), + m_currentTrack(currentTrack) +{ + QVBox *vBox = makeVBoxMainWidget(); + + QHBox *countBox = new QHBox(vBox); + countBox->setSpacing(4); + new QLabel(i18n("How many tracks do you want to add?"), countBox); + m_count = new QSpinBox(countBox); + m_count->setMinValue(1); + m_count->setMaxValue(32); + m_count->setValue(1); + + QHBox *posBox = new QHBox(vBox); + posBox->setSpacing(4); + new QLabel(i18n("Add tracks"), posBox); + m_position = new KComboBox(posBox); + m_position->insertItem(i18n("At the top")); + m_position->insertItem(i18n("Above the current selected track")); + m_position->insertItem(i18n("Below the current selected track")); + m_position->insertItem(i18n("At the bottom")); + + KConfig *config = kapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + m_position->setCurrentItem(config->readUnsignedNumEntry("lastaddtracksposition", 2)); +} + +int +AddTracksDialog::getTracks() +{ + return m_count->value(); +} + +int +AddTracksDialog::getInsertPosition() +{ + int opt = m_position->currentItem(); + + KConfig *config = kapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + config->writeEntry("lastaddtracksposition", opt); + + int pos = 0; + + switch (opt) { + case 0: // at top + pos = 0; + break; + case 1: // above current track + pos = m_currentTrack; + break; + case 2: // below current track + pos = m_currentTrack + 1; + break; + case 3: // at bottom + pos = -1; + break; + } + + return pos; +} + +} +#include "AddTracksDialog.moc" diff --git a/src/gui/dialogs/AddTracksDialog.h b/src/gui/dialogs/AddTracksDialog.h new file mode 100644 index 0000000..9930e46 --- /dev/null +++ b/src/gui/dialogs/AddTracksDialog.h @@ -0,0 +1,57 @@ +/* -*- 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_ADDTRACKSDIALOG_H_ +#define _RG_ADDTRACKSDIALOG_H_ + +#include <kdialogbase.h> + +class QWidget; +class QSpinBox; +class QComboBox; + +namespace Rosegarden +{ + +class AddTracksDialog : public KDialogBase +{ + Q_OBJECT + +public: + AddTracksDialog(QWidget *parent, int currentTrack = -1); + + int getTracks(); + int getInsertPosition(); + +protected: + int m_currentTrack; + QSpinBox *m_count; + QComboBox *m_position; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/AudioManagerDialog.cpp b/src/gui/dialogs/AudioManagerDialog.cpp new file mode 100644 index 0000000..5982632 --- /dev/null +++ b/src/gui/dialogs/AudioManagerDialog.cpp @@ -0,0 +1,1257 @@ +/* -*- 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 "AudioManagerDialog.h" +#include <kapplication.h> + +#include "base/Event.h" +#include "misc/Debug.h" +#include "misc/Strings.h" +#include "AudioPlayingDialog.h" +#include "base/Composition.h" +#include "base/Exception.h" +#include "base/Instrument.h" +#include "base/MidiProgram.h" +#include "base/NotationTypes.h" +#include "base/RealTime.h" +#include "base/Segment.h" +#include "base/Selection.h" +#include "base/Studio.h" +#include "base/Track.h" +#include "document/MultiViewCommandHistory.h" +#include "document/RosegardenGUIDoc.h" +#include "document/ConfigGroups.h" +#include "gui/application/RosegardenGUIView.h" +#include "gui/application/RosegardenApplication.h" +#include "gui/widgets/AudioListItem.h" +#include "gui/widgets/AudioListView.h" +#include "gui/widgets/CurrentProgressDialog.h" +#include "gui/widgets/ProgressDialog.h" +#include "sound/AudioFile.h" +#include "sound/AudioFileManager.h" +#include "sound/WAVAudioFile.h" +#include "UnusedAudioSelectionDialog.h" +#include <klocale.h> +#include <kstddirs.h> +#include <kaction.h> +#include <kcommand.h> +#include <kfiledialog.h> +#include <kglobal.h> +#include <klineeditdlg.h> +#include <klistview.h> +#include <kmainwindow.h> +#include <kmessagebox.h> +#include <kstdaction.h> +#include <kurl.h> +#include <kxmlguiclient.h> +#include <kio/netaccess.h> +#include <qaccel.h> +#include <qcstring.h> +#include <qdatastream.h> +#include <qdialog.h> +#include <qdragobject.h> +#include <qfile.h> +#include <qfileinfo.h> +#include <qiconset.h> +#include <qlabel.h> +#include <qlistview.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qstring.h> +#include <qstrlist.h> +#include <qtimer.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +const int AudioManagerDialog::m_maxPreviewWidth = 100; +const int AudioManagerDialog::m_previewHeight = 30; +const char* const AudioManagerDialog::m_listViewLayoutName = "AudioManagerDialog Layout"; + +AudioManagerDialog::AudioManagerDialog(QWidget *parent, + RosegardenGUIDoc *doc): + KMainWindow(parent, "audioManagerDialog"), + m_doc(doc), + m_playingAudioFile(0), + m_audioPlayingDialog(0), + m_playTimer(new QTimer(this)), + m_audiblePreview(true) +{ + setCaption(i18n("Audio File Manager")); + setWFlags(WDestructiveClose); + + QVBox *box = new QVBox(this); + setCentralWidget(box); + box->setMargin(10); + box->setSpacing(5); + + m_sampleRate = 0; + + QCString replyType; + QByteArray replyData; + if (rgapp->sequencerCall("getSampleRate()", replyType, replyData)) { + QDataStream streamIn(replyData, IO_ReadOnly); + unsigned int result; + streamIn >> result; + m_sampleRate = result; + } + + m_fileList = new AudioListView(box); + + m_wrongSampleRates = new QLabel(i18n("* Some audio files are encoded at a sample rate different from that of the JACK audio server.\nRosegarden will play them at the correct speed, but they will sound terrible.\nPlease consider resampling such files externally, or adjusting the sample rate of the JACK server."), box); + m_wrongSampleRates->hide(); + + QString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/"); + QIconSet icon(QPixmap(pixmapDir + "/toolbar/transport-play.xpm")); + + new KAction(i18n("&Add Audio File..."), "fileopen", 0, this, + SLOT(slotAdd()), actionCollection(), "add_audio"); + + new KAction(i18n("&Unload Audio File"), "editdelete", 0, this, + SLOT(slotRemove()), + actionCollection(), "remove_audio"); + + icon = QIconSet(QPixmap(pixmapDir + "/toolbar/transport-play.xpm")); + new KAction(i18n("&Play Preview"), icon, 0, this, + SLOT(slotPlayPreview()), + actionCollection(), "preview_audio"); + + /*!!! Not actually implemented -- this never worked right! + new KAction(i18n("Re&label"), 0, 0, this, + SLOT(slotRename()), + actionCollection(), "rename_audio"); + */ + + icon = QIconSet(QPixmap(pixmapDir + "/toolbar/insert_audio_into_track.xpm")); + new KAction(i18n("&Insert into Selected Audio Track"), + icon, 0, this, SLOT(slotInsert()), + actionCollection(), "insert_audio"); + + new KAction(i18n("Unload &all Audio Files"), 0, 0, this, + SLOT(slotRemoveAll()), + actionCollection(), "remove_all_audio"); + + new KAction(i18n("Unload all &Unused Audio Files"), 0, 0, this, + SLOT(slotRemoveAllUnused()), + actionCollection(), "remove_all_unused_audio"); + + new KAction(i18n("&Delete Unused Audio Files..."), 0, 0, this, + SLOT(slotDeleteUnused()), + actionCollection(), "delete_unused_audio"); + + new KAction(i18n("&Export Audio File..."), "fileexport", 0, this, + SLOT(slotExportAudio()), + actionCollection(), "export_audio"); +/* + new KAction(i18n("Distribute Audio on &MIDI"), + 0, 0, this, + SLOT(slotDistributeOnMidiSegment()), + actionCollection(), + "distribute_audio"); +*/ + // Set the column names + // + m_fileList->addColumn(i18n("Name")); // 0 + m_fileList->addColumn(i18n("Duration")); // 1 + m_fileList->addColumn(i18n("Envelope")); // 2 + m_fileList->addColumn(i18n("Sample rate")); // 3 + m_fileList->addColumn(i18n("Channels")); // 4 + m_fileList->addColumn(i18n("Resolution")); // 5 + m_fileList->addColumn(i18n("File")); // 6 + + m_fileList->setColumnAlignment(1, Qt::AlignHCenter); + m_fileList->setColumnAlignment(2, Qt::AlignHCenter); + m_fileList->setColumnAlignment(3, Qt::AlignHCenter); + m_fileList->setColumnAlignment(4, Qt::AlignHCenter); + m_fileList->setColumnAlignment(5, Qt::AlignHCenter); + + m_fileList->restoreLayout(kapp->config(), m_listViewLayoutName); + + // a minimum width for the list box + //m_fileList->setMinimumWidth(300); + + // show focus across all columns + m_fileList->setAllColumnsShowFocus(true); + + // show tooltips when columns are partially hidden + m_fileList->setShowToolTips(true); + + // connect selection mechanism + connect(m_fileList, SIGNAL(selectionChanged(QListViewItem*)), + SLOT(slotSelectionChanged(QListViewItem*))); + + connect(m_fileList, SIGNAL(dropped(QDropEvent*, QListViewItem*)), + SLOT(slotDropped(QDropEvent*, QListViewItem*))); + + // setup local accelerators + // + m_accelerators = new QAccel(this); + + // delete + // + m_accelerators->connectItem(m_accelerators->insertItem(Key_Delete), + this, + SLOT(slotRemove())); + + slotPopulateFileList(); + + // Connect command history for updates + // + connect(getCommandHistory(), SIGNAL(commandExecuted(KCommand *)), + this, SLOT(slotCommandExecuted(KCommand *))); + + //setInitialSize(configDialogSize(AudioManagerDialogConfigGroup)); + + connect(m_playTimer, SIGNAL(timeout()), + this, SLOT(slotCancelPlayingAudio())); + + KStdAction::close(this, + SLOT(slotClose()), + actionCollection()); + + createGUI("audiomanager.rc"); + + updateActionState(false); +} + +AudioManagerDialog::~AudioManagerDialog() +{ + RG_DEBUG << "\n*** AudioManagerDialog::~AudioManagerDialog\n" << endl; + m_fileList->saveLayout(kapp->config(), m_listViewLayoutName); + //saveDialogSize(AudioManagerDialogConfigGroup); +} + +void +AudioManagerDialog::slotPopulateFileList() +{ + // create pixmap of given size + QPixmap *audioPixmap = new QPixmap(m_maxPreviewWidth, m_previewHeight); + + // Store last selected item if we have one + // + AudioListItem *selectedItem = + dynamic_cast<AudioListItem*>(m_fileList->selectedItem()); + AudioFileId lastId = 0; + Segment *lastSegment = 0; + bool findSelection = false; + bool foundSelection = false; + + if (selectedItem) { + lastId = selectedItem->getId(); + lastSegment = selectedItem->getSegment(); + findSelection = true; + } + + // We don't want the selection changes to be propagated + // to the main view + // + m_fileList->blockSignals(true); + + // clear file list and disable associated action buttons + m_fileList->clear(); + + if (m_doc->getAudioFileManager().begin() == + m_doc->getAudioFileManager().end()) { + // Turn off selection and report empty list + // + new AudioListItem(m_fileList, i18n("<no audio files>"), 0); + m_fileList->setSelectionMode(QListView::NoSelection); + m_fileList->setRootIsDecorated(false); + + m_fileList->blockSignals(false); + updateActionState(false); + return ; + } + + // show tree hierarchy + m_fileList->setRootIsDecorated(true); + + // enable selection + m_fileList->setSelectionMode(QListView::Single); + + // for the sample file length + QString msecs, sRate; + RealTime length; + + // Create a vector of audio Segments only + // + std::vector<Segment*> segments; + std::vector<Segment*>::const_iterator iit; + + for (Composition::iterator it = m_doc->getComposition().begin(); + it != m_doc->getComposition().end(); ++it) { + if ((*it)->getType() == Segment::Audio) + segments.push_back(*it); + } + + // duration + RealTime segmentDuration; + bool wrongSampleRates = false; + + for (std::vector<AudioFile*>::const_iterator + it = m_doc->getAudioFileManager().begin(); + it != m_doc->getAudioFileManager().end(); + ++it) { + try { + m_doc->getAudioFileManager(). + drawPreview((*it)->getId(), + RealTime::zeroTime, + (*it)->getLength(), + audioPixmap); + } catch (Exception e) { + audioPixmap->fill(); // white + QPainter p(audioPixmap); + p.setPen(Qt::black); + p.drawText(10, m_previewHeight / 2, QString("<no preview>")); + } + + //!!! Why isn't the label the label the user assigned to the file? + // Why do we allow the user to assign a label at all, then? + + QString label = QString((*it)->getShortFilename().c_str()); + + // Set the label, duration, envelope pixmap and filename + // + AudioListItem *item = new AudioListItem(m_fileList, label, + (*it)->getId()); + // Duration + // + length = (*it)->getLength(); + msecs.sprintf("%03d", length.nsec / 1000000); + item->setText(1, QString("%1.%2s").arg(length.sec).arg(msecs)); + + // set start time and duration + item->setStartTime(RealTime::zeroTime); + item->setDuration(length); + + // Envelope pixmap + // + item->setPixmap(2, *audioPixmap); + + // File location + // + item->setText(6, QString( + m_doc->getAudioFileManager(). + substituteHomeForTilde((*it)->getFilename()).c_str())); + + // Resolution + // + item->setText(5, QString("%1 bits").arg((*it)->getBitsPerSample())); + + // Channels + // + item->setText(4, QString("%1").arg((*it)->getChannels())); + + // Sample rate + // + if (m_sampleRate != 0 && (*it)->getSampleRate() != m_sampleRate) { + sRate.sprintf("%.1f KHz *", float((*it)->getSampleRate()) / 1000.0); + wrongSampleRates = true; + } else { + sRate.sprintf("%.1f KHz", float((*it)->getSampleRate()) / 1000.0); + } + item->setText(3, sRate); + + // Test audio file element for selection criteria + // + if (findSelection && lastSegment == 0 && lastId == (*it)->getId()) { + m_fileList->setSelected(item, true); + findSelection = false; + } + + // Add children + // + for (iit = segments.begin(); iit != segments.end(); iit++) { + if ((*iit)->getAudioFileId() == (*it)->getId()) { + AudioListItem *childItem = + new AudioListItem(item, + QString((*iit)->getLabel().c_str()), + (*it)->getId()); + segmentDuration = (*iit)->getAudioEndTime() - + (*iit)->getAudioStartTime(); + + // store the start time + // + childItem->setStartTime((*iit)->getAudioStartTime()); + childItem->setDuration(segmentDuration); + + // Write segment duration + // + msecs.sprintf("%03d", segmentDuration.nsec / 1000000); + childItem->setText(1, QString("%1.%2s") + .arg(segmentDuration.sec) + .arg(msecs)); + + try { + m_doc->getAudioFileManager(). + drawHighlightedPreview((*it)->getId(), + RealTime::zeroTime, + (*it)->getLength(), + (*iit)->getAudioStartTime(), + (*iit)->getAudioEndTime(), + audioPixmap); + } catch (Exception e) { + // should already be set to "no file" + } + + // set pixmap + // + childItem->setPixmap(2, *audioPixmap); + + // set segment + // + childItem->setSegment(*iit); + + if (findSelection && lastSegment == (*iit)) { + m_fileList->setSelected(childItem, true); + findSelection = false; + foundSelection = true; + } + + // Add children + } + } + } + + updateActionState(foundSelection); + + if (wrongSampleRates) { + m_wrongSampleRates->show(); + } else { + m_wrongSampleRates->hide(); + } + + m_fileList->blockSignals(false); +} + +AudioFile* +AudioManagerDialog::getCurrentSelection() +{ + // try and get the selected item + AudioListItem *item = + dynamic_cast<AudioListItem*>(m_fileList->selectedItem()); + if (item == 0) + return 0; + + std::vector<AudioFile*>::const_iterator it; + + for (it = m_doc->getAudioFileManager().begin(); + it != m_doc->getAudioFileManager().end(); + ++it) { + // If we match then return the valid AudioFile + // + if (item->getId() == (*it)->getId()) + return (*it); + } + + return 0; +} + +void +AudioManagerDialog::slotExportAudio() +{ + WAVAudioFile *sourceFile + = dynamic_cast<WAVAudioFile*>(getCurrentSelection()); + + AudioListItem *item = + dynamic_cast<AudioListItem*>(m_fileList->selectedItem()); + + Segment *segment = item->getSegment(); + + QString saveFile = + KFileDialog::getSaveFileName(":WAVS", + i18n("*.wav|WAV files (*.wav)"), + this, i18n("Choose a name to save this file as")); + + if (sourceFile == 0 || item == 0 || saveFile.isEmpty()) + return ; + + // Check for a dot extension and append ".wav" if not found + // + if (saveFile.contains(".") == 0) + saveFile += ".wav"; + + ProgressDialog progressDlg(i18n("Exporting audio file..."), + 100, + this); + + progressDlg.progressBar()->setProgress(0); + + RealTime clipStartTime = RealTime::zeroTime; + RealTime clipDuration = sourceFile->getLength(); + + if (segment) { + clipStartTime = segment->getAudioStartTime(); + clipDuration = segment->getAudioEndTime() - clipStartTime; + } + + WAVAudioFile *destFile + = new WAVAudioFile(qstrtostr(saveFile), + sourceFile->getChannels(), + sourceFile->getSampleRate(), + sourceFile->getBytesPerSecond(), + sourceFile->getBytesPerFrame(), + sourceFile->getBitsPerSample()); + + if (sourceFile->open() == false) { + delete destFile; + return ; + } + + destFile->write(); + + sourceFile->scanTo(clipStartTime); + destFile->appendSamples(sourceFile->getSampleFrameSlice(clipDuration)); + + destFile->close(); + sourceFile->close(); + delete destFile; + + progressDlg.progressBar()->setProgress(100); +} + +void +AudioManagerDialog::slotRemove() +{ + AudioFile *audioFile = getCurrentSelection(); + AudioListItem *item = + dynamic_cast<AudioListItem*>(m_fileList->selectedItem()); + + if (audioFile == 0 || item == 0) + return ; + + // If we're on a Segment then delete it at the Composition + // and refresh the list. + // + if (item->getSegment()) { + // Get the next item to highlight + // + QListViewItem *newItem = item->itemBelow(); + + // Or try above + // + if (newItem == 0) + newItem = item->itemAbove(); + + // Or the parent + // + if (newItem == 0) + newItem = item->parent(); + + // Get the id and segment of the next item so that we can + // match against it + // + AudioFileId id = 0; + Segment *segment = 0; + AudioListItem *aItem = dynamic_cast<AudioListItem*>(newItem); + + if (aItem) { + segment = aItem->getSegment(); + id = aItem->getId(); + } + + // Jump to new selection + // + if (newItem) + setSelected(id, segment, true); // propagate + + // Do it - will force update + // + SegmentSelection selection; + selection.insert(item->getSegment()); + emit deleteSegments(selection); + + return ; + } + + // remove segments along with audio file + // + AudioFileId id = audioFile->getId(); + SegmentSelection selection; + Composition &comp = m_doc->getComposition(); + + bool haveSegments = false; + for (Composition::iterator it = comp.begin(); it != comp.end(); ++it) { + if ((*it)->getType() == Segment::Audio && + (*it)->getAudioFileId() == id) { + haveSegments = true; + break; + } + } + + if (haveSegments) { + + QString question = i18n("This will unload audio file \"%1\" and remove all associated segments. Are you sure?") + .arg(QString(audioFile->getFilename().c_str())); + + // Ask the question + int reply = KMessageBox::warningContinueCancel(this, question); + + if (reply != KMessageBox::Continue) + return ; + } + + for (Composition::iterator it = comp.begin(); it != comp.end(); ++it) { + if ((*it)->getType() == Segment::Audio && + (*it)->getAudioFileId() == id) + selection.insert(*it); + } + emit deleteSegments(selection); + + m_doc->notifyAudioFileRemoval(id); + + m_doc->getAudioFileManager().removeFile(id); + + // tell the sequencer + emit deleteAudioFile(id); + + // repopulate + slotPopulateFileList(); +} + +void +AudioManagerDialog::slotPlayPreview() +{ + AudioFile *audioFile = getCurrentSelection(); + AudioListItem *item = + dynamic_cast<AudioListItem*>(m_fileList->selectedItem()); + + if (item == 0 || audioFile == 0) + return ; + + // store the audio file we're playing + m_playingAudioFile = audioFile->getId(); + + // tell the sequencer + emit playAudioFile(audioFile->getId(), + item->getStartTime(), + item->getDuration()); + + // now open up the playing dialog + // + m_audioPlayingDialog = + new AudioPlayingDialog(this, QString(audioFile->getFilename().c_str())); + + // Setup timer to pop down dialog after file has completed + // + int msecs = item->getDuration().sec * 1000 + + item->getDuration().nsec / 1000000; + m_playTimer->start(msecs, true); // single shot + + // just execute + // + if (m_audioPlayingDialog->exec() == QDialog::Rejected) + emit cancelPlayingAudioFile(m_playingAudioFile); + + delete m_audioPlayingDialog; + m_audioPlayingDialog = 0; + + m_playTimer->stop(); + +} + +void +AudioManagerDialog::slotCancelPlayingAudio() +{ + //std::cout << "AudioManagerDialog::slotCancelPlayingAudio" << std::endl; + if (m_audioPlayingDialog) { + m_playTimer->stop(); + delete m_audioPlayingDialog; + m_audioPlayingDialog = 0; + } +} + +void +AudioManagerDialog::slotAdd() +{ + QString extensionList = i18n("*.wav|WAV files (*.wav)\n*.*|All files"); + + if (RosegardenGUIApp::self()->haveAudioImporter()) { + //!!! This list really needs to come from the importer helper program + // (which has an option to supply it -- we just haven't recorded it) + extensionList = i18n("*.wav *.flac *.ogg *.mp3|Audio files (*.wav *.flac *.ogg *.mp3)\n*.wav|WAV files (*.wav)\n*.flac|FLAC files (*.flac)\n*.ogg|Ogg files (*.ogg)\n*.mp3|MP3 files (*.mp3)\n*.*|All files"); + } + + KURL::List kurlList = + KFileDialog::getOpenURLs(":WAVS", + extensionList, + // i18n("*.wav|WAV files (*.wav)\n*.mp3|MP3 files (*.mp3)"), + this, i18n("Select one or more audio files")); + + KURL::List::iterator it; + + for (it = kurlList.begin(); it != kurlList.end(); ++it) + addFile(*it); +} + +void +AudioManagerDialog::updateActionState(bool haveSelection) +{ + if (m_doc->getAudioFileManager().begin() == + m_doc->getAudioFileManager().end()) { + stateChanged("have_audio_files", KXMLGUIClient::StateReverse); + } else { + stateChanged("have_audio_files", KXMLGUIClient::StateNoReverse); + } + + if (haveSelection) { + + stateChanged("have_audio_selected", KXMLGUIClient::StateNoReverse); + + if (m_audiblePreview) { + stateChanged("have_audible_preview", KXMLGUIClient::StateNoReverse); + } else { + stateChanged("have_audible_preview", KXMLGUIClient::StateReverse); + } + + if (isSelectedTrackAudio()) { + stateChanged("have_audio_insertable", KXMLGUIClient::StateNoReverse); + } else { + stateChanged("have_audio_insertable", KXMLGUIClient::StateReverse); + } + + } else { + stateChanged("have_audio_selected", KXMLGUIClient::StateReverse); + stateChanged("have_audio_insertable", KXMLGUIClient::StateReverse); + stateChanged("have_audible_preview", KXMLGUIClient::StateReverse); + } +} + +void +AudioManagerDialog::slotInsert() +{ + AudioFile *audioFile = getCurrentSelection(); + if (audioFile == 0) + return ; + + RG_DEBUG << "AudioManagerDialog::slotInsert\n"; + + emit insertAudioSegment(audioFile->getId(), + RealTime::zeroTime, + audioFile->getLength()); +} + +void +AudioManagerDialog::slotRemoveAll() +{ + QString question = + i18n("This will unload all audio files and remove their associated segments.\nThis action cannot be undone, and associations with these files will be lost.\nFiles will not be removed from your disk.\nAre you sure?"); + + int reply = KMessageBox::warningContinueCancel(this, question); + + if (reply != KMessageBox::Continue) + return ; + + SegmentSelection selection; + Composition &comp = m_doc->getComposition(); + + for (Composition::iterator it = comp.begin(); it != comp.end(); ++it) { + if ((*it)->getType() == Segment::Audio) + selection.insert(*it); + } + // delete segments + emit deleteSegments(selection); + + for (std::vector<AudioFile*>::const_iterator + aIt = m_doc->getAudioFileManager().begin(); + aIt != m_doc->getAudioFileManager().end(); ++aIt) { + m_doc->notifyAudioFileRemoval((*aIt)->getId()); + } + + m_doc->getAudioFileManager().clear(); + + // and now the audio files + emit deleteAllAudioFiles(); + + // clear the file list + m_fileList->clear(); + slotPopulateFileList(); +} + +void +AudioManagerDialog::slotRemoveAllUnused() +{ + QString question = + i18n("This will unload all audio files that are not associated with any segments in this composition.\nThis action cannot be undone, and associations with these files will be lost.\nFiles will not be removed from your disk.\nAre you sure?"); + + int reply = KMessageBox::warningContinueCancel(this, question); + + if (reply != KMessageBox::Continue) + return ; + + std::set + <AudioFileId> audioFiles; + Composition &comp = m_doc->getComposition(); + + for (Composition::iterator it = comp.begin(); it != comp.end(); ++it) { + if ((*it)->getType() == Segment::Audio) + audioFiles.insert((*it)->getAudioFileId()); + } + + std::vector<AudioFileId> toDelete; + for (std::vector<AudioFile*>::const_iterator + aIt = m_doc->getAudioFileManager().begin(); + aIt != m_doc->getAudioFileManager().end(); ++aIt) { + if (audioFiles.find((*aIt)->getId()) == audioFiles.end()) + toDelete.push_back((*aIt)->getId()); + } + + // Delete the audio files from the AFM + // + for (std::vector<AudioFileId>::iterator dIt = toDelete.begin(); + dIt != toDelete.end(); ++dIt) { + + m_doc->notifyAudioFileRemoval(*dIt); + m_doc->getAudioFileManager().removeFile(*dIt); + emit deleteAudioFile(*dIt); + } + + // clear the file list + m_fileList->clear(); + slotPopulateFileList(); +} + +void +AudioManagerDialog::slotDeleteUnused() +{ + std::set + <AudioFileId> audioFiles; + Composition &comp = m_doc->getComposition(); + + for (Composition::iterator it = comp.begin(); it != comp.end(); ++it) { + if ((*it)->getType() == Segment::Audio) + audioFiles.insert((*it)->getAudioFileId()); + } + + std::vector<QString> toDelete; + std::map<QString, AudioFileId> nameMap; + + for (std::vector<AudioFile*>::const_iterator + aIt = m_doc->getAudioFileManager().begin(); + aIt != m_doc->getAudioFileManager().end(); ++aIt) { + if (audioFiles.find((*aIt)->getId()) == audioFiles.end()) { + toDelete.push_back(strtoqstr((*aIt)->getFilename())); + nameMap[strtoqstr((*aIt)->getFilename())] = (*aIt)->getId(); + } + } + + UnusedAudioSelectionDialog *dialog = new UnusedAudioSelectionDialog + (this, + i18n("The following audio files are not used in the current composition.\n\nPlease select the ones you wish to delete permanently from the hard disk.\n"), + toDelete); + + if (dialog->exec() == QDialog::Accepted) { + + std::vector<QString> names = dialog->getSelectedAudioFileNames(); + + if (names.size() > 0) { + + QString question = + i18n("<qt>About to delete 1 audio file permanently from the hard disk.<br>This action cannot be undone, and there will be no way to recover this file.<br>Are you sure?</qt>\n", "<qt>About to delete %n audio files permanently from the hard disk.<br>This action cannot be undone, and there will be no way to recover these files.<br>Are you sure?</qt>", names.size()); + + int reply = KMessageBox::warningContinueCancel(this, question); + + if (reply != KMessageBox::Continue) { + delete dialog; + return ; + } + + for (int i = 0; i < names.size(); ++i) { + std::cerr << i << ": " << names[i] << std::endl; + QFile file(names[i]); + if (!file.remove()) { + KMessageBox::error(this, i18n("File %1 could not be deleted.").arg(names[i])); + } else { + if (nameMap.find(names[i]) != nameMap.end()) { + m_doc->getAudioFileManager().removeFile(nameMap[names[i]]); + emit deleteAudioFile(nameMap[names[i]]); + } else { + std::cerr << "WARNING: Audio file name " << names[i] << " not in name map" << std::endl; + } + + QFile peakFile(QString("%1.pk").arg(names[i])); + peakFile.remove(); + } + } + } + } + + m_fileList->clear(); + slotPopulateFileList(); + + delete dialog; +} + +void +AudioManagerDialog::slotRename() +{ + AudioFile *audioFile = getCurrentSelection(); + + if (audioFile == 0) + return ; + + bool ok = false; + + QString newText = KLineEditDlg::getText( + i18n("Change Audio File label"), + i18n("Enter new label"), + QString(audioFile->getName().c_str()), + &ok, + this); + + if ( ok && !newText.isEmpty() ) + audioFile->setName(qstrtostr(newText)); + + slotPopulateFileList(); +} + +void +AudioManagerDialog::slotSelectionChanged(QListViewItem *item) +{ + AudioListItem *aItem = dynamic_cast<AudioListItem*>(item); + + // If we're on a segment then send a "select" signal + // and enable appropriate buttons. + // + if (aItem && aItem->getSegment()) { + SegmentSelection selection; + selection.insert(aItem->getSegment()); + emit segmentsSelected(selection); + } + + updateActionState(aItem != 0); +} + +void +AudioManagerDialog::setSelected(AudioFileId id, + const Segment *segment, + bool propagate) +{ + QListViewItem *it = m_fileList->firstChild(); + QListViewItem *chIt = 0; + AudioListItem *aItem; + + while (it) { + // If we're looking for a top level audio file + if (segment == 0) { + aItem = dynamic_cast<AudioListItem*>(it); + + if (aItem->getId() == id) { + selectFileListItemNoSignal(it); + return ; + } + } else // look for a child + { + if (it->childCount() > 0) + chIt = it->firstChild(); + + while (chIt) { + aItem = dynamic_cast<AudioListItem*>(chIt); + + if (aItem) { + if (aItem->getId() == id && aItem->getSegment() == segment) { + selectFileListItemNoSignal(chIt); + + // Only propagate to segmentcanvas if asked to + if (propagate) { + SegmentSelection selection; + selection.insert(aItem->getSegment()); + emit segmentsSelected(selection); + } + + return ; + } + } + chIt = chIt->nextSibling(); + } + } + + it = it->nextSibling(); + } + +} + +void +AudioManagerDialog::selectFileListItemNoSignal(QListViewItem* it) +{ + m_fileList->blockSignals(true); + + if (it) { + m_fileList->ensureItemVisible(it); + m_fileList->setSelected(it, true); + } else { + m_fileList->clearSelection(); + } + + m_fileList->blockSignals(false); +} + +MultiViewCommandHistory* +AudioManagerDialog::getCommandHistory() +{ + return m_doc->getCommandHistory(); +} + +void +AudioManagerDialog::slotCommandExecuted(KCommand*) +{ + slotPopulateFileList(); +} + +void +AudioManagerDialog::slotSegmentSelection( + const SegmentSelection &segments) +{ + const Segment *segment = 0; + + for (SegmentSelection::const_iterator it = segments.begin(); + it != segments.end(); ++it) { + if ((*it)->getType() == Segment::Audio) { + // Only get one audio segment + if (segment == 0) + segment = *it; + else + segment = 0; + } + + } + + if (segment) { + // We don't propagate this segment setting to the canvas + // as we probably got called from there. + // + setSelected(segment->getAudioFileId(), segment, false); + } else { + selectFileListItemNoSignal(0); + } + +} + +void +AudioManagerDialog::slotCancelPlayingAudioFile() +{ + emit cancelPlayingAudioFile(m_playingAudioFile); +} + +void +AudioManagerDialog::closePlayingDialog(AudioFileId id) +{ + //std::cout << "AudioManagerDialog::closePlayingDialog" << std::endl; + if (m_audioPlayingDialog && id == m_playingAudioFile) { + m_playTimer->stop(); + delete m_audioPlayingDialog; + m_audioPlayingDialog = 0; + } + +} + +bool +AudioManagerDialog::addFile(const KURL& kurl) +{ + AudioFileId id = 0; + + AudioFileManager &aFM = m_doc->getAudioFileManager(); + + if (!kurl.isLocalFile()) { + if (!RosegardenGUIApp::self()->testAudioPath("importing a remote audio file")) return false; + } else if (aFM.fileNeedsConversion(qstrtostr(kurl.path()), m_sampleRate)) { + if (!RosegardenGUIApp::self()->testAudioPath("importing an audio file that needs to be converted or resampled")) return false; + } + + ProgressDialog progressDlg(i18n("Adding audio file..."), + 100, + this); + + CurrentProgressDialog::set(&progressDlg); + progressDlg.progressBar()->hide(); + progressDlg.show(); + + // Connect the progress dialog + // + connect(&aFM, SIGNAL(setProgress(int)), + progressDlg.progressBar(), SLOT(setValue(int))); + connect(&aFM, SIGNAL(setOperationName(QString)), + &progressDlg, SLOT(slotSetOperationName(QString))); + connect(&progressDlg, SIGNAL(cancelClicked()), + &aFM, SLOT(slotStopImport())); + + try { + id = aFM.importURL(kurl, m_sampleRate); + } catch (AudioFileManager::BadAudioPathException e) { + CurrentProgressDialog::freeze(); + QString errorString = i18n("Failed to add audio file. ") + strtoqstr(e.getMessage()); + KMessageBox::sorry(this, errorString); + return false; + } catch (SoundFile::BadSoundFileException e) { + CurrentProgressDialog::freeze(); + QString errorString = i18n("Failed to add audio file. ") + strtoqstr(e.getMessage()); + KMessageBox::sorry(this, errorString); + return false; + } + + disconnect(&progressDlg, SIGNAL(cancelClicked()), + &aFM, SLOT(slotStopImport())); + connect(&progressDlg, SIGNAL(cancelClicked()), + &aFM, SLOT(slotStopPreview())); + progressDlg.progressBar()->show(); + progressDlg.slotSetOperationName(i18n("Generating audio preview...")); + + try { + aFM.generatePreview(id); + } catch (Exception e) { + CurrentProgressDialog::freeze(); + + QString message = strtoqstr(e.getMessage()) + "\n\n" + + i18n("Try copying this file to a directory where you have write permission and re-add it"); + KMessageBox::information(this, message); + } + + disconnect(&progressDlg, SIGNAL(cancelClicked()), + &aFM, SLOT(slotStopPreview())); + + slotPopulateFileList(); + + // tell the sequencer + emit addAudioFile(id); + + return true; +} + +void +AudioManagerDialog::slotDropped(QDropEvent *event, QListViewItem*) +{ + QStrList uri; + + // see if we can decode a URI.. if not, just ignore it + if (QUriDrag::decode(event, uri)) { + // okay, we have a URI.. process it + for (QString url = uri.first(); url; url = uri.next()) { + + RG_DEBUG << "AudioManagerDialog::dropEvent() : got " + << url << endl; + + addFile(KURL(url)); + } + + } +} + +void +AudioManagerDialog::closeEvent(QCloseEvent *e) +{ + RG_DEBUG << "AudioManagerDialog::closeEvent()\n"; + emit closing(); + KMainWindow::closeEvent(e); +} + +void +AudioManagerDialog::slotClose() +{ + emit closing(); + close(); + //KDockMainWindow::slotClose(); + // delete this; +} + +void +AudioManagerDialog::setAudioSubsystemStatus(bool ok) +{ + // We can do something more fancy in the future but for the moment + // this will suffice. + // + m_audiblePreview = ok; +} + +bool +AudioManagerDialog::addAudioFile(const QString &filePath) +{ + return addFile(QFileInfo(filePath).absFilePath()); +} + +bool +AudioManagerDialog::isSelectedTrackAudio() +{ + Composition &comp = m_doc->getComposition(); + Studio &studio = m_doc->getStudio(); + + TrackId currentTrackId = comp.getSelectedTrack(); + Track *track = comp.getTrackById(currentTrackId); + + if (track) { + InstrumentId ii = track->getInstrument(); + Instrument *instrument = studio.getInstrumentById(ii); + + if (instrument && + instrument->getType() == Instrument::Audio) + return true; + } + + return false; + +} + +void +AudioManagerDialog::slotDistributeOnMidiSegment() +{ + RG_DEBUG << "AudioManagerDialog::slotDistributeOnMidiSegment" << endl; + + //Composition &comp = m_doc->getComposition(); + + QList<RosegardenGUIView>& viewList = m_doc->getViewList(); + RosegardenGUIView *w = 0; + SegmentSelection selection; + + for (w = viewList.first(); w != 0; w = viewList.next()) { + selection = w->getSelection(); + } + + // Store the insert times in a local vector + // + std::vector<timeT> insertTimes; + + for (SegmentSelection::iterator i = selection.begin(); + i != selection.end(); ++i) { + // For MIDI (Internal) Segments only of course + // + if ((*i)->getType() == Segment::Internal) { + for (Segment::iterator it = (*i)->begin(); it != (*i)->end(); ++it) { + if ((*it)->isa(Note::EventType)) + insertTimes.push_back((*it)->getAbsoluteTime()); + } + } + } + + for (unsigned int i = 0; i < insertTimes.size(); ++i) { + RG_DEBUG << "AudioManagerDialog::slotDistributeOnMidiSegment - " + << "insert audio segment at " << insertTimes[i] + << endl; + } +} + +} +#include "AudioManagerDialog.moc" diff --git a/src/gui/dialogs/AudioManagerDialog.h b/src/gui/dialogs/AudioManagerDialog.h new file mode 100644 index 0000000..728b700 --- /dev/null +++ b/src/gui/dialogs/AudioManagerDialog.h @@ -0,0 +1,206 @@ + +/* -*- 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_AUDIOMANAGERDIALOG_H_ +#define _RG_AUDIOMANAGERDIALOG_H_ + +#include "sound/AudioFile.h" +#include <kmainwindow.h> +#include "document/ConfigGroups.h" + + +class QWidget; +class QTimer; +class QString; +class QListViewItem; +class QLabel; +class QDropEvent; +class QCloseEvent; +class QAccel; +class KURL; +class KListView; +class KCommand; + + +namespace Rosegarden +{ + +class SegmentSelection; +class Segment; +class RosegardenGUIDoc; +class RealTime; +class MultiViewCommandHistory; +class AudioPlayingDialog; +class AudioFile; + + +class AudioManagerDialog : public KMainWindow +{ + Q_OBJECT + +public: + AudioManagerDialog(QWidget *parent, + RosegardenGUIDoc *doc); + ~AudioManagerDialog(); + + // Populate the file list from the AudioFileManager + // + + // Return a pointer to the currently selected AudioFile - + // returns 0 if nothing is selected + // + AudioFile* getCurrentSelection(); + + // Scroll and expand to show this selected item + // + void setSelected(AudioFileId id, + const Segment *segment, + bool propagate); // if true then we tell the segmentcanvas + + MultiViewCommandHistory *getCommandHistory(); + + // Pop down playing dialog if it's currently up + // + void closePlayingDialog(AudioFileId id); + + // Can we playback audio currently? + // + void setAudioSubsystemStatus(bool ok); + + // Return the accelerator object + // + QAccel* getAccelerators() { return m_accelerators; } + + // Add a new file to the audio file manager + // + bool addAudioFile(const QString &filePath); + + +public slots: + void slotAdd(); + void slotPlayPreview(); + void slotRename(); + void slotInsert(); + void slotRemove(); + void slotRemoveAll(); + void slotRemoveAllUnused(); + void slotDeleteUnused(); + void slotExportAudio(); + + // get selection + void slotSelectionChanged(QListViewItem *); + + // Repopulate + // + void slotPopulateFileList(); + + // Commands + // + void slotCommandExecuted(KCommand *); + + /** + * Accept a list of Segments and highlight accordingly + * Used to reflect a selection on the main view + * (when the user selects an audio track, the corresponding item + * in the audio manager should be selected in turn) + * + * We check for embedded audio segments and if we find exactly one + * we highlight it. If we don't we unselect everything. + * + */ + void slotSegmentSelection(const SegmentSelection &); + + /** + * Cancel the currently playing audio file + */ + void slotCancelPlayingAudioFile(); + + void slotClose(); + + /** + * Turn a MIDI segment into a set of audio segments triggered + * by the MIDI Note Ons + */ + void slotDistributeOnMidiSegment(); + +signals: + + // Control signals so we can tell the sequencer about our changes + // or actions. + // + void addAudioFile(AudioFileId); + void deleteAudioFile(AudioFileId); + void playAudioFile(AudioFileId, + const RealTime &, + const RealTime &); + void cancelPlayingAudioFile(AudioFileId); + void deleteAllAudioFiles(); + + // We've selected a segment here, make the canvas select it too + // + void segmentsSelected(const SegmentSelection&); + void deleteSegments(const SegmentSelection&); + void insertAudioSegment(AudioFileId, + const RealTime &, + const RealTime &); + + void closing(); +protected slots: + void slotDropped(QDropEvent*, QListViewItem*); + void slotCancelPlayingAudio(); + +protected: + bool addFile(const KURL& kurl); + bool isSelectedTrackAudio(); + void selectFileListItemNoSignal(QListViewItem*); + void updateActionState(bool haveSelection); + + virtual void closeEvent(QCloseEvent *); + + //--------------- Data members --------------------------------- + + KListView *m_fileList; + QLabel *m_wrongSampleRates; + RosegardenGUIDoc *m_doc; + + QAccel *m_accelerators; + + AudioFileId m_playingAudioFile; + AudioPlayingDialog *m_audioPlayingDialog; + QTimer *m_playTimer; + + static const char* const m_listViewLayoutName; + static const int m_maxPreviewWidth; + static const int m_previewHeight; + + bool m_audiblePreview; + int m_sampleRate; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/AudioPlayingDialog.cpp b/src/gui/dialogs/AudioPlayingDialog.cpp new file mode 100644 index 0000000..0915ef2 --- /dev/null +++ b/src/gui/dialogs/AudioPlayingDialog.cpp @@ -0,0 +1,55 @@ +/* -*- 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 "AudioPlayingDialog.h" + +#include <klocale.h> +#include <kdialogbase.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qstring.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +AudioPlayingDialog::AudioPlayingDialog(QWidget *parent, + const QString &name): + KDialogBase(parent, 0, true, + i18n("Playing audio file"), + Cancel) +{ + QHBox *w = makeHBoxMainWidget(); + QLabel *label = new + QLabel(i18n("Playing audio file \"%1\"").arg(name), w); + + label->setMinimumHeight(80); + + +} + +} +#include "AudioPlayingDialog.moc" diff --git a/src/gui/dialogs/AudioPlayingDialog.h b/src/gui/dialogs/AudioPlayingDialog.h new file mode 100644 index 0000000..880d0bd --- /dev/null +++ b/src/gui/dialogs/AudioPlayingDialog.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_AUDIOPLAYINGDIALOG_H_ +#define _RG_AUDIOPLAYINGDIALOG_H_ + +#include <kdialogbase.h> +#include "gui/application/RosegardenDCOP.h" + + +class QWidget; +class QString; + + +namespace Rosegarden +{ + + + +class AudioPlayingDialog : public KDialogBase +{ + Q_OBJECT + +public: + AudioPlayingDialog(QWidget *parent, const QString &label); + +signals: + +}; + + +} + +#endif diff --git a/src/gui/dialogs/AudioPluginDialog.cpp b/src/gui/dialogs/AudioPluginDialog.cpp new file mode 100644 index 0000000..7f54f71 --- /dev/null +++ b/src/gui/dialogs/AudioPluginDialog.cpp @@ -0,0 +1,916 @@ +/* -*- 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 "AudioPluginDialog.h" +#include <qlayout.h> + +#include <klocale.h> +#include "misc/Debug.h" +#include "misc/Strings.h" +#include "base/AudioPluginInstance.h" +#include "base/Instrument.h" +#include "base/MidiProgram.h" +#include "gui/studio/AudioPluginClipboard.h" +#include "gui/studio/AudioPlugin.h" +#include "gui/studio/AudioPluginManager.h" +#include "gui/studio/AudioPluginOSCGUIManager.h" +#include "gui/studio/StudioControl.h" +#include "gui/widgets/PluginControl.h" +#include "sound/MappedStudio.h" +#include "sound/PluginIdentifier.h" +#include <kcombobox.h> +#include <kdialogbase.h> +#include <qaccel.h> +#include <qcheckbox.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qsizepolicy.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qtooltip.h> +#include <qvbox.h> +#include <qwidget.h> +#include <set> + +namespace Rosegarden +{ + +AudioPluginDialog::AudioPluginDialog(QWidget *parent, + AudioPluginManager *aPM, +#ifdef HAVE_LIBLO + AudioPluginOSCGUIManager *aGM, +#endif + PluginContainer *pluginContainer, + int index): + KDialogBase(parent, "", false, i18n("Audio Plugin"), +#ifdef HAVE_LIBLO + Close | Details | Help), +#else + Close | Help), +#endif + m_pluginManager(aPM), +#ifdef HAVE_LIBLO + m_pluginGUIManager(aGM), +#endif + m_pluginContainer(pluginContainer), + m_containerId(pluginContainer->getId()), + m_programLabel(0), + m_index(index), + m_generating(true), + m_guiShown(false) +{ + setHelp("studio-plugins"); + + setSizePolicy(QSizePolicy(QSizePolicy::Preferred, + QSizePolicy::Fixed)); + +#ifdef HAVE_LIBLO + + setButtonText(Details, i18n("Editor")); +#endif + + QVBox *vbox = makeVBoxMainWidget(); + + QGroupBox *pluginSelectionBox = new QGroupBox + (1, Horizontal, i18n("Plugin"), vbox); + + makePluginParamsBox(vbox, 0, 10); + + m_pluginCategoryBox = new QHBox(pluginSelectionBox); + new QLabel(i18n("Category:"), m_pluginCategoryBox); + m_pluginCategoryList = new KComboBox(m_pluginCategoryBox); + m_pluginCategoryList->setSizeLimit(20); + + QHBox *hbox = new QHBox(pluginSelectionBox); + m_pluginLabel = new QLabel(i18n("Plugin:"), hbox); + m_pluginList = new KComboBox(hbox); + m_pluginList->setSizeLimit(20); + QToolTip::add + (m_pluginList, i18n("Select a plugin from this list.")); + + QHBox *h = new QHBox(pluginSelectionBox); + +// top line + m_bypass = new QCheckBox(i18n("Bypass"), h); + QToolTip::add + (m_bypass, i18n("Bypass this plugin.")); + + connect(m_bypass, SIGNAL(toggled(bool)), + this, SLOT(slotBypassChanged(bool))); + + + m_insOuts = new QLabel(i18n("<ports>"), h); + m_insOuts->setAlignment(AlignRight); + QToolTip::add + (m_insOuts, i18n("Input and output port counts.")); + + m_pluginId = new QLabel(i18n("<id>"), h); + m_pluginId->setAlignment(AlignRight); + QToolTip::add + (m_pluginId, i18n("Unique ID of plugin.")); + + connect(m_pluginList, SIGNAL(activated(int)), + this, SLOT(slotPluginSelected(int))); + + connect(m_pluginCategoryList, SIGNAL(activated(int)), + this, SLOT(slotCategorySelected(int))); + +// new line + h = new QHBox(pluginSelectionBox); + m_copyButton = new QPushButton(i18n("Copy"), h); + connect(m_copyButton, SIGNAL(clicked()), + this, SLOT(slotCopy())); + QToolTip::add + (m_copyButton, i18n("Copy plugin parameters")); + + m_pasteButton = new QPushButton(i18n("Paste"), h); + connect(m_pasteButton, SIGNAL(clicked()), + this, SLOT(slotPaste())); + QToolTip::add + (m_pasteButton, i18n("Paste plugin parameters")); + + m_defaultButton = new QPushButton(i18n("Default"), h); + connect(m_defaultButton, SIGNAL(clicked()), + this, SLOT(slotDefault())); + QToolTip::add + (m_defaultButton, i18n("Set to defaults")); + + populatePluginCategoryList(); + populatePluginList(); + + m_generating = false; + + m_accelerators = new QAccel(this); +} + +#ifdef HAVE_LIBLO + +void +AudioPluginDialog::slotDetails() +{ + slotShowGUI(); +} +#endif + +void +AudioPluginDialog::slotShowGUI() +{ + emit showPluginGUI(m_containerId, m_index); + m_guiShown = true; + + //!!! need to get notification of when a plugin gui exits from the + //gui manager +} + +void +AudioPluginDialog::populatePluginCategoryList() +{ + AudioPluginInstance *inst = m_pluginContainer->getPlugin(m_index); + std::set + <QString> categories; + QString currentCategory; + + for (PluginIterator i = m_pluginManager->begin(); + i != m_pluginManager->end(); ++i) { + + if (( isSynth() && (*i)->isSynth()) || + (!isSynth() && (*i)->isEffect())) { + + if ((*i)->getCategory() != "") { + categories.insert((*i)->getCategory()); + } + + if (inst && inst->isAssigned() && + ((*i)->getIdentifier() == inst->getIdentifier().c_str())) { + currentCategory = (*i)->getCategory(); + } + } + } + + if (inst) { + RG_DEBUG << "AudioPluginDialog::populatePluginCategoryList: inst id " << inst->getIdentifier() << ", cat " << currentCategory << endl; + } + + if (categories.empty()) { + m_pluginCategoryBox->hide(); + m_pluginLabel->hide(); + } + + m_pluginCategoryList->clear(); + m_pluginCategoryList->insertItem(i18n("(any)")); + m_pluginCategoryList->insertItem(i18n("(unclassified)")); + m_pluginCategoryList->setCurrentItem(0); + + for (std::set + <QString>::iterator i = categories.begin(); + i != categories.end(); ++i) { + + m_pluginCategoryList->insertItem(*i); + + if (*i == currentCategory) { + m_pluginCategoryList->setCurrentItem(m_pluginCategoryList->count() - 1); + } + } +} + +void +AudioPluginDialog::populatePluginList() +{ + m_pluginList->clear(); + m_pluginsInList.clear(); + + m_pluginList->insertItem(i18n("(none)")); + m_pluginsInList.push_back(0); + + QString category; + bool needCategory = false; + + if (m_pluginCategoryList->currentItem() > 0) { + needCategory = true; + if (m_pluginCategoryList->currentItem() == 1) { + category = ""; + } else { + category = m_pluginCategoryList->currentText(); + } + } + + // Check for plugin and setup as required + AudioPluginInstance *inst = m_pluginContainer->getPlugin(m_index); + if (inst) + m_bypass->setChecked(inst->isBypassed()); + + // Use this temporary map to ensure that the plugins are sorted + // by name when they go into the combobox + typedef std::pair<int, AudioPlugin *> PluginPair; + typedef std::map<QString, PluginPair> PluginMap; + PluginMap plugins; + int count = 0; + + for (PluginIterator i = m_pluginManager->begin(); + i != m_pluginManager->end(); ++i) { + + ++count; + + if (( isSynth() && (*i)->isSynth()) || + (!isSynth() && (*i)->isEffect())) { + + if (needCategory) { + QString cat = ""; + if ((*i)->getCategory()) + cat = (*i)->getCategory(); + if (cat != category) + continue; + } + + QString name = (*i)->getName(); + bool store = true; + + if (plugins.find(name) != plugins.end()) { + // We already have a plugin of this name. If it's a + // LADSPA plugin, replace it (this one might be + // something better); otherwise leave it alone. + QString id = plugins[name].second->getIdentifier(); + QString type, soname, label; + PluginIdentifier::parseIdentifier(id, type, soname, label); + if (type != "ladspa") { + store = false; + } + } + + if (store) { + plugins[(*i)->getName()] = PluginPair(count, *i); + } + } + } + + const char *currentId = 0; + if (inst && inst->isAssigned()) + currentId = inst->getIdentifier().c_str(); + + for (PluginMap::iterator i = plugins.begin(); i != plugins.end(); ++i) { + + QString name = i->first; + if (name.endsWith(" VST")) + name = name.left(name.length() - 4); + + m_pluginList->insertItem(name); + m_pluginsInList.push_back(i->second.first); + + if (currentId && currentId == i->second.second->getIdentifier()) { + m_pluginList->setCurrentItem(m_pluginList->count() - 1); + } + } + + slotPluginSelected(m_pluginList->currentItem()); +} + +void +AudioPluginDialog::makePluginParamsBox(QWidget *parent, int portCount, + int tooManyPorts) +{ + m_pluginParamsBox = new QFrame(parent); + + int columns = 2; + if (portCount > tooManyPorts) { + columns = 2; + } else if (portCount > 24) { + if (portCount > 60) { + columns = (portCount - 1) / 16 + 1; + } else { + columns = (portCount - 1) / 12 + 1; + } + } + + int perColumn = 4; + if (portCount > 48) { // no bounds will be shown + perColumn = 2; + } + + m_gridLayout = new QGridLayout(m_pluginParamsBox, + 1, // rows (will expand) + columns * perColumn, + 5); // margin + + m_gridLayout->setColStretch(3, 2); + m_gridLayout->setColStretch(7, 2); +} + +void +AudioPluginDialog::slotCategorySelected(int) +{ + populatePluginList(); +} + +void +AudioPluginDialog::slotPluginSelected(int i) +{ + bool guiWasShown = m_guiShown; + + if (m_guiShown) { + emit stopPluginGUI(m_containerId, m_index); + m_guiShown = false; + } + + int number = m_pluginsInList[i]; + + RG_DEBUG << "AudioPluginDialog::::slotPluginSelected - " + << "setting up plugin from position " << number << " at menu item " << i << endl; + + QString caption = + strtoqstr(m_pluginContainer->getName()) + + QString(" [ %1 ] - ").arg(m_index + 1); + + if (number == 0) { + setCaption(caption + i18n("<no plugin>")); + m_insOuts->setText(i18n("<ports>")); + m_pluginId->setText(i18n("<id>")); + + QToolTip::hide(); + QToolTip::remove + (m_pluginList); + + QToolTip::add + (m_pluginList, i18n("Select a plugin from this list.")); + } + + AudioPlugin *plugin = m_pluginManager->getPlugin(number - 1); + + // Destroy old param widgets + // + QWidget* parent = dynamic_cast<QWidget*>(m_pluginParamsBox->parent()); + + delete m_pluginParamsBox; + m_pluginWidgets.clear(); // The widgets are deleted with the parameter box + m_programCombo = 0; + + int portCount = 0; + if (plugin) { + for (AudioPlugin::PortIterator it = plugin->begin(); it != plugin->end(); ++it) { + if (((*it)->getType() & PluginPort::Control) && + ((*it)->getType() & PluginPort::Input)) + ++portCount; + } + } + + int tooManyPorts = 96; + makePluginParamsBox(parent, portCount, tooManyPorts); + bool showBounds = (portCount <= 48); + + if (portCount > tooManyPorts) { + + m_gridLayout->addMultiCellWidget( + new QLabel(i18n("This plugin has too many controls to edit here."), + m_pluginParamsBox), + 1, 1, 0, m_gridLayout->numCols() - 1, Qt::AlignCenter); + } + + AudioPluginInstance *inst = m_pluginContainer->getPlugin(m_index); + if (!inst) + return ; + + if (plugin) { + setCaption(caption + plugin->getName()); + m_pluginId->setText(i18n("Id: %1").arg(plugin->getUniqueId())); + + QString pluginInfo = plugin->getAuthor() + QString("\n") + + plugin->getCopyright(); + + QToolTip::hide(); + QToolTip::remove + (m_pluginList); + QToolTip::add + (m_pluginList, pluginInfo); + + std::string identifier = plugin->getIdentifier().data(); + + // Only clear ports &c if this method is accessed by user + // action (after the constructor) + // + if (m_generating == false) { + inst->clearPorts(); + if (inst->getIdentifier() != identifier) { + inst->clearConfiguration(); + } + } + + inst->setIdentifier(identifier); + + AudioPlugin::PortIterator it = plugin->begin(); + int count = 0; + int ins = 0, outs = 0; + + for (; it != plugin->end(); ++it) { + if (((*it)->getType() & PluginPort::Control) && + ((*it)->getType() & PluginPort::Input)) { + // Check for port existence and create with default value + // if it doesn't exist. Modification occurs through the + // slotPluginPortChanged signal. + // + if (inst->getPort(count) == 0) { + inst->addPort(count, (float)(*it)->getDefaultValue()); +// std::cerr << "Plugin port name " << (*it)->getName() << ", default: " << (*it)->getDefaultValue() << std::endl; + } + + } else if ((*it)->getType() & PluginPort::Audio) { + if ((*it)->getType() & PluginPort::Input) + ++ins; + else if ((*it)->getType() & PluginPort::Output) + ++outs; + } + + ++count; + } + + if (ins == 1 && outs == 1) + m_insOuts->setText(i18n("mono")); + else if (ins == 2 && outs == 2) + m_insOuts->setText(i18n("stereo")); + else + m_insOuts->setText(i18n("%1 in, %2 out").arg(ins).arg(outs)); + + QString shortName(plugin->getName()); + int parenIdx = shortName.find(" ("); + if (parenIdx > 0) { + shortName = shortName.left(parenIdx); + if (shortName == "Null") + shortName = "Plugin"; + } + } + + adjustSize(); + setFixedSize(minimumSizeHint()); + + // tell the sequencer + emit pluginSelected(m_containerId, m_index, number - 1); + + if (plugin) { + + int current = -1; + QStringList programs = getProgramsForInstance(inst, current); + + if (programs.count() > 0) { + + m_programLabel = new QLabel(i18n("Program: "), m_pluginParamsBox); + + m_programCombo = new KComboBox(m_pluginParamsBox); + m_programCombo->setSizeLimit(20); + m_programCombo->insertItem(i18n("<none selected>")); + m_gridLayout->addMultiCellWidget(m_programLabel, + 0, 0, 0, 0, Qt::AlignRight); + m_gridLayout->addMultiCellWidget(m_programCombo, + 0, 0, 1, m_gridLayout->numCols() - 1, + Qt::AlignLeft); + connect(m_programCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotPluginProgramChanged(const QString &))); + + m_programCombo->clear(); + m_programCombo->insertItem(i18n("<none selected>")); + m_programCombo->insertStringList(programs); + m_programCombo->setCurrentItem(current + 1); + m_programCombo->adjustSize(); + + m_programLabel->show(); + m_programCombo->show(); + } + + AudioPlugin::PortIterator it = plugin->begin(); + int count = 0; + + for (; it != plugin->end(); ++it) { + if (((*it)->getType() & PluginPort::Control) && + ((*it)->getType() & PluginPort::Input)) { + PluginControl *control = + new PluginControl(m_pluginParamsBox, + m_gridLayout, + PluginControl::Rotary, + *it, + m_pluginManager, + count, + inst->getPort(count)->value, + showBounds, + portCount > tooManyPorts); + + connect(control, SIGNAL(valueChanged(float)), + this, SLOT(slotPluginPortChanged(float))); + + m_pluginWidgets.push_back(control); + } + + ++count; + } + + m_pluginParamsBox->show(); + } + + if (guiWasShown) { + emit showPluginGUI(m_containerId, m_index); + m_guiShown = true; + } + +#ifdef HAVE_LIBLO + bool gui = m_pluginGUIManager->hasGUI(m_containerId, m_index); + actionButton(Details)->setEnabled(gui); +#endif + +} + +QStringList +AudioPluginDialog::getProgramsForInstance(AudioPluginInstance *inst, int ¤t) +{ + QStringList list; + int mappedId = inst->getMappedId(); + QString currentProgram = strtoqstr(inst->getProgram()); + + MappedObjectPropertyList propertyList = StudioControl::getStudioObjectProperty + (mappedId, MappedPluginSlot::Programs); + + current = -1; + + for (MappedObjectPropertyList::iterator i = propertyList.begin(); + i != propertyList.end(); ++i) { + if (*i == currentProgram) + current = list.count(); + list.append(*i); + } + + return list; +} + +void +AudioPluginDialog::slotPluginPortChanged(float value) +{ + const QObject* object = sender(); + + const PluginControl* control = dynamic_cast<const PluginControl*>(object); + + if (!control) + return ; + + // store the new value + AudioPluginInstance *inst = m_pluginContainer->getPlugin(m_index); + inst->getPort(control->getIndex())->setValue(value); + + emit pluginPortChanged(m_containerId, m_index, control->getIndex()); +} + +void +AudioPluginDialog::slotPluginProgramChanged(const QString &value) +{ + // store the new value + AudioPluginInstance *inst = m_pluginContainer->getPlugin(m_index); + + if (m_programCombo && value == m_programCombo->text(0)) { // "<none set>" + inst->setProgram(""); + } else { + inst->setProgram(qstrtostr(value)); + emit pluginProgramChanged(m_containerId, m_index); + } +} + +void +AudioPluginDialog::updatePlugin(int number) +{ + for (unsigned int i = 0; i < m_pluginsInList.size(); ++i) { + if (m_pluginsInList[i] == number + 1) { + blockSignals(true); + m_pluginList->setCurrentItem(i); + blockSignals(false); + return ; + } + } +} + +void +AudioPluginDialog::updatePluginPortControl(int port) +{ + AudioPluginInstance *inst = m_pluginContainer->getPlugin(m_index); + if (inst) { + PluginPortInstance *pti = inst->getPort(port); + if (pti) { + for (std::vector<PluginControl *>::iterator i = m_pluginWidgets.begin(); + i != m_pluginWidgets.end(); ++i) { + if ((*i)->getIndex() == port) { + (*i)->setValue(pti->value, false); // don't emit + return ; + } + } + } + } +} + +void +AudioPluginDialog::updatePluginProgramControl() +{ + AudioPluginInstance *inst = m_pluginContainer->getPlugin(m_index); + if (inst) { + std::string program = inst->getProgram(); + if (m_programCombo) { + m_programCombo->blockSignals(true); + m_programCombo->setCurrentText(strtoqstr(program)); + m_programCombo->blockSignals(false); + } + for (std::vector<PluginControl *>::iterator i = m_pluginWidgets.begin(); + i != m_pluginWidgets.end(); ++i) { + PluginPortInstance *pti = inst->getPort((*i)->getIndex()); + if (pti) { + (*i)->setValue(pti->value, false); // don't emit + } + } + } +} + +void +AudioPluginDialog::updatePluginProgramList() +{ + if (!m_programLabel) + return ; + + AudioPluginInstance *inst = m_pluginContainer->getPlugin(m_index); + if (!inst) + return ; + + if (!m_programCombo) { + + int current = -1; + QStringList programs = getProgramsForInstance(inst, current); + + if (programs.count() > 0) { + + m_programLabel = new QLabel(i18n("Program: "), m_pluginParamsBox); + + m_programCombo = new KComboBox(m_pluginParamsBox); + m_programCombo->setSizeLimit(20); + m_programCombo->insertItem(i18n("<none selected>")); + m_gridLayout->addMultiCellWidget(m_programLabel, + 0, 0, 0, 0, Qt::AlignRight); + m_gridLayout->addMultiCellWidget(m_programCombo, + 0, 0, 1, m_gridLayout->numCols() - 1, + Qt::AlignLeft); + + m_programCombo->clear(); + m_programCombo->insertItem(i18n("<none selected>")); + m_programCombo->insertStringList(programs); + m_programCombo->setCurrentItem(current + 1); + m_programCombo->adjustSize(); + + m_programLabel->show(); + m_programCombo->show(); + + m_programCombo->blockSignals(true); + connect(m_programCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotPluginProgramChanged(const QString &))); + + } else { + return ; + } + } else { + } + + while (m_programCombo->count() > 0) { + m_programCombo->removeItem(0); + } + + int current = -1; + QStringList programs = getProgramsForInstance(inst, current); + + if (programs.count() > 0) { + m_programCombo->show(); + m_programLabel->show(); + m_programCombo->clear(); + m_programCombo->insertItem(i18n("<none selected>")); + m_programCombo->insertStringList(programs); + m_programCombo->setCurrentItem(current + 1); + } else { + m_programLabel->hide(); + m_programCombo->hide(); + } + + m_programCombo->blockSignals(false); +} + +void +AudioPluginDialog::slotBypassChanged(bool bp) +{ + AudioPluginInstance *inst = m_pluginContainer->getPlugin(m_index); + + if (inst) + inst->setBypass(bp); + + emit bypassed(m_containerId, m_index, bp); +} + +void +AudioPluginDialog::windowActivationChange(bool oldState) +{ + if (isActiveWindow()) { + emit windowActivated(); + } +} + +void +AudioPluginDialog::closeEvent(QCloseEvent *e) +{ + e->accept(); + emit destroyed(m_containerId, m_index); +} + +void +AudioPluginDialog::slotClose() +{ + emit destroyed(m_containerId, m_index); + reject(); +} + +void +AudioPluginDialog::slotCopy() +{ + int item = m_pluginList->currentItem(); + int number = m_pluginsInList[item] - 1; + + if (number >= 0) { + AudioPluginClipboard *clipboard = + m_pluginManager->getPluginClipboard(); + + clipboard->m_pluginNumber = number; + + AudioPluginInstance *inst = m_pluginContainer->getPlugin(m_index); + if (inst) { + clipboard->m_configuration = inst->getConfiguration(); + } else { + clipboard->m_configuration.clear(); + } + + std::cout << "AudioPluginDialog::slotCopy - plugin number = " << number + << std::endl; + + if (m_programCombo && m_programCombo->currentItem() > 0) { + clipboard->m_program = qstrtostr(m_programCombo->currentText()); + } else { + clipboard->m_program = ""; + } + + clipboard->m_controlValues.clear(); + std::vector<PluginControl*>::iterator it; + for (it = m_pluginWidgets.begin(); it != m_pluginWidgets.end(); ++it) { + std::cout << "AudioPluginDialog::slotCopy - " + << "value = " << (*it)->getValue() << std::endl; + + clipboard->m_controlValues.push_back((*it)->getValue()); + } + } +} + +void +AudioPluginDialog::slotPaste() +{ + AudioPluginClipboard *clipboard = m_pluginManager->getPluginClipboard(); + + std::cout << "AudioPluginDialog::slotPaste - paste plugin id " + << clipboard->m_pluginNumber << std::endl; + + if (clipboard->m_pluginNumber != -1) { + int count = 0; + for (std::vector<int>::iterator it = m_pluginsInList.begin(); + it != m_pluginsInList.end(); ++it) { + if ((*it) == clipboard->m_pluginNumber + 1) + break; + count++; + } + + if (count >= int(m_pluginsInList.size())) + return ; + + // now select the plugin + // + m_pluginList->setCurrentItem(count); + slotPluginSelected(count); + + // set configuration data + // + for (std::map<std::string, std::string>::const_iterator i = + clipboard->m_configuration.begin(); + i != clipboard->m_configuration.end(); ++i) { + emit changePluginConfiguration(m_containerId, + m_index, + false, + strtoqstr(i->first), + strtoqstr(i->second)); + } + + // and set the program + // + if (m_programCombo && clipboard->m_program != "") { + m_programCombo->setCurrentText(strtoqstr(clipboard->m_program)); + slotPluginProgramChanged(strtoqstr(clipboard->m_program)); + } + + // and ports + // + count = 0; + + for (std::vector<PluginControl *>::iterator i = m_pluginWidgets.begin(); + i != m_pluginWidgets.end(); ++i) { + + if (count < clipboard->m_controlValues.size()) { + (*i)->setValue(clipboard->m_controlValues[count], true); + } + ++count; + } + } +} + +void +AudioPluginDialog::slotDefault() +{ + AudioPluginInstance *inst = m_pluginContainer->getPlugin(m_index); + if (!inst) + return ; + + int i = m_pluginList->currentItem(); + int n = m_pluginsInList[i]; + if (n == 0) + return ; + + AudioPlugin *plugin = m_pluginManager->getPlugin(n - 1); + if (!plugin) + return ; + + for (std::vector<PluginControl *>::iterator i = m_pluginWidgets.begin(); + i != m_pluginWidgets.end(); ++i) { + + for (AudioPlugin::PortIterator pi = plugin->begin(); pi != plugin->end(); ++pi) { + if ((*pi)->getNumber() == (*i)->getIndex()) { + (*i)->setValue((*pi)->getDefaultValue(), true); // and emit + break; + } + } + } +} + +} +#include "AudioPluginDialog.moc" diff --git a/src/gui/dialogs/AudioPluginDialog.h b/src/gui/dialogs/AudioPluginDialog.h new file mode 100644 index 0000000..bc8a38b --- /dev/null +++ b/src/gui/dialogs/AudioPluginDialog.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_AUDIOPLUGINDIALOG_H_ +#define _RG_AUDIOPLUGINDIALOG_H_ + +#include "base/Instrument.h" +#include "base/MidiProgram.h" +#include <kdialogbase.h> +#include <qstring.h> +#include <qstringlist.h> +#include <vector> + + +class QWidget; +class QPushButton; +class QLabel; +class QGridLayout; +class QFrame; +class QCloseEvent; +class QCheckBox; +class QAccel; +class KComboBox; + + +namespace Rosegarden +{ + +class PluginControl; +class PluginContainer; +class AudioPluginOSCGUIManager; +class AudioPluginManager; +class AudioPluginInstance; + + +class AudioPluginDialog : public KDialogBase +{ + Q_OBJECT + +public: + AudioPluginDialog(QWidget *parent, + AudioPluginManager *aPM, +#ifdef HAVE_LIBLO + AudioPluginOSCGUIManager *aGM, +#endif + PluginContainer *instrument, + int index); + + PluginContainer* getPluginContainer() const { return m_pluginContainer; } + + QAccel* getAccelerators() { return m_accelerators; } + + bool isSynth() { return m_index == int(Instrument::SYNTH_PLUGIN_POSITION); } + + void updatePlugin(int number); + void updatePluginPortControl(int port); + void updatePluginProgramControl(); + void updatePluginProgramList(); + void guiExited() { m_guiShown = false; } + +public slots: + void slotCategorySelected(int); + void slotPluginSelected(int index); + void slotPluginPortChanged(float value); + void slotPluginProgramChanged(const QString &value); + void slotBypassChanged(bool); + void slotCopy(); + void slotPaste(); + void slotDefault(); + void slotShowGUI(); + +#ifdef HAVE_LIBLO + virtual void slotDetails(); +#endif + +signals: + void pluginSelected(InstrumentId, int pluginIndex, int plugin); + void pluginPortChanged(InstrumentId, int pluginIndex, int portIndex); + void pluginProgramChanged(InstrumentId, int pluginIndex); + void changePluginConfiguration(InstrumentId, int pluginIndex, + bool global, QString key, QString value); + void showPluginGUI(InstrumentId, int pluginIndex); + void stopPluginGUI(InstrumentId, int pluginIndex); + + // is the plugin being bypassed + void bypassed(InstrumentId, int pluginIndex, bool bp); + void destroyed(InstrumentId, int index); + + void windowActivated(); + +protected slots: + virtual void slotClose(); + +protected: + virtual void closeEvent(QCloseEvent *e); + virtual void windowActivationChange(bool); + + void makePluginParamsBox(QWidget*, int portCount, int tooManyPorts); + QStringList getProgramsForInstance(AudioPluginInstance *inst, int ¤t); + + //--------------- Data members --------------------------------- + + AudioPluginManager *m_pluginManager; +#ifdef HAVE_LIBLO + AudioPluginOSCGUIManager *m_pluginGUIManager; +#endif + PluginContainer *m_pluginContainer; + InstrumentId m_containerId; + + QFrame *m_pluginParamsBox; + QWidget *m_pluginCategoryBox; + KComboBox *m_pluginCategoryList; + QLabel *m_pluginLabel; + KComboBox *m_pluginList; + std::vector<int> m_pluginsInList; + QLabel *m_insOuts; + QLabel *m_pluginId; + QCheckBox *m_bypass; + QPushButton *m_copyButton; + QPushButton *m_pasteButton; + QPushButton *m_defaultButton; + QPushButton *m_guiButton; + + QLabel *m_programLabel; + KComboBox *m_programCombo; + std::vector<PluginControl*> m_pluginWidgets; + QGridLayout *m_gridLayout; + + int m_index; + + bool m_generating; + bool m_guiShown; + + QAccel *m_accelerators; + + void populatePluginCategoryList(); + void populatePluginList(); +}; + + +} // end of namespace + + + +#endif diff --git a/src/gui/dialogs/AudioSplitDialog.cpp b/src/gui/dialogs/AudioSplitDialog.cpp new file mode 100644 index 0000000..42290b3 --- /dev/null +++ b/src/gui/dialogs/AudioSplitDialog.cpp @@ -0,0 +1,339 @@ +/* -*- 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 "AudioSplitDialog.h" +#include <kapplication.h> + +#include <klocale.h> +#include "misc/Debug.h" +#include "misc/Strings.h" +#include "base/Exception.h" +#include "base/RealTime.h" +#include "base/Segment.h" +#include "document/RosegardenGUIDoc.h" +#include "gui/application/RosegardenApplication.h" +#include "sound/AudioFileManager.h" +#include <kdialogbase.h> +#include <qcanvas.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qpalette.h> +#include <qscrollview.h> +#include <qspinbox.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +AudioSplitDialog::AudioSplitDialog(QWidget *parent, + Segment *segment, + RosegardenGUIDoc *doc): + KDialogBase(parent, 0, true, + i18n("Autosplit Audio Segment"), Ok | Cancel), + m_doc(doc), + m_segment(segment), + m_canvasWidth(500), + m_canvasHeight(200), + m_previewWidth(400), + m_previewHeight(100) +{ + if (!segment || segment->getType() != Segment::Audio) + reject(); + + QVBox *w = makeVBoxMainWidget(); + + new QLabel(i18n("AutoSplit Segment \"") + + strtoqstr(m_segment->getLabel()) + QString("\""), w); + + m_canvas = new QCanvas(w); + m_canvas->resize(m_canvasWidth, m_canvasHeight); + m_canvasView = new QCanvasView(m_canvas, w); + m_canvasView->setFixedWidth(m_canvasWidth); + m_canvasView->setFixedHeight(m_canvasHeight); + + m_canvasView->setHScrollBarMode(QScrollView::AlwaysOff); + m_canvasView->setVScrollBarMode(QScrollView::AlwaysOff); + m_canvasView->setDragAutoScroll(false); + + QHBox *hbox = new QHBox(w); + new QLabel(i18n("Threshold"), hbox); + m_thresholdSpin = new QSpinBox(hbox); + m_thresholdSpin->setSuffix(" %"); + connect(m_thresholdSpin, SIGNAL(valueChanged(int)), + SLOT(slotThresholdChanged(int))); + + // ensure this is cleared + m_previewBoxes.clear(); + + // Set thresholds + // + int threshold = 1; + m_thresholdSpin->setValue(threshold); + drawPreview(); + drawSplits(1); +} + +void +AudioSplitDialog::drawPreview() +{ + // Delete everything on the canvas + // + QCanvasItemList list = m_canvas->allItems(); + for (QCanvasItemList::Iterator it = list.begin(); it != list.end(); it++) + delete *it; + + // empty the preview boxes + m_previewBoxes.erase(m_previewBoxes.begin(), m_previewBoxes.end()); + + // Draw a bounding box + // + int border = 5; + QCanvasRectangle *rect = new QCanvasRectangle(m_canvas); + rect->setSize(m_canvasWidth - border * 2, m_canvasHeight - border * 2); + rect->setX(border); + rect->setY(border); + rect->setZ(1); + rect->setPen(kapp->palette().color(QPalette::Active, QColorGroup::Dark)); + rect->setBrush(kapp->palette().color(QPalette::Active, QColorGroup::Base)); + rect->setVisible(true); + + // Get preview in vector form + // + AudioFileManager &aFM = m_doc->getAudioFileManager(); + int channels = aFM.getAudioFile(m_segment->getAudioFileId())->getChannels(); + + std::vector<float> values; + + try { + values = aFM.getPreview(m_segment->getAudioFileId(), + m_segment->getAudioStartTime(), + m_segment->getAudioEndTime(), + m_previewWidth, + false); + } catch (Exception e) { + QCanvasText *text = new QCanvasText(m_canvas); + text->setColor(kapp->palette(). + color(QPalette::Active, QColorGroup::Shadow)); + text->setText(i18n("<no preview generated for this audio file>")); + text->setX(30); + text->setY(30); + text->setZ(4); + text->setVisible(true); + m_canvas->update(); + return ; + } + + int startX = (m_canvasWidth - m_previewWidth) / 2; + int halfHeight = m_canvasHeight / 2; + float h1, h2; + std::vector<float>::iterator it = values.begin(); + + // Draw preview + // + for (int i = 0; i < m_previewWidth; i++) { + if (channels == 1) { + h1 = *(it++); + h2 = h1; + } else { + h1 = *(it++); + h2 = *(it++); + } + + + int startY = halfHeight + int(h1 * float(m_previewHeight / 2)); + int endY = halfHeight - int(h2 * float(m_previewHeight / 2)); + + if ( startY < 0 ) { + RG_DEBUG << "AudioSplitDialog::AudioSplitDialog - " + << "startY - out of negative range" + << endl; + startY = 0; + } + + if (endY < 0) { + RG_DEBUG << "AudioSplitDialog::AudioSplitDialog - " + << "endY - out of negative range" + << endl; + endY = 0; + } + + QCanvasLine *line = new QCanvasLine(m_canvas); + line->setPoints(startX + i, + startY, + startX + i, + endY); + line->setZ(3); + line->setPen(kapp-> + palette().color(QPalette::Active, QColorGroup::Shadow)); + line->setBrush(kapp-> + palette().color(QPalette::Active, QColorGroup::Shadow)); + line->setVisible(true); + + } + + // Draw zero dc line + // + rect = new QCanvasRectangle(m_canvas); + rect->setX(startX); + rect->setY(halfHeight - 1); + rect->setSize(m_previewWidth, 2); + rect->setPen(kapp->palette().color(QPalette::Active, QColorGroup::Shadow)); + rect->setBrush(kapp->palette().color(QPalette::Active, QColorGroup::Shadow)); + rect->setZ(4); + rect->setVisible(true); + + // Start time + // + char msecs[100]; + sprintf(msecs, "%03d", m_segment->getAudioStartTime().msec()); + QString startText = QString("%1.%2s") + .arg(m_segment->getAudioStartTime().sec) + .arg(msecs); + QCanvasText *text = new QCanvasText(m_canvas); + text->setColor( + kapp->palette().color(QPalette::Active, QColorGroup::Shadow)); + text->setText(startText); + text->setX(startX - 20); + text->setY(m_canvasHeight / 2 - m_previewHeight / 2 - 35); + text->setZ(3); + text->setVisible(true); + + rect = new QCanvasRectangle(m_canvas); + rect->setX(startX - 1); + rect->setY(m_canvasHeight / 2 - m_previewHeight / 2 - 14); + rect->setSize(1, m_previewHeight + 28); + rect->setPen(kapp->palette().color(QPalette::Active, QColorGroup::Shadow)); + rect->setZ(3); + rect->setVisible(true); + + // End time + // + sprintf(msecs, "%03d", m_segment->getAudioEndTime().msec()); + QString endText = QString("%1.%2s") + .arg(m_segment->getAudioEndTime().sec) + .arg(msecs); + text = new QCanvasText(m_canvas); + text->setColor( + kapp->palette().color(QPalette::Active, QColorGroup::Shadow)); + text->setText(endText); + text->setX(startX + m_previewWidth - 20); + text->setY(m_canvasHeight / 2 - m_previewHeight / 2 - 35); + text->setZ(3); + text->setVisible(true); + + rect = new QCanvasRectangle(m_canvas); + rect->setX(startX + m_previewWidth - 1); + rect->setY(m_canvasHeight / 2 - m_previewHeight / 2 - 14); + rect->setSize(1, m_previewHeight + 28); + rect->setPen(kapp->palette().color(QPalette::Active, QColorGroup::Shadow)); + rect->setZ(3); + rect->setVisible(true); + + m_canvas->update(); +} + +void +AudioSplitDialog::drawSplits(int threshold) +{ + // Now get the current split points and paint them + // + RealTime startTime = m_segment->getAudioStartTime(); + RealTime endTime = m_segment->getAudioEndTime(); + + AudioFileManager &aFM = m_doc->getAudioFileManager(); + std::vector<SplitPointPair> splitPoints = + aFM.getSplitPoints(m_segment->getAudioFileId(), + startTime, + endTime, + threshold); + + std::vector<SplitPointPair>::iterator it; + std::vector<QCanvasRectangle*> tempRects; + + RealTime length = endTime - startTime; + double ticksPerUsec = double(m_previewWidth) / + double((length.sec * 1000000.0) + length.usec()); + + int startX = (m_canvasWidth - m_previewWidth) / 2; + int halfHeight = m_canvasHeight / 2; + int x1, x2; + int overlapHeight = 10; + + for (it = splitPoints.begin(); it != splitPoints.end(); it++) { + RealTime splitStart = it->first - startTime; + RealTime splitEnd = it->second - startTime; + + x1 = int(ticksPerUsec * double(double(splitStart.sec) * + 1000000.0 + (double)splitStart.usec())); + + x2 = int(ticksPerUsec * double(double(splitEnd.sec) * + 1000000.0 + double(splitEnd.usec()))); + + QCanvasRectangle *rect = new QCanvasRectangle(m_canvas); + rect->setX(startX + x1); + rect->setY(halfHeight - m_previewHeight / 2 - overlapHeight / 2); + rect->setZ(2); + rect->setSize(x2 - x1, m_previewHeight + overlapHeight); + rect->setPen(kapp-> + palette().color(QPalette::Active, QColorGroup::Mid)); + rect->setBrush(kapp-> + palette().color(QPalette::Active, QColorGroup::Mid)); + rect->setVisible(true); + tempRects.push_back(rect); + } + + std::vector<QCanvasRectangle*>::iterator pIt; + + // We've written the new Rects, now delete the old ones + // + if (m_previewBoxes.size()) { + // clear any previous preview boxes + // + for (pIt = m_previewBoxes.begin(); pIt != m_previewBoxes.end(); pIt++) { + //(*pIt)->setVisible(false); + delete (*pIt); + } + m_previewBoxes.erase(m_previewBoxes.begin(), m_previewBoxes.end()); + m_canvas->update(); + } + m_canvas->update(); + + // Now store the new ones + // + for (pIt = tempRects.begin(); pIt != tempRects.end(); pIt++) + m_previewBoxes.push_back(*pIt); +} + +void +AudioSplitDialog::slotThresholdChanged(int threshold) +{ + drawSplits(threshold); +} + +} +#include "AudioSplitDialog.moc" diff --git a/src/gui/dialogs/AudioSplitDialog.h b/src/gui/dialogs/AudioSplitDialog.h new file mode 100644 index 0000000..7dc52c0 --- /dev/null +++ b/src/gui/dialogs/AudioSplitDialog.h @@ -0,0 +1,88 @@ + +/* -*- 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_AUDIOSPLITDIALOG_H_ +#define _RG_AUDIOSPLITDIALOG_H_ + +#include <kdialogbase.h> +#include <vector> +#include <qspinbox.h> + + +class QWidget; +class QCanvasView; +class QCanvasRectangle; +class QCanvas; + + +namespace Rosegarden +{ + +class Segment; +class RosegardenGUIDoc; + + +class AudioSplitDialog : public KDialogBase +{ + Q_OBJECT +public: + AudioSplitDialog(QWidget *parent, + Segment *segment, + RosegardenGUIDoc *doc); + + // Draw an audio preview over the segment and draw + // the potential splits along it. + // + void drawPreview(); + void drawSplits(int threshold); + + // Get the threshold + // + int getThreshold() { return m_thresholdSpin->value(); } + +public slots: + void slotThresholdChanged(int); + +protected: + RosegardenGUIDoc *m_doc; + Segment *m_segment; + QCanvas *m_canvas; + QCanvasView *m_canvasView; + QSpinBox *m_thresholdSpin; + + int m_canvasWidth; + int m_canvasHeight; + int m_previewWidth; + int m_previewHeight; + + std::vector<QCanvasRectangle*> m_previewBoxes; + +}; + + + +} + +#endif diff --git a/src/gui/dialogs/BeatsBarsDialog.cpp b/src/gui/dialogs/BeatsBarsDialog.cpp new file mode 100644 index 0000000..774ddb9 --- /dev/null +++ b/src/gui/dialogs/BeatsBarsDialog.cpp @@ -0,0 +1,66 @@ +/* -*- 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 "BeatsBarsDialog.h" +#include <qlayout.h> + +#include <klocale.h> +#include "base/Segment.h" +#include <kcombobox.h> +#include <kdialogbase.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qhbox.h> +#include <qspinbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +BeatsBarsDialog::BeatsBarsDialog(QWidget* parent) : + KDialogBase(parent, 0, true, i18n("Audio Segment Duration"), + Ok | Cancel, Ok) +{ + QHBox *hbox = makeHBoxMainWidget(); + + QGroupBox *gbox = new QGroupBox(1, Horizontal, + i18n("The selected audio segment contains:"), hbox); + + QFrame *frame = new QFrame(gbox); + QGridLayout *layout = new QGridLayout(frame, 1, 2, 5, 5); + + m_spinBox = new QSpinBox(1, INT_MAX, 1, frame, "glee"); + layout->addWidget(m_spinBox, 0, 0); + + m_comboBox = new KComboBox(false, frame); + m_comboBox->insertItem(i18n("beat(s)")); + m_comboBox->insertItem(i18n("bar(s)")); + m_comboBox->setCurrentItem(0); + layout->addWidget(m_comboBox, 0, 1); +} + +} +#include "BeatsBarsDialog.moc" diff --git a/src/gui/dialogs/BeatsBarsDialog.h b/src/gui/dialogs/BeatsBarsDialog.h new file mode 100644 index 0000000..6546f01 --- /dev/null +++ b/src/gui/dialogs/BeatsBarsDialog.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_BEATSBARSDIALOG_H_ +#define _RG_BEATSBARSDIALOG_H_ + +#include <kdialogbase.h> +#include <qspinbox.h> +#include <kcombobox.h> + +class QWidget; + + +namespace Rosegarden +{ + +/** + * ask the user to give us information about the selected audio segment for + * Tempo calculations + */ +class BeatsBarsDialog : public KDialogBase +{ + Q_OBJECT + +public: + BeatsBarsDialog(); + BeatsBarsDialog(QWidget *parent); + + int getQuantity() { return m_spinBox->value(); } + int getMode() { return m_comboBox->currentItem(); } + +protected: + QSpinBox *m_spinBox; + KComboBox *m_comboBox; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/ClefDialog.cpp b/src/gui/dialogs/ClefDialog.cpp new file mode 100644 index 0000000..8f802b0 --- /dev/null +++ b/src/gui/dialogs/ClefDialog.cpp @@ -0,0 +1,273 @@ +/* -*- 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 "ClefDialog.h" + +#include "base/NotationTypes.h" +#include "gui/editors/notation/NotePixmapFactory.h" +#include "gui/widgets/BigArrowButton.h" +#include <klocale.h> +#include <kdialogbase.h> +#include <qbuttongroup.h> +#include <qgroupbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qobject.h> +#include <qpixmap.h> +#include <qradiobutton.h> +#include <qstring.h> +#include <qtooltip.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +ClefDialog::ClefDialog(QWidget *parent, + NotePixmapFactory *npf, + Clef defaultClef, + bool showConversionOptions) : + KDialogBase(parent, 0, true, i18n("Clef"), Ok | Cancel | Help), + m_notePixmapFactory(npf), + m_clef(defaultClef) +{ + setHelp("nv-signatures-clef"); + + QVBox *vbox = makeVBoxMainWidget(); + + QGroupBox *clefFrame = new QGroupBox + (1, Horizontal, i18n("Clef"), vbox); + + QButtonGroup *conversionFrame = new QButtonGroup + (1, Horizontal, i18n("Existing notes following clef change"), vbox); + + QHBox *clefBox = new QHBox(clefFrame); + + BigArrowButton *clefDown = new BigArrowButton(clefBox, Qt::LeftArrow); + QToolTip::add + (clefDown, i18n("Lower clef")); + + QHBox *clefLabelBox = new QVBox(clefBox); + + m_octaveUp = new BigArrowButton(clefLabelBox, Qt::UpArrow); + QToolTip::add + (m_octaveUp, i18n("Up an Octave")); + + m_clefLabel = new QLabel(i18n("Clef"), clefLabelBox); + m_clefLabel->setAlignment(AlignVCenter | AlignHCenter); + + m_octaveDown = new BigArrowButton(clefLabelBox, Qt::DownArrow); + QToolTip::add + (m_octaveDown, i18n("Down an Octave")); + + BigArrowButton *clefUp = new BigArrowButton(clefBox, Qt::RightArrow); + QToolTip::add + (clefUp, i18n("Higher clef")); + + m_clefNameLabel = new QLabel(i18n("Clef"), clefLabelBox); + m_clefNameLabel->setAlignment(AlignVCenter | AlignHCenter); + + if (showConversionOptions) { + m_noConversionButton = + new QRadioButton + (i18n("Maintain current pitches"), conversionFrame); + m_changeOctaveButton = + new QRadioButton + (i18n("Transpose into appropriate octave"), conversionFrame); + m_transposeButton = 0; + + //!!! why aren't we offering this option? does it not work? too difficult to describe? + // m_transposeButton = + // new QRadioButton + // (i18n("Maintain current positions on the staff"), conversionFrame); + m_changeOctaveButton->setChecked(true); + } else { + m_noConversionButton = 0; + m_changeOctaveButton = 0; + m_transposeButton = 0; + conversionFrame->hide(); + } + + QObject::connect(clefUp, SIGNAL(clicked()), this, SLOT(slotClefUp())); + QObject::connect(clefDown, SIGNAL(clicked()), this, SLOT(slotClefDown())); + QObject::connect(m_octaveUp, SIGNAL(clicked()), this, SLOT(slotOctaveUp())); + QObject::connect(m_octaveDown, SIGNAL(clicked()), this, SLOT(slotOctaveDown())); + + redrawClefPixmap(); +} + +Clef +ClefDialog::getClef() const +{ + return m_clef; +} + +ClefDialog::ConversionType + +ClefDialog::getConversionType() const +{ + if (m_noConversionButton && m_noConversionButton->isChecked()) { + return NoConversion; + } else if (m_changeOctaveButton && m_changeOctaveButton->isChecked()) { + return ChangeOctave; + } else if (m_transposeButton && m_transposeButton->isChecked()) { + return Transpose; + } + return NoConversion; +} + +void +ClefDialog::slotClefUp() +{ + int octaveOffset = m_clef.getOctaveOffset(); + Clef::ClefList clefs(Clef::getClefs()); + + for (Clef::ClefList::iterator i = clefs.begin(); + i != clefs.end(); ++i) { + + if (m_clef.getClefType() == i->getClefType()) { + if (++i == clefs.end()) + i = clefs.begin(); + m_clef = Clef(i->getClefType(), octaveOffset); + break; + } + } + + redrawClefPixmap(); +} + +void +ClefDialog::slotClefDown() +{ + int octaveOffset = m_clef.getOctaveOffset(); + Clef::ClefList clefs(Clef::getClefs()); + + for (Clef::ClefList::iterator i = clefs.begin(); + i != clefs.end(); ++i) { + + if (m_clef.getClefType() == i->getClefType()) { + if (i == clefs.begin()) + i = clefs.end(); + --i; + m_clef = Clef(i->getClefType(), octaveOffset); + break; + } + } + + redrawClefPixmap(); +} + +void +ClefDialog::slotOctaveUp() +{ + int octaveOffset = m_clef.getOctaveOffset(); + if (octaveOffset == 2) + return ; + + ++octaveOffset; + + m_octaveDown->setEnabled(true); + if (octaveOffset == 2) { + m_octaveUp->setEnabled(false); + } + + m_clef = Clef(m_clef.getClefType(), octaveOffset); + redrawClefPixmap(); +} + +void +ClefDialog::slotOctaveDown() +{ + int octaveOffset = m_clef.getOctaveOffset(); + if (octaveOffset == -2) + return ; + + --octaveOffset; + + m_octaveUp->setEnabled(true); + if (octaveOffset == 2) { + m_octaveDown->setEnabled(false); + } + + m_clef = Clef(m_clef.getClefType(), octaveOffset); + redrawClefPixmap(); +} + +void +ClefDialog::redrawClefPixmap() +{ + QPixmap pmap = NotePixmapFactory::toQPixmap + (m_notePixmapFactory->makeClefDisplayPixmap(m_clef)); + m_clefLabel->setPixmap(pmap); + + QString name; + int octave = m_clef.getOctaveOffset(); + + switch (octave) { + case - 1: + name = i18n("%1 down an octave"); + break; + case - 2: + name = i18n("%1 down two octaves"); + break; + case 1: + name = i18n("%1 up an octave"); + break; + case 2: + name = i18n("%1 up two octaves"); + break; + default: + name = "%1"; + break; + } + + std::string type = m_clef.getClefType(); + if (type == Clef::Treble) + name = name.arg(i18n("Treble")); + else if (type == Clef::French) + name = name.arg(i18n("French violin")); + else if (type == Clef::Soprano) + name = name.arg(i18n("Soprano")); + else if (type == Clef::Mezzosoprano) + name = name.arg(i18n("Mezzo-soprano")); + else if (type == Clef::Alto) + name = name.arg(i18n("Alto")); + else if (type == Clef::Tenor) + name = name.arg(i18n("Tenor")); + else if (type == Clef::Baritone) + name = name.arg(i18n("C-baritone")); + else if (type == Clef::Varbaritone) + name = name.arg(i18n("F-baritone")); + else if (type == Clef::Bass) + name = name.arg(i18n("Bass")); + else if (type == Clef::Subbass) + name = name.arg(i18n("Sub-bass")); + + m_clefNameLabel->setText(name); +} + +} +#include "ClefDialog.moc" diff --git a/src/gui/dialogs/ClefDialog.h b/src/gui/dialogs/ClefDialog.h new file mode 100644 index 0000000..771cd4a --- /dev/null +++ b/src/gui/dialogs/ClefDialog.h @@ -0,0 +1,93 @@ + +/* -*- 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_CLEFDIALOG_H_ +#define _RG_CLEFDIALOG_H_ + +#include "base/NotationTypes.h" +#include <kdialogbase.h> + + +class QWidget; +class QRadioButton; +class QLabel; + + +namespace Rosegarden +{ + +class BigArrowButton; +class NotePixmapFactory; + + +class ClefDialog : public KDialogBase +{ + Q_OBJECT + +public: + enum ConversionType { + NoConversion, + ChangeOctave, + Transpose, + }; + + ClefDialog(QWidget *parent, + NotePixmapFactory *npf, + Clef defaultClef, + bool showConversionOptions = true); + + Clef getClef() const; + ConversionType getConversionType() const; + +public slots: + void slotClefUp(); + void slotClefDown(); + void slotOctaveUp(); + void slotOctaveDown(); + +protected: + void redrawClefPixmap(); + + //--------------- Data members --------------------------------- + + NotePixmapFactory *m_notePixmapFactory; + Clef m_clef; + + QLabel *m_clefLabel; + QLabel *m_clefNameLabel; + + BigArrowButton *m_octaveUp; + BigArrowButton *m_octaveDown; + + QRadioButton *m_noConversionButton; + QRadioButton *m_changeOctaveButton; + QRadioButton *m_transposeButton; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/CompositionLengthDialog.cpp b/src/gui/dialogs/CompositionLengthDialog.cpp new file mode 100644 index 0000000..24a3107 --- /dev/null +++ b/src/gui/dialogs/CompositionLengthDialog.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 "CompositionLengthDialog.h" + +#include <klocale.h> +#include "base/Composition.h" +#include <kdialogbase.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qspinbox.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +CompositionLengthDialog::CompositionLengthDialog( + QWidget *parent, + Composition *composition): + KDialogBase(parent, 0, true, i18n("Change Composition Length"), + Ok | Cancel), + m_composition(composition) +{ + QVBox *vBox = makeVBoxMainWidget(); + + new QLabel(i18n("Set the Start and End bar markers for this Composition"), + vBox); + + QHBox *startBox = new QHBox(vBox); + new QLabel(i18n("Start Bar"), startBox); + m_startMarkerSpinBox = new QSpinBox(startBox); + m_startMarkerSpinBox->setMinValue( -10); + m_startMarkerSpinBox->setMaxValue(10000); + m_startMarkerSpinBox->setValue( + m_composition->getBarNumber(m_composition->getStartMarker()) + 1); + + QHBox *endBox = new QHBox(vBox); + new QLabel(i18n("End Bar"), endBox); + m_endMarkerSpinBox = new QSpinBox(endBox); + m_endMarkerSpinBox->setMinValue( -10); + m_endMarkerSpinBox->setMaxValue(10000); + m_endMarkerSpinBox->setValue( + m_composition->getBarNumber(m_composition->getEndMarker())); + +} + +timeT +CompositionLengthDialog::getStartMarker() +{ + return m_composition->getBarStart(m_startMarkerSpinBox->value() - 1); +} + +timeT +CompositionLengthDialog::getEndMarker() +{ + return m_composition->getBarStart(m_endMarkerSpinBox->value()); +} + +} +#include "CompositionLengthDialog.moc" diff --git a/src/gui/dialogs/CompositionLengthDialog.h b/src/gui/dialogs/CompositionLengthDialog.h new file mode 100644 index 0000000..e6d688c --- /dev/null +++ b/src/gui/dialogs/CompositionLengthDialog.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_COMPOSITIONLENGTHDIALOG_H_ +#define _RG_COMPOSITIONLENGTHDIALOG_H_ + +#include <kdialogbase.h> +#include "base/Event.h" + + +class QWidget; +class QSpinBox; + + +namespace Rosegarden +{ + +class Composition; + + +class CompositionLengthDialog : public KDialogBase +{ + Q_OBJECT +public: + CompositionLengthDialog(QWidget *parent, + Composition *composition); + + timeT getStartMarker(); + timeT getEndMarker(); + +protected: + + QSpinBox *m_startMarkerSpinBox; + QSpinBox *m_endMarkerSpinBox; + Composition *m_composition; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/ConfigureDialog.cpp b/src/gui/dialogs/ConfigureDialog.cpp new file mode 100644 index 0000000..1bdd3b4 --- /dev/null +++ b/src/gui/dialogs/ConfigureDialog.cpp @@ -0,0 +1,118 @@ +/* -*- 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 "ConfigureDialog.h" +#include <qlayout.h> + +#include <klocale.h> +#include "ConfigureDialogBase.h" +#include "document/RosegardenGUIDoc.h" +#include "gui/configuration/GeneralConfigurationPage.h" +#include "gui/configuration/NotationConfigurationPage.h" +#include "gui/configuration/AudioConfigurationPage.h" +#include "gui/configuration/MIDIConfigurationPage.h" +#include <kconfig.h> +#include <kdialogbase.h> +#include <kstddirs.h> +#include <qstring.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +static QPixmap loadIcon(const char *name) +{ + QString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/"); + QString fileBase = pixmapDir + "/misc/"; + fileBase += name; + if (QFile(fileBase + ".png").exists()) { + return QPixmap(fileBase + ".png"); + } else if (QFile(fileBase + ".xpm").exists()) { + return QPixmap(fileBase + ".xpm"); + } + QPixmap pmap = KGlobal::instance()->iconLoader() + ->loadIcon(QString::fromLatin1(name), KIcon::NoGroup, KIcon::SizeMedium); + return pmap; +} + + +ConfigureDialog::ConfigureDialog(RosegardenGUIDoc *doc, + KConfig* cfg, + QWidget *parent, + const char *name) + : ConfigureDialogBase(parent, i18n("Configure Rosegarden"), name) +{ + QWidget *pageWidget = 0; + QVBoxLayout *vlay = 0; + ConfigurationPage* page = 0; + + // General Page + // + pageWidget = addPage(GeneralConfigurationPage::iconLabel(), + GeneralConfigurationPage::title(), + loadIcon(GeneralConfigurationPage::iconName())); + vlay = new QVBoxLayout(pageWidget, 0, spacingHint()); + page = new GeneralConfigurationPage(doc, cfg, pageWidget); + vlay->addWidget(page); + page->setPageIndex(pageIndex(pageWidget)); + m_configurationPages.push_back(page); + + connect(page, SIGNAL(updateAutoSaveInterval(unsigned int)), + this, SIGNAL(updateAutoSaveInterval(unsigned int))); + connect(page, SIGNAL(updateSidebarStyle(unsigned int)), + this, SIGNAL(updateSidebarStyle(unsigned int))); + + pageWidget = addPage(MIDIConfigurationPage::iconLabel(), + MIDIConfigurationPage::title(), + loadIcon(MIDIConfigurationPage::iconName())); + vlay = new QVBoxLayout(pageWidget, 0, spacingHint()); + page = new MIDIConfigurationPage(doc, cfg, pageWidget); + vlay->addWidget(page); + page->setPageIndex(pageIndex(pageWidget)); + m_configurationPages.push_back(page); + + pageWidget = addPage(AudioConfigurationPage::iconLabel(), + AudioConfigurationPage::title(), + loadIcon(AudioConfigurationPage::iconName())); + vlay = new QVBoxLayout(pageWidget, 0, spacingHint()); + page = new AudioConfigurationPage(doc, cfg, pageWidget); + vlay->addWidget(page); + page->setPageIndex(pageIndex(pageWidget)); + m_configurationPages.push_back(page); + + // Notation Page + pageWidget = addPage(NotationConfigurationPage::iconLabel(), + NotationConfigurationPage::title(), + loadIcon(NotationConfigurationPage::iconName())); + vlay = new QVBoxLayout(pageWidget, 0, spacingHint()); + page = new NotationConfigurationPage(cfg, pageWidget); + vlay->addWidget(page); + page->setPageIndex(pageIndex(pageWidget)); + m_configurationPages.push_back(page); +} + +} +#include "ConfigureDialog.moc" diff --git a/src/gui/dialogs/ConfigureDialog.h b/src/gui/dialogs/ConfigureDialog.h new file mode 100644 index 0000000..4dd6fff --- /dev/null +++ b/src/gui/dialogs/ConfigureDialog.h @@ -0,0 +1,58 @@ + +/* -*- 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_CONFIGUREDIALOG_H_ +#define _RG_CONFIGUREDIALOG_H_ + +#include "ConfigureDialogBase.h" + + +class QWidget; +class KConfig; + + +namespace Rosegarden +{ + +class RosegardenGUIDoc; + + +class ConfigureDialog : public ConfigureDialogBase +{ + Q_OBJECT +public: + ConfigureDialog(RosegardenGUIDoc *doc, + KConfig* cfg, + QWidget *parent=0, + const char *name=0); +signals: + void updateAutoSaveInterval(unsigned int); + void updateSidebarStyle(unsigned int); +}; + + +} + +#endif diff --git a/src/gui/dialogs/ConfigureDialogBase.cpp b/src/gui/dialogs/ConfigureDialogBase.cpp new file mode 100644 index 0000000..7d5555a --- /dev/null +++ b/src/gui/dialogs/ConfigureDialogBase.cpp @@ -0,0 +1,76 @@ +/* -*- 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 "ConfigureDialogBase.h" + +#include <klocale.h> +#include "gui/configuration/ConfigurationPage.h" +#include <kdialogbase.h> +#include <qstring.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +ConfigureDialogBase::ConfigureDialogBase(QWidget *parent, + QString label, + const char *name): + KDialogBase(IconList, label ? label : i18n("Configure"), Help | Apply | Ok | Cancel, + Ok, parent, name, true) // modal +{ + setWFlags(WDestructiveClose); +} + +ConfigureDialogBase::~ConfigureDialogBase() +{} + +void +ConfigureDialogBase::slotApply() +{ + for (configurationpages::iterator i = m_configurationPages.begin(); + i != m_configurationPages.end(); ++i) + (*i)->apply(); +} + +void +ConfigureDialogBase::slotActivateApply() +{ + // ApplyButton->setDisabled(false); +} + +void +ConfigureDialogBase::slotOk() +{ + slotApply(); + accept(); +} + +void +ConfigureDialogBase::slotCancelOrClose() +{} + +} +#include "ConfigureDialogBase.moc" diff --git a/src/gui/dialogs/ConfigureDialogBase.h b/src/gui/dialogs/ConfigureDialogBase.h new file mode 100644 index 0000000..fe05ebe --- /dev/null +++ b/src/gui/dialogs/ConfigureDialogBase.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_CONFIGUREDIALOGBASE_H_ +#define _RG_CONFIGUREDIALOGBASE_H_ + +#include <kdialogbase.h> +#include <qstring.h> +#include <vector> + + +class QWidget; + + +namespace Rosegarden +{ + +class ConfigurationPage; + + +class ConfigureDialogBase : public KDialogBase +{ + Q_OBJECT +public: + ConfigureDialogBase(QWidget *parent=0, + QString label = 0, + const char *name=0); + virtual ~ConfigureDialogBase(); + + typedef std::vector<ConfigurationPage*> configurationpages; + +protected slots: + virtual void slotOk(); + virtual void slotApply(); + virtual void slotCancelOrClose(); + + virtual void slotActivateApply(); + +protected: + + configurationpages m_configurationPages; +}; + + +} + +#endif diff --git a/src/gui/dialogs/CountdownBar.cpp b/src/gui/dialogs/CountdownBar.cpp new file mode 100644 index 0000000..cfad3d8 --- /dev/null +++ b/src/gui/dialogs/CountdownBar.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 "CountdownBar.h" + +#include "gui/general/GUIPalette.h" +#include <qframe.h> +#include <qpainter.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +CountdownBar::CountdownBar(QWidget *parent, int width, int height): + QFrame(parent), m_width(width), m_height(height), m_position(0) +{ + resize(m_width, m_height); + repaint(); +} + +void +CountdownBar::paintEvent(QPaintEvent *e) +{ + QPainter p(this); + + p.setClipRegion(e->region()); + p.setClipRect(e->rect().normalize()); + + p.setPen(GUIPalette::getColour(GUIPalette::AudioCountdownBackground)); + p.setBrush(GUIPalette::getColour(GUIPalette::AudioCountdownBackground)); + p.drawRect(0, 0, m_position, m_height); + p.setPen(GUIPalette::getColour(GUIPalette::AudioCountdownForeground)); + p.setBrush(GUIPalette::getColour(GUIPalette::AudioCountdownForeground)); + p.drawRect(m_position, 0, m_width, m_height); +} + +void +CountdownBar::setPosition(int position) +{ + m_position = position; + repaint(); +} + +} +#include "CountdownBar.moc" diff --git a/src/gui/dialogs/CountdownBar.h b/src/gui/dialogs/CountdownBar.h new file mode 100644 index 0000000..364d0cf --- /dev/null +++ b/src/gui/dialogs/CountdownBar.h @@ -0,0 +1,59 @@ + +/* -*- 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_COUNTDOWNBAR_H_ +#define _RG_COUNTDOWNBAR_H_ + +#include <qframe.h> + + +class QWidget; +class QPaintEvent; + + +namespace Rosegarden +{ + + + +class CountdownBar : public QFrame +{ + Q_OBJECT +public: + CountdownBar(QWidget *parent, int width, int height); + void setPosition(int position); + +protected: + virtual void paintEvent(QPaintEvent *e); + + int m_width; + int m_height; + int m_position; +}; + + +} + +#endif diff --git a/src/gui/dialogs/CountdownDialog.cpp b/src/gui/dialogs/CountdownDialog.cpp new file mode 100644 index 0000000..f624aba --- /dev/null +++ b/src/gui/dialogs/CountdownDialog.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. + + 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 "CountdownDialog.h" +#include <qlayout.h> + +#include <klocale.h> +#include "CountdownBar.h" +#include <qaccel.h> +#include <qdialog.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qwidget.h> +#include "misc/Debug.h" + + +namespace Rosegarden +{ + +CountdownDialog::CountdownDialog(QWidget *parent, int seconds): + QDialog(parent, "", false, WStyle_StaysOnTop | WStyle_DialogBorder), + m_pastEndMode(false), + m_totalTime(seconds), + m_progressBarWidth(150), + m_progressBarHeight(15) +{ + QBoxLayout *layout = new QBoxLayout(this, QBoxLayout::TopToBottom, 10, 14); + setCaption(i18n("Recording...")); + + QHBox *hBox = new QHBox(this); + m_label = new QLabel(hBox); + m_time = new QLabel(hBox); + + layout->addWidget(hBox, 0, AlignCenter); + + m_label->setText(i18n("Recording time remaining: ")); + m_progressBar = + new CountdownBar(this, m_progressBarWidth, m_progressBarHeight); + + m_progressBar->setFixedSize(m_progressBarWidth, m_progressBarHeight); + + // Simply re-emit from Stop button + // + m_stopButton = new QPushButton(i18n("Stop"), this); + m_stopButton->setFixedWidth(60); + + layout->addWidget(m_progressBar, 0, AlignCenter); + layout->addWidget(m_stopButton, 0, AlignRight); + + connect (m_stopButton, SIGNAL(released()), this, SIGNAL(stopped())); + + // Set the total time to show the bar in initial position + // + setElapsedTime(0); + + m_accelerators = new QAccel(this); + +} + +void +CountdownDialog::setLabel(const QString &label) +{ + m_label->setText(label); +} + +void +CountdownDialog::setTotalTime(int seconds) +{ + m_totalTime = seconds; + setElapsedTime(0); // clear +} + +void +CountdownDialog::setElapsedTime(int elapsedSeconds) +{ + int seconds = m_totalTime - elapsedSeconds; + + if (seconds < 0) { + seconds = - seconds; + if (!m_pastEndMode) + setPastEndMode(); + } + + QString h, m, s; + h.sprintf("%02d", seconds / 3600); + m.sprintf("%02d", seconds / 60); + s.sprintf("%02d", seconds % 60); + + if (seconds < 3600) // less than an hour + { + m_time->setText(QString("%1:%2").arg(m).arg(s)); + } else if (seconds < 86400) // less than a day + { + m_time->setText(QString("%1:%2:%3").arg(h).arg(m).arg(s)); + } else { + m_time->setText(i18n("Just how big is your hard disk?")); + } + + // Draw the progress bar + // + if (m_pastEndMode) { + m_progressBar->setPosition(m_progressBarWidth); + } else { + // Attempt a simplistic fix for #1838190. In the context of an isolated + // test example, I'm fairly sure m_totalTime was 0, causing a divide by + // zero error, though the trace just listed it as an "Arithmetic + // exception." + if (m_totalTime == 0) { + RG_DEBUG << "CountdownDialog::setElapsedTime: FAILSAFE CODE FIRED, see bug #1838190 for details" << endl; + m_totalTime = 1; + } + int barPosition = m_progressBarWidth - + (elapsedSeconds * m_progressBarWidth) / m_totalTime; + m_progressBar->setPosition(barPosition); + } + + // Dialog complete if the display time is zero + if (seconds == 0) + emit completed(); + +} + +void +CountdownDialog::setPastEndMode() +{ + if (m_pastEndMode) // already called + return ; + + m_pastEndMode = true; + m_label->setText(i18n("Recording beyond end of composition: ")); + +} + +} +#include "CountdownDialog.moc" diff --git a/src/gui/dialogs/CountdownDialog.h b/src/gui/dialogs/CountdownDialog.h new file mode 100644 index 0000000..00aa6e0 --- /dev/null +++ b/src/gui/dialogs/CountdownDialog.h @@ -0,0 +1,87 @@ + +/* -*- 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_COUNTDOWNDIALOG_H_ +#define _RG_COUNTDOWNDIALOG_H_ + +#include <kdialogbase.h> +#include <qdialog.h> + + +class QWidget; +class QString; +class QPushButton; +class QLabel; +class QAccel; + + +namespace Rosegarden +{ + +class CountdownBar; + + +class CountdownDialog : public QDialog // KDialogBase +{ + Q_OBJECT + +public: + CountdownDialog(QWidget *parent, int seconds = 300); + + void setLabel(const QString &label); + void setElapsedTime(int seconds); + + int getTotalTime() const { return m_totalTime; } + void setTotalTime(int seconds); + + QAccel* getAccelerators() { return m_accelerators; } + +signals: + void completed(); // m_totalTime has elapsed + void stopped(); // someone pushed the stop button + +protected: + void setPastEndMode(); + + bool m_pastEndMode; + + int m_totalTime; + + QLabel *m_label; + QLabel *m_time; + CountdownBar *m_progressBar; + + QPushButton *m_stopButton; + + int m_progressBarWidth; + int m_progressBarHeight; + + QAccel *m_accelerators; +}; + + +} + +#endif diff --git a/src/gui/dialogs/DocumentConfigureDialog.cpp b/src/gui/dialogs/DocumentConfigureDialog.cpp new file mode 100644 index 0000000..5f79f33 --- /dev/null +++ b/src/gui/dialogs/DocumentConfigureDialog.cpp @@ -0,0 +1,151 @@ +/* -*- 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 "DocumentConfigureDialog.h" +#include <qlayout.h> + +#include <klocale.h> +#include "ConfigureDialogBase.h" +#include "document/RosegardenGUIDoc.h" +#include "gui/configuration/AudioPropertiesPage.h" +#include "gui/configuration/ColourConfigurationPage.h" +#include "gui/configuration/DocumentMetaConfigurationPage.h" +#include "gui/configuration/GeneralConfigurationPage.h" +#include <kdialogbase.h> +#include <qstring.h> +#include <qwidget.h> +#include <kstddirs.h> + + +namespace Rosegarden +{ +static QPixmap loadIcon(const char *name) +{ + QString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/"); + QString fileBase = pixmapDir + "/misc/"; + fileBase += name; + if (QFile(fileBase + ".png").exists()) { + return QPixmap(fileBase + ".png"); + } else if (QFile(fileBase + ".xpm").exists()) { + return QPixmap(fileBase + ".xpm"); + } + + QPixmap pmap = KGlobal::instance()->iconLoader() + ->loadIcon(QString::fromLatin1(name), KIcon::NoGroup, KIcon::SizeMedium); + return pmap; +} + + +DocumentConfigureDialog::DocumentConfigureDialog(RosegardenGUIDoc *doc, + QWidget *parent, + const char *name) + : ConfigureDialogBase(parent, i18n("Document Properties"), name) +{ + QWidget *pageWidget = 0; + QVBoxLayout *vlay = 0; + ConfigurationPage* page = 0; + + // Document Meta Page + // + pageWidget = addPage(DocumentMetaConfigurationPage::iconLabel(), + DocumentMetaConfigurationPage::title(), + loadIcon(DocumentMetaConfigurationPage::iconName())); + vlay = new QVBoxLayout(pageWidget, 0, spacingHint()); + page = new DocumentMetaConfigurationPage(doc, pageWidget); + vlay->addWidget(page); + page->setPageIndex(pageIndex(pageWidget)); + m_configurationPages.push_back(page); + + // Audio Page + // + pageWidget = addPage(AudioPropertiesPage::iconLabel(), + AudioPropertiesPage::title(), + loadIcon(AudioPropertiesPage::iconName())); + vlay = new QVBoxLayout(pageWidget, 0, spacingHint()); + page = new AudioPropertiesPage(doc, pageWidget); + vlay->addWidget(page); + page->setPageIndex(pageIndex(pageWidget)); + m_configurationPages.push_back(page); + + // Colour Page + pageWidget = addPage(ColourConfigurationPage::iconLabel(), + ColourConfigurationPage::title(), + loadIcon(ColourConfigurationPage::iconName())); + + vlay = new QVBoxLayout(pageWidget, 0, spacingHint()); + page = new ColourConfigurationPage(doc, pageWidget); + vlay->addWidget(page); + page->setPageIndex(pageIndex(pageWidget)); + m_configurationPages.push_back(page); + + resize(minimumSize()); +} + +void +DocumentConfigureDialog::showAudioPage() +{ + int index = 0; + + for (configurationpages::iterator i = m_configurationPages.begin(); + i != m_configurationPages.end(); ++i) { + + AudioPropertiesPage *page = + dynamic_cast<AudioPropertiesPage *>(*i); + + if (!page) { + ++index; + continue; + } + + showPage(index); + return ; + } +} + +/* hjj: WHAT TO DO WITH THIS ? +void +DocumentConfigureDialog::selectMetadata(QString name) +{ + int index = 0; + + for (configurationpages::iterator i = m_configurationPages.begin(); + i != m_configurationPages.end(); ++i) { + + DocumentMetaConfigurationPage *page = + dynamic_cast<DocumentMetaConfigurationPage *>(*i); + + if (!page) { + ++index; + continue; + } + + page->selectMetadata(name); + showPage(index); + return ; + } +} +*/ + +} diff --git a/src/gui/dialogs/DocumentConfigureDialog.h b/src/gui/dialogs/DocumentConfigureDialog.h new file mode 100644 index 0000000..6713047 --- /dev/null +++ b/src/gui/dialogs/DocumentConfigureDialog.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_DOCUMENTCONFIGUREDIALOG_H_ +#define _RG_DOCUMENTCONFIGUREDIALOG_H_ + +#include "ConfigureDialogBase.h" +#include <qstring.h> + + +class QWidget; + + +namespace Rosegarden +{ + +class RosegardenGUIDoc; + + +class DocumentConfigureDialog : public ConfigureDialogBase +{ +public: + DocumentConfigureDialog(RosegardenGUIDoc *doc, + QWidget *parent=0, + const char *name=0); + + void showAudioPage(); + +/* hjj: WHAT TO DO WITH THIS ? + void selectMetadata(QString name); +*/ +}; + + + + +} + +#endif diff --git a/src/gui/dialogs/EventEditDialog.cpp b/src/gui/dialogs/EventEditDialog.cpp new file mode 100644 index 0000000..c9991f1 --- /dev/null +++ b/src/gui/dialogs/EventEditDialog.cpp @@ -0,0 +1,528 @@ +/* -*- 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 "EventEditDialog.h" + +#include <klocale.h> +#include "misc/Strings.h" +#include "base/Event.h" +#include "base/MidiTypes.h" +#include "base/NotationTypes.h" +#include "base/PropertyName.h" +#include "base/RealTime.h" +#include "gui/editors/notation/NotePixmapFactory.h" +#include <kdialogbase.h> +#include <kmessagebox.h> +#include <qcheckbox.h> +#include <qfont.h> +#include <qgrid.h> +#include <qgroupbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qobject.h> +#include <qobjectlist.h> +#include <qpushbutton.h> +#include <qscrollview.h> +#include <qsize.h> +#include <qspinbox.h> +#include <qstring.h> +#include <qtooltip.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +EventEditDialog::EventEditDialog(QWidget *parent, + const Event &event, + bool editable) : + KDialogBase(parent, 0, true, i18n(editable ? "Advanced Event Edit" : "Advanced Event Viewer"), + (editable ? (Ok | Cancel) : Ok)), + m_durationDisplay(0), + m_durationDisplayAux(0), + m_persistentGrid(0), + m_nonPersistentGrid(0), + m_nonPersistentView(0), + m_originalEvent(event), + m_event(event), + m_type(event.getType()), + m_absoluteTime(event.getAbsoluteTime()), + m_duration(event.getDuration()), + m_subOrdering(event.getSubOrdering()), + m_modified(false) +{ + QVBox *vbox = makeVBoxMainWidget(); + + QGroupBox *intrinsicBox = new QGroupBox + (1, Horizontal, i18n("Intrinsics"), vbox); + + QGrid *intrinsicGrid = new QGrid(4, QGrid::Horizontal, intrinsicBox); + + new QLabel(i18n("Event type: "), intrinsicGrid); + new QLabel("", intrinsicGrid); + new QLabel("", intrinsicGrid); + QLineEdit *lineEdit = new QLineEdit(intrinsicGrid); + lineEdit->setText(strtoqstr(event.getType())); + + new QLabel(i18n("Absolute time: "), intrinsicGrid); + new QLabel("", intrinsicGrid); + new QLabel("", intrinsicGrid); + QSpinBox *absoluteTime = new QSpinBox + (INT_MIN, INT_MAX, Note(Note::Shortest).getDuration(), intrinsicGrid); + absoluteTime->setValue(event.getAbsoluteTime()); + QObject::connect(absoluteTime, SIGNAL(valueChanged(int)), + this, SLOT(slotAbsoluteTimeChanged(int))); + slotAbsoluteTimeChanged(event.getAbsoluteTime()); + + new QLabel(i18n("Duration: "), intrinsicGrid); + m_durationDisplay = new QLabel("(note)", intrinsicGrid); + m_durationDisplay->setMinimumWidth(20); + m_durationDisplayAux = new QLabel("(note)", intrinsicGrid); + m_durationDisplayAux->setMinimumWidth(20); + + QSpinBox *duration = new QSpinBox + (0, INT_MAX, Note(Note::Shortest).getDuration(), intrinsicGrid); + duration->setValue(event.getDuration()); + QObject::connect(duration, SIGNAL(valueChanged(int)), + this, SLOT(slotDurationChanged(int))); + slotDurationChanged(event.getDuration()); + + new QLabel(i18n("Sub-ordering: "), intrinsicGrid); + new QLabel("", intrinsicGrid); + new QLabel("", intrinsicGrid); + + QSpinBox *subOrdering = new QSpinBox( -100, 100, 1, intrinsicGrid); + subOrdering->setValue(event.getSubOrdering()); + QObject::connect(subOrdering, SIGNAL(valueChanged(int)), + this, SLOT(slotSubOrderingChanged(int))); + slotSubOrderingChanged(event.getSubOrdering()); + + QGroupBox *persistentBox = new QGroupBox + (1, Horizontal, i18n("Persistent properties"), vbox); + m_persistentGrid = new QGrid(4, QGrid::Horizontal, persistentBox); + + QLabel *label = new QLabel(i18n("Name"), m_persistentGrid); + QFont font(label->font()); + font.setItalic(true); + label->setFont(font); + + label = new QLabel(i18n("Type"), m_persistentGrid); + label->setFont(font); + label = new QLabel(i18n("Value"), m_persistentGrid); + label->setFont(font); + label = new QLabel("", m_persistentGrid); + label->setFont(font); + + Event::PropertyNames p = event.getPersistentPropertyNames(); + + for (Event::PropertyNames::iterator i = p.begin(); + i != p.end(); ++i) { + addPersistentProperty(*i); + } + + p = event.getNonPersistentPropertyNames(); + + if (p.begin() == p.end()) { + m_nonPersistentView = 0; + m_nonPersistentGrid = 0; + } else { + + QGroupBox *nonPersistentBox = new QGroupBox + (1, Horizontal, i18n("Non-persistent properties"), vbox); + new QLabel(i18n("These are cached values, lost if the event is modified."), + nonPersistentBox); + + m_nonPersistentView = new QScrollView(nonPersistentBox); + //m_nonPersistentView->setHScrollBarMode(QScrollView::AlwaysOff); + m_nonPersistentView->setResizePolicy(QScrollView::AutoOneFit); + + m_nonPersistentGrid = new QGrid + (4, QGrid::Horizontal, m_nonPersistentView->viewport()); + m_nonPersistentView->addChild(m_nonPersistentGrid); + + m_nonPersistentGrid->setSpacing(4); + m_nonPersistentGrid->setMargin(5); + + label = new QLabel(i18n("Name "), m_nonPersistentGrid); + label->setFont(font); + label = new QLabel(i18n("Type "), m_nonPersistentGrid); + label->setFont(font); + label = new QLabel(i18n("Value "), m_nonPersistentGrid); + label->setFont(font); + label = new QLabel("", m_nonPersistentGrid); + label->setFont(font); + + for (Event::PropertyNames::iterator i = p.begin(); + i != p.end(); ++i) { + + new QLabel(strtoqstr(*i), m_nonPersistentGrid, strtoqstr(*i)); + new QLabel(strtoqstr(event.getPropertyTypeAsString(*i)), m_nonPersistentGrid, strtoqstr(*i)); + new QLabel(strtoqstr(event.getAsString(*i)), m_nonPersistentGrid, strtoqstr(*i)); + QPushButton *button = new QPushButton("P", m_nonPersistentGrid, strtoqstr(*i)); + button->setFixedSize(QSize(24, 24)); + QToolTip::add + (button, i18n("Make persistent")); + QObject::connect(button, SIGNAL(clicked()), + this, SLOT(slotPropertyMadePersistent())); + } + } +} + +void +EventEditDialog::addPersistentProperty(const PropertyName &name) +{ + QLabel *label = new QLabel(strtoqstr(name), m_persistentGrid, strtoqstr(name)); + label->show(); + label = new QLabel(strtoqstr(m_originalEvent.getPropertyTypeAsString(name)), + m_persistentGrid, strtoqstr(name)); + label->show(); + + PropertyType type(m_originalEvent.getPropertyType(name)); + switch (type) { + + case Int: { + int min = INT_MIN, max = INT_MAX; + // DMM - constrain program changes to a useful range of values + // Might other types have a similar need for such limits? + if (m_originalEvent.isa(ProgramChange::EventType)) { + min = 0; + max = 127; + } + QSpinBox *spinBox = new QSpinBox + (min, max, 1, m_persistentGrid, strtoqstr(name)); + spinBox->setValue(m_originalEvent.get<Int>(name)); + QObject::connect(spinBox, SIGNAL(valueChanged(int)), + this, SLOT(slotIntPropertyChanged(int))); + spinBox->show(); + break; + } +case UInt: { + int min = 0; + int max = UINT_MAX; + if (m_originalEvent.isa(ProgramChange::EventType)) { + min = 0; + max = 65535; + } + QSpinBox *spinBox = new QSpinBox + (min, max, 1, m_persistentGrid, strtoqstr(name)); + spinBox->setValue(m_originalEvent.get<UInt>(name)); + QObject::connect(spinBox, SIGNAL(valueChanged(int)), + this, SLOT(slotIntPropertyChanged(int))); + spinBox->show(); + break; + } + case RealTimeT: { + RealTime realTime = m_originalEvent.get<RealTimeT>(name); + + QHBox* hbox = new QHBox(m_persistentGrid); + + // seconds + // + QSpinBox *spinBox = new QSpinBox + (INT_MIN, INT_MAX, 1, + hbox, strtoqstr(name) + "%sec"); + spinBox->setValue(realTime.sec); + + QObject::connect(spinBox, SIGNAL(valueChanged(int)), + this, SLOT(slotRealTimePropertyChanged(int))); + + // nseconds + // + spinBox = new QSpinBox + (INT_MIN, INT_MAX, 1, + hbox, strtoqstr(name) + "%nsec"); + spinBox->setValue(realTime.nsec); + + QObject::connect(spinBox, SIGNAL(valueChanged(int)), + this, SLOT(slotRealTimePropertyChanged(int))); + spinBox->show(); + break; + } + + case Bool: { + QCheckBox *checkBox = new QCheckBox + ("", m_persistentGrid, strtoqstr(name)); + checkBox->setChecked(m_originalEvent.get<Bool>(name)); + QObject::connect(checkBox, SIGNAL(activated()), + this, SLOT(slotBoolPropertyChanged())); + checkBox->show(); + break; + } + + case String: { + QLineEdit *lineEdit = new QLineEdit + (strtoqstr(m_originalEvent.get<String>(name)), + m_persistentGrid, + strtoqstr(name)); + QObject::connect(lineEdit, SIGNAL(textChanged(const QString &)), + this, SLOT(slotStringPropertyChanged(const QString &))); + lineEdit->show(); + break; + } + } + + QPushButton *button = new QPushButton("X", m_persistentGrid, + strtoqstr(name)); + button->setFixedSize(QSize(24, 24)); + QToolTip::add + (button, i18n("Delete this property")); + QObject::connect(button, SIGNAL(clicked()), + this, SLOT(slotPropertyDeleted())); + button->show(); +} + +Event +EventEditDialog::getEvent() const +{ + return Event(m_event, m_absoluteTime, m_duration, m_subOrdering); +} + +void +EventEditDialog::slotEventTypeChanged(const QString &type) +{ + std::string t(qstrtostr(type)); + if (t != m_type) { + m_modified = true; + m_type = t; + } +} + +void +EventEditDialog::slotAbsoluteTimeChanged(int value) +{ + if (value == m_absoluteTime) + return ; + m_modified = true; + m_absoluteTime = value; +} + +void +EventEditDialog::slotDurationChanged(int value) +{ + timeT error = 0; + m_durationDisplay->setPixmap + (NotePixmapFactory::toQPixmap(m_notePixmapFactory.makeNoteMenuPixmap(timeT(value), error))); + + if (error >= value / 2) { + m_durationDisplayAux->setText("++ "); + } else if (error > 0) { + m_durationDisplayAux->setText("+ "); + } else if (error < 0) { + m_durationDisplayAux->setText("- "); + } else { + m_durationDisplayAux->setText(" "); + } + + if (timeT(value) == m_duration) + return ; + + m_modified = true; + m_duration = value; +} + +void +EventEditDialog::slotSubOrderingChanged(int value) +{ + if (value == m_subOrdering) + return ; + m_modified = true; + m_subOrdering = value; +} + +void +EventEditDialog::slotIntPropertyChanged(int value) +{ + const QObject *s = sender(); + const QSpinBox *spinBox = dynamic_cast<const QSpinBox *>(s); + if (!spinBox) + return ; + + m_modified = true; + QString propertyName = spinBox->name(); + m_event.set<Int>(qstrtostr(propertyName), value); +} + +void +EventEditDialog::slotRealTimePropertyChanged(int value) +{ + const QObject *s = sender(); + const QSpinBox *spinBox = dynamic_cast<const QSpinBox *>(s); + if (!spinBox) + return ; + + m_modified = true; + QString propertyFullName = spinBox->name(); + + QString propertyName = propertyFullName.section('%', 0, 0), + nsecOrSec = propertyFullName.section('%', 1, 1); + + RealTime realTime = m_event.get<RealTimeT>(qstrtostr(propertyName)); + + if (nsecOrSec == "sec") + realTime.sec = value; + else + realTime.nsec = value; + + m_event.set<Int>(qstrtostr(propertyName), value); +} + +void +EventEditDialog::slotBoolPropertyChanged() +{ + const QObject *s = sender(); + const QCheckBox *checkBox = dynamic_cast<const QCheckBox *>(s); + if (!checkBox) + return ; + + m_modified = true; + QString propertyName = checkBox->name(); + bool checked = checkBox->isChecked(); + + m_event.set<Bool>(qstrtostr(propertyName), checked); +} + +void +EventEditDialog::slotStringPropertyChanged(const QString &value) +{ + const QObject *s = sender(); + const QLineEdit *lineEdit = dynamic_cast<const QLineEdit *>(s); + if (!lineEdit) + return ; + + m_modified = true; + QString propertyName = lineEdit->name(); + m_event.set<String>(qstrtostr(propertyName), qstrtostr(value)); +} + +void +EventEditDialog::slotPropertyDeleted() +{ + const QObject *s = sender(); + const QPushButton *pushButton = dynamic_cast<const QPushButton *>(s); + if (!pushButton) + return ; + + QString propertyName = pushButton->name(); + + if (KMessageBox::warningContinueCancel + (this, + i18n("Are you sure you want to delete the \"%1\" property?\n\n" + "Removing necessary properties may cause unexpected behavior."). + arg(propertyName), + i18n("Edit Event"), + i18n("&Delete")) != KMessageBox::Continue) + return ; + + m_modified = true; + QObjectList *list = m_persistentGrid->queryList(0, propertyName, false); + QObjectListIt i(*list); + QObject *obj; + while ((obj = i.current()) != 0) { + ++i; + delete obj; + } + delete list; + + m_event.unset(qstrtostr(propertyName)); +} + +void +EventEditDialog::slotPropertyMadePersistent() +{ + const QObject *s = sender(); + const QPushButton *pushButton = dynamic_cast<const QPushButton *>(s); + if (!pushButton) + return ; + + QString propertyName = pushButton->name(); + + if (KMessageBox::warningContinueCancel + (this, + i18n("Are you sure you want to make the \"%1\" property persistent?\n\n" + "This could cause problems if it overrides a different " + "computed value later on."). + arg(propertyName), + i18n("Edit Event"), + i18n("Make &Persistent")) != KMessageBox::Continue) + return ; + + QObjectList *list = m_nonPersistentGrid->queryList(0, propertyName, false); + QObjectListIt i(*list); + QObject *obj; + while ((obj = i.current()) != 0) { + ++i; + delete obj; + } + delete list; + + m_modified = true; + addPersistentProperty(qstrtostr(propertyName)); + + PropertyType type = + m_originalEvent.getPropertyType(qstrtostr(propertyName)); + + switch (type) { + + case Int: + m_event.set<Int> + (qstrtostr(propertyName), + m_originalEvent.get<Int> + (qstrtostr(propertyName))); + break; + + case UInt: + m_event.set<UInt> + (qstrtostr(propertyName), + m_originalEvent.get<UInt> + (qstrtostr(propertyName))); + break; + + case RealTimeT: + m_event.set<RealTimeT> + (qstrtostr(propertyName), + m_originalEvent.get<RealTimeT> + (qstrtostr(propertyName))); + break; + + case Bool: + m_event.set<Bool> + (qstrtostr(propertyName), + m_originalEvent.get<Bool> + (qstrtostr(propertyName))); + break; + + case String: + m_event.set<String> + (qstrtostr(propertyName), + m_originalEvent.get<String> + (qstrtostr(propertyName))); + break; + } +} + +} +#include "EventEditDialog.moc" diff --git a/src/gui/dialogs/EventEditDialog.h b/src/gui/dialogs/EventEditDialog.h new file mode 100644 index 0000000..337a190 --- /dev/null +++ b/src/gui/dialogs/EventEditDialog.h @@ -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. +*/ + +#ifndef _RG_EVENTEDITDIALOG_H_ +#define _RG_EVENTEDITDIALOG_H_ + +#include "base/Event.h" +#include "gui/editors/notation/NotePixmapFactory.h" +#include <string> +#include <kdialogbase.h> + + +class QWidget; +class QString; +class QScrollView; +class QLabel; +class QGrid; + + +namespace Rosegarden +{ + +class PropertyName; + + +class EventEditDialog : public KDialogBase +{ + Q_OBJECT + +public: + /** + * Construct an event-edit dialog showing the properties of the + * given event. If editable is false, the user will not be allowed + * to modify the event; otherwise the event will be editable and + * the resulting edited version can subsequently be queried + * through getEvent(). + */ + EventEditDialog(QWidget *parent, + const Event &event, + bool editable = true); + + bool isModified() const { return m_modified; } + Event getEvent() const; + +public slots: + void slotEventTypeChanged(const QString &); + void slotAbsoluteTimeChanged(int value); + void slotDurationChanged(int value); + void slotSubOrderingChanged(int value); + + void slotIntPropertyChanged(int); + void slotRealTimePropertyChanged(int); + void slotBoolPropertyChanged(); + void slotStringPropertyChanged(const QString &); + + void slotPropertyDeleted(); + void slotPropertyMadePersistent(); + +protected: + void addPersistentProperty(const PropertyName &); + + //--------------- Data members --------------------------------- + NotePixmapFactory m_notePixmapFactory; + + QLabel *m_durationDisplay; + QLabel *m_durationDisplayAux; + + QGrid *m_persistentGrid; + QGrid *m_nonPersistentGrid; + + QScrollView *m_nonPersistentView; + + const Event &m_originalEvent; + Event m_event; + + std::string m_type; + timeT m_absoluteTime; + timeT m_duration; + int m_subOrdering; + + bool m_modified; +}; + +/* + * A simpler event editor for use by the EventView and MatrixView + * and people who want to remain sane. + */ + +} + +#endif diff --git a/src/gui/dialogs/EventFilterDialog.cpp b/src/gui/dialogs/EventFilterDialog.cpp new file mode 100644 index 0000000..7b0c15c --- /dev/null +++ b/src/gui/dialogs/EventFilterDialog.cpp @@ -0,0 +1,476 @@ +/* -*- 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> + + This file is Copyright 2003-2006 + D. Michael McIntyre <dmmcintyr@users.sourceforge.net> + + 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 "EventFilterDialog.h" + +#include "misc/Debug.h" +#include "base/BaseProperties.h" +#include "base/Event.h" +#include "base/NotationTypes.h" +#include "base/BasicQuantizer.h" +#include "gui/dialogs/PitchPickerDialog.h" +#include "gui/editors/notation/NotationStrings.h" +#include "gui/editors/notation/NotePixmapFactory.h" +#include "document/ConfigGroups.h" +#include <kapplication.h> +#include <kconfig.h> +#include <kdialogbase.h> +#include <klocale.h> +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qdialog.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpixmap.h> +#include <qpushbutton.h> +#include <qsizepolicy.h> +#include <qspinbox.h> +#include <qstring.h> +#include <qtooltip.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +EventFilterDialog::EventFilterDialog(QWidget* parent) + : KDialogBase(parent, "eventfilerdialog", true, i18n("Event Filter"), Ok | Cancel, Ok), + m_standardQuantizations(BasicQuantizer::getStandardQuantizations()) +{ + cfg = kapp->config(); + initDialog(); +} + +EventFilterDialog::~EventFilterDialog() +{ + // nothing here +} + +void +EventFilterDialog::initDialog() +{ + QVBox* mainWidget = makeVBoxMainWidget(); + + + //----------[ Note Filter Widgets ]------------------------- + + // Frame + QGroupBox* noteFrame = new QGroupBox(i18n("Note Events"), mainWidget); + QGridLayout* noteFrameLayout = new QGridLayout(noteFrame, 1, 1, 20, 6); + + // Labels + QLabel* pitchFromLabel = new QLabel(i18n("lowest:"), noteFrame); + noteFrameLayout->addWidget(pitchFromLabel, 0, 2); + + QLabel* pitchToLabel = new QLabel(i18n("highest:"), noteFrame); + noteFrameLayout->addWidget(pitchToLabel, 0, 4); + + QLabel* pitchLabel = new QLabel(i18n("Pitch:"), noteFrame); + noteFrameLayout->addWidget(pitchLabel, 1, 1); + + QLabel* velocityLabel = new QLabel(i18n("Velocity:"), noteFrame); + noteFrameLayout->addWidget(velocityLabel, 2, 1); + + QLabel* durationLabel = new QLabel(i18n("Duration:"), noteFrame); + noteFrameLayout->addWidget(durationLabel, 3, 1); + + // Include Boxes + m_notePitchIncludeComboBox = new QComboBox(0, noteFrame); + m_notePitchIncludeComboBox->insertItem(i18n("include")); + m_notePitchIncludeComboBox->insertItem(i18n("exclude")); + cfg->setGroup(EventFilterDialogConfigGroup); + m_notePitchIncludeComboBox->setCurrentItem(cfg->readBoolEntry("pitchinclude", 0)); + noteFrameLayout->addWidget(m_notePitchIncludeComboBox, 1, 0); + + m_noteVelocityIncludeComboBox = new QComboBox(0, noteFrame); + m_noteVelocityIncludeComboBox->insertItem(i18n("include")); + m_noteVelocityIncludeComboBox->insertItem(i18n("exclude")); + cfg->setGroup(EventFilterDialogConfigGroup); + m_noteVelocityIncludeComboBox->setCurrentItem(cfg->readBoolEntry("velocityinclude", 0)); + noteFrameLayout->addWidget(m_noteVelocityIncludeComboBox, 2, 0); + + m_noteDurationIncludeComboBox = new QComboBox(0, noteFrame); + m_noteDurationIncludeComboBox->insertItem(i18n("include")); + m_noteDurationIncludeComboBox->insertItem(i18n("exclude")); + cfg->setGroup(EventFilterDialogConfigGroup); + m_noteDurationIncludeComboBox->setCurrentItem(cfg->readBoolEntry("durationinclude", 0)); + noteFrameLayout->addWidget(m_noteDurationIncludeComboBox, 3, 0); + + // Pitch From + m_pitchFromSpinBox = new QSpinBox(noteFrame); + m_pitchFromSpinBox->setMaxValue(127); + cfg->setGroup(EventFilterDialogConfigGroup); + m_pitchFromSpinBox->setValue(cfg->readUnsignedNumEntry("pitchfrom", 0)); + noteFrameLayout->addWidget(m_pitchFromSpinBox, 1, 2); + connect(m_pitchFromSpinBox, SIGNAL(valueChanged(int)), + SLOT(slotPitchFromChanged(int))); + + m_pitchFromChooserButton = new QPushButton(i18n("edit"), noteFrame); + m_pitchFromChooserButton->setSizePolicy(QSizePolicy((QSizePolicy::SizeType)0, + (QSizePolicy::SizeType)0, 0, 0, m_pitchFromChooserButton-> + sizePolicy().hasHeightForWidth())); + QToolTip::add + (m_pitchFromChooserButton, i18n("choose a pitch using a staff")); + noteFrameLayout->addWidget(m_pitchFromChooserButton, 1, 3); + connect(m_pitchFromChooserButton, SIGNAL(clicked()), + SLOT(slotPitchFromChooser())); + + // Pitch To + m_pitchToSpinBox = new QSpinBox(noteFrame); + m_pitchToSpinBox->setMaxValue(127); + cfg->setGroup(EventFilterDialogConfigGroup); + m_pitchToSpinBox->setValue(cfg->readUnsignedNumEntry("pitchto", 127)); + noteFrameLayout->addWidget(m_pitchToSpinBox, 1, 4); + connect(m_pitchToSpinBox, SIGNAL(valueChanged(int)), + SLOT(slotPitchToChanged(int))); + + m_pitchToChooserButton = new QPushButton(i18n("edit"), noteFrame); + QToolTip::add + (m_pitchToChooserButton, i18n("choose a pitch using a staff")); + noteFrameLayout->addWidget(m_pitchToChooserButton, 1, 5); + connect(m_pitchToChooserButton, SIGNAL(clicked()), + SLOT(slotPitchToChooser())); + + // Velocity From/To + m_velocityFromSpinBox = new QSpinBox(noteFrame); + m_velocityFromSpinBox->setMaxValue(127); + cfg->setGroup(EventFilterDialogConfigGroup); + m_velocityFromSpinBox->setValue(cfg->readUnsignedNumEntry("velocityfrom", 0)); + noteFrameLayout->addWidget(m_velocityFromSpinBox, 2, 2); + connect(m_velocityFromSpinBox, SIGNAL(valueChanged(int)), + SLOT(slotVelocityFromChanged(int))); + + m_velocityToSpinBox = new QSpinBox(noteFrame); + m_velocityToSpinBox->setMaxValue(127); + cfg->setGroup(EventFilterDialogConfigGroup); + m_velocityToSpinBox->setValue(cfg->readUnsignedNumEntry("velocityto", 127)); + noteFrameLayout->addWidget( m_velocityToSpinBox, 2, 4 ); + connect(m_velocityToSpinBox, SIGNAL(valueChanged(int)), + SLOT(slotVelocityToChanged(int))); + + + // Duration From/To + m_noteDurationFromComboBox = new QComboBox(0, noteFrame); + m_noteDurationFromComboBox->insertItem(i18n("longest")); + noteFrameLayout->addWidget(m_noteDurationFromComboBox, 3, 2); + connect(m_noteDurationFromComboBox, SIGNAL(activated(int)), + SLOT(slotDurationFromChanged(int))); + + m_noteDurationToComboBox = new QComboBox(0, noteFrame); + m_noteDurationToComboBox->insertItem(i18n("longest")); + noteFrameLayout->addWidget(m_noteDurationToComboBox, 3, 4); + connect(m_noteDurationToComboBox, SIGNAL(activated(int)), + SLOT(slotDurationToChanged(int))); + + populateDurationCombos(); + + + //---------[ Buttons ]-------------------------------------- + QFrame* privateLayoutWidget = new QFrame(mainWidget); + QGridLayout* buttonLayout = new QGridLayout(privateLayoutWidget, 1, 1, 20, 6); + + m_buttonAll = new QPushButton(i18n("Include all"), privateLayoutWidget); + m_buttonAll->setAutoDefault(true); + QToolTip::add + (m_buttonAll, i18n("Include entire range of values")); + buttonLayout->addWidget( m_buttonAll, 0, 0 ); + + m_buttonNone = new QPushButton(i18n("Exclude all"), privateLayoutWidget); + m_buttonNone->setAutoDefault(true); + QToolTip::add + (m_buttonNone, i18n("Exclude entire range of values")); + buttonLayout->addWidget( m_buttonNone, 0, 1 ); + + connect(m_buttonAll, SIGNAL(clicked()), this, SLOT(slotToggleAll())); + connect(m_buttonNone, SIGNAL(clicked()), this, SLOT(slotToggleNone())); + + +} + +void +EventFilterDialog::populateDurationCombos() +{ + QPixmap noMap = NotePixmapFactory::toQPixmap + (NotePixmapFactory::makeToolbarPixmap("menu-no-note")); + + for (unsigned int i = 0; i < m_standardQuantizations.size(); ++i) { + timeT time = m_standardQuantizations[i]; + timeT error = 0; + QString label = NotationStrings::makeNoteMenuLabel(time, true, error); + QPixmap pmap = NotePixmapFactory::toQPixmap + (NotePixmapFactory::makeNoteMenuPixmap(time, error)); + m_noteDurationFromComboBox->insertItem(error ? noMap : pmap, label); + m_noteDurationToComboBox ->insertItem(error ? noMap : pmap, label); + } + m_noteDurationFromComboBox->insertItem(noMap, i18n("shortest")); + m_noteDurationToComboBox->insertItem(noMap, i18n("shortest")); + + cfg->setGroup(EventFilterDialogConfigGroup); + m_noteDurationFromComboBox->setCurrentItem( + cfg->readUnsignedNumEntry("durationfrom", 0)); + m_noteDurationToComboBox->setCurrentItem( + cfg->readUnsignedNumEntry("durationto", (m_noteDurationToComboBox->count() - 1))); +} + +void +EventFilterDialog::slotToggleAll() +{ + RG_DEBUG << "EventFilterDialog::slotToggleAll()" << endl; + m_pitchFromSpinBox ->setValue(0); + m_pitchToSpinBox ->setValue(127); + m_velocityFromSpinBox ->setValue(0); + m_velocityToSpinBox ->setValue(127); + m_noteDurationFromComboBox ->setCurrentItem(11); // hard coded; should be variable + m_noteDurationToComboBox ->setCurrentItem(0); // 0 = unlimited; 11 = 0 +} + +void +EventFilterDialog::slotToggleNone() +{ + RG_DEBUG << "EventFilterDialog::slotToggleNone()" << endl; + m_pitchFromSpinBox ->setValue(0); + m_pitchToSpinBox ->setValue(0); + m_velocityFromSpinBox ->setValue(0); + m_velocityToSpinBox ->setValue(0); + m_noteDurationFromComboBox ->setCurrentItem(11); + m_noteDurationToComboBox ->setCurrentItem(11); +} + +void +EventFilterDialog::slotOk() +{ + cfg->setGroup(EventFilterDialogConfigGroup); + + cfg->writeEntry("pitchinclude", m_notePitchIncludeComboBox->currentItem()); + cfg->writeEntry("pitchfrom", m_pitchFromSpinBox->value()); + cfg->writeEntry("pitchto", m_pitchToSpinBox->value()); + + cfg->writeEntry("velocityinclude", m_noteVelocityIncludeComboBox->currentItem()); + cfg->writeEntry("velocityfrom", m_velocityFromSpinBox->value()); + cfg->writeEntry("velocityto", m_velocityToSpinBox->value()); + + cfg->writeEntry("durationinclude", m_noteDurationIncludeComboBox->currentItem()); + cfg->writeEntry("durationfrom", m_noteDurationFromComboBox->currentItem()); + cfg->writeEntry("durationto", m_noteDurationToComboBox->currentItem()); + + accept(); +} + +void +EventFilterDialog::slotPitchFromChanged(int pitch) +{ + if (pitch > m_pitchToSpinBox->value()) + m_pitchToSpinBox->setValue(pitch); +} + +void +EventFilterDialog::slotPitchToChanged(int pitch) +{ + if (pitch < m_pitchFromSpinBox->value()) + m_pitchFromSpinBox->setValue(pitch); +} + +void +EventFilterDialog::slotVelocityFromChanged(int velocity) +{ + if (velocity > m_velocityToSpinBox->value()) + m_velocityToSpinBox->setValue(velocity); +} + +void +EventFilterDialog::slotVelocityToChanged(int velocity) +{ + if (velocity < m_velocityFromSpinBox->value()) + m_velocityFromSpinBox->setValue(velocity); +} + +void +EventFilterDialog::slotDurationFromChanged(int index) +{ + if (index < m_noteDurationToComboBox->currentItem()) + m_noteDurationToComboBox->setCurrentItem(index); +} + +void +EventFilterDialog::slotDurationToChanged(int index) +{ + if (index > m_noteDurationFromComboBox->currentItem()) + m_noteDurationFromComboBox->setCurrentItem(index); +} + + +void +EventFilterDialog::slotPitchFromChooser() +{ + PitchPickerDialog dialog(this, m_pitchFromSpinBox->value(), i18n("Lowest pitch")); + + if (dialog.exec() == QDialog::Accepted) { + m_pitchFromSpinBox->setValue(dialog.getPitch()); + } +} + +void +EventFilterDialog::slotPitchToChooser() +{ + PitchPickerDialog dialog(this, m_pitchToSpinBox->value(), i18n("Highest pitch")); + + if (dialog.exec() == QDialog::Accepted) { + m_pitchToSpinBox->setValue(dialog.getPitch()); + } +} + +long +EventFilterDialog::getDurationFromIndex(int index) +{ + switch (index) { + // 0 + case 11: + return 0; + // 1/96 + case 10: + return long(Note(Note::SixtyFourthNote).getDuration() / 3); + // 1/64 + case 9 : + return long(Note(Note::SixtyFourthNote).getDuration()); + // 1/48 + case 8 : + return long(Note(Note::ThirtySecondNote).getDuration() / 3); + // 1/32 + case 7 : + return long(Note(Note::ThirtySecondNote).getDuration()); + // 1/24 + case 6 : + return long(Note(Note::SixteenthNote).getDuration() / 3); + // 1/16 + case 5 : + return long(Note(Note::SixteenthNote).getDuration()); + // 1/8 + case 4 : + return long(Note(Note::EighthNote).getDuration()); + // 1/4 + case 3 : + return long(Note(Note::QuarterNote).getDuration()); + // 1/2 + case 2 : + return long(Note(Note::HalfNote).getDuration()); + // 1/1 + case 1 : + return long(Note(Note::WholeNote).getDuration()); + // unlimited + case 0 : + return LONG_MAX; + } + // failsafe + return LONG_MAX; +} + +void +EventFilterDialog::invert(EventFilterDialog::filterRange &foo) +{ + long c = foo.first; + foo.first = foo.second; + foo.second = c; +} + +EventFilterDialog::filterRange +EventFilterDialog::getPitch() +{ + EventFilterDialog::filterRange foo; + foo.first = m_pitchFromSpinBox->value(); + foo.second = m_pitchToSpinBox ->value(); + if (!pitchIsInclusive()) + invert(foo); + return foo; +} + +EventFilterDialog::filterRange +EventFilterDialog::getVelocity() +{ + EventFilterDialog::filterRange foo; + foo.first = m_velocityFromSpinBox->value(); + foo.second = m_velocityToSpinBox ->value(); + if (!velocityIsInclusive()) + invert(foo); + return foo; +} + +EventFilterDialog::filterRange +EventFilterDialog::getDuration() +{ + EventFilterDialog::filterRange foo; + foo.first = getDurationFromIndex(m_noteDurationFromComboBox->currentItem()); + foo.second = getDurationFromIndex(m_noteDurationToComboBox ->currentItem()); + if (!durationIsInclusive()) + invert(foo); + return foo; +} + +bool +EventFilterDialog::keepEvent(Event* const &e) +{ + if ((*e).isa(Note::EventType)) { + long property = 0; + + // pitch + (*e).get<Int>(BaseProperties::PITCH, property); + if (!eventInRange(getPitch(), property)) { + RG_DEBUG << "EventFilterDialog::keepEvent(): rejecting event; pitch " << property + << " out of range." << endl; + return false; + } + property = 0; + + // velocity + (*e).get<Int>(BaseProperties::VELOCITY, property); + if (!EventFilterDialog::eventInRange(getVelocity(), property)) { + RG_DEBUG << "EventFilterDialog::keepEvent(): rejecting event; velocity " << property + << " out of range." << endl; + return false; + } + property = 0; + + // duration + property = (*e).getNotationDuration(); + if (!EventFilterDialog::eventInRange(getDuration(), property)) { + RG_DEBUG << "EventFilterDialog::keepEvent(): rejecting event; duration " << property + << " out of range." << endl; + return false; + } + property = 0; + + return true; + } + return false; +} + +} + +#include "EventFilterDialog.moc" diff --git a/src/gui/dialogs/EventFilterDialog.h b/src/gui/dialogs/EventFilterDialog.h new file mode 100644 index 0000000..0d3eb05 --- /dev/null +++ b/src/gui/dialogs/EventFilterDialog.h @@ -0,0 +1,170 @@ +/* -*- 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> + + This file is Copyright 2003-2006 + D. Michael McIntyre <dmmcintyr@users.sourceforge.net> + + 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_EVENTFILTERDIALOG_H_ +#define _RG_EVENTFILTERDIALOG_H_ + +#include <kdialogbase.h> +#include <utility> +#include <vector> +#include "base/Event.h" +#include <qcheckbox.h> +#include <qcombobox.h> + +class QWidget; +class QSpinBox; +class QPushButton; +class QGridLayout; +class KConfig; + + +namespace Rosegarden +{ + +class Event; + + +/** + * Creates a dialog box to allow the user to dial up various selection + * criteria used for removing events from a selection. It is up to the caller + * to actually manipulate the selection. After the dialog has been accepted, + * its filterEvent() method can be used to decide whether a particular event + * should continue to be selected. See matrixview.cpp slotFilterSelection() + * for an example of how to use this. + */ +class EventFilterDialog : public KDialogBase +{ + Q_OBJECT + +public: + + EventFilterDialog(QWidget* parent); + ~EventFilterDialog(); + + KConfig *cfg; + + //-------[ accessor functions ]------------------------ + + // NOTE: the filterRange type is used to return an A B pair with A and B set + // according to the state of the related include/exclude combo. If A > B + // then this is an inclusive range. If A < B then it's an exclusive + // range. This saves passing around a third variable. + typedef std::pair<long, long> filterRange; + + filterRange getPitch(); + filterRange getVelocity(); + filterRange getDuration(); + + // returns TRUE if the property value falls with in the filterRange + bool eventInRange(filterRange foo, long property) { + if (foo.first > foo.second) + return (property <= foo.second || property >= foo.first); + else + return (property >= foo.first && property <= foo.second); } + + // Used to do the work of deciding whether to keep or reject an event + // based on the state of the dialog's widgets. Returns TRUE if an event + // should continue to be selected. This method is the heart of the + // EventFilterDialog's public interface. + bool keepEvent(Event* const &e); + +protected: + + //--------[ member functions ]------------------------- + + // initialize the dialog + void initDialog(); + + // populate the duration combos + void populateDurationCombos(); + + // convert duration from combobox index into actual RG duration + // between 0 and LONG_MAX + long getDurationFromIndex(int index); + + // simple A B swap used to flip inclusive/exclusive values + void invert (filterRange &); + + // return inclusive/exclusive toggle states concisely for tidy code + bool pitchIsInclusive() { return (m_notePitchIncludeComboBox->currentItem() == 0); } + bool velocityIsInclusive() { return (m_noteVelocityIncludeComboBox->currentItem() == 0); } + bool durationIsInclusive() { return (m_noteDurationIncludeComboBox->currentItem() == 0); } + +protected slots: + + // set widget values to include everything + void slotToggleAll(); + + // set widget values to include nothing + void slotToggleNone(); + + // write out settings to kconfig data for next time and call accept() + virtual void slotOk(); + + // update note name text display and ensure From <= To + void slotPitchFromChanged(int pitch); + void slotPitchToChanged(int pitch); + + // ensure From <= To to guarantee a logical range for these sets + void slotVelocityFromChanged(int velocity); + void slotVelocityToChanged(int velocity); + void slotDurationFromChanged(int index); + void slotDurationToChanged(int index); + + // create a pitch chooser widget sub-dialog to show pitch on staff + void slotPitchFromChooser(); + void slotPitchToChooser(); + +private: + //---------[ data members ]----------------------------- + + QGridLayout* layout; + + QComboBox* m_noteDurationFromComboBox; + QComboBox* m_noteDurationIncludeComboBox; + QComboBox* m_noteDurationToComboBox; + QComboBox* m_notePitchIncludeComboBox; + QComboBox* m_noteVelocityIncludeComboBox; + + QPushButton* m_pitchFromChooserButton; + QPushButton* m_pitchToChooserButton; + QPushButton* m_buttonAll; + QPushButton* m_buttonNone; + + QSpinBox* m_pitchFromSpinBox; + QSpinBox* m_pitchToSpinBox; + QSpinBox* m_velocityFromSpinBox; + QSpinBox* m_velocityToSpinBox; + + std::vector<timeT> m_standardQuantizations; + +}; + + +} + +#endif diff --git a/src/gui/dialogs/EventParameterDialog.cpp b/src/gui/dialogs/EventParameterDialog.cpp new file mode 100644 index 0000000..036491e --- /dev/null +++ b/src/gui/dialogs/EventParameterDialog.cpp @@ -0,0 +1,185 @@ +/* -*- 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 "EventParameterDialog.h" + +#include <klocale.h> +#include "misc/Debug.h" +#include "misc/Strings.h" +#include "base/PropertyName.h" +#include <kcombobox.h> +#include <kdialogbase.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +EventParameterDialog::EventParameterDialog( + QWidget *parent, + const QString &name, + const PropertyName &property, + int startValue): + KDialogBase(parent, 0, true, name, Ok | Cancel), + m_property(property) +{ + QVBox *vBox = makeVBoxMainWidget(); + + QHBox *topBox = new QHBox(vBox); + QLabel *explainLabel = new QLabel(topBox); + QString text = i18n("Set the %1 property of the event selection:"). + arg(strtoqstr(property)); + explainLabel->setText(text); + + QHBox *patternBox = new QHBox(vBox); + new QLabel(i18n("Pattern"), patternBox); + m_patternCombo = new KComboBox(patternBox); + + // create options + // 0 flat + text = i18n("Flat - set %1 to value").arg(strtoqstr(property)); + m_patternCombo->insertItem(text); + + // 1 alternating + text = i18n("Alternating - set %1 to max and min on alternate events").arg(strtoqstr(property)); + m_patternCombo->insertItem(text); + + // 2 crescendo + text = i18n("Crescendo - set %1 rising from min to max").arg(strtoqstr(property)); + m_patternCombo->insertItem(text); + + // 3 diminuendo + text = i18n("Diminuendo - set %1 falling from max to min").arg(strtoqstr(property)); + m_patternCombo->insertItem(text); + + // 4 ringing + text = i18n("Ringing - set %1 alternating from max to min with both dying to zero").arg(strtoqstr(property)); + m_patternCombo->insertItem(text); + + connect(m_patternCombo, SIGNAL(activated(int)), + this, SLOT(slotPatternSelected(int))); + + QHBox *value1Box = new QHBox(vBox); + m_value1Label = new QLabel(i18n("Value"), value1Box); + m_value1Combo = new KComboBox(value1Box); + + QHBox *value2Box = new QHBox(vBox); + m_value2Label = new QLabel(i18n("Value"), value2Box); + m_value2Combo = new KComboBox(value2Box); + + for (unsigned int i = 0; i < 128; i++) { + m_value1Combo->insertItem(QString("%1").arg(i)); + m_value2Combo->insertItem(QString("%1").arg(i)); + } + m_value1Combo->setCurrentItem(127); + + slotPatternSelected(0); + + // start value + m_value1Combo->setCurrentItem(startValue); + m_value2Combo->setCurrentItem(startValue); + +} + +void +EventParameterDialog::slotPatternSelected(int value) +{ + switch (value) { + case 0: // flat + m_value1Label->setText(i18n("Value")); + m_value1Label->show(); + m_value1Combo->show(); + m_value2Label->hide(); + m_value2Combo->hide(); + break; + + case 1: // alternating + m_value1Label->setText(i18n("First Value")); + m_value2Label->setText(i18n("Second Value")); + m_value1Label->show(); + m_value1Combo->show(); + m_value2Label->show(); + m_value2Combo->show(); + break; + + case 2: // crescendo + m_value1Label->setText(i18n("Low Value")); + m_value2Label->setText(i18n("High Value")); + m_value1Label->show(); + m_value1Combo->show(); + m_value2Label->show(); + m_value2Combo->show(); + break; + + case 3: // decrescendo + m_value1Label->setText(i18n("High Value")); + m_value2Label->setText(i18n("Low Value")); + m_value1Label->show(); + m_value1Combo->show(); + m_value2Label->show(); + m_value2Combo->show(); + break; + + case 4: // ringing + m_value1Label->setText(i18n("First Value")); + m_value2Label->setText(i18n("Second Value")); + m_value1Label->show(); + m_value1Combo->show(); + m_value2Label->show(); + m_value2Combo->show(); + break; + + default: + RG_DEBUG << "EventParameterDialog::slotPatternSelected - " + << "unrecognised pattern number" << endl; + break; + } + +} + +PropertyPattern +EventParameterDialog::getPattern() +{ + return PropertyPattern(m_patternCombo->currentItem()); +} + +int +EventParameterDialog::getValue1() +{ + return m_value1Combo->currentItem(); +} + +int +EventParameterDialog::getValue2() +{ + return m_value2Combo->currentItem(); +} + +} +#include "EventParameterDialog.moc" diff --git a/src/gui/dialogs/EventParameterDialog.h b/src/gui/dialogs/EventParameterDialog.h new file mode 100644 index 0000000..040e2f9 --- /dev/null +++ b/src/gui/dialogs/EventParameterDialog.h @@ -0,0 +1,80 @@ + +/* -*- 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_EVENTPARAMETERDIALOG_H_ +#define _RG_EVENTPARAMETERDIALOG_H_ + +#include "base/PropertyName.h" +#include <kdialogbase.h> +#include "commands/edit/SelectionPropertyCommand.h" + +class QWidget; +class QString; +class QLabel; +class KComboBox; + + +namespace Rosegarden +{ + + + +class EventParameterDialog : public KDialogBase +{ + Q_OBJECT + +public: + EventParameterDialog(QWidget *parent, + const QString &name, // name + const PropertyName &property, // property + int startValue); // start + + int getValue1(); + int getValue2(); + PropertyPattern getPattern(); + +public slots: + void slotPatternSelected(int value); + +protected: + //--------------- Data members --------------------------------- + PropertyName m_property; + PropertyPattern m_pattern; + + KComboBox *m_value1Combo; + KComboBox *m_value2Combo; + KComboBox *m_patternCombo; + + QLabel *m_value1Label; + QLabel *m_value2Label; + +}; + + +// ---------------- CompositionLengthDialog ----------- + +} + +#endif diff --git a/src/gui/dialogs/ExportDeviceDialog.cpp b/src/gui/dialogs/ExportDeviceDialog.cpp new file mode 100644 index 0000000..ce5f52e --- /dev/null +++ b/src/gui/dialogs/ExportDeviceDialog.cpp @@ -0,0 +1,66 @@ +/* -*- 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 "ExportDeviceDialog.h" + +#include <klocale.h> +#include <kdialogbase.h> +#include <qbuttongroup.h> +#include <qlabel.h> +#include <qradiobutton.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +ExportDeviceDialog::ExportDeviceDialog(QWidget *parent, QString deviceName) : + KDialogBase(parent, "exportdevicedialog", true, i18n("Export Devices..."), + Ok | Cancel, Ok) +{ + QVBox *vbox = makeVBoxMainWidget(); + QButtonGroup *bg = new QButtonGroup(1, Qt::Horizontal, + i18n("Export devices"), + vbox); + m_exportAll = new QRadioButton(i18n("Export all devices"), bg); + m_exportOne = new QRadioButton(i18n("Export selected device only"), bg); + new QLabel(i18n(" (\"%1\")").arg(deviceName), bg); + + m_exportOne->setChecked(true); +} + +ExportDeviceDialog::ExportType + +ExportDeviceDialog::getExportType() +{ + if (m_exportAll->isChecked()) + return ExportAll; + else + return ExportOne; +} + +} diff --git a/src/gui/dialogs/ExportDeviceDialog.h b/src/gui/dialogs/ExportDeviceDialog.h new file mode 100644 index 0000000..21fc183 --- /dev/null +++ b/src/gui/dialogs/ExportDeviceDialog.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_EXPORTDEVICEDIALOG_H_ +#define _RG_EXPORTDEVICEDIALOG_H_ + +#include <kdialogbase.h> +#include <qstring.h> + + +class QWidget; +class QRadioButton; + + +namespace Rosegarden +{ + + + +class ExportDeviceDialog : public KDialogBase +{ +public: + enum ExportType { ExportOne, ExportAll }; + + ExportDeviceDialog(QWidget *parent, QString deviceName); + + ExportType getExportType(); + +protected: + QRadioButton *m_exportAll; + QRadioButton *m_exportOne; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/FileLocateDialog.cpp b/src/gui/dialogs/FileLocateDialog.cpp new file mode 100644 index 0000000..4f153c8 --- /dev/null +++ b/src/gui/dialogs/FileLocateDialog.cpp @@ -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. +*/ + + +#include "FileLocateDialog.h" + +#include <klocale.h> +#include "misc/Debug.h" +#include <kdialogbase.h> +#include <kfiledialog.h> +#include <qfileinfo.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qstring.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +FileLocateDialog::FileLocateDialog(QWidget *parent, + const QString &file, + const QString & /*path*/): + KDialogBase(parent, 0, true, + i18n("Locate audio file"), + User1 | User2 | User3, + Ok, + false, + i18n("&Skip"), + i18n("Skip &All"), + i18n("&Locate")), + m_file(file) +{ + QHBox *w = makeHBoxMainWidget(); + QString label = + i18n("Can't find file \"%1\".\n" + "Would you like to try and locate this file or skip it?").arg(m_file); + + QLabel *labelW = new QLabel(label, w); + labelW->setAlignment(Qt::AlignCenter); + labelW->setMinimumHeight(60); +} + +void +FileLocateDialog::slotUser3() +{ + if (!m_file.isEmpty()) { + m_file = KFileDialog::getOpenFileName + (":WAVS", + i18n("%1|Requested file (%2)\n*.wav|WAV files (*.wav)") + .arg(QFileInfo(m_file).fileName()) + .arg(QFileInfo(m_file).fileName()), + this, i18n("Select an Audio File")); + + RG_DEBUG << "FileLocateDialog::slotUser3() : m_file = " << m_file << endl; + + if (m_file.isEmpty()) { + RG_DEBUG << "FileLocateDialog::slotUser3() : reject\n"; + reject(); + } else { + QFileInfo fileInfo(m_file); + m_path = fileInfo.dirPath(); + accept(); + } + + } else + reject(); +} + +void +FileLocateDialog::slotUser1() +{ + reject(); +} + +void +FileLocateDialog::slotUser2() +{ + done( -1); +} + +} +#include "FileLocateDialog.moc" diff --git a/src/gui/dialogs/FileLocateDialog.h b/src/gui/dialogs/FileLocateDialog.h new file mode 100644 index 0000000..1786221 --- /dev/null +++ b/src/gui/dialogs/FileLocateDialog.h @@ -0,0 +1,66 @@ + +/* -*- 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_FILELOCATEDIALOG_H_ +#define _RG_FILELOCATEDIALOG_H_ + +#include <kdialogbase.h> +#include <qstring.h> + + +class QWidget; + + +namespace Rosegarden +{ + + + +class FileLocateDialog : public KDialogBase +{ + Q_OBJECT + +public: + FileLocateDialog(QWidget *parent, + const QString &file, + const QString &path); + + QString getDirectory() { return m_path; } + QString getFilename() { return m_file; } + +protected: + virtual void slotUser1(); + virtual void slotUser2(); + virtual void slotUser3(); + + QString m_file; + QString m_path; + +}; + + +} + +#endif diff --git a/src/gui/dialogs/FileMergeDialog.cpp b/src/gui/dialogs/FileMergeDialog.cpp new file mode 100644 index 0000000..d997327 --- /dev/null +++ b/src/gui/dialogs/FileMergeDialog.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 "FileMergeDialog.h" + +#include <klocale.h> +#include <kcombobox.h> +#include <kdialogbase.h> +#include <qcheckbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> +#include "document/RosegardenGUIDoc.h" + + +namespace Rosegarden +{ + +FileMergeDialog::FileMergeDialog(QWidget *parent, + QString /*fileName*/, + bool timingsDiffer) : + KDialogBase(parent, 0, true, i18n("Merge File"), Ok | Cancel | Help) +{ + setHelp("file-merge"); + + QVBox *vbox = makeVBoxMainWidget(); + + QHBox *hbox = new QHBox(vbox); + new QLabel(i18n("Merge new file "), hbox); + + m_choice = new KComboBox(hbox); + m_choice->insertItem(i18n("At start of existing composition")); + m_choice->insertItem(i18n("From end of existing composition")); + m_useTimings = 0; + + if (timingsDiffer) { + new QLabel(i18n("The file has different time signatures or tempos."), vbox); + m_useTimings = new QCheckBox(i18n("Import these as well"), vbox); + m_useTimings->setChecked(false); + } +} + +int +FileMergeDialog::getMergeOptions() +{ + int options = MERGE_KEEP_OLD_TIMINGS | MERGE_IN_NEW_TRACKS; + + if (m_choice->currentItem() == 1) { + options |= MERGE_AT_END; + } + + if (m_useTimings && m_useTimings->isChecked()) { + options |= MERGE_KEEP_NEW_TIMINGS; + } + + return options; +} + +} +#include "FileMergeDialog.moc" diff --git a/src/gui/dialogs/FileMergeDialog.h b/src/gui/dialogs/FileMergeDialog.h new file mode 100644 index 0000000..f305cae --- /dev/null +++ b/src/gui/dialogs/FileMergeDialog.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_FILEMERGEDIALOG_H_ +#define _RG_FILEMERGEDIALOG_H_ + +#include <kdialogbase.h> +#include <qstring.h> + + +class QWidget; +class QCheckBox; +class KComboBox; + + +namespace Rosegarden +{ + + + +class FileMergeDialog : public KDialogBase +{ + Q_OBJECT + +public: + FileMergeDialog(QWidget *parent, QString fileName, bool timingsDiffer); + + int getMergeOptions(); + +private: + KComboBox *m_choice; + QCheckBox *m_useTimings; +}; + + +// Locate a file +// + +} + +#endif diff --git a/src/gui/dialogs/FloatEdit.cpp b/src/gui/dialogs/FloatEdit.cpp new file mode 100644 index 0000000..06e8aa3 --- /dev/null +++ b/src/gui/dialogs/FloatEdit.cpp @@ -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. +*/ + + +#include "FloatEdit.h" + +#include "gui/widgets/HSpinBox.h" +#include <kdialogbase.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> +#include <cmath> + +namespace Rosegarden +{ + +FloatEdit::FloatEdit(QWidget *parent, + const QString &title, + const QString &text, + float min, + float max, + float value, + float step): + KDialogBase(parent, "rosegardenFloatEdit", true, title, Ok | Cancel, Ok) +{ + QVBox *vbox = makeVBoxMainWidget(); + QGroupBox *groupBox = new QGroupBox(1, Horizontal, text, vbox); + QVBox *inVbox = new QVBox(groupBox); + + // Calculate decimal points according to the step size + // + double calDP = log10(step); + int dps = 0; + if (calDP < 0.0) + dps = int( -calDP); + //std::cout << "CAL DP = " << calDP << ", dps = " << dps << std::endl; + + m_spin = new HSpinBox(inVbox, value, 1, min, max, dps); + new QLabel(QString("(min: %1, max: %2)").arg(min).arg(max), inVbox); +} + +float +FloatEdit::getValue() const +{ + return m_spin->valuef(); +} + +} +#include "FloatEdit.moc" diff --git a/src/gui/dialogs/FloatEdit.h b/src/gui/dialogs/FloatEdit.h new file mode 100644 index 0000000..24f1b2c --- /dev/null +++ b/src/gui/dialogs/FloatEdit.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_ROSEGARDENFLOATEDIT_H_ +#define _RG_ROSEGARDENFLOATEDIT_H_ + +#include <kdialogbase.h> + + +class QWidget; +class QString; +class QLabel; + + +namespace Rosegarden +{ + +class HSpinBox; + + +class FloatEdit : public KDialogBase +{ + Q_OBJECT + +public: + FloatEdit(QWidget *parent, + const QString &title, + const QString &text, + float min, + float max, + float value, + float step); + + float getValue() const; + +protected: + + QLabel *m_text; + HSpinBox *m_spin; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/IdentifyTextCodecDialog.cpp b/src/gui/dialogs/IdentifyTextCodecDialog.cpp new file mode 100644 index 0000000..07b5ec1 --- /dev/null +++ b/src/gui/dialogs/IdentifyTextCodecDialog.cpp @@ -0,0 +1,173 @@ +/* -*- 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 "IdentifyTextCodecDialog.h" + +#include <klocale.h> +#include "misc/Strings.h" +#include "base/NotationTypes.h" +#include <kcombobox.h> +#include <kdialogbase.h> +#include <qfont.h> +#include <qlabel.h> +#include <qstring.h> +#include <qtextcodec.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +IdentifyTextCodecDialog::IdentifyTextCodecDialog(QWidget *parent, + std::string text) : + KDialogBase(parent, 0, true, i18n("Choose Text Encoding"), Ok), + m_text(text) +{ + QVBox *vbox = makeVBoxMainWidget(); + new QLabel(i18n("\nThis file contains text in an unknown language encoding.\n\nPlease select one of the following estimated text encodings\nfor use with the text in this file:\n"), vbox); + + KComboBox *codecs = new KComboBox(vbox); + + std::string defaultCodec; + QTextCodec *cc = QTextCodec::codecForContent(text.c_str(), text.length()); + QTextCodec *codec = 0; + + std::cerr << "cc is " << (cc ? cc->name() : "null") << std::endl; + + std::map<std::string, QString> codecDescriptions; + codecDescriptions["SJIS"] = i18n("Japanese Shift-JIS"); + codecDescriptions["UTF-8"] = i18n("Unicode variable-width"); + codecDescriptions["ISO 8859-1"] = i18n("Western Europe"); + codecDescriptions["ISO 8859-15"] = i18n("Western Europe + Euro"); + codecDescriptions["ISO 8859-2"] = i18n("Eastern Europe"); + codecDescriptions["ISO 8859-3"] = i18n("Southern Europe"); + codecDescriptions["ISO 8859-4"] = i18n("Northern Europe"); + codecDescriptions["ISO 8859-5"] = i18n("Cyrillic"); + codecDescriptions["ISO 8859-6"] = i18n("Arabic"); + codecDescriptions["ISO 8859-7"] = i18n("Greek"); + codecDescriptions["ISO 8859-8"] = i18n("Hebrew"); + codecDescriptions["ISO 8859-9"] = i18n("Turkish"); + codecDescriptions["ISO 8859-10"] = i18n("Nordic"); + codecDescriptions["ISO 8859-11"] = i18n("Thai"); + codecDescriptions["ISO 8859-13"] = i18n("Baltic"); + codecDescriptions["ISO 8859-14"] = i18n("Celtic"); + codecDescriptions["SJIS"] = i18n("Japanese Shift-JIS"); + codecDescriptions["Big5"] = i18n("Traditional Chinese"); + codecDescriptions["GB18030"] = i18n("Simplified Chinese"); + codecDescriptions["KOI8-R"] = i18n("Russian"); + codecDescriptions["KOI8-U"] = i18n("Ukrainian"); + codecDescriptions["TSCII"] = i18n("Tamil"); + + int i = 0; + int current = -1; + + int selectedProbability = 0; + if (cc) { + selectedProbability = cc->heuristicContentMatch + (m_text.c_str(), m_text.length()); + } + + while ((codec = QTextCodec::codecForIndex(i)) != 0) { + + int probability = codec->heuristicContentMatch + (m_text.c_str(), m_text.length()); + + if (probability <= 0) { + ++i; + continue; + } + + std::string name = codec->name(); + + std::cerr << "codec " << name << " probability " << probability << std::endl; + + if (name == "UTF-8" && + (!cc || (cc->name() != name)) && + probability > selectedProbability/2) { + std::cerr << "UTF-8 has a decent probability, selecting it instead to promote global harmony" << std::endl; + cc = codec; + } + + QString description = codecDescriptions[name]; + if (description == "") { + if (strtoqstr(name).left(3) == "CP ") { + description = i18n("Microsoft Code Page %1"). + arg(strtoqstr(name).right(name.length() - 3)); + } + } + + if (description != "") { + description = i18n("%1 (%2)").arg(strtoqstr(name)).arg(description); + } else { + description = strtoqstr(name); + } + + codecs->insertItem(description, 0); + m_codecs.push_front(name); + if (current >= 0) ++current; + + if (cc && (name == cc->name())) { + current = 0; + } + + ++i; + } + + connect(codecs, SIGNAL(activated(int)), + this, SLOT(slotCodecSelected(int))); + + new QLabel(i18n("\nExample text from file:"), vbox); + m_example = new QLabel("", vbox); + QFont font; + font.setStyleHint(QFont::TypeWriter); + m_example->setFont(font); + m_example->setPaletteForegroundColor(Qt::blue); + std::cerr << "calling slotCodecSelected(" << current << ")" << std::endl; + if (current < 0) current = 0; + codecs->setCurrentItem(current); + slotCodecSelected(current); +} + +void +IdentifyTextCodecDialog::slotCodecSelected(int i) +{ +// std::cerr << "codec index = " << i << std::endl; + if (i < 0 || i >= m_codecs.size()) return; + std::string name = m_codecs[i]; +// std::cerr << "codecs: "; +// for (int j = 0; j < m_codecs.size(); ++j) std::cerr << m_codecs[j] << " "; +// std::cerr << std::endl; + QTextCodec *codec = QTextCodec::codecForName(strtoqstr(name)); + if (!codec) return; + m_codec = qstrtostr(codec->name()); + std::cerr << "Applying codec " << m_codec << std::endl; + QString outText = codec->toUnicode(m_text.c_str(), m_text.length()); + if (outText.length() > 80) outText = outText.left(80); + m_example->setText("\"" + outText + "\""); +} + +} +#include "IdentifyTextCodecDialog.moc" diff --git a/src/gui/dialogs/IdentifyTextCodecDialog.h b/src/gui/dialogs/IdentifyTextCodecDialog.h new file mode 100644 index 0000000..288cd17 --- /dev/null +++ b/src/gui/dialogs/IdentifyTextCodecDialog.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_IDENTIFYTEXTCODECDIALOG_H_ +#define _RG_IDENTIFYTEXTCODECDIALOG_H_ + +#include <string> +#include <kdialogbase.h> +#include <deque> + + +class QWidget; +class QLabel; + + +namespace Rosegarden +{ + + + +class IdentifyTextCodecDialog : public KDialogBase +{ + Q_OBJECT + +public: + IdentifyTextCodecDialog(QWidget *parent, std::string text); + + std::string getCodec() const { return m_codec; } + +protected slots: + void slotCodecSelected(int); + +protected: + std::string m_text; + std::string m_codec; + std::deque<std::string> m_codecs; + QLabel *m_example; +}; + + +/* + * Creates a small dialog box containing a PitchChooser widget. The + * info paramter provides extra information as a reminder what this particular + * picker is for, eg. Highest, Lowest, From, To + */ + +} + +#endif diff --git a/src/gui/dialogs/ImportDeviceDialog.cpp b/src/gui/dialogs/ImportDeviceDialog.cpp new file mode 100644 index 0000000..58a6ce5 --- /dev/null +++ b/src/gui/dialogs/ImportDeviceDialog.cpp @@ -0,0 +1,389 @@ +/* -*- 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 "ImportDeviceDialog.h" +#include <qlayout.h> +#include <kapplication.h> + +#include <klocale.h> +#include "misc/Strings.h" +#include "document/ConfigGroups.h" +#include "base/MidiDevice.h" +#include "base/MidiProgram.h" +#include "document/RosegardenGUIDoc.h" +#include "sound/SF2PatchExtractor.h" +#include <kcombobox.h> +#include <kconfig.h> +#include <kdialogbase.h> +#include <kmessagebox.h> +#include <kurl.h> +#include <kio/netaccess.h> +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qgroupbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qradiobutton.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +ImportDeviceDialog::ImportDeviceDialog(QWidget *parent, KURL url) : + KDialogBase(parent, "importdevicedialog", true, + i18n("Import from Device..."), + Ok | Cancel, Ok), + m_url(url), + m_fileDoc(0), + m_device(0) +{} + +ImportDeviceDialog::~ImportDeviceDialog() +{ + if (m_fileDoc) { + delete m_fileDoc; + } else { + delete m_device; + } +} + +bool +ImportDeviceDialog::doImport() +{ + QVBox *mainFrame = makeVBoxMainWidget(); + + if (m_url.isEmpty()) { + reject(); + return false; + } + + QString target; + if (KIO::NetAccess::download(m_url, target) == false) { + KMessageBox::error(this, i18n("Cannot download file %1").arg(m_url.prettyURL())); + return false; + } + + bool fileRead = false; + if (SF2PatchExtractor::isSF2File(target.data())) { + fileRead = importFromSF2(target); + } else { + fileRead = importFromRG(target); + } + if (!fileRead) { + KMessageBox::error + (this, i18n("Cannot open file %1").arg(m_url.prettyURL())); + reject(); + close(); + return false; + } + if (m_devices.size() == 0) { + KMessageBox::sorry + (this, i18n("No devices found in file %1").arg(m_url.prettyURL())); + reject(); + close(); + return false; + } + + QGroupBox *groupBox = new QGroupBox(2, Qt::Horizontal, + i18n("Source device"), + mainFrame); + + QHBox *deviceBox = new QHBox(groupBox); + QHBoxLayout *bl = new QHBoxLayout(deviceBox); + bl->addWidget(new QLabel(i18n("Import from: "), deviceBox)); + + bool showRenameOption = false; + + if (m_devices.size() > 1) { + m_deviceCombo = new KComboBox(deviceBox); + m_deviceLabel = 0; + bl->addWidget(m_deviceCombo); + } else { + m_deviceCombo = 0; + m_deviceLabel = new QLabel(deviceBox); + bl->addWidget(m_deviceLabel); + } + + bl->addStretch(10); + + int count = 1; + for (std::vector<MidiDevice *>::iterator i = m_devices.begin(); + i != m_devices.end(); ++i) { + if ((*i)->getName() != "") { + showRenameOption = true; + } else { + (*i)->setName(qstrtostr(i18n("Device %1").arg(count))); + } + if (m_devices.size() > 1) { + m_deviceCombo->insertItem(strtoqstr((*i)->getName())); + } else { + m_deviceLabel->setText(strtoqstr((*i)->getName())); + } + ++count; + } + + QHBox *optionsBox = new QHBox(mainFrame); + + QGroupBox *gb = new QGroupBox(1, Horizontal, i18n("Options"), + optionsBox); + + m_importBanks = new QCheckBox(i18n("Import banks"), gb); + m_importKeyMappings = new QCheckBox(i18n("Import key mappings"), gb); + m_importControllers = new QCheckBox(i18n("Import controllers"), gb); + + if (showRenameOption) { + m_rename = new QCheckBox(i18n("Import device name"), gb); + } else { + m_rename = 0; + } + + m_buttonGroup = new QButtonGroup(1, Qt::Horizontal, + i18n("Bank import behavior"), + optionsBox); + m_mergeBanks = new QRadioButton(i18n("Merge banks"), m_buttonGroup); + m_overwriteBanks = new QRadioButton(i18n("Overwrite banks"), m_buttonGroup); + + KConfig *config = kapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + + m_importBanks->setChecked(config->readBoolEntry("importbanks", true)); + m_importKeyMappings->setChecked(config->readBoolEntry("importkeymappings", true)); + m_importControllers->setChecked(config->readBoolEntry("importcontrollers", true)); + + bool rename = config->readBoolEntry("importbanksrename", true); + if (m_rename) + m_rename->setChecked(rename); + + bool overwrite = config->readBoolEntry("importbanksoverwrite", true); + if (overwrite) + m_buttonGroup->setButton(1); + else + m_buttonGroup->setButton(0); + + return true; +} + +void +ImportDeviceDialog::slotOk() +{ + int index = 0; + if (m_deviceCombo) + index = m_deviceCombo->currentItem(); + m_device = m_devices[index]; + + int v = m_buttonGroup->id(m_buttonGroup->selected()); + KConfig *config = kapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + config->writeEntry("importbanksoverwrite", v == 1); + if (m_rename) + config->writeEntry("importbanksrename", m_rename->isChecked()); + accept(); +} + +void +ImportDeviceDialog::slotCancel() +{ + reject(); +} + +std::string ImportDeviceDialog::getDeviceName() const +{ + return m_device->getName(); +} + +const BankList& ImportDeviceDialog::getBanks() const +{ + return m_device->getBanks(); +} + +const ProgramList& ImportDeviceDialog::getPrograms() const +{ + return m_device->getPrograms(); +} + +const KeyMappingList& ImportDeviceDialog::getKeyMappings() const +{ + return m_device->getKeyMappings(); +} + +const ControlList& ImportDeviceDialog::getControllers() const +{ + return m_device->getControlParameters(); +} + +std::string ImportDeviceDialog::getLibrarianName() const +{ + return m_device->getLibrarianName(); +} + +std::string ImportDeviceDialog::getLibrarianEmail() const +{ + return m_device->getLibrarianEmail(); +} + +MidiDevice::VariationType +ImportDeviceDialog::getVariationType() const +{ + return m_device->getVariationType(); +} + +bool +ImportDeviceDialog::shouldImportBanks() const +{ + return m_importBanks->isChecked(); +} + +bool +ImportDeviceDialog::shouldImportKeyMappings() const +{ + return m_importKeyMappings->isChecked(); +} + +bool +ImportDeviceDialog::shouldImportControllers() const +{ + return m_importControllers->isChecked(); +} + +bool +ImportDeviceDialog::shouldOverwriteBanks() const +{ + return m_buttonGroup->id(m_buttonGroup->selected()) != 0; +} + +bool +ImportDeviceDialog::shouldRename() const +{ + return m_rename ? m_rename->isChecked() : false; +} + +bool +ImportDeviceDialog::importFromRG(QString fileName) +{ + m_fileDoc = new RosegardenGUIDoc(RosegardenGUIApp::self(), 0, true); // skipAutoload + + // Add some dummy devices for bank population when we open the document. + // We guess that the file won't have more than 32 devices. + // + // for (unsigned int i = 0; i < 32; i++) { + // m_fileDoc->getStudio().addDevice("", i, Device::Midi); + // } + + if (!m_fileDoc->openDocument(fileName, false)) { + return false; + } + + m_devices.clear(); + + DeviceList *list = m_fileDoc->getStudio().getDevices(); + if (list->size() == 0) { + return true; // true because we successfully read the document + } + + for (DeviceListIterator it = list->begin(); + it != list->end(); ++it) { + + MidiDevice *device = + dynamic_cast<MidiDevice*>(*it); + + if (device) { + std::vector<MidiBank> banks = + device->getBanks(); + + // DMM - check for controllers too, because some users have + // created .rgd files that contain only controllers + // see bug #1183522 + // + std::vector<ControlParameter> controllers = + device->getControlParameters(); + + // We've got a bank on a Device fom this file + // (or a device that contains controllers or key mappings) + // + if (banks.size() || + controllers.size() || + device->getKeyMappings().size()) + m_devices.push_back(device); + } + } + + return true; +} + +bool +ImportDeviceDialog::importFromSF2(QString filename) +{ + SF2PatchExtractor::Device sf2device; + try { + sf2device = SF2PatchExtractor::read(filename.data()); + + // These exceptions shouldn't happen -- the isSF2File call before this + // one should have weeded them out + } catch (SF2PatchExtractor::FileNotFoundException e) { + return false; + } catch (SF2PatchExtractor::WrongFileFormatException e) { + return false; + } + + std::vector<MidiBank> banks; + std::vector<MidiProgram> programs; + + for (SF2PatchExtractor::Device::const_iterator i = sf2device.begin(); + i != sf2device.end(); ++i) { + + int bankNumber = i->first; + const SF2PatchExtractor::Bank &sf2bank = i->second; + + int msb = bankNumber / 128; + int lsb = bankNumber % 128; + + MidiBank bank + (msb == 1, msb, lsb, + qstrtostr(i18n("Bank %1:%2").arg(msb).arg(lsb))); + + banks.push_back(bank); + + for (SF2PatchExtractor::Bank::const_iterator j = sf2bank.begin(); + j != sf2bank.end(); ++j) { + + MidiProgram program(bank, j->first, j->second); + programs.push_back(program); + } + } + + MidiDevice *device = new MidiDevice + (0, "", MidiDevice::Play); + device->replaceBankList(banks); + device->replaceProgramList(programs); + m_devices.push_back(device); + + return true; +} + +} +#include "ImportDeviceDialog.moc" diff --git a/src/gui/dialogs/ImportDeviceDialog.h b/src/gui/dialogs/ImportDeviceDialog.h new file mode 100644 index 0000000..bb79e3b --- /dev/null +++ b/src/gui/dialogs/ImportDeviceDialog.h @@ -0,0 +1,110 @@ + +/* -*- 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_IMPORTDEVICEDIALOG_H_ +#define _RG_IMPORTDEVICEDIALOG_H_ + +#include "base/MidiDevice.h" +#include <string> +#include <kdialogbase.h> +#include <qstring.h> +#include <vector> +#include <kurl.h> + + +class QWidget; +class QRadioButton; +class QLabel; +class QCheckBox; +class QButtonGroup; +class ProgramList; +class KeyMappingList; +class KComboBox; +class ControlList; +class BankList; + + +namespace Rosegarden +{ + +class RosegardenGUIDoc; + + +class ImportDeviceDialog : public KDialogBase +{ + Q_OBJECT + +public: + ImportDeviceDialog(QWidget *parent, KURL url); + virtual ~ImportDeviceDialog(); + + bool doImport(); + + bool shouldImportBanks() const; + bool shouldImportKeyMappings() const; + bool shouldImportControllers() const; + bool shouldOverwriteBanks() const; + bool shouldRename() const; + + std::string getDeviceName() const; + const BankList &getBanks() const; + const ProgramList &getPrograms() const; + const KeyMappingList &getKeyMappings() const; + const ControlList &getControllers() const; + std::string getLibrarianName() const; + std::string getLibrarianEmail() const; + MidiDevice::VariationType getVariationType() const; + +public slots: + void slotOk(); + void slotCancel(); + +protected: + bool importFromRG(QString fileName); + bool importFromSF2(QString fileName); + + KURL m_url; + + KComboBox *m_deviceCombo; + QLabel *m_deviceLabel; + + QCheckBox *m_importBanks; + QCheckBox *m_importKeyMappings; + QCheckBox *m_importControllers; + QCheckBox *m_rename; + + QButtonGroup *m_buttonGroup; + QRadioButton *m_mergeBanks; + QRadioButton *m_overwriteBanks; + + RosegardenGUIDoc *m_fileDoc; + std::vector<MidiDevice *> m_devices; + MidiDevice *m_device; +}; + + +} + +#endif diff --git a/src/gui/dialogs/InterpretDialog.cpp b/src/gui/dialogs/InterpretDialog.cpp new file mode 100644 index 0000000..b11e3c4 --- /dev/null +++ b/src/gui/dialogs/InterpretDialog.cpp @@ -0,0 +1,123 @@ +/* -*- 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 "InterpretDialog.h" +#include <kapplication.h> + +#include <klocale.h> +#include "document/ConfigGroups.h" +#include "commands/notation/InterpretCommand.h" +#include <kconfig.h> +#include <kdialogbase.h> +#include <qcheckbox.h> +#include <qgroupbox.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +InterpretDialog::InterpretDialog(QWidget *parent) : + KDialogBase(parent, 0, true, i18n("Interpret"), Ok | Cancel | Help) +{ + setHelp("nv-interpret"); + + QVBox *vbox = makeVBoxMainWidget(); + QGroupBox *groupBox = new QGroupBox + (1, Horizontal, i18n("Interpretations to apply"), vbox); + + m_applyTextDynamics = new QCheckBox + (i18n("Apply text dynamics (p, mf, ff etc)"), groupBox); + m_applyHairpins = new QCheckBox + (i18n("Apply hairpin dynamics"), groupBox); + m_stressBeats = new QCheckBox + (i18n("Stress beats"), groupBox); + m_articulate = new QCheckBox + (i18n("Articulate slurs, staccato, tenuto etc"), groupBox); + m_allInterpretations = new QCheckBox + (i18n("All available interpretations"), groupBox); + + KConfig *config = kapp->config(); + config->setGroup(NotationViewConfigGroup); + + m_allInterpretations->setChecked + (config->readBoolEntry("interpretall", true)); + m_applyTextDynamics->setChecked + (config->readBoolEntry("interprettextdynamics", true)); + m_applyHairpins->setChecked + (config->readBoolEntry("interprethairpins", true)); + m_stressBeats->setChecked + (config->readBoolEntry("interpretstressbeats", true)); + m_articulate->setChecked + (config->readBoolEntry("interpretarticulate", true)); + + connect(m_allInterpretations, + SIGNAL(clicked()), this, SLOT(slotAllBoxChanged())); + + slotAllBoxChanged(); +} + +void +InterpretDialog::slotAllBoxChanged() +{ + bool all = m_allInterpretations->isChecked(); + m_applyTextDynamics->setEnabled(!all); + m_applyHairpins->setEnabled(!all); + m_stressBeats->setEnabled(!all); + m_articulate->setEnabled(!all); +} + +int +InterpretDialog::getInterpretations() +{ + KConfig *config = kapp->config(); + config->setGroup(NotationViewConfigGroup); + + config->writeEntry("interpretall", m_allInterpretations->isChecked()); + config->writeEntry("interprettextdynamics", m_applyTextDynamics->isChecked()); + config->writeEntry("interprethairpins", m_applyHairpins->isChecked()); + config->writeEntry("interpretstressbeats", m_stressBeats->isChecked()); + config->writeEntry("interpretarticulate", m_articulate->isChecked()); + + if (m_allInterpretations->isChecked()) { + return InterpretCommand::AllInterpretations; + } else { + int in = 0; + if (m_applyTextDynamics->isChecked()) + in |= InterpretCommand::ApplyTextDynamics; + if (m_applyHairpins->isChecked()) + in |= InterpretCommand::ApplyHairpins; + if (m_stressBeats->isChecked()) + in |= InterpretCommand::StressBeats; + if (m_articulate->isChecked()) { + in |= InterpretCommand::Articulate; + } + return in; + } +} + +} +#include "InterpretDialog.moc" diff --git a/src/gui/dialogs/InterpretDialog.h b/src/gui/dialogs/InterpretDialog.h new file mode 100644 index 0000000..75c8694 --- /dev/null +++ b/src/gui/dialogs/InterpretDialog.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_INTERPRETDIALOG_H_ +#define _RG_INTERPRETDIALOG_H_ + +#include <kdialogbase.h> + + +class QWidget; +class QCheckBox; + + +namespace Rosegarden +{ + + + +class InterpretDialog : public KDialogBase +{ + Q_OBJECT +public: + InterpretDialog(QWidget *parent); + + // an OR from InterpretCommand's constants + int getInterpretations(); + +protected slots: + void slotAllBoxChanged(); + +private: + QCheckBox *m_allInterpretations; + QCheckBox *m_applyTextDynamics; + QCheckBox *m_applyHairpins; + QCheckBox *m_stressBeats; + QCheckBox *m_articulate; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/IntervalDialog.cpp b/src/gui/dialogs/IntervalDialog.cpp new file mode 100644 index 0000000..061fc31 --- /dev/null +++ b/src/gui/dialogs/IntervalDialog.cpp @@ -0,0 +1,367 @@ +/* -*- 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 "IntervalDialog.h" +#include <qlayout.h> + +#include <iostream> +#include <klocale.h> +#include "misc/Strings.h" +#include "base/MidiDevice.h" +#include "base/NotationRules.h" +#include <kcombobox.h> +#include <kdialogbase.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qradiobutton.h> +#include <qbuttongroup.h> +#include <qsizepolicy.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +IntervalDialog::IntervalDialog(QWidget *parent, bool askChangeKey, bool askTransposeSegmentBack) : + KDialogBase(parent, 0, true, i18n("Specify Interval"), Ok | Cancel ) +{ + QVBox *vBox = makeVBoxMainWidget(); + + QHBox *hBox = new QHBox( vBox ); + + m_referencenote = new DiatonicPitchChooser( i18n("Reference note:"), hBox ); + m_targetnote = new DiatonicPitchChooser( i18n("Target note:"), hBox ); + + intervalChromatic = 0; + intervalDiatonic = 0; + + //m_intervalPitchLabel = new QLabel( i18n("Pitch: %1").arg(intervalChromatic), hBox); + //m_intervalOctavesLabel = new QLabel( i18n("Octaves: %1").arg(intervalDiatonic / 7), hBox); + //m_intervalStepsLabel = new QLabel( i18n("Steps: %1").arg(intervalDiatonic % 7), hBox); + + m_intervalLabel = new QLabel( i18n("a perfect unison"), vBox); + m_intervalLabel->setAlignment(Qt::AlignCenter); + QFont font(m_intervalLabel->font()); + font.setItalic(true); + m_intervalLabel->setFont(font); + + if (askChangeKey) + { + QButtonGroup *affectKeyGroup = new QButtonGroup(1, Horizontal, i18n("Effect on Key"), vBox); + m_transposeWithinKey = new QRadioButton(i18n("Transpose within key"), affectKeyGroup); + m_transposeWithinKey->setChecked(true); + m_transposeChangingKey = new QRadioButton(i18n("Change key for selection"), affectKeyGroup); + } + else + { + m_transposeChangingKey = NULL; + m_transposeWithinKey = NULL; + } + + if (askTransposeSegmentBack) + { + m_transposeSegmentBack = new QCheckBox( i18n("Adjust segment transposition in opposite direction (maintain audible pitch)"), vBox ); + m_transposeSegmentBack->setTristate(false); + m_transposeSegmentBack->setChecked(false); + } + else + { + m_transposeSegmentBack = NULL; + } + + connect(m_referencenote, SIGNAL(noteChanged(int,int,int)), + this, SLOT(slotSetReferenceNote(int,int,int))); + + connect(m_targetnote, SIGNAL(noteChanged(int,int,int)), + this, SLOT(slotSetTargetNote(int,int,int))); +} + +// number of octaves the notes are apart +int +IntervalDialog::getOctaveDistance() +{ + return m_targetnote->getOctave() - m_referencenote->getOctave(); +} + +// chromatic distance between the steps, not taking account octaves or +// accidentals +int +IntervalDialog::getStepDistanceChromatic() +{ + return scale_Cmajor[m_targetnote->getStep()] - scale_Cmajor[m_referencenote->getStep()]; + // - getChromaticStepValue(m_referencestep->currentItem()); + //return m_targetnote->getPitch() - m_referencenote->getPitch(); +} + +// correction due to accidentals +int +IntervalDialog::getAccidentalCorrectionChromatic() +{ + return m_targetnote->getAccidental() - m_referencenote->getAccidental(); +} + +int +IntervalDialog::getDiatonicDistance() +{ + return getOctaveDistance() * 7 + m_targetnote->getStep() - m_referencenote->getStep(); +} + +int +IntervalDialog::getChromaticDistance() +{ + return getOctaveDistance() * 12 + getStepDistanceChromatic() + getAccidentalCorrectionChromatic(); +} + +QString +IntervalDialog::getIntervalName(int intervalDiatonic, int intervalChromatic) +{ + // displayInterval: an intervalDiatonic of -3 will yield a displayInterval of 3 and + // set the boolean 'down' to true. + int displayIntervalDiatonic = intervalDiatonic; + int displayIntervalChromatic = intervalChromatic; + bool down = (intervalDiatonic < 0 || + (intervalDiatonic == 0 && + intervalChromatic < 0)); + if (down) + { + displayIntervalDiatonic = -displayIntervalDiatonic; + displayIntervalChromatic = -displayIntervalChromatic; + } + + int octaves = displayIntervalDiatonic / 7; + int deviation = displayIntervalChromatic % 12 - scale_Cmajor[displayIntervalDiatonic % 7]; + // Note (hjj): + // "1 octave and a diminished octave" is better than + // "2 octaves and a diminished unison" + if (displayIntervalDiatonic % 7 == 0) { + if (octaves > 0) { + deviation = (deviation < 5 ? deviation : deviation - 12); + } else if (octaves < 0) { + deviation = (deviation < 5 ? -deviation : 12 - deviation); + } + } else if (down) { + // Note (hjj): + // an augmented prime down, NOT a diminished prime down + deviation = -deviation; + } + + // show the step for an unison only if the octave doesn't change, any other interval + // always, and augmented/dimnished unisons (modulo octaves) always. + bool showStep = displayIntervalDiatonic == 0 || + displayIntervalDiatonic % 7 != 0 || deviation != 0; + + QString textInterval = ""; + QString textIntervalDeviated = ""; + if (showStep) + { + switch (displayIntervalDiatonic % 7) + { + // First the diminished/perfect/augmented: + case 0: // unison or octaves + case 3: // fourth + case 4: // fifth + if (deviation == -1) + textIntervalDeviated += i18n("a diminished"); + else if (deviation == 1) + textIntervalDeviated += i18n("an augmented"); + else if (deviation == -2) + textIntervalDeviated += i18n("a doubly diminished"); + else if (deviation == 2) + textIntervalDeviated += i18n("a doubly augmented"); + else if (deviation == -3) + textIntervalDeviated += i18n("a triply diminished"); + else if (deviation == 3) + textIntervalDeviated += i18n("a triply augmented"); + else if (deviation == -4) + textIntervalDeviated += i18n("a quadruply diminished"); + else if (deviation == 4) + textIntervalDeviated += i18n("a quadruply augmented"); + else if (deviation == 0) + textIntervalDeviated += i18n("a perfect"); + else + textIntervalDeviated += i18n("an (unknown, %1)").arg(deviation); + break; + // Then the major/minor: + case 1: // second + case 2: // third + case 5: // sixth + case 6: // seventh + if (deviation == -1) + textIntervalDeviated += i18n("a minor"); + else if (deviation == 0) + textIntervalDeviated += i18n("a major"); + else if (deviation == -2) + textIntervalDeviated += i18n("a diminished"); + else if (deviation == 1) + textIntervalDeviated += i18n("an augmented"); + else if (deviation == -3) + textIntervalDeviated += i18n("a doubly diminished"); + else if (deviation == 2) + textIntervalDeviated += i18n("a doubly augmented"); + else if (deviation == -4) + textIntervalDeviated += i18n("a triply diminished"); + else if (deviation == 3) + textIntervalDeviated += i18n("a triply augmented"); + else if (deviation == 4) + textIntervalDeviated += i18n("a quadruply augmented"); + else if (deviation == 0) + textIntervalDeviated += i18n("a perfect"); + else + textIntervalDeviated += i18n("an (unknown, %1)").arg(deviation); + break; + default: + textIntervalDeviated += i18n("an (unknown)"); + } + switch (displayIntervalDiatonic % 7) + { + case 0: + // Note (hjj): + // "1 octave and a diminished octave" is better than + // "2 octaves and a diminished unison" + if (octaves > 0) { + textInterval += i18n("%1 octave").arg(textIntervalDeviated); + octaves--; + } else if (octaves < 0) { + textInterval += i18n("%1 octave").arg(textIntervalDeviated); + octaves++; + } else { + textInterval += i18n("%1 unison").arg(textIntervalDeviated); + } + break; + case 1: + textInterval += i18n("%1 second").arg(textIntervalDeviated); + break; + case 2: + textInterval += i18n("%1 third").arg(textIntervalDeviated); + break; + case 3: + textInterval += i18n("%1 fourth").arg(textIntervalDeviated); + break; + case 4: + textInterval += i18n("%1 fifth").arg(textIntervalDeviated); + break; + case 5: + textInterval += i18n("%1 sixth").arg(textIntervalDeviated); + break; + case 6: + textInterval += i18n("%1 seventh").arg(textIntervalDeviated); + break; + default: + textInterval += i18n("%1").arg(textIntervalDeviated); + } + } + + if (displayIntervalChromatic != 0 || displayIntervalDiatonic != 0) + { + if (!down) + { + if (octaves != 0) { + if (showStep) { + return i18n("up 1 octave and %1", + "up %n octaves and %1", + octaves).arg(textInterval); + } else { + return i18n("up 1 octave", + "up %n octaves", + octaves); + } + } else { + return i18n("up %1").arg(textInterval); + } + } + else + { + if (octaves != 0) { + if (showStep) { + return i18n("down 1 octave and %1", + "down %n octaves and %1", + octaves).arg(textInterval); + } else { + return i18n("down 1 octave", + "down %n octaves", + octaves); + } + } else { + return i18n("down %1").arg(textInterval); + } + } + } else { + return i18n("a perfect unison"); + } +} + +void +IntervalDialog::slotSetTargetNote(int pitch, int octave, int step) +{ + intervalChromatic = pitch - m_referencenote->getPitch(); + intervalDiatonic = (octave * 7 + step) - (m_referencenote->getOctave() * 7 + m_referencenote->getStep()); + + m_intervalLabel->setText( getIntervalName( intervalDiatonic, intervalChromatic ) ); +} + +void +IntervalDialog::slotSetReferenceNote(int pitch, int octave, int step) +{ + // recalculate target note based on reference note and current interval + int pitch_new = pitch + intervalChromatic; + int diatonic_new = (octave * 7 + step) + intervalDiatonic; + int octave_new = diatonic_new / 7; + int step_new = diatonic_new % 7; + + m_targetnote->slotSetNote( pitch_new, octave_new, step_new ); +} + +bool +IntervalDialog::getChangeKey() +{ + if (m_transposeChangingKey == NULL) + { + return false; + } + else + { + return m_transposeChangingKey->isChecked(); + } +} + +bool +IntervalDialog::getTransposeSegmentBack() +{ + if (m_transposeSegmentBack == NULL) + { + return false; + } + else + { + return m_transposeSegmentBack->isChecked(); + } +} + +} +#include "IntervalDialog.moc" diff --git a/src/gui/dialogs/IntervalDialog.h b/src/gui/dialogs/IntervalDialog.h new file mode 100644 index 0000000..b9927d2 --- /dev/null +++ b/src/gui/dialogs/IntervalDialog.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_INTERVALDIALOG_H_ +#define _RG_INTERVALDIALOG_H_ + +#include <kdialogbase.h> +#include <vector> +#include "gui/application/RosegardenDCOP.h" +#include "gui/widgets/DiatonicPitchChooser.h" + + +class QWidget; +class KComboBox; +class QRadioButton; +class QCheckBox; + + +namespace Rosegarden +{ + +class RosegardenGUIDoc; + + +class IntervalDialog : public KDialogBase +{ + Q_OBJECT +public: + IntervalDialog(QWidget *parent, bool askChangeKey = false, bool askTransposeSegmentBack = false); + + // Distance in semitones + int getChromaticDistance(); + + // Distance in steps + int getDiatonicDistance(); + + // Transpose within key or change the key? + bool getChangeKey(); + + // Transpose the segment itself in the opposite direction? + bool getTransposeSegmentBack(); + + static QString getIntervalName(int intervalDiatonic, int intervalChromatic); + +public slots: + void slotSetReferenceNote(int,int,int); + void slotSetTargetNote(int,int,int); + +private: + int getOctaveDistance(); + int getStepDistanceChromatic(); + int getAccidentalCorrectionChromatic(); + + DiatonicPitchChooser *m_referencenote; + DiatonicPitchChooser *m_targetnote; + + QRadioButton *m_transposeWithinKey; + QRadioButton *m_transposeChangingKey; + bool changeKey; + + QCheckBox *m_transposeSegmentBack; + + int intervalChromatic; + int intervalDiatonic; + QLabel *m_intervalLabel; + +}; + + +} + +#endif diff --git a/src/gui/dialogs/KeySignatureDialog.cpp b/src/gui/dialogs/KeySignatureDialog.cpp new file mode 100644 index 0000000..c703c0a --- /dev/null +++ b/src/gui/dialogs/KeySignatureDialog.cpp @@ -0,0 +1,402 @@ +/* -*- 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 "KeySignatureDialog.h" + +#include <klocale.h> +#include "misc/Strings.h" +#include "base/NotationTypes.h" +#include "gui/editors/notation/NotePixmapFactory.h" +#include "gui/widgets/BigArrowButton.h" +#include <kcombobox.h> +#include <kdialogbase.h> +#include <qbuttongroup.h> +#include <qgroupbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qobject.h> +#include <qpixmap.h> +#include <qradiobutton.h> +#include <qstring.h> +#include <qtooltip.h> +#include <qvbox.h> +#include <qwidget.h> +#include <qcheckbox.h> +#include <algorithm> + +namespace Rosegarden +{ + +KeySignatureDialog::KeySignatureDialog(QWidget *parent, + NotePixmapFactory *npf, + Clef clef, + Rosegarden::Key defaultKey, + bool showApplyToAll, + bool showConversionOptions, + QString explanatoryText) : + KDialogBase(parent, 0, true, i18n("Key Change"), Ok | Cancel | Help), + m_notePixmapFactory(npf), + m_key(defaultKey), + m_clef(clef), + m_valid(true), + m_ignoreComboChanges(false), + m_explanatoryLabel(0), + m_applyToAllButton(0), + m_noPercussionCheckBox(0) +{ + setHelp("nv-signatures-key"); + + QVBox *vbox = makeVBoxMainWidget(); + + QHBox *keyBox = 0; + QHBox *nameBox = 0; + + QGroupBox *keyFrame = new QGroupBox + (1, Horizontal, i18n("Key signature"), vbox); + + QGroupBox *transposeFrame = new QButtonGroup + (1, Horizontal, i18n("Key transposition"), vbox); + + QGroupBox *buttonFrame = new QButtonGroup + (1, Horizontal, i18n("Scope"), vbox); + + QButtonGroup *conversionFrame = new QButtonGroup + (1, Horizontal, i18n("Existing notes following key change"), vbox); + + keyBox = new QHBox(keyFrame); + nameBox = new QHBox(keyFrame); + + QLabel *explanatoryLabel = 0; + if (explanatoryText) { + explanatoryLabel = new QLabel(explanatoryText, keyFrame); + } + + BigArrowButton *keyDown = new BigArrowButton(keyBox, Qt::LeftArrow); + QToolTip::add + (keyDown, i18n("Flatten")); + + m_keyLabel = new QLabel(i18n("Key"), keyBox); + m_keyLabel->setAlignment(AlignVCenter | AlignHCenter); + + BigArrowButton *keyUp = new BigArrowButton(keyBox, Qt::RightArrow); + QToolTip::add + (keyUp, i18n("Sharpen")); + + m_keyCombo = new KComboBox(nameBox); + m_majorMinorCombo = new KComboBox(nameBox); + m_majorMinorCombo->insertItem(i18n("Major")); + m_majorMinorCombo->insertItem(i18n("Minor")); + if (m_key.isMinor()) { + m_majorMinorCombo->setCurrentItem(m_majorMinorCombo->count() - 1); + } + + regenerateKeyCombo(); + redrawKeyPixmap(); + m_explanatoryLabel = explanatoryLabel; + + m_keyLabel->setMinimumWidth(m_keyLabel->pixmap()->width()); + m_keyLabel->setMinimumHeight(m_keyLabel->pixmap()->height()); + + m_yesTransposeButton = + new QRadioButton(i18n("Transpose key according to segment transposition"), + transposeFrame); + QRadioButton *noTransposeButton = + new QRadioButton(i18n("Use specified key. Do not transpose"), transposeFrame); + m_yesTransposeButton->setChecked(true); + + // just to shut up the compiler warning about unused variable: + noTransposeButton->setChecked(false); + + if (showApplyToAll) { + QRadioButton *applyToOneButton = + new QRadioButton(i18n("Apply to current segment only"), + buttonFrame); + m_applyToAllButton = + new QRadioButton(i18n("Apply to all segments at this time"), + buttonFrame); + applyToOneButton->setChecked(true); + m_noPercussionCheckBox = + new QCheckBox(i18n("Exclude percussion segments"), buttonFrame); + m_noPercussionCheckBox->setChecked(true); + + } else { + m_applyToAllButton = 0; + buttonFrame->hide(); + } + + if (showConversionOptions) { + m_noConversionButton = + new QRadioButton + (i18n("Maintain current pitches"), conversionFrame); + m_convertButton = + new QRadioButton + (i18n("Maintain current accidentals"), conversionFrame); + m_transposeButton = + new QRadioButton + (i18n("Transpose into this key"), conversionFrame); + m_noConversionButton->setChecked(true); + } else { + m_noConversionButton = 0; + m_convertButton = 0; + m_transposeButton = 0; + conversionFrame->hide(); + } + + QObject::connect(keyUp, SIGNAL(clicked()), this, SLOT(slotKeyUp())); + QObject::connect(keyDown, SIGNAL(clicked()), this, SLOT(slotKeyDown())); + QObject::connect(m_keyCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotKeyNameChanged(const QString &))); + QObject::connect(m_keyCombo, SIGNAL(textChanged(const QString &)), + this, SLOT(slotKeyNameChanged(const QString &))); + QObject::connect(m_majorMinorCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotMajorMinorChanged(const QString &))); +} + +KeySignatureDialog::ConversionType + +KeySignatureDialog::getConversionType() const +{ + if (m_noConversionButton && m_noConversionButton->isChecked()) { + return NoConversion; + } else if (m_convertButton && m_convertButton->isChecked()) { + return Convert; + } else if (m_transposeButton && m_transposeButton->isChecked()) { + return Transpose; + } + return NoConversion; +} + +bool +KeySignatureDialog::shouldApplyToAll() const +{ + return m_applyToAllButton && m_applyToAllButton->isChecked(); +} + +bool +KeySignatureDialog::shouldBeTransposed() const +{ + return m_yesTransposeButton && m_yesTransposeButton->isChecked(); +} + +bool +KeySignatureDialog::shouldIgnorePercussion() const +{ + return m_noPercussionCheckBox && m_noPercussionCheckBox->isChecked(); +} + +void +KeySignatureDialog::slotKeyUp() +{ + bool sharp = m_key.isSharp(); + int ac = m_key.getAccidentalCount(); + if (ac == 0) + sharp = true; + if (sharp) { + if (++ac > 7) + ac = 7; + } else { + if (--ac < 1) { + ac = 0; + sharp = true; + } + } + + try { + m_key = Rosegarden::Key(ac, sharp, m_key.isMinor()); + setValid(true); + } catch (Rosegarden::Key::BadKeySpec s) { + std::cerr << s.getMessage() << std::endl; + setValid(false); + } + + regenerateKeyCombo(); + redrawKeyPixmap(); +} + +void +KeySignatureDialog::slotKeyDown() +{ + bool sharp = m_key.isSharp(); + int ac = m_key.getAccidentalCount(); + if (ac == 0) + sharp = false; + if (sharp) { + if (--ac < 0) { + ac = 1; + sharp = false; + } + } else { + if (++ac > 7) + ac = 7; + } + + try { + m_key = Rosegarden::Key(ac, sharp, m_key.isMinor()); + setValid(true); + } catch (Rosegarden::Key::BadKeySpec s) { + std::cerr << s.getMessage() << std::endl; + setValid(false); + } + + regenerateKeyCombo(); + redrawKeyPixmap(); +} + +struct KeyNameComparator +{ + bool operator()(const Rosegarden::Key &k1, const Rosegarden::Key &k2) { + return (k1.getName() < k2.getName()); + } +}; + + +void +KeySignatureDialog::regenerateKeyCombo() +{ + if (m_explanatoryLabel) + m_explanatoryLabel->hide(); + + m_ignoreComboChanges = true; + QString currentText = m_keyCombo->currentText(); + Rosegarden::Key::KeyList keys(Rosegarden::Key::getKeys(m_key.isMinor())); + m_keyCombo->clear(); + + std::sort(keys.begin(), keys.end(), KeyNameComparator()); + bool textSet = false; + + for (Rosegarden::Key::KeyList::iterator i = keys.begin(); + i != keys.end(); ++i) { + + QString name(strtoqstr(i->getName())); + int space = name.find(' '); + if (space > 0) + name = name.left(space); + + m_keyCombo->insertItem(name); + + if (m_valid && (*i == m_key)) { + m_keyCombo->setCurrentItem(m_keyCombo->count() - 1); + textSet = true; + } + } + + if (!textSet) { + m_keyCombo->setEditText(currentText); + } + m_ignoreComboChanges = false; +} + +bool +KeySignatureDialog::isValid() const +{ + return m_valid; +} + +Rosegarden::Key +KeySignatureDialog::getKey() const +{ + return m_key; +} + +void +KeySignatureDialog::redrawKeyPixmap() +{ + if (m_valid) { + QPixmap pmap = + NotePixmapFactory::toQPixmap(m_notePixmapFactory->makeKeyDisplayPixmap(m_key, m_clef)); + m_keyLabel->setPixmap(pmap); + } else { + m_keyLabel->setText(i18n("No such key")); + } +} + +void +KeySignatureDialog::slotKeyNameChanged(const QString &s) +{ + if (m_ignoreComboChanges) + return ; + + if (m_explanatoryLabel) + m_explanatoryLabel->hide(); + + std::string name(getKeyName(s, m_key.isMinor())); + + try { + m_key = Rosegarden::Key(name); + setValid(true); + + int space = name.find(' '); + if (space > 0) + name = name.substr(0, space); + m_keyCombo->setEditText(strtoqstr(name)); + + } catch (Rosegarden::Key::BadKeyName s) { + std::cerr << s.getMessage() << std::endl; + setValid(false); + } + + redrawKeyPixmap(); +} + +void +KeySignatureDialog::slotMajorMinorChanged(const QString &s) +{ + if (m_ignoreComboChanges) + return ; + + std::string name(getKeyName(m_keyCombo->currentText(), s == i18n("Minor"))); + + try { + m_key = Rosegarden::Key(name); + setValid(true); + } catch (Rosegarden::Key::BadKeyName s) { + std::cerr << s.getMessage() << std::endl; + setValid(false); + } + + regenerateKeyCombo(); + redrawKeyPixmap(); +} + +void +KeySignatureDialog::setValid(bool valid) +{ + m_valid = valid; + enableButton(Ok, m_valid); +} + +std::string +KeySignatureDialog::getKeyName(const QString &s, bool minor) +{ + QString u((s.length() >= 1) ? (s.left(1).upper() + s.right(s.length() - 1)) + : s); + + std::string name(qstrtostr(u)); + name = name + " " + (minor ? "minor" : "major"); + return name; +} + +} +#include "KeySignatureDialog.moc" diff --git a/src/gui/dialogs/KeySignatureDialog.h b/src/gui/dialogs/KeySignatureDialog.h new file mode 100644 index 0000000..cd4a340 --- /dev/null +++ b/src/gui/dialogs/KeySignatureDialog.h @@ -0,0 +1,118 @@ + +/* -*- 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_KEYSIGNATUREDIALOG_H_ +#define _RG_KEYSIGNATUREDIALOG_H_ + +#include "base/NotationTypes.h" +#include <string> +#include <kdialogbase.h> +#include <qstring.h> +#include <qcheckbox.h> + + +class QWidget; +class QRadioButton; +class QLabel; +class KComboBox; +class QCheckBox; + + +namespace Rosegarden +{ + +class NotePixmapFactory; + + +class KeySignatureDialog : public KDialogBase +{ + Q_OBJECT + +public: + enum ConversionType { + NoConversion, + Convert, + Transpose + }; + + KeySignatureDialog(QWidget *parent, + NotePixmapFactory *npf, + Clef clef, + Rosegarden::Key defaultKey = + Rosegarden::Key::DefaultKey, + bool showApplyToAll = true, + bool showConversionOptions = true, + QString explanatoryText = 0); + + bool isValid() const; + ::Rosegarden::Key getKey() const; + + bool shouldApplyToAll() const; + bool shouldBeTransposed() const; + ConversionType getConversionType() const; + bool shouldIgnorePercussion() const; + +public slots: + void slotKeyUp(); + void slotKeyDown(); + void slotKeyNameChanged(const QString &); + void slotMajorMinorChanged(const QString &); + +protected: + + void redrawKeyPixmap(); + void regenerateKeyCombo(); + void setValid(bool valid); + std::string getKeyName(const QString &s, bool minor); + + //--------------- Data members --------------------------------- + + NotePixmapFactory *m_notePixmapFactory; + + Rosegarden::Key m_key; + Clef m_clef; + bool m_valid; + bool m_ignoreComboChanges; + + QLabel *m_keyLabel; + KComboBox *m_keyCombo; + KComboBox *m_majorMinorCombo; + QLabel *m_explanatoryLabel; + + QRadioButton *m_applyToAllButton; + QRadioButton *m_yesTransposeButton; + + QRadioButton *m_noConversionButton; + QRadioButton *m_convertButton; + QRadioButton *m_transposeButton; + + QCheckBox *m_noPercussionCheckBox; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/LilyPondOptionsDialog.cpp b/src/gui/dialogs/LilyPondOptionsDialog.cpp new file mode 100644 index 0000000..f693467 --- /dev/null +++ b/src/gui/dialogs/LilyPondOptionsDialog.cpp @@ -0,0 +1,363 @@ +/* -*- 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 "LilyPondOptionsDialog.h" +#include "document/io/LilyPondExporter.h" +#include "gui/configuration/HeadersConfigurationPage.h" + +#include <qlayout.h> +#include <kapplication.h> + +#include "document/ConfigGroups.h" +#include "document/RosegardenGUIDoc.h" +#include "misc/Strings.h" +#include <kcombobox.h> +#include <klineedit.h> +#include <kconfig.h> +#include <kdialogbase.h> +#include <kglobal.h> +#include <klocale.h> +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qstring.h> +#include <qtabwidget.h> +#include <qtooltip.h> +#include <qvbox.h> +#include <qwidget.h> +#include <iostream> + +namespace Rosegarden +{ + +LilyPondOptionsDialog::LilyPondOptionsDialog(QWidget *parent, + RosegardenGUIDoc *doc, + QString windowCaption, + QString heading) : + KDialogBase(parent, 0, true, + (windowCaption = "" ? i18n("LilyPond Export/Preview") : windowCaption), + Apply | Ok | Cancel), + m_doc(doc) +{ + setHelp("file-printing"); + + KConfig *config = kapp->config(); + config->setGroup(NotationViewConfigGroup); + + QVBox * mainbox = makeVBoxMainWidget(); + + // + // Arrange options in "General" and "Advanced" tabs. + // + + QTabWidget * tabWidget = new QTabWidget(mainbox); + + QFrame *generalFrame; + QFrame *advancedFrame; + QGridLayout *generalGrid; + QGridLayout *advancedGrid; + + generalFrame = new QFrame(); + tabWidget->addTab(generalFrame, i18n("General options")); + + generalGrid = new QGridLayout(generalFrame, 1, 1, 5, 5); + + advancedFrame = new QFrame(); + tabWidget->addTab(advancedFrame, i18n("Advanced options")); + + advancedGrid = new QGridLayout(advancedFrame, 1, 1, 5, 5); + + m_headersPage = new HeadersConfigurationPage(this, m_doc); + tabWidget->addTab(m_headersPage, i18n("Headers")); + + m_headersPage->setSpacing(5); + m_headersPage->setMargin(5); + + // + // LilyPond export: Basic options + // + + QGroupBox *basicOptionsBox = new QGroupBox + (1, Horizontal, + i18n("Basic options"), generalFrame); + generalGrid->addWidget(basicOptionsBox, 0, 0); + + QFrame *frameBasic = new QFrame(basicOptionsBox); + QGridLayout *layoutBasic = new QGridLayout(frameBasic, 3, 2, 10, 5); + + layoutBasic->addWidget(new QLabel( + i18n("Compatibility level"), frameBasic), 0, 0); + + m_lilyLanguage = new KComboBox(frameBasic); + // See also setDefaultLilyPondVersion below + m_lilyLanguage->insertItem(i18n("LilyPond %1").arg("2.6")); + m_lilyLanguage->insertItem(i18n("LilyPond %1").arg("2.8")); + m_lilyLanguage->insertItem(i18n("LilyPond %1").arg("2.10")); + m_lilyLanguage->insertItem(i18n("LilyPond %1").arg("2.12")); + m_lilyLanguage->setCurrentItem(config->readUnsignedNumEntry("lilylanguage", 0)); + layoutBasic->addWidget(m_lilyLanguage, 0, 1); + + layoutBasic->addWidget(new QLabel( + i18n("Paper size"), frameBasic), 1, 0); + + QHBoxLayout *hboxPaper = new QHBoxLayout( frameBasic ); + m_lilyPaperSize = new KComboBox(frameBasic); + m_lilyPaperSize->insertItem(i18n("A3")); + m_lilyPaperSize->insertItem(i18n("A4")); + m_lilyPaperSize->insertItem(i18n("A5")); + m_lilyPaperSize->insertItem(i18n("A6")); + m_lilyPaperSize->insertItem(i18n("Legal")); + m_lilyPaperSize->insertItem(i18n("US Letter")); + m_lilyPaperSize->insertItem(i18n("Tabloid")); + m_lilyPaperSize->insertItem(i18n("do not specify")); + int defaultPaperSize = 1; // A4 + if (KGlobal::locale()->country() == "us" || + KGlobal::locale()->country() == "US") defaultPaperSize = 5; // Letter + m_lilyPaperSize->setCurrentItem(config->readUnsignedNumEntry + ("lilypapersize", defaultPaperSize)); + + m_lilyPaperLandscape = new QCheckBox(i18n("Landscape"), frameBasic); + m_lilyPaperLandscape->setChecked(config->readBoolEntry("lilypaperlandscape", false)); + + hboxPaper->addWidget( m_lilyPaperSize ); + hboxPaper->addWidget( new QLabel( " ", frameBasic ) ); // fixed-size spacer + hboxPaper->addWidget( m_lilyPaperLandscape ); + layoutBasic->addLayout(hboxPaper, 1, 1); + + layoutBasic->addWidget(new QLabel( + i18n("Font size"), frameBasic), 2, 0); + + m_lilyFontSize = new KComboBox(frameBasic); + int sizes[] = { 11, 13, 16, 19, 20, 23, 26 }; + for (int i = 0; i < sizeof(sizes)/sizeof(sizes[0]); ++i) { + m_lilyFontSize->insertItem(i18n("%1 pt").arg(sizes[i])); + } + m_lilyFontSize->setCurrentItem(config->readUnsignedNumEntry + ("lilyfontsize", 4)); + layoutBasic->addWidget(m_lilyFontSize, 2, 1); + + // + // LilyPond export: Staff level options + // + + QGroupBox *staffOptionsBox = new QGroupBox + (1, Horizontal, + i18n("Staff level options"), generalFrame); + generalGrid->addWidget(staffOptionsBox, 1, 0); + + QFrame *frameStaff = new QFrame(staffOptionsBox); + QGridLayout *layoutStaff = new QGridLayout(frameStaff, 2, 2, 10, 5); + + layoutStaff->addWidget(new QLabel( + i18n("Export content"), frameStaff), 0, 0); + + m_lilyExportSelection = new KComboBox(frameStaff); + m_lilyExportSelection->insertItem(i18n("All tracks")); + m_lilyExportSelection->insertItem(i18n("Non-muted tracks")); + m_lilyExportSelection->insertItem(i18n("Selected track")); + m_lilyExportSelection->insertItem(i18n("Selected segments")); + m_lilyExportSelection->setCurrentItem(config->readUnsignedNumEntry("lilyexportselection", 1)); + + layoutStaff->addWidget(m_lilyExportSelection, 0, 1); + + m_lilyExportStaffMerge = new QCheckBox( + i18n("Merge tracks that have the same name"), frameStaff); + m_lilyExportStaffMerge->setChecked(config->readBoolEntry("lilyexportstaffmerge", false)); + layoutStaff->addMultiCellWidget(m_lilyExportStaffMerge, 1, 1, 0, 1); + + // + // LilyPond export: Notation options + // + + QGroupBox *notationOptionsBox = new QGroupBox + (1, Horizontal, + i18n("Notation options"), generalFrame); + generalGrid->addWidget(notationOptionsBox, 2, 0); + + QFrame *frameNotation = new QFrame(notationOptionsBox); + QGridLayout *layoutNotation = new QGridLayout(frameNotation, 4, 2, 10, 5); + + m_lilyTempoMarks = new KComboBox( frameNotation ); + m_lilyTempoMarks->insertItem(i18n("None")); + m_lilyTempoMarks->insertItem(i18n("First")); + m_lilyTempoMarks->insertItem(i18n("All")); + m_lilyTempoMarks->setCurrentItem(config->readUnsignedNumEntry("lilyexporttempomarks", 0)); + + layoutNotation->addWidget( new QLabel( + i18n("Export tempo marks "), frameNotation), 0, 0 ); + layoutNotation->addWidget(m_lilyTempoMarks, 0, 1); + + m_lilyExportLyrics = new QCheckBox( + i18n("Export lyrics"), frameNotation); + // default to lyric export == false because if you export the default + // empty "- - -" lyrics, crap results ensue, and people will know if they + // do need to export the lyrics - DMM + // fixed, no "- - -" lyrics are generated for an empty lyrics + // default again into lyrics - HJJ + m_lilyExportLyrics->setChecked(config->readBoolEntry("lilyexportlyrics", true)); + layoutNotation->addMultiCellWidget(m_lilyExportLyrics, 1, 1, 0, 1); + + m_lilyExportBeams = new QCheckBox( + i18n("Export beamings"), frameNotation); + m_lilyExportBeams->setChecked(config->readBoolEntry("lilyexportbeamings", false)); + layoutNotation->addMultiCellWidget(m_lilyExportBeams, 2, 2, 0, 1); + + // recycle this for a new option to ignore the track brackets (so it is less + // obnoxious to print single parts where brackets are in place) + m_lilyExportStaffGroup = new QCheckBox( + i18n("Export track staff brackets"), frameNotation); + m_lilyExportStaffGroup->setChecked(config->readBoolEntry("lilyexportstaffbrackets", true)); + layoutNotation->addMultiCellWidget(m_lilyExportStaffGroup, 3, 3, 0, 1); + + generalGrid->setRowStretch(4, 10); + + // + // LilyPond export: Advanced options + // + + QGroupBox *advancedLayoutOptionsBox = new QGroupBox + (1, Horizontal, + i18n("Layout options"), advancedFrame); + advancedGrid->addWidget(advancedLayoutOptionsBox, 0, 0); + + QFrame *frameAdvancedLayout = new QFrame(advancedLayoutOptionsBox); + QGridLayout *layoutAdvancedLayout = new QGridLayout(frameAdvancedLayout, 2, 2, 10, 5); + + m_lilyLyricsHAlignment = new KComboBox( frameAdvancedLayout ); + m_lilyLyricsHAlignment->insertItem(i18n("Left")); + m_lilyLyricsHAlignment->insertItem(i18n("Center")); + m_lilyLyricsHAlignment->insertItem(i18n("Right")); + m_lilyLyricsHAlignment->setCurrentItem(config->readUnsignedNumEntry("lilylyricshalignment", 0)); + + layoutAdvancedLayout->addWidget(new QLabel( + i18n("Lyrics alignment"), frameAdvancedLayout), 0, 0); + layoutAdvancedLayout->addWidget(m_lilyLyricsHAlignment, 0, 1); + + m_lilyRaggedBottom = new QCheckBox( + i18n("Ragged bottom (systems will not be spread vertically across the page)"), frameAdvancedLayout); + m_lilyRaggedBottom->setChecked(config->readBoolEntry("lilyraggedbottom", false)); + layoutAdvancedLayout->addMultiCellWidget(m_lilyRaggedBottom, 1, 2, 0, 1); + + QGroupBox *miscOptionsBox = new QGroupBox + (1, Horizontal, + i18n("Miscellaneous options"), advancedFrame); + advancedGrid->addWidget(miscOptionsBox, 1, 0); + + QFrame *frameMisc = new QFrame(miscOptionsBox); + QGridLayout *layoutMisc = new QGridLayout(frameMisc, 2, 2, 10, 5); + + m_lilyExportPointAndClick = new QCheckBox( + i18n("Enable \"point and click\" debugging"), frameMisc); + m_lilyExportPointAndClick->setChecked(config->readBoolEntry("lilyexportpointandclick", false)); + layoutMisc->addMultiCellWidget(m_lilyExportPointAndClick, 0, 0, 0, 1); + + m_lilyExportMidi = new QCheckBox( + i18n("Export \\midi block"), frameMisc); + m_lilyExportMidi->setChecked(config->readBoolEntry("lilyexportmidi", false)); + layoutMisc->addMultiCellWidget(m_lilyExportMidi, 1, 1, 0, 1); + + m_lilyMarkerMode = new KComboBox(frameMisc); + m_lilyMarkerMode->insertItem(i18n("No markers")); + m_lilyMarkerMode->insertItem(i18n("Rehearsal marks")); + m_lilyMarkerMode->insertItem(i18n("Marker text")); + m_lilyMarkerMode->setCurrentItem(config->readUnsignedNumEntry("lilyexportmarkermode", 0)); + + layoutMisc->addWidget( new QLabel( + i18n("Export markers"), frameMisc),2, 0 ); + layoutMisc->addWidget(m_lilyMarkerMode, 2, 1); + + advancedGrid->setRowStretch(2, 10); + + resize(minimumSize()); +} + +void +LilyPondOptionsDialog::slotApply() +{ + KConfig *config = kapp->config(); + config->setGroup(NotationViewConfigGroup); + + config->writeEntry("lilylanguage", m_lilyLanguage->currentItem()); + config->writeEntry("lilypapersize", m_lilyPaperSize->currentItem()); + config->writeEntry("lilypaperlandscape", m_lilyPaperLandscape->isChecked()); + config->writeEntry("lilyfontsize", m_lilyFontSize->currentItem()); + config->writeEntry("lilyraggedbottom", m_lilyRaggedBottom->isChecked()); + config->writeEntry("lilyexportlyrics", m_lilyExportLyrics->isChecked()); + config->writeEntry("lilyexportmidi", m_lilyExportMidi->isChecked()); + config->writeEntry("lilyexporttempomarks", m_lilyTempoMarks->currentItem()); + config->writeEntry("lilyexportselection", m_lilyExportSelection->currentItem()); + config->writeEntry("lilyexportpointandclick", m_lilyExportPointAndClick->isChecked()); + config->writeEntry("lilyexportbeamings", m_lilyExportBeams->isChecked()); + config->writeEntry("lilyexportstaffmerge", m_lilyExportStaffMerge->isChecked()); + config->writeEntry("lilyexportstaffbrackets", m_lilyExportStaffGroup->isChecked()); + config->writeEntry("lilylyricshalignment", m_lilyLyricsHAlignment->currentItem()); + config->writeEntry("lilyexportmarkermode", m_lilyMarkerMode->currentItem()); + m_headersPage->apply(); +} + +void +LilyPondOptionsDialog::slotOk() +{ + slotApply(); + accept(); +} + +void +LilyPondOptionsDialog::setDefaultLilyPondVersion(QString version) +{ + KConfig *config = kapp->config(); + config->setGroup(NotationViewConfigGroup); + int index = -1; + bool unstable = false; + if (version == "2.6" || version.startsWith("2.6.")) { + index = 0; + } else if (version == "2.7" || version.startsWith("2.7.")) { + unstable = true; + index = 1; + } else if (version == "2.8" || version.startsWith("2.8.")) { + index = 1; + } else if (version == "2.9" || version.startsWith("2.9.")) { + unstable = true; + index = 2; + } else if (version == "2.10" || version.startsWith("2.10.")) { + index = 2; + } else if (version == "2.11" || version.startsWith("2.11.")) { + unstable = true; + index = 3; + } else if (version == "2.12" || version.startsWith("2.12.")) { + index = 3; + } + if (unstable) { + std::cerr << "\nWARNING: Unstable LilyPond version detected, selecting next language version up\n" << std::endl; + } + if (index >= 0) { + config->writeEntry("lilylanguage", index); + } +} + +} +#include "LilyPondOptionsDialog.moc" diff --git a/src/gui/dialogs/LilyPondOptionsDialog.h b/src/gui/dialogs/LilyPondOptionsDialog.h new file mode 100644 index 0000000..a8f2476 --- /dev/null +++ b/src/gui/dialogs/LilyPondOptionsDialog.h @@ -0,0 +1,86 @@ +/* -*- 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_LILYPONDOPTIONSDIALOG_H_ +#define _RG_LILYPONDOPTIONSDIALOG_H_ + +#include <kdialogbase.h> +#include <qstring.h> + +#include "gui/configuration/HeadersConfigurationPage.h" + +class QWidget; +class QCheckBox; +class QComboBox; +class QLineEdit; +class QLineEdit; + +namespace Rosegarden +{ + +class RosegardenGUIDoc; +class HeadersConfigurationPage; + +class LilyPondOptionsDialog : public KDialogBase +{ + Q_OBJECT + +public: + LilyPondOptionsDialog(QWidget *parent, + RosegardenGUIDoc *doc, + QString windowCaption = "", + QString heading = ""); + + static void setDefaultLilyPondVersion(QString version); + +public slots: + void slotApply(); + void slotOk(); + +protected: + RosegardenGUIDoc *m_doc; + QComboBox *m_lilyLanguage; + QComboBox *m_lilyPaperSize; + QComboBox *m_lilyFontSize; + QComboBox *m_lilyTempoMarks; + QComboBox *m_lilyExportSelection; + QComboBox *m_lilyLyricsHAlignment; + QCheckBox *m_lilyPaperLandscape; + QCheckBox *m_lilyRaggedBottom; + QCheckBox *m_lilyExportLyrics; + QCheckBox *m_lilyExportMidi; + QCheckBox *m_lilyExportPointAndClick; + QCheckBox *m_lilyExportBeams; + QCheckBox *m_lilyExportStaffMerge; + QCheckBox *m_lilyExportStaffGroup; + QComboBox *m_lilyMarkerMode; + HeadersConfigurationPage *m_headersPage; + +}; + + + +} + +#endif diff --git a/src/gui/dialogs/LyricEditDialog.cpp b/src/gui/dialogs/LyricEditDialog.cpp new file mode 100644 index 0000000..4dfeba2 --- /dev/null +++ b/src/gui/dialogs/LyricEditDialog.cpp @@ -0,0 +1,253 @@ +/* -*- 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 "LyricEditDialog.h" + +#include "base/Event.h" +#include "base/BaseProperties.h" +#include <klocale.h> +#include "misc/Strings.h" +#include "misc/Debug.h" +#include "base/Composition.h" +#include "base/NotationTypes.h" +#include "base/Segment.h" +#include <kdialogbase.h> +#include <qgroupbox.h> +#include <qregexp.h> +#include <qstring.h> +#include <qtextedit.h> +#include <qvbox.h> +#include <qwidget.h> +#include <kcombobox.h> +#include <qlabel.h> +#include <qpushbutton.h> + + +namespace Rosegarden +{ + +LyricEditDialog::LyricEditDialog(QWidget *parent, + Segment *segment) : + KDialogBase(parent, 0, true, i18n("Edit Lyrics"), Ok | Cancel | Help), + m_segment(segment), + m_verseCount(0) +{ + setHelp("nv-text-lyrics"); + + QVBox *vbox = makeVBoxMainWidget(); + + QGroupBox *groupBox = new QGroupBox + (1, Horizontal, i18n("Lyrics for this segment"), vbox); + + QHBox *hbox = new QHBox(groupBox); + hbox->setSpacing(5); +// new QLabel(i18n("Verse:"), hbox); + m_verseNumber = new KComboBox(hbox); + m_verseNumber->setEditable(false); + connect(m_verseNumber, SIGNAL(activated(int)), this, SLOT(slotVerseNumberChanged(int))); + m_verseAddButton = new QPushButton(i18n("Add Verse"), hbox); + connect(m_verseAddButton, SIGNAL(clicked()), this, SLOT(slotAddVerse())); + QFrame *f = new QFrame(hbox); + hbox->setStretchFactor(f, 10); + + m_textEdit = new QTextEdit(groupBox); + m_textEdit->setTextFormat(Qt::PlainText); + + m_textEdit->setMinimumWidth(300); + m_textEdit->setMinimumHeight(200); + + unparse(); + + for (int i = 0; i < m_verseCount; ++i) { + m_verseNumber->insertItem(i18n("Verse %1").arg(i + 1)); + } + m_currentVerse = 0; + if (m_verseCount == 12) m_verseAddButton->setEnabled(false); +} + +void +LyricEditDialog::slotVerseNumberChanged(int verse) +{ + NOTATION_DEBUG << "LyricEditDialog::slotVerseNumberChanged(" << verse << ")" << endl; + QString text = m_textEdit->text(); + m_texts[m_currentVerse] = text; + m_textEdit->setText(m_texts[verse]); + m_currentVerse = verse; +} + +void +LyricEditDialog::slotAddVerse() +{ + NOTATION_DEBUG << "LyricEditDialog::slotAddVerse" << endl; + m_verseCount++; + m_texts.push_back(m_skeleton); + m_verseNumber->insertItem(i18n("Verse %1").arg(m_verseCount)); + m_verseNumber->setCurrentItem(m_verseCount - 1); + slotVerseNumberChanged(m_verseCount - 1); + if (m_verseCount == 12) m_verseAddButton->setEnabled(false); +} + +void +LyricEditDialog::countVerses() +{ + m_verseCount = 1; + + for (Segment::iterator i = m_segment->begin(); + m_segment->isBeforeEndMarker(i); ++i) { + + if ((*i)->isa(Text::EventType)) { + + std::string textType; + if ((*i)->get<String>(Text::TextTypePropertyName, textType) && + textType == Text::Lyric) { + + long verse = 0; + (*i)->get<Int>(Text::LyricVersePropertyName, verse); + + if (verse >= m_verseCount) m_verseCount = verse + 1; + } + } + } +} + +void +LyricEditDialog::unparse() +{ + // This and SetLyricsCommand::execute() are opposites that will + // need to be kept in sync with any changes in one another. (They + // should really both be in a common lyric management class.) + + countVerses(); + + Composition *comp = m_segment->getComposition(); + + bool firstNote = true; + timeT lastTime = m_segment->getStartTime(); + int lastBarNo = comp->getBarNumber(lastTime); + std::map<int, bool> haveLyric; + + QString fragment = QString("[%1] ").arg(lastBarNo + 1); + + m_skeleton = fragment; + m_texts.clear(); + for (size_t v = 0; v < m_verseCount; ++v) { + m_texts.push_back(fragment); + haveLyric[v] = false; + } + + for (Segment::iterator i = m_segment->begin(); + m_segment->isBeforeEndMarker(i); ++i) { + + bool isNote = (*i)->isa(Note::EventType); + bool isLyric = false; + + if (!isNote) { + if ((*i)->isa(Text::EventType)) { + std::string textType; + if ((*i)->get<String>(Text::TextTypePropertyName, textType) && + textType == Text::Lyric) { + isLyric = true; + } + } + } else { + if ((*i)->has(BaseProperties::TIED_BACKWARD) && + (*i)->get<Bool>(BaseProperties::TIED_BACKWARD)) { + continue; + } + } + + if (!isNote && !isLyric) continue; + + timeT myTime = (*i)->getNotationAbsoluteTime(); + int myBarNo = comp->getBarNumber(myTime); + + if (myBarNo > lastBarNo) { + + fragment = ""; + + while (myBarNo > lastBarNo) { + fragment += " /"; + ++lastBarNo; + } + + fragment += QString("\n[%1] ").arg(myBarNo + 1); + + m_skeleton += fragment; + for (size_t v = 0; v < m_verseCount; ++v) m_texts[v] += fragment; + } + + if (isNote) { + if ((myTime > lastTime) || firstNote) { + m_skeleton += " ."; + for (size_t v = 0; v < m_verseCount; ++v) { + if (!haveLyric[v]) m_texts[v] += " ."; + haveLyric[v] = false; + } + lastTime = myTime; + firstNote = false; + } + } + + if (isLyric) { + + std::string ssyllable; + (*i)->get<String>(Text::TextPropertyName, ssyllable); + + long verse = 0; + (*i)->get<Int>(Text::LyricVersePropertyName, verse); + + QString syllable(strtoqstr(ssyllable)); + syllable.replace(QRegExp("\\s+"), "~"); + + m_texts[verse] += " " + syllable; + haveLyric[verse] = true; + } + } + + if (!m_texts.empty()) { + m_textEdit->setText(m_texts[0]); + } else { + m_texts.push_back(m_skeleton); + } +} + +int +LyricEditDialog::getVerseCount() const +{ + return m_verseCount; +} + +QString +LyricEditDialog::getLyricData(int verse) const +{ + if (verse == m_verseNumber->currentItem()) { + return m_textEdit->text(); + } else { + return m_texts[verse]; + } +} + +} +#include "LyricEditDialog.moc" diff --git a/src/gui/dialogs/LyricEditDialog.h b/src/gui/dialogs/LyricEditDialog.h new file mode 100644 index 0000000..f4a5154 --- /dev/null +++ b/src/gui/dialogs/LyricEditDialog.h @@ -0,0 +1,78 @@ + +/* -*- 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_LYRICEDITDIALOG_H_ +#define _RG_LYRICEDITDIALOG_H_ + +#include <kdialogbase.h> +#include <qstring.h> +#include <vector> + + +class QWidget; +class QTextEdit; +class QComboBox; +class QPushButton; + + +namespace Rosegarden +{ + +class Segment; + + +class LyricEditDialog : public KDialogBase +{ + Q_OBJECT + +public: + LyricEditDialog(QWidget *parent, Segment *segment); + + int getVerseCount() const; + QString getLyricData(int verse) const; + +protected slots: + void slotVerseNumberChanged(int); + void slotAddVerse(); + +protected: + Segment *m_segment; + + int m_currentVerse; + QComboBox *m_verseNumber; + QTextEdit *m_textEdit; + QPushButton *m_verseAddButton; + + int m_verseCount; + std::vector<QString> m_texts; + QString m_skeleton; + + void countVerses(); + void unparse(); +}; + +} + +#endif diff --git a/src/gui/dialogs/MakeOrnamentDialog.cpp b/src/gui/dialogs/MakeOrnamentDialog.cpp new file mode 100644 index 0000000..7e82a22 --- /dev/null +++ b/src/gui/dialogs/MakeOrnamentDialog.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 "MakeOrnamentDialog.h" + +#include <klocale.h> +#include "gui/widgets/PitchChooser.h" +#include <kdialogbase.h> +#include <qgroupbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +MakeOrnamentDialog::MakeOrnamentDialog(QWidget *parent, QString defaultName, + int defaultBasePitch) : + KDialogBase(parent, "makeornamentdialog", true, i18n("Make Ornament"), + Ok | Cancel, Ok) +{ + QVBox *vbox = makeVBoxMainWidget(); + QGroupBox *nameBox = new QGroupBox(2, Vertical, i18n("Name"), vbox); + + new QLabel(i18n("The name is used to identify both the ornament\nand the triggered segment that stores\nthe ornament's notes."), nameBox); + + QHBox *hbox = new QHBox(nameBox); + new QLabel(i18n("Name: "), hbox); + m_name = new QLineEdit(defaultName, hbox); + + m_pitch = new PitchChooser(i18n("Base pitch"), vbox, defaultBasePitch); +} + +QString +MakeOrnamentDialog::getName() const +{ + return m_name->text(); +} + +int +MakeOrnamentDialog::getBasePitch() const +{ + return m_pitch->getPitch(); +} + +} +#include "MakeOrnamentDialog.moc" diff --git a/src/gui/dialogs/MakeOrnamentDialog.h b/src/gui/dialogs/MakeOrnamentDialog.h new file mode 100644 index 0000000..3f1957b --- /dev/null +++ b/src/gui/dialogs/MakeOrnamentDialog.h @@ -0,0 +1,62 @@ + +/* -*- 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_MAKEORNAMENTDIALOG_H_ +#define _RG_MAKEORNAMENTDIALOG_H_ + +#include <kdialogbase.h> +#include <qstring.h> + + +class QWidget; +class QLineEdit; + + +namespace Rosegarden +{ + +class PitchChooser; + + +class MakeOrnamentDialog : public KDialogBase +{ + Q_OBJECT + +public: + MakeOrnamentDialog(QWidget *parent, QString defaultName, int defaultBasePitch); + + QString getName() const; + int getBasePitch() const; + +protected: + QLineEdit *m_name; + PitchChooser *m_pitch; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/ManageMetronomeDialog.cpp b/src/gui/dialogs/ManageMetronomeDialog.cpp new file mode 100644 index 0000000..a0f73d6 --- /dev/null +++ b/src/gui/dialogs/ManageMetronomeDialog.cpp @@ -0,0 +1,508 @@ +/* -*- 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 "ManageMetronomeDialog.h" +#include <qlayout.h> + +#include <klocale.h> +#include "misc/Debug.h" +#include "misc/Strings.h" +#include "base/Composition.h" +#include "base/Device.h" +#include "base/Instrument.h" +#include "base/MidiDevice.h" +#include "base/MidiProgram.h" +#include "base/RealTime.h" +#include "base/Studio.h" +#include "document/RosegardenGUIDoc.h" +#include "gui/editors/parameters/InstrumentParameterBox.h" +#include "gui/seqmanager/SequenceManager.h" +#include "gui/studio/StudioControl.h" +#include "gui/widgets/PitchChooser.h" +#include "sound/MappedEvent.h" +#include <kcombobox.h> +#include <kdialogbase.h> +#include <qcheckbox.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qspinbox.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +ManageMetronomeDialog::ManageMetronomeDialog(QWidget *parent, + RosegardenGUIDoc *doc) : + KDialogBase(parent, 0, true, i18n("Metronome"), Ok | Apply | Close | Help), + m_doc(doc) +{ + setHelp("studio-metronome"); + + QHBox *hbox = makeHBoxMainWidget(); + + // I think having this as well probably just overcomplicates things + m_instrumentParameterBox = 0; + // m_instrumentParameterBox = new InstrumentParameterBox(doc, hbox); + + QVBox *vbox = new QVBox(hbox); + + QGroupBox *deviceBox = new QGroupBox + (1, Horizontal, i18n("Metronome Instrument"), vbox); + + QFrame *frame = new QFrame(deviceBox); + QGridLayout *layout = new QGridLayout(frame, 2, 2, 10, 5); + + layout->addWidget(new QLabel(i18n("Device"), frame), 0, 0); + m_metronomeDevice = new KComboBox(frame); + layout->addWidget(m_metronomeDevice, 0, 1); + + DeviceList *devices = doc->getStudio().getDevices(); + DeviceListConstIterator it; + + Studio &studio = m_doc->getStudio(); + DeviceId deviceId = studio.getMetronomeDevice(); + + for (it = devices->begin(); it != devices->end(); it++) { + MidiDevice *dev = + dynamic_cast<MidiDevice*>(*it); + + if (dev && dev->getDirection() == MidiDevice::Play) { + QString label = strtoqstr(dev->getName()); + QString connection = strtoqstr(dev->getConnection()); + label += " - "; + if (connection == "") + label += i18n("No connection"); + else + label += connection; + m_metronomeDevice->insertItem(label); + if (dev->getId() == deviceId) { + m_metronomeDevice->setCurrentItem(m_metronomeDevice->count() - 1); + } + } + } + + layout->addWidget(new QLabel(i18n("Instrument"), frame), 1, 0); + m_metronomeInstrument = new KComboBox(frame); + connect(m_metronomeInstrument, SIGNAL(activated(int)), this, SLOT(slotSetModified())); + connect(m_metronomeInstrument, SIGNAL(activated(int)), this, SLOT(slotInstrumentChanged(int))); + layout->addWidget(m_metronomeInstrument, 1, 1); + + QGroupBox *beatBox = new QGroupBox + (1, Horizontal, i18n("Beats"), vbox); + + frame = new QFrame(beatBox); + layout = new QGridLayout(frame, 4, 2, 10, 5); + + layout->addWidget(new QLabel(i18n("Resolution"), frame), 0, 0); + m_metronomeResolution = new KComboBox(frame); + m_metronomeResolution->insertItem(i18n("None")); + m_metronomeResolution->insertItem(i18n("Bars only")); + m_metronomeResolution->insertItem(i18n("Bars and beats")); + m_metronomeResolution->insertItem(i18n("Bars, beats, and divisions")); + connect(m_metronomeResolution, SIGNAL(activated(int)), this, SLOT(slotResolutionChanged(int))); + layout->addWidget(m_metronomeResolution, 0, 1); + + layout->addWidget(new QLabel(i18n("Bar velocity"), frame), 1, 0); + m_metronomeBarVely = new QSpinBox(frame); + m_metronomeBarVely->setMinValue(0); + m_metronomeBarVely->setMaxValue(127); + connect(m_metronomeBarVely, SIGNAL(valueChanged(int)), this, SLOT(slotSetModified())); + layout->addWidget(m_metronomeBarVely, 1, 1); + + layout->addWidget(new QLabel(i18n("Beat velocity"), frame), 2, 0); + m_metronomeBeatVely = new QSpinBox(frame); + m_metronomeBeatVely->setMinValue(0); + m_metronomeBeatVely->setMaxValue(127); + connect(m_metronomeBeatVely, SIGNAL(valueChanged(int)), this, SLOT(slotSetModified())); + layout->addWidget(m_metronomeBeatVely, 2, 1); + + layout->addWidget(new QLabel(i18n("Sub-beat velocity"), frame), 3, 0); + m_metronomeSubBeatVely = new QSpinBox(frame); + m_metronomeSubBeatVely->setMinValue(0); + m_metronomeSubBeatVely->setMaxValue(127); + connect(m_metronomeSubBeatVely, SIGNAL(valueChanged(int)), this, SLOT(slotSetModified())); + layout->addWidget(m_metronomeSubBeatVely, 3, 1); + + vbox = new QVBox(hbox); + + m_metronomePitch = new PitchChooser(i18n("Pitch"), vbox, 60); + connect(m_metronomePitch, SIGNAL(pitchChanged(int)), this, SLOT(slotPitchChanged(int))); + connect(m_metronomePitch, SIGNAL(preview(int)), this, SLOT(slotPreviewPitch(int))); + + m_metronomePitchSelector = new KComboBox(m_metronomePitch); + m_metronomePitchSelector->insertItem(i18n("for Bar")); + m_metronomePitchSelector->insertItem(i18n("for Beat")); + m_metronomePitchSelector->insertItem(i18n("for Sub-beat")); + connect(m_metronomePitchSelector, SIGNAL(activated(int)), this, SLOT(slotPitchSelectorChanged(int))); + + QGroupBox *enableBox = new QGroupBox + (1, Horizontal, i18n("Metronome Activated"), vbox); + m_playEnabled = new QCheckBox(i18n("Playing"), enableBox); + m_recordEnabled = new QCheckBox(i18n("Recording"), enableBox); + connect(m_playEnabled, SIGNAL(clicked()), this, SLOT(slotSetModified())); + connect(m_recordEnabled, SIGNAL(clicked()), this, SLOT(slotSetModified())); + + // populate the dialog + populate(m_metronomeDevice->currentItem()); + + // connect up the device list + connect(m_metronomeDevice, SIGNAL(activated(int)), + this, SLOT(populate(int))); + // connect up the device list + connect(m_metronomeDevice, SIGNAL(activated(int)), + this, SLOT(slotSetModified())); + + setModified(false); +} + +void +ManageMetronomeDialog::slotResolutionChanged(int depth) +{ + m_metronomeBeatVely->setEnabled(depth > 1); + m_metronomeSubBeatVely->setEnabled(depth > 2); + slotSetModified(); +} + +void +ManageMetronomeDialog::populate(int deviceIndex) +{ + m_metronomeInstrument->clear(); + + DeviceList *devices = m_doc->getStudio().getDevices(); + DeviceListConstIterator it; + int count = 0; + MidiDevice *dev = 0; + + for (it = devices->begin(); it != devices->end(); it++) { + dev = dynamic_cast<MidiDevice*>(*it); + + if (dev && dev->getDirection() == MidiDevice::Play) { + if (count == deviceIndex) + break; + + count++; + } + } + + // sanity + if (count < 0 || dev == 0) { + if (m_instrumentParameterBox) + m_instrumentParameterBox->useInstrument(0); + return ; + } + + // populate instrument list + InstrumentList list = dev->getPresentationInstruments(); + InstrumentList::iterator iit; + + const MidiMetronome *metronome = dev->getMetronome(); + + // if we've got no metronome against this device then create one + if (metronome == 0) { + InstrumentId id = SystemInstrumentBase; + + for (iit = list.begin(); iit != list.end(); ++iit) { + if ((*iit)->isPercussion()) { + id = (*iit)->getId(); + break; + } + } + + dev->setMetronome(MidiMetronome(id)); + + metronome = dev->getMetronome(); + } + + // metronome should now be set but we still check it + if (metronome) { + int position = 0; + int count = 0; + for (iit = list.begin(); iit != list.end(); ++iit) { + QString iname(strtoqstr((*iit)->getPresentationName())); + QString pname(strtoqstr((*iit)->getProgramName())); + if (pname != "") + iname += " (" + pname + ")"; + + bool used = false; + for (Composition::trackcontainer::iterator tit = + m_doc->getComposition().getTracks().begin(); + tit != m_doc->getComposition().getTracks().end(); ++tit) { + + if (tit->second->getInstrument() == (*iit)->getId()) { + used = true; + break; + } + } + + // if (used) iname = i18n("%1 [used]").arg(iname); + + m_metronomeInstrument->insertItem(iname); + + if ((*iit)->getId() == metronome->getInstrument()) { + position = count; + } + count++; + } + m_metronomeInstrument->setCurrentItem(position); + slotInstrumentChanged(position); + + m_barPitch = metronome->getBarPitch(); + m_beatPitch = metronome->getBeatPitch(); + m_subBeatPitch = metronome->getSubBeatPitch(); + slotPitchSelectorChanged(0); + m_metronomeResolution->setCurrentItem(metronome->getDepth()); + m_metronomeBarVely->setValue(metronome->getBarVelocity()); + m_metronomeBeatVely->setValue(metronome->getBeatVelocity()); + m_metronomeSubBeatVely->setValue(metronome->getSubBeatVelocity()); + m_playEnabled->setChecked(m_doc->getComposition().usePlayMetronome()); + m_recordEnabled->setChecked(m_doc->getComposition().useRecordMetronome()); + slotResolutionChanged(metronome->getDepth()); + } +} + +void +ManageMetronomeDialog::slotInstrumentChanged(int i) +{ + if (!m_instrumentParameterBox) + return ; + + int deviceIndex = m_metronomeDevice->currentItem(); + + DeviceList *devices = m_doc->getStudio().getDevices(); + DeviceListConstIterator it; + int count = 0; + MidiDevice *dev = 0; + + for (it = devices->begin(); it != devices->end(); it++) { + dev = dynamic_cast<MidiDevice*>(*it); + + if (dev && dev->getDirection() == MidiDevice::Play) { + if (count == deviceIndex) + break; + + count++; + } + } + + // sanity + if (count < 0 || dev == 0) { + m_instrumentParameterBox->useInstrument(0); + return ; + } + + // populate instrument list + InstrumentList list = dev->getPresentationInstruments(); + + if (i < 0 || i >= (int)list.size()) + return ; + + m_instrumentParameterBox->useInstrument(list[i]); +} + +void +ManageMetronomeDialog::slotOk() +{ + slotApply(); + accept(); +} + +void +ManageMetronomeDialog::slotSetModified() +{ + setModified(true); +} + +void +ManageMetronomeDialog::setModified(bool value) +{ + if (m_modified == value) + return ; + + if (value) { + enableButtonApply(true); + } else { + enableButtonApply(false); + } + + m_modified = value; +} + +void +ManageMetronomeDialog::slotApply() +{ + Studio &studio = m_doc->getStudio(); + + DeviceList *devices = m_doc->getStudio().getDevices(); + DeviceListConstIterator it; + int count = 0; + MidiDevice *dev = 0; + + for (it = devices->begin(); it != devices->end(); it++) { + dev = dynamic_cast<MidiDevice*>(*it); + + if (dev && dev->getDirection() == MidiDevice::Play) { + if (count == m_metronomeDevice->currentItem()) + break; + + count++; + } + } + + if (!dev) { + std::cerr << "Warning: ManageMetronomeDialog::slotApply: no " << m_metronomeDevice->currentItem() << "th device" << std::endl; + return ; + } + + DeviceId deviceId = dev->getId(); + studio.setMetronomeDevice(deviceId); + + if (dev->getMetronome() == 0) + return ; + MidiMetronome metronome(*dev->getMetronome()); + + // get instrument + InstrumentList list = dev->getPresentationInstruments(); + + Instrument *inst = + list[m_metronomeInstrument->currentItem()]; + + if (inst) { + metronome.setInstrument(inst->getId()); + } + + metronome.setBarPitch(m_barPitch); + metronome.setBeatPitch(m_beatPitch); + metronome.setSubBeatPitch(m_subBeatPitch); + + metronome.setDepth( + m_metronomeResolution->currentItem()); + + metronome.setBarVelocity( + MidiByte(m_metronomeBarVely->value())); + + metronome.setBeatVelocity( + MidiByte(m_metronomeBeatVely->value())); + + metronome.setSubBeatVelocity( + MidiByte(m_metronomeSubBeatVely->value())); + + dev->setMetronome(metronome); + + m_doc->getComposition().setPlayMetronome(m_playEnabled->isChecked()); + m_doc->getComposition().setRecordMetronome(m_recordEnabled->isChecked()); + + m_doc->getSequenceManager()->metronomeChanged(inst->getId(), true); + m_doc->slotDocumentModified(); + setModified(false); +} + +void +ManageMetronomeDialog::slotPreviewPitch(int pitch) +{ + RG_DEBUG << "ManageMetronomeDialog::slotPreviewPitch" << endl; + + DeviceList *devices = m_doc->getStudio().getDevices(); + DeviceListConstIterator it; + int count = 0; + MidiDevice *dev = 0; + + for (it = devices->begin(); it != devices->end(); it++) { + dev = dynamic_cast<MidiDevice*>(*it); + + if (dev && dev->getDirection() == MidiDevice::Play) { + if (count == m_metronomeDevice->currentItem()) + break; + + count++; + } + } + + if (!dev) + return ; + + const MidiMetronome *metronome = dev->getMetronome(); + if (metronome == 0) + return ; + + InstrumentList list = dev->getPresentationInstruments(); + + Instrument *inst = + list[m_metronomeInstrument->currentItem()]; + + if (inst) { + RG_DEBUG << "ManageMetronomeDialog::slotPreviewPitch" + << " - previewing" << endl; + MappedEvent mE(inst->getId(), + MappedEvent::MidiNoteOneShot, + pitch, + MidiMaxValue, + RealTime::zeroTime, + RealTime(0, 10000000), + RealTime::zeroTime); + + StudioControl::sendMappedEvent(mE); + } +} + +void +ManageMetronomeDialog::slotPitchChanged(int pitch) +{ + switch (m_metronomePitchSelector->currentItem()) { + case 0: + m_barPitch = pitch; + break; + case 1: + m_beatPitch = pitch; + break; + case 2: + m_subBeatPitch = pitch; + break; + } + setModified(true); +} + +void +ManageMetronomeDialog::slotPitchSelectorChanged(int selection) +{ + switch (selection) { + case 0: + m_metronomePitch->slotSetPitch(m_barPitch); + break; + case 1: + m_metronomePitch->slotSetPitch(m_beatPitch); + break; + case 2: + m_metronomePitch->slotSetPitch(m_subBeatPitch); + break; + } +} + +} +#include "ManageMetronomeDialog.moc" diff --git a/src/gui/dialogs/ManageMetronomeDialog.h b/src/gui/dialogs/ManageMetronomeDialog.h new file mode 100644 index 0000000..08b806c --- /dev/null +++ b/src/gui/dialogs/ManageMetronomeDialog.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_MANAGEMETRONOMEDIALOG_H_ +#define _RG_MANAGEMETRONOMEDIALOG_H_ + +#include "base/MidiProgram.h" +#include <kdialogbase.h> + + +class QWidget; +class QSpinBox; +class QCheckBox; +class KComboBox; + + +namespace Rosegarden +{ + +class RosegardenGUIDoc; +class PitchChooser; +class InstrumentParameterBox; + + +class ManageMetronomeDialog : public KDialogBase +{ + Q_OBJECT + +public: + ManageMetronomeDialog(QWidget *parent, RosegardenGUIDoc *doc); + + void setModified(bool value); + +public slots: + void slotOk(); + void slotApply(); + void slotSetModified(); + void slotResolutionChanged(int); + void slotPreviewPitch(int); + void slotInstrumentChanged(int); + void slotPitchSelectorChanged(int); + void slotPitchChanged(int); + void populate(int dev); + +protected: + + //--------------- Data members --------------------------------- + + RosegardenGUIDoc *m_doc; + + KComboBox *m_metronomeDevice; + KComboBox *m_metronomeInstrument; + KComboBox *m_metronomeResolution; + KComboBox *m_metronomePitchSelector; + PitchChooser *m_metronomePitch; + QSpinBox *m_metronomeBarVely; + QSpinBox *m_metronomeBeatVely; + QSpinBox *m_metronomeSubBeatVely; + InstrumentParameterBox *m_instrumentParameterBox; + QCheckBox *m_playEnabled; + QCheckBox *m_recordEnabled; + + bool m_modified; + MidiByte m_barPitch; + MidiByte m_beatPitch; + MidiByte m_subBeatPitch; +}; + + +} + +#endif diff --git a/src/gui/dialogs/MarkerModifyDialog.cpp b/src/gui/dialogs/MarkerModifyDialog.cpp new file mode 100644 index 0000000..69e658b --- /dev/null +++ b/src/gui/dialogs/MarkerModifyDialog.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 "MarkerModifyDialog.h" +#include <qlayout.h> + +#include <klocale.h> +#include "base/Composition.h" +#include "document/RosegardenGUIDoc.h" +#include "gui/widgets/TimeWidget.h" +#include <kdialogbase.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qspinbox.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> +#include "misc/Strings.h" + + +namespace Rosegarden +{ + +MarkerModifyDialog::MarkerModifyDialog(QWidget *parent, + Composition *composition, + int time, + const QString &name, + const QString &des): + KDialogBase(parent, 0, true, i18n("Edit Marker"), Ok | Cancel) +{ + initialise(composition, time, name, des); +} + +MarkerModifyDialog::MarkerModifyDialog(QWidget *parent, + Composition *composition, + Marker *marker) : + KDialogBase(parent, 0, true, i18n("Edit Marker"), Ok | Cancel) +{ + initialise(composition, marker->getTime(), + strtoqstr(marker->getName()), + strtoqstr(marker->getDescription())); +} + +void +MarkerModifyDialog::initialise(Composition *composition, + int time, + const QString &name, + const QString &des) +{ + m_originalTime = time; + + QVBox *vbox = makeVBoxMainWidget(); + + m_timeEdit = new TimeWidget(i18n("Marker Time"), vbox, composition, + time); + + /*!!! + + layout->addWidget(new QLabel(i18n("Absolute Time:"), frame), 0, 0); + m_timeEdit = new QSpinBox(frame); + layout->addWidget(m_timeEdit, 0, 1); + + m_timeEdit->setMinValue(INT_MIN); + m_timeEdit->setMaxValue(INT_MAX); + m_timeEdit->setLineStep( + Note(Note::Shortest).getDuration()); + m_timeEdit->setValue(time); + */ + QGroupBox *groupBox = new QGroupBox + (1, Horizontal, i18n("Marker Properties"), vbox); + + QFrame *frame = new QFrame(groupBox); + + QGridLayout *layout = new QGridLayout(frame, 2, 2, 5, 5); + + layout->addWidget(new QLabel(i18n("Text:"), frame), 0, 0); + m_nameEdit = new QLineEdit(name, frame); + layout->addWidget(m_nameEdit, 0, 1); + + layout->addWidget(new QLabel(i18n("Description:"), frame), 1, 0); + m_desEdit = new QLineEdit(des, frame); + layout->addWidget(m_desEdit, 1, 1); + + m_nameEdit->selectAll(); + m_nameEdit->setFocus(); +} + +} +#include "MarkerModifyDialog.moc" diff --git a/src/gui/dialogs/MarkerModifyDialog.h b/src/gui/dialogs/MarkerModifyDialog.h new file mode 100644 index 0000000..5b87b14 --- /dev/null +++ b/src/gui/dialogs/MarkerModifyDialog.h @@ -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. +*/ + +#ifndef _RG_MARKERMODIFYDIALOG_H_ +#define _RG_MARKERMODIFYDIALOG_H_ + +#include <kdialogbase.h> +#include <qstring.h> +#include <qlineedit.h> + +#include "base/Marker.h" +#include "gui/widgets/TimeWidget.h" + + +namespace Rosegarden +{ + +class TimeWidget; +class RosegardenGUIDoc; +class Composition; + + +class MarkerModifyDialog : public KDialogBase +{ + Q_OBJECT +public: + MarkerModifyDialog(QWidget *parent, + Composition *composition, + int time, + const QString &name, + const QString &des); + + MarkerModifyDialog(QWidget *parent, + Composition *composition, + Marker *marker); + + QString getName() const { return m_nameEdit->text(); } + QString getDescription() const { return m_desEdit->text(); } + int getTime() const { return m_timeEdit->getTime(); } + int getOriginalTime() const { return m_originalTime; } + +protected: + void initialise(Composition *composition, + int time, + const QString &name, + const QString &des); + + RosegardenGUIDoc *m_doc; + + TimeWidget *m_timeEdit; + QLineEdit *m_nameEdit; + QLineEdit *m_desEdit; + + int m_originalTime; +}; + + + + +} + +#endif diff --git a/src/gui/dialogs/PasteNotationDialog.cpp b/src/gui/dialogs/PasteNotationDialog.cpp new file mode 100644 index 0000000..0c725d5 --- /dev/null +++ b/src/gui/dialogs/PasteNotationDialog.cpp @@ -0,0 +1,101 @@ +/* -*- 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 "PasteNotationDialog.h" + +#include <klocale.h> +#include "commands/edit/PasteEventsCommand.h" +#include <kdialogbase.h> +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qobject.h> +#include <qradiobutton.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +PasteNotationDialog::PasteNotationDialog(QWidget *parent, + PasteEventsCommand::PasteType defaultType) : + KDialogBase(parent, 0, true, i18n("Paste"), Ok | Cancel | Help ), + m_defaultType(defaultType) +{ + setHelp("nv-paste-types"); + + QVBox *vbox = makeVBoxMainWidget(); + + QButtonGroup *pasteTypeGroup = new QButtonGroup + (1, Horizontal, i18n("Paste type"), vbox); + + PasteEventsCommand::PasteTypeMap pasteTypes = + PasteEventsCommand::getPasteTypes(); + + for (PasteEventsCommand::PasteTypeMap::iterator i = pasteTypes.begin(); + i != pasteTypes.end(); ++i) { + + QRadioButton *button = new QRadioButton(i->second, pasteTypeGroup); + button->setChecked(m_defaultType == i->first); + QObject::connect(button, SIGNAL(clicked()), + this, SLOT(slotPasteTypeChanged())); + + m_pasteTypeButtons.push_back(button); + } + + QButtonGroup *setAsDefaultGroup = new QButtonGroup + (1, Horizontal, i18n("Options"), vbox); + + m_setAsDefaultButton = new QCheckBox + (i18n("Make this the default paste type"), setAsDefaultGroup); + m_setAsDefaultButton->setChecked(true); +} + +PasteEventsCommand::PasteType +PasteNotationDialog::getPasteType() const +{ + for (unsigned int i = 0; i < m_pasteTypeButtons.size(); ++i) { + if (m_pasteTypeButtons[i]->isChecked()) { + return (PasteEventsCommand::PasteType)i; + } + } + + return PasteEventsCommand::Restricted; +} + +bool +PasteNotationDialog::setAsDefault() const +{ + return m_setAsDefaultButton->isChecked(); +} + +void +PasteNotationDialog::slotPasteTypeChanged() +{ + m_setAsDefaultButton->setChecked(m_defaultType == getPasteType()); +} + +} +#include "PasteNotationDialog.moc" diff --git a/src/gui/dialogs/PasteNotationDialog.h b/src/gui/dialogs/PasteNotationDialog.h new file mode 100644 index 0000000..213eaf8 --- /dev/null +++ b/src/gui/dialogs/PasteNotationDialog.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_PASTENOTATIONDIALOG_H_ +#define _RG_PASTENOTATIONDIALOG_H_ + +#include "commands/edit/PasteEventsCommand.h" +#include <kdialogbase.h> +#include <vector> + + +class QWidget; +class QRadioButton; +class QCheckBox; + + +namespace Rosegarden +{ + + + +class PasteNotationDialog : public KDialogBase +{ + Q_OBJECT + +public: + PasteNotationDialog(QWidget *parent, + PasteEventsCommand::PasteType defaultType); + + PasteEventsCommand::PasteType getPasteType() const; + bool setAsDefault() const; + +public slots: + void slotPasteTypeChanged(); + +protected: + + //--------------- Data members --------------------------------- + + std::vector<QRadioButton *> m_pasteTypeButtons; + QCheckBox *m_setAsDefaultButton; + + PasteEventsCommand::PasteType m_defaultType; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/PitchDialog.cpp b/src/gui/dialogs/PitchDialog.cpp new file mode 100644 index 0000000..05fed08 --- /dev/null +++ b/src/gui/dialogs/PitchDialog.cpp @@ -0,0 +1,57 @@ +/* -*- 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 "PitchDialog.h" + +#include <klocale.h> +#include "gui/widgets/PitchChooser.h" +#include <kdialogbase.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +PitchDialog::PitchDialog(QWidget *parent, QString title, int defaultPitch) : + KDialogBase(parent, 0, true, title, User1 | Ok) +{ + QVBox *vbox = makeVBoxMainWidget(); + m_pitchChooser = new PitchChooser(title, vbox, defaultPitch); + + setButtonText(User1, i18n("Reset")); + connect(this, SIGNAL(user1Clicked()), + m_pitchChooser, SLOT(slotResetToDefault())); +} + +int +PitchDialog::getPitch() const +{ + return m_pitchChooser->getPitch(); +} + +} +#include "PitchDialog.moc" diff --git a/src/gui/dialogs/PitchDialog.h b/src/gui/dialogs/PitchDialog.h new file mode 100644 index 0000000..72e6381 --- /dev/null +++ b/src/gui/dialogs/PitchDialog.h @@ -0,0 +1,58 @@ + +/* -*- 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_PITCHDIALOG_H_ +#define _RG_PITCHDIALOG_H_ + +#include <kdialogbase.h> +#include <qstring.h> + + +class QWidget; + + +namespace Rosegarden +{ + +class PitchChooser; + + +class PitchDialog : public KDialogBase +{ + Q_OBJECT +public: + PitchDialog(QWidget *parent, QString title, int defaultPitch = 60); + + int getPitch() const; + +protected: + PitchChooser *m_pitchChooser; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/PitchPickerDialog.cpp b/src/gui/dialogs/PitchPickerDialog.cpp new file mode 100644 index 0000000..ddd1f23 --- /dev/null +++ b/src/gui/dialogs/PitchPickerDialog.cpp @@ -0,0 +1,58 @@ +/* -*- 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 "PitchPickerDialog.h" +#include <klocale.h> +#include <kdialogbase.h> +#include <qlayout.h> +#include <qframe.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +PitchPickerDialog::PitchPickerDialog(QWidget *parent, int initialPitch, QString text) : + KDialogBase(parent, 0, true, i18n("Pitch Selector"), Ok | Cancel) +{ + QVBox *vBox = makeVBoxMainWidget(); + + QFrame *frame = new QFrame(vBox); + + QGridLayout *layout = new QGridLayout(frame, 4, 3, 10, 5); + + m_pitch = new PitchChooser(text, frame, initialPitch); + layout->addMultiCellWidget(m_pitch, 0, 0, 0, 2, Qt::AlignHCenter); +} + +PitchPickerDialog::~PitchPickerDialog() +{ + // Nothing here... +} + +} +#include "PitchPickerDialog.moc" diff --git a/src/gui/dialogs/PitchPickerDialog.h b/src/gui/dialogs/PitchPickerDialog.h new file mode 100644 index 0000000..ebd0a6d --- /dev/null +++ b/src/gui/dialogs/PitchPickerDialog.h @@ -0,0 +1,57 @@ + +/* -*- 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_PITCHPICKERDIALOG_H_ +#define _RG_PITCHPICKERDIALOG_H_ + +#include "gui/widgets/PitchChooser.h" +#include <kdialogbase.h> + + +class QWidget; + + +namespace Rosegarden +{ + +class PitchPickerDialog : public KDialogBase +{ + Q_OBJECT + +public: + + PitchPickerDialog(QWidget* parent, int initialPitch, QString text); + ~PitchPickerDialog(); + + int getPitch() { return m_pitch->getPitch(); } + +private: + PitchChooser* m_pitch; +}; + + +} + +#endif diff --git a/src/gui/dialogs/QuantizeDialog.cpp b/src/gui/dialogs/QuantizeDialog.cpp new file mode 100644 index 0000000..b934dd5 --- /dev/null +++ b/src/gui/dialogs/QuantizeDialog.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 "QuantizeDialog.h" + +#include <klocale.h> +#include "base/Quantizer.h" +#include "gui/widgets/QuantizeParameters.h" +#include <kdialogbase.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +QuantizeDialog::QuantizeDialog(QWidget *parent, bool inNotation) : + KDialogBase(parent, 0, true, i18n("Quantize"), Ok | Cancel | Details | Help) +{ + setHelp("quantization"); + + QVBox *vbox = makeVBoxMainWidget(); + + m_quantizeFrame = + new QuantizeParameters + (vbox, inNotation ? QuantizeParameters::Notation : + QuantizeParameters::Grid, + true, false, 0); + + setButtonText(Details, i18n("Advanced")); + setDetailsWidget(m_quantizeFrame->getAdvancedWidget()); + m_quantizeFrame->getAdvancedWidget()->hide(); + + m_quantizeFrame->adjustSize(); + vbox->adjustSize(); + adjustSize(); +} + +Quantizer * +QuantizeDialog::getQuantizer() const +{ + return m_quantizeFrame->getQuantizer(); +} + +} +#include "QuantizeDialog.moc" diff --git a/src/gui/dialogs/QuantizeDialog.h b/src/gui/dialogs/QuantizeDialog.h new file mode 100644 index 0000000..a787dd1 --- /dev/null +++ b/src/gui/dialogs/QuantizeDialog.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_QUANTIZEDIALOG_H_ +#define _RG_QUANTIZEDIALOG_H_ + +#include <kdialogbase.h> + + +class QWidget; + + +namespace Rosegarden +{ + +class Quantizer; +class QuantizeParameters; + + +class QuantizeDialog : public KDialogBase +{ + Q_OBJECT + +public: + QuantizeDialog(QWidget *parent, bool inNotation = false); + + /// Returned quantizer object is on heap -- caller must delete + Quantizer *getQuantizer() const; + +protected: + QuantizeParameters *m_quantizeFrame; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/RescaleDialog.cpp b/src/gui/dialogs/RescaleDialog.cpp new file mode 100644 index 0000000..d99a6fb --- /dev/null +++ b/src/gui/dialogs/RescaleDialog.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 "RescaleDialog.h" + +#include <klocale.h> +#include "document/ConfigGroups.h" +#include "base/Composition.h" +#include "gui/widgets/TimeWidget.h" +#include <kconfig.h> +#include <kdialogbase.h> +#include <qcheckbox.h> +#include <qgroupbox.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> +#include <kapplication.h> + + +namespace Rosegarden +{ + +RescaleDialog::RescaleDialog(QWidget *parent, + Composition *composition, + timeT startTime, + timeT originalDuration, + bool showCloseGapOption, + bool constrainToCompositionDuration) : + KDialogBase(parent, 0, true, i18n("Rescale"), User1 | Ok | Cancel) +{ + QVBox *vbox = makeVBoxMainWidget(); + + m_newDuration = new TimeWidget + (i18n("Duration of selection"), vbox, composition, + startTime, originalDuration, true, + constrainToCompositionDuration); + + if (showCloseGapOption) { + QGroupBox *optionBox = new QGroupBox(1, Horizontal, i18n("Options"), vbox); + m_closeGap = new QCheckBox(i18n("Adjust times of following events accordingly"), + optionBox); + KConfig *config = kapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + m_closeGap->setChecked + (config->readBoolEntry("rescaledialogadjusttimes", true)); + } else { + m_closeGap = 0; + } + + setButtonText(User1, i18n("Reset")); + connect(this, SIGNAL(user1Clicked()), + m_newDuration, SLOT(slotResetToDefault())); +} + +timeT +RescaleDialog::getNewDuration() +{ + return m_newDuration->getTime(); +} + +bool +RescaleDialog::shouldCloseGap() +{ + if (m_closeGap) { + KConfig *config = kapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + config->writeEntry("rescaledialogadjusttimes", m_closeGap->isChecked()); + return m_closeGap->isChecked(); + } else { + return true; + } +} + +/* +int +RescaleDialog::getMultiplier() +{ + return m_to; +} + +int +RescaleDialog::getDivisor() +{ + return m_from; +} + +void +RescaleDialog::slotFromChanged(int i) +{ + m_from = i + 1; + int perTenThou = m_to * 10000 / m_from; + m_percent->setText(QString("%1.%2%"). + arg(perTenThou / 100). + arg(perTenThou % 100)); +} + +void +RescaleDialog::slotToChanged(int i) +{ + m_to = i + 1; + int perTenThou = m_to * 10000 / m_from; + m_percent->setText(QString("%1.%2%"). + arg(perTenThou / 100). + arg(perTenThou % 100)); +} +*/ + +} +#include "RescaleDialog.moc" diff --git a/src/gui/dialogs/RescaleDialog.h b/src/gui/dialogs/RescaleDialog.h new file mode 100644 index 0000000..196dd87 --- /dev/null +++ b/src/gui/dialogs/RescaleDialog.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_RESCALEDIALOG_H_ +#define _RG_RESCALEDIALOG_H_ + +#include <kdialogbase.h> +#include "base/Event.h" + + +class QWidget; +class QCheckBox; + + +namespace Rosegarden +{ + +class TimeWidget; +class Composition; + + +class RescaleDialog : public KDialogBase +{ + Q_OBJECT + +public: + RescaleDialog(QWidget *parent, + Composition *composition, // for TimeWidget calculations + timeT startTime, + timeT originalDuration, + bool showCloseGapOption, + bool constrainToCompositionDuration); + + timeT getNewDuration(); + bool shouldCloseGap(); + +protected: + TimeWidget *m_newDuration; + QCheckBox *m_closeGap; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/ShowSequencerStatusDialog.cpp b/src/gui/dialogs/ShowSequencerStatusDialog.cpp new file mode 100644 index 0000000..d98933c --- /dev/null +++ b/src/gui/dialogs/ShowSequencerStatusDialog.cpp @@ -0,0 +1,79 @@ +/* -*- 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 "ShowSequencerStatusDialog.h" + +#include <klocale.h> +#include <kdialogbase.h> +#include <qcstring.h> +#include <qdatastream.h> +#include <qlabel.h> +#include <qstring.h> +#include <qtextedit.h> +#include <qvbox.h> +#include <qwidget.h> +#include "gui/application/RosegardenApplication.h" + + +namespace Rosegarden +{ + +ShowSequencerStatusDialog::ShowSequencerStatusDialog(QWidget *parent) : + KDialogBase(parent, 0, true, i18n("Sequencer status"), Close) +{ + QVBox *vbox = makeVBoxMainWidget(); + + new QLabel(i18n("Sequencer status:"), vbox); + + QString status(i18n("Status not available.")); + + QCString replyType; + QByteArray replyData; + QByteArray data; + + if (!rgapp->sequencerCall("getStatusLog()", replyType, replyData)) { + status = i18n("Sequencer is not running or is not responding."); + } + + QDataStream streamIn(replyData, IO_ReadOnly); + QString result; + streamIn >> result; + if (!result) { + status = i18n("Sequencer is not returning a valid status report."); + } else { + status = result; + } + + QTextEdit *text = new QTextEdit(vbox); + text->setTextFormat(Qt::PlainText); + text->setReadOnly(true); + text->setMinimumWidth(500); + text->setMinimumHeight(200); + + text->setText(status); +} + +} +#include "ShowSequencerStatusDialog.moc" diff --git a/src/gui/dialogs/ShowSequencerStatusDialog.h b/src/gui/dialogs/ShowSequencerStatusDialog.h new file mode 100644 index 0000000..ce21ab1 --- /dev/null +++ b/src/gui/dialogs/ShowSequencerStatusDialog.h @@ -0,0 +1,54 @@ + +/* -*- 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_SHOWSEQUENCERSTATUSDIALOG_H_ +#define _RG_SHOWSEQUENCERSTATUSDIALOG_H_ + +#include <kdialogbase.h> + + +class QWidget; + + +namespace Rosegarden +{ + + + +class ShowSequencerStatusDialog : public KDialogBase +{ + Q_OBJECT +public: + ShowSequencerStatusDialog(QWidget *parent); +}; + + +// Timer dialog for counting down +// + + +} + +#endif diff --git a/src/gui/dialogs/SimpleEventEditDialog.cpp b/src/gui/dialogs/SimpleEventEditDialog.cpp new file mode 100644 index 0000000..ca6b76a --- /dev/null +++ b/src/gui/dialogs/SimpleEventEditDialog.cpp @@ -0,0 +1,1061 @@ +/* -*- 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 "SimpleEventEditDialog.h" +#include <qlayout.h> + +#include "base/BaseProperties.h" +#include "base/Event.h" +#include "base/MidiTypes.h" +#include "base/NotationTypes.h" +#include "document/RosegardenGUIDoc.h" +#include "gui/editors/guitar/Chord.h" +#include "misc/Strings.h" +#include "PitchDialog.h" +#include "TimeDialog.h" +#include <kcombobox.h> +#include <kdialogbase.h> +#include <kfiledialog.h> +#include <klocale.h> +#include <qcheckbox.h> +#include <qdialog.h> +#include <qfile.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qpushbutton.h> +#include <qspinbox.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +SimpleEventEditDialog::SimpleEventEditDialog(QWidget *parent, + RosegardenGUIDoc *doc, + const Event &event, + bool inserting) : + KDialogBase(parent, 0, true, + i18n(inserting ? "Insert Event" : "Edit Event"), Ok | Cancel), + m_event(event), + m_doc(doc), + m_type(event.getType()), + m_absoluteTime(event.getAbsoluteTime()), + m_duration(event.getDuration()), + m_modified(false) +{ + QVBox *vbox = makeVBoxMainWidget(); + + QGroupBox *groupBox = new QGroupBox + (1, Horizontal, i18n("Event Properties"), vbox); + + QFrame *frame = new QFrame(groupBox); + + QGridLayout *layout = new QGridLayout(frame, 7, 3, 5, 5); + + layout->addWidget(new QLabel(i18n("Event type:"), frame), 0, 0); + + if (inserting) { + + m_typeLabel = 0; + + m_typeCombo = new KComboBox(frame); + layout->addWidget(m_typeCombo, 0, 1); + + m_typeCombo->insertItem(strtoqstr(Note::EventType)); + m_typeCombo->insertItem(strtoqstr(Controller::EventType)); + m_typeCombo->insertItem(strtoqstr(KeyPressure::EventType)); + m_typeCombo->insertItem(strtoqstr(ChannelPressure::EventType)); + m_typeCombo->insertItem(strtoqstr(ProgramChange::EventType)); + m_typeCombo->insertItem(strtoqstr(SystemExclusive::EventType)); + m_typeCombo->insertItem(strtoqstr(PitchBend::EventType)); + m_typeCombo->insertItem(strtoqstr(Indication::EventType)); + m_typeCombo->insertItem(strtoqstr(Text::EventType)); + m_typeCombo->insertItem(strtoqstr(Note::EventRestType)); + m_typeCombo->insertItem(strtoqstr(Clef::EventType)); + m_typeCombo->insertItem(strtoqstr(::Rosegarden::Key::EventType)); + m_typeCombo->insertItem(strtoqstr(Guitar::Chord::EventType)); + + // Connect up the combos + // + connect(m_typeCombo, SIGNAL(activated(int)), + SLOT(slotEventTypeChanged(int))); + + } else { + + m_typeCombo = 0; + + m_typeLabel = new QLabel(frame); + layout->addWidget(m_typeLabel, 0, 1); + } + + m_timeLabel = new QLabel(i18n("Absolute time:"), frame); + layout->addWidget(m_timeLabel, 1, 0); + m_timeSpinBox = new QSpinBox(INT_MIN, INT_MAX, Note(Note::Shortest).getDuration(), frame); + m_timeEditButton = new QPushButton("edit", frame); + layout->addWidget(m_timeSpinBox, 1, 1); + layout->addWidget(m_timeEditButton, 1, 2); + + connect(m_timeSpinBox, SIGNAL(valueChanged(int)), + SLOT(slotAbsoluteTimeChanged(int))); + connect(m_timeEditButton, SIGNAL(released()), + SLOT(slotEditAbsoluteTime())); + + m_durationLabel = new QLabel(i18n("Duration:"), frame); + layout->addWidget(m_durationLabel, 2, 0); + m_durationSpinBox = new QSpinBox(0, INT_MAX, Note(Note::Shortest).getDuration(), frame); + m_durationEditButton = new QPushButton("edit", frame); + layout->addWidget(m_durationSpinBox, 2, 1); + layout->addWidget(m_durationEditButton, 2, 2); + + connect(m_durationSpinBox, SIGNAL(valueChanged(int)), + SLOT(slotDurationChanged(int))); + connect(m_durationEditButton, SIGNAL(released()), + SLOT(slotEditDuration())); + + m_pitchLabel = new QLabel(i18n("Pitch:"), frame); + layout->addWidget(m_pitchLabel, 3, 0); + m_pitchSpinBox = new QSpinBox(frame); + m_pitchEditButton = new QPushButton("edit", frame); + layout->addWidget(m_pitchSpinBox, 3, 1); + layout->addWidget(m_pitchEditButton, 3, 2); + + connect(m_pitchSpinBox, SIGNAL(valueChanged(int)), + SLOT(slotPitchChanged(int))); + connect(m_pitchEditButton, SIGNAL(released()), + SLOT(slotEditPitch())); + + m_pitchSpinBox->setMinValue(MidiMinValue); + m_pitchSpinBox->setMaxValue(MidiMaxValue); + + m_controllerLabel = new QLabel(i18n("Controller name:"), frame); + m_controllerLabelValue = new QLabel(i18n("<none>"), frame); + m_controllerLabelValue->setAlignment(QLabel::AlignRight); + + layout->addWidget(m_controllerLabel, 4, 0); + layout->addWidget(m_controllerLabelValue, 4, 1); + + m_velocityLabel = new QLabel(i18n("Velocity:"), frame); + layout->addWidget(m_velocityLabel, 5, 0); + m_velocitySpinBox = new QSpinBox(frame); + layout->addWidget(m_velocitySpinBox, 5, 1); + + connect(m_velocitySpinBox, SIGNAL(valueChanged(int)), + SLOT(slotVelocityChanged(int))); + + m_velocitySpinBox->setMinValue(MidiMinValue); + m_velocitySpinBox->setMaxValue(MidiMaxValue); + + m_metaLabel = new QLabel(i18n("Meta string:"), frame); + layout->addWidget(m_metaLabel, 6, 0); + m_metaEdit = new QLineEdit(frame); + layout->addWidget(m_metaEdit, 6, 1); + + m_sysexLoadButton = new QPushButton(i18n("Load data"), frame); + layout->addWidget(m_sysexLoadButton, 6, 2); + m_sysexSaveButton = new QPushButton(i18n("Save data"), frame); + layout->addWidget(m_sysexSaveButton, 4, 2); + + connect(m_metaEdit, SIGNAL(textChanged(const QString &)), + SLOT(slotMetaChanged(const QString &))); + connect(m_sysexLoadButton, SIGNAL(released()), + SLOT(slotSysexLoad())); + connect(m_sysexSaveButton, SIGNAL(released()), + SLOT(slotSysexSave())); + + m_notationGroupBox = new QGroupBox + (1, Horizontal, i18n("Notation Properties"), vbox); + + frame = new QFrame(m_notationGroupBox); + + layout = new QGridLayout(frame, 3, 3, 5, 5); + + m_lockNotationValues = new QCheckBox(i18n("Lock to changes in performed values"), frame); + layout->addMultiCellWidget(m_lockNotationValues, 0, 0, 0, 2); + m_lockNotationValues->setChecked(true); + + connect(m_lockNotationValues, SIGNAL(released()), + SLOT(slotLockNotationChanged())); + + m_notationTimeLabel = new QLabel(i18n("Notation time:"), frame); + layout->addWidget(m_notationTimeLabel, 1, 0); + m_notationTimeSpinBox = new QSpinBox(INT_MIN, INT_MAX, Note(Note::Shortest).getDuration(), frame); + m_notationTimeEditButton = new QPushButton("edit", frame); + layout->addWidget(m_notationTimeSpinBox, 1, 1); + layout->addWidget(m_notationTimeEditButton, 1, 2); + + connect(m_notationTimeSpinBox, SIGNAL(valueChanged(int)), + SLOT(slotNotationAbsoluteTimeChanged(int))); + connect(m_notationTimeEditButton, SIGNAL(released()), + SLOT(slotEditNotationAbsoluteTime())); + + m_notationDurationLabel = new QLabel(i18n("Notation duration:"), frame); + layout->addWidget(m_notationDurationLabel, 2, 0); + m_notationDurationSpinBox = new QSpinBox(0, INT_MAX, Note(Note::Shortest).getDuration(), frame); + m_notationDurationEditButton = new QPushButton("edit", frame); + layout->addWidget(m_notationDurationSpinBox, 2, 1); + layout->addWidget(m_notationDurationEditButton, 2, 2); + + connect(m_notationDurationSpinBox, SIGNAL(valueChanged(int)), + SLOT(slotNotationDurationChanged(int))); + connect(m_notationDurationEditButton, SIGNAL(released()), + SLOT(slotEditNotationDuration())); + + setupForEvent(); +} + +void +SimpleEventEditDialog::setupForEvent() +{ + using BaseProperties::PITCH; + using BaseProperties::VELOCITY; + + if (m_typeCombo) { + m_typeCombo->blockSignals(true); + } + m_timeSpinBox->blockSignals(true); + m_notationTimeSpinBox->blockSignals(true); + m_durationSpinBox->blockSignals(true); + m_notationDurationSpinBox->blockSignals(true); + m_pitchSpinBox->blockSignals(true); + m_velocitySpinBox->blockSignals(true); + m_metaEdit->blockSignals(true); + + m_pitchSpinBox->setMinValue(MidiMinValue); + m_pitchSpinBox->setMaxValue(MidiMaxValue); + + // Some common settings + // + m_durationLabel->setText(i18n("Absolute time:")); + m_timeLabel->show(); + m_timeSpinBox->show(); + m_timeEditButton->show(); + m_timeSpinBox->setValue(m_event.getAbsoluteTime()); + + m_durationLabel->setText(i18n("Duration:")); + m_durationLabel->show(); + m_durationSpinBox->show(); + m_durationEditButton->show(); + m_durationSpinBox->setValue(m_event.getDuration()); + + m_notationGroupBox->hide(); + m_lockNotationValues->setChecked(true); + + if (m_typeLabel) + m_typeLabel->setText(strtoqstr(m_event.getType())); + + m_absoluteTime = m_event.getAbsoluteTime(); + m_notationAbsoluteTime = m_event.getNotationAbsoluteTime(); + m_duration = m_event.getDuration(); + m_notationDuration = m_event.getNotationDuration(); + + m_sysexLoadButton->hide(); + m_sysexSaveButton->hide(); + + if (m_type == Note::EventType) { + m_notationGroupBox->show(); + m_notationTimeSpinBox->setValue(m_notationAbsoluteTime); + m_notationDurationSpinBox->setValue(m_notationDuration); + + m_pitchLabel->show(); + m_pitchLabel->setText(i18n("Note pitch:")); + m_pitchSpinBox->show(); + m_pitchEditButton->show(); + + m_controllerLabel->hide(); + m_controllerLabelValue->hide(); + + m_velocityLabel->show(); + m_velocityLabel->setText(i18n("Note velocity:")); + m_velocitySpinBox->show(); + + m_metaLabel->hide(); + m_metaEdit->hide(); + + try { + m_pitchSpinBox->setValue(m_event.get<Int>(PITCH)); + } catch (Event::NoData) { + m_pitchSpinBox->setValue(60); + } + + try { + m_velocitySpinBox->setValue(m_event.get<Int>(VELOCITY)); + } catch (Event::NoData) { + m_velocitySpinBox->setValue(100); + } + + if (m_typeCombo) + m_typeCombo->setCurrentItem(0); + + } else if (m_type == Controller::EventType) { + + m_durationLabel->hide(); + m_durationSpinBox->hide(); + m_durationEditButton->hide(); + + m_pitchLabel->show(); + m_pitchLabel->setText(i18n("Controller number:")); + m_pitchSpinBox->show(); + m_pitchEditButton->hide(); + + m_controllerLabel->show(); + m_controllerLabelValue->show(); + m_controllerLabel->setText(i18n("Controller name:")); + + m_velocityLabel->show(); + m_velocityLabel->setText(i18n("Controller value:")); + m_velocitySpinBox->show(); + + m_metaLabel->hide(); + m_metaEdit->hide(); + + try { + m_pitchSpinBox->setValue(m_event.get<Int> + (Controller::NUMBER)); + } catch (Event::NoData) { + m_pitchSpinBox->setValue(0); + } + + try { + m_velocitySpinBox->setValue(m_event.get<Int> + (Controller::VALUE)); + } catch (Event::NoData) { + m_velocitySpinBox->setValue(0); + } + + if (m_typeCombo) + m_typeCombo->setCurrentItem(1); + + } else if (m_type == KeyPressure::EventType) { + + m_durationLabel->hide(); + m_durationSpinBox->hide(); + m_durationEditButton->hide(); + + m_pitchLabel->show(); + m_pitchLabel->setText(i18n("Key pitch:")); + m_pitchSpinBox->show(); + m_pitchEditButton->show(); + + m_controllerLabel->hide(); + m_controllerLabelValue->hide(); + + m_velocityLabel->show(); + m_velocityLabel->setText(i18n("Key pressure:")); + m_velocitySpinBox->show(); + + m_metaLabel->hide(); + m_metaEdit->hide(); + + try { + m_pitchSpinBox->setValue(m_event.get<Int> + (KeyPressure::PITCH)); + } catch (Event::NoData) { + m_pitchSpinBox->setValue(0); + } + + try { + m_velocitySpinBox->setValue(m_event.get<Int> + (KeyPressure::PRESSURE)); + } catch (Event::NoData) { + m_velocitySpinBox->setValue(0); + } + + if (m_typeCombo) + m_typeCombo->setCurrentItem(2); + + } else if (m_type == ChannelPressure::EventType) { + + m_durationLabel->hide(); + m_durationSpinBox->hide(); + m_durationEditButton->hide(); + + m_pitchLabel->show(); + m_pitchLabel->setText(i18n("Channel pressure:")); + m_pitchSpinBox->show(); + m_pitchEditButton->hide(); + + m_controllerLabel->hide(); + m_controllerLabelValue->hide(); + + m_velocityLabel->hide(); + m_velocitySpinBox->hide(); + + m_metaLabel->hide(); + m_metaEdit->hide(); + + try { + m_pitchSpinBox->setValue(m_event.get<Int> + (ChannelPressure::PRESSURE)); + } catch (Event::NoData) { + m_pitchSpinBox->setValue(0); + } + + if (m_typeCombo) + m_typeCombo->setCurrentItem(3); + + } else if (m_type == ProgramChange::EventType) { + + m_durationLabel->hide(); + m_durationSpinBox->hide(); + m_durationEditButton->hide(); + + m_pitchSpinBox->setMinValue(MidiMinValue + 1); + m_pitchSpinBox->setMaxValue(MidiMaxValue + 1); + + m_pitchLabel->show(); + m_pitchLabel->setText(i18n("Program change:")); + m_pitchSpinBox->show(); + m_pitchEditButton->hide(); + + m_controllerLabel->hide(); + m_controllerLabelValue->hide(); + + m_velocityLabel->hide(); + m_velocitySpinBox->hide(); + + m_metaLabel->hide(); + m_metaEdit->hide(); + + try { + m_pitchSpinBox->setValue(m_event.get<Int> + (ProgramChange::PROGRAM) + 1); + } catch (Event::NoData) { + m_pitchSpinBox->setValue(0); + } + + if (m_typeCombo) + m_typeCombo->setCurrentItem(4); + + } else if (m_type == SystemExclusive::EventType) { + + m_durationLabel->hide(); + m_durationSpinBox->hide(); + m_durationEditButton->hide(); + + m_pitchLabel->hide(); + m_pitchSpinBox->hide(); + m_pitchEditButton->hide(); + + m_controllerLabel->show(); + m_controllerLabelValue->show(); + + m_velocityLabel->hide(); + m_velocitySpinBox->hide(); + + m_metaLabel->show(); + m_metaEdit->show(); + + m_sysexLoadButton->show(); + m_sysexSaveButton->show(); + + m_controllerLabel->setText(i18n("Data length:")); + m_metaLabel->setText(i18n("Data:")); + try { + SystemExclusive sysEx(m_event); + m_controllerLabelValue->setText(QString("%1"). + arg(sysEx.getRawData().length())); + m_metaEdit->setText(strtoqstr(sysEx.getHexData())); + } catch (...) { + m_controllerLabelValue->setText("0"); + } + + if (m_typeCombo) + m_typeCombo->setCurrentItem(5); + + } else if (m_type == PitchBend::EventType) { + + m_durationLabel->hide(); + m_durationSpinBox->hide(); + m_durationEditButton->hide(); + + m_pitchLabel->show(); + m_pitchLabel->setText(i18n("Pitchbend MSB:")); + m_pitchSpinBox->show(); + m_pitchEditButton->hide(); + + m_controllerLabel->hide(); + m_controllerLabelValue->hide(); + + m_velocityLabel->show(); + m_velocityLabel->setText(i18n("Pitchbend LSB:")); + m_velocitySpinBox->show(); + + m_metaLabel->hide(); + m_metaEdit->hide(); + + try { + m_pitchSpinBox->setValue(m_event.get<Int> + (PitchBend::MSB)); + } catch (Event::NoData) { + m_pitchSpinBox->setValue(0); + } + + try { + m_velocitySpinBox->setValue(m_event.get<Int> + (PitchBend::LSB)); + } catch (Event::NoData) { + m_velocitySpinBox->setValue(0); + } + + if (m_typeCombo) + m_typeCombo->setCurrentItem(6); + + } else if (m_type == Indication::EventType) { + + m_pitchLabel->hide(); + m_pitchSpinBox->hide(); + m_pitchEditButton->hide(); + + m_controllerLabel->hide(); + m_controllerLabelValue->hide(); + + m_velocityLabel->hide(); + m_velocitySpinBox->hide(); + + m_metaLabel->show(); + m_metaEdit->show(); + m_metaLabel->setText(i18n("Indication:")); + + try { + Indication ind(m_event); + m_metaEdit->setText(strtoqstr(ind.getIndicationType())); + m_durationSpinBox->setValue(ind.getIndicationDuration()); + } catch (...) { + m_metaEdit->setText(i18n("<none>")); + } + + if (m_typeCombo) + m_typeCombo->setCurrentItem(7); + + } else if (m_type == Text::EventType) { + + m_durationLabel->hide(); + m_durationSpinBox->hide(); + m_durationEditButton->hide(); + + m_pitchLabel->hide(); + m_pitchSpinBox->hide(); + m_pitchEditButton->hide(); + + m_controllerLabel->show(); + m_controllerLabelValue->show(); + + m_velocityLabel->hide(); + m_velocitySpinBox->hide(); + + m_metaLabel->show(); + m_metaEdit->show(); + + m_controllerLabel->setText(i18n("Text type:")); + m_metaLabel->setText(i18n("Text:")); + + // get the text event + try { + Text text(m_event); + m_controllerLabelValue->setText(strtoqstr(text.getTextType())); + m_metaEdit->setText(strtoqstr(text.getText())); + } catch (...) { + m_controllerLabelValue->setText(i18n("<none>")); + m_metaEdit->setText(i18n("<none>")); + } + + if (m_typeCombo) + m_typeCombo->setCurrentItem(8); + + } else if (m_type == Note::EventRestType) { + + m_pitchLabel->hide(); + m_pitchSpinBox->hide(); + m_pitchEditButton->hide(); + + m_controllerLabel->hide(); + m_controllerLabelValue->hide(); + + m_velocityLabel->hide(); + m_velocitySpinBox->hide(); + + m_metaLabel->hide(); + m_metaEdit->hide(); + + if (m_typeCombo) + m_typeCombo->setCurrentItem(9); + + } else if (m_type == Clef::EventType) { + + m_durationLabel->hide(); + m_durationSpinBox->hide(); + m_durationEditButton->hide(); + + m_pitchLabel->hide(); + m_pitchSpinBox->hide(); + m_pitchEditButton->hide(); + + m_controllerLabel->show(); + m_controllerLabelValue->show(); + + m_controllerLabel->setText(i18n("Clef type:")); + + try { + Clef clef(m_event); + m_controllerLabelValue->setText(strtoqstr(clef.getClefType())); + } catch (...) { + m_controllerLabelValue->setText(i18n("<none>")); + } + + m_velocityLabel->hide(); + m_velocitySpinBox->hide(); + + m_metaLabel->hide(); + m_metaEdit->hide(); + + if (m_typeCombo) + m_typeCombo->setCurrentItem(10); + + } else if (m_type == ::Rosegarden::Key::EventType) { + + m_durationLabel->hide(); + m_durationSpinBox->hide(); + m_durationEditButton->hide(); + + m_pitchLabel->hide(); + m_pitchSpinBox->hide(); + m_pitchEditButton->hide(); + + m_controllerLabel->show(); + m_controllerLabelValue->show(); + + m_controllerLabel->setText(i18n("Key name:")); + + try { + ::Rosegarden::Key key(m_event); + m_controllerLabelValue->setText(strtoqstr(key.getName())); + } catch (...) { + m_controllerLabelValue->setText(i18n("<none>")); + } + + m_velocityLabel->hide(); + m_velocitySpinBox->hide(); + + m_metaLabel->hide(); + m_metaEdit->hide(); + + if (m_typeCombo) + m_typeCombo->setCurrentItem(11); + + } else if (m_type == Guitar::Chord::EventType) { + + m_durationLabel->hide(); + m_durationSpinBox->hide(); + m_durationEditButton->hide(); + + m_pitchLabel->hide(); + m_pitchSpinBox->hide(); + m_pitchEditButton->hide(); + + m_controllerLabel->hide(); + m_controllerLabelValue->hide(); + + m_velocityLabel->hide(); + m_velocitySpinBox->hide(); + + m_metaLabel->hide(); + m_metaEdit->hide(); + + // m_controllerLabel->setText(i18n("Text type:")); + // m_metaLabel->setText(i18n("Chord:")); + + // get the fingering event + try { + Guitar::Chord chord( m_event ); + } catch (...) { + // m_controllerLabelValue->setText(i18n("<none>")); + // m_metaEdit->setText(i18n("<none>")); + } + + if (m_typeCombo) + m_typeCombo->setCurrentItem(12); + + } else { + + m_durationLabel->setText(i18n("Unsupported event type:")); + m_durationLabel->show(); + m_durationSpinBox->hide(); + m_durationEditButton->hide(); + + m_pitchLabel->hide(); + m_pitchSpinBox->hide(); + m_pitchEditButton->hide(); + + m_controllerLabel->hide(); + m_controllerLabelValue->show(); + m_controllerLabelValue->setText(strtoqstr(m_type)); + + m_velocityLabel->hide(); + m_velocitySpinBox->hide(); + + m_metaLabel->hide(); + m_metaEdit->hide(); + + if (m_typeCombo) + m_typeCombo->setEnabled(false); + } + + if (m_typeCombo) + m_typeCombo->blockSignals(false); + m_timeSpinBox->blockSignals(false); + m_notationTimeSpinBox->blockSignals(false); + m_durationSpinBox->blockSignals(false); + m_notationDurationSpinBox->blockSignals(false); + m_pitchSpinBox->blockSignals(false); + m_velocitySpinBox->blockSignals(false); + m_metaEdit->blockSignals(false); + + slotLockNotationChanged(); +} + +Event +SimpleEventEditDialog::getEvent() +{ + bool useSeparateNotationValues = + (m_event.getType() == Note::EventType); + + if (m_typeCombo) { + + int subordering = 0; + if (m_type == Indication::EventType) { + subordering = Indication::EventSubOrdering; + } else if (m_type == Clef::EventType) { + subordering = Clef::EventSubOrdering; + } else if (m_type == ::Rosegarden::Key::EventType) { + subordering = ::Rosegarden::Key::EventSubOrdering; + } else if (m_type == Text::EventType) { + subordering = Text::EventSubOrdering; + } else if (m_type == Note::EventRestType) { + subordering = Note::EventRestSubOrdering; + } else if (m_type == PitchBend::EventType) { + subordering = PitchBend::EventSubOrdering; + } else if (m_type == Controller::EventType) { + subordering = Controller::EventSubOrdering; + } else if (m_type == KeyPressure::EventType) { + subordering = KeyPressure::EventSubOrdering; + } else if (m_type == ChannelPressure::EventType) { + subordering = ChannelPressure::EventSubOrdering; + } else if (m_type == ProgramChange::EventType) { + subordering = ProgramChange::EventSubOrdering; + } else if (m_type == SystemExclusive::EventType) { + subordering = SystemExclusive::EventSubOrdering; + } + + m_event = Event(m_type, + m_absoluteTime, + m_duration, + subordering, + (useSeparateNotationValues ? + m_notationAbsoluteTime : m_absoluteTime), + (useSeparateNotationValues ? + m_notationDuration : m_duration)); + + // ensure these are set on m_event correctly + slotPitchChanged(m_pitchSpinBox->value()); + slotVelocityChanged(m_velocitySpinBox->value()); + } + + Event event(m_event, + m_absoluteTime, + m_duration, + m_event.getSubOrdering(), + (useSeparateNotationValues ? + m_notationAbsoluteTime : m_absoluteTime), + (useSeparateNotationValues ? + m_notationDuration : m_duration)); + + // Values from the pitch and velocity spin boxes should already + // have been set on m_event (and thus on event) by slotPitchChanged + // and slotVelocityChanged. Absolute time and duration were set in + // the event ctor above; that just leaves the meta values. + + if (m_type == Indication::EventType) { + + event.set<String>(Indication::IndicationTypePropertyName, + qstrtostr(m_metaEdit->text())); + + } else if (m_type == Text::EventType) { + + event.set<String>(Text::TextTypePropertyName, + qstrtostr(m_controllerLabelValue->text())); + event.set<String>(Text::TextPropertyName, + qstrtostr(m_metaEdit->text())); + + } else if (m_type == Clef::EventType) { + + event.set<String>(Clef::ClefPropertyName, + qstrtostr(m_controllerLabelValue->text())); + + } else if (m_type == ::Rosegarden::Key::EventType) { + + event.set<String>(::Rosegarden::Key::KeyPropertyName, + qstrtostr(m_controllerLabelValue->text())); + + } else if (m_type == SystemExclusive::EventType) { + + event.set<String>(SystemExclusive::DATABLOCK, + qstrtostr(m_metaEdit->text())); + + } + + return event; +} + +void +SimpleEventEditDialog::slotEventTypeChanged(int value) +{ + m_type = qstrtostr(m_typeCombo->text(value)); + m_modified = true; + + if (m_type != m_event.getType()) + Event m_event(m_type, m_absoluteTime, m_duration); + + setupForEvent(); + + // update whatever pitch and velocity correspond to + if (!m_pitchSpinBox->isHidden()) + slotPitchChanged(m_pitchSpinBox->value()); + if (!m_velocitySpinBox->isHidden()) + slotVelocityChanged(m_velocitySpinBox->value()); +} + +void +SimpleEventEditDialog::slotAbsoluteTimeChanged(int value) +{ + m_absoluteTime = value; + + if (m_notationGroupBox->isHidden()) { + m_notationAbsoluteTime = value; + } else if (m_lockNotationValues->isChecked()) { + m_notationAbsoluteTime = value; + m_notationTimeSpinBox->setValue(value); + } + + m_modified = true; +} + +void +SimpleEventEditDialog::slotNotationAbsoluteTimeChanged(int value) +{ + m_notationAbsoluteTime = value; + m_modified = true; +} + +void +SimpleEventEditDialog::slotDurationChanged(int value) +{ + m_duration = value; + + if (m_notationGroupBox->isHidden()) { + m_notationDuration = value; + } else if (m_lockNotationValues->isChecked()) { + m_notationDuration = value; + m_notationDurationSpinBox->setValue(value); + } + + m_modified = true; +} + +void +SimpleEventEditDialog::slotNotationDurationChanged(int value) +{ + m_notationDuration = value; + m_modified = true; +} + +void +SimpleEventEditDialog::slotPitchChanged(int value) +{ + m_modified = true; + + if (m_type == Note::EventType) { + m_event.set<Int>(BaseProperties::PITCH, value); + + } else if (m_type == Controller::EventType) { + m_event.set<Int>(Controller::NUMBER, value); + + } else if (m_type == KeyPressure::EventType) { + m_event.set<Int>(KeyPressure::PITCH, value); + + } else if (m_type == ChannelPressure::EventType) { + m_event.set<Int>(ChannelPressure::PRESSURE, value); + + } else if (m_type == ProgramChange::EventType) { + if (value < 1) + value = 1; + m_event.set<Int>(ProgramChange::PROGRAM, value - 1); + + } else if (m_type == PitchBend::EventType) { + m_event.set<Int>(PitchBend::MSB, value); + } + //!!!??? sysex? +} + +void +SimpleEventEditDialog::slotVelocityChanged(int value) +{ + m_modified = true; + + if (m_type == Note::EventType) { + m_event.set<Int>(BaseProperties::VELOCITY, value); + + } else if (m_type == Controller::EventType) { + m_event.set<Int>(Controller::VALUE, value); + + } else if (m_type == KeyPressure::EventType) { + m_event.set<Int>(KeyPressure::PRESSURE, value); + + } else if (m_type == PitchBend::EventType) { + m_event.set<Int>(PitchBend::LSB, value); + } +} + +void +SimpleEventEditDialog::slotMetaChanged(const QString &) +{ + m_modified = true; +} + +void +SimpleEventEditDialog::slotLockNotationChanged() +{ + bool enable = !m_lockNotationValues->isChecked(); + m_notationTimeSpinBox->setEnabled(enable); + m_notationTimeEditButton->setEnabled(enable); + m_notationDurationSpinBox->setEnabled(enable); + m_notationDurationEditButton->setEnabled(enable); +} + +void +SimpleEventEditDialog::slotEditAbsoluteTime() +{ + TimeDialog dialog(this, i18n("Edit Event Time"), + &m_doc->getComposition(), + m_timeSpinBox->value(), + true); + if (dialog.exec() == QDialog::Accepted) { + m_timeSpinBox->setValue(dialog.getTime()); + } +} + +void +SimpleEventEditDialog::slotEditNotationAbsoluteTime() +{ + TimeDialog dialog(this, i18n("Edit Event Notation Time"), + &m_doc->getComposition(), + m_notationTimeSpinBox->value(), + true); + if (dialog.exec() == QDialog::Accepted) { + m_notationTimeSpinBox->setValue(dialog.getTime()); + } +} + +void +SimpleEventEditDialog::slotEditDuration() +{ + TimeDialog dialog(this, i18n("Edit Duration"), + &m_doc->getComposition(), + m_timeSpinBox->value(), + m_durationSpinBox->value(), + true); + if (dialog.exec() == QDialog::Accepted) { + m_durationSpinBox->setValue(dialog.getTime()); + } +} + +void +SimpleEventEditDialog::slotEditNotationDuration() +{ + TimeDialog dialog(this, i18n("Edit Notation Duration"), + &m_doc->getComposition(), + m_notationTimeSpinBox->value(), + m_notationDurationSpinBox->value(), + true); + if (dialog.exec() == QDialog::Accepted) { + m_notationDurationSpinBox->setValue(dialog.getTime()); + } +} + +void +SimpleEventEditDialog::slotEditPitch() +{ + PitchDialog dialog(this, i18n("Edit Pitch"), m_pitchSpinBox->value()); + if (dialog.exec() == QDialog::Accepted) { + m_pitchSpinBox->setValue(dialog.getPitch()); + } +} + +void +SimpleEventEditDialog::slotSysexLoad() +{ + QString path = KFileDialog::getOpenFileName(":SYSTEMEXCLUSIVE", + i18n("*.syx|System exclusive files (*.syx)"), + this, i18n("Load System Exclusive data in File")); + if (path.isNull()) + return ; + + QFile file(path); + file.open(IO_ReadOnly); + std::string s; + unsigned char c; + while (((c = (unsigned char)file.getch()) != 0xf0) && (file.status() == IO_Ok)) + ; + while ( file.status() == IO_Ok ) { + s += c; + if (c == 0xf7 ) + break; + c = (unsigned char)file.getch(); + } + file.close(); + m_metaEdit->setText(strtoqstr(SystemExclusive::toHex(s))); +} + +void +SimpleEventEditDialog::slotSysexSave() +{ + QString path = KFileDialog::getSaveFileName(":SYSTEMEXCLUSIVE", + i18n("*.syx|System exclusive files (*.syx)"), + this, i18n("Save System Exclusive data to...")); + if (path.isNull()) + return ; + + QFile file(path); + file.open(IO_WriteOnly); + SystemExclusive sysEx(m_event); + file.writeBlock(sysEx.getRawData().c_str(), sysEx.getRawData().length()); + file.close(); +} + +} +#include "SimpleEventEditDialog.moc" diff --git a/src/gui/dialogs/SimpleEventEditDialog.h b/src/gui/dialogs/SimpleEventEditDialog.h new file mode 100644 index 0000000..60b8441 --- /dev/null +++ b/src/gui/dialogs/SimpleEventEditDialog.h @@ -0,0 +1,134 @@ + +/* -*- 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_SIMPLEEVENTEDITDIALOG_H_ +#define _RG_SIMPLEEVENTEDITDIALOG_H_ + +#include "base/Event.h" +#include <string> +#include <kdialogbase.h> + + +class QWidget; +class QString; +class QSpinBox; +class QPushButton; +class QLineEdit; +class QLabel; +class QGroupBox; +class QCheckBox; +class KComboBox; + + +namespace Rosegarden +{ + +class RosegardenGUIDoc; + + +class SimpleEventEditDialog : public KDialogBase +{ + Q_OBJECT +public: + SimpleEventEditDialog(QWidget *parent, + RosegardenGUIDoc *doc, + const Event &event, + bool inserting = false); // inserting or editing + + bool isModified() const { return m_modified; } + Event getEvent(); + + // Setup the dialog for a new event type + void setupForEvent(); + +public slots: + void slotEventTypeChanged(int value); + void slotAbsoluteTimeChanged(int value); + void slotDurationChanged(int value); + void slotNotationAbsoluteTimeChanged(int value); + void slotNotationDurationChanged(int value); + void slotPitchChanged(int value); + void slotVelocityChanged(int value); + void slotMetaChanged(const QString &); + void slotEditAbsoluteTime(); + void slotEditNotationAbsoluteTime(); + void slotEditDuration(); + void slotEditNotationDuration(); + void slotLockNotationChanged(); + void slotEditPitch(); + void slotSysexLoad(); + void slotSysexSave(); + +protected: + Event m_event; + RosegardenGUIDoc *m_doc; + + std::string m_type; + timeT m_absoluteTime; + timeT m_notationAbsoluteTime; + timeT m_duration; + timeT m_notationDuration; + + KComboBox *m_typeCombo; + QLabel *m_typeLabel; + + QLabel *m_timeLabel; + QLabel *m_durationLabel; + QLabel *m_pitchLabel; + QLabel *m_velocityLabel; + QLabel *m_metaLabel; + QLabel *m_controllerLabel; + QLabel *m_controllerLabelValue; + + QSpinBox *m_timeSpinBox; + QSpinBox *m_durationSpinBox; + QSpinBox *m_pitchSpinBox; + QSpinBox *m_velocitySpinBox; + + QPushButton *m_timeEditButton; + QPushButton *m_durationEditButton; + QPushButton *m_pitchEditButton; + QPushButton *m_sysexLoadButton; + QPushButton *m_sysexSaveButton; + + QGroupBox *m_notationGroupBox; + QLabel *m_notationTimeLabel; + QLabel *m_notationDurationLabel; + QSpinBox *m_notationTimeSpinBox; + QSpinBox *m_notationDurationSpinBox; + QPushButton *m_notationTimeEditButton; + QPushButton *m_notationDurationEditButton; + QCheckBox *m_lockNotationValues; + + QLineEdit *m_metaEdit; + + bool m_modified; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/SplitByPitchDialog.cpp b/src/gui/dialogs/SplitByPitchDialog.cpp new file mode 100644 index 0000000..9b3dffa --- /dev/null +++ b/src/gui/dialogs/SplitByPitchDialog.cpp @@ -0,0 +1,111 @@ +/* -*- 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 "SplitByPitchDialog.h" + +#include <klocale.h> +#include "commands/segment/SegmentSplitByPitchCommand.h" +#include "gui/general/ClefIndex.h" +#include "gui/widgets/PitchChooser.h" +#include <kcombobox.h> +#include <kdialogbase.h> +#include <qcheckbox.h> +#include <qframe.h> +#include <qlabel.h> +#include <qvbox.h> +#include <qwidget.h> +#include <qlayout.h> + + +namespace Rosegarden +{ + +SplitByPitchDialog::SplitByPitchDialog(QWidget *parent) : + KDialogBase(parent, 0, true, i18n("Split by Pitch"), Ok | Cancel) +{ + QVBox *vBox = makeVBoxMainWidget(); + + QFrame *frame = new QFrame(vBox); + + QGridLayout *layout = new QGridLayout(frame, 4, 3, 10, 5); + + m_pitch = new PitchChooser(i18n("Starting split pitch"), frame, 60); + layout->addMultiCellWidget(m_pitch, 0, 0, 0, 2, Qt::AlignHCenter); + + m_range = new QCheckBox(i18n("Range up and down to follow music"), frame); + layout->addMultiCellWidget(m_range, + 1, 1, // fromRow, toRow + 0, 2 // fromCol, toCol + ); + + m_duplicate = new QCheckBox(i18n("Duplicate non-note events"), frame); + layout->addMultiCellWidget(m_duplicate, 2, 2, 0, 2); + + layout->addWidget(new QLabel(i18n("Clef handling:"), frame), 3, 0); + + m_clefs = new KComboBox(frame); + m_clefs->insertItem(i18n("Leave clefs alone")); + m_clefs->insertItem(i18n("Guess new clefs")); + m_clefs->insertItem(i18n("Use treble and bass clefs")); + layout->addMultiCellWidget(m_clefs, 3, 3, 1, 2); + + m_range->setChecked(true); + m_duplicate->setChecked(true); + m_clefs->setCurrentItem(2); +} + +int +SplitByPitchDialog::getPitch() +{ + return m_pitch->getPitch(); +} + +bool +SplitByPitchDialog::getShouldRange() +{ + return m_range->isChecked(); +} + +bool +SplitByPitchDialog::getShouldDuplicateNonNoteEvents() +{ + return m_duplicate->isChecked(); +} + +int +SplitByPitchDialog::getClefHandling() +{ + switch (m_clefs->currentItem()) { + case 0: + return (int)SegmentSplitByPitchCommand::LeaveClefs; + case 1: + return (int)SegmentSplitByPitchCommand::RecalculateClefs; + default: + return (int)SegmentSplitByPitchCommand::UseTrebleAndBassClefs; + } +} + +} +#include "SplitByPitchDialog.moc" diff --git a/src/gui/dialogs/SplitByPitchDialog.h b/src/gui/dialogs/SplitByPitchDialog.h new file mode 100644 index 0000000..40a6fb8 --- /dev/null +++ b/src/gui/dialogs/SplitByPitchDialog.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_SPLITBYPITCHDIALOG_H_ +#define _RG_SPLITBYPITCHDIALOG_H_ + +#include <kdialogbase.h> + + +class QWidget; +class QCheckBox; +class KComboBox; + + +namespace Rosegarden +{ + +class PitchChooser; + + +class SplitByPitchDialog : public KDialogBase +{ + Q_OBJECT +public: + SplitByPitchDialog(QWidget *parent); + + int getPitch(); + + bool getShouldRange(); + bool getShouldDuplicateNonNoteEvents(); + int getClefHandling(); // actually SegmentSplitByPitchCommand::ClefHandling + +private: + PitchChooser *m_pitch; + + QCheckBox *m_range; + QCheckBox *m_duplicate; + KComboBox *m_clefs; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/SplitByRecordingSrcDialog.cpp b/src/gui/dialogs/SplitByRecordingSrcDialog.cpp new file mode 100644 index 0000000..cc61bfa --- /dev/null +++ b/src/gui/dialogs/SplitByRecordingSrcDialog.cpp @@ -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. +*/ + + +#include "SplitByRecordingSrcDialog.h" +#include <qlayout.h> + +#include <klocale.h> +#include "misc/Strings.h" +#include "base/MidiDevice.h" +#include "document/RosegardenGUIDoc.h" +#include <kcombobox.h> +#include <kdialogbase.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qsizepolicy.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +SplitByRecordingSrcDialog::SplitByRecordingSrcDialog(QWidget *parent, RosegardenGUIDoc *doc) : + KDialogBase(parent, 0, true, i18n("Split by Recording Source"), Ok | Cancel ) +{ + QVBox *vBox = makeVBoxMainWidget(); + + QGroupBox *groupBox = new QGroupBox + (1, Horizontal, i18n("Recording Source"), vBox); + QFrame *frame = new QFrame(groupBox); + QGridLayout *layout = new QGridLayout(frame, 2, 2, 10, 5); + + layout->addWidget(new QLabel( i18n("Channel:"), frame ), 0, 0); + m_channel = new KComboBox( frame ); + m_channel->setSizeLimit( 17 ); + layout->addWidget(m_channel, 0, 1); + QSpacerItem *spacer = new QSpacerItem( 1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum ); + layout->addItem( spacer, 0, 2 ); + + m_channel->insertItem(i18n("any")); + for (int i = 1; i < 17; ++i) { + m_channel->insertItem(QString::number(i)); + } + + layout->addWidget(new QLabel( i18n("Device:"), frame ), 1, 0); + m_device = new KComboBox( frame ); + layout->addMultiCellWidget( m_device, 1, 1, 1, 2 ); + + m_deviceIds.clear(); + m_deviceIds.push_back( -1); + m_device->insertItem(i18n("any")); + + DeviceList *devices = doc->getStudio().getDevices(); + DeviceListConstIterator it; + for (it = devices->begin(); it != devices->end(); it++) { + MidiDevice *dev = + dynamic_cast<MidiDevice*>(*it); + if (dev && dev->getDirection() == MidiDevice::Record) { + QString label = QString::number(dev->getId()); + label += ": "; + label += strtoqstr(dev->getName()); + QString connection = strtoqstr(dev->getConnection()); + label += " - "; + if (connection == "") + label += i18n("No connection"); + else + label += connection; + m_device->insertItem(label); + m_deviceIds.push_back(dev->getId()); + } + } + + m_channel->setCurrentItem(0); + m_device->setCurrentItem(0); +} + +int +SplitByRecordingSrcDialog::getChannel() +{ + return m_channel->currentItem() - 1; +} + +int +SplitByRecordingSrcDialog::getDevice() +{ + return m_deviceIds[m_device->currentItem()]; +} + +} +#include "SplitByRecordingSrcDialog.moc" diff --git a/src/gui/dialogs/SplitByRecordingSrcDialog.h b/src/gui/dialogs/SplitByRecordingSrcDialog.h new file mode 100644 index 0000000..af982a2 --- /dev/null +++ b/src/gui/dialogs/SplitByRecordingSrcDialog.h @@ -0,0 +1,62 @@ + +/* -*- 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_SPLITBYRECORDINGSRCDIALOG_H_ +#define _RG_SPLITBYRECORDINGSRCDIALOG_H_ + +#include <kdialogbase.h> +#include <vector> +#include "gui/application/RosegardenDCOP.h" + + +class QWidget; +class KComboBox; + + +namespace Rosegarden +{ + +class RosegardenGUIDoc; + + +class SplitByRecordingSrcDialog : public KDialogBase +{ + Q_OBJECT +public: + SplitByRecordingSrcDialog(QWidget *parent, RosegardenGUIDoc *doc); + + int getChannel(); + int getDevice(); + +private: + std::vector<int> m_deviceIds; + KComboBox *m_channel; + KComboBox *m_device; +}; + + +} + +#endif diff --git a/src/gui/dialogs/TempoDialog.cpp b/src/gui/dialogs/TempoDialog.cpp new file mode 100644 index 0000000..3896fde --- /dev/null +++ b/src/gui/dialogs/TempoDialog.cpp @@ -0,0 +1,475 @@ +/* -*- 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 "TempoDialog.h" +#include <qlayout.h> + +#include <klocale.h> +#include "misc/Debug.h" +#include "base/Composition.h" +#include "base/NotationTypes.h" +#include "base/RealTime.h" +#include "document/RosegardenGUIDoc.h" +#include "gui/editors/notation/NotePixmapFactory.h" +#include "gui/widgets/TimeWidget.h" +#include "gui/widgets/HSpinBox.h" +#include <kdialogbase.h> +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qradiobutton.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +TempoDialog::TempoDialog(QWidget *parent, RosegardenGUIDoc *doc, + bool timeEditable): + KDialogBase(parent, 0, true, i18n("Insert Tempo Change"), Ok | Cancel | Help), + m_doc(doc), + m_tempoTime(0) +{ + setHelp("tempo"); + + QVBox *vbox = makeVBoxMainWidget(); + QGroupBox *groupBox = new QGroupBox(1, Horizontal, i18n("Tempo"), vbox); + + QFrame *frame = new QFrame(groupBox); + QGridLayout *layout = new QGridLayout(frame, 4, 3, 5, 5); + + // Set tempo + layout->addWidget(new QLabel(i18n("New tempo:"), frame), 0, 1); + m_tempoValueSpinBox = new HSpinBox(frame, 0, 100000, 0.0, 1000.0, 5); + layout->addWidget(m_tempoValueSpinBox, 0, 2); + + connect(m_tempoValueSpinBox, SIGNAL(valueChanged(const QString &)), + SLOT(slotTempoChanged(const QString &))); + + m_tempoTap= new QPushButton(i18n("Tap"), frame); + layout->addWidget(m_tempoTap, 0, 3); + connect(m_tempoTap, SIGNAL(clicked()), SLOT(slotTapClicked())); + + + m_tempoConstant = new QRadioButton(i18n("Tempo is fixed until the following tempo change"), frame); + m_tempoRampToNext = new QRadioButton(i18n("Tempo ramps to the following tempo"), frame); + m_tempoRampToTarget = new QRadioButton(i18n("Tempo ramps to:"), frame); + + // m_tempoTargetCheckBox = new QCheckBox(i18n("Ramping to:"), frame); + m_tempoTargetSpinBox = new HSpinBox(frame, 0, 100000, 0.0, 1000.0, 5); + + // layout->addMultiCellWidget(m_tempoTargetCheckBox, 1, 1, 0, 1, AlignRight); + // layout->addWidget(m_tempoTargetSpinBox, 1, 2); + + layout->addMultiCellWidget(m_tempoConstant, 1, 1, 1, 2); + layout->addMultiCellWidget(m_tempoRampToNext, 2, 2, 1, 2); + layout->addWidget(m_tempoRampToTarget, 3, 1); + layout->addWidget(m_tempoTargetSpinBox, 3, 2); + + // connect(m_tempoTargetCheckBox, SIGNAL(clicked()), + // SLOT(slotTargetCheckBoxClicked())); + connect(m_tempoConstant, SIGNAL(clicked()), + SLOT(slotTempoConstantClicked())); + connect(m_tempoRampToNext, SIGNAL(clicked()), + SLOT(slotTempoRampToNextClicked())); + connect(m_tempoRampToTarget, SIGNAL(clicked()), + SLOT(slotTempoRampToTargetClicked())); + connect(m_tempoTargetSpinBox, SIGNAL(valueChanged(const QString &)), + SLOT(slotTargetChanged(const QString &))); + + m_tempoBeatLabel = new QLabel(frame); + layout->addWidget(m_tempoBeatLabel, 0, 4); + + m_tempoBeat = new QLabel(frame); + layout->addWidget(m_tempoBeat, 0, 5); + + m_tempoBeatsPerMinute = new QLabel(frame); + layout->addWidget(m_tempoBeatsPerMinute, 0, 6); + + m_timeEditor = 0; + + if (timeEditable) { + m_timeEditor = new TimeWidget + (i18n("Time of tempo change"), + vbox, &m_doc->getComposition(), 0, true); + populateTempo(); + return ; + } + + // Scope Box + QButtonGroup *scopeGroup = new QButtonGroup(1, Horizontal, + i18n("Scope"), vbox); + +// new QLabel(scopeBox); + + QVBox *scopeBox = new QVBox(scopeGroup); + + scopeBox->setSpacing(5); + scopeBox->setMargin(5); + + QHBox *currentBox = new QHBox(scopeBox); + new QLabel(i18n("The pointer is currently at "), currentBox); + m_tempoTimeLabel = new QLabel(currentBox); + m_tempoBarLabel = new QLabel(currentBox); + QLabel *spare = new QLabel(currentBox); + currentBox->setStretchFactor(spare, 20); + + m_tempoStatusLabel = new QLabel(scopeBox); + +// new QLabel(scopeBox); + + QHBox *changeWhereBox = new QHBox(scopeBox); + spare = new QLabel(" ", changeWhereBox); + QVBox *changeWhereVBox = new QVBox(changeWhereBox); + changeWhereBox->setStretchFactor(changeWhereVBox, 20); + + m_tempoChangeHere = new QRadioButton + (i18n("Apply this tempo from here onwards"), + changeWhereVBox); + + m_tempoChangeBefore = new QRadioButton + (i18n("Replace the last tempo change"), + changeWhereVBox); + m_tempoChangeBeforeAt = new QLabel(changeWhereVBox); + m_tempoChangeBeforeAt->hide(); + + m_tempoChangeStartOfBar = new QRadioButton + (i18n("Apply this tempo from the start of this bar"), changeWhereVBox); + + m_tempoChangeGlobal = new QRadioButton + (i18n("Apply this tempo to the whole composition"), changeWhereVBox); + + QHBox *optionHBox = new QHBox(changeWhereVBox); + new QLabel(" ", optionHBox); + m_defaultBox = new QCheckBox + (i18n("Also make this the default tempo"), optionHBox); + spare = new QLabel(optionHBox); + optionHBox->setStretchFactor(spare, 20); + +// new QLabel(scopeBox); + + connect(m_tempoChangeHere, SIGNAL(clicked()), + SLOT(slotActionChanged())); + connect(m_tempoChangeBefore, SIGNAL(clicked()), + SLOT(slotActionChanged())); + connect(m_tempoChangeStartOfBar, SIGNAL(clicked()), + SLOT(slotActionChanged())); + connect(m_tempoChangeGlobal, SIGNAL(clicked()), + SLOT(slotActionChanged())); + + m_tempoChangeHere->setChecked(true); + + // disable initially + m_defaultBox->setEnabled(false); + + populateTempo(); +} + +TempoDialog::~TempoDialog() +{} + +void +TempoDialog::setTempoPosition(timeT time) +{ + m_tempoTime = time; + populateTempo(); +} + +void +TempoDialog::populateTempo() +{ + Composition &comp = m_doc->getComposition(); + tempoT tempo = comp.getTempoAtTime(m_tempoTime); + std::pair<bool, tempoT> ramping(false, tempo); + + int tempoChangeNo = comp.getTempoChangeNumberAt(m_tempoTime); + if (tempoChangeNo >= 0) { + tempo = comp.getTempoChange(tempoChangeNo).second; + ramping = comp.getTempoRamping(tempoChangeNo, false); + } + + m_tempoValueSpinBox->setValue(tempo); + + if (ramping.first) { + if (ramping.second) { + m_tempoTargetSpinBox->setEnabled(true); + m_tempoTargetSpinBox->setValue(ramping.second); + m_tempoConstant->setChecked(false); + m_tempoRampToNext->setChecked(false); + m_tempoRampToTarget->setChecked(true); + } else { + ramping = comp.getTempoRamping(tempoChangeNo, true); + m_tempoTargetSpinBox->setEnabled(false); + m_tempoTargetSpinBox->setValue(ramping.second); + m_tempoConstant->setChecked(false); + m_tempoRampToNext->setChecked(true); + m_tempoRampToTarget->setChecked(false); + } + } else { + m_tempoTargetSpinBox->setEnabled(false); + m_tempoTargetSpinBox->setValue(tempo); + m_tempoConstant->setChecked(true); + m_tempoRampToNext->setChecked(false); + m_tempoRampToTarget->setChecked(false); + } + + // m_tempoTargetCheckBox->setChecked(ramping.first); + m_tempoTargetSpinBox->setEnabled(ramping.first); + + updateBeatLabels(comp.getTempoQpm(tempo)); + + if (m_timeEditor) { + m_timeEditor->slotSetTime(m_tempoTime); + return ; + } + + RealTime tempoTime = comp.getElapsedRealTime(m_tempoTime); + QString milliSeconds; + milliSeconds.sprintf("%03d", tempoTime.msec()); + m_tempoTimeLabel->setText(i18n("%1.%2 s,").arg(tempoTime.sec) + .arg(milliSeconds)); + + int barNo = comp.getBarNumber(m_tempoTime); + if (comp.getBarStart(barNo) == m_tempoTime) { + m_tempoBarLabel->setText + (i18n("at the start of measure %1.").arg(barNo + 1)); + m_tempoChangeStartOfBar->setEnabled(false); + } else { + m_tempoBarLabel->setText( + i18n("in the middle of measure %1.").arg(barNo + 1)); + m_tempoChangeStartOfBar->setEnabled(true); + } + + m_tempoChangeBefore->setEnabled(false); + m_tempoChangeBeforeAt->setEnabled(false); + + bool havePrecedingTempo = false; + + if (tempoChangeNo >= 0) { + + timeT lastTempoTime = comp.getTempoChange(tempoChangeNo).first; + if (lastTempoTime < m_tempoTime) { + + RealTime lastRT = comp.getElapsedRealTime(lastTempoTime); + QString lastms; + lastms.sprintf("%03d", lastRT.msec()); + int lastBar = comp.getBarNumber(lastTempoTime); + m_tempoChangeBeforeAt->setText + (i18n(" (at %1.%2 s, in measure %3)").arg(lastRT.sec) + .arg(lastms).arg(lastBar + 1)); + m_tempoChangeBeforeAt->show(); + + m_tempoChangeBefore->setEnabled(true); + m_tempoChangeBeforeAt->setEnabled(true); + + havePrecedingTempo = true; + } + } + + if (comp.getTempoChangeCount() > 0) { + + if (havePrecedingTempo) { + m_tempoStatusLabel->hide(); + } else { + m_tempoStatusLabel->setText + (i18n("There are no preceding tempo changes.")); + } + + m_tempoChangeGlobal->setEnabled(true); + + } else { + + m_tempoStatusLabel->setText + (i18n("There are no other tempo changes.")); + + m_tempoChangeGlobal->setEnabled(false); + } + + m_defaultBox->setEnabled(false); +} + +void +TempoDialog::updateBeatLabels(double qpm) +{ + Composition &comp = m_doc->getComposition(); + + // If the time signature's beat is not a crotchet, need to show + // bpm separately + + timeT beat = comp.getTimeSignatureAt(m_tempoTime).getBeatDuration(); + if (beat == Note(Note::Crotchet).getDuration()) { + m_tempoBeatLabel->setText(i18n(" bpm")); + m_tempoBeatLabel->show(); + m_tempoBeat->hide(); + m_tempoBeatsPerMinute->hide(); + } else { + // m_tempoBeatLabel->setText(" ("); + m_tempoBeatLabel->setText(" "); + + timeT error = 0; + m_tempoBeat->setPixmap(NotePixmapFactory::toQPixmap + (NotePixmapFactory::makeNoteMenuPixmap(beat, error))); + m_tempoBeat->setMaximumWidth(25); + if (error) + m_tempoBeat->setPixmap(NotePixmapFactory::toQPixmap + (NotePixmapFactory::makeToolbarPixmap + ("menu-no-note"))); + + m_tempoBeatsPerMinute->setText + // (QString("= %1 )").arg + (QString("= %1 ").arg + (int(qpm * Note(Note::Crotchet).getDuration() / beat))); + m_tempoBeatLabel->show(); + m_tempoBeat->show(); + m_tempoBeatsPerMinute->show(); + } +} + +void +TempoDialog::slotTempoChanged(const QString &) +{ + updateBeatLabels(double(m_tempoValueSpinBox->valuef())); +} + +void +TempoDialog::slotTargetChanged(const QString &) +{ + //... +} + +void +TempoDialog::slotTempoConstantClicked() +{ + m_tempoRampToNext->setChecked(false); + m_tempoRampToTarget->setChecked(false); + m_tempoTargetSpinBox->setEnabled(false); +} + +void +TempoDialog::slotTempoRampToNextClicked() +{ + m_tempoConstant->setChecked(false); + m_tempoRampToTarget->setChecked(false); + m_tempoTargetSpinBox->setEnabled(false); +} + +void +TempoDialog::slotTempoRampToTargetClicked() +{ + m_tempoConstant->setChecked(false); + m_tempoRampToNext->setChecked(false); + m_tempoTargetSpinBox->setEnabled(true); +} + +void +TempoDialog::slotActionChanged() +{ + m_defaultBox->setEnabled(m_tempoChangeGlobal->isChecked()); +} + +void +TempoDialog::slotOk() +{ + tempoT tempo = m_tempoValueSpinBox->value(); + RG_DEBUG << "Tempo is " << tempo << endl; + + tempoT target = -1; + if (m_tempoRampToNext->isChecked()) { + target = 0; + } else if (m_tempoRampToTarget->isChecked()) { + target = m_tempoTargetSpinBox->value(); + } + + RG_DEBUG << "Target is " << target << endl; + + if (m_timeEditor) { + + emit changeTempo(m_timeEditor->getTime(), + tempo, + target, + AddTempo); + + } else { + + TempoDialogAction action = AddTempo; + + if (m_tempoChangeBefore->isChecked()) { + action = ReplaceTempo; + } else if (m_tempoChangeStartOfBar->isChecked()) { + action = AddTempoAtBarStart; + } else if (m_tempoChangeGlobal->isChecked()) { + action = GlobalTempo; + if (m_defaultBox->isChecked()) { + action = GlobalTempoWithDefault; + } + } + + emit changeTempo(m_tempoTime, + tempo, + target, + action); + } + + KDialogBase::slotOk(); +} + +void +TempoDialog::slotTapClicked() +{ + QTime now = QTime::currentTime(); + + if (m_tapMinusOne != QTime()) { + + int ms1 = m_tapMinusOne.msecsTo(now); + + if (ms1 < 10000) { + + int msec = ms1; + + if (m_tapMinusTwo != QTime()) { + int ms2 = m_tapMinusTwo.msecsTo(m_tapMinusOne); + if (ms2 < 10000) { + msec = (ms1 + ms2) / 2; + } + } + + int bpm = 60000 / msec; + m_tempoValueSpinBox->setValue(bpm * 100000); + } + } + + m_tapMinusTwo = m_tapMinusOne; + m_tapMinusOne = now; +} + + +} + +#include "TempoDialog.moc" diff --git a/src/gui/dialogs/TempoDialog.h b/src/gui/dialogs/TempoDialog.h new file mode 100644 index 0000000..dd3edf1 --- /dev/null +++ b/src/gui/dialogs/TempoDialog.h @@ -0,0 +1,128 @@ + +/* -*- 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_TEMPODIALOG_H_ +#define _RG_TEMPODIALOG_H_ + +#include <kdialogbase.h> +#include "base/Event.h" +#include "base/Composition.h" +#include <qpushbutton.h> +#include <qdatetime.h> + + +class QWidget; +class QString; +class QRadioButton; +class QLabel; +class QCheckBox; + + +namespace Rosegarden +{ + +class TimeWidget; +class RosegardenGUIDoc; +class HSpinBox; + + +class TempoDialog : public KDialogBase +{ + Q_OBJECT +public: + enum TempoDialogAction { + AddTempo, + ReplaceTempo, + AddTempoAtBarStart, + GlobalTempo, + GlobalTempoWithDefault + }; + + TempoDialog(QWidget *parent, RosegardenGUIDoc *doc, + bool timeEditable = false); + ~TempoDialog(); + + // Set the position at which we're checking the tempo + // + void setTempoPosition(timeT time); + +public slots: + virtual void slotOk(); + void slotActionChanged(); + void slotTempoChanged(const QString &); + void slotTempoConstantClicked(); + void slotTempoRampToNextClicked(); + void slotTempoRampToTargetClicked(); + void slotTargetChanged(const QString &); + void slotTapClicked(); + +signals: + // Return results in this signal + // + void changeTempo(timeT, // tempo change time + tempoT, // tempo value + tempoT, // target tempo value + TempoDialog::TempoDialogAction); // tempo action + +protected: + void populateTempo(); + void updateBeatLabels(double newTempo); + + //--------------- Data members --------------------------------- + + RosegardenGUIDoc *m_doc; + timeT m_tempoTime; + HSpinBox *m_tempoValueSpinBox; + QPushButton *m_tempoTap; + QTime m_tapMinusTwo; + QTime m_tapMinusOne; + + QRadioButton *m_tempoConstant; + QRadioButton *m_tempoRampToNext; + QRadioButton *m_tempoRampToTarget; + HSpinBox *m_tempoTargetSpinBox; + + QLabel *m_tempoBeatLabel; + QLabel *m_tempoBeat; + QLabel *m_tempoBeatsPerMinute; + + TimeWidget *m_timeEditor; + + QLabel *m_tempoTimeLabel; + QLabel *m_tempoBarLabel; + QLabel *m_tempoStatusLabel; + + QRadioButton *m_tempoChangeHere; + QRadioButton *m_tempoChangeBefore; + QLabel *m_tempoChangeBeforeAt; + QRadioButton *m_tempoChangeStartOfBar; + QRadioButton *m_tempoChangeGlobal; + QCheckBox *m_defaultBox; +}; + + +} + +#endif diff --git a/src/gui/dialogs/TextEventDialog.cpp b/src/gui/dialogs/TextEventDialog.cpp new file mode 100644 index 0000000..156b5d1 --- /dev/null +++ b/src/gui/dialogs/TextEventDialog.cpp @@ -0,0 +1,593 @@ +/* -*- 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 "TextEventDialog.h" +#include <kapplication.h> + +#include <klocale.h> +#include "misc/Strings.h" +#include "document/ConfigGroups.h" +#include "base/NotationTypes.h" +#include "gui/editors/notation/NotePixmapFactory.h" +#include <kcombobox.h> +#include <kconfig.h> +#include <kdialogbase.h> +#include <qbitmap.h> +#include <qgrid.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qobject.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> +#include <qspinbox.h> + +namespace Rosegarden +{ + +TextEventDialog::TextEventDialog(QWidget *parent, + NotePixmapFactory *npf, + Text defaultText, + int maxLength) : + KDialogBase(parent, 0, true, i18n("Text"), Ok | Cancel | Help), + m_notePixmapFactory(npf), + m_styles(Text::getUserStyles()) /*, + //m_directives(Text::getLilyPondDirectives()) */ +{ + setHelp("nv-text"); + QVBox *vbox = makeVBoxMainWidget(); + + QGroupBox *entryBox = new QGroupBox + (1, Horizontal, i18n("Specification"), vbox); + QGroupBox *exampleBox = new QGroupBox + (1, Horizontal, i18n("Preview"), vbox); + + QGrid *entryGrid = new QGrid(2, QGrid::Horizontal, entryBox); + + new QLabel(i18n("Text: "), entryGrid); + m_text = new QLineEdit(entryGrid); + m_text->setText(strtoqstr(defaultText.getText())); + if (maxLength > 0) + m_text->setMaxLength(maxLength); + + // style combo + new QLabel(i18n("Style: "), entryGrid); + m_typeCombo = new KComboBox(entryGrid); + + for (unsigned int i = 0; i < m_styles.size(); ++i) + { + + std::string style = m_styles[i]; + + // if the style is in this list, we can i18n it (kludgy): + + if (style == Text::Dynamic) { // index // + m_typeCombo->insertItem(i18n("Dynamic")); // 0 + + } else if (style == Text::Direction) { + m_typeCombo->insertItem(i18n("Direction")); // 1 + + } else if (style == Text::LocalDirection) { + m_typeCombo->insertItem(i18n("Local Direction")); // 2 + + } else if (style == Text::Tempo) { + m_typeCombo->insertItem(i18n("Tempo")); // 3 + + } else if (style == Text::LocalTempo) { + m_typeCombo->insertItem(i18n("Local Tempo")); // 4 + + } else if (style == Text::Lyric) { + m_typeCombo->insertItem(i18n("Lyric")); // 5 + + } else if (style == Text::Chord) { + m_typeCombo->insertItem(i18n("Chord")); // 6 + + } else if (style == Text::Annotation) { + m_typeCombo->insertItem(i18n("Annotation")); // 7 + + } else if (style == Text::LilyPondDirective) { + m_typeCombo->insertItem(i18n("LilyPond Directive")); // 8 + + } else { + // not i18n()-able + + std::string styleName; + styleName += (char)toupper(style[0]); + styleName += style.substr(1); + + int uindex = styleName.find('_'); + if (uindex > 0) { + styleName = + styleName.substr(0, uindex) + " " + + styleName.substr(uindex + 1); + } + + m_typeCombo->insertItem(strtoqstr(styleName)); + } + + if (style == defaultText.getTextType()) { + m_typeCombo->setCurrentItem(m_typeCombo->count() - 1); + } + } + + m_verseLabel = new QLabel(i18n("Verse: "), entryGrid); + m_verseLabel->hide(); + m_verseSpin = new QSpinBox(entryGrid); + m_verseSpin->setMinValue(1); + m_verseSpin->setMaxValue(12); + m_verseSpin->setLineStep(1); + m_verseSpin->setValue(defaultText.getVerse() + 1); + m_verseSpin->hide(); + + // dynamic shortcuts combo + m_dynamicShortcutLabel = new QLabel(i18n("Dynamic: "), entryGrid); + m_dynamicShortcutLabel->hide(); + + m_dynamicShortcutCombo = new KComboBox(entryGrid); + m_dynamicShortcutCombo->insertItem(i18n("ppp")); + m_dynamicShortcutCombo->insertItem(i18n("pp")); + m_dynamicShortcutCombo->insertItem(i18n("p")); + m_dynamicShortcutCombo->insertItem(i18n("mp")); + m_dynamicShortcutCombo->insertItem(i18n("mf")); + m_dynamicShortcutCombo->insertItem(i18n("f")); + m_dynamicShortcutCombo->insertItem(i18n("ff")); + m_dynamicShortcutCombo->insertItem(i18n("fff")); + m_dynamicShortcutCombo->insertItem(i18n("rfz")); + m_dynamicShortcutCombo->insertItem(i18n("sf")); + m_dynamicShortcutCombo->hide(); + + // direction shortcuts combo + m_directionShortcutLabel = new QLabel(i18n("Direction: "), entryGrid); + m_directionShortcutLabel->hide(); + + m_directionShortcutCombo = new KComboBox(entryGrid); + // note, the " ," is a breath mark; the extra spaces are a cheap hack to + // try to improve the probability of Rosegarden drawing the blasted thing + // where it's supposed to go, without the need to micro-diddle each and + // every bliffin' one. (Micro-diddling is not exportable to LilyPond + // either, is it? I rather doubt it.) + m_directionShortcutCombo->insertItem(i18n(" ,")); + m_directionShortcutCombo->insertItem(i18n("D.C. al Fine")); + m_directionShortcutCombo->insertItem(i18n("D.S. al Fine")); + m_directionShortcutCombo->insertItem(i18n("Fine")); + m_directionShortcutCombo->insertItem(i18n("D.S. al Coda")); + m_directionShortcutCombo->insertItem(i18n("to Coda")); + m_directionShortcutCombo->insertItem(i18n("Coda")); + m_directionShortcutCombo->hide(); + + // local direction shortcuts combo + m_localDirectionShortcutLabel = new QLabel(i18n("Local Direction: "), entryGrid); + m_localDirectionShortcutLabel->hide(); + + m_localDirectionShortcutCombo = new KComboBox(entryGrid); + m_localDirectionShortcutCombo->insertItem(i18n("accel.")); + m_localDirectionShortcutCombo->insertItem(i18n("ritard.")); + m_localDirectionShortcutCombo->insertItem(i18n("ralletando")); + m_localDirectionShortcutCombo->insertItem(i18n("a tempo")); + m_localDirectionShortcutCombo->insertItem(i18n("legato")); + m_localDirectionShortcutCombo->insertItem(i18n("simile")); + m_localDirectionShortcutCombo->insertItem(i18n("pizz.")); + m_localDirectionShortcutCombo->insertItem(i18n("arco")); + m_localDirectionShortcutCombo->insertItem(i18n("non vib.")); + m_localDirectionShortcutCombo->insertItem(i18n("sul pont.")); + m_localDirectionShortcutCombo->insertItem(i18n("sul tasto")); + m_localDirectionShortcutCombo->insertItem(i18n("con legno")); + m_localDirectionShortcutCombo->insertItem(i18n("sul tasto")); + m_localDirectionShortcutCombo->insertItem(i18n("sul G")); + m_localDirectionShortcutCombo->insertItem(i18n("ordinario")); + m_localDirectionShortcutCombo->insertItem(i18n("Muta in ")); + m_localDirectionShortcutCombo->insertItem(i18n("volti subito ")); + m_localDirectionShortcutCombo->insertItem(i18n("soli")); + m_localDirectionShortcutCombo->insertItem(i18n("div.")); + m_localDirectionShortcutCombo->hide(); + + // tempo shortcuts combo + m_tempoShortcutLabel = new QLabel(i18n("Tempo: "), entryGrid); + m_tempoShortcutLabel->hide(); + + m_tempoShortcutCombo = new KComboBox(entryGrid); + m_tempoShortcutCombo->insertItem(i18n("Grave")); + m_tempoShortcutCombo->insertItem(i18n("Adagio")); + m_tempoShortcutCombo->insertItem(i18n("Largo")); + m_tempoShortcutCombo->insertItem(i18n("Lento")); + m_tempoShortcutCombo->insertItem(i18n("Andante")); + m_tempoShortcutCombo->insertItem(i18n("Moderato")); + m_tempoShortcutCombo->insertItem(i18n("Allegretto")); + m_tempoShortcutCombo->insertItem(i18n("Allegro")); + m_tempoShortcutCombo->insertItem(i18n("Vivace")); + m_tempoShortcutCombo->insertItem(i18n("Presto")); + m_tempoShortcutCombo->insertItem(i18n("Prestissimo")); + m_tempoShortcutCombo->insertItem(i18n("Maestoso")); + m_tempoShortcutCombo->insertItem(i18n("Sostenuto")); + m_tempoShortcutCombo->insertItem(i18n("Tempo Primo")); + m_tempoShortcutCombo->hide(); + + // local tempo shortcuts combo (duplicates the non-local version, because + // nobody is actually sure what is supposed to distinguish Tempo from + // Local Tempo, or what this text style is supposed to be good for in the + // way of standard notation) + m_localTempoShortcutLabel = new QLabel(i18n("Local Tempo: "), entryGrid); + m_localTempoShortcutLabel->hide(); + + m_localTempoShortcutCombo = new KComboBox(entryGrid); + m_localTempoShortcutCombo->insertItem(i18n("Grave")); + m_localTempoShortcutCombo->insertItem(i18n("Adagio")); + m_localTempoShortcutCombo->insertItem(i18n("Largo")); + m_localTempoShortcutCombo->insertItem(i18n("Lento")); + m_localTempoShortcutCombo->insertItem(i18n("Andante")); + m_localTempoShortcutCombo->insertItem(i18n("Moderato")); + m_localTempoShortcutCombo->insertItem(i18n("Allegretto")); + m_localTempoShortcutCombo->insertItem(i18n("Allegro")); + m_localTempoShortcutCombo->insertItem(i18n("Vivace")); + m_localTempoShortcutCombo->insertItem(i18n("Presto")); + m_localTempoShortcutCombo->insertItem(i18n("Prestissimo")); + m_localTempoShortcutCombo->insertItem(i18n("Maestoso")); + m_localTempoShortcutCombo->insertItem(i18n("Sostenuto")); + m_localTempoShortcutCombo->insertItem(i18n("Tempo Primo")); + m_localTempoShortcutCombo->hide(); + + // LilyPond directive combo + m_directiveLabel = new QLabel(i18n("Directive: "), entryGrid); + m_directiveLabel->hide(); + + m_lilyPondDirectiveCombo = new KComboBox(entryGrid); + m_lilyPondDirectiveCombo->hide(); + + // not i18nable, because the directive exporter currently depends on the + // textual contents of these strings, not some more abstract associated + // type label + m_lilyPondDirectiveCombo->insertItem(Text::Segno); + m_lilyPondDirectiveCombo->insertItem(Text::Coda); + m_lilyPondDirectiveCombo->insertItem(Text::Alternate1); + m_lilyPondDirectiveCombo->insertItem(Text::Alternate2); + m_lilyPondDirectiveCombo->insertItem(Text::BarDouble); + m_lilyPondDirectiveCombo->insertItem(Text::BarEnd); + m_lilyPondDirectiveCombo->insertItem(Text::BarDot); + m_lilyPondDirectiveCombo->insertItem(Text::Gliss); + m_lilyPondDirectiveCombo->insertItem(Text::Arpeggio); + // m_lilyPondDirectiveCombo->insertItem(Text::ArpeggioUp); + // m_lilyPondDirectiveCombo->insertItem(Text::ArpeggioDn); + m_lilyPondDirectiveCombo->insertItem(Text::Tiny); + m_lilyPondDirectiveCombo->insertItem(Text::Small); + m_lilyPondDirectiveCombo->insertItem(Text::NormalSize); + + QVBox *exampleVBox = new QVBox(exampleBox); + + int ls = m_notePixmapFactory->getLineSpacing(); + + int mapWidth = 200; + QPixmap map(mapWidth, ls * 5 + 1); + QBitmap mask(mapWidth, ls * 5 + 1); + + map.fill(); + mask.fill(Qt::color0); + + QPainter p, pm; + + p.begin(&map); + pm.begin(&mask); + + p.setPen(Qt::black); + pm.setPen(Qt::white); + + for (int i = 0; i < 5; ++i) + { + p.drawLine(0, ls * i, mapWidth - 1, ls * i); + pm.drawLine(0, ls * i, mapWidth - 1, ls * i); + } + + p.end(); + pm.end(); + + map.setMask(mask); + + m_staffAboveLabel = new QLabel("staff", exampleVBox); + m_staffAboveLabel->setPixmap(map); + + m_textExampleLabel = new QLabel(i18n("Example"), exampleVBox); + + m_staffBelowLabel = new QLabel("staff", exampleVBox); + m_staffBelowLabel->setPixmap(map); + + // restore last setting for shortcut combos + KConfig *config = kapp->config(); + config->setGroup(NotationViewConfigGroup); + + m_dynamicShortcutCombo->setCurrentItem(config->readNumEntry("dynamic_shortcut", 0)); + m_directionShortcutCombo->setCurrentItem(config->readNumEntry("direction_shortcut", 0)); + m_localDirectionShortcutCombo->setCurrentItem(config->readNumEntry("local_direction_shortcut", 0)); + m_tempoShortcutCombo->setCurrentItem(config->readNumEntry("tempo_shortcut", 0)); + m_localTempoShortcutCombo->setCurrentItem(config->readNumEntry("local_tempo_shortcut", 0)); + m_lilyPondDirectiveCombo->setCurrentItem(config->readNumEntry("lilyPond_directive_combo", 0)); + + m_prevChord = config->readEntry("previous_chord", ""); + m_prevLyric = config->readEntry("previous_lyric", ""); + m_prevAnnotation = config->readEntry("previous_annotation", ""); + + QObject::connect(m_text, SIGNAL(textChanged(const QString &)), + this, SLOT(slotTextChanged(const QString &))); + QObject::connect(m_typeCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotTypeChanged(const QString &))); + QObject::connect(this, SIGNAL(okClicked()), this, SLOT(slotOK())); + QObject::connect(m_dynamicShortcutCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotDynamicShortcutChanged(const QString &))); + QObject::connect(m_directionShortcutCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotDirectionShortcutChanged(const QString &))); + QObject::connect(m_localDirectionShortcutCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotLocalDirectionShortcutChanged(const QString &))); + QObject::connect(m_tempoShortcutCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotTempoShortcutChanged(const QString &))); + QObject::connect(m_localTempoShortcutCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotLocalTempoShortcutChanged(const QString &))); + QObject::connect(m_lilyPondDirectiveCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotLilyPondDirectiveChanged(const QString &))); + + m_text->setFocus(); + slotTypeChanged(strtoqstr(getTextType())); + + // a hacky little fix for #1512143, to restore the capability to edit + // existing annotations and other whatnots + //!!! tacking another one of these on the bottom strikes me as lame in the + // extreme, but it works, and it costs little, and other solutions I can + // imagine would cost so much more. + m_text->setText(strtoqstr(defaultText.getText())); +} + +Text +TextEventDialog::getText() const +{ + Text text(getTextString(), getTextType()); + text.setVerse(m_verseSpin->value() - 1); + return text; +} + +std::string +TextEventDialog::getTextType() const +{ + return m_styles[m_typeCombo->currentItem()]; +} + +std::string +TextEventDialog::getTextString() const +{ + return std::string(qstrtostr(m_text->text())); +} + +void +TextEventDialog::slotTextChanged(const QString &qtext) +{ + std::string type(getTextType()); + + QString qtrunc(qtext); + if (qtrunc.length() > 20) + qtrunc = qtrunc.left(20) + "..."; + std::string text(qstrtostr(qtrunc)); + if (text == "") + text = "Sample"; + + Text rtext(text, type); + m_textExampleLabel->setPixmap + (NotePixmapFactory::toQPixmap(m_notePixmapFactory->makeTextPixmap(rtext))); +} + +void +TextEventDialog::slotTypeChanged(const QString &) +{ + std::string type(getTextType()); + + QString qtrunc(m_text->text()); + if (qtrunc.length() > 20) + qtrunc = qtrunc.left(20) + "..."; + std::string text(qstrtostr(qtrunc)); + if (text == "") + text = "Sample"; + + Text rtext(text, type); + m_textExampleLabel->setPixmap + (NotePixmapFactory::toQPixmap(m_notePixmapFactory->makeTextPixmap(rtext))); + + // + // swap widgets in and out, depending on the current text type + // + if (type == Text::Dynamic) { + m_dynamicShortcutLabel->show(); + m_dynamicShortcutCombo->show(); + slotDynamicShortcutChanged(text); + } else { + m_dynamicShortcutLabel->hide(); + m_dynamicShortcutCombo->hide(); + } + + if (type == Text::Direction) { + m_directionShortcutLabel->show(); + m_directionShortcutCombo->show(); + slotDirectionShortcutChanged(text); + } else { + m_directionShortcutLabel->hide(); + m_directionShortcutCombo->hide(); + } + + if (type == Text::LocalDirection) { + m_localDirectionShortcutLabel->show(); + m_localDirectionShortcutCombo->show(); + slotLocalDirectionShortcutChanged(text); + } else { + m_localDirectionShortcutLabel->hide(); + m_localDirectionShortcutCombo->hide(); + } + + if (type == Text::Tempo) { + m_tempoShortcutLabel->show(); + m_tempoShortcutCombo->show(); + slotTempoShortcutChanged(text); + } else { + m_tempoShortcutLabel->hide(); + m_tempoShortcutCombo->hide(); + } + + if (type == Text::LocalTempo) { + m_localTempoShortcutLabel->show(); + m_localTempoShortcutCombo->show(); + slotLocalTempoShortcutChanged(text); + } else { + m_localTempoShortcutLabel->hide(); + m_localTempoShortcutCombo->hide(); + } + + // restore previous text of appropriate type + if (type == Text::Lyric) + m_text->setText(m_prevLyric); + else if (type == Text::Chord) + m_text->setText(m_prevChord); + else if (type == Text::Annotation) + m_text->setText(m_prevAnnotation); + + // + // LilyPond directives only taking temporary residence here; will move out + // into some new class eventually + // + if (type == Text::LilyPondDirective) { + m_lilyPondDirectiveCombo->show(); + m_directiveLabel->show(); + m_staffAboveLabel->hide(); + m_staffBelowLabel->show(); + m_text->setReadOnly(true); + m_text->setEnabled(false); + slotLilyPondDirectiveChanged(text); + } else { + m_lilyPondDirectiveCombo->hide(); + m_directiveLabel->hide(); + m_text->setReadOnly(false); + m_text->setEnabled(true); + + if (type == Text::Dynamic || + type == Text::LocalDirection || + type == Text::UnspecifiedType || + type == Text::Lyric || + type == Text::Annotation) { + + m_staffAboveLabel->show(); + m_staffBelowLabel->hide(); + + } else { + m_staffAboveLabel->hide(); + m_staffBelowLabel->show(); + + } + + if (type == Text::Lyric) { + m_verseLabel->show(); + m_verseSpin->show(); + } + } +} + +void +TextEventDialog::slotOK() +{ + // store last setting for shortcut combos + KConfig *config = kapp->config(); + config->setGroup(NotationViewConfigGroup); + + config->writeEntry("dynamic_shortcut", m_dynamicShortcutCombo->currentItem()); + config->writeEntry("direction_shortcut", m_directionShortcutCombo->currentItem()); + config->writeEntry("local_direction_shortcut", m_localDirectionShortcutCombo->currentItem()); + config->writeEntry("tempo_shortcut", m_tempoShortcutCombo->currentItem()); + config->writeEntry("local_tempo_shortcut", m_localTempoShortcutCombo->currentItem()); + // temporary home: + config->writeEntry("lilyPond_directive_combo", m_lilyPondDirectiveCombo->currentItem()); + + // store last chord, lyric, annotation, depending on what's currently in + // the text entry widget + int index = m_typeCombo->currentItem(); + if (index == 5) + config->writeEntry("previous_chord", m_text->text()); + else if (index == 6) + config->writeEntry("previous_lyric", m_text->text()); + else if (index == 7) + config->writeEntry("previous_annotation", m_text->text()); +} + +void +TextEventDialog::slotDynamicShortcutChanged(const QString &text) +{ + if (text == "" || text == "Sample") { + m_text->setText(strtoqstr(m_dynamicShortcutCombo->currentText())); + } else { + m_text->setText(text); + } +} + +void +TextEventDialog::slotDirectionShortcutChanged(const QString &text) +{ + if (text == "" || text == "Sample") { + m_text->setText(strtoqstr(m_directionShortcutCombo->currentText())); + } else { + m_text->setText(text); + } +} + +void +TextEventDialog::slotLocalDirectionShortcutChanged(const QString &text) +{ + if (text == "" || text == "Sample") { + m_text->setText(strtoqstr(m_localDirectionShortcutCombo->currentText())); + } else { + m_text->setText(text); + } +} + +void +TextEventDialog::slotTempoShortcutChanged(const QString &text) +{ + if (text == "" || text == "Sample") { + m_text->setText(strtoqstr(m_tempoShortcutCombo->currentText())); + } else { + m_text->setText(text); + } +} + +void +TextEventDialog::slotLocalTempoShortcutChanged(const QString &text) +{ + if (text == "" || text == "Sample") { + m_text->setText(strtoqstr(m_localTempoShortcutCombo->currentText())); + } else { + m_text->setText(text); + } +} + +void +TextEventDialog::slotLilyPondDirectiveChanged(const QString &) +{ + m_text->setText(strtoqstr(m_lilyPondDirectiveCombo->currentText())); +} + +} +#include "TextEventDialog.moc" diff --git a/src/gui/dialogs/TextEventDialog.h b/src/gui/dialogs/TextEventDialog.h new file mode 100644 index 0000000..0f389b0 --- /dev/null +++ b/src/gui/dialogs/TextEventDialog.h @@ -0,0 +1,129 @@ + +/* -*- 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_TEXTEVENTDIALOG_H_ +#define _RG_TEXTEVENTDIALOG_H_ + +#include "base/NotationTypes.h" +#include <string> +#include <kdialogbase.h> +#include <qstring.h> +#include <vector> + + +class QWidget; +class QLineEdit; +class QLabel; +class KComboBox; +class QSpinBox; + +namespace Rosegarden +{ + +class NotePixmapFactory; + + +class TextEventDialog : public KDialogBase +{ + Q_OBJECT + +public: + TextEventDialog(QWidget *parent, + NotePixmapFactory *npf, + Text defaultText, + int maxLength = -1); // for Qt default + + Text getText() const; + +public slots: + void slotTextChanged(const QString &); + void slotTypeChanged(const QString &); + + /* + * Save previous state of assorted widgets for restoration in the next + * instance + */ + void slotOK(); + + // convenience canned texts + void slotDynamicShortcutChanged(const QString &); + void slotDirectionShortcutChanged(const QString &); + void slotLocalDirectionShortcutChanged(const QString &); + void slotTempoShortcutChanged(const QString &); + void slotLocalTempoShortcutChanged(const QString &); + + // + // special LilyPond directives, initial phase, as cheap text events; will + // eventually move out of Text, and out of this dialog into + // some other less cheesy interface + // + void slotLilyPondDirectiveChanged(const QString &); + +protected: + + std::string getTextType() const; + std::string getTextString() const; + + //--------------- Data members --------------------------------- + + QLineEdit *m_text; + KComboBox *m_typeCombo; + QSpinBox *m_verseSpin; + KComboBox *m_dynamicShortcutCombo; + KComboBox *m_directionShortcutCombo; + KComboBox *m_localDirectionShortcutCombo; + KComboBox *m_tempoShortcutCombo; + KComboBox *m_localTempoShortcutCombo; + // temporary home: + KComboBox *m_lilyPondDirectiveCombo; + + + QLabel *m_staffAboveLabel; + QLabel *m_textExampleLabel; + QLabel *m_staffBelowLabel; + QLabel *m_dynamicShortcutLabel; + QLabel *m_directionShortcutLabel; + QLabel *m_localDirectionShortcutLabel; + QLabel *m_tempoShortcutLabel; + QLabel *m_localTempoShortcutLabel; + QLabel *m_verseLabel; + // temporary home: + QLabel *m_directiveLabel; + + QString m_prevChord; + QString m_prevLyric; + QString m_prevAnnotation; + + NotePixmapFactory *m_notePixmapFactory; + std::vector<std::string> m_styles; +// std::vector<std::string> m_directives; + +}; + + + +} + +#endif diff --git a/src/gui/dialogs/TimeDialog.cpp b/src/gui/dialogs/TimeDialog.cpp new file mode 100644 index 0000000..40d1da2 --- /dev/null +++ b/src/gui/dialogs/TimeDialog.cpp @@ -0,0 +1,80 @@ +/* -*- 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 "TimeDialog.h" + +#include <klocale.h> +#include "base/Composition.h" +#include "gui/widgets/TimeWidget.h" +#include <kdialogbase.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +TimeDialog::TimeDialog(QWidget *parent, QString title, + Composition *composition, + timeT defaultTime, + bool constrainToCompositionDuration) : + KDialogBase(parent, 0, true, title, User1 | Ok | Cancel) +{ + QVBox *vbox = makeVBoxMainWidget(); + m_timeWidget = new TimeWidget + (title, vbox, composition, defaultTime, true, + constrainToCompositionDuration); + + setButtonText(User1, i18n("Reset")); + connect(this, SIGNAL(user1Clicked()), + m_timeWidget, SLOT(slotResetToDefault())); +} + +TimeDialog::TimeDialog(QWidget *parent, QString title, + Composition *composition, + timeT startTime, + timeT defaultTime, + bool constrainToCompositionDuration) : + KDialogBase(parent, 0, true, title, User1 | Ok | Cancel) +{ + QVBox *vbox = makeVBoxMainWidget(); + m_timeWidget = new TimeWidget + (title, vbox, composition, startTime, defaultTime, true, + constrainToCompositionDuration); + + setButtonText(User1, i18n("Reset")); + connect(this, SIGNAL(user1Clicked()), + m_timeWidget, SLOT(slotResetToDefault())); +} + +timeT +TimeDialog::getTime() const +{ + return m_timeWidget->getTime(); +} + +} +#include "TimeDialog.moc" diff --git a/src/gui/dialogs/TimeDialog.h b/src/gui/dialogs/TimeDialog.h new file mode 100644 index 0000000..e12a007 --- /dev/null +++ b/src/gui/dialogs/TimeDialog.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_TIMEDIALOG_H_ +#define _RG_TIMEDIALOG_H_ + +#include <kdialogbase.h> +#include <qstring.h> +#include "base/Event.h" + + +class QWidget; + + +namespace Rosegarden +{ + +class TimeWidget; +class Composition; + + +class TimeDialog : public KDialogBase +{ + Q_OBJECT +public: + /// for absolute times + TimeDialog(QWidget *parent, QString title, Composition *composition, + timeT defaultTime, bool constrainToCompositionDuration); + + /// for durations + TimeDialog(QWidget *parent, QString title, Composition *composition, + timeT startTime, timeT defaultDuration, + bool constrainToCompositionDuration); + + timeT getTime() const; + +protected: + TimeWidget *m_timeWidget; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/TimeSignatureDialog.cpp b/src/gui/dialogs/TimeSignatureDialog.cpp new file mode 100644 index 0000000..082f123 --- /dev/null +++ b/src/gui/dialogs/TimeSignatureDialog.cpp @@ -0,0 +1,316 @@ +/* -*- 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 "TimeSignatureDialog.h" +#include <kapplication.h> + +#include <klocale.h> +#include "document/ConfigGroups.h" +#include "base/Composition.h" +#include "base/NotationTypes.h" +#include "gui/widgets/TimeWidget.h" +#include "gui/widgets/BigArrowButton.h" +#include <kconfig.h> +#include <kdialogbase.h> +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qfont.h> +#include <qgroupbox.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qobject.h> +#include <qradiobutton.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +TimeSignatureDialog::TimeSignatureDialog(QWidget *parent, + Composition *composition, + timeT insertionTime, + TimeSignature sig, + bool timeEditable, + QString explanatoryText) : + KDialogBase(parent, 0, true, i18n("Time Signature"), Ok | Cancel | Help), + m_composition(composition), + m_timeSignature(sig), + m_time(insertionTime), + m_numLabel(0), + m_denomLabel(0), + m_explanatoryLabel(0), + m_commonTimeButton(0), + m_hideSignatureButton(0), + m_normalizeRestsButton(0), + m_asGivenButton(0), + m_startOfBarButton(0), + m_timeEditor(0) +{ + static QFont *timeSigFont = 0; + + if (timeSigFont == 0) { + timeSigFont = new QFont("new century schoolbook", 8, QFont::Bold); + timeSigFont->setPixelSize(20); + } + + QVBox *vbox = makeVBoxMainWidget(); + QGroupBox *groupBox = new QGroupBox + (1, Horizontal, i18n("Time signature"), vbox); + QHBox *numBox = new QHBox(groupBox); + QHBox *denomBox = new QHBox(groupBox); + + QLabel *explanatoryLabel = 0; + if (explanatoryText) { + explanatoryLabel = new QLabel(explanatoryText, groupBox); + } + + BigArrowButton *numDown = new BigArrowButton(numBox, Qt::LeftArrow); + BigArrowButton *denomDown = new BigArrowButton(denomBox, Qt::LeftArrow); + + m_numLabel = new QLabel + (QString("%1").arg(m_timeSignature.getNumerator()), numBox); + m_denomLabel = new QLabel + (QString("%1").arg(m_timeSignature.getDenominator()), denomBox); + + m_numLabel->setAlignment(AlignHCenter | AlignVCenter); + m_denomLabel->setAlignment(AlignHCenter | AlignVCenter); + + m_numLabel->setFont(*timeSigFont); + m_denomLabel->setFont(*timeSigFont); + + BigArrowButton *numUp = new BigArrowButton(numBox, Qt::RightArrow); + BigArrowButton *denomUp = new BigArrowButton(denomBox, Qt::RightArrow); + + QObject::connect(numDown, SIGNAL(clicked()), this, SLOT(slotNumDown())); + QObject::connect(numUp, SIGNAL(clicked()), this, SLOT(slotNumUp())); + QObject::connect(denomDown, SIGNAL(clicked()), this, SLOT(slotDenomDown())); + QObject::connect(denomUp, SIGNAL(clicked()), this, SLOT(slotDenomUp())); + + if (timeEditable) { + + m_timeEditor = new TimeWidget + (i18n("Time where signature takes effect"), + vbox, + composition, + m_time, + true); + + m_asGivenButton = 0; + m_startOfBarButton = 0; + + } else { + + m_timeEditor = 0; + + groupBox = new QButtonGroup(1, Horizontal, i18n("Scope"), vbox); + + int barNo = composition->getBarNumber(m_time); + bool atStartOfBar = (m_time == composition->getBarStart(barNo)); + + if (!atStartOfBar) { + + QString scopeText; + + if (barNo != 0 || !atStartOfBar) { + if (atStartOfBar) { + scopeText = QString + (i18n("Insertion point is at start of measure %1.")) + .arg(barNo + 1); + } else { + scopeText = QString + (i18n("Insertion point is in the middle of measure %1.")) + .arg(barNo + 1); + } + } else { + scopeText = QString + (i18n("Insertion point is at start of composition.")); + } + + new QLabel(scopeText, groupBox); + m_asGivenButton = new QRadioButton + (i18n("Start measure %1 here").arg(barNo + 2), groupBox); + + if (!atStartOfBar) { + m_startOfBarButton = new QRadioButton + (i18n("Change time from start of measure %1") + .arg(barNo + 1), groupBox); + m_startOfBarButton->setChecked(true); + } else { + m_asGivenButton->setChecked(true); + } + } else { + new QLabel(i18n("Time change will take effect at the start of measure %1.") + .arg(barNo + 1), groupBox); + } + } + + groupBox = new QGroupBox(1, Horizontal, i18n("Options"), vbox); + KConfig *config = kapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + + m_hideSignatureButton = new QCheckBox + (i18n("Hide the time signature"), groupBox); + m_hideSignatureButton->setChecked + (config->readBoolEntry("timesigdialogmakehidden", false)); + + m_hideBarsButton = new QCheckBox + (i18n("Hide the affected bar lines"), groupBox); + m_hideBarsButton->setChecked + (config->readBoolEntry("timesigdialogmakehiddenbars", false)); + + m_commonTimeButton = new QCheckBox + (i18n("Show as common time"), groupBox); + m_commonTimeButton->setChecked + (config->readBoolEntry("timesigdialogshowcommon", true)); + + m_normalizeRestsButton = new QCheckBox + (i18n("Correct the durations of following measures"), groupBox); + m_normalizeRestsButton->setChecked + (config->readBoolEntry("timesigdialognormalize", true)); + + QObject::connect(m_hideSignatureButton, SIGNAL(clicked()), this, + SLOT(slotUpdateCommonTimeButton())); + slotUpdateCommonTimeButton(); + m_explanatoryLabel = explanatoryLabel; + + setHelp("time-signature"); +} + +TimeSignature +TimeSignatureDialog::getTimeSignature() const +{ + KConfig *config = kapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + + config->writeEntry("timesigdialogmakehidden", m_hideSignatureButton->isChecked()); + config->writeEntry("timesigdialogmakehiddenbars", m_hideBarsButton->isChecked()); + config->writeEntry("timesigdialogshowcommon", m_commonTimeButton->isChecked()); + config->writeEntry("timesigdialognormalize", m_normalizeRestsButton->isChecked()); + + TimeSignature ts(m_timeSignature.getNumerator(), + m_timeSignature.getDenominator(), + (m_commonTimeButton && + m_commonTimeButton->isEnabled() && + m_commonTimeButton->isChecked()), + (m_hideSignatureButton && + m_hideSignatureButton->isEnabled() && + m_hideSignatureButton->isChecked()), + (m_hideBarsButton && + m_hideBarsButton->isEnabled() && + m_hideBarsButton->isChecked())); + return ts; +} + +void +TimeSignatureDialog::slotNumDown() +{ + int n = m_timeSignature.getNumerator(); + if (--n >= 1) { + m_timeSignature = TimeSignature(n, m_timeSignature.getDenominator()); + m_numLabel->setText(QString("%1").arg(n)); + } + slotUpdateCommonTimeButton(); +} + +void +TimeSignatureDialog::slotNumUp() +{ + int n = m_timeSignature.getNumerator(); + if (++n <= 99) { + m_timeSignature = TimeSignature(n, m_timeSignature.getDenominator()); + m_numLabel->setText(QString("%1").arg(n)); + } + slotUpdateCommonTimeButton(); +} + +void +TimeSignatureDialog::slotDenomDown() +{ + int n = m_timeSignature.getDenominator(); + if ((n /= 2) >= 1) { + m_timeSignature = TimeSignature(m_timeSignature.getNumerator(), n); + m_denomLabel->setText(QString("%1").arg(n)); + } + slotUpdateCommonTimeButton(); +} + +void +TimeSignatureDialog::slotDenomUp() +{ + int n = m_timeSignature.getDenominator(); + if ((n *= 2) <= 64) { + m_timeSignature = TimeSignature(m_timeSignature.getNumerator(), n); + m_denomLabel->setText(QString("%1").arg(n)); + } + slotUpdateCommonTimeButton(); +} + +void +TimeSignatureDialog::slotUpdateCommonTimeButton() +{ + if (m_explanatoryLabel) + m_explanatoryLabel->hide(); + if (!m_hideSignatureButton || !m_hideSignatureButton->isChecked()) { + if (m_timeSignature.getDenominator() == m_timeSignature.getNumerator()) { + if (m_timeSignature.getNumerator() == 4) { + m_commonTimeButton->setText(i18n("Display as common time")); + m_commonTimeButton->setEnabled(true); + return ; + } else if (m_timeSignature.getNumerator() == 2) { + m_commonTimeButton->setText(i18n("Display as cut common time")); + m_commonTimeButton->setEnabled(true); + return ; + } + } + } + m_commonTimeButton->setEnabled(false); +} + +timeT +TimeSignatureDialog::getTime() const +{ + if (m_timeEditor) { + return m_timeEditor->getTime(); + } else if (m_asGivenButton && m_asGivenButton->isChecked()) { + return m_time; + } else if (m_startOfBarButton && m_startOfBarButton->isChecked()) { + int barNo = m_composition->getBarNumber(m_time); + return m_composition->getBarStart(barNo); + } else { + return m_time; + } +} + +bool +TimeSignatureDialog::shouldNormalizeRests() const +{ + return (m_normalizeRestsButton && m_normalizeRestsButton->isEnabled() && + m_normalizeRestsButton->isChecked()); +} + +} +#include "TimeSignatureDialog.moc" diff --git a/src/gui/dialogs/TimeSignatureDialog.h b/src/gui/dialogs/TimeSignatureDialog.h new file mode 100644 index 0000000..330134c --- /dev/null +++ b/src/gui/dialogs/TimeSignatureDialog.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_TIMESIGNATUREDIALOG_H_ +#define _RG_TIMESIGNATUREDIALOG_H_ + +#include "base/NotationTypes.h" +#include <kdialogbase.h> +#include <qstring.h> +#include "base/Event.h" + + +class QWidget; +class QRadioButton; +class QLabel; +class QCheckBox; + + +namespace Rosegarden +{ + +class TimeWidget; +class Composition; + + +class TimeSignatureDialog : public KDialogBase +{ + Q_OBJECT + +public: + TimeSignatureDialog(QWidget *parent, + Composition *composition, + timeT insertionTime, + TimeSignature defaultSig = + TimeSignature::DefaultTimeSignature, + bool timeEditable = false, + QString explanatoryText = 0); + + TimeSignature getTimeSignature() const; + + timeT getTime() const; + bool shouldNormalizeRests() const; + +public slots: + void slotNumUp(); + void slotNumDown(); + void slotDenomUp(); + void slotDenomDown(); + void slotUpdateCommonTimeButton(); + +protected: + //--------------- Data members --------------------------------- + + Composition *m_composition; + TimeSignature m_timeSignature; + timeT m_time; + + QLabel *m_numLabel; + QLabel *m_denomLabel; + QLabel *m_explanatoryLabel; + + QCheckBox *m_commonTimeButton; + QCheckBox *m_hideSignatureButton; + QCheckBox *m_hideBarsButton; + QCheckBox *m_normalizeRestsButton; + + QRadioButton *m_asGivenButton; + QRadioButton *m_startOfBarButton; + + TimeWidget *m_timeEditor; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/TransportDialog.cpp b/src/gui/dialogs/TransportDialog.cpp new file mode 100644 index 0000000..115a528 --- /dev/null +++ b/src/gui/dialogs/TransportDialog.cpp @@ -0,0 +1,1164 @@ +/* -*- 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 "TransportDialog.h" + +#include <klocale.h> +#include <kstddirs.h> +#include "base/Composition.h" +#include "base/NotationTypes.h" +#include "base/RealTime.h" +#include "misc/Debug.h" +#include "gui/application/RosegardenApplication.h" +#include "gui/general/MidiPitchLabel.h" +#include "gui/studio/StudioControl.h" +#include "gui/widgets/Label.h" +#include "sound/MappedEvent.h" +#include "document/ConfigGroups.h" +#include <kconfig.h> +#include <kglobal.h> +#include <qaccel.h> +#include <qcolor.h> +#include <qcstring.h> +#include <qdatastream.h> +#include <qfont.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qpalette.h> +#include <qpixmap.h> +#include <qpushbutton.h> +#include <qstring.h> +#include <qtimer.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +TransportDialog::TransportDialog(QWidget *parent, + const char *name, + WFlags flags): + QWidget(parent, name, WType_TopLevel | WStyle_DialogBorder | WStyle_Minimize | WStyle_SysMenu | WDestructiveClose), + m_transport(0), + m_lastTenHours(0), + m_lastUnitHours(0), + m_lastTenMinutes(0), + m_lastUnitMinutes(0), + m_lastTenSeconds(0), + m_lastUnitSeconds(0), + m_lastTenths(0), + m_lastHundreths(0), + m_lastThousandths(0), + m_lastTenThousandths(0), + m_lastNegative(false), + m_lastMode(RealMode), + m_currentMode(RealMode), + m_tempo(0), + m_numerator(0), + m_denominator(0), + m_framesPerSecond(24), + m_bitsPerFrame(80), + m_isExpanded(true), + m_haveOriginalBackground(false), + m_isBackgroundSet(false), + m_sampleRate(0) +{ + m_transport = new RosegardenTransport(this); + + setCaption(i18n("Rosegarden Transport")); + + resetFonts(); + + initModeMap(); + + // set the LCD frame background to black + // + m_transport->LCDBoxFrame->setBackgroundColor(Qt::black); + + // set all the pixmap backgrounds to black to avoid + // flickering when we update + // + m_transport->TenThousandthsPixmap->setBackgroundColor(Qt::black); + m_transport->ThousandthsPixmap->setBackgroundColor(Qt::black); + m_transport->HundredthsPixmap->setBackgroundColor(Qt::black); + m_transport->TenthsPixmap->setBackgroundColor(Qt::black); + m_transport->UnitSecondsPixmap->setBackgroundColor(Qt::black); + m_transport->TenSecondsPixmap->setBackgroundColor(Qt::black); + m_transport->UnitMinutesPixmap->setBackgroundColor(Qt::black); + m_transport->TenMinutesPixmap->setBackgroundColor(Qt::black); + m_transport->UnitHoursPixmap->setBackgroundColor(Qt::black); + m_transport->TenHoursPixmap->setBackgroundColor(Qt::black); + m_transport->NegativePixmap->setBackgroundColor(Qt::black); + + // unset the negative sign to begin with + m_transport->NegativePixmap->clear(); + + // Set our toggle buttons + // + m_transport->PlayButton->setToggleButton(true); + m_transport->RecordButton->setToggleButton(true); + +// Disable the loop button if JACK transport enabled, because this +// causes a nasty race condition, and it just seems our loops are not JACK compatible +// #1240039 - DMM +// KConfig* config = rgapp->config(); +// config->setGroup(SequencerOptionsConfigGroup); +// if (config->readBoolEntry("jacktransport", false)) +// { +// m_transport->LoopButton->setEnabled(false); +// } + + // fix and hold the size of the dialog + // + setMinimumSize(m_transport->width(), m_transport->height()); + setMaximumSize(m_transport->width(), m_transport->height()); + + loadPixmaps(); + + // Create Midi label timers + m_midiInTimer = new QTimer(this); + m_midiOutTimer = new QTimer(this); + m_clearMetronomeTimer = new QTimer(this); + + connect(m_midiInTimer, SIGNAL(timeout()), + SLOT(slotClearMidiInLabel())); + + connect(m_midiOutTimer, SIGNAL(timeout()), + SLOT(slotClearMidiOutLabel())); + + connect(m_clearMetronomeTimer, SIGNAL(timeout()), + SLOT(slotResetBackground())); + + m_transport->TimeDisplayLabel->hide(); + m_transport->ToEndLabel->hide(); + + connect(m_transport->TimeDisplayButton, SIGNAL(clicked()), + SLOT(slotChangeTimeDisplay())); + + connect(m_transport->ToEndButton, SIGNAL(clicked()), + SLOT(slotChangeToEnd())); + + connect(m_transport->LoopButton, SIGNAL(clicked()), + SLOT(slotLoopButtonClicked())); + + connect(m_transport->PanelOpenButton, SIGNAL(clicked()), + SLOT(slotPanelOpenButtonClicked())); + + connect(m_transport->PanelCloseButton, SIGNAL(clicked()), + SLOT(slotPanelCloseButtonClicked())); + + connect(m_transport->PanicButton, SIGNAL(clicked()), SIGNAL(panic())); + + m_panelOpen = *m_transport->PanelOpenButton->pixmap(); + m_panelClosed = *m_transport->PanelCloseButton->pixmap(); + + + connect(m_transport->SetStartLPButton, SIGNAL(clicked()), SLOT(slotSetStartLoopingPointAtMarkerPos())); + connect(m_transport->SetStopLPButton, SIGNAL(clicked()), SLOT(slotSetStopLoopingPointAtMarkerPos())); + + // clear labels + // + slotClearMidiInLabel(); + slotClearMidiOutLabel(); + + // and by default we close the lower panel + // + int rfh = m_transport->RecordingFrame->height(); + m_transport->RecordingFrame->hide(); + setFixedSize(width(), height() - rfh); + m_transport->PanelOpenButton->setPixmap(m_panelClosed); + + // and since by default we show real time (not SMPTE), by default + // we hide the small colon pixmaps + // + m_transport->SecondColonPixmap->hide(); + m_transport->HundredthColonPixmap->hide(); + + // We have to specify these settings in this class (copied + // from rosegardentransport.cpp) as we're using a specialised + // widgets for TempoDisplay. Ugly but works - does mean that + // if the rest of the Transport ever changes then this code + // will have to as well. + // + QPalette pal; + pal.setColor(QColorGroup::Foreground, QColor(192, 216, 255)); + + m_transport->TempoDisplay->setPalette(pal); + m_transport->TempoDisplay->setAlignment(int(QLabel::AlignVCenter | QLabel::AlignRight)); + + m_transport->TimeSigDisplay->setPalette(pal); + m_transport->TimeSigDisplay->setAlignment(int(QLabel::AlignVCenter | QLabel::AlignRight)); + + QFont localFont(m_transport->OutDisplay->font() ); + localFont.setFamily( "lucida" ); + localFont.setBold( TRUE ); + + m_transport->TempoDisplay->setFont( localFont ); + m_transport->TimeSigDisplay->setFont( localFont ); + + connect(m_transport->TempoDisplay, SIGNAL(doubleClicked()), + this, SLOT(slotEditTempo())); + + connect(m_transport->TempoDisplay, SIGNAL(scrollWheel(int)), + this, SIGNAL(scrollTempo(int))); + + connect(m_transport->TimeSigDisplay, SIGNAL(doubleClicked()), + this, SLOT(slotEditTimeSignature())); + + // toil through the individual pixmaps + connect(m_transport->NegativePixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->TenHoursPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->UnitHoursPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->HourColonPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->TenMinutesPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->UnitMinutesPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->MinuteColonPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->TenSecondsPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->UnitSecondsPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->SecondColonPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->TenthsPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->HundredthsPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->HundredthColonPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->TenThousandthsPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + connect(m_transport->ThousandthsPixmap, SIGNAL(doubleClicked()), + this, SLOT(slotEditTime())); + + // accelerator object + // + m_accelerators = new QAccel(this); +} + +TransportDialog::~TransportDialog() +{ + if (isVisible()) { + KConfig* config = rgapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + config->writeEntry("transportx", x()); + config->writeEntry("transporty", y()); + } +} + +std::string +TransportDialog::getCurrentModeAsString() +{ + bool found = false; + for (std::map<std::string, TimeDisplayMode>::iterator iter = m_modeMap.begin(); + iter != m_modeMap.end() && !found; + iter++) + { + if (iter->second == m_currentMode) { + return iter->first; + } + } + + // we shouldn't get here unless the map is not well-configured + RG_DEBUG << "TransportDialog::getCurrentModeAsString: could not map current mode " + << m_currentMode << " to string." << endl; + throw Exception("could not map current mode to string."); +} + +void +TransportDialog::initModeMap() +{ + m_modeMap["RealMode"] = RealMode; + m_modeMap["SMPTEMode"] = SMPTEMode; + m_modeMap["BarMode"] = BarMode; + m_modeMap["BarMetronomeMode"] = BarMetronomeMode; + m_modeMap["FrameMode"] = FrameMode; +} + +void +TransportDialog::show() +{ + KConfig* config = rgapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + int x = config->readNumEntry("transportx", -1); + int y = config->readNumEntry("transporty", -1); + if (x >= 0 && y >= 0) { + int dw = QApplication::desktop()->availableGeometry(QPoint(x, y)).width(); + int dh = QApplication::desktop()->availableGeometry(QPoint(x, y)).height(); + if (x + m_transport->width() > dw) x = dw - m_transport->width(); + if (y + m_transport->height() > dh) y = dh - m_transport->height(); + move(x, y); +// std::cerr << "TransportDialog::show(): moved to " << x << "," << y << std::endl; + QWidget::show(); +// std::cerr << "TransportDialog::show(): now at " << this->x() << "," << this->y() << std::endl; + } else { + QWidget::show(); + } +} + +void +TransportDialog::hide() +{ + if (isVisible()) { + KConfig* config = rgapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + config->writeEntry("transportx", x()); + config->writeEntry("transporty", y()); + } + QWidget::hide(); +} + +void +TransportDialog::loadPixmaps() +{ + m_lcdList.clear(); + QString fileName; + QString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/"); + + for (int i = 0; i < 10; i++) { + fileName = QString("%1/transport/led-%2.xpm").arg(pixmapDir).arg(i); + if (!m_lcdList[i].load(fileName)) { + std::cerr << "TransportDialog - failed to load pixmap \"" + << fileName << "\"" << std::endl; + } + } + + // Load the "negative" sign pixmap + // + fileName = QString("%1/transport/led--.xpm").arg(pixmapDir); + m_lcdNegative.load(fileName); + +} + +void +TransportDialog::resetFonts() +{ + resetFont(m_transport->TimeSigLabel); + resetFont(m_transport->TimeSigDisplay); + resetFont(m_transport->TempoLabel); + resetFont(m_transport->TempoDisplay); + resetFont(m_transport->DivisionLabel); + resetFont(m_transport->DivisionDisplay); + resetFont(m_transport->InLabel); + resetFont(m_transport->InDisplay); + resetFont(m_transport->OutLabel); + resetFont(m_transport->OutDisplay); + resetFont(m_transport->ToEndLabel); + resetFont(m_transport->TimeDisplayLabel); +} + +void +TransportDialog::resetFont(QWidget *w) +{ + QFont font = w->font(); + font.setPixelSize(10); + w->setFont(font); +} + +void +TransportDialog::setSMPTEResolution(int framesPerSecond, + int bitsPerFrame) +{ + m_framesPerSecond = framesPerSecond; + m_bitsPerFrame = bitsPerFrame; +} + +void +TransportDialog::getSMPTEResolution(int &framesPerSecond, + int &bitsPerFrame) +{ + framesPerSecond = m_framesPerSecond; + bitsPerFrame = m_bitsPerFrame; +} + +void +TransportDialog::computeSampleRate() +{ + if (m_sampleRate == 0) { + + QCString replyType; + QByteArray replyData; + m_sampleRate = 0; + + if (rgapp->sequencerCall("getSampleRate()", replyType, replyData)) { + QDataStream streamIn(replyData, IO_ReadOnly); + unsigned int result; + streamIn >> result; + m_sampleRate = result; + } else { + m_sampleRate = -1; + } + } + +} + +void +TransportDialog::cycleThroughModes() +{ + switch (m_currentMode) { + + case RealMode: + if (m_sampleRate > 0) + m_currentMode = FrameMode; + else + m_currentMode = BarMode; + break; + + case FrameMode: + m_currentMode = BarMode; + break; + + case SMPTEMode: + m_currentMode = BarMode; + break; + + case BarMode: + m_currentMode = BarMetronomeMode; + break; + + case BarMetronomeMode: + m_currentMode = RealMode; + break; + } +} + +void +TransportDialog::displayTime() +{ + switch (m_currentMode) { + case RealMode: + m_clearMetronomeTimer->stop(); + m_transport->TimeDisplayLabel->hide(); + break; + + case SMPTEMode: + m_clearMetronomeTimer->stop(); + m_transport->TimeDisplayLabel->setText("SMPTE"); // DO NOT i18n + m_transport->TimeDisplayLabel->show(); + break; + + case BarMode: + m_clearMetronomeTimer->stop(); + m_transport->TimeDisplayLabel->setText("BAR"); // DO NOT i18n + m_transport->TimeDisplayLabel->show(); + break; + + case BarMetronomeMode: + m_clearMetronomeTimer->start(1700, FALSE); + m_transport->TimeDisplayLabel->setText("MET"); // DO NOT i18n + m_transport->TimeDisplayLabel->show(); + break; + + case FrameMode: + m_clearMetronomeTimer->stop(); + m_transport->TimeDisplayLabel->setText(QString("%1").arg(m_sampleRate)); + m_transport->TimeDisplayLabel->show(); + break; + } +} + +void +TransportDialog::setNewMode(const std::string& newModeAsString) +{ + TimeDisplayMode newMode = RealMode; // default value if not found + + std::map<std::string, TimeDisplayMode>::iterator iter = + m_modeMap.find(newModeAsString); + + if (iter != m_modeMap.end()) { + // value found + newMode = iter->second; + } else { + // don't fail: use default value set at declaration + } + + setNewMode(newMode); +} + +void +TransportDialog::setNewMode(const TimeDisplayMode& newMode) +{ + computeSampleRate(); + + m_currentMode = newMode; + + displayTime(); +} + + +void +TransportDialog::slotChangeTimeDisplay() +{ + computeSampleRate(); + + cycleThroughModes(); + + displayTime(); +} + +void +TransportDialog::slotChangeToEnd() +{ + if (m_transport->ToEndButton->isOn()) { + m_transport->ToEndLabel->show(); + } else { + m_transport->ToEndLabel->hide(); + } +} + +bool +TransportDialog::isShowingTimeToEnd() +{ + return m_transport->ToEndButton->isOn(); +} + +void +TransportDialog::displayRealTime(const RealTime &rt) +{ + RealTime st = rt; + + slotResetBackground(); + + if (m_lastMode != RealMode) { + m_transport->HourColonPixmap->show(); + m_transport->MinuteColonPixmap->show(); + m_transport->SecondColonPixmap->hide(); + m_transport->HundredthColonPixmap->hide(); + m_lastMode = RealMode; + } + + // If time is negative then reverse the time and set the minus flag + // + if (st < RealTime::zeroTime) { + st = RealTime::zeroTime - st; + if (!m_lastNegative) { + m_transport->NegativePixmap->setPixmap(m_lcdNegative); + m_lastNegative = true; + } + } else // don't show the flag + { + if (m_lastNegative) { + m_transport->NegativePixmap->clear(); + m_lastNegative = false; + } + } + + m_tenThousandths = ( st.usec() / 100 ) % 10; + m_thousandths = ( st.usec() / 1000 ) % 10; + m_hundreths = ( st.usec() / 10000 ) % 10; + m_tenths = ( st.usec() / 100000 ) % 10; + + m_unitSeconds = ( st.sec ) % 10; + m_tenSeconds = ( st.sec / 10 ) % 6; + + m_unitMinutes = ( st.sec / 60 ) % 10; + m_tenMinutes = ( st.sec / 600 ) % 6; + + m_unitHours = ( st.sec / 3600 ) % 10; + m_tenHours = (st.sec / 36000 ) % 10; + + updateTimeDisplay(); +} + +void +TransportDialog::displayFrameTime(const RealTime &rt) +{ + RealTime st = rt; + + slotResetBackground(); + + if (m_lastMode != FrameMode) { + m_transport->HourColonPixmap->hide(); + m_transport->MinuteColonPixmap->hide(); + m_transport->SecondColonPixmap->hide(); + m_transport->HundredthColonPixmap->hide(); + m_lastMode = FrameMode; + } + + // If time is negative then reverse the time and set the minus flag + // + if (st < RealTime::zeroTime) { + st = RealTime::zeroTime - st; + if (!m_lastNegative) { + m_transport->NegativePixmap->setPixmap(m_lcdNegative); + m_lastNegative = true; + } + } else // don't show the flag + { + if (m_lastNegative) { + m_transport->NegativePixmap->clear(); + m_lastNegative = false; + } + } + + long frame = RealTime::realTime2Frame(st, m_sampleRate); + + m_tenThousandths = frame % 10; + frame /= 10; + m_thousandths = frame % 10; + frame /= 10; + m_hundreths = frame % 10; + frame /= 10; + m_tenths = frame % 10; + frame /= 10; + m_unitSeconds = frame % 10; + frame /= 10; + m_tenSeconds = frame % 10; + frame /= 10; + m_unitMinutes = frame % 10; + frame /= 10; + m_tenMinutes = frame % 10; + frame /= 10; + m_unitHours = frame % 10; + frame /= 10; + m_tenHours = frame % 10; + frame /= 10; + + updateTimeDisplay(); +} + +void +TransportDialog::displaySMPTETime(const RealTime &rt) +{ + RealTime st = rt; + + slotResetBackground(); + + if (m_lastMode != SMPTEMode) { + m_transport->HourColonPixmap->show(); + m_transport->MinuteColonPixmap->show(); + m_transport->SecondColonPixmap->show(); + m_transport->HundredthColonPixmap->show(); + m_lastMode = SMPTEMode; + } + + // If time is negative then reverse the time and set the minus flag + // + if (st < RealTime::zeroTime) { + st = RealTime::zeroTime - st; + if (!m_lastNegative) { + m_transport->NegativePixmap->setPixmap(m_lcdNegative); + m_lastNegative = true; + } + } else // don't show the flag + { + if (m_lastNegative) { + m_transport->NegativePixmap->clear(); + m_lastNegative = false; + } + } + + m_tenThousandths = + (( st.usec() * m_framesPerSecond * m_bitsPerFrame) / 1000000 ) % 10; + m_thousandths = + (( st.usec() * m_framesPerSecond * m_bitsPerFrame) / 10000000 ) % + (m_bitsPerFrame / 10); + m_hundreths = + (( st.usec() * m_framesPerSecond) / 1000000 ) % 10; + m_tenths = + (( st.usec() * m_framesPerSecond) / 10000000 ) % 10; + + m_unitSeconds = ( st.sec ) % 10; + m_tenSeconds = ( st.sec / 10 ) % 6; + + m_unitMinutes = ( st.sec / 60 ) % 10; + m_tenMinutes = ( st.sec / 600 ) % 6; + + m_unitHours = ( st.sec / 3600 ) % 10; + m_tenHours = ( st.sec / 36000 ) % 10; + + updateTimeDisplay(); +} + +void +TransportDialog::displayBarTime(int bar, int beat, int unit) +{ + if (m_lastMode != BarMode) { + m_transport->HourColonPixmap->hide(); + m_transport->MinuteColonPixmap->show(); + m_transport->SecondColonPixmap->hide(); + m_transport->HundredthColonPixmap->hide(); + m_lastMode = BarMode; + } + + // If time is negative then reverse the time and set the minus flag + // + if (bar < 0) { + bar = -bar; + if (!m_lastNegative) { + m_transport->NegativePixmap->setPixmap(m_lcdNegative); + m_lastNegative = true; + } + } else // don't show the flag + { + if (m_lastNegative) { + m_transport->NegativePixmap->clear(); + m_lastNegative = false; + } + } + + if (m_currentMode == BarMetronomeMode && unit < 2) { + if (beat == 1) { + slotSetBackground(Qt::red); + } else { + slotSetBackground(Qt::cyan); + } + } else { + slotResetBackground(); + } + + m_tenThousandths = ( unit ) % 10; + m_thousandths = ( unit / 10 ) % 10; + m_hundreths = ( unit / 100 ) % 10; + m_tenths = ( unit / 1000 ) % 10; + + if (m_tenths == 0) { + m_tenths = -1; + if (m_hundreths == 0) { + m_hundreths = -1; + if (m_thousandths == 0) { + m_thousandths = -1; + } + } + } + + m_unitSeconds = ( beat ) % 10; + m_tenSeconds = ( beat / 10 ) % 6; + + if (m_tenSeconds == 0) { + m_tenSeconds = -1; + } + + m_unitMinutes = ( bar ) % 10; + m_tenMinutes = ( bar / 10 ) % 10; + + m_unitHours = ( bar / 100 ) % 10; + m_tenHours = ( bar / 1000 ) % 10; + + if (m_tenHours == 0) { + m_tenHours = -1; + if (m_unitHours == 0) { + m_unitHours = -1; + if (m_tenMinutes == 0) { + m_tenMinutes = -1; + } + } + } + + updateTimeDisplay(); +} + +void +TransportDialog::updateTimeDisplay() +{ + if (m_tenThousandths != m_lastTenThousandths) { + if (m_tenThousandths < 0) + m_transport->TenThousandthsPixmap->clear(); + else + m_transport->TenThousandthsPixmap->setPixmap(m_lcdList[m_tenThousandths]); + m_lastTenThousandths = m_tenThousandths; + } + + if (m_thousandths != m_lastThousandths) { + if (m_thousandths < 0) + m_transport->ThousandthsPixmap->clear(); + else + m_transport->ThousandthsPixmap->setPixmap(m_lcdList[m_thousandths]); + m_lastThousandths = m_thousandths; + } + + if (m_hundreths != m_lastHundreths) { + if (m_hundreths < 0) + m_transport->HundredthsPixmap->clear(); + else + m_transport->HundredthsPixmap->setPixmap(m_lcdList[m_hundreths]); + m_lastHundreths = m_hundreths; + } + + if (m_tenths != m_lastTenths) { + if (m_tenths < 0) + m_transport->TenthsPixmap->clear(); + else + m_transport->TenthsPixmap->setPixmap(m_lcdList[m_tenths]); + m_lastTenths = m_tenths; + } + + if (m_unitSeconds != m_lastUnitSeconds) { + if (m_unitSeconds < 0) + m_transport->UnitSecondsPixmap->clear(); + else + m_transport->UnitSecondsPixmap->setPixmap(m_lcdList[m_unitSeconds]); + m_lastUnitSeconds = m_unitSeconds; + } + + if (m_tenSeconds != m_lastTenSeconds) { + if (m_tenSeconds < 0) + m_transport->TenSecondsPixmap->clear(); + else + m_transport->TenSecondsPixmap->setPixmap(m_lcdList[m_tenSeconds]); + m_lastTenSeconds = m_tenSeconds; + } + + if (m_unitMinutes != m_lastUnitMinutes) { + if (m_unitMinutes < 0) + m_transport->UnitMinutesPixmap->clear(); + else + m_transport->UnitMinutesPixmap->setPixmap(m_lcdList[m_unitMinutes]); + m_lastUnitMinutes = m_unitMinutes; + } + + if (m_tenMinutes != m_lastTenMinutes) { + if (m_tenMinutes < 0) + m_transport->TenMinutesPixmap->clear(); + else + m_transport->TenMinutesPixmap->setPixmap(m_lcdList[m_tenMinutes]); + m_lastTenMinutes = m_tenMinutes; + } + + if (m_unitHours != m_lastUnitHours) { + if (m_unitHours < 0) + m_transport->UnitHoursPixmap->clear(); + else + m_transport->UnitHoursPixmap->setPixmap(m_lcdList[m_unitHours]); + m_lastUnitHours = m_unitHours; + } + + if (m_tenHours != m_lastTenHours) { + if (m_tenHours < 0) + m_transport->TenHoursPixmap->clear(); + else + m_transport->TenHoursPixmap->setPixmap(m_lcdList[m_tenHours]); + m_lastTenHours = m_tenHours; + } +} + +void +TransportDialog::setTempo(const tempoT &tempo) +{ + if (m_tempo == tempo) + return ; + m_tempo = tempo; + + // Send the quarter note length to the sequencer - shouldn't + // really hang this off here but at least it's a single point + // where the tempo should always be consistent. Quarter Note + // Length is sent (MIDI CLOCK) at 24ppqn. + // + double qnD = 60.0 / Composition::getTempoQpm(tempo); + RealTime qnTime = + RealTime(long(qnD), + long((qnD - double(long(qnD))) * 1000000000.0)); + + StudioControl::sendQuarterNoteLength(qnTime); + + QString tempoString; + tempoString.sprintf("%4.3f", Composition::getTempoQpm(tempo)); + + m_transport->TempoDisplay->setText(tempoString); +} + +void +TransportDialog::setTimeSignature(const TimeSignature &timeSig) +{ + int numerator = timeSig.getNumerator(); + int denominator = timeSig.getDenominator(); + if (m_numerator == numerator && m_denominator == denominator) + return ; + m_numerator = numerator; + m_denominator = denominator; + + QString timeSigString; + timeSigString.sprintf("%d/%d", numerator, denominator); + m_transport->TimeSigDisplay->setText(timeSigString); +} + +void +TransportDialog::setMidiInLabel(const MappedEvent *mE) +{ + assert(mE > 0); + + switch (mE->getType()) { + case MappedEvent::MidiNote: + case MappedEvent::MidiNoteOneShot: + { + // don't do anything if we've got an effective NOTE OFF + // + if (mE->getVelocity() == 0) + return ; + + MidiPitchLabel mPL(mE->getPitch()); + m_transport->InDisplay->setText + (mPL.getQString() + + QString(" %1").arg(mE->getVelocity())); + } + break; + + case MappedEvent::MidiPitchBend: + m_transport->InDisplay->setText(i18n("PITCH WHEEL")); + break; + + case MappedEvent::MidiController: + m_transport->InDisplay->setText(i18n("CONTROLLER")); + break; + + case MappedEvent::MidiProgramChange: + m_transport->InDisplay->setText(i18n("PROG CHNGE")); + break; + + case MappedEvent::MidiKeyPressure: + case MappedEvent::MidiChannelPressure: + m_transport->InDisplay->setText(i18n("PRESSURE")); + break; + + case MappedEvent::MidiSystemMessage: + m_transport->InDisplay->setText(i18n("SYS MESSAGE")); + break; + + default: // do nothing + return ; + } + + // Reset the timer if it's already running + // + if (m_midiInTimer->isActive()) + m_midiInTimer->stop(); + + // 1.5 second timeout for MIDI event + // + m_midiInTimer->start(1500, true); +} + +void +TransportDialog::slotClearMidiInLabel() +{ + m_transport->InDisplay->setText(i18n(QString("NO EVENTS"))); + + // also, just to be sure: + slotResetBackground(); +} + +void +TransportDialog::setMidiOutLabel(const MappedEvent *mE) +{ + assert(mE > 0); + + switch (mE->getType()) { + case MappedEvent::MidiNote: + case MappedEvent::MidiNoteOneShot: + { + MidiPitchLabel mPL(mE->getPitch()); + m_transport->OutDisplay->setText + (mPL.getQString() + + QString(" %1").arg(mE->getVelocity())); + } + break; + + case MappedEvent::MidiPitchBend: + m_transport->OutDisplay->setText(i18n("PITCH WHEEL")); + break; + + case MappedEvent::MidiController: + m_transport->OutDisplay->setText(i18n("CONTROLLER")); + break; + + case MappedEvent::MidiProgramChange: + m_transport->OutDisplay->setText(i18n("PROG CHNGE")); + break; + + case MappedEvent::MidiKeyPressure: + case MappedEvent::MidiChannelPressure: + m_transport->OutDisplay->setText(i18n("PRESSURE")); + break; + + case MappedEvent::MidiSystemMessage: + m_transport->OutDisplay->setText(i18n("SYS MESSAGE")); + break; + + default: // do nothing + return ; + } + + // Reset the timer if it's already running + // + if (m_midiOutTimer->isActive()) + m_midiOutTimer->stop(); + + // 200 millisecond timeout + // + m_midiOutTimer->start(200, true); +} + +void +TransportDialog::slotClearMidiOutLabel() +{ + m_transport->OutDisplay->setText(i18n(QString("NO EVENTS"))); +} + +void +TransportDialog::closeEvent (QCloseEvent * /*e*/) +{ + //e->accept(); // accept the close event here + emit closed(); +} + +void +TransportDialog::slotLoopButtonClicked() +{ + // disable if JACK transport has been set #1240039 - DMM + // KConfig* config = rgapp->config(); + // config->setGroup(SequencerOptionsConfigGroup); + // if (config->readBoolEntry("jacktransport", false)) + // { + // //!!! - this will fail silently + // m_transport->LoopButton->setEnabled(false); + // m_transport->LoopButton->setOn(false); + // return; + // } + + if (m_transport->LoopButton->isOn()) { + emit setLoop(); + } else { + emit unsetLoop(); + } +} + +void +TransportDialog::slotSetStartLoopingPointAtMarkerPos() +{ + emit setLoopStartTime(); +} + +void +TransportDialog::slotSetStopLoopingPointAtMarkerPos() +{ + emit setLoopStopTime(); +} + +void +TransportDialog::slotPanelOpenButtonClicked() +{ + int rfh = m_transport->RecordingFrame->height(); + + if (m_transport->RecordingFrame->isVisible()) { + m_transport->RecordingFrame->hide(); + setFixedSize(width(), height() - rfh); + m_transport->PanelOpenButton->setPixmap(m_panelClosed); + m_isExpanded = false; + } else { + setFixedSize(width(), height() + rfh); + m_transport->RecordingFrame->show(); + m_transport->PanelOpenButton->setPixmap(m_panelOpen); + m_isExpanded = true; + } +} + +void +TransportDialog::slotPanelCloseButtonClicked() +{ + int rfh = m_transport->RecordingFrame->height(); + + if (m_transport->RecordingFrame->isVisible()) { + m_transport->RecordingFrame->hide(); + setFixedSize(width(), height() - rfh); + m_transport->PanelOpenButton->setPixmap(m_panelClosed); + m_isExpanded = false; + } +} + +bool +TransportDialog::isExpanded() +{ + return m_isExpanded; +} + +void +TransportDialog::slotEditTempo() +{ + emit editTempo(this); +} + +void +TransportDialog::slotEditTimeSignature() +{ + emit editTimeSignature(this); +} + +void +TransportDialog::slotEditTime() +{ + emit editTransportTime(this); +} + +void +TransportDialog::slotSetBackground(QColor c) +{ + if (!m_haveOriginalBackground) { + m_originalBackground = m_transport->LCDBoxFrame->paletteBackgroundColor(); + m_haveOriginalBackground = true; + } + + m_transport->LCDBoxFrame->setPaletteBackgroundColor(c); + m_transport->NegativePixmap->setPaletteBackgroundColor(c); + m_transport->TenHoursPixmap->setPaletteBackgroundColor(c); + m_transport->UnitHoursPixmap->setPaletteBackgroundColor(c); + m_transport->TimeDisplayLabel->setPaletteBackgroundColor(c); + + /* this is a bit more thorough, but too slow and flickery: + + const QObjectList *children = m_transport->LCDBoxFrame->children(); + QObjectListIt it(*children); + QObject *obj; + + while ((obj = it.current()) != 0) { + + QWidget *w = dynamic_cast<QWidget *>(obj); + if (w) { + w->setPaletteBackgroundColor(c); + } + ++it; + } + + */ + + m_isBackgroundSet = true; +} + +void +TransportDialog::slotResetBackground() +{ + if (m_isBackgroundSet) { + slotSetBackground(m_originalBackground); + } + m_isBackgroundSet = false; +} + +} +#include "TransportDialog.moc" diff --git a/src/gui/dialogs/TransportDialog.h b/src/gui/dialogs/TransportDialog.h new file mode 100644 index 0000000..e5c4948 --- /dev/null +++ b/src/gui/dialogs/TransportDialog.h @@ -0,0 +1,231 @@ +/* -*- 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_ROSEGARDENTRANSPORTDIALOG_H_ +#define _RG_ROSEGARDENTRANSPORTDIALOG_H_ + +#include <map> +#include <kdockwidget.h> +#include <qcolor.h> +#include <qpixmap.h> +#include "base/Composition.h" // for tempoT +#include "RosegardenTransport.h" // generated by uic + +class RosegardenTransport; +class QWidget; +class QTimer; +class QPushButton; +class QCloseEvent; +class QAccel; + + +namespace Rosegarden +{ + +class TimeSignature; +class RealTime; +class MappedEvent; + + +class TransportDialog : public QWidget +{ +Q_OBJECT +public: + TransportDialog(QWidget *parent=0, + const char *name=0, + WFlags flags = /*Qt::WStyle_StaysOnTop |*/ + Qt::WStyle_NormalBorder); + ~TransportDialog(); + + enum TimeDisplayMode { RealMode, SMPTEMode, BarMode, BarMetronomeMode, FrameMode }; + + std::string getCurrentModeAsString(); + TimeDisplayMode getCurrentMode() { return m_currentMode; } + void setNewMode(const std::string& newModeAsString); + void setNewMode(const TimeDisplayMode& newMode); + bool isShowingTimeToEnd(); + bool isExpanded(); + + void displayRealTime(const RealTime &rt); + void displaySMPTETime(const RealTime &rt); + void displayFrameTime(const RealTime &rt); + void displayBarTime(int bar, int beat, int unit); + + void setTempo(const tempoT &tempo); + void setTimeSignature(const TimeSignature &timeSig); + + void setSMPTEResolution(int framesPerSecond, int bitsPerFrame); + void getSMPTEResolution(int &framesPerSecond, int &bitsPerFrame); + + // Called indirectly from the sequencer and from the GUI to + // show incoming and outgoing MIDI events on the Transport + // + void setMidiInLabel(const MappedEvent *mE); + void setMidiOutLabel(const MappedEvent *mE); + + // Return the accelerator object + // + QAccel* getAccelerators() { return m_accelerators; } + + // RosegardenTransport member accessors + QPushButton* MetronomeButton() { return m_transport->MetronomeButton; } + QPushButton* SoloButton() { return m_transport->SoloButton; } + QPushButton* LoopButton() { return m_transport->LoopButton; } + QPushButton* PlayButton() { return m_transport->PlayButton; } + QPushButton* StopButton() { return m_transport->StopButton; } + QPushButton* FfwdButton() { return m_transport->FfwdButton; } + QPushButton* RewindButton() { return m_transport->RewindButton; } + QPushButton* RecordButton() { return m_transport->RecordButton; } + QPushButton* RewindEndButton() { return m_transport->RewindEndButton; } + QPushButton* FfwdEndButton() { return m_transport->FfwdEndButton; } + QPushButton* TimeDisplayButton() { return m_transport->TimeDisplayButton; } + QPushButton* ToEndButton() { return m_transport->ToEndButton; } + + virtual void show(); + virtual void hide(); + +protected: + virtual void closeEvent(QCloseEvent * e); + void computeSampleRate(); + void cycleThroughModes(); + void displayTime(); + +public slots: + + // These two slots are activated by QTimers + // + void slotClearMidiInLabel(); + void slotClearMidiOutLabel(); + + // These just change the little labels that say what + // mode we're in, nothing else + // + void slotChangeTimeDisplay(); + void slotChangeToEnd(); + + void slotLoopButtonClicked(); + + void slotPanelOpenButtonClicked(); + void slotPanelCloseButtonClicked(); + + void slotEditTempo(); + void slotEditTimeSignature(); + void slotEditTime(); + + void slotSetBackground(QColor); + void slotResetBackground(); + + void slotSetStartLoopingPointAtMarkerPos(); + void slotSetStopLoopingPointAtMarkerPos(); + +signals: + void closed(); + + // Set and unset the loop at the RosegardenGUIApp + // + void setLoop(); + void unsetLoop(); + void setLoopStartTime(); + void setLoopStopTime(); + + void editTempo(QWidget *); + void editTimeSignature(QWidget *); + void editTransportTime(QWidget *); + void scrollTempo(int); + void panic(); + +private: + void loadPixmaps(); + void resetFonts(); + void resetFont(QWidget *); + void initModeMap(); + + //--------------- Data members --------------------------------- + + RosegardenTransport* m_transport; + + std::map<int, QPixmap> m_lcdList; + QPixmap m_lcdNegative; + + int m_lastTenHours; + int m_lastUnitHours; + int m_lastTenMinutes; + int m_lastUnitMinutes; + int m_lastTenSeconds; + int m_lastUnitSeconds; + int m_lastTenths; + int m_lastHundreths; + int m_lastThousandths; + int m_lastTenThousandths; + + bool m_lastNegative; + TimeDisplayMode m_lastMode; + TimeDisplayMode m_currentMode; + + int m_tenHours; + int m_unitHours; + int m_tenMinutes; + int m_unitMinutes; + int m_tenSeconds; + int m_unitSeconds; + int m_tenths; + int m_hundreths; + int m_thousandths; + int m_tenThousandths; + + tempoT m_tempo; + int m_numerator; + int m_denominator; + + int m_framesPerSecond; + int m_bitsPerFrame; + + QTimer *m_midiInTimer; + QTimer *m_midiOutTimer; + QTimer *m_clearMetronomeTimer; + + QPixmap m_panelOpen; + QPixmap m_panelClosed; + + void updateTimeDisplay(); + + QAccel *m_accelerators; + bool m_isExpanded; + + bool m_haveOriginalBackground; + bool m_isBackgroundSet; + QColor m_originalBackground; + + int m_sampleRate; + + std::map<std::string, TimeDisplayMode> m_modeMap; +}; + + + + + +} + +#endif diff --git a/src/gui/dialogs/TriggerSegmentDialog.cpp b/src/gui/dialogs/TriggerSegmentDialog.cpp new file mode 100644 index 0000000..a5064e1 --- /dev/null +++ b/src/gui/dialogs/TriggerSegmentDialog.cpp @@ -0,0 +1,181 @@ +/* -*- 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 "TriggerSegmentDialog.h" +#include <kapplication.h> + +#include "base/BaseProperties.h" +#include <klocale.h> +#include "misc/Strings.h" +#include "document/ConfigGroups.h" +#include "base/Composition.h" +#include "base/TriggerSegment.h" +#include <kcombobox.h> +#include <kconfig.h> +#include <kdialogbase.h> +#include <qcheckbox.h> +#include <qframe.h> +#include <qlabel.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> +#include <qlayout.h> + + +namespace Rosegarden +{ + +TriggerSegmentDialog::TriggerSegmentDialog(QWidget *parent, + Composition *composition) : + KDialogBase(parent, "triggersegmentdialog", true, i18n("Trigger Segment"), + Ok | Cancel, Ok), + m_composition(composition) +{ + QVBox *vbox = makeVBoxMainWidget(); + + QFrame *frame = new QFrame(vbox); + QGridLayout *layout = new QGridLayout(frame, 3, 2, 5, 5); + + QLabel *label = new QLabel(i18n("Trigger segment: "), frame); + layout->addWidget(label, 0, 0); + + m_segment = new KComboBox(frame); + layout->addWidget(m_segment, 0, 1); + + int n = 1; + for (Composition::triggersegmentcontaineriterator i = + m_composition->getTriggerSegments().begin(); + i != m_composition->getTriggerSegments().end(); ++i) { + m_segment->insertItem + (QString("%1. %2").arg(n++).arg(strtoqstr((*i)->getSegment()->getLabel()))); + } + + label = new QLabel(i18n("Perform with timing: "), frame); + layout->addWidget(label, 1, 0); + + m_adjustTime = new KComboBox(frame); + layout->addWidget(m_adjustTime, 1, 1); + + m_adjustTime->insertItem(i18n("As stored")); + m_adjustTime->insertItem(i18n("Truncate if longer than note")); + m_adjustTime->insertItem(i18n("End at same time as note")); + m_adjustTime->insertItem(i18n("Stretch or squash segment to note duration")); + + m_retune = new QCheckBox(i18n("Adjust pitch to note"), frame); + m_retune->setChecked(true); + + layout->addWidget(m_retune, 2, 1); + + setupFromConfig(); +} + +void +TriggerSegmentDialog::setupFromConfig() +{ + KConfig *config = kapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + + int seg = config->readNumEntry("triggersegmentlastornament", 0); + std::string timing = qstrtostr + (config->readEntry + ("triggersegmenttiming", + strtoqstr(BaseProperties::TRIGGER_SEGMENT_ADJUST_SQUISH))); + bool retune = config->readBoolEntry("triggersegmentretune", true); + + if (seg >= 0 && seg < m_segment->count()) + m_segment->setCurrentItem(seg); + + if (timing == BaseProperties::TRIGGER_SEGMENT_ADJUST_NONE) { + m_adjustTime->setCurrentItem(0); + } else if (timing == BaseProperties::TRIGGER_SEGMENT_ADJUST_SQUISH) { + m_adjustTime->setCurrentItem(3); + } else if (timing == BaseProperties::TRIGGER_SEGMENT_ADJUST_SYNC_START) { + m_adjustTime->setCurrentItem(1); + } else if (timing == BaseProperties::TRIGGER_SEGMENT_ADJUST_SYNC_END) { + m_adjustTime->setCurrentItem(2); + } + + m_retune->setChecked(retune); +} + +TriggerSegmentId +TriggerSegmentDialog::getId() const +{ + int ix = m_segment->currentItem(); + + for (Composition::triggersegmentcontaineriterator i = + m_composition->getTriggerSegments().begin(); + i != m_composition->getTriggerSegments().end(); ++i) { + + if (ix == 0) + return (*i)->getId(); + --ix; + } + + return 0; +} + +bool +TriggerSegmentDialog::getRetune() const +{ + return m_retune->isChecked(); +} + +std::string +TriggerSegmentDialog::getTimeAdjust() const +{ + int option = m_adjustTime->currentItem(); + + switch (option) { + + case 0: + return BaseProperties::TRIGGER_SEGMENT_ADJUST_NONE; + case 1: + return BaseProperties::TRIGGER_SEGMENT_ADJUST_SYNC_START; + case 2: + return BaseProperties::TRIGGER_SEGMENT_ADJUST_SYNC_END; + case 3: + return BaseProperties::TRIGGER_SEGMENT_ADJUST_SQUISH; + + default: + return BaseProperties::TRIGGER_SEGMENT_ADJUST_NONE; + } +} + +void +TriggerSegmentDialog::slotOk() +{ + KConfig *config = kapp->config(); + config->setGroup(GeneralOptionsConfigGroup); + + config->writeEntry("triggersegmenttiming", strtoqstr(getTimeAdjust())); + config->writeEntry("triggersegmentretune", m_retune->isChecked()); + config->writeEntry("triggersegmentlastornament", m_segment->currentItem()); + + accept(); +} + +} +#include "TriggerSegmentDialog.moc" diff --git a/src/gui/dialogs/TriggerSegmentDialog.h b/src/gui/dialogs/TriggerSegmentDialog.h new file mode 100644 index 0000000..3f74f45 --- /dev/null +++ b/src/gui/dialogs/TriggerSegmentDialog.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_TRIGGERSEGMENTDIALOG_H_ +#define _RG_TRIGGERSEGMENTDIALOG_H_ + +#include "base/TriggerSegment.h" +#include <string> +#include <kdialogbase.h> + + +class QWidget; +class QCheckBox; +class KComboBox; + + +namespace Rosegarden +{ + +class Composition; + + +class TriggerSegmentDialog : public KDialogBase +{ + Q_OBJECT + +public: + TriggerSegmentDialog(QWidget *parent, Composition *); + + TriggerSegmentId getId() const; + bool getRetune() const; + std::string getTimeAdjust() const; + +public slots: + void slotOk(); + +protected: + void setupFromConfig(); + + Composition *m_composition; + KComboBox *m_segment; + QCheckBox *m_retune; + KComboBox *m_adjustTime; +}; + + +} + +#endif diff --git a/src/gui/dialogs/TupletDialog.cpp b/src/gui/dialogs/TupletDialog.cpp new file mode 100644 index 0000000..ed1c583 --- /dev/null +++ b/src/gui/dialogs/TupletDialog.cpp @@ -0,0 +1,365 @@ +/* -*- 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 "TupletDialog.h" +#include <qlayout.h> + +#include <klocale.h> +#include "base/NotationTypes.h" +#include "gui/editors/notation/NotationStrings.h" +#include "gui/editors/notation/NotePixmapFactory.h" +#include <kcombobox.h> +#include <kdialogbase.h> +#include <qcheckbox.h> +#include <qframe.h> +#include <qgrid.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qobject.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +TupletDialog::TupletDialog(QWidget *parent, Note::Type defaultUnitType, + timeT maxDuration) : + KDialogBase(parent, 0, true, i18n("Tuplet"), Ok | Cancel | Help), + m_maxDuration(maxDuration) +{ + setHelp("nv-tuplets"); + QVBox *vbox = makeVBoxMainWidget(); + + QGroupBox *timingBox = new QGroupBox + (1, Horizontal, i18n("New timing for tuplet group"), vbox); + + if (m_maxDuration > 0) { + + // bit of a sanity check + if (maxDuration < Note(Note::Semiquaver).getDuration()) { + maxDuration = Note(Note::Semiquaver).getDuration(); + } + + Note::Type maxUnitType = + Note::getNearestNote(maxDuration / 2, 0).getNoteType(); + if (defaultUnitType > maxUnitType) + defaultUnitType = maxUnitType; + } + + QFrame *timingFrame = new QFrame(timingBox); + QGridLayout *timingLayout = new QGridLayout(timingFrame, 3, 3, 5, 5); + + timingLayout->addWidget(new QLabel(i18n("Play "), timingFrame), 0, 0); + + m_untupledCombo = new KComboBox(timingFrame); + timingLayout->addWidget(m_untupledCombo, 0, 1); + + m_unitCombo = new KComboBox(timingFrame); + timingLayout->addWidget(m_unitCombo, 0, 2); + + for (Note::Type t = Note::Shortest; t <= Note::Longest; ++t) { + Note note(t); + timeT duration(note.getDuration()); + if (maxDuration > 0 && (2 * duration > maxDuration)) + break; + timeT e; // error factor, ignore + m_unitCombo->insertItem(NotePixmapFactory::toQPixmap + (NotePixmapFactory::makeNoteMenuPixmap(duration, e)), + NotationStrings::makeNoteMenuLabel(duration, false, e, true)); + if (defaultUnitType == t) { + m_unitCombo->setCurrentItem(m_unitCombo->count() - 1); + } + } + + timingLayout->addWidget(new QLabel(i18n("in the time of "), timingFrame), 1, 0); + + m_tupledCombo = new KComboBox(timingFrame); + timingLayout->addWidget(m_tupledCombo, 1, 1); + + m_hasTimingAlready = new QCheckBox + (i18n("Timing is already correct: update display only"), timingFrame); + m_hasTimingAlready->setChecked(false); + timingLayout->addMultiCellWidget(m_hasTimingAlready, 2, 2, 0, 2); + + connect(m_hasTimingAlready, SIGNAL(clicked()), this, SLOT(slotHasTimingChanged())); + + updateUntupledCombo(); + updateTupledCombo(); + + m_timingDisplayBox = new QGroupBox + (1, Horizontal, i18n("Timing calculations"), vbox); + + QGrid *timingDisplayGrid = new QGrid(3, QGrid::Horizontal, m_timingDisplayBox); + + if (maxDuration > 0) { + + new QLabel(i18n("Selected region:"), timingDisplayGrid); + new QLabel("", timingDisplayGrid); + m_selectionDurationDisplay = new QLabel("x", timingDisplayGrid); + m_selectionDurationDisplay->setAlignment(int(QLabel::AlignVCenter | + QLabel::AlignRight)); + } else { + m_selectionDurationDisplay = 0; + } + + new QLabel(i18n("Group with current timing:"), timingDisplayGrid); + m_untupledDurationCalculationDisplay = new QLabel("x", timingDisplayGrid); + m_untupledDurationDisplay = new QLabel("x", timingDisplayGrid); + m_untupledDurationDisplay->setAlignment(int(QLabel::AlignVCenter | + QLabel::AlignRight)); + + new QLabel(i18n("Group with new timing:"), timingDisplayGrid); + m_tupledDurationCalculationDisplay = new QLabel("x", timingDisplayGrid); + m_tupledDurationDisplay = new QLabel("x", timingDisplayGrid); + m_tupledDurationDisplay->setAlignment(int(QLabel::AlignVCenter | + QLabel::AlignRight)); + + new QLabel(i18n("Gap created by timing change:"), timingDisplayGrid); + m_newGapDurationCalculationDisplay = new QLabel("x", timingDisplayGrid); + m_newGapDurationDisplay = new QLabel("x", timingDisplayGrid); + m_newGapDurationDisplay->setAlignment(int(QLabel::AlignVCenter | + QLabel::AlignRight)); + + if (maxDuration > 0) { + + new QLabel(i18n("Unchanged at end of selection:"), timingDisplayGrid); + m_unchangedDurationCalculationDisplay = new QLabel + ("x", timingDisplayGrid); + m_unchangedDurationDisplay = new QLabel("x", timingDisplayGrid); + m_unchangedDurationDisplay->setAlignment(int(QLabel::AlignVCenter | + QLabel::AlignRight)); + + } else { + m_unchangedDurationDisplay = 0; + } + + updateTimingDisplays(); + + QObject::connect(m_unitCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotUnitChanged(const QString &))); + + QObject::connect(m_untupledCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotUntupledChanged(const QString &))); + QObject::connect(m_untupledCombo, SIGNAL(textChanged(const QString &)), + this, SLOT(slotUntupledChanged(const QString &))); + + QObject::connect(m_tupledCombo, SIGNAL(activated(const QString &)), + this, SLOT(slotTupledChanged(const QString &))); + QObject::connect(m_tupledCombo, SIGNAL(textChanged(const QString &)), + this, SLOT(slotTupledChanged(const QString &))); +} + +void +TupletDialog::slotHasTimingChanged() +{ + updateUntupledCombo(); + updateTupledCombo(); + m_timingDisplayBox->setEnabled(!m_hasTimingAlready->isChecked()); +} + +Note::Type +TupletDialog::getUnitType() const +{ + return Note::Shortest + m_unitCombo->currentItem(); +} + +int +TupletDialog::getUntupledCount() const +{ + bool isNumeric = true; + int count = m_untupledCombo->currentText().toInt(&isNumeric); + if (count == 0 || !isNumeric) + return 1; + else + return count; +} + +int +TupletDialog::getTupledCount() const +{ + bool isNumeric = true; + int count = m_tupledCombo->currentText().toInt(&isNumeric); + if (count == 0 || !isNumeric) + return 1; + else + return count; +} + +bool +TupletDialog::hasTimingAlready() const +{ + return m_hasTimingAlready->isChecked(); +} + +void +TupletDialog::updateUntupledCombo() +{ + // Untupled combo can contain numbers up to the maximum + // duration divided by the unit duration. If there's no + // maximum, we'll have to put in some likely values and + // allow the user to edit it. Both the numerical combos + // should possibly be spinboxes, except I think I like + // being able to "suggest" a few values + + int maxValue = 12; + + if (m_maxDuration) { + if (m_hasTimingAlready->isChecked()) { + maxValue = (m_maxDuration * 2) / Note(getUnitType()).getDuration(); + } else { + maxValue = m_maxDuration / Note(getUnitType()).getDuration(); + } + } + + QString previousText = m_untupledCombo->currentText(); + if (previousText.toInt() == 0) { + if (maxValue < 3) + previousText = QString("%1").arg(maxValue); + else + previousText = "3"; + } + + m_untupledCombo->clear(); + bool setText = false; + + for (int i = 1; i <= maxValue; ++i) { + QString text = QString("%1").arg(i); + m_untupledCombo->insertItem(text); + if (m_hasTimingAlready->isChecked()) { + if (i == (m_maxDuration * 3) / (Note(getUnitType()).getDuration()*2)) { + m_untupledCombo->setCurrentItem(m_untupledCombo->count() - 1); + } + } else if (text == previousText) { + m_untupledCombo->setCurrentItem(m_untupledCombo->count() - 1); + setText = true; + } + } + + if (!setText) { + m_untupledCombo->setEditText(previousText); + } +} + +void +TupletDialog::updateTupledCombo() +{ + // should contain all positive integers less than the + // largest value in the untupled combo. In principle + // we can support values larger, but we can't quite + // do the tupleting transformation yet + + int untupled = getUntupledCount(); + + QString previousText = m_tupledCombo->currentText(); + if (previousText.toInt() == 0 || + previousText.toInt() > untupled) { + if (untupled < 2) + previousText = QString("%1").arg(untupled); + else + previousText = "2"; + } + + m_tupledCombo->clear(); + + for (int i = 1; i < untupled; ++i) { + QString text = QString("%1").arg(i); + m_tupledCombo->insertItem(text); + if (m_hasTimingAlready->isChecked()) { + if (i == m_maxDuration / Note(getUnitType()).getDuration()) { + m_tupledCombo->setCurrentItem(m_tupledCombo->count() - 1); + } + } else if (text == previousText) { + m_tupledCombo->setCurrentItem(m_tupledCombo->count() - 1); + } + } +} + +void +TupletDialog::updateTimingDisplays() +{ + timeT unitDuration = Note(getUnitType()).getDuration(); + + int untupledCount = getUntupledCount(); + int tupledCount = getTupledCount(); + + timeT untupledDuration = unitDuration * untupledCount; + timeT tupledDuration = unitDuration * tupledCount; + + if (m_selectionDurationDisplay) { + m_selectionDurationDisplay->setText(QString("%1").arg(m_maxDuration)); + } + + m_untupledDurationCalculationDisplay->setText + (QString(" %1 x %2 = ").arg(untupledCount).arg(unitDuration)); + m_untupledDurationDisplay->setText + (QString("%1").arg(untupledDuration)); + + m_tupledDurationCalculationDisplay->setText + (QString(" %1 x %2 = ").arg(tupledCount).arg(unitDuration)); + m_tupledDurationDisplay->setText + (QString("%1").arg(tupledDuration)); + + m_newGapDurationCalculationDisplay->setText + (QString(" %1 - %2 = ").arg(untupledDuration).arg(tupledDuration)); + m_newGapDurationDisplay->setText + (QString("%1").arg(untupledDuration - tupledDuration)); + + if (m_selectionDurationDisplay && m_unchangedDurationDisplay) { + if (m_maxDuration != untupledDuration) { + m_unchangedDurationCalculationDisplay->setText + (QString(" %1 - %2 = ").arg(m_maxDuration).arg(untupledDuration)); + } else { + m_unchangedDurationCalculationDisplay->setText(""); + } + m_unchangedDurationDisplay->setText + (QString("%1").arg(m_maxDuration - untupledDuration)); + } +} + +void +TupletDialog::slotUnitChanged(const QString &) +{ + updateUntupledCombo(); + updateTupledCombo(); + updateTimingDisplays(); +} + +void +TupletDialog::slotUntupledChanged(const QString &) +{ + updateTupledCombo(); + updateTimingDisplays(); +} + +void +TupletDialog::slotTupledChanged(const QString &) +{ + updateTimingDisplays(); +} + +} +#include "TupletDialog.moc" diff --git a/src/gui/dialogs/TupletDialog.h b/src/gui/dialogs/TupletDialog.h new file mode 100644 index 0000000..bc7252b --- /dev/null +++ b/src/gui/dialogs/TupletDialog.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_TUPLETDIALOG_H_ +#define _RG_TUPLETDIALOG_H_ + +#include "base/NotationTypes.h" +#include <kdialogbase.h> +#include "base/Event.h" + + +class QWidget; +class QString; +class QLabel; +class QGroupBox; +class QCheckBox; +class KComboBox; + + +namespace Rosegarden +{ + + + +class TupletDialog : public KDialogBase +{ + Q_OBJECT + +public: + TupletDialog(QWidget *parent, + Note::Type defaultUnitType, + timeT maxDuration = 0); + + Note::Type getUnitType() const; + int getUntupledCount() const; + int getTupledCount() const; + bool hasTimingAlready() const; + +public slots: + void slotUnitChanged(const QString &); + void slotUntupledChanged(const QString &); + void slotTupledChanged(const QString &); + void slotHasTimingChanged(); + +protected: + + void updateUntupledCombo(); + void updateTupledCombo(); + void updateTimingDisplays(); + + //--------------- Data members --------------------------------- + + KComboBox *m_unitCombo; + KComboBox *m_untupledCombo; + KComboBox *m_tupledCombo; + + QCheckBox *m_hasTimingAlready; + + QGroupBox *m_timingDisplayBox; + QLabel *m_selectionDurationDisplay; + QLabel *m_untupledDurationCalculationDisplay; + QLabel *m_untupledDurationDisplay; + QLabel *m_tupledDurationCalculationDisplay; + QLabel *m_tupledDurationDisplay; + QLabel *m_newGapDurationCalculationDisplay; + QLabel *m_newGapDurationDisplay; + QLabel *m_unchangedDurationCalculationDisplay; + QLabel *m_unchangedDurationDisplay; + + timeT m_maxDuration; +}; + + + +} + +#endif diff --git a/src/gui/dialogs/UnusedAudioSelectionDialog.cpp b/src/gui/dialogs/UnusedAudioSelectionDialog.cpp new file mode 100644 index 0000000..0a44168 --- /dev/null +++ b/src/gui/dialogs/UnusedAudioSelectionDialog.cpp @@ -0,0 +1,92 @@ +/* -*- 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 "UnusedAudioSelectionDialog.h" + +#include <klocale.h> +#include <kdialogbase.h> +#include <klistview.h> +#include <qfileinfo.h> +#include <qlabel.h> +#include <qlistview.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +UnusedAudioSelectionDialog::UnusedAudioSelectionDialog(QWidget *parent, + QString introductoryText, + std::vector<QString> fileNames, + bool offerCancel) : + KDialogBase(parent, 0, true, i18n("Select Unused Audio Files"), (offerCancel ? (Ok | Cancel) : Ok)) +{ + QVBox *vbox = makeVBoxMainWidget(); + new QLabel(introductoryText, vbox); + + m_listView = new KListView(vbox); + + m_listView->addColumn(i18n("File name")); + m_listView->addColumn(i18n("File size")); + m_listView->addColumn(i18n("Last modified date")); + + for (unsigned int i = 0; i < fileNames.size(); ++i) { + QString fileName = fileNames[i]; + QFileInfo info(fileName); + QString fileSize = i18n(" (not found) "); + QString fileDate; + if (info.exists()) { + fileSize = QString(" %1 ").arg(info.size()); + fileDate = QString(" %1 ").arg(info.lastModified().toString()); + } + QListViewItem *item = new KListViewItem + (m_listView, fileName, fileSize, fileDate); + } + + m_listView->setSelectionMode(QListView::Multi); +} + +std::vector<QString> +UnusedAudioSelectionDialog::getSelectedAudioFileNames() const +{ + std::vector<QString> selectedNames; + + QListViewItem *item = m_listView->firstChild(); + + while (item) { + + if (m_listView->isSelected(item)) { + selectedNames.push_back(item->text(0)); + } + + item = item->nextSibling(); + } + + return selectedNames; +} + +} diff --git a/src/gui/dialogs/UnusedAudioSelectionDialog.h b/src/gui/dialogs/UnusedAudioSelectionDialog.h new file mode 100644 index 0000000..e11301a --- /dev/null +++ b/src/gui/dialogs/UnusedAudioSelectionDialog.h @@ -0,0 +1,62 @@ + +/* -*- 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_UNUSEDAUDIOSELECTIONDIALOG_H_ +#define _RG_UNUSEDAUDIOSELECTIONDIALOG_H_ + +#include <kdialogbase.h> +#include <qstring.h> +#include <vector> + + +class QWidget; +class QListView; + + +namespace Rosegarden +{ + + + +class UnusedAudioSelectionDialog : public KDialogBase +{ +public: + UnusedAudioSelectionDialog(QWidget *, + QString introductoryText, + std::vector<QString> fileNames, + bool offerCancel = true); + + std::vector<QString> getSelectedAudioFileNames() const; + +protected: + QListView *m_listView; +}; + + + + +} + +#endif diff --git a/src/gui/dialogs/UseOrnamentDialog.cpp b/src/gui/dialogs/UseOrnamentDialog.cpp new file mode 100644 index 0000000..971f170 --- /dev/null +++ b/src/gui/dialogs/UseOrnamentDialog.cpp @@ -0,0 +1,264 @@ +/* -*- 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 "UseOrnamentDialog.h" +#include <qlayout.h> +#include <kapplication.h> + +#include "base/BaseProperties.h" +#include <klocale.h> +#include "misc/Strings.h" +#include "document/ConfigGroups.h" +#include "base/Composition.h" +#include "base/NotationTypes.h" +#include "base/TriggerSegment.h" +#include "gui/editors/notation/NotePixmapFactory.h" +#include <kcombobox.h> +#include <kconfig.h> +#include <kdialogbase.h> +#include <qcheckbox.h> +#include <qframe.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qstring.h> +#include <qvbox.h> +#include <qwidget.h> + + +namespace Rosegarden +{ + +UseOrnamentDialog::UseOrnamentDialog(QWidget *parent, + Composition *composition) : + KDialogBase(parent, "useornamentdialog", true, i18n("Use Ornament"), + Ok | Cancel, Ok), + m_composition(composition) +{ + QVBox *vbox = makeVBoxMainWidget(); + QLabel *label; + + QGroupBox *notationBox = new QGroupBox(1, Horizontal, i18n("Notation"), vbox); + + QFrame *frame = new QFrame(notationBox); + QGridLayout *layout = new QGridLayout(frame, 4, 1, 5, 5); + + label = new QLabel(i18n("Display as: "), frame); + layout->addWidget(label, 0, 0); + + m_mark = new KComboBox(frame); + layout->addWidget(m_mark, 0, 1); + + m_marks.push_back(Marks::Trill); + m_marks.push_back(Marks::LongTrill); + m_marks.push_back(Marks::TrillLine); + m_marks.push_back(Marks::Turn); + m_marks.push_back(Marks::Mordent); + m_marks.push_back(Marks::MordentInverted); + m_marks.push_back(Marks::MordentLong); + m_marks.push_back(Marks::MordentLongInverted); + + const QString markLabels[] = { + i18n("Trill"), i18n("Trill with line"), i18n("Trill line only"), + i18n("Turn"), i18n("Mordent"), i18n("Inverted mordent"), + i18n("Long mordent"), i18n("Long inverted mordent"), + }; + + for (size_t i = 0; i < m_marks.size(); ++i) { + m_mark->insertItem(NotePixmapFactory::toQPixmap + (NotePixmapFactory::makeMarkMenuPixmap(m_marks[i])), + markLabels[i]); + } + m_mark->insertItem(i18n("Text mark")); + + connect(m_mark, SIGNAL(activated(int)), this, SLOT(slotMarkChanged(int))); + + m_textLabel = new QLabel(i18n(" Text: "), frame); + layout->addWidget(m_textLabel, 0, 2); + + m_text = new QLineEdit(frame); + layout->addWidget(m_text, 0, 3); + + QGroupBox *performBox = new QGroupBox(1, Horizontal, i18n("Performance"), vbox); + + frame = new QFrame(performBox); + layout = new QGridLayout(frame, 3, 2, 5, 5); + + label = new QLabel(i18n("Perform using triggered segment: "), frame); + layout->addWidget(label, 0, 0); + + m_ornament = new KComboBox(frame); + layout->addWidget(m_ornament, 0, 1); + + int n = 1; + for (Composition::triggersegmentcontaineriterator i = + m_composition->getTriggerSegments().begin(); + i != m_composition->getTriggerSegments().end(); ++i) { + m_ornament->insertItem + (QString("%1. %2").arg(n++).arg(strtoqstr((*i)->getSegment()->getLabel()))); + } + + label = new QLabel(i18n("Perform with timing: "), frame); + layout->addWidget(label, 1, 0); + + m_adjustTime = new KComboBox(frame); + layout->addWidget(m_adjustTime, 1, 1); + + m_adjustTime->insertItem(i18n("As stored")); + m_adjustTime->insertItem(i18n("Truncate if longer than note")); + m_adjustTime->insertItem(i18n("End at same time as note")); + m_adjustTime->insertItem(i18n("Stretch or squash segment to note duration")); + + m_retune = new QCheckBox(i18n("Adjust pitch to note"), frame); + m_retune->setChecked(true); + + layout->addWidget(m_retune, 2, 1); + + setupFromConfig(); +} + +void +UseOrnamentDialog::setupFromConfig() +{ + KConfig *config = kapp->config(); + config->setGroup(NotationViewConfigGroup); + + Mark mark = qstrtostr(config->readEntry("useornamentmark", "trill")); + int seg = config->readNumEntry("useornamentlastornament", 0); + std::string timing = qstrtostr + (config->readEntry + ("useornamenttiming", + strtoqstr(BaseProperties::TRIGGER_SEGMENT_ADJUST_SQUISH))); + bool retune = config->readBoolEntry("useornamentretune", true); + + size_t i = 0; + for (i = 0; i < m_marks.size(); ++i) { + if (mark == m_marks[i]) { + m_mark->setCurrentItem(i); + m_text->setEnabled(false); + break; + } + } + if (i >= m_marks.size()) { + m_mark->setCurrentItem(m_marks.size()); + m_text->setEnabled(true); + m_text->setText(strtoqstr(Marks::getTextFromMark(mark))); + } + + if (seg >= 0 && seg < m_ornament->count()) + m_ornament->setCurrentItem(seg); + + if (timing == BaseProperties::TRIGGER_SEGMENT_ADJUST_NONE) { + m_adjustTime->setCurrentItem(0); + } else if (timing == BaseProperties::TRIGGER_SEGMENT_ADJUST_SQUISH) { + m_adjustTime->setCurrentItem(3); + } else if (timing == BaseProperties::TRIGGER_SEGMENT_ADJUST_SYNC_START) { + m_adjustTime->setCurrentItem(1); + } else if (timing == BaseProperties::TRIGGER_SEGMENT_ADJUST_SYNC_END) { + m_adjustTime->setCurrentItem(2); + } + + m_retune->setChecked(retune); +} + +TriggerSegmentId +UseOrnamentDialog::getId() const +{ + int ix = m_ornament->currentItem(); + + for (Composition::triggersegmentcontaineriterator i = + m_composition->getTriggerSegments().begin(); + i != m_composition->getTriggerSegments().end(); ++i) { + + if (ix == 0) + return (*i)->getId(); + --ix; + } + + return 0; +} + +Mark +UseOrnamentDialog::getMark() const +{ + if (int(m_marks.size()) > m_mark->currentItem()) + return m_marks[m_mark->currentItem()]; + else + return Marks::getTextMark(qstrtostr(m_text->text())); +} + +bool +UseOrnamentDialog::getRetune() const +{ + return m_retune->isChecked(); +} + +std::string +UseOrnamentDialog::getTimeAdjust() const +{ + int option = m_adjustTime->currentItem(); + + switch (option) { + + case 0: + return BaseProperties::TRIGGER_SEGMENT_ADJUST_NONE; + case 1: + return BaseProperties::TRIGGER_SEGMENT_ADJUST_SYNC_START; + case 2: + return BaseProperties::TRIGGER_SEGMENT_ADJUST_SYNC_END; + case 3: + return BaseProperties::TRIGGER_SEGMENT_ADJUST_SQUISH; + + default: + return BaseProperties::TRIGGER_SEGMENT_ADJUST_NONE; + } +} + +void +UseOrnamentDialog::slotMarkChanged(int i) +{ + if (i == 2) { + m_text->setEnabled(true); + } else { + m_text->setEnabled(false); + } +} + +void +UseOrnamentDialog::slotOk() +{ + KConfig *config = kapp->config(); + config->setGroup(NotationViewConfigGroup); + + config->writeEntry("useornamentmark", strtoqstr(getMark())); + config->writeEntry("useornamenttiming", strtoqstr(getTimeAdjust())); + config->writeEntry("useornamentretune", m_retune->isChecked()); + config->writeEntry("useornamentlastornament", m_ornament->currentItem()); + + accept(); +} + +} +#include "UseOrnamentDialog.moc" diff --git a/src/gui/dialogs/UseOrnamentDialog.h b/src/gui/dialogs/UseOrnamentDialog.h new file mode 100644 index 0000000..d721329 --- /dev/null +++ b/src/gui/dialogs/UseOrnamentDialog.h @@ -0,0 +1,82 @@ + +/* -*- 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_USEORNAMENTDIALOG_H_ +#define _RG_USEORNAMENTDIALOG_H_ + +#include "base/TriggerSegment.h" +#include "base/NotationTypes.h" +#include <string> +#include <kdialogbase.h> +#include <vector> + + +class QWidget; +class QLineEdit; +class QLabel; +class QCheckBox; +class KComboBox; + + +namespace Rosegarden +{ + +class Composition; + + +class UseOrnamentDialog : public KDialogBase +{ + Q_OBJECT + +public: + UseOrnamentDialog(QWidget *parent, Composition *); + + TriggerSegmentId getId() const; + Mark getMark() const; + bool getRetune() const; + std::string getTimeAdjust() const; + +public slots: + void slotOk(); + void slotMarkChanged(int); + +protected: + void setupFromConfig(); + + std::vector<Mark> m_marks; + + Composition *m_composition; + KComboBox *m_ornament; + KComboBox *m_mark; + QLabel *m_textLabel; + QLineEdit *m_text; + QCheckBox *m_retune; + KComboBox *m_adjustTime; +}; + + +} + +#endif |