I want to use a Combobox in DOpus scripts. How do I do this?
There's an example here:
Can we have a simple new parameter? This will make it easier for people to write scripts.
e.g.
DOpus.input(topic, [notes], [default value], [style], [cancel], [width], [height], [items], [icon])
or shorter:
DOpus.input(topic, [notes], [default value], [style], [items], [icon])
You can add the drop-down options very easily in the resource editor GUI. They don't need to be in the code at all.
(Just realised the Pulldown_Array
thing in the example code I linked to doesn't do anything and that whole line could be deleted. It was left over from the original code earlier in that thread.)
I tried it a few months ago. i need this combobox:
Is it possible to trigger that drop-down list when the down key is pressed?
/*
===============================================================================
Name : ComboX
Function : Edit and drop-down Combo box template
Created : 2022-11-21
Modified : 2022-11-22
Version : v0.2
===============================================================================
*/
function OnClick(clickData)
{
var text = "item1, item2, item3, item4, item5, item6"; //Text
var dlg = DOpus.Dlg;
dlg.title = "Directory Opus"; // Title
dlg.template = "dlgCombox";
dlg.detach = true;
dlg.Create();
dlg.Control("static").style = "b";
dlg.Control("static").label = "Topic"; // Topic
dlg.Control("static2").label = "Notes"; // Notes
dlg.Control("static3").label = "D:\\Icons\\XYplorer Search Find.png"; // Icon
var myArray = text.split(", "); //Seprator
dlg.Control("combo").label = myArray[0]; // Defalut value
dlg.Control("combo").SelectRange(0, -1); // Select defalut value
for(i = 0; myArray[i]; i++) {
dlg.Control("combo").AddItem(myArray[i]); //Add each item to drop-down list
}
dlg.Show();
// msg loop
do
{
msg = dlg.GetMsg();
/*
// Selection
if(msg == true && dlg.Control("combo").focus == true) {
DOpus.Output(dlg.Control("combo").label);
}
*/
// Result
if(dlg.result == 1) {
DOpus.Output(dlg.Control("combo").label);
}
//If the button 1 is pressed
if(dlg.result == 3) {
DOpus.Output("Button 1 is pressed");
}
//If the button 2 is pressed
if(dlg.result == 4) {
DOpus.Output("Button 2 is pressed");
}
} while (msg == true);
}
==SCRIPT RESOURCES
<resources>
<resource name="dlgCombox" type="dialog">
<dialog fontsize="8" height="100" lang="english" resize="yes" standard_buttons="ok,cancel" title="Directory Opus" width="320">
<control edit="yes" height="40" name="combo" type="combo" width="305" x="8" y="60" />
<control close="3" height="14" name="btn1" resize="xy" title="&1" type="button" width="50" x="104" y="82" />
<control close="4" height="14" name="btn2" resize="xy" title="&2" type="button" width="50" x="158" y="82" />
<control halign="left" height="16" name="static" title="Topic" type="static" valign="top" width="279" x="28" y="11" />
<control halign="left" height="16" name="static2" title="Notes" type="static" valign="top" width="279" x="28" y="35" />
<control halign="center" height="14" image="yes" name="static3" title="Icon" type="static" valign="top" width="14" x="8" y="8" />
</dialog>
</resource>
</resources>
F4 opens the focused drop-down in Windows (for standard controls, at least).
I like to press the down key directly. How to add internal icon to dialogs?
Invalid:
dlg.Control("static3").label = "copy"; // Icon
The down arrow / cursor key will go to the next option in the drop-down without opening it. (This is standard Windows drop-down behavior and not specific to Opus.)
See Load icon(internal sets) to control.label property in a script dialog - #2 by Leo
Hi Guys;
This script shows AI's current limitations. As the saying goes, ‘Everyone has ideas, but only a few can execute these ideas';. However, I am now using ChatGPT's state-of-the-art AI model 'o1' and Claude 3.5 Sonnet; neither model has the necessary intelligence or data to solve my problem. After many iterations, here is the code they produced. The final code was analysed using 'o1', and it still doesn't work even though I have shown it many DO Scripting examples, including WKen's combo-box example. So here is the idea I think of as an automatic file in folder cleanup assistant. Here is what it is supposed to do, as accurately summarised by Claude 3.5 Sonnet:
If anyone is up for the challenge, I would love to see this become part of the DO toolkit. I don't want any recognition for the idea. As I said, ideas are cheap. Here is what the script is supposed to do. You can even add other things like dated sub-folders if you like.
Purpose
- This is a Directory Opus script (JScript API) for file management
- Creates a utility to move selected files into new or existing subfolders
- Runs within Directory Opus file manager environment
Key Components
-
Dialog Interface
- Shows combo box for existing subfolders
- Provides text input for new folder creation
- Includes checkbox for extension-based sorting
-
File Operations
- Reads current Directory Opus tab location
- Lists existing subfolders
- Moves selected files to target folder
- Handles file operation progress
-
Directory Opus Integration
- Uses DOpus JScript API
- Integrates with Directory Opus UI
- Manages file system operations safely
Core Functionality
-
User Selection
- User selects files in Directory Opus
- Script shows dialog for destination
- Choose existing or create new subfolder
-
File Movement
- Safe file moves with progress tracking
- Handles existing file conflicts
- Reports success/failure status
-
Error Handling
- Validates folder names
- Manages file system errors
- Provides operation feedback
Target API
- Directory Opus JScript API
- Specifically targeting Dialog and FileSystem operations
- Uses DOpus.FSUtil for file operations
- Integrates with DOpus.Dlg for UI
Would you like me to proceed with suggesting improvements to specific areas of this functionality?
The AI implementation which continues to have parser errors:
///////////////////////////////////////////////////////////////////////////////
// MoveToSubfolder.js - Script Add-In version (JScript for Directory Opus)
///////////////////////////////////////////////////////////////////////////////
function OnInit(initData)
{
// Identify the script add-in
initData.name = "MoveToSubfolder (Add-In)";
initData.version = "1.0";
initData.desc = "Adds a custom command to move selected files to a subfolder.";
initData.copyright = "";
initData.default_enable = true;
// Create a custom command named "MoveToSubfolder"
var cmd = initData.AddCommand();
cmd.name = "MoveToSubfolder";
cmd.method = "OnMoveToSubfolder";
cmd.desc = "Moves selected files to an existing or new subfolder, optionally sorted by extension.";
cmd.label = "Move To Subfolder...";
cmd.template = ""; // No command-line args for this example
}
///////////////////////////////////////////////////////////////////////////////
// Called when the user runs the "MoveToSubfolder" command
///////////////////////////////////////////////////////////////////////////////
function OnMoveToSubfolder(scriptCmdData)
{
var sourceTab = scriptCmdData.func.sourcetab;
if (!sourceTab)
{
// No source tab, nothing to do
return;
}
var selectedFiles = sourceTab.selected;
if (selectedFiles.count == 0)
{
DOpus.MsgBox("No files are selected.", 0, "Move to Subfolder");
return;
}
// Enumerate existing subfolders in current path
var currentPath = sourceTab.path;
var folderEnum = DOpus.FSUtil.ReadDir(currentPath, false /* non-recursive /);
var subfolderList = [];
while (!folderEnum.complete)
{
var itm = folderEnum.Next(); // or "folderEnum.next" if preferred
if (itm && itm.is_dir)
{
subfolderList.push(itm.name);
}
}
subfolderList.sort();
// Build a dialog (programmatic template approach)
var dlg = scriptCmdData.func.Dlg; // Get dialog object from the command data
dlg.detach = false; // We can let Opus handle the loop automatically
dlg.title = "Move Files to Subfolder";
dlg.width = 360;
dlg.height = 0; // Auto-size height based on controls
dlg.icon = "move";
dlg.buttons = "ok|cancel";
// We'll define a template of controls as a Vector
// 1) Label: "Select an existing subfolder:"
// 2) Combo: list of subfolders (name="cboFolder")
// 3) Label: "Or enter new subfolder name:"
// 4) Edit: (name="txtNewFolder")
// 5) Check: (name="chkExtensionSort") for extension sorting
var controls = DOpus.NewVector(
{
type : "static",
x : 10,
y : 10,
width : 200,
height : 12,
label : "Select an existing subfolder:"
},
{
type : "combo",
name : "cboFolder",
x : 10,
y : 25,
width : 330,
height : 12,
drop : true,
edit : false
},
{
type : "static",
x : 10,
y : 50,
width : 200,
height : 12,
label : "Or enter new subfolder name:"
},
{
type : "edit",
name : "txtNewFolder",
x : 10,
y : 65,
width : 330,
height : 14,
value : ""
},
{
type : "check",
name : "chkExtensionSort",
x : 10,
y : 90,
width : 300,
height : 12,
label : "Sort into subfolders by extension",
value : false
}
);
// Assign that to dlg.template
dlg.template = controls;
// Now create the dialog
dlg.Create();
// Populate the combo with the existing subfolders
var ctrlCombo = dlg.Control("cboFolder");
for (var i = 0; i < subfolderList.length; i++)
{
ctrlCombo.AddItem(subfolderList[i]);
}
// Show the dialog
var userClicked = dlg.Show();
// userClicked = 0 means Cancel or close, 1 means OK, 2 means second button, etc.
if (userClicked == 0)
{
// Dialog cancelled
return;
}
// Gather user choices
var txtControl = dlg.Control("txtNewFolder");
var newFolderName = txtControl.value ? txtControl.value.trim() : "";
var chosenSubfolder = ctrlCombo.value ? ctrlCombo.value.trim() : "";
var chkExtensionSort = dlg.Control("chkExtensionSort").value;
// Decide final target folder name
var targetFolderName = "";
if (newFolderName !== "")
{
targetFolderName = newFolderName;
}
else if (chosenSubfolder !== "")
{
targetFolderName = chosenSubfolder;
}
else
{
DOpus.MsgBox("No subfolder specified. Operation cancelled.", 0, "Move to Subfolder");
return;
}
// Validate folder name (no illegal characters)
var invalidCharsRegex = /[<>:"/\|?]/;
if (invalidCharsRegex.test(targetFolderName))
{
DOpus.MsgBox("Invalid subfolder name. Operation cancelled.", 0, "Move to Subfolder");
return;
}
// Build full path
var targetFullPath = currentPath + "\" + targetFolderName;
var cmd = scriptCmdData.func.command;
cmd.ClearFiles();
// Create folder if needed
var folderExists = DOpus.FSUtil.Exists(targetFullPath);
if (!folderExists)
{
// Attempt creation
cmd.RunCommand('CreateFolder NAME="' + targetFullPath + '"');
// Check again
folderExists = DOpus.FSUtil.Exists(targetFullPath);
if (!folderExists)
{
DOpus.MsgBox("Failed to create folder: " + targetFolderName, 0, "Move to Subfolder");
return;
}
}
else if (!folderExists.is_dir)
{
// There's a file with that name
DOpus.MsgBox("A file with that name already exists. Operation cancelled.", 0, "Move to Subfolder");
return;
}
// Now move the files
if (chkExtensionSort)
{
// Sort by extension
var e = new Enumerator(selectedFiles);
for (; !e.atEnd(); e.moveNext())
{
var fileItem = e.item();
var ext = fileItem.ext.toLowerCase();
if (ext.indexOf(".") === 0) {
ext = ext.substr(1);
}
if (!ext) {
ext = "NoExtension";
}
var extFolderPath = targetFullPath + "\" + ext;
// Create extension subfolder if needed
if (!DOpus.FSUtil.Exists(extFolderPath)) {
cmd.RunCommand('CreateFolder NAME="' + extFolderPath + '"');
}
// Move the file
cmd.ClearFiles();
cmd.AddFile(fileItem);
cmd.RunCommand('Copy MOVE WHENEXISTS=ask TO="' + extFolderPath + '"');
}
}
else
{
// Move all at once
cmd.AddFiles(selectedFiles);
cmd.RunCommand('Copy MOVE WHENEXISTS=ask TO="' + targetFullPath + '"');
}
DOpus.MsgBox("Files moved successfully!", 0, "Move to Subfolder");
}
Why This Version Should Work according to ChatGPT 'o1'
Implements a recognized Directory Opus event: OnInit. Opus sees this and loads the script, creating the custom command.
The custom command is named "MoveToSubfolder" and uses the method "OnMoveToSubfolder".
We programmatically create the dialog using dlg.template = DOpus.NewVector(...) rather than <resources> or dlg.AddControl(). Not all versions of Opus fully support AddControl() in a script add-in, and <resources> can trigger parser conflicts.
The code enumerates subfolders using folderEnum.Next() (which should work in JScript). If that fails in your version, try folderEnum.next.
After the user fills in the dialog and clicks OK, it checks the chosen folder (or new folder name), creates it if needed, then runs a Copy MOVE command.
No extraneous text after the final brace. The script ends right after the last function, reducing parser-related confusion.
Once installed in Preferences > Toolbars > Scripts, simply create a button (or hotkey) containing:
MoveToSubfolder
Then select files in a lister, invoke that button/command, and the dialog should appear.
I'll take a deeper look, but it can not work as is:
- Some methods do not exist (DOpus.MsgBox at least)
- Dialogs and Controls do not work that way. They work as described in the manual.
When you post code, please use proper code tags so it is more readable.
Please stop trying to use AI to write code. It simply isn’t capable.
So ... you basically threw away everything I told you in the other post where you tried to get advice about AI generated code.
I advised not to use it for Opus scripting, or at most as a skeleton. I also told you to look at examples from this forum or the manual. You obviously did neither.
At the very least, you could have tried to run this script to look for syntax or execution errors and with a quick look at the manual sections I mentioned, you could have come to something that would have looked a lot better than this.
Out of curiosity, I tried to execute this. First execution error is on line 55 saying the method or property does not exist for this object.
That line is dlg.width = 360;
A direct look at the scripting reference section of the manual confirms it. The Dialog object has no such property. A quick look at the sections I pointed to (how to build simple or detached dialogs) would have helped you to fix this (not to mention that when commenting lines 55 & 56, next error is when calling Create()
method on this simple dialog when it's reserved for detached dialogs).
You said you were in the process of learning how to program. There were no AI when I did, so I can't be 100% accurate ... but honestly, I do not believe you'll go very far in Opus scripting with this approach of asking an AI to do the code for you and then submit it here for us to fix it.
YOU have to do the work and put some effort into it. As said in the other post, take it slow/step by step and if you have specific issues, create a specific thread to ask for help.
Yes, all this may be true, but ChatGPT claims their latest model, '01', can perform better than 86% of software engineers in complex tasks. Well, this exercise proved that assertion to be BS.
This might be true for large codebase languages : python, c, c++, current javascript, ...
Here, we are with an older version of javascript and an injected Opus object model.
There isn't enough data to make this accurate enough.
The given example where it applies a method (Create) on a simple dialog when it can only be used on detached dialog is proving that. Understanding that would require a human understanding the manual not an AI (yet ?).
I do work in IT and have had discussion with very good developers that use AI on a daily basis : they use it to get the first 80% of the job done, but then rely on their advanced knowledge of programming to focus and refine that raw output to their specific needs.
That means that they use AI as an accelerator not as a replacement.
That applies to the output you shared, since the main logic is here :
- Input parameters checking
- Enumerating folders in source
- Building the ui
- Checking user input in UI
- Building the command and executing it
BUT it just does it wrong in many places where it tries to invent things that it could not figure out.
Just to share : this week-end I was trying to build a button to automate from a selection of files the creation of a batch job in StaxRip and its execution.
The command line interface of StaxRip is sparsely documented and very few examples can be found. I asked Copilot, and it kept inventing command line switches that do not exists or presenting me answers that would launch in parallel several instances of StaxRip which is not what I asked and everytime I pointed that out, it would come up with an excuse saying I was right and then proposing me again with another non compliant solution (basically alternating between made-up switches and parallel executions).
I finally gave up, tried some stuff by myself and found the solution.
I guess this is another example of AI inability to come up with the proper solution when you're searching for something that doesn't have enough examples to be found online.
ChatGPT are full of it, and funded entirely on hype, empty promises and the sunk costs fallacy.
The things AI can do well and reliably are the things we were already using it for before this hype bubble started.