Workspace order, where are these defined

Im trying to find out where the order of the workspaces are defined. The simplest manner to find the order for me was doing a loop over the bpy.data.workspaces. This seems to return a list which is alphabetically ordened. I tried looking into how the workspace toolbar is setup, but thats doesnt seem to accessibly by python. Atleast i have not found the correct method of accessing it.

I have this addon, quickswitch

Users can store the workspace set to hotkeys. The issue is that when i change the name of th workspace, the hotkey gets reassigned to the items closest to the new name. My idea was to trigger to check for the names and compare them to a list of saved items. Downside is, only method of doing this is use persistent, so with each click or interaction it does this check.

I cant seem to figure out a method of doing so. There for i thought i store the correct order of them, then it would be much easily to compare them directly

ive also found this post, but without any response. I tried looking in source code, but i dont knwo much about c++

From briefly looking at the relevant code it seems the whole workspace order is handled somewhat convoluted. The order field mentioned in Need python access to workspace tab order (workspace.order) indeed holds the order, but it’s not directly exposed to Python, nor does there seem to be another way.

The only (nasty) workaround I can think of is to use bpy.ops.screen.workspace_cycle(direction='NEXT') to cycle through all the workspaces and check bpy.context.window.workspace.name until it loops around. But that operator can not be called during UI drawing operations it seems (get a can't modify blend data in this state (drawing/rendering)), so it might actually not be possible to use it. Plus, switching workspaces causes delays the first time, due to resources needing to be initialized.

The simplest fix would be to add an order property to the C code:

diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c
index d76ad254140..d97089691a6 100644
--- a/source/blender/makesrna/intern/rna_workspace.c
+++ b/source/blender/makesrna/intern/rna_workspace.c
@@ -429,6 +429,8 @@ static void rna_def_workspace(BlenderRNA *brna)
                            "(which has its own active asset library)");
   RNA_def_property_update(prop, NC_ASSET | ND_ASSET_LIST_READING, NULL);
 
+  prop = RNA_def_property(srna, "order", PROP_INT, PROP_NONE);
+
   RNA_api_workspace(srna);
 }

which you can then use as

>>> bpy.data.workspaces[0].name
'Animation'

>>> bpy.data.workspaces[0].order
6

I’ll submit the patch for review and inclusion in the next release.

Edit: ⚙ D13889 Make workspace order available from Python

1 Like

Ow wow, thats a very fast response!

I hope im correct actually, im not sure if order can solve my issue. Im still need to try my own solution to get around the renaming of a workspace issue and the pre-set hotkey getting shifted.

In the preferences i use an EnumProp to store the workspace name. Issue is when the workspace name is changed, the hotkey seems to shift to the one closest to the old name.

This is the starting order, its alway alphabetical

After change, notice that Compositing shifted downwards.
quickswitch-hotkey-shift

I have 10 preset or hotkeys assigned, max 10 workspaces. They are assigned to a layoutName WorkspaceSwitcher 0/10. My idea was to store those layoutnames and the assigned workspace name. They check them with @persistent. Its kinda horrible that i need to that just to keep this working.

I hope ive explained the issue

Below is example of one of the menu’s. The order gets shifted

This happens because the EnumProp i use to be able to pick the workspaces has changed its order as well. Below is a example of the EnumProp which changes its order because of the alphabetical ordering which is done automatically.

I use a very simple function to get those names.

def get_names_workspaces(self,context):
	'''
	enumerates available Workspaces and adding more items:
	Maximize Area - will toggle current area to maximum window size
	User Preferences - opens User Preferences window
	'''

	ws = bpy.data.workspaces
	wsNames = [ ("Preferences", "Preferences", "Preferences")]
			# (identifier, name, description) optionally: (.., icon name, unique number)

	for ws in bpy.data.workspaces:
		wsNames.append((ws.name, ws.name, ws.name))
	return wsNames

The issue perhaps is that the Enum is shifting because its stored as an order, i believe its the index numbering. But im using names when i append them. Should i perhaps use integer numbers for the first attribute when i append an item?!

Perhaps my issue is easier to solve vs adding a new prop in the source code. Im not that good of a coder.

I was looking at the EnumProperty again and perhaps i can make use of get and set function. Ive never used those actually. But i see it has integer number at the end. So perhaps i can use that number to compare the original order?! Though im not sure of that set method, its not clear to me what it does when i look at this example. I can could also use items and update to do this.

import bpy
# Enum property.
# Note: the getter/setter callback must use integer identifiers!
test_items = [
    ("RED", "Red", "", 1),
    ("GREEN", "Green", "", 2),
    ("BLUE", "Blue", "", 3),
    ("YELLOW", "Yellow", "", 4),
]


def get_enum(self):
    import random
    return random.randint(1, 4)


def set_enum(self, value):
    print("setting value", value)


bpy.types.Scene.test_enum = bpy.props.EnumProperty(items=test_items, get=get_enum, set=set_enum)

# Testing the properties:
scene = bpy.context.scene

scene.test_enum = 'BLUE'
print('test_enum:', scene.test_enum)

# The above outputs:
# setting value 3
# test_enum: GREEN

code source: Property Definitions (bpy.props) — Blender Python API

What i dont get with that get set is what i does. In the example its set as ‘BLUE’ but returns ‘GREEN’…

Though when i test this, i get red?!?!

setting value 3
test_enum: RED

when i call scene.test_enum it randomly spits back the colors. I dont understand whats going there

I remember this older post on stackexchange, it used an id to if anything changes. Still dont see a difference using this method. Guess i need to make some change to the function perhaps

def get_names_workspaces(self,context):
	'''
	enumerates available Workspaces and adding more items:
	store it using id
	https://blender.stackexchange.com/questions/78133/dynamic-enumproperty-values-changing-unexpectedly
	'''
	ws = bpy.data.workspaces
	items_store = []
	wsNames = []
	wsNames.append(("Preferences","Preferences","Preferences", 0))
	#Scan the list of IDs to see if we already have one for this mesh
	maxid = -1
	id = -1
	found = False
	for ws in bpy.data.workspaces:
		for idrec in items_store:
			print("idrec %s - %s" % (idrec[0],idrec[1]))
			id = idrec[0]
			if id > maxid:
				maxid = id
			if idrec[1] == ws.name:
				found = True
				break
		if not found:
			items_store.append((maxid+1, ws.name,ws.name))
		# AMENDED CODE - include the ID	
		wsNames.append( (ws.name, ws.name, ws.name, id) )
	# print(wsNames)
	return wsNames

Doesnt the EnumProp store it by the ID or does it use the names?!

I think im going to try this approach. so i need to store the list when its first created, then check each time
compare list of 2 in python
But this has one issue and that is that on first run, it doesnt have 2 lists. Could a pre and post handler fix this?

listA= [13, 'Mon',23, 62,'Sun']
listB = [5, 'Mon',23, 6,'Sun']

# index variable
idx = 0

# Result list
res = []

# With iteration
for i in listA:
   if i != listB[idx]:
      res.append(idx)
   idx = idx + 1

# Result
print("The index positions with mismatched values:\n",res)

I’m quite lost, in the end your shortcuts aims to map the workspaces’ position?

Like for example:

  • Ctrl 1 for the 1st
  • Ctrl 2 for the 2nd
    etc… ?

If so exposing the order property in the rna, as proposed in the patch above, should allow you to do it fairly easy, I think.
(btw @PaulMelis you should probably also add the ui description end the proper dependency graph tag for the property)

I wouldn’t honestly understand why you’d want to use a shortcut for a specific workspace instead, since they are file-dependant. But maybe I’m missing something here.

1 Like

True, they are being stored per file. Im trying to find a solution for custom scenes as well.
I was thinking of simply returning the order given from the loop. THough i need to figure out how to assign temp hotkeys then.