Skip to content

Commit

Permalink
Merge pull request #1036 from BartlomiejLewandowski/similar-in-range
Browse files Browse the repository at this point in the history
Similar in range
  • Loading branch information
lasconic committed Jul 16, 2014
2 parents 35a65b2 + f50a4ec commit 30b93f5
Show file tree
Hide file tree
Showing 16 changed files with 1,907 additions and 172 deletions.
38 changes: 1 addition & 37 deletions libmscore/measure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2305,44 +2305,8 @@ void Measure::scanElements(void* data, void (*func)(void*, Element*), bool all)
func(data, ms->noText());
}

int tracks = nstaves * VOICES;
for (Segment* s = first(); s; s = s->next()) {
// bar line visibility depends on spanned staves,
// not simply on visibility of first staff
if (s->segmentType() == Segment::Type::BarLine || s->segmentType() == Segment::Type::EndBarLine
|| s->segmentType() == Segment::Type::StartRepeatBarLine) {
for (int staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
Element* e = s->element(staffIdx*VOICES);
if (e == 0) // if no element, skip
continue;
// if staff not visible
if (!all && !(visible(staffIdx) && score()->staff(staffIdx)->show())) {
// if bar line spans just this staff...
if (static_cast<BarLine*>(e)->span() <= 1
// ...or span another staff but without entering INTO it...
|| (static_cast<BarLine*>(e)->span() < 2 &&
static_cast<BarLine*>(e)->spanTo() < 1) )
continue; // ...skip
}
e->scanElements(data, func, all);
}
}
else
for (int track = 0; track < tracks; ++track) {
int staffIdx = track/VOICES;
if (!all && !(visible(staffIdx) && score()->staff(staffIdx)->show())) {
track += VOICES - 1;
continue;
}
Element* e = s->element(track);
if (e == 0)
continue;
e->scanElements(data, func, all);
}
foreach(Element* e, s->annotations()) {
if (all || e->systemFlag() || visible(e->staffIdx()))
e->scanElements(data, func, all);
}
s->scanElements(data,func,all);
}
}

Expand Down
93 changes: 93 additions & 0 deletions libmscore/score.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1745,6 +1745,14 @@ void Score::scanElements(void* data, void (*func)(void*, Element*), bool all)
page->scanElements(data, func, all);
}

void Score::scanElementsInRange(void* data, void (*func)(void*, Element*), bool all)
{
Segment* startSeg = _selection.startSegment();
for (Segment* s = startSeg; s && s!=_selection.endSegment(); s = s->next1MM()) {
s->scanElements(data,func,all);
}
}

//---------------------------------------------------------
// customKeySigIdx
// try to find custom key signature in table,
Expand Down Expand Up @@ -2957,6 +2965,91 @@ void Score::selectRange(Element* e, int staffIdx)
}

//---------------------------------------------------------
// collectMatch
//---------------------------------------------------------

void Score::collectMatch(void* data, Element* e)
{
ElementPattern* p = static_cast<ElementPattern*>(data);
/* if (p->type == e->type() && p->subtype != e->subtype())
qDebug("%s subtype %d does not match", e->name(), e->subtype());
*/
//TODO if ((p->type != e->type()) || (p->subtypeValid && p->subtype != e->subtype()))
if (p->type != int(e->type()))
return;
if ((p->staffStart != -1)
&& ((p->staffStart > e->staffIdx()) || (p->staffEnd <= e->staffIdx())))
return;
if (e->type() == Element::Type::CHORD || e->type() == Element::Type::REST || e->type() == Element::Type::NOTE || e->type() == Element::Type::LYRICS || e->type() == Element::Type::STEM) {
if (p->voice != -1 && p->voice != e->voice())
return;
}
if (p->system) {
Element* ee = e;
do {
if (ee->type() == Element::Type::SYSTEM) {
if (p->system != ee)
return;
break;
}
ee = ee->parent();
} while (ee);
}
p->el.append(e);
}

void Score::selectSimilar(Element* e, bool sameStaff)
{
Element::Type type = e->type();
//TODO int subtype = e->subtype();

ElementPattern pattern;
pattern.subtypeValid = true;
//TODO if (type == VOLTA_SEGMENT) {
// Volta* volta = static_cast<VoltaSegment*>(e)->volta();
// type = volta->type();
// subtype = volta->subtype();
pattern.subtypeValid = false;
// }

Score* score = e->score();
pattern.type = int(type);
pattern.subtype = 0; // TODO subtype;
pattern.staffStart = sameStaff ? e->staffIdx() : -1;
pattern.staffEnd = sameStaff ? e->staffIdx()+1 : -1;
pattern.voice = -1;
pattern.system = 0;

score->scanElements(&pattern, collectMatch);

score->select(0, SelectType::SINGLE, 0);
foreach(Element* e, pattern.el) {
score->select(e, SelectType::ADD, 0);
}
}

void Score::selectSimilarInRange(Element* e)
{
Element::Type type = e->type();
ElementPattern pattern;

Score* score = e->score();
pattern.type = int(type);
pattern.subtype = 0;
pattern.staffStart = selection().staffStart();
pattern.staffEnd = selection().staffEnd();
pattern.voice = -1;
pattern.system = 0;
pattern.subtypeValid = false;

score->scanElementsInRange(&pattern, collectMatch);

score->select(0, SelectType::SINGLE, 0);
foreach(Element* e, pattern.el) {
score->select(e, SelectType::ADD, 0);
}
}
//---------------------------------------------------------
// lassoSelect
//---------------------------------------------------------

Expand Down
4 changes: 4 additions & 0 deletions libmscore/score.h
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,9 @@ class Score : public QObject {
void getSelectedChordRest2(ChordRest** cr1, ChordRest** cr2) const;

void select(Element* obj, SelectType = SelectType::SINGLE, int staff = 0);
void selectSimilar(Element* e, bool sameStaff);
void selectSimilarInRange(Element* e);
static void collectMatch(void* data, Element* e);
void deselect(Element* obj);
void deselectAll() { _selection.deselectAll(); }
void updateSelection() { _selection.update(); }
Expand Down Expand Up @@ -818,6 +821,7 @@ class Score : public QObject {
qreal point(const Spatium sp) const { return sp.val() * spatium(); }

void scanElements(void* data, void (*func)(void*, Element*), bool all=true);
void scanElementsInRange(void* data, void (*func)(void*, Element*), bool all = true);
QByteArray buildCanonical(int track);
int fileDivision() const { return _fileDivision; } ///< division of current loading *.msc file
void splitStaff(int staffIdx, int splitPoint);
Expand Down
44 changes: 44 additions & 0 deletions libmscore/segment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -953,4 +953,48 @@ Ms::Element* Segment::elementAt(int track) const {
return e;
}

//---------------------------------------------------------
// scanElements
//---------------------------------------------------------

void Segment::scanElements(void* data, void (*func)(void*, Element*), bool all)
{
// bar line visibility depends on spanned staves,
// not simply on visibility of first staff
if (segmentType() == Segment::Type::BarLine || segmentType() == Segment::Type::EndBarLine
|| segmentType() == Segment::Type::StartRepeatBarLine) {
for (int staffIdx = 0; staffIdx < _score->nstaves(); ++staffIdx) {
Element* e = element(staffIdx*VOICES);
if (e == 0) // if no element, skip
continue;
// if staff not visible
if (!all && !(measure()->visible(staffIdx) && _score->staff(staffIdx)->show())) {
// if bar line spans just this staff...
if (static_cast<BarLine*>(e)->span() <= 1
// ...or span another staff but without entering INTO it...
|| (static_cast<BarLine*>(e)->span() < 2 &&
static_cast<BarLine*>(e)->spanTo() < 1) )
continue; // ...skip
}
e->scanElements(data, func, all);
}
}
else
for (int track = 0; track < _score->nstaves() * VOICES; ++track) {
int staffIdx = track/VOICES;
if (!all && !(measure()->visible(staffIdx) && _score->staff(staffIdx)->show())) {
track += VOICES - 1;
continue;
}
Element* e = element(track);
if (e == 0)
continue;
e->scanElements(data, func, all);
}
foreach(Element* e, annotations()) {
if (all || e->systemFlag() || measure()->visible(e->staffIdx()))
e->scanElements(data, func, all);
}
}

} // namespace Ms
1 change: 1 addition & 0 deletions libmscore/segment.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ class Segment : public Element {
void removeElement(int track);
void setElement(int track, Element* el);
const QList<Lyrics*>* lyricsList(int track) const;
virtual void scanElements(void* data, void (*func)(void*, Element*), bool all=true);

Measure* measure() const { return (Measure*)parent(); }
System* system() const { return (System*)parent()->parent(); }
Expand Down
3 changes: 2 additions & 1 deletion libmscore/select.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ struct ElementPattern {
QList<Element*> el;
int type;
int subtype;
int staff;
int staffStart;
int staffEnd; // exclusive
int voice;
const System* system;
bool subtypeValid;
Expand Down
7 changes: 7 additions & 0 deletions mscore/actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1833,6 +1833,13 @@ Shortcut Shortcut::sc[] = {
QT_TRANSLATE_NOOP("action","All Similar Elements in Same Staff"),
QT_TRANSLATE_NOOP("action","Select all similar elements in same staff")
),
Shortcut(
STATE_NORMAL | STATE_NOTE_ENTRY,
0,
"select-similar-range",
QT_TRANSLATE_NOOP("action","All Similar Elements in Range Selection"),
QT_TRANSLATE_NOOP("action","Select all similar elements in the range selection")
),
Shortcut(
STATE_NORMAL | STATE_NOTE_ENTRY | STATE_PLAY,
0,
Expand Down
71 changes: 15 additions & 56 deletions mscore/musescore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,7 @@ void MuseScore::selectionChanged(SelState selectionState)
bool enable = selectionState != SelState::NONE;
getAction("cut")->setEnabled(enable);
getAction("copy")->setEnabled(enable);
getAction("select-similar-range")->setEnabled(selectionState == SelState::RANGE);
if (pianorollEditor)
pianorollEditor->changeSelection(selectionState);
if (drumrollEditor)
Expand Down Expand Up @@ -2531,6 +2532,8 @@ void MuseScore::changeState(ScoreState val)
a->setEnabled(cs && cs->selection().state() != SelState::NONE);
else if (enable && strcmp(s->key(), "copy") == 0)
a->setEnabled(cs && cs->selection().state() != SelState::NONE);
else if (enable && strcmp(s->key(), "select-similar-range") == 0)
a->setEnabled(cs && cs->selection().state() == SelState::RANGE);
else if (enable && strcmp(s->key(), "synth-control") == 0) {
Driver* driver = seq ? seq->driver() : 0;
// a->setEnabled(driver && driver->getSynth());
Expand Down Expand Up @@ -3701,77 +3704,33 @@ void MuseScore::loadFile(const QUrl& url)
networkManager->get(QNetworkRequest(url));
}

//---------------------------------------------------------
// collectMatch
//---------------------------------------------------------

static void collectMatch(void* data, Element* e)
{
ElementPattern* p = static_cast<ElementPattern*>(data);
/* if (p->type == e->type() && p->subtype != e->subtype())
qDebug("%s subtype %d does not match", e->name(), e->subtype());
*/
//TODO if ((p->type != e->type()) || (p->subtypeValid && p->subtype != e->subtype()))
if (p->type != int(e->type()))
return;
if ((p->staff != -1) && (p->staff != e->staffIdx()))
return;
if (e->type() == Element::Type::CHORD || e->type() == Element::Type::REST || e->type() == Element::Type::NOTE || e->type() == Element::Type::LYRICS || e->type() == Element::Type::STEM) {
if (p->voice != -1 && p->voice != e->voice())
return;
}
if (p->system) {
Element* ee = e;
do {
if (ee->type() == Element::Type::SYSTEM) {
if (p->system != ee)
return;
break;
}
ee = ee->parent();
} while (ee);
}
p->el.append(e);
}

//---------------------------------------------------------
// selectSimilar
//---------------------------------------------------------

void MuseScore::selectSimilar(Element* e, bool sameStaff)
{
Element::Type type = e->type();
//TODO int subtype = e->subtype();
Score* score = e->score();
score->selectSimilar(e, sameStaff);

ElementPattern pattern;
pattern.subtypeValid = true;
//TODO if (type == VOLTA_SEGMENT) {
// Volta* volta = static_cast<VoltaSegment*>(e)->volta();
// type = volta->type();
// subtype = volta->subtype();
pattern.subtypeValid = false;
// }
if (score->selectionChanged()) {
score->setSelectionChanged(false);
SelState ss = score->selection().state();
selectionChanged(ss);
}
}

void MuseScore::selectSimilarInRange(Element* e)
{
Score* score = e->score();
pattern.type = int(type);
pattern.subtype = 0; // TODO subtype;
pattern.staff = sameStaff ? e->staffIdx() : -1;
pattern.voice = -1;
pattern.system = 0;
score->selectSimilarInRange(e);

score->scanElements(&pattern, collectMatch);

score->select(0, SelectType::SINGLE, 0);
foreach(Element* e, pattern.el) {
score->select(e, SelectType::ADD, 0);
}
if (score->selectionChanged()) {
score->setSelectionChanged(false);
SelState ss = score->selection().state();
selectionChanged(ss);
}
}

//---------------------------------------------------------
// selectElementDialog
//---------------------------------------------------------
Expand All @@ -3783,7 +3742,7 @@ void MuseScore::selectElementDialog(Element* e)
if (sd.exec()) {
ElementPattern pattern;
sd.setPattern(&pattern);
score->scanElements(&pattern, collectMatch);
score->scanElements(&pattern, Score::collectMatch);
if (sd.doReplace()) {
score->select(0, SelectType::SINGLE, 0);
foreach(Element* ee, pattern.el)
Expand Down
1 change: 1 addition & 0 deletions mscore/musescore.h
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ class MuseScore : public QMainWindow, public MuseScoreCore {

Tuplet* tupletDialog();
void selectSimilar(Element*, bool);
void selectSimilarInRange(Element* e);
void selectElementDialog(Element* e);
void transpose();

Expand Down
3 changes: 3 additions & 0 deletions mscore/scoreview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,7 @@ void ScoreView::objectPopup(const QPoint& pos, Element* obj)
QMenu* selMenu = popup->addMenu(tr("Select"));
selMenu->addAction(getAction("select-similar"));
selMenu->addAction(getAction("select-similar-staff"));
selMenu->addAction(getAction("select-similar-range"));
a = selMenu->addAction(tr("More..."));
a->setData("select-dialog");
popup->addSeparator();
Expand Down Expand Up @@ -1036,6 +1037,8 @@ void ScoreView::objectPopup(const QPoint& pos, Element* obj)
mscore->selectSimilar(obj, false);
else if (cmd == "select-similar-staff")
mscore->selectSimilar(obj, true);
else if (cmd == "select-similar-range")
mscore->selectSimilarInRange(obj);
else if (cmd == "select-dialog")
mscore->selectElementDialog(obj);
else {
Expand Down

0 comments on commit 30b93f5

Please sign in to comment.