diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3845ad7fbcb7a03dfd7675a2eb4fabc9f2341592..36a36974f155f166e12c3105fa706ff54ddf2bfa 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -83,6 +83,7 @@ set(NOOTKA_SRC main/thelpdialogbase.cpp main/texamhelp.cpp main/ttiphandler.cpp + main/tmainscoreobject.cpp dialogs/tdialogloaderobject.cpp dialogs/tlevelcreatoritem.cpp diff --git a/src/main.cpp b/src/main.cpp index 2e62dd598eb5f0872a04a9093ed3ab1abc52ec5b..b8df76359c6ebfdf8fbc379cfdc8a7c988017226 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,6 +33,7 @@ #include <tnootkaqml.h> #include <tsound.h> #include "main/tnameitem.h" +#include "main/tmainscoreobject.h" #include "dialogs/tdialogloaderobject.h" #if defined (Q_OS_ANDROID) @@ -147,11 +148,12 @@ int main(int argc, char *argv[]) GLOB->isFirstRun = false; } qmlRegisterType<TnameItem>("Nootka.Main", 1, 0, "TnameItem"); + qmlRegisterType<TmainScoreObject>("Nootka.Main", 1, 0, "TmainScoreObject"); qmlRegisterType<TdialogLoaderObject>("Nootka.Dialogs", 1, 0, "TdialogObject"); e->load(QUrl(QStringLiteral("qrc:/MainWindow.qml"))); // #if defined (Q_OS_ANDROID) -// w->showFullScreen(); // TODO +// w->showFullScreen(); // TODO seems to be not necessary // #endif if (firstTime) { diff --git a/src/main/tmainscoreobject.cpp b/src/main/tmainscoreobject.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f14146985c1d72b9721962803e8a45c7192e5a15 --- /dev/null +++ b/src/main/tmainscoreobject.cpp @@ -0,0 +1,117 @@ +/*************************************************************************** + * Copyright (C) 2017 by Tomasz Bojczuk * + * seelook@gmail.com * + * * + * 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 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "tmainscoreobject.h" +#include <score/tscoreobject.h> +#include <taction.h> +#include <tglobals.h> +#include <qtr.h> +#include <tnootkaqml.h> +#include <tsound.h> + +#include <QtCore/qdebug.h> + + +TmainScoreObject* TmainScoreObject::m_instance = nullptr; + + +TmainScoreObject::TmainScoreObject(QObject* parent) : + QObject(parent) +{ + if (m_instance) { + qDebug() << "TmainScoreObject instance already exists!"; + return; + } + m_instance = this; + + m_playAct = new Taction(qTR("QShortcut", "Play"), QStringLiteral("playMelody"), this); + m_recModeAct = new Taction(QString(), QString(), this); + m_showNamesAct = new Taction(tr("Show note names"), QString(), this); + m_showNamesAct->setCheckable(true); + m_showNamesAct->setChecked(GLOB->namesOnScore()); + + m_extraAccidsAct = new Taction(tr("Additional accidentals"), QString(), this); + m_extraAccidsAct->setCheckable(true); +// m_showNamesAct->setChecked(GLOB->????); + + m_deleteLastAct = new Taction(tr("Delete note"), QStringLiteral("delete"), this); + m_clearScoreAct = new Taction(tr("Delete all notes"), QStringLiteral("clear-score"), this); + + m_zoomOutAct = new Taction(tr("Zoom score out"), QStringLiteral("zoom-out"), this); + m_zoomInAct = new Taction(tr("Zoom score in"), QStringLiteral("zoom-in"), this); + + m_openXmlAct = new Taction(qTR("QShortcut", "Open"), QStringLiteral("open"), this); + connect(m_openXmlAct, &Taction::triggered, this, &TmainScoreObject::openXmlActSlot); + + m_saveXmlAct = new Taction(qTR("QShortcut", "Save"), QStringLiteral("save"), this); + connect(m_saveXmlAct, &Taction::triggered, this, &TmainScoreObject::saveXmlActSlot); + + isExamChangedSlot(); +} + + +TmainScoreObject::~TmainScoreObject() +{ + m_instance = nullptr; +} + + +void TmainScoreObject::setScoreObject(TscoreObject* scoreObj) { + if (m_scoreObject) { + qDebug() << "[TmainScoreObject] score object was already set. FIX IT!"; + return; + } + m_scoreObject = scoreObj; + connect(m_showNamesAct, &Taction::triggered, [=]{ m_scoreObject->setShowNoteNames(m_showNamesAct->checked()); }); +// connect(m_extraAccidsAct); + connect(m_deleteLastAct, &Taction::triggered, [=]{ m_scoreObject->deleteLastNote(); }); + connect(m_clearScoreAct, &Taction::triggered, [=]{ m_scoreObject->clearScore(); }); + connect(m_playAct, &Taction::triggered, SOUND, &Tsound::playScore); + connect(m_recModeAct, &Taction::triggered, [=]{ m_scoreObject->setRecordMode(!m_scoreObject->recordMode()); }); + connect(m_zoomOutAct, &Taction::triggered, [=]{ m_scoreObject->setScaleFactor(qMax(0.4, m_scoreObject->scaleFactor() - 0.2)); }); + connect(m_zoomInAct, &Taction::triggered, [=]{ m_scoreObject->setScaleFactor(qMin(m_scoreObject->scaleFactor() + 0.2, 1.4)); }); + connect(GLOB, &Tglobals::isExamChanged, this, &TmainScoreObject::isExamChangedSlot); +} + +//################################################################################################# +//################### PROTECTED ############################################ +//################################################################################################# + +void TmainScoreObject::openXmlActSlot() { + SOUND->stopListen(); + m_scoreObject->openMusicXml(NOO->getXmlToOpen()); + SOUND->startListen(); +} + + +void TmainScoreObject::saveXmlActSlot() { + SOUND->stopListen(); + m_scoreObject->saveMusicXml(NOO->getXmlToSave()); + SOUND->startListen(); +} + + +void TmainScoreObject::isExamChangedSlot() { + m_scoreActions.clear(); + if (GLOB->isExam()) + m_scoreActions << m_zoomOutAct << m_zoomInAct << m_deleteLastAct << m_clearScoreAct; + else + m_scoreActions << m_playAct << m_recModeAct << m_openXmlAct << m_saveXmlAct << m_showNamesAct << m_extraAccidsAct + << m_zoomOutAct << m_zoomInAct << m_deleteLastAct << m_clearScoreAct; + emit scoreActionsChanged(); +} diff --git a/src/main/tmainscoreobject.h b/src/main/tmainscoreobject.h new file mode 100644 index 0000000000000000000000000000000000000000..1e8d5c575ad1285635ffb1b064522de57e123361 --- /dev/null +++ b/src/main/tmainscoreobject.h @@ -0,0 +1,101 @@ +/*************************************************************************** + * Copyright (C) 2017 by Tomasz Bojczuk * + * seelook@gmail.com * + * * + * 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 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef TMAINSCOREOBJECT_H +#define TMAINSCOREOBJECT_H + + +#include <QtCore/qobject.h> + + +class Taction; +class TscoreObject; + + +#define MAIN_SCORE TmainScoreObject::instance() + + +/** + * @p TmainScoreObject is yet another helper to divide score implementation and move its logic to C++ + * It manages all score actions, but their shortcuts have to be set on QML side. + * @p scoreActions() is the list of currently available actions used by @p ScoreMenuContent.qml as a model. + * The list changes during exam. + * IT HAS TO HAVE @p TscoreObject set through @p scoreObject QML property + */ +class TmainScoreObject : public QObject +{ + + Q_OBJECT + + Q_PROPERTY(TscoreObject* scoreObject READ scoreObject WRITE setScoreObject) + Q_PROPERTY(Taction* playAct READ playAct) + Q_PROPERTY(Taction* recModeAct READ recModeAct) + Q_PROPERTY(Taction* showNamesAct READ showNamesAct) + Q_PROPERTY(Taction* extraAccidsAct READ extraAccidsAct) + Q_PROPERTY(Taction* deleteLastAct READ deleteLastAct) + Q_PROPERTY(Taction* clearScoreAct READ clearScoreAct) + Q_PROPERTY(Taction* openXmlAct READ openXmlAct) + Q_PROPERTY(Taction* saveXmlAct READ saveXmlAct) + Q_PROPERTY(Taction* zoomOutAct READ zoomOutAct) + Q_PROPERTY(Taction* zoomInAct READ zoomInAct) + Q_PROPERTY(QList<QObject*> scoreActions READ scoreActions NOTIFY scoreActionsChanged) + +public: + explicit TmainScoreObject(QObject* parent = nullptr); + ~TmainScoreObject() override; + + static TmainScoreObject* instance() { return m_instance; } + + TscoreObject* scoreObject() { return m_scoreObject; } + void setScoreObject(TscoreObject* scoreObj); + + Taction* playAct() { return m_playAct; } + Taction* recModeAct() { return m_recModeAct; } + Taction* showNamesAct() { return m_showNamesAct; } + Taction* extraAccidsAct() { return m_extraAccidsAct; } + Taction* deleteLastAct() { return m_deleteLastAct; } + Taction* clearScoreAct() { return m_clearScoreAct; } + Taction* openXmlAct() { return m_openXmlAct; } + Taction* saveXmlAct() { return m_saveXmlAct; } + Taction* zoomOutAct() { return m_zoomOutAct; } + Taction* zoomInAct() { return m_zoomInAct; } + + QList<QObject*> scoreActions() { return m_scoreActions; } + +signals: + void scoreActionsChanged(); + +protected: + void openXmlActSlot(); + void saveXmlActSlot(); + void isExamChangedSlot(); + +private: + TscoreObject *m_scoreObject = nullptr; + Taction *m_playAct, *m_recModeAct; + Taction *m_showNamesAct, *m_extraAccidsAct; + Taction *m_zoomOutAct, *m_zoomInAct; + Taction *m_deleteLastAct, *m_clearScoreAct; + Taction *m_openXmlAct, *m_saveXmlAct; + QList<QObject*> m_scoreActions; + + static TmainScoreObject *m_instance; + +}; + +#endif // TMAINSCOREOBJECT_H diff --git a/src/qml/MainScore.qml b/src/qml/MainScore.qml index 1d29ed2c46cd4ce7b37f568e5f039036f85dce0c..eb8e246fe8a3adb86be19b2e011d332f6e1df46e 100644 --- a/src/qml/MainScore.qml +++ b/src/qml/MainScore.qml @@ -7,6 +7,7 @@ import QtQuick.Controls 2.2 import Score 1.0 import Nootka 1.0 +import Nootka.Main 1.0 Score { @@ -14,16 +15,17 @@ Score { width: parent.width - property alias showNamesAct: showNamesAct - property alias extraAccidsAct: extraAccidsAct - property alias zoomInAct: zoomInAct - property alias zoomOutAct: zoomOutAct - property alias openXmlAct: openXmlAct - property alias saveXmlAct: saveXmlAct - property alias deleteLastAct: deleteLastAct - property alias clearScoreAct: clearScoreAct - property alias recModeAct: recModeAct - property alias playAct: playAct + property alias showNamesAct: mainObj.showNamesAct + property alias extraAccidsAct: mainObj.extraAccidsAct + property alias zoomInAct: mainObj.zoomInAct + property alias zoomOutAct: mainObj.zoomOutAct + property alias openXmlAct: mainObj.openXmlAct + property alias saveXmlAct: mainObj.saveXmlAct + property alias deleteLastAct: mainObj.deleteLastAct + property alias clearScoreAct: mainObj.clearScoreAct + property alias recModeAct: mainObj.recModeAct + property alias playAct: mainObj.playAct + property alias scoreActions: mainObj.scoreActions scoreObj.meter: GLOB.rhythmsEnabled && !GLOB.singleNoteMode ? Tmeter.Meter_4_4 : Tmeter.NoMeter focus: true @@ -42,6 +44,19 @@ Score { scoreObj.nameStyle: GLOB.noteNameStyle scoreObj.enableDoubleAccidentals: GLOB.enableDoubleAccids + TmainScoreObject { + id: mainObj + scoreObject: scoreObj + deleteLastAct.shortcut: Shortcut { sequence: "Del"; onActivated: deleteLastAct.triggered(); enabled: !GLOB.singleNoteMode } + clearScoreAct.shortcut: Shortcut { sequence: "Shift+Del"; onActivated: clearScoreAct.triggered(); enabled: !GLOB.singleNoteMode } + openXmlAct.shortcut: Shortcut { sequence: StandardKey.Open; onActivated: openXmlAct.triggered(); enabled: !GLOB.singleNoteMode } + saveXmlAct.shortcut: Shortcut { sequence: StandardKey.Save; onActivated: saveXmlAct.triggered(); enabled: !GLOB.singleNoteMode } + zoomOutAct.shortcut: Shortcut { sequence: StandardKey.ZoomOut; onActivated: zoomOutAct.triggered(); enabled: !GLOB.singleNoteMode } + zoomInAct.shortcut: Shortcut { sequence: StandardKey.ZoomIn; onActivated: zoomInAct.triggered(); enabled: !GLOB.singleNoteMode } + recModeAct.text: recordMode ? qsTr("Note by note") : qsTr("Edit") + recModeAct.icon: recordMode ? "record" : "stopMelody" + } + Timer { id: zoomTimer; interval: 500 } MouseArea { anchors.fill: parent @@ -127,94 +142,11 @@ Score { height: currentNote ? Math.min(12.0, currentNote.notePosY + 6.0) : 0 x: currentNote ? -width * 0.25 : 0 y: currentNote ? Math.min(currentNote.height - height, Math.max(0.0, currentNote.notePosY - height / 2.0)) : 0 - color: Qt.rgba(activPal.highlight.r, activPal.highlight.g, activPal.highlight.b, 0.3) + color: Noo.alpha(activPal.highlight, 75) z: -1 radius: width / 3.0 } - Taction { - id: playAct - text: Noo.TR("QShortcut", "Play") - icon: "playMelody" - onTriggered: SOUND.playScore() -// shortcut: Shortcut { sequence: "Space"; onActivated: recModeAct.triggered() } - } - Taction { - id: recModeAct - text: recordMode ? qsTr("Note by note") : qsTr("Edit") - icon: recordMode ? "record" : "stopMelody" - onTriggered: recordMode = !recordMode -// shortcut: Shortcut { sequence: "Ctrl+Space"; onActivated: recModeAct.triggered() } - } - Taction { - id: openXmlAct - text: Noo.TR("QShortcut", "Open") - icon: "open" - onTriggered: { - SOUND.stopListen() - var xmlFle = Noo.getXmlToOpen() - scoreObj.openMusicXml(xmlFle) - SOUND.startListen() - } - shortcut: Shortcut { sequence: StandardKey.Open; onActivated: openXmlAct.triggered() } - } - Taction { - id: saveXmlAct - text: Noo.TR("QShortcut", "Save") - icon: "save" - onTriggered: { - var xmlFle = Noo.getXmlToSave() - scoreObj.saveMusicXml(xmlFle) - } - shortcut: Shortcut { sequence: StandardKey.Save; onActivated: saveXmlAct.triggered() } - } - Taction { - id: extraAccidsAct - enabled: !GLOB.singleNoteMode - text: qsTr("Additional accidentals") - checkable: true - } - Taction { - id: showNamesAct - enabled: !GLOB.singleNoteMode - text: qsTr("Show note names") - checkable: true - checked: GLOB.namesOnScore - onTriggered: { scoreObj.showNoteNames = checked } - } - Taction { - id: zoomOutAct - enabled: !GLOB.singleNoteMode - icon: "zoom-out" - text: qsTr("Zoom score out") - onTriggered: scaleFactor = Math.max(0.4, scaleFactor - 0.2) - shortcut: Shortcut { sequence: StandardKey.ZoomOut; onActivated: zoomOutAct.triggered() } - } - Taction { - id: zoomInAct - enabled: !GLOB.singleNoteMode - icon: "zoom-in" - text: qsTr("Zoom score in") - onTriggered: scaleFactor = scaleFactor = Math.min(scaleFactor + 0.2, 1.4) - shortcut: Shortcut { sequence: StandardKey.ZoomIn; onActivated: zoomInAct.triggered() } - } - Taction { - id: deleteLastAct - enabled: !GLOB.singleNoteMode - icon: "delete" - text: qsTr("Delete note") - onTriggered: scoreObj.deleteLastNote() - shortcut: Shortcut { sequence: "Del"; onActivated: deleteLastAct.triggered() } - } - Taction { - id: clearScoreAct - enabled: !GLOB.singleNoteMode - icon: "clear-score" - text: qsTr("Delete all notes") - onTriggered: clearScore() - shortcut: Shortcut { sequence: "Shift+Del"; onActivated: clearScoreAct.triggered() } - } - Shortcut { enabled: !GLOB.singleNoteMode sequence: StandardKey.MoveToNextChar;