concept: keyboard navigation by subsections
This commit is contained in:
parent
66f33addca
commit
b75e2f460e
14 changed files with 524 additions and 125 deletions
|
@ -63,5 +63,6 @@
|
|||
<file>qml/DevTools/Autobot/AutobotControl.qml</file>
|
||||
<file>qml/DevTools/KeyNav/KeyNavExample.qml</file>
|
||||
<file>qml/DevTools/KeyNav/KeyNavSection.qml</file>
|
||||
<file>qml/DevTools/KeyNav/KeyNavSubSection.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -16,6 +16,7 @@ Rectangle {
|
|||
|
||||
sectionName: "sect 2"
|
||||
sectionOrder: 2
|
||||
subsecCount: 3
|
||||
}
|
||||
|
||||
KeyNavSection {
|
||||
|
@ -25,6 +26,7 @@ Rectangle {
|
|||
|
||||
sectionName: "sect 1"
|
||||
sectionOrder: 1
|
||||
subsecCount: 1
|
||||
}
|
||||
|
||||
KeyNavSection {
|
||||
|
@ -34,6 +36,7 @@ Rectangle {
|
|||
|
||||
sectionName: "sect 3"
|
||||
sectionOrder: 3
|
||||
subsecCount: 2
|
||||
}
|
||||
|
||||
KeyNavSection {
|
||||
|
@ -43,6 +46,7 @@ Rectangle {
|
|||
|
||||
sectionName: "sect 4"
|
||||
sectionOrder: 4
|
||||
subsecCount: 4
|
||||
}
|
||||
|
||||
KeyNavSection {
|
||||
|
@ -52,6 +56,7 @@ Rectangle {
|
|||
|
||||
sectionName: "sect 5"
|
||||
sectionOrder: 5
|
||||
subsecCount: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ Rectangle {
|
|||
property alias sectionName: keynavsec.name
|
||||
property alias sectionOrder: keynavsec.order
|
||||
|
||||
property alias subsecCount: subsecrepeater.model
|
||||
|
||||
height: 48
|
||||
|
||||
border.color: "#75507b"
|
||||
|
@ -19,15 +21,33 @@ Rectangle {
|
|||
}
|
||||
|
||||
Text {
|
||||
id: title
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: btn.left
|
||||
anchors.leftMargin: 8
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
width: 48
|
||||
text: root.sectionName
|
||||
}
|
||||
|
||||
Row {
|
||||
id: subs
|
||||
anchors.left: title.right
|
||||
anchors.right: btn.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 8
|
||||
|
||||
Repeater {
|
||||
id: subsecrepeater
|
||||
KeyNavSubSection {
|
||||
keynavSection: keynavsec
|
||||
subsectionName: "subsec" + model.index
|
||||
subsectionOrder: model.index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlatButton {
|
||||
id: btn
|
||||
anchors.right: parent.right
|
||||
|
|
20
src/appshell/qml/DevTools/KeyNav/KeyNavSubSection.qml
Normal file
20
src/appshell/qml/DevTools/KeyNav/KeyNavSubSection.qml
Normal file
|
@ -0,0 +1,20 @@
|
|||
import QtQuick 2.15
|
||||
import MuseScore.Ui 1.0
|
||||
|
||||
Rectangle {
|
||||
|
||||
property alias keynavSection: keynavsec.section
|
||||
property alias subsectionName: keynavsec.name
|
||||
property alias subsectionOrder: keynavsec.order
|
||||
|
||||
height: 40
|
||||
width: 40
|
||||
opacity: 0.8
|
||||
|
||||
border.color: "#75507b"
|
||||
border.width: keynavsec.active ? 4 : 0
|
||||
|
||||
KeyNavigationSubSection {
|
||||
id: keynavsec
|
||||
}
|
||||
}
|
|
@ -101,6 +101,8 @@ set(MODULE_SRC
|
|||
${CMAKE_CURRENT_LIST_DIR}/view/abstractmenumodel.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/keynavigationsection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/keynavigationsection.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/keynavigationsubsection.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/view/keynavigationsubsection.h
|
||||
|
||||
${CMAKE_CURRENT_LIST_DIR}/dev/interactivetestsmodel.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/dev/interactivetestsmodel.h
|
||||
|
|
|
@ -20,8 +20,21 @@
|
|||
#define MU_UI_IKEYNAVIGATIONSECTION_H
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
|
||||
namespace mu::ui {
|
||||
class IKeyNavigationSubSection
|
||||
{
|
||||
public:
|
||||
virtual ~IKeyNavigationSubSection() = default;
|
||||
|
||||
virtual QString name() const = 0;
|
||||
virtual int order() const = 0;
|
||||
virtual bool enabled() const = 0;
|
||||
virtual bool active() const = 0;
|
||||
virtual void setActive(bool arg) = 0;
|
||||
};
|
||||
|
||||
class IKeyNavigationSection
|
||||
{
|
||||
public:
|
||||
|
@ -32,6 +45,8 @@ public:
|
|||
virtual bool enabled() const = 0;
|
||||
virtual bool active() const = 0;
|
||||
virtual void setActive(bool arg) = 0;
|
||||
|
||||
virtual const QList<IKeyNavigationSubSection*>& subsections() const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -24,168 +24,301 @@
|
|||
|
||||
using namespace mu::ui;
|
||||
|
||||
void KeyNavigationController::init()
|
||||
// algorithms
|
||||
template<class T>
|
||||
static T* findFirstEnabled(typename QList<T*>::const_iterator it, typename QList<T*>::const_iterator end)
|
||||
{
|
||||
dispatcher()->reg(this, "nav-next-section", this, &KeyNavigationController::nextSection);
|
||||
dispatcher()->reg(this, "nav-prev-section", this, &KeyNavigationController::prevSection);
|
||||
}
|
||||
|
||||
static void print(const std::string& title, const std::vector<IKeyNavigationSection*>& chain)
|
||||
{
|
||||
LOGI() << title;
|
||||
for (size_t i = 0; i < chain.size(); ++i) {
|
||||
LOGI() << " " << i << chain.at(i)->name() << " order: " << chain.at(i)->order();
|
||||
for (; it != end; ++it) {
|
||||
T* s = *it;
|
||||
if (s->enabled()) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
void KeyNavigationController::reg(IKeyNavigationSection* s)
|
||||
{
|
||||
//! TODO add check on valid state
|
||||
|
||||
m_chain.push_back(s);
|
||||
print("after push_back", m_chain);
|
||||
std::sort(m_chain.begin(), m_chain.end(), [this](const IKeyNavigationSection* f, const IKeyNavigationSection* s) {
|
||||
return f->order() < s->order();
|
||||
});
|
||||
|
||||
print("after sort", m_chain);
|
||||
}
|
||||
|
||||
void KeyNavigationController::unreg(IKeyNavigationSection* s)
|
||||
{
|
||||
m_chain.erase(std::remove(m_chain.begin(), m_chain.end(), s), m_chain.end());
|
||||
}
|
||||
|
||||
IKeyNavigationSection* KeyNavigationController::firstSection() const
|
||||
{
|
||||
if (!m_chain.empty()) {
|
||||
return findFirstEnabledSection(m_chain.cbegin(), m_chain.cend());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IKeyNavigationSection* KeyNavigationController::lastSection() const
|
||||
template<class T>
|
||||
static T* findLastEnabled(typename QList<T*>::const_iterator it, typename QList<T*>::const_iterator begin)
|
||||
{
|
||||
if (!m_chain.empty()) {
|
||||
auto last = --m_chain.cend();
|
||||
return findLastEnabledSection(last, m_chain.cbegin());
|
||||
for (; it != begin; --it) {
|
||||
T* s = *it;
|
||||
if (s->enabled()) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
T* s = *begin;
|
||||
if (s->enabled()) {
|
||||
return s;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IKeyNavigationSection* KeyNavigationController::nextSection(const IKeyNavigationSection* s) const
|
||||
template<class T>
|
||||
static T* firstEnabled(const QList<T*>& list)
|
||||
{
|
||||
auto it = std::find(m_chain.begin(), m_chain.end(), s);
|
||||
IF_ASSERT_FAILED(it != m_chain.end()) {
|
||||
if (list.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
return findFirstEnabled<T>(list.cbegin(), list.cend());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static T* lastEnabled(const QList<T*>& list)
|
||||
{
|
||||
if (list.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto last = --list.cend();
|
||||
return findLastEnabled<T>(last, list.cbegin());
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static T* nextEnabled(const QList<T*>& list, const T* s)
|
||||
{
|
||||
auto it = std::find(list.begin(), list.end(), s);
|
||||
IF_ASSERT_FAILED(it != list.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
++it;
|
||||
if (it == m_chain.end()) {
|
||||
|
||||
if (it == list.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return findFirstEnabledSection(it, m_chain.end());
|
||||
|
||||
return findFirstEnabled<T>(it, list.end());
|
||||
}
|
||||
|
||||
IKeyNavigationSection* KeyNavigationController::prevSection(const IKeyNavigationSection* s) const
|
||||
template<class T>
|
||||
static T* prevEnabled(const QList<T*>& list, const T* s)
|
||||
{
|
||||
auto it = std::find(m_chain.begin(), m_chain.end(), s);
|
||||
IF_ASSERT_FAILED(it != m_chain.end()) {
|
||||
auto it = std::find(list.begin(), list.end(), s);
|
||||
IF_ASSERT_FAILED(it != list.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
if (it == m_chain.begin()) {
|
||||
if (it == list.begin()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
--it;
|
||||
|
||||
return findLastEnabledSection(it, m_chain.cbegin());
|
||||
return findLastEnabled<T>(it, list.cbegin());
|
||||
}
|
||||
|
||||
IKeyNavigationSection* KeyNavigationController::findFirstEnabledSection(Chain::const_iterator it, Chain::const_iterator end) const
|
||||
template<class T>
|
||||
static T* findActive(const QList<T*>& list)
|
||||
{
|
||||
for (; it != end; ++it) {
|
||||
IKeyNavigationSection* s = *it;
|
||||
if (s->enabled()) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IKeyNavigationSection* KeyNavigationController::findLastEnabledSection(Chain::const_iterator it, Chain::const_iterator begin) const
|
||||
{
|
||||
for (; it != begin; --it) {
|
||||
IKeyNavigationSection* s = *it;
|
||||
if (s->enabled()) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
IKeyNavigationSection* s = *begin;
|
||||
if (s->enabled()) {
|
||||
return s;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IKeyNavigationSection* KeyNavigationController::activeSection() const
|
||||
{
|
||||
auto it = std::find_if(m_chain.cbegin(), m_chain.cend(), [this](const IKeyNavigationSection* s) {
|
||||
auto it = std::find_if(list.cbegin(), list.cend(), [](const T* s) {
|
||||
return s->active();
|
||||
});
|
||||
|
||||
if (it != m_chain.cend()) {
|
||||
if (it != list.cend()) {
|
||||
return *it;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void KeyNavigationController::init()
|
||||
{
|
||||
dispatcher()->reg(this, "nav-next-section", this, &KeyNavigationController::nextSection);
|
||||
dispatcher()->reg(this, "nav-prev-section", this, &KeyNavigationController::prevSection);
|
||||
dispatcher()->reg(this, "nav-next-subsection", this, &KeyNavigationController::nextSubSection);
|
||||
dispatcher()->reg(this, "nav-prev-subsection", this, &KeyNavigationController::prevSubSection);
|
||||
}
|
||||
|
||||
void KeyNavigationController::reg(IKeyNavigationSection* s)
|
||||
{
|
||||
//! TODO add check on valid state
|
||||
|
||||
m_sections.push_back(s);
|
||||
std::sort(m_sections.begin(), m_sections.end(), [this](const IKeyNavigationSection* f, const IKeyNavigationSection* s) {
|
||||
return f->order() < s->order();
|
||||
});
|
||||
}
|
||||
|
||||
void KeyNavigationController::unreg(IKeyNavigationSection* s)
|
||||
{
|
||||
m_sections.erase(std::remove(m_sections.begin(), m_sections.end(), s), m_sections.end());
|
||||
}
|
||||
|
||||
void KeyNavigationController::activateSection(IKeyNavigationSection* s)
|
||||
{
|
||||
IF_ASSERT_FAILED(s) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (IKeyNavigationSubSection* sub : s->subsections()) {
|
||||
sub->setActive(false);
|
||||
}
|
||||
|
||||
s->setActive(true);
|
||||
|
||||
IKeyNavigationSubSection* firstSub = firstEnabled(s->subsections());
|
||||
if (firstSub) {
|
||||
firstSub->setActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyNavigationController::deactivateSection(IKeyNavigationSection* s)
|
||||
{
|
||||
IF_ASSERT_FAILED(s) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (IKeyNavigationSubSection* sub : s->subsections()) {
|
||||
sub->setActive(false);
|
||||
}
|
||||
|
||||
s->setActive(false);
|
||||
}
|
||||
|
||||
void KeyNavigationController::nextSection()
|
||||
{
|
||||
LOGI() << "====";
|
||||
if (m_chain.empty()) {
|
||||
if (m_sections.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
IKeyNavigationSection* activeSec = activeSection();
|
||||
IKeyNavigationSection* activeSec = findActive(m_sections);
|
||||
if (!activeSec) { // no any active
|
||||
firstSection()->setActive(true);
|
||||
IKeyNavigationSection* first = firstEnabled(m_sections);
|
||||
if (first) {
|
||||
activateSection(first);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
activeSec->setActive(false);
|
||||
deactivateSection(activeSec);
|
||||
|
||||
IKeyNavigationSection* nextSec = nextSection(activeSec);
|
||||
IKeyNavigationSection* nextSec = nextEnabled(m_sections, activeSec);
|
||||
if (!nextSec) { // active is last
|
||||
firstSection()->setActive(true);
|
||||
IKeyNavigationSection* first = firstEnabled(m_sections);
|
||||
if (first) {
|
||||
activateSection(first);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nextSec->setActive(true);
|
||||
activateSection(nextSec);
|
||||
}
|
||||
|
||||
void KeyNavigationController::prevSection()
|
||||
{
|
||||
LOGI() << "====";
|
||||
if (m_chain.empty()) {
|
||||
if (m_sections.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
IKeyNavigationSection* activeSec = activeSection();
|
||||
IKeyNavigationSection* activeSec = findActive(m_sections);
|
||||
if (!activeSec) { // no any active
|
||||
lastSection()->setActive(true);
|
||||
IKeyNavigationSection* last = lastEnabled(m_sections);
|
||||
if (last) {
|
||||
activateSection(last);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
activeSec->setActive(false);
|
||||
deactivateSection(activeSec);
|
||||
|
||||
IKeyNavigationSection* prevSec = prevSection(activeSec);
|
||||
IKeyNavigationSection* prevSec = prevEnabled(m_sections, activeSec);
|
||||
if (!prevSec) { // active is first
|
||||
lastSection()->setActive(true);
|
||||
IKeyNavigationSection* last = lastEnabled(m_sections);
|
||||
if (last) {
|
||||
activateSection(last);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
prevSec->setActive(true);
|
||||
activateSection(prevSec);
|
||||
}
|
||||
|
||||
const QList<IKeyNavigationSubSection*>& KeyNavigationController::subsectionsOfActiveSection(bool doActiveIfNoAnyActive) const
|
||||
{
|
||||
static const QList<IKeyNavigationSubSection*> null;
|
||||
|
||||
if (m_sections.empty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IKeyNavigationSection* activeSec = findActive(m_sections);
|
||||
if (!activeSec) { // no any active
|
||||
if (!doActiveIfNoAnyActive) {
|
||||
return null;
|
||||
}
|
||||
|
||||
activeSec = firstEnabled(m_sections);
|
||||
if (!activeSec) {
|
||||
return null;
|
||||
}
|
||||
activeSec->setActive(true);
|
||||
}
|
||||
|
||||
return activeSec->subsections();
|
||||
}
|
||||
|
||||
void KeyNavigationController::nextSubSection()
|
||||
{
|
||||
LOGI() << "====";
|
||||
|
||||
const QList<IKeyNavigationSubSection*>& subsections = subsectionsOfActiveSection();
|
||||
if (subsections.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
IKeyNavigationSubSection* activeSubSec = findActive(subsections);
|
||||
if (!activeSubSec) { // no any active
|
||||
IKeyNavigationSubSection* firstSub = firstEnabled(subsections);
|
||||
if (firstSub) {
|
||||
firstSub->setActive(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
activeSubSec->setActive(false);
|
||||
|
||||
IKeyNavigationSubSection* nextSubSec = nextEnabled(subsections, activeSubSec);
|
||||
if (!nextSubSec) { // active is last
|
||||
IKeyNavigationSubSection* firstSub = firstEnabled(subsections);
|
||||
if (firstSub) {
|
||||
firstSub->setActive(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
nextSubSec->setActive(true);
|
||||
}
|
||||
|
||||
void KeyNavigationController::prevSubSection()
|
||||
{
|
||||
LOGI() << "====";
|
||||
|
||||
const QList<IKeyNavigationSubSection*>& subsections = subsectionsOfActiveSection();
|
||||
if (subsections.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
IKeyNavigationSubSection* activeSubSec = findActive(subsections);
|
||||
if (!activeSubSec) { // no any active
|
||||
IKeyNavigationSubSection* lastSub = lastEnabled(subsections);
|
||||
if (lastSub) {
|
||||
lastSub->setActive(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
activeSubSec->setActive(false);
|
||||
|
||||
IKeyNavigationSubSection* prevSubSec = prevEnabled(subsections, activeSubSec);
|
||||
if (!prevSubSec) { // active is first
|
||||
IKeyNavigationSubSection* lastSub = lastEnabled(subsections);
|
||||
if (lastSub) {
|
||||
lastSub->setActive(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
prevSubSec->setActive(true);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#ifndef MU_UI_KEYNAVIGATIONCONTROLLER_H
|
||||
#define MU_UI_KEYNAVIGATIONCONTROLLER_H
|
||||
|
||||
#include <vector>
|
||||
#include <QList>
|
||||
|
||||
#include "../ikeynavigationcontroller.h"
|
||||
#include "modularity/ioc.h"
|
||||
|
@ -41,18 +41,15 @@ public:
|
|||
private:
|
||||
void nextSection();
|
||||
void prevSection();
|
||||
void nextSubSection();
|
||||
void prevSubSection();
|
||||
|
||||
using Chain = std::vector<IKeyNavigationSection*>;
|
||||
void activateSection(IKeyNavigationSection* s);
|
||||
void deactivateSection(IKeyNavigationSection* s);
|
||||
|
||||
IKeyNavigationSection* firstSection() const;
|
||||
IKeyNavigationSection* lastSection() const;
|
||||
IKeyNavigationSection* nextSection(const IKeyNavigationSection* s) const;
|
||||
IKeyNavigationSection* prevSection(const IKeyNavigationSection* s) const;
|
||||
IKeyNavigationSection* findFirstEnabledSection(Chain::const_iterator from, Chain::const_iterator end) const;
|
||||
IKeyNavigationSection* findLastEnabledSection(Chain::const_iterator from, Chain::const_iterator begin) const;
|
||||
IKeyNavigationSection* activeSection() const;
|
||||
const QList<IKeyNavigationSubSection*>& subsectionsOfActiveSection(bool doActiveIfNoAnyActive = true) const;
|
||||
|
||||
Chain m_chain;
|
||||
QList<IKeyNavigationSection*> m_sections;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,12 @@ const UiActionList KeyNavigationUiActions::m_actions = {
|
|||
UiAction("nav-prev-section",
|
||||
mu::context::UiCtxAny
|
||||
),
|
||||
UiAction("nav-next-subsection",
|
||||
mu::context::UiCtxAny
|
||||
),
|
||||
UiAction("nav-prev-subsection",
|
||||
mu::context::UiCtxAny
|
||||
)
|
||||
};
|
||||
|
||||
const UiActionList& KeyNavigationUiActions::actionsList() const
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "view/musicalsymbolcodes.h"
|
||||
#include "view/qmldialog.h"
|
||||
#include "view/keynavigationsection.h"
|
||||
#include "view/keynavigationsubsection.h"
|
||||
|
||||
#include "dev/interactivetestsmodel.h"
|
||||
#include "dev/testdialog.h"
|
||||
|
@ -99,6 +100,7 @@ void UiModule::registerUiTypes()
|
|||
|
||||
qmlRegisterType<QmlDialog>("MuseScore.Ui", 1, 0, "QmlDialog");
|
||||
qmlRegisterType<KeyNavigationSection>("MuseScore.Ui", 1, 0, "KeyNavigationSection");
|
||||
qmlRegisterType<KeyNavigationSubSection>("MuseScore.Ui", 1, 0, "KeyNavigationSubSection");
|
||||
|
||||
qmlRegisterType<InteractiveTestsModel>("MuseScore.Ui", 1, 0, "InteractiveTestsModel");
|
||||
qRegisterMetaType<TestDialog>("TestDialog");
|
||||
|
|
|
@ -34,12 +34,7 @@ KeyNavigationSection::~KeyNavigationSection()
|
|||
|
||||
void KeyNavigationSection::setName(QString name)
|
||||
{
|
||||
if (m_name == name) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_name = name;
|
||||
emit nameChanged(m_name);
|
||||
}
|
||||
|
||||
QString KeyNavigationSection::name() const
|
||||
|
@ -49,12 +44,7 @@ QString KeyNavigationSection::name() const
|
|||
|
||||
void KeyNavigationSection::setOrder(int order)
|
||||
{
|
||||
if (m_order == order) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_order = order;
|
||||
emit orderChanged(m_order);
|
||||
}
|
||||
|
||||
int KeyNavigationSection::order() const
|
||||
|
@ -100,5 +90,24 @@ void KeyNavigationSection::componentComplete()
|
|||
{
|
||||
//! NOTE Reg after set properties.
|
||||
LOGD() << "Completed: " << m_name << ", order: " << m_order;
|
||||
|
||||
IF_ASSERT_FAILED(!m_name.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
IF_ASSERT_FAILED(m_order > -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
keyNavigationController()->reg(this);
|
||||
}
|
||||
|
||||
void KeyNavigationSection::addSubSection(IKeyNavigationSubSection* s)
|
||||
{
|
||||
m_subsections.append(s);
|
||||
}
|
||||
|
||||
const QList<IKeyNavigationSubSection*>& KeyNavigationSection::subsections() const
|
||||
{
|
||||
return m_subsections;
|
||||
}
|
||||
|
|
|
@ -21,18 +21,21 @@
|
|||
|
||||
#include <QObject>
|
||||
#include <QQmlParserStatus>
|
||||
#include <QList>
|
||||
|
||||
#include "../ikeynavigationsection.h"
|
||||
|
||||
#include "modularity/ioc.h"
|
||||
#include "../ikeynavigationcontroller.h"
|
||||
|
||||
namespace mu::ui {
|
||||
class KeyNavigationSubSection;
|
||||
class KeyNavigationSection : public QObject, public IKeyNavigationSection, public QQmlParserStatus
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QQmlParserStatus)
|
||||
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
|
||||
Q_PROPERTY(int order READ order WRITE setOrder NOTIFY orderChanged)
|
||||
Q_PROPERTY(QString name READ name WRITE setName)
|
||||
Q_PROPERTY(int order READ order WRITE setOrder)
|
||||
|
||||
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
|
||||
Q_PROPERTY(bool active READ active NOTIFY activeChanged)
|
||||
|
@ -48,27 +51,30 @@ public:
|
|||
bool enabled() const override;
|
||||
bool active() const override;
|
||||
void setActive(bool active) override;
|
||||
const QList<IKeyNavigationSubSection*>& subsections() const override;
|
||||
|
||||
// QQmlParserStatus
|
||||
void classBegin() override;
|
||||
void componentComplete() override;
|
||||
|
||||
void addSubSection(IKeyNavigationSubSection* s);
|
||||
|
||||
public slots:
|
||||
void setName(QString name);
|
||||
void setOrder(int order);
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
signals:
|
||||
void nameChanged(QString name);
|
||||
void activeChanged(bool active);
|
||||
void orderChanged(int order);
|
||||
void enabledChanged(bool enabled);
|
||||
void activeChanged(bool active);
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
int m_order = -1;
|
||||
bool m_active = false;
|
||||
bool m_enabled = true;
|
||||
|
||||
QList<IKeyNavigationSubSection*> m_subsections;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
109
src/framework/ui/view/keynavigationsubsection.cpp
Normal file
109
src/framework/ui/view/keynavigationsubsection.cpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2021 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// 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, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#include "keynavigationsubsection.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
using namespace mu::ui;
|
||||
|
||||
KeyNavigationSubSection::KeyNavigationSubSection(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
KeyNavigationSection* KeyNavigationSubSection::section() const
|
||||
{
|
||||
return m_section;
|
||||
}
|
||||
|
||||
void KeyNavigationSubSection::setSection(KeyNavigationSection* section)
|
||||
{
|
||||
m_section = section;
|
||||
if (m_section) {
|
||||
m_section->addSubSection(this);
|
||||
}
|
||||
}
|
||||
|
||||
void KeyNavigationSubSection::setName(QString name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
QString KeyNavigationSubSection::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
void KeyNavigationSubSection::setOrder(int order)
|
||||
{
|
||||
m_order = order;
|
||||
}
|
||||
|
||||
int KeyNavigationSubSection::order() const
|
||||
{
|
||||
return m_order;
|
||||
}
|
||||
|
||||
void KeyNavigationSubSection::setEnabled(bool enabled)
|
||||
{
|
||||
if (m_enabled == enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_enabled = enabled;
|
||||
emit enabledChanged(m_enabled);
|
||||
}
|
||||
|
||||
bool KeyNavigationSubSection::enabled() const
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
void KeyNavigationSubSection::setActive(bool active)
|
||||
{
|
||||
if (m_active == active) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_active = active;
|
||||
emit activeChanged(m_active);
|
||||
}
|
||||
|
||||
bool KeyNavigationSubSection::active() const
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
|
||||
void KeyNavigationSubSection::classBegin()
|
||||
{
|
||||
}
|
||||
|
||||
void KeyNavigationSubSection::componentComplete()
|
||||
{
|
||||
//! NOTE Reg after set properties.
|
||||
LOGD() << "Completed: " << m_name << ", order: " << m_order;
|
||||
|
||||
IF_ASSERT_FAILED(!m_name.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
IF_ASSERT_FAILED(m_order > -1) {
|
||||
return;
|
||||
}
|
||||
}
|
74
src/framework/ui/view/keynavigationsubsection.h
Normal file
74
src/framework/ui/view/keynavigationsubsection.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
//=============================================================================
|
||||
// MuseScore
|
||||
// Music Composition & Notation
|
||||
//
|
||||
// Copyright (C) 2021 MuseScore BVBA and others
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License version 2.
|
||||
//
|
||||
// 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, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
//=============================================================================
|
||||
#ifndef MU_UI_KEYNAVIGATIONSUBSECTION_H
|
||||
#define MU_UI_KEYNAVIGATIONSUBSECTION_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlParserStatus>
|
||||
#include "../ikeynavigationsection.h"
|
||||
#include "keynavigationsection.h"
|
||||
|
||||
namespace mu::ui {
|
||||
class KeyNavigationSubSection : public QObject, public IKeyNavigationSubSection, public QQmlParserStatus
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(QQmlParserStatus)
|
||||
Q_PROPERTY(KeyNavigationSection * section READ section WRITE setSection)
|
||||
|
||||
Q_PROPERTY(QString name READ name WRITE setName)
|
||||
Q_PROPERTY(int order READ order WRITE setOrder)
|
||||
|
||||
Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
|
||||
Q_PROPERTY(bool active READ active NOTIFY activeChanged)
|
||||
|
||||
public:
|
||||
explicit KeyNavigationSubSection(QObject* parent = nullptr);
|
||||
|
||||
KeyNavigationSection* section() const;
|
||||
|
||||
QString name() const override;
|
||||
int order() const override;
|
||||
bool enabled() const override;
|
||||
bool active() const override;
|
||||
void setActive(bool active) override;
|
||||
|
||||
// QQmlParserStatus
|
||||
void classBegin() override;
|
||||
void componentComplete() override;
|
||||
|
||||
public slots:
|
||||
void setSection(KeyNavigationSection* section);
|
||||
void setName(QString name);
|
||||
void setOrder(int order);
|
||||
void setEnabled(bool enabled);
|
||||
|
||||
signals:
|
||||
void enabledChanged(bool enabled);
|
||||
void activeChanged(bool active);
|
||||
|
||||
private:
|
||||
KeyNavigationSection* m_section = nullptr;
|
||||
QString m_name;
|
||||
int m_order = -1;
|
||||
bool m_active = false;
|
||||
bool m_enabled = true;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // MU_UI_KEYNAVIGATIONSUBSECTION_H
|
Loading…
Reference in a new issue