56 mEditor->installEventFilter(
this );
57 installEventFilter(
this );
59 QVBoxLayout *vl =
new QVBoxLayout();
60 vl->setContentsMargins( 0, 0, 0, 0 );
62 vl->addWidget(
editor, 1 );
66 QGridLayout *layout =
new QGridLayout( mEditor );
67 layout->setContentsMargins( 0, 0, 0, 0 );
68 layout->addItem(
new QSpacerItem( 20, 40, QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Expanding ), 1, 0, 1, 1 );
71 QSizePolicy sizePolicy = QSizePolicy( QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Fixed );
72 mMessageBar->setSizePolicy( sizePolicy );
73 layout->addWidget( mMessageBar, 0, 0, 1, 1 );
76 mFindWidget =
new QWidget();
77 QGridLayout *layoutFind =
new QGridLayout();
78 layoutFind->setContentsMargins( 0, 2, 0, 0 );
79 layoutFind->setSpacing( 1 );
81 if ( !mEditor->isReadOnly() )
83 mShowReplaceBarButton =
new QToolButton();
84 mShowReplaceBarButton->setToolTip( tr(
"Replace" ) );
85 mShowReplaceBarButton->setCheckable(
true );
86 mShowReplaceBarButton->setAutoRaise(
true );
88 layoutFind->addWidget( mShowReplaceBarButton, 0, 0 );
94 mLineEditFind->setShowSearchIcon(
true );
95 mLineEditFind->setPlaceholderText( tr(
"Enter text to find…" ) );
96 layoutFind->addWidget( mLineEditFind, 0, mShowReplaceBarButton ? 1 : 0 );
99 mLineEditReplace->setShowSearchIcon(
true );
100 mLineEditReplace->setPlaceholderText( tr(
"Replace…" ) );
101 layoutFind->addWidget( mLineEditReplace, 1, mShowReplaceBarButton ? 1 : 0 );
103 QHBoxLayout *findButtonLayout =
new QHBoxLayout();
104 findButtonLayout->setContentsMargins( 0, 0, 0, 0 );
105 findButtonLayout->setSpacing( 1 );
106 mCaseSensitiveButton =
new QToolButton();
107 mCaseSensitiveButton->setToolTip( tr(
"Case Sensitive" ) );
108 mCaseSensitiveButton->setCheckable(
true );
109 mCaseSensitiveButton->setAutoRaise(
true );
111 findButtonLayout->addWidget( mCaseSensitiveButton );
113 mWholeWordButton =
new QToolButton();
114 mWholeWordButton->setToolTip( tr(
"Whole Word" ) );
115 mWholeWordButton->setCheckable(
true );
116 mWholeWordButton->setAutoRaise(
true );
118 findButtonLayout->addWidget( mWholeWordButton );
120 mRegexButton =
new QToolButton();
121 mRegexButton->setToolTip( tr(
"Use Regular Expressions" ) );
122 mRegexButton->setCheckable(
true );
123 mRegexButton->setAutoRaise(
true );
125 findButtonLayout->addWidget( mRegexButton );
127 mWrapAroundButton =
new QToolButton();
128 mWrapAroundButton->setToolTip( tr(
"Wrap Around" ) );
129 mWrapAroundButton->setCheckable(
true );
130 mWrapAroundButton->setAutoRaise(
true );
132 findButtonLayout->addWidget( mWrapAroundButton );
134 mFindPrevButton =
new QToolButton();
135 mFindPrevButton->setEnabled(
false );
136 mFindPrevButton->setToolTip( tr(
"Find Previous" ) );
138 mFindPrevButton->setAutoRaise(
true );
139 findButtonLayout->addWidget( mFindPrevButton );
141 mFindNextButton =
new QToolButton();
142 mFindNextButton->setEnabled(
false );
143 mFindNextButton->setToolTip( tr(
"Find Next" ) );
145 mFindNextButton->setAutoRaise(
true );
146 findButtonLayout->addWidget( mFindNextButton );
148 connect( mLineEditFind, &QLineEdit::returnPressed,
this, &QgsCodeEditorWidget::findNext );
149 connect( mLineEditFind, &QLineEdit::textChanged,
this, &QgsCodeEditorWidget::textSearchChanged );
150 connect( mFindNextButton, &QToolButton::clicked,
this, &QgsCodeEditorWidget::findNext );
151 connect( mFindPrevButton, &QToolButton::clicked,
this, &QgsCodeEditorWidget::findPrevious );
152 connect( mCaseSensitiveButton, &QToolButton::toggled,
this, &QgsCodeEditorWidget::updateSearch );
153 connect( mWholeWordButton, &QToolButton::toggled,
this, &QgsCodeEditorWidget::updateSearch );
154 connect( mRegexButton, &QToolButton::toggled,
this, &QgsCodeEditorWidget::updateSearch );
155 connect( mWrapAroundButton, &QCheckBox::toggled,
this, &QgsCodeEditorWidget::updateSearch );
157 QShortcut *findShortcut =
new QShortcut( QKeySequence::StandardKey::Find, mEditor );
158 findShortcut->setContext( Qt::ShortcutContext::WidgetWithChildrenShortcut );
161 QShortcut *findNextShortcut =
new QShortcut( QKeySequence::StandardKey::FindNext,
this );
162 findNextShortcut->setContext( Qt::ShortcutContext::WidgetWithChildrenShortcut );
163 connect( findNextShortcut, &QShortcut::activated,
this, &QgsCodeEditorWidget::findNext );
165 QShortcut *findPreviousShortcut =
new QShortcut( QKeySequence::StandardKey::FindPrevious,
this );
166 findPreviousShortcut->setContext( Qt::ShortcutContext::WidgetWithChildrenShortcut );
167 connect( findPreviousShortcut, &QShortcut::activated,
this, &QgsCodeEditorWidget::findPrevious );
169 if ( !mEditor->isReadOnly() )
171 QShortcut *replaceShortcut =
new QShortcut( QKeySequence::StandardKey::Replace,
this );
172 replaceShortcut->setContext( Qt::ShortcutContext::WidgetWithChildrenShortcut );
173 connect( replaceShortcut, &QShortcut::activated,
this, [
this] {
175 const bool show = mLineEditReplace->isHidden();
185 QShortcut *closeFindShortcut =
new QShortcut( Qt::Key::Key_Escape,
this );
186 closeFindShortcut->setContext( Qt::ShortcutContext::WidgetWithChildrenShortcut );
187 connect( closeFindShortcut, &QShortcut::activated,
this, [
this] {
192 layoutFind->addLayout( findButtonLayout, 0, mShowReplaceBarButton ? 2 : 1 );
194 QHBoxLayout *replaceButtonLayout =
new QHBoxLayout();
195 replaceButtonLayout->setContentsMargins( 0, 0, 0, 0 );
196 replaceButtonLayout->setSpacing( 1 );
198 mReplaceButton =
new QToolButton();
199 mReplaceButton->setText( tr(
"Replace" ) );
200 mReplaceButton->setEnabled(
false );
201 connect( mReplaceButton, &QToolButton::clicked,
this, &QgsCodeEditorWidget::replace );
202 replaceButtonLayout->addWidget( mReplaceButton );
204 mReplaceAllButton =
new QToolButton();
205 mReplaceAllButton->setText( tr(
"Replace All" ) );
206 mReplaceAllButton->setEnabled(
false );
207 connect( mReplaceAllButton, &QToolButton::clicked,
this, &QgsCodeEditorWidget::replaceAll );
208 replaceButtonLayout->addWidget( mReplaceAllButton );
210 layoutFind->addLayout( replaceButtonLayout, 1, mShowReplaceBarButton ? 2 : 1 );
212 QToolButton *closeFindButton =
new QToolButton(
this );
213 closeFindButton->setToolTip( tr(
"Close" ) );
215 closeFindButton->setStyleSheet(
216 "QToolButton { border:none; background-color: rgba(0, 0, 0, 0); }"
217 "QToolButton::menu-button { border:none; background-color: rgba(0, 0, 0, 0); }"
219 closeFindButton->setCursor( Qt::PointingHandCursor );
223 closeFindButton->setIconSize( QSize( iconSize, iconSize ) );
224 closeFindButton->setFixedSize( QSize( iconSize, iconSize ) );
225 connect( closeFindButton, &QAbstractButton::clicked,
this, [
this] {
229 layoutFind->addWidget( closeFindButton, 0, mShowReplaceBarButton ? 3 : 2 );
231 layoutFind->setColumnStretch( mShowReplaceBarButton ? 1 : 0, 1 );
233 mFindWidget->setLayout( layoutFind );
234 vl->addWidget( mFindWidget );
241 mHighlightController = std::make_unique<QgsScrollBarHighlightController>();
242 mHighlightController->setScrollArea( mEditor );
539 const QString accessToken =
QgsSettings().
value(
"pythonConsole/accessTokenGithub", QString() ).toString();
540 if ( accessToken.isEmpty() )
543 mMessageBar->pushWarning( QString(), tr(
"GitHub personal access token must be generated (see IDE Options)" ) );
547 QString defaultFileName;
548 switch ( mEditor->language() )
551 defaultFileName = QStringLiteral(
"pyqgis_snippet.py" );
555 defaultFileName = QStringLiteral(
"qgis_snippet.css" );
559 defaultFileName = QStringLiteral(
"qgis_snippet" );
563 defaultFileName = QStringLiteral(
"qgis_snippet.html" );
567 defaultFileName = QStringLiteral(
"qgis_snippet.js" );
571 defaultFileName = QStringLiteral(
"qgis_snippet.json" );
575 defaultFileName = QStringLiteral(
"qgis_snippet.r" );
579 defaultFileName = QStringLiteral(
"qgis_snippet.sql" );
583 defaultFileName = QStringLiteral(
"qgis_snippet.bat" );
587 defaultFileName = QStringLiteral(
"qgis_snippet.sh" );
591 defaultFileName = QStringLiteral(
"qgis_snippet.txt" );
594 const QString filename = mFilePath.isEmpty() ? defaultFileName : QFileInfo( mFilePath ).fileName();
596 const QString contents = mEditor->hasSelectedText() ? mEditor->selectedText() : mEditor->text();
597 const QVariantMap data {
598 { QStringLiteral(
"description" ),
"Gist created by PyQGIS Console" },
599 { QStringLiteral(
"public" ), isPublic },
600 { QStringLiteral(
"files" ), QVariantMap { { filename, QVariantMap { { QStringLiteral(
"content" ), contents } } } } }
603 QNetworkRequest request;
604 request.setUrl( QUrl( QStringLiteral(
"https://api.github.com/gists" ) ) );
605 request.setRawHeader(
"Authorization", QStringLiteral(
"token %1" ).arg( accessToken ).toLocal8Bit() );
606 request.setHeader( QNetworkRequest::ContentTypeHeader, QLatin1String(
"application/json" ) );
607 request.setAttribute( QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy );
611 connect( reply, &QNetworkReply::finished,
this, [
this, reply] {
612 if ( reply->error() == QNetworkReply::NoError )
615 const QString link = replyJson.value( QStringLiteral(
"html_url" ) ).toString();
616 QDesktopServices::openUrl( QUrl( link ) );
621 mMessageBar->pushCritical( QString(), tr(
"Connection error: %1" ).arg( reply->errorString() ) );
623 reply->deleteLater();