added navigation for instrument settings popup

This commit is contained in:
Igor Korsukov 2021-04-21 09:27:17 +02:00 committed by pereverzev+v
parent 659098c905
commit 26fdf4d66c
18 changed files with 426 additions and 158 deletions

View file

@ -27,6 +27,14 @@
#include "log.h"
//#define NAVIGATION_LOGGING_ENABLED
#ifdef NAVIGATION_LOGGING_ENABLED
#define MYLOG() LOGI()
#else
#define MYLOG() LOGN()
#endif
using namespace mu::ui;
static const mu::UriQuery DEV_SHOW_CONTROLS_URI("musescore://devtools/keynav/controls?sync=false&modal=false");
@ -295,7 +303,7 @@ void NavigationController::doActivateSection(INavigationSection* s, bool isActiv
}
s->setActive(true);
LOGD() << "activated section: " << s->name() << ", order: " << s->index().order();
MYLOG() << "activated section: " << s->name() << ", order: " << s->index().order();
INavigationPanel* toActivatePanel = nullptr;
if (isActivateLastPanel) {
@ -333,7 +341,7 @@ void NavigationController::doActivatePanel(INavigationPanel* sub)
}
sub->setActive(true);
LOGD() << "activated subsection: " << sub->name() << ", order: " << sub->index().order();
MYLOG() << "activated subsection: " << sub->name() << ", order: " << sub->index().order();
INavigationControl* firstCtr = firstEnabled(sub->controls());
if (firstCtr) {
@ -361,7 +369,7 @@ void NavigationController::doActivateControl(INavigationControl* c)
}
c->setActive(true);
LOGD() << "activated control: " << c->name() << ", row: " << c->index().row << ", column: " << c->index().column;
MYLOG() << "activated control: " << c->name() << ", row: " << c->index().row << ", column: " << c->index().column;
}
void NavigationController::doDeactivateControl(INavigationControl* c)
@ -425,7 +433,7 @@ INavigationControl* NavigationController::activeControl() const
void NavigationController::goToNextSection()
{
LOGI() << "====";
MYLOG() << "====";
if (m_sections.empty()) {
return;
}
@ -448,7 +456,7 @@ void NavigationController::goToNextSection()
void NavigationController::goToPrevSection(bool isActivateLastPanel)
{
LOGI() << "====";
MYLOG() << "====";
if (m_sections.empty()) {
return;
}
@ -471,8 +479,7 @@ void NavigationController::goToPrevSection(bool isActivateLastPanel)
void NavigationController::goToNextPanel()
{
LOGI() << "====";
MYLOG() << "====";
INavigationSection* activeSec = activeSection();
if (!activeSec) {
doActivateFirst();
@ -502,7 +509,7 @@ void NavigationController::goToNextPanel()
void NavigationController::goToPrevPanel()
{
LOGI() << "====";
MYLOG() << "====";
INavigationSection* activeSec = activeSection();
if (!activeSec) {
doActivateLast();
@ -672,6 +679,7 @@ void NavigationController::onUp()
void NavigationController::onEscape()
{
MYLOG() << "====";
INavigationPanel* activeSubSec = activePanel();
if (!activeSubSec) {
return;
@ -691,20 +699,19 @@ void NavigationController::onEscape()
void NavigationController::goToFirstControl()
{
LOGI() << "====";
MYLOG() << "====";
goToControl(MoveDirection::First);
}
void NavigationController::goToLastControl()
{
LOGI() << "====";
MYLOG() << "====";
goToControl(MoveDirection::Last);
}
void NavigationController::goToNextRowControl()
{
LOGI() << "====";
MYLOG() << "====";
INavigationPanel* activeSubSec = activePanel();
if (!activeSubSec) {
return;
@ -734,8 +741,7 @@ void NavigationController::goToNextRowControl()
void NavigationController::goToPrevRowControl()
{
LOGI() << "====";
MYLOG() << "====";
INavigationPanel* activeSubSec = activePanel();
if (!activeSubSec) {
return;
@ -765,8 +771,7 @@ void NavigationController::goToPrevRowControl()
void NavigationController::goToControl(MoveDirection direction, INavigationPanel* activeSubSec)
{
LOGI() << "direction: " << direction;
MYLOG() << "direction: " << direction;
if (!activeSubSec) {
activeSubSec = activePanel();
}
@ -777,6 +782,10 @@ void NavigationController::goToControl(MoveDirection direction, INavigationPanel
INavigationControl* activeControl = findActive(activeSubSec->controls());
if (activeControl) {
MYLOG() << "current activated control: " << activeControl->name()
<< ", row: " << activeControl->index().row
<< ", column: " << activeControl->index().column;
doDeactivateControl(activeControl);
}
@ -846,13 +855,13 @@ void NavigationController::goToControl(MoveDirection direction, INavigationPanel
void NavigationController::doTriggerControl()
{
LOGI() << "====";
MYLOG() << "====";
INavigationControl* activeCtrl= activeControl();
if (!activeCtrl) {
return;
}
LOGD() << "triggered control: " << activeCtrl->name();
MYLOG() << "triggered control: " << activeCtrl->name();
activeCtrl->trigger();
}
@ -868,7 +877,7 @@ void NavigationController::onForceActiveRequested(INavigationSection* sec, INavi
}
sec->setActive(true);
LOGD() << "activated section: " << sec->name() << ", order: " << sec->index().order();
MYLOG() << "activated section: " << sec->name() << ", order: " << sec->index().order();
INavigationPanel* activeSub = findActive(sec->panels());
if (activeSub && activeSub != sub) {
@ -876,7 +885,7 @@ void NavigationController::onForceActiveRequested(INavigationSection* sec, INavi
}
sub->setActive(true);
LOGD() << "activated subsection: " << sub->name() << ", order: " << sub->index().order();
MYLOG() << "activated subsection: " << sub->name() << ", order: " << sub->index().order();
INavigationControl* activeCtrl = findActive(sub->controls());
if (activeCtrl && activeCtrl != ctrl) {
@ -884,5 +893,5 @@ void NavigationController::onForceActiveRequested(INavigationSection* sec, INavi
}
ctrl->setActive(true);
LOGD() << "activated control: " << ctrl->name() << ", row: " << ctrl->index().row << ", column: " << ctrl->index().column;
MYLOG() << "activated control: " << ctrl->name() << ", row: " << ctrl->index().row << ", column: " << ctrl->index().column;
}

View file

@ -80,6 +80,12 @@ Rectangle {
id: item
property var section: modelData
property bool active: section.active
onActiveChanged: {
if (active) {
view.positionViewAtIndex(model.index, ListView.Beginning)
}
}
width: parent ? parent.width : 0
height: 48 + subView.height

View file

@ -19,11 +19,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.0
import QtQuick 2.15
import QtQuick.Layouts 1.3
import MuseScore.Ui 1.0
FocusableItem {
FocusScope {
id: root
property bool checked: false
@ -33,6 +33,8 @@ FocusableItem {
property alias font: label.font
property alias wrapMode: label.wrapMode
property alias navigation: navCtrl
signal clicked
implicitHeight: contentRow.height
@ -40,6 +42,28 @@ FocusableItem {
opacity: root.enabled ? 1.0 : ui.theme.itemOpacityDisabled
function ensureActiveFocus() {
if (!root.activeFocus) {
root.forceActiveFocus()
}
if (!navCtrl.active) {
navCtrl.forceActive()
}
}
NavigationControl {
id: navCtrl
name: root.objectName != "" ? root.objectName : "CheckBox"
enabled: root.enabled
onActiveChanged: {
if (!root.activeFocus) {
root.forceActiveFocus()
}
}
onTriggered: root.clicked()
}
RowLayout {
id: contentRow
@ -55,15 +79,13 @@ FocusableItem {
border.width: 1
border.color: "#00000000"
color: ui.theme.buttonColor
radius: 2
color: ui.theme.buttonColor
opacity: ui.theme.buttonOpacityNormal
StyledIconLabel {
anchors.fill: parent
iconCode: root.isIndeterminate ? IconCode.MINUS : IconCode.TICK_RIGHT_ANGLE
visible: root.checked || root.isIndeterminate
}
}
@ -90,20 +112,32 @@ FocusableItem {
hoverEnabled: true
onClicked: { root.clicked() }
onClicked: {
root.ensureActiveFocus()
root.clicked()
}
}
states: [
State {
name: "FOCUSED"
when: navCtrl.active
PropertyChanges {
target: box
border.color: ui.theme.focusColor
border.width: 2
}
},
State {
name: "HOVERED"
when: clickableArea.containsMouse && !clickableArea.pressed
PropertyChanges {
target: box
color: ui.theme.buttonColor
opacity: ui.theme.buttonOpacityHover
border.color: ui.theme.strokeColor
border.width: 1
border.color: navCtrl.active ? ui.theme.focusColor : ui.theme.strokeColor
}
},
@ -113,9 +147,8 @@ FocusableItem {
PropertyChanges {
target: box
color: ui.theme.buttonColor
opacity: ui.theme.buttonOpacityHit
border.color: ui.theme.strokeColor
border.color: navCtrl.active ? ui.theme.focusColor : ui.theme.strokeColor
}
}
]

View file

@ -33,7 +33,7 @@ FocusScope {
property alias navigation: keynavItem
function insureActiveFocus() {
function ensureActiveFocus() {
if (!root.activeFocus) {
root.forceActiveFocus()
}
@ -50,7 +50,7 @@ FocusScope {
onActiveChanged: {
if (keynavItem.active) {
root.insureActiveFocus()
root.ensureActiveFocus()
}
}
}
@ -62,19 +62,19 @@ FocusScope {
border.width: keynavItem.active ? 2 : 0
}
MouseArea {
id: mouseAreaItem
anchors.fill: parent
onClicked: {
root.ensureActiveFocus()
}
}
Item {
id: contentItem
objectName: "FocusableControlContent"
anchors.fill: focusRectItem
anchors.margins: 2 //! NOTE margin needed to show focus border
}
MouseArea {
id: mouseAreaItem
anchors.fill: parent
onClicked: {
root.insureActiveFocus()
}
}
}

View file

@ -130,8 +130,8 @@ Item {
ValueAdjustControl {
id: valueAdjustControl
anchors.verticalCenter: textInputField.verticalCenter
anchors.right: textInputField.right
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
icon: IconCode.SMALL_ARROW_DOWN

View file

@ -19,7 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.9
import QtQuick 2.15
import QtQuick.Controls 2.2
import QtGraphicalEffects 1.0
import MuseScore.Ui 1.0
@ -35,8 +35,33 @@ ComboBox {
property var value
property var maxVisibleItemCount: 6
property alias navigation: navCtrl
opacity: root.enabled ? 1 : ui.theme.itemOpacityDisabled
Keys.onReleased: {
//! TODO Conflicted with navigation, needs research
if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return) {
event.accepted = true
}
}
onPressedChanged: {
if (root.pressed) {
root.ensureActiveFocus()
}
}
function ensureActiveFocus() {
if (!root.activeFocus) {
root.forceActiveFocus()
}
if (!navCtrl.active) {
navCtrl.forceActive()
}
}
function valueFromModel(index, roleName) {
// Simple models (like JS array) with single predefined role name - modelData
@ -81,6 +106,24 @@ ComboBox {
padding: 0
NavigationControl {
id: navCtrl
name: root.objectName != "" ? root.objectName : "StyledComboBox"
enabled: root.enabled
onActiveChanged: {
if (!root.activeFocus) {
root.forceActiveFocus()
}
}
onTriggered: {
if (root.popup.opened) {
root.popup.close()
} else {
root.popup.open()
}
}
}
QtObject {
id: privateProperties
@ -126,30 +169,39 @@ ComboBox {
name: "TOP_CORNERS_ROUNDED"
when: index === 0
PropertyChanges { target: delegateBackgroundRect; topLeftRadius: 4
topRightRadius: 4
bottomLeftRadius: 0
bottomRightRadius: 0 }
PropertyChanges {
target: delegateBackgroundRect;
topLeftRadius: 4
topRightRadius: 4
bottomLeftRadius: 0
bottomRightRadius: 0
}
},
State {
name: "NO_ROUNDED_CORNERS"
when: index !== 0 && index !== count - 1
PropertyChanges { target: delegateBackgroundRect; topLeftRadius: 0
topRightRadius: 0
bottomLeftRadius: 0
bottomRightRadius: 0 }
PropertyChanges {
target: delegateBackgroundRect;
topLeftRadius: 0
topRightRadius: 0
bottomLeftRadius: 0
bottomRightRadius: 0
}
},
State {
name: "BOTTOM_CORNERS_ROUNDED"
when: index === count - 1
PropertyChanges { target: delegateBackgroundRect; topLeftRadius: 0
topRightRadius: 0
bottomLeftRadius: 4
bottomRightRadius: 4 }
PropertyChanges {
target: delegateBackgroundRect;
topLeftRadius: 0
topRightRadius: 0
bottomLeftRadius: 4
bottomRightRadius: 4
}
}
]
}
@ -167,32 +219,24 @@ ComboBox {
horizontalAlignment: Qt.AlignLeft
}
background: RoundedRectangle {
height: root.implicitHeight
width: contentItem.width
background: Rectangle {
height: root.height
width: root.width
color: ui.theme.buttonColor
opacity: ui.theme.buttonOpacityNormal
topLeftRadius: 4
topRightRadius: 0
bottomLeftRadius: 4
bottomRightRadius: 0
radius: 4
border.width: navCtrl.active ? 2 : 0
border.color: ui.theme.focusColor
}
indicator: RoundedRectangle {
indicator: Item {
id: indicatorCanvas
height: root.implicitHeight
width: height
topLeftRadius: 0
bottomLeftRadius: 0
topRightRadius: 4
bottomRightRadius: 4
color: ui.theme.buttonColor
x: root.width - width
y: root.topPadding + (root.availableHeight - height) / 2

View file

@ -19,12 +19,12 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.9
import QtQuick.Controls 2.1
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.3
import MuseScore.Ui 1.0
Rectangle {
FocusableControl {
id: root
property bool isIndeterminate: false
@ -45,7 +45,6 @@ Rectangle {
function selectAll() {
valueInput.selectAll()
forceActiveFocus()
}
function clear() {
@ -54,21 +53,22 @@ Rectangle {
textCleared()
}
function forceActiveFocus() {
valueInput.forceActiveFocus()
onActiveFocusChanged: {
if (activeFocus) {
valueInput.forceActiveFocus()
}
}
implicitHeight: 30
implicitWidth: parent.width
color: ui.theme.textFieldColor
border.color: ui.theme.strokeColor
border.width: 1
background.color: ui.theme.textFieldColor
background.border.color: navigation.active ? ui.theme.focusColor : ui.theme.strokeColor
background.border.width: navigation.active ? 2 : 1
background.radius: 4
opacity: root.enabled ? 1.0 : ui.theme.itemOpacityDisabled
radius: 4
RowLayout {
anchors.fill: parent
anchors.leftMargin: hintIcon.visible ? 0 : 12
@ -88,6 +88,8 @@ Rectangle {
TextField {
id: valueInput
objectName: "TextField"
Layout.alignment: Qt.AlignVCenter
Layout.fillWidth: !measureUnitsLabel.visible
@ -151,7 +153,7 @@ Rectangle {
icon: IconCode.CLOSE_X_ROUNDED
visible: root.clearTextButtonVisible
normalStateColor: root.color
normalStateColor: root.background.color
hoveredStateColor: ui.theme.accentColor
pressedStateColor: ui.theme.accentColor
@ -168,8 +170,8 @@ Rectangle {
StyledTextLabel {
id: undefinedValueLabel
anchors.verticalCenter: root.verticalCenter
anchors.left: root.left
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
anchors.leftMargin: 12
text: root.indeterminateText
@ -183,9 +185,7 @@ Rectangle {
when: clickableArea.containsMouse && !valueInput.activeFocus
PropertyChanges {
target: root
border.color: ui.theme.strokeColor
border.width: 1
target: root.background
opacity: 0.6
}
},
@ -195,7 +195,7 @@ Rectangle {
when: valueInput.activeFocus
PropertyChanges {
target: root
target: root.background
border.color: ui.theme.accentColor
border.width: 1
opacity: 1
@ -216,10 +216,8 @@ Rectangle {
hoverEnabled: true
onPressed: {
if (!valueInput.activeFocus) {
valueInput.forceActiveFocus()
}
root.ensureActiveFocus()
valueInput.forceActiveFocus()
mouse.accepted = false
}
}

View file

@ -22,6 +22,7 @@
#include "popupview.h"
#include <QQuickView>
#include <QQmlEngine>
#include <QUrl>
#include <QQmlContext>
@ -30,13 +31,161 @@
#include "log.h"
namespace mu::uicomponents {
// the private part of PopupView implementation
class PopupWindow : public QObject
{
public:
PopupWindow(QQmlEngine* engine);
~PopupWindow();
void setContent(QQuickItem* item);
void show(QPoint p);
void hide();
bool isVisible() const;
const QRect& geometry() const;
void forceActiveFocus();
private:
bool eventFilter(QObject* watched, QEvent* event) override;
QQuickView* m_view = nullptr;
QWidget* m_widget = nullptr;
};
PopupWindow::PopupWindow(QQmlEngine* engine)
: QObject()
{
setObjectName("PopupWindow");
m_view = new QQuickView(engine, nullptr);
m_widget->setObjectName("PopupQuickWindow");
m_view->setFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);
m_view->setResizeMode(QQuickView::SizeViewToRootObject);
m_view->setColor(QColor(0, 0, 0, 0)); // transparent
m_view->installEventFilter(this);
//! HACK The shortcut system expects
//! the active window should be a QWidget window or QWidget Popup,
//! else shortcut not working, even with Application Shortcut context.
//! So, added QWidget Window for shortcuts to work
/* From Qt source
* https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qshortcut.cpp.html#_Z29qWidgetShortcutContextMatcherP7QObjectN2Qt15ShortcutContextE
bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context)
{
QWidget *active_window = QApplication::activeWindow();
// popups do not become the active window,
// so we fake it here to get the correct context
// for the shortcut system.
if (QApplication::activePopupWidget())
active_window = QApplication::activePopupWidget();
if (!active_window) {
QWindow *qwindow = QGuiApplication::focusWindow();
if (qwindow && qwindow->isActive()) {
while (qwindow) {
if (auto widgetWindow = qobject_cast<QWidgetWindow *>(qwindow)) {
active_window = widgetWindow->widget();
break;
}
qwindow = qwindow->parent();
}
}
}
if (!active_window)
return false;
...
}
*/
m_widget = QWidget::createWindowContainer(m_view, nullptr, Qt::Window | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);
m_widget->setObjectName("PopupWidgetWindow");
m_widget->setAutoFillBackground(false);
m_widget->setAttribute(Qt::WA_TranslucentBackground);
m_widget->installEventFilter(this);
connect(m_view, &QQuickView::widthChanged, [this](int arg) {
m_widget->resize(arg, m_widget->height());
});
connect(m_view, &QQuickView::heightChanged, [this](int arg) {
m_widget->resize(m_widget->width(), arg);
});
}
PopupWindow::~PopupWindow()
{
delete m_widget;
}
void PopupWindow::setContent(QQuickItem* item)
{
m_view->setContent(QUrl(), nullptr, item);
}
void PopupWindow::forceActiveFocus()
{
if (!m_view->contentItem()->hasActiveFocus()) {
m_widget->setFocus();
}
}
void PopupWindow::show(QPoint p)
{
m_widget->move(p);
m_widget->show();
m_widget->setFocus();
}
void PopupWindow::hide()
{
m_widget->hide();
}
bool PopupWindow::isVisible() const
{
return m_widget->isVisible();
}
const QRect& PopupWindow::geometry() const
{
return m_widget->geometry();
}
bool PopupWindow::eventFilter(QObject* watched, QEvent* event)
{
// Please, don't remove
// static QMetaEnum typeEnum = QMetaEnum::fromType<QEvent::Type>();
// LOGI() << watched->objectName() << " event: " << typeEnum.key(event->type());
// QQuickView events
if (watched == m_view) {
if (event->type() == QEvent::FocusIn) {
m_view->contentItem()->forceActiveFocus();
}
if (event->type() == QEvent::MouseButtonPress) {
forceActiveFocus();
}
}
return QObject::eventFilter(watched, event);
}
}
using namespace mu::uicomponents;
PopupView::PopupView(QQuickItem* parent)
: QObject(parent)
{
setObjectName("PopupView");
qApp->installEventFilter(this);
connect(qApp, &QApplication::applicationStateChanged, this, &PopupView::onApplicationStateChanged);
}
@ -57,11 +206,10 @@ void PopupView::setParentItem(QQuickItem* parent)
void PopupView::forceActiveFocus()
{
IF_ASSERT_FAILED(m_view) {
IF_ASSERT_FAILED(m_window) {
return;
}
//! TODO Not working yet
//m_view->requestActivate();
m_window->forceActiveFocus();
}
void PopupView::open()
@ -70,7 +218,7 @@ void PopupView::open()
return;
}
IF_ASSERT_FAILED(m_view) {
IF_ASSERT_FAILED(m_window) {
return;
}
@ -84,12 +232,7 @@ void PopupView::open()
pos.setX(pos.x() + m_localPos.x());
QPointF global = prn->mapToGlobal(pos);
m_view->setPosition(global.toPoint());
m_view->show();
//! TODO Not working yet
//m_view->requestActivate();
//m_view->setKeyboardGrabEnabled(true);
m_window->show(global.toPoint());
emit isOpenedChanged();
emit opened();
@ -101,12 +244,11 @@ void PopupView::close()
return;
}
IF_ASSERT_FAILED(m_view) {
IF_ASSERT_FAILED(m_window) {
return;
}
m_view->hide();
m_view->setKeyboardGrabEnabled(false);
m_window->hide();
emit isOpenedChanged();
emit closed();
@ -123,7 +265,7 @@ void PopupView::toggleOpened()
bool PopupView::isOpened() const
{
return m_view ? m_view->isVisible() : false;
return m_window ? m_window->isVisible() : false;
}
PopupView::ClosePolicy PopupView::closePolicy() const
@ -197,11 +339,8 @@ void PopupView::componentComplete()
return;
}
m_view = new QQuickView(engine, nullptr);
m_view->setFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);
m_view->setResizeMode(QQuickView::SizeViewToRootObject);
m_view->setColor(QColor(0, 0, 0, 0)); // transparent
m_view->setContent(QUrl(), nullptr, m_contentItem);
m_window = new PopupWindow(engine);
m_window->setContent(m_contentItem);
}
bool PopupView::eventFilter(QObject* watched, QEvent* event)
@ -252,6 +391,6 @@ void PopupView::mouseReleaseEvent(QMouseEvent* event)
bool PopupView::isMouseWithinBoundaries(const QPoint& mousePos) const
{
QRect viewRect = m_view->geometry();
QRect viewRect = m_window->geometry();
return viewRect.contains(mousePos);
}

View file

@ -24,13 +24,13 @@
#define MU_UICOMPONENTS_POPUPVIEW_H
#include <QQuickItem>
#include <QQuickView>
#include <QQmlParserStatus>
#include "modularity/ioc.h"
#include "ui/imainwindow.h"
namespace mu::uicomponents {
class PopupWindow;
class PopupView : public QObject, public QQmlParserStatus
{
Q_OBJECT
@ -91,7 +91,6 @@ signals:
void closePolicyChanged(ClosePolicy closePolicy);
void isOpenedChanged();
void opened();
void closed();
@ -107,7 +106,7 @@ private:
bool isMouseWithinBoundaries(const QPoint& mousePos) const;
QQuickView* m_view = nullptr;
PopupWindow* m_window = nullptr;
QQuickItem* m_contentItem = nullptr;
QPointF m_localPos;

View file

@ -55,7 +55,7 @@ Item {
}
NavigationPanel {
id: keynavTreeSub
id: navigationTreePanel
name: "InstrumentsTree"
section: root.keynavSection
direction: NavigationPanel.Both
@ -225,7 +225,7 @@ Item {
isSelected: treeItemDelegateLoader.isSelected
keynavRow: model ? model.index : 0
keynavSubSection: keynavTreeSub
navigationPanel: navigationTreePanel
isDragAvailable: dropArea.isSelectable
type: treeItemDelegateLoader.delegateType
@ -270,7 +270,7 @@ Item {
isHighlighted: treeItemDelegateLoader.isSelected
keynavRow: model ? model.index : 0
keynavSubSection: keynavTreeSub
navigationPanel: navigationTreePanel
onClicked: {
styleData.value.appendNewItem()

View file

@ -19,7 +19,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import QtQuick 2.9
import QtQuick 2.15
import MuseScore.Ui 1.0
import MuseScore.UiComponents 1.0
@ -31,6 +31,13 @@ StyledPopupView {
contentHeight: contentColumn.childrenRect.height
contentWidth: 240
navigation.name: "InstrumentSettingsPopup"
navigation.direction: NavigationPanel.Vertical
onOpened: {
instrNameField.ensureActiveFocus()
}
function load(instrument) {
settingsModel.load(instrument)
}
@ -50,8 +57,11 @@ StyledPopupView {
}
TextInputField {
id: instrNameField
objectName: "InstrNameField"
navigation.panel: root.navigation
navigation.row: 1
currentText: settingsModel.instrumentName
onCurrentTextEdited: {
settingsModel.instrumentName = newTextValue
}
@ -62,8 +72,10 @@ StyledPopupView {
}
TextInputField {
objectName: "AbbreviatureField"
navigation.panel: root.navigation
navigation.row: 2
currentText: settingsModel.abbreviature
onCurrentTextEdited: {
settingsModel.abbreviature = newTextValue
}
@ -74,8 +86,10 @@ StyledPopupView {
}
TextInputField {
objectName: "PartNameField"
navigation.panel: root.navigation
navigation.row: 3
currentText: settingsModel.partName
onCurrentTextEdited: {
settingsModel.partName = newTextValue
}
@ -89,6 +103,7 @@ StyledPopupView {
FlatButton {
width: parent.width
navigation.panel: root.navigation
navigation.row: 4
text: qsTrc("instruments", "Replace instrument")
onClicked: {

View file

@ -31,7 +31,7 @@ Item {
property bool isHighlighted: false
property int keynavRow: 0
property NavigationPanel keynavSubSection: null
property NavigationPanel navigationPanel: null
Rectangle {
anchors.fill: parent
@ -48,7 +48,7 @@ Item {
NavigationControl {
id: keynavItem
name: "InstrumentsTreeItemControl"
panel: root.keynavSubSection
panel: root.navigationPanel
row: root.keynavRow
column: 0
enabled: visible
@ -85,7 +85,7 @@ Item {
height: width
objectName: "InstrumentsAddStaffBtn"
navigation.panel: root.keynavSubSection
navigation.panel: root.navigationPanel
navigation.row: root.keynavRow
navigation.column: 1

View file

@ -38,7 +38,7 @@ Item {
property var type: InstrumentTreeItemType.UNDEFINED
property int keynavRow: 0
property NavigationPanel keynavSubSection: null
property NavigationPanel navigationPanel: null
property int sideMargin: 0
@ -104,7 +104,7 @@ Item {
NavigationControl {
id: keynavItem
name: "ItemInstrumentsTree"
panel: root.keynavSubSection
panel: root.navigationPanel
row: root.keynavRow
column: 0
enabled: visible
@ -230,8 +230,7 @@ Item {
Component {
id: instrumentSettingsComp
InstrumentSettingsPopup {
navigation.name: "InstrumentSettingsPopup"
navigation.parentControl: keynavItem
navigation.parentControl: settingsButton.navigation
onClosed: {
prv.resetOpenedPopup()
popupLoader.sourceComponent = null
@ -242,8 +241,7 @@ Item {
Component {
id: staffSettingsComp
StaffSettingsPopup {
navigation.name: "StaffSettingsPopup"
navigation.parentControl: keynavItem
navigation.parentControl: settingsButton.navigation
onClosed: {
prv.resetOpenedPopup()
popupLoader.sourceComponent = null
@ -263,7 +261,7 @@ Item {
Layout.preferredWidth: width
objectName: "VisibleBtnInstrument"
navigation.panel: root.keynavSubSection
navigation.panel: root.navigationPanel
navigation.row: root.keynavRow
navigation.column: 1
@ -294,7 +292,7 @@ Item {
objectName: "ExpandBtnInstrument"
enabled: expandButton.visible
navigation.panel: root.keynavSubSection
navigation.panel: root.navigationPanel
navigation.row: root.keynavRow
navigation.column: 2
@ -345,7 +343,7 @@ Item {
objectName: "SettingsBtnInstrument"
enabled: root.visible
navigation.panel: root.keynavSubSection
navigation.panel: root.navigationPanel
navigation.row: root.keynavRow
navigation.column: 3

View file

@ -31,10 +31,17 @@ StyledPopupView {
contentHeight: contentColumn.childrenRect.height
contentWidth: 240
navigation.name: "StaffSettingsPopup"
navigation.direction: NavigationPanel.Vertical
function load(staff) {
settingsModel.load(staff)
}
onOpened: {
staffTypesComboBox.ensureActiveFocus()
}
StaffSettingsModel {
id: settingsModel
}
@ -51,8 +58,12 @@ StyledPopupView {
}
StyledComboBox {
id: staffTypesComboBox
width: parent.width
navigation.panel: root.navigation
navigation.row: 1
textRoleName: "text"
valueRoleName: "value"
@ -81,21 +92,24 @@ StyledPopupView {
text: qsTrc("instruments", "Voices visible in the score")
}
ListView {
height: contentItem.childrenRect.height
Row {
height: 40
width: parent.width
spacing: 26
orientation: ListView.Horizontal
Repeater {
model: settingsModel.voices
delegate: CheckBox {
id: item
objectName: "Voice"+modelData.title+"CheckBox"
navigation.panel: root.navigation
navigation.row: model.index + 2 //! NOTE after staffTypesComboBox
text: modelData.title
checked: modelData.visible
model: settingsModel.voices
delegate: CheckBox {
text: modelData.title
checked: modelData.visible
onClicked: {
settingsModel.setVoiceVisible(model.index, !checked)
onClicked: {
item.checked = !item.checked
settingsModel.setVoiceVisible(model.index, !checked)
}
}
}
}
@ -106,10 +120,10 @@ StyledPopupView {
}
CheckBox {
navigation.panel: root.navigation
navigation.row: 20 // Should be more than a voices checkbox
text: qsTrc("instruments", "Small staff")
checked: settingsModel.isSmallStaff
onClicked: {
settingsModel.setIsSmallStaff(!checked)
}
@ -120,6 +134,9 @@ StyledPopupView {
anchors.right: parent.right
anchors.rightMargin: 20
navigation.panel: root.navigation
navigation.row: 21 // after small staff CheckBox
text: qsTrc("instruments", "Hide all measures that do not contain notation (cutaway)")
wrapMode: Text.WordWrap
@ -139,6 +156,7 @@ StyledPopupView {
width: parent.width
navigation.panel: root.navigation
navigation.row: 22 // after cutaway CheckBox
text: qsTrc("instruments", "Create a linked staff")

View file

@ -106,7 +106,15 @@ void StaffSettingsModel::setVoiceVisible(int voiceIndex, bool visible)
m_voicesVisibility[voiceIndex] = visible;
parts()->setVoiceVisible(m_staffId, voiceIndex, visible);
emit voicesChanged();
//! NOTE Do not send a signal to change the list
//! This will lead to the re-creation of the controlы (checkboxes),
//! and so we will lose the control with active focus,
//! and new controls will be created and added.
//! None of the controls will be the active focus.
//! The checkbox state changes in the view.
//! An alternative solution - we need to make a powerful model
//! and not recreate elements when their state changes (do not reset it completely)
//emit voicesChanged();
}
bool StaffSettingsModel::isSmallStaff() const

View file

@ -36,8 +36,8 @@ FlatButton {
accentButton: popup.visible
StyledTextLabel {
anchors.horizontalCenter: root.horizontalCenter
anchors.verticalCenter: root.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
property string pickupMessage: {
if (withPickupMeasure.checked) {

View file

@ -38,8 +38,8 @@ FlatButton {
TimeSignatureView {
id: timeSignatureView
anchors.horizontalCenter: root.horizontalCenter
anchors.verticalCenter: root.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
numerator: root.model.musicSymbolCodes(root.model.timeSignature.numerator)
denominator: root.model.musicSymbolCodes(root.model.timeSignature.denominator)

View file

@ -31,6 +31,7 @@
#define LOGW() IF_LOGLEVEL(haw::logger::Normal) LOG(haw::logger::Logger::WARN, LOG_TAG)
#define LOGI() IF_LOGLEVEL(haw::logger::Normal) LOG(haw::logger::Logger::INFO, LOG_TAG)
#define LOGD() IF_LOGLEVEL(haw::logger::Debug) LOG(haw::logger::Logger::DEBG, LOG_TAG)
#define LOGN() if (0) LOG(haw::logger::Logger::DEBG, LOG_TAG) // compiling, but no output
//! Helps
#define DEPRECATED LOGD() << "This function deprecated!!"