amuse/Editor/MainWindow.hpp

308 lines
10 KiB
C++
Raw Normal View History

2018-10-07 03:40:25 +00:00
#pragma once
2018-03-15 00:25:29 +00:00
#include <QMainWindow>
#include <QUndoStack>
2018-07-17 04:48:38 +00:00
#include <QProgressDialog>
#include <QThread>
2018-07-18 07:39:26 +00:00
#include <QStyledItemDelegate>
#include <QSortFilterProxyModel>
#include <QLinkedList>
2018-08-30 08:16:37 +00:00
#include <QFileDialog>
#include "ui_MainWindow.h"
#include "amuse/Engine.hpp"
#include "amuse/BooBackend.hpp"
#include "boo/audiodev/IAudioVoiceEngine.hpp"
#include "ProjectModel.hpp"
2018-07-18 07:39:26 +00:00
#include "EditorWidget.hpp"
2018-07-28 04:34:29 +00:00
#include "MIDIReader.hpp"
2018-08-16 06:26:44 +00:00
#include "StudioSetupWidget.hpp"
2018-07-28 04:34:29 +00:00
#define MaxRecentFiles 4
namespace Ui {
class MainWindow;
}
2018-03-15 00:25:29 +00:00
2018-07-18 07:39:26 +00:00
class MainWindow;
class SongGroupEditor;
class SoundGroupEditor;
class SoundMacroEditor;
class ADSREditor;
class CurveEditor;
class KeymapEditor;
class LayersEditor;
2018-07-29 03:37:06 +00:00
class SampleEditor;
2018-08-19 00:28:52 +00:00
enum BackgroundTaskId
{
TaskOpen,
TaskImport,
TaskExport,
TaskReloadSamples
};
2018-07-17 04:48:38 +00:00
class BackgroundTask : public QObject
{
Q_OBJECT
2018-08-19 00:28:52 +00:00
int m_id;
2018-07-17 04:48:38 +00:00
std::function<void(BackgroundTask&)> m_task;
UIMessenger m_threadMessenger;
bool m_cancelled = false;
public:
2018-08-19 00:28:52 +00:00
explicit BackgroundTask(int id, std::function<void(BackgroundTask&)>&& task)
: m_id(id), m_task(std::move(task)), m_threadMessenger(this) {}
2018-07-17 04:48:38 +00:00
bool isCanceled() const { QCoreApplication::processEvents(); return m_cancelled; }
UIMessenger& uiMessenger() { return m_threadMessenger; }
signals:
void setMinimum(int minimum);
void setMaximum(int maximum);
void setValue(int value);
void setLabelText(const QString& text);
2018-08-19 00:28:52 +00:00
void finished(int id);
2018-07-17 04:48:38 +00:00
public slots:
2018-08-19 00:28:52 +00:00
void run() { m_task(*this); emit finished(m_id); }
2018-07-17 04:48:38 +00:00
void cancel() { m_cancelled = true; }
};
2018-07-18 07:39:26 +00:00
class TreeDelegate : public QStyledItemDelegate
{
Q_OBJECT
MainWindow& m_window;
public:
explicit TreeDelegate(MainWindow& window, QObject* parent = Q_NULLPTR)
: QStyledItemDelegate(parent), m_window(window) {}
bool editorEvent(QEvent *event,
QAbstractItemModel *model,
const QStyleOptionViewItem &option,
const QModelIndex &index);
public slots:
void doExportGroup();
void doFindUsages();
void doCut();
void doCopy();
void doPaste();
void doDuplicate();
void doDelete();
void doRename();
2018-07-18 07:39:26 +00:00
};
class MainWindow : public QMainWindow
2018-03-15 00:25:29 +00:00
{
2018-07-28 04:34:29 +00:00
friend class MIDIReader;
friend class ProjectModel;
friend class GroupNodeUndoCommand;
friend class TreeDelegate;
Q_OBJECT
Ui::MainWindow m_ui;
QAction* m_goBack;
QAction* m_goForward;
QLinkedList<ProjectModel::INode*> m_navList;
QLinkedList<ProjectModel::INode*>::iterator m_navIt;
2018-07-28 04:34:29 +00:00
QAction* m_clearRecentFileAct;
QAction* m_recentFileActs[MaxRecentFiles];
2018-07-18 07:39:26 +00:00
TreeDelegate m_treeDelegate;
2018-07-17 04:48:38 +00:00
UIMessenger m_mainMessenger;
ProjectModel* m_projectModel = nullptr;
2018-07-18 07:39:26 +00:00
QWidget* m_faceSvg;
SongGroupEditor* m_songGroupEditor = nullptr;
SoundGroupEditor* m_soundGroupEditor = nullptr;
SoundMacroEditor* m_soundMacroEditor = nullptr;
ADSREditor* m_adsrEditor = nullptr;
CurveEditor* m_curveEditor = nullptr;
KeymapEditor* m_keymapEditor = nullptr;
LayersEditor* m_layersEditor = nullptr;
2018-07-29 03:37:06 +00:00
SampleEditor* m_sampleEditor = nullptr;
2018-08-16 06:26:44 +00:00
StudioSetupWidget* m_studioSetup = nullptr;
2018-09-08 21:34:01 +00:00
QFileDialog m_openDirectoryDialog;
QFileDialog m_openFileDialog;
QFileDialog m_newFileDialog;
std::unique_ptr<boo::IAudioVoiceEngine> m_voxEngine;
2018-07-28 04:34:29 +00:00
std::unique_ptr<VoiceAllocator> m_voxAllocator;
std::unique_ptr<amuse::Engine> m_engine;
2018-07-29 03:37:06 +00:00
amuse::ObjToken<amuse::Voice> m_lastSound;
amuse::ObjToken<amuse::Sequencer> m_interactiveSeq;
2018-07-28 04:34:29 +00:00
int m_velocity = 90;
float m_pitch = 0.f;
2018-07-29 03:37:06 +00:00
int8_t m_ctrlVals[128] = {};
2018-08-19 00:28:52 +00:00
float m_auxAVol = 0.f;
float m_auxBVol = 0.f;
2018-07-28 04:34:29 +00:00
bool m_uiDisabled = false;
bool m_clipboardAmuseData = false;
QUndoStack* m_undoStack;
QMetaObject::Connection m_cutConn;
QMetaObject::Connection m_copyConn;
QMetaObject::Connection m_pasteConn;
QMetaObject::Connection m_deleteConn;
QMetaObject::Connection m_canEditConn;
2018-07-17 04:48:38 +00:00
BackgroundTask* m_backgroundTask = nullptr;
QProgressDialog* m_backgroundDialog = nullptr;
QThread m_backgroundThread;
2018-08-28 03:48:53 +00:00
uint64_t m_timerFireCount = 0;
2018-08-30 08:16:37 +00:00
int m_peakVoices = 0;
2018-08-28 03:48:53 +00:00
2018-07-17 04:48:38 +00:00
void connectMessenger(UIMessenger* messenger, Qt::ConnectionType type);
2018-07-29 03:37:06 +00:00
void updateWindowTitle();
2018-07-28 04:34:29 +00:00
void updateRecentFileActions();
void updateNavigationButtons();
bool setProjectPath(const QString& path);
void refreshAudioIO();
void refreshMIDIIO();
2018-07-28 04:34:29 +00:00
void timerEvent(QTimerEvent* ev);
void setSustain(bool sustain);
void keyPressEvent(QKeyEvent* ev);
void keyReleaseEvent(QKeyEvent* ev);
2018-08-19 00:28:52 +00:00
void startBackgroundTask(int id, const QString& windowTitle, const QString& label,
2018-07-17 04:48:38 +00:00
std::function<void(BackgroundTask&)>&& task);
bool _setEditor(EditorWidget* widget, bool appendNav = true);
2018-07-18 07:39:26 +00:00
public:
explicit MainWindow(QWidget* parent = Q_NULLPTR);
~MainWindow();
2018-07-28 04:34:29 +00:00
bool openProject(const QString& path);
bool openEditor(ProjectModel::SongGroupNode* node, bool appendNav = true);
bool openEditor(ProjectModel::SoundGroupNode* node, bool appendNav = true);
bool openEditor(ProjectModel::SoundMacroNode* node, bool appendNav = true);
bool openEditor(ProjectModel::ADSRNode* node, bool appendNav = true);
bool openEditor(ProjectModel::CurveNode* node, bool appendNav = true);
bool openEditor(ProjectModel::KeymapNode* node, bool appendNav = true);
bool openEditor(ProjectModel::LayersNode* node, bool appendNav = true);
bool openEditor(ProjectModel::SampleNode* node, bool appendNav = true);
bool openEditor(ProjectModel::INode* node, bool appendNav = true);
2018-07-18 07:39:26 +00:00
void closeEditor();
2018-07-28 04:34:29 +00:00
ProjectModel::INode* getEditorNode() const;
2018-08-03 03:45:48 +00:00
EditorWidget* getEditorWidget() const;
2018-07-31 08:04:43 +00:00
amuse::ObjToken<amuse::Voice> startEditorVoice(uint8_t key, uint8_t vel);
2018-08-10 06:19:23 +00:00
amuse::ObjToken<amuse::Voice> startSFX(amuse::GroupId groupId, amuse::SFXId sfxId);
amuse::ObjToken<amuse::Sequencer> startSong(amuse::GroupId groupId, amuse::SongId songId,
const unsigned char* arrData);
void pushUndoCommand(EditorUndoCommand* cmd);
2018-08-07 07:09:23 +00:00
void updateFocus();
2018-07-28 04:34:29 +00:00
void aboutToDeleteNode(ProjectModel::INode* node);
2018-08-30 08:19:53 +00:00
bool askAboutSave();
2018-08-16 06:26:44 +00:00
void closeEvent(QCloseEvent* ev);
void showEvent(QShowEvent* ev);
2018-07-28 04:34:29 +00:00
2018-08-10 06:19:23 +00:00
QString getGroupName(ProjectModel::GroupNode* group) const;
ProjectModel::GroupNode* getSelectedGroupNode() const;
QString getSelectedGroupName() const;
void _recursiveExpandOutline(const QModelIndex& filterIndex) const;
2018-08-10 06:19:23 +00:00
void recursiveExpandAndSelectOutline(const QModelIndex& index) const;
2018-07-28 04:34:29 +00:00
ProjectModel* projectModel() const { return m_projectModel; }
UIMessenger& uiMessenger() { return m_mainMessenger; }
void setItemEditFlags(AmuseItemEditFlags flags);
void setItemNewEnabled(bool enabled);
AmuseItemEditFlags outlineEditFlags();
bool isUiDisabled() const { return m_uiDisabled; }
void findUsages(ProjectModel::INode* node);
public slots:
void newAction();
2018-08-30 08:16:37 +00:00
void _newAction(const QString& path);
void openAction();
2018-08-30 08:16:37 +00:00
void _openAction(const QString& path);
2018-07-28 04:34:29 +00:00
void openRecentFileAction();
void clearRecentFilesAction();
void saveAction();
void revertAction();
2018-07-29 03:37:06 +00:00
void reloadSampleDataAction();
void importAction();
2018-08-30 08:16:37 +00:00
void _importAction(const QString& path);
2018-08-10 08:11:08 +00:00
void importSongsAction();
2018-08-30 08:16:37 +00:00
void _importSongsAction(const QString& path);
void exportAction();
void importHeadersAction();
2018-08-30 08:16:37 +00:00
void _importHeadersAction(const QString& path);
void exportHeadersAction();
2018-08-30 08:16:37 +00:00
void _exportHeadersAction(const QString& path);
2018-07-18 07:39:26 +00:00
void newSubprojectAction();
void newSFXGroupAction();
void newSongGroupAction();
void newSoundMacroAction();
2018-07-18 07:39:26 +00:00
void newADSRAction();
void newCurveAction();
void newKeymapAction();
void newLayersAction();
void goForward();
void goBack();
void aboutToShowAudioIOMenu();
void aboutToShowMIDIIOMenu();
void setAudioIO();
2018-08-19 00:28:52 +00:00
void setMIDIIO(bool checked);
2018-08-19 20:05:39 +00:00
void aboutAmuseAction();
void aboutQtAction();
2018-07-28 04:34:29 +00:00
void notePressed(int key);
void noteReleased();
void velocityChanged(int vel);
void modulationChanged(int mod);
void pitchChanged(int pitch);
void killSounds();
2018-08-16 06:26:44 +00:00
void fxPressed();
void volumeChanged(int vol);
2018-08-19 00:28:52 +00:00
void auxAChanged(int vol);
void auxBChanged(int vol);
2018-07-28 04:34:29 +00:00
void outlineCutAction();
void outlineCopyAction();
void outlinePasteAction();
void outlineDeleteAction();
void onFocusChanged(QWidget* old, QWidget* now);
void onClipboardChanged();
2018-08-09 07:42:17 +00:00
void outlineItemActivated(const QModelIndex& index);
2018-07-28 04:34:29 +00:00
void onOutlineSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);
void onTextSelect();
void onTextDelete();
2018-08-16 06:26:44 +00:00
void cleanChanged(bool clean);
void studioSetupHidden();
void studioSetupShown();
2018-08-19 00:28:52 +00:00
void onBackgroundTaskFinished(int id);
2018-07-17 04:48:38 +00:00
QMessageBox::StandardButton msgInformation(const QString &title,
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
2018-08-28 03:48:53 +00:00
int msgQuestion(const QString &title,
const QString& text,
const QString& button0Text,
const QString& button1Text = QString(),
const QString& button2Text = QString(),
int defaultButtonNumber = 0,
int escapeButtonNumber = -1);
2018-07-17 04:48:38 +00:00
QMessageBox::StandardButton msgQuestion(const QString &title,
const QString &text, QMessageBox::StandardButtons buttons =
QMessageBox::StandardButtons(QMessageBox::Yes | QMessageBox::No),
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
QMessageBox::StandardButton msgWarning(const QString &title,
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
QMessageBox::StandardButton msgCritical(const QString &title,
const QString &text, QMessageBox::StandardButtons buttons = QMessageBox::Ok,
QMessageBox::StandardButton defaultButton = QMessageBox::NoButton);
2018-03-15 00:25:29 +00:00
};