QElectroTech  0.70
richtexteditor.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the Qt Designer of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
48 #include "richtexteditor_p.h"
49 #include "ui_addlinkdialog.h"
50 
51 //#include <QtDesigner/QDesignerFormEditorInterface>
52 
53 #include <QtCore/QList>
54 #include <QtCore/QMap>
55 #include <QtCore/QPointer>
56 #include <QtCore/QXmlStreamReader>
57 #include <QtCore/QXmlStreamWriter>
58 #include <QtCore/QXmlStreamAttributes>
59 
60 #include <QAction>
61 #include <QColorDialog>
62 #include <QComboBox>
63 #include <QtGui/QFontDatabase>
64 #include <QtGui/QTextCursor>
65 #include <QtGui/QPainter>
66 #include <QtGui/QIcon>
67 #include <QMenu>
68 #include <QtGui/QMoveEvent>
69 #include <QTabWidget>
70 #include <QtGui/QTextDocument>
71 #include <QtGui/QTextBlock>
72 #include <QToolBar>
73 #include <QToolButton>
74 #include <QVBoxLayout>
75 #include <QHBoxLayout>
76 #include <QPushButton>
77 #include <QDialogButtonBox>
78 
79 QT_BEGIN_NAMESPACE
80 
81 //static const char RichTextDialogGroupC[] = "RichTextDialog";
82 //static const char GeometryKeyC[] = "Geometry";
83 //static const char TabKeyC[] = "Tab";
84 
85 //const bool simplifyRichTextDefault = true;
86 
87 namespace qdesigner_internal {
88  // Richtext simplification filter helpers: Elements to be discarded
89  static inline bool filterElement(const QStringRef &name)
90  {
91  return name != QLatin1String("meta") && name != QLatin1String("style");
92  }
93 
94  // Richtext simplification filter helpers: Filter attributes of elements
95  static inline void filterAttributes(const QStringRef &name,
96  QXmlStreamAttributes *atts,
97  bool *paragraphAlignmentFound)
98  {
99  typedef QXmlStreamAttributes::iterator AttributeIt;
100 
101  if (atts->isEmpty())
102  return;
103 
104  // No style attributes for <body>
105  if (name == QLatin1String("body")) {
106  atts->clear();
107  return;
108  }
109 
110  // Clean out everything except 'align' for 'p'
111  if (name == QLatin1String("p")) {
112  for (AttributeIt it = atts->begin(); it != atts->end(); ) {
113  if (it->name() == QLatin1String("align")) {
114  ++it;
115  *paragraphAlignmentFound = true;
116  } else {
117  it = atts->erase(it);
118  }
119  }
120  return;
121  }
122  }
123 
124  // Richtext simplification filter helpers: Check for blank QStringRef.
125  static inline bool isWhiteSpace(const QStringRef &in)
126  {
127  const int count = in.size();
128  for (int i = 0; i < count; i++)
129  if (!in.at(i).isSpace())
130  return false;
131  return true;
132  }
133 
134  // Richtext simplification filter: Remove hard-coded font settings,
135  // <style> elements, <p> attributes other than 'align' and
136  // and unnecessary meta-information.
137  QString simplifyRichTextFilter(const QString &in, bool *isPlainTextPtr = nullptr)
138  {
139  unsigned elementCount = 0;
140  bool paragraphAlignmentFound = false;
141  QString out;
142  QXmlStreamReader reader(in);
143  QXmlStreamWriter writer(&out);
144  writer.setAutoFormatting(false);
145  writer.setAutoFormattingIndent(0);
146 
147  while (!reader.atEnd()) {
148  switch (reader.readNext()) {
149  case QXmlStreamReader::StartElement:
150  elementCount++;
151  if (filterElement(reader.name())) {
152  const QStringRef name = reader.name();
153  QXmlStreamAttributes attributes = reader.attributes();
154  filterAttributes(name, &attributes, &paragraphAlignmentFound);
155  writer.writeStartElement(name.toString());
156  if (!attributes.isEmpty())
157  writer.writeAttributes(attributes);
158  } else {
159  reader.readElementText(); // Skip away all nested elements and characters.
160  }
161  break;
162  case QXmlStreamReader::Characters:
163  if (!isWhiteSpace(reader.text()))
164  writer.writeCharacters(reader.text().toString());
165  break;
166  case QXmlStreamReader::EndElement:
167  writer.writeEndElement();
168  break;
169  default:
170  break;
171  }
172  }
173  // Check for plain text (no spans, just <html><head><body><p>)
174  if (isPlainTextPtr)
175  *isPlainTextPtr = !paragraphAlignmentFound && elementCount == 4u; //
176  return out;
177  }
178 
179 class RichTextEditor : public QTextEdit
180 {
181  Q_OBJECT
182 public:
183  RichTextEditor(QWidget *parent = nullptr);
184  void setDefaultFont(QFont font);
185 
186  QToolBar *createToolBar(QWidget *parent = nullptr);
187  bool simplifyRichText() const { return m_simplifyRichText; }
188 
189 public slots:
190  void setFontBold(bool b);
191  void setFontPointSize(double);
192  void setText(const QString &text);
193  void setSimplifyRichText(bool v);
194  QString text(Qt::TextFormat format) const;
195 
196 signals:
197  void stateChanged();
198  void simplifyRichTextChanged(bool);
199 
200 private:
202 };
203 
204 class AddLinkDialog : public QDialog
205 {
206  Q_OBJECT
207 
208 public:
209  AddLinkDialog(RichTextEditor *editor, QWidget *parent = nullptr);
210  ~AddLinkDialog() override;
211 
212  int showDialog();
213 
214 public slots:
215  void accept() override;
216 
217 private:
220 };
221 
222 AddLinkDialog::AddLinkDialog(RichTextEditor *editor, QWidget *parent) :
223  QDialog(parent),
224  m_ui(new Ui::AddLinkDialog)
225 {
226  m_ui->setupUi(this);
227 
228  setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
229 
230  m_editor = editor;
231 }
232 
234 {
235  delete m_ui;
236 }
237 
239 {
240  // Set initial focus
241  const QTextCursor cursor = m_editor->textCursor();
242  if (cursor.hasSelection()) {
243  m_ui->titleInput->setText(cursor.selectedText());
244  m_ui->urlInput->setFocus();
245  } else {
246  m_ui->titleInput->setFocus();
247  }
248 
249  return exec();
250 }
251 
253 {
254  const QString title = m_ui->titleInput->text();
255  const QString url = m_ui->urlInput->text();
256 
257  if (!title.isEmpty()) {
258  QString html = QLatin1String("<a href=\"");
259  html += url;
260  html += QLatin1String("\">");
261  html += title;
262  html += QLatin1String("</a>");
263 
264  m_editor->insertHtml(html);
265  }
266 
267  m_ui->titleInput->clear();
268  m_ui->urlInput->clear();
269 
270  QDialog::accept();
271 }
272 
273 class HtmlTextEdit : public QTextEdit
274 {
275  Q_OBJECT
276 
277 public:
278  HtmlTextEdit(QWidget *parent = nullptr)
279  : QTextEdit(parent)
280  {}
281 
282  void contextMenuEvent(QContextMenuEvent *event) override;
283 
284 private slots:
285  void actionTriggered(QAction *action);
286 };
287 
288 void HtmlTextEdit::contextMenuEvent(QContextMenuEvent *event)
289 {
290  QMenu *menu = createStandardContextMenu();
291  QMenu *htmlMenu = new QMenu(tr("Insert HTML entity"), menu);
292 
293  typedef struct {
294  const char *text;
295  const char *entity;
296  } Entry;
297 
298  const Entry entries[] = {
299  { "&&amp; (&&)", "&amp;" },
300  { "&&nbsp;", "&nbsp;" },
301  { "&&lt; (<)", "&lt;" },
302  { "&&gt; (>)", "&gt;" },
303  { "&&copy; (Copyright)", "&copy;" },
304  { "&&reg; (Trade Mark)", "&reg;" },
305  };
306 
307  for (int i = 0; i < 6; ++i) {
308  QAction *entityAction = new QAction(QLatin1String(entries[i].text),
309  htmlMenu);
310  entityAction->setData(QLatin1String(entries[i].entity));
311  htmlMenu->addAction(entityAction);
312  }
313 
314  menu->addMenu(htmlMenu);
315  connect(htmlMenu, SIGNAL(triggered(QAction*)),
316  SLOT(actionTriggered(QAction*)));
317  menu->exec(event->globalPos());
318  delete menu;
319 }
320 
321 void HtmlTextEdit::actionTriggered(QAction *action)
322 {
323  insertPlainText(action->data().toString());
324 }
325 
326 class ColorAction : public QAction
327 {
328  Q_OBJECT
329 
330 public:
331  ColorAction(QObject *parent);
332 
333  const QColor& color() const { return m_color; }
334  void setColor(const QColor &color);
335 
336 signals:
337  void colorChanged(const QColor &color);
338 
339 private slots:
340  void chooseColor();
341 
342 private:
343  QColor m_color;
344 };
345 
346 ColorAction::ColorAction(QObject *parent):
347  QAction(parent)
348 {
349  setText(tr("Text Color"));
350  setColor(Qt::black);
351  connect(this, SIGNAL(triggered()), this, SLOT(chooseColor()));
352 }
353 
354 void ColorAction::setColor(const QColor &color)
355 {
356  if (color == m_color)
357  return;
358  m_color = color;
359  QPixmap pix(24, 24);
360  QPainter painter(&pix);
361  painter.setRenderHint(QPainter::Antialiasing, false);
362  painter.fillRect(pix.rect(), m_color);
363  painter.setPen(m_color.darker());
364  painter.drawRect(pix.rect().adjusted(0, 0, -1, -1));
365  setIcon(pix);
366 }
367 
369 {
370  const QColor col = QColorDialog::getColor(m_color, nullptr);
371  if (col.isValid() && col != m_color) {
372  setColor(col);
373  emit colorChanged(m_color);
374  }
375 }
376 
377 class RichTextEditorToolBar : public QToolBar
378 {
379  Q_OBJECT
380 public:
382  QWidget *parent = nullptr);
383 
384 public slots:
385  void updateActions();
386 
387 private slots:
388  void alignmentActionTriggered(QAction *action);
389  void sizeInputActivated(const QString &size);
390  void colorChanged(const QColor &color);
391  void setVAlignSuper(bool super);
392  void setVAlignSub(bool sub);
393  void insertLink();
394  void insertImage();
395 
396 
397 private:
398  QAction *m_bold_action;
399  QAction *m_italic_action;
407  QAction *m_link_action;
408  QAction *m_image_action;
411  QComboBox *m_font_size_input;
412 
413  QPointer<RichTextEditor> m_editor;
414 };
415 
416 static QAction *createCheckableAction(const QIcon &icon, const QString &text,
417  QObject *receiver, const char *slot,
418  QObject *parent = nullptr)
419 {
420  QAction *result = new QAction(parent);
421  result->setIcon(icon);
422  result->setText(text);
423  result->setCheckable(true);
424  result->setChecked(false);
425  if (slot)
426  QObject::connect(result, SIGNAL(triggered(bool)), receiver, slot);
427  return result;
428 }
429 
431  QWidget *parent) :
432  QToolBar(parent),
433  m_link_action(new QAction(this)),
434  m_image_action(new QAction(this)),
435  m_color_action(new ColorAction(this)),
436  m_font_size_input(new QComboBox),
437  m_editor(editor)
438 {
439 
440  // Font size combo box
441  m_font_size_input->setEditable(false);
442  const QList<int> font_sizes = QFontDatabase::standardSizes();
443  foreach (int font_size, font_sizes)
444  m_font_size_input->addItem(QString::number(font_size));
445 
446  connect(m_font_size_input, SIGNAL(activated(QString)),
447  this, SLOT(sizeInputActivated(QString)));
448  addWidget(m_font_size_input);
449 
450 
451  // Bold, italic and underline buttons
452 
454  QIcon(":/ico/32x32/format-text-bold.png"),
455  tr("Texte en gras"), editor, SLOT(setFontBold(bool)), this);
456  m_bold_action->setShortcut(tr("CTRL+B"));
457  addAction(m_bold_action);
458 
460  QIcon(":/ico/32x32/format-text-italic.png"),
461  tr("Texte en italique"), editor, SLOT(setFontItalic(bool)), this);
462  m_italic_action->setShortcut(tr("CTRL+I"));
463  addAction(m_italic_action);
464 
466  QIcon(":/ico/32x32/format-text-underline.png"),
467  tr("Texte souligé"), editor, SLOT(setFontUnderline(bool)), this);
468  m_underline_action->setShortcut(tr("CTRL+U"));
469  addAction(m_underline_action);
470 
471 
472  // Left, center, right and justified alignment buttons
473 
474  QActionGroup *alignment_group = new QActionGroup(this);
475  connect(alignment_group, SIGNAL(triggered(QAction*)),
476  SLOT(alignmentActionTriggered(QAction*)));
477 
479  QIcon(),
480  tr("Left Align"), editor, nullptr, alignment_group);
481  addAction(m_align_left_action);
482 
484  QIcon(),
485  tr("Center"), editor, nullptr, alignment_group);
486  addAction(m_align_center_action);
487 
489  QIcon(),
490  tr("Right Align"), editor, nullptr, alignment_group);
491  addAction(m_align_right_action);
492 
494  QIcon(),
495  tr("Justify"), editor, nullptr, alignment_group);
496  addAction(m_align_justify_action);
497 
498  m_align_justify_action -> setVisible( false );
499  m_align_center_action -> setVisible( false );
500  m_align_left_action -> setVisible( false );
501  m_align_right_action -> setVisible( false );
502 
503  // Superscript and subscript buttons
504 
506  QIcon(":/ico/22x22/format-text-superscript.png"),
507  tr("Superscript"),
508  this, SLOT(setVAlignSuper(bool)), this);
509  addAction(m_valign_sup_action);
510 
512  QIcon(":/ico/22x22/format-text-subscript.png"),
513  tr("Subscript"),
514  this, SLOT(setVAlignSub(bool)), this);
515  addAction(m_valign_sub_action);
516 
517  m_valign_sup_action -> setVisible( true );
518  m_valign_sub_action -> setVisible( true );
519 
520  // Insert hyperlink and image buttons
521 
522  m_link_action->setText(tr("Insérer un lien"));
523  connect(m_link_action, SIGNAL(triggered()), SLOT(insertLink()));
524  addAction(m_link_action);
525 
526  m_image_action->setText(tr("Insert &Image"));
527  connect(m_image_action, SIGNAL(triggered()), SLOT(insertImage()));
528  addAction(m_image_action);
529 
530  m_image_action -> setVisible( false );
531  addSeparator();
532 
533  // Text color button
534  connect(m_color_action, SIGNAL(colorChanged(QColor)),
535  this, SLOT(colorChanged(QColor)));
536  addAction(m_color_action);
537 
538 
539  // Simplify rich text
541  QIcon(":/ico/32x32/simplifyrichtext.png"),
542  tr("Simplify Rich Text"), editor, SLOT(setSimplifyRichText(bool)),this);
543  m_simplify_richtext_action->setChecked(editor->simplifyRichText());
544  connect(m_editor, SIGNAL(simplifyRichTextChanged(bool)),
545  m_simplify_richtext_action, SLOT(setChecked(bool)));
546  addAction(m_simplify_richtext_action);
547 
548  connect(editor, SIGNAL(textChanged()), this, SLOT(updateActions()));
549  connect(editor, SIGNAL(stateChanged()), this, SLOT(updateActions()));
550 
551  updateActions();
552 }
553 
555 {
556  Qt::Alignment new_alignment;
557 
558  if (action == m_align_left_action) {
559  new_alignment = Qt::AlignLeft;
560  } else if (action == m_align_center_action) {
561  new_alignment = Qt::AlignCenter;
562  } else if (action == m_align_right_action) {
563  new_alignment = Qt::AlignRight;
564  } else {
565  new_alignment = Qt::AlignJustify;
566  }
567 
568  m_editor->setAlignment(new_alignment);
569 }
570 
571 
572 
573 void RichTextEditorToolBar::colorChanged(const QColor &color)
574 {
575  m_editor->setTextColor(color);
576  m_editor->setFocus();
577 }
578 
580 {
581  bool ok;
582  int i = size.toInt(&ok);
583  if (!ok)
584  return;
585 
586  m_editor->setFontPointSize(i);
587  m_editor->setFocus();
588 }
589 
591 {
592  const QTextCharFormat::VerticalAlignment align = super ?
593  QTextCharFormat::AlignSuperScript : QTextCharFormat::AlignNormal;
594 
595  QTextCharFormat charFormat = m_editor->currentCharFormat();
596  charFormat.setVerticalAlignment(align);
597  m_editor->setCurrentCharFormat(charFormat);
598 
599  m_valign_sub_action->setChecked(false);
600 }
601 
603 {
604  const QTextCharFormat::VerticalAlignment align = sub ?
605  QTextCharFormat::AlignSubScript : QTextCharFormat::AlignNormal;
606 
607  QTextCharFormat charFormat = m_editor->currentCharFormat();
608  charFormat.setVerticalAlignment(align);
609  m_editor->setCurrentCharFormat(charFormat);
610 
611  m_valign_sup_action->setChecked(false);
612 }
613 
615 {
616  AddLinkDialog linkDialog(m_editor, this);
617  linkDialog.showDialog();
618  m_editor->setFocus();
619 }
620 
622 {
623 #ifdef hip
624  const QString path = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), QString(), this);
625  if (!path.isEmpty())
626  m_editor->insertHtml(QLatin1String("<img src=\"") + path + QLatin1String("\"/>"));
627 #endif
628 }
629 
631 {
632  if (m_editor == nullptr) {
633  setEnabled(false);
634  return;
635  }
636 
637  const Qt::Alignment alignment = m_editor->alignment();
638  const QTextCursor cursor = m_editor->textCursor();
639  const QTextCharFormat charFormat = cursor.charFormat();
640  const QFont font = charFormat.font();
641  const QTextCharFormat::VerticalAlignment valign =
642  charFormat.verticalAlignment();
643  const bool superScript = valign == QTextCharFormat::AlignSuperScript;
644  const bool subScript = valign == QTextCharFormat::AlignSubScript;
645 
646  if (alignment & Qt::AlignLeft) {
647  m_align_left_action->setChecked(true);
648  } else if (alignment & Qt::AlignRight) {
649  m_align_right_action->setChecked(true);
650  } else if (alignment & Qt::AlignHCenter) {
651  m_align_center_action->setChecked(true);
652  } else {
653  m_align_justify_action->setChecked(true);
654  }
655 
656  m_bold_action->setChecked(font.bold());
657  m_italic_action->setChecked(font.italic());
658  m_underline_action->setChecked(font.underline());
659  m_valign_sup_action->setChecked(superScript);
660  m_valign_sub_action->setChecked(subScript);
661 
662  const int size = font.pointSize();
663  const int idx = m_font_size_input->findText(QString::number(size));
664  if (idx != -1)
665  m_font_size_input->setCurrentIndex(idx);
666 
667  m_color_action->setColor(m_editor->textColor());
668 }
669 
671  : QTextEdit(parent)
672 {
673  connect(this, SIGNAL(currentCharFormatChanged(QTextCharFormat)),
674  this, SIGNAL(stateChanged()));
675  connect(this, SIGNAL(cursorPositionChanged()),
676  this, SIGNAL(stateChanged()));
677 }
678 
679 QToolBar *RichTextEditor::createToolBar(QWidget *parent)
680 {
681  return new RichTextEditorToolBar(this, parent);
682 }
683 
685 {
686  if (b)
687  setFontWeight(QFont::Bold);
688  else
689  setFontWeight(QFont::Normal);
690 }
691 
693 {
694  QTextEdit::setFontPointSize(qreal(d));
695 }
696 
697 void RichTextEditor::setText(const QString &text)
698 {
699  if (Qt::mightBeRichText(text))
700  setHtml(text);
701  else
702  setPlainText(text);
703 }
704 
706 {
707  if (v != m_simplifyRichText) {
708  m_simplifyRichText = v;
709  emit simplifyRichTextChanged(v);
710  }
711 }
712 
714 {
715  // Some default fonts on Windows have a default size of 7.8,
716  // which results in complicated rich text generated by toHtml().
717  // Use an integer value.
718  const int pointSize = qRound(font.pointSizeF());
719  if (pointSize > 0 && !qFuzzyCompare(qreal(pointSize), font.pointSizeF())) {
720  font.setPointSize(pointSize);
721  }
722 
723  document()->setDefaultFont(font);
724  if (font.pointSize() > 0)
725  setFontPointSize(font.pointSize());
726  else
727  setFontPointSize(QFontInfo(font).pointSize());
728  emit textChanged();
729 }
730 
731 QString RichTextEditor::text(Qt::TextFormat format) const
732 {
733  switch (format) {
734  case Qt::PlainText:
735  return toPlainText();
736  case Qt::RichText:
737  return m_simplifyRichText ? simplifyRichTextFilter(toHtml()) : toHtml();
738  case Qt::AutoText:
739  break;
740  }
741  const QString html = toHtml();
742  bool isPlainText;
743  const QString simplifiedHtml = simplifyRichTextFilter(html, &isPlainText);
744  if (isPlainText)
745  return toPlainText();
746  return m_simplifyRichText ? simplifiedHtml : html;
747 }
748 
750  QDialog(parent),
751  m_editor(new RichTextEditor()),
752  m_text_edit(new HtmlTextEdit),
753  m_tab_widget(new QTabWidget),
754  m_state(Clean)
755 {
756  setWindowTitle(tr("Edit text"));
757  setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
758 
759  m_text_edit->setAcceptRichText(false);
760 
761  connect(m_editor, SIGNAL(textChanged()), this, SLOT(richTextChanged()));
762  connect(m_editor, SIGNAL(simplifyRichTextChanged(bool)), this, SLOT(richTextChanged()));
763  connect(m_text_edit, SIGNAL(textChanged()), this, SLOT(sourceChanged()));
764 
765  // The toolbar needs to be created after the RichTextEditor
766  QToolBar *tool_bar = m_editor->createToolBar();
767  tool_bar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
768 
769  QWidget *rich_edit = new QWidget;
770  QVBoxLayout *rich_edit_layout = new QVBoxLayout(rich_edit);
771  rich_edit_layout->addWidget(tool_bar);
772  rich_edit_layout->addWidget(m_editor);
773 
774  QWidget *plain_edit = new QWidget;
775  QVBoxLayout *plain_edit_layout = new QVBoxLayout(plain_edit);
776  plain_edit_layout->addWidget(m_text_edit);
777 
778  m_tab_widget->setTabPosition(QTabWidget::South);
779  m_tab_widget->addTab(rich_edit, tr("Rich Text"));
780  m_tab_widget->addTab(plain_edit, tr("Source"));
781  connect(m_tab_widget, SIGNAL(currentChanged(int)),
782  SLOT(tabIndexChanged(int)));
783 
784  QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal);
785  QPushButton *ok_button = buttonBox->button(QDialogButtonBox::Ok);
786  ok_button->setText(tr("&OK"));
787  ok_button->setDefault(true);
788  buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("&Cancel"));
789  connect(buttonBox, SIGNAL(accepted()), this, SLOT(on_buttonBox_accepted()));
790  connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
791 
792  QVBoxLayout *layout = new QVBoxLayout(this);
793  layout->addWidget(m_tab_widget);
794  layout->addWidget(buttonBox);
795 
796  m_editor->setFocus();
797 
798 }
799 
801 {
802 }
803 
808  emit applyEditText( text(Qt::RichText) );
809  this->close();
810 }
811 
812 
814 {
815  m_tab_widget->setCurrentIndex(0);
816  m_editor->selectAll();
817  m_editor->setFocus();
818 
819  return exec();
820 }
821 
823 {
824  m_editor->setDefaultFont(font);
825 }
826 
827 void RichTextEditorDialog::setText(const QString &text)
828 {
829  // Generally simplify rich text unless verbose text is found.
830  const bool isSimplifiedRichText = !text.startsWith("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">");
831  m_editor->setSimplifyRichText(isSimplifiedRichText);
833  m_text_edit->setPlainText(text);
834  m_state = Clean;
835 }
836 
837 QString RichTextEditorDialog::text(Qt::TextFormat format) const
838 {
839  // In autotext mode, if the user has changed the source, use that
840  if (format == Qt::AutoText && (m_state == Clean || m_state == SourceChanged))
841  return m_text_edit->toPlainText();
842  // If the plain text HTML editor is selected, first copy its contents over
843  // to the rich text editor so that it is converted to Qt-HTML or actual
844  // plain text.
845  if (m_tab_widget->currentIndex() == SourceIndex && m_state == SourceChanged)
846  m_editor->setHtml(m_text_edit->toPlainText());
847  return m_editor->text(format);
848 }
849 
851 {
852  // Anything changed, is there a need for a conversion?
853  if (newIndex == SourceIndex && m_state != RichTextChanged)
854  return;
855  if (newIndex == RichTextIndex && m_state != SourceChanged)
856  return;
857  const State oldState = m_state;
858  // Remember the cursor position, since it is invalidated by setPlainText
859  QTextEdit *new_edit = (newIndex == SourceIndex) ? m_text_edit : m_editor;
860  const int position = new_edit->textCursor().position();
861 
862  if (newIndex == SourceIndex) {
863  const QString html = m_editor->text(Qt::RichText);
864  m_text_edit->setPlainText(html);
865 
866  } else
867  m_editor->setHtml(m_text_edit->toPlainText());
868 
869  QTextCursor cursor = new_edit->textCursor();
870  cursor.movePosition(QTextCursor::End);
871  if (cursor.position() > position) {
872  cursor.setPosition(position);
873  }
874  new_edit->setTextCursor(cursor);
875  m_state = oldState; // Changed is triggered by setting the text
876 }
877 
879 {
881 }
882 
884 {
886 }
887 
888 } // namespace qdesigner_internal
889 
890 QT_END_NAMESPACE
891 
892 #include "richtexteditor.moc"
void setupUi(QDialog *AddLinkDialog)
static bool isWhiteSpace(const QStringRef &in)
QIcon South
Definition: qeticons.cpp:161
QLineEdit * titleInput
QToolBar * createToolBar(QWidget *parent=nullptr)
void actionTriggered(QAction *action)
void on_buttonBox_accepted()
RichTextEditorDialog::on_buttonBox_accepted.
void contextMenuEvent(QContextMenuEvent *event) override
RichTextEditorDialog(QWidget *parent=nullptr)
HtmlTextEdit(QWidget *parent=nullptr)
RichTextEditor(QWidget *parent=nullptr)
static void filterAttributes(const QStringRef &name, QXmlStreamAttributes *atts, bool *paragraphAlignmentFound)
static bool filterElement(const QStringRef &name)
QLineEdit * urlInput
static QAction * createCheckableAction(const QIcon &icon, const QString &text, QObject *receiver, const char *slot, QObject *parent=nullptr)
QIcon tr
Definition: qeticons.cpp:204
QString simplifyRichTextFilter(const QString &in, bool *isPlainTextPtr=nullptr)
void setColor(const QColor &color)
void sizeInputActivated(const QString &size)
QString text(Qt::TextFormat format) const
QString text(Qt::TextFormat format=Qt::AutoText) const
QIcon sub
Definition: qeticons.cpp:214
AddLinkDialog(RichTextEditor *editor, QWidget *parent=nullptr)
QIcon Cancel
Definition: qeticons.cpp:34
const QColor & color() const
RichTextEditorToolBar(RichTextEditor *editor, QWidget *parent=nullptr)
QIcon it
Definition: qeticons.cpp:196
QIcon super
Definition: qeticons.cpp:213
Horizontal segment.
Definition: qet.h:87
void setText(const QString &text)
void colorChanged(const QColor &color)