Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport queued_ltr_backports] Raster - paletted: fix slow rendering with huge number of classes #57037

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
4a47868
[network] Enable strict transport security to fix http->https WMS (et…
nirvn Feb 24, 2024
b203f78
Fix bookmarks manager model signals emitted twice
elpaso Feb 23, 2024
feb6120
Use pixel based scrolling instead of rows for identify results
nyalldawson Feb 27, 2024
0247ce5
Use better python repr for null QgsRectangle
nyalldawson Feb 27, 2024
ef98c93
[Postgres] Fixes #54260 : Remove listener wait condition
troopa81 Oct 26, 2023
84b8ac4
Consistently return invalid QVariant for QgsVectorDataProvider::defau…
nyalldawson Feb 28, 2024
7e2296f
Update test_provider_spatialite.py: add NULL import
rouault Feb 28, 2024
b1ac747
[map canvas] Fix clearing of temporal and elevation triggered cache f…
nirvn Mar 4, 2024
8367ef4
QgsGeos::asGeos(): only error out on invalid subgeometry only if requ…
rouault Mar 4, 2024
eb25c1c
[vector layer] Fix QgsVectorLayerFeatureIterator::isValid() value whe…
nirvn Mar 1, 2024
5c56196
[processing] Fix "Random points along line" alg
agiudiceandrea Mar 4, 2024
4bfc618
Apply suggestion from code review
agiudiceandrea Mar 4, 2024
b606fba
[gps] Don't emit stateChanged for incomplete nmea messages
nyalldawson Mar 6, 2024
9e4b8ef
qgsshadowrenderingframegraph: Fix blendequation for transparent entities
ptitjano Mar 5, 2024
f4a0aba
Fix global QGIS setting key in check validity algorithm
Djedouas Mar 6, 2024
b51f985
[Server] QgsWmsRenderContext::isValidWidthHeight(): rewrite sanity ch…
rouault Mar 7, 2024
7994e93
[console] Don't needlessly store QgsSettings objects
nyalldawson Mar 6, 2024
e20e793
[console] Ensure stored last dir path settings is always a folder
nyalldawson Mar 6, 2024
b81cdef
[console] Minor cleanups
nyalldawson Mar 6, 2024
0affcf3
Browser: fix slow behavior with network drives on windows
elpaso Mar 14, 2024
c565938
[postgres] Avoid setting nextval() clause if no default sequence was …
gacarrillor Mar 11, 2024
15d9da9
[tests] Add tests for fix #54058
gacarrillor Mar 11, 2024
6832983
suggest PQgetisnull
jef-n Mar 11, 2024
d67a11e
[plugins manager] Normalize _all_ version references
nirvn Mar 15, 2024
136eabf
Add a bunch of debugging output to diagnose GPS connection errors
nyalldawson Mar 6, 2024
0a5065a
Rework QgsGpsDetector to make it memory safe
nyalldawson Mar 11, 2024
991d03d
Cleanup GPS detector timeout timer handling
nyalldawson Mar 11, 2024
9abe827
As soon as we detect a valid device, stop listening for device status
nyalldawson Mar 11, 2024
bcb4691
Before releasing the connection, disconnect everything from the detector
nyalldawson Mar 11, 2024
88ea592
Add a few more logging outputs
nyalldawson Mar 11, 2024
d3a4ce1
Demote debug messages
nyalldawson Mar 12, 2024
99b2a2a
[processing] Use correct ellipsoid for network analysis tools
nyalldawson Mar 8, 2024
e37f52f
Fix test
nyalldawson Mar 13, 2024
dd7cb7f
qgswfsgetfeature: Do not invert axis if no SRSNAME is passed
ptitjano Nov 2, 2023
f98bcdc
qgswfsgetfeature: Add a comment to explain axis inversion logic
ptitjano Nov 13, 2023
8481f49
Fix QgsSymbol::drawPreviewIcon
agiudiceandrea Mar 20, 2024
1dcf0c3
[layouts] Defer legend item feature count until layout is drawn
nirvn Mar 18, 2024
0238727
Browser: avoid calling slow functions on disconnected drives
elpaso Mar 13, 2024
6b8f065
Raster - paletted: fix slow rendering with huge number of classes
elpaso Mar 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,11 @@ the specified ``spacing`` between the grid lines.

SIP_PYOBJECT __repr__();
%MethodCode
QString str = QStringLiteral( "<QgsRectangle: %1>" ).arg( sipCpp->asWktCoordinates() );
QString str;
if ( sipCpp->isNull() )
str = QStringLiteral( "<QgsRectangle()>" );
else
str = QStringLiteral( "<QgsRectangle: %1>" ).arg( sipCpp->asWktCoordinates() );
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
%End

Expand Down
48 changes: 46 additions & 2 deletions python/PyQt6/core/auto_generated/gps/qgsgpsdetector.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,41 @@ Class to detect the GPS port
#include "qgsgpsdetector.h"
%End
public:
QgsGpsDetector( const QString &portName );


QgsGpsDetector( const QString &portName = QString(), bool useUnsafeSignals = true );
%Docstring
Constructor for QgsGpsDetector.

If ``portName`` is specified, then only devices from the given port will be scanned. Otherwise
all connection types will be attempted (including internal GPS devices).

Since QGIS 3.38, the ``useUnsafeSignals`` parameter can be set to ``False`` to avoid emitting the
dangerous and fragile :py:func:`~QgsGpsDetector.detected` signal. This is highly recommended, but is opt-in to avoid
breaking stable QGIS 3.x API. If ``useUnsafeSignals`` is set to ``False``, only the safe :py:func:`~QgsGpsDetector.connectionDetected` signal
will be emitted and clients must manually take ownership of the detected connection via a call
to :py:func:`~QgsGpsDetector.takeConnection`.
%End


~QgsGpsDetector();

QgsGpsConnection *takeConnection() /TransferBack/;
%Docstring
Returns the detected GPS connection, and removes it from the detector.

The caller takes ownership of the connection. Only the first call to this
method following a :py:func:`~QgsGpsDetector.connectionDetected` signal will be able to retrieve the
detected connection -- subsequent calls will return ``None``.

.. warning::

Do not call this method if the useUnsafeSignals option in the
QgsGpsDetector constructor was set to ``True``.

.. versionadded:: 3.38
%End

static QList< QPair<QString, QString> > availablePorts();

public slots:
Expand All @@ -37,14 +67,28 @@ Class to detect the GPS port

signals:

void connectionDetected();
%Docstring
Emitted when a GPS connection is successfully detected.

Call :py:func:`~QgsGpsDetector.takeConnection` to take ownership of the detected connection.

void detected( QgsGpsConnection *connection );
.. versionadded:: 3.38
%End

void detected( QgsGpsConnection *connection ) /Deprecated/;
%Docstring
Emitted when the GPS connection has been detected. A single connection must listen for this signal and
immediately take ownership of the ``connection`` object.

.. deprecated::
This signal is dangerous and extremely unsafe! It is recommended to instead set the ``useUnsafeSignals`` parameter to ``False`` in the QgsGpsDetector constructor and use the safe :py:func:`~QgsGpsDetector.connectionDetected` signal instead.
%End

void detectionFailed();
%Docstring
Emitted when the detector could not find a valid GPS connection.
%End

};

Expand Down
29 changes: 15 additions & 14 deletions python/console/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,6 @@ def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setWindowTitle(QCoreApplication.translate("PythonConsole", "Python Console"))

self.settings = QgsSettings()

self.shell = ShellScintilla(self)
self.setFocusProxy(self.shell)
self.shellOut = ShellOutputScintilla(self)
Expand Down Expand Up @@ -310,7 +308,7 @@ def __init__(self, parent=None):
objList = QCoreApplication.translate("PythonConsole", "Object Inspector…")
self.objectListButton = QAction(self)
self.objectListButton.setCheckable(True)
self.objectListButton.setEnabled(self.settings.value("pythonConsole/enableObjectInsp",
self.objectListButton.setEnabled(QgsSettings().value("pythonConsole/enableObjectInsp",
False, type=bool))
self.objectListButton.setIcon(QgsApplication.getThemeIcon("console/iconClassBrowserConsole.svg"))
self.objectListButton.setMenuRole(QAction.PreferencesRole)
Expand Down Expand Up @@ -675,7 +673,8 @@ def openScriptFileExtEditor(self):
QDesktopServices.openUrl(QUrl.fromLocalFile(path))

def openScriptFile(self):
lastDirPath = self.settings.value("pythonConsole/lastDirPath", QDir.homePath())
settings = QgsSettings()
lastDirPath = settings.value("pythonConsole/lastDirPath", QDir.homePath())
openFileTr = QCoreApplication.translate("PythonConsole", "Open File")
fileList, selected_filter = QFileDialog.getOpenFileNames(
self, openFileTr, lastDirPath, "Script file (*.py)")
Expand All @@ -691,7 +690,7 @@ def openScriptFile(self):
self.tabEditorWidget.newTabEditor(tabName, pyFile)

lastDirPath = QFileInfo(pyFile).path()
self.settings.setValue("pythonConsole/lastDirPath", pyFile)
settings.setValue("pythonConsole/lastDirPath", pyFile)
self.updateTabListScript(pyFile, action='append')

def saveScriptFile(self):
Expand All @@ -710,7 +709,7 @@ def saveAsScriptFile(self, index=None):
index = self.tabEditorWidget.currentIndex()
if not tabWidget.path:
fileName = self.tabEditorWidget.tabText(index).replace('*', '') + '.py'
folder = self.settings.value("pythonConsole/lastDirPath", QDir.homePath())
folder = QgsSettings().value("pythonConsole/lastDirPath", QDir.homePath())
pathFileName = os.path.join(folder, fileName)
fileNone = True
else:
Expand Down Expand Up @@ -776,22 +775,24 @@ def updateTabListScript(self, script, action=None):
self.tabListScript.append(script)
else:
self.tabListScript = []
self.settings.setValue("pythonConsole/tabScripts",
QgsSettings().setValue("pythonConsole/tabScripts",
self.tabListScript)

def saveSettingsConsole(self):
self.settings.setValue("pythonConsole/splitterConsole", self.splitter.saveState())
self.settings.setValue("pythonConsole/splitterObj", self.splitterObj.saveState())
self.settings.setValue("pythonConsole/splitterEditor", self.splitterEditor.saveState())
settings = QgsSettings()
settings.setValue("pythonConsole/splitterConsole", self.splitter.saveState())
settings.setValue("pythonConsole/splitterObj", self.splitterObj.saveState())
settings.setValue("pythonConsole/splitterEditor", self.splitterEditor.saveState())

self.shell.writeHistoryFile()

def restoreSettingsConsole(self):
storedTabScripts = self.settings.value("pythonConsole/tabScripts", [])
settings = QgsSettings()
storedTabScripts = settings.value("pythonConsole/tabScripts", [])
self.tabListScript = storedTabScripts
self.splitter.restoreState(self.settings.value("pythonConsole/splitterConsole", QByteArray()))
self.splitterEditor.restoreState(self.settings.value("pythonConsole/splitterEditor", QByteArray()))
self.splitterObj.restoreState(self.settings.value("pythonConsole/splitterObj", QByteArray()))
self.splitter.restoreState(settings.value("pythonConsole/splitterConsole", QByteArray()))
self.splitterEditor.restoreState(settings.value("pythonConsole/splitterEditor", QByteArray()))
self.splitterObj.restoreState(settings.value("pythonConsole/splitterObj", QByteArray()))


if __name__ == '__main__':
Expand Down
44 changes: 21 additions & 23 deletions python/console/console_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import re
import sys
import tempfile
from typing import Optional
from functools import partial
from operator import itemgetter
from pathlib import Path
Expand Down Expand Up @@ -60,10 +61,9 @@ class Editor(QgsCodeEditorPython):
def __init__(self, parent=None):
super().__init__(parent)
self.parent = parent
self.path = None
self.path: Optional[str] = None
# recent modification time
self.lastModified = 0
self.settings = QgsSettings()

self.setMinimumHeight(120)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
Expand Down Expand Up @@ -186,7 +186,7 @@ def contextMenuEvent(self, e):
redoAction.setEnabled(True)
if QApplication.clipboard().text():
pasteAction.setEnabled(True)
if self.settings.value("pythonConsole/enableObjectInsp",
if QgsSettings().value("pythonConsole/enableObjectInsp",
False, type=bool):
showCodeInspection.setEnabled(True)
menu.exec_(self.mapToGlobal(e.pos()))
Expand Down Expand Up @@ -239,7 +239,7 @@ def objectListEditor(self):
self.pythonconsole.objectListButton.setChecked(True)

def shareOnGist(self, is_public):
ACCESS_TOKEN = self.settings.value("pythonConsole/accessTokenGithub", '', type=QByteArray)
ACCESS_TOKEN = QgsSettings().value("pythonConsole/accessTokenGithub", '', type=QByteArray)
if not ACCESS_TOKEN:
msg_text = QCoreApplication.translate(
'PythonConsole', 'GitHub personal access token must be generated (see Console Options)')
Expand Down Expand Up @@ -307,7 +307,7 @@ def createTempFile(self):
return name

def runScriptCode(self):
autoSave = self.settings.value("pythonConsole/autoSaveScript", False, type=bool)
autoSave = QgsSettings().value("pythonConsole/autoSaveScript", False, type=bool)
tabWidget = self.tabwidget.currentWidget()
filename = tabWidget.path
msgEditorBlank = QCoreApplication.translate('PythonConsole',
Expand Down Expand Up @@ -404,24 +404,23 @@ def loadFile(self, filename, readOnly=False):
self.setModified(False)
self.recolor()

def save(self, filename=None):
def save(self, filename: Optional[str] = None):
if self.isReadOnly():
return

if self.pythonconsole.settings.value("pythonConsole/formatOnSave", False, type=bool):
if QgsSettings().value("pythonConsole/formatOnSave", False, type=bool):
self.reformatCode()

tabwidget = self.tabwidget
index = tabwidget.indexOf(self.parent)
index = self.tabwidget.indexOf(self.parent)
if filename:
self.path = filename
if self.path is None:
if not self.path:
saveTr = QCoreApplication.translate('PythonConsole',
'Python Console: Save file')
folder = self.pythonconsole.settings.value("pythonConsole/lastDirPath", QDir.homePath())
folder = QgsSettings().value("pythonConsole/lastDirPath", QDir.homePath())
self.path, filter = QFileDialog().getSaveFileName(self,
saveTr,
os.path.join(folder, tabwidget.tabText(index).replace('*', '') + '.py'),
os.path.join(folder, self.tabwidget.tabText(index).replace('*', '') + '.py'),
"Script file (*.py)")
# If the user didn't select a file, abort the save operation
if not self.path:
Expand All @@ -436,15 +435,15 @@ def save(self, filename=None):
# Need to use newline='' to avoid adding extra \r characters on Windows
with open(self.path, 'w', encoding='utf-8', newline='') as f:
f.write(self.text())
tabwidget.setTabTitle(index, Path(self.path).name)
tabwidget.setTabToolTip(index, self.path)
self.tabwidget.setTabTitle(index, Path(self.path).name)
self.tabwidget.setTabToolTip(index, self.path)
self.setModified(False)
self.pythonconsole.saveFileButton.setEnabled(False)
self.lastModified = QFileInfo(self.path).lastModified()
self.pythonconsole.updateTabListScript(self.path, action='append')
tabwidget.listObject(self.parent)
lastDirPath = str(Path(self.path).parent)
self.pythonconsole.settings.setValue("pythonConsole/lastDirPath", lastDirPath)
self.tabwidget.listObject(self.parent)
QgsSettings().setValue("pythonConsole/lastDirPath",
Path(self.path).parent.as_posix())

def event(self, e):
""" Used to override the Application shortcuts when the editor has focus """
Expand Down Expand Up @@ -553,8 +552,6 @@ def __init__(self, parent):
super().__init__(parent=None)
self.parent = parent

self.settings = QgsSettings()

self.idx = -1
# Layout for top frame (restore tabs)
self.layoutTopFrame = QGridLayout(self)
Expand Down Expand Up @@ -641,7 +638,7 @@ def __init__(self, parent):
self.newTabButton.clicked.connect(self.newTabEditor)

def _currentWidgetChanged(self, tab):
if self.settings.value("pythonConsole/enableObjectInsp",
if QgsSettings().value("pythonConsole/enableObjectInsp",
False, type=bool):
self.listObject(tab)
self.changeLastDirPath(tab)
Expand Down Expand Up @@ -788,7 +785,7 @@ def restoreTabsOrAddNew(self):
Restore tabs if they are found in the settings. If none are found it will add a new empty tab.
"""
# Restore scripts from the previous session
tabScripts = self.settings.value("pythonConsole/tabScripts", [])
tabScripts = QgsSettings().value("pythonConsole/tabScripts", [])
self.restoreTabList = tabScripts

if self.restoreTabList:
Expand Down Expand Up @@ -911,7 +908,7 @@ def listObject(self, tab):
self.parent.listClassMethod.addTopLevelItem(msgItem)

def refreshSettingsEditor(self):
objInspectorEnabled = self.settings.value("pythonConsole/enableObjectInsp",
objInspectorEnabled = QgsSettings().value("pythonConsole/enableObjectInsp",
False, type=bool)
listObj = self.parent.objectListButton
if self.parent.listClassMethod.isVisible():
Expand All @@ -926,7 +923,8 @@ def refreshSettingsEditor(self):
def changeLastDirPath(self, tab):
tabWidget = self.widget(tab)
if tabWidget and tabWidget.path:
self.settings.setValue("pythonConsole/lastDirPath", tabWidget.path)
QgsSettings().setValue("pythonConsole/lastDirPath",
Path(tabWidget.path).parent.as_posix())

def showMessage(self, text, level=Qgis.Info, timeout=-1, title=""):
currWidget = self.currentWidget()
Expand Down
4 changes: 1 addition & 3 deletions python/console/console_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def write(self, m):

if self.style == "_traceback":
# Show errors in red
stderrColor = QColor(self.sO.settings.value("pythonConsole/stderrFontColor", QColor(self.ERROR_COLOR)))
stderrColor = QColor(QgsSettings().value("pythonConsole/stderrFontColor", QColor(self.ERROR_COLOR)))
self.sO.SendScintilla(QsciScintilla.SCI_STYLESETFORE, 0o01, stderrColor)
self.sO.SendScintilla(QsciScintilla.SCI_STYLESETITALIC, 0o01, True)
self.sO.SendScintilla(QsciScintilla.SCI_STYLESETBOLD, 0o01, True)
Expand Down Expand Up @@ -122,8 +122,6 @@ def __init__(self, parent=None):
self.parent = parent
self.shell = self.parent.shell

self.settings = QgsSettings()

# Creates layout for message bar
self.layout = QGridLayout(self)
self.layout.setContentsMargins(0, 0, 0, 0)
Expand Down
2 changes: 0 additions & 2 deletions python/console/console_sci.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,6 @@ def __init__(self, parent=None):
self.opening = ['(', '{', '[', "'", '"']
self.closing = [')', '}', ']', "'", '"']

self.settings = QgsSettings()

self.setHistoryFilePath(
os.path.join(QgsApplication.qgisSettingsDirPath(), "console_history.txt"))

Expand Down
6 changes: 5 additions & 1 deletion python/core/auto_generated/geometry/qgsrectangle.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,11 @@ the specified ``spacing`` between the grid lines.

SIP_PYOBJECT __repr__();
%MethodCode
QString str = QStringLiteral( "<QgsRectangle: %1>" ).arg( sipCpp->asWktCoordinates() );
QString str;
if ( sipCpp->isNull() )
str = QStringLiteral( "<QgsRectangle()>" );
else
str = QStringLiteral( "<QgsRectangle: %1>" ).arg( sipCpp->asWktCoordinates() );
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
%End

Expand Down