You can subclass QTextEdit and listen for changes in the document size using document()->size() (not the size of the QTextEdit, mind). You can then resize the QTextEdit's parent to reflect the new size. To fill the parent with the widget, use a layout. I've used QVBoxLayout several times below for this purpose. (One, to hold multiple QTextEdit widgets in a vertical column; Two, to hold a single TextEdit).
#include <QtCore>
#include <QtWidgets>
class DyTextEdit : public QTextEdit
{
Q_OBJECT
public:
DyTextEdit(QWidget *parent = nullptr) :
QTextEdit(parent)
{
QTextDocument *doc = document();
currentSize = doc->size();
qDebug() << "[Init] Size:" << currentSize;
// listen to text/content changes
connect(this, &QTextEdit::textChanged, this, &DyTextEdit::on_textChanged);
// connect <> 💡
connect(this, &DyTextEdit::sizeChanged, this, &DyTextEdit::resizeParent);
doc->setTextWidth(-1);
emit sizeChanged(currentSize); // init
}
signals:
// emitted when document size changes
void sizeChanged(QSizeF size);
public slots:
void on_textChanged()
{
QSizeF newSize = document()->size();
qDebug() << "[TextChanged] Size:" << newSize;
// detect changes in the document size
if (newSize != currentSize)
emit sizeChanged(newSize); // emit signal💡
// update size
currentSize = newSize;
}
void resizeParent(QSizeF size)
{
// resize the parent's height, don't bother with the width
parentWidget()->setFixedHeight(size.height());
}
private:
QSizeF currentSize; // keeps track of current document size
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// holds all dytextedits
QWidget aggregateWidget;
QVBoxLayout aggregateLayout(&aggregateWidget);
// note: for scalability, use a QList (or QLists)
// first textbox
QWidget widget;
QVBoxLayout vbLayout(&widget);
vbLayout.setMargin(0);
DyTextEdit dytext(&widget);
vbLayout.addWidget(&dytext);
// first button row
QHBoxLayout hbLayout(&widget);
hbLayout.setMargin(0);
QPushButton pb1a("Push this.", &widget);
hbLayout.addWidget(&pb1a);
QPushButton pb1b("Push this.", &widget);
hbLayout.addWidget(&pb1b);
// second textbox
QWidget widget2;
QVBoxLayout vbLayout2(&widget2);
vbLayout2.setMargin(0);
DyTextEdit dytext2(&widget2);
vbLayout2.addWidget(&dytext2);
// second button row
QHBoxLayout hbLayout2(&widget2);
hbLayout2.setMargin(0);
QPushButton pb2a("Push this.", &widget2);
hbLayout2.addWidget(&pb2a);
QPushButton pb2b("Push this.", &widget2);
hbLayout2.addWidget(&pb2b);
// add widgets to layout
aggregateLayout.addWidget(&widget); // cell 1
aggregateLayout.addLayout(&hbLayout); // |
aggregateLayout.addWidget(&widget2); // cell 2
aggregateLayout.addLayout(&hbLayout2); // |
aggregateLayout.setSizeConstraint(QLayout::SetMinAndMaxSize);
aggregateWidget.show();
return a.exec();
}
#include "main.moc" // include if there are QObject classes in main.cpp
Note that above, I've used rows of buttons using QHBoxLayout and added them to the overall, aggregate layout detached from the textbox widgets. You can still use a say, QGridLayout if you wish to set your buttons in a different format. You can also combine the textedits and button layouts as children under another widget (to serve as an umbrella) covering both. That would more clearly form a cell of widget and may be easier to move around. (I've uploaded a workable example of this on Github.)
Demo (macOS):
This is a screenshot of after typing content and copy-pasting content.

Note that the aggregate widget will contract on removal of lines of text.