diff options
Diffstat (limited to 'kommander/plugin')
-rw-r--r-- | kommander/plugin/Makefile.am | 17 | ||||
-rw-r--r-- | kommander/plugin/kommanderplugin.cpp | 82 | ||||
-rw-r--r-- | kommander/plugin/kommanderplugin.h | 103 | ||||
-rw-r--r-- | kommander/plugin/specialinformation.cpp | 623 | ||||
-rw-r--r-- | kommander/plugin/specialinformation.h | 119 | ||||
-rw-r--r-- | kommander/plugin/specials.h | 77 |
6 files changed, 1021 insertions, 0 deletions
diff --git a/kommander/plugin/Makefile.am b/kommander/plugin/Makefile.am new file mode 100644 index 00000000..be1bb9f4 --- /dev/null +++ b/kommander/plugin/Makefile.am @@ -0,0 +1,17 @@ +lib_LTLIBRARIES = libkommanderplugin.la + +# set the include path for X, qt and KDE +INCLUDES = -I$(top_srcdir)/kommander/widget $(all_includes) + +# the library search path. +libkommanderplugin_la_LDFLAGS = $(KDE_RPATH) $(all_libraries) -no-undefined + +# the libraries to link against. +libkommanderplugin_la_LIBADD = $(LIB_KDEUI) $(LIB_QT) + +libkommanderplugin_la_SOURCES = kommanderplugin.cpp specialinformation.cpp + +include_HEADERS = kommanderplugin.h specials.h + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO diff --git a/kommander/plugin/kommanderplugin.cpp b/kommander/plugin/kommanderplugin.cpp new file mode 100644 index 00000000..9be1c2d5 --- /dev/null +++ b/kommander/plugin/kommanderplugin.cpp @@ -0,0 +1,82 @@ +/*************************************************************************** + kommanderplugin.cpp - An interface to Kommander widget plugins + ------------------- + copyright : (C) 2003 by Marc Britton + email : consume@optusnet.com.au + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "kommanderplugin.h" +#include "specialinformation.h" + +KommanderPlugin::KommanderPlugin() +{ +} + +KommanderPlugin::~KommanderPlugin() +{ +} + +void KommanderPlugin::addWidget( const QString &name, const QString &group, const QString &toolTip, QIconSet *iconSet, const QString &whatsThis, bool isContainer) +{ + m_widgets[name] = WidgetInfo( group, toolTip, iconSet, whatsThis, isContainer ); +} + +void KommanderPlugin::removeWidget( const QString &name ) +{ + m_widgets.remove( name ); +} + +QStringList KommanderPlugin::widgets() const +{ + QStringList ws; + WidgetInfos::ConstIterator it; + for( it = m_widgets.begin() ; it != m_widgets.end() ; ++ it ) + ws += it.key(); + return ws; +} + +QString KommanderPlugin::group( const QString &name ) const +{ + return m_widgets[name].group; +} + +QString KommanderPlugin::toolTip( const QString &name ) const +{ + return m_widgets[name].toolTip; +} + +QString KommanderPlugin::whatsThis( const QString &name ) const +{ + return m_widgets[name].whatsThis; +} + +bool KommanderPlugin::isContainer( const QString &name ) const +{ + return m_widgets[name].isContainer; +} + +QIconSet* KommanderPlugin::iconSet( const QString &name ) const +{ + return m_widgets[name].iconSet; +} + +void KommanderPlugin::setDefaultGroup( int id ) +{ + SpecialInformation::setDefaultGroup(id); +} + +bool KommanderPlugin::registerFunction(int id, const QString& function, const QString description , int minArgs, int maxArgs) +{ + return SpecialInformation::insert(id, function, description, minArgs, maxArgs); +} + +#include "kommanderplugin.moc" diff --git a/kommander/plugin/kommanderplugin.h b/kommander/plugin/kommanderplugin.h new file mode 100644 index 00000000..ecba3384 --- /dev/null +++ b/kommander/plugin/kommanderplugin.h @@ -0,0 +1,103 @@ +/**************************************************************************** + ** kommanderplugin.h - KommanderPlugin class definition created from QWidgetPlugin + ** Copyright (C) 2001 Trolltech AS. All rights reserved. + ** Copyright (C) 2003 Marc Britton + ** + ** This file is part of the widgets module of the Qt GUI Toolkit. + ** + ** This file may be distributed under the terms of the Q Public License + ** as defined by Trolltech AS of Norway and appearing in the file + ** LICENSE.QPL included in the packaging of this file. + ** + ** This file may be distributed and/or modified under the terms of the + ** GNU General Public License version 2 as published by the Free Software + ** Foundation and appearing in the file LICENSE.GPL included in the + ** packaging of this file. + ** + ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition + ** licenses may use this file in accordance with the Qt Commercial License + ** Agreement provided with the Software. + ** + ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + ** + ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for + ** information about Qt Commercial License Agreements. + ** See http://www.trolltech.com/qpl/ for QPL licensing information. + ** See http://www.trolltech.com/gpl/ for GPL licensing information. + ** + ** Contact info@trolltech.com if any conditions of this licensing are + ** not clear to you. + ** + **********************************************************************/ + +#ifndef _HAVE_KOMMANDERPLUGIN_H_ +#define _HAVE_KOMMANDERPLUGIN_H_ + +#include <qobject.h> +#include <qmap.h> +#include <qstringlist.h> +#include "kommander_export.h" + +class QWidget; +class QIconSet; + +class KOMMANDER_EXPORT KommanderPlugin : public QObject +{ + Q_OBJECT + public: + KommanderPlugin(); + ~KommanderPlugin(); + + virtual void addWidget( const QString &name, const QString &group, const QString &toolTip, QIconSet *iconSet, const QString &whatsThis = QString::null, bool isContainer = false); + virtual void removeWidget( const QString &name ); + virtual QStringList widgets() const; + + virtual QWidget *create( const QString &key, QWidget *parent = 0, const char *name = 0 ) = 0; + virtual QString group( const QString &key ) const; + virtual QString toolTip( const QString &key ) const; + virtual QString whatsThis( const QString &key ) const; + virtual bool isContainer( const QString &key ) const; + virtual QIconSet *iconSet( const QString &key ) const; + + /** + * Sets the default group for functions. Must be called before registerFunction. + * @param group the groups ID + */ + static void setDefaultGroup(int group); + + /** + * Register a function of the plugin. + * @param id Kommander wide unique ID + * @param function function signature + * @param description description of what the function does + * @param minArgs minimum number of accepted arguments + * @param maxArgs maximum number of accepted arguments + * @return true if registration was successful + */ + static bool registerFunction(int id, const QString& function, const QString description = QString::null, + int minArgs = -1, int maxArgs = -1); + + + +private: + struct WidgetInfo + { + WidgetInfo() { } + WidgetInfo( const QString &g, const QString &t, QIconSet *i, const QString &w = QString::null, bool c = false) + : group( g ), toolTip( t ), iconSet(i), whatsThis( w ), isContainer( c ) + {} + + QString group; + QString toolTip; + QIconSet *iconSet; + QString whatsThis; + bool isContainer; + }; + typedef QMap<QString, WidgetInfo> WidgetInfos; + WidgetInfos m_widgets; +}; + +#define KOMMANDER_EXPORT_PLUGIN(plugin) extern "C" { KOMMANDER_EXPORT void *kommander_plugin() { return new plugin; } } + +#endif // _HAVE_KOMMANDERPLUGIN_H_ diff --git a/kommander/plugin/specialinformation.cpp b/kommander/plugin/specialinformation.cpp new file mode 100644 index 00000000..5e86eb16 --- /dev/null +++ b/kommander/plugin/specialinformation.cpp @@ -0,0 +1,623 @@ +/*************************************************************************** + specialinformation.cpp - internal commands information + ------------------- + copyright : (C) 2004 by Michal Rudolf <mrudolf@kdewebdev.org> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "specials.h" +#include "specialinformation.h" + +#include <klocale.h> + +SpecialFunction::SpecialFunction(const QString& name, const QString& description, + int minArgs, int maxArgs) +{ + m_parserTypes = AllParsers; + int lbracket = name.find('('); + int rbracket = name.find(')'); + m_function = (lbracket != -1) ? name.left(lbracket) : name; + m_description = description; + if (lbracket != -1 && rbracket != -1) + { + QString part = name.mid(lbracket+1, rbracket - lbracket - 1); + QStringList args = QStringList::split(",", part); + for (uint i=0; i<args.count(); i++) + { + m_types.append(args[i].stripWhiteSpace().section(' ', 0, 0)); + m_args.append(args[i].stripWhiteSpace().section(' ', 1, 1)); + } + } + m_minArgs = (minArgs == -1) ? m_types.count() : minArgs; + m_maxArgs = (maxArgs == -1) ? m_types.count() : maxArgs; +} + +SpecialFunction::SpecialFunction(ParserType p, const QString& name, const QString& description, + int minArgs, int maxArgs) +{ + m_parserTypes = p; + int lbracket = name.find('('); + int rbracket = name.find(')'); + m_function = (lbracket != -1) ? name.left(lbracket) : name; + m_description = description; + if (lbracket != -1 && rbracket != -1) + { + QString part = name.mid(lbracket+1, rbracket - lbracket - 1); + QStringList args = QStringList::split(",", part); + for (uint i=0; i<args.count(); i++) + { + m_types.append(args[i].stripWhiteSpace().section(' ', 0, 0)); + m_args.append(args[i].stripWhiteSpace().section(' ', 1, 1)); + } + } + m_minArgs = (minArgs == -1) ? m_types.count() : minArgs; + m_maxArgs = (maxArgs == -1) ? m_types.count() : maxArgs; +} + + +QString SpecialFunction::prototype(uint prototypeFlags) const +{ + if (!m_types.count()) + return m_function; + int start = (prototypeFlags & SkipFirstArgument) ? 1 : 0; + QStringList params; + for (uint i=start; i<m_types.count(); i++) + if (prototypeFlags & ShowArgumentNames) + params.append(QString("%1 %2").arg(m_types[i]).arg(m_args[i])); + else + params.append(m_types[i]); + if (!params.count()) + return m_function; + else if (prototypeFlags & NoSpaces) + return QString("%1(%2)").arg(m_function).arg(params.join(",")); + else + return QString("%1(%2)").arg(m_function).arg(params.join(", ")); +} + +QString SpecialFunction::argumentName(uint i) const +{ + if (i < m_args.count()) + return m_args[i]; + return QString(); +} + +QString SpecialFunction::argumentType(uint i) const +{ + if (i < m_types.count()) + return m_types[i]; + return QString(); +} + +int SpecialFunction::argumentCount() const +{ + return m_types.count(); +} + + + + +int SpecialInformation::function(int group, const QString& fname) +{ + QString f = fname.lower(); + if (m_functions.contains(group) && m_functions[group].contains(f)) + return m_functions[group][f]; + else if (m_aliases.contains(group) && m_aliases[group].contains(f)) + return m_aliases[group][f]; + return -1; +} + +SpecialFunction SpecialInformation::functionObject(const QString& gname, const QString& fname) +{ + int gid = group(gname); + return m_specials[gid][function(gid, fname)]; +} + +int SpecialInformation::group(const QString& gname) +{ + if (m_groups.contains(gname)) + return m_groups[gname]; + return -1; +} + +bool SpecialInformation::isValid(int gname, int fname) +{ + return m_specials.contains(gname) && m_specials[gname].contains(fname); +} + +bool SpecialInformation::isValid(const QString& gname, const QString& fname) +{ + return function(group(gname), fname) != -1; +} + +bool SpecialInformation::isValid(int gname, int fname, SpecialFunction::ParserType p) +{ + return m_specials.contains(gname) && m_specials[gname].contains(fname) + && m_specials[gname][fname].isSupported(p); +} + +bool SpecialInformation::isValid(const QString& gname, const QString& fname, + SpecialFunction::ParserType p) +{ + int g = group(gname); + int f = function(g, fname); + return f != -1 && m_specials[g][f].isSupported(p); +} + +int SpecialInformation::minArg(int gname, int fname) +{ + if (isValid(gname, fname)) + return m_specials[gname][fname].minArg(); + return -1; +} + +int SpecialInformation::maxArg(int gname, int fname) +{ + if (isValid(gname, fname)) + return m_specials[gname][fname].maxArg(); + return -1; +} + +int SpecialInformation::argCount(int gname, int fname) +{ + if (isValid(gname, fname)) + return m_specials[gname][fname].argumentCount(); + return -1; +} + +bool SpecialInformation::isValidArg(int gname, int fname, int args) +{ + if (isValid(gname, fname)) + return m_specials[gname][fname].isValidArg(args); + return -1; +} + +QString SpecialInformation::description(int gname, int fname) +{ + if (isValid(gname, fname)) + return m_specials[gname][fname].description(); + return QString(); +} + +QString SpecialInformation::prototype(int gname, int fname, uint flags) +{ + if (isValid(gname, fname)) + return m_specials[gname][fname].prototype(flags); + return QString(); +} + +bool SpecialInformation::insert(int id, const QString& function, const QString description, + int minArgs, int maxArgs, SpecialFunction::ParserType pType) +{ + if (isValid(m_defaultGroup, id)) /* function already defined */ + return false; + if (m_functions[m_defaultGroup].contains(function.lower())) + return false; /* function name already in use */ + if (m_aliases[m_defaultGroup].contains(function.lower())) + return false; /* function name already in use */ + SpecialFunction sf(pType, function, description, minArgs, maxArgs); + m_specials[m_defaultGroup][id] = sf; + m_functions[m_defaultGroup][sf.name().lower()] = id; + return true; +} + +bool SpecialInformation::insertMacro(int id, const QString& function, const QString description, + int minArgs, int maxArgs) +{ + return insert(id, function, description, minArgs, maxArgs, SpecialFunction::MacroParser); +} + +bool SpecialInformation::insertInternal(int id, const QString& function, const QString description, + int minArgs, int maxArgs) +{ + return insert(id, function, description, minArgs, maxArgs, SpecialFunction::InternalParser); +} + +bool SpecialInformation::insertAlias(int id, const QString& alias) +{ + if (!isValid(m_defaultGroup, id)) /* function doesn't exists */ + return false; + if (m_functions[m_defaultGroup].contains(alias.lower())) + return false; + if (m_aliases[m_defaultGroup].contains(alias.lower())) + return false; + m_aliases[m_defaultGroup][alias] = id; + return true; +} + +void SpecialInformation::setDefaultGroup(int gname) +{ + m_defaultGroup = gname; +} + +void SpecialInformation::insertGroup(int id, const QString& name, const QString& parserName) +{ + if (group(name) == -1) { + m_groups[name] = id; + m_parserGroups[name] = parserName; + m_defaultGroup = id; + } +} + +QString SpecialInformation::parserGroupName(const QString& name) +{ + if (m_parserGroups.contains(name)) + return m_parserGroups[name]; + else + return name; +} + +QStringList SpecialInformation::groups() +{ + return m_groups.keys(); +} + +QStringList SpecialInformation::functions(const QString& g) +{ + int gid = group(g); + if (gid == -1) + return QStringList(); + else + { + QStringList list; + const QMap<int, SpecialFunction> fgroup = m_specials[gid]; + for(QMap<int, SpecialFunction>::ConstIterator it = fgroup.begin(); it != fgroup.end(); ++it) + list.append(it.data().name()); + return list; + } +} + +bool SpecialFunction::isSupported(ParserType p) const +{ + return (m_parserTypes & p); +} + +void SpecialInformation::registerSpecials() +{ + insertGroup(Group::DCOP, "DCOP", ""); + insert(DCOP::addUniqueItem, "addUniqueItem(QString widget, QString item)", + i18n("Inserts the item if it will not create a duplicate."), 2); + insert(DCOP::associatedText, "associatedText(QString widget)", + i18n("Returns scripts associated with widget. This is an advanced feature that would not be commonly used."), 1); + insert(DCOP::cancel, "cancel(QString widget)", i18n("Stops execution of the script associated with the widget."), 1); + insert(DCOP::cellText, "cellText(QString widget, int row, int column)", + i18n("Returns text of a cell in a table."), 3); + insert(DCOP::checked, "checked(QString widget)", + i18n("Returns 1 for checked boxes, 0 for unchecked."), 1); + insert(DCOP::children, "children(QString widget, bool recursive)", + i18n("Returns the list of child widgets contained in the parent widget. Set the <i>recursive</i> parameter to <i>true</i> to include widgets contained by child widgets."), 2); + insert(DCOP::clear, "clear(QString widget)", + i18n("Removes all content from the widget."), 1); + insertAlias(DCOP::clear, "clearList"); + insertInternal(DCOP::columnCount, "columnCount(QString widget)", + i18n("Get the column count"), 1); + insert(DCOP::count, "count(QString widget)", + i18n("Returns number of items in a widget such as combobox or listbox."), 1); + insert(DCOP::currentColumn, "currentColumn(QString widget)", + i18n("Returns index of current column."), 1); + insert(DCOP::currentItem, "currentItem(QString widget)", + i18n("Returns index of current item."), 1); + insert(DCOP::currentRow, "currentRow(QString widget)", + i18n("Returns index of current row."), 1); + insert(DCOP::execute, "execute(QString widget)", + i18n("Executes the script associated with the widget. With the new parser the execute method can take one or more arguments."), 1, 9); + insert(DCOP::findItem, "findItem(QString widget, QString item, int column, bool CaseSensitive, bool ExactMatch)", + i18n("Returns the index of an item with the given text. Defaults to case sensitive. Matching can be an exact match or match if it contains the string. Only the first argument is requred. If no column is given it will search the first by default."), 2, 5); + insert(DCOP::insertColumn, "insertColumn(QString widget, int column, int count)", + i18n("Inserts new column (or <i>count</i> columns) at <i>column</i> position."), 2); + insert(DCOP::insertItem, "insertItem(QString widget, QString item, int index)", + i18n("Inserts item at <i>index</i> position."), 3); + insertAlias(DCOP::insertItem, "addListItem"); + insert(DCOP::insertItems, "insertItems(QString widget, QStringList items, int index)", + i18n("Inserts multiple items (EOL-separated) at <i>index</i> position."), 3); + insertAlias(DCOP::insertItems, "addListItems"); + insert(DCOP::insertRow, "insertRow(QString widget, int row, int count)", + i18n("Inserts new row (or <i>count</i> rows) at <i>row</i> position."), 2); + insert(DCOP::item, "item(QString widget, int index)", + i18n("Returns the text of the item at the given index."), 2); + insert(DCOP::itemDepth, "itemDepth(QString widget, int index)", + i18n("Returns the depth of the current item in the tree. Root items have depth 0."), 2); + insert(DCOP::itemPath, "itemPath(QString widget, int index)", + i18n("Returns the slash-separated path to the given item in the tree."), 2); + insert(DCOP::removeColumn, "removeColumn(QString widget, int column, int count)", + i18n("Removes the column (or <i>count</i> consecutive columns) with the given index."), 2, 3); + insert(DCOP::removeItem, "removeItem(QString widget, int index)", + i18n("Removes the item with the given index."), 2); + insertAlias(DCOP::removeItem, "removeListItem"); + insert(DCOP::removeRow, "removeRow(QString widget, int row, int count)", + i18n("Removes the row (or <i>count</i> consecutive rows) with the given index."), 3); + insertAlias(DCOP::removeItem, "removeListItem"); + insert(DCOP::selection, "selection(QString widget)", + i18n("Returns selected text or text of current item.\nIn case of Table widgets, returns the selection coordinates, separated by commas in TopRow,LeftColumn,BottomRow,RightColumn form. "), 1); + insert(DCOP::setAssociatedText, "setAssociatedText(QString widget, QString text)", + i18n("Sets scripts associated with widget. This is an advanced feature that would not be commonly used."), 2); + insert(DCOP::setEnabled, "setEnabled(QString widget, bool enabled)", + i18n("Enables or disables widget."), 2); + insertAlias(DCOP::setEnabled, "enableWidget"); + insert(DCOP::setCellText, "setCellText(QString widget, int row, int col, QString text)", + i18n("Sets text of a cell in a table."), 4); + insert(DCOP::setCellWidget, "setCellWidget(QString widget, int row, int col, QString cellWidget)", + i18n("Inserts a widget into a cell of a table."), 4); + insert(DCOP::cellWidget, "cellWidget(QString widget, int row, int col)", + i18n("Returns the name of a widget inserted into a cell, or an empty string if the cell contains no widget or an unknown widget type."), 3); + insert(DCOP::setChecked, "setChecked(QString widget, bool checked)", + i18n("Sets/unsets checkbox."), 2); + insert(DCOP::setColumnCaption, "setColumnCaption(QString widget, int column, QString text)", + i18n("Sets caption of the column <i>column</i>."), 3); + insert(DCOP::setCurrentItem, "setCurrentItem(QString widget, int index)", + i18n("Selects the item at the specified index. Indexes are zero based."), 2); + insertAlias(DCOP::setCurrentItem, "setCurrentTab"); + insert(DCOP::insertTab, "insertTab(QString widget, QString label,int index)", + i18n("Inserts a tab to the tabwidget with the specified label at the given index. Indexes are zero based."), 3); //enable for 3.5.8 + insert(DCOP::setMaximum, "setMaximum(QString widget, int value)", + i18n("Sets maximum numeric value"), 2); + insert(DCOP::setPixmap, "setPixmap(QString widget, QString iconName, int index)", + i18n("Sets pixmap at the given index to the specified icon. Use <i>index = -1</i> to set the pixmap for all items."), 3); + insert(DCOP::setRowCaption, "setRowCaption(QString widget, int row, QString text)", + i18n("Sets caption of the row <i>row</i>."), 3); + insert(DCOP::setSelection, "setSelection(QString widget, QString text)", + i18n("Selects given text or select item containing given text."), 2); + insertAlias(DCOP::setSelection, "setCurrentListItem"); + insert(DCOP::setText, "setText(QString widget, QString text)", + i18n("Sets widget's content."), 2); + insertAlias(DCOP::setText, "changeWidgetText"); + insert(DCOP::setVisible, "setVisible(QString widget, bool visible)", + i18n("Shows/hides widget."), 2); + insert(DCOP::text, "text(QString widget)", i18n("Returns content of widget."), 1); + insert(DCOP::type, "type(QString widget)", + i18n("Returns type(class) of widget."), 1); + insert(DCOP::setEditable, "setEditable(QString widget, bool editable)", + i18n("Makes the widget editable or read only, depending on the editable argument."), 2); + insertInternal(DCOP::geometry, "geometry(QString widget)", + i18n("Return the widget's geometry as <i>x y w h</i>. This is useful for positioning a created widget."), 1); + insertInternal(DCOP::hasFocus, "hasFocus(QString widget)", + i18n("Returns true if the widget has focus."), 1); + insertInternal(DCOP::getBackgroundColor, "getBackgroundColor(QString widget)", + i18n("Gets the widget's background color."), 1); + insertInternal(DCOP::setBackgroundColor, "setBackgroundColor(QString widget, QString Color)", + i18n("Sets the widget's background color. Colors can be by name, like blue, or in hex like #0000ff for blue. Use the color dialog or a color picker if unsure."), 2); + insertInternal(DCOP::isModified, "isModified(QString widget)", + i18n("See if widget has been modified."), 1); + + insertGroup(Group::Slots, i18n("Slots"), ""); + + insertGroup(Group::Kommander, "Kommander", ""); + insertMacro(Kommander::widgetText, "widgetText", + i18n("Returns current widget's content. This was required inside widget A to return widget A content when requested by widget B. The new method is to use @A.text inside B instead of just @A if you just want the unaltered text."), 0); + insertMacro(Kommander::selectedWidgetText, "selectedWidgetText", + i18n("Returns selected text or text of current item. This is deprecated for <i>@mywidget.selected</i>."), 0); + insertMacro(Kommander::null, "null", + i18n("Does nothing. This is useful if you request a CheckBox or RadioButton to return a value where a state, typically the unchecked state, has no value. The @null prevents an error indicating it is empty."), 0); + insert(Kommander::pid, "pid", + i18n("Returns the pid (process ID) of the current process."), 0); + insert(Kommander::dcopid, "dcopid", + i18n("Returns DCOP identifier of current process. This is shorthand for <i>kmdr-executor-@pid</i>."), + 0); + insert(Kommander::parentPid, "parentPid", + i18n("Returns the pid of the parent Kommander window."), 0); + insert(Kommander::debug, "debug(QString text)", + i18n("Writes <i>text</i> on stderr."), 1); + insert(Kommander::echo, "echo(QString text)", + i18n("Writes <i>text</i> on standard output."), 1); + insertMacro(Kommander::execBegin, "execBegin(QString shell)", + i18n("Executes a script block. Bash is used if no shell is given. It is primarily for use in non-button widgets where script actions are not expected. Full path is not required for the shell which may be useful for portability. <p><i>If this is used inside a button it allows alternate script languages to be used and will return a value to the main script, which may be unexpected.</i>"), 0); + insert(Kommander::env, "env(QString variable)", + i18n("Returns value of an environment (shell) variable. Do not use <i>$</i> in the name. For example, <i>@env(PATH)</i>."), 1); + insert(Kommander::exec, "exec(QString command)", + i18n("Executes an external shell command."), 1); + insertInternal(Kommander::execBackground, "execBackground(QString command)", + i18n("Executes an external shell command."), 1); + insertMacro(Kommander::expr, "expr(QString expression)", + i18n("Parses an expression and returns computed value."), 1); + insert(Kommander::forEachBlock, "forEach(QString variable, QString items)", + i18n("Executes loop: values from <i>items</i> list (passed as EOL-separated string) are assigned to the variable. <br><b>Old</b><br> <i>@forEach(i,A\\nB\\nC\\n)<br> @# @i=A<br>@end</i><br><b>New</b><br><i>foreach i in MyArray do<br> //i = key, MyArray[i] = val<br>end "), 2); + insert(Kommander::forBlock, "for(QString variable, int start, int end, int step)", + i18n("Executes loop: variable is set to <i>start</i> and is increased by <i>step</i> each time loop is executed. Execution stops when variable becomes larger then <i>end</i>. <br><b>Old</b><br><i>@for(i,1,10,1)<br> @# @i=1<br>@endif</i><br><b>New</b><br><i>for i=0 to 20 step 5 do<br> debug(i)<br>end</i>."), 3); + insertMacro(Kommander::global, "global(QString variable)", + i18n("Returns the value of a global variable."), 1); + insert(Kommander::i18n, "i18n(QString variable)", + i18n("Translates the string into the current language. Texts in GUI would be automatically extracted for translation."), 1); + insert(Kommander::ifBlock, "if(QString expression)", + i18n("Executes block if expression is true (non-zero number or non-empty string.) <p><b>Old</b>Close with <b>@endif</b></p><p><b>New</b><br>if val == true then<br>// do op<br>elseif cond<br>// second chance<br>else<br>// cond failed<br>endif</p>"), 1); + insert(Kommander::dialog, "dialog(QString file, QString args)", + i18n("Executes another Kommander dialog. Current dialog directory is used if no path is given. Arguments may be given as named arguments which will become global variables in the new dialog. For instance: <i>var=val</i>"), 1); + insert(Kommander::readSetting, "readSetting(QString key, QString default)", + i18n("Reads setting from configration file for this dialog."), 2); + insert(Kommander::setGlobal, "setGlobal(QString variable, QString value)", + i18n("Sets the value of a global variable. Global variables exist for the life of the Kommander window."), 2); + insert(Kommander::writeSetting, "writeSetting(QString key, QString value)", + i18n("Stores setting in configuration file for this dialog."), 2); + insertMacro(Kommander::switchBlock, "switch(QString expresion)", + i18n("Begin of <b>switch</b> block. Following <b>case</b> values are compared to <i>expression</i>.<p>@switch()<br>@case()<br>@end"), 1); + insert(Kommander::dcop, "dcop(QString id, QString interface, QString function, QString args)", + i18n("Executes an external DCOP call."), 3, 9); + insertMacro(Kommander::comment, "#", + i18n("Adds a comment to EOL that Kommander will not parse"), 0); + insertInternal(Kommander::createWidget, "createWidget(QString widgetName, QString widgetType, QString parent)", + i18n("Creates a new widget with the specified type and as the child of parent."), 3); + insertInternal(Kommander::widgetExists, "widgetExists(QString widgetName)", + i18n("Returns true if there is a widget with the passed name, false otherwise."), 1); + insertInternal(Kommander::connect, "connect(QString sender, QString signal, QString receiver, QString slot)", + i18n("Connects the signal of sender with the slot of the receiver"), 4); + insertInternal(Kommander::disconnect, "disconnect(QString sender, QString signal, QString receiver, QString slot)", + i18n("Disconnects the signal of sender from the slot of the receiver"), 4); +/* insertInternal(Kommander::switchInternal, "switch(QString Variable)", + i18n("Can use can use <br>switch var<br>case 1<br> //code<br>else<br> //code<br>end<p>also can use the form of <br>switch var {<br>case 1; //code<br>else; code<br>}<p> semicolons are optional in place of returns. Currently switch does not parse value from arrays.") ); +*/ + insertInternal(Kommander::exit, "exit", + i18n("Exits script execution and returns"), 0); + insertInternal(Kommander::Break, "break", + i18n("Exits the current block of a while, for or foreach loop"), 0); + insertInternal(Kommander::Continue, "continue", + i18n("Exit a step and return to the beginning of a loop"), 0); + insertInternal(Kommander::Return, "return(QString value)", + i18n("Return from a script, optionaly with a value from the script to the caller"), 0, 1); + + insertGroup(Group::Array, "Array", "array"); + insert(Array::values, "values(QString array)", + i18n("Returns an EOL-separated list of all values in the array."), 1); + insert(Array::keys,"keys(QString array)", + i18n("Returns an EOL-separated list of all keys in the array."), 1); + insert(Array::clear,"clear(QString array)", + i18n("Removes all elements from the array."), 1); + insert(Array::count,"count(QString array)", + i18n("Returns the number of elements in the array."), 1); + insertMacro(Array::value, "value(QString array, QString key)", + i18n("Returns the value associated with the given key."), 2); + insert(Array::remove,"remove(QString array, QString key)", + i18n("Removes element with the given key from the array."), 2); + insertMacro(Array::setValue,"setValue(QString array, QString key, QString value)", + i18n("Adds element with the given key and value to the array"), 3); + insert(Array::fromString, "fromString(QString array, QString string)", + i18n("Adds all elements in the string to the array. " + "String should have <i>key\\tvalue\\n</i> format."), 2); + insert(Array::toString, "toString(QString array)", + i18n("Returns all elements in the array in <pre>key\\tvalue\\n</pre> format."), 1); + insertInternal(Array::indexedFromString, "indexedFromString(QString array, QString string, QString separator)", + i18n( "Create an integer indexed array - starting from 0 - from a string. Use the separator character to split the string. The separator's default value is '\\t'."), 2, 3); + insertInternal(Array::indexedToString, "indexedToString(QString array, QString separator)", + i18n( "Create a string from an integer indexed array. Concatenate the elements with the separator character. The separator's default value is '\\t'."), 1, 2); + insertInternal(Array::indexedRemoveElements, "indexedRemoveElements(QString array, int keyStart, int keyNum)", + i18n( "Remove keyNum elements starting with keyStart from an indexed array and reindex the array. If keyNum is not specified, remove only the keyStart element."), 2, 3); + insertInternal(Array::indexedInsertElements, "indexedInsertElements(QString array, int key, QString string, QString separator)", + i18n( "Insert the elements from string starting at key and reindex the array. Use the separator to separate the elements from the string. The separator's default value is '\\t'."), 3, 4); + insertInternal(Array::flipCopy, "flipCopy(QString Array, QString Copy)", + i18n("Create a flipped copy of the array where the keys and values switch places. NOTE: If the values are not unique they will be overwritten as keys! Set the name of the array to copy to and go. Useful with combos and lists were you have an index, a key and a value for data purposes."), 2, 2); + + insertGroup(Group::Matrix, "Matrix", "matrix"); + insertInternal(Matrix::fromString, "fromString(QString matrix, QString String, bool With-Row-Keys, bool With-Col-Keys)", + i18n("Create a 2D array with zero based integer keys. Rows seperated with returns or \\n and columns with tabs or \\t. You can then read and alter values with \"name[0][1]\".<br><b>NOTE: Watch keys!</b> The row and column keys when set to true will read respectively the first row and first column as headings. If for instance you set one where there is no column or row heading to read it will read data, and if the data is not unique you will have missing columns or rows as well as addressing not working."), 2, 4); + insertInternal(Matrix::toString, "toString(QString matrix, bool RowHeadings, bool ColHeadings)", + i18n("Convert 2D array to string, optionaly with row and column headings. If written without values set it will default to no headings."), 1, 3); + insertInternal(Matrix::rows, "rows(QString matrix)", + i18n("Return the number of rows in the matrix"), 1); + insertInternal(Matrix::columns, "columns(QString matrix)", + i18n("Return the number of columns in the matrix"), 1); + insertInternal(Matrix::clear, "clear(QString matrix)", + i18n("Clear the entire matrix"), 1); + insertInternal(Matrix::rowToArray, "rowToArray(QString matrix, QString Row, QString Array, bool Clear-First, bool Indexed)", + i18n("Convert row to array. Useful break out rows of data to work with. If you want to avoid spurious data Clear-First will wipe the array before filling it. If you choose indexed it will use a zero based index. Otherwise it will use the column keys."), 3, 5); + insertInternal(Matrix::columnToArray, "columnToArray(QString matrix, QString Column, QString Array)", + i18n("Copy a column of a Matrix to an array and optionally clear array first to avoid spurious data in loops"), 3); + insertInternal(Matrix::columnToIndexedArray, "columnToIndexedArray(QString matrix, QString Column, QString Array)", + i18n("Copy a column of a Matrix to an indexed array"), 3); + insertInternal(Matrix::rowKeys, "rowKeys(QString Matrix, QString Seperator)", + i18n("Return the row keys from the matrix. Separator defaults to [tab] \"\\t\" if left empty"), 1, 2); + insertInternal(Matrix::columnKeys, "columnKeys(QString Matrix, QString Seperator)", + i18n("Return the column keys from the matrix. Separator defaults to [tab] \"\\t\" if left empty"), 1, 2); + insertInternal(Matrix::addRow, "addRow(QString Matrix, QString RowKey, QString data)", + i18n("Add a row to the matrix. Specifiy the row key and format the data as column key [tab] column value on each line using key\\tval\\nkey\\tval format"), 3); + insertInternal(Matrix::removeRow, "removeRow(QString Matrix, QString RowKey)", + i18n("Remove a row from the matrix by key name. Returns true if key is found."), 2); + insertInternal(Matrix::removeColumn, "removeColumn(QString Matrix, QString ColKey)", + i18n("Remove a column from the matrix by key name. Returns true if key is found."), 2); + insertInternal(Matrix::findRow, "findRow(QString Matrix, QString Col-Key, QString Col-Value, int Iteration)", + i18n("Find the row key that matches a column value. Use this for unique key searches. Iteration may be omitted and the default is to return the first instance. In a loop it will return sequential finds until there are no more, in which case it returns null."), 3, 4); + + insertGroup(Group::String, "String", "str"); + insert(String::length, "length(QString string)", + i18n("Returns number of chars in the string."), 1); + insert(String::contains, "contains(QString string, QString substring)", + i18n("Checks if the the string contains the given substring."), 2); + insert(String::find, "find(QString string, QString sought, int index)", + i18n("Returns the position of a substring in the string, or -1 if it is not found."), 2); + insert(String::findRev, "findRev(QString string, QString sought, int index)", + i18n("Returns the position of a substring in the string, or -1 if it is not found. String is searched backwards"), 2); + insertInternal(String::count, "count(QString String, QString substring)", + i18n("Returns the count of a given substring in the given string."), 2); + insert(String::left, "left(QString string, int n)", + i18n("Returns the first <i>n</i> chars of the string."), 2); + insert(String::right, "right(QString string, int n)", + i18n("Returns the last <i>n</i> chars of the string."), 2); + insert(String::mid, "mid(QString string, int start, int n)", + i18n("Returns <i>n</i> chars of the string, starting from <i>start</i>."), 3); + insert(String::remove, "remove(QString string, QString substring)", + i18n("Removes all occurrences of given substring."), 2); + insert(String::replace, "replace(QString string, QString substring, QString replacement)", + i18n("Replaces all occurrences of the given substring with the given replacement."), 3); + insert(String::upper, "upper(QString string)", + i18n("Converts the string to uppercase."), 1); + insert(String::lower, "lower(QString string)", + i18n("Converts the string to lowercase."), 1); + insert(String::compare, "compare(QString string1, QString string2)", + i18n("Compares two strings. Returns 0 if they are equal, " + "-1 if the first one is lower, 1 if the first one is higher"), 2); + insert(String::isEmpty, "isEmpty(QString string)", + i18n("Checks if the string is empty."), 1); + insert(String::isNumber, "isNumber(QString string)", + i18n("Checks if the string is a valid number."), 1); + insert(String::section, "section(QString string, QString separator, int index)", + i18n("Returns given section of a string."), 1); + insert(String::args, "args(QString string, QString arg1, QString arg2, QString arg3)", + i18n("Returns the given string with %1, %2, %3 replaced with <i>arg1</i>, <i>arg2</i>, <i>arg3</i> accordingly."), 2); + insert(String::round, "round(QString Number, int Digits)", + i18n("Round a floating point number by x digits."), 2); + insertInternal(String::sort, "sort(QString String, QString Separator)", + i18n("Sort a string list. Only first paramter is required. Default separator is a newline."), 1, 2); + insertInternal(String::trim, "trim(QString String)", + i18n("Strips white space from beginning and end of string."), 1); + insertInternal(String::padLeft, "padLeft(QString String, int Length, QString Pad)", + i18n("Pads the string to the total length indicated. if no pad character is given spaces will be used. Try this with 0 on integer sequences and read them with str_toint."), 1, 2); + insertInternal(String::padRight, "padRight(QString String, int Length, QString Pad)", + i18n("Pads the string to the total length indicated. if no pad character is given spaces will be used."), 1, 2); + + insertInternal(String::toInt, "toint(QString string, QString default)", + i18n("Convert a string to an integer. If not possible use the default value"), 1, 2); + insertInternal(String::toDouble, "todouble(QString string, QString default)", + i18n("Convert a string to a double precision floating point value. If not possible use the default value"), 1, 2); + + insertGroup(Group::File, "File", "file"); + insert(File::read, "read(QString file)", + i18n("Returns content of given file."), 1); + insert(File::write, "write(QString file, QString string)", + i18n("Writes given string to a file."), 2); + insert(File::append, "append(QString file, QString string)", + i18n("Appends given string to the end of a file."), 2); + insert(File::exists, "exists(QString file)", + i18n("Checks to see if file exists."), 1); + + insertGroup(Group::Input, "Input", "input"); + insert(Input::color, "color(QString defaultColor)", i18n("Shows color dialog. Returns color in #RRGGBB format. Defaults to the parameter, if specified."), 0, 1); + insert(Input::text, "text(QString caption, QString label, QString default)", + i18n("Shows text selection dialog. Returns entered text."), 2); + insert(Input::password, "password(QString caption, QString password)", + i18n("Shows a dialog asking user for password and returns it."), 1); + insert(Input::value, "value(QString caption, QString label, int value, int min, int max, int step)", + i18n("Shows value selection dialog. Returns entered value."), 5); + insert(Input::valueDouble, "double(QString caption, QString label, double value, double min, double max, double step)", + i18n("Shows float value selection dialog. Returns entered value."), 6); + insert(Input::openfile, "openfile(QString startdir, QString filter, QString caption)", + i18n("Shows existing file selection dialog. Returns selected file."), 0); + insert(Input::savefile, "savefile(QString startdir, QString filter, QString caption)", + i18n("Shows save file selection dialog. Returns selected file."), 0); + insert(Input::directory, "directory(QString startdir, QString filter, QString caption)", + i18n("Shows directory selection dialog. Returns selected directory."), 0); + insert(Input::openfiles, "openfiles(QString startdir, QString filter, QString caption)", + i18n("Shows multiple files selection dialog. Returns EOL-separated list of selected files."), 0); + + insertGroup(Group::Message, "Message", "message"); + insert(Message::info, "info(QString text, QString caption)", + i18n("Shows an information dialog. Returns true when clicked so you can check for user response."), 1); + insert(Message::error, "error(QString text, QString caption)", + i18n("Shows an error dialog. Returns true when clicked so you can check for user response."), 1); + insert(Message::warning, "warning(QString text, QString caption, QString button1, QString button2, QString button3)", + i18n("Shows a warning dialog with up to three buttons. Returns number of selected button."), 1); + insert(Message::question, "question(QString text, QString caption, QString button1, QString button2, QString button3)", + i18n("Shows a question dialog with up to three buttons. Returns number of selected button."), 1); + +} + +QMap<int, QMap<int, SpecialFunction> > SpecialInformation::m_specials; +QMap<QString, int> SpecialInformation::m_groups; +QMap<QString, QString> SpecialInformation::m_parserGroups; +QMap<int, QMap<QString, int> > SpecialInformation::m_functions; +QMap<int, QMap<QString, int> > SpecialInformation::m_aliases; +int SpecialInformation::m_defaultGroup; + diff --git a/kommander/plugin/specialinformation.h b/kommander/plugin/specialinformation.h new file mode 100644 index 00000000..20b6ea04 --- /dev/null +++ b/kommander/plugin/specialinformation.h @@ -0,0 +1,119 @@ +/*************************************************************************** + specialinformation.h - internal commands information + ------------------- + copyright : (C) 2004 by Michal Rudolf <mrudolf@kdewebdev.org> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + + +#ifndef _HAVE_SPECIALINFORMATION_H_ +#define _HAVE_SPECIALINFORMATION_H_ + +/* QT INCLUDES */ +#include <qstring.h> +#include <qstringlist.h> +#include <qmap.h> +#include <qpair.h> + +class SpecialFunction +{ +public: + + /* flags for getting function prototype: + SkipFirstArgument - ignore first argument (useful for Kommander functions + prefixed by widget name + ShowArgumentNames - show parameter names, not only types + */ + enum PrototypeFlags {SkipFirstArgument = 1, ShowArgumentNames = 2, NoSpaces = 4}; + /* Flags describing which parser supports the function */ + enum ParserType {MacroParser = 1, InternalParser = 2, AllParsers = 3}; + SpecialFunction(const QString& function, const QString& description + = QString::null, int minArgs = -1, int maxArgs = -1); + SpecialFunction(ParserType p, const QString& function, const QString& description + = QString::null, int minArgs = -1, int maxArgs = -1); + SpecialFunction() {m_minArgs = m_maxArgs = 0;} + /* minimum number of arguments */ + int minArg() const {return m_minArgs;} + /* maximum number of arguments */ + int maxArg() const {return m_maxArgs;} + /* checks number of arguments */ + bool isValidArg(int args) const {return args >= minArg() && args <= maxArg();} + /* function description */ + QString description() const {return m_description;} + /* function name */ + QString name() const {return m_function;} + /* function prototype: with parameter types and optional names */ + QString prototype(uint prototypeFlags = 0) const; + /* i-th parameter name */ + QString argumentName(uint i) const; + /* i-th parameter type */ + QString argumentType(uint i) const; + /* number of named arguments */ + int argumentCount() const; + /* check whether given parser supports the function */ + bool isSupported(ParserType p) const; +protected: + QString m_function; + QString m_description; + int m_minArgs, m_maxArgs; + QStringList m_args; + QStringList m_types; + unsigned m_parserTypes; +}; + + + + +class SpecialInformation +{ +public: + SpecialInformation() {m_defaultGroup = -1;} + static int function(int group, const QString& fname); + static SpecialFunction functionObject(const QString& gname, const QString& fname); + static int group(const QString& gname); + static bool isValid(int gname, int fname); + static bool isValid(const QString& gname, const QString& fname); + static bool isValid(int gname, int fname, SpecialFunction::ParserType p); + static bool isValid(const QString& gname, const QString& fname, SpecialFunction::ParserType p); + static int minArg(int gname, int fname); + static int maxArg(int gname, int fname); + static int argCount(int gname, int fname); + static bool isValidArg(int gname, int fname, int args); + static QString description(int gname, int fname); + static QString prototype(int gname, int fname, uint prototypeFlags = 0); + /* Insert function supported by all parsers */ + static bool insert(int id, const QString& function, const QString description = QString::null, + int minArgs = -1, int maxArgs = -1, SpecialFunction::ParserType = SpecialFunction::AllParsers); + /* Insert function supported by (old) macro parser */ + static bool insertMacro(int id, const QString& function, const QString description = QString::null, + int minArgs = -1, int maxArgs = -1); + /* Insert function supported by (new) internal parser */ + static bool insertInternal(int id, const QString& function, const QString description = QString::null, + int minArgs = -1, int maxArgs = -1); + static bool insertAlias(int id, const QString& alias); + static void insertGroup(int id, const QString& name, const QString& parserName); + static void setDefaultGroup(int gname); + static void registerSpecials(); + static QString parserGroupName(const QString&); + static QStringList groups(); + static QStringList functions(const QString& group); +protected: + static QMap<int, QMap<int, SpecialFunction> > m_specials; + static QMap<QString, int> m_groups; + static QMap<QString, QString> m_parserGroups; + static QMap<int, QMap<QString, int> > m_functions; + static QMap<int, QMap<QString, int> > m_aliases; + static int m_defaultGroup; +}; + + +#endif + diff --git a/kommander/plugin/specials.h b/kommander/plugin/specials.h new file mode 100644 index 00000000..2d46200a --- /dev/null +++ b/kommander/plugin/specials.h @@ -0,0 +1,77 @@ +/*************************************************************************** + specials.h - known specials and DCOP calls + ------------------- + copyright : (C) 2004 by Michal Rudolf <mrudolf@kdewebdev.org> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _HAVE_SPECIALS_H_ +#define _HAVE_SPECIALS_H_ + +/** This file contains the global Kommander defined. In case a new Group, method, etc. is +added it MUST be added to the end of the enum lists in order to keep compatibility with the +existing plugins. */ + + +namespace Group +{ + enum {DCOP, Kommander, String, Array, File, Input, Message, Slots, Matrix}; +} + +namespace DCOP +{ + enum {addUniqueItem, associatedText, cancel, cellText, clear, checked, children, columnCount, count, currentColumn, + currentItem, currentRow, execute, findItem, global, insertColumn, insertItem, insertItems, insertRow, + item, itemDepth, itemPath, removeColumn, removeItem, removeRow, selection, setAssociatedText, setChecked, + setCellText, setCurrentItem, insertTab, setColumnCaption, setEnabled, setGlobal, setMaximum, setPixmap, + setRowCaption, setSelection, setText, getBackgroundColor, setBackgroundColor, + setVisible, text, type, setCellWidget, cellWidget, setEditable, geometry, hasFocus, isModified}; +} + +namespace Kommander +{ + enum {widgetText, selectedWidgetText, null, pid, dcopid, parentPid, debug, + echo, env, exec, expr, global, i18n, dialog, readSetting, setGlobal, writeSetting, dcop, + switchBlock, execBegin, forBlock, forEachBlock, ifBlock, comment, createWidget, connect, disconnect, widgetExists, exit, Break, Continue, Return, execBackground, switchInternal}; //, focusWidget}; +} + +namespace Array +{ + enum {values, keys, clear, count, value, remove, setValue, fromString, toString, indexedFromString, indexedToString, indexedRemoveElements, indexedInsertElements, flipCopy}; +} + +namespace Matrix +{ + enum {fromString, toString, clear, rows, columns, rowToArray, columnToArray, columnToIndexedArray, rowKeys, columnKeys, addRow, removeRow, removeColumn, findRow}; +} + +namespace String +{ + enum {length, contains, find, findRev, left, right, mid, remove, replace, upper, lower, + compare, isEmpty, isNumber, section, args, toInt, toDouble, round, sort, trim, padLeft, padRight, count}; +} + +namespace File +{ + enum {read, write, append, exists}; +} + +namespace Input +{ + enum {color, text, password, value, valueDouble, openfile, openfiles, savefile, directory}; +} + +namespace Message +{ + enum {info, error, question, warning}; +} + +#endif |