Results 1 to 20 of 21

Thread: Add "Check for updates" feature

Hybrid View

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

    Default Re: Add "Check for updates" feature

    I have just started and now the first problem.

    I got a segmentation fault with this code:

    Qt Code:
    1. ...
    2. if(!file.open()) {
    3. ...
    4. }
    5.  
    6. QUrl url("http://localhost/mysite");
    7. http = new QHttp;
    8. http->setHost(url.host(), url.port(80));
    9. http->get("/lastrelease.xml", &file);
    10. http->close();
    To copy to clipboard, switch view to plain text mode 

    If I comment http->get no more error. The temporary file is created with this path: /tmp//qt_temp.xxxx . Is it normal the double '/' ?

    Before somebody asks me, the local server is running and http://localhost/mysite/lastrelease.xml exists.

    If I use QFile instead of QTemporaryFile:
    Qt Code:
    1. QFile file("/tmp/lastrelease.xml");
    2. if(!file.open(QIODevice::ReadWrite)){...}
    To copy to clipboard, switch view to plain text mode 

    I have no segmentation fault at all but the file created in /tmp is empty. In the console I have this line:
    QIODevice::write: ReadOnly device
    Where is the mistake?

    Thanks
    Giuseppe CalÃ

  2. #2
    Join Date
    Nov 2007
    Posts
    89
    Qt products
    Qt4
    Platforms
    Windows
    Thanked 21 Times in 18 Posts

    Default Re: Add "Check for updates" feature

    Qt Code:
    1. ...
    2. if(!file.open()) {
    3. ...
    4. }
    5.  
    6. QUrl url("http://localhost/mysite");
    7. http = new QHttp;
    8. http->setHost(url.host(), url.port(80));
    9. http->get("/lastrelease.xml", &file);
    10. http->close();
    To copy to clipboard, switch view to plain text mode 

    I think it should be:
    Qt Code:
    1. http->setHost("localhost");
    2. http->get("/mysite/lastrelease.xml");
    To copy to clipboard, switch view to plain text mode 


    The temporary file is created with this path: /tmp//qt_temp.xxxx . Is it normal the double '/' ?
    Multiple / are ignored. You can check with ls /usr////src or similar.


    QIODevice::write: ReadOnly device
    Is /tmp writable? Try another directory (like $HOME).

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

    Default Re: Add "Check for updates" feature

    Quote Originally Posted by bender86 View Post
    [CODE]...
    I think it should be:
    Qt Code:
    1. http->setHost("localhost");
    2. http->get("/mysite/lastrelease.xml");
    To copy to clipboard, switch view to plain text mode 
    It gives the same problem.

    I have also tried to get some page from the remote site, but nothing changes. Using QTemporaryFile gives the segmentation fault; with QFile an empty output.

    Try this:

    Qt Code:
    1. if(!file.open()) {
    2. QMessageBox::critical(0,QString(),tr("Can't open the file!"));
    3. }
    4.  
    5. QUrl url("http://www.bzip.org");
    6. http = new QHttp;
    7. http->setHost(url.host(), url.port(80));
    8. http->get("/docs.html", &file);
    9. http->close();
    To copy to clipboard, switch view to plain text mode 

    or this:

    Qt Code:
    1. QFile file("/tmp/output.html");
    2. if(!file.open(QIODevice::ReadWrite)) {
    3. QMessageBox::critical(0,QString(),tr("Can't open the file!"));
    4. }
    5.  
    6. QUrl url("http://www.bzip.org");
    7. http = new QHttp;
    8. http->setHost(url.host(), url.port(80));
    9. http->get("/docs.html", &file);
    10. http->close();
    To copy to clipboard, switch view to plain text mode 

    Quote Originally Posted by bender86 View Post
    Is /tmp writable? Try another directory (like $HOME).
    Of course /tmp is writable.

    Regards
    Giuseppe CalÃ

  4. #4
    Join Date
    Nov 2007
    Posts
    89
    Qt products
    Qt4
    Platforms
    Windows
    Thanked 21 Times in 18 Posts

    Default Re: Add "Check for updates" feature

    You have to close the QFile after writing into.
    You can catch QHttp::dataReadProgress(int done, int total). If done == total, then download is complete, and you can close file (you will need an event loop, so call QCoreApplication::exec()).
    Check also QHttp example.

    For QTemporaryFile, keep in mind that if you create it on stack, it will be destroyed when gone out of scope (usually after a }). If you pass his address to http.get("/file",&tempFile), QHttp will try to write to a invalid address.

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

    Default Re: Add "Check for updates" feature

    Quote Originally Posted by bender86 View Post
    Check also QHttp example.
    I give it a try.

    Quote Originally Posted by bender86 View Post
    For QTemporaryFile, keep in mind that if you create it on stack, it will be destroyed when gone out of scope (usually after a }). If you pass his address to http.get("/file",&tempFile), QHttp will try to write to a invalid address.
    As I wrote in my previous code QTemporaryFile should be in the same scope of http.

    Bye
    Giuseppe CalÃ

  6. #6
    Join Date
    Nov 2007
    Posts
    89
    Qt products
    Qt4
    Platforms
    Windows
    Thanked 21 Times in 18 Posts

    Default Re: Add "Check for updates" feature

    Quote Originally Posted by jiveaxe View Post
    As I wrote in my previous code QTemporaryFile should be in the same scope of http.
    QHttp::get() is asynchronous. If you do something like this:
    Qt Code:
    1. void f() {
    2. temp.open();
    3. QHttp *http = new QHttp;
    4. http->setHost("localhost");
    5. http->get("/file",&file);
    6. }
    To copy to clipboard, switch view to plain text mode 
    QHttp::get returns immediately, before actually download file. http is a heap allocated object, so it survives at and of f(), but file not, and is destroyed. When http obtains file from webserver, tries to write to an invalid location (because file is no longer existant).
    You should declare both QHttp and QTemporaryFile as pointers and create their instances with new, and catch QHttp signal to know when http request is finished. However QHttp example explains well.

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

    Default Re: Add "Check for updates" feature

    Finally I have made a working code; if It may help somebody else here it is:

    Qt Code:
    1. MainWindow::MainWindow()
    2. {
    3. ...
    4. http = new QHttp(this);
    5. connect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(httpRequestFinished(int, bool)));
    6. connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)), this, SLOT(readResponseHeader(const QHttpResponseHeader &)));
    7.  
    8. file = 0;
    9. downloadFile();
    10. }
    11.  
    12. MainWindow::~MainWindow()
    13. {
    14. if(file) {
    15. delete file;
    16. file = 0;
    17. }
    18. }
    19.  
    20. void MainWindow::downloadFile()
    21. {
    22. if(file) {
    23. delete file;
    24. file = 0;
    25. }
    26.  
    27. QUrl url("http://localhost/sito/lastrelease.xml");
    28.  
    29. file = new QTemporaryFile;
    30. if (!file->open()) {
    31. statusBar()->showMessage(tr("Impossible to save the file %1: %2.").arg(file->fileName()).arg(file->errorString()));
    32. delete file;
    33. file = 0;
    34. return;
    35. }
    36.  
    37. http->setHost(url.host(), url.port(80));
    38.  
    39. httpRequestAborted = false;
    40. httpGetId = http->get(url.path(), file);
    41. }
    42.  
    43. void MainWindow::httpRequestFinished(int requestId, bool error)
    44. {
    45. if (requestId != httpGetId)
    46. return;
    47. if (httpRequestAborted) {
    48. if(file) {
    49. file->close();
    50. file->remove();
    51. }
    52. return;
    53. }
    54.  
    55. if (requestId != httpGetId)
    56. return;
    57.  
    58. file->close();
    59.  
    60. if (error) {
    61. file->remove();
    62. statusBar()->showMessage(tr("Download failed: %1.").arg(http->errorString()));
    63. } else {
    64. statusBar()->showMessage(tr("lastrelease downloaded"));
    65. }
    66. }
    67.  
    68. void MainWindow::readResponseHeader(const QHttpResponseHeader &responseHeader)
    69. {
    70. if (responseHeader.statusCode() != 200) {
    71. statusBar()->showMessage(tr("Download failed: %1.").arg(responseHeader.reasonPhrase()));
    72. httpRequestAborted = true;
    73. http->abort();
    74. return;
    75. }
    76. }
    To copy to clipboard, switch view to plain text mode 

    Also the xml part of the work is ok. I have to decide where store the current versions of application/database: for application probably is better in the code for simple retrieving; for database I don't know if is better to store it in a table or in the name of the db file (db-20070115 for example). Perhaps the first solution is simpler. What do you say?

    Thanks
    Giuseppe CalÃ

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

    Default Re: Add "Check for updates" feature

    Hi,
    I have choosen to store database version on one table of the db itself. Now I have to work on compressed archive for distributing the updates. I have found an interesting article on qtnode about Self-Extracting Installer. It seems what I was looking for but I haven't well understand the usage. My update package should contain a sqlite file (appdb for example) and a folder containing some images. Can I store all of this as they are or Self-Extracting_Installer can stores only files and not folders? In the latter case after extracting the qcompress archive I should do something like this:

    cp appdb QDir::homePath() + QDir::separator() + ".appname";
    cp *.png QDir::homePath() + QDir::separator() + ".appname/images";
    Am I right?

    One more question: which extension should have the final package?

    Thanks

    EDIT:
    Ok, ok; with some trying I have understand the usage. The files must be appended to stub (which is an executable): so the final package is an executable (and in windows should have .exe exention). Regards paths, when a file is stored, it is stored even the path given during compression, so

    qcompress images/image1.png update-20080116
    qcompress appdb update-20080116
    gives during decompression the following files:

    appdb
    images/image1.png
    Than I can move all together

    cp -r * QDir::homePath + QDir::separator + ".appname/";
    Regards
    Last edited by jiveaxe; 16th January 2008 at 09:17.
    Giuseppe CalÃ

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

    Default Re: Add "Check for updates" feature

    I diverted on QuaZIP a qt widget for accessing zip files.

    Bye
    Giuseppe CalÃ

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

    Default Re: Add "Check for updates" feature

    I have a new problem with an undesidered requestFinished signal. For clearness I list here the steps of the code section:

    1: Click download button

    2: http->get(...);

    (when requestFinished(...) signal is emitted)

    3: QMessageBox: Need to quit MainApp before install

    (if OK)

    4: quit MainApp

    5: install new files

    6: QMessageBox: now restart MainApp and quit updater

    (if OK)

    7: updater closed and MainApp restarted
    If I follow the steps without pause the code works good but if I don't click any button on the QMessageBox at step 6 after 10-15 seconds is emitted a new requestFinished signal and the QMessageBox of the step 3 pops up while that at step 6 is still running.

    Here the code:

    Qt Code:
    1. void Updater::httpRequestFinished(int requestId, bool error)
    2. {
    3. if (requestId != httpGetId)
    4. return;
    5. if (httpRequestAborted) {
    6. if (file) {
    7. file->close();
    8. file->remove();
    9. delete file;
    10. file = 0;
    11. }
    12.  
    13. progressDialog->hide();
    14. return;
    15. }
    16.  
    17. progressDialog->hide();
    18. file->close();
    19.  
    20. if (error) {
    21. file->remove();
    22. QMessageBox::information(this, tr("HTTP"),
    23. trUtf8("Download failed: %1.")
    24. .arg(http->errorString()));
    25. }
    26. }
    To copy to clipboard, switch view to plain text mode 

    (httpRequestFinished is connected with requestFinished)
    I tryed using http->close() and http->clearPendingRequests() at the end of httpRequestFinished() but the signal is still emitted.

    Hoping I was clear enough, someone can tell me what I have missed?

    Thanks
    Giuseppe CalÃ

  11. #11
    Join Date
    Jul 2007
    Posts
    56
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows
    Thanks
    6
    Thanked 2 Times in 2 Posts

    Question Re: Add "Check for updates" feature

    Did you ever find a solution for this double "requestFinished" signal being sent? I'm having the same problem. I'm closing the temporary file I use to download the page when I get the first "requestFinished" signal, but then sometimes I get another "requestFinished" signal with the same id and error=0.

    This causes the application to crash - I presume because I'm deleting the temporary file used in the Qhttp get().

    I'm using Qt 4.3.4 on Windows.

    It also seems that if I don't display a dialog to the user when I get the "requestFinished" signal then this doesn't happen. So maybe Qt is sending another signal if the first one is blocked by the dialog being shown?
    Last edited by will49; 18th September 2008 at 22:25.

  12. #12
    Join Date
    Jul 2007
    Posts
    56
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows
    Thanks
    6
    Thanked 2 Times in 2 Posts

    Default Re: Add "Check for updates" feature

    FYI - I got around this by not displaying the dialog box immediately. Instead I used a timer to delay it. I found that it would only happen on the non-Debug build and only if the dialog is displayed as soon as I get the "requestFinished" signal. Also it has nothing to do with closing the temporary file used in the Qhttp get().

    Weird.....

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
  •  
Qt is a trademark of The Qt Company.