Merge pull request #10401 from RomanPudashkin/grip_points_nagivation

[MU4] Fix #9902: Can't adjust line or slur length via keyboard
This commit is contained in:
RomanPudashkin 2022-02-04 14:57:41 +02:00 committed by GitHub
commit a8be42c6ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 238 additions and 147 deletions

View file

@ -1938,10 +1938,10 @@ void Score::cmdAddOttava(OttavaType type)
}
//---------------------------------------------------------
// addHairpin
// addHairpins
//---------------------------------------------------------
void Score::addHairpin(HairpinType type)
std::vector<Hairpin*> Score::addHairpins(HairpinType type)
{
// special case for two selected chordrests on same staff
bool twoNotesSameStaff = false;
@ -1954,12 +1954,14 @@ void Score::addHairpin(HairpinType type)
}
}
std::vector<Hairpin*> hairpins;
// add hairpin on each staff if possible
if (selection().isRange() && selection().staffStart() != selection().staffEnd() - 1) {
for (int staffIdx = selection().staffStart(); staffIdx < selection().staffEnd(); ++staffIdx) {
ChordRest* cr1 = selection().firstChordRest(staffIdx * VOICES);
ChordRest* cr2 = selection().lastChordRest(staffIdx * VOICES);
addHairpin(type, cr1, cr2, /* toCr2End */ true);
hairpins.push_back(addHairpin(type, cr1, cr2, /* toCr2End */ true));
}
} else if (selection().isRange() || selection().isSingle() || twoNotesSameStaff) {
// for single staff range selection, or single selection,
@ -1968,8 +1970,10 @@ void Score::addHairpin(HairpinType type)
ChordRest* cr2 = nullptr;
getSelectedChordRest2(&cr1, &cr2);
addHairpin(type, cr1, cr2, /* toCr2End */ !twoNotesSameStaff);
hairpins.push_back(addHairpin(type, cr1, cr2, /* toCr2End */ !twoNotesSameStaff));
}
return hairpins;
}
//---------------------------------------------------------

View file

@ -584,7 +584,7 @@ public:
void cmdToggleTie();
static std::vector<Note*> cmdTieNoteList(const Selection& selection, bool noteEntryMode);
void cmdAddOttava(OttavaType);
void addHairpin(HairpinType);
std::vector<Ms::Hairpin*> addHairpins(HairpinType);
void addNoteLine();
void padToggle(Pad p, const EditData& ed);
void cmdAddPitch(const EditData&, int note, bool addFlag, bool insert);

View file

@ -174,6 +174,8 @@ bool SlurSegment::edit(EditData& ed)
Part* part = e->part();
int endTrack = part->endTrack();
cr = searchCR(e->segment(), startTrack, endTrack);
} else {
return false;
}
if (cr && cr != e1) {
changeAnchor(ed, cr);

View file

@ -101,7 +101,9 @@ public:
virtual void redo() = 0;
// Change selection
virtual bool moveSelectionAvailable(MoveSelectionType type) const = 0;
virtual void moveSelection(MoveDirection d, MoveSelectionType type) = 0;
virtual void moveLyrics(MoveDirection d) = 0;
virtual void expandSelection(ExpandSelectionMode mode) = 0;
virtual void addToSelection(MoveDirection d, MoveSelectionType type) = 0;
@ -159,7 +161,7 @@ public:
virtual void addTiedNoteToChord() = 0;
virtual void addSlurToSelection() = 0;
virtual void addOttavaToSelection(OttavaType type) = 0;
virtual void addHairpinToSelection(HairpinType type) = 0;
virtual void addHairpinsToSelection(HairpinType type) = 0;
virtual void addAccidentalToSelection(AccidentalType type) = 0;
virtual void putRestToSelection() = 0;
virtual void putRest(DurationType duration) = 0;

View file

@ -162,16 +162,19 @@ void NotationActionController::init()
registerAction("toggle-visible", &Interaction::toggleVisible);
registerAction("next-element", &Interaction::moveSelection, MoveDirection::Right, MoveSelectionType::EngravingItem,
PlayMode::PlayNote);
registerAction("prev-element", &Interaction::moveSelection, MoveDirection::Left, MoveSelectionType::EngravingItem,
PlayMode::PlayNote);
registerMoveSelectionAction("next-element", MoveSelectionType::EngravingItem, MoveDirection::Right, PlayMode::PlayNote);
registerMoveSelectionAction("prev-element", MoveSelectionType::EngravingItem, MoveDirection::Left, PlayMode::PlayNote);
registerMoveSelectionAction("next-track", MoveSelectionType::Track, MoveDirection::Right, PlayMode::PlayChord);
registerMoveSelectionAction("prev-track", MoveSelectionType::Track, MoveDirection::Left, PlayMode::PlayChord);
registerMoveSelectionAction("next-frame", MoveSelectionType::Frame, MoveDirection::Right);
registerMoveSelectionAction("prev-frame", MoveSelectionType::Frame, MoveDirection::Left);
registerMoveSelectionAction("next-system", MoveSelectionType::System, MoveDirection::Right);
registerMoveSelectionAction("prev-system", MoveSelectionType::System, MoveDirection::Left);
registerAction("notation-move-right", &Controller::move, MoveDirection::Right, false);
registerAction("notation-move-left", &Controller::move, MoveDirection::Left, false);
registerAction("notation-move-right-quickly", &Controller::move, MoveDirection::Right, true, &Controller::measureNavigationAvailable);
registerAction("notation-move-left-quickly", &Controller::move, MoveDirection::Left, true, &Controller::measureNavigationAvailable);
registerAction("next-track", &Interaction::moveSelection, MoveDirection::Right, MoveSelectionType::Track, PlayMode::PlayChord);
registerAction("prev-track", &Interaction::moveSelection, MoveDirection::Left, MoveSelectionType::Track, PlayMode::PlayChord);
registerAction("pitch-up", &Controller::move, MoveDirection::Up, false);
registerAction("pitch-down", &Controller::move, MoveDirection::Down, false);
registerAction("pitch-up-octave", &Controller::move, MoveDirection::Up, true);
@ -218,10 +221,6 @@ void NotationActionController::init()
registerAction("move-down", &Interaction::moveChordRestToStaff, MoveDirection::Down, &Controller::hasSelection);
registerAction("move-left", &Interaction::swapChordRest, MoveDirection::Left, &Controller::isNoteInputMode);
registerAction("move-right", &Interaction::swapChordRest, MoveDirection::Right, &Controller::isNoteInputMode);
registerAction("next-frame", &Interaction::moveSelection, MoveDirection::Right, MoveSelectionType::Frame);
registerAction("prev-frame", &Interaction::moveSelection, MoveDirection::Left, MoveSelectionType::Frame);
registerAction("next-system", &Interaction::moveSelection, MoveDirection::Right, MoveSelectionType::System);
registerAction("prev-system", &Interaction::moveSelection, MoveDirection::Left, MoveSelectionType::System);
registerAction("next-segment-element", &Interaction::moveSegmentSelection, MoveDirection::Right, PlayMode::PlayNote);
registerAction("prev-segment-element", &Interaction::moveSegmentSelection, MoveDirection::Left, PlayMode::PlayNote);
@ -286,8 +285,8 @@ void NotationActionController::init()
registerAction("add-8va", &Interaction::addOttavaToSelection, OttavaType::OTTAVA_8VA);
registerAction("add-8vb", &Interaction::addOttavaToSelection, OttavaType::OTTAVA_8VB);
registerAction("add-hairpin", &Interaction::addHairpinToSelection, HairpinType::CRESC_HAIRPIN);
registerAction("add-hairpin-reverse", &Interaction::addHairpinToSelection, HairpinType::DECRESC_HAIRPIN);
registerAction("add-hairpin", &Interaction::addHairpinsToSelection, HairpinType::CRESC_HAIRPIN);
registerAction("add-hairpin-reverse", &Interaction::addHairpinsToSelection, HairpinType::DECRESC_HAIRPIN);
registerAction("add-noteline", &Interaction::addAnchoredLineToSelectedNotes);
registerAction("title-text", [this]() { addText(TextStyleType::TITLE); });
@ -478,7 +477,7 @@ bool NotationActionController::canReceiveAction(const actions::ActionCode& code)
auto iter = m_isEnabledMap.find(code);
if (iter != m_isEnabledMap.end()) {
bool enabled = (this->*iter->second)();
bool enabled = iter->second();
return enabled;
}
@ -794,6 +793,22 @@ void NotationActionController::halveNoteInputDuration()
}
}
bool NotationActionController::moveSelectionAvailable(MoveSelectionType type) const
{
auto interaction = currentNotationInteraction();
return interaction && interaction->moveSelectionAvailable(type);
}
void NotationActionController::moveSelection(MoveSelectionType type, MoveDirection direction)
{
auto interaction = currentNotationInteraction();
if (!interaction) {
return;
}
interaction->moveSelection(direction, type);
}
void NotationActionController::move(MoveDirection direction, bool quickly)
{
TRACEFUNC;
@ -1712,7 +1727,7 @@ bool NotationActionController::isNotEditingElement() const
void NotationActionController::registerAction(const mu::actions::ActionCode& code,
std::function<void()> handler, bool (NotationActionController::* isEnabled)() const)
{
m_isEnabledMap[code] = isEnabled;
m_isEnabledMap[code] = std::bind(isEnabled, this);
dispatcher()->reg(this, code, handler);
}
@ -1720,7 +1735,7 @@ void NotationActionController::registerAction(const mu::actions::ActionCode& cod
std::function<void(const actions::ActionData&)> handler,
bool (NotationActionController::* isEnabled)() const)
{
m_isEnabledMap[code] = isEnabled;
m_isEnabledMap[code] = std::bind(isEnabled, this);
dispatcher()->reg(this, code, handler);
}
@ -1728,7 +1743,7 @@ void NotationActionController::registerAction(const mu::actions::ActionCode& cod
void (NotationActionController::* handler)(const actions::ActionData& data),
bool (NotationActionController::* isEnabled)() const)
{
m_isEnabledMap[code] = isEnabled;
m_isEnabledMap[code] = std::bind(isEnabled, this);
dispatcher()->reg(this, code, this, handler);
}
@ -1736,7 +1751,7 @@ void NotationActionController::registerAction(const mu::actions::ActionCode& cod
void (NotationActionController::* handler)(),
bool (NotationActionController::* isEnabled)() const)
{
m_isEnabledMap[code] = isEnabled;
m_isEnabledMap[code] = std::bind(isEnabled, this);
dispatcher()->reg(this, code, this, handler);
}
@ -1760,6 +1775,25 @@ void NotationActionController::registerTabPadNoteAction(const mu::actions::Actio
registerAction(code, [this, padding]() { padNote(padding); }, &NotationActionController::isTablatureStaff);
}
void NotationActionController::registerMoveSelectionAction(const mu::actions::ActionCode& code, MoveSelectionType type,
MoveDirection direction, PlayMode playMode)
{
auto moveSelectionFunc = [this, type, direction, playMode]() {
moveSelection(type, direction);
if (playMode != PlayMode::NoPlay) {
playSelectedElement(playMode == PlayMode::PlayChord);
}
};
auto moveSelectionAvailableFunc = [this, type]() {
return moveSelectionAvailable(type);
};
m_isEnabledMap[code] = moveSelectionAvailableFunc;
dispatcher()->reg(this, code, moveSelectionFunc);
}
void NotationActionController::registerAction(const mu::actions::ActionCode& code,
void (INotationInteraction::* handler)(), PlayMode playMode,
bool (NotationActionController::* enabler)() const)

View file

@ -83,6 +83,8 @@ private:
void putTuplet(const TupletOptions& options);
void putTuplet(int tupletCount);
bool moveSelectionAvailable(MoveSelectionType type) const;
void moveSelection(MoveSelectionType type, MoveDirection direction);
void move(MoveDirection direction, bool quickly = false);
void moveWithinChord(MoveDirection direction);
void selectTopOrBottomOfChord(MoveDirection direction);
@ -195,6 +197,7 @@ private:
bool (NotationActionController::*)() const = &NotationActionController::isNotEditingElement);
void registerAction(const mu::actions::ActionCode&, void (NotationActionController::*)(MoveDirection, bool), MoveDirection, bool,
bool (NotationActionController::*)() const = &NotationActionController::isNotEditingElement);
void registerNoteInputAction(const mu::actions::ActionCode&, NoteInputMethod inputMethod);
void registerNoteAction(const mu::actions::ActionCode&, NoteName, NoteAddingMode addingMode = NoteAddingMode::NextChord);
@ -205,6 +208,9 @@ private:
NoPlay, PlayNote, PlayChord
};
void registerMoveSelectionAction(const mu::actions::ActionCode& code, MoveSelectionType type, MoveDirection direction,
PlayMode playMode = PlayMode::NoPlay);
void registerAction(const mu::actions::ActionCode&, void (INotationInteraction::*)(), bool (NotationActionController::*)() const);
void registerAction(const mu::actions::ActionCode&, void (INotationInteraction::*)(), PlayMode = PlayMode::NoPlay,
bool (NotationActionController::*)() const = &NotationActionController::isNotEditingElement);
@ -218,7 +224,9 @@ private:
bool (NotationActionController::*)() const = &NotationActionController::isNotEditingElement);
async::Notification m_currentNotationNoteInputChanged;
std::map<mu::actions::ActionCode, bool (NotationActionController::*)() const> m_isEnabledMap;
using IsActionEnabledFunc = std::function<bool ()>;
std::map<mu::actions::ActionCode, IsActionEnabledFunc> m_isEnabledMap;
};
}

View file

@ -89,10 +89,47 @@ static int findBracketIndex(Ms::EngravingItem* element)
if (!element->isBracket()) {
return -1;
}
Ms::Bracket* bracket = toBracket(element);
return bracket->system()->brackets().indexOf(bracket);
}
static qreal nudgeDistance(const Ms::EditData& editData)
{
qreal spatium = editData.element->spatium();
if (editData.element->isBeam()) {
if (editData.modifiers & Qt::ControlModifier) {
return spatium;
} else if (editData.modifiers & Qt::AltModifier) {
return spatium * 4;
}
return spatium * 0.25;
}
if (editData.modifiers & Qt::ControlModifier) {
return spatium * Ms::MScore::nudgeStep10;
} else if (editData.modifiers & Qt::AltModifier) {
return spatium * Ms::MScore::nudgeStep50;
}
return spatium * Ms::MScore::nudgeStep;
}
static qreal nudgeDistance(const Ms::EditData& editData, qreal raster)
{
qreal distance = nudgeDistance(editData);
if (raster > 0) {
raster = editData.element->spatium() / raster;
if (distance < raster) {
distance = raster;
}
}
return distance;
}
NotationInteraction::NotationInteraction(Notation* notation, INotationUndoStackPtr undoStack)
: m_notation(notation), m_undoStack(undoStack), m_editData(&m_scoreCallbacks)
{
@ -105,6 +142,14 @@ NotationInteraction::NotationInteraction(Notation* notation, INotationUndoStackP
}
});
m_undoStack->undoNotification().onNotify(this, [this]() {
endEditElement();
});
m_undoStack->redoNotification().onNotify(this, [this]() {
endEditElement();
});
m_dragData.ed = Ms::EditData(&m_scoreCallbacks);
m_dropData.ed = Ms::EditData(&m_scoreCallbacks);
@ -180,7 +225,6 @@ void NotationInteraction::notifyAboutTextEditingChanged()
void NotationInteraction::notifyAboutSelectionChanged()
{
updateGripEdit();
m_selectionChanged.notify();
}
@ -192,6 +236,7 @@ void NotationInteraction::paint(mu::draw::Painter* painter)
drawTextEditMode(painter);
drawSelectionRange(painter);
drawGripPoints(painter);
if (m_lasso && !m_lasso->isEmpty()) {
m_lasso->draw(painter);
}
@ -1671,11 +1716,13 @@ void NotationInteraction::doAddSlur(ChordRest* firstChordRest, ChordRest* second
if (!slur || slur->slurDirection() != Ms::DirectionV::AUTO) {
slur = score()->addSlur(firstChordRest, secondChordRest, slurTemplate);
}
if (m_noteInput->isNoteInputMode()) {
m_noteInput->addSlur(slur);
} else if (!secondChordRest) {
select({ slur->frontSegment() }, SelectType::SINGLE);
updateGripEdit();
Ms::SlurSegment* segment = slur->frontSegment();
select({ segment }, SelectType::SINGLE);
startEditGrip(segment, Ms::Grip::END);
}
}
@ -1944,22 +1991,13 @@ void NotationInteraction::drawSelectionRange(draw::Painter* painter)
void NotationInteraction::drawGripPoints(draw::Painter* painter)
{
Ms::EngravingItem* selectedElement = selection()->element();
int gripsCount = selectedElement ? selectedElement->gripsCount() : 0;
Ms::EngravingItem* editedElement = m_editData.element;
int gripsCount = editedElement ? editedElement->gripsCount() : 0;
if (gripsCount == 0) {
return;
}
bool editingElement = m_editData.element != nullptr;
if (!editingElement) {
m_editData.element = selectedElement;
if (!m_editData.element->isTextBase() && !m_editData.getData(m_editData.element)) {
m_editData.element->startEdit(m_editData);
}
}
m_editData.grips = gripsCount;
m_editData.grip.resize(m_editData.grips);
@ -1968,19 +2006,15 @@ void NotationInteraction::drawGripPoints(draw::Painter* painter)
qreal gripSize = DEFAULT_GRIP_SIZE / scaling;
RectF newRect(-gripSize / 2, -gripSize / 2, gripSize, gripSize);
const EngravingItem* page = m_editData.element->findAncestor(ElementType::PAGE);
PointF pageOffset = page ? page->pos() : m_editData.element->pos();
const EngravingItem* page = editedElement->findAncestor(ElementType::PAGE);
PointF pageOffset = page ? page->pos() : editedElement->pos();
for (RectF& gripRect: m_editData.grip) {
gripRect = newRect.translated(pageOffset);
}
m_editData.element->updateGrips(m_editData);
m_editData.element->drawEditMode(painter, m_editData, scaling);
if (!editingElement) {
m_editData.element = nullptr;
}
editedElement->updateGrips(m_editData);
editedElement->drawEditMode(painter, m_editData, scaling);
}
ChordRest* activeCr(Ms::Score* score)
@ -2079,6 +2113,19 @@ void NotationInteraction::addToSelection(MoveDirection d, MoveSelectionType type
}
}
bool NotationInteraction::moveSelectionAvailable(MoveSelectionType type) const
{
if (type != MoveSelectionType::EngravingItem) {
return !isElementEditStarted();
}
if (isGripEditStarted()) {
return true;
}
return !isElementEditStarted();
}
void NotationInteraction::moveSelection(MoveDirection d, MoveSelectionType type)
{
IF_ASSERT_FAILED(MoveSelectionType::Undefined != type) {
@ -2242,11 +2289,13 @@ void NotationInteraction::moveElementSelection(MoveDirection d)
el = score()->selection().elements().last();
}
bool isLeftDirection = MoveDirection::Left == d;
if (!el) {
ChordRest* cr = score()->selection().currentCR();
if (cr) {
if (cr->isChord()) {
if (MoveDirection::Left == d) {
if (isLeftDirection) {
el = toChord(cr)->upNote();
} else {
el = toChord(cr)->downNote();
@ -2259,21 +2308,30 @@ void NotationInteraction::moveElementSelection(MoveDirection d)
}
EngravingItem* toEl = nullptr;
if (el) {
toEl = (MoveDirection::Left == d) ? score()->prevElement() : score()->nextElement();
toEl = isLeftDirection ? score()->prevElement() : score()->nextElement();
} else {
toEl = (MoveDirection::Left == d) ? score()->lastElement() : score()->firstElement();
toEl = isLeftDirection ? score()->lastElement() : score()->firstElement();
}
if (!toEl) {
return;
}
if (isElementEditStarted()) {
endEditElement();
}
select({ toEl }, SelectType::SINGLE);
if (toEl->type() == ElementType::NOTE || toEl->type() == ElementType::HARMONY) {
score()->setPlayNote(true);
}
if (toEl->hasGrips()) {
startEditGrip(toEl, toEl->defaultGrip());
}
}
void NotationInteraction::moveStringSelection(MoveDirection d)
@ -2463,61 +2521,35 @@ void NotationInteraction::editText(QInputMethodEvent* event)
notifyAboutTextEditingChanged();
}
static qreal nudgeDistance(const Ms::EditData& editData)
{
qreal spatium = editData.element->spatium();
if (editData.element->isBeam()) {
if (editData.modifiers & Qt::ControlModifier) {
return spatium;
} else if (editData.modifiers & Qt::AltModifier) {
return spatium * 4;
} else {
return spatium * 0.25;
}
} else {
if (editData.modifiers & Qt::ControlModifier) {
return spatium * Ms::MScore::nudgeStep10;
} else if (editData.modifiers & Qt::AltModifier) {
return spatium * Ms::MScore::nudgeStep50;
} else {
return spatium * Ms::MScore::nudgeStep;
}
}
}
static qreal nudgeDistance(const Ms::EditData& editData, qreal raster)
{
qreal distance = nudgeDistance(editData);
if (raster > 0) {
raster = editData.element->spatium() / raster;
if (distance < raster) {
distance = raster;
}
}
return distance;
}
bool NotationInteraction::handleKeyPress(QKeyEvent* event)
{
if (event->modifiers() == Qt::KeyboardModifier::AltModifier && !isElementEditStarted()) {
if (event->modifiers() & Qt::KeyboardModifier::AltModifier) {
return false;
}
if (m_editData.element->isTextBase()) {
return false;
}
qreal vRaster = Ms::MScore::vRaster(), hRaster = Ms::MScore::hRaster();
qreal vRaster = Ms::MScore::vRaster();
qreal hRaster = Ms::MScore::hRaster();
switch (event->key()) {
case Qt::Key_Tab:
if (!m_editData.element->nextGrip(m_editData)) {
if (!m_editData.element->hasGrips()) {
return false;
}
updateAnchorLines();
m_editData.element->nextGrip(m_editData);
return true;
case Qt::Key_Backtab:
if (!m_editData.element->prevGrip(m_editData)) {
if (!m_editData.element->hasGrips()) {
return false;
}
updateAnchorLines();
m_editData.element->prevGrip(m_editData);
return true;
case Qt::Key_Left:
m_editData.delta = QPointF(-nudgeDistance(m_editData, hRaster), 0);
@ -2534,18 +2566,24 @@ bool NotationInteraction::handleKeyPress(QKeyEvent* event)
default:
return false;
}
m_editData.evtDelta = m_editData.moveDelta = m_editData.delta;
m_editData.hRaster = hRaster;
m_editData.vRaster = vRaster;
if (m_editData.curGrip == Ms::Grip::NO_GRIP) {
m_editData.curGrip = m_editData.element->defaultGrip();
}
if (m_editData.curGrip != Ms::Grip::NO_GRIP && int(m_editData.curGrip) < m_editData.grips) {
m_editData.pos = m_editData.grip[int(m_editData.curGrip)].center() + m_editData.delta;
}
m_scoreCallbacks.setScore(score());
m_editData.element->startEditDrag(m_editData);
m_editData.element->editDrag(m_editData);
m_editData.element->endEditDrag(m_editData);
return true;
}
@ -2731,43 +2769,50 @@ void NotationInteraction::changeEditElement(EngravingItem* newElement)
void NotationInteraction::editElement(QKeyEvent* event)
{
m_editData.modifiers = event->modifiers();
if (isDragStarted()) {
return; // ignore all key strokes while dragging
}
bool wasEditing = m_editData.element != nullptr;
if (!wasEditing && selection()->element()) {
m_editData.element = selection()->element();
}
if (!m_editData.element) {
return;
}
m_editData.modifiers = event->modifiers();
if (isDragStarted()) {
return; // ignore all key strokes while dragging
}
m_editData.key = event->key();
m_editData.s = event->text();
startEdit();
int systemIndex = findSystemIndex(m_editData.element);
int bracketIndex = findBracketIndex(m_editData.element);
bool handled = m_editData.element->edit(m_editData) || (wasEditing && handleKeyPress(event));
if (!wasEditing) {
m_editData.element = nullptr;
bool handled = m_editData.element->edit(m_editData);
if (!handled) {
handled = handleKeyPress(event);
}
if (handled) {
event->accept();
apply();
if (isGripEditStarted()) {
updateAnchorLines();
}
} else {
m_undoStack->rollbackChanges();
rollback();
}
if (isTextEditingStarted()) {
notifyAboutTextEditingChanged();
} else {
if (bracketIndex >= 0 && systemIndex < score()->systems().size()) {
Ms::System* sys = score()->systems()[systemIndex];
Ms::EngravingItem* bracket = sys->brackets()[bracketIndex];
score()->select(bracket);
notifyAboutSelectionChanged();
}
return;
}
if (bracketIndex >= 0 && systemIndex < score()->systems().size()) {
const Ms::System* system = score()->systems()[systemIndex];
Ms::EngravingItem* bracket = system->brackets()[bracketIndex];
score()->select(bracket);
notifyAboutSelectionChanged();
}
}
@ -3076,19 +3121,21 @@ void NotationInteraction::deleteSelection()
}
startEdit();
if (isTextEditingStarted()) {
auto textBase = toTextBase(m_editData.element);
Ms::TextBase* textBase = toTextBase(m_editData.element);
if (!textBase->deleteSelectedText(m_editData)) {
m_editData.key = Qt::Key_Backspace;
m_editData.modifiers = {};
textBase->edit(m_editData);
}
} else {
doEndEditElement();
resetGripEdit();
score()->cmdDeleteSelection();
}
apply();
resetGripEdit();
apply();
notifyAboutSelectionChanged();
notifyAboutNotationChanged();
@ -3151,17 +3198,21 @@ void NotationInteraction::addOttavaToSelection(OttavaType type)
notifyAboutSelectionChanged();
}
void NotationInteraction::addHairpinToSelection(HairpinType type)
void NotationInteraction::addHairpinsToSelection(HairpinType type)
{
if (selection()->isNone()) {
return;
}
startEdit();
score()->addHairpin(type);
std::vector<Ms::Hairpin*> hairpins = score()->addHairpins(type);
apply();
notifyAboutSelectionChanged();
if (hairpins.size() == 1) {
Ms::LineSegment* segment = hairpins.front()->frontSegment();
select({ segment });
startEditGrip(segment, Ms::Grip::END);
}
}
void NotationInteraction::addAccidentalToSelection(AccidentalType type)
@ -3895,32 +3946,6 @@ bool NotationInteraction::needEndTextEditing(const std::vector<EngravingItem*>&
return newSelectedElements.front() != m_editData.element;
}
void NotationInteraction::updateGripEdit()
{
const auto& elements = score()->selection().elements();
if (elements.isEmpty() || elements.size() > 1) {
resetGripEdit();
return;
}
EngravingItem* element = elements.front();
if (!element->hasGrips()) {
resetGripEdit();
return;
}
m_editData.grips = element->gripsCount();
m_editData.curGrip = Ms::Grip::NO_GRIP;
bool editingElement = m_editData.element != nullptr;
m_editData.element = element;
element->startEdit(m_editData);
updateAnchorLines();
if (!editingElement) {
m_editData.element = nullptr;
}
}
void NotationInteraction::resetGripEdit()
{
m_editData.grips = 0;

View file

@ -110,6 +110,7 @@ public:
void redo() override;
// Change selection
bool moveSelectionAvailable(MoveSelectionType type) const override;
void moveSelection(MoveDirection d, MoveSelectionType type) override;
void expandSelection(ExpandSelectionMode mode) override;
void addToSelection(MoveDirection d, MoveSelectionType type) override;
@ -165,7 +166,7 @@ public:
void addTiedNoteToChord() override;
void addSlurToSelection() override;
void addOttavaToSelection(OttavaType type) override;
void addHairpinToSelection(HairpinType type) override;
void addHairpinsToSelection(HairpinType type) override;
void addAccidentalToSelection(AccidentalType type) override;
void putRestToSelection() override;
void putRest(DurationType duration) override;
@ -328,7 +329,6 @@ private:
bool needEndTextEditing(const std::vector<EngravingItem*>& newSelectedElements) const;
void updateGripEdit();
void resetGripEdit();
bool elementsSelected(const std::vector<ElementType>& elementsTypes) const;

View file

@ -877,12 +877,26 @@ void NotationPaintView::shortcutOverride(QKeyEvent* event)
bool NotationPaintView::event(QEvent* event)
{
if (event->type() == QEvent::Type::ShortcutOverride) {
shortcutOverride(dynamic_cast<QKeyEvent*>(event));
}
QEvent::Type eventType = event->type();
if (hasFocus() && event->type() == QEvent::Type::ContextMenu) {
if (eventType == QEvent::Type::ShortcutOverride) {
auto keyEvent = dynamic_cast<QKeyEvent*>(event);
shortcutOverride(keyEvent);
if (keyEvent->isAccepted()) {
m_lastAcceptedKey = keyEvent->key();
}
} else if (eventType == QEvent::Type::KeyPress) {
auto keyEvent = dynamic_cast<const QKeyEvent*>(event);
if (keyEvent->key() == m_lastAcceptedKey) {
m_lastAcceptedKey = -1;
// required to prevent Qt-Quick from changing focus on tab
return true;
}
} else if (eventType == QEvent::Type::ContextMenu && hasFocus()) {
QPointF contextMenuPosition;
if (m_inputController->selectionType() == ElementType::PAGE) {
contextMenuPosition = QPointF(width() / 2, height() / 2);
} else {

View file

@ -222,7 +222,9 @@ private:
qreal m_previousVerticalScrollPosition = 0;
qreal m_previousHorizontalScrollPosition = 0;
bool m_publishMode = false;
int m_lastAcceptedKey = -1;
};
}