summaryrefslogtreecommitdiff
path: root/utils/regtools/qeditor/aux.cpp
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2014-04-07 11:28:04 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2014-05-01 19:34:18 +0200
commit4356666101e0e7985e65a19f86bc4a74519e93f9 (patch)
treebf8de8057d93d0fab0a30cae92a90f5a4edc79dc /utils/regtools/qeditor/aux.cpp
parent3754624edc48539c5cc5acbf426ce909477e87d8 (diff)
downloadrockbox-4356666101e0e7985e65a19f86bc4a74519e93f9.tar.gz
rockbox-4356666101e0e7985e65a19f86bc4a74519e93f9.zip
regtools: completely rework qeditor, improve soc desc library and tools
The graphical editor can now display and editor description files. The library has been improved to provide more useful function. The XML format has been slightly changed: only one soc is allowed per file (this is was already de facto the case since <soc> was the root tag). Also introduce a DTD to validate the files. Change-Id: If70ba35b6dc0242bdb87411cf4baee9597798aac
Diffstat (limited to 'utils/regtools/qeditor/aux.cpp')
-rw-r--r--utils/regtools/qeditor/aux.cpp746
1 files changed, 746 insertions, 0 deletions
diff --git a/utils/regtools/qeditor/aux.cpp b/utils/regtools/qeditor/aux.cpp
new file mode 100644
index 0000000000..0614bb57f6
--- /dev/null
+++ b/utils/regtools/qeditor/aux.cpp
@@ -0,0 +1,746 @@
1#include "aux.h"
2#include <QFontMetrics>
3#include <QPainter>
4#include <QTextDocument>
5#include <QAbstractTextDocumentLayout>
6#include <QHeaderView>
7#include <QDebug>
8#include <QElapsedTimer>
9#include <QXmlStreamReader>
10#include <QXmlStreamWriter>
11#include <QTextBlock>
12
13/**
14 * SocBitRangeValidator
15 */
16SocBitRangeValidator::SocBitRangeValidator(QObject *parent)
17 :QValidator(parent)
18{
19}
20
21void SocBitRangeValidator::fixup(QString& input) const
22{
23 input = input.trimmed();
24}
25
26QValidator::State SocBitRangeValidator::validate(QString& input, int& pos) const
27{
28 Q_UNUSED(pos);
29 int first, last;
30 State state = parse(input, last, first);
31 return state;
32}
33
34QValidator::State SocBitRangeValidator::parse(const QString& input, int& last, int& first) const
35{
36 // the empty string is always intermediate
37 if(input.size() == 0)
38 return Intermediate;
39 // check if there is ':'
40 int pos = input.indexOf(':');
41 if(pos == -1)
42 pos = input.size();
43 // if field start with ':', the last bit is implicit and is 31
44 if(pos > 0)
45 {
46 // parse last bit and check it's between 0 and 31
47 bool ok = false;
48 last = input.left(pos).toInt(&ok);
49 if(!ok || last < 0 || last >= 32)
50 return Invalid;
51 }
52 else
53 last = 31;
54 // parse first bit
55 if(pos < input.size() - 1)
56 {
57 bool ok = false;
58 first = input.mid(pos + 1).toInt(&ok);
59 if(!ok || first < 0 || first > last)
60 return Invalid;
61 }
62 // if input ends with ':', first bit is implicit and is 0
63 else if(pos == input.size() - 1)
64 first = 0;
65 // if there no ':', first=last
66 else
67 first = last;
68 return Acceptable;
69}
70
71/**
72 * SocFieldValidator
73 */
74
75SocFieldValidator::SocFieldValidator(QObject *parent)
76 :QValidator(parent)
77{
78 m_field.first_bit = 0;
79 m_field.last_bit = 31;
80}
81
82SocFieldValidator::SocFieldValidator(const soc_reg_field_t& field, QObject *parent)
83 :QValidator(parent), m_field(field)
84{
85}
86
87void SocFieldValidator::fixup(QString& input) const
88{
89 input = input.trimmed();
90}
91
92QValidator::State SocFieldValidator::validate(QString& input, int& pos) const
93{
94 Q_UNUSED(pos);
95 soc_word_t val;
96 State state = parse(input, val);
97 return state;
98}
99
100QValidator::State SocFieldValidator::parse(const QString& input, soc_word_t& val) const
101{
102 // the empty string is always intermediate
103 if(input.size() == 0)
104 return Intermediate;
105 // first check named values
106 State state = Invalid;
107 foreach(const soc_reg_field_value_t& value, m_field.value)
108 {
109 QString name = QString::fromLocal8Bit(value.name.c_str());
110 // cannot be a substring if too long or empty
111 if(input.size() > name.size())
112 continue;
113 // check equal string
114 if(input == name)
115 {
116 state = Acceptable;
117 val = value.value;
118 break;
119 }
120 // check substring
121 if(name.startsWith(input))
122 state = Intermediate;
123 }
124 // early return for exact match
125 if(state == Acceptable)
126 return state;
127 // do a few special cases for convenience
128 if(input.compare("0x", Qt::CaseInsensitive) == 0 ||
129 input.compare("0b", Qt::CaseInsensitive) == 0)
130 return Intermediate;
131 // try by parsing
132 unsigned basis, pos;
133 if(input.size() >= 2 && input.startsWith("0x", Qt::CaseInsensitive))
134 {
135 basis = 16;
136 pos = 2;
137 }
138 else if(input.size() >= 2 && input.startsWith("0b", Qt::CaseInsensitive))
139 {
140 basis = 2;
141 pos = 2;
142 }
143 else if(input.size() >= 2 && input.startsWith("0"))
144 {
145 basis = 8;
146 pos = 1;
147 }
148 else
149 {
150 basis = 10;
151 pos = 0;
152 }
153 bool ok = false;
154 unsigned long v = input.mid(pos).toULong(&ok, basis);
155 // if not ok, return result of name parsing
156 if(!ok)
157 return state;
158 // if ok, check if it fits in the number of bits
159 unsigned nr_bits = m_field.last_bit - m_field.first_bit + 1;
160 unsigned long max = nr_bits == 32 ? 0xffffffff : (1 << nr_bits) - 1;
161 if(v <= max)
162 {
163 val = v;
164 return Acceptable;
165 }
166
167 return state;
168}
169
170/**
171 * RegLineEdit
172 */
173RegLineEdit::RegLineEdit(QWidget *parent)
174 :QWidget(parent)
175{
176 m_layout = new QHBoxLayout(this);
177 m_button = new QToolButton(this);
178 m_button->setCursor(Qt::ArrowCursor);
179 m_button->setStyleSheet("QToolButton { font-weight: bold; color: white; background: black; }");
180 m_button->setPopupMode(QToolButton::InstantPopup);
181 m_edit = new QLineEdit(this);
182 m_layout->addWidget(m_button);
183 m_layout->addWidget(m_edit);
184 m_menu = new QMenu(this);
185 connect(m_menu->addAction("Write"), SIGNAL(triggered()), this, SLOT(OnWriteAct()));
186 connect(m_menu->addAction("Set"), SIGNAL(triggered()), this, SLOT(OnSetAct()));
187 connect(m_menu->addAction("Clear"), SIGNAL(triggered()), this, SLOT(OnClearAct()));
188 connect(m_menu->addAction("Toggle"), SIGNAL(triggered()), this, SLOT(OnToggleAct()));
189 EnableSCT(false);
190 SetReadOnly(false);
191 ShowMode(true);
192 SetMode(Write);
193}
194
195void RegLineEdit::SetReadOnly(bool ro)
196{
197 m_edit->setReadOnly(ro);
198 m_readonly = ro;
199 ShowMode(!ro);
200}
201
202void RegLineEdit::EnableSCT(bool en)
203{
204 m_has_sct = en;
205 if(!m_has_sct)
206 {
207 m_button->setMenu(0);
208 SetMode(Write);
209 }
210 else
211 m_button->setMenu(m_menu);
212}
213
214RegLineEdit::~RegLineEdit()
215{
216}
217
218QLineEdit *RegLineEdit::GetLineEdit()
219{
220 return m_edit;
221}
222
223void RegLineEdit::ShowMode(bool show)
224{
225 if(show)
226 m_button->show();
227 else
228 m_button->hide();
229}
230
231void RegLineEdit::OnWriteAct()
232{
233 SetMode(Write);
234}
235
236void RegLineEdit::OnSetAct()
237{
238 SetMode(Set);
239}
240
241void RegLineEdit::OnClearAct()
242{
243 SetMode(Clear);
244}
245
246void RegLineEdit::OnToggleAct()
247{
248 SetMode(Toggle);
249}
250
251void RegLineEdit::SetMode(EditMode mode)
252{
253 m_mode = mode;
254 switch(m_mode)
255 {
256 case Write: m_button->setText("WR"); break;
257 case Set: m_button->setText("SET"); break;
258 case Clear: m_button->setText("CLR"); break;
259 case Toggle: m_button->setText("TOG"); break;
260 default: break;
261 }
262}
263
264RegLineEdit::EditMode RegLineEdit::GetMode()
265{
266 return m_mode;
267}
268
269void RegLineEdit::setText(const QString& text)
270{
271 m_edit->setText(text);
272}
273
274QString RegLineEdit::text() const
275{
276 return m_edit->text();
277}
278
279/**
280 * SocFieldItemDelegate
281 */
282
283QString SocFieldItemDelegate::displayText(const QVariant& value, const QLocale& locale) const
284{
285 if(value.type() == QVariant::UInt)
286 return QString("0x%1").arg(value.toUInt(), (m_bitcount + 3) / 4, 16, QChar('0'));
287 else
288 return QStyledItemDelegate::displayText(value, locale);
289}
290
291/**
292 * SocFieldEditor
293 */
294SocFieldEditor::SocFieldEditor(const soc_reg_field_t& field, QWidget *parent)
295 :QLineEdit(parent), m_reg_field(field)
296{
297 m_validator = new SocFieldValidator(field);
298 setValidator(m_validator);
299}
300
301SocFieldEditor::~SocFieldEditor()
302{
303 delete m_validator;
304}
305
306uint SocFieldEditor::field() const
307{
308 soc_word_t v;
309 /* in case validator fails to parse, return old value */
310 if(m_validator->parse(text(), v) == QValidator::Acceptable)
311 return v;
312 else
313 return m_field;
314}
315
316void SocFieldEditor::setField(uint field)
317{
318 m_field = field;
319 int digits = (m_reg_field.last_bit - m_reg_field.first_bit + 4) / 4;
320 setText(QString("0x%1").arg(field, digits, 16, QChar('0')));
321}
322
323/**
324 * SocFieldEditorCreator
325 */
326QWidget *SocFieldEditorCreator::createWidget(QWidget *parent) const
327{
328 return new SocFieldEditor(m_field, parent);
329}
330
331QByteArray SocFieldEditorCreator::valuePropertyName() const
332{
333 return QByteArray("field");
334}
335
336/**
337 * RegSexyDisplay
338 */
339RegSexyDisplay::RegSexyDisplay(const SocRegRef& reg, QWidget *parent)
340 :QWidget(parent), m_reg(reg)
341{
342 m_size = QSize();
343}
344
345int RegSexyDisplay::separatorSize() const
346{
347 return 1;
348}
349
350int RegSexyDisplay::marginSize() const
351{
352 return fontMetrics().height() / 3;
353}
354
355int RegSexyDisplay::textSep() const
356{
357 return marginSize() / 2;
358}
359
360int RegSexyDisplay::headerHeight() const
361{
362 return 2 * marginSize() + textSep() + 2 * fontMetrics().height();
363}
364
365int RegSexyDisplay::columnWidth() const
366{
367 return 2 * marginSize() + fontMetrics().height();
368}
369
370int RegSexyDisplay::maxContentHeight() const
371{
372 int max = 0;
373 QFontMetrics metrics = fontMetrics();
374 for(size_t i = 0; i < m_reg.GetReg().field.size(); i++)
375 {
376 QString s = QString::fromStdString(m_reg.GetReg().field[i].name);
377 // add extra spaces arounds
378 s = " " + s + " ";
379 max = qMax(max, metrics.boundingRect(s).width());
380 }
381 return 2 * marginSize() + max;
382}
383
384int RegSexyDisplay::gapHeight() const
385{
386 return marginSize() / 2;
387}
388
389QSize RegSexyDisplay::minimumSizeHint() const
390{
391 /* cache computation because it's expensive */
392 if(m_size.isValid())
393 return m_size;
394 /* width: display 32 columns + 33 vertical separators */
395 m_size.setWidth(32 * columnWidth() + 33 * separatorSize());
396 /* height: one separator + two digits + one separator + margin + separator
397 * + names + separator */
398 m_size.setHeight(4 * separatorSize() + headerHeight() + gapHeight() + maxContentHeight());
399 return m_size;
400}
401
402QSize RegSexyDisplay::sizeHint() const
403{
404 return minimumSizeHint();
405}
406
407void RegSexyDisplay::paintEvent(QPaintEvent *event)
408{
409 // FIXME could be optimised with QStaticText
410 Q_UNUSED(event);
411 int txt_h = fontMetrics().height();
412 int sep_sz = separatorSize();
413 int w = width();
414 int h = height() - 1;
415 int col_w = (w - 33 * sep_sz) / 32;
416 int hdr_h = headerHeight();
417 int gap_h = gapHeight();
418 int tot_w = 33 * sep_sz + 32 * col_w;
419 int margin = marginSize();
420 int txt_sep = textSep();
421 int tot_hdr_sz = 2 * sep_sz + hdr_h;
422 // computer xshift
423 int x_shift = (w - tot_w) / 2;
424#define ith_col_x(i) (x_shift + (i) * (sep_sz + col_w))
425
426 QPainter painter(this);
427 QBrush back_brush = palette().base();
428 QBrush line_brush = palette().dark();
429
430 // fill interesting zone with base
431 painter.fillRect(x_shift, 0, tot_w, h, back_brush);
432
433 // draw top and bottom lines
434 painter.setPen(QPen(palette().dark(), sep_sz));
435 painter.fillRect(x_shift, 0, tot_w, sep_sz, line_brush);
436 painter.fillRect(x_shift, h - sep_sz, tot_w, sep_sz, line_brush);
437 // draw intemediate lines
438 for(int i = 0; i <= 32; i++)
439 painter.fillRect(ith_col_x(i), 0, sep_sz, 2 * sep_sz + hdr_h, line_brush);
440 // draw bottom header lines
441 painter.fillRect(ith_col_x(0), sep_sz + hdr_h, tot_w, sep_sz, line_brush);
442 painter.fillRect(ith_col_x(0), tot_hdr_sz + gap_h, tot_w, sep_sz, line_brush);
443 // redraw some lines but wider
444 for(int i = 4; i < 32; i += 4)
445 painter.fillRect(ith_col_x(i) - sep_sz, 0, 3 * sep_sz, tot_hdr_sz, line_brush);
446 // draw numbers in the header
447 painter.setPen(palette().brush(QPalette::ButtonText).color());
448 for(int i = 0; i < 32; i++)
449 {
450 QRect r(ith_col_x(i), sep_sz + margin, col_w, txt_h);
451 painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) / 10));
452 r.translate(0, txt_h + txt_sep);
453 painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) % 10));
454 }
455 // display content
456 for(size_t i = 0; i < m_reg.GetReg().field.size(); i++)
457 {
458 const soc_reg_field_t& field = m_reg.GetReg().field[i];
459 QRect r(QPoint(ith_col_x(31 - field.last_bit) + sep_sz, tot_hdr_sz),
460 QPoint(ith_col_x(32 - field.first_bit), h - sep_sz));
461 painter.fillRect(r.x() - sep_sz, r.y(), sep_sz, r.height(), line_brush);
462 painter.fillRect(r.right(), r.y(), sep_sz, r.height(), line_brush);
463 r.setY(r.y() + gap_h + sep_sz);
464 // draw rotated text
465 painter.save();
466 painter.translate(r.bottomLeft());
467 painter.rotate(-90);
468 //painter.fillRect(QRect(0, 0, r.height(), r.width()), QBrush(Qt::red));
469 QRect r2(0, 0, r.height(), r.width());
470 painter.drawText(r2, Qt::AlignCenter, QString::fromStdString(field.name));
471 painter.restore();
472 }
473#undef ith_col_x
474}
475
476/**
477 * GrowingTextEdit
478 */
479GrowingTextEdit::GrowingTextEdit(QWidget *parent)
480 :QTextEdit(parent)
481{
482 connect(this, SIGNAL(textChanged()), this, SLOT(TextChanged()));
483 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
484 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
485}
486
487void GrowingTextEdit::TextChanged()
488{
489 int content_size = document()->documentLayout()->documentSize().height();
490 content_size = qMax(content_size, fontMetrics().height());
491 setFixedHeight(content_size + contentsMargins().top() + contentsMargins().bottom());
492}
493
494/**
495 * GrowingTableWidget
496 */
497GrowingTableWidget::GrowingTableWidget(QWidget *parent)
498 :QTableWidget(parent)
499{
500 connect(model(), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
501 this, SLOT(DataChanged(const QModelIndex&, const QModelIndex&)));
502}
503
504void GrowingTableWidget::DataChanged(const QModelIndex& tl, const QModelIndex& br)
505{
506 Q_UNUSED(tl);
507 Q_UNUSED(br);
508 resizeRowsToContents();
509 resizeColumnsToContents();
510 int h = contentsMargins().top() + contentsMargins().bottom();
511 h += horizontalHeader()->height();
512 for(int i = 0; i < rowCount(); i++)
513 h += rowHeight(i);
514 setMinimumHeight(h);
515}
516
517/**
518 * MyTextEditor
519 */
520MyTextEditor::MyTextEditor(QWidget *parent)
521 :QWidget(parent)
522{
523 QVBoxLayout *layout = new QVBoxLayout;
524 m_toolbar = new QToolBar(this);
525 m_edit = new QTextEdit(this);
526 layout->addWidget(m_toolbar, 0);
527 layout->addWidget(m_edit, 1);
528 setLayout(layout);
529 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
530
531 m_edit->setAcceptRichText(false);
532 m_edit->setAutoFormatting(QTextEdit::AutoAll);
533
534 m_bold_button = new QToolButton(this);
535 m_bold_button->setIcon(QIcon::fromTheme("format-text-bold"));
536 m_bold_button->setText("bold");
537 m_bold_button->setCheckable(true);
538
539 m_italic_button = new QToolButton(this);
540 m_italic_button->setIcon(QIcon::fromTheme("format-text-italic"));
541 m_italic_button->setText("italic");
542 m_italic_button->setCheckable(true);
543
544 m_underline_button = new QToolButton(this);
545 m_underline_button->setIcon(QIcon::fromTheme("format-text-underline"));
546 m_underline_button->setText("underline");
547 m_underline_button->setCheckable(true);
548
549 m_toolbar->addWidget(m_bold_button);
550 m_toolbar->addWidget(m_italic_button);
551 m_toolbar->addWidget(m_underline_button);
552
553 connect(m_bold_button, SIGNAL(toggled(bool)), this, SLOT(OnTextBold(bool)));
554 connect(m_italic_button, SIGNAL(toggled(bool)), this, SLOT(OnTextItalic(bool)));
555 connect(m_underline_button, SIGNAL(toggled(bool)), this, SLOT(OnTextUnderline(bool)));
556 connect(m_edit, SIGNAL(textChanged()), this, SLOT(OnInternalTextChanged()));
557 connect(m_edit, SIGNAL(currentCharFormatChanged(const QTextCharFormat&)),
558 this, SLOT(OnCharFormatChanged(const QTextCharFormat&)));
559
560 SetGrowingMode(false);
561 SetReadOnly(false);
562}
563
564void MyTextEditor::SetReadOnly(bool en)
565{
566 m_read_only = en;
567 if(en)
568 m_toolbar->hide();
569 else
570 m_toolbar->hide();
571 m_edit->setReadOnly(en);
572}
573
574void MyTextEditor::SetGrowingMode(bool en)
575{
576 m_growing_mode = en;
577 if(en)
578 {
579 m_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
580 m_edit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
581 OnTextChanged();
582 }
583 else
584 {
585 m_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
586 m_edit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
587 }
588}
589
590void MyTextEditor::OnInternalTextChanged()
591{
592 if(m_growing_mode)
593 {
594 int content_size = m_edit->document()->documentLayout()->documentSize().height();
595 content_size = qMax(content_size, m_edit->fontMetrics().height());
596 m_edit->setMinimumHeight(content_size + m_edit->contentsMargins().top() +
597 m_edit->contentsMargins().bottom());
598 }
599 emit OnTextChanged();
600}
601
602void MyTextEditor::OnTextBold(bool checked)
603{
604 QTextCursor cursor = m_edit->textCursor();
605 QTextCharFormat fmt = cursor.charFormat();
606 fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal);
607 cursor.setCharFormat(fmt);
608 m_edit->setTextCursor(cursor);
609}
610
611void MyTextEditor::OnTextItalic(bool checked)
612{
613 QTextCursor cursor = m_edit->textCursor();
614 QTextCharFormat fmt = cursor.charFormat();
615 fmt.setFontItalic(checked);
616 cursor.setCharFormat(fmt);
617 m_edit->setTextCursor(cursor);
618}
619
620void MyTextEditor::OnTextUnderline(bool checked)
621{
622 QTextCursor cursor = m_edit->textCursor();
623 QTextCharFormat fmt = cursor.charFormat();
624 fmt.setFontUnderline(checked);
625 cursor.setCharFormat(fmt);
626 m_edit->setTextCursor(cursor);
627}
628
629void MyTextEditor::OnCharFormatChanged(const QTextCharFormat& fmt)
630{
631 /* NOTE: changing the button states programmaticaly doesn't trigger
632 * the toggled() signals, otherwise it would result in a loop
633 * between this function and OnText{Bold,Italic,Underline,...} */
634 m_bold_button->setChecked(fmt.fontWeight() > QFont::Normal);
635 m_italic_button->setChecked(fmt.fontItalic());
636 m_underline_button->setChecked(fmt.fontUnderline());
637}
638
639void MyTextEditor::SetTextHtml(const QString& text)
640{
641 m_edit->setHtml(text);
642}
643
644QString MyTextEditor::GetTextHtml()
645{
646 return m_edit->toPlainText();
647}
648
649bool MyTextEditor::IsModified()
650{
651 return m_edit->document()->isModified();
652}
653
654/**
655 * MySwitchableTextEditor
656 */
657MySwitchableTextEditor::MySwitchableTextEditor(QWidget *parent)
658 :QWidget(parent)
659{
660 QVBoxLayout *layout = new QVBoxLayout(this);
661 m_edit = new MyTextEditor(this);
662 m_label = new QLabel(this);
663 m_label->setTextFormat(Qt::RichText);
664 m_label->setAlignment(Qt::AlignTop);
665 m_line = new QLineEdit(this);
666
667 layout->addWidget(m_label);
668 layout->addWidget(m_edit);
669 layout->addWidget(m_line);
670
671 setLayout(layout);
672
673 m_editor_mode = false;
674 m_line_mode = false;
675 UpdateVisibility();
676}
677
678void MySwitchableTextEditor::SetEditorMode(bool edit)
679{
680 if(edit == m_editor_mode)
681 return;
682 QString text = GetTextHtml();
683 m_editor_mode = edit;
684 UpdateVisibility();
685 SetTextHtml(text);
686}
687
688QString MySwitchableTextEditor::GetTextHtml()
689{
690 if(m_editor_mode)
691 return m_line_mode ? m_line->text() : m_edit->GetTextHtml();
692 else
693 return m_label->text();
694}
695
696void MySwitchableTextEditor::SetTextHtml(const QString& text)
697{
698 if(m_editor_mode)
699 {
700 if(m_line_mode)
701 m_line->setText(text);
702 else
703 m_edit->SetTextHtml(text);
704 }
705 else
706 m_label->setText(text);
707}
708
709MyTextEditor *MySwitchableTextEditor::GetEditor()
710{
711 return m_edit;
712}
713
714void MySwitchableTextEditor::SetLineMode(bool en)
715{
716 if(m_line_mode == en)
717 return;
718 QString text = GetTextHtml();
719 m_line_mode = en;
720 SetTextHtml(text);
721 UpdateVisibility();
722}
723
724QLineEdit *MySwitchableTextEditor::GetLineEdit()
725{
726 return m_line;
727}
728
729void MySwitchableTextEditor::UpdateVisibility()
730{
731 m_label->setVisible(!m_editor_mode);
732 m_edit->setVisible(m_editor_mode && !m_line_mode);
733 m_line->setVisible(m_editor_mode && m_line_mode);
734}
735
736QLabel *MySwitchableTextEditor::GetLabel()
737{
738 return m_label;
739}
740
741bool MySwitchableTextEditor::IsModified()
742{
743 if(!m_editor_mode)
744 return false;
745 return m_line_mode ? m_line->isModified() : m_edit->IsModified();
746}