Label filters, how to higlight folders containing PDFs

Is it possible to make a label filter, that highlights all folders, that contain a certain file type, for instance PDFs. I've tried several approaches, like "type=folder, subclause / name *.pdf", or
"type=folder, contains *.pdf", or "type=folder, subclause *.pdf" etc., but couldn't find the right combination. And if it's possible, can the filter be activated on demand, not statically?

The idea is, to build several types of filters to highlight various contents like PDF, or dirs containing certain names, etc.

You would need to a script which provides a "does the folder contain a PDF?" column, then filter on that column.

Interesting. Unfortunately i have no clues about scripting at all. Maybe someone else interested in a function like that could help out? Thanks, Leo.

Hi abr,

I once did this for somebody around here, to select folders which contain *.iso files (edit the upper section to match other file types).
It's a button in it's current state, but maybe it is still of help to you.

<?xml version="1.0"?>
<button backcol="none" display="both" separate="yes" textcol="none">
	<label>Folder Selector</label>
	<tip>Folder Selector</tip>
	<icon1>#newcommand</icon1>
	<function type="script">
		<instruction>@script jscript</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>// Simple dialog-based search to select folders.</instruction>
		<instruction>// Folders will be selected if they contain matching files and at the same</instruction>
		<instruction>// time do not contain a subfolder (optional).</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>var defaultSearch = new SearchParams(</instruction>
		<instruction>	/*search string*/	&apos;iso&apos;,</instruction>
		<instruction>	/*search extension*/	true,</instruction>
		<instruction>	/*search stem*/		false,</instruction>
		<instruction>	/*subfolder name*/	&apos;video_ts&apos;,</instruction>
		<instruction>	/*exclude subfolder*/	true</instruction>
		<instruction>);</instruction>
		<instruction />
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function OnClick(data){</instruction>
		<instruction>	DOpus.ClearOutput();</instruction>
		<instruction>	data.func.command.ClearFiles();</instruction>
		<instruction />
		<instruction>	//get enumerator and count of selected folders or complete list of folders</instruction>
		<instruction>	var folders = GetFolders(data);</instruction>
		<instruction />
		<instruction>	//get a combination of default, last used and current dialog search params</instruction>
		<instruction>	var params = GetSearchParams(data); if (!params) return; //dialog cancelled</instruction>
		<instruction />
		<instruction>	//save current search params</instruction>
		<instruction>	SaveSearchParams(data, params);</instruction>
		<instruction />
		<instruction>	//init, open and return progress dialog</instruction>
		<instruction>	var progress = OpenProgressDialog( data, &quot;Folder Selector..&quot;, folders.count);</instruction>
		<instruction />
		<instruction>	var searchMode = params.GetSearchMode();</instruction>
		<instruction>	while (!folders.enumerator.atEnd() ) {</instruction>
		<instruction>		var folder = folders.enumerator.item(); folders.enumerator.moveNext();</instruction>
		<instruction>		dout(&quot;Folder [&quot;+folder.name+&quot;]..&quot;);</instruction>
		<instruction>		progress.SetName(folder.name);</instruction>
		<instruction>		//if subfolder to exclude is given, search subfolders before looking for matching files</instruction>
		<instruction>		if (params.excludeFolder &amp;&amp; defaultSearch.excludeFolderName!=&quot;&quot; &amp;&amp; SubFolderExists( folder.path+&quot;\\&quot;+folder.name, defaultSearch.excludeFolderName)){</instruction>
		<instruction>			dout(&quot;    Contains subfolder [&quot;+defaultSearch.excludeFolderName+&quot;], skipping folder.&quot;);</instruction>
		<instruction>			progress.StepFiles(1);</instruction>
		<instruction>			continue;</instruction>
		<instruction>		}</instruction>
		<instruction>		if (exists = FileExists( folder.path+&quot;\\&quot;+folder.name, params.searchMe, searchMode)){</instruction>
		<instruction>			dout(&quot;    Contains at least one matching file.&quot;);</instruction>
		<instruction>			data.func.command.AddFile(folder);</instruction>
		<instruction>		}</instruction>
		<instruction>		progress.StepFiles(1);</instruction>
		<instruction>    }</instruction>
		<instruction />
		<instruction>	data.func.command.RunCommand(&quot;Select FROMSCRIPT DESELECTNOMATCH MAKEVISIBLE&quot;);</instruction>
		<instruction>	progress.Hide();</instruction>
		<instruction>	DOMsgBox(&quot;ISO-FolderSelector&quot;,&quot;Found &quot;+data.func.command.files.count+&quot; folder(s) matching your search.&quot;,&quot;Ok&quot;);</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function ReadFolder( path, recurse, exception){</instruction>
		<instruction>	if (recurse == undefined) recurse=false;</instruction>
		<instruction>	if (exception == undefined) exception=true;</instruction>
		<instruction>	var fEnum = DOpus.FSUtil.ReadDir( path, true);</instruction>
		<instruction>	if (fEnum.error!=0){</instruction>
		<instruction>		var error = &quot;ReadFolder(): Error reading folder [&quot;+name+&quot;], code [&quot;+fEnum.error+&quot;].&quot;;</instruction>
		<instruction>		if (exception) throw error;</instruction>
		<instruction>		dout(error);</instruction>
		<instruction>	}</instruction>
		<instruction>	return fEnum;</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function SubFolderExists( folderPath, subFolderName){</instruction>
		<instruction>	subFolderName = subFolderName.toLowerCase();</instruction>
		<instruction>	var fEnum = ReadFolder( folderPath, true, true);</instruction>
		<instruction>	while (!fEnum.complete &amp;&amp; (fItem = fEnum.Next()))</instruction>
		<instruction>		if (fItem.is_dir &amp;&amp; (fItem.name.toLowerCase() == subFolderName))</instruction>
		<instruction>			return true;</instruction>
		<instruction>	return false;</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function FileExists( folderPath, searchMe, searchMode){</instruction>
		<instruction>	if (searchMode == undefined) searchMode=&apos;full&apos;;</instruction>
		<instruction>	searchMe = searchMe.toLowerCase();</instruction>
		<instruction>	if (searchMode==&apos;ext&apos;) searchMe=searchMe.replace(&apos;\.&apos;,&apos;&apos;);</instruction>
		<instruction>	var fEnum = ReadFolder( folderPath, true, true);</instruction>
		<instruction>	while (!fEnum.complete &amp;&amp; (fItem = fEnum.Next())){</instruction>
		<instruction>		if (fItem.is_dir) continue;</instruction>
		<instruction>		switch (searchMode){</instruction>
		<instruction>			case &apos;ext&apos;:</instruction>
		<instruction>				if (fItem.ext.toLowerCase()==&quot;.&quot;+searchMe)</instruction>
		<instruction>					return true;</instruction>
		<instruction>			break;</instruction>
		<instruction>			case &apos;stem&apos;:</instruction>
		<instruction>				if (fItem.name_stem.toLowerCase().indexOf(searchMe)!=-1)</instruction>
		<instruction>					return true;</instruction>
		<instruction>			break;</instruction>
		<instruction>			case &apos;full&apos;:</instruction>
		<instruction>			default:</instruction>
		<instruction>				if (fItem.name.toLowerCase().indexOf(searchMe)!=-1)</instruction>
		<instruction>					return true;</instruction>
		<instruction>			break;</instruction>
		<instruction>		}</instruction>
		<instruction>	}</instruction>
		<instruction>	return false;</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function GetFolders(data){</instruction>
		<instruction>	if (data.func.sourcetab.selected_dirs.count)</instruction>
		<instruction>		var dirs = data.func.sourcetab.selected_dirs;</instruction>
		<instruction>	else</instruction>
		<instruction>		var dirs = data.func.sourcetab.dirs;</instruction>
		<instruction>	return { enumerator:new Enumerator(dirs), count:dirs.count};</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function DoDialog( params){</instruction>
		<instruction>	var dlg = DOpus.Dlg</instruction>
		<instruction>	dlg.window = DOpus.Listers(0);</instruction>
		<instruction>	dlg.message = &quot;Please enter string/extension to search for:\n &quot;;</instruction>
		<instruction>	dlg.title = &quot;Folder Selector..&quot;;</instruction>
		<instruction>	dlg.buttons = &quot;OK|Cancel&quot;;</instruction>
		<instruction>	dlg.icon = &quot;question&quot;;</instruction>
		<instruction />
		<instruction>	dlg.max = 128; //enable text field</instruction>
		<instruction>	dlg[&apos;default&apos;] = params.searchMe;</instruction>
		<instruction />
		<instruction>	dlg.options(0).label = &quot;search extension&quot;;</instruction>
		<instruction>	dlg.options(0).state = params.searchExtension;</instruction>
		<instruction />
		<instruction>	dlg.options(1).label = &quot;search stem&quot;;</instruction>
		<instruction>	dlg.options(1).state = params.searchStem;</instruction>
		<instruction />
		<instruction>	if (defaultSearch.excludeFolderName!=&quot;&quot;){</instruction>
		<instruction>		dlg.options(2).label = &quot;may not contain folder (&quot;+defaultSearch.excludeFolderName+&quot;)&quot;;</instruction>
		<instruction>		dlg.options(2).state = params.excludeFolder;</instruction>
		<instruction>	}</instruction>
		<instruction>	return dlg;</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function OpenProgressDialog( data, title, numFiles){</instruction>
		<instruction>	var progress = data.func.command.progress;</instruction>
		<instruction>	progress.delay = false;</instruction>
		<instruction>	progress.abort = true;</instruction>
		<instruction>	progress.Init(data.func.sourcetab, title);</instruction>
		<instruction>	progress.AddFiles(numFiles);</instruction>
		<instruction>	progress.Show();</instruction>
		<instruction>	return progress;</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function SearchParams(searchMe, searchExtension, searchStem, excludeFolderName, excludeFolder){</instruction>
		<instruction>	if (searchMe == undefined) searchMe=&apos;iso&apos;;</instruction>
		<instruction>	if (searchExtension == undefined) searchExtension=true;</instruction>
		<instruction>	if (searchStem == undefined) searchStem=false;</instruction>
		<instruction>	if (excludeFolderName == undefined) excludeFolderName=&quot;&quot;;</instruction>
		<instruction>	if (excludeFolder == undefined) excludeFolder=false;</instruction>
		<instruction>	this.searchMe=searchMe;</instruction>
		<instruction>	this.searchExtension=searchExtension;</instruction>
		<instruction>	this.searchStem=searchStem;</instruction>
		<instruction>	this.excludeFolderName=excludeFolderName;</instruction>
		<instruction>	this.excludeFolder=excludeFolder;</instruction>
		<instruction>	this.GetSearchMode = function(){</instruction>
		<instruction>		var searchMode=&apos;full&apos;;</instruction>
		<instruction>		if (this.searchExtension &amp;&amp; !this.searchStem) searchMode=&apos;ext&apos;;</instruction>
		<instruction>		if (!this.searchExtension &amp;&amp; this.searchStem) searchMode=&apos;stem&apos;;</instruction>
		<instruction>		return searchMode;</instruction>
		<instruction>	}</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function GetSearchParamsFromDialog(dlg){</instruction>
		<instruction>	var dlgSearchParams = new SearchParams();</instruction>
		<instruction>	dlgSearchParams.searchMe = dlg.input;</instruction>
		<instruction>	dlgSearchParams.searchExtension = dlg.options(0).state;</instruction>
		<instruction>	dlgSearchParams.searchStem = dlg.options(1).state;</instruction>
		<instruction>	if (defaultSearch.excludeFolderName){ //exclude subfolder name given, so option is present to exclude it</instruction>
		<instruction>		dlgSearchParams.excludeFolder = dlg.options(2).state;</instruction>
		<instruction>	}</instruction>
		<instruction>	return dlgSearchParams;</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function ValidateSearchParams(params){</instruction>
		<instruction>	if (!params)</instruction>
		<instruction>		return false;</instruction>
		<instruction>	if (!params.searchExtension &amp;&amp; !params.searchStem){</instruction>
		<instruction>			DOMsgBox(&quot;Folder Selector..&quot;, &quot;You need to select stem or extension or both!&quot;, &quot;Oops!&quot;);</instruction>
		<instruction>			return false;</instruction>
		<instruction>	}</instruction>
		<instruction>	if (params.searchMe==&quot;&quot;){</instruction>
		<instruction>			DOMsgBox(&quot;Folder Selector..&quot;, &quot;You forgot to enter a string to search for!&quot;, &quot;Oops!&quot;);</instruction>
		<instruction>			return false;</instruction>
		<instruction>	}</instruction>
		<instruction>	return true;</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function GetDefaultOrLastSearchParams(data){</instruction>
		<instruction>	var search = defaultSearch;</instruction>
		<instruction>	if (data.func.sourcetab.vars.exists(&quot;lastSearch&quot;))</instruction>
		<instruction>		search = Vector2Search(data.func.sourcetab.vars.get(&quot;lastSearch&quot;));</instruction>
		<instruction>	return search;</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function GetCombinedSearchParams(data){</instruction>
		<instruction>	var userSearchParams = GetDefaultOrLastSearchParams(data);</instruction>
		<instruction>	var dlg = DoDialog(userSearchParams);</instruction>
		<instruction>	var result=dlg.Show();</instruction>
		<instruction>	if (result==0){</instruction>
		<instruction>		dout(&quot;Folder Selector dialog cancelled.&quot;);</instruction>
		<instruction>		return null;</instruction>
		<instruction>	}</instruction>
		<instruction>	return GetSearchParamsFromDialog(dlg);</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function GetSearchParams(data){</instruction>
		<instruction>	var params = null;</instruction>
		<instruction>	while (!ValidateSearchParams(params)){</instruction>
		<instruction>		params = GetCombinedSearchParams(data);</instruction>
		<instruction>		if (!params)</instruction>
		<instruction>			return false; //dialog canceled</instruction>
		<instruction>	}</instruction>
		<instruction>	return params;</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function SaveSearchParams(data, params){</instruction>
		<instruction>	data.func.sourcetab.vars.set(&quot;lastSearch&quot;, Search2Vector(params));</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function Search2Vector( search){</instruction>
		<instruction>	var vector = DOpus.NewVector();</instruction>
		<instruction>	vector.push_back(search.searchMe);</instruction>
		<instruction>	vector.push_back(search.searchExtension);</instruction>
		<instruction>	vector.push_back(search.searchStem);</instruction>
		<instruction>	vector.push_back(search.excludeFolderName);</instruction>
		<instruction>	vector.push_back(search.excludeFolder);</instruction>
		<instruction>	return vector;</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function Vector2Search( vector){</instruction>
		<instruction>	return new SearchParams( vector(0), vector(1), vector(2), vector(3), vector(4));</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function DOMsgBox(title,message,buttons){</instruction>
		<instruction>	var dlg = DOpus.Dlg</instruction>
		<instruction>	dlg.window = DOpus.Listers(0);</instruction>
		<instruction>	dlg.message = message;</instruction>
		<instruction>	dlg.title = title;</instruction>
		<instruction>	dlg.buttons = buttons;</instruction>
		<instruction>	var result = dlg.Show();</instruction>
		<instruction>	dout(title+&quot; - &quot;+message+&quot; - &quot;+buttons+&quot; -&gt; &quot;+result);</instruction>
		<instruction>	return result;</instruction>
		<instruction>}</instruction>
		<instruction>///////////////////////////////////////////////////////////////////////////////</instruction>
		<instruction>function dout(text){</instruction>
		<instruction>	DOpus.Output(text);</instruction>
		<instruction>}</instruction>
	</function>
</button>

Technically, there also is this command, it includes all necessary parts to put something together that would build a column like Leo suggested.

Combined with the general approach of the following column set, which enables easy adding, configuring and removing of columns, this would result in some nice addin.

So, who does it? o)

It works all well, does exactly what i was looking for. A great to have in my tool collection. Thanks a lot, tbone! :thumbsup:

My pleasure! o)