20#include <QDesktopServices>
27#include "moc_qgsjsoneditwidget.cpp"
31 , mCopyValueAction( new QAction( tr(
"Copy Value" ), this ) )
32 , mCopyKeyAction( new QAction( tr(
"Copy Key" ), this ) )
38 mCodeEditorJson->setReadOnly(
true );
39 mCodeEditorJson->setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
40 mCodeEditorJson->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
41 mCodeEditorJson->indicatorDefine( QsciScintilla::PlainIndicator, SCINTILLA_UNDERLINE_INDICATOR_INDEX );
42 mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_SETINDICATORCURRENT, SCINTILLA_UNDERLINE_INDICATOR_INDEX );
43 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 );
65 return mCodeEditorJson;
71 mClickableLinkList.clear();
73 const QJsonDocument jsonDocument = QJsonDocument::fromJson( mJsonText.toUtf8() );
75 mCodeEditorJson->blockSignals(
true );
76 if ( jsonDocument.isNull() )
78 mCodeEditorJson->setText( mJsonText );
82 switch ( mFormatJsonMode )
85 mCodeEditorJson->setText( jsonDocument.toJson( QJsonDocument::Indented ) );
88 mCodeEditorJson->setText( jsonDocument.toJson( QJsonDocument::Compact ) );
91 mCodeEditorJson->setText( mJsonText );
95 mCodeEditorJson->blockSignals(
false );
97 refreshTreeView( jsonDocument );
111 mStackedWidget->setCurrentWidget( mStackedWidgetPageText );
112 mTextToolButton->setChecked(
true );
113 mTreeToolButton->setChecked(
false );
118 mStackedWidget->setCurrentWidget( mStackedWidgetPageTree );
119 mTreeToolButton->setChecked(
true );
120 mTextToolButton->setChecked(
false );
128 mFormatJsonMode = formatJson;
133 mControlsWidget->setVisible( visible );
136void QgsJsonEditWidget::textToolButtonClicked(
bool checked )
144void QgsJsonEditWidget::treeToolButtonClicked(
bool checked )
152void QgsJsonEditWidget::copyValueActionTriggered()
154 if ( !mTreeWidget->currentItem() )
157 const QJsonValue jsonValue = QJsonValue::fromVariant( mTreeWidget->currentItem()->data(
static_cast<int>( TreeWidgetColumn::Value ), Qt::UserRole ) );
159 switch ( jsonValue.type() )
161 case QJsonValue::Null:
162 case QJsonValue::Bool:
163 case QJsonValue::Double:
164 case QJsonValue::Undefined:
165 QApplication::clipboard()->setText( mTreeWidget->currentItem()->text(
static_cast<int>( TreeWidgetColumn::Value ) ) );
167 case QJsonValue::String:
168 QApplication::clipboard()->setText( jsonValue.toString() );
170 case QJsonValue::Array:
172 const QJsonDocument jsonDocument( jsonValue.toArray() );
173 QApplication::clipboard()->setText( jsonDocument.toJson() );
176 case QJsonValue::Object:
178 const QJsonDocument jsonDocument( jsonValue.toObject() );
179 QApplication::clipboard()->setText( jsonDocument.toJson() );
185void QgsJsonEditWidget::copyKeyActionTriggered()
187 if ( !mTreeWidget->currentItem() )
190 QApplication::clipboard()->setText( mTreeWidget->currentItem()->text(
static_cast<int>( TreeWidgetColumn::Key ) ) );
193void QgsJsonEditWidget::codeEditorJsonTextChanged()
195 mJsonText = mCodeEditorJson->text();
196 const QJsonDocument jsonDocument = QJsonDocument::fromJson( mJsonText.toUtf8() );
197 refreshTreeView( jsonDocument );
200void QgsJsonEditWidget::codeEditorJsonIndicatorClicked(
int line,
int index, Qt::KeyboardModifiers state )
202 if ( !state.testFlag( Qt::ControlModifier ) )
205 const int position = mCodeEditorJson->positionFromLineIndex( line, index );
206 const int clickableLinkListIndex = mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_INDICATORVALUEAT, SCINTILLA_UNDERLINE_INDICATOR_INDEX, position );
207 if ( clickableLinkListIndex <= 0 )
210 QDesktopServices::openUrl( mClickableLinkList.at( clickableLinkListIndex - 1 ) );
213void QgsJsonEditWidget::codeEditorJsonDwellStart(
int position,
int x,
int y )
218 const int clickableLinkListIndex = mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_INDICATORVALUEAT, SCINTILLA_UNDERLINE_INDICATOR_INDEX, position );
219 if ( clickableLinkListIndex <= 0 )
222 QToolTip::showText( QCursor::pos(), 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 treeWidgetItem->setFont( 0, monospaceFont() );
260 refreshTreeViewItem( treeWidgetItem, jsonValue );
261 mTreeWidget->addTopLevelItem( treeWidgetItem );
262 mTreeWidget->expandItem( treeWidgetItem );
265 else if ( jsonDocument.isArray() )
267 const QJsonArray array = jsonDocument.array();
268 const auto arraySize = array.size();
272 constexpr decltype( arraySize ) MAX_ELTS = 200;
275 if ( arraySize > MAX_ELTS )
276 mEnableUrlHighlighting =
false;
277 for (
auto index =
decltype( arraySize ) { 0 }; index < arraySize; index++ )
279 QTreeWidgetItem *treeWidgetItem =
new QTreeWidgetItem( mTreeWidget, QStringList() << QString::number( index ) );
280 treeWidgetItem->setFont( 0, monospaceFont() );
281 if ( arraySize <= MAX_ELTS || ( index < MAX_ELTS / 2 || index + MAX_ELTS / 2 > arraySize ) )
283 refreshTreeViewItem( treeWidgetItem, array.at( index ) );
284 mTreeWidget->addTopLevelItem( treeWidgetItem );
285 mTreeWidget->expandItem( treeWidgetItem );
287 else if ( index == MAX_ELTS / 2 )
289 index = arraySize - MAX_ELTS / 2;
290 refreshTreeViewItem( treeWidgetItem, tr(
"... truncated ..." ) );
291 mTreeWidget->addTopLevelItem( treeWidgetItem );
292 mTreeWidget->expandItem( treeWidgetItem );
297 mTreeWidget->resizeColumnToContents(
static_cast<int>( TreeWidgetColumn::Key ) );
300void QgsJsonEditWidget::refreshTreeViewItem( QTreeWidgetItem *treeWidgetItem,
const QJsonValue &jsonValue )
302 treeWidgetItem->setData(
static_cast<int>( TreeWidgetColumn::Value ), Qt::UserRole, jsonValue.toVariant() );
304 switch ( jsonValue.type() )
306 case QJsonValue::Null:
309 case QJsonValue::Bool:
312 case QJsonValue::Double:
315 case QJsonValue::String:
317 const QString jsonValueString = jsonValue.toString();
318 if ( !mEnableUrlHighlighting || QUrl( jsonValueString ).scheme().isEmpty() )
324 QLabel *label =
new QLabel( QString(
"<a href='%1'>%1</a>" ).arg( jsonValueString ) );
325 label->setOpenExternalLinks(
true );
326 label->setFont( monospaceFont() );
327 mTreeWidget->setItemWidget( treeWidgetItem,
static_cast<int>( TreeWidgetColumn::Value ), label );
329 mClickableLinkList.append( jsonValueString );
330 mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_SETINDICATORVALUE,
static_cast<int>( mClickableLinkList.size() ) );
331 mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_INDICATORFILLRANGE, mCodeEditorJson->text().indexOf( jsonValueString ), jsonValueString.size() );
335 case QJsonValue::Array:
337 const QJsonArray jsonArray = jsonValue.toArray();
338 const auto arraySize = jsonArray.size();
342 constexpr decltype( arraySize ) MAX_ELTS = 200;
345 if ( arraySize > MAX_ELTS )
346 mEnableUrlHighlighting =
false;
347 for (
auto index =
decltype( arraySize ) { 0 }; index < arraySize; index++ )
349 QTreeWidgetItem *treeWidgetItemChild =
new QTreeWidgetItem( treeWidgetItem, QStringList() << QString::number( index ) );
350 treeWidgetItemChild->setFont( 0, monospaceFont() );
351 if ( arraySize <= MAX_ELTS || ( index < MAX_ELTS / 2 || index + MAX_ELTS / 2 > arraySize ) )
353 refreshTreeViewItem( treeWidgetItemChild, jsonArray.at( index ) );
354 treeWidgetItem->addChild( treeWidgetItemChild );
355 treeWidgetItem->setExpanded(
true );
357 else if ( index == MAX_ELTS / 2 )
359 index = arraySize - MAX_ELTS / 2;
360 refreshTreeViewItem( treeWidgetItemChild, tr(
"... truncated ..." ) );
361 treeWidgetItem->addChild( treeWidgetItemChild );
362 treeWidgetItem->setExpanded(
true );
367 case QJsonValue::Object:
369 const QJsonObject jsonObject = jsonValue.toObject();
370 const QStringList keys = jsonObject.keys();
371 for (
const QString &key : keys )
373 QTreeWidgetItem *treeWidgetItemChild =
new QTreeWidgetItem( treeWidgetItem, QStringList() << key );
374 treeWidgetItemChild->setFont( 0, monospaceFont() );
375 refreshTreeViewItem( treeWidgetItemChild, jsonObject.value( key ) );
376 treeWidgetItem->addChild( treeWidgetItemChild );
377 treeWidgetItem->setExpanded(
true );
381 case QJsonValue::Undefined:
387void QgsJsonEditWidget::refreshTreeViewItemValue( QTreeWidgetItem *treeWidgetItem,
const QString &jsonValueString,
const QColor &textColor )
389 QLabel *label =
new QLabel( jsonValueString );
390 label->setFont( monospaceFont() );
392 if ( textColor.isValid() )
393 label->setStyleSheet( QStringLiteral(
"color: %1;" ).arg( textColor.name() ) );
394 mTreeWidget->setItemWidget( treeWidgetItem,
static_cast<int>( TreeWidgetColumn::Value ), label );
397QFont QgsJsonEditWidget::monospaceFont()
const
401 f.setPointSize( font().pointSize() );
@ DoubleQuote
Double quote color.
A JSON editor based on QScintilla2.
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.