diff options
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); |