Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to change behaviour of CTextEdit
Qt 6.11 is out! See what's new in the release blog

How to change behaviour of CTextEdit

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 2 Posters 424 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • SPlattenS Offline
    SPlattenS Offline
    SPlatten
    wrote on last edited by SPlatten
    #1

    I have created my own class clsQtTextEdit, here is the prototype:

        class clsQtTextEdit : public QTextEdit, public clsXMLinterface {
        Q_OBJECT
        private:
            static mpSignals mscmpSignals;
    
            void setProperty(QString strProperty, QString strValue);
    
        private slots:
            void blankControl();
            void onRedoChange();
            void onUndoChange();
            void rptrCopyAvailable(bool blnYes);
            void rptrCurrentCharFormatChanged(const QTextCharFormat& format);
            void rptrCursorPositionChanged();
            void rptrRedoAvailable(bool blnAvailable);
            void rptrSelectionChanged();
            void rptrTextChanged();
            void rptrUndoAvailable(bool blnAvailable);
    
        public slots:
    
        public:
            static const char mscszQtSignalCopyAvailable[];
            static const char mscszQtSignalCurrentCharFormatChanged[];
            static const char mscszQtSignalCursorPositionChanged[];
            static const char mscszQtSignalRedoAvailable[];
            static const char mscszQtSignalSelectionChanged[];
            static const char mscszQtSignalTextChanged[];
            static const char mscszQtSignalUndoAvailable[];
    
            explicit clsQtTextEdit(clsXMLnode* pobjNode, QString* pstrCSS
                                  ,QStringList* pslstProperties
                                  ,QWidget* parent = nullptr);
            static bool blnValidSignal(QString strSignal);
            QJsonObject objGetData(QString* pstrValue = nullptr) override;
            static mpSignals* pmpGetSignals() { return &clsQtTextEdit::mscmpSignals; }
            void setData(const QString& crstrData, bool blnTrackChange = true) override;
            QString strGetData();
    
        signals:
    
        public slots:
            void setText(const QString& crstrText);
        };
    

    And the implementation:

    /**
     * File:    clsQtTextEdit.cpp
     * Notes:   Contains implementation of the overriden signal/slot
     *          helper class for the QTextEdit control
     * History: 2020/06/11 Created by Simon Platten
     */
    #include <clsCNT.h>
    #include <clsQtTextEdit.h>
    #include <clsScriptHelper.h>
    //Static members
    const char clsQtTextEdit::mscszQtSignalCopyAvailable[]            = "copyAvailable";
    const char clsQtTextEdit::mscszQtSignalCurrentCharFormatChanged[] = "currentCharFormatChanged";
    const char clsQtTextEdit::mscszQtSignalCursorPositionChanged[]    = "cursorPositionChanged";
    const char clsQtTextEdit::mscszQtSignalRedoAvailable[]            = "redoAvailable";
    const char clsQtTextEdit::mscszQtSignalSelectionChanged[]         = "selectionChanged";
    const char clsQtTextEdit::mscszQtSignalTextChanged[]              = "textChanged";
    const char clsQtTextEdit::mscszQtSignalUndoAvailable[]            = "undoAvailable";
    mpSignals clsQtTextEdit::mscmpSignals = {
            std::make_pair(QString(clsQtTextEdit::mscszQtSignalCopyAvailable)
                          ,new clsSignal(clsCNT::mscszTextEdit
                                        ,clsQtTextEdit::mscszQtSignalCopyAvailable))
           ,std::make_pair(QString(clsQtTextEdit::mscszQtSignalCurrentCharFormatChanged)
                          ,new clsSignal(clsCNT::mscszTextEdit
                                        ,clsQtTextEdit::mscszQtSignalCurrentCharFormatChanged))
           ,std::make_pair(QString(clsQtTextEdit::mscszQtSignalCursorPositionChanged)
                          ,new clsSignal(clsCNT::mscszTextEdit
                                        ,clsQtTextEdit::mscszQtSignalCursorPositionChanged))
           ,std::make_pair(QString(clsQtTextEdit::mscszQtSignalRedoAvailable)
                          ,new clsSignal(clsCNT::mscszTextEdit
                                        ,clsQtTextEdit::mscszQtSignalRedoAvailable))
           ,std::make_pair(QString(clsQtTextEdit::mscszQtSignalSelectionChanged)
                          ,new clsSignal(clsCNT::mscszTextEdit
                                        ,clsQtTextEdit::mscszQtSignalSelectionChanged))
           ,std::make_pair(QString(clsQtTextEdit::mscszQtSignalTextChanged)
                          ,new clsSignal(clsCNT::mscszTextEdit
                                        ,clsQtTextEdit::mscszQtSignalTextChanged))
           ,std::make_pair(QString(clsQtTextEdit::mscszQtSignalUndoAvailable)
                          ,new clsSignal(clsCNT::mscszTextEdit
                                        ,clsQtTextEdit::mscszQtSignalUndoAvailable))
                                            };
    /**
     * @brief clsQtTextEdit::clsQtTextEdit
     * @param pobjNode : Pointer to XML node
     * @param pstrCSS : Pointer to CSS
     * @param pslstProperties : Pointer to properties
     * @param pParent : Pointer to parent widget
     */
    clsQtTextEdit::clsQtTextEdit(clsXMLnode* pobjNode, QString* pstrCSS
                                                     , QStringList* pslstProperties
                                                     , QWidget* pParent)
                        : QTextEdit(pParent), clsXMLinterface(pobjNode) {
        mpobjNode->setWidget(this); //Should always be first line in constructor
        clsXMLnode::addSignalsToMap(&clsQtTextEdit::mscmpSignals);
    //Any properties
        if ( pslstProperties != nullptr ) {
            foreach( QString strProperty, *pslstProperties ) {
                QStringList slstProperty(strProperty.split(clsXMLnode::msccPropertyDelimiter));
                if ( slstProperty.length() != 2 ) {
                    continue;
                }
                setProperty(slstProperty[0], slstProperty[1]);
            }
        }
        if ( pstrCSS != nullptr && pstrCSS->isEmpty() != true ) {
            setStyleSheet(*pstrCSS);
        }
        QString strColumns(mpobjNode->strGetAttribute(clsXMLnode::mscszAttrColumns))
               ,strRows(mpobjNode->strGetAttribute(clsXMLnode::mscszAttrRows));
        QRect rctGeom(geometry());
        bool blnModified(false);
        if ( strColumns.isEmpty() != true ) {
            int intCharWidth(QFontMetrics(font()).maxWidth())
               ,intPixelWidth(strColumns.toInt() * intCharWidth);
            rctGeom.setWidth(intPixelWidth);
            setFixedWidth(intPixelWidth);
            blnModified = true;
        }
        if ( strRows.isEmpty() != true ) {
            int intCharHeight(QFontMetrics(font()).height())
               ,intPixelHeight(strRows.toInt() * (intCharHeight + 1));
            rctGeom.setHeight(intPixelHeight);
            setFixedHeight(intPixelHeight);
            blnModified = true;
        }
        if ( blnModified == true && rctGeom.isValid() == true ) {
            mpobjNode->setGeometry(rctGeom);
        }    
        if ( blnModified == true ) {
            QWidget* pobjWidget(mpobjNode->pobjGetWidget());
            if ( pobjWidget != nullptr ) {
                pobjWidget->setMinimumSize(rctGeom.width(), rctGeom.height());
            }
        }
        //Connect native signals to repeater signals
        QMetaObject::Connection cn;
        cn = QObject::connect(this, &clsQtTextEdit::copyAvailable
                             ,this, &clsQtTextEdit::rptrCopyAvailable);
        Q_ASSERT_X(cn, clsQtTextEdit::metaObject()->className()
                  ,QString(clsXMLnode::mscszAssertCannotConnectToRepeater)
                    .arg(clsQtTextEdit::mscszQtSignalCopyAvailable)
                              .toLocal8Bit().data());
        cn = QObject::connect(this, &clsQtTextEdit::currentCharFormatChanged
                             ,this, &clsQtTextEdit::rptrCurrentCharFormatChanged);
        Q_ASSERT_X(cn, clsQtTextEdit::metaObject()->className()
                  ,QString(clsXMLnode::mscszAssertCannotConnectToRepeater)
                    .arg(clsQtTextEdit::mscszQtSignalCurrentCharFormatChanged)
                              .toLocal8Bit().data());
        cn = QObject::connect(this, &clsQtTextEdit::cursorPositionChanged
                             ,this, &clsQtTextEdit::rptrCursorPositionChanged);
        Q_ASSERT_X(cn, clsQtTextEdit::metaObject()->className()
                  ,QString(clsXMLnode::mscszAssertCannotConnectToRepeater)
                    .arg(clsQtTextEdit::mscszQtSignalCursorPositionChanged)
                              .toLocal8Bit().data());
        cn = QObject::connect(this, &clsQtTextEdit::redoAvailable
                             ,this, &clsQtTextEdit::rptrRedoAvailable);
        Q_ASSERT_X(cn, clsQtTextEdit::metaObject()->className()
                  ,QString(clsXMLnode::mscszAssertCannotConnectToRepeater)
                    .arg(clsQtTextEdit::mscszQtSignalRedoAvailable)
                              .toLocal8Bit().data());
        cn = QObject::connect(this, &clsQtTextEdit::selectionChanged
                             ,this, &clsQtTextEdit::rptrSelectionChanged);
        Q_ASSERT_X(cn, clsQtTextEdit::metaObject()->className()
                  ,QString(clsXMLnode::mscszAssertCannotConnectToRepeater)
                    .arg(clsQtTextEdit::mscszQtSignalSelectionChanged)
                              .toLocal8Bit().data());
        cn = QObject::connect(this, &clsQtTextEdit::textChanged
                             ,this, &clsQtTextEdit::rptrTextChanged);
        Q_ASSERT_X(cn, clsQtTextEdit::metaObject()->className()
                  ,QString(clsXMLnode::mscszAssertCannotConnectToRepeater)
                    .arg(clsQtTextEdit::mscszQtSignalTextChanged)
                              .toLocal8Bit().data());
        cn = QObject::connect(this, &clsQtTextEdit::undoAvailable
                             ,this, &clsQtTextEdit::rptrUndoAvailable);
        Q_ASSERT_X(cn, clsQtTextEdit::metaObject()->className()
                  ,QString(clsXMLnode::mscszAssertCannotConnectToRepeater)
                    .arg(clsQtTextEdit::mscszQtSignalUndoAvailable)
                              .toLocal8Bit().data());
        mpobjWindow = mpobjNode->pobjGetWindow();
        if ( mpobjWindow != nullptr ) {
            cn = QObject::connect(mpobjWindow, &clsXMLnode::blankControls
                                 ,this, &clsQtTextEdit::blankControl);
            Q_ASSERT_X(cn, clsQtTextEdit::metaObject()->className()
                      ,QString(clsXMLnode::mscszAssertCannotConnect)
                        .arg(clsXMLnode::mscszSignalBlankControls)
                                  .toLocal8Bit().data());
            cn = QObject::connect(mpobjWindow, &clsXMLnode::redoChanges
                                 ,this, &clsQtTextEdit::onRedoChange);
            Q_ASSERT_X(cn, clsQtTextEdit::metaObject()->className()
                      ,QString("Cannot connect %1!").arg(clsXMLnode::mscszSignalRedoChanges)
                                  .toLocal8Bit().data());
            cn = QObject::connect(mpobjWindow, &clsXMLnode::undoChanges
                                 ,this, &clsQtTextEdit::onUndoChange);
            Q_ASSERT_X(cn, clsQtTextEdit::metaObject()->className()
                      ,QString("Cannot connect %1!").arg(clsXMLnode::mscszSignalUndoChanges)
                                  .toLocal8Bit().data());
        }
        //Now the widget should be set-up, finalise set-up
        addNodeToWindow();
    }
    /**
     * @brief clsQtTextEdit::blankControl
     */
    void clsQtTextEdit::blankControl() {
        setData("");
    }
    /**
     * @brief clsQtTextEdit::blnValidSignal
     * @param strSignal : The signal to validate
     * @return true if the signal is valid else false
     */
    bool clsQtTextEdit::blnValidSignal(QString strSignal) {
        return clsXMLinterface::blnValidSignal(&clsQtTextEdit::mscmpSignals, strSignal);
    }
    /**
     * @brief clsQtTextEdit::objGetData
     * @param pstrValue : Optional, pointer return value as string
     * @return Current text from control
     */
    QJsonObject clsQtTextEdit::objGetData(QString* pstrValue) {
        QString strValue(strGetData());
        QJsonObject objJSON;
        objJSON.insert(clsXMLnode::mscszAttrText, strValue);
        if ( pstrValue != nullptr ) {
            *pstrValue = strValue;
        }
        return objJSON;
    }
    /**
     * @brief clsQtTextEdit::onRedoChange
     */
    void clsQtTextEdit::onRedoChange() {
        if ( mpobjNode->blnCheckAndRestoreFocus(*this) != true ) {
            return;
        }
        clsXMLinterface* pobjXMLIF(dynamic_cast<clsXMLinterface*>(this));
        if ( pobjXMLIF == nullptr ) {
            return;
        }
        if ( *mpintUndoRedoIdx < mpobjUndoRedo->size() - 1 ) {
            const QJsonValue cobjJSON(pobjXMLIF->at(++*mpintUndoRedoIdx));
            setData(cobjJSON.toString(), false);
        }
        pobjXMLIF->setUndoRedoButtonStates();
    }
    /**
     * @brief clsQtTextEdit::onUndoChange
     */
    void clsQtTextEdit::onUndoChange() {
        if ( mpobjNode->blnCheckAndRestoreFocus(*this) != true ) {
            return;
        }
        clsXMLinterface* pobjXMLIF(dynamic_cast<clsXMLinterface*>(this));
        if ( pobjXMLIF == nullptr ) {
            return;
        }
        if ( *mpintUndoRedoIdx == -1 || *mpintUndoRedoIdx >= mpobjUndoRedo->size() ) {
        //Default to the end of the stack
            *mpintUndoRedoIdx = mpobjUndoRedo->size() - 1;
        }
        if ( *mpintUndoRedoIdx > 0 ) {
            const QJsonValue cobjJSON(pobjXMLIF->at(--*mpintUndoRedoIdx));
            setData(cobjJSON.toString(), false);
        }
        pobjXMLIF->setUndoRedoButtonStates();
    }
    /**
     * @brief clsQtTextEdit::rptrCopyAvailable
     * @param blnYes : boolean yes = true else false
     */
    void clsQtTextEdit::rptrCopyAvailable(bool blnYes) {
        QJsonObject objJSON;
        if ( mpobjNode->blnCheckSubscribers(clsQtTextEdit::mscszQtSignalCopyAvailable
                                           ,&objJSON) == true ) {
            QJsonObject objParam;
            objParam["yes"] = blnYes;
            objJSON[clsXMLnode::mscszAttrParameters] = objParam;
            emit mpobjNode->commonRptdSignal(objJSON);
        }
    }
    /**
     * @brief clsQtTextEdit::rptrCurrentCharFormatChanged
     * @param format : format information
     */
    void clsQtTextEdit::rptrCurrentCharFormatChanged(const QTextCharFormat& format) {
        QJsonObject objJSON;
        if ( mpobjNode->blnCheckSubscribers(clsQtTextEdit::mscszQtSignalCurrentCharFormatChanged
                                           ,&objJSON) == true ) {
            QJsonObject objParam;
            //objParam["format"] = format;
            objJSON[clsXMLnode::mscszAttrParameters] = objParam;
            emit mpobjNode->commonRptdSignal(objJSON);
        }
        (void)format;
    }
    /**
     * @brief clsQtTextEdit::rptrCursorPositionChanged
     */
    void clsQtTextEdit::rptrCursorPositionChanged() {
        QJsonObject objJSON;
        if ( mpobjNode->blnCheckSubscribers(clsQtTextEdit::mscszQtSignalCursorPositionChanged
                                           ,&objJSON) == true ) {
            QJsonObject objParam;
            QCursor curPos = cursor();
            QPoint ptCursor = curPos.pos();
            objParam[clsXMLnode::mscszAttrX] = ptCursor.x();
            objParam[clsXMLnode::mscszAttrY] = ptCursor.y();
            objJSON[clsXMLnode::mscszAttrParameters] = objParam;
            emit mpobjNode->commonRptdSignal(objJSON);
        }
    }
    /**
     * @brief clsQtTextEdit::rptrRedoAvailable
     * @param blnAvailable : boolean yes = true else false
     */
    void clsQtTextEdit::rptrRedoAvailable(bool blnAvailable) {    
        QJsonObject objJSON;
        if ( mpobjNode->blnCheckSubscribers(clsQtTextEdit::mscszQtSignalRedoAvailable
                                           ,&objJSON) == true ) {
            QJsonObject objParam;
            objParam[clsXMLnode::mscszAttrAvailable] = blnAvailable;
            objJSON[clsXMLnode::mscszAttrParameters] = objParam;
            emit mpobjNode->commonRptdSignal(objJSON);
        }
    }
    /**
     * @brief clsQtTextEdit::rptrSelectionChanged
     */
    void clsQtTextEdit::rptrSelectionChanged() {
        QJsonObject objJSON;
        if ( mpobjNode->blnCheckSubscribers(clsQtTextEdit::mscszQtSignalSelectionChanged
                                           ,&objJSON) == true ) {
            emit mpobjNode->commonRptdSignal(objJSON);
        }
    }
    /**
     * @brief clsQtTextEdit::rptrTextChanged
     */
    void clsQtTextEdit::rptrTextChanged() {
        QJsonObject objJSON(mpobjNode->makeJSONresponse(clsQtTextEdit::mscszQtSignalTextChanged));
        const QString cstrText(strGetData());
        objJSON[clsXMLnode::mscszAttrData] = cstrText;
        emit mpobjNode->commonRptdSignal(objJSON);
        setData(cstrText);
    }
    /**
     * @brief clsQtTextEdit::rptrUndoAvailable
     * @param blnAvailable : boolean yes = true else false
     */
    void clsQtTextEdit::rptrUndoAvailable(bool blnAvailable) {
        QJsonObject objJSON;
        if ( mpobjNode->blnCheckSubscribers(clsQtTextEdit::mscszQtSignalUndoAvailable
                                           ,&objJSON) == true ) {
            QJsonObject objParam;
            objParam[clsXMLnode::mscszAttrAvailable] = blnAvailable;
            objJSON[clsXMLnode::mscszAttrParameters] = objParam;
            emit mpobjNode->commonRptdSignal(objJSON);
        }
    }
    /**
     * @brief clsQtTextEdit::setData
     * @param crstrData : Constant reference to data string
     * @param blnTrackChange : Optional, default is true
     */
    void clsQtTextEdit::setData(const QString& crstrData, bool blnTrackChange) {
        if ( mpobjWindow == nullptr ) {
            return;
        }
        QString strID(mpobjNode->strGetAttribute(clsXMLnode::mscszAttrID));
        if ( strID.isEmpty() == true ) {
            return;
        }
        QByteArray arybyt(strID.toLatin1());
        const char* cpszID(arybyt.data());
        QVariant varLast(mpobjWindow->property(cpszID));
        QJsonValue objLast, objValue(crstrData);
        //Any previous state stored?
        if ( varLast.isValid() == true ) {
            objLast = varLast.toJsonValue();
        } else {
        //No use current value as last
            objLast = objValue;
            mpobjWindow->QObject::setProperty(cpszID, objValue);
        }
        if ( blnTrackChange == false || blnPush(objValue) == true ) {
            bool blnBlock(QTextEdit::blockSignals(true));
            QString strCurrent(QTextEdit::toPlainText());
            if ( strCurrent.compare(crstrData) != 0 ) {
                QTextEdit::setText(crstrData);
            }
            QTextEdit::blockSignals(blnBlock);
        }
        emit mpobjNode->controlUpdate(strID, objValue != objLast);
        if ( blnTrackChange == true ) {
            emit mpobjNode->setWidgetInFocus(this);
        }
    }
    /**
     * @brief clsQtTextEdit::setProperty
     * @param strProperty : The property name
     * @param strValue : Value to assign to property
     */
    void clsQtTextEdit::setProperty(QString strProperty, QString strValue) {
        if ( strProperty.compare(clsXMLnode::mscszPropertyCursorWidth) == 0 ) {
            setCursorWidth(strValue.toInt());
        } else if ( strProperty.compare(clsXMLnode::mscszPropertyOverwrite) == 0 ) {
            bool blnOverwrite;
    
            if ( strValue.compare(clsXMLnode::mscszTrue) == 0 ) {
                blnOverwrite = true;
            } else {
                blnOverwrite = false;
            }
            setOverwriteMode(blnOverwrite);
        } else if ( strProperty.compare(clsXMLnode::mscszPropertyReadOnly) == 0 ) {
            bool blnReadOnly;
    
            if ( strValue.compare(clsXMLnode::mscszTrue) == 0 ) {
                blnReadOnly = true;
            } else {
                blnReadOnly = false;
            }
            setReadOnly(blnReadOnly);
        } else if ( strProperty.compare(clsXMLnode::mscszPropertyRichText) == 0 ) {
            bool blnRichText;
    
            if ( strValue.compare(clsXMLnode::mscszTrue) == 0 ) {
                blnRichText = true;
            } else {
                blnRichText = false;
            }
            setAcceptRichText(blnRichText);
        }
    }
    /**
     * @brief clsQtTextEdit::setText
     * @param crstrText : Constant reference to text to use
     */
    void clsQtTextEdit::setText(const QString& crstrText) {
        setData(crstrText);
    }
    /**
     * @brief clsQtTextEdit::strGetData
     * @return Text trimmed of whitespace
     */
    QString clsQtTextEdit::strGetData() {
        return toPlainText().trimmed();
    }
    

    I load form content from an XML file:

    <?xml version="1.0" encoding="utf-8"?>
    <form title="Test form" id="frmTest" hspacing="0" vspacing="0" width="420"
    	  height="360" modal="false">
    	<entry cols="24" control="listwidget" eol="true" 
    		   excludeFromChangeCheck="true" id="enSEL" label="Select" mode="single"
    		   resetPropertiesOnChange="true" rows="1">
    		<subscriber signal="currentItemChanged"
    					target="simon2.js@listWidgetChanged"/>
    		<subscriber signal="itemSelectionChanged"
    					target="simon2.js@listWidgetHandler"/>
    	</entry>
    	<entry control="lineedit" label="First name" id="enFN" eol="true"
    		   cols="24" maxlength="24" accept="alpha_only"/>
    	<entry control="lineedit" label="Surname" id="enSN" eol="true"
    		   cols="24" maxlength="24" accept="alpha_only"/>
    	<label text="Sex"/>		   	
    	<layout eol="true" height="56" hspacing="0" id="rdoLO" scrollbar="false" 
    			type="grid" vspacing="0" width="72">
    		<buttongroup id="enSEX" default="rdoM">
    			<radiobutton id="rdoM" height="28" text="Male"/>
    			<radiobutton id="rdoF" height="28" text="Female"/>
    		</buttongroup>
    	</layout>
    	<entry control="textedit" label="Address" id="enADR" eol="true"
    		   maxlength="256" accept="alpha_numeric" cols="24" rows="5"
    		   properties="margin-bottom: 16px;"/> 
    	<entry control="checkbox" eol="true" id="enEmp" label="Employed"
    		   default="0"/>
    <!-- TO DO LIST
    
    1. Undo button (done)
    2. Apply button
    3. Submit and close button
    4. When 
    
    When any the content changes from what it was, gray out "enSEL" and enable the 
    "Undo" button, if the data matches original gray out "Undo" button restore
    if data is back to original.
    -->	
    	<layout colspan="2" id="btnbarLO" scrollbar="false" type="horizontal">
    		<buttongroup id="enBar">
    			<button id="btnApply" api="applyChanges"
    					excludeFromChangeCheck="true"
    					image="~/XMLMPAM/config/svg/apply.svg"
    					tooltip="!apply!">
    				<subscriber signal="clicked"
    							target="simon2.js@submitForm"/>
    			</button>
    			<button id="btnUndo" api="undoChanges"
    					excludeFromChangeCheck="true"
    					image="~/XMLMPAM/config/svg/undo.svg"
    					tooltip="!undo!"/>					
    			<button id="btnRedo" api="redoChanges"
    					excludeFromChangeCheck="true"
    					image="~/XMLMPAM/config/svg/redo.svg"
    					tooltip="!redo!"/>
    			<button id="btnOK" api="submitAndClose"
    					excludeFromChangeCheck="true"
    					image="~/XMLMPAM/config/svg/ok.svg"
    					tooltip="!submit!">	
    				<subscriber signal="clicked"
    							target="simon2.js@submitForm"/>
    			</button>
    			<button id="btnCancel" api="cancelAndClose"
    					excludeFromChangeCheck="true"
    					image="~/XMLMPAM/config/svg/cancel.svg"
    					tooltip="!candc!"/>
    		</buttongroup>
    	</layout>
    	<on setup="simon2.js@setupForm"/>
    </form>
    

    This is just a demo, please ask if there is anything else you would like to see. The output from the above as rendered by my engine is:
    Screenshot 2022-08-02 at 09.01.00.png
    I am observing some strange behaviour in the Address, if I start typing for example abc then press return/enter the cursor jumps back to the beginning of the line and not a new line as I would like. If I then continue to type abc and then press return/enter again, this time a new line is created and now I have:

    abc
    abc
    

    Is there a way I can change this so that when I enter text and press return/enter a new line is added immediately ?

    Kind Regards,
    Sy

    1 Reply Last reply
    0
    • Axel SpoerlA Offline
      Axel SpoerlA Offline
      Axel Spoerl
      Moderators
      wrote on last edited by
      #2

      @SPlatten said in How to change behaviour of CTextEdit:

      QTextEdit::setText(crstrData);

      Having quickly browsed through the code: QTextEdit::setText(crstrData) could be a suspect. It sets crstrData as the new text, which puts the cursor at the beginning, even though signals are correctly blocked.

      Software Engineer
      The Qt Company, Oslo

      SPlattenS 1 Reply Last reply
      0
      • Axel SpoerlA Axel Spoerl

        @SPlatten said in How to change behaviour of CTextEdit:

        QTextEdit::setText(crstrData);

        Having quickly browsed through the code: QTextEdit::setText(crstrData) could be a suspect. It sets crstrData as the new text, which puts the cursor at the beginning, even though signals are correctly blocked.

        SPlattenS Offline
        SPlattenS Offline
        SPlatten
        wrote on last edited by SPlatten
        #3

        @Axel-Spoerl , thank you, I will look into it, how would I set the text without resetting the cursor position?

        [Edit] So now I've modified the code to:

                    QTextCursor cursor(textCursor());
                    QTextEdit::setText(crstrData);
                    setTextCursor(cursor);
        

        Now when I press enter/return it does nothing....will look into this.

        [Edit2] When debugging this with no content I type A, then press enter/return. I can see that cursor is returned as 1 then after calling setText with A\n the cursor I had queried before calling setText changes to 2.

        Kind Regards,
        Sy

        1 Reply Last reply
        0
        • Axel SpoerlA Offline
          Axel SpoerlA Offline
          Axel Spoerl
          Moderators
          wrote on last edited by
          #4

          A QTextEdit handels the input by itself- including the enter key which adds a new line and puts the cursor at its beginning.

          Do you expect the enter key to trigger anything different?

          Upon calling setText(), it is expected the a user's input is overwritten with something else. The current cursor position might even no longer be valid in case the new text is shorter than the previous user input. This is why setting the cursor back at the beginning is expected behavior. Reading the cursor and restoring it after setText() might work, but it is only safe if you know that its previous position is still a valid one.

          Can you explain which behavior you expect from the interaction of user input and setText() .

          Software Engineer
          The Qt Company, Oslo

          SPlattenS 1 Reply Last reply
          0
          • Axel SpoerlA Axel Spoerl

            A QTextEdit handels the input by itself- including the enter key which adds a new line and puts the cursor at its beginning.

            Do you expect the enter key to trigger anything different?

            Upon calling setText(), it is expected the a user's input is overwritten with something else. The current cursor position might even no longer be valid in case the new text is shorter than the previous user input. This is why setting the cursor back at the beginning is expected behavior. Reading the cursor and restoring it after setText() might work, but it is only safe if you know that its previous position is still a valid one.

            Can you explain which behavior you expect from the interaction of user input and setText() .

            SPlattenS Offline
            SPlattenS Offline
            SPlatten
            wrote on last edited by
            #5

            @Axel-Spoerl , thank you, part of the issues is the way I manage the data so the way I've implemented redo/undo work.

            Kind Regards,
            Sy

            1 Reply Last reply
            0
            • Axel SpoerlA Offline
              Axel SpoerlA Offline
              Axel Spoerl
              Moderators
              wrote on last edited by
              #6

              Understand. But which role does the enter button play in that game?

              A native Qt application (including Creator) would put the cursor

              • (undo): to the position where it was before the undone change was made.
              • (redo): to the last character of the change that is redone.

              This behavior is meant to draw the user's attention to the position where a change has been made.
              If you elect to adopt his policy, the undo stack needs to remember the cursor position.
              It would never stay where it was when the undo/redo button operation was initiated.

              Software Engineer
              The Qt Company, Oslo

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved