9 days ago
add QT implementation for menubars, sub-menus and simple menu items
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2025 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "text.h" #include "container.h" #include "../common/context.h" #include "../common/document.h" /* * Gets or creates a QTextDocument for the UiText value and initializes it * with the UiText string value */ static QTextDocument* get_or_create_doc(UiText *value) { QTextDocument *document = nullptr; if(value->data1) { document = (QTextDocument*)value->data1; } else { document = new QTextDocument(); if(value->value.ptr) { QString str = QString::fromUtf8(value->value.ptr); document->setPlainText(str); } } if(value->value.free) { value->value.free(value->value.ptr); } value->value.ptr = NULL; value->value.free = NULL; return document; } UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) { UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); QTextEdit *textarea = new QTextEdit(); ctn->add(textarea, true); QTextDocument *document = nullptr; UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_STRING); if(var) { UiText *value = (UiText*)var->value; document = get_or_create_doc(value); value->save = ui_textarea_save; value->restore = ui_textarea_restore; value->destroy = ui_textarea_text_destroy; value->get = ui_textarea_get; value->set = ui_textarea_set; value->getsubstr = ui_textarea_getsubstr; value->insert = ui_textarea_insert; value->setposition = ui_textarea_setposition; value->position = ui_textarea_position; value->setselection = ui_textarea_setselection; value->selection = ui_textarea_selection; value->length = ui_textarea_length; value->remove = ui_textarea_remove; value->obj = textarea; value->data1 = document; } else { document = new QTextDocument(); } textarea->setDocument(document); return textarea; } void ui_textarea_save(UiText *text) { // NOOP } void ui_textarea_restore(UiText *text) { QTextEdit *textarea = (QTextEdit*)text->obj; QTextDocument *document = get_or_create_doc(text); textarea->setDocument(document); } void ui_textarea_text_destroy(UiText *text) { QTextDocument *document = (QTextDocument*)text->data1; if(document) { delete document; } } char* ui_textarea_get(UiText *text) { // clean previous value if(text->value.free) { text->value.free(text->value.ptr); } // get string QTextDocument *doc = (QTextDocument*)text->data1; QString str = doc->toPlainText(); QByteArray array = str.toUtf8(); const char *cstr = array.constData(); // store a copy of the string in the UiText value text->value.ptr = strdup(cstr); text->value.free = free; return text->value.ptr; } void ui_textarea_set(UiText *text, const char *str) { if(text->value.free) { text->value.free(text->value.ptr); } text->value.ptr = NULL; text->value.free = NULL; QTextDocument *doc = (QTextDocument*)text->data1; QString qstr = QString::fromUtf8(str); doc->setPlainText(qstr); } char* ui_textarea_getsubstr(UiText *text, int begin, int end) { QTextDocument *doc = (QTextDocument*)text->data1; QTextCursor cursor(doc); cursor.setPosition(begin, QTextCursor::MoveAnchor); cursor.setPosition(end, QTextCursor::KeepAnchor); QString str = cursor.selectedText(); QByteArray bytes = str.toUtf8(); const char *cstr = bytes.constData(); return cstr ? strdup(cstr) : NULL; } void ui_textarea_insert(UiText *text, int pos, char *str) { QTextDocument *doc = (QTextDocument*)text->data1; QTextCursor cursor(doc); cursor.setPosition(pos); cursor.insertText(str); } void ui_textarea_setposition(UiText *text, int pos) { QTextEdit *textview = (QTextEdit*)text->obj; QTextCursor cursor = textview->textCursor(); cursor.setPosition(pos); textview->setTextCursor(cursor); } int ui_textarea_position(UiText *text) { QTextEdit *textview = (QTextEdit*)text->obj; QTextCursor cursor = textview->textCursor(); return cursor.position(); } void ui_textarea_selection(UiText *text, int *begin, int *end) { QTextEdit *textview = (QTextEdit*)text->obj; QTextCursor cursor = textview->textCursor(); if(cursor.hasSelection()) { if(begin) { *begin = cursor.selectionStart(); } if(end) { *end = cursor.selectionEnd(); } } } void ui_textarea_setselection(UiText *text, int begin, int end) { QTextEdit *textview = (QTextEdit*)text->obj; QTextCursor cursor = textview->textCursor(); cursor.setPosition(begin, QTextCursor::MoveAnchor); cursor.setPosition(end, QTextCursor::KeepAnchor); textview->setTextCursor(cursor); } int ui_textarea_length(UiText *text) { QTextDocument *doc = (QTextDocument*)text->data1; return doc->characterCount(); } void ui_textarea_remove(UiText *text, int begin, int end) { // TODO } /* ------------------------------ TextField ------------------------------ */ static UIWIDGET create_textfield(UiObject *obj, UiTextFieldArgs args, bool password, bool frameless) { UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); QLineEdit *textfield = new QLineEdit(); ctn->add(textfield, false); if(password) { textfield->setEchoMode(QLineEdit::Password); } UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_STRING); if(var) { UiString *value = (UiString*)var->value; if(value->value.ptr) { QString str = QString::fromUtf8(value->value.ptr); textfield->setText(str); if(value->value.free) { value->value.free(value->value.ptr); } value->value.ptr = NULL; } value->set = ui_textfield_set; value->get = ui_textfield_get; value->obj = textfield; } return textfield; } UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs args) { return create_textfield(obj, args, false, false); } UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs args) { return create_textfield(obj, args, false, true); } UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs args) { return create_textfield(obj, args, true, false); } char* ui_textfield_get(UiString *str) { QLineEdit *textfield = (QLineEdit*)str->obj; QString qstr = textfield->text(); if(str->value.free) { str->value.free(str->value.ptr); } QByteArray array = qstr.toUtf8(); const char *cstr = array.constData(); str->value.ptr = strdup(cstr); str->value.free = free; return str->value.ptr; } void ui_textfield_set(UiString *str, const char *value) { QLineEdit *textfield = (QLineEdit*)str->obj; QString qstr = QString::fromUtf8(value); textfield->setText(qstr); if(str->value.free) { str->value.free(str->value.ptr); } str->value.ptr = NULL; }