From 6389aabffe198ece92b58ae34a905902c7eefe7c Mon Sep 17 00:00:00 2001 From: deva Date: Tue, 28 Jun 2011 06:38:10 +0000 Subject: Complete rewrite of the way lua widget methods, 'inheritance' in particular, are handled. --- client/luawidget.cc | 32 ++------ client/luawidget.h | 2 +- client/test/testaltcombobox.cc | 93 ++++++++++++++++++--- client/test/testcomboboxedit.cc | 2 +- client/test/testcomboboxsearch.cc | 4 +- client/test/testcomboboxselect.cc | 2 +- client/test/util.cc | 8 +- client/widgets/altcombobox.cc | 165 ++++++++++---------------------------- client/widgets/altcombobox.h | 51 +++++++++--- client/widgets/button.h | 7 +- client/widgets/checkbox.cc | 4 +- client/widgets/checkbox.h | 13 ++- client/widgets/checkgroupbox.cc | 163 +++++++------------------------------ client/widgets/checkgroupbox.h | 58 +++++++++----- client/widgets/combobox.cc | 83 ++++++++++++------- client/widgets/combobox.h | 47 ++++++++++- client/widgets/common.cc | 17 +--- client/widgets/datetime.h | 5 +- client/widgets/groupbox.h | 11 ++- client/widgets/label.h | 3 +- client/widgets/lineedit.cc | 8 +- client/widgets/lineedit.h | 12 ++- client/widgets/listbox.cc | 72 +++++++++++++++++ client/widgets/listbox.h | 70 +++++++++++++++- client/widgets/metawidget.h | 14 +++- client/widgets/multilist.h | 10 ++- client/widgets/radiobuttons.h | 8 +- client/widgets/textedit.h | 4 +- client/widgets/widget.cc | 144 +++++++++++++++++++++++---------- client/widgets/widget.h | 44 ++++++++-- 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 + +#include + #include "util.h" #include "altcombobox.h" -#include static QString xml = - "\n" + "\n" " \n" " \n" - " \n" + " \n" + " \n" + " \n" + "\n"; + +static QString xml_lua = + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" "\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 #include #include +#include #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 #include +#ifdef LUA_CLASS +#undef LUA_CLASS +#endif +#define LUA_CLASS "AltComboBox" + /*** * ComboBox Widget with Alternate Value * @tag altcombobox * @extends combobox + * @screenshot Example: altitem selected. + * + * + * + * + * + * @screenshot Example: altitem not selected. + * + * + * + * + * * @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 <item> 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 + *