QGIS API Documentation  3.25.0-Master (dec16ba68b)
qgsrichtexteditor.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Jiří Procházka (Hobrasoft)
4 ** Contact: http://www.hobrasoft.cz/
5 **
6 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
7 ** Contact: http://www.qt-project.org/legal
8 **
9 ** This library is free software; you can redistribute it and/or
10 ** modify it under the terms of the GNU Lesser General Public
11 ** License as published by the Free Software Foundation; either
12 ** version 2.1 of the License, or (at your option) any later version.
13 **
14 ** $QT_BEGIN_LICENSE:LGPL$
15 ** GNU Lesser General Public License Usage
16 ** This file is under the terms of the GNU Lesser General Public License
17 ** version 2.1 as published by the Free Software Foundation and appearing
18 ** in the file LICENSE.LGPL included in the packaging of this file.
19 ** Please review the following information to ensure the
20 ** GNU Lesser General Public License version 2.1 requirements
21 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 **
23 ** In addition, as a special exception, Digia gives you certain additional
24 ** rights. These rights are described in the Digia Qt LGPL Exception
25 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 **
27 ** $QT_END_LICENSE$
28 **
29 ****************************************************************************/
30 
31 #include "qgsrichtexteditor.h"
32 #include "qgsguiutils.h"
33 #include "qgscolorbutton.h"
34 #include "qgscodeeditor.h"
35 #include "qgscodeeditorhtml.h"
36 
37 #include <QMimeData>
38 #include <QApplication>
39 #include <QClipboard>
40 #include <QFontDatabase>
41 #include <QInputDialog>
42 #include <QTextList>
43 #include <QtDebug>
44 #include <QFileDialog>
45 #include <QImageReader>
46 #include <QSettings>
47 #include <QUrl>
48 #include <QMenu>
49 #include <QComboBox>
50 #include <QToolButton>
51 
53  : QWidget( parent )
54 {
55  setupUi( this );
56 
57  mMonospaceFontFamily = QgsCodeEditor::getMonospaceFont().family();
58 
59  QVBoxLayout *sourceLayout = new QVBoxLayout();
60  sourceLayout->setContentsMargins( 0, 0, 0, 0 );
61  mSourceEdit = new QgsCodeEditorHTML();
62  sourceLayout->addWidget( mSourceEdit );
63  mPageSourceEdit->setLayout( sourceLayout );
64 
65  mToolBar->setIconSize( QgsGuiUtils::iconSize( false ) );
66 
67  connect( mTextEdit, &QTextEdit::currentCharFormatChanged, this, &QgsRichTextEditor::slotCurrentCharFormatChanged );
68  connect( mTextEdit, &QTextEdit::cursorPositionChanged, this, &QgsRichTextEditor::slotCursorPositionChanged );
69 
70  // paragraph formatting
71  mParagraphStyleCombo = new QComboBox();
72  mParagraphStyleCombo->addItem( tr( "Standard" ), ParagraphStandard );
73  mParagraphStyleCombo->addItem( tr( "Heading 1" ), ParagraphHeading1 );
74  mParagraphStyleCombo->addItem( tr( "Heading 2" ), ParagraphHeading2 );
75  mParagraphStyleCombo->addItem( tr( "Heading 3" ), ParagraphHeading3 );
76  mParagraphStyleCombo->addItem( tr( "Heading 4" ), ParagraphHeading4 );
77  mParagraphStyleCombo->addItem( tr( "Monospace" ), ParagraphMonospace );
78 
79  connect( mParagraphStyleCombo, qOverload< int >( &QComboBox::activated ), this, &QgsRichTextEditor::textStyle );
80  mToolBar->insertWidget( mToolBar->actions().at( 0 ), mParagraphStyleCombo );
81 
82  mFontSizeCombo = new QComboBox();
83  mFontSizeCombo->setEditable( true );
84  mToolBar->insertWidget( mActionBold, mFontSizeCombo );
85 
86  // undo & redo
87  mActionUndo->setShortcut( QKeySequence::Undo );
88  mActionRedo->setShortcut( QKeySequence::Redo );
89 
90  connect( mTextEdit->document(), &QTextDocument::undoAvailable, mActionUndo, &QAction::setEnabled );
91  connect( mTextEdit->document(), &QTextDocument::redoAvailable, mActionRedo, &QAction::setEnabled );
92 
93  mActionUndo->setEnabled( mTextEdit->document()->isUndoAvailable() );
94  mActionRedo->setEnabled( mTextEdit->document()->isRedoAvailable() );
95 
96  connect( mActionUndo, &QAction::triggered, mTextEdit, &QTextEdit::undo );
97  connect( mActionRedo, &QAction::triggered, mTextEdit, &QTextEdit::redo );
98 
99  // cut, copy & paste
100  mActionCut->setShortcut( QKeySequence::Cut );
101  mActionCopy->setShortcut( QKeySequence::Copy );
102  mActionPaste->setShortcut( QKeySequence::Paste );
103 
104  mActionCut->setEnabled( false );
105  mActionCopy->setEnabled( false );
106 
107  connect( mActionCut, &QAction::triggered, mTextEdit, &QTextEdit::cut );
108  connect( mActionCopy, &QAction::triggered, mTextEdit, &QTextEdit::copy );
109  connect( mActionPaste, &QAction::triggered, mTextEdit, &QTextEdit::paste );
110 
111  connect( mTextEdit, &QTextEdit::copyAvailable, mActionCut, &QAction::setEnabled );
112  connect( mTextEdit, &QTextEdit::copyAvailable, mActionCopy, &QAction::setEnabled );
113 
114 #ifndef QT_NO_CLIPBOARD
115  connect( QApplication::clipboard(), &QClipboard::dataChanged, this, &QgsRichTextEditor::slotClipboardDataChanged );
116 #endif
117 
118  // link
119  mActionInsertLink->setShortcut( QKeySequence( QStringLiteral( "CTRL+L" ) ) );
120  connect( mActionInsertLink, &QAction::triggered, this, &QgsRichTextEditor::textLink );
121 
122  // bold, italic & underline
123  mActionBold->setShortcut( QKeySequence( QStringLiteral( "CTRL+B" ) ) );
124  mActionItalic->setShortcut( QKeySequence( QStringLiteral( "CTRL+I" ) ) );
125  mActionUnderline->setShortcut( QKeySequence( QStringLiteral( "CTRL+U" ) ) );
126 
127  connect( mActionBold, &QAction::triggered, this, &QgsRichTextEditor::textBold );
128  connect( mActionItalic, &QAction::triggered, this, &QgsRichTextEditor::textItalic );
129  connect( mActionUnderline, &QAction::triggered, this, &QgsRichTextEditor::textUnderline );
130  connect( mActionStrikeOut, &QAction::triggered, this, &QgsRichTextEditor::textStrikeout );
131 
132  QAction *removeFormat = new QAction( tr( "Remove Character Formatting" ), this );
133  removeFormat->setShortcut( QKeySequence( QStringLiteral( "CTRL+M" ) ) );
134  connect( removeFormat, &QAction::triggered, this, &QgsRichTextEditor::textRemoveFormat );
135  mTextEdit->addAction( removeFormat );
136 
137  QAction *removeAllFormat = new QAction( tr( "Remove all Formatting" ), this );
138  connect( removeAllFormat, &QAction::triggered, this, &QgsRichTextEditor::textRemoveAllFormat );
139  mTextEdit->addAction( removeAllFormat );
140 
141  QAction *clearText = new QAction( tr( "Clear all Content" ), this );
142  connect( clearText, &QAction::triggered, this, &QgsRichTextEditor::clearSource );
143  mTextEdit->addAction( clearText );
144 
145  QMenu *menu = new QMenu( this );
146  menu->addAction( removeAllFormat );
147  menu->addAction( removeFormat );
148  menu->addAction( clearText );
149 
150  QToolButton *menuButton = new QToolButton();
151  menuButton->setMenu( menu );
152  menuButton->setPopupMode( QToolButton::InstantPopup );
153  menuButton->setToolTip( tr( "Advanced Options" ) );
154  menuButton->setText( QStringLiteral( "…" ) );
155  QWidget *spacer = new QWidget();
156  spacer->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
157  mToolBar->addWidget( spacer );
158  mToolBar->addWidget( menuButton );
159 
160  // lists
161  mActionBulletList->setShortcut( QKeySequence( QStringLiteral( "CTRL+-" ) ) );
162  mActionOrderedList->setShortcut( QKeySequence( QStringLiteral( "CTRL+=" ) ) );
163  connect( mActionBulletList, &QAction::triggered, this, &QgsRichTextEditor::listBullet );
164  connect( mActionOrderedList, &QAction::triggered, this, &QgsRichTextEditor::listOrdered );
165 
166  // indentation
167  mActionDecreaseIndent->setShortcut( QKeySequence( QStringLiteral( "CTRL+," ) ) );
168  mActionIncreaseIndent->setShortcut( QKeySequence( QStringLiteral( "CTRL+." ) ) );
169  connect( mActionIncreaseIndent, &QAction::triggered, this, &QgsRichTextEditor::increaseIndentation );
170  connect( mActionDecreaseIndent, &QAction::triggered, this, &QgsRichTextEditor::decreaseIndentation );
171 
172  // font size
173  const QList< int > sizes = QFontDatabase::standardSizes();
174  for ( const int size : sizes )
175  mFontSizeCombo->addItem( QString::number( size ), size );
176 
177  mFontSizeCombo->setCurrentIndex( mFontSizeCombo->findData( QApplication::font().pointSize() ) );
178 
179  // text foreground color
180  mForeColorButton = new QgsColorButton();
181  mForeColorButton->setAllowOpacity( false );
182  mForeColorButton->setColorDialogTitle( tr( "Foreground Color" ) );
183  mForeColorButton->setColor( palette().windowText().color() );
184  mForeColorButton->setShowNoColor( false );
185  mForeColorButton->setToolTip( tr( "Foreground color" ) );
186  mForeColorButton->setMinimumWidth( QFontMetrics( font() ).horizontalAdvance( QStringLiteral( "x" ) ) * 10 );
187  mForeColorButton->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
188 
189  QAction *listSeparator = mToolBar->insertSeparator( mActionBulletList );
190 
191  connect( mForeColorButton, &QgsColorButton::colorChanged, this, &QgsRichTextEditor::textFgColor );
192  mToolBar->insertWidget( listSeparator, mForeColorButton );
193 
194  // text background color
195  mBackColorButton = new QgsColorButton();
196  mBackColorButton->setAllowOpacity( false );
197  mBackColorButton->setColorDialogTitle( tr( "Background Color" ) );
198  mBackColorButton->setToolTip( tr( "Background color" ) );
199  mBackColorButton->setShowNull( true, tr( "No Background Color" ) );
200  mBackColorButton->setToNull();
201  mBackColorButton->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed );
202  mBackColorButton->setMinimumWidth( QFontMetrics( font() ).horizontalAdvance( QStringLiteral( "x" ) ) * 10 );
203  connect( mBackColorButton, &QgsColorButton::colorChanged, this, &QgsRichTextEditor::textBgColor );
204  mToolBar->insertWidget( listSeparator, mBackColorButton );
205 
206  connect( mActionEditSource, &QAction::toggled, this, &QgsRichTextEditor::editSource );
207 
208  // images
209  connect( mActionInsertImage, &QAction::triggered, this, &QgsRichTextEditor::insertImage );
210 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
211  connect( mFontSizeCombo, qOverload< const QString &>( &QComboBox::activated ), this, &QgsRichTextEditor::textSize );
212 #else
213  connect( mFontSizeCombo, &QComboBox::textActivated, this, &QgsRichTextEditor::textSize );
214 #endif
215 
216  fontChanged( mTextEdit->font() );
217 
218  connect( mTextEdit, &QTextEdit::textChanged, this, &QgsRichTextEditor::textChanged );
219  connect( mSourceEdit, &QgsCodeEditorHTML::textChanged, this, &QgsRichTextEditor::textChanged );
220 }
221 
223 {
224  switch ( mStackedWidget->currentIndex() )
225  {
226  case 0:
227  return mTextEdit->toPlainText();
228 
229  case 1:
230  // go via text edit to remove html from text...
231  mTextEdit->setText( mSourceEdit->text() );
232  return mTextEdit->toPlainText();
233  }
234  return QString();
235 }
236 
238 {
239  switch ( mStackedWidget->currentIndex() )
240  {
241  case 0:
242  return mTextEdit->toHtml();
243 
244  case 1:
245  return mSourceEdit->text();
246  }
247  return QString();
248 }
249 
250 void QgsRichTextEditor::editSource( bool enabled )
251 {
252  if ( enabled )
253  {
254  mSourceEdit->setText( mTextEdit->toHtml() );
255  mStackedWidget->setCurrentIndex( 1 );
256  }
257  else
258  {
259  mTextEdit->setHtml( mSourceEdit->text() );
260  mStackedWidget->setCurrentIndex( 0 );
261  mSourceEdit->clear();
262  }
263 
264  // disable formatting actions when in html edit mode
265  mFontSizeCombo->setEnabled( !enabled );
266  mParagraphStyleCombo->setEnabled( !enabled );
267  mForeColorButton->setEnabled( !enabled );
268  mBackColorButton->setEnabled( !enabled );
269  mActionUndo->setEnabled( !enabled );
270  mActionRedo->setEnabled( !enabled );
271  mActionCut->setEnabled( !enabled );
272  mActionCopy->setEnabled( !enabled );
273  mActionPaste->setEnabled( !enabled );
274  mActionInsertLink->setEnabled( !enabled );
275  mActionBold->setEnabled( !enabled );
276  mActionItalic->setEnabled( !enabled );
277  mActionUnderline->setEnabled( !enabled );
278  mActionStrikeOut->setEnabled( !enabled );
279  mActionBulletList->setEnabled( !enabled );
280  mActionOrderedList->setEnabled( !enabled );
281  mActionDecreaseIndent->setEnabled( !enabled );
282  mActionIncreaseIndent->setEnabled( !enabled );
283  mActionInsertImage->setEnabled( !enabled );
284 }
285 
287 {
288  mTextEdit->clear();
289 }
290 
291 void QgsRichTextEditor::textRemoveFormat()
292 {
293  QTextCharFormat format;
294  format.setFontWeight( QFont::Normal );
295  format.setFontUnderline( false );
296  format.setFontStrikeOut( false );
297  format.setFontItalic( false );
298  format.setFontPointSize( 9 );
299 
300  mActionBold->setChecked( false );
301  mActionUnderline->setChecked( false );
302  mActionItalic->setChecked( false );
303  mActionStrikeOut->setChecked( false );
304  mFontSizeCombo->setCurrentIndex( mFontSizeCombo->findData( 9 ) );
305 
306  format.clearBackground();
307 
308  mergeFormatOnWordOrSelection( format );
309 }
310 
311 void QgsRichTextEditor::textRemoveAllFormat()
312 {
313  mActionBold->setChecked( false );
314  mActionUnderline->setChecked( false );
315  mActionItalic->setChecked( false );
316  mActionStrikeOut->setChecked( false );
317  mFontSizeCombo->setCurrentIndex( mFontSizeCombo->findData( 9 ) );
318  const QString text = mTextEdit->toPlainText();
319  mTextEdit->setPlainText( text );
320 }
321 
322 void QgsRichTextEditor::textBold()
323 {
324  QTextCharFormat format;
325  format.setFontWeight( mActionBold->isChecked() ? QFont::Bold : QFont::Normal );
326  mergeFormatOnWordOrSelection( format );
327 }
328 
329 void QgsRichTextEditor::focusInEvent( QFocusEvent * )
330 {
331  mTextEdit->setFocus( Qt::TabFocusReason );
332 }
333 
334 void QgsRichTextEditor::textUnderline()
335 {
336  QTextCharFormat format;
337  format.setFontUnderline( mActionUnderline->isChecked() );
338  mergeFormatOnWordOrSelection( format );
339 }
340 
341 void QgsRichTextEditor::textItalic()
342 {
343  QTextCharFormat format;
344  format.setFontItalic( mActionItalic->isChecked() );
345  mergeFormatOnWordOrSelection( format );
346 }
347 
348 void QgsRichTextEditor::textStrikeout()
349 {
350  QTextCharFormat format;
351  format.setFontStrikeOut( mActionStrikeOut->isChecked() );
352  mergeFormatOnWordOrSelection( format );
353 }
354 
355 void QgsRichTextEditor::textSize( const QString &p )
356 {
357  const qreal pointSize = p.toDouble();
358  if ( p.toFloat() > 0 )
359  {
360  QTextCharFormat format;
361  format.setFontPointSize( pointSize );
362  mergeFormatOnWordOrSelection( format );
363  }
364 }
365 
366 void QgsRichTextEditor::textLink( bool checked )
367 {
368  bool unlink = false;
369  QTextCharFormat format;
370  if ( checked )
371  {
372  const QString url = mTextEdit->currentCharFormat().anchorHref();
373  bool ok;
374  const QString newUrl = QInputDialog::getText( this, tr( "Create a Link" ),
375  tr( "Link URL:" ), QLineEdit::Normal,
376  url,
377  &ok );
378  if ( ok )
379  {
380  format.setAnchor( true );
381  format.setAnchorHref( newUrl );
382  format.setForeground( palette().color( QPalette::Link ) );
383  format.setFontUnderline( true );
384  }
385  else
386  {
387  unlink = true;
388  }
389  }
390  else
391  {
392  unlink = true;
393  }
394  if ( unlink )
395  {
396  format.setAnchor( false );
397  format.setForeground( palette().color( QPalette::Text ) );
398  format.setFontUnderline( false );
399  }
400  mergeFormatOnWordOrSelection( format );
401 }
402 
403 void QgsRichTextEditor::textStyle( int )
404 {
405  QTextCursor cursor = mTextEdit->textCursor();
406  cursor.beginEditBlock();
407 
408  // standard
409  if ( !cursor.hasSelection() )
410  {
411  cursor.select( QTextCursor::BlockUnderCursor );
412  }
413  QTextCharFormat format;
414  cursor.setCharFormat( format );
415  mTextEdit->setCurrentCharFormat( format );
416 
417  const ParagraphItems style = static_cast< ParagraphItems >( mParagraphStyleCombo->currentData().toInt() );
418 
419  switch ( style )
420  {
421  case QgsRichTextEditor::ParagraphStandard:
422  break;
423 
424  case QgsRichTextEditor::ParagraphHeading1:
425  format.setFontPointSize( mFontSizeH1 );
426  format.setFontWeight( QFont::Bold );
427  break;
428 
429  case QgsRichTextEditor::ParagraphHeading2:
430  format.setFontPointSize( mFontSizeH2 );
431  format.setFontWeight( QFont::Bold );
432  format.setFontItalic( true );
433  break;
434 
435  case QgsRichTextEditor::ParagraphHeading3:
436  format.setFontPointSize( mFontSizeH3 );
437  format.setFontWeight( QFont::Bold );
438  break;
439 
440  case QgsRichTextEditor::ParagraphHeading4:
441  format.setFontPointSize( mFontSizeH4 );
442  format.setFontWeight( QFont::Bold );
443  format.setFontItalic( true );
444  break;
445 
446  case QgsRichTextEditor::ParagraphMonospace:
447  {
448  format = cursor.charFormat();
449  format.setFontFamily( mMonospaceFontFamily );
450  format.setFontStyleHint( QFont::Monospace );
451  format.setFontFixedPitch( true );
452  break;
453  }
454  }
455 
456  cursor.setCharFormat( format );
457  mTextEdit->setCurrentCharFormat( format );
458 
459  cursor.endEditBlock();
460 }
461 
462 void QgsRichTextEditor::textFgColor()
463 {
464  QTextCharFormat format;
465  format.setForeground( mForeColorButton->color() );
466  mergeFormatOnWordOrSelection( format );
467 }
468 
469 void QgsRichTextEditor::textBgColor()
470 {
471  QTextCharFormat format;
472  const QColor col = mBackColorButton->color();
473  if ( col.isValid() )
474  {
475  format.setBackground( col );
476  }
477  else
478  {
479  format.clearBackground();
480  }
481  mergeFormatOnWordOrSelection( format );
482 }
483 
484 void QgsRichTextEditor::listBullet( bool checked )
485 {
486  if ( checked )
487  {
488  mActionOrderedList->setChecked( false );
489  }
490  list( checked, QTextListFormat::ListDisc );
491 }
492 
493 void QgsRichTextEditor::listOrdered( bool checked )
494 {
495  if ( checked )
496  {
497  mActionBulletList->setChecked( false );
498  }
499  list( checked, QTextListFormat::ListDecimal );
500 }
501 
502 void QgsRichTextEditor::list( bool checked, QTextListFormat::Style style )
503 {
504  QTextCursor cursor = mTextEdit->textCursor();
505  cursor.beginEditBlock();
506  if ( !checked )
507  {
508  const QTextBlockFormat originalFormat = cursor.blockFormat();
509  QTextBlockFormat format;
510  format.setIndent( originalFormat.indent() );
511  cursor.setBlockFormat( format );
512  }
513  else
514  {
515  QTextListFormat listFormat;
516  if ( cursor.currentList() )
517  {
518  listFormat = cursor.currentList()->format();
519  }
520  listFormat.setStyle( style );
521  cursor.createList( listFormat );
522  }
523  cursor.endEditBlock();
524 }
525 
526 void QgsRichTextEditor::mergeFormatOnWordOrSelection( const QTextCharFormat &format )
527 {
528  QTextCursor cursor = mTextEdit->textCursor();
529  if ( !cursor.hasSelection() )
530  {
531  cursor.select( QTextCursor::WordUnderCursor );
532  }
533  cursor.mergeCharFormat( format );
534  mTextEdit->mergeCurrentCharFormat( format );
535  mTextEdit->setFocus( Qt::TabFocusReason );
536 }
537 
538 void QgsRichTextEditor::slotCursorPositionChanged()
539 {
540  QTextList *l = mTextEdit->textCursor().currentList();
541  if ( mLastBlockList && ( l == mLastBlockList || ( l != nullptr && mLastBlockList != nullptr
542  && l->format().style() == mLastBlockList->format().style() ) ) )
543  {
544  return;
545  }
546  mLastBlockList = l;
547  if ( l )
548  {
549  const QTextListFormat listFormat = l->format();
550  if ( listFormat.style() == QTextListFormat::ListDisc )
551  {
552  mActionBulletList->setChecked( true );
553  mActionOrderedList->setChecked( false );
554  }
555  else if ( listFormat.style() == QTextListFormat::ListDecimal )
556  {
557  mActionBulletList->setChecked( false );
558  mActionOrderedList->setChecked( true );
559  }
560  else
561  {
562  mActionBulletList->setChecked( false );
563  mActionOrderedList->setChecked( false );
564  }
565  }
566  else
567  {
568  mActionBulletList->setChecked( false );
569  mActionOrderedList->setChecked( false );
570  }
571 }
572 
573 void QgsRichTextEditor::fontChanged( const QFont &f )
574 {
575  mFontSizeCombo->setCurrentIndex( mFontSizeCombo->findData( f.pointSize() ) );
576  mActionBold->setChecked( f.bold() );
577  mActionItalic->setChecked( f.italic() );
578  mActionUnderline->setChecked( f.underline() );
579  mActionStrikeOut->setChecked( f.strikeOut() );
580  if ( f.pointSize() == mFontSizeH1 )
581  {
582  mParagraphStyleCombo->setCurrentIndex( ParagraphHeading1 );
583  }
584  else if ( f.pointSize() == mFontSizeH2 )
585  {
586  mParagraphStyleCombo->setCurrentIndex( ParagraphHeading2 );
587  }
588  else if ( f.pointSize() == mFontSizeH3 )
589  {
590  mParagraphStyleCombo->setCurrentIndex( ParagraphHeading3 );
591  }
592  else if ( f.pointSize() == mFontSizeH4 )
593  {
594  mParagraphStyleCombo->setCurrentIndex( ParagraphHeading4 );
595  }
596  else
597  {
598  if ( f.fixedPitch() && f.family() == mMonospaceFontFamily )
599  {
600  mParagraphStyleCombo->setCurrentIndex( ParagraphMonospace );
601  }
602  else
603  {
604  mParagraphStyleCombo->setCurrentIndex( ParagraphStandard );
605  }
606  }
607  if ( mTextEdit->textCursor().currentList() )
608  {
609  const QTextListFormat listFormat = mTextEdit->textCursor().currentList()->format();
610  if ( listFormat.style() == QTextListFormat::ListDisc )
611  {
612  mActionBulletList->setChecked( true );
613  mActionOrderedList->setChecked( false );
614  }
615  else if ( listFormat.style() == QTextListFormat::ListDecimal )
616  {
617  mActionBulletList->setChecked( false );
618  mActionOrderedList->setChecked( true );
619  }
620  else
621  {
622  mActionBulletList->setChecked( false );
623  mActionOrderedList->setChecked( false );
624  }
625  }
626  else
627  {
628  mActionBulletList->setChecked( false );
629  mActionOrderedList->setChecked( false );
630  }
631 }
632 
633 void QgsRichTextEditor::fgColorChanged( const QColor &c )
634 {
635  whileBlocking( mForeColorButton )->setColor( c );
636 }
637 
638 void QgsRichTextEditor::bgColorChanged( const QColor &c )
639 {
640  if ( c.isValid() )
641  whileBlocking( mBackColorButton )->setColor( c );
642  else
643  whileBlocking( mBackColorButton )->setToNull();
644 }
645 
646 void QgsRichTextEditor::slotCurrentCharFormatChanged( const QTextCharFormat &format )
647 {
648  fontChanged( format.font() );
649  bgColorChanged( ( format.background().isOpaque() ) ? format.background().color() : QColor() );
650  fgColorChanged( ( format.foreground().isOpaque() ) ? format.foreground().color() : palette().windowText().color() );
651  mActionInsertLink->setChecked( format.isAnchor() );
652 }
653 
654 void QgsRichTextEditor::slotClipboardDataChanged()
655 {
656 #ifndef QT_NO_CLIPBOARD
657  if ( const QMimeData *md = QApplication::clipboard()->mimeData() )
658  mActionPaste->setEnabled( md->hasText() );
659 #endif
660 }
661 
662 void QgsRichTextEditor::increaseIndentation()
663 {
664  indent( +1 );
665 }
666 
667 void QgsRichTextEditor::decreaseIndentation()
668 {
669  indent( -1 );
670 }
671 
672 void QgsRichTextEditor::indent( int delta )
673 {
674  QTextCursor cursor = mTextEdit->textCursor();
675  cursor.beginEditBlock();
676  QTextBlockFormat format = cursor.blockFormat();
677  const int indent = format.indent();
678  if ( indent + delta >= 0 )
679  {
680  format.setIndent( indent + delta );
681  }
682  cursor.setBlockFormat( format );
683  cursor.endEditBlock();
684 }
685 
686 void QgsRichTextEditor::setText( const QString &text )
687 {
688  if ( text.isEmpty() )
689  {
690  setPlainText( text );
691  return;
692  }
693  if ( text[0] == '<' )
694  {
695  setHtml( text );
696  }
697  else
698  {
699  setPlainText( text );
700  }
701 }
702 
703 void QgsRichTextEditor::insertImage()
704 {
705  const QSettings s;
706  const QString attdir = s.value( QStringLiteral( "general/filedialog-path" ) ).toString();
707  const QString file = QFileDialog::getOpenFileName( this,
708  tr( "Select an image" ),
709  attdir,
710  tr( "JPEG (*.jpg);; GIF (*.gif);; PNG (*.png);; BMP (*.bmp);; All (*)" ) );
711  if ( file.isEmpty() )
712  return;
713 
714  const QImage image = QImageReader( file ).read();
715 
716  mTextEdit->dropImage( image, QFileInfo( file ).suffix().toUpper().toLocal8Bit().data() );
717 }
A HTML editor based on QScintilla2.
static QFont getMonospaceFont()
Returns the monospaced font to use for code editors.
A cross platform button subclass for selecting colors.
void colorChanged(const QColor &color)
Emitted whenever a new color is set for the button.
void setColorDialogTitle(const QString &title)
Set the title for the color chooser dialog window.
void setShowNull(bool showNull, const QString &nullString=QString())
Sets whether a set to null (clear) option is shown in the button's drop-down menu.
void setAllowOpacity(bool allowOpacity)
Sets whether opacity modification (transparency) is permitted for the color.
void setShowNoColor(const bool showNoColorOption)
Sets whether the "no color" option should be shown in the button's drop-down menu.
void setToNull()
Sets color to null.
void setColor(const QColor &color)
Sets the current color for the button.
QgsRichTextEditor(QWidget *parent=nullptr)
Constructor for QgsRichTextEditor, with the specified parent widget.
QString toPlainText() const
Returns the widget's content as a plain text string.
QString toHtml() const
Returns the widget's content as a HTML string.
void textChanged()
Emitted when the text contents are changed.
void clearSource()
Clears the current text from the widget.
void focusInEvent(QFocusEvent *event) override
void setText(const QString &text)
Sets the text to show in the widget.
QSize iconSize(bool dockableToolbar)
Returns the user-preferred size of a window's toolbar icons.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:1929