﻿// (c) 2023 Cris
// This is a script for Directory Opus.
// See https://www.gpsoft.com.au/DScripts/redirect.asp?page=scripts for development information.
// Called by Directory Opus to initialize the script

var script_name = "Columns Viewer";
var script_version = "1.0.2";
var script_copyright = "(c) 2023 Christian Arellano García";
var script_desc = "GUI for view/copy values for almost all available columns";

function OnInit(initData) {
	initData.name = script_name;
	initData.version = script_version;
	initData.copyright = script_copyright;
	initData.url = "https://resource.dopus.com/t/columns-viewer/47072/12";
	initData.desc = script_desc;
	initData.default_enable = true;
	initData.min_version = "13.0.46";
	initData.config_desc = DOpus.Create.Map();
	initData.config.debug = DOpus.Create.Vector(1, 'OFF', 'WARNING', 'ALL');
	initData.config_desc('debug') = DOpus.strings.Get('debug');
	initData.config.ignored_script_columns = DOpus.Create.Vector();
	initData.config_desc('ignored_script_columns') = DOpus.strings.Get('ignored_script_columns');
	initData.config.sc_cols_custom_names = DOpus.Create.Vector('"ColumnExifTool.js.txt": "ExifTool"');
	initData.config_desc('sc_cols_custom_names') = DOpus.strings.Get('sc_cols_custom_names');
	initData.config.size_mode = DOpus.Create.Vector(0, 'auto', 'last used');
	initData.config_desc('size_mode') = DOpus.strings.Get('size_mode');
}
// Called to add commands to Opus
function OnAddCommands(addCmdData) {
	var cmd = addCmdData.AddCommand();
	cmd.name = "ColumnsViewer";
	cmd.method = "OnColumnsViewer";
	cmd.desc = script_desc;
	cmd.label = script_name;
	cmd.template = "FILE";
	cmd.hide = false;
	cmd.icon = "script";
}

function OnColumnsViewer(scriptCmdData) {
	if (Script.config.debug) DOpus.ClearOutput();

	// ======= GET FILE ARG ==========================================
	// If no provided, use first selected
	Log(2, "INFO    => cmdline     :" + scriptCmdData.cmdline);
	var tab = scriptCmdData.func.sourcetab;
	var file = (scriptCmdData.func.args.got_arg.file) ? scriptCmdData.func.args.file : ((tab && tab.selected.count > 0) ? tab.selected(0) : false);
	Log(2, "INFO    => file        :" + file + '(' + DOpus.TypeOf(file) + ')');
	if (!file || !DOpus.FSUtil.Exists(file)) {
		Log(3, "ERROR   => Can't continue without a file!");
		DOpus.dlg.Request(DOpus.strings.Get('alert_no_file'), "OK", script_name);
		return;
	}
	if (DOpus.TypeOf(file) != 'object.Item') file = DOpus.FSUtil.GetItem(file);
	if (file.metadata == 'none') {
		DOpus.dlg.Request(file + 'has no metadata', 'OK', script_name);
		return;
	}
	var sel_items, clip, update_sw;
	var str_tools = DOpus.Create.StringTools();
	var old_editvalue = '';
	var dlg = DOpus.Dlg;
	dlg.title = script_name + " v" + script_version + " - " + file;
	dlg.template = "main";
	dlg.detach = true;
	dlg.Create();
	// ======= GET COLUMN'S VALUES ==========================================
	var columns = BuildColumnsList(file, str_tools);

	// ======= FILL COMBOBOX CATEGORIES ==========================================
	dlg.Control("Categories").AddItem(str_tools.LanguageStr(2135));
	for (var e = new Enumerator(columns); !e.atEnd(); e.moveNext())
		dlg.Control("Categories").AddItem(e.item());
	dlg.Control("Categories").value = 0;

	// ======= GET TRANSLATED STRINGS FOR UI ==========================================
	// dlg.Control('btnClear').label = str_tools.LanguageStr(1042);
	dlg.Control('btnRefresh').label = str_tools.LanguageStr(487) + ' (F5)';
	dlg.Control('btnCopy').label = str_tools.LanguageStr('CopySelection');
	dlg.Control('btnClose').label = str_tools.LanguageStr(474);
	var keyword_str = str_tools.LanguageStr(310);
	var title_str = str_tools.LanguageStr(457);
	var header_str = str_tools.LanguageStr(5599);
	var type_str = str_tools.LanguageStr(312);

	var value_str = str_tools.LanguageStr(6501);
	var copy_str = str_tools.LanguageStr(646);

	dlg.Control('columns_list').columns.GetColumnAt(0).name = keyword_str; //name or keyword
	dlg.Control('columns_list').columns.GetColumnAt(1).name = title_str; //Label
	dlg.Control('columns_list').columns.GetColumnAt(2).name = header_str; // Header
	dlg.Control('columns_list').columns.GetColumnAt(3).name = type_str; //Type
	dlg.Control('columns_list').columns.GetColumnAt(4).name = value_str; //Value

	// ======= SET HOTKEYS ==========================================
	dlg.AddHotkey("refresh_key", "F5");
	dlg.AddHotkey("copy_key", "ctrl+c");
	// dlg.AddHotkey("close_key", "Esc");
	// ======= FINAL ARRANGEMENTS ==========================================
	//set Find icon from current icon set
	dlg.Control('search_icon').label = '#0:find';
	updateList(dlg, columns, str_tools);
	//resize the dialog based on user choice
	sizeDlg(dlg, Script.config.size_mode);
	sel_items = DOpus.Create.Vector();
	dlg.Show();

	while (true) {
		var msg = dlg.GetMsg();
		if (!msg.result) break;

		if (msg.event == "selchange" && msg.Control == "columns_list") {
			sel_items = dlg.Control("columns_list").value;
			Log(2, "INFO    => Selected items: " + sel_items.count);
			dlg.Control('btnCopy').visible = (sel_items.count > 0);
		}
		if (dlg.Control("columns_list").focus && msg.event == "rclick" && sel_items.count > 0) {
			var dlgMenu = DOpus.Dlg();
			dlgMenu.choices = DOpus.Create.Vector(copy_str + ' ' + keyword_str, copy_str + ' ' + value_str, copy_str + ' ' + keyword_str + '+' + value_str, copy_str + ' ' + title_str + '+' + value_str, copy_str + ' ' + header_str + '+' + value_str, str_tools.LanguageStr('CopyAll'));
			dlgMenu.menu = DOpus.Create.Vector(1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
			var menuReturn = dlgMenu.Show();
			copyToClip(sel_items, menuReturn);
		}
		//Copy all the values from selected items using Ctrl+C 
		if (dlg.Control("columns_list").focus && msg.event == "hotkey" && msg.Control === "copy_key" && sel_items.count > 0)
			copyToClip(sel_items, 6);

		if (msg.event == "click" && dlg.Control("btnCopy").focus)
			copyToClip(sel_items, 6);

		if ((msg.event == "click" && dlg.Control("btnRefresh").focus) || (msg.event == "hotkey" && msg.Control == "refresh_key")) {
			columns = BuildColumnsList(file, str_tools);
			updateList(dlg, columns, str_tools);
		}
		if (msg.event == "click" && dlg.Control("btnClear").focus) {
			dlg.Control("editFilter").value = "";
			updateList(dlg, columns, str_tools);
		}
		if (msg.event == "selchange" && msg.Control == "Categories")
			updateList(dlg, columns, str_tools);

		if (msg.event == "editchange" && msg.Control == "editFilter") {
			while (old_editvalue !== dlg.Control("editFilter").value) {
				old_editvalue = dlg.Control("editFilter").value;
				DOpus.Delay(200); //mini pause
				update_sw = true;
			}
			if (dlg.Control("editFilter").focus && update_sw) {
				updateList(dlg, columns, str_tools);
				// old_editvalue = '';
				update_sw = false;
			}
		}
		if (msg.event == "hotkey" && msg.Control === "close_key") dlg.EndDlg(0);
	}
	//save dlg size and position 
	dlg.SavePosition("CommandViewers");
	tab = null;
	columns = null;
	str_tools = null;
	file = null;
	dlg = null;
	Log(2, "INFO    => FINNISH");
	CollectGarbage();
}

function updateList(dlg, cols_map, str_tools) {
	strFilter = dlg.Control("editFilter").value;
	Log(2, "INFO    => Updating list : " + strFilter);
	// if (!dlg.Control("editFilter").value) return;
	dlg.Control("columns_list").RemoveItem(-1);
	var strName, strLabel, strHeader, strValue, strFilter, fila, e, f, subcol_map;
	var category = dlg.Control("Categories").value.name;
	var regex = new RegExp(strFilter.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), "i");
	// Log(2, "INFO    => category   :" + category);
	//category is Music,Documents,General,Paths,Sizes,Dates,Pictures,Videos or Programs
	if (cols_map.Exists(category)) {
		for (e = new Enumerator(cols_map(category)); !e.atEnd(); e.moveNext()) {
			strName = e.item();
			strLabel = cols_map(category)(strName)['label'];
			strHeader = cols_map(category)(strName)['header'];
			strValue = cols_map(category)(strName)['value'];
			// Log(2, "INFO    => strName   :" + strName);
			try {
				if (!regex.test(str_tools.RemoveDiacritics(strLabel)) && !regex.test(strName) && !regex.test(str_tools.RemoveDiacritics(strHeader))) continue;
				fila = dlg.Control("columns_list").GetItemAt(dlg.Control("columns_list").AddItem(strName));
				fila.subitems(0) = strLabel;
				fila.subitems(1) = strHeader;
				fila.subitems(2) = category;
				fila.subitems(3) = strValue;
			} catch (e) {}
		}
		//category is All
	} else {
		for (e = new Enumerator(cols_map); !e.atEnd(); e.moveNext()) {
			// Log(2, "INFO    => category:" + e.item());
			subcol_map = cols_map.Get(e.item());
			// Log(2, "INFO    => items:" + subcol_map.count);
			for (f = new Enumerator(subcol_map); !f.atEnd(); f.moveNext()) {
				strName = f.item();
				// Log(2, "\tINFO    => label:" + strLabel);
				strLabel = subcol_map(strName)['label'];
				strHeader = subcol_map(strName)['header'];
				strValue = subcol_map(strName)['value'];
				// Log(2, "INFO    => strName   :" + strName);
				if (!regex.test(str_tools.RemoveDiacritics(strLabel)) && !regex.test(strName) && !regex.test(str_tools.RemoveDiacritics(strHeader))) continue;
				fila = dlg.Control("columns_list").GetItemAt(dlg.Control("columns_list").AddItem(strName));
				fila.subitems(0) = strLabel;
				fila.subitems(1) = strHeader;
				fila.subitems(2) = e.item();
				fila.subitems(3) = strValue;
			}
		}
	}
	dlg.Control("columns_list").columns.AutoSize();
	dlg.Control("staticNotify").label = str_tools.LanguageStr(5015) + ": " + dlg.Control("columns_list").count;
	Log(2, "INFO    => List updated");
}

function BuildColumnsList(item, tools) {
	Log(2, "INFO    => Building column's list. Please Wait...");
	var ini = new Date();
	var value;
	var main_map = DOpus.Create.Map();

	// ########     ###    ######## ########       ###    ##    ## ########     ######## #### ##     ## ######## 
	// ##     ##   ## ##      ##    ##            ## ##   ###   ## ##     ##       ##     ##  ###   ### ##       
	// ##     ##  ##   ##     ##    ##           ##   ##  ####  ## ##     ##       ##     ##  #### #### ##       
	// ##     ## ##     ##    ##    ######      ##     ## ## ## ## ##     ##       ##     ##  ## ### ## ######   
	// ##     ## #########    ##    ##          ######### ##  #### ##     ##       ##     ##  ##     ## ##       
	// ##     ## ##     ##    ##    ##          ##     ## ##   ### ##     ##       ##     ##  ##     ## ##       
	// ########  ##     ##    ##    ########    ##     ## ##    ## ########        ##    #### ##     ## ########
	var date_map = DOpus.Create.Map();

	date_map('accesseddate') = {
		'label': tools.LanguageStr(318),
		'header': tools.LanguageStr(18),
		'value': item.access.Format('d', 'n')
	};
	date_map('createddate') = {
		'label': tools.LanguageStr(316),
		'header': tools.LanguageStr(16),
		'value': item.create.Format('d', 'n')
	};
	date_map('modifieddate') = {
		'label': tools.LanguageStr(313),
		'header': tools.LanguageStr(13),
		'value': item.modify.Format('d', 'n')
	};
	date_map('created') = {
		'label': tools.LanguageStr(566),
		'header': tools.LanguageStr(21),
		'value': item.create.Format("", "s")
	};
	date_map('modified') = {
		'label': tools.LanguageStr(565),
		'header': tools.LanguageStr(20),
		'value': item.modify.Format("", "s")
	};
	date_map('accesed') = {
		'label': tools.LanguageStr(567),
		'header': tools.LanguageStr(22),
		'value': item.access.Format("", "s")
	};
	// value = tools.LanguageStr();
	// date_map(value) = {
	// 	'name': 'daterel',
	// 	'value': item.created.Format('d', 'n')
	// };
	date_map('accessedtime') = {
		'label': tools.LanguageStr(319),
		'header': tools.LanguageStr(19),
		'value': item.access.Format('t', 's')
	};
	date_map('createdtime') = {
		'label': tools.LanguageStr(317),
		'header': tools.LanguageStr(17),
		'value': item.create.Format('t', 's')
	};
	date_map('modifiedtime') = {
		'label': tools.LanguageStr(314),
		'header': tools.LanguageStr(14),
		'value': item.modify.Format('t', 's')
	};
	Log(2, "INFO    => Date/Time   :" + date_map.count + " columns added");

	main_map.Set(tools.LanguageStr(5142), date_map);

	date_map = null;

	// ########     ###    ######## ##     ##  ######  
	// ##     ##   ## ##      ##    ##     ## ##    ## 
	// ##     ##  ##   ##     ##    ##     ## ##       
	// ########  ##     ##    ##    #########  ######  
	// ##        #########    ##    ##     ##       ## 
	// ##        ##     ##    ##    ##     ## ##    ## 
	// ##        ##     ##    ##    ##     ##  ######
	var path_map = DOpus.Create.Map();

	path_map('ext') = {
		'label': tools.LanguageStr(323),
		'header': tools.LanguageStr(23),
		'value': item.ext.slice(1)
	};
	path_map('extdir') = {
		'label': tools.LanguageStr(381),
		'header': tools.LanguageStr(23),
		'value': (item.is_dir) ? tools.LanguageStr(2132) : item.ext.slice(1)
	};
	path_map('name') = {
		'label': tools.LanguageStr(310),
		'header': tools.LanguageStr(10),
		'value': item.name
	};
	value = item.realpath;
	path_map('fullpath') = {
		'label': tools.LanguageStr(144),
		'header': tools.LanguageStr(144),
		'value': String(value)
	};
	path_map('pathlen') = {
		'label': tools.LanguageStr(143),
		'header': tools.LanguageStr(143),
		'value': String(value).length
	};

	path_map('path') = {
		'label': tools.LanguageStr(39),
		'header': tools.LanguageStr(39),
		'value': value.pathpart
	};
	if (value.test_parent) value.Parent();
	path_map('parent') = {
		'label': tools.LanguageStr(410),
		'header': tools.LanguageStr(410),
		'value': (item.realpath.test_parent) ? value.filepart : ''
	};
	path_map('parentlocation') = {
		'label': tools.LanguageStr(412),
		'header': tools.LanguageStr(110),
		'value': (value.test_parent) ? (value.filepart + ' (' + value.pathpart + ')') : ''
	};
	path_map('parentpath') = {
		'label': tools.LanguageStr(411),
		'header': tools.LanguageStr(111),
		'value': (value.test_parent) ? value.pathpart : ''
	};

	path_map('pathrel') = {
		'label': tools.LanguageStr(380),
		'header': tools.LanguageStr(39),
		'value': ''
	};
	Log(2, "INFO    => Paths       :" + path_map.count + " columns added");

	main_map.Set(tools.LanguageStr(5144), path_map);
	path_map = null;

	// ######## #### ##       ########  ######  #### ######## ######## 
	// ##        ##  ##       ##       ##    ##  ##       ##  ##       
	// ##        ##  ##       ##       ##        ##      ##   ##       
	// ######    ##  ##       ######    ######   ##     ##    ######   
	// ##        ##  ##       ##             ##  ##    ##     ##       
	// ##        ##  ##       ##       ##    ##  ##   ##      ##       
	// ##       #### ######## ########  ######  #### ######## ######## 
	var size_map = DOpus.Create.Map();

	size_map('sizekb') = {
		'label': tools.LanguageStr(353),
		'header': tools.LanguageStr(11),
		'value': (item.size / 1024) + ' ' + tools.LanguageStr(1542)
	};
	size_map('sizeauto') = {
		'label': tools.LanguageStr(348),
		'header': tools.LanguageStr(11),
		'value': item.size.fmt
	};
	size_map('size') = {
		'label': tools.LanguageStr(311),
		'header': tools.LanguageStr(11),
		'value': item.size
	};
	size_map('disksizekb') = {
		'label': tools.LanguageStr(400),
		'header': tools.LanguageStr(94),
		'value': ''
	};
	size_map('disksizeauto') = {
		'label': tools.LanguageStr(399),
		'header': tools.LanguageStr(94),
		'value': ''
	};
	size_map('disksize') = {
		'label': tools.LanguageStr(398),
		'header': tools.LanguageStr(94),
		'value': ''
	};

	size_map('filecount') = {
		'label': tools.LanguageStr(390),
		'header': tools.LanguageStr(88),
		'value': item.metadata.other.filecount
	};
	size_map('dircount') = {
		'label': tools.LanguageStr(391),
		'header': tools.LanguageStr(87),
		'value': item.metadata.other.dircount
	};
	size_map('filecounttotal') = {
		'label': tools.LanguageStr(388),
		'header': tools.LanguageStr(86),
		'value': item.metadata.other.filecounttotal
	};
	size_map('dircounttotal') = {
		'label': tools.LanguageStr(389),
		'header': tools.LanguageStr(85),
		'value': item.metadata.other.dircounttotal
	};
	Log(2, "INFO    => Size        :" + size_map.count + " columns added");

	main_map.Set(tools.LanguageStr(5143), size_map);
	size_map = null;

	//  ######   ######## ##    ## ######## ########     ###    ##       
	// ##    ##  ##       ###   ## ##       ##     ##   ## ##   ##       
	// ##        ##       ####  ## ##       ##     ##  ##   ##  ##       
	// ##   #### ######   ## ## ## ######   ########  ##     ## ##       
	// ##    ##  ##       ##  #### ##       ##   ##   ######### ##       
	// ##    ##  ##       ##   ### ##       ##    ##  ##     ## ##       
	//  ######   ######## ##    ## ######## ##     ## ##     ## ######## 
	var general_map = DOpus.Create.Map();

	general_map('attr') = {
		'label': tools.LanguageStr(315),
		'header': tools.LanguageStr(15),
		'value': item.attr_text
	};
	value = tools.LanguageStr(145);
	general_map('availability') = {
		'label': value,
		'header': value,
		'value': item.ShellProp("System.OfflineAvailability", "r")
	};
	value = tools.LanguageStr(146);
	general_map('desc') = {
		'label': value,
		'header': value,
		'value': item.ShellProp("System.FileDescription", "r")
	};
	value = tools.LanguageStr(409);
	general_map('fontname') = {
		'label': value,
		'header': value,
		'value': ''
	};
	value = tools.LanguageStr(457);
	helper = '';
	var labels = item.Labels('*', 'explicit');
	for (var k = 0; k < labels.count; k++) helper += labels(k) + ';';
	general_map('label') = {
		'label': value,
		'header': value,
		'value': (helper) ? helper.slice(0, -1) : ''
	};
	value = tools.LanguageStr(347);
	general_map('owner') = {
		'label': value,
		'header': value,
		'value': item.ShellProp("System.FileOwner", "r")
	};
	value = tools.LanguageStr(420);
	general_map('rating') = {
		'label': value,
		'header': value,
		'value': item.metadata.other.rating
	};
	helper = '';
	var labels = item.Labels('Status');
	for (var k = 0; k < labels.count; k++) helper += labels(k) + ';';
	general_map('status') = {
		'label': tools.LanguageStr(564),
		'header': tools.LanguageStr(147),
		'value': (helper) ? helper.slice(0, -1) : ''
	};
	value = tools.LanguageStr(28074);
	helper = '';
	for (var k = 0; k < item.metadata.tags.count; k++) helper += item.metadata.tags(k) + ';';
	general_map('keywords') = {
		'label': value,
		'header': value,
		'value': (helper) ? helper.slice(0, -1) : ''
	};
	value = tools.LanguageStr(553);
	general_map('target') = {
		'label': value,
		'header': value,
		'value': item.metadata.other.target
	};
	value = tools.LanguageStr(312);
	general_map('type') = {
		'label': value,
		'header': value,
		'value': item.metadata.other.target_type
	};
	value = tools.LanguageStr(140);
	general_map('userdesc') = {
		'label': value,
		'header': value,
		'value': item.metadata.other.usercomment
	};
	Log(2, "INFO    => General     :" + general_map.count + " columns added");

	main_map.Set(tools.LanguageStr(5029), general_map);
	general_map = null;

	//    ###    ##     ## ########  ####  #######  
	//   ## ##   ##     ## ##     ##  ##  ##     ## 
	//  ##   ##  ##     ## ##     ##  ##  ##     ## 
	// ##     ## ##     ## ##     ##  ##  ##     ## 
	// ######### ##     ## ##     ##  ##  ##     ## 
	// ##     ## ##     ## ##     ##  ##  ##     ## 
	// ##     ##  #######  ########  ####  #######  
	var audio_map = DOpus.Create.Map();
	value = tools.LanguageStr(36);
	audio_map('mp3album') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.mp3album
	};
	value = tools.LanguageStr(138);
	audio_map('mp3albumartist') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.mp3albumartist
	};
	value = tools.LanguageStr(35);
	audio_map('mp3artists') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.mp3artist
	};
	value = tools.LanguageStr(92);
	audio_map('audiocodec') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.audiocodec
	};
	value = tools.LanguageStr(116);
	audio_map('mp3bpm') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.mp3bpm
	};
	audio_map('picdepth') = {
		'label': tools.LanguageStr(327),
		'header': tools.LanguageStr(27),
		'value': item.metadata.audio_text.picdepth
	};
	value = tools.LanguageStr(330);
	audio_map('mp3bitrate') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.mp3bitrate
	};
	value = tools.LanguageStr(572);
	audio_map('compilation') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.compilation
	};
	value = tools.LanguageStr(436);
	audio_map('composers') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.composers
	};
	value = tools.LanguageStr(437);
	audio_map('conductors') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.conductors
	};
	value = tools.LanguageStr(344);
	audio_map('copyright') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.copyright
	};
	audio_map('mp3disc') = {
		'label': tools.LanguageStr(458),
		'header': tools.LanguageStr(134),
		'value': item.metadata.audio_text.mp3disc
	};
	audio_map('duration') = {
		'label': tools.LanguageStr(50),
		'header': tools.LanguageStr(350),
		'value': item.metadata.audio_text.duration
	};
	audio_map('mp3encoder') = {
		'label': tools.LanguageStr(89),
		'header': tools.LanguageStr(393),
		'value': item.metadata.audio_text.mp3encoder
	};
	audio_map('mp3encodingsoftware') = {
		'label': tools.LanguageStr(570),
		'header': tools.LanguageStr(150),
		'value': item.metadata.audio_text.mp3encodingsoftware
	};
	value = tools.LanguageStr(33);
	audio_map('mp3genre') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.mp3genre
	};
	value = tools.LanguageStr(441);
	audio_map('initialkey') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.initialkey
	};
	value = tools.LanguageStr(32);
	audio_map('mp3mode') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.mp3mode
	};
	value = tools.LanguageStr(38);
	audio_map('mp3comment') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.mp3comment
	};
	value = tools.LanguageStr(46);
	audio_map('mp3info') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.mp3info
	};
	value = tools.LanguageStr(34);
	audio_map('mp3title') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.mp3title
	};
	value = tools.LanguageStr(418);
	audio_map('mp3drm') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.mp3drm
	};
	value = tools.LanguageStr(447);
	audio_map('releasedate') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.releasedate
	};
	audio_map('mp3samplerate') = {
		'label': tools.LanguageStr(331),
		'header': tools.LanguageStr(31),
		'value': item.metadata.audio_text.mp3samplerate
	};
	audio_map('mp3track') = {
		'label': tools.LanguageStr(371),
		'header': tools.LanguageStr(70),
		'value': item.metadata.audio_text.mp3track
	};
	value = tools.LanguageStr(37);
	audio_map('mp3year') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.mp3year
	};
	value = tools.LanguageStr(434);
	audio_map('publisher') = {
		'label': value,
		'header': value,
		'value': item.metadata.audio_text.publisher
	};
	Log(2, "INFO    => Audio       :" + audio_map.count + " columns added");

	main_map.Set(tools.LanguageStr(5031), audio_map);
	audio_map = null;

	// ########   #######   ######  ##     ## ##     ## ######## ##    ## ########  ######  
	// ##     ## ##     ## ##    ## ##     ## ###   ### ##       ###   ##    ##    ##    ## 
	// ##     ## ##     ## ##       ##     ## #### #### ##       ####  ##    ##    ##       
	// ##     ## ##     ## ##       ##     ## ## ### ## ######   ## ## ##    ##     ######  
	// ##     ## ##     ## ##       ##     ## ##     ## ##       ##  ####    ##          ## 
	// ##     ## ##     ## ##    ## ##     ## ##     ## ##       ##   ###    ##    ##    ## 
	// ########   #######   ######   #######  ##     ## ######## ##    ##    ##     ######  
	var doc_map = DOpus.Create.Map();
	value = tools.LanguageStr(363);
	doc_map('author') = {
		'label': value,
		'header': value,
		'value': item.metadata.doc_text.author
	};
	value = tools.LanguageStr(366);
	doc_map('category ') = {
		'label': value,
		'header': value,
		'value': item.metadata.doc_text.category
	};
	value = tools.LanguageStr(368);
	doc_map('comments') = {
		'label': value,
		'header': value,
		'value': item.metadata.doc_text.comments
	};
	doc_map('companyname') = {
		'label': tools.LanguageStr(45),
		'header': tools.LanguageStr(345),
		'value': item.metadata.doc_text.companyname
	};
	value = tools.LanguageStr(44);
	doc_map('copyright') = {
		'label': value,
		'header': value,
		'value': item.metadata.doc_text.copyright
	};
	value = tools.LanguageStr(426);
	doc_map('creator') = {
		'label': value,
		'header': value,
		'value': item.metadata.doc_text.creator
	};
	doc_map('doccreateddate') = {
		'label': tools.LanguageStr(403),
		'header': tools.LanguageStr(103),
		'value': item.metadata.doc_text.doccreateddate
	};
	value = tools.LanguageStr(105);
	doc_map('docedittime') = {
		'label': value,
		'header': value,
		'value': item.metadata.doc_text.docedittime
	};
	value = tools.LanguageStr(406);
	doc_map('doclastsavedby ') = {
		'label': value,
		'header': value,
		'value': item.metadata.doc_text.doclastsavedby
	};
	value = tools.LanguageStr(404);
	doc_map('doclastsaveddate') = {
		'label': value,
		'header': value,
		'value': item.metadata.doc_text.doclastsaveddate
	};
	value = tools.LanguageStr(367);
	doc_map('pages') = {
		'label': value,
		'header': value,
		'value': item.metadata.doc_text.pages
	};
	value = tools.LanguageStr(427);
	doc_map('producer') = {
		'label': value,
		'header': value,
		'value': item.metadata.doc_text.producer
	};
	value = tools.LanguageStr(365);
	doc_map('subject') = {
		'label': value,
		'header': value,
		'value': item.metadata.doc_text.subject
	};
	value = tools.LanguageStr(364);
	doc_map('title') = {
		'label': value,
		'header': value,
		'value': item.metadata.doc_text.title
	};
	Log(2, "INFO    => Documents   :" + doc_map.count + " columns added");

	main_map.Set(tools.LanguageStr(5033), doc_map);
	doc_map = null;

	// ########  ####  ######  ######## ##     ## ########  ########  ######  
	// ##     ##  ##  ##    ##    ##    ##     ## ##     ## ##       ##    ## 
	// ##     ##  ##  ##          ##    ##     ## ##     ## ##       ##       
	// ########   ##  ##          ##    ##     ## ########  ######    ######  
	// ##         ##  ##          ##    ##     ## ##   ##   ##             ## 
	// ##         ##  ##    ##    ##    ##     ## ##    ##  ##       ##    ## 
	// ##        ####  ######     ##     #######  ##     ## ########  ######  
	var image_map = DOpus.Create.Map();

	value = tools.LanguageStr(386);
	image_map('35mmfocallength') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text['35mmfocallength']
	};
	value = tools.LanguageStr(101);
	image_map('altitude') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.altitude
	};
	value = tools.LanguageStr(357);
	image_map('apertureval') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.apertureval
	};
	value = tools.LanguageStr(53);
	image_map('cameramake') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.cameramake
	};
	value = tools.LanguageStr(54);
	image_map('cameramodel') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.cameramodel
	};
	value = tools.LanguageStr(29389);
	image_map('colormodel') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.colormodel
	};
	value = tools.LanguageStr(383);
	image_map('contrast') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.contrast
	};
	value = tools.LanguageStr(100);
	image_map('coords') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.coords
	};
	image_map('datedigitized') = {
		'label': tools.LanguageStr(425),
		'header': tools.LanguageStr(122),
		'value': item.metadata.image_text.datedigitized
	};
	value = tools.LanguageStr(356);
	image_map('datetaken') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.datetaken
	};
	value = tools.LanguageStr(387);
	image_map('digitalzoom') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.digitalzoom
	};
	value = tools.LanguageStr(60);
	image_map('exposurebias') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.exposurebias
	};
	value = tools.LanguageStr(375);
	image_map('exposureprogram') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.exposureprogram
	};
	value = tools.LanguageStr(377);
	image_map('exposuretime') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.exposuretime
	};
	value = tools.LanguageStr(61);
	image_map('flash') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.flash
	};
	value = tools.LanguageStr(77);
	image_map('fnumber') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.fnumber
	};
	value = tools.LanguageStr(373);
	image_map('focallength') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.focallength
	};
	image_map('imagedesc') = {
		'label': tools.LanguageStr(563),
		'header': tools.LanguageStr(24),
		'value': item.metadata.image_text.imagedesc
	};
	value = tools.LanguageStr(120);
	image_map('imagequality') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.imagequality
	};
	image_map('instructions') = {
		'label': tools.LanguageStr(571),
		'header': tools.LanguageStr(151),
		'value': item.metadata.image_text.instructions
	};
	value = tools.LanguageStr(58);
	image_map('isospeed') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.isospeed
	};
	value = tools.LanguageStr(98);
	image_map('latitude') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.latitude
	};
	value = tools.LanguageStr(153);
	image_map('lensmake') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.lensmake
	};
	value = tools.LanguageStr(152);
	image_map('lensmodel') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.lensmodel
	};
	value = tools.LanguageStr(99);
	image_map('longitude') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.longitude
	};
	value = tools.LanguageStr(119);
	image_map('macromode') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.macromode
	};
	value = tools.LanguageStr(374);
	image_map('meteringmode') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.meteringmode
	};
	value = tools.LanguageStr(136);
	image_map('picphysx') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.picphysx
	};
	value = tools.LanguageStr(137);
	image_map('picphysy') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.picphysy
	};
	value = tools.LanguageStr(30007);
	image_map('picres') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.picres
	};
	image_map('picresx') = {
		'label': tools.LanguageStr(369),
		'header': tools.LanguageStr(68),
		'value': item.metadata.image_text.picresx
	};
	image_map('picresy') = {
		'label': tools.LanguageStr(370),
		'header': tools.LanguageStr(69),
		'value': item.metadata.image_text.picresy
	};
	value = tools.LanguageStr(382);
	image_map('rotation') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.rotation
	};
	value = tools.LanguageStr(384);
	image_map('saturation') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.saturation
	};
	value = tools.LanguageStr(78);
	image_map('scenecapturetype') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.scenecapturetype
	};
	value = tools.LanguageStr(118);
	image_map('scenemode') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.scenemode
	};
	value = tools.LanguageStr(385);
	image_map('sharpness') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.sharpness
	};
	value = tools.LanguageStr(57);
	image_map('shutterspeed') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.shutterspeed
	};
	value = tools.LanguageStr(417);
	image_map('software') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.software
	};
	value = tools.LanguageStr(376);
	image_map('subjectdistance') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.subjectdistance
	};
	value = tools.LanguageStr(59);
	image_map('whitebalance') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.whitebalance
	};
	value = tools.LanguageStr(416);
	image_map('aspectratio') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.aspectratio
	};
	value = tools.LanguageStr(363);
	image_map('author') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.author
	};
	value = tools.LanguageStr(44);
	image_map('copyright') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.copyright
	};
	value = tools.LanguageStr(35);
	image_map('mp3artist') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.mp3artist
	};
	image_map('picdepth') = {
		'label': tools.LanguageStr(327),
		'header': tools.LanguageStr(27),
		'value': item.metadata.image_text.picdepth
	};
	value = tools.LanguageStr(26);
	image_map('picheight') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.picheight
	};
	value = tools.LanguageStr(28);
	image_map('picsize') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.picsize
	};
	value = tools.LanguageStr(25);
	image_map('picwidth') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.picwidth
	};
	value = tools.LanguageStr(365);
	image_map('subject') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.subject
	};
	value = tools.LanguageStr(364);
	image_map('title') = {
		'label': value,
		'header': value,
		'value': item.metadata.image_text.title
	};
	Log(2, "INFO    => Pictures    :" + image_map.count + " columns added");

	main_map.Set(tools.LanguageStr(5040), image_map);
	image_map = null;

	// ##     ## #### ########  ########  #######  
	// ##     ##  ##  ##     ## ##       ##     ## 
	// ##     ##  ##  ##     ## ##       ##     ## 
	// ##     ##  ##  ##     ## ######   ##     ## 
	//  ##   ##   ##  ##     ## ##       ##     ## 
	//   ## ##    ##  ##     ## ##       ##     ## 
	//    ###    #### ########  ########  #######  
	// t = tools.LanguageStr(5083) + ': ';
	var video_map = DOpus.Create.Map();

	// value = tools.LanguageStr(363);
	// video_map('author') = {
	// 	'label': value,
	// 	'header': value,
	// 	'value': item.metadata.doc_text.author
	// };
	// video_map('title') = {
	// 	'label': tools.LanguageStr(364),
	// 	'header': tools.LanguageStr(),
	// 	'value': item.metadata.doc_text.title
	// };
	video_map('audiocount') = {
		'label': tools.LanguageStr(29378),
		'header': tools.LanguageStr(29388),
		'value': item.metadata.video_text.audiocount
	};
	video_map('subtitlecount') = {
		'label': tools.LanguageStr(29382),
		'header': tools.LanguageStr(29393),
		'value': item.metadata.video_text.subtitlecount
	};
	video_map('videocount') = {
		'label': tools.LanguageStr(29384),
		'header': tools.LanguageStr(29395),
		'value': item.metadata.video_text.videocount
	};
	value = tools.LanguageStr(444);
	video_map('director') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.director
	};
	value = tools.LanguageStr(436);
	video_map('composers') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.composers
	};
	value = tools.LanguageStr(437);
	video_map('conductors') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.conductors
	};
	value = tools.LanguageStr(35);
	video_map('mp3artist') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.mp3artist
	};
	value = tools.LanguageStr(33);
	video_map('mp3genre') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.mp3genre
	};
	value = tools.LanguageStr(34);
	video_map('mp3title') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.mp3title
	};
	value = tools.LanguageStr(37);
	video_map('mp3year') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.mp3year
	};
	value = tools.LanguageStr(447);
	video_map('releasedate') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.releasedate
	};
	value = tools.LanguageStr(416);
	video_map('aspectratio') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.aspectratio
	};
	value = tools.LanguageStr(92);
	video_map('audiocodec') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.audiocodec
	};
	video_map('picdepth') = {
		'label': tools.LanguageStr(327),
		'header': tools.LanguageStr(27),
		'value': item.metadata.video_text.picdepth
	};
	value = tools.LanguageStr(330);
	video_map('mp3bitrate') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.mp3bitrate
	};
	value = tools.LanguageStr(129);
	video_map('broadcastdate') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.broadcastdate
	};
	video_map('channel') = {
		'label': tools.LanguageStr(450),
		'header': tools.LanguageStr(126),
		'value': item.metadata.video_text.channel
	};
	value = tools.LanguageStr(449);
	video_map('credits') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.credits
	};
	value = tools.LanguageStr(395);
	video_map('datarate') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.datarate
	};
	value = tools.LanguageStr(28);
	video_map('picsize') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.picsize
	};
	value = tools.LanguageStr(350);
	video_map('duration') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.duration
	};
	value = tools.LanguageStr(124);
	video_map('episodename') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.episodename
	};
	video_map('fourcc') = {
		'label': tools.LanguageStr(558),
		'header': tools.LanguageStr(142),
		'value': item.metadata.video_text.fourcc
	};
	video_map('framerate') = {
		'label': tools.LanguageStr(90),
		'header': tools.LanguageStr(394),
		'value': item.metadata.video_text.framerate
	};
	video_map('picheight') = {
		'label': tools.LanguageStr(26),
		'header': tools.LanguageStr(326),
		'value': item.metadata.video_text.picheight
	};
	video_map('ishd') = {
		'label': tools.LanguageStr(451),
		'header': tools.LanguageStr(127),
		'value': item.metadata.video_text.ishd
	};
	video_map('mp3mode') = {
		'label': tools.LanguageStr(332),
		'header': tools.LanguageStr(32),
		'value': item.metadata.video_text.mp3mode
	};
	video_map('picphyssize') = {
		'label': tools.LanguageStr(459),
		'header': tools.LanguageStr(135),
		'value': item.metadata.video_text.picphyssize
	};
	value = tools.LanguageStr(434);
	video_map('publisher') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.publisher
	};
	video_map('recordingtime') = {
		'label': tools.LanguageStr(454),
		'header': tools.LanguageStr(130),
		'value': item.metadata.video_text.recordingtime
	};
	video_map('isrepeat') = {
		'label': tools.LanguageStr(452),
		'header': tools.LanguageStr(128),
		'value': item.metadata.video_text.isrepeat
	};
	video_map('mp3samplerate') = {
		'label': tools.LanguageStr(331),
		'header': tools.LanguageStr(31),
		'value': item.metadata.video_text.mp3samplerate
	};
	video_map('station') = {
		'label': tools.LanguageStr(455),
		'header': tools.LanguageStr(131),
		'value': item.metadata.video_text.station
	};
	video_map('videocodec') = {
		'label': tools.LanguageStr(397),
		'header': tools.LanguageStr(93),
		'value': item.metadata.video_text.videocodec
	};
	video_map('picwidth') = {
		'label': tools.LanguageStr(325),
		'header': tools.LanguageStr(25),
		'value': item.metadata.video_text.picwidth
	};
	video_map('alllangs') = {
		'label': tools.LanguageStr(29375),
		'header': tools.LanguageStr(7572),
		'value': item.metadata.video_text.alllangs
	};
	video_map('audiolangs') = {
		'label': tools.LanguageStr(29377),
		'header': tools.LanguageStr(29387),
		'value': item.metadata.video_text.audiolangs
	};
	video_map('hdrtypes') = {
		'label': tools.LanguageStr(29380),
		'header': tools.LanguageStr(29390),
		'value': item.metadata.video_text.hdrtypes
	};
	value = tools.LanguageStr(418);
	video_map('mp3drm') = {
		'label': value,
		'header': value,
		'value': item.metadata.video_text.mp3drm
	};
	video_map('subtitlelangs') = {
		'label': tools.LanguageStr(29381),
		'header': tools.LanguageStr(29392),
		'value': item.metadata.video_text.subtitlelangs
	};
	video_map('videolangs') = {
		'label': tools.LanguageStr(29383),
		'header': tools.LanguageStr(29394),
		'value': item.metadata.video_text.videolangs
	};
	Log(2, "INFO    => Video       :" + video_map.count + " columns added");

	main_map.Set(tools.LanguageStr(5083), video_map);
	video_map = null;

	// ########  ########   #######   ######   ########     ###    ##     ##  ######  
	// ##     ## ##     ## ##     ## ##    ##  ##     ##   ## ##   ###   ### ##    ## 
	// ##     ## ##     ## ##     ## ##        ##     ##  ##   ##  #### #### ##       
	// ########  ########  ##     ## ##   #### ########  ##     ## ## ### ##  ######  
	// ##        ##   ##   ##     ## ##    ##  ##   ##   ######### ##     ##       ## 
	// ##        ##    ##  ##     ## ##    ##  ##    ##  ##     ## ##     ## ##    ## 
	// ##        ##     ##  #######   ######   ##     ## ##     ## ##     ##  ######  
	var exe_map = DOpus.Create.Map();

	exe_map('moddesc') = {
		'label': tools.LanguageStr(40),
		'header': tools.LanguageStr(340),
		'value': item.metadata.exe_text.moddesc
	};
	exe_map('modversion') = {
		'label': tools.LanguageStr(41),
		'header': tools.LanguageStr(341),
		'value': item.metadata.exe_text.modversion
	};
	exe_map('prodname') = {
		'label': tools.LanguageStr(42),
		'header': tools.LanguageStr(342),
		'value': item.metadata.exe_text.prodname
	};
	exe_map('prodversion') = {
		'label': tools.LanguageStr(43),
		'header': tools.LanguageStr(343),
		'value': item.metadata.exe_text.prodversion
	};
	exe_map('copyright') = {
		'label': tools.LanguageStr(44),
		'header': tools.LanguageStr(344),
		'value': item.metadata.exe_text.copyright
	};
	exe_map('companyname') = {
		'label': tools.LanguageStr(45),
		'header': tools.LanguageStr(345),
		'value': item.metadata.exe_text.companyname
	};

	Log(2, "INFO    => Programs    :" + exe_map.count + " columns added");

	main_map.Set(tools.LanguageStr(5032), exe_map);
	exe_map = null;

	//  ######   ######  ########  #### ########  ########  ######      ######   #######  ##        ######  
	// ##    ## ##    ## ##     ##  ##  ##     ##    ##    ##    ##    ##    ## ##     ## ##       ##    ## 
	// ##       ##       ##     ##  ##  ##     ##    ##    ##          ##       ##     ## ##       ##       
	//  ######  ##       ########   ##  ########     ##     ######     ##       ##     ## ##        ######  
	//       ## ##       ##   ##    ##  ##           ##          ##    ##       ##     ## ##             ## 
	// ##    ## ##    ## ##    ##   ##  ##           ##    ##    ##    ##    ## ##     ## ##       ##    ## 
	//  ######   ######  ##     ## #### ##           ##     ######      ######   #######  ########  ######

	// ######## ##     ##    ###    ##       ##     ##    ###    ########  #######  ########  
	// ##       ##     ##   ## ##   ##       ##     ##   ## ##      ##    ##     ## ##     ## 
	// ##       ##     ##  ##   ##  ##       ##     ##  ##   ##     ##    ##     ## ##     ## 
	// ######   ##     ## ##     ## ##       ##     ## ##     ##    ##    ##     ## ########  
	// ##        ##   ##  ######### ##       ##     ## #########    ##    ##     ## ##   ##   
	// ##         ## ##   ##     ## ##       ##     ## ##     ##    ##    ##     ## ##    ##  
	// ########    ###    ##     ## ########  #######  ##     ##    ##     #######  ##     ##

	//For script columns, we have to read info from 2 files
	// /dopusdata\ConfigFiles\scriptcolumns.oxc	=> get column guid
	// /dopusdata\ConfigFiles\scriptaddins.oxc	=> check if that guid is not disabled
	var scr_cols_file = DOpus.Aliases('dopusdata').path + '\\ConfigFiles\\scriptcolumns.oxc';
	var scr_addins_file = DOpus.Aliases('dopusdata').path + '\\ConfigFiles\\scriptaddins.oxc';
	var eval_cols_file = DOpus.Aliases('dopusdata').path + '\\ConfigFiles\\evalcols.oxc';
	//ParseFile returns a map with the necessary values if succesful, otherwise returns false
	try {
		var scr_arr = parseScriptXmls(scr_addins_file, scr_cols_file);
		var eval_arr = parseEvaluatorXml(eval_cols_file, (DOpus.FSUtil.PathType(item) == 'filesys') ? 'shell' : 'all');
		if (scr_arr[0] || eval_arr[0]) {
			var DOvar = 'sc_columns';
			//create a  rename preset using script columns as new name then store the value into a DOpus var
			//Evaluator is needed since that way special chars are not replaced
			//Needs to be done in batchs since there's a length limit for the new name
			scr_arr[0].push_back(eval_arr[0]);
			var cmd = DOpus.Create.Command();
			cmd.AddFile(item);
			DOpus.Vars.Delete(DOvar);
			Log(2, "INFO    => Scripts     :" + scr_arr[0].length + " presets needed");
			var scr_values = [];
			var eval_values = [];
			for (var k = 0; k < scr_arr[0].length; k++) {
				if (CreateRenamePresetTxt(DOvar, scr_arr[0](k))) {
					cmd.RunCommand('RENAME PRESET="' + DOvar + '"');
					if (DOpus.Vars.Exists(DOvar)) {
						Log(2, "INFO    => DOpus var " + DOvar + " raw values:" + DOpus.Vars.Get(DOvar));
						//split between Evaluator and scripts values
						value = DOpus.Vars.Get(DOvar).split('#_sep_#');
						// Log(2, "INFO    => Scripts     :values sp=>" + value.length);
						if (value.length > 0) scr_values = scr_values.concat(value[0].split('#_#'));
						if (value.length > 1) eval_values = eval_values.concat(value[1].split('#_#'));
						Log(2, "INFO    => Scripts     :scr_values=>" + scr_values.length);
						Log(2, "INFO    => Scripts     :eval_values=>" + eval_values.length);
					} else
						Log(1, "WARNING => DOpus var " + DOvar + " doesn't exist! Skipping scripts/Evaluator columns");
				} else
					Log(1, "WARNING => Unable to write rename preset file !! Skipping scripts/Evaluator columns");
			}
			if (scr_values.length > 0) {
				scr_arr = scr_arr.slice(1);
				var scripts_map = DOpus.Create.Map();
				for (var i = 0; i < scr_arr.length; i++) {
					Log(2, "INFO    => keyword:" + scr_arr[i]['value'] + "; label:" + scr_arr[i]['name'] + "; header:" + scr_arr[i]['name'] + "; value:" + scr_values[i]);
					scripts_map(scr_arr[i]['value']) = {
						'label': scr_arr[i]['name'],
						'header': scr_arr[i]['name'],
						'value': scr_values[i]
					};
				}
				Log(2, "INFO    => Scripts     :" + scripts_map.count + " columns added");
				main_map.Set(tools.LanguageStr(30087), scripts_map);
				scripts_map = null;
			}
			if (eval_values.length > 0) {
				eval_arr = eval_arr.slice(1);
				var eval_map = DOpus.Create.Map();
				for (var i = 0; i < eval_arr.length; i++) {
					eval_map(eval_arr[i]['value']) = {
						'label': eval_arr[i]['name'],
						'header': eval_arr[i]['header'],
						'value': eval_values[i]
					};
				}
				Log(2, "INFO    => Evaluator   :" + eval_map.count + " columns added");
				main_map.Set(tools.LanguageStr(28574), eval_map);
				eval_map = null;
			}
			//Delete the global var used
			DOpus.Vars.Delete(DOvar);
			//Delete the renmae preset created
			DOvar = DOpus.Aliases('dopusdata').path + '\\Rename Presets\\' + DOvar + '.orp';
			// cmd.RunCommand('DELETE "' + DOvar + '" NORECYCLE FORCE QUIET');
			cmd = null;
		}
	} catch (e) {
		Log(1, "WARNING => Error when trying to get values for script/Evaluator columns");
	}
	scr_arr = null;
	eval_arr = null;

	//  ######  ##     ## ######## ##       ##          ########  ########   #######  ########   ######  
	// ##    ## ##     ## ##       ##       ##          ##     ## ##     ## ##     ## ##     ## ##    ## 
	// ##       ##     ## ##       ##       ##          ##     ## ##     ## ##     ## ##     ## ##       
	//  ######  ######### ######   ##       ##          ########  ########  ##     ## ########   ######  
	//       ## ##     ## ##       ##       ##          ##        ##   ##   ##     ## ##              ## 
	// ##    ## ##     ## ##       ##       ##          ##        ##    ##  ##     ## ##        ##    ## 
	//  ######  ##     ## ######## ######## ########    ##        ##     ##  #######  ##         ######

	var shell_cols_file = DOpus.Aliases('dopuslocaldata').path + '\\State Data\\shellcolumns.osd';
	try {
		var shell_map = parseShellXml(shell_cols_file, item);
		if (shell_map.count > 0) {
			Log(2, "INFO    => Shell       :" + shell_map.count + " columns added");
			main_map.Set(tools.LanguageStr(28611), shell_map);
			shell_map = null;
		}
	} catch (e) {
		Log(1, "WARNING => Error when trying to get values for Shell Properties columns");
	}
	value = null;
	Log(2, "INFO    => Building column's list finnished: " + (new Date() - ini));
	return main_map;
}

function parseShellXml(shell_cols_file, item) {
	Log(2, "INFO    => shell       :Parsing Shell Properties columns xml file: " + shell_cols_file);
	Log(2, "INFO    => shell       :file: " + item + '(' + DOpus.TypeOf(item) + ')');
	var xmlDocShell = new ActiveXObject("Msxml2.DOMDocument");
	xmlDocShell.load(shell_cols_file);

	// Verify if the files have been loaded correctly
	if (xmlDocShell.parseError.errorCode == 0) {
		// Get all columns inside <shellcolumns>.
		var shellcolumns = xmlDocShell.selectNodes("//shellcolumns/column");
		var results = DOpus.Create.Map();
		var FSU = DOpus.FSUtil();

		for (var i = 0; i < shellcolumns.length; i++) {
			// Get keyword and title
			var keyword = shellcolumns[i].getAttribute("key");
			var title = shellcolumns[i].selectSingleNode("shell/title").text;
			Log(2, 'INFO    => shell       :Found "' + keyword + '" column');
			if (title && keyword) {
				//get the shell property
				var value = FSU.GetShellProperty(item, keyword);
				if (value) {
					//if is a vector, convert into a single line
					if (DOpus.TypeOf(value) == 'object.Vector') {
						var text = '';
						for (var i = 0; i < value.length; i++)
							text += value(i) + ';';
						value = text.slice(0, -1);
					}
					Log(2, "INFO    => shell       :" + keyword + " value is " + value);
					results(keyword) = {
						'label': title,
						'header': title,
						'value': value
					};
				} else
					Log(2, "INFO    => shell       :Error when getting shell property:" + keyword);
			} else
				Log(1, 'WARNING => shell       :"' + keyword + '" does not seems valid');
		}
		FSU = null;
	} else
		Log(1, "WARNING => shell       :Error while parsing " + shell_cols_file);
	xmlDocShell = null;
	return results;
}

function parseScriptXmls(scr_addins_file, scr_cols_file) {
	Log(2, "INFO    => script      :Parsing script columns xml file:" + scr_addins_file);
	Log(2, "INFO    => script      :Parsing script columns xml file:" + scr_cols_file);
	// Create DOMDocument objects for both files
	var xmlDocAddins = new ActiveXObject("Msxml2.DOMDocument");
	var xmlDocCols = new ActiveXObject("Msxml2.DOMDocument");
	var results = [''];
	var scripts_path = DOpus.Aliases('scripts').path + '\\';
	var ignored_scripts = Script.config.ignored_script_columns;
	var scripts_names = DOpus.Create.Map();
	var FSU = DOpus.FSUtil();
	//convert scripts_names into a Map
	for (var i = 0; i < Script.config.sc_cols_custom_names.length; i++) {
		m = Script.config.sc_cols_custom_names(i).match(/^"(.*)" *: *"(.*)"$/);
		if (m) scripts_names.Set(m[1], m[2]);
	}
	// Load XML content from files
	xmlDocAddins.load(scr_addins_file);
	xmlDocCols.load(scr_cols_file);

	// Verify if the files have been loaded correctly
	if (xmlDocAddins.parseError.errorCode == 0 && xmlDocCols.parseError.errorCode == 0) {
		// Find the <disabled> tag
		var disabledTag = xmlDocAddins.selectSingleNode("//scriptaddins/disabled");

		// Get all scripts inside <scriptcolumns>.
		var colScripts = xmlDocCols.selectNodes("//scriptcolumns/col");

		// Create an associative object to store id and path of non-disabled scripts
		var scriptsNoDesactivados = {};
		var cmdline = '';
		var cmdlines = DOpus.Create.Vector();
		for (var i = 0; i < colScripts.length; i++) {
			// Get name and script
			var name = colScripts[i].getAttribute("name");
			var script = colScripts[i].getAttribute("script");
			// Check if the script is disabled
			// If it is not deactivated, perform the required logic
			if (!disabledTag.selectSingleNode("script[@id='{" + script + "}']")) {
				// Get path value in addins.xml
				var pathNode = xmlDocAddins.selectSingleNode("//scriptaddins/idmap/script[@id='{" + script + "}']");
				if (!pathNode) {
					Log(1, 'WARNING => script      :"' + name + '" is not listed in scriptaddins.oxc');
					continue;
				}
				var path = pathNode.getAttribute("path");
				// Log(2, "INFO    => name:" + name);
				// Log(2, "INFO    => path:" + path);
				//check if that script file exists
				if (!FSU.Exists(scripts_path + path)) {
					Log(1, 'WARNING => script      :"' + scripts_path + path + '" does not exists in scripts folder');
					continue;
				}
				//Check if script file is listed as ignored
				if (ExistsinVector(ignored_scripts, path)) {
					Log(2, 'INFO    => script      :"' + path + '" is configured to be ignored');
					continue;
				}
				//Check if the script has a name/keyword different than the script filename
				if (scripts_names.Exists(path)) path = scripts_names.Get(path);

				// Remove the final part that says js|vbs or js|vbs.txt or the path preceding if is an osp package
				else path = path.replace(/(?:.*?\.osp\\)?([^\\]+)\.(?:js|vbs)(?:\.txt)?/, '$1');

				Log(2, "INFO    => script      :Column GUID:" + script + "; name:" + name + "; path:" + path);

				var result = path + "/" + name;
				result = result.replace(/ /g, '');
				if (path && name) {
					// We have to create a preset every 10000 chars or less
					if (cmdline.length + result.length > 10000) {
						// Log(2, "INFO    => script      :It needs an additional rename preset");
						cmdlines.push_back(cmdline.slice(0, -3));
						cmdline = '';
					}
					cmdline += '{=Val("scp:' + result + '")=}#_#';
					results.push({
						'name': name,
						'value': result
					});
				}
			} else
				Log(2, 'INFO    => script      :"' + name + '" is listed as disabled');
		}
		if (cmdline)
			cmdlines.push_back(cmdline.slice(0, -3));
		results[0] = cmdlines;
	} else
		Log(1, "WARNING => script      :Error while parsing script columns xml files");
	xmlDocAddins = null;
	xmlDocCols = null;
	FSU = null;
	return results;
}

function parseEvaluatorXml(ev_col_file, item_type) {
	Log(2, "INFO    => Evaluator   :Parsing Evaluator columns xml file:" + ev_col_file);
	Log(2, "INFO    => Evaluator   :item path type: " + item_type);
	var results = [''];
	var xmlDocEv = new ActiveXObject("Msxml2.DOMDocument");
	xmlDocEv.load(ev_col_file);

	if (xmlDocEv.parseError.errorCode == 0) {
		var evalcolumns = xmlDocEv.selectNodes("//prefs/evalcolumns/column");
		var cmdline = '';
		for (var i = 0; i < evalcolumns.length; i++) {
			//if foldertype doesn't match with item system type, ignore column
			if (item_type != evalcolumns[i].getAttribute("foldertype")) {
				Log(2, "INFO    => Evaluator   :Skipped column cause " + evalcolumns[i].getAttribute("foldertype") + " != " + item_type);
				continue;
			}
			// Get keyword, header and title
			var keyword = evalcolumns[i].getAttribute("keyword");
			var header = evalcolumns[i].getAttribute("header");
			var title = evalcolumns[i].getAttribute("title");
			Log(2, "INFO    => Evaluator   :Column: " + keyword);

			if (title && keyword) {
				//cmdline stores all code necessary for the rename preset used to get values
				//each entry is separated by '#_#'
				cmdline += '{=Val("eval:' + keyword + '")=}#_#';
				results.push({
					'name': title,
					'header': (header) ? header : title,
					'value': keyword
				});
			} else
				Log(1, 'WARNING => Evaluator   :"' + keyword + '" columns does not seems valid');
		}
		if (cmdline) {
			//'#_sep_#' to identify between Evaluator and sc cols values
			cmdline = cmdline.slice(0, -3);
			results[0] = '#_sep_#' + cmdline;
		}
	} else
		Log(1, "WARNING => Evaluator   :Error parsing Evaluator xml file");
	xmlDocEv = null;
	return results;
}

function CreateRenamePresetTxt(preset, to) {
	Log(2, 'INFO    => Creating rename preset "' + preset + '"');
	Log(2, "INFO    => Rename preset TO: " + to);
	to = to.replace(/&/g, '&amp;');
	to = to.replace(/"/g, '&quot;');
	to = to.replace(/</g, '&lt;');
	to = to.replace(/>/g, '&gt;');
	to = to.replace(/'/g, '&apos;');
	var content = '<?xml version="1.0" encoding="UTF-8"?>\r\n';
	content += '<rename_preset applynomatch="yes" case="none" script="yes" type="normal" version="13">\r\n\t<from></from>\r\n\t<to>';
	content += to + '</to>\r\n\t<script>@script JScript\r\n\t\t';
	content += 'function OnGetNewName(g) {DOpus.Vars.Set(&quot;' + preset + '&quot;, g.newname);return true;}\r\n\t</script>\r\n</rename_preset>';
	preset = DOpus.Aliases('dopusdata').path + '\\Rename Presets\\' + preset + '.orp';
	var file = DOpus.FSUtil.OpenFile(preset, 'w');
	if (file.error != 0) return false;
	try {
		var r = file.Write(content);
		file.Close();
	} catch (e) {
		Log(1, "WARNING => Can't write " + preset + ": " + e.description);
		r = 0;
	}
	file = null;
	if (r != 0) Log(2, "INFO    => Rename preset succesfully created: " + r + " bytes");
	return r;
}

function autoSizeDlg(dlg) {
	Log(2, "INFO    => Auto sizing dialog window based on current list content...");
	var lista = dlg.Control('columns_list');
	var w = lista.x * 2;
	var bottom_h = dlg.cy - lista.y - lista.cy;
	for (var i = 0; i < lista.columns.count; i++) w += lista.columns.getColumnAt(i).width;
	w += 50; //Add extra 50 px to width
	var mon_width = DOpus.Create.SysInfo.WorkAreas(0).width;
	var mon_height = DOpus.Create.SysInfo.WorkAreas(0).height;
	//don't make the dialog width bigger than 7/8 of screen size
	var max_width = Math.floor(DOpus.Create.SysInfo.WorkAreas(0).width * 7 / 8);
	//don't make the dialog height bigger than 7/8 of screen size
	var max_height = Math.floor(DOpus.Create.SysInfo.WorkAreas(0).height * 7 / 8);
	// 28 is an arbitrary row height
	var h = (lista.count + 1) * 28 + lista.y + bottom_h;
	if (h < dlg.cy) h = dlg.cy;
	else if (h > max_height) h = max_height;
	if (w > max_width) w = max_width;
	dlg.position = "absolute";
	dlg.position_fix = false;
	dlg.cx = w;
	dlg.cy = h;
	x = Math.floor((mon_width - w) / 2);
	y = Math.floor((mon_height - h) / 2);
	dlg.x = x;
	dlg.y = y;
	Log(2, "INFO    => Dialog metrics: X=" + x + "\tY=" + y + "\tW=" + w + "\tH=" + h);
}

function sizeDlg(dlg, mode) {
	Log(2, "INFO    => Resize dialog mode :" + ((mode == 0) ? " Autosize" : " Last saved"));
	if (mode == 0)
		autoSizeDlg(dlg);
	else
		dlg.LoadPosition("CommandViewers");
}

function ExistsinVector(vector, value) {
	for (var i = 0; i < vector.length; i++) {
		if (vector(i) == value) return true;
	}
	return false;
}

function copyToClip(sel_items, mode) {
	var clip = '';
	if (mode != 0) {}
	for (var i = 0; i < sel_items.length; i++) {
		//Copy selected keywords
		if (mode == 1)
			clip += sel_items(i).name + '\r\n';
		//Copy selected values
		else if (mode == 2)
			clip += sel_items(i).subitems(3) + '\r\n';
		//Copy selected keywords and values
		else if (mode == 3)
			clip += sel_items(i).name + '\t' + sel_items(i).subitems(3) + '\r\n';
		// Copy selected titles and values
		else if (mode == 4)
			clip += sel_items(i).subitems(0) + '\t' + sel_items(i).subitems(3) + '\r\n';
		// Copy selected headers and values
		else if (mode == 5)
			clip += sel_items(i).subitems(1) + '\t' + sel_items(i).subitems(3) + '\r\n';
		//Copy all 
		else if (mode == 6)
			clip += sel_items(i).name + '\t' + sel_items(i).subitems(0) + '\t' + sel_items(i).subitems(1) + '\t' + sel_items(i).subitems(2) + '\t' + sel_items(i).subitems(3) + '\r\n';
	}
	if (clip) DOpus.SetClip(clip.slice(0, -1));
}

function Log(level, text) {
	if (Script.config.debug >= level || level == 3) DOpus.Output(text);
}
==SCRIPT RESOURCES
<resources>
	<resource name="main" type="dialog">
		<dialog fontsize="9" height="282" lang="english" resize="yes" width="351">
			<control halign="left" height="12" name="editFilter" resize="w" tip="Filter entries" type="edit" width="240" x="24" y="5" />
			<control fullrow="yes" height="243" multisel="yes" name="columns_list" resize="wh" sort="yes" type="listview" viewmode="details" width="345" x="3" y="21">
				<columns>
					<item text="Name" />
					<item text="Label" />
					<item text="Header" />
					<item text="Type" />
					<item text="Value" />
				</columns>
			</control>
			<control height="12" name="btnClear" resize="x" title="❌" type="button" width="15" x="264" y="5" />
			<control height="12" name="btnRefresh" resize="x" title="Refresh" type="button" width="66" x="282" y="5" />
			<control halign="left" height="17" name="staticNotify" resize="yw" title="Total: 0" type="static" valign="center" width="99" x="117" y="264" />
			<control height="12" name="Categories" resize="y" type="combo" width="111" x="3" y="267" />
			<control halign="left" height="12" image="yes" name="search_icon" type="static" valign="center" width="15" x="6" y="5" />
			<control height="12" name="btnCopy" resize="xy" title="Copy Selection" type="button" visible="no" width="77" x="219" y="267" />
			<control close="0" default="yes" height="12" name="btnClose" resize="xy" title="Close" type="button" width="50" x="298" y="267" />
		</dialog>
	</resource>
	<resource type="strings">
		<strings lang="english">
			<string id="alert_no_file">Can&apos;t continue without a file!</string>
			<string id="debug">Logging level to be displayed. OFF to shows none. 
ALL to shows all the messages. 
WARNING to shows error conditions that are of consideration.</string>
			<string id="ignored_script_columns">List of all script filenames that you don&apos;t want to be used. 
All columns declared within those files will be ignored by this command.</string>
			<string id="sc_cols_custom_names">Script columns whose name does not match their base filename. One entry per line.
Fill in the form &quot;&lt;script_filename&gt;&quot;: &quot;&lt;name&gt;&quot;. Where &lt;name&gt; is the value that is used in ScriptInitData.name property in the script.
Eg: &quot;ColumnExifTool.js.txt&quot;: &quot;ExifTool&quot;</string>
			<string id="size_mode">Choose how the dialog window will resize when open.
AUTO : Auto resize based on screen resolution and list dimensions.
LAST USED: Remember the last window size and position.</string>
		</strings>
		<strings lang="esm">
			<string id="alert_no_file">!No se puede continuar sin un archivo!</string>
			<string id="debug">Nivel de registro a mostrar. OFF para no mostrar ninguno. 
INFO para mostrar todos los mensajes. 
WARNING para mostrar errores de consideración.</string>
			<string id="ignored_script_columns">Lista de todos los nombres de archivo de scripts que no desea utilizar.
Todas las columnas dentro del archivo serán ignoradas por este comando.</string>
			<string id="sc_cols_custom_names">Columnas de script cuyo nombre no coincide con su nombre de archivo base.
Llenar en la forma &quot;&lt;script_filename&gt;&quot;:&quot;&lt;name&gt;&quot;, donde &lt;name&gt; es el valor usado para ScriptInitData.name en el script.
Ej: &quot;ColumnExifTool.js.txt&quot;: &quot;ExifTool&quot;</string>
			<string id="size_mode">Elija como se redimensionará el diálogo al abrirse.
AUTO : Redimensionarse en base a la resolución de pantalla y el tamaño de la lista.
LAST USED: Recordar el último tamaño y posición de la ventana.</string>
		</strings>
		<strings lang="espanol">
			<string id="alert_no_file">!No se puede continuar sin un archivo!</string>
			<string id="debug">Nivel de registro a mostrar. OFF para no mostrar ninguno. 
INFO para mostrar todos los mensajes. 
WARNING para mostrar errores de consideración.</string>
			<string id="ignored_script_columns">Lista de todos los nombres de archivo de scripts que no desea utilizar.
Todas las columnas dentro del archivo serán ignoradas por este comando.</string>
			<string id="sc_cols_custom_names">Columnas de script cuyo nombre no coincide con su nombre de archivo base.
Llenar en la forma &quot;&lt;script_filename&gt;&quot;:&quot;&lt;name&gt;&quot;, donde &lt;name&gt; es el valor usado para ScriptInitData.name en el script.
Ej: &quot;ColumnExifTool.js.txt&quot;: &quot;ExifTool&quot;</string>
			<string id="size_mode">Elija cómo se abrirá el cuadro de diálogo.
AUTO : Elegir el tamaño en base a la resolución de pantalla y el tamaño de la lista.
LAST USED: Recordar el ul´timo tamaño y posición de la ventana.</string>
		</strings>
	</resource>
</resources>
