Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Close the editor widget of QStyledItemDelegate correctly...



  • Hello everyone!
    I have created an RichEditor put into QStyledItemDelegate for a QTableWidget . like this:
    alt text

    I block on that... I would like to know if an widget editor created with QStyledItemDelegate on QTableWidget is open ? is it possible?


  • Lifetime Qt Champion

    Hi,

    What do you want to do with that information ?



  • @SGaist I want commit data and close editor, when user click on another button outside of editor or leave the QtableWidget.

    I tried in many ways, but I dont find the good approach.


  • Lifetime Qt Champion

    That's what should happen by default when your editor loses focus.

    How did you implement it ?



  • @SGaist That's what should happen by default when your editor loses focus.
    Yes I found the problem -> when I click and focus into the textEdit, and then loses focus on it, Editor does not closed...

    like this:
    alt text

    How did you implement it ?

    /**
     * @brief The itemTextEditStyle class
     *		  Create a textEdit with advanced settings like the spell checker, HTML...
     */
    class itemTextEditStyle : public QStyledItemDelegate
    {
       Q_OBJECT
    
    public:
       itemTextEditStyle(QLocale &lang, mDico *myDico, bool spellCheck, QObject *parent ) : QStyledItemDelegate(parent) {
    		m_lang  = lang;
    		m_dico = myDico;
    		m_spellCheck = spellCheck;
    		mTableWidget = qobject_cast<QTableWidget *>(parent);
       }
    
       // Paint html with render
       void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
       {
    	   QStyleOptionViewItem mOption = option;
    	   initStyleOption(&mOption, index);
    
    	   QStyle *style = mOption.widget? mOption.widget->style() : QApplication::style();
    
    	   /// Painting item without text
    	   mOption.text = QString();
    	   style->drawControl(QStyle::CE_ItemViewItem, &mOption, painter);
    
    	   /// Paint html
    		QTextDocument HtmlTxt;
    		QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &mOption);
    		HtmlTxt.setHtml( index.data().toString() );
    		HtmlTxt.setTextWidth(option.rect.width()-20);// - width of Ico
    		painter->save();
    		painter->translate(textRect.topLeft());
    		painter->setClipRect(textRect.translated(-textRect.topLeft()));
    		HtmlTxt.drawContents(painter);
    		painter->restore();
       }
    
    	// Create complex widget
       QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& style, const QModelIndex& index) const {
    	   Q_UNUSED(style);Q_UNUSED(index);
    
    	   QLocale lang =  m_lang;
    	   McTextEditRich *mEditor = new McTextEditRich(lang, m_spellCheck, m_dico, parent);
    
    	   // Connection signal of keypressReturn of Editor
    	   MCTextEdit *txtEditor = mEditor->findChild<MCTextEdit*>("mTextEditRich");
    	   connect(txtEditor,SIGNAL(keyPressReturn(const QString&, const int&)), this, SLOT(keyPressEvent(const QString&, const int&)));
    	   return mEditor;
       }
    
    	// Set Data to the editor
       void setEditorData(QWidget *editor,const QModelIndex &index) const {
    	   MCTextEdit *txtEditor = editor->findChild<MCTextEdit*>("mTextEditRich");
    	   if (txtEditor) {
    			txtEditor->setHtml(index.data().toString());
    			return;
    	   }
    	   else QStyledItemDelegate::setEditorData(editor, index);
       }
    
    	// Set Data into the model
       void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
    	   MCTextEdit *txtEditor = editor->findChild<MCTextEdit*>("mTextEditRich");
    	   if (txtEditor) {
    			model->setData(index, txtEditor->toHtml());
    			return;
    		}
    	   else QStyledItemDelegate::setModelData(editor, model, index);
       }
     
    private slots:
    
    	// Set the height of row according to the editor
    	void keyPressEvent(const QString& textContent, const int& widthEditor) {
    		QTextDocument HtmlTxt;
    		HtmlTxt.setHtml(textContent);
    		HtmlTxt.setTextWidth(widthEditor);
    
    		mTableWidget->setRowHeight(mTableWidget->currentRow(), int(HtmlTxt.size().height()) + 40);
    	}
    
    private:
    	QLocale m_lang;
    	mDico *m_dico;
    	bool m_spellCheck;
    	QTableWidget *mTableWidget;
    };
    

    An idea ? :(


  • Lifetime Qt Champion

    Not knowing how MCTextEdit is implemented, I can't really comment.

    Take a look a the Star Delegate Example. That might give you some additional clue.



  • @SGaist said in Close the editor widget of QStyledItemDelegate correctly...:

    MCTextEdit

    Your right, I have tried with simple QTextEdit, in my McTextEditRich QWidget, the result is the same...
    I inspired me by the example "the Star Delegate Example." ;)

    I have install an eventFilter on editor to debug this,

    // Install Event filter on mEditor debug
    mEditor->installEventFilter(const_cast<itemTextEditStyle*>(this));
    ...
    bool eventFilter(QObject *object, QEvent *event) {
    
    	if(qobject_cast<McTextEditRich*>(object)) {
    		if((event->type() == QEvent::FocusAboutToChange) || (event->type() == QEvent::FocusOut))
    			qDebug() << "eventFilter " << event->type();
    		}
    		return QStyledItemDelegate::eventFilter(object, event);
    	}
    

    And apparently the QEvent::Type(FocusOut) is emit if I enter in QTextedit...

    When I enter in QTextedit :
    QEvent::Type(FocusAboutToChange)
    QEvent::Type(FocusOut)
    

    And after when I focus on other widgets outsite of my editor, QEvent::Type(FocusOut) is not emit and editor stay open... like the gif above.


  • Lifetime Qt Champion

    One thing you could try is to handle the leaveEvent and put the focus on the "whole editor".



  • @SGaist Nice!
    I had tested with commitData() et closeEditor() but this crash sometime my app.

    So I finally keep the eventFilter function like this :

    // Set focus on editor if leave Editor !
    bool eventFilter(QObject *object, QEvent *event) {
    
    	McTextEditRich *mEditor = qobject_cast<McTextEditRich*>(object);
    	if(mEditor) {
    		// if leave Editor
    		if((event->type() == QEvent::Leave)){
    			// Set focus on editor to allow after, the emit of QEvent::Type(FocusOut) normally
    			mEditor->setFocus();
    			return true;
    		}
    	}
    	return QStyledItemDelegate::eventFilter(object, event);
    }
    

    Thanks for your time @SGaist ;) ++



  • @cfdev Maybe you should listen QTextEdit viewport events, not QTextEdit directly.



  • I had the same problem and for me, the cause was that my editor had a focus proxy set. This prevents that FocusIn, FocusOut and FocusAboutToChange events are delivered to the editor (they are delivered to the focus proxy instead). But QStyledItemDelegate relies on those events to commit the editor when it loses focus.

    To fix it, I installed an event filter on the focus proxy and used QCoreApplication::sendEvent() to forward the focus events to the editor:

    bool MyEditor::eventFilter( QObject* eventTarget, QEvent* event ) override
    {
    	switch( event->type() )
    	{
    	case QEvent::FocusIn:
    	case QEvent::FocusOut:
    	case QEvent::FocusAboutToChange:
    		if( eventTarget == focusProxy() )
    		{
    			// Forward focus events to editor because the QStyledItemDelegate relies on them
    			QCoreApplication::sendEvent( this, event );
    		}
    		break;
    	default:
    		break;
    	}
    
    	return BaseClass::eventFilter( eventTarget, event );
    }
    

Log in to reply