/*************************************************************************** CTextBox.cpp The TextBox class (c) 2000-2007 Benoit Minisini This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ***************************************************************************/ #define __CTEXTBOX_CPP #include #include #include #include #include #include #include "gambas.h" #include "CConst.h" #include "CTextBox.h" DECLARE_EVENT(EVENT_Change); DECLARE_EVENT(EVENT_Activate); DECLARE_EVENT(EVENT_Click); #define MAX_LEN 32767 /*************************************************************************** TextBox ***************************************************************************/ static bool get(void *_object, QLineEdit **wid, bool error = true) { QComboBox *combo; if (TEXTBOX->isA("QLineEdit")) { *wid = TEXTBOX; return false; } combo = COMBOBOX; if (!combo->editable()) { if (error) GB.Error("ComboBox is read-only"); return true; } *wid = combo->lineEdit(); return false; } #define GET_TEXT_BOX() \ QLineEdit *textbox; \ if (get(_object, &textbox)) \ return; BEGIN_METHOD(CTEXTBOX_new, GB_OBJECT parent) QLineEdit *wid = new QLineEdit(QCONTAINER(VARG(parent))); QObject::connect(wid, SIGNAL(textChanged(const QString &)), &CTextBox::manager, SLOT(event_change())); QObject::connect(wid, SIGNAL(returnPressed()), &CTextBox::manager, SLOT(event_activate())); wid->setAlignment(Qt::AlignLeft); CWIDGET_new(wid, (void *)_object); END_METHOD BEGIN_METHOD_VOID(CTEXTBOX_clear) TEXTBOX->clear(); END_METHOD BEGIN_METHOD(CTEXTBOX_insert, GB_STRING text) GET_TEXT_BOX(); //textbox->insert(QString(GB.ToZeroString(ARG(text)))); textbox->insert(QSTRING_ARG(text)); END_METHOD BEGIN_PROPERTY(CTEXTBOX_text) if (READ_PROPERTY) GB.ReturnNewZeroString(TO_UTF8(TEXTBOX->text())); else TEXTBOX->setText(QSTRING_PROP()); END_PROPERTY BEGIN_PROPERTY(CTEXTBOX_length) GB.ReturnInteger(TEXTBOX->text().length()); END_PROPERTY BEGIN_PROPERTY(CTEXTBOX_alignment) if (READ_PROPERTY) GB.ReturnInteger(CCONST_alignment(TEXTBOX->alignment() + Qt::AlignVCenter, ALIGN_NORMAL, false)); else TEXTBOX->setAlignment(CCONST_alignment(VPROP(GB_INTEGER), ALIGN_NORMAL, true) & Qt::AlignHorizontal_Mask); END_PROPERTY BEGIN_PROPERTY(CTEXTBOX_pos) GET_TEXT_BOX(); if (READ_PROPERTY) GB.ReturnInteger(textbox->cursorPosition()); else textbox->setCursorPosition(VPROP(GB_INTEGER)); END_PROPERTY BEGIN_PROPERTY(CTEXTBOX_read_only) if (READ_PROPERTY) GB.ReturnBoolean(TEXTBOX->isReadOnly()); else TEXTBOX->setReadOnly(VPROP(GB_BOOLEAN)); END_PROPERTY BEGIN_PROPERTY(CTEXTBOX_border) GET_TEXT_BOX(); if (READ_PROPERTY) GB.ReturnBoolean(textbox->frame()); else textbox->setFrame(VPROP(GB_BOOLEAN)); END_PROPERTY BEGIN_PROPERTY(CTEXTBOX_password) GET_TEXT_BOX(); if (READ_PROPERTY) GB.ReturnBoolean(textbox->echoMode() != QLineEdit::Normal); else textbox->setEchoMode(VPROP(GB_BOOLEAN) ? QLineEdit::Password : QLineEdit::Normal); END_PROPERTY BEGIN_PROPERTY(CTEXTBOX_max_length) int max; GET_TEXT_BOX(); if (READ_PROPERTY) { max = textbox->maxLength(); GB.ReturnInteger(max >= MAX_LEN ? 0 : max); } else { max = VPROP(GB_INTEGER); if (max < 1 || max > MAX_LEN) max = MAX_LEN; textbox->setMaxLength(max); } END_PROPERTY BEGIN_PROPERTY(CTEXTBOX_selection) RETURN_SELF(); END_PROPERTY /*************************************************************************** .TextBox.Selection ***************************************************************************/ BEGIN_PROPERTY(CTEXTBOX_sel_text) GET_TEXT_BOX(); if (READ_PROPERTY) GB.ReturnNewZeroString(TO_UTF8(textbox->markedText())); else textbox->insert(QSTRING_PROP()); END_PROPERTY static void set_selection(QLineEdit *textbox, int start, int length) { int len = (int)textbox->text().length(); if (start < 0 || start >= len) { start = textbox->cursorPosition(); length = 0; } textbox->setCursorPosition(start); if (length <= 0) textbox->deselect(); else { if ((start + length) >= len) length = len - start; textbox->setSelection(start, length); } } static void get_selection(QLineEdit *textbox, int *start, int *length) { *start = textbox->cursorPosition(); if (!textbox->hasMarkedText()) *length = 0; else *length = textbox->markedText().length(); } BEGIN_PROPERTY(CTEXTBOX_sel_length) int start, length; GET_TEXT_BOX(); get_selection(textbox, &start, &length); GB.ReturnInteger(length); END_PROPERTY BEGIN_PROPERTY(CTEXTBOX_sel_start) int start, length; GET_TEXT_BOX(); get_selection(textbox, &start, &length); GB.ReturnInteger(start); END_PROPERTY BEGIN_METHOD_VOID(CTEXTBOX_sel_clear) GET_TEXT_BOX(); textbox->deselect(); END_METHOD BEGIN_METHOD_VOID(CTEXTBOX_selected) GET_TEXT_BOX(); GB.ReturnBoolean(textbox->hasSelectedText()); END_METHOD BEGIN_METHOD(CTEXTBOX_sel_select, GB_INTEGER start; GB_INTEGER length) GET_TEXT_BOX(); if (MISSING(start) && MISSING(length)) textbox->selectAll(); else if (!MISSING(start) && !MISSING(length)) set_selection(textbox, VARG(start), VARG(length)); END_METHOD BEGIN_METHOD_VOID(CTEXTBOX_sel_all) GET_TEXT_BOX(); textbox->selectAll(); END_METHOD /*************************************************************************** ComboBox ***************************************************************************/ #undef THIS #define THIS OBJECT(CCOMBOBOX) static void setCurrentItem(void *_object, int item) { if (item < COMBOBOX->count()) COMBOBOX->setCurrentItem(item); if (item >= 0) GB.Raise(_object, EVENT_Click, 0); } static void combo_set_editable(void *_object, bool ed) { QLineEdit *textbox; if (ed) { if (!COMBOBOX->editable()) { //CWidget::removeFilter(COMBOBOX); COMBOBOX->setEditable(true); //CWidget::installFilter(COMBOBOX); QObject::connect(COMBOBOX->lineEdit(), SIGNAL(returnPressed()), &CTextBox::manager, SLOT(event_activate())); if (CWIDGET_test_flag(THIS, WF_DESIGN)) { get(_object, &textbox); //textbox->removeEventFilter(COMBOBOX); COMBOBOX->setFocusProxy(0); } } } else { COMBOBOX->setEditable(false); } if (CWIDGET_test_flag(THIS, WF_DESIGN)) COMBOBOX->setFocusPolicy(QWidget::NoFocus); COMBOBOX->calcMinimumHeight(); } BEGIN_METHOD(CCOMBOBOX_new, GB_OBJECT parent) MyComboBox *wid = new MyComboBox(QCONTAINER(VARG(parent))); QObject::connect(wid, SIGNAL(textChanged(const QString &)), &CTextBox::manager, SLOT(event_change())); QObject::connect(wid, SIGNAL(activated(int)), &CTextBox::manager, SLOT(event_click())); //QObject::connect(wid, SIGNAL(highlighted(int)), &CTextBox::manager, SLOT(event_click())); wid->setInsertionPolicy(QComboBox::NoInsertion); CWIDGET_new(wid, (void *)_object); combo_set_editable(_object, true); END_METHOD BEGIN_METHOD_VOID(CCOMBOBOX_clear) COMBOBOX->clear(); COMBOBOX->clearEdit(); END_METHOD BEGIN_METHOD_VOID(CCOMBOBOX_popup) COMBOBOX->popup(); END_METHOD BEGIN_PROPERTY(CCOMBOBOX_text) int pos; if (READ_PROPERTY) GB.ReturnNewZeroString(TO_UTF8(COMBOBOX->currentText())); else { QString text = QSTRING_PROP(); if (COMBOBOX->editable()) COMBOBOX->lineEdit()->setText(text); pos = CTextBox::find(COMBOBOX, text); COMBOBOX->setCurrentItem(pos); } END_PROPERTY BEGIN_PROPERTY(CCOMBOBOX_length) GB.ReturnInteger(COMBOBOX->currentText().length()); END_PROPERTY BEGIN_PROPERTY(CCOMBOBOX_read_only) if (READ_PROPERTY) GB.ReturnBoolean(!COMBOBOX->editable()); else combo_set_editable(_object, !VPROP(GB_BOOLEAN)); END_PROPERTY BEGIN_METHOD(CCOMBOBOX_get, GB_INTEGER index) int index = VARG(index); if (index < 0 || index >= (int)COMBOBOX->count()) { GB.Error("Bad index"); return; } THIS->index = index; RETURN_SELF(); END_METHOD BEGIN_PROPERTY(CCOMBOBOX_item_text) if (READ_PROPERTY) GB.ReturnNewZeroString(TO_UTF8(COMBOBOX->text(THIS->index))); else { COMBOBOX->blockSignals(true); COMBOBOX->changeItem(QSTRING_PROP(), THIS->index); COMBOBOX->blockSignals(false); } END_PROPERTY BEGIN_METHOD(CCOMBOBOX_add, GB_STRING item; GB_INTEGER pos) int index; int pos; COMBOBOX->blockSignals(true); index = COMBOBOX->currentItem(); pos = VARGOPT(pos, -1); if (pos < 0 || pos >= COMBOBOX->count()) pos = -1; COMBOBOX->insertItem(QSTRING_ARG(item), pos); if (THIS->sorted) COMBOBOX->listBox()->sort(); COMBOBOX->setCurrentItem(index); COMBOBOX->blockSignals(false); END_METHOD BEGIN_METHOD(CCOMBOBOX_remove, GB_INTEGER pos) COMBOBOX->blockSignals(true); COMBOBOX->removeItem(VARG(pos)); COMBOBOX->blockSignals(false); END_METHOD BEGIN_PROPERTY(CCOMBOBOX_sorted) if (READ_PROPERTY) GB.ReturnBoolean(THIS->sorted); else { THIS->sorted = VPROP(GB_BOOLEAN); if (THIS->sorted) COMBOBOX->listBox()->sort(); } END_METHOD BEGIN_PROPERTY(CCOMBOBOX_count) GB.ReturnInteger(COMBOBOX->count()); END_PROPERTY BEGIN_PROPERTY(CCOMBOBOX_index) if (READ_PROPERTY) GB.ReturnInteger(COMBOBOX->currentItem()); else setCurrentItem(_object, VPROP(GB_INTEGER)); END_PROPERTY BEGIN_PROPERTY(CCOMBOBOX_current) THIS->index = COMBOBOX->currentItem(); if (THIS->index < 0) GB.ReturnNull(); else RETURN_SELF(); END_PROPERTY /* BEGIN_PROPERTY(CCOMBOBOX_mouse) if (READ_PROPERTY) GB.ReturnInteger(COMBOBOX->cursor().shape()); else { if (COMBOBOX->editable()) COMBOBOX->lineEdit()->setCursor(PROPERTY(int)); COMBOBOX->setCursor(PROPERTY(int)); } END_METHOD */ BEGIN_METHOD(CCOMBOBOX_find, GB_STRING item) GB.ReturnInteger(CTextBox::find(COMBOBOX, QSTRING_ARG(item))); END_METHOD BEGIN_PROPERTY(CCOMBOBOX_list) GB_ARRAY array; if (READ_PROPERTY) { GB.Array.New(&array, GB_T_STRING, COMBOBOX->count()); CTextBox::getAll(COMBOBOX, array); GB.ReturnObject(array); } else { CTextBox::setAll(COMBOBOX, (GB_ARRAY)VPROP(GB_OBJECT)); if (THIS->sorted) COMBOBOX->listBox()->sort(); } END_PROPERTY /*************************************************************************** class MyComboBox ***************************************************************************/ MyComboBox::MyComboBox(QWidget *parent) : QComboBox(false, parent) { calcMinimumHeight(); } void MyComboBox::fontChange(const QFont &font) { QWidget::fontChange(font); calcMinimumHeight(); } void MyComboBox::calcMinimumHeight() { QFontMetrics fm = fontMetrics(); if (editable()) setMinimumHeight(fm.lineSpacing() + height() - lineEdit()->height()); else setMinimumHeight(fm.lineSpacing() + 2); } /*************************************************************************** class CTextBox ***************************************************************************/ CTextBox CTextBox::manager; void CTextBox::event_change(void) { RAISE_EVENT(EVENT_Change); } void CTextBox::event_activate(void) { RAISE_EVENT(EVENT_Activate); } void CTextBox::event_click() { RAISE_EVENT(EVENT_Click); } int CTextBox::find(QComboBox *list, const QString& s) { for (int i = 0; i < (int)list->count(); i++) { if (list->text(i) == s) return i; } return (-1); } void CTextBox::getAll(QComboBox *list, GB_ARRAY array) { int i; char *str; for (i = 0; i < list->count(); i++) { GB.NewString(&str, TO_UTF8(list->text(i)), 0); *((char **)GB.Array.Get(array, i)) = str; } } void CTextBox::setAll(QComboBox *list, GB_ARRAY array) { int i; list->clear(); list->blockSignals(true); if (array) { for (i = 0; i < GB.Array.Count(array); i++) { list->insertItem(TO_QSTRING(*((char **)GB.Array.Get(array, i)))); } } list->blockSignals(false); } /*************************************************************************** Descriptions ***************************************************************************/ GB_DESC CTextBoxSelectionDesc[] = { GB_DECLARE(".TextBoxSelection", 0), GB_VIRTUAL_CLASS(), GB_PROPERTY("Text", "s", CTEXTBOX_sel_text), GB_PROPERTY_READ("Length", "i", CTEXTBOX_sel_length), GB_PROPERTY_READ("Start", "i", CTEXTBOX_sel_start), GB_PROPERTY_READ("Pos", "i", CTEXTBOX_sel_start), GB_METHOD("Hide", NULL, CTEXTBOX_sel_clear, NULL), GB_END_DECLARE }; GB_DESC CTextBoxDesc[] = { GB_DECLARE("TextBox", sizeof(CTEXTBOX)), GB_INHERITS("Control"), GB_METHOD("_new", NULL, CTEXTBOX_new, "(Parent)Container;"), GB_PROPERTY("Text", "s", CTEXTBOX_text), GB_PROPERTY("Alignment", "i", CTEXTBOX_alignment), GB_PROPERTY_READ("Length", "i", CTEXTBOX_length), GB_PROPERTY("Pos", "i", CTEXTBOX_pos), GB_PROPERTY("ReadOnly", "b", CTEXTBOX_read_only), GB_PROPERTY("Border", "b", CTEXTBOX_border), GB_PROPERTY("Password", "b", CTEXTBOX_password), GB_PROPERTY("MaxLength", "i", CTEXTBOX_max_length), GB_PROPERTY_SELF("Selection", ".TextBoxSelection"), GB_METHOD("Select", NULL, CTEXTBOX_sel_select, "[(Start)i(Length)i]"), GB_METHOD("SelectAll", NULL, CTEXTBOX_sel_all, NULL), GB_METHOD("Unselect", NULL, CTEXTBOX_sel_clear, NULL), GB_PROPERTY_READ("Selected", "b", CTEXTBOX_selected), GB_METHOD("Clear", NULL, CTEXTBOX_clear, NULL), GB_METHOD("Insert", NULL, CTEXTBOX_insert, "(Text)s"), GB_EVENT("Change", NULL, NULL, &EVENT_Change), GB_EVENT("Activate", NULL, NULL, &EVENT_Activate), TEXTBOX_DESCRIPTION, GB_END_DECLARE }; GB_DESC CComboBoxItemDesc[] = { GB_DECLARE(".ComboBoxItem", 0), GB_VIRTUAL_CLASS(), GB_PROPERTY("Text", "s", CCOMBOBOX_item_text), GB_END_DECLARE }; GB_DESC CComboBoxDesc[] = { GB_DECLARE("ComboBox", sizeof(CCOMBOBOX)), GB_INHERITS("Control"), GB_METHOD("_new", NULL, CCOMBOBOX_new, "(Parent)Container;"), GB_METHOD("_get", ".ComboBoxItem", CCOMBOBOX_get, "(Index)i"), GB_PROPERTY("Text", "s", CCOMBOBOX_text), GB_PROPERTY_READ("Length", "i", CCOMBOBOX_length), GB_PROPERTY("Pos", "i", CTEXTBOX_pos), GB_PROPERTY("ReadOnly", "b", CCOMBOBOX_read_only), GB_PROPERTY("Password", "b", CTEXTBOX_password), GB_PROPERTY("MaxLength", "i", CTEXTBOX_max_length), GB_PROPERTY_SELF("Selection", ".TextBoxSelection"), GB_METHOD("Select", NULL, CTEXTBOX_sel_select, "[(Start)i(Length)i]"), GB_METHOD("SelectAll", NULL, CTEXTBOX_sel_all, NULL), GB_METHOD("Unselect", NULL, CTEXTBOX_sel_clear, NULL), GB_PROPERTY_READ("Selected", "b", CTEXTBOX_selected), GB_METHOD("Popup", NULL, CCOMBOBOX_popup, NULL), GB_METHOD("Clear", NULL, CCOMBOBOX_clear, NULL), GB_METHOD("Insert", NULL, CTEXTBOX_insert, "(Text)s"), GB_METHOD("Add", NULL, CCOMBOBOX_add, "(Item)s[(Index)i]"), GB_METHOD("Remove", NULL, CCOMBOBOX_remove, "(Index)i"), GB_METHOD("Find", "i", CCOMBOBOX_find, "(Item)s"), GB_PROPERTY("Sorted", "b", CCOMBOBOX_sorted), GB_PROPERTY("List", "String[]", CCOMBOBOX_list), //GB_PROPERTY("Contents", "s", CCOMBOBOX_list), GB_PROPERTY_READ("Count", "i", CCOMBOBOX_count), GB_PROPERTY_READ("Current", ".ComboBoxItem", CCOMBOBOX_current), GB_PROPERTY("Index", "i", CCOMBOBOX_index), GB_EVENT("Change", NULL, NULL, &EVENT_Change), GB_EVENT("Activate", NULL, NULL, &EVENT_Activate), GB_EVENT("Click", NULL, NULL, &EVENT_Click), COMBOBOX_DESCRIPTION, GB_END_DECLARE };