File Browser Command¶
Introduction¶
This article provides C++ source code for spawning a file browser from a command.
File dialogs are documented in depth, here: [http://modo.sdk.thefoundry.co.uk/wiki/Dialog_Commands#File_Dialogs File Dialogs]
Code¶
cmd_filebrowse.cpp¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | /*
*
* Implement a simple command for spawning a file browser.
*
* Usage: "file.browse"
*
*/
#include <lx_plugin.hpp>
#include <lxu_command.hpp>
#include <lx_value.hpp>
#include <lx_command.hpp>
#define SERVER_NAME "file.browse"
#define ARG_FILENAME "filename"
#define ARGi_FILENAME 0
/*
* Disambiguate everything with a namespace. This isn't necessary,
* but it's good practice and allows generic names to be used for
* things like the Command class.
*/
namespace FileBrowse_Cmd
{
/*
* Implement the command class. This inherits from CLxBasicCommand,
* which is a wrapper class that does a lot of the heavy lifting
* when implementing a command.
*/
class Command : public CLxBasicCommand
{
public:
static void initialize ()
{
CLxGenericPolymorph *srv;
srv = new CLxPolymorph <Command>;
srv->AddInterface (new CLxIfc_Command <Command>);
srv->AddInterface (new CLxIfc_Attributes <Command>);
srv->AddInterface (new CLxIfc_AttributesUI <Command>);
srv->AddInterface (new CLxIfc_StaticDesc <Command>);
lx::AddServer (SERVER_NAME, srv);
}
Command ();
int basic_CmdFlags () LXx_OVERRIDE;
bool basic_Enable (CLxUser_Message &msg) LXx_OVERRIDE;
void cmd_Interact () LXx_OVERRIDE;
void cmd_Execute (unsigned int flags) LXx_OVERRIDE;
static LXtTagInfoDesc descInfo[];
};
Command::Command ()
{
/*
* The constructor is a good place to add arguments and
* set flags for those arguments. This command will have
* a single argument for the filename. The flags will mark
* the argument as optional. This will prevent modo from
* launching a dialog to ask for a filename string and
* instead allow the command to handle the missing argument
* value by spawning a file dialog.
*/
dyna_Add (ARG_FILENAME, LXsTYPE_FILEPATH);
basic_SetFlags (ARGi_FILENAME, LXfCMDARG_OPTIONAL);
}
int Command::basic_CmdFlags ()
{
/*
* The flags define if this should be an undoable command
* or not. If the command changes the state of the scene,
* then it should implement both the MODEL and UNDO flags.
*/
return LXfCMD_MODEL | LXfCMD_UNDO;
}
bool Command::basic_Enable (CLxUser_Message &msg)
{
/*
* In practice, a command usually has an enabled state and
* a disabled state. This function allows you to return True
* or False to enable/disable the command. A message interface
* is provided to allow you to pass detailed information about
* the enable state back to the user. This command is always
* enabled.
*/
return true;
}
void Command::cmd_Interact ()
{
/*
* When the command is executed, this function is first called.
* It's the ideal place to open a file dialog and ask for user
* interaction. The resulting path can then be passed to the
* commands execute method using the filename argument.
*
* No scene or state altering code should be performed here.
*/
CLxUser_CommandService cmd_svc;
CLxUser_Command command;
CLxUser_ValueArray val_array;
LXtObjectID obj = NULL;
std::string filename = "";
unsigned n = 0;
/*
* Check if the filename argument is set, if it is, return early.
*/
if (dyna_IsSet (ARGi_FILENAME))
return;
/*
* Fire the commands to open the file dialog.
*/
cmd_svc.ExecuteArgString (-1, LXiCTAG_NULL, "dialog.setup fileOpen");
cmd_svc.ExecuteArgString (-1, LXiCTAG_NULL, "dialog.title {Browse For Files...}");
cmd_svc.ExecuteArgString (-1, LXiCTAG_NULL, "dialog.fileTypeCustom movie {Quicktime Movie} {*.mov;*.mp4} mov");
cmd_svc.ExecuteArgString (-1, LXiCTAG_NULL, "dialog.open");
/*
* Spawn a command that can be queried for the result.
*/
if (LXx_FAIL (cmd_svc.NewCommand (command, "dialog.result")))
return;
/*
* Query the first argument on the dialog.result command
* and store the results in a value array.
*/
if (LXx_FAIL (cmd_svc.QueryIndex (command, 0, val_array)))
return;
/*
* Get the number of elements in the array. There should
* only be one. If there are none, return early.
*/
n = val_array.Count ();
if (!n)
return;
/*
* Read the string from the value array and set the filename
* argument to the value of the string.
*/
val_array.String (0, filename);
attr_SetString (ARGi_FILENAME, filename.c_str());
}
void Command::cmd_Execute (unsigned int flags)
{
/*
* As the name suggests, this is where the command is executed.
* In this command, we won't actually do anything, other than
* read the filename argument into a string.
*/
std::string filename_arg = "";
if (dyna_IsSet (ARGi_FILENAME))
attr_GetString (ARGi_FILENAME, filename_arg);
}
void initialize ()
{
Command :: initialize ();
}
LXtTagInfoDesc Command::descInfo[] = {
{ 0 }
};
}; // End Namespace.
/*
* Initialize the servers.
*/
void initialize ()
{
FileBrowse_Cmd :: initialize ();
}
|