ui/qt/text.cpp

changeset 103
6606616eca9f
parent 0
2483f517c562
child 108
77254bd6dccb
--- a/ui/qt/text.cpp	Tue Feb 25 21:11:00 2025 +0100
+++ b/ui/qt/text.cpp	Sat Apr 05 16:46:11 2025 +0200
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
+ * 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:
@@ -32,124 +32,203 @@
 #include "../common/context.h"
 #include "../common/document.h"
 
-UIWIDGET ui_textarea(UiObject *obj, UiText *value) {
-    QTextDocument *txtdoc = value && value->obj ? (QTextDocument*)value->obj : new QTextDocument();
+/*
+ * 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;
     
-    if(value) {
-        if(value->value && value->obj) {
-            QString str = QString::fromUtf8(value->value);
-            txtdoc->setPlainText(str);
-        }
+    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 = txtdoc;
-        value->value = NULL;
+        value->obj = textarea;
+        value->data1 = document;
+    } else {
+        document = new QTextDocument();
     }
     
-    UiContainer *ct = uic_get_current_container(obj); 
-    QTextEdit *textedit = new QTextEdit();
-    textedit->setDocument(txtdoc);
-    ct->add(textedit, true);
+    textarea->setDocument(document);
     
-    return textedit;
+    return textarea;
 }
 
-UIWIDGET ui_textarea_nv(UiObject *obj, char *varname) {
-    UiVar *var = uic_connect_var(obj->ctx, varname, UI_VAR_TEXT);
-    if(var) {
-        UiText *value = (UiText*)var->value;
-        return ui_textarea(obj, value);
-    } else {
-        // TODO: error
-    }
-    return NULL;
+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) {
-    if(text->value) {
-        free(text->value);
+    // clean previous value
+    if(text->value.free) {
+        text->value.free(text->value.ptr);
     }
     
-    QTextDocument *doc = (QTextDocument*)text->obj;
+    // get string
+    QTextDocument *doc = (QTextDocument*)text->data1;
     QString str = doc->toPlainText();
-    QByteArray array = str.toLocal8Bit();
+    QByteArray array = str.toUtf8();
     const char *cstr = array.constData();
     
-    if(text->value) {
-        free(text->value);
-    }
-    text->value = strdup(cstr);
-    return text->value;
+    // 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, char *str) {
-    // set text
-    QTextDocument *doc = (QTextDocument*)text->obj;
+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);
-    // cleanup
-    if(text->value) {
-        free(text->value);
-    }
-    text->value = NULL;
 }
 
 char* ui_textarea_getsubstr(UiText *text, int begin, int end) {
-    QTextDocument *doc = (QTextDocument*)text->obj;
-    return NULL; // TODO
+    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->obj;
+    QTextDocument *doc = (QTextDocument*)text->data1;
+    QTextCursor cursor(doc);
+    cursor.setPosition(pos);
+    cursor.insertText(str);
 }
 
 void ui_textarea_setposition(UiText *text, int pos) {
-    // TODO
+    QTextEdit *textview = (QTextEdit*)text->obj;
+    QTextCursor cursor = textview->textCursor();
+    cursor.setPosition(pos);
+    textview->setTextCursor(cursor); 
 }
 
 int ui_textarea_position(UiText *text) {
-    QTextDocument *doc = (QTextDocument*)text->obj;
-    return 0; // TODO
+    QTextEdit *textview = (QTextEdit*)text->obj;
+    QTextCursor cursor = textview->textCursor();
+    return cursor.position();
 }
 
 void ui_textarea_selection(UiText *text, int *begin, int *end) {
-    QTextDocument *doc = (QTextDocument*)text->obj;
+    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->obj;
-    return 0; // TODO
+    QTextDocument *doc = (QTextDocument*)text->data1;
+    return doc->characterCount();
 }
 
 void ui_textarea_remove(UiText *text, int begin, int end) {
-    QTextDocument *doc = (QTextDocument*)text->obj;
+    // TODO
 }
 
-
-/* ------------------- TextField ------------------- */
+/* ------------------------------ TextField ------------------------------ */
 
-UIWIDGET ui_textfield(UiObject *obj, UiString *value) {
+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);
+    }
     
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->add(textfield, false);
-    
-    if(value) {
-        if(value->value) {
-            QString str = QString::fromUtf8(value->value);
+    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);
-            free(value->value);
-            value->value = NULL;
+            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;
@@ -158,38 +237,40 @@
     return textfield;
 }
 
-UIWIDGET ui_textfield_nv(UiObject *obj, char *varname) {
-    UiVar *var = uic_connect_var(obj->ctx, varname, UI_VAR_STRING);
-    if(var) {
-        UiString *value = (UiString*)var->value;
-        return ui_textfield(obj, value);
-    } else {
-        // TODO: error
-    }
-    return NULL;
+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);
+    if(str->value.free) {
+        str->value.free(str->value.ptr);
     }
-    QByteArray array = qstr.toLocal8Bit();
+    QByteArray array = qstr.toUtf8();
     const char *cstr = array.constData();
-    str->value = strdup(cstr);
+    str->value.ptr = strdup(cstr);
+    str->value.free = free;
     
-    return str->value;
+    return str->value.ptr;
 }
 
-void ui_textfield_set(UiString *str, char *value) {
+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);
+    if(str->value.free) {
+        str->value.free(str->value.ptr);
     }
-    str->value = NULL;
+    str->value.ptr = NULL;
 }

mercurial