47 , mMessageBar( messageBar )
51 mEditor->installEventFilter(
this );
52 installEventFilter(
this );
54 QVBoxLayout *vl =
new QVBoxLayout();
55 vl->setContentsMargins( 0, 0, 0, 0 );
57 vl->addWidget(
editor, 1 );
61 QGridLayout *layout =
new QGridLayout( mEditor );
62 layout->setContentsMargins( 0, 0, 0, 0 );
63 layout->addItem(
new QSpacerItem( 20, 40, QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Expanding ), 1, 0, 1, 1 );
66 QSizePolicy sizePolicy = QSizePolicy( QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Fixed );
67 mMessageBar->setSizePolicy( sizePolicy );
68 layout->addWidget( mMessageBar, 0, 0, 1, 1 );
71 mFindWidget =
new QWidget();
72 QGridLayout *layoutFind =
new QGridLayout();
73 layoutFind->setContentsMargins( 0, 2, 0, 0 );
74 layoutFind->setSpacing( 1 );
76 if ( !mEditor->isReadOnly() )
78 mShowReplaceBarButton =
new QToolButton();
79 mShowReplaceBarButton->setToolTip( tr(
"Replace" ) );
80 mShowReplaceBarButton->setCheckable(
true );
81 mShowReplaceBarButton->setAutoRaise(
true );
83 layoutFind->addWidget( mShowReplaceBarButton, 0, 0 );
90 mLineEditFind->setPlaceholderText( tr(
"Enter text to find…" ) );
91 layoutFind->addWidget( mLineEditFind, 0, mShowReplaceBarButton ? 1 : 0 );
95 mLineEditReplace->setPlaceholderText( tr(
"Replace…" ) );
96 layoutFind->addWidget( mLineEditReplace, 1, mShowReplaceBarButton ? 1 : 0 );
98 QHBoxLayout *findButtonLayout =
new QHBoxLayout();
99 findButtonLayout->setContentsMargins( 0, 0, 0, 0 );
100 findButtonLayout->setSpacing( 1 );
101 mCaseSensitiveButton =
new QToolButton();
102 mCaseSensitiveButton->setToolTip( tr(
"Case Sensitive" ) );
103 mCaseSensitiveButton->setCheckable(
true );
104 mCaseSensitiveButton->setAutoRaise(
true );
106 findButtonLayout->addWidget( mCaseSensitiveButton );
108 mWholeWordButton =
new QToolButton( );
109 mWholeWordButton->setToolTip( tr(
"Whole Word" ) );
110 mWholeWordButton->setCheckable(
true );
111 mWholeWordButton->setAutoRaise(
true );
113 findButtonLayout->addWidget( mWholeWordButton );
115 mRegexButton =
new QToolButton( );
116 mRegexButton->setToolTip( tr(
"Use Regular Expressions" ) );
117 mRegexButton->setCheckable(
true );
118 mRegexButton->setAutoRaise(
true );
120 findButtonLayout->addWidget( mRegexButton );
122 mWrapAroundButton =
new QToolButton();
123 mWrapAroundButton->setToolTip( tr(
"Wrap Around" ) );
124 mWrapAroundButton->setCheckable(
true );
125 mWrapAroundButton->setAutoRaise(
true );
127 findButtonLayout->addWidget( mWrapAroundButton );
129 mFindPrevButton =
new QToolButton();
130 mFindPrevButton->setEnabled(
false );
131 mFindPrevButton->setToolTip( tr(
"Find Previous" ) );
133 mFindPrevButton->setAutoRaise(
true );
134 findButtonLayout->addWidget( mFindPrevButton );
136 mFindNextButton =
new QToolButton();
137 mFindNextButton->setEnabled(
false );
138 mFindNextButton->setToolTip( tr(
"Find Next" ) );
140 mFindNextButton->setAutoRaise(
true );
141 findButtonLayout->addWidget( mFindNextButton );
143 connect( mLineEditFind, &QLineEdit::returnPressed,
this, &QgsCodeEditorWidget::findNext );
144 connect( mLineEditFind, &QLineEdit::textChanged,
this, &QgsCodeEditorWidget::textSearchChanged );
145 connect( mFindNextButton, &QToolButton::clicked,
this, &QgsCodeEditorWidget::findNext );
146 connect( mFindPrevButton, &QToolButton::clicked,
this, &QgsCodeEditorWidget::findPrevious );
147 connect( mCaseSensitiveButton, &QToolButton::toggled,
this, &QgsCodeEditorWidget::updateSearch );
148 connect( mWholeWordButton, &QToolButton::toggled,
this, &QgsCodeEditorWidget::updateSearch );
149 connect( mRegexButton, &QToolButton::toggled,
this, &QgsCodeEditorWidget::updateSearch );
150 connect( mWrapAroundButton, &QCheckBox::toggled,
this, &QgsCodeEditorWidget::updateSearch );
152 QShortcut *findShortcut =
new QShortcut( QKeySequence::StandardKey::Find, mEditor );
153 findShortcut->setContext( Qt::ShortcutContext::WidgetWithChildrenShortcut );
156 QShortcut *findNextShortcut =
new QShortcut( QKeySequence::StandardKey::FindNext,
this );
157 findNextShortcut->setContext( Qt::ShortcutContext::WidgetWithChildrenShortcut );
158 connect( findNextShortcut, &QShortcut::activated,
this, &QgsCodeEditorWidget::findNext );
160 QShortcut *findPreviousShortcut =
new QShortcut( QKeySequence::StandardKey::FindPrevious,
this );
161 findPreviousShortcut->setContext( Qt::ShortcutContext::WidgetWithChildrenShortcut );
162 connect( findPreviousShortcut, &QShortcut::activated,
this, &QgsCodeEditorWidget::findPrevious );
164 if ( !mEditor->isReadOnly() )
166 QShortcut *replaceShortcut =
new QShortcut( QKeySequence::StandardKey::Replace,
this );
167 replaceShortcut->setContext( Qt::ShortcutContext::WidgetWithChildrenShortcut );
168 connect( replaceShortcut, &QShortcut::activated,
this, [ = ]
171 const bool show = mLineEditReplace->isHidden();
181 QShortcut *closeFindShortcut =
new QShortcut( Qt::Key::Key_Escape,
this );
182 closeFindShortcut->setContext( Qt::ShortcutContext::WidgetWithChildrenShortcut );
183 connect( closeFindShortcut, &QShortcut::activated,
this, [
this]
189 layoutFind->addLayout( findButtonLayout, 0, mShowReplaceBarButton ? 2 : 1 );
191 QHBoxLayout *replaceButtonLayout =
new QHBoxLayout();
192 replaceButtonLayout->setContentsMargins( 0, 0, 0, 0 );
193 replaceButtonLayout->setSpacing( 1 );
195 mReplaceButton =
new QToolButton();
196 mReplaceButton->setText( tr(
"Replace" ) );
197 mReplaceButton->setEnabled(
false );
198 connect( mReplaceButton, &QToolButton::clicked,
this, &QgsCodeEditorWidget::replace );
199 replaceButtonLayout->addWidget( mReplaceButton );
201 mReplaceAllButton =
new QToolButton();
202 mReplaceAllButton->setText( tr(
"Replace All" ) );
203 mReplaceAllButton->setEnabled(
false );
204 connect( mReplaceAllButton, &QToolButton::clicked,
this, &QgsCodeEditorWidget::replaceAll );
205 replaceButtonLayout->addWidget( mReplaceAllButton );
207 layoutFind->addLayout( replaceButtonLayout, 1, mShowReplaceBarButton ? 2 : 1 );
209 QToolButton *closeFindButton =
new QToolButton(
this );
210 closeFindButton->setToolTip( tr(
"Close" ) );
212 closeFindButton->setStyleSheet(
213 "QToolButton { border:none; background-color: rgba(0, 0, 0, 0); }"
214 "QToolButton::menu-button { border:none; background-color: rgba(0, 0, 0, 0); }" );
215 closeFindButton->setCursor( Qt::PointingHandCursor );
219 closeFindButton->setIconSize( QSize( iconSize, iconSize ) );
220 closeFindButton->setFixedSize( QSize( iconSize, iconSize ) );
221 connect( closeFindButton, &QAbstractButton::clicked,
this, [
this]
226 layoutFind->addWidget( closeFindButton, 0, mShowReplaceBarButton ? 3 : 2 );
228 layoutFind->setColumnStretch( mShowReplaceBarButton ? 1 : 0, 1 );
230 mFindWidget->setLayout( layoutFind );
231 vl->addWidget( mFindWidget );
238 mHighlightController = std::make_unique< QgsScrollBarHighlightController >();
239 mHighlightController->setScrollArea( mEditor );
536 const QString accessToken =
QgsSettings().
value(
"pythonConsole/accessTokenGithub", QString() ).toString();
537 if ( accessToken.isEmpty() )
540 mMessageBar->
pushWarning( QString(), tr(
"GitHub personal access token must be generated (see IDE Options)" ) );
544 QString defaultFileName;
548 defaultFileName = QStringLiteral(
"pyqgis_snippet.py" );
552 defaultFileName = QStringLiteral(
"qgis_snippet.css" );
556 defaultFileName = QStringLiteral(
"qgis_snippet" );
560 defaultFileName = QStringLiteral(
"qgis_snippet.html" );
564 defaultFileName = QStringLiteral(
"qgis_snippet.js" );
568 defaultFileName = QStringLiteral(
"qgis_snippet.json" );
572 defaultFileName = QStringLiteral(
"qgis_snippet.r" );
576 defaultFileName = QStringLiteral(
"qgis_snippet.sql" );
580 defaultFileName = QStringLiteral(
"qgis_snippet.bat" );
584 defaultFileName = QStringLiteral(
"qgis_snippet.sh" );
588 defaultFileName = QStringLiteral(
"qgis_snippet.txt" );
591 const QString filename = mFilePath.isEmpty() ? defaultFileName : QFileInfo( mFilePath ).fileName();
593 const QString contents = mEditor->hasSelectedText() ? mEditor->selectedText() : mEditor->text();
594 const QVariantMap data
596 { QStringLiteral(
"description" ),
"Gist created by PyQGIS Console"},
597 { QStringLiteral(
"public" ), isPublic },
598 { QStringLiteral(
"files" ), QVariantMap{ {filename, QVariantMap{{ QStringLiteral(
"content" ), contents }} } } }
601 QNetworkRequest request;
602 request.setUrl( QUrl( QStringLiteral(
"https://api.github.com/gists" ) ) );
603 request.setRawHeader(
"Authorization", QStringLiteral(
"token %1" ).arg( accessToken ).toLocal8Bit() );
604 request.setHeader( QNetworkRequest::ContentTypeHeader, QLatin1String(
"application/json" ) );
605 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy );
609 connect( reply, &QNetworkReply::finished,
this, [
this, reply]
611 if ( reply->error() == QNetworkReply::NoError )
613 const QVariantMap replyJson = QgsJsonUtils::parseJson( reply->readAll() ).toMap();
614 const QString link = replyJson.value( QStringLiteral(
"html_url" ) ).toString();
615 QDesktopServices::openUrl( QUrl( link ) );
620 mMessageBar->pushCritical( QString(), tr(
"Connection error: %1" ).arg( reply->errorString() ) );
622 reply->deleteLater();