AppleScript to set thumbnail of group to same as parent group?

I like to set my group icons in DEVONthink to colorful custom icons. Copy-pasting icons using the inspector has become tedious, so I wanted to try write a script to set the icon of a selected group to that of its parent. But the code that I thought would work,

tell application id "DNtp"
	set rec to (item 1 of (selection as list))
	set parentRec to (item 1 of (parent of rec))
	set parentThumb to get thumbnail of parentRec
	set thumbnail of rec to parentThumb
end tell

does not: it produces an error along the lines of

DEVONthink 3 got an error: Can’t make «data ***89504E470D0A1A....6082» into type anything.

Does anyone know how I can resolve this error and make the script work?

@cgrunenberg would probably know about that. I stumbled about a similar issue some time ago with JavaScript: the data returned by reading the Thumbnail property seems to be not quite what setting the same property requires.

If a record got no thumbnail then

is undefined, i.e. there’s no (direct) result that could be used.

But we can test whether there’s a thumbnail by using a try block.

-- Set child groups's thumbnails to selected group's thumbnail

tell application id "DNtp"
	try
		set theRecords to selected records
		
		repeat with thisRecord in theRecords
			set thisRecord_Type to (type of thisRecord) as string
			if thisRecord_Type is in {"group", "«constant ****DTgr»"} then
				
				try
					-- test whether this selected group got a thumbnail
					set thisRecord_Thumbnail to thumbnail of thisRecord as anything
					
					-- set all child groups' thumbnails to this selected group's thumbnail
					set (thumbnail of children of thisRecord whose type = group) to thumbnail of thisRecord
					
				on error
					-- do something else, e.g. reset child groups' thumbnails
					
					set thisRecord_ChildGroups to (children of thisRecord whose type = group)
					repeat with thisChildGroup in thisRecord_ChildGroups
						delete thumbnail of thisChildGroup
					end repeat
				end try
				
			end if
		end repeat
		
	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

This might also be interesting

If you’d like to colorize your groups (or any other record) you could try Script: Colorize DEVONthink Icons.

1 Like

The error message seems to indicate that in this case there was a thumbnail, I think.

2 Likes

Maybe. However it’s only possible to set a record’s thumbnail to another record’s thumbnail directly (see my script), i.e. without storing the thumbnail in a variable.

1 Like

Ahh, yes, if there’s data then there’s probably a thumbnail :slight_smile:

Yuck. I’d overlooked that in your script. The scripting architecture probably does something “clever” when reading the property.
So basically, this

(() => {
  const app = Application("DEVONthink 3");
  const toRec = app.selectedRecords()[0];
  const fromRec = app.getRecordWithUuid('6DB1D86E-C836-446B-9D00-6AEF4E36C648');
  toRec.thumbnail = fromRec.thumbnail();
})()

should set the thumbnail of toRec to the one of fromRec? Which it doesn’t do here :frowning:

Edit: Well, the AppleScript equivalent of this script works just as expected. So I guess this is another case of the JS bridge (or whatever it is) not quite behaving as it should, @cgrunenberg?

@pete31 and @chrillek thank you for your efforts on this.

I’m sorry it wasn’t obvious (and I didn’t explicitly mention) that I was careful to test a case where there was a custom icon on the parent group.

I had seen that before (fantastic work, btw) as well as the related threads (e.g., Can we color the project icon? from 2019), but I’m just not a fan of DEVONthink’s icons, so have been replacing them with custom icons rather than just coloring them.

Ahhhhh … that’s the part that didn’t occur to me [1].

Yes, indeed. If I change the code to

tell application id "DNtp"
	set rec to (item 1 of (selection as list))
	set parentRec to (item 1 of (parent of rec))
	set thumbnail of rec to thumbnail of parentRec
end tell

it works. :confounded:

@pete31 thank for the code that checks for the existence of the thumbnail above. That will be a good addition to what I’m doing.

[1] I mean, come on. The value can’t be stored in a variable, but the code works if you assign it directly? What? What? :face_with_symbols_over_mouth:

1 Like

The joys of AppleScript and its sometimes unpredictable conversions/coercions.

4 Likes

In case it’s useful for anyone else, here’s the script as it currently stands. This tests that the selection is a group, and when looking at parents, uses the first one that is a group. (The latter is a precaution against the selection’s list of parents containing tag groups. Getting tag groups seems to be possible in other scripts I’ve written, so while I don’t have an actual example of this script running into that case, it seems reasonable to take precautions.)

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

tell application id "DNtp"
	try
		repeat with rec in (selected records)
			set recType to (type of rec) as string
			if recType is in {"group", "«constant ****DTgr»"} then
				my setIconToParentIcon(rec)
			else
				set recName to name of rec
				display notification ¬
					"Ignoring item because it's not a group: " & recName
			end if
		end repeat
	on error msg number err
		if err is not -128 then ¬
			display alert "DEVONthink" message msg as warning
	end try
end tell

on setIconToParentIcon(rec)
	-- Items can have multiple parents.	 Look for the first one
	-- that is a group, and use it.
	tell application id "DNtp"
		repeat with parentRec in (parent of rec)
			set recType to (type of parentRec) as string
			if recType is in {"group", "«constant ****DTgr»"} then
				-- Note: *must* set directly; can't use intermediate variable.
				set thumbnail of rec to thumbnail of parentRec
				return
			end if
		end repeat
	end tell
end setIconToParentIcon

Here’s the repository directory where I’m keeping the latest version of this code: devonthink-hacks/set-icon-to-parent-icon at main · mhucka/devonthink-hacks · GitHub

1 Like

You could perhaps use the recently introduced location group property instead of looping over all parents.

1 Like

And that’s only AppleScript: With JavaScript, one can’t even set the thumbnail of one record directly from the thumbnail of another one. Which leads me to the question: In what format is the thumbnail stored, and why do I see a string when I look at the thumbnail property?

You’re right; I completely forgot about that. Thanks for mentioning it!

Raw binary data (e.g. JPEG, PNG or TIFF data) and that’s at least what AppleScript returns:

Bildschirmfoto 2022-01-24 um 09.58.56

I see the same thing, but that doesn’t look very binary to me. In fact, it seems to be a hexadecimal representation (at least after ‘****’). I’ll see if I can figure that out.

Edit: Yes, that’s a hexadecimal representation of the binary data. The string “504E47” above corresponds to “PNG”, and one can actually use Perl to transform this beast to a PNG (and possibly other tools, too).

It’s a string representation of the data and its AppleEvent code created by the Script Editor.app for logging. It’s definitely not a string unless you use JXA :grin:

Added a workaround to the next release so that the string used by JXA is converted back to the expected data.

3 Likes