Editable column view presets

Apologies if this has been discussed before (it has been - but that was 2013 - wondered if it had changed yet…)

I have a number of groups but I want to be able to customise the column view - ie: Which columns are displayed, depending on what I’m doing… I might want to see file information for one task, custom metadata for another, or annotations etc…

Is there not a way of setting up preset column views, so I can change which columns are displayed, in what arrangement, and just quickly change the view on a whim?
It seems whenever I set up a new group, I need to add columns I want to view again… but again, it depends on what content I’m viewing… surely there’s a quick way of choosing a predefined column view quickly?

Thanks,

J.

1 Like

The setup of List view columns is currently specific for each database and for each global smart group/rule. But predefined sets are not possible, we’ll consider this for future releases.

6 Likes

+1 for this feature, please.

2 Likes

Some time ago I tried to speed up the process of adding and removing columns. Unfortunately it wasn’t possible to use Keyboard Maestro’s Select or Show a Menu Item action which I didn’t understand back then. I now tried again and found the reason:

DEVONthink’s View menu contains ambiguous names

Didn’t notice that before so I wrote an UI script as a last resort instead of simply requesting unambiguous names.

The script shows a list of all columns and adds / removes the ones you choose.

Note: You have to change values in

  • property theUIColumns_default
  • property theDifferentNames
  • and in Handler replaceColumnNames you have to set those menu item names whose displayed column name differs from that displayed in the menu

to your language.

If you want a predefined list of columns instead of choosing every time you could change the script, if you need help let me know.

-- Add or remove columns

-- Note: You have to change values in property theUIColumns_default, property theDifferentNames and values in Handler replaceColumnNames to your language

property sortTitles : true
property thePlistPath : POSIX path of (path to application support from user domain) & "DEVONthink 3/CustomMetaData.plist"
property theUIColumns_default : {"Art", "URL", "Pfad", "Ort", "Finder-Kommentar", "Aliases", "Tags", "Wertung", "Etikett", "Fällig", "Hinzugefügt", "Erstellt", "Geändert", "Geöffnet", "Zugriffe", "Größe", "Wörter", "Buchstaben", "Breite x Höhe", "Länge", "Anhänge", "PDF-Annotationen", "Eintreffende Verweise", "Ausgehende Verweise", "Sprache", "Land", "Postleitzahl", "Bezirk", "Ortschaft", "Autor", "Titel", "Betreff", "Schlagwörter"}
property theDifferentNames : {"Fällig", "Hinzugefügt", "Erstellt", "Geändert", "Geöffnet", "Wörter", "Buchstaben"}

tell application "System Events"
	try
		set theTitles to {}
		tell property list file thePlistPath
			repeat with thisItem in property list items
				set thisItem_Value to value of thisItem
				set thisTitle to |title| of thisItem_Value
				set end of theTitles to thisTitle
			end repeat
		end tell
		if sortTitles = true then set theTitles to my sort_list(theTitles)
		
		set theUIColumns_all to theUIColumns_default & theTitles
		
	on error error_message number error_number
		if the error_number is not -128 then display alert "System Events" message error_message as warning
		return
	end try
end tell

tell application id "DNtp"
	try
		if not (exists viewer window 1) then error "Please open a window"
		set theTarget to my getTarget()
		if theTarget ≠ missing value then
			set theUIColumns_activate to my getActiveColumns(theTarget)
		else
			set theUIColumns_activate to {}
		end if
		activate
		set theUIColumns_Choice to choose from list theUIColumns_all & {""} with prompt "" default items theUIColumns_activate with title "Spalten" with multiple selections allowed
		if theUIColumns_Choice is false then return
		my clickMenuItems(theUIColumns_activate, theUIColumns_Choice, theUIColumns_all, theTarget)
		
	on error error_message number error_number
		if the error_number is not -128 then display alert "DEVONthink" message error_message as warning
		return
	end try
end tell

on getTarget()
	try
		activate application id "DNtp"
		tell application "System Events"
			tell process "DEVONthink 3"
				set theTarget to missing value
				try
					set theTarget to group 1 of outline 1 of scroll area 1 of group 1 of splitter group 1 of splitter group 1 of window 1
				end try
				try
					if theTarget = missing value then set theTarget to group 1 of outline 1 of scroll area 1 of group 1 of splitter group 2 of splitter group 1 of window 1
				end try
				return theTarget
			end tell
		end tell
	on error error_message number error_number
		activate application id "DNtp"
		display alert "Error: Handler \"getTarget\"" message error_message as warning
		error number -128
	end try
end getTarget

on getActiveColumns(theTarget)
	try
		activate application id "DNtp"
		tell application "System Events"
			tell process "DEVONthink 3"
				try
					set theColumns_activate to name of buttons of theTarget
				on error
					error "Can't get Column names"
				end try
				set theColumns_activate_clean to {}
				repeat with thisColumn in theColumns_activate
					set thisColumn to thisColumn as string
					if thisColumn is not in {"missing value", "Name"} then set end of theColumns_activate_clean to thisColumn
				end repeat
				return theColumns_activate_clean
			end tell
		end tell
	on error error_message number error_number
		activate application id "DNtp"
		display alert "Error: Handler \"getActiveColumns\"" message error_message as warning
		error number -128
	end try
end getActiveColumns

on clickMenuItems(theUIColumns_activate, theUIColumns_Choice, theUIColumns_all, theTarget)
	try
		activate application id "DNtp"
		tell application "System Events"
			tell process "DEVONthink 3"
				if theTarget = missing value then
					click menu bar item 8 of menu bar 1
					click menu item 25 of menu 1 of menu bar item 8 of menu bar 1
					click menu item 1 of menu 1 of menu item 25 of menu 1 of menu bar item 8 of menu bar 1
					set theFirstMenuItemName to name of menu item 1 of menu 1 of menu item 25 of menu 1 of menu bar item 8 of menu bar 1
					delay 0.1
					set theTarget to my getTarget()
				else
					set theFirstMenuItemName to missing value
				end if
				if theTarget ≠ missing value then
					
					repeat with thisMenuName in theUIColumns_all
						set thisMenuName to thisMenuName as string
						if (thisMenuName is not in theUIColumns_activate and thisMenuName is in theUIColumns_Choice) then
							set thisMenuName to my replaceColumnNames(thisMenuName)
							tell theTarget to perform action "AXShowMenu"
							delay 0.1
							try
								click (first menu item of menu 1 of theTarget whose value of attribute "AXTitle" = thisMenuName)
							on error
								display dialog "Can't click menu item \"" & thisMenuName & "\""
							end try
						end if
					end repeat
					
					repeat with thisMenuName in theUIColumns_all
						set thisMenuName to thisMenuName as string
						if (thisMenuName is in theUIColumns_activate and thisMenuName is not in theUIColumns_Choice) then
							set thisMenuName to my replaceColumnNames(thisMenuName)
							tell theTarget to perform action "AXShowMenu"
							delay 0.1
							try
								click (first menu item of menu 1 of theTarget whose value of attribute "AXTitle" = thisMenuName)
							on error
								display dialog "Can't click menu item \"" & thisMenuName & "\""
							end try
						end if
					end repeat
					
					if theFirstMenuItemName ≠ missing value then
						tell theTarget to perform action "AXShowMenu"
						delay 0.1
						try
							click (first menu item of menu 1 of theTarget whose value of attribute "AXTitle" = theFirstMenuItemName)
						on error
							display dialog "Can't click menu item \"" & thisMenuName & "\""
						end try
					end if
				else
					error "Can't get Column names"
				end if
			end tell
		end tell
	on error error_message number error_number
		activate application id "DNtp"
		display alert "Error: Handler \"clickMenuItems\"" message error_message as warning
		error number -128
	end try
end clickMenuItems

on replaceColumnNames(thisItem)
	try
		if thisItem is in theDifferentNames then
			if thisItem = "Fällig" then
				set thisItem_replaced to my replace_String(thisItem, "Fällig", "Fälligkeitsdatum")
			else if thisItem = "Hinzugefügt" then
				set thisItem_replaced to my replace_String(thisItem, "Hinzugefügt", "Hinzufügungsdatum")
			else if thisItem = "Erstellt" then
				set thisItem_replaced to my replace_String(thisItem, "Erstellt", "Erstellungsdatum")
			else if thisItem = "Geändert" then
				set thisItem_replaced to my replace_String(thisItem, "Geändert", "Änderungsdatum")
			else if thisItem = "Geöffnet" then
				set thisItem_replaced to my replace_String(thisItem, "Geöffnet", "Öffnungsdatum")
			else if thisItem = "Wörter" then
				set thisItem_replaced to my replace_String(thisItem, "Wörter", "Wortanzahl")
			else if thisItem = "Buchstaben" then
				set thisItem_replaced to my replace_String(thisItem, "Buchstaben", "Buchstabenanzahl")
			end if
			return thisItem_replaced
		else
			return thisItem
		end if
	on error error_message number error_number
		activate application id "DNtp"
		display alert "Error: Handler \"replaceColumnNames\"" message error_message as warning
		error number -128
	end try
end replaceColumnNames

on sort_list(theList)
	considering numeric strings
		set theIndexList to {}
		set theSortedList to {}
		repeat (length of theList) times
			set theLowItem to ""
			repeat with a from 1 to (length of theList)
				if a is not in theIndexList then
					set theCurrentItem to item a of theList as text
					if theLowItem is "" then
						set theLowItem to theCurrentItem
						set theLowItemIndex to a
					else if theCurrentItem comes before theLowItem then
						set theLowItem to theCurrentItem
						set theLowItemIndex to a
					end if
				end if
			end repeat
			set end of theSortedList to theLowItem
			set end of theIndexList to theLowItemIndex
		end repeat
	end considering
	return theSortedList
end sort_list

on replace_String(theText, oldString, newString)
	local ASTID, theText, oldString, newString, lst
	set ASTID to AppleScript's text item delimiters
	try
		considering case
			set AppleScript's text item delimiters to oldString
			set lst to every text item of theText
			set AppleScript's text item delimiters to newString
			set theText to lst as string
		end considering
		set AppleScript's text item delimiters to ASTID
		return theText
	on error eMsg number eNum
		set AppleScript's text item delimiters to ASTID
		error "Can't replaceString: " & eMsg number eNum
	end try
end replace_String

2 Likes

Thanks! I’ll give this a try! Much appreciated!

I’ve tried the script, but it seems to fall over after selecting columns… looking at it, once the window with the columns pops up to choose, that’s when the script tells system events to click the menus (view, columns) etc - BUT… I think it doesn’t activate the Devonthink window again… so when it brings up the devonthink columns menu, they’re all greyed out, because the devonthink window isn’t active… Not sure why?

UI scripting is not suggested as it’s a fragile and unreliable mechanism.

Strange, it’s working fine over here, as a toolbar script and also when run from Script Debugger.

Not sure I understand what you’re describing.

DEVONthink never looses focus, there’s no other app activated. System Events is used but it tells process “DEVONthink” to click etc., System Events itself is not activated.

How do you run the script? Maybe a screenshot could help understanding what’s happening.

I really don’t want to use it, unfortunately changing columns in DEVONthink is a pain, so

And there’s currently simply no better way than UI scripting because DEVONthink doesn’t use unique menu names which makes it impossible to use Keyboard Maestro to alter columns.

Of course the best solution would be if DEVONthink had some kind of window in which users can:

  • de/select multiple columns in one go.

I don’t remember where I saw this but it’s definitely possible to make this a very user friendly task. Currently it’s unfortunately really a pain …

Feature request: Please add a window in which we can de/select multiple columns.

There already is a panel at the bottom of the View > Columns menu and the contextual menu for the headers. However it is a global panel, not for setting columns on a per-database basis.

That being said, each database has it own set of columns, do you can set it on a group in a database and the columns should be preserved for that database.

And there’s currently simply no better way than UI scripting because DEVONthink doesn’t use unique menu names which makes it impossible to use Keyboard Maestro to alter columns.

And there are also situations for which using a faulty, unreliable, or fragile mechanism still isn’t an optimal choice. Sometimes you just have to accept a situation can’t be reliably automated.
You should look into the work of Rube Goldberg. :smirk:

That’s the problem. I often need to change columns depending on the current group. It’s unnecessary complicated, one has to do each step twice because there’s no window or something like that that would stay open.

Click to open,
click to choose.
Click to open,
click to choose.
Click to open,
click to choose.
Click to open,
click to choose.

From a user’s perspective that’s not how it should be.

2 Likes

Why are you using so many different column configurations?

@cgrunenberg would have to assess this. Perhaps we could just leave the columns contextual menu open until you click away (like a popover). However this will not apply individual sets to specific groups in the same database.

I basically start off with an item selected in the window, and run the script from the scripts menu…

It pops up the window for me to select columns, I click ok - but then when it automates the menu clicks, at that very point, my DEVONthink window seems to have lost focus so the columns menu is all greyed out and nothing happens… I have to manually click in the window at that point for the script to continue then it returns the error…

I’ll do a screen recording shortly so you can see what happens…

Because I use DEVONthink for many different things…

I use it for keeping evidence of copyright infringements of my work, I’m also using it to keep my research for my degree projects, where I’m citing images, websites, books etc.

I have many different needs depending on which projects I’m working on. Sometimes I just want to view a small amount of info, sometimes I need a broader view of the metadata - depending on my task and what material I’m viewing.

J

1 Like

I’ve made a screen recording to show what happens when I run the script - if you look very carefully, you’ll see that right before the window pops up for me to choose columns, the Devonthink window loses focus… when I click ok on the dialogue, the devonthink window doesn’t regain focus, so the menus are still greyed out…

I totally agree that the easier it is to switch to different column configurations the better

There are lots of use cases but they can be summed up easily: Custom Metadata

Custom Metadata is a wonderful feature, but our hands are then tied if it is harder to make use of it

In many situations it is far easier to have custom metadata in column form than only in the inspector - but there is only so much screen real estate available, plus certain custom metadata only applies to a particular database or to a particular group(s)

2 Likes

Thanks for the recording! Unfortunately I couldn’t find what might be the cause.

Over here (using a window setup like in your recording and triggering the script via menu bar) the DEVONthink window of course looses focus but gets it again after the choose from list window is closed. No idea what might be the difference.

Exactly this

and this

:slight_smile:

This and/or using unambiguous menu names would help a lot, I think.

2 Likes

My two cents:
In many of the professional video editing software packages, metadata comes in vast quantities and variety. I’ve used almost all of them and for a wide variety of purposes.
What I would say is that AVID Media Composer (AVID MC) has the best column display paradigm. It’s a bit of an old fashioned bit of software in that it still has vestiges of the physical film metaphor that made it popular in the beginning but it’s very powerful and still the dominant editing software in the biggest sectors. In DevonThink terms, most video editing software is basically a huge database that indexes media stored on external drives.
The main AVID MC project window is a list of “bins” which are a kind of folder or container for everything you edit and import. In the bin window you can pick from a huge list of columns to display. Some are regular usage and never-empty fields like Media Start, or custom metadata that the user enters. Managing an edit frequently requires displaying different combinations of columns to track footage, find source clips, solve problems etc.
AVID MC has a settings list for “bin view” which saves the columns selected and can be named and this bin view can be made exported to other users or projects. I frequently toggle between full layouts of all the file source data for tracking sync and camera details and minimal layouts for just the pertinent creative details like scene, take, size, etc.
DevonThink is one of the few pieces of software I’ve come across where I could really use a “saved bin view”. It feels like the more powerful and all encompassing my data in DT gets the more I need to have different ways to look at it, even within the same database.
/My 2 cents :smirk::

I think that was 4.5 cents :thinking:
:stuck_out_tongue:

2 Likes