diff options
| author | deva <deva> | 2011-06-28 06:38:10 +0000 | 
|---|---|---|
| committer | deva <deva> | 2011-06-28 06:38:10 +0000 | 
| commit | 6389aabffe198ece92b58ae34a905902c7eefe7c (patch) | |
| tree | cfda4b340e462e5193f4ac2e6814cce5d707ca4f /client | |
| parent | 01febc40e2aad29bf6cf6cbeb457c44354aba0f9 (diff) | |
Complete rewrite of the way lua widget methods, 'inheritance' in particular, are handled.
Diffstat (limited to 'client')
30 files changed, 706 insertions, 450 deletions
| diff --git a/client/luawidget.cc b/client/luawidget.cc index 2095a64..28ae488 100644 --- a/client/luawidget.cc +++ b/client/luawidget.cc @@ -31,36 +31,12 @@  #include "debug.h" -/** - ** Copied from lauxlib.c, but modified return NULL upon error instead of - ** casting a lua error. - **/ -void *luaL_isudata (lua_State *L, int ud, const char *tname) -{ -  void *p = lua_touserdata(L, ud); -  if (p != NULL) {  /* value is a userdata? */ -    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */ -      lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get correct metatable */ -      if (lua_rawequal(L, -1, -2)) {  /* does it have the correct mt? */ -        lua_pop(L, 2);  /* remove both metatables */ -        return p; -      } -    } -  } -  //  luaL_typerror(L, ud, tname);  /* else error */ -  return NULL;  /* to avoid warnings */ -} -  int wdg_make_widget(lua_State *L, Widget *widget)  {    wdg_userdata *wdgu;    wdgu = (wdg_userdata *)lua_newuserdata(L, sizeof(wdg_userdata)); +  luaL_getmetatable(L, widget->luaclass().toStdString().c_str()); -  if(widget->type() == "combobox") luaL_getmetatable(L, "ComboBox"); -  else if(widget->type() == "checkbox") luaL_getmetatable(L, "CheckBox"); -  else if(widget->type() == "lineedit") luaL_getmetatable(L, "LineEdit"); -  else luaL_getmetatable(L, "Widget"); -      lua_setmetatable(L, -2);    wdgu->widget = widget; @@ -71,8 +47,14 @@ int wdg_make_widget(lua_State *L, Widget *widget)  void register_widgets(lua_State *L)  {    register_widget(L); +    register_checkbox(L); +  register_checkgroupbox(L); +    register_combobox(L); +  register_altcombobox(L); + +  register_listbox(L);    register_lineedit(L);  } diff --git a/client/luawidget.h b/client/luawidget.h index e6e0be3..c9551c8 100644 --- a/client/luawidget.h +++ b/client/luawidget.h @@ -35,7 +35,7 @@  #define LUA_SRC "lua" -void *luaL_isudata (lua_State *L, int ud, const char *tname); +//void *luaL_isudata (lua_State *L, int ud, const char *tname);  #define luaL_checkbool(L, i) \    (lua_isboolean(L,i) ? lua_toboolean(L,i) : luaL_checkint(L,i)) diff --git a/client/test/testaltcombobox.cc b/client/test/testaltcombobox.cc index 84d92ad..5eb7afb 100644 --- a/client/test/testaltcombobox.cc +++ b/client/test/testaltcombobox.cc @@ -1,31 +1,72 @@  /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */  #include <QtTest/QtTest> + +#include <QComboBox> +  #include "util.h"  #include "altcombobox.h" -#include <QAbstractItemView>  static QString xml =  -	"<altcombobox name=\"mycombobox\" type=\"search\">\n" +	"<altcombobox name=\"mycombobox\" value=\"item1\" type=\"search\">\n"  	"  <item value=\"item1\" caption=\"Item 1\"/>\n"  	"  <item value=\"item3\" caption=\"Item 3\"/>\n" -	"  <item value=\"item2\" caption=\"Item 2\"/>\n" +	"  <altitem value=\"item2\" caption=\"Item 2\" innerwidget=\"in\">\n" +	"    <lineedit name=\"in\" value=\"test\">\n" +	"  </altitem>\n" +	"</altcombobox>\n"; + +static QString xml_lua =  +	"<altcombobox name=\"mycombobox\" value=\"item1\" type=\"search\"\n" +  "             onInit=\"this:addItem('Item 4')\">\n" +	"  <item value=\"item1\" caption=\"Item 1\"/>\n" +	"  <item value=\"item3\" caption=\"Item 3\"/>\n" +	"  <altitem value=\"item2\" caption=\"Item 2\" innerwidget=\"in\">\n" +	"    <lineedit name=\"in\" value=\"test\">\n" +	"  </altitem>\n"  	"</altcombobox>\n";  class TestAltComboBox: public QObject  {  Q_OBJECT  private slots: +    void creation() { TEST_CREATION(AltComboBox); }    void disable() { TEST_DISABLE(AltComboBox); } -  void edit() +  void visible() +	{ +		QDomDocument doc;	doc.setContent(xml); +    QDomElement e = doc.documentElement(); +    AltComboBox cmb(e, createMacroWindow()); +    cmb.qwidget()->show(); +    cmb.setValues(); +     +    QCOMPARE(cmb.visible(), true); + +    Widget *w = cmb.findWidget("in", true); +    QCOMPARE(w->visible(), false); + +    QTest::keyClicks(cmb.qcombobox(), "\b2"); +    QCOMPARE(w->visible(), true); + +    QTest::keyClicks(cmb.qcombobox(), "\b3"); +    QCOMPARE(w->visible(), false); +  } + +  void value()  	{  		QDomDocument doc;	doc.setContent(xml);      QDomElement e = doc.documentElement();      AltComboBox cmb(e, createMacroWindow()); +    cmb.setValues(); -    QTest::keyClicks(cmb.qwidget(), "Item 2"); -    QCOMPARE(cmb.value(), QString("Item 2")); +    QCOMPARE(cmb.value(), QString("item1")); + +    QTest::keyClicks(cmb.qcombobox(), "\b3"); +    QCOMPARE(cmb.value(), QString("item3")); + +    QTest::keyClicks(cmb.qcombobox(), "\b2"); +    QCOMPARE(cmb.value(), QString("test"));    }    void arrow() @@ -34,12 +75,18 @@ private slots:      QDomElement e = doc.documentElement();      AltComboBox cmb(e, createMacroWindow()); +    cmb.setValues(); + +    QCOMPARE(cmb.value(), QString("item1")); -		cmb.qwidget()->setFocus(); -    QTest::keyPress(cmb.qwidget(), Qt::Key_Down); -    QTest::keyPress(cmb.qwidget(), Qt::Key_Down); -    QTest::keyPress(cmb.qwidget(), Qt::Key_Enter); +		cmb.qcombobox()->setFocus(); +    QTest::keyPress(cmb.qcombobox(), Qt::Key_Down); +    QTest::keyPress(cmb.qcombobox(), Qt::Key_Enter);      QCOMPARE(cmb.value(), QString("item3")); + +    QTest::keyPress(cmb.qcombobox(), Qt::Key_Down); +    QTest::keyPress(cmb.qcombobox(), Qt::Key_Enter); +    QCOMPARE(cmb.value(), QString("test"));    }  	void changeEmits() @@ -47,10 +94,32 @@ private slots:  		QDomDocument doc;	doc.setContent(xml);      QDomElement e = doc.documentElement();      AltComboBox cmb(e, createMacroWindow()); +    cmb.setValues(); +  		QSignalSpy spy(&cmb, SIGNAL(wasChanged())); -    QTest::keyClicks(cmb.qwidget(), "I"); -		QCOMPARE(spy.count(), 1); + +    QTest::keyClicks(cmb.qcombobox(), "\b2"); +		QCOMPARE(spy.count(), 2); +    QCOMPARE(cmb.value(), QString("test")); + +    Widget *w = cmb.findWidget("in", true); +    QTest::keyClicks(w->qwidget(), "A"); +    QCOMPARE(cmb.value(), QString("testA")); +		QCOMPARE(spy.count(), 3);  	} + +  void lua() +  { +		QDomDocument doc;	doc.setContent(xml_lua); +    QDomElement e = doc.documentElement(); +    AltComboBox cmb(e, createMacroWindow()); +    cmb.setValues(); +    cmb.qwidget()->show(); +    cmb.runEventOnInit(true); +     +    QTest::keyClicks(cmb.qcombobox(), "\b4"); +    QCOMPARE(cmb.value(), QString("Item 4")); +  }  };  QTEST_MAIN(TestAltComboBox) diff --git a/client/test/testcomboboxedit.cc b/client/test/testcomboboxedit.cc index 76a9792..d85c4e5 100644 --- a/client/test/testcomboboxedit.cc +++ b/client/test/testcomboboxedit.cc @@ -39,7 +39,7 @@ private slots:      ComboBox cmb(e, createMacroWindow());      QTest::keyClicks(cmb.qwidget(), "Item 2"); -    QCOMPARE(cmb.value(), QString("Item 2")); +    QCOMPARE(cmb.value(), QString("item2"));    }    void arrowSelect() diff --git a/client/test/testcomboboxsearch.cc b/client/test/testcomboboxsearch.cc index ff737db..564f5c1 100644 --- a/client/test/testcomboboxsearch.cc +++ b/client/test/testcomboboxsearch.cc @@ -39,7 +39,7 @@ private slots:  		// Full item search      QTest::keyClicks(cmb.qwidget(), "Item 2"); -    QCOMPARE(cmb.value(), QString("Item 2")); +    QCOMPARE(cmb.value(), QString("item2"));    }    void searchPrefix() @@ -54,7 +54,7 @@ private slots:  		QCOMPARE(qcmb->completer()->currentCompletion(), QString("Thingy"));      QTest::keyClicks(cmb.qwidget(), qcmb->completer()->currentCompletion()); -    QCOMPARE(cmb.value(), QString("Thingy")); +    QCOMPARE(cmb.value(), QString("thingy"));    }    void searchNegative() diff --git a/client/test/testcomboboxselect.cc b/client/test/testcomboboxselect.cc index 3eaac00..86700c1 100644 --- a/client/test/testcomboboxselect.cc +++ b/client/test/testcomboboxselect.cc @@ -39,7 +39,7 @@ private slots:      ComboBox cmb(e, createMacroWindow());      QTest::keyClicks(cmb.qwidget(), "Item 2"); -    QCOMPARE(cmb.value(), QString("Item 2")); +    QCOMPARE(cmb.value(), QString("item2"));    }    void arrowSelect() diff --git a/client/test/util.cc b/client/test/util.cc index 1fd09d4..80556c8 100644 --- a/client/test/util.cc +++ b/client/test/util.cc @@ -9,17 +9,14 @@  MacroWindow *createMacroWindow()  { -  MacroWindow *m; -    QSettings settings("pracro.ini", QSettings::IniFormat);    settings.beginGroup("server");    QString host = settings.value("host").toString();    int port = settings.value("port").toInt();    settings.endGroup(); -	NetCom netcom(host, port); -	QDomNode node; -  m = new MacroWindow(netcom, node, "test"); +  NetCom netcom(host, port); +  MacroWindow *m = new MacroWindow(netcom, "test", true, false, NULL, NULL);    return m;  } @@ -33,3 +30,4 @@ QDomElement getWidgetElement(QString type, QString name, QString value)    return e;  } + diff --git a/client/widgets/altcombobox.cc b/client/widgets/altcombobox.cc index 78797f6..9956fff 100644 --- a/client/widgets/altcombobox.cc +++ b/client/widgets/altcombobox.cc @@ -30,16 +30,19 @@  #include <QHBoxLayout>  #include <QVBoxLayout>  #include <QComboBox> +#include <QLineEdit>  #include "common.h"  #include "multilist.h"  #include "macrowindow.h"  #include "debug.h" +#include "luawidget.h"  AltComboBox::AltComboBox(QDomNode &node, MacroWindow *macrowindow) -  : Widget(node, macrowindow) +  : ComboBox(node, macrowindow)  { +  combobox = (QComboBox*)widget;    frame = new QFrame();    widget = frame; @@ -50,18 +53,10 @@ AltComboBox::AltComboBox(QDomNode &node, MacroWindow *macrowindow)    setCommonAttributes(frame, node);    setCommonLayout(frame, node); -  combobox = new ComboBox(node, macrowindow); -  frame->layout()->addWidget(combobox->qwidget()); -  combobox->qwidget()->show(); +  frame->layout()->addWidget(combobox); +  frame->layout()->setContentsMargins(0,0,0,0); -  altframerepl = new QFrame(); -  QHBoxLayout *l = new QHBoxLayout(); -  altframerepl->setLayout(l); -  l->addStretch(); -  altframe = new QFrame(); -  frame->layout()->addWidget(altframe); - -  QVector< Widget* > widgets; +  altframe = NULL;    QString iwname; @@ -70,11 +65,12 @@ AltComboBox::AltComboBox(QDomNode &node, MacroWindow *macrowindow)      QDomElement item = items.at(i).toElement();      if(item.tagName() == "altitem") { -       +      altframe = new Frame(item, macrowindow); +        if(item.hasAttribute("value")) {          altvalue = item.attribute("value");        } else { -        ERROR(altcombobos, "altitem tag is missing the value attribute, " +        ERROR(altcombobox, "altitem tag is missing the value attribute, "                "in altcombobox!\n");        } @@ -85,63 +81,42 @@ AltComboBox::AltComboBox(QDomNode &node, MacroWindow *macrowindow)                 "in altcombobox!\n");        } -      if(item.hasAttribute("layout")) { -        if(item.attribute("layout") == "hbox") { -          QHBoxLayout *layout = new QHBoxLayout(); -          altframe->setLayout(layout); -        } else if(item.attribute("layout") == "vbox") { -          QVBoxLayout *layout = new QVBoxLayout(); -          altframe->setLayout(layout);       -        } else { // Illigal layout choosen. -          QVBoxLayout *layout = new QVBoxLayout(); -          altframe->setLayout(layout); -        } -      } else { -        QHBoxLayout *layout = new QHBoxLayout(); -        altframe->setLayout(layout); -      } - -      addChildren(item, altframe->layout()); +      frame->layout()->addWidget(altframe->qwidget()); +      children.push_back(altframe); +      break;      } -    }    innerwidget = findWidget(iwname, true);    if(innerwidget == NULL) {      ERROR(altcombobox, "Inner Widget %s not found (in altcombobox)!\n", -           iwname.toStdString().c_str()); +          iwname.toStdString().c_str());    } -  // To detect if the altvalue has been selected: -  connect(combobox->qwidget(), SIGNAL(currentIndexChanged(int)), -          this, SLOT(onValueChange(int))); -  connect(combobox->qwidget(), SIGNAL(editTextChanged(const QString&)), -          this, SLOT(onValueChange(const QString&))); +  // Set visibility of altframe when combo selection changes. +  connect(this, SIGNAL(eventOnChange()), this, SLOT(comboChanged())); -  // To react to changes in any of the children: -  connect(combobox, SIGNAL(wasChanged()), this, SLOT(onChildChange())); +  // Propagate wasChanged events in the innerwidget    if(innerwidget)      connect(innerwidget, SIGNAL(wasChanged()), this, SLOT(onChildChange())); - -  if(frame->layout()) frame->layout()->setContentsMargins(0,0,0,0); -  if(altframe->layout()) altframe->layout()->setContentsMargins(0,0,0,0); - -  frame->show(); // Force altframe to get resized to its real size. -  altframerepl->setFixedHeight(altframe->height());  }  AltComboBox::~AltComboBox()  { -  // delete frame; +} + +QComboBox *AltComboBox::qcombobox() +{ +  return combobox;  }  bool AltComboBox::preValid()  { -  if(!combobox->valid()) return false; +  if(ComboBox::preValid() == false) return false; -  if(innerwidget && combobox->value() == altvalue) { +  if(innerwidget && ComboBox::value() == altvalue) {      if(!innerwidget->valid()) return false;    } @@ -150,101 +125,49 @@ bool AltComboBox::preValid()  QString AltComboBox::value()  { -  if(combobox->value() == altvalue) { +  QString val = ComboBox::value(); + +  DEBUG(altcombobox, "ComboBox::value() => %s\n", val.toStdString().c_str()); + +  if(val == altvalue) {      if(innerwidget) return innerwidget->value();      else return "";    } else { -    return combobox->value(); +    return val;    }  }  void AltComboBox::setValue(QString value, QString source)  { -  // No need for this, it will be enitted by the children. -  // if(isUserSource(source)) emit wasChanged(); - -  QComboBox *cmb = (QComboBox*)combobox->qwidget(); +  QComboBox *cmb = combobox;    if(cmb->findData(value) != -1) { - -    combobox->setValue(value, source); - +    ComboBox::setValue(value, source);    } else { -    combobox->setValue(altvalue); +    ComboBox::setValue(altvalue);      if(innerwidget) {        innerwidget->setValue(value, source);      }    } - -  //  setInitialValue(value);  } -void AltComboBox::onValueChange(int index) +void AltComboBox::comboChanged()  { -  QComboBox *cmb = (QComboBox*)combobox->qwidget(); - -  DEBUG(alcombobox, "Value changed: %s altvalue: %s\n", -        cmb->itemData(index).toString().toStdString().c_str(), -        altvalue.toStdString().c_str()); - -  if(cmb->itemData(index).toString() == altvalue) { - -    altframerepl->setVisible(false); -    frame->layout()->removeWidget(altframerepl); - -    frame->layout()->addWidget(altframe); -    altframe->setVisible(true); - -  } else { - -    altframe->setVisible(false); -    frame->layout()->removeWidget(altframe); - -    frame->layout()->addWidget(altframerepl); -    altframerepl->setVisible(true); +  DEBUG(altcombobox, "comboChanged to '%s'\n", +        ComboBox::value().toStdString().c_str()); +  if(altframe) { +    DEBUG(altcombobox, "inner->setVisible(%d)\n", +          ComboBox::value() == altvalue); +    altframe->setVisible(ComboBox::value() == altvalue);    } - -  emit eventOnChange(true); -} - -void AltComboBox::onValueChange(const QString &text) -{ -  QComboBox *cmb = (QComboBox*)combobox->qwidget(); -  onValueChange(cmb->findText(text));  }  void AltComboBox::onChildChange()  { -  emit eventOnChange(true); -  emit wasChanged(); -} - -bool AltComboBox::setKeyboardFocus() -{ -  if(combobox->value() == altvalue) { -    if(innerwidget) return innerwidget->setKeyboardFocus(); +  DEBUG(altcombobox, "onChildChange\n"); +  if(ComboBox::value() == altvalue) { +    emit eventOnChange(true); +    emit wasChanged();    } - -  combobox->setKeyboardFocus(); -  return true; -} - -void AltComboBox::setWdgValid(bool valid) -{ -  DEBUG(altcombobox, "Set valid(%s)\n", valid?"true":"false"); - -  QPalette palette; - -  if(valid) { -    // valid string -    palette.setBrush(QPalette::Base, QBrush(QColor(255, 255, 255))); -  } else { -    // invalid string -    palette.setBrush(QPalette::Base, QBrush(QColor(230, 200, 200))); -  } - -  //  frame->setPalette(palette); -  combobox->setWdgValid(valid); -  //  if(innerwidget) innerwidget->setWdgValid(valid);  } diff --git a/client/widgets/altcombobox.h b/client/widgets/altcombobox.h index ccc81cd..e6a21d7 100644 --- a/client/widgets/altcombobox.h +++ b/client/widgets/altcombobox.h @@ -30,16 +30,37 @@  #include "widget.h"  #include "combobox.h" +#include "frame.h"  #include <QDomNode>  #include <QMap> +#ifdef LUA_CLASS +#undef LUA_CLASS +#endif +#define LUA_CLASS "AltComboBox" +  /***   * ComboBox Widget with Alternate Value   * @tag altcombobox   * @extends combobox + * @screenshot Example: altitem selected. + * <altcombobox name="ex" layout="vbox" value="altitem" type="select"> + *   <item caption="Item" value="item"/> + *   <altitem caption="Alt Item" value="altitem" innerwidget="in" layout="hbox"> + *     <label caption="Alt label:"/> + *     <lineedit name="in" value="Alt value"/> + *   </altitem> + * </altcombobox> + * @screenshot Example: altitem not selected. + * <altcombobox name="ex" layout="vbox" value="item" type="select"> + *   <item caption="Item" value="item"/> + *   <altitem caption="Alt Item" value="altitem" innerwidget="in" layout="hbox"> + *     <label caption="Alt label:"/> + *     <lineedit name="in" value="Alt value"/> + *   </altitem> + * </altcombobox>   * @container - * @screenshot   * The AltComboBox is used to make a normal selection with a ComboBox but with   * a special list item that shows an alternate widget and uses this widget for   * input. The AltComboBox contains <code><item></code> tags in the same @@ -56,33 +77,45 @@   */  class QFrame; -class AltComboBox : public Widget +class QComboBox; +class AltComboBox : public ComboBox  {  Q_OBJECT  public:    AltComboBox(QDomNode &node, MacroWindow *macrowindow);    ~AltComboBox(); +  virtual QString luaclass() { return LUA_CLASS; } +    QString value();    void setValue(QString value, QString source = "");    bool preValid(); -  void setWdgValid(bool valid); -  bool setKeyboardFocus(); +  QComboBox *qcombobox();  public slots: -  void onValueChange(int index); -  void onValueChange(const QString &text); +  void comboChanged();    void onChildChange();  private:    QFrame *frame; -  ComboBox *combobox; +  QComboBox *combobox;    Widget *innerwidget;    QString altvalue; -  QWidget *altframe; -  QWidget *altframerepl; +  Frame *altframe;  }; +const struct luaL_Reg acmbbox_meths[] = +  { WDG_METHS, CMBBOX_METHS, {NULL, NULL} }; + +inline void register_altcombobox(lua_State *L) +{ +  luaL_newmetatable(L, LUA_CLASS); +  lua_pushliteral(L, "__index"); +  lua_pushvalue(L, -2); +  lua_rawset(L, -3); +  luaL_register(L, NULL, acmbbox_meths); +} +  #endif/*__PRACRO_ALTCOMBOBOX_H__*/ diff --git a/client/widgets/button.h b/client/widgets/button.h index 0fa7521..0bd7db9 100644 --- a/client/widgets/button.h +++ b/client/widgets/button.h @@ -34,7 +34,12 @@  /***   * PushButton Widget   * @tag button - * @screenshot + * @screenshot Example button + * <button caption="Click me"/> + * @screenshot Example cancel button + * <button caption="Cancel" action="cancel"/> + * @screenshot Example commit button (inactive) + * <button caption="Commit" action="commit"/>   * @extends widget   * This is a normal pushbutton that can be clicked by the user.   * @att caption The caption of the button. diff --git a/client/widgets/checkbox.cc b/client/widgets/checkbox.cc index 9083990..7d81b1a 100644 --- a/client/widgets/checkbox.cc +++ b/client/widgets/checkbox.cc @@ -132,7 +132,7 @@ int chk_checked(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "CheckBox"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "checkbox expected");    CheckBox *chk = (CheckBox*)wdgu->widget; @@ -145,7 +145,7 @@ int chk_set_checked(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "CheckBox"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "checkbox expected");    bool val = luaL_checkbool(L, 2); diff --git a/client/widgets/checkbox.h b/client/widgets/checkbox.h index 92cc4b3..ce31a62 100644 --- a/client/widgets/checkbox.h +++ b/client/widgets/checkbox.h @@ -30,11 +30,18 @@  #include "widget.h"  #include <QDomNode> +#ifdef LUA_CLASS +#undef LUA_CLASS +#endif +#define LUA_CLASS "CheckBox" +  /***   * CheckBox Widget   * @tag checkbox + * @screenshot An example checkbox + * <checkbox name="example" truevalue="true" falsevalue="false" value="true" + *           caption="A simple checkbox"/>   * @extends widget - * @screenshot   * This widget is used to retrieve boolean values from the user. The widget can   * either be in checked state or unschecked state. The value of the widget   * depends on its state and the values of the falseval and trueval attributes. @@ -51,6 +58,8 @@ public:    CheckBox(QDomNode &node, MacroWindow *macrowindow);    ~CheckBox(); +  virtual QString luaclass() { return LUA_CLASS; } +    QString value();    void setValue(QString value, QString source = ""); @@ -98,7 +107,7 @@ inline void register_checkbox(lua_State *L)  {    register_widget(L); -  luaL_newmetatable(L, "CheckBox"); +  luaL_newmetatable(L, LUA_CLASS);    lua_pushliteral(L, "__index");    lua_pushvalue(L, -2);    lua_rawset(L, -3); diff --git a/client/widgets/checkgroupbox.cc b/client/widgets/checkgroupbox.cc index a5692b2..fa662e1 100644 --- a/client/widgets/checkgroupbox.cc +++ b/client/widgets/checkgroupbox.cc @@ -28,7 +28,6 @@  #include "checkgroupbox.h"  #include <QGroupBox> -#include <QCheckBox>  #include <QHBoxLayout> @@ -36,168 +35,62 @@  #include "debug.h"  CheckGroupBox::CheckGroupBox(QDomNode &node, MacroWindow *macrowindow) -  : Widget(node, macrowindow) +  : CheckBox(node, macrowindow)  { -  QDomElement elem = node.toElement(); +  checkbox = (QCheckBox*)widget; +  connect(this, SIGNAL(wasChanged()), this, SLOT(cgb_state_change())); +  QDomElement elem = node.toElement();    type = elem.attribute("type", "framed"); -   -  checkbox = NULL; -  groupbox = NULL;    if(type == "framed") { -    groupbox = new QGroupBox(); -    groupbox->setCheckable(true); -    connect(groupbox, SIGNAL(toggled(bool)), this, SLOT(state_change(bool))); - -    widget = groupbox; - -    setCommonLayout(widget, node); - -    addChildren(node, widget->layout()); - -    if(elem.hasAttribute("caption")) { -      groupbox->setTitle(elem.attribute("caption")); -    } - +    QGroupBox *gb = new QGroupBox(); +    gb->setTitle(" "); +    widget = gb;    } else if(type == "simple") {      widget = new QWidget(); -    widget->setContentsMargins(0,0,0,0); -    QHBoxLayout *l = new QHBoxLayout(); -    l->setContentsMargins(0,0,0,0); -    widget->setLayout(l); -    checkbox = new QCheckBox(); -    connect(checkbox, SIGNAL(toggled(bool)), this, SLOT(state_change(bool))); -    if(elem.hasAttribute("caption")) { -      checkbox->setText(elem.attribute("caption")); -    } -    l->addWidget(checkbox); -    container = new QWidget(); -    l->addWidget(container); - -    setCommonLayout(container, node); - -    addChildren(node, container->layout()); -    container->layout()->setContentsMargins(0,0,0,0); -     -    } else {      ERROR(checkgroupbox, "Illegal value of attribute 'type'\n"); +    return;    } +  setCommonLayout(widget, node);    setCommonAttributes(widget, node); -  // -  // From CheckBox -  // -  changedByUser = true; -   -  if(elem.hasAttribute("truevalue")) { -    truevalue = elem.attribute("truevalue"); -  } else { -    truevalue = "true"; -  } - -  if(elem.hasAttribute("falsevalue")) { -    falsevalue = elem.attribute("falsevalue"); -  } else { -    falsevalue = "false"; -  } -} - -CheckGroupBox::~CheckGroupBox() -{ -  //  delete groupbox; -} - -QString CheckGroupBox::value() -{ -  if(groupbox && groupbox->isChecked()) return truevalue; -  if(checkbox && checkbox->isChecked()) return truevalue; -  return falsevalue; -} - -void CheckGroupBox::setValue(QString value, QString source) -{ -  if(isUserSource(source)) emit wasChanged(); +  checkbox->setParent(widget); +  checkbox->resize(checkbox->sizeHint().width(), 32); +  checkbox->show(); -  changedByUser = false; - -  bool old = false; -  if(groupbox) old = groupbox->isChecked(); -  if(checkbox) old = checkbox->isChecked(); - -  if(value == truevalue) { -    if(groupbox) groupbox->setChecked(true); -    if(checkbox) { -      checkbox->setChecked(true); -      container->setEnabled(true); -    } -  } else if(value == falsevalue) { -    if(groupbox) groupbox->setChecked(false); -    if(checkbox) { -      checkbox->setChecked(false); -      container->setEnabled(false); -    } -  } else { -    printf("Unknown checkbox value: %s\n", value.toStdString().c_str()); +  if(type == "framed") { +    widget->setContentsMargins(0, 10, 0, 0); +    checkbox->move(5, -9); +    checkbox->setAutoFillBackground(true);    } -  // If set operation did not change the value we must invocate the code manually. -  if(groupbox && old == groupbox->isChecked()) state_change(old); -  if(checkbox && old == checkbox->isChecked()) state_change(old); - -  //  setInitialValue(value); - -  changedByUser = true; -} - -void CheckGroupBox::state_change(bool state) -{ -  emit eventOnChange(); -  if(changedByUser) emit wasChanged(); - -  if(checkbox) { -    container->setEnabled(state); +  if(type == "simple") { +    widget->setContentsMargins(checkbox->sizeHint().width(), 0, 0, 0); +    checkbox->move(0, 3);    } -} - -bool CheckGroupBox::checked() -{ -  return value() == truevalue; -} -void CheckGroupBox::setChecked(bool checked) -{ -  setValue(checked ? truevalue : falsevalue); +  addChildren(node, widget->layout());  } -void CheckGroupBox::setWdgValid(bool valid) +CheckGroupBox::~CheckGroupBox()  { -  QPalette palette; - -  if(valid) { -    // valid string -    palette.setBrush(QPalette::Base, QBrush(QColor(255, 255, 255))); -  } else { -    // invalid string -    palette.setBrush(QPalette::Base, QBrush(QColor(230, 200, 200))); -  } - -  if(groupbox) groupbox->setPalette(palette); -  if(checkbox) checkbox->setPalette(palette);  } -bool CheckGroupBox::setKeyboardFocus() +void CheckGroupBox::cgb_state_change()  {    QVector< Widget* >::iterator i = children.begin();    while(i != children.end()) {      Widget *w = *i; -    if(w) { -      if(w->setKeyboardFocus()) return true; -    } +    if(w) w->setEnabled(checkbox->isChecked());      i++;    } +} -  return false; +bool CheckGroupBox::setKeyboardFocus() +{ +  checkbox->setFocus(); +  return true;  } diff --git a/client/widgets/checkgroupbox.h b/client/widgets/checkgroupbox.h index 9b6dcdc..5dfa7fb 100644 --- a/client/widgets/checkgroupbox.h +++ b/client/widgets/checkgroupbox.h @@ -28,14 +28,32 @@  #ifndef __PRACRO_CHECKGROUPBOX_H__  #define __PRACRO_CHECKGROUPBOX_H__ -#include "widget.h" +#include "checkbox.h" +  #include <QDomNode> +#include <QCheckBox> + +#ifdef LUA_CLASS +#undef LUA_CLASS +#endif +#define LUA_CLASS "CheckGroupBox"  /***   * Checkable GroupBox Widget   * @tag checkgroupbox   * @extends checkbox - * @screenshot + * @screenshot Example 1: type="framed" + * <checkgroupbox name="example" caption="Example" type="framed" layout="vbox" + *                truevalue="true" falsevalue="false" value="true"> + *   <lineedit name="dims" value="Contained widget 1"/> + *   <lineedit name="dims" value="Contained widget 2"/> + * </checkgroupbox> + * @screenshot Example 2: type="simple" + * <checkgroupbox name="example" caption="Example" type="simple" layout="vbox" + *                truevalue="true" falsevalue="false" value="true"> + *   <lineedit name="dims" value="Contained widget 1"/> + *   <lineedit name="dims" value="Contained widget 2"/> + * </checkgroupbox>   * @container    * @att layout The layout used in the groupbox. Can be one of 'vbox' or 'hbox'.   * @att type Defines the type of the checkbox. It can be one of 'framed' or @@ -44,39 +62,39 @@   * to the right of it. Default is 'framed'.   */ -class QGroupBox; -class QCheckBox; -class CheckGroupBox : public Widget +class CheckGroupBox : public CheckBox  {  Q_OBJECT  public:    CheckGroupBox(QDomNode &node, MacroWindow *macrowindow);    ~CheckGroupBox(); -  QString value(); -  void setValue(QString value, QString source = ""); - -  void setWdgValid(bool valid); - -  bool checked(); -  void setChecked(bool checked); +  //void setWdgValid(bool valid);    bool setKeyboardFocus();  public slots: -  void state_change(bool); +  void cgb_state_change();  private: -  QString truevalue; -  QString falsevalue; -    QString type; -    bool changedByUser; -   -  QGroupBox *groupbox; +    QCheckBox *checkbox; -  QWidget *container;  }; +const struct luaL_Reg chkgrpbox_meths[] = +  { WDG_METHS, CHKBOX_METHS, {NULL, NULL} }; + +inline void register_checkgroupbox(lua_State *L) +{ +  register_widget(L); + +  luaL_newmetatable(L, LUA_CLASS); +  lua_pushliteral(L, "__index"); +  lua_pushvalue(L, -2); +  lua_rawset(L, -3); +  luaL_register(L, NULL, chkgrpbox_meths); +} +  #endif/*__PRACRO_CHECKGROUPBOX_H__*/ diff --git a/client/widgets/combobox.cc b/client/widgets/combobox.cc index 768f035..eed2d10 100644 --- a/client/widgets/combobox.cc +++ b/client/widgets/combobox.cc @@ -76,7 +76,7 @@ ComboBox::ComboBox(QDomNode &node, MacroWindow *macrowindow)    combobox->setInsertPolicy(QComboBox::InsertAlphabetically);    QDomNodeList children = node.childNodes(); -  QStringList itemlist; +  //  QStringList itemlist;    for (int i=0; i<children.count();i++) {      QDomNode child = children.at(i); @@ -131,23 +131,8 @@ ComboBox::ComboBox(QDomNode &node, MacroWindow *macrowindow)    case SEARCH:      combobox->setEditable(true); -    { -      QString rxs = "("; -      for(int i = 0; i < itemlist.size(); i++) { -        if(rxs != "(") rxs += "|"; -        rxs += QRegExp::escape(itemlist.at(i)); -      } -      rxs += ")"; -      rx = QRegExp(rxs); -      rx.setCaseSensitivity(Qt::CaseInsensitive); -    } -    {     -      QCompleter *completer = new QCompleter(itemlist, this); -      completer->setCaseSensitivity(Qt::CaseInsensitive); -      completer->setCompletionMode(QCompleter::PopupCompletion); -      combobox->setCompleter(completer); -      combobox->setValidator(new QRegExpValidator(rx, this)); -    } + +    updateSearchList();      connect(combobox, SIGNAL(editTextChanged(QString)), this, SLOT(changed()));      break; @@ -159,16 +144,41 @@ ComboBox::~ComboBox()    // delete combobox;  } +void ComboBox::updateSearchList() +{ +  { +    QString rxs = "("; +    for(int i = 0; i < itemlist.size(); i++) { +      if(rxs != "(") rxs += "|"; +      rxs += QRegExp::escape(itemlist.at(i)); +    } +    rxs += ")"; +    rx = QRegExp(rxs); +    rx.setCaseSensitivity(Qt::CaseInsensitive); +  } +  {     +    QCompleter *completer = new QCompleter(itemlist, this); +    completer->setCaseSensitivity(Qt::CaseInsensitive); +    completer->setCompletionMode(QCompleter::PopupCompletion); +    combobox->setCompleter(completer); +    combobox->setValidator(new QRegExpValidator(rx, this)); +  } +} +  QString ComboBox::value()  {    QString value; -  int idx = combobox->currentIndex(); -   -  if(idx != -1 && combobox->itemText(idx) == combobox->currentText()) -    value = combobox->itemData(idx).toString(); +  int idx = combobox->findText(combobox->currentText()); +  /* +  DEBUG(combobox, "idx => %d currentText => '%s'\n", idx, +        combobox->currentText().toStdString().c_str()); +  */ +  if(idx != -1) value = combobox->itemData(idx).toString();    else value = combobox->currentText(); +  DEBUG(combobox, "value() => '%s'\n", value.toStdString().c_str()); +    return value;  } @@ -243,13 +253,20 @@ void ComboBox::clear()    ignoreChangeEvents = false;  } -void ComboBox::addItem(QString item) +void ComboBox::addItem(QString item, QString value)  {    ignoreChangeEvents = true; -  combobox->addItem(item, item); +  combobox->addItem(item, value); +    if(combotype == EDIT) {      combobox->completer()->complete();    } + +  if(combotype == SEARCH) { +    itemlist.push_back(item); +    updateSearchList(); +  } +    ignoreChangeEvents = false;  } @@ -273,7 +290,7 @@ int cmb_clear(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "combobox expected");    ComboBox *cmb = (ComboBox*)wdgu->widget; @@ -286,13 +303,19 @@ int cmb_add_item(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); +  size_t nargs = lua_gettop(L); // number of arguments + +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "combobox expected"); -  QString val = luaL_checkstring(L, 2); +  QString cap = luaL_checkstring(L, 2); +  QString val = cap; +  if(nargs == 3) { +    val = luaL_checkstring(L, 3); +  }    ComboBox *cmb = (ComboBox*)wdgu->widget; -  cmb->addItem(val); +  cmb->addItem(cap, val);    return 0;  } @@ -301,7 +324,7 @@ int cmb_le_value(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "combobox expected");    ComboBox *cmb = (ComboBox*)wdgu->widget; @@ -314,7 +337,7 @@ int cmb_le_set_value(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "combobox expected");    const char *val = luaL_checkstring(L, 2); diff --git a/client/widgets/combobox.h b/client/widgets/combobox.h index 92a0e39..bf61b1a 100644 --- a/client/widgets/combobox.h +++ b/client/widgets/combobox.h @@ -32,11 +32,19 @@  #include "widget.h" +#ifdef LUA_CLASS +#undef LUA_CLASS +#endif +#define LUA_CLASS "ComboBox" +  /***   * ComboBox Widget   * @tag combobox + * @screenshot Example + * <combobox name="ex" layout="vbox" value="item" type="select"> + *   <item caption="Item" value="item"/> + * </combobox>   * @extends widget - * @screenshot   * The ComboBox is used to make a selection from a list of items.   * The ComboBox contains <code><item></code> tags each describing    * an entry in the selection list. @@ -67,6 +75,8 @@ public:    ComboBox(QDomNode &node, MacroWindow *macrowindow);    ~ComboBox(); +  virtual QString luaclass() { return LUA_CLASS; } +    QString value();    void setValue(QString value, QString source = ""); @@ -78,7 +88,7 @@ public:    void setWdgValid(bool valid);    void clear(); -  void addItem(QString item); +  void addItem(QString item, QString value);  public slots:    void changed(); @@ -89,17 +99,48 @@ protected:    void changeEvent(QEvent *event);  private: +  void updateSearchList(); +    QRegExp rx;    types_t combotype;    bool ischangingbyuser;    QComboBox *combobox;    bool ignoreChangeEvents; + +  QStringList itemlist;  }; +/*** + * @method nil clear() + * This method removes all items from the combobox. + */  int cmb_clear(lua_State *L); + +/*** + * @method nil addItem(string caption, string value) + * This method adds an item to the selectionlist of the combobox. + * @param caption The item text to be added. It will be added both as the value + * and caption of the item. + * @param value The item value. This value is optional. If left out, the + * caption will be used as the item value. + */  int cmb_add_item(lua_State *L); + +/*** + * @method string lineEditValue() + * This method is used to get the value from the combobox lineedit (in case it + * is in edit mode). + * @return a string containing the current value of the combobox lineedit. + */  int cmb_le_value(lua_State *L); + +/*** + * @method nil setLineEditValue(string text) + * This method is used to set the value of the combobox lineedit (in case it + * is in edit mode). + * @param text The text string to be set. + */  int cmb_le_set_value(lua_State *L);  #define CMBBOX_METHS \ @@ -113,7 +154,7 @@ const struct luaL_Reg cmbbox_meths[] =  inline void register_combobox(lua_State *L)  { -  luaL_newmetatable(L, "ComboBox"); +  luaL_newmetatable(L, LUA_CLASS);    lua_pushliteral(L, "__index");    lua_pushvalue(L, -2);    lua_rawset(L, -3); diff --git a/client/widgets/common.cc b/client/widgets/common.cc index c545ed8..2262074 100644 --- a/client/widgets/common.cc +++ b/client/widgets/common.cc @@ -80,21 +80,10 @@ void setCommonLayout(QWidget *widget, QDomNode &node)  {    QDomElement elem = node.toElement(); -  if(elem.hasAttribute("layout")) { -    if(elem.attribute("layout") == "hbox") { -      QHBoxLayout *layout = new QHBoxLayout(widget); -      widget->setLayout(layout); -    } else if (elem.attribute("layout") == "vbox") { -      QVBoxLayout *layout = new QVBoxLayout(widget); -      widget->setLayout(layout); -    } else { // Illigal layout choosen. -      QVBoxLayout *layout = new QVBoxLayout(widget); -      widget->setLayout(layout); -    } - +  if(elem.attribute("layout", "vbox") == "hbox") { +    widget->setLayout(new QHBoxLayout(widget));    } else { -    QHBoxLayout *layout = new QHBoxLayout(widget); -    widget->setLayout(layout); +    widget->setLayout(new QVBoxLayout(widget));    }    widget->setContentsMargins(0,0,0,0); diff --git a/client/widgets/datetime.h b/client/widgets/datetime.h index d238ea0..84df018 100644 --- a/client/widgets/datetime.h +++ b/client/widgets/datetime.h @@ -35,7 +35,10 @@  /***   * Date and Time Widget   * @tag datetime - * @screenshot + * @screenshot Example with fuzziness="1" and value="1234567890" + * <datetime name="x" fuzziness="1" value="1234567890"/> + * @screenshot Example with fuzziness="7" and value="1234567890" + * <datetime name="x" fuzziness="7" value="1234567890"/>   * @extends widget   * This widget is used to get structured time and date information.   * <em>NOTE</em>: The value attribute must be a unix timestamp (number of diff --git a/client/widgets/groupbox.h b/client/widgets/groupbox.h index 73b6508..58e52bb 100644 --- a/client/widgets/groupbox.h +++ b/client/widgets/groupbox.h @@ -37,8 +37,17 @@  /***   * Layout or Frame Widget    * @tag frame + * @screenshot Example with caption. + * <frame caption="Caption" layout="vbox"> + *   <label caption="Label"/> + *   <lineedit name="x" value="LineEdit"/> + * </frame> + * @screenshot Example without caption (frame is invisible). + * <frame layout="vbox"> + *   <label caption="Label"/> + *   <lineedit name="x" value="LineEdit"/> + * </frame>   * @extends widget - * @screenshot   * This widget is used to control the layout of the child widgets and/or produce   * a frame and caption for them. <em>NOTE</em>: The value of this widget is   * always the empty string. It cannot be set. diff --git a/client/widgets/label.h b/client/widgets/label.h index 7c32916..b303d0d 100644 --- a/client/widgets/label.h +++ b/client/widgets/label.h @@ -34,7 +34,8 @@  /***   * Label Widget   * @tag label - * @screenshot + * @screenshot Example + * <label width="300" caption="A nice label with a caption"/>   * @extends widget   * This widget is used to present text to the user. It is a read-only widget   * and its value will always be the empty string. diff --git a/client/widgets/lineedit.cc b/client/widgets/lineedit.cc index e50f9cd..10f1199 100644 --- a/client/widgets/lineedit.cc +++ b/client/widgets/lineedit.cc @@ -180,7 +180,7 @@ int lin_clear_suggestions(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "lineedit expected");    LineEdit *led = (LineEdit*)wdgu->widget; @@ -193,7 +193,7 @@ int lin_show_suggestions(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "lineedit expected");    LineEdit *led = (LineEdit*)wdgu->widget; @@ -206,7 +206,7 @@ int lin_is_suggested(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "lineedit expected");    const char *val = luaL_checkstring(L, 2); @@ -222,7 +222,7 @@ int lin_add_suggestion(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "lineedit expected");    const char *val = luaL_checkstring(L, 2); diff --git a/client/widgets/lineedit.h b/client/widgets/lineedit.h index e76fe74..08230a6 100644 --- a/client/widgets/lineedit.h +++ b/client/widgets/lineedit.h @@ -31,11 +31,17 @@  #include "widget.h" +#ifdef LUA_CLASS +#undef LUA_CLASS +#endif +#define LUA_CLASS "LineEdit" +  /***   * Line Edit Widget   * @tag lineedit + * @screenshot Example + * <lineedit name="myname" value="some text"/>   * @extends widget - * @screenshot   * The lineedit is a single line textual input field.   * @example Simple example of usage:   * <lineedit name="myname" value="some text"/> @@ -55,6 +61,8 @@ public:    LineEdit(QDomNode &node, MacroWindow *macrowindow);    ~LineEdit(); +  virtual QString luaclass() { return LUA_CLASS; } +    QString value();    void setValue(QString value, QString source); @@ -135,7 +143,7 @@ const struct luaL_Reg linedt_meths[] =  inline void register_lineedit(lua_State *L)  { -  luaL_newmetatable(L, "LineEdit"); +  luaL_newmetatable(L, LUA_CLASS);    lua_pushliteral(L, "__index");    lua_pushvalue(L, -2);    lua_rawset(L, -3); diff --git a/client/widgets/listbox.cc b/client/widgets/listbox.cc index b691650..3000f35 100644 --- a/client/widgets/listbox.cc +++ b/client/widgets/listbox.cc @@ -30,6 +30,7 @@  #include <QListWidget>  #include "common.h" +#include "luawidget.h"  static QListWidgetItem *createItem(QDomElement &elem)  { @@ -146,3 +147,74 @@ void ListBox::setWdgValid(bool valid)    listwidget->setPalette(palette);  } + +void ListBox::clear() +{ +  listwidget->clear(); +} + +void ListBox::addItem(QString text, QString type) +{ +  QDomDocument doc; +  QDomElement elem = doc.createElement("item"); +  elem.setAttribute("caption", text); +  elem.setAttribute("value", text); +  if(type != "") elem.setAttribute("type", type); +  listwidget->addItem(createItem(elem)); +} + +int lst_clear(lua_State *L) +{ +  wdg_userdata *wdgu; + +  wdgu = (wdg_userdata *)lua_touserdata(L, 1); +  luaL_argcheck(L, wdgu, 1, "listbox expected"); + +  ListBox *lst = (ListBox*)wdgu->widget; +  lst->clear(); + +  return 0; +} + +int lst_add_item(lua_State *L) +{ +  wdg_userdata *wdgu; + +  wdgu = (wdg_userdata *)lua_touserdata(L, 1); +  luaL_argcheck(L, wdgu, 1, "listbox expected"); + +  QString val = luaL_checkstring(L, 2); + +  ListBox *lst = (ListBox*)wdgu->widget; +  lst->addItem(val, ""); + +  return 0; +} + +int lst_add_header(lua_State *L) +{ +  wdg_userdata *wdgu; + +  wdgu = (wdg_userdata *)lua_touserdata(L, 1); +  luaL_argcheck(L, wdgu, 1, "listbox expected"); + +  QString val = luaL_checkstring(L, 2); + +  ListBox *lst = (ListBox*)wdgu->widget; +  lst->addItem(val, "header"); + +  return 0; +} + +int lst_add_separator(lua_State *L) +{ +  wdg_userdata *wdgu; + +  wdgu = (wdg_userdata *)lua_touserdata(L, 1); +  luaL_argcheck(L, wdgu, 1, "listbox expected"); + +  ListBox *lst = (ListBox*)wdgu->widget; +  lst->addItem("", "separator"); + +  return 0; +} diff --git a/client/widgets/listbox.h b/client/widgets/listbox.h index fcfc1b0..82c5dfc 100644 --- a/client/widgets/listbox.h +++ b/client/widgets/listbox.h @@ -31,10 +31,28 @@  #include <QDomNode> +#ifdef LUA_CLASS +#undef LUA_CLASS +#endif +#define LUA_CLASS "ListBox" +  /***   * ListBox Widget   * @tag listbox - * @screenshot + * @screenshot Example + * <listbox name="x" value="item1"> + *   <item type="header" value="" caption="Numbers"/> + *   <item value="item1" caption="Item 1"/> + *   <item value="item2" caption="Item 2"/> + *   <item value="item3" caption="Item 3"/> + *   <item value="item4" caption="Item 4"/> + *   <item value="" caption="" type="separator"/> + *   <item type="header" value="" caption="Letters"/> + *   <item value="itemA" caption="Item A"/> + *   <item value="itemB" caption="Item B"/> + *   <item value="itemC" caption="Item C"/> + *   <item value="itemD" caption="Item D"/> + * </listbox>   * @extends widget   * This widget is a list of selectable items.   * @att value [item] The value of the item and the value of the widget if this @@ -54,12 +72,17 @@ public:    ListBox(QDomNode &node, MacroWindow *macrowindow);    ~ListBox(); +  virtual QString luaclass() { return LUA_CLASS; } +    QString value();    void setValue(QString value, QString source);    bool preValid();    void setWdgValid(bool valid); +  void clear(); +  void addItem(QString text, QString type); +  public slots:    void changed(); @@ -68,4 +91,49 @@ private:    QListWidget *listwidget;  }; +/*** + * @method nil clear() + * This method removes all items from the listbox. + */ +int lst_clear(lua_State *L); + +/*** + * @method nil addItem(string text) + * This method adds an item to the list. + * @param text The item text to be added. It will be added both as the value + * and caption of the item. + */ +int lst_add_item(lua_State *L); + +/*** + * @method nil addHeader(string text) + * This method adds a header item to the list. + * @param text The caption of the header. + */ +int lst_add_header(lua_State *L); + +/*** + * @method nil addSeparator() + * This method adds a separator item to the list. + */ +int lst_add_separator(lua_State *L); + +#define LSTBOX_METHS \ +  {"clear", lst_clear},\ +  {"addItem", lst_add_item}, \ +  {"addHeader", lst_add_header}, \ +  {"addSeparator", lst_add_separator} + +const struct luaL_Reg lstbox_meths[] = +  { WDG_METHS, LSTBOX_METHS, {NULL, NULL} }; + +inline void register_listbox(lua_State *L) +{ +  luaL_newmetatable(L, LUA_CLASS); +  lua_pushliteral(L, "__index"); +  lua_pushvalue(L, -2); +  lua_rawset(L, -3); +  luaL_register(L, NULL, lstbox_meths); +} +  #endif/*__PRACRO_LISTBOX_H__*/ diff --git a/client/widgets/metawidget.h b/client/widgets/metawidget.h index ac18b91..c6bf5d0 100644 --- a/client/widgets/metawidget.h +++ b/client/widgets/metawidget.h @@ -38,13 +38,19 @@   * Meta Widget   * @extends widget   * @tag metawidget + * @screenshot An example of a metawidget with two inner widgets. The metawidget is not in itself visible. + * <metawidget layout="vbox" name="dims" format="''" storechildren="true"> + *   <lineedit name="test1" value="test"/> + *   <checkbox name="test2" value="ja" truevalue="ja" falsevalue="nej" + *             caption="Og svaret er?"/> + * </metawidget>   * @container - * This widget is simply a caotainer compositing its value from the widgets + * This widget is simply a container compositing its value from the widgets   * within it. The value of the widget cannot be set and its value attribute is   * therefore ignored.   * @example An example of how to use metawidget with two inner widgets: - * <metawidget layout="vbox" name="dims" format="${test1}: ${test2}" - *             storechildren="true"> + * <metawidget layout="vbox" name="dims" storechildren="true" + *             format="return widget('test1'):value() .. ': ' .. widget('test2'):value()">   *   <lineedit name="test1" value="test"/>   *   <checkbox name="test2" value="ja" truevalue="ja" falsevalue="nej"   *             caption="Og svaret er?"/> @@ -52,7 +58,7 @@   * @att layout the layout of the widget. Can be one of 'vbox' or 'hbox'.   * @att storechildren This attribute indicates wether the child widgets should   * be stored on macro commit. It can be either 'true' or 'false'. - * @att format This attribute comtains lua code. The return value of the code + * @att format This attribute contains lua code. The return value of the code   * is the resulting value of the meta widget.   * @att layout The layout assigned to the widget. Can be one of 'hbox' or   * 'vbox'. diff --git a/client/widgets/multilist.h b/client/widgets/multilist.h index 878603f..f7da8fa 100644 --- a/client/widgets/multilist.h +++ b/client/widgets/multilist.h @@ -38,8 +38,16 @@   * Multi List Widget   * @tag multilist   * @container + * @screenshot Example of multilist containing a metawidget. + * <multilist name="x" layout="vbox" innerwidget="in" value="Abc: Def + * Hij: Klm"> + *   <metawidget name="in" layout="hbox" format="return ''"> + *     <lineedit name="a" value="Abc"/> + *     <label caption=":"/> + *     <lineedit name="b" value="Def"/> + *   </metawidget> + * </multilist>   * @extends widget - * @screenshot   * This widget is used to produce a list of text items constructed using other   * widgets. The value of the widget is contained in a simple string using the   * newline character to seperate items. diff --git a/client/widgets/radiobuttons.h b/client/widgets/radiobuttons.h index 3ddb05c..4b9ce67 100644 --- a/client/widgets/radiobuttons.h +++ b/client/widgets/radiobuttons.h @@ -36,7 +36,13 @@   * Radio Button Group Widget   * @tag radiobuttons   * @extends widget - * @screenshot + * @screenshot Example with four radiobuttons + * <radiobuttons name="x" value="item2"> + *   <radiobutton value="item1" caption="Item 1"/> + *   <radiobutton value="item2" caption="Item 2"/> + *   <radiobutton value="item3" caption="Item 3"/> + *   <radiobutton value="item4" caption="Item 4"/> + * </radiobuttons>   * @container   * This widget is in many ways similar to the @see listbox widget. It is a   * container for radiobuttons represented by <code><radiobutton></code> diff --git a/client/widgets/textedit.h b/client/widgets/textedit.h index 4398878..bfe7374 100644 --- a/client/widgets/textedit.h +++ b/client/widgets/textedit.h @@ -35,8 +35,10 @@  /***   * Multiline Text Edit Widget   * @tag textedit + * @screenshot Example of a textedit. + * <textedit name="x" value="This is a multiline textfield. + * It may contain all text in the universe, it will simply add a scrollbar."/>   * @extends widget - * @screenshot   * The textedit is a multiline textual input field. Unlike the @see lineedit it   * accepts the newline character which will also be part of its resulting value.   * @att readonly Make the textedit readonly (not changeable by the user), but diff --git a/client/widgets/widget.cc b/client/widgets/widget.cc index c0c9e81..2374c6f 100644 --- a/client/widgets/widget.cc +++ b/client/widgets/widget.cc @@ -77,6 +77,8 @@ Widget::Widget(QDomNode &node, MacroWindow *macrowindow)    connect(this, SIGNAL(eventOnInit()),            this, SLOT(runEventOnInit()), Qt::QueuedConnection); +  replwidget = NULL; +    DEBUG(widget, "Create Widget '%s' of type '%s'\n",          name().toStdString().c_str(),          type().toStdString().c_str()); @@ -238,8 +240,64 @@ bool Widget::enabled()  void Widget::setVisible(bool visible)  { +  if(visible == this->visible()) return; + +  QBoxLayout *l = (QBoxLayout *)widget->parentWidget()->layout(); + +  if(visible == false) { +    if(replwidget == NULL) delete replwidget; + +    replwidget = new QFrame(); +    replwidget->setMinimumSize(widget->frameGeometry().size()); + +    { +      int l,t,r,b; +      widget->getContentsMargins(&l,&t,&r,&b); +      replwidget->setContentsMargins(l, t, r, b); +    } + +    int idx = l->indexOf(widget); +    l->insertWidget(idx, replwidget); + +  } else { +    int idx = l->indexOf(replwidget); +    if(replwidget) { +      delete replwidget; +      replwidget = NULL; +    } +    l->insertWidget(idx, widget); +  } + +  //  replwidget->setVisible(!visible);    widget->setVisible(visible); -  if(visible) emit eventOnChange(); + +  if(visible) { +    emit eventOnChange(); + +    QVector< Widget* >::iterator i = children.begin(); +    while(i != children.end()) { +      if(*i) (*i)->runEventOnChange(true); +      i++; +    } +  } +} + +bool Widget::visible() +{ +  return widget->isVisible(); +} + +void Widget::setHidden(bool hidden) +{ +  if(hidden == this->hidden()) return; + +  widget->setHidden(hidden); +  if(replwidget) replwidget->setHidden(hidden); + +  if(macrowindow) +    macrowindow->setFixedHeight(macrowindow->minimumSizeHint().height()); + +  if(hidden == false) emit eventOnChange();    QVector< Widget* >::iterator i = children.begin();    while(i != children.end()) { @@ -248,9 +306,9 @@ void Widget::setVisible(bool visible)    }  } -bool Widget::visible() +bool Widget::hidden()  { -  return widget->isVisible(); +  return widget->isHidden();  }  bool Widget::setKeyboardFocus() @@ -261,7 +319,9 @@ bool Widget::setKeyboardFocus()  Widget *Widget::findWidget(QString n, bool deep)  { -  DEBUG(widget, "Find Widget this: %s\n", name().toStdString().c_str()); +  DEBUG(widget, "Find Widget '%s' this: '%s' (hide?%d deep?%d #child:%d)\n", +        n.toStdString().c_str(), name().toStdString().c_str(), +        hideChildren, deep, children.size());    if(n == name()) return this; @@ -445,10 +505,7 @@ int wdg_name(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "Widget"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "CheckBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "widget expected");    lua_pushstring(L, wdgu->widget->name().toStdString().c_str()); @@ -460,10 +517,7 @@ int wdg_type(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "Widget"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "CheckBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "widget expected");    // return error code @@ -476,10 +530,7 @@ int wdg_value(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "Widget"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "CheckBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "widget expected");    lua_pushstring(L, wdgu->widget->value().toStdString().c_str()); @@ -491,10 +542,7 @@ int wdg_set_value(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "Widget"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "CheckBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "widget expected");    const char *val = luaL_checkstring(L, 2); @@ -508,10 +556,7 @@ int wdg_enabled(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "Widget"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "CheckBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "widget expected");    lua_pushboolean(L, wdgu->widget->enabled()); @@ -523,10 +568,7 @@ int wdg_set_enabled(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "Widget"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "CheckBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "widget expected");    bool val = luaL_checkbool(L, 2); @@ -540,10 +582,7 @@ int wdg_visible(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "Widget"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "CheckBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "widget expected");    lua_pushboolean(L, wdgu->widget->visible()); @@ -555,10 +594,7 @@ int wdg_set_visible(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "Widget"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "CheckBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "widget expected");    bool val = luaL_checkbool(L, 2); @@ -568,14 +604,37 @@ int wdg_set_visible(lua_State *L)    return 0;  } +int wdg_hidden(lua_State *L) +{ +  wdg_userdata *wdgu; + +  wdgu = (wdg_userdata *)lua_touserdata(L, 1); +  luaL_argcheck(L, wdgu, 1, "widget expected"); + +  lua_pushboolean(L, wdgu->widget->hidden()); + +  return 1; +} + +int wdg_set_hidden(lua_State *L) +{ +  wdg_userdata *wdgu; + +  wdgu = (wdg_userdata *)lua_touserdata(L, 1); +  luaL_argcheck(L, wdgu, 1, "widget expected"); + +  bool val = luaL_checkbool(L, 2); + +  wdgu->widget->setHidden(val); +   +  return 0; +} +  int wdg_valid(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "Widget"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "CheckBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "widget expected");    lua_pushboolean(L, wdgu->widget->valid()); @@ -587,10 +646,7 @@ int wdg_set_valid(lua_State *L)  {    wdg_userdata *wdgu; -  wdgu = (wdg_userdata *)luaL_isudata(L, 1, "Widget"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "CheckBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "ComboBox"); -  if(!wdgu) wdgu = (wdg_userdata *)luaL_isudata(L, 1, "LineEdit"); +  wdgu = (wdg_userdata *)lua_touserdata(L, 1);    luaL_argcheck(L, wdgu, 1, "widget expected");    bool val = luaL_checkbool(L, 2); diff --git a/client/widgets/widget.h b/client/widgets/widget.h index 3de148f..d0f1799 100644 --- a/client/widgets/widget.h +++ b/client/widgets/widget.h @@ -32,9 +32,15 @@  #include <QRegExp>  #include <QObject>  #include <QVector> +#include <QFrame>  #include "lua.h" +#ifdef LUA_CLASS +#undef LUA_CLASS +#endif +#define LUA_CLASS "Widget" +  /***   * Virtual Base Widget   * This tag is purely virtual. It is inherited by all other widgets. @@ -71,6 +77,8 @@ public:    QString type();    bool local(); +  virtual QString luaclass() { return LUA_CLASS; } +    virtual QString value() = 0;    virtual void setValue(QString value, QString source) = 0; @@ -93,9 +101,12 @@ public:    virtual void setVisible(bool visible);    virtual bool visible(); +  virtual void setHidden(bool hidden); +  virtual bool hidden(); +    virtual bool setKeyboardFocus(); -  QWidget *qwidget() { return widget; } +  virtual QWidget *qwidget() { return widget; }    // Set deep to true to search through inner widgets.    Widget *findWidget(QString name, bool deep = false); @@ -153,6 +164,8 @@ protected:    bool hasOnInitEvent;    QString onInitEventScript; + +  QFrame *replwidget;  };  /*** @@ -206,8 +219,8 @@ int wdg_set_enabled(lua_State *L);  /***   * @method boolean visible() - * This method is used to get the current enable state of the widget. - * @return a boolean value. If the widget is enabled the method returns true + * This method is used to get the current visibility state of the widget. + * @return a boolean value. If the widget is visible the method returns true   * otherwise it returns false.   */  int wdg_visible(lua_State *L); @@ -218,7 +231,7 @@ int wdg_visible(lua_State *L);   * The widget will take up an equal amount of layout space regardless of its   * visibility state meaning that the layout will remain static after a   * hiding/showing of the widget. - * <em>NOTE</em>: A hidden widget will not supply its value to the server + * <em>NOTE</em>: An invisble widget will not supply its value to the server   * during a commit.   * @param visible A boolean value. If true the widget is shown. If false the   * widget is hidden. @@ -226,6 +239,25 @@ int wdg_visible(lua_State *L);  int wdg_set_visible(lua_State *L);  /*** + * @method boolean hidden() + * This method is used to get the current hide state of the widget. + * @return a boolean value. If the widget is hidden the method returns true + * otherwise it returns false. + */ +int wdg_hidden(lua_State *L); + +/*** + * @method nil setHidden(boolean hidden) + * This method is used to either show or hide the widget, collapsing the occupied + * space. + * <em>NOTE</em>: A hidden widget will not supply its value to the server + * during a commit. + * @param hidden A boolean value. If true the widget is hidden. If false the + * widget is shown. + */ +int wdg_set_hidden(lua_State *L); + +/***   * @method boolean valid()   * This method is used to get the current validity state of the widget. See   * also @see setValid(). @@ -255,6 +287,8 @@ int wdg_set_valid(lua_State *L);    {"setEnabled", wdg_set_enabled},\    {"visible", wdg_visible},\    {"setVisible", wdg_set_visible},\ +  {"hidden", wdg_hidden},\ +  {"setHidden", wdg_set_hidden},\    {"valid", wdg_valid},\    {"setValid", wdg_set_valid} @@ -263,7 +297,7 @@ const struct luaL_Reg wdg_meths[] =  inline void register_widget(lua_State *L)  { -  luaL_newmetatable(L, "Widget"); +  luaL_newmetatable(L, LUA_CLASS);    lua_pushliteral(L, "__index");    lua_pushvalue(L, -2);    lua_rawset(L, -3); | 
