20 #include <QDesktopServices> 
   23 #include <QPushButton> 
   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 );
 
  131 void QgsJsonEditWidget::textToolButtonClicked( 
bool checked )
 
  139 void QgsJsonEditWidget::treeToolButtonClicked( 
bool checked )
 
  147 void 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() );
 
  180 void QgsJsonEditWidget::copyKeyActionTriggered()
 
  182   if ( !mTreeWidget->currentItem() )
 
  185   QApplication::clipboard()->setText( mTreeWidget->currentItem()->text( 
static_cast<int>( TreeWidgetColumn::Key ) ) );
 
  188 void QgsJsonEditWidget::codeEditorJsonTextChanged()
 
  190   mJsonText = mCodeEditorJson->text();
 
  191   const QJsonDocument jsonDocument = QJsonDocument::fromJson( mJsonText.toUtf8() );
 
  192   refreshTreeView( jsonDocument );
 
  195 void QgsJsonEditWidget::codeEditorJsonIndicatorClicked( 
int line, 
int index, Qt::KeyboardModifiers state )
 
  197   if ( !state.testFlag( Qt::ControlModifier ) )
 
  200   int position = mCodeEditorJson->positionFromLineIndex( line, index );
 
  201   int clickableLinkListIndex = mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_INDICATORVALUEAT,
 
  202                                SCINTILLA_UNDERLINE_INDICATOR_INDEX,
 
  204   if ( clickableLinkListIndex <= 0 )
 
  207   QDesktopServices::openUrl( mClickableLinkList.at( clickableLinkListIndex - 1 ) );
 
  210 void QgsJsonEditWidget::codeEditorJsonDwellStart( 
int position, 
int x, 
int y )
 
  215   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 ) ) );
 
  225 void QgsJsonEditWidget::codeEditorJsonDwellEnd( 
int position, 
int x, 
int y )
 
  230   QToolTip::hideText();
 
  233 void 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 ) );
 
  278 void 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, 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" ),
 
  355 void 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.