summaryrefslogtreecommitdiff
path: root/utils/regtools/qeditor/utils.cpp
diff options
context:
space:
mode:
authorDmitry Gamza <gamzad@yahoo.com>2014-05-12 09:59:24 +0400
committerAmaury Pouly <amaury.pouly@gmail.com>2014-05-12 19:05:19 +0200
commit440ff9500bc74cc278e0b66f528cfdf624547240 (patch)
treeeed9c67fa3d282e33821267ca0d7d94bb97dc7e7 /utils/regtools/qeditor/utils.cpp
parent7b590a953639714cf8ea4b550dd7f6558698e23f (diff)
downloadrockbox-440ff9500bc74cc278e0b66f528cfdf624547240.tar.gz
rockbox-440ff9500bc74cc278e0b66f528cfdf624547240.zip
qeditor: on Windows it’s not impossible to create a file with AUX
Change-Id: Ic7ef01328eccbed4afddb0a09d2afbb6c1f6a28f Reviewed-on: http://gerrit.rockbox.org/811 Reviewed-by: Amaury Pouly <amaury.pouly@gmail.com>
Diffstat (limited to 'utils/regtools/qeditor/utils.cpp')
-rw-r--r--utils/regtools/qeditor/utils.cpp800
1 files changed, 800 insertions, 0 deletions
diff --git a/utils/regtools/qeditor/utils.cpp b/utils/regtools/qeditor/utils.cpp
new file mode 100644
index 0000000000..1662169bdb
--- /dev/null
+++ b/utils/regtools/qeditor/utils.cpp
@@ -0,0 +1,800 @@
1#include "utils.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 * SocFieldCachedItemDelegate
325 */
326
327QString SocFieldCachedItemDelegate::displayText(const QVariant& value, const QLocale& locale) const
328{
329 // FIXME see QTBUG-30392
330 if(value.type() == QVariant::UserType && value.userType() == qMetaTypeId< SocFieldCachedValue >())
331 {
332 const SocFieldCachedValue& v = value.value< SocFieldCachedValue >();
333 int bitcount = v.field().last_bit - v.field().first_bit;
334 return QString("0x%1").arg(v.value(), (bitcount + 3) / 4, 16, QChar('0'));
335 }
336 else
337 return QStyledItemDelegate::displayText(value, locale);
338}
339
340/**
341 * SocFieldCachedEditor
342 */
343SocFieldCachedEditor::SocFieldCachedEditor(QWidget *parent)
344 :SocFieldEditor(soc_reg_field_t(), parent)
345{
346}
347
348SocFieldCachedEditor::~SocFieldCachedEditor()
349{
350}
351
352SocFieldCachedValue SocFieldCachedEditor::value() const
353{
354 return SocFieldCachedValue(m_value.field(), field());
355}
356
357void SocFieldCachedEditor::setValue(SocFieldCachedValue val)
358{
359 m_value = val;
360 SetRegField(m_value.field());
361 setField(m_value.value());
362}
363
364/**
365 * SocFieldEditorCreator
366 */
367QWidget *SocFieldEditorCreator::createWidget(QWidget *parent) const
368{
369 return new SocFieldEditor(m_field, parent);
370}
371
372QByteArray SocFieldEditorCreator::valuePropertyName() const
373{
374 return QByteArray("field");
375}
376
377/**
378 * SocFieldCachedEditorCreator
379 */
380QWidget *SocFieldCachedEditorCreator::createWidget(QWidget *parent) const
381{
382 return new SocFieldCachedEditor(parent);
383}
384
385QByteArray SocFieldCachedEditorCreator::valuePropertyName() const
386{
387 return QByteArray("value");
388}
389
390/**
391 * RegSexyDisplay
392 */
393RegSexyDisplay::RegSexyDisplay(const SocRegRef& reg, QWidget *parent)
394 :QWidget(parent), m_reg(reg)
395{
396 m_size = QSize();
397}
398
399int RegSexyDisplay::separatorSize() const
400{
401 return 1;
402}
403
404int RegSexyDisplay::marginSize() const
405{
406 return fontMetrics().height() / 3;
407}
408
409int RegSexyDisplay::textSep() const
410{
411 return marginSize() / 2;
412}
413
414int RegSexyDisplay::headerHeight() const
415{
416 return 2 * marginSize() + textSep() + 2 * fontMetrics().height();
417}
418
419int RegSexyDisplay::columnWidth() const
420{
421 return 2 * marginSize() + fontMetrics().height();
422}
423
424int RegSexyDisplay::maxContentHeight() const
425{
426 int max = 0;
427 QFontMetrics metrics = fontMetrics();
428 for(size_t i = 0; i < m_reg.GetReg().field.size(); i++)
429 {
430 QString s = QString::fromStdString(m_reg.GetReg().field[i].name);
431 // add extra spaces arounds
432 s = " " + s + " ";
433 max = qMax(max, metrics.boundingRect(s).width());
434 }
435 return 2 * marginSize() + max;
436}
437
438int RegSexyDisplay::gapHeight() const
439{
440 return marginSize() / 2;
441}
442
443QSize RegSexyDisplay::minimumSizeHint() const
444{
445 /* cache computation because it's expensive */
446 if(m_size.isValid())
447 return m_size;
448 /* width: display 32 columns + 33 vertical separators */
449 m_size.setWidth(32 * columnWidth() + 33 * separatorSize());
450 /* height: one separator + two digits + one separator + margin + separator
451 * + names + separator */
452 m_size.setHeight(4 * separatorSize() + headerHeight() + gapHeight() + maxContentHeight());
453 return m_size;
454}
455
456QSize RegSexyDisplay::sizeHint() const
457{
458 return minimumSizeHint();
459}
460
461void RegSexyDisplay::paintEvent(QPaintEvent *event)
462{
463 // FIXME could be optimised with QStaticText
464 Q_UNUSED(event);
465 int txt_h = fontMetrics().height();
466 int sep_sz = separatorSize();
467 int w = width();
468 int h = height() - 1;
469 int col_w = (w - 33 * sep_sz) / 32;
470 int hdr_h = headerHeight();
471 int gap_h = gapHeight();
472 int tot_w = 33 * sep_sz + 32 * col_w;
473 int margin = marginSize();
474 int txt_sep = textSep();
475 int tot_hdr_sz = 2 * sep_sz + hdr_h;
476 // computer xshift
477 int x_shift = (w - tot_w) / 2;
478#define ith_col_x(i) (x_shift + (i) * (sep_sz + col_w))
479
480 QPainter painter(this);
481 QBrush back_brush = palette().base();
482 QBrush line_brush = palette().dark();
483
484 // fill interesting zone with base
485 painter.fillRect(x_shift, 0, tot_w, h, back_brush);
486
487 // draw top and bottom lines
488 painter.setPen(QPen(palette().dark(), sep_sz));
489 painter.fillRect(x_shift, 0, tot_w, sep_sz, line_brush);
490 painter.fillRect(x_shift, h - sep_sz, tot_w, sep_sz, line_brush);
491 // draw intemediate lines
492 for(int i = 0; i <= 32; i++)
493 painter.fillRect(ith_col_x(i), 0, sep_sz, 2 * sep_sz + hdr_h, line_brush);
494 // draw bottom header lines
495 painter.fillRect(ith_col_x(0), sep_sz + hdr_h, tot_w, sep_sz, line_brush);
496 painter.fillRect(ith_col_x(0), tot_hdr_sz + gap_h, tot_w, sep_sz, line_brush);
497 // redraw some lines but wider
498 for(int i = 4; i < 32; i += 4)
499 painter.fillRect(ith_col_x(i) - sep_sz, 0, 3 * sep_sz, tot_hdr_sz, line_brush);
500 // draw numbers in the header
501 painter.setPen(palette().brush(QPalette::ButtonText).color());
502 for(int i = 0; i < 32; i++)
503 {
504 QRect r(ith_col_x(i), sep_sz + margin, col_w, txt_h);
505 painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) / 10));
506 r.translate(0, txt_h + txt_sep);
507 painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) % 10));
508 }
509 // display content
510 for(size_t i = 0; i < m_reg.GetReg().field.size(); i++)
511 {
512 const soc_reg_field_t& field = m_reg.GetReg().field[i];
513 QRect r(QPoint(ith_col_x(31 - field.last_bit) + sep_sz, tot_hdr_sz),
514 QPoint(ith_col_x(32 - field.first_bit), h - sep_sz));
515 painter.fillRect(r.x() - sep_sz, r.y(), sep_sz, r.height(), line_brush);
516 painter.fillRect(r.right(), r.y(), sep_sz, r.height(), line_brush);
517 r.setY(r.y() + gap_h + sep_sz);
518 // draw rotated text
519 painter.save();
520 painter.translate(r.bottomLeft());
521 painter.rotate(-90);
522 //painter.fillRect(QRect(0, 0, r.height(), r.width()), QBrush(Qt::red));
523 QRect r2(0, 0, r.height(), r.width());
524 painter.drawText(r2, Qt::AlignCenter, QString::fromStdString(field.name));
525 painter.restore();
526 }
527#undef ith_col_x
528}
529
530/**
531 * GrowingTextEdit
532 */
533GrowingTextEdit::GrowingTextEdit(QWidget *parent)
534 :QTextEdit(parent)
535{
536 connect(this, SIGNAL(textChanged()), this, SLOT(TextChanged()));
537 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
538 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
539}
540
541void GrowingTextEdit::TextChanged()
542{
543 int content_size = document()->documentLayout()->documentSize().height();
544 content_size = qMax(content_size, fontMetrics().height());
545 setFixedHeight(content_size + contentsMargins().top() + contentsMargins().bottom());
546}
547
548/**
549 * GrowingTableWidget
550 */
551GrowingTableWidget::GrowingTableWidget(QWidget *parent)
552 :QTableWidget(parent)
553{
554 connect(model(), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
555 this, SLOT(DataChanged(const QModelIndex&, const QModelIndex&)));
556}
557
558void GrowingTableWidget::DataChanged(const QModelIndex& tl, const QModelIndex& br)
559{
560 Q_UNUSED(tl);
561 Q_UNUSED(br);
562 resizeRowsToContents();
563 resizeColumnsToContents();
564 int h = contentsMargins().top() + contentsMargins().bottom();
565 h += horizontalHeader()->height();
566 for(int i = 0; i < rowCount(); i++)
567 h += rowHeight(i);
568 setMinimumHeight(h);
569}
570
571/**
572 * MyTextEditor
573 */
574MyTextEditor::MyTextEditor(QWidget *parent)
575 :QWidget(parent)
576{
577 QVBoxLayout *layout = new QVBoxLayout;
578 m_toolbar = new QToolBar(this);
579 m_edit = new QTextEdit(this);
580 layout->addWidget(m_toolbar, 0);
581 layout->addWidget(m_edit, 1);
582 setLayout(layout);
583 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
584
585 m_edit->setAcceptRichText(false);
586 m_edit->setAutoFormatting(QTextEdit::AutoAll);
587
588 m_bold_button = new QToolButton(this);
589 m_bold_button->setIcon(QIcon::fromTheme("format-text-bold"));
590 m_bold_button->setText("bold");
591 m_bold_button->setCheckable(true);
592
593 m_italic_button = new QToolButton(this);
594 m_italic_button->setIcon(QIcon::fromTheme("format-text-italic"));
595 m_italic_button->setText("italic");
596 m_italic_button->setCheckable(true);
597
598 m_underline_button = new QToolButton(this);
599 m_underline_button->setIcon(QIcon::fromTheme("format-text-underline"));
600 m_underline_button->setText("underline");
601 m_underline_button->setCheckable(true);
602
603 m_toolbar->addWidget(m_bold_button);
604 m_toolbar->addWidget(m_italic_button);
605 m_toolbar->addWidget(m_underline_button);
606
607 connect(m_bold_button, SIGNAL(toggled(bool)), this, SLOT(OnTextBold(bool)));
608 connect(m_italic_button, SIGNAL(toggled(bool)), this, SLOT(OnTextItalic(bool)));
609 connect(m_underline_button, SIGNAL(toggled(bool)), this, SLOT(OnTextUnderline(bool)));
610 connect(m_edit, SIGNAL(textChanged()), this, SLOT(OnInternalTextChanged()));
611 connect(m_edit, SIGNAL(currentCharFormatChanged(const QTextCharFormat&)),
612 this, SLOT(OnCharFormatChanged(const QTextCharFormat&)));
613
614 SetGrowingMode(false);
615 SetReadOnly(false);
616}
617
618void MyTextEditor::SetReadOnly(bool en)
619{
620 m_read_only = en;
621 if(en)
622 m_toolbar->hide();
623 else
624 m_toolbar->hide();
625 m_edit->setReadOnly(en);
626}
627
628void MyTextEditor::SetGrowingMode(bool en)
629{
630 m_growing_mode = en;
631 if(en)
632 {
633 m_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
634 m_edit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
635 OnTextChanged();
636 }
637 else
638 {
639 m_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
640 m_edit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
641 }
642}
643
644void MyTextEditor::OnInternalTextChanged()
645{
646 if(m_growing_mode)
647 {
648 int content_size = m_edit->document()->documentLayout()->documentSize().height();
649 content_size = qMax(content_size, m_edit->fontMetrics().height());
650 m_edit->setMinimumHeight(content_size + m_edit->contentsMargins().top() +
651 m_edit->contentsMargins().bottom());
652 }
653 emit OnTextChanged();
654}
655
656void MyTextEditor::OnTextBold(bool checked)
657{
658 QTextCursor cursor = m_edit->textCursor();
659 QTextCharFormat fmt = cursor.charFormat();
660 fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal);
661 cursor.setCharFormat(fmt);
662 m_edit->setTextCursor(cursor);
663}
664
665void MyTextEditor::OnTextItalic(bool checked)
666{
667 QTextCursor cursor = m_edit->textCursor();
668 QTextCharFormat fmt = cursor.charFormat();
669 fmt.setFontItalic(checked);
670 cursor.setCharFormat(fmt);
671 m_edit->setTextCursor(cursor);
672}
673
674void MyTextEditor::OnTextUnderline(bool checked)
675{
676 QTextCursor cursor = m_edit->textCursor();
677 QTextCharFormat fmt = cursor.charFormat();
678 fmt.setFontUnderline(checked);
679 cursor.setCharFormat(fmt);
680 m_edit->setTextCursor(cursor);
681}
682
683void MyTextEditor::OnCharFormatChanged(const QTextCharFormat& fmt)
684{
685 /* NOTE: changing the button states programmaticaly doesn't trigger
686 * the toggled() signals, otherwise it would result in a loop
687 * between this function and OnText{Bold,Italic,Underline,...} */
688 m_bold_button->setChecked(fmt.fontWeight() > QFont::Normal);
689 m_italic_button->setChecked(fmt.fontItalic());
690 m_underline_button->setChecked(fmt.fontUnderline());
691}
692
693void MyTextEditor::SetTextHtml(const QString& text)
694{
695 m_edit->setHtml(text);
696}
697
698QString MyTextEditor::GetTextHtml()
699{
700 return m_edit->toPlainText();
701}
702
703bool MyTextEditor::IsModified()
704{
705 return m_edit->document()->isModified();
706}
707
708/**
709 * MySwitchableTextEditor
710 */
711MySwitchableTextEditor::MySwitchableTextEditor(QWidget *parent)
712 :QWidget(parent)
713{
714 QVBoxLayout *layout = new QVBoxLayout(this);
715 m_edit = new MyTextEditor(this);
716 m_label = new QLabel(this);
717 m_label->setTextFormat(Qt::RichText);
718 m_label->setAlignment(Qt::AlignTop);
719 m_line = new QLineEdit(this);
720
721 layout->addWidget(m_label);
722 layout->addWidget(m_edit);
723 layout->addWidget(m_line);
724
725 setLayout(layout);
726
727 m_editor_mode = false;
728 m_line_mode = false;
729 UpdateVisibility();
730}
731
732void MySwitchableTextEditor::SetEditorMode(bool edit)
733{
734 if(edit == m_editor_mode)
735 return;
736 QString text = GetTextHtml();
737 m_editor_mode = edit;
738 UpdateVisibility();
739 SetTextHtml(text);
740}
741
742QString MySwitchableTextEditor::GetTextHtml()
743{
744 if(m_editor_mode)
745 return m_line_mode ? m_line->text() : m_edit->GetTextHtml();
746 else
747 return m_label->text();
748}
749
750void MySwitchableTextEditor::SetTextHtml(const QString& text)
751{
752 if(m_editor_mode)
753 {
754 if(m_line_mode)
755 m_line->setText(text);
756 else
757 m_edit->SetTextHtml(text);
758 }
759 else
760 m_label->setText(text);
761}
762
763MyTextEditor *MySwitchableTextEditor::GetEditor()
764{
765 return m_edit;
766}
767
768void MySwitchableTextEditor::SetLineMode(bool en)
769{
770 if(m_line_mode == en)
771 return;
772 QString text = GetTextHtml();
773 m_line_mode = en;
774 SetTextHtml(text);
775 UpdateVisibility();
776}
777
778QLineEdit *MySwitchableTextEditor::GetLineEdit()
779{
780 return m_line;
781}
782
783void MySwitchableTextEditor::UpdateVisibility()
784{
785 m_label->setVisible(!m_editor_mode);
786 m_edit->setVisible(m_editor_mode && !m_line_mode);
787 m_line->setVisible(m_editor_mode && m_line_mode);
788}
789
790QLabel *MySwitchableTextEditor::GetLabel()
791{
792 return m_label;
793}
794
795bool MySwitchableTextEditor::IsModified()
796{
797 if(!m_editor_mode)
798 return false;
799 return m_line_mode ? m_line->isModified() : m_edit->IsModified();
800}