This is a delete menu button for the image viewer.
The main functionality is a dialog where you can choose to delete files with the same name but different extension (eg you view the jpg and want to delete the raw and xmp sidecar file at once). You can also set if you want do confirm deletions and if to send them to the recycle bin. These settings are saved in global variables and are accessible for the two other buttons (delete raw, delete both which do not offer a dialog).
<?xml version="1.0"?>
<button backcol="none" display="both" label_pos="right" separate="yes" textcol="none" type="menu_button">
<label>Delete</label>
<hotkeys>
<key>delete</key>
<key>shift+delete</key>
</hotkeys>
<icon1>#delete</icon1>
<function type="normal">
<instruction>Show VIEWERCMD=delete</instruction>
</function>
<button backcol="none" display="both" hotkey="alt+delete" label_pos="right" textcol="none">
<label>Delete Raw\tAlt + Entf</label>
<icon1>#deletefilter</icon1>
<function type="script">
<instruction>@script JScript</instruction>
<instruction>// (c) Felix Frömel 2022</instruction>
<instruction>// v1.1 (2022-03-20)</instruction>
<instruction>function OnClick(clickData)</instruction>
<instruction>{</instruction>
<instruction> var viewer = clickData.func.viewer;</instruction>
<instruction> var current = viewer.current;</instruction>
<instruction> var tab = viewer.parenttab;</instruction>
<instruction> var cmd = clickData.func.command;</instruction>
<instruction />
<instruction> var raw = GetRaw(current);</instruction>
<instruction> if(raw)</instruction>
<instruction> { </instruction>
<instruction> var cmdLine = "Delete " + (GetConfirmDelete() ? "" : "Quiet ") + (GetSendToRecycleBin() ? "" : "NORECYCLE");</instruction>
<instruction> cmd.AddLine(cmdLine);</instruction>
<instruction> cmd.AddFile(raw);</instruction>
<instruction> cmd.AddLine("Show VIEWERCMD=refresh");</instruction>
<instruction> Log(cmdLine);</instruction>
<instruction> viewer.Command(cmd); //show the confirmation dialog on top of the viewer instead of the lister</instruction>
<instruction> }</instruction>
<instruction> else</instruction>
<instruction> Log("No raw image found for deletion");</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function GetRaw(item)</instruction>
<instruction>{</instruction>
<instruction> return GetFile(item, [".nef", ".dng", ".cr2", ".cr3"]);</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function GetFile(item, extensions)</instruction>
<instruction>{</instruction>
<instruction> var basePath = item.realpath.pathpart + "\\" + item.realpath.stem;</instruction>
<instruction> for(var i = 0; i < extensions.length; i++)</instruction>
<instruction> {</instruction>
<instruction> var path = basePath + extensions[i];</instruction>
<instruction> if(DOpus.FSUtil.Exists(path))</instruction>
<instruction> {</instruction>
<instruction> return DOpus.FSUtil.GetItem(path);</instruction>
<instruction> }</instruction>
<instruction> }</instruction>
<instruction> return null;</instruction>
<instruction>}</instruction>
<instruction />
<instruction />
<instruction>var ConfirmationDialogKey = "DeleteOptions.ConfirmDelete";</instruction>
<instruction />
<instruction>function GetConfirmDelete()</instruction>
<instruction>{</instruction>
<instruction> var vars = DOpus.vars;</instruction>
<instruction> if(vars.Exists(ConfirmationDialogKey))</instruction>
<instruction> return vars.Get(ConfirmationDialogKey);</instruction>
<instruction> </instruction>
<instruction> return true;</instruction>
<instruction>}</instruction>
<instruction />
<instruction>var SendToRecycleBinKey = "DeleteOptions.SendToRecycleBin";</instruction>
<instruction />
<instruction>function GetSendToRecycleBin()</instruction>
<instruction>{</instruction>
<instruction> var vars = DOpus.vars;</instruction>
<instruction> if(vars.Exists(SendToRecycleBinKey))</instruction>
<instruction> return vars.Get(SendToRecycleBinKey);</instruction>
<instruction> </instruction>
<instruction> return true;</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function Log(msg){DOpus.Output(String(msg));}</instruction>
</function>
</button>
<button backcol="none" display="both" hotkey="ctrl+shift+delete" label_pos="right" textcol="none">
<label>Delete Both\tShift + Entf</label>
<icon1>#deletesecure</icon1>
<function type="script">
<instruction>@script JScript</instruction>
<instruction>// (c) Felix Frömel 2022</instruction>
<instruction>// v1.1 (2022-03-20)</instruction>
<instruction />
<instruction>function OnClick(clickData)</instruction>
<instruction>{</instruction>
<instruction> var viewer = clickData.func.viewer;</instruction>
<instruction> var current = viewer.current;</instruction>
<instruction> var tab = viewer.parenttab;</instruction>
<instruction> var cmd = clickData.func.command;</instruction>
<instruction />
<instruction> var img = GetImage(current);</instruction>
<instruction> var raw = GetRaw(current);</instruction>
<instruction> if(img || raw)</instruction>
<instruction> { </instruction>
<instruction> if(! img && raw)</instruction>
<instruction> Log("Just one image type found for deletion");</instruction>
<instruction> </instruction>
<instruction> var cmdLine = "Delete " + (GetConfirmDelete() ? "" : "Quiet ") + (GetSendToRecycleBin() ? "" : "NORECYCLE");</instruction>
<instruction> cmd.AddLine(cmdLine);</instruction>
<instruction> if(img)</instruction>
<instruction> cmd.AddFile(img);</instruction>
<instruction> if(raw)</instruction>
<instruction> cmd.AddFile(raw);</instruction>
<instruction> cmd.AddLine("Show VIEWERCMD=refresh");</instruction>
<instruction> Log(cmdLine);</instruction>
<instruction> viewer.Command(cmd); //show the confirmation dialog on top of the viewer instead of the lister</instruction>
<instruction> }</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function GetImage(item)</instruction>
<instruction>{</instruction>
<instruction> return GetFile(item, [".bmp", ".gif", ".heic", ".jpe", ".jpg", ".jpeg", ".png"]);</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function GetRaw(item)</instruction>
<instruction>{</instruction>
<instruction> return GetFile(item, [".nef", ".dng", ".cr2", ".cr3"]);</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function GetFile(item, extensions)</instruction>
<instruction>{</instruction>
<instruction> var basePath = item.realpath.pathpart + "\\" + item.realpath.stem;</instruction>
<instruction> for(var i = 0; i < extensions.length; i++)</instruction>
<instruction> {</instruction>
<instruction> var path = basePath + extensions[i];</instruction>
<instruction> if(DOpus.FSUtil.Exists(path))</instruction>
<instruction> {</instruction>
<instruction> return DOpus.FSUtil.GetItem(path);</instruction>
<instruction> }</instruction>
<instruction> }</instruction>
<instruction> return null;</instruction>
<instruction>}</instruction>
<instruction />
<instruction />
<instruction>var ConfirmationDialogKey = "DeleteOptions.ConfirmDelete";</instruction>
<instruction />
<instruction>function GetConfirmDelete()</instruction>
<instruction>{</instruction>
<instruction> var vars = DOpus.vars;</instruction>
<instruction> if(vars.Exists(ConfirmationDialogKey))</instruction>
<instruction> return vars.Get(ConfirmationDialogKey);</instruction>
<instruction> </instruction>
<instruction> return true;</instruction>
<instruction>}</instruction>
<instruction />
<instruction>var SendToRecycleBinKey = "DeleteOptions.SendToRecycleBin";</instruction>
<instruction />
<instruction>function GetSendToRecycleBin()</instruction>
<instruction>{</instruction>
<instruction> var vars = DOpus.vars;</instruction>
<instruction> if(vars.Exists(SendToRecycleBinKey))</instruction>
<instruction> return vars.Get(SendToRecycleBinKey);</instruction>
<instruction> </instruction>
<instruction> return true;</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function Log(msg){DOpus.Output(String(msg));}</instruction>
</function>
</button>
<button backcol="none" display="both" hotkey="ctrl+delete" label_pos="right" textcol="none">
<label>Delete Options\tCtrl + Del</label>
<icon1>#deletecollection</icon1>
<function type="script">
<instruction>@script JScript</instruction>
<instruction>// (c) Felix Frömel 2022</instruction>
<instruction>// v1.1 (2022-03-20)</instruction>
<instruction />
<instruction>function OnClick(clickData)</instruction>
<instruction>{</instruction>
<instruction> var viewer = clickData.func.viewer;</instruction>
<instruction> var current = viewer.current;</instruction>
<instruction> var tab = viewer.parenttab;</instruction>
<instruction> var cmd = clickData.func.command;</instruction>
<instruction />
<instruction> var imgType = GetImageType(current.ext);</instruction>
<instruction />
<instruction> var img = GetImage(current);</instruction>
<instruction> var raw = GetRaw(current);</instruction>
<instruction> var xmp = GetXMP(current);</instruction>
<instruction> </instruction>
<instruction> var buttons = "";</instruction>
<instruction> var deleteFunctions = [];</instruction>
<instruction> var foundTypes = 0;</instruction>
<instruction> </instruction>
<instruction> var dlg = clickData.func.Dlg;</instruction>
<instruction> dlg.icon = "warning";</instruction>
<instruction> dlg.message = "Current image '" + current.name + "'\nFolder '" + current.realpath.pathpart + "'\n\nDelete ...";</instruction>
<instruction> dlg.title = "Delete matching";</instruction>
<instruction> dlg.options(0).label = "Confirm deletion";</instruction>
<instruction> dlg.options(0).state = GetConfirmDelete();</instruction>
<instruction> dlg.options(1).label = "Send to recycle bin";</instruction>
<instruction> dlg.options(1).state = GetSendToRecycleBin();</instruction>
<instruction> </instruction>
<instruction> if(img)</instruction>
<instruction> {</instruction>
<instruction> buttons += "Image (" + img.ext + ")|";</instruction>
<instruction> deleteFunctions.push(function () { Log("img"); Delete(tab, cmd, viewer, img); });</instruction>
<instruction> foundTypes++;</instruction>
<instruction> if(raw && imgType == "image")</instruction>
<instruction> dlg.defid = 2;</instruction>
<instruction> } </instruction>
<instruction> if(raw)</instruction>
<instruction> {</instruction>
<instruction> buttons += "Raw (" + raw.ext + ")|";</instruction>
<instruction> deleteFunctions.push(function () { Log("raw"); Delete(tab, cmd, viewer, raw); });</instruction>
<instruction> foundTypes++;</instruction>
<instruction> if(img && imgType == "raw")</instruction>
<instruction> dlg.defid = 1;</instruction>
<instruction> }</instruction>
<instruction> if(xmp)</instruction>
<instruction> {</instruction>
<instruction> buttons += "XMP (" + xmp.ext + ")|";</instruction>
<instruction> deleteFunctions.push(function () { Log("xmp"); Delete(tab, cmd, viewer, xmp); });</instruction>
<instruction> foundTypes++;</instruction>
<instruction> }</instruction>
<instruction> if(raw && xmp)</instruction>
<instruction> {</instruction>
<instruction> buttons += "Raw and XMP|";</instruction>
<instruction> deleteFunctions.push(function () { Log("raw+xmp"); Delete(tab, cmd, viewer, raw, xmp); });</instruction>
<instruction> }</instruction>
<instruction> if(foundTypes > 1)</instruction>
<instruction> {</instruction>
<instruction> buttons += "All (" + foundTypes + ")|";</instruction>
<instruction> if(img)</instruction>
<instruction> {</instruction>
<instruction> if(raw)</instruction>
<instruction> {</instruction>
<instruction> if(xmp)</instruction>
<instruction> deleteFunctions.push(function () { Log("All"); Delete(tab, cmd, viewer, img, raw, xmp); });</instruction>
<instruction> else</instruction>
<instruction> deleteFunctions.push(function () { Log("All"); Delete(tab, cmd, viewer, img, raw); });</instruction>
<instruction> }</instruction>
<instruction> else if(xmp)</instruction>
<instruction> deleteFunctions.push(function () { Log("All"); Delete(tab, cmd, viewer, img, xmp); });</instruction>
<instruction> }</instruction>
<instruction> else if(raw)</instruction>
<instruction> {</instruction>
<instruction> if(xmp)</instruction>
<instruction> deleteFunctions.push(function () { Log("All"); Delete(tab, cmd, viewer, raw, xmp); });</instruction>
<instruction> }</instruction>
<instruction> }</instruction>
<instruction />
<instruction> buttons += "Cancel";</instruction>
<instruction> deleteFunctions.splice(0, 0, function () { Log("cancel"); return; }); //cancel button retuns 0</instruction>
<instruction> //https://stackoverflow.com/questions/586182/how-to-insert-an-item-into-an-array-at-a-specific-index-javascript</instruction>
<instruction />
<instruction> dlg.buttons = buttons;</instruction>
<instruction> var result = dlg.Show();</instruction>
<instruction />
<instruction> if(result > 0)</instruction>
<instruction> {</instruction>
<instruction> SetConfirmDelete(dlg.options(0).state);</instruction>
<instruction> SetSendToRecycleBin(dlg.options(1).state);</instruction>
<instruction> }</instruction>
<instruction> </instruction>
<instruction> deleteFunctions[result]();</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function Delete()</instruction>
<instruction>{</instruction>
<instruction> var tab = arguments[0];</instruction>
<instruction> var cmd = arguments[1];</instruction>
<instruction> var viewer = arguments[2];</instruction>
<instruction />
<instruction> Log("Found " + (arguments.length - 3) + " images for deletion");</instruction>
<instruction />
<instruction> for(var i=3;i<arguments.length;i++)</instruction>
<instruction> cmd.AddFile(arguments[i]);</instruction>
<instruction />
<instruction> var cmdLine = "Delete " + (GetConfirmDelete() ? "" : "Quiet ") + (GetSendToRecycleBin() ? "" : "NORECYCLE");</instruction>
<instruction> cmd.AddLine(cmdLine);</instruction>
<instruction> cmd.AddLine("Show VIEWERCMD=refresh");</instruction>
<instruction> Log(cmdLine);</instruction>
<instruction> viewer.Command(cmd); //show the confirmation dialog on top of the viewer instead of the lister</instruction>
<instruction>}</instruction>
<instruction />
<instruction>var ConfirmationDialogKey = "DeleteOptions.ConfirmDelete";</instruction>
<instruction />
<instruction>function GetConfirmDelete()</instruction>
<instruction>{</instruction>
<instruction> var vars = DOpus.vars;</instruction>
<instruction> if(vars.Exists(ConfirmationDialogKey))</instruction>
<instruction> return vars.Get(ConfirmationDialogKey);</instruction>
<instruction> </instruction>
<instruction> return true;</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function SetConfirmDelete(enabled)</instruction>
<instruction>{</instruction>
<instruction> DOpus.vars.Set(ConfirmationDialogKey, enabled);</instruction>
<instruction> DOpus.vars(ConfirmationDialogKey).persist = true;</instruction>
<instruction>}</instruction>
<instruction />
<instruction />
<instruction>var SendToRecycleBinKey = "DeleteOptions.SendToRecycleBin";</instruction>
<instruction />
<instruction>function GetSendToRecycleBin()</instruction>
<instruction>{</instruction>
<instruction> var vars = DOpus.vars;</instruction>
<instruction> if(vars.Exists(SendToRecycleBinKey))</instruction>
<instruction> return vars.Get(SendToRecycleBinKey);</instruction>
<instruction> </instruction>
<instruction> return true;</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function SetSendToRecycleBin(enabled)</instruction>
<instruction>{</instruction>
<instruction> DOpus.vars.Set(SendToRecycleBinKey, enabled);</instruction>
<instruction> DOpus.vars(SendToRecycleBinKey).persist = true;</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function GetImageType(extension)</instruction>
<instruction>{</instruction>
<instruction> extension = extension.toLowerCase();</instruction>
<instruction> switch(extension)</instruction>
<instruction> {</instruction>
<instruction> case ".bmp":</instruction>
<instruction> case ".gif":</instruction>
<instruction> case ".heic":</instruction>
<instruction> case ".jpe":</instruction>
<instruction> case ".jpg":</instruction>
<instruction> case ".jpeg":</instruction>
<instruction> case ".png":</instruction>
<instruction> return "image";</instruction>
<instruction> case ".nef":</instruction>
<instruction> case ".dng":</instruction>
<instruction> case ".cr2":</instruction>
<instruction> case ".cr3":</instruction>
<instruction> return "raw";</instruction>
<instruction> }</instruction>
<instruction />
<instruction> return "unknown";</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function GetXMP(item)</instruction>
<instruction>{</instruction>
<instruction> var basePath = item.realpath.pathpart + "\\" + item.realpath.stem;</instruction>
<instruction> var path = basePath + ".xmp";</instruction>
<instruction> if(DOpus.FSUtil.Exists(path))</instruction>
<instruction> return DOpus.FSUtil.GetItem(path);</instruction>
<instruction />
<instruction> return null;</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function GetImage(item)</instruction>
<instruction>{</instruction>
<instruction> return GetFile(item, [".bmp", ".gif", ".heic", ".jpe", ".jpg", ".jpeg", ".png"]);</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function GetRaw(item)</instruction>
<instruction>{</instruction>
<instruction> return GetFile(item, [".nef", ".dng", ".cr2", ".cr3"]);</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function GetFile(item, extensions)</instruction>
<instruction>{</instruction>
<instruction> var basePath = item.realpath.pathpart + "\\" + item.realpath.stem;</instruction>
<instruction> for(var i = 0; i < extensions.length; i++)</instruction>
<instruction> {</instruction>
<instruction> var path = basePath + extensions[i];</instruction>
<instruction> if(DOpus.FSUtil.Exists(path))</instruction>
<instruction> {</instruction>
<instruction> return DOpus.FSUtil.GetItem(path);</instruction>
<instruction> }</instruction>
<instruction> }</instruction>
<instruction> return null;</instruction>
<instruction>}</instruction>
<instruction />
<instruction>function Log(msg){DOpus.Output(String(msg));}</instruction>
</function>
</button>
</button>
Download
v1.1 (2022-03-20) Delete.dcf (20.0 KB) had a wrong call in the "delete options" button so that it didnt delete the image as requested. please update
v1.0 (2022-03-17) Delete.dcf (20.0 KB)
Installation
Edit your viewer toolbar via context menu and either drag and drop the dcf file where you want the menu button or copy the code above and paste it via contextmenu to the toolbar.