The problem is in the load_style_from_database(self, layer) function, starting from row #368:
369 manager = layer.styleManager()
370 existing_styles = manager.styles()
371 for s in existing_styles:
372 manager.removeStyle(s)
373
374 manager.currentStyle()
375 manager.renameStyle(manager.currentStyle(), '')
376 manager.renameStyle('', 'default')
377 styles = layer.listStylesInDatabase()
378 if len(styles) == 0:
379 # No style for all layers in the database, we do nothing
380 return
381
382 number_styles = styles[0]
383 if number_styles == 0:
384 # No style for this layer in the database, we do nothing
385 return
386
387
388 related_styles_idx = styles[1][0:number_styles]
389 related_styles_names = styles[2][0:number_styles]
390 related_styles_description = styles[3][0:number_styles]
391 related_styles = zip(related_styles_idx, related_styles_names, related_styles_description)
392 for style in related_styles:
393 if Qgis.QGIS_VERSION_INT < 30000:
394 xml_style = layer.getStyleFromDatabase(style[0], '')
395 else:
396 xml_style = layer.getStyleFromDatabase(style[0])[0]
397 # description = style[2]
398 manager.addStyle(style[1], QgsMapLayerStyle(xml_style))
399
400 # Deactivated in 0.3, because in QGIS 2.18 we can't know which one is the default style
401 # if len(number_styles) > 0:
402 # # If we have at least one style, we take the first one for the title and name
403 # layer.setTitle(related_styles[0][2])
404 # layer.setName(related_styles[0][2])
405
406 # len(zip object) do not exist on Python 3
407 if len(list(related_styles)) >= 1:
408 # We got one layer, we can set it by default in QGIS
409 manager.setCurrentStyle(related_styles[0][1])
410 manager.removeStyle('default')
411
412 self.iface.messageBar().pushInfo(
413 tr('Style Loaded'),
414 tr('{layer_name} has {number} styles loaded successfully.').format(
415 layer_name=layer.name(), number=len(list(related_styles))))
If I already have got styles associated to the layer (like when I reopen the project and the Load styles automatically button is toggled), it removes all but the last one.
removeStyle()
bool QgsMapLayerStyleManager::removeStyle ( const QString & name )
Remove a stored style.
Returns
true on success (style exists and it is not the last one)
Definition at line 128 of file qgsmaplayerstylemanager.cpp.
The first problem is that this last style is then renamed as 'default':
According to me one third problem (not of the plugin) is that QGIS re-sorts the added styles in the style selection popup and in the project file according to the default Python sorting, i.e. taking care of the case (uppercase first and then lowercase). Well, it isn't a big problem, but I would like to sort my layers as I want...:
One workaround for the first problem can be a "selective" style removing in line #371, but if the user has changed the 'default' style it will stay the same also after the style reset:
>>>for s in (x for x in existing_styles if x!='default'):
... manager.removeStyle(s)
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
True
>>>manager.styles()
['default']
A second (and I think more valid) workaround can be:
move the conditionals from line #377 to line #385 at the beginning of the function (do nothing in case there aren't valid styles in the database)
after deletion, rename the "remaining" style to 'garbage' in line #375;
not renaming to 'default' in line #376;
check if there's a new loaded style called 'default' and making it the current one;
remove the 'garbage' style.
The function code will change in the following manner:
def load_style_from_database(self, layer):
styles = layer.listStylesInDatabase()
if len(styles) == 0:
# No style for all layers in the database, we do nothing
return
number_styles = styles[0]
if number_styles == 0:
# No style for this layer in the database, we do nothing
return
manager = layer.styleManager()
existing_styles = manager.styles()
for s in existing_styles:
manager.removeStyle(s)
manager.currentStyle()
manager.renameStyle(manager.currentStyle(), 'garbage')
# manager.renameStyle('', 'default')
related_styles_idx = styles[1][0:number_styles]
related_styles_names = styles[2][0:number_styles]
related_styles_description = styles[3][0:number_styles]
related_styles = zip(related_styles_idx, related_styles_names, related_styles_description)
for style in related_styles:
if Qgis.QGIS_VERSION_INT < 30000:
xml_style = layer.getStyleFromDatabase(style[0], '')
else:
xml_style = layer.getStyleFromDatabase(style[0])[0]
# description = style[2]
manager.addStyle(style[1], QgsMapLayerStyle(xml_style))
loaded_styles = manager.styles()
for s in (x for x in loaded_styles if x=='default'):
manager.setCurrentStyle(s)
manager.removeStyle('garbage')
# Deactivated in 0.3, because in QGIS 2.18 we can't know which one is the default style
# if len(number_styles) > 0:
# # If we have at least one style, we take the first one for the title and name
# layer.setTitle(related_styles[0][2])
# layer.setName(related_styles[0][2])
# len(zip object) do not exist on Python 3
if len(list(related_styles)) >= 1:
# We got one layer, we can set it by default in QGIS
manager.setCurrentStyle(related_styles[0][1])
manager.removeStyle('default')
self.iface.messageBar().pushInfo(
tr('Style Loaded'),
tr('{layer_name} has {number} styles loaded successfully.').format(
layer_name=layer.name(), number=len(list(related_styles))))
As said some lines up, in python3 any iteration (or listing) cancels the contents of the zip so the code from lines #406 to #415 won't work ( len(list(related_styles)) = 0 after the iteration).
The remaining problem is that if a user has created a new style and, after that, he wants to load also the styles from the db, the procedure will erase his newly created style (if he hasn't saved it in the db)...
I think there's a small bug in the code.
The problem is in the
load_style_from_database(self, layer)
function, starting from row #368:If I already have got styles associated to the layer (like when I reopen the project and the Load styles automatically button is toggled), it removes all but the last one.
That code leaves the last saved style (not ever the default one). In fact it is confirmed by the definition of the
removeStyle()
function:https://qgis.org/api/classQgsMapLayerStyleManager.html#a23ab0b557dc0c1ad6a12e1d17798ba63
The first problem is that this last style is then renamed as 'default':
The second problem is that it stays there "as is" when the code goes on to retrieve the styles from the database:
According to me one third problem (not of the plugin) is that QGIS re-sorts the added styles in the style selection popup and in the project file according to the default Python sorting, i.e. taking care of the case (uppercase first and then lowercase). Well, it isn't a big problem, but I would like to sort my layers as I want...:
One workaround for the first problem can be a "selective" style removing in line #371, but if the user has changed the 'default' style it will stay the same also after the style reset:
A second (and I think more valid) workaround can be:
The function code will change in the following manner:
As said some lines up, in python3 any iteration (or listing) cancels the contents of the zip so the code from lines #406 to #415 won't work (
len(list(related_styles))
= 0 after the iteration).The remaining problem is that if a user has created a new style and, after that, he wants to load also the styles from the db, the procedure will erase his newly created style (if he hasn't saved it in the db)...