Script: Create or change smart group(s)

In case you tried to run the script you’ve found that it doesn’t work as expected in DEVONthink 3.6.

There’s a problem with creating Smart Groups via AppleScript, see Are Smart Groups in DEVONthink 3.6 broken?.

Updated the script with a workaround.

-- Create or change smart group(s)

property theMetaGroupName : "Smart"
property theSmartGroupName : "_Subsets"
property revealInCurrentWindow : true
property openInCurrentWindow : false
property openInNewWindow : false
property openInNewWindows : false
property theHelpFileOrRefURL : ((POSIX path of (path to application id "DNtp") as text) & "/Contents/Resources/DEVONthink.help/Contents/Resources/pgs/appendix-searchprefixes.html") as string
property theIconPath : (((path to application id "DNtp") & "Contents:Resources:DEVONthink 3.icns:") as string) as alias
property theTemplateThumbnailUUID : ""

tell application id "DNtp"
	try
		set theSearchGroups to selection of viewer window 1
		
		if (count theSearchGroups) = 1 then
			set theType to type of item 1 of theSearchGroups as string
			if (theType = "smart group" or theType = "«constant ****DTsg»") then
				my updateSmartGroup(item 1 of theSearchGroups)
				return
			end if
		end if
		
		set scopeDatabase to false
		set theDatabase to current database
		if theSearchGroups = {} then
			set theSearchGroups to root of window 1
			try
				set theSearchGroups to theSearchGroups as list
			on error
				display alert "Hoppla!" buttons {"OK"} default button 1 message "Mehrfachauswahl in Seitenleiste nicht möglich." as informational
				return
			end try
			set scopeDatabase to true
			set theType to type of item 1 of theSearchGroups as string
			if theType = "group" or theType = "«constant ****DTgr»" then set scopeDatabase to false
			if uuid of item 1 of theSearchGroups = (uuid of theDatabase) then set scopeDatabase to true
		else
			repeat with thisSearchGroup in theSearchGroups
				set theType to type of thisSearchGroup as string
				if theType = "group" or theType = "«constant ****DTgr»" then set scopeDatabase to false
			end repeat
		end if
		
		try
			set selectedText to selected text of window 1 & "" as string
			set defaultAnswer to selectedText
			set scopeDatabase to true
			set theSearchGroups to {theDatabase}
		on error
			set defaultAnswer to ""
		end try
		set dialogButtons to {"Hilfe", "Abbrechen", "OK"}
		set theDialog to display dialog "Suche:" default answer defaultAnswer buttons dialogButtons default button 3 with title "" with icon theIconPath
		set {theButton, theQuery} to {button returned, text returned} of theDialog
		if theButton = item 1 of dialogButtons then
			do shell script "open " & quoted form of theHelpFileOrRefURL
			return
		else if theButton = item 2 of dialogButtons then
			return
		else
			if theQuery = "" then return
		end if
		
		set theMetaGroup to create location ("/" & theMetaGroupName) in theDatabase
		if theTemplateThumbnailUUID ≠ "" then set thumbnail of theMetaGroup to thumbnail of (get record with uuid theTemplateThumbnailUUID)
		
		if scopeDatabase = true then
			set theSubsetsSmartGroup to {}
			set theSmartGroups to (smart groups of theDatabase whose location is ("/" & theMetaGroupName & "/") and search predicates = theQuery)
			if theSmartGroups = {} then
				set theSmartGroup to create record with {type:smart group, search predicates:theQuery, name:theQuery, exclude from search:true} in theMetaGroup
				set search group of theSmartGroup to (item 1 of theSearchGroups)
			else
				set theSmartGroup to item 1 of theSmartGroups
			end if
		else
			if not (exists record at ("/" & theMetaGroupName & "/" & theSmartGroupName) in theDatabase) then
				set theSubsetsSmartGroup to create record with {type:smart group, search predicates:"kind:smart group", name:theSmartGroupName, exclude from search:true} in theMetaGroup
				set search group of theSubsetsSmartGroup to theDatabase
			else
				set theSubsetsSmartGroup to get record at ("/" & theMetaGroupName & "/" & theSmartGroupName) in theDatabase
			end if
			set newSmartGroups to {}
			repeat with thisSearchGroup in theSearchGroups
				set theSmartGroups to (smart groups of theDatabase whose location is (location of thisSearchGroup & name of thisSearchGroup & "/") and search predicates = theQuery)
				if theSmartGroups = {} then
					set theSmartGroup to create record with {type:smart group, search predicates:theQuery, name:theQuery & " in: " & name of thisSearchGroup} in thisSearchGroup
					set search group of theSmartGroup to thisSearchGroup
				else
					set theSmartGroup to item 1 of theSmartGroups
				end if
				set end of newSmartGroups to theSmartGroup
			end repeat
		end if
		
		if revealInCurrentWindow = true then
			if (count theSearchGroups) = 1 then
				set selection of window 1 to {theSmartGroup}
			else
				set root of window 1 to theSubsetsSmartGroup
				set selection of window 1 to newSmartGroups
			end if
		else if openInCurrentWindow = true then
			if (count theSearchGroups) = 1 then
				set root of window 1 to theSmartGroup
			else
				set root of window 1 to theSubsetsSmartGroup
				set selection of window 1 to newSmartGroups
			end if
		else if openInNewWindow = true then
			if (count theSearchGroups) = 1 then
				open window for record theSmartGroup
			else
				open window for record theSubsetsSmartGroup
				set selection of window 1 to newSmartGroups
			end if
		else if openInNewWindows = true then
			if (count theSearchGroups) = 1 then
				open window for record theSmartGroup
			else
				repeat with thisSmartGroup in newSmartGroups
					open window for record thisSmartGroup
				end repeat
			end if
		end if
		
	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 updateSmartGroup(theRecord)
	tell application id "DNtp"
		try
			set {theName, theQuery} to {name, search predicates} of theRecord
			set dialogButtons to {"Hilfe", "Abbrechen", "OK"}
			set theDialog to display dialog theQuery default answer theQuery buttons dialogButtons default button 3 with title theName with icon theIconPath
			set {theButton, newQuery} to {button returned, text returned} of theDialog
			if theButton = item 1 of dialogButtons then
				do shell script "open " & quoted form of theHelpFileOrRefURL
				return
			else if theButton = item 2 of dialogButtons then
				return
			else
				considering case
					if newQuery = theQuery or newQuery = "" then return
				end considering
				set search predicates of theRecord to newQuery
				set dialogButtons to {"Abbrechen", "OK"}
				set theDialog to display dialog "Name:" default answer newQuery buttons dialogButtons default button 2 with title theName with icon theIconPath
				set {theButton, newName} to {button returned, text returned} of theDialog
				if theButton = item 1 of dialogButtons then
					return
				else if theButton = item 2 of dialogButtons then
					if newName = "" then return
					if location of theRecord = ("/" & theMetaGroupName & "/") then
						set name of theRecord to newName
					else
						set name of theRecord to newName & " in: " & name of parent 1 of theRecord
					end if
				end if
			end if
			
		on error error_message number error_number
			error number -128
		end try
	end tell
end updateSmartGroup
1 Like