Results 1 to 8 of 8

Thread: Some errors if I don't click on QMessageBox button

  1. #1
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Some errors if I don't click on QMessageBox button

    Hi,
    first of all sorry if I report in a new thread a question made in this discussion but the problem not seems strictly related to that particular case. The problems shows when I don't click any button in QMessageBox asking if install (in the sample code a simple QFile::copy()) a downloaded file: in this case pops up the same dialog because is emitted a new QHTTP::requestFinished() signal. If then I click ok/cancel on these QMessageBoxes I got segmentation fault and/or

    ASSERT: "!isEmpty()" in file ../../include/QtCore/../../src/corelib/tools/qlist.h, line 248
    If I click on the confirmation massage without pausing or remove the qmessagebox and install just after downloading no errors are reported.

    Test yourself this code (sorry if no so minimal):

    Qt Code:
    1. #include <QApplication>
    2. #include <QDialog>
    3. #include <QtGui>
    4. #include <QtNetwork>
    5.  
    6. #include <iostream>
    7.  
    8. class Dialog: public QDialog
    9. {
    10. Q_OBJECT
    11.  
    12. public:
    13. Dialog(QWidget *parent = 0);
    14.  
    15. private slots:
    16. void httpRequestFinished(int requestId, bool error);
    17. void updateDataReadProgress(int bytesRead, int totalBytes);
    18. void readResponseHeader(const QHttpResponseHeader &responseHeader);
    19. void cancelDownload();
    20. void downloadFile();
    21.  
    22. private:
    23. QString fileName;
    24. QFile *file;
    25. QPushButton *downloadButton;
    26. QPushButton *closeButton;
    27. QProgressDialog *progressDialog;
    28. QHttp *http;
    29. int httpGetId;
    30. QDir dir;
    31. bool httpRequestAborted;
    32. void installFile();
    33. };
    34.  
    35. Dialog::Dialog(QWidget *parent)
    36. : QDialog(parent)
    37. {
    38. downloadButton = new QPushButton("Download");
    39. closeButton = new QPushButton("Close");
    40.  
    41. QHBoxLayout *buttonsLayout = new QHBoxLayout;
    42. buttonsLayout->addStretch();
    43. buttonsLayout->addWidget(downloadButton);
    44. buttonsLayout->addWidget(closeButton);
    45. buttonsLayout->addStretch();
    46.  
    47. setLayout(buttonsLayout);
    48.  
    49. connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
    50. connect(downloadButton, SIGNAL(clicked()), this, SLOT(downloadFile()));
    51.  
    52. progressDialog = new QProgressDialog(this);
    53. http = new QHttp(this);
    54.  
    55. connect(http, SIGNAL(requestFinished(int, bool)),
    56. this, SLOT(httpRequestFinished(int, bool)));
    57. connect(http, SIGNAL(dataReadProgress(int, int)),
    58. this, SLOT(updateDataReadProgress(int, int)));
    59. connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
    60. this, SLOT(readResponseHeader(const QHttpResponseHeader &)));
    61. connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelDownload()));
    62. }
    63.  
    64. void Dialog::downloadFile()
    65. {
    66. QUrl url("http://www.nih.at/libzip/index.html");
    67. QFileInfo fileInfo(url.path());
    68. QString fileName;
    69. fileName = QDir::tempPath() + fileInfo.fileName();
    70.  
    71. if (QFile::exists(fileName)) {
    72. if (QMessageBox::question(this,
    73. tr("HTTP"),
    74. trUtf8("There already exists a file called %1 in the current directory. Overwrite?")
    75. .arg(fileName),
    76. QMessageBox::Ok|QMessageBox::Cancel, QMessageBox::Cancel)
    77. == QMessageBox::Cancel)
    78. return;
    79. QFile::remove(fileName);
    80. }
    81. file = new QFile(fileName);
    82. if (!file->open(QIODevice::WriteOnly)) {
    83. QMessageBox::information(this,
    84. tr("HTTP"),
    85. trUtf8("Impossibile salvare il file %1: %2.")
    86. .arg(fileName).arg(file->errorString()));
    87. delete file;
    88. file = 0;
    89. return;
    90. }
    91. QHttp::ConnectionMode mode = url.scheme().toLower() == "https" ? QHttp::ConnectionModeHttps : QHttp::ConnectionModeHttp;
    92. http->setHost(url.host(), mode, url.port() == -1 ? 0 : url.port());
    93.  
    94. httpRequestAborted = false;
    95. httpGetId = http->get(url.path(), file);
    96.  
    97. progressDialog->setWindowTitle(tr("HTTP"));
    98. progressDialog->setLabelText(tr("Downloading %1.").arg(fileName));
    99. downloadButton->setEnabled(false);
    100. }
    101.  
    102. void Dialog::cancelDownload()
    103. {
    104. httpRequestAborted = true;
    105. http->abort();
    106. downloadButton->setEnabled(true);
    107. }
    108.  
    109. void Dialog::httpRequestFinished(int requestId, bool error)
    110. {
    111. std::cout << "httpRequestFinished()" << std::endl;
    112. if (requestId != httpGetId)
    113. return;
    114. if (httpRequestAborted) {
    115. if (file) {
    116. file->close();
    117. file->remove();
    118. delete file;
    119. file = 0;
    120. }
    121.  
    122. progressDialog->hide();
    123. return;
    124. }
    125.  
    126. if (requestId != httpGetId)
    127. return;
    128.  
    129. progressDialog->hide();
    130. file->close();
    131.  
    132. if (error) {
    133. file->remove();
    134. QMessageBox::information(this,
    135. tr("HTTP"),
    136. trUtf8("Download failed: %1.")
    137. .arg(http->errorString()));
    138. } else
    139. installFile();
    140.  
    141. delete file;
    142. file = 0;
    143. }
    144.  
    145. void Dialog::readResponseHeader(const QHttpResponseHeader &responseHeader)
    146. {
    147. if (responseHeader.statusCode() != 200) {
    148. QMessageBox::information(this,
    149. tr("HTTP"),
    150. trUtf8("Download failed: %1.").
    151. arg(responseHeader.reasonPhrase()));
    152. httpRequestAborted = true;
    153. progressDialog->hide();
    154. http->abort();
    155. return;
    156. }
    157. }
    158.  
    159. void Dialog::updateDataReadProgress(int bytesRead, int totalBytes)
    160. {
    161. if (httpRequestAborted)
    162. return;
    163.  
    164. progressDialog->setMaximum(totalBytes);
    165. progressDialog->setValue(bytesRead);
    166. }
    167.  
    168. void Dialog::installFile()
    169. {
    170. if (QMessageBox::question(this,
    171. tr("Ready"),
    172. trUtf8("If you don't click me quickly\nI will make some unwanted thing."),
    173. QMessageBox::Ok|QMessageBox::Cancel, QMessageBox::Cancel)
    174. == QMessageBox::Ok) {
    175. QString fileName;
    176. QFileInfo fi(file->fileName());
    177. fileName = fi.fileName();
    178. file->copy(QDir::tempPath() + "copied-index.html");
    179. }
    180. downloadButton->setEnabled(true);
    181. }
    182.  
    183. int main(int argc, char *argv[])
    184. {
    185. QApplication app(argc,argv);
    186. Dialog *dialog = new Dialog;
    187. dialog->show();
    188. return app.exec();
    189. }
    190.  
    191. #include "main.moc"
    To copy to clipboard, switch view to plain text mode 
    Giuseppe CalÃ

  2. #2
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Some errors if I don't click on QMessageBox button

    I recall seeing this bug but I couldn't find it on Task-Tracker. The problem is that QHttp::requestFinished() is emitted twice when the slot starts an event loop (a modal message box in your case). Here's a minimal compilable example reproducing the problem:
    Qt Code:
    1. #include <QtCore>
    2. #include <QtNetwork>
    3.  
    4. class Downloader : public QHttp
    5. {
    6. Q_OBJECT
    7. public:
    8. Downloader()
    9. {
    10. connect(this, SIGNAL(requestFinished(int,bool)), this, SLOT(onRequestFinished(int,bool)));
    11. }
    12.  
    13. private slots:
    14. void onRequestFinished(int id, bool error)
    15. {
    16. qDebug() << "Downloader::requestFinished()" << id << error;
    17. if (id == 2)
    18. {
    19. // start an event loop when "get" request is finished
    20. // NOTICE: "Downloader::requestFinished() 2 false" is printed twice
    21. QEventLoop eventLoop;
    22. eventLoop.exec();
    23. }
    24. }
    25. };
    26.  
    27. int main(int argc, char* argv[])
    28. {
    29. QCoreApplication app(argc, argv);
    30. Downloader downloader;
    31. downloader.setHost("www.trolltech.com"); // id == 1
    32. downloader.get("/index.html"); // id == 2
    33. return app.exec();
    34. }
    35.  
    36. #include "main.moc"
    To copy to clipboard, switch view to plain text mode 
    J-P Nurmi

  3. #3
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Some errors if I don't click on QMessageBox button

    Quote Originally Posted by jpn View Post
    I recall seeing this bug but I couldn't find it on Task-Tracker.
    This means that the updater has to install new files soon after downloading them, quitting the mainapp without warnings and without let the user finish its work. Very bad solution.

    Thanks
    Giuseppe CalÃ

  4. #4
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Some errors if I don't click on QMessageBox button

    Quote Originally Posted by jiveaxe View Post
    This means that the updater has to install new files soon after downloading them, quitting the mainapp without warnings and without let the user finish its work. Very bad solution.
    Don't you notice how two message boxes appear on top of each other? Just add a proper check to work it around...
    J-P Nurmi

  5. #5
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Some errors if I don't click on QMessageBox button

    Quote Originally Posted by jpn View Post
    Don't you notice how two message boxes appear on top of each other? Just add a proper check to work it around...
    I have naively admit I don't undertand your tip; if you mean putting a control for avoiding the second messabox appear I have already tryed in this manner: I have created a bool installationPending which is set to true when the installFile() member is called and this bool is tested at the beginning of Dialog::httpRequestFinished(): the first time this bool is false so all the code of httpRequestFinished() is executed until calling installFile() which sets to true installationPending; so when QHttp::requestFinished() is emittend for the second time the code inside httpRequestFinished() is ignored, so no extra messagebox, but when I click "Ok" I got the usual:

    ASSERT: "!isEmpty()" in file ../../include/QtCore/../../src/corelib/tools/qlist.h, line 248
    Aborted (core dumped)
    The real problem is not the second messagebox itself but the bug you talk about and the only solution seems to be or click "Ok" quite soon or make it install automatically without prompting.

    Regards
    Giuseppe CalÃ

  6. #6
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Some errors if I don't click on QMessageBox button

    A quick and dirty fix is to make installFile() a slot and in httpRequestFinished() invoke the slot with help of timer (to allow control to return to QHttp, where the signal was emitted from):
    Qt Code:
    1. if (error) {
    2. ...
    3. } else {
    4. //installFile();
    5. QTimer::singleShot(0, this, SLOT(installFile()));
    6. }
    7.  
    8. //delete file;
    9. //file = 0;
    To copy to clipboard, switch view to plain text mode 
    Notice also that you can't either delete the file here because you will later use it in installFile().
    J-P Nurmi

  7. #7
    Join Date
    Feb 2006
    Location
    Oslo, Norway
    Posts
    6,264
    Thanks
    36
    Thanked 1,519 Times in 1,389 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Some errors if I don't click on QMessageBox button

    Yet another (easier and more elegant) way would be to simply force a queued connection:
    Qt Code:
    1. connect(http, SIGNAL(requestFinished(int, bool)),
    2. this, SLOT(httpRequestFinished(int, bool)), Qt::QueuedConnection);
    To copy to clipboard, switch view to plain text mode 
    In this case you wouldn't need modifications represented in my last message.
    J-P Nurmi

  8. The following 2 users say thank you to jpn for this useful post:

    jiveaxe (23rd January 2008), sgmurphy19 (3rd October 2008)

  9. #8
    Join Date
    Aug 2007
    Posts
    244
    Thanks
    42
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Some errors if I don't click on QMessageBox button

    Great code, jpn. Now the program runs very fine.

    A thousand thanks.
    Giuseppe CalÃ

Similar Threads

  1. Set up the Qt4.3.2 with Visual Studio 2005
    By lamoda in forum Installation and Deployment
    Replies: 6
    Last Post: 30th January 2008, 06:51
  2. QPaintEvent on button click?
    By vishal.chauhan in forum Qt Programming
    Replies: 1
    Last Post: 5th June 2007, 08:44
  3. change font size and button size of QMessageBox
    By nass in forum Qt Programming
    Replies: 6
    Last Post: 13th September 2006, 19:16
  4. get button on QMessageBox
    By manhds in forum Qt Programming
    Replies: 3
    Last Post: 27th June 2006, 04:38
  5. Push button double click
    By curtisw in forum Qt Programming
    Replies: 3
    Last Post: 15th February 2006, 16:40

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.