Crash on language change caused by auto generated code when using a QTableWidget
-
Hello everybody
I faced a crash on my application when the user tries to change the language. After some investigating I found out that the issue is generated by the auto generated code during the ui'incing process. The behaviour is very easy to reproduce:-
create a QtGuiApplication for desktop and name it QtGuiApplication1
-
On the main form add a QTableWidget and with the designer add some column and some rows with some text inside
-
Add a translation file and translate the text of the rows on the QTableWidget
-
Use the usual code to manage the language change using the QTranlastor class and reimplementing the QtGuiApplication1::changeEvent for the event QEvent::LanguageChange
-
In the method where you call QTranslator::Load and then QApplication::installTranslator bofore doing anything delete the sample rows added in design time
-
In this case inside the auto generated method retranslateUi (inside the file ui_QtGuiApplication1.h) you will will get a crash
-
This is because the code doesn't test if the QTableWidgetItem * is null before trying to translate it
Below my code for QtGuiApplication1 and the auto generated file. I'm using Qt 5.13.0
#include "QtGuiApplication1.h" QTranslator QtGuiApplication1::translator; QtGuiApplication1::QtGuiApplication1(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); connect(ui.pushButtonTranslate, SIGNAL(clicked()), this, SLOT(onTranslate())); inited = false; } void QtGuiApplication1::onTranslate() { if (!inited) { ui.tableWidget->setRowCount(0); inited = true; } QApplication::removeTranslator(&translator); // load the new translator if (translator.load("qtguiapplication1_it.qm", "E:\\Progetti\\QtGuiApplication1\\x64\\Debug")) QApplication::installTranslator(&translator); } void QtGuiApplication1::changeEvent(QEvent* event) { if (event && event->type() == QEvent::LanguageChange) { // retranslate designer form (single inheritance approach) ui.retranslateUi(this); } QWidget::changeEvent(event); }
#pragma once #include <QtWidgets/QMainWindow> #include "ui_QtGuiApplication1.h" #include <QTranslator> class QtGuiApplication1 : public QMainWindow { Q_OBJECT public: QtGuiApplication1(QWidget *parent = Q_NULLPTR); protected slots: virtual void changeEvent(QEvent* event); void onTranslate(); private: bool inited; static QTranslator translator; Ui::QtGuiApplication1Class ui; };
/******************************************************************************** ** Form generated from reading UI file 'QtGuiApplication1.ui' ** ** Created by: Qt User Interface Compiler version 5.13.0 ** ** WARNING! All changes made in this file will be lost when recompiling UI file! ********************************************************************************/ #ifndef UI_QTGUIAPPLICATION1_H #define UI_QTGUIAPPLICATION1_H #include <QtCore/QVariant> #include <QtWidgets/QApplication> #include <QtWidgets/QHeaderView> #include <QtWidgets/QMainWindow> #include <QtWidgets/QMenuBar> #include <QtWidgets/QPushButton> #include <QtWidgets/QStatusBar> #include <QtWidgets/QTableWidget> #include <QtWidgets/QToolBar> #include <QtWidgets/QWidget> QT_BEGIN_NAMESPACE class Ui_QtGuiApplication1Class { public: QWidget *centralWidget; QTableWidget *tableWidget; QPushButton *pushButtonTranslate; QMenuBar *menuBar; QToolBar *mainToolBar; QStatusBar *statusBar; void setupUi(QMainWindow *QtGuiApplication1Class) { if (QtGuiApplication1Class->objectName().isEmpty()) QtGuiApplication1Class->setObjectName(QString::fromUtf8("QtGuiApplication1Class")); QtGuiApplication1Class->resize(600, 519); centralWidget = new QWidget(QtGuiApplication1Class); centralWidget->setObjectName(QString::fromUtf8("centralWidget")); tableWidget = new QTableWidget(centralWidget); if (tableWidget->columnCount() < 6) tableWidget->setColumnCount(6); QTableWidgetItem *__qtablewidgetitem = new QTableWidgetItem(); tableWidget->setHorizontalHeaderItem(0, __qtablewidgetitem); QTableWidgetItem *__qtablewidgetitem1 = new QTableWidgetItem(); tableWidget->setHorizontalHeaderItem(1, __qtablewidgetitem1); QTableWidgetItem *__qtablewidgetitem2 = new QTableWidgetItem(); tableWidget->setHorizontalHeaderItem(2, __qtablewidgetitem2); if (tableWidget->rowCount() < 8) tableWidget->setRowCount(8); QTableWidgetItem *__qtablewidgetitem3 = new QTableWidgetItem(); tableWidget->setVerticalHeaderItem(0, __qtablewidgetitem3); QTableWidgetItem *__qtablewidgetitem4 = new QTableWidgetItem(); tableWidget->setVerticalHeaderItem(1, __qtablewidgetitem4); QTableWidgetItem *__qtablewidgetitem5 = new QTableWidgetItem(); tableWidget->setVerticalHeaderItem(2, __qtablewidgetitem5); QTableWidgetItem *__qtablewidgetitem6 = new QTableWidgetItem(); tableWidget->setItem(0, 0, __qtablewidgetitem6); QTableWidgetItem *__qtablewidgetitem7 = new QTableWidgetItem(); tableWidget->setItem(0, 1, __qtablewidgetitem7); QTableWidgetItem *__qtablewidgetitem8 = new QTableWidgetItem(); tableWidget->setItem(0, 2, __qtablewidgetitem8); QTableWidgetItem *__qtablewidgetitem9 = new QTableWidgetItem(); tableWidget->setItem(1, 0, __qtablewidgetitem9); QTableWidgetItem *__qtablewidgetitem10 = new QTableWidgetItem(); tableWidget->setItem(1, 1, __qtablewidgetitem10); QTableWidgetItem *__qtablewidgetitem11 = new QTableWidgetItem(); tableWidget->setItem(1, 2, __qtablewidgetitem11); QTableWidgetItem *__qtablewidgetitem12 = new QTableWidgetItem(); tableWidget->setItem(2, 0, __qtablewidgetitem12); QTableWidgetItem *__qtablewidgetitem13 = new QTableWidgetItem(); tableWidget->setItem(2, 1, __qtablewidgetitem13); QTableWidgetItem *__qtablewidgetitem14 = new QTableWidgetItem(); tableWidget->setItem(2, 2, __qtablewidgetitem14); tableWidget->setObjectName(QString::fromUtf8("tableWidget")); tableWidget->setGeometry(QRect(40, 10, 531, 301)); tableWidget->setRowCount(8); tableWidget->setColumnCount(6); pushButtonTranslate = new QPushButton(centralWidget); pushButtonTranslate->setObjectName(QString::fromUtf8("pushButtonTranslate")); pushButtonTranslate->setGeometry(QRect(40, 340, 161, 61)); QtGuiApplication1Class->setCentralWidget(centralWidget); menuBar = new QMenuBar(QtGuiApplication1Class); menuBar->setObjectName(QString::fromUtf8("menuBar")); menuBar->setGeometry(QRect(0, 0, 600, 21)); QtGuiApplication1Class->setMenuBar(menuBar); mainToolBar = new QToolBar(QtGuiApplication1Class); mainToolBar->setObjectName(QString::fromUtf8("mainToolBar")); QtGuiApplication1Class->addToolBar(Qt::TopToolBarArea, mainToolBar); statusBar = new QStatusBar(QtGuiApplication1Class); statusBar->setObjectName(QString::fromUtf8("statusBar")); QtGuiApplication1Class->setStatusBar(statusBar); retranslateUi(QtGuiApplication1Class); QMetaObject::connectSlotsByName(QtGuiApplication1Class); } // setupUi void retranslateUi(QMainWindow *QtGuiApplication1Class) { QtGuiApplication1Class->setWindowTitle(QCoreApplication::translate("QtGuiApplication1Class", "QtGuiApplication1", nullptr)); QTableWidgetItem *___qtablewidgetitem = tableWidget->horizontalHeaderItem(0); ___qtablewidgetitem->setText(QCoreApplication::translate("QtGuiApplication1Class", "col 1", nullptr)); QTableWidgetItem *___qtablewidgetitem1 = tableWidget->horizontalHeaderItem(1); ___qtablewidgetitem1->setText(QCoreApplication::translate("QtGuiApplication1Class", "col2", nullptr)); QTableWidgetItem *___qtablewidgetitem2 = tableWidget->horizontalHeaderItem(2); ___qtablewidgetitem2->setText(QCoreApplication::translate("QtGuiApplication1Class", "col3", nullptr)); QTableWidgetItem *___qtablewidgetitem3 = tableWidget->verticalHeaderItem(0); ___qtablewidgetitem3->setText(QCoreApplication::translate("QtGuiApplication1Class", "New Row", nullptr)); QTableWidgetItem *___qtablewidgetitem4 = tableWidget->verticalHeaderItem(1); ___qtablewidgetitem4->setText(QCoreApplication::translate("QtGuiApplication1Class", "New Row", nullptr)); QTableWidgetItem *___qtablewidgetitem5 = tableWidget->verticalHeaderItem(2); ___qtablewidgetitem5->setText(QCoreApplication::translate("QtGuiApplication1Class", "New Row", nullptr)); const bool __sortingEnabled = tableWidget->isSortingEnabled(); tableWidget->setSortingEnabled(false); QTableWidgetItem *___qtablewidgetitem6 = tableWidget->item(0, 0); ___qtablewidgetitem6->setText(QCoreApplication::translate("QtGuiApplication1Class", "aaaa", nullptr)); QTableWidgetItem *___qtablewidgetitem7 = tableWidget->item(0, 1); ___qtablewidgetitem7->setText(QCoreApplication::translate("QtGuiApplication1Class", "aaaa", nullptr)); QTableWidgetItem *___qtablewidgetitem8 = tableWidget->item(0, 2); ___qtablewidgetitem8->setText(QCoreApplication::translate("QtGuiApplication1Class", "aaaa", nullptr)); QTableWidgetItem *___qtablewidgetitem9 = tableWidget->item(1, 0); ___qtablewidgetitem9->setText(QCoreApplication::translate("QtGuiApplication1Class", "bbbb", nullptr)); QTableWidgetItem *___qtablewidgetitem10 = tableWidget->item(1, 1); ___qtablewidgetitem10->setText(QCoreApplication::translate("QtGuiApplication1Class", "bbbb", nullptr)); QTableWidgetItem *___qtablewidgetitem11 = tableWidget->item(1, 2); ___qtablewidgetitem11->setText(QCoreApplication::translate("QtGuiApplication1Class", "bbbb", nullptr)); QTableWidgetItem *___qtablewidgetitem12 = tableWidget->item(2, 0); ___qtablewidgetitem12->setText(QCoreApplication::translate("QtGuiApplication1Class", "cccc", nullptr)); QTableWidgetItem *___qtablewidgetitem13 = tableWidget->item(2, 1); ___qtablewidgetitem13->setText(QCoreApplication::translate("QtGuiApplication1Class", "cccc", nullptr)); QTableWidgetItem *___qtablewidgetitem14 = tableWidget->item(2, 2); ___qtablewidgetitem14->setText(QCoreApplication::translate("QtGuiApplication1Class", "cccc", nullptr)); tableWidget->setSortingEnabled(__sortingEnabled); pushButtonTranslate->setText(QCoreApplication::translate("QtGuiApplication1Class", "Translate", nullptr)); } // retranslateUi }; namespace Ui { class QtGuiApplication1Class: public Ui_QtGuiApplication1Class {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_QTGUIAPPLICATION1_H
-
-
Hi
And if you in the process,
completely delete ui_QtGuiApplication1.h
and rebuild build all ?It sounds like some code left overs.
"This is because the code doesn't test if the QTableWidgetItem * "
Why would it be NULL ?
If you delete from the UI (visually) that code should no longer be there.