Fix #25060 - Fix FiguredBass creating, editing and displaying.

After the recent changes to Text styling and editing, FiguredBass has been broken. This patch attempts to fix it.

As the current Text in-place editor insists in inserting spurious (and sometime wrong) HTML markup and styling which jeopardize the parsing of FiguredBassItem's, I have modified the FiguredBass endEdit() callback function to discard all HTML and keep only the plain text.

This may reduce the flexibility of entering extra indications in FiguredBass elements, but ensure that properly structured texts are parsed and recognized.

The patch also corrects two points in text.cpp which forced extra HTML formatting to be inserted.
This commit is contained in:
Maurizio M. Gavioli 2014-03-28 01:23:44 +01:00
parent 4a780b308e
commit 0a05faddb5
3 changed files with 63 additions and 50 deletions

View file

@ -989,70 +989,65 @@ void FiguredBass::read(XmlReader& e)
void FiguredBass::layout() void FiguredBass::layout()
{ {
// qreal y; qreal yOff = score()->styleD(ST_figuredBassYOffset);
qreal _sp = spatium();
// if 'our' style, force 'our' style data from FiguredBass parameters // if 'our' style, force 'our' style data from FiguredBass parameters
if(textStyleType() == TEXT_STYLE_FIGURED_BASS) { if(textStyleType() == TEXT_STYLE_FIGURED_BASS) {
TextStyle st("Figured Bass", g_FBFonts[0].family, score()->styleD(ST_figuredBassFontSize), TextStyle st("Figured Bass", g_FBFonts[0].family, score()->styleD(ST_figuredBassFontSize),
false, false, false, ALIGN_LEFT | ALIGN_TOP, QPointF(0, score()->styleD(ST_figuredBassYOffset)), false, false, false, ALIGN_LEFT | ALIGN_TOP, QPointF(0, yOff),
OFFSET_SPATIUM); OFFSET_SPATIUM);
st.setSizeIsSpatiumDependent(true); st.setSizeIsSpatiumDependent(true);
setTextStyle(st); setTextStyle(st);
} }
Text::layout(); // Text and/or SimpleText may expect some internal data to be setup
// if style has been changed (or text not styled), do nothing else, keeping default laying out and formatting // if in edit mode or if style has been changed,
if(textStyleType() != TEXT_STYLE_FIGURED_BASS) // do nothing else, keeping default laying out and formatting
if(editMode() || textStyleType() != TEXT_STYLE_FIGURED_BASS) {
Text::layout();
return; return;
}
// bounding box // VERTICAL POSITION:
if(editMode()) { yOff *= _sp; // convert spatium value to raster units
qreal h, w, w1; // if any staff, add staff y-offset
QFontMetricsF fm(textStyle().font(spatium())); if (parent() && parent()->type() == SEGMENT) {
// box width Segment* s = static_cast<Segment*>(parent());
w = 0; System* system = s->measure()->system();
QStringList list = text().split('\n'); if (system) {
foreach(QString str, list) { SysStaff* sstaff = system->staff(staffIdx());
w1 = fm.width(str); yOff += sstaff->y();
if(w1 > w)
w = w1;
}
// bbox height
h = fm.lineSpacing();
h *= score()->styleD(ST_figuredBassLineHeight);
h *= (list.size() > 1 ? list.size() : 1); // at least 1 line
// ready to set position and bbox
// setPos(0, y);
bbox().setRect(0-2, 0-2, w+4, h+4);
}
else {
// if element could be parsed into items, layout each element
if(items.size() > 0) {
layoutLines();
bbox().setRect(0, 0, _lineLenghts.at(0), 0);
// layout each item and enlarge bbox to include items bboxes
for(int i=0; i < items.size(); i++) {
items[i].layout();
addbbox(items[i].bbox().translated(items[i].pos()));
}
} }
} }
setPos(QPointF(0.0, yOff));
// adjustReadPos(); // already taken into account by Text::layout() // BOUNDING BOX and individual item layout (if requried)
createLayout(); // prepare structs and data expected by Text methods
// if element could be parsed into items, layout each element
if(items.size() > 0) {
layoutLines();
bbox().setRect(0, 0, _lineLenghts.at(0), 0);
// layout each item and enlarge bbox to include items bboxes
for(int i=0; i < items.size(); i++) {
items[i].layout();
addbbox(items[i].bbox().translated(items[i].pos()));
}
}
adjustReadPos();
} }
//--------------------------------------------------------- //---------------------------------------------------------
// layoutLines // layoutLines
// //
// lays out the duration indicator line(s), filling the _lineLengths array // lays out the duration indicator line(s), filling the _lineLengths array
// and the length of printed lines (used by continuation lines)
//--------------------------------------------------------- //---------------------------------------------------------
void FiguredBass::layoutLines() void FiguredBass::layoutLines()
{ {
if(_ticks <= 0) { if(_ticks <= 0) {
NoLen: NoLen:
_lineLenghts.resize(1); _lineLenghts.resize(1); // be sure to always have
_lineLenghts[0] = 0; _lineLenghts[0] = 0; // at least 1 item in array
return; return;
} }
@ -1131,23 +1126,24 @@ qDebug("FiguredBass: duration indicator end line not implemented");
void FiguredBass::draw(QPainter* painter) const void FiguredBass::draw(QPainter* painter) const
{ {
// if not printing, draw duration line(s) // if neither edit mode or printing, draw duration line(s)
if( !score()->printing() ) { if( !editMode() && !score()->printing() ) {
foreach(qreal len, _lineLenghts) foreach(qreal len, _lineLenghts)
if(len > 0) { if(len > 0) {
painter->setPen(QPen(Qt::lightGray, 1)); painter->setPen(QPen(Qt::lightGray, 1));
painter->drawLine(0.0, -2, len, -2); // -2: 2 rast. un. above digits painter->drawLine(0.0, -2, len, -2); // -2: 2 rast. un. above digits
} }
} }
// if in edit mode or with custom style, use default drawing // if in edit mode or with custom style, use standard text drawing
if(editMode() || textStyleType() != TEXT_STYLE_FIGURED_BASS) if(editMode() || textStyleType() != TEXT_STYLE_FIGURED_BASS)
Text::draw(painter); Text::draw(painter);
// not edit mode:
else { else {
if(items.size() < 1) if(items.size() < 1) // if not parseable into f.b. items
Text::draw(painter); Text::draw(painter); // draw as standard text
else else
foreach(FiguredBassItem item, items) { foreach(FiguredBassItem item, items) { // if parseable into f.b. items
painter->translate(item.pos()); painter->translate(item.pos()); // draw each item in its proper position
item.draw(painter); item.draw(painter);
painter->translate(-item.pos()); painter->translate(-item.pos());
} }
@ -1160,16 +1156,25 @@ void FiguredBass::draw(QPainter* painter) const
} }
//--------------------------------------------------------- //---------------------------------------------------------
// endEdit // startEdit / edit / endEdit
//--------------------------------------------------------- //---------------------------------------------------------
void FiguredBass::startEdit(MuseScoreView * msv, const QPointF & pt)
{
Text::layout(); // convert layout to standard Text conventions
Text::startEdit(msv, pt);
}
void FiguredBass::endEdit() void FiguredBass::endEdit()
{ {
int idx; int idx;
Text::endEdit(); Text::endEdit();
QString txt = text(); // as the standard text editor keeps inserting spurious HTML formatting and styles
// retrieve and work only on the plain text
QString txt = plainText();
if(txt.isEmpty()) { // if no text, nothing to do if(txt.isEmpty()) { // if no text, nothing to do
setText(txt); // clear the stored text: the empty f.b. element will be deleted
return; return;
} }

View file

@ -278,11 +278,13 @@ class FiguredBass : public Text {
virtual FiguredBass* clone() const { return new FiguredBass(*this); } virtual FiguredBass* clone() const { return new FiguredBass(*this); }
virtual ElementType type() const { return FIGURED_BASS; } virtual ElementType type() const { return FIGURED_BASS; }
virtual void draw(QPainter* painter) const; virtual void draw(QPainter* painter) const;
// virtual bool edit(MuseScoreView*msv, int currGrip, int key, Qt::KeyboardModifiers modifiers, const QString& _s);
virtual void endEdit(); virtual void endEdit();
virtual void layout(); virtual void layout();
virtual void read(XmlReader&); virtual void read(XmlReader&);
virtual void setSelected(bool f); virtual void setSelected(bool f);
virtual void setVisible(bool f); virtual void setVisible(bool f);
virtual void startEdit(MuseScoreView *msv, const QPointF &pt);
virtual void write(Xml& xml) const; virtual void write(Xml& xml) const;
// read / write MusicXML // read / write MusicXML

View file

@ -1335,6 +1335,8 @@ void Text::genText()
for (const TextBlock& block : _layout) { for (const TextBlock& block : _layout) {
for (const TextFragment& f : block.fragments()) { for (const TextFragment& f : block.fragments()) {
if (f.text.isEmpty()) // skip empty fragments, not to
continue; // insert extra HTML formatting
const CharFormat& format = f.format; const CharFormat& format = f.format;
if (format.type() == CharFormatType::TEXT) { if (format.type() == CharFormatType::TEXT) {
if (cursor.format()->bold() != format.bold()) { if (cursor.format()->bold() != format.bold()) {
@ -1467,16 +1469,20 @@ bool Text::edit(MuseScoreView*, int, int key, Qt::KeyboardModifiers modifiers, c
switch (key) { switch (key) {
case Qt::Key_Enter: case Qt::Key_Enter:
case Qt::Key_Return: case Qt::Key_Return:
{
if (_cursor.hasSelection()) if (_cursor.hasSelection())
deleteSelectedText(); deleteSelectedText();
CharFormat* charFmt = _cursor.format(); // take current format
_layout.insert(_cursor.line() + 1, curLine().split(_cursor.column())); _layout.insert(_cursor.line() + 1, curLine().split(_cursor.column()));
_layout[_cursor.line()].setEol(true); _layout[_cursor.line()].setEol(true);
_cursor.setLine(_cursor.line() + 1); _cursor.setLine(_cursor.line() + 1);
_cursor.setColumn(0); _cursor.setColumn(0);
_cursor.setFormat(*charFmt); // restore orig. format at new line
s.clear(); s.clear();
_cursor.clearSelection(); _cursor.clearSelection();
break; break;
}
case Qt::Key_Backspace: case Qt::Key_Backspace:
if (_cursor.hasSelection()) if (_cursor.hasSelection())
@ -1495,13 +1501,13 @@ bool Text::edit(MuseScoreView*, int, int key, Qt::KeyboardModifiers modifiers, c
break; break;
case Qt::Key_Left: case Qt::Key_Left:
if (!movePosition(ctrlPressed ? QTextCursor::StartOfLine : QTextCursor::Left, mm) && (type() == LYRICS || type() == FIGURED_BASS)) if (!movePosition(ctrlPressed ? QTextCursor::StartOfLine : QTextCursor::Left, mm) && type() == LYRICS)
return false; return false;
s.clear(); s.clear();
break; break;
case Qt::Key_Right: case Qt::Key_Right:
if (!movePosition(ctrlPressed ? QTextCursor::EndOfLine : QTextCursor::Right, mm) && (type() == LYRICS || type() == FIGURED_BASS)) if (!movePosition(ctrlPressed ? QTextCursor::EndOfLine : QTextCursor::Right, mm) && type() == LYRICS)
return false; return false;
s.clear(); s.clear();
break; break;