Vision File Explorer

The Reporting module has two components, File explorer and PDF Viewer, which are very useful also when you don’t use reporting.
The customer wants to have the ability to display various documentation (.docx, .xlsx, .pdf, .txt) to the operators inside the Vision client on every production line. But they don’t need the Reporting module, because they have their own solution in place.
The File Explorer component from the Reporting module is ideal for this situation (as we already have a license for Web Browser).
When you use the File Explorer on the Vision window, the component displays “UNLICENSED Ignition REPORTING PLUGIN” overlay over the component.
I know that PDF Viewer you can use without a license for the Reporting module, but not the File Explorer.

I’ve been searching the forum for the ‘alternative’ and found some suggestions to use the tree view component.
I’m wondering how others solved this and if anyone can show an example of using Tree View like File Explorer. Pretty please…

Check out glob and os modules for navigating the file system. I was doing something similar a while back (this was in a Windows environment) and came up with the following, which should get you started. I’m sure there are other ways of doing this, but I had plenty of other things to do and moved on after getting this to work :slightly_smiling_face:

I created 2 custom properties on the root container named pdfRootFolder, and selectedFilePath. The selectedFilePath has this binding, which I then bound the File Path of the PDF Viewer to.

	{Root Container.Tree View.selectedItem} > -1,
	{Root Container.pdfRootFolder} + '\\' + {Root Container.Tree View.selectedPath},

I used a button to refresh the items in the tree view with the following code on actionPerformed.

import glob, os
pdfDirectory = event.source.parent.pdfRootFolder
pdfFiles = glob.glob('*.pdf')

headers = ['path','text','icon','background','foreground','tooltip','border','selectedText','selectedIcon','selectedBackground','selectedForeground','selectedTooltip','selectedBorder']
data = [] 
for file in pdfFiles:
	path = ''
	text = file
	icon = ''
	background = 'color(255,255,255,255)'
	foreground = 'color(46,46,46,255)'
	tooltip = ''
	border = None
	selectedText = ''
	selectedIcon = ''
	selectedBackground = 'color(71,169,230,255)'
	selectedForeground = 'color(255,255,255,255)'
	selectedTooltip = '',
	selectedBorder = None

event.source.parent.getComponent('Tree View').data = system.dataset.toDataSet(headers, data)

Hopefully that points you in the right direction.

1 Like

This is what I ended up with:

In the ‘Choose Folder’ button ‘ActionPerformed’ event I have:

from javax.swing import JFileChooser

chooser = JFileChooser(event.source.parent.getComponent('txtPot').text)
chooser.setDialogTitle("Select Folder")
if chooser.showOpenDialog(None) == JFileChooser.APPROVE_OPTION:
	event.source.parent.getComponent('txtPot').text = str(chooser.getSelectedFile())

In the ‘txtFolder’ propertyChange event I have:

if event.propertyName == 'text':
	treeView = event.source.parent.getComponent('Tree View')
	headers = system.dataset.getColumnHeaders(
	rows = [] = system.dataset.toDataSet(headers, rows)	#Emptying treeView
	rootPath = event.source.parent.getComponent('txtPot').text
	lblLoading = event.source.parent.getComponent('lblLoading')
	lblLoading.visible = True
	def longProcess(treeView=treeView, headers=headers, rows=rows, rootPath=rootPath, lblLoading=lblLoading):
		import os
		for path, dirs, files in os.walk(rootPath,topdown=True):
			for f in files:
				my_suffixes = (".docx",".doc",".xlsx",".xls",".pdf",".txt")
				if f.endswith(my_suffixes):
					filename, file_extension = os.path.splitext(f)
					#print filename, file_extension
					ikona = {
						'.docx' : 'Icons/docx.png',
						'.doc' : 'Icons/docx.png',
						'.xlsx' : 'Icons/xlsx.png',
						'.xls' : 'Icons/xlsx.png',
						'.pdf' : 'Icons/pdf.png',
						'.txt' : 'Icons/txt.png'}[file_extension]
					newRow = [

		data = system.dataset.toDataSet(headers, rows) = data
		lblLoading.visible = False
	system.util.invokeAsynchronous(longProcess) #Note that this is 'longProcess' instead of 'longProcess()'

In the ‘Refresh’ button actionPerformed event I have:

izbranapot = event.source.parent.getComponent('txtPot').text
event.source.parent.getComponent('txtPot').text = ""
event.source.parent.getComponent('txtPot').text = izbranapot

And in the ‘Tree View’ mouseClicked event I have:

if event.clickCount == 2:
	fileName = event.source.selectedPath
	if event.source.selectedItem > -1:"file:///" + fileName)

In the end, it turned out just fine…
Of course, any suggestions are more than welcome. :+1:

OK, it turns out, that this solution won’t show the empty Folders (when there are no files in it).

If I write by hand into the TreeView dataset just the Path then ‘Null 1’ is shown…

But our customer wants to show these empty folders also…
Does anyone have an idea, how to do that?
EDIT: That’s what I/we need: Tree View Folder without a Node object? - #2 by Travis.Cox

Please, vote.