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. Global image position inside a QTextEdit
Forum Updated to NodeBB v4.3 + New Features

Global image position inside a QTextEdit

Scheduled Pinned Locked Moved General and Desktop
16 Posts 5 Posters 10.2k Views 1 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.
  • G Offline
    G Offline
    goetz
    wrote on last edited by
    #4

    As far as I know, there is no public API for that - unfortunately :-/

    http://www.catb.org/~esr/faqs/smart-questions.html

    1 Reply Last reply
    0
    • B Offline
      B Offline
      Bareos
      wrote on last edited by
      #5

      okay. thanks for your time

      1 Reply Last reply
      0
      • B Offline
        B Offline
        Bareos
        wrote on last edited by
        #6

        Now don't know how to programm my WYSIWYG-Texteditor. Maybe you can give me a Hint. I want to design a Texteditor with the possibility to resize images through the mouse.

        1 Reply Last reply
        0
        • G Offline
          G Offline
          goetz
          wrote on last edited by
          #7

          Sorry, I don't have any ideas for that - maybe someone else?

          http://www.catb.org/~esr/faqs/smart-questions.html

          1 Reply Last reply
          0
          • K Offline
            K Offline
            Kxyu
            wrote on last edited by
            #8

            It's a very intersting question and I want to show you a possible solution I've invented.

            So the problem is that wen you insert an image into a QTextDocument you don't have an object to manipulate that image, like change size, detect mouse events on it and so on. We start with introducing such an object.

            @
            class MyTextEditAdvancedObject : public QObject
            {
            Q_OBJECT
            public:
            explicit MyTextEditAdvancedObject(QObject *parent = 0);

            void setRect(const QRectF &_rect)
            {
                m_rect=_rect;
            }
            
            const QRectF &rect()
            {
                return m_rect;
            }
            
            void paint(QPainter &painter);
            QSizeF getSize();
            void pressed();
            

            private:
            QRectF m_rect;

            };

            @

            It's just an example, you can implement the class in an abstract fashion and then make a whole hierarchy of such classes, that can be inserted into QTextEdit. Methods of the class:

            • paint - paints whatever you want yo be painte
            • getSize - returns the size of your object
            • pressed - for demonstration, the code inside is executed whenever a user presses a mouse button over an object
            • rect setter and getter are used to keep object position up-to-date

            Then we have to insert this somehow in a QTextEdit. Qt has a special QTextObjectInterface class to implement custom objects. We can do like this:

            @
            class MyImageTextObject : public QObject, public QTextObjectInterface
            {
            Q_OBJECT
            Q_INTERFACES(QTextObjectInterface)

            public:
            MyImageTextObject();

            QSizeF intrinsicSize(QTextDocument *doc, int posInDocument,
                                 const QTextFormat &format);
            void drawObject(QPainter *painter, const QRectF &rect, QTextDocument *doc,
                            int posInDocument, const QTextFormat &format);
            

            };
            @

            So this is just a declaration. We've got to methods to implement - one returning size and one painting the object. We can just delegate that to our class, but the question is, how to connect this interface and our object/objects?

            Let's have a look at how to add custom objects to QTextEdit. I've made a method for that:
            @
            void MyTextEdit::addAdvancedObject(MyTextEditAdvancedObject *advObject)
            {
            advObjects<<advObject;

            QObject *_advObject=advObject;
            QTextCharFormat myCharFormat;
            myCharFormat.setObjectType(MyTextEdit::MyTextFormat);
            

            myCharFormat.setProperty(MyTextEdit::pointerData,qVariantFromValue(_advObject));

            QTextCursor cursor = this->textCursor();
            cursor.insertText(QString(QChar::ObjectReplacementCharacter), myCharFormat);
            this->setTextCursor(cursor);
            }
            @

            We need to create a QTextCharFormat object, set it type and insert then. But the QTextCharFormat object is accessible from QTextObjectInterface methods! So we can add a dynamic property there, containing a pointer to our object. We have to cast it to QObject*, so it's not type-safe, but it works.

            After that implementing our custom interface can be done like that:
            @
            void MyImageTextObject::drawObject(QPainter *painter, const QRectF &rect,
            QTextDocument * /doc/, int pos,
            const QTextFormat &format)
            {

            MyTextEditAdvancedObject *advObject;
            advObject=qobject_cast<MyTextEditAdvancedObject*>(qVariantValue<QObject*>(format.property(MyTextEdit::pointerData)));
            advObject->setRect(rect);
            
            advObject->paint(*painter);
            

            }

            @

            The final thing is to reimplement QTextEdit's mousePressed method.
            @
            void MyTextEdit::mousePressEvent(QMouseEvent *e)
            {
            QPoint point=e->pos();
            bool hit=false;
            point.ry()+=verticalScrollBar()->value(); //adjusting coordinates as they are mapped to widget

            foreach (MyTextEditAdvancedObject *advObject,advObjects)
            {
                if (advObject->rect().contains(point))
                {
                    advObject->pressed();       
                    hit=true;
                }
            
            }
            if (!hit) QTextEdit::mousePressEvent(e);
            

            }
            @

            That's it! Now you can work with an object inside a QTextEdit like with a widget, or may be implement a real proxy for QWidget.

            1 Reply Last reply
            0
            • B Offline
              B Offline
              Bareos
              wrote on last edited by
              #9

              That's looks like an very interesting solution. But there are some Points ich don't understand:

              • advObjects in your addAdvancedObject Methode fit a QSet?
              • If it is a QSet, how do you track whether the MyImageTextObject are deleted in the Textfield?
              1 Reply Last reply
              0
              • K Offline
                K Offline
                Kxyu
                wrote on last edited by
                #10

                a QList, but yes, that problem exists - we need to track if the special placeholder symbol is still in a QTextDocument. It's not a great problem, but some sort of a memory leak. As for me, I see several issues in this method:

                • deleting objects when the are deleted in QTextEdit
                • changing cursor - of course you want the cursor to be a hand or an arrow over the image (or maybe some resize cursors), but calling setCursor does nothing
                • how to save QTextDocument with such objects into a file
                • repainting issue - I tested the idea with selecting an image with a border after clicking on it. The problem was that the text cursor was put after that action after the image and only some area around it was repainted. Calling repaint() or update() explicitly didn't help.

                But we can work on that! You really would like to see Volker's and other pros' comments on that.

                1 Reply Last reply
                0
                • B Offline
                  B Offline
                  Bareos
                  wrote on last edited by
                  #11

                  I look forward to a good collaboration. Here are some of my thoughts:

                  • repainting issue: I think you can solve the problem like this in your QTextEdit:
                    @this->viewport()->update();@
                  • save issue: Maybe we can replace the QChar::ObjectReplacementCharacter with a Html-Image-Tag. Afterwards it is easy to save the whole document as a Html-page
                  • cursor issue: Are you sure that somethink like this don't work?
                    @QCursor cursor;
                    cursor.setShape(Qt::SizeFDiagCursor);
                    this->setCursor(cursor);@
                  • deleting issue: The only way coming through my mind is to search the whole document for QChar::ObjectReplacementCharacter. That sounds not like an very pretty way.
                  1 Reply Last reply
                  0
                  • K Offline
                    K Offline
                    Kxyu
                    wrote on last edited by
                    #12

                    Yeah, you are right, the viewport works! And the cursor thing also needed viewport (this->viewport()->setCursor())

                    The problem with saving is still a huge one - we just don't have an inerface for that. Of course we can try some dirty tricks, like

                    find all images

                    replace them with some id tokens

                    render to html

                    replace token with <img>

                    1 Reply Last reply
                    0
                    • B Offline
                      B Offline
                      Bareos
                      wrote on last edited by
                      #13

                      I worked a little on resizing the image and i noticed that the Image get smaller but not the place it allocate in the document. I searcht a bit and find another way to solve the repainting issue:

                      • track the document position like you did with the rect
                      • mark the QChar::ObjectReplacementCharacter in your document from QTextEdit as "dirty":
                        @this->document()->markContentsDirty(advObject->position(),1);@
                        if you use more than one char as replacement you have to replace the "1" with the lenght of your replacment.
                      1 Reply Last reply
                      0
                      • B Offline
                        B Offline
                        Bareos
                        wrote on last edited by
                        #14

                        We have a new problem. MyTextEditAdvancedObject can't be copy or past at the moment.

                        1 Reply Last reply
                        0
                        • T Offline
                          T Offline
                          tiho_d
                          wrote on last edited by
                          #15

                          Some time ago I have implemented a rubber band selection for an inside-editor image resizing. The complete idea I have described in the following "link":http://stackoverflow.com/questions/3720502/how-to-resize-an-image-in-a-qtextedit/25743848#25743848 .

                          The following code might help you get what you want.
                          @
                          QRect MyTextEditDecorator::imageRect(const QTextCursor &cursor) const
                          {
                          QTextImageFormat fmt = cursor.charFormat().toImageFormat();
                          if (!fmt.isValid())
                          return QRect();
                          if (!cursor.block().layout())
                          return QRect();

                          QRect cursorRect = textEdit()->cursorRect(cursor);
                          QRect cursorFrameRect(cursorRect.topLeft(), QSize(fmt.width(), fmt.height()));
                          
                          QTextLayout *blockLayout = cursor.block().layout();
                          QTextLine curLine = blockLayout->lineForTextPosition(cursor.positionInBlock());
                          QRectF curLineRect = curLine.rect();
                          curLineRect.moveTopLeft(blockLayout->position() + curLineRect.topLeft());
                          
                          int x = cursorRect.topLeft().x() - fmt.width();
                          int y = curLineRect.y() + curLine.ascent() + (curLine.leadingIncluded() ? qMax(curLine.leading(), 0.0) : 0); //baseline
                          y -= textEdit()->verticalScrollBar()->value();
                          
                          return QRect(x, y, fmt.width(), fmt.height());
                          

                          }
                          @

                          The above code does not take into account the image alignment(only baseline) and right to left text layout.
                          Assume that the textEdit() function above, returns a pointer to the QTextEdit object. If you put the above function inside a QTextEdit derived class simply replace it with a "this" pointer.

                          Hope it helps.

                          1 Reply Last reply
                          0
                          • S Offline
                            S Offline
                            salwa
                            wrote on last edited by
                            #16

                            @tiho_d
                            Hi Tiho_d
                            could you post the whole code, please?

                            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