Scripts

 

When scripts are processed they automatically have three objects made available globally to them. These objects are:

  • mainwindow, the GUIClient class object that represents the application's Main MDI window interface.
  • mywindow, the XMainWindow or XDialogBox that represents the screen the script is being run against.
  • toolbox, the ScriptToolbox helper class that provides functionality not available normally through the QtScript interface.

In addition to these objects there is also a helper class called ScriptQuery that can be used to access query result information. The ScriptQuery object is returned by the executeQuery() method of ScriptToolbox. 

Object mainwindow

The object mainwindow provided to all scripts is the GUIClient class of the application and contains the MDI interface as well as the full menu structure. Any child of this object is accessible by using the findChild() method, as described in the QtScript documentation. Menu items are the most useful object you can gain access to through this object, but there are several other properties and methods that can be accessed, as well.

First, any properties, signals, and public slots of the QMainWindow class and its parent classes are available. In addition, there are several other slots and signals that can accessed from this object specifically provided for the xTuple application.

Public Slots

sReportError(const QString &);

This slot writes a debugging message. See Script Debugging below.

sTick();

This slot is typically used internally by the application and should rarely be used in scripts. It checks the connection to the database server and updates the user's event notification icon.

sChecksUpdated(int, int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more bank Checks.

sAssortmentsUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Assortments.

sBBOMsUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Breeder Bills of Materials.

sBOMsUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Bills of Materials.

sBOOsUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Bills of Operations.

sBudgetsUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Budgets.

sBankAdjustmentsUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Bank Adjustments.

sBillingSelectionUpdated(int, int);

This slot tells other open windows that this script has updated the definition or status of one or more Billing Selections.

sCashReceiptsUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Cash Receipts.

sConfigureGLUpdated();

This slot tells other open windows that this script has updated the General Ledger configuration.

sCreditMemosUpdated();

This slot tells other open windows that this script has updated the definition or status of one or more Credit Memos.

sCrmAccountsUpdated(int);

This slot tells other open windows that this script has updated the definition or status of one or more CRM Accounts.

sCustomCommand();

This slot tells other open windows that this script has updated the definition or status of one or more Custom Commands.

sCustomersUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Customers.

sGlSeriesUpdated();

Use this slot to tell other windows in the application that this script has updated the definition or status of one or more General Ledger Series.

sInvoicesUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Invoices.

sItemGroupsUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Item Groups.

sItemsUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Items.

sItemsitesUpdated();

This slot tells other open windows that this script has updated the definition or status of one or more Item Sites.

sPaymentsUpdated(int, int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Payments.

sProjectsUpdated(int);

This slot tells other open windows that this script has updated the definition or status of one or more Projects.

sProspectsUpdated();

This slot tells other open windows that this script has updated the definition or status of one or more Prospects.

sPurchaseOrderReceiptsUpdated();

This slot tells other open windows that this script has updated the list of Receipts.

sPurchaseOrdersUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Purchase Orders.

sPurchaseRequestsUpdated();

This slot tells other open windows that this script has updated the definition or status of one or more Purchase Requests.

sQOHChanged(int, bool);

This slot tells other open windows that this script has updated the Quantity on Hand of some Item Site.

sQuotesUpdated(int);

This slot tells other open windows that this script has updated the definition or status of one or more Quotes.

sReportsChanged(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more Reports.

sReturnAuthorizationsUpdated();

This slot tells other open windows that this script has updated the definition or status of one or more Return Authorizations.

sSalesOrdersUpdated(int);

This slot tells other open windows that this script has updated the definition or status of one or more Sales Orders.

sStandardPeriodsUpdated();

This slot tells other open windows that this script has updated the definition or status of one or more Standard Periods.

sTaxAuthsUpdated(int);

This slot tells other open windows that this script has updated the definition or status of one or more Tax Authorities.

sTransferOrdersUpdated(int);

This slot tells other open windows that this script has updated the definition or status of one or more Transfer Orders.

sVendorsUpdated();

This slot tells other open windows that this script has updated the definition or status of one or more Vendors.

sVouchersUpdated();

This slot tells other open windows that this script has updated the definition or status of one or more Vouchers.

sWarehousesUpdated();

This slot tells other open windows that this script has updated the definition or status of one or more Sites or Warehouses.

sWorkCentersUpdated();

This slot tells other open windows that this script has updated the definition or status of one or more work centers.

sWorkOrderMaterialsUpdated(int, int, bool);

This slot tells other open windows that this script has updated the definition or status of work order materials.

sWorkOrderOperationsUpdated(int, int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more work order operations.

sWorkOrdersUpdated(int, bool);

This slot tells other open windows that this script has updated the definition or status of one or more work orders.

sIdleTimeout();

This slot should rarely or never be called by a script. It is used by the application to inform the user that s/he has been idle for a long time and asks if the user wants to exit the application.

sFocusChanged(QWidget* old, QWidget* now);

This slot should rarely or never be called by a script. It indicates to the application that the user's focus has changed from one window to another.

Many of these slots "tell other windows" something. This means that any windows that are open and listening for certain corresponding signals listed below will refresh themselves. A script should only call these slots if you want to inform other open windows of changes made by the script itself. These slots do not save any data to the database and scripts are not required to call them. Any script that calls these slots should do so after committing changes to the database. A significant limitation of these slots is that they can only inform other windows opened by the same instance of the xTuple ERP application, not windows opened by other users whether or not they are running on the same host or workstation.

Signals

tick();

This signal is emitted on a regular basis, usually every minute or so. Scripts that want to repeat an action at a regular interval can connect to this signal. This is often used by Automatically Update check boxes.

checksUpdated(int, int, bool);

These signals are connected by the xTuple ERP application to the slots described above. Every time a window anywhere in the application calls one of those slots the application emits one of these signals. Scripts can connect these signals to functions in the script or to methods of the windows being scripted to cause certain activity whenever another part of the application reports a data change.

assortmentsUpdated(int, bool);

bankAdjustmentsUpdated(int, bool);

bbomsUpdated(int, bool);

billingSelectionUpdated(int, int);

bomsUpdated(int, bool);

boosUpdated(int, bool);

budgetsUpdated(int, bool);

cashReceiptsUpdated(int, bool);

configureGLUpdated();

creditMemosUpdated();

crmAccountsUpdated(int);

customersUpdated(int, bool);

glSeriesUpdated();

invoicesUpdated(int, bool);

itemGroupsUpdated(int, bool);

itemsUpdated(int, bool);

itemsitesUpdated();

paymentsUpdated(int, int, bool);

projectsUpdated(int);

prospectsUpdated();

purchaseOrderReceiptsUpdated();

purchaseOrdersUpdated(int, bool);

purchaseRequestsUpdated();

qohChanged(int, bool);

quotesUpdated(int, bool);

reportsChanged(int, bool);

returnAuthorizationsUpdated();

salesOrdersUpdated(int, bool);

standardPeriodsUpdated();

taxAuthsUpdated(int);

transferOrdersUpdated(int);

vendorsUpdated();

vouchersUpdated();

warehousesUpdated();

workCentersUpdated();

workOrderMaterialsUpdated(int, int, bool);

workOrderOperationsUpdated(int, int, bool);

workOrdersUpdated(int, bool);

Object mywindow

The mywindow object is the object representing the screen that the script is being run against. This can either be a QDialog or QMainWindow, depending on the specific screen. Often the difference between the two is of little concern but it is good to know, as some of the available methods will be different. Sometimes, as well, the way you implement your scripts could be different, as Dialogs are modal and do not allow other non-modal windows to be opened at the same time.

For a list of available properties, signals, and slots, please see the Qt reference documentation for QDialog and QMainWindow.

Object toolbox

The toolbox object is a collection of miscellaneous functions that xTuple has found useful for writing scripts. The toolbox is sure to grow over time. Here is the set of features available in xTuple release 3.1:

Execute Queries  

QObject * executeQuery(const QString & query);

This method takes a SQL statement, executes the it against the database server, and returns that query as a ScriptQuery object.

QObject * executeQuery(const QString & query, const ParameterList & params); This method takes MetaSQL and a set of parameter name/value pairs, executes the resulting query against the database server, and returns that query as a ScriptQuery object.
QObject * executeDbQuery(const QString & group, const QString & name); This method loads a MetaSQL statement stored in the database. It executes the resulting query against the database server, and returns that query as a ScriptQuery object.
QObject * executeDbQuery(const QString & group, const QString & name, const ParameterList & params); This method loads a MetaSQL statement stored in the database, and applies a list of parameter name/value pairs. It executes the resulting query against the database server, and returns that query as a ScriptQuery object.
QObject * executeBegin(); Executes the SQL command "BEGIN;" to signal the beginning of a database transaction.
QObject * executeCommit(); Executes the SQL command "COMMIT;" to signal the end of a database transaction.
QObject * executeRollback(); Executes the SQL command "ROLLBACK;" to rollback all activity previously recorded inside transaction.
Add Validators to fields  
QObject * qtyVal(); Quantity validator.  Apply to widgets that accept text to enforce decimal place precision as defined in user's local settings. Does not allow negative values.
QObject * TransQtyVal(); Transaction Quantity validator.  Apply to widgets that accept text to enforce decimal place precision as defined in user's local settings. Allows negative values.
QObject * qtyPerVal(); Quantity Per validator.  Apply to widgets that accept text to enforce decimal place precision as defined in user's local settings. Does not allow negative values.
QObject * percentVal(); Percent validator.  Apply to widgets that accept text to enforce decimal place precision. Does not allow negative values.
QObject * moneyVal(); Money validator.  Apply to widgets that accept text to enforce decimal place precision as defined in user's local settings.  Does not allow negative values.
QObject * negMoneyVal(); Quantity validator.  Apply to widgets that accept text to enforce decimal place precision as defined in user's local settings. Allows negative values.
QObject * priceVal(); Price validator.  Apply to widgets that accept text to enforce decimal place precision as defined in user's local settings. Does not allows negative values.
QObject * costVal(); Cost validator.  Apply to widgets that accept text to enforce decimal place precision as defined in user's local settings. Does not allows negative values.
QObject * ratioVal(); UOM ratio validator.  Apply to widgets that accept text to enforce decimal place precision as defined in user's local settings. Does not allows negative values.
QObject * weightVal(); Weight validator.  Apply to widgets that accept text to enforce decimal place precision. Does not allows negative values.
QObject * runTimeVal(); Run Time validator.  Apply to widgets that accept text to enforce decimal place precision as defined in user's local settings. Does not allows negative values.
QObject * orderVal(); Order validator.  Apply to widgets that accept text to enforce decimal place precision as defined in user's local settings. Does not allows negative values.
QObject * dayVal(); Day validator.  Apply to widgets that accept text to enforce decimal place precision as defined user's local settings. Does not allows negative values.
Manipulate Layouts  

QObject * widgetGetLayout(QWidget * w);

If you have a widget that you have added to a form or that you have retreived from a form, this method gives you the layout object that contains that widget. Then you can use one of the methods below to place another widget on the window near a widget you choose.

void layoutBoxInsertWidget(QObject *, int index, QWidget *, int stretch = 0, int alignment = 0);

These let you add new widgets to an existing form so that they are positioned appropriately and respond properly to window size changes.

void layoutGridAddWidget(QObject *, QWidget *, int row, int column, int alignment = 0);

void layoutGridAddWidget(QObject *, QWidget *, int fromRow, int fromColumn, int rowSpan, int columnSpan, int alignment = 0);

void layoutStackedInsertWidget(QObject *, int index, QWidget *);

Manipulate Menus  

QObject * menuAddAction(QObject * menu, const QString & text);

This lets you add an item to a menu with a particular name. The returned object is the action that will be taken when the user selects this new menu item. The script must populate the properties of this action to ensure the desired result.

QObject * menuAddMenu(QObject * menu, const QString & text, const QString & name = QString());

This lets you add a submenu to an existing menu.

QObject * menuAddSeparator(QObject * menu); Add a separator to the bottom an existing menu.
QObject * menuInsertAction(QObject * menu, QObject * before, const QString & name = QString(), const bool enabled = true); Insert an action before another on an existing menu with a given name.
QObject * menuInsertMenu(QObject * menu, QObject * before, const QString & name); Insert a menu before an existing action with a given name.
 QObject * menuInsertSeparator(QObject * menu, QObject * before); Insert a separator to a menu before an existing action on the menu.
void menuRemove(QObject * menu, QObject * action); Remove a menu action.  Useful to remove custom commands menu actions for which new menu actions have been made and placed elsewhere on the menu structure.
int menuActionCount(QObject * menu); Counts how many actions are on a menu.  Useful to determine if all actions have been removed from a custom menu.  If so, you can remove the menu itself.
Manipulate Tab Widget  

QWidget * tabWidget(QWidget * tab, int idx);

This method lets you retrieve a particular tab from a tab widget. The idx is the integer associated with the desired tab.

int tabCount(QWidget * tab); Returns the number of tabs on a tab widget.  Useful to determine what the index should be for a next tab to be added.
QWidget * tabWidget(QWidget * tab, int idx); Returns the page on a tab widget based on the index passed.  Useful to reference child objects on the tab page.

int tabInsertTab(QWidget * tab, int idx, QWidget * page, const QString & text);

This method lets you add a new tab to an existing tab widget in position idx.

int tabTabIndex(QWidget * tab, QWidget * page); Returns the index number on a tab of a given page.

void tabRemoveTab(QWidget * tab, int idx);

This method lets you remove a tab from an existing tab widget.

void tabSetTabEnabled(QWidget * tab, int idx, bool enable); Sets the enabled property on a given tab and tab index, based on the boolean passed.

void tabSetTabText(QWidget * tab, int idx, const QString & text);

This method lets you change the label of a particular tab in a tab widget.

QString tabtabText(QWidget * tab, int idx);

This method lets you retrieve the label of a particular tab in a tab widget.

Create new objects  

QWidget * createWidget(const QString & className, QWidget * parent = 0, const QString & name = QString());

This method lets you create a new widget. The first parameter is the name of the desired widget's class (e.g. QSpinBox or ContactCluster. The second parameter is the window or dialog that should take responsibility for destroying the widget (usually this). The third parameter is the name of the widget (this is not the label visible to the user, but rather a string that can be used later to find the widget again if the QWidget* variable gets lost).

QObject * createLayout(const QString & className, QWidget * parent, const QString & name = QString());

This method lets you create a new layout. The first parameter is the name of the desired layout's class (e.g. QGridLayout or QHBoxLayout). The second parameter is the widget that layout is to be applied. The third parameter is the name of the layout (this is not the label visible to the user, but rather a string that can be used later to find the widget again if the QObject* variable gets lost).

QWidget * loadUi(const QString & screenName, QWidget * parent = 0);

This method lets you load a UI file from the database. The first parameter is the name of the screen as you have specified it in the Screen window of the application. The second parameter is the window or dialog that should take responsibility for destroying the widget (usually this).

QWidget * lastWindow() const;

Passes a reference back to the last window opened.  Generally used in conjunction with the openWindow method below to pass parameters.
QWidget * openWindow(const QString pname, QWidget *parent = 0, Qt::WindowModality modality = Qt::NonModal, Qt::WindowFlags flags = 0);

This method opens a new window using a user defined screen and script.  pname is the name of the screen, parent is the caller (usually mywindow),  modality determines whether the window opens in a modal state. 

Note: Opening core C++ windows using script and passing parameters is not supported at this time.

bool printReport(const QString & name, const ParameterList  & params);

This takes a report name and a set of parameter name/value pairs and causes the named report to print.

Manipulate XTreeWidgets  
void addColumnXTreeWidget(QWidget * tree, const QString & pString, int pWidth, int pAlignment, bool pVisible = true, const QString pEditColumn = QString(), const QString pDisplayColumn = QString()); Add a column to to an XTreeWidget where tree is the XTreeWidget, pString is the column title, pWidth is the width, pAlignment is the alignment, pVisible is default visibility status, pEditColumn is the bound column on the query and pDisplayColumn is the display role column.
void populateXTreeWidget(QWidget * tree, QObject * pSql, bool = FALSE); Populate an XTreeWidget with the result of a query where tree is the XTreeWidget, pSql is a query result set, and bool determines whether the second column in the query should be considered an alternate id.
Manipulate WebViews  
void loadQWebView(QWidget * webView, const QString & url); Allows script to load a URL into a QWebView widget on a screen by passing the QWebView object and a URL as a string.
Manipulate Files  
QString fileDialog(QWidget * parent, const QString & caption, const QString & dir, const QString & filter, int fileModeSel, int acceptModeSel);

Opens a file dialog window from the parent with a caption of caption, a starting directory of dir a file type filter of filter in selection mode fileModeSel and returns a file path.

fileModeSel enumerators are:

  • 1 = Existing File
  • 2 = Directory
  • 3 = Directory Only
  • 4 = Existing Files
  • 5 = Any File
void openUrl(const QString & fileUrl);

Opens the given url in the appropriate Web browser for the user's desktop environment, and returns true if successful; otherwise returns false.

If the URL is a reference to a local file (i.e., the URL scheme is "file") then it will be opened with a suitable application instead of a Web browser.

If a mailto URL is specified, the user's e-mail client will be used to open a composer window containing the options specified in the URL, similar to the way mailto links are handled by a Web browser.

bool copyFile(const QString & oldName, const QString & newName);

Copies the file fileName to newName. Returns true if successful; otherwise returns false.

If a file with the name newName already exists, copyFile() returns false (i.e., the script will not overwrite it).

QString getFileName(const QString & path) Returns the name of the file, excluding the path.
bool renameFile(const QString & oldName, const QString & newName);

Renames the file oldName to newName. Returns true if successful; otherwise returns false.

If a file with the name newName already exists, renameFile() returns false (i.e., script will not overwrite it).

bool removeFile(const QString & name);

Removes the file specified by name. Returns true if successful; otherwise returns false.

The file is closed before it is removed.

bool fileExists(const QString & name); Returns true if the file specified by name exists; otherwise returns false.
QString getCurrentDir(); Returns the absolute path of the application's current directory.
QString getHomeDir();

Returns the absolute path of the user's home directory.

Under Windows this function will return the directory of the current user's profile. Typically, this is:

 C:/Documents and Settings/Username

Use the toNativeSeparators() function to convert the separators to the ones that are appropriate for the underlying operating system.

If the directory of the current user's profile does not exist or cannot be retrieved, the following alternatives will be checked (in the given order) until an existing and available path is found:

  1. The path specified by the USERPROFILE environment variable.
  2. The path formed by concatenating the HOMEDRIVE and HOMEPATH environment variables.
  3. The path specified by the HOME environment variable.
  4. The path returned by the rootPath() function (which uses the SystemDrive environment variable)
  5. The C:/ directory.

Under non-Windows operating systems the HOME environment variable is used if it exists, otherwise the path returned by the rootPath() function is used.

bool  makePath(const QString & mkPath, const QString & rootPath);

Creates the directory path mkPath in the directory rootPath.

The function will create all parent directories necessary to create the directory.

Returns true if successful; otherwise returns false.

bool    removePath(const QString & rmPath, const QString & rootPath);

Removes the directory path rmPath from the rootPath.

The function will remove all parent directories in rmPath, provided that they are empty. This is the opposite of makepath(mkPath, rootPath).

Returns true if successful; otherwise returns false.

QString rootPath();

Returns the absolute path of the root directory.

For Unix operating systems this returns "/". For Windows file systems this normally returns "c:/".

QString textStreamRead(const QString & name); Returns the text of file name.
bool    textStreamWrite(const QString & name, const QString & WriteText); Writes WriteText to file name.
Credit Card Processor  
int     saveCreditCard(QWidget *parent,
                              int custId,
                              QString ccName,
                              QString ccAddress1,
                              QString ccAddress2,
                              QString ccCity,
                              QString ccState,
                              QString ccZip,
                              QString ccCountry,
                              QString ccNumber,
                              QString ccType,
                              QString ccExpireMonth,
                              QString ccExpireYear,
                              int ccId = 0,
                              bool ccActive = true );
Saves a credit card in the database against a customer record.  If the credit card is determined to already exist for the customer, it is updated with new changes.
QObject *getCreditCardProcessor(); Creates a credit card processor object that can be used to process credit card transactions.
Miscellaneous Utilities  

int messageBox(const QString & type, QWidget * parent, const QString & title, const QString & text, int buttons = 0x00000400, int defaultButton = 0x00000000);

This is a convenience function to create a message dialog. The first parameter is either "critical", "information", "question", or "warning" and controls the icon that will appear in the dialog. The second parameter is the parent window (usuallythis) and controls where the dialog box will appear. The third parameter lets the script set the title bar of the message dialog, while the fourth parameter sets the main content text displayed inside the dialog. The buttons and defaultButton parameters are describe further in the QMessageBox documentation; in general they let you choose from among a set of pre-defined buttons to display and select which one is the default button. This method returns the value of the button which the user clicked.

void    listProperties(const QScriptValue &obj) const; A debugging utility that prints a list of properties on a given script object.
   

bool coreDisconnect(QObject * sender, const QString & signal, QObject * receiver, const QString method);

Disconnects a signal/slot connection made in the core.  Usually used when there is a desire to over-ride existing core behavior with new behavior defined by a script, such as replacing a standard query function with a new one.

bool printReport(const QString & name, const ParameterList & params, const QString & pdfFilename = QString::null); Print a report that exists in the database whene name is the name of the report definition, params is a parameter list for MetaSQL, and pdfFilename is the file path to save the report as a pdf document.  If no file name is provided, the document will print to a printer.

Object ScriptQuery

The ScriptQuery class is used to manipulate database queries from xTuple ERP application scripts. You create and execute a query using the toolbox object'sexecuteQuery() method. Once you have executed a query you can do any of the following things with it:

XSqlQuery query()

Get the XSqlQuery object from the ScriptQuery. XSqlQuery is an xTuple subclass of Qt's QSqlQuery class, so anything you can script with a QSqlQuery can be scripted with the value returned by query().

void setQuery(XSqlQuery query)

If you have an XSqlQuery object, perhaps from a prior call to query(), you can assign it to a ScriptQuery variable.

bool isActive()

These are wrappers around QSqlQuery object methods and are provided here to make it easy to use them. Consult the QSqlQuery documentation for more information.

bool isValid()

bool isForwardOnly()

bool isSelect()

bool first()

The script should call this when it needs to read the first result row from an executed query.

bool last()

The script should call this when it wants to skip over the intervening results and look at the last row returned by an executed query.

bool next()

The script should call this when it wants to retrieve the next available row from an executed query's result set. If the query has just been executed and first() has not yet been called, next() returns the first result row.

bool previous()

The script should call this if it needs to look backwards through the query result set.

int size()

This method returns the approximate number of rows in the query result set.

int numRowsAffected()

This returns the (approximate) number of rows modified by a query containing an update statement, removed by a query containing a delete statement, or added by a query containing an insert statement.

QScriptValue value(int)

Once the script has executed a query and positioned itself on a particular row (using first()last()next(), or previous()) you usevalue() to read the contents of a particular column. You can either refer to the column by its position in the select statement by passing an integer to value() or by its name in the query using the QString version of value().

QScriptValue value(const QString)

QVariantMap lastError()

You can learn about errors executing queries by looking at the lastError(). You can ask for the databaseText, driverText, text, number, type, and validity of the error. See the Sample Scripts for examples of how lastError() can be used.

Most of the functions in the ScriptQuery class are wrappers around methods with the same name in the QSqlQuery class. You should read the QSqlQuery documentation for more information about them.

Script Debugging

It is difficult to debug an application script without a sophisticated development environment embedded in the xTuple ERP application. However there are some basic tools built in to the application and the Qt framework to help solve basic problems. The most important of these is debugging output. Unfortunately access to this output differs on the three major platforms. Conceptually they're the same, so here are the concepts. Qt has a function qDebug(). This is called any number of places in the Qt libraries and the xTuple ERP application for sending debugging messages to the developer. Qt uses this function to tell developers about unexpected and probably unintentional behavior by the application, such as application code asking a query object for a column that wasn't named in the query or syntax errors found while trying to execute a Qt Script. Script authors can use the sReportError() slot described above to send debugging output to the same place.

Qt applications are driven by the connections between signals and slots, so much of the time problems manifest themselves long after a script has been loaded. xTuple ERP does not install error traps for all script errors, just those that occur during the initial load of the script when its parent window is created. To help you debug script functions that are run as a result of signal/slot connections, use QtScript's try/catch mechanism: {{{!#javascript function sSave() {

     try {

           var params; params.id = _widget.id; var q = executeQuery("INSERT ... ;", params); // error: toolbox.executeQuery

           ..

     } catch (e) {

         mainwindow.sReportError("exception in sSave: " + e);

     }

}

mywindow.getChild("_save").clicked.connect(sSave); }}} When the user clicks on the button named _save, this code will cause a debugging message to be written that looks something like this:

exception in sSave: ReferenceError: executeQuery is not defined

Windows Script Debugging

On Microsoft Windows platforms you have to attach to the xTuple ERP application while it is running to see qDebug() and sReportError() output. For example you can start the xTuple ERP application and Visual Studio, then with Visual Studio select Tools -> Attach to Process... and select xtuple.exe from the list of Available Processes. In the Output window of Visual Studio, select "Show output from: Debug". Then try running your script from the main application and watch the Visual Studio Output window.

Macintosh Script Debugging

On the Macintosh you have two options. Either start the xTuple ERP application from a Terminal window or from the Finder. If you choose the first option, starting from Terminal, then you have to run the binary within the application package - .../xtuple.app/Contents/MacOS/xtuple. Now the debugging output will go to your Terminal window. If you use the open xtuple.app command then follow the same steps as debugging from the Finder.

If you open the application from the Finder or using open then run /Applications/Utilities/Console and watch that window for the debugging output.

Linux Script Debugging

On Linux you should run the xTuple ERP application from a Terminal or Shell window - .../xtuple and watch that Terminal or Shell window for the debugging output.