Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-3319

Erratic return value QAbstractTextDocumentLayout::documentSize ()

    XMLWordPrintable

Details

    Description

      QAbstractTextDocumentLayout::documentSize() will return an an erratic range of sizes even when document is not being changed. This can be demonstrated by running the following example:

      By entering some text at about 10 letters or more in the bottom window it will start returning incorrect size values.

      ///////////////////////////////////////////////////////////////////////////////
      // ElasticTextEdit decl //
      ///////////////////////////////////////////////////////////////////////////////

      #include <QtGui/QTextEdit>
      #include <QDebug>

      /**

      • This is a subclass of QTextEdit that changes its preferred height
      • as a function of its width and the text it contains. It's otherwise
      • the same as QTextEdit.
        */

      class ElasticTextEdit : public QTextEdit {
      Q_OBJECT

      public:
      ElasticTextEdit(QWidget* parent = 0);
      ElasticTextEdit(const QString& text, QWidget* parent = 0);
      ~ElasticTextEdit();

      // QWidget overrides
      int heightForWidth(int width) const;
      QSize sizeHint() const;

      public slots:
      // private
      void heightForWidthMayHaveChanged();
      } ;

      ///////////////////////////////////////////////////////////////////////////////
      // ElasticTextEdit impl //
      ///////////////////////////////////////////////////////////////////////////////

      #include <QtGui/QAbstractTextDocumentLayout>
      #include <QtGui/QSizePolicy>

      ElasticTextEdit::ElasticTextEdit(QWidget* parent)
      : QTextEdit(parent) {
      // Make hasHeightForWidth be enabled by default
      QSizePolicy policy(sizePolicy());
      policy.setHeightForWidth(true);
      setSizePolicy(policy);

      connect(this, SIGNAL(textChanged()),
      this, SLOT(heightForWidthMayHaveChanged()));
      }

      ElasticTextEdit::ElasticTextEdit(const QString& text, QWidget* parent)
      : QTextEdit(text, parent) {
      }

      ElasticTextEdit::~ElasticTextEdit() {
      }

      int
      ElasticTextEdit::heightForWidth(int width) const {
      QTextDocument* doc = document();
      qreal savedWidth = doc->textWidth();

      // Fudge factor. This is supposed to be the difference between the
      // height of the widget and the height of the area where the text is
      // actually drawn. I don't know how to get it exactly.
      int fudge = 2;

      // Do the calculation assuming no scrollbars
      doc->setTextWidth(width);
      int noScrollbarHeight =
      doc->documentLayout()->documentSize().height() + fudge;
      qDebug() << "h: " << doc->documentLayout()->documentSize().height();
      qDebug() << "w: " << doc->documentLayout()->documentSize().width();

      // (If noScrollbarHeight is greater than the maximum height we'll be
      // allowed, then there will be scrollbars, and the actual required
      // height will be even higher. But since in this case we've already
      // hit the maximum height, it doesn't matter that we underestimate.)

      // Get minimum height (even if string is empty): one line of text
      int minimumHeight = QFontMetrics(doc->defaultFont()).lineSpacing() + fudge;
      int ret = qMax(noScrollbarHeight, minimumHeight);

      doc->setTextWidth(savedWidth);
      return ret;
      }

      QSize
      ElasticTextEdit::sizeHint() const {
      QSize size = QTextEdit::sizeHint();
      if (size.width() == 0)
      size.setWidth(400); // arbitrary value
      size.setHeight(heightForWidth(size.width()));
      return size;
      }

      void
      ElasticTextEdit::heightForWidthMayHaveChanged() {
      updateGeometry();
      }

      ///////////////////////////////////////////////////////////////////////////////
      // test //
      ///////////////////////////////////////////////////////////////////////////////

      #include <QtGui/QApplication>
      #include <QtGui/QSizePolicy>
      #include <QtGui/QTextEdit>
      #include <QtGui/QVBoxLayout>

      class Demo : public QWidget {
      public:
      Demo(QWidget* parent = 0);
      } ;

      Demo::Demo(QWidget* parent)
      : QWidget(parent) {
      QVBoxLayout* verticalLayout = new QVBoxLayout(this);

      QTextEdit* top = new QTextEdit(this);
      QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      sizePolicy.setHorizontalStretch(0);
      sizePolicy.setVerticalStretch(0);
      sizePolicy.setHeightForWidth(top->sizePolicy().hasHeightForWidth());
      top->setSizePolicy(sizePolicy);
      top->setMinimumSize(QSize(0, 50));
      verticalLayout->addWidget(top);

      ElasticTextEdit* bottom = new ElasticTextEdit(this);
      QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Preferred);
      sizePolicy1.setHorizontalStretch(0);
      sizePolicy1.setVerticalStretch(0);
      sizePolicy1.setHeightForWidth(bottom->sizePolicy().hasHeightForWidth());
      bottom->setSizePolicy(sizePolicy1);
      verticalLayout->addWidget(bottom);
      }

      #include "main.moc"

      int main(int argc, char *argv[]) {
      QApplication app(argc, argv);

      Demo demo;
      demo.show();

      return app.exec();
      }

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            sletta Gunnar Sletta
            janichol Andy Nichols
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes