QGIS API Documentation  3.24.2-Tisler (13c1a02865)
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 
220 {
221  switch ( mStackedWidget->currentIndex() )
222  {
223  case 0:
224  return mTextEdit->toPlainText();
225 
226  case 1:
227  // go via text edit to remove html from text...
228  mTextEdit->setText( mSourceEdit->text() );
229  return mTextEdit->toPlainText();
230  }
231  return QString();
232 }
233 
235 {
236  switch ( mStackedWidget->currentIndex() )
237  {
238  case 0:
239  return mTextEdit->toHtml();
240 
241  case 1:
242  return mSourceEdit->text();
243  }
244  return QString();
245 }
246 
247 void QgsRichTextEditor::editSource( bool enabled )
248 {
249  if ( enabled )
250  {
251  mSourceEdit->setText( mTextEdit->toHtml() );
252  mStackedWidget->setCurrentIndex( 1 );
253  }
254  else
255  {
256  mTextEdit->setHtml( mSourceEdit->text() );
257  mStackedWidget->setCurrentIndex( 0 );
258  mSourceEdit->clear();
259  }
260 
261  // disable formatting actions when in html edit mode
262  mFontSizeCombo->setEnabled( !enabled );
263  mParagraphStyleCombo->setEnabled( !enabled );
264  mForeColorButton->setEnabled( !enabled );
265  mBackColorButton->setEnabled( !enabled );
266  mActionUndo->setEnabled( !enabled );
267  mActionRedo->setEnabled( !enabled );
268  mActionCut->setEnabled( !enabled );
269  mActionCopy->setEnabled( !enabled );
270  mActionPaste->setEnabled( !enabled );
271  mActionInsertLink->setEnabled( !enabled );
272  mActionBold->setEnabled( !enabled );
273  mActionItalic->setEnabled( !enabled );
274  mActionUnderline->setEnabled( !enabled );
275  mActionStrikeOut->setEnabled( !enabled );
276  mActionBulletList->setEnabled( !enabled );
277  mActionOrderedList->setEnabled( !enabled );
278  mActionDecreaseIndent->setEnabled( !enabled );
279  mActionIncreaseIndent->setEnabled( !enabled );
280  mActionInsertImage->setEnabled( !enabled );
281 }
282 
284 {
285  mTextEdit->clear();
286 }
287 
288 void QgsRichTextEditor::textRemoveFormat()
289 {
290  QTextCharFormat format;
291  format.setFontWeight( QFont::Normal );
292  format.setFontUnderline( false );
293  format.setFontStrikeOut( false );
294  format.setFontItalic( false );
295  format.setFontPointSize( 9 );
296 
297  mActionBold->setChecked( false );
298  mActionUnderline->setChecked( false );
299  mActionItalic->setChecked( false );
300  mActionStrikeOut->setChecked( false );
301  mFontSizeCombo->setCurrentIndex( mFontSizeCombo->findData( 9 ) );
302 
303  format.clearBackground();
304 
305  mergeFormatOnWordOrSelection( format );
306 }
307 
308 void QgsRichTextEditor::textRemoveAllFormat()
309 {
310  mActionBold->setChecked( false );
311  mActionUnderline->setChecked( false );
312  mActionItalic->setChecked( false );
313  mActionStrikeOut->setChecked( false );
314  mFontSizeCombo->setCurrentIndex( mFontSizeCombo->findData( 9 ) );
315  const QString text = mTextEdit->toPlainText();
316  mTextEdit->setPlainText( text );
317 }
318 
319 void QgsRichTextEditor::textBold()
320 {
321  QTextCharFormat format;
322  format.setFontWeight( mActionBold->isChecked() ? QFont::Bold : QFont::Normal );
323  mergeFormatOnWordOrSelection( format );
324 }
325 
326 void QgsRichTextEditor::focusInEvent( QFocusEvent * )
327 {
328  mTextEdit->setFocus( Qt::TabFocusReason );
329 }
330 
331 void QgsRichTextEditor::textUnderline()
332 {
333  QTextCharFormat format;
334  format.setFontUnderline( mActionUnderline->isChecked() );
335  mergeFormatOnWordOrSelection( format );
336 }
337 
338 void QgsRichTextEditor::textItalic()
339 {
340  QTextCharFormat format;
341  format.setFontItalic( mActionItalic->isChecked() );
342  mergeFormatOnWordOrSelection( format );
343 }
344 
345 void QgsRichTextEditor::textStrikeout()
346 {
347  QTextCharFormat format;
348  format.setFontStrikeOut( mActionStrikeOut->isChecked() );
349  mergeFormatOnWordOrSelection( format );
350 }
351 
352 void QgsRichTextEditor::textSize( const QString &p )
353 {
354  const qreal pointSize = p.toDouble();
355  if ( p.toFloat() > 0 )
356  {
357  QTextCharFormat format;
358  format.setFontPointSize( pointSize );
359  mergeFormatOnWordOrSelection( format );
360  }
361 }
362 
363 void QgsRichTextEditor::textLink( bool checked )
364 {
365  bool unlink = false;
366  QTextCharFormat format;
367  if ( checked )
368  {
369  const QString url = mTextEdit->currentCharFormat().anchorHref();
370  bool ok;
371  const QString newUrl = QInputDialog::getText( this, tr( "Create a Link" ),
372  tr( "Link URL:" ), QLineEdit::Normal,
373  url,
374  &ok );
375  if ( ok )
376  {
377  format.setAnchor( true );
378  format.setAnchorHref( newUrl );
379  format.setForeground( palette().color( QPalette::Link ) );
380  format.setFontUnderline( true );
381  }
382  else
383  {
384  unlink = true;
385  }
386  }
387  else
388  {
389  unlink = true;
390  }
391  if ( unlink )
392  {
393  format.setAnchor( false );
394  format.setForeground( palette().color( QPalette::Text ) );
395  format.setFontUnderline( false );
396  }
397  mergeFormatOnWordOrSelection( format );
398 }
399 
400 void QgsRichTextEditor::textStyle( int )
401 {
402  QTextCursor cursor = mTextEdit->textCursor();
403  cursor.beginEditBlock();
404 
405  // standard
406  if ( !cursor.hasSelection() )
407  {
408  cursor.select( QTextCursor::BlockUnderCursor );
409  }
410  QTextCharFormat format;
411  cursor.setCharFormat( format );
412  mTextEdit->setCurrentCharFormat( format );
413 
414  const ParagraphItems style = static_cast< ParagraphItems >( mParagraphStyleCombo->currentData().toInt() );
415 
416  switch ( style )
417  {
418  case QgsRichTextEditor::ParagraphStandard:
419  break;
420 
421  case QgsRichTextEditor::ParagraphHeading1:
422  format.setFontPointSize( mFontSizeH1 );
423  format.setFontWeight( QFont::Bold );
424  break;
425 
426  case QgsRichTextEditor::ParagraphHeading2:
427  format.setFontPointSize( mFontSizeH2 );
428  format.setFontWeight( QFont::Bold );
429  format.setFontItalic( true );
430  break;
431 
432  case QgsRichTextEditor::ParagraphHeading3:
433  format.setFontPointSize( mFontSizeH3 );
434  format.setFontWeight( QFont::Bold );
435  break;
436 
437  case QgsRichTextEditor::ParagraphHeading4:
438  format.setFontPointSize( mFontSizeH4 );
439  format.setFontWeight( QFont::Bold );
440  format.setFontItalic( true );
441  break;
442 
443  case QgsRichTextEditor::ParagraphMonospace:
444  {
445  format = cursor.charFormat();
446  format.setFontFamily( mMonospaceFontFamily );
447  format.setFontStyleHint( QFont::Monospace );
448  format.setFontFixedPitch( true );
449  break;
450  }
451  }
452 
453  cursor.setCharFormat( format );
454  mTextEdit->setCurrentCharFormat( format );
455 
456  cursor.endEditBlock();
457 }
458 
459 void QgsRichTextEditor::textFgColor()
460 {
461  QTextCharFormat format;
462  format.setForeground( mForeColorButton->color() );
463  mergeFormatOnWordOrSelection( format );
464 }
465 
466 void QgsRichTextEditor::textBgColor()
467 {
468  QTextCharFormat format;
469  const QColor col = mBackColorButton->color();
470  if ( col.isValid() )
471  {
472  format.setBackground( col );
473  }
474  else
475  {
476  format.clearBackground();
477  }
478  mergeFormatOnWordOrSelection( format );
479 }
480 
481 void QgsRichTextEditor::listBullet( bool checked )
482 {
483  if ( checked )
484  {
485  mActionOrderedList->setChecked( false );
486  }
487  list( checked, QTextListFormat::ListDisc );
488 }
489 
490 void QgsRichTextEditor::listOrdered( bool checked )
491 {
492  if ( checked )
493  {
494  mActionBulletList->setChecked( false );
495  }
496  list( checked, QTextListFormat::ListDecimal );
497 }
498 
499 void QgsRichTextEditor::list( bool checked, QTextListFormat::Style style )
500 {
501  QTextCursor cursor = mTextEdit->textCursor();
502  cursor.beginEditBlock();
503  if ( !checked )
504  {
505  const QTextBlockFormat originalFormat = cursor.blockFormat();
506  QTextBlockFormat format;
507  format.setIndent( originalFormat.indent() );
508  cursor.setBlockFormat( format );
509  }
510  else
511  {
512  QTextListFormat listFormat;
513  if ( cursor.currentList() )
514  {
515  listFormat = cursor.currentList()->format();
516  }
517  listFormat.setStyle( style );
518  cursor.createList( listFormat );
519  }
520  cursor.endEditBlock();
521 }
522 
523 void QgsRichTextEditor::mergeFormatOnWordOrSelection( const QTextCharFormat &format )
524 {
525  QTextCursor cursor = mTextEdit->textCursor();
526  if ( !cursor.hasSelection() )
527  {
528  cursor.select( QTextCursor::WordUnderCursor );
529  }
530  cursor.mergeCharFormat( format );
531  mTextEdit->mergeCurrentCharFormat( format );
532  mTextEdit->setFocus( Qt::TabFocusReason );
533 }
534 
535 void QgsRichTextEditor::slotCursorPositionChanged()
536 {
537  QTextList *l = mTextEdit->textCursor().currentList();
538  if ( mLastBlockList && ( l == mLastBlockList || ( l != nullptr && mLastBlockList != nullptr
539  && l->format().style() == mLastBlockList->format().style() ) ) )
540  {
541  return;
542  }
543  mLastBlockList = l;
544  if ( l )
545  {
546  const QTextListFormat listFormat = l->format();
547  if ( listFormat.style() == QTextListFormat::ListDisc )
548  {
549  mActionBulletList->setChecked( true );
550  mActionOrderedList->setChecked( false );
551  }
552  else if ( listFormat.style() == QTextListFormat::ListDecimal )
553  {
554  mActionBulletList->setChecked( false );
555  mActionOrderedList->setChecked( true );
556  }
557  else
558  {
559  mActionBulletList->setChecked( false );
560  mActionOrderedList->setChecked( false );
561  }
562  }
563  else
564  {
565  mActionBulletList->setChecked( false );
566  mActionOrderedList->setChecked( false );
567  }
568 }
569 
570 void QgsRichTextEditor::fontChanged( const QFont &f )
571 {
572  mFontSizeCombo->setCurrentIndex( mFontSizeCombo->findData( f.pointSize() ) );
573  mActionBold->setChecked( f.bold() );
574  mActionItalic->setChecked( f.italic() );
575  mActionUnderline->setChecked( f.underline() );
576  mActionStrikeOut->setChecked( f.strikeOut() );
577  if ( f.pointSize() == mFontSizeH1 )
578  {
579  mParagraphStyleCombo->setCurrentIndex( ParagraphHeading1 );
580  }
581  else if ( f.pointSize() == mFontSizeH2 )
582  {
583  mParagraphStyleCombo->setCurrentIndex( ParagraphHeading2 );
584  }
585  else if ( f.pointSize() == mFontSizeH3 )
586  {
587  mParagraphStyleCombo->setCurrentIndex( ParagraphHeading3 );
588  }
589  else if ( f.pointSize() == mFontSizeH4 )
590  {
591  mParagraphStyleCombo->setCurrentIndex( ParagraphHeading4 );
592  }
593  else
594  {
595  if ( f.fixedPitch() && f.family() == mMonospaceFontFamily )
596  {
597  mParagraphStyleCombo->setCurrentIndex( ParagraphMonospace );
598  }
599  else
600  {
601  mParagraphStyleCombo->setCurrentIndex( ParagraphStandard );
602  }
603  }
604  if ( mTextEdit->textCursor().currentList() )
605  {
606  const QTextListFormat listFormat = mTextEdit->textCursor().currentList()->format();
607  if ( listFormat.style() == QTextListFormat::ListDisc )
608  {
609  mActionBulletList->setChecked( true );
610  mActionOrderedList->setChecked( false );
611  }
612  else if ( listFormat.style() == QTextListFormat::ListDecimal )
613  {
614  mActionBulletList->setChecked( false );
615  mActionOrderedList->setChecked( true );
616  }
617  else
618  {
619  mActionBulletList->setChecked( false );
620  mActionOrderedList->setChecked( false );
621  }
622  }
623  else
624  {
625  mActionBulletList->setChecked( false );
626  mActionOrderedList->setChecked( false );
627  }
628 }
629 
630 void QgsRichTextEditor::fgColorChanged( const QColor &c )
631 {
632  whileBlocking( mForeColorButton )->setColor( c );
633 }
634 
635 void QgsRichTextEditor::bgColorChanged( const QColor &c )
636 {
637  if ( c.isValid() )
638  whileBlocking( mBackColorButton )->setColor( c );
639  else
640  whileBlocking( mBackColorButton )->setToNull();
641 }
642 
643 void QgsRichTextEditor::slotCurrentCharFormatChanged( const QTextCharFormat &format )
644 {
645  fontChanged( format.font() );
646  bgColorChanged( ( format.background().isOpaque() ) ? format.background().color() : QColor() );
647  fgColorChanged( ( format.foreground().isOpaque() ) ? format.foreground().color() : palette().windowText().color() );
648  mActionInsertLink->setChecked( format.isAnchor() );
649 }
650 
651 void QgsRichTextEditor::slotClipboardDataChanged()
652 {
653 #ifndef QT_NO_CLIPBOARD
654  if ( const QMimeData *md = QApplication::clipboard()->mimeData() )
655  mActionPaste->setEnabled( md->hasText() );
656 #endif
657 }
658 
659 void QgsRichTextEditor::increaseIndentation()
660 {
661  indent( +1 );
662 }
663 
664 void QgsRichTextEditor::decreaseIndentation()
665 {
666  indent( -1 );
667 }
668 
669 void QgsRichTextEditor::indent( int delta )
670 {
671  QTextCursor cursor = mTextEdit->textCursor();
672  cursor.beginEditBlock();
673  QTextBlockFormat format = cursor.blockFormat();
674  const int indent = format.indent();
675  if ( indent + delta >= 0 )
676  {
677  format.setIndent( indent + delta );
678  }
679  cursor.setBlockFormat( format );
680  cursor.endEditBlock();
681 }
682 
683 void QgsRichTextEditor::setText( const QString &text )
684 {
685  if ( text.isEmpty() )
686  {
687  setPlainText( text );
688  return;
689  }
690  if ( text[0] == '<' )
691  {
692  setHtml( text );
693  }
694  else
695  {
696  setPlainText( text );
697  }
698 }
699 
700 void QgsRichTextEditor::insertImage()
701 {
702  const QSettings s;
703  const QString attdir = s.value( QStringLiteral( "general/filedialog-path" ) ).toString();
704  const QString file = QFileDialog::getOpenFileName( this,
705  tr( "Select an image" ),
706  attdir,
707  tr( "JPEG (*.jpg);; GIF (*.gif);; PNG (*.png);; BMP (*.bmp);; All (*)" ) );
708  if ( file.isEmpty() )
709  return;
710 
711  const QImage image = QImageReader( file ).read();
712 
713  mTextEdit->dropImage( image, QFileInfo( file ).suffix().toUpper().toLocal8Bit().data() );
714 }
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 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:1517