17#include "moc_qgsjsoneditwidget.cpp"
21#include <QDesktopServices>
30 , mCopyValueAction( new QAction( tr(
"Copy Value" ), this ) )
31 , mCopyKeyAction( new QAction( tr(
"Copy Key" ), this ) )
37 mCodeEditorJson->setReadOnly(
true );
38 mCodeEditorJson->setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
39 mCodeEditorJson->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
40 mCodeEditorJson->indicatorDefine( QsciScintilla::PlainIndicator, SCINTILLA_UNDERLINE_INDICATOR_INDEX );
41 mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_SETINDICATORCURRENT, SCINTILLA_UNDERLINE_INDICATOR_INDEX );
42 mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_SETMOUSEDWELLTIME, 400 );
44 mTreeWidget->setContextMenuPolicy( Qt::ActionsContextMenu );
45 mTreeWidget->addAction( mCopyValueAction );
46 mTreeWidget->addAction( mCopyKeyAction );
48 connect( mTextToolButton, &QToolButton::clicked,
this, &QgsJsonEditWidget::textToolButtonClicked );
49 connect( mTreeToolButton, &QToolButton::clicked,
this, &QgsJsonEditWidget::treeToolButtonClicked );
51 connect( mCopyValueAction, &QAction::triggered,
this, &QgsJsonEditWidget::copyValueActionTriggered );
52 connect( mCopyKeyAction, &QAction::triggered,
this, &QgsJsonEditWidget::copyKeyActionTriggered );
54 connect( mCodeEditorJson, &QgsCodeEditorJson::textChanged,
this, &QgsJsonEditWidget::codeEditorJsonTextChanged );
57 connect( mCodeEditorJson, &QsciScintilla::indicatorClicked,
this, &QgsJsonEditWidget::codeEditorJsonIndicatorClicked );
58 connect( mCodeEditorJson, &QsciScintillaBase::SCN_DWELLSTART,
this, &QgsJsonEditWidget::codeEditorJsonDwellStart );
59 connect( mCodeEditorJson, &QsciScintillaBase::SCN_DWELLEND,
this, &QgsJsonEditWidget::codeEditorJsonDwellEnd );
64 return mCodeEditorJson;
70 mClickableLinkList.clear();
72 const QJsonDocument jsonDocument = QJsonDocument::fromJson( mJsonText.toUtf8() );
74 mCodeEditorJson->blockSignals(
true );
75 if ( jsonDocument.isNull() )
77 mCodeEditorJson->setText( mJsonText );
81 switch ( mFormatJsonMode )
84 mCodeEditorJson->setText( jsonDocument.toJson( QJsonDocument::Indented ) );
87 mCodeEditorJson->setText( jsonDocument.toJson( QJsonDocument::Compact ) );
90 mCodeEditorJson->setText( mJsonText );
94 mCodeEditorJson->blockSignals(
false );
96 refreshTreeView( jsonDocument );
110 mStackedWidget->setCurrentWidget( mStackedWidgetPageText );
111 mTextToolButton->setChecked(
true );
112 mTreeToolButton->setChecked(
false );
117 mStackedWidget->setCurrentWidget( mStackedWidgetPageTree );
118 mTreeToolButton->setChecked(
true );
119 mTextToolButton->setChecked(
false );
127 mFormatJsonMode = formatJson;
132 mControlsWidget->setVisible( visible );
135void QgsJsonEditWidget::textToolButtonClicked(
bool checked )
143void QgsJsonEditWidget::treeToolButtonClicked(
bool checked )
151void QgsJsonEditWidget::copyValueActionTriggered()
153 if ( !mTreeWidget->currentItem() )
156 const QJsonValue jsonValue = QJsonValue::fromVariant( mTreeWidget->currentItem()->data(
static_cast<int>( TreeWidgetColumn::Value ), Qt::UserRole ) );
158 switch ( jsonValue.type() )
160 case QJsonValue::Null:
161 case QJsonValue::Bool:
162 case QJsonValue::Double:
163 case QJsonValue::Undefined:
164 QApplication::clipboard()->setText( mTreeWidget->currentItem()->text(
static_cast<int>( TreeWidgetColumn::Value ) ) );
166 case QJsonValue::String:
167 QApplication::clipboard()->setText( jsonValue.toString() );
169 case QJsonValue::Array:
171 const QJsonDocument jsonDocument( jsonValue.toArray() );
172 QApplication::clipboard()->setText( jsonDocument.toJson() );
175 case QJsonValue::Object:
177 const QJsonDocument jsonDocument( jsonValue.toObject() );
178 QApplication::clipboard()->setText( jsonDocument.toJson() );
184void QgsJsonEditWidget::copyKeyActionTriggered()
186 if ( !mTreeWidget->currentItem() )
189 QApplication::clipboard()->setText( mTreeWidget->currentItem()->text(
static_cast<int>( TreeWidgetColumn::Key ) ) );
192void QgsJsonEditWidget::codeEditorJsonTextChanged()
194 mJsonText = mCodeEditorJson->text();
195 const QJsonDocument jsonDocument = QJsonDocument::fromJson( mJsonText.toUtf8() );
196 refreshTreeView( jsonDocument );
199void QgsJsonEditWidget::codeEditorJsonIndicatorClicked(
int line,
int index, Qt::KeyboardModifiers state )
201 if ( !state.testFlag( Qt::ControlModifier ) )
204 const int position = mCodeEditorJson->positionFromLineIndex( line, index );
205 const int clickableLinkListIndex = mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_INDICATORVALUEAT, SCINTILLA_UNDERLINE_INDICATOR_INDEX, position );
206 if ( clickableLinkListIndex <= 0 )
209 QDesktopServices::openUrl( mClickableLinkList.at( clickableLinkListIndex - 1 ) );
212void QgsJsonEditWidget::codeEditorJsonDwellStart(
int position,
int x,
int y )
217 const int clickableLinkListIndex = mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_INDICATORVALUEAT, SCINTILLA_UNDERLINE_INDICATOR_INDEX, position );
218 if ( clickableLinkListIndex <= 0 )
221 QToolTip::showText( QCursor::pos(), tr(
"%1\nCTRL + click to follow link" ).arg( mClickableLinkList.at( clickableLinkListIndex - 1 ) ) );
224void QgsJsonEditWidget::codeEditorJsonDwellEnd(
int position,
int x,
int y )
229 QToolTip::hideText();
232void QgsJsonEditWidget::refreshTreeView(
const QJsonDocument &jsonDocument )
234 mTreeWidget->clear();
236 if ( jsonDocument.isNull() )
239 mTextToolButton->setDisabled(
true );
240 mTreeToolButton->setDisabled(
true );
241 mTreeToolButton->setToolTip( tr(
"Invalid JSON, tree view not available" ) );
246 mTextToolButton->setEnabled(
true );
247 mTreeToolButton->setEnabled(
true );
248 mTreeToolButton->setToolTip( tr(
"Tree view" ) );
251 if ( jsonDocument.isObject() )
253 const QStringList keys = jsonDocument.object().keys();
254 for (
const QString &key : keys )
256 const QJsonValue jsonValue = jsonDocument.object().value( key );
257 QTreeWidgetItem *treeWidgetItem =
new QTreeWidgetItem( mTreeWidget, QStringList() << key );
258 treeWidgetItem->setFont( 0, monospaceFont() );
259 refreshTreeViewItem( treeWidgetItem, jsonValue );
260 mTreeWidget->addTopLevelItem( treeWidgetItem );
261 mTreeWidget->expandItem( treeWidgetItem );
264 else if ( jsonDocument.isArray() )
266 const QJsonArray array = jsonDocument.array();
267 const auto arraySize = array.size();
271 constexpr decltype( arraySize ) MAX_ELTS = 200;
274 if ( arraySize > MAX_ELTS )
275 mEnableUrlHighlighting =
false;
276 for (
auto index =
decltype( arraySize ) { 0 }; index < arraySize; index++ )
278 QTreeWidgetItem *treeWidgetItem =
new QTreeWidgetItem( mTreeWidget, QStringList() << QString::number( index ) );
279 treeWidgetItem->setFont( 0, monospaceFont() );
280 if ( arraySize <= MAX_ELTS || ( index < MAX_ELTS / 2 || index + MAX_ELTS / 2 > arraySize ) )
282 refreshTreeViewItem( treeWidgetItem, array.at( index ) );
283 mTreeWidget->addTopLevelItem( treeWidgetItem );
284 mTreeWidget->expandItem( treeWidgetItem );
286 else if ( index == MAX_ELTS / 2 )
288 index = arraySize - MAX_ELTS / 2;
289 refreshTreeViewItem( treeWidgetItem, tr(
"... truncated ..." ) );
290 mTreeWidget->addTopLevelItem( treeWidgetItem );
291 mTreeWidget->expandItem( treeWidgetItem );
296 mTreeWidget->resizeColumnToContents(
static_cast<int>( TreeWidgetColumn::Key ) );
299void QgsJsonEditWidget::refreshTreeViewItem( QTreeWidgetItem *treeWidgetItem,
const QJsonValue &jsonValue )
301 treeWidgetItem->setData(
static_cast<int>( TreeWidgetColumn::Value ), Qt::UserRole, jsonValue.toVariant() );
303 switch ( jsonValue.type() )
305 case QJsonValue::Null:
308 case QJsonValue::Bool:
309 refreshTreeViewItemValue( treeWidgetItem, jsonValue.toBool() ? QStringLiteral(
"true" ) : QStringLiteral(
"false" ),
QgsCodeEditor::color(
QgsCodeEditorColorScheme::ColorRole::Keyword ) );
311 case QJsonValue::Double:
314 case QJsonValue::String:
316 const QString jsonValueString = jsonValue.toString();
317 if ( !mEnableUrlHighlighting || QUrl( jsonValueString ).scheme().isEmpty() )
323 QLabel *label =
new QLabel( QString(
"<a href='%1'>%1</a>" ).arg( jsonValueString ) );
324 label->setOpenExternalLinks(
true );
325 label->setFont( monospaceFont() );
326 mTreeWidget->setItemWidget( treeWidgetItem,
static_cast<int>( TreeWidgetColumn::Value ), label );
328 mClickableLinkList.append( jsonValueString );
329 mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_SETINDICATORVALUE,
static_cast<int>( mClickableLinkList.size() ) );
330 mCodeEditorJson->SendScintilla( QsciScintillaBase::SCI_INDICATORFILLRANGE, mCodeEditorJson->text().indexOf( jsonValueString ), jsonValueString.size() );
334 case QJsonValue::Array:
336 const QJsonArray jsonArray = jsonValue.toArray();
337 const auto arraySize = jsonArray.size();
341 constexpr decltype( arraySize ) MAX_ELTS = 200;
344 if ( arraySize > MAX_ELTS )
345 mEnableUrlHighlighting =
false;
346 for (
auto index =
decltype( arraySize ) { 0 }; index < arraySize; index++ )
348 QTreeWidgetItem *treeWidgetItemChild =
new QTreeWidgetItem( treeWidgetItem, QStringList() << QString::number( index ) );
349 treeWidgetItemChild->setFont( 0, monospaceFont() );
350 if ( arraySize <= MAX_ELTS || ( index < MAX_ELTS / 2 || index + MAX_ELTS / 2 > arraySize ) )
352 refreshTreeViewItem( treeWidgetItemChild, jsonArray.at( index ) );
353 treeWidgetItem->addChild( treeWidgetItemChild );
354 treeWidgetItem->setExpanded(
true );
356 else if ( index == MAX_ELTS / 2 )
358 index = arraySize - MAX_ELTS / 2;
359 refreshTreeViewItem( treeWidgetItemChild, tr(
"... truncated ..." ) );
360 treeWidgetItem->addChild( treeWidgetItemChild );
361 treeWidgetItem->setExpanded(
true );
366 case QJsonValue::Object:
368 const QJsonObject jsonObject = jsonValue.toObject();
369 const QStringList keys = jsonObject.keys();
370 for (
const QString &key : keys )
372 QTreeWidgetItem *treeWidgetItemChild =
new QTreeWidgetItem( treeWidgetItem, QStringList() << key );
373 treeWidgetItemChild->setFont( 0, monospaceFont() );
374 refreshTreeViewItem( treeWidgetItemChild, jsonObject.value( key ) );
375 treeWidgetItem->addChild( treeWidgetItemChild );
376 treeWidgetItem->setExpanded(
true );
380 case QJsonValue::Undefined:
386void QgsJsonEditWidget::refreshTreeViewItemValue( QTreeWidgetItem *treeWidgetItem,
const QString &jsonValueString,
const QColor &textColor )
388 QLabel *label =
new QLabel( jsonValueString );
389 label->setFont( monospaceFont() );
391 if ( textColor.isValid() )
392 label->setStyleSheet( QStringLiteral(
"color: %1;" ).arg( textColor.name() ) );
393 mTreeWidget->setItemWidget( treeWidgetItem,
static_cast<int>( TreeWidgetColumn::Value ), label );
396QFont QgsJsonEditWidget::monospaceFont()
const
400 f.setPointSize( font().pointSize() );
Defines a color scheme for use in QgsCodeEditor widgets.
@ DoubleQuote
Double quote color.
A JSON editor based on QScintilla2.
A text 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.