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
QtWS25 Last Chance

Global image position inside a QTextEdit

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

    Hi.
    I'm working on a WYSIWYG-Editor which contain images and Text. Now I want to resize an image through the mouse. Through the QTextImageFormat i can resize my image. To solve the task i need the global position of an image-edge. Does anybody can help me find thuch a global position?

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

      Is "QCursor::pos() ":http://doc.qt.nokia.com/4.7/qcursor.html#pos what you need? Maybe you'll have to use "QWidget::mapFromGlobal() ":http://doc.qt.nokia.com/4.7/qwidget.html#mapFromGlobal to translate between global and widget-local coordinates.

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

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

        no. QCursor::pos() is the mouse position. I need the position of my image insiede the QTextEdit. Hopefully in some screen position. At the moment i only get the position in my QTextDocument, but thats only the positon of the x char in my document.

        1 Reply Last reply
        0
        • 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