function OnInit(initData)
{
DOpus.ClearOutput
Log("0001000 OnInit Enter", true);
initData.name = "Command.SelectByDate";
initData.version = "1.31 (2021.10.30)";
initData.copyright = "(c) 2021 Felix";
initData.url = "https://resource.dopus.com/t/command-select-bydate-dynamic-command-to-select-files-by-various-dates-and-parameters/39697";
initData.desc = "Selecting files by date";
initData.default_enable = true;
initData.min_version = "12.0";
initData.group = "Command";
var cmd = initData.AddCommand();
cmd.name = "SelectByDate";
cmd.method = "OnSelectByDate";
cmd.desc = "Selecting files by date";
cmd.label = "SelectByDate";
//https://www.gpsoft.com.au/help/opus12/index.html#!Documents/Argument_Types.htm/S
//https://www.gpsoft.com.au/help/opus12/index.html#!Documents/Internal_Command_Arguments.htm
//cmd.template = "DATESOURCE/K[access,create,modify,doccreateddate,docedittime,doclastsaveddate,datedigitized,datetaken,recordingtime,releasedate,mp3year],ONLYFROMSELECTEDFILES/S";
cmd.template = "DATESOURCE/K[access,create,modify,doccreateddate,docedittime,doclastsaveddate,datedigitized,datetaken,recordingtime,releasedate],ONLYFROMSELECTEDITEMS/S,DEFAULTSELECTOR/K[matchingselector,bydate,bydaterange,bydatetimerange],ITEMTYPE/K[all,files,folders]";
cmd.hide = false;
cmd.icon = "setdate";
Log("0009010 OnInit Exit", true);
}
//Command entrypoint
function OnSelectByDate(scriptCmdData)
{
Log(" 0002000 OnSelectByDate Enter", true);
var source = scriptCmdData.func.sourcetab;
var args = scriptCmdData.func.args;
var dateSource = null;
var defaultSelector = args.got_arg.DEFAULTSELECTOR ? args.DEFAULTSELECTOR.toLowerCase() : null;
var defaultItemType = args.got_arg.ITEMTYPE ? args.ITEMTYPE.toLowerCase() : null;
var selectOnlyFromSelectedItems = args.got_arg.ONLYFROMSELECTEDITEMS ? true : null; //not pretty but used for dialog
if(!args.got_arg.DATESOURCE)
{
Log(" 0002010 !args.got_arg.DATESOURCE call ShowSourceDateSelectionDialog", true);
var result = ShowSourceDateSelectionDialog(scriptCmdData, selectOnlyFromSelectedItems, defaultSelector, defaultItemType);
if(!result)
return;
dateSource = result.dateSource;
selectOnlyFromSelectedItems = result.selectOnlyFromSelectedItems;
defaultSelector = result.defaultSelector;
defaultItemType = result.defaultItemType;
}
else
dateSource = args.DATESOURCE;
if(selectOnlyFromSelectedItems == null)
selectOnlyFromSelectedItems = false;
if(defaultItemType == null)
defaultItemType = "all";
Log(" 0002020 call RunSelectByDateCommand", true);
RunSelectByDateCommand(scriptCmdData, source, dateSource, defaultItemType, selectOnlyFromSelectedItems, defaultSelector, defaultItemType);
Log(" 0002090 OnSelectByDate Exit", true);
}
//Dialog where to choose source date, default selector and if select only from selected files
function ShowSourceDateSelectionDialog(scriptCmdData, selectOnlyFromSelectedItems, defaultSelector, defaultItemType)
{
Log(" 0003000 ShowSourceDateSelectionDialog Enter", true);
var tab = scriptCmdData.func.sourcetab;
var dlg = DOpus.Dlg;
dlg.window = tab;
dlg.template = "DateSourceSelectionDialog";
dlg.detach = false;
dlg.Create();
var itemTypes = ["all", "files", "folders"];
var comboSourceDate = dlg.Control("comboSourceDate");
var comboItemType = dlg.Control("comboItemType");
var comboDefaultSelector = dlg.Control("comboDefaultSelector");
var checkOnlySelectedItems = dlg.Control("checkOnlySelectedItems");
comboSourceDate.value = GetDefaultDate();
comboItemType.value = GetDefaultItemType(defaultItemType);
comboDefaultSelector.value = GetDefaultSelector(defaultSelector);
checkOnlySelectedItems.value = GetOnlyFromSelectedValue(selectOnlyFromSelectedItems);
var items = MapItemType(tab, itemTypes[comboItemType.value], true); //always true because here we only want to know count of selected items
var count = items ? items.count : 0;
checkOnlySelectedItems.label = "Select only from selected " + MapItemTypeToString(itemTypes[comboItemType.value]) + " (" + count + ")";
dlg.Show();
while (true)
{
var msg = dlg.GetMsg();
if (!msg.result)
break;
if(msg.event == "selchange" && msg.control == "comboItemType" || msg.event == "click" && msg.control == "checkOnlySelectedItems")
{
var items = MapItemType(tab, itemTypes[comboItemType.value], true);//always true because here we only want to know count of selected items
var count = items ? items.count : 0;
checkOnlySelectedItems.label = "Select only from selected " + MapItemTypeToString(itemTypes[comboItemType.value]) + " (" + count + ")";
}
}
var result = dlg.result; // Int Maybe 0=Ok 1=Cancel etc Button to close the dialog
if(result == 1) //ok
{
var selectedDateSourceIndex = comboSourceDate.value;
var selectedItemTypeIndex = comboItemType.value;
var selectedDefaultSelectorIndex = comboDefaultSelector.value;
var selectOnlyFromSelectedItems = checkOnlySelectedItems.value;
Script.vars.Set(LAST_PICKED_DATESOURCE, selectedDateSourceIndex);
Script.vars.Set(LAST_PICKED_DEFAULTSELECTOR, selectedDefaultSelectorIndex);
Script.vars.Set(LAST_PICKED_ITEM_TYPE, selectedItemTypeIndex);
Script.vars.Set(LAST_USED_ONLYFROMSELECTEDITEMS_VALUE, selectOnlyFromSelectedItems);
var dateSource = ["access", "create", "modify", "doccreateddate", "docedittime", "doclastsaveddate", "datedigitized", "datetaken", "recordingtime", "releasedate", "mp3year"][selectedDateSourceIndex];
defaultItemType = itemTypes[selectedItemTypeIndex];
defaultSelector = ["matchingselector","bydate","bydaterange","bydatetimerange"][selectedDefaultSelectorIndex];
Log(" 0003010 ShowSourceDateSelectionDialog result = 1 Exit", true);
return { dateSource : dateSource, selectOnlyFromSelectedItems : selectOnlyFromSelectedItems, defaultSelector : defaultSelector, defaultItemType : defaultItemType};
}
else if(result == 0) //cancel
{
Log(" 0003020 ShowSourceDateSelectionDialog result = 0 Exit", true);
return null;
}
}
var LAST_PICKED_DATESOURCE = "LastPickedDateSource";
var LAST_PICKED_DEFAULTSELECTOR = "LastPickedDefaultSelector";
var LAST_PICKED_ITEM_TYPE = "LastPickedItemType";
var LAST_USED_ONLYFROMSELECTEDITEMS_VALUE = "LastUsedOnlyFromSelectedItemsValue";
//Returns index for datesource which was picked last
function GetDefaultDate()
{
if(Script.vars.Exists(LAST_PICKED_DATESOURCE))
return Script.vars.Get(LAST_PICKED_DATESOURCE);
return 1;
}
//Get which selector to be default, if not specified get from settings else default value (by date)
function GetDefaultSelector(defaultSelector)
{
if(defaultSelector)
{
var selectors = ["matchingselector","bydate","bydaterange","bydatetimerange"];
for(var i = 0; i < selectors.length; i++)
if(selectors[i] == defaultSelector)
return i;
}
if(Script.vars.Exists(LAST_PICKED_DEFAULTSELECTOR))
return Script.vars.Get(LAST_PICKED_DEFAULTSELECTOR);
return 1;
}
//Select between all items, files onyl, folders only
function GetDefaultItemType(defaultItemType)
{
if(defaultItemType)
{
var itemTypes = ["all", "files", "folders"];
for(var i = 0; i < itemTypes.length; i++)
if(itemTypes[i] == defaultItemType)
return i;
}
if(Script.vars.Exists(LAST_PICKED_ITEM_TYPE))
return Script.vars.Get(LAST_PICKED_ITEM_TYPE);
return 0;
}
//Map to a readable string
function MapItemTypeToString(itemType)
{
if(itemType == null || itemType == "all")
return "items";
else
return itemType;
}
//return items depending on itemtype and selectOnlyFromSelectedItems
function MapItemType(tab, itemType, selectOnlyFromSelectedItems)
{
Log(itemType + " " + selectOnlyFromSelectedItems);
if(itemType == "all")
{
if(selectOnlyFromSelectedItems)
return tab.selected;
else
return tab.all;
}
else if(itemType == "files")
{
if(selectOnlyFromSelectedItems)
return tab.selected_files;
else
return tab.files;
}
else if(itemType == "folders")
{
if(selectOnlyFromSelectedItems)
return tab.selected_dirs;
else
return tab.dirs;
}
return null;
}
//Get if use the ONLYFROMSELECTEDFILES param either from args, settings or default value
function GetOnlyFromSelectedValue(selectOnlyFromSelectedItems)
{
if(selectOnlyFromSelectedItems) //could be null
return true;
if(Script.vars.Exists(LAST_USED_ONLYFROMSELECTEDITEMS_VALUE))
return Script.vars.Get(LAST_USED_ONLYFROMSELECTEDITEMS_VALUE);
return false;
}
//Actual functionality
function RunSelectByDateCommand(scriptCmdData, tab, dateSource, itemType, selectOnlyFromSelectedItems, defaultSelector)
{
Log(" 0004000 RunSelectByDateCommand Enter", true);
var cmd = scriptCmdData.func.command;
var progress = scriptCmdData.func.command.progress;
progress.abort = progress.pause = true;
var dateSelectorFunction = CreateSourceDateSelector(dateSource);
var result = ShowSelectionDetailsDialog(tab, dateSelectorFunction, dateSource, progress, itemType, selectOnlyFromSelectedItems, defaultSelector);
if(!result)
return;
progress.abort = progress.pause = false;
progress.Restart();
var filesToSelect = SelectFiles(tab, result.selectorFunction, result.cachedDates, result.fileCount, progress);
if(filesToSelect)
{
cmd.SetFiles(filesToSelect);
cmd.RunCommand("Select FROMSCRIPT EXACT MAKEVISIBLE SETFOCUS");
}
Log(" 0004090 RunSelectByDateCommand Exit", true);
}
//Display a dialog that shows the date ranges / selection options
function ShowSelectionDetailsDialog(tab, dateSelectorFunction, dateSource, progress, itemType, selectOnlyFromSelectedItems, defaultSelector)
{
Log(" 0010000 ShowSelectionDetailsDialog Enter", true);
var fileQueryResult = QueryFileDates(tab, dateSelectorFunction, dateSource, progress, itemType, selectOnlyFromSelectedItems);
if(!fileQueryResult)
return null;
var dlg = DOpus.Dlg;
dlg.window = tab;
if(fileQueryResult.validFileCount == 0)
{
dlg.message = "No files found in \"" + tab.path + "\" with '" + dateSource + "' property.";
dlg.buttons = "OK";
dlg.title = "No files found";
dlg.Show();
return null;
}
dlg.template = "SelectionDetailsDialog";
dlg.detach = true;
dlg.title = "How should the files be selected by '" + dateSource + "' date selector";
dlg.Create();
var comboDate = dlg.Control("comboDate");
var comboDateStart = dlg.Control("comboDateStart");
var comboDateEnd = dlg.Control("comboDateEnd");
var comboDateTimeStart = dlg.Control("comboDateTimeStart");
var comboDateTimeEnd = dlg.Control("comboDateTimeEnd");
var radioAllItemsMatching = dlg.Control("radioAllItemsMatching");
var radioDate = dlg.Control("radioDate");
var radioDateRange = dlg.Control("radioDateRange");
var radioDateTimeRange = dlg.Control("radioDateTimeRange");
var radiosDateSelectors =
{
"matchingselector" : radioAllItemsMatching,
"bydate" : radioDate,
"bydaterange" : radioDateRange,
"bydatetimerange" : radioDateTimeRange
};
if(defaultSelector)
radiosDateSelectors[defaultSelector].value = true;
for(var i = 0; i < fileQueryResult.dates.length; i++)
{
var item = fileQueryResult.dates[i];
comboDate.AddItem(item);
comboDateStart.AddItem(item);
comboDateEnd.AddItem(item);
}
for(var i = 0; i < fileQueryResult.dateTimes.length; i++)
{
var item = fileQueryResult.dateTimes[i];
comboDateTimeStart.AddItem(item);
comboDateTimeEnd.AddItem(item);
}
Log(" 0010000 ShowSelectionDetailsDialog Line 315", true);
radioAllItemsMatching.title = "All items matching '" + dateSource + "' date selector (" + fileQueryResult.validFileCount + ")";
Log(" 0010000 ShowSelectionDetailsDialog Line 317", true);
comboDate.value = comboDateStart.value = comboDateTimeStart.value = 0;
comboDateEnd.value = fileQueryResult.dates.length > 1 ? 1 : 0;
comboDateTimeEnd.value = fileQueryResult.dateTimes.length > 1 ? 1 : 0;
dlg.Show();
while (true)
{
var msg = dlg.GetMsg();
if (!msg.result)
break;
//Log("Msg Event = " + msg.event + " by " + msg.control);
if (msg.event == "click")
{
if(msg.control == "buttonOK")
{
if(radioAllItemsMatching.value)
{
var selectorFunction = function(date)
{
//Log("Selector function: Contains datesource");
return dateSelectorFunction(date) != null;
}
return {selectorFunction : selectorFunction, fileCount : fileQueryResult.validFileCount, cachedDates : fileQueryResult.cachedDates };
}
else if(radioDate.value)
{
var selectorFunction = function(date)
{
if(date)
{
//Log("Selector function: Date " + date.Format("D#yyyy.MM.dd") + " == " + fileQueryResult.dates[comboDate.value]);
return date.Format("D#yyyy.MM.dd") == fileQueryResult.dates[comboDate.value];
}
return false;
}
return {selectorFunction : selectorFunction, fileCount : fileQueryResult.validFileCount, cachedDates : fileQueryResult.cachedDates };
}
else if(radioDateRange.value)
{
var startDate = fileQueryResult.dates[comboDateStart.value];
var endDate = fileQueryResult.dates[comboDateEnd.value];
if(endDate < startDate)
{
var tmp = startDate;
startDate = endDate;
endDate = tmp;
}
var selectorFunction = function(date)
{
if(date)
{
//Log("Selector function: Date range " + startDate + " <= " + date.Format("D#yyyy.MM.dd") + " && " + date.Format("D#yyyy.MM.dd") + " <= " + endDate);
var itemDate = date.Format("D#yyyy.MM.dd");
return startDate <= itemDate && itemDate <= endDate;
}
return false;
}
return {selectorFunction : selectorFunction, fileCount : fileQueryResult.validFileCount, cachedDates : fileQueryResult.cachedDates };
}
else if(radioDateTimeRange.value)
{
var startDateTime = fileQueryResult.dateTimes[comboDateTimeStart.value];
var endDateTime = fileQueryResult.dateTimes[comboDateTimeEnd.value];
if(endDateTime < startDateTime)
{
var tmp = startDateTime;
startDateTime = endDateTime;
endDateTime = tmp;
}
var selectorFunction = function(date)
{
if(date)
{
//Log("Selector function: Date time range " + startDateTime + " <= " + date.Format("D#yyyy.MM.dd T#HH:mm:ss") + " && " + date.Format("D#yyyy.MM.dd T#HH:mm:ss") + " <= " + endDateTime);
var itemDate = date.Format("D#yyyy.MM.dd T#HH:mm:ss");
return startDateTime <= itemDate && itemDate <= endDateTime;
}
return false;
}
return {selectorFunction : selectorFunction, fileCount : fileQueryResult.validFileCount, cachedDates : fileQueryResult.cachedDates };
}
}
}
else if(msg.event == "selchange")
{
if(msg.control == "comboDate")
{
radioDate.value = true;
}
if(msg.control == "comboDateStart")
{
radioDateRange.value = true;
if(comboDateStart.value >= comboDateEnd.value)
if(comboDateEnd.value < fileQueryResult.dates.length - 1)//there are enough items in the list
comboDateEnd.SelectItem(comboDateStart.value + 1);
}
else if(msg.control == "comboDateEnd")
{
radioDateRange.value = true;
if(comboDateStart.value >= comboDateEnd.value)
if(comboDateStart.value > 1)
comboDateStart.SelectItem(comboDateEnd.value - 1);
}
else if(msg.control == "comboDateTimeStart")
{
radioDateTimeRange.value = true;
if(comboDateTimeStart.value >= comboDateTimeEnd.value)
if(comboDateTimeEnd.value < fileQueryResult.dateTimes.length - 1)//there are enough items in the list
comboDateTimeEnd.SelectItem(comboDateTimeStart.value + 1);
}
else if(msg.control == "comboDateTimeEnd")
{
radioDateTimeRange.value = true;
if(comboDateTimeStart.value >= comboDateTimeEnd.value)
if(comboDateTimeStart.value > 1)
comboDateTimeStart.SelectItem(comboDateTimeEnd.value - 1);
}
}
}
return null;
Log(" 0010010 ShowSelectionDetailsDialog Exit", true);
}
//Create and return a function that selects the desired date according to the params of the command
function CreateSourceDateSelector(arg)
{
var dateSelector = function(item) //default is create
{
return item.create;
};
if(arg)
{
arg = arg.toLowerCase();
if(arg == "access")
dateSelector = function(item)
{
return item.access;
};
else if(arg == "modify")
dateSelector = function(item)
{
return item.modify;
};
else if(arg == "doccreateddate")
dateSelector = function(item)
{
if(item.metadata)
{
if(item.metadata == "doc")
return item.metadata.doc.doccreateddate;
}
return null;
};
else if(arg == "docedittime")
dateSelector = function(item)
{
if(item.metadata)
{
if(item.metadata == "doc")
return item.metadata.doc.docedittime;
}
return null;
};
else if(arg == "doclastsaveddate")
dateSelector = function(item)
{
if(item.metadata)
{
if(item.metadata == "doc")
return item.metadata.doc.doclastsaveddate;
}
return null;
};
else if(arg == "datedigitized")
dateSelector = function(item)
{
if(item.metadata)
{
if(item.metadata == "image")
return item.metadata.image.datedigitized;
}
return null;
};
else if(arg == "datetaken")
dateSelector = function(item)
{
if(item.metadata)
{
if(item.metadata == "image")
return item.metadata.image.datetaken;
}
return null;
};
else if(arg == "recordingtime")
dateSelector = function(item)
{
if(item.metadata)
{
if(item.metadata == "video")
return item.metadata.video.recordingtime;
}
return null;
};
else if(arg == "releasedate")
dateSelector = function(item)
{
if(item.metadata)
{
if(item.metadata == "audio")
return item.metadata.audio.releasedate;
}
return null;
};
/*
else if(arg == "mp3year")
dateSelector = function(item)
{
if(item.metadata)
{
if(item.metadata == "audio")
return item.metadata.audio.mp3year; //this brings problems as it is a number, not a date
}
return null;
};
*/
}
return dateSelector;
}
//Enumerate the dates in a specified tab
function QueryFileDates(tab, dateSelector, dateSource, progress, itemType, selectOnlyFromSelectedItems)
{
var path = tab.path;
var minDate = DOpus.Create.Date();
var maxDate = DOpus.Create.Date();
var dates = [];
var dateTimes = [];
var cachedDates = {};
var items = MapItemType(tab, itemType, selectOnlyFromSelectedItems);
if(!items)
{
Log("No items mappable", true);
return;
}
if(selectOnlyFromSelectedItems && items.count == 0)
{
var dlg = DOpus.Dlg;
dlg.window = tab;
dlg.buttons = "Yes|Cancel";
dlg.title = "No items in selection";
dlg.message = "Select.ByDate was started with the \"ONLYFROMSELECTEDITEMS\" option but there are no selected items. Select from all items instead?";
var result = dlg.Show();
if(result == 1)
{
items = MapItemType(tab, itemType, false);
}
else
return null;
}
progress.Init(tab, "Querying date information in '" + tab.path + "'");
progress.SetStatus("Querying 0/" + items.count + " items");
progress.SetFiles(items.count);
DOpus.Delay(200);
progress.Show();
var processedFilesCount = 0;
var validFileCount = 0;
var fileEnum = new Enumerator(items);
while (!fileEnum.atEnd())
{
var abortState = progress.GetAbortState();
if (abortState == "a")
{
return null;
}
else if (abortState == "p")
{
DOpus.Delay(500);
continue;
}
var item = fileEnum.item();
var date = dateSelector(item);
if(date)
{
if(maxDate < date)
maxDate = date;
else if(date < minDate)
minDate = date;
var datePart = date.Format("D#yyyy.MM.dd")
if(!ArrayIncludes(dates, datePart))
dates.push(datePart);
var dateTime = date.Format("D#yyyy.MM.dd T#HH:mm:ss");
if(!ArrayIncludes(dateTimes, dateTime))
dateTimes.push(dateTime);
cachedDates[item] = date;
validFileCount++;
}
fileEnum.moveNext();
progress.SetStatus("Querying " + ++processedFilesCount + "/" + items.count + " items (" + validFileCount + " items with '" + dateSource + "')");
progress.SetFilesProgress(processedFilesCount);
}
DOpus.Delay(800);//progress Bug workaround
progress.Hide();
dates = dates.sort();
dateTimes = dateTimes.sort();
return { minDate: minDate, maxDate: maxDate, dates: dates, dateTimes: dateTimes, validFileCount: validFileCount, cachedDates : cachedDates };
}
//Select files in source
function SelectFiles(tab, selectorFunction, cachedDates, fileCount, progress)
{
var selectedFilesResultVector = DOpus.Create.Vector();
progress.SetStatus("Selecting 0/" + fileCount + " files");
progress.SetFiles(fileCount);
DOpus.Delay(200);
progress.Show();
var processedFilesCount = 0;
for(var file in cachedDates)
{
var date = cachedDates[file];
if(selectorFunction(date))
{
selectedFilesResultVector.push_back(file);
}
progress.SetStatus("Selecting " + processedFilesCount + "/" + fileCount + " files");
progress.SetFilesProgress(processedFilesCount++);
}
progress.Hide();
return selectedFilesResultVector;
}
function ArrayIncludes(array, item)
{
for(var i = 0; i < array.length; i++)
if(array[i] == item)
return true;
return false;
}
function Log(msg, e)
{
DOpus.output(String(msg), e || false);
}
// //maybe in a next release
==SCRIPT RESOURCES