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