#include "RsButtonOnText.h" #include #include #include #include #include #include #include #include #include RSButtonOnText::RSButtonOnText(QWidget *parent) : QPushButton(parent) { _uuid = QUuid::createUuid().toString(); _lenght = -1; _mouseOver = false; _pressed = false; } RSButtonOnText::RSButtonOnText(const QString &text, QWidget *parent) : QPushButton(parent) //: RSButtonOnText(parent)//delegating constructors only available with -std=c++11 or -std=gnu++11 { _uuid = QUuid::createUuid().toString(); _lenght = -1; _mouseOver = false; _pressed = false; setText(text); } RSButtonOnText::RSButtonOnText(const QIcon& icon, const QString &text, QWidget *parent) : QPushButton(parent) //: RSButtonOnText(text, parent)//delegating constructors only available with -std=c++11 or -std=gnu++11 { _uuid = QUuid::createUuid().toString(); _lenght = -1; _mouseOver = false; _pressed = false; setIcon(icon); setText(text); } RSButtonOnText::RSButtonOnText(QTextEdit *textEdit, QWidget *parent) : QPushButton(parent) //: RSButtonOnText(parent)//delegating constructors only available with -std=c++11 or -std=gnu++11 { _uuid = QUuid::createUuid().toString(); _lenght = -1; _mouseOver = false; _pressed = false; appendToText(textEdit); } RSButtonOnText::RSButtonOnText(const QString &text, QTextEdit *textEdit, QWidget *parent) : QPushButton(parent) //: RSButtonOnText(parent)//delegating constructors only available with -std=c++11 or -std=gnu++11 { _uuid = QUuid::createUuid().toString(); _lenght = -1; _mouseOver = false; _pressed = false; setText(text); appendToText(textEdit); } RSButtonOnText::RSButtonOnText(const QIcon& icon, const QString &text, QTextEdit *textEdit, QWidget *parent) : QPushButton(parent) //: RSButtonOnText(parent)//delegating constructors only available with -std=c++11 or -std=gnu++11 { _uuid = QUuid::createUuid().toString(); _lenght = -1; _mouseOver = false; _pressed = false; setIcon(icon); setText(text); appendToText(textEdit); } RSButtonOnText::~RSButtonOnText() { clear(); } bool RSButtonOnText::eventFilter(QObject *obj, QEvent *event) { // comment electron: // the guard is here, because someone deletes this object in callbacks(slots) called from here // the QPointer can detect this // but this is bad practice, because it hides the root cause for the problem, // which is the deletion of objects in their own signals // TODO: better use the Qt function deleteLater QPointer guard(this); QPoint point; if (isEventForThis(obj, event, point)) { if (event->type() == QEvent::ToolTip) { QToolTip::showText(point, this->toolTip()); event->ignore();//For other don't clear this one return true; } if (event->type() == QEvent::MouseButtonPress) { QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseButtonPress ,QPoint(1,1),Qt::LeftButton,Qt::LeftButton,0); QPushButton::mousePressEvent(mouseEvent); delete mouseEvent; if (guard) _pressed = true; //if (guard) emit pressed(); if (guard) updateImage(); } if (event->type() == QEvent::MouseButtonRelease) { QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseButtonPress ,QPoint(1,1),Qt::LeftButton,Qt::LeftButton,0); QPushButton::mouseReleaseEvent(mouseEvent); delete mouseEvent; if (guard) _pressed = false; //if (guard) emit released(); //if (guard) emit clicked(); //if (guard) if (isCheckable()) emit clicked(QPushButton::isChecked()); //if (guard) if (isCheckable()) emit toggled(QPushButton::isChecked()); if (guard) updateImage(); } if (event->type() == QEvent::MouseMove) { if (!_mouseOver){ //QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseButtonPress // ,QPoint(1,1),Qt::LeftButton,Qt::LeftButton,0); //QPushButton::enterEvent(mouseEvent);//Do nothing //delete mouseEvent; //QPushButton::setDown(true); if (guard) emit mouseEnter(); } if (guard) _mouseOver = true; if (guard) updateImage(); } } else { if (event->type() == QEvent::MouseMove) { if (_mouseOver) { //QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseButtonPress // ,QPoint(1,1),Qt::LeftButton,Qt::LeftButton,0); //QPushButton::leaveEvent(mouseEvent);//Do nothing //delete mouseEvent; //QPushButton::setDown(false); _mouseOver = false; if (guard) emit mouseLeave(); if (guard) updateImage(); } if (_pressed){ QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseButtonPress ,QPoint(1,1),Qt::LeftButton,Qt::LeftButton,0); QPushButton::mouseReleaseEvent(mouseEvent); delete mouseEvent; //if (guard) emit released(); if (guard) updateImage(); } } } if(!guard) std::cerr << "BIG FAT WARNING from RSButtonOnText::eventFilter(): i was deleted in my own event handler. This is bad practice. Please make a patch and use deleteLater to delay deletion." << std::endl; // pass the event on to the parent class return QWidget::eventFilter(obj, event); } bool RSButtonOnText::isEventForThis(QObject *obj, QEvent *event, QPoint &point) { switch (event->type()) { case QEvent::MouseButtonPress://2 case QEvent::MouseButtonRelease://3 case QEvent::MouseButtonDblClick://4 case QEvent::MouseMove://5 { QMouseEvent* mouseEvent = static_cast(event); point = mouseEvent->pos(); } break; case QEvent::ToolTip://110 { QHelpEvent* helpEvent = static_cast(event); point = helpEvent->globalPos(); } break; default: return false; } if (!event->isAccepted()) return false;//Already other take this event (true by default) if (obj ==_textEditViewPort) { if (_textEdit){ QTextCursor cursor = _textEdit->cursorForPosition(point); if ( (_textCursor->anchor() <= cursor.anchor()) && (cursor.position() <= _textCursor->anchor()+_lenght)){ return true; } } } return false; } QString RSButtonOnText::uuid() { return _uuid; } QString RSButtonOnText::htmlText() { return ""; } void RSButtonOnText::appendToText(QTextEdit *textEdit) { clear(); _textEdit = textEdit; _textEditViewPort = textEdit->viewport(); updateImage(); _textCursor = new QTextCursor(textEdit->textCursor()); _textCursor->movePosition(QTextCursor::End); _textEdit->insertPlainText(QString(QChar::Nbsp));//To get cursorForPosition, else it returns next char after middle int textCursorSavePos = _textCursor->position(); _textCursor->insertHtml(htmlText()); _textCursor->setPosition(textCursorSavePos); _textCursor->movePosition(QTextCursor::End, QTextCursor::KeepAnchor); _lenght = _textCursor->position() - _textCursor->anchor(); _textEdit->insertPlainText(QString(QChar::Nbsp));//To get cursorForPosition, else it returns next char after middle _textCursor->setPosition(textCursorSavePos); _textEditViewPort->installEventFilter(this); } void RSButtonOnText::clear() { if(_lenght > 0){ _textCursor->setPosition(_textCursor->anchor()-1);//Remove Space too _textCursor->setPosition(_textCursor->anchor() + _lenght + 2, QTextCursor::KeepAnchor); _textCursor->deleteChar(); _lenght = -1; } } void RSButtonOnText::updateImage() { if (_textEdit){ adjustSize(); QPixmap pixmap; // Can't get Qt's grab functionality to draw a transparent background so we use our own drawing on a pixmap //#if QT_VERSION >= QT_VERSION_CHECK (5, 0, 0) // pixmap = this->grab();//QT5 //#else // pixmap = QPixmap::grabWidget(this); //#endif // get a transparent pixmap pixmap = QPixmap(size()); pixmap.fill(Qt::transparent); // init options QStyleOptionButton option; initStyleOption(&option); // draw the button onto the pixmap QStylePainter painter(&pixmap, this); painter.drawControl(QStyle::CE_PushButton, option); painter.end(); _textEdit->setUpdatesEnabled(false); _textEdit->document()->addResource(QTextDocument::ImageResource,QUrl(_uuid),QVariant(pixmap)); _textEdit->setUpdatesEnabled(true); } }