20#include <QDesktopServices> 
   29  , mCopyValueAction( new QAction( tr( 
"Copy value" ), this ) )
 
   30  , mCopyKeyAction( new QAction( tr( 
"Copy key" ), this ) )
 
   36  mCodeEditorJson->setReadOnly( 
true );
 
   37  mCodeEditorJson->setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
 
   38  mCodeEditorJson->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
 
   39  mCodeEditorJson->indicatorDefine( QsciScintilla::PlainIndicator, SCINTILLA_UNDERLINE_INDICATOR_INDEX );
 
   40  mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_SETINDICATORCURRENT, SCINTILLA_UNDERLINE_INDICATOR_INDEX );
 
   41  mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_SETMOUSEDWELLTIME, 400 );
 
   45  mTreeWidget->setContextMenuPolicy( Qt::ActionsContextMenu );
 
   46  mTreeWidget->addAction( mCopyValueAction );
 
   47  mTreeWidget->addAction( mCopyKeyAction );
 
   49  connect( mTextToolButton, &QToolButton::clicked, 
this, &QgsJsonEditWidget::textToolButtonClicked );
 
   50  connect( mTreeToolButton, &QToolButton::clicked, 
this, &QgsJsonEditWidget::treeToolButtonClicked );
 
   52  connect( mCopyValueAction, &QAction::triggered, 
this, &QgsJsonEditWidget::copyValueActionTriggered );
 
   53  connect( mCopyKeyAction, &QAction::triggered, 
this, &QgsJsonEditWidget::copyKeyActionTriggered );
 
   55  connect( mCodeEditorJson, &QgsCodeEditorJson::textChanged, 
this, &QgsJsonEditWidget::codeEditorJsonTextChanged );
 
   58  connect( mCodeEditorJson, &QsciScintilla::indicatorClicked, 
this, &QgsJsonEditWidget::codeEditorJsonIndicatorClicked );
 
   59  connect( mCodeEditorJson, &QsciScintillaBase::SCN_DWELLSTART, 
this, &QgsJsonEditWidget::codeEditorJsonDwellStart );
 
   60  connect( mCodeEditorJson, &QsciScintillaBase::SCN_DWELLEND, 
this, &QgsJsonEditWidget::codeEditorJsonDwellEnd );
 
   66  mClickableLinkList.clear();
 
   68  const QJsonDocument jsonDocument = QJsonDocument::fromJson( mJsonText.toUtf8() );
 
   70  mCodeEditorJson->blockSignals( 
true );
 
   71  if ( jsonDocument.isNull() )
 
   73    mCodeEditorJson->setText( mJsonText );
 
   77    switch ( mFormatJsonMode )
 
   80        mCodeEditorJson->setText( jsonDocument.toJson( QJsonDocument::Indented ) );
 
   83        mCodeEditorJson->setText( jsonDocument.toJson( QJsonDocument::Compact ) );
 
   86        mCodeEditorJson->setText( mJsonText );
 
   90  mCodeEditorJson->blockSignals( 
false );
 
   92  refreshTreeView( jsonDocument );
 
  106      mStackedWidget->setCurrentWidget( mStackedWidgetPageText );
 
  107      mTextToolButton->setChecked( 
true );
 
  108      mTreeToolButton->setChecked( 
false );
 
  113      mStackedWidget->setCurrentWidget( mStackedWidgetPageTree );
 
  114      mTreeToolButton->setChecked( 
true );
 
  115      mTextToolButton->setChecked( 
false );
 
  123  mFormatJsonMode = formatJson;
 
  128  mControlsWidget->setVisible( visible );
 
  131void QgsJsonEditWidget::textToolButtonClicked( 
bool checked )
 
  139void QgsJsonEditWidget::treeToolButtonClicked( 
bool checked )
 
  147void QgsJsonEditWidget::copyValueActionTriggered()
 
  149  if ( !mTreeWidget->currentItem() )
 
  152  const QJsonValue jsonValue = QJsonValue::fromVariant( mTreeWidget->currentItem()->data( 
static_cast<int>( TreeWidgetColumn::Value ), Qt::UserRole ) );
 
  154  switch ( jsonValue.type() )
 
  156    case QJsonValue::Null:
 
  157    case QJsonValue::Bool:
 
  158    case QJsonValue::Double:
 
  159    case QJsonValue::Undefined:
 
  160      QApplication::clipboard()->setText( mTreeWidget->currentItem()->text( 
static_cast<int>( TreeWidgetColumn::Value ) ) );
 
  162    case QJsonValue::String:
 
  163      QApplication::clipboard()->setText( jsonValue.toString() );
 
  165    case QJsonValue::Array:
 
  167      const QJsonDocument jsonDocument( jsonValue.toArray() );
 
  168      QApplication::clipboard()->setText( jsonDocument.toJson() );
 
  171    case QJsonValue::Object:
 
  173      const QJsonDocument jsonDocument( jsonValue.toObject() );
 
  174      QApplication::clipboard()->setText( jsonDocument.toJson() );
 
  180void QgsJsonEditWidget::copyKeyActionTriggered()
 
  182  if ( !mTreeWidget->currentItem() )
 
  185  QApplication::clipboard()->setText( mTreeWidget->currentItem()->text( 
static_cast<int>( TreeWidgetColumn::Key ) ) );
 
  188void QgsJsonEditWidget::codeEditorJsonTextChanged()
 
  190  mJsonText = mCodeEditorJson->text();
 
  191  const QJsonDocument jsonDocument = QJsonDocument::fromJson( mJsonText.toUtf8() );
 
  192  refreshTreeView( jsonDocument );
 
  195void QgsJsonEditWidget::codeEditorJsonIndicatorClicked( 
int line, 
int index, Qt::KeyboardModifiers state )
 
  197  if ( !state.testFlag( Qt::ControlModifier ) )
 
  200  const int position = mCodeEditorJson->positionFromLineIndex( line, index );
 
  201  const int clickableLinkListIndex = mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_INDICATORVALUEAT,
 
  202                                     SCINTILLA_UNDERLINE_INDICATOR_INDEX,
 
  204  if ( clickableLinkListIndex <= 0 )
 
  207  QDesktopServices::openUrl( mClickableLinkList.at( clickableLinkListIndex - 1 ) );
 
  210void QgsJsonEditWidget::codeEditorJsonDwellStart( 
int position, 
int x, 
int y )
 
  215  const int clickableLinkListIndex = mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_INDICATORVALUEAT,
 
  216                                     SCINTILLA_UNDERLINE_INDICATOR_INDEX,
 
  218  if ( clickableLinkListIndex <= 0 )
 
  221  QToolTip::showText( QCursor::pos(),
 
  222                      tr( 
"%1\nCTRL + click to follow link" ).arg( mClickableLinkList.at( clickableLinkListIndex - 1 ) ) );
 
  225void QgsJsonEditWidget::codeEditorJsonDwellEnd( 
int position, 
int x, 
int y )
 
  230  QToolTip::hideText();
 
  233void QgsJsonEditWidget::refreshTreeView( 
const QJsonDocument &jsonDocument )
 
  235  mTreeWidget->clear();
 
  237  if ( jsonDocument.isNull() )
 
  240    mTextToolButton->setDisabled( 
true );
 
  241    mTreeToolButton->setDisabled( 
true );
 
  242    mTreeToolButton->setToolTip( tr( 
"Invalid JSON, tree view not available" ) );
 
  247    mTextToolButton->setEnabled( 
true );
 
  248    mTreeToolButton->setEnabled( 
true );
 
  249    mTreeToolButton->setToolTip( tr( 
"Tree view" ) );
 
  252  if ( jsonDocument.isObject() )
 
  254    const QStringList keys = jsonDocument.object().keys();
 
  255    for ( 
const QString &key : keys )
 
  257      const QJsonValue jsonValue = jsonDocument.object().value( key );
 
  258      QTreeWidgetItem *treeWidgetItem = 
new QTreeWidgetItem( mTreeWidget, QStringList() << key );
 
  259      refreshTreeViewItem( treeWidgetItem, jsonValue );
 
  260      mTreeWidget->addTopLevelItem( treeWidgetItem );
 
  261      mTreeWidget->expandItem( treeWidgetItem );
 
  264  else if ( jsonDocument.isArray() )
 
  266    for ( 
int index = 0; index < jsonDocument.array().size(); index++ )
 
  268      QTreeWidgetItem *treeWidgetItem = 
new QTreeWidgetItem( mTreeWidget, QStringList() << QString::number( index ) );
 
  269      refreshTreeViewItem( treeWidgetItem, jsonDocument.array().at( index ) );
 
  270      mTreeWidget->addTopLevelItem( treeWidgetItem );
 
  271      mTreeWidget->expandItem( treeWidgetItem );
 
  275  mTreeWidget->resizeColumnToContents( 
static_cast<int>( TreeWidgetColumn::Key ) );
 
  278void QgsJsonEditWidget::refreshTreeViewItem( QTreeWidgetItem *treeWidgetItem, 
const QJsonValue &jsonValue )
 
  280  treeWidgetItem->setData( 
static_cast<int>( TreeWidgetColumn::Value ), Qt::UserRole, jsonValue.toVariant() );
 
  282  switch ( jsonValue.type() )
 
  284    case QJsonValue::Null:
 
  285      refreshTreeViewItemValue( treeWidgetItem,
 
  286                                QStringLiteral( 
"null" ),
 
  289    case QJsonValue::Bool:
 
  290      refreshTreeViewItemValue( treeWidgetItem,
 
  291                                jsonValue.toBool() ? QStringLiteral( 
"true" ) : QStringLiteral( 
"false" ),
 
  294    case QJsonValue::Double:
 
  295      refreshTreeViewItemValue( treeWidgetItem,
 
  296                                QString::number( jsonValue.toDouble() ),
 
  299    case QJsonValue::String:
 
  301      const QString jsonValueString = jsonValue.toString();
 
  302      if ( QUrl( jsonValueString ).scheme().isEmpty() )
 
  304        refreshTreeViewItemValue( treeWidgetItem,
 
  310        QLabel *label = 
new QLabel( QString( 
"<a href='%1'>%1</a>" ).arg( jsonValueString ) );
 
  311        label->setOpenExternalLinks( 
true );
 
  312        mTreeWidget->setItemWidget( treeWidgetItem, 
static_cast<int>( TreeWidgetColumn::Value ), label );
 
  314        mClickableLinkList.append( jsonValueString );
 
  315        mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_SETINDICATORVALUE, 
static_cast< int >( mClickableLinkList.size() ) );
 
  316        mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_INDICATORFILLRANGE,
 
  317                                        mCodeEditorJson->text().indexOf( jsonValueString ),
 
  318                                        jsonValueString.size() );
 
  322    case QJsonValue::Array:
 
  324      const QJsonArray jsonArray = jsonValue.toArray();
 
  325      for ( 
int index = 0; index < jsonArray.size(); index++ )
 
  327        QTreeWidgetItem *treeWidgetItemChild = 
new QTreeWidgetItem( treeWidgetItem, QStringList() << QString::number( index ) );
 
  328        refreshTreeViewItem( treeWidgetItemChild, jsonArray.at( index ) );
 
  329        treeWidgetItem->addChild( treeWidgetItemChild );
 
  330        treeWidgetItem->setExpanded( 
true );
 
  334    case QJsonValue::Object:
 
  336      const QJsonObject jsonObject = jsonValue.toObject();
 
  337      const QStringList keys = jsonObject.keys();
 
  338      for ( 
const QString &key : keys )
 
  340        QTreeWidgetItem *treeWidgetItemChild = 
new QTreeWidgetItem( treeWidgetItem, QStringList() << key );
 
  341        refreshTreeViewItem( treeWidgetItemChild, jsonObject.value( key ) );
 
  342        treeWidgetItem->addChild( treeWidgetItemChild );
 
  343        treeWidgetItem->setExpanded( 
true );
 
  347    case QJsonValue::Undefined:
 
  348      refreshTreeViewItemValue( treeWidgetItem,
 
  349                                QStringLiteral( 
"Undefined value" ),
 
  355void QgsJsonEditWidget::refreshTreeViewItemValue( QTreeWidgetItem *treeWidgetItem, 
const QString &jsonValueString, 
const QColor &textColor )
 
  357  QLabel *label = 
new QLabel( jsonValueString );
 
  358  if ( textColor.isValid() )
 
  359    label->setStyleSheet( QStringLiteral( 
"color: %1;" ).arg( textColor.name() ) );
 
  360  mTreeWidget->setItemWidget( treeWidgetItem, 
static_cast<int>( TreeWidgetColumn::Value ), label );
 
@ DoubleQuote
Double quote color.
 
static QFont getMonospaceFont()
Returns the monospaced font to use for code editors.
 
static QColor color(QgsCodeEditorColorScheme::ColorRole role)
Returns the color to use in the editor for the specified role.