PageRenderTime 49ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/FlightCrew-0.7.2/src/FlightCrew-gui/UpdateChecker.cpp

#
C++ | 187 lines | 111 code | 40 blank | 36 comment | 14 complexity | 93b4e2d2429031f15742fd626cd21d74 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1
  1. /************************************************************************
  2. **
  3. ** Copyright (C) 2010 Strahinja Markovic
  4. **
  5. ** This file is part of FlightCrew.
  6. **
  7. ** FlightCrew is free software: you can redistribute it and/or modify
  8. ** it under the terms of the GNU Lesser General Public License as published
  9. ** by the Free Software Foundation, either version 3 of the License, or
  10. ** (at your option) any later version.
  11. **
  12. ** FlightCrew is distributed in the hope that it will be useful,
  13. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ** GNU Lesser General Public License for more details.
  16. **
  17. ** You should have received a copy of the GNU Lesser General Public License
  18. ** along with FlightCrew. If not, see <http://www.gnu.org/licenses/>.
  19. **
  20. *************************************************************************/
  21. #include <QRegExp>
  22. #include <QSettings>
  23. #include <QNetworkAccessManager>
  24. #include <QNetworkRequest>
  25. #include <QNetworkReply>
  26. #include <QDateTime>
  27. #include <QMessageBox>
  28. #include <QDesktopServices>
  29. #include <QXmlStreamReader>
  30. #include <QTextStream>
  31. #include "UpdateChecker.h"
  32. static const QString DOWNLOAD_PAGE_LOCATION = "http://code.google.com/p/flightcrew/downloads/list";
  33. static const QString UPDATE_XML_LOCATION = "http://flightcrew.googlecode.com/git/version.xml";
  34. static const QString XML_VERSION_ELEMENT = "current-version";
  35. static const QString LAST_ONLINE_VERSION_KEY = "last_online_version";
  36. static const QString LAST_CHECK_TIME_KEY = "last_check_time";
  37. static const QString SETTINGS_GROUP = "updatechecker";
  38. static const QString VERSION_NUMBERS = "(\\d+)\\.(\\d+)\\.(\\d+)";
  39. static const QString FLIGHTCREW_VERSION = QString( FLIGHTCREW_FULL_VERSION );
  40. // Delta is six hours
  41. static const int SECONDS_BETWEEN_CHECKS = 60 * 60 * 6 ;
  42. UpdateChecker::UpdateChecker( QObject *parent )
  43. :
  44. QObject( parent ),
  45. m_NetworkManager( new QNetworkAccessManager( this ) )
  46. {
  47. connect( m_NetworkManager, SIGNAL( finished( QNetworkReply* ) ),
  48. this, SLOT( ReplyRecieved( QNetworkReply* ) )
  49. );
  50. }
  51. void UpdateChecker::CheckForUpdate()
  52. {
  53. QSettings settings;
  54. settings.beginGroup( SETTINGS_GROUP );
  55. // The default time is one always longer than the check interval
  56. QDateTime default_time = QDateTime::currentDateTime().addSecs( - SECONDS_BETWEEN_CHECKS - 1 );
  57. QDateTime last_check_time = settings.value( LAST_CHECK_TIME_KEY, default_time ).toDateTime();
  58. // We want to check for a new version
  59. // no sooner than every six hours
  60. if ( last_check_time.secsTo( QDateTime::currentDateTime() ) > SECONDS_BETWEEN_CHECKS )
  61. {
  62. settings.setValue( LAST_CHECK_TIME_KEY, QDateTime::currentDateTime() );
  63. m_NetworkManager->get( QNetworkRequest( QUrl( UPDATE_XML_LOCATION ) ) );
  64. }
  65. }
  66. void UpdateChecker::ReplyRecieved( QNetworkReply* reply )
  67. {
  68. QSettings settings;
  69. settings.beginGroup( SETTINGS_GROUP );
  70. QString last_online_version = settings.value( LAST_ONLINE_VERSION_KEY, QString() ).toString();
  71. QString current_online_version = ReadOnlineVersion( TextInReply( reply ) );
  72. bool is_newer = IsOnlineVersionNewer( FLIGHTCREW_VERSION, current_online_version );
  73. // The message box is displayed only if the online version is newer
  74. // and only if the user hasn't been informed about this release before
  75. if ( is_newer && ( current_online_version != last_online_version ) )
  76. {
  77. QMessageBox::StandardButton button_clicked;
  78. button_clicked = QMessageBox::question( 0,
  79. QObject::tr( "FlightCrew" ),
  80. QObject::tr( "<p>A newer version of FlightCrew is available, version <b>%1</b>.<br/>"
  81. "The ChangeLog can be seen <a href='http://flightcrew.googlecode.com/git/ChangeLog.txt'>here</a>.</p>"
  82. "<p>Would you like to go to the download page?</p>" )
  83. .arg( current_online_version ),
  84. QMessageBox::Yes | QMessageBox::No,
  85. QMessageBox::Yes );
  86. if ( button_clicked == QMessageBox::Yes )
  87. {
  88. QDesktopServices::openUrl( QUrl( DOWNLOAD_PAGE_LOCATION ) );
  89. }
  90. }
  91. // Store the current online version as the last one checked
  92. settings.setValue( LAST_ONLINE_VERSION_KEY, current_online_version );
  93. // Schedule this object for deletion.
  94. // There is no point for its existence
  95. // after it has received and processed the net reply.
  96. deleteLater();
  97. }
  98. QString UpdateChecker::TextInReply( QNetworkReply* reply ) const
  99. {
  100. if ( !reply->open( QIODevice::ReadOnly | QIODevice::Text ) )
  101. {
  102. return "";
  103. }
  104. QTextStream in( reply );
  105. // Input should be UTF-8
  106. in.setCodec( "UTF-8" );
  107. // This will automatically switch reading from
  108. // UTF-8 to UTF-16 if a BOM is detected
  109. in.setAutoDetectUnicode( true );
  110. return in.readAll();
  111. }
  112. QString UpdateChecker::ReadOnlineVersion( const QString &online_version_xml ) const
  113. {
  114. if ( online_version_xml.isEmpty() )
  115. return QString();
  116. QXmlStreamReader version_reader( online_version_xml );
  117. while ( !version_reader.atEnd() )
  118. {
  119. // Get the next token from the stream
  120. if ( ( version_reader.readNext() == QXmlStreamReader::StartElement ) &&
  121. ( version_reader.name() == XML_VERSION_ELEMENT )
  122. )
  123. {
  124. return version_reader.readElementText();
  125. }
  126. }
  127. return QString();
  128. }
  129. bool UpdateChecker::IsOnlineVersionNewer( const QString &current_version_string,
  130. const QString &online_version_string ) const
  131. {
  132. if ( current_version_string.isEmpty() || online_version_string.isEmpty() )
  133. return false;
  134. QRegExp current_version_numbers( VERSION_NUMBERS );
  135. QString( current_version_string ).indexOf( current_version_numbers );
  136. QRegExp online_version_numbers( VERSION_NUMBERS );
  137. QString( online_version_string ).indexOf( online_version_numbers );
  138. // This code assumes three digits per field,
  139. // which should be way more than enough
  140. int current_version = current_version_numbers.cap( 1 ).toInt() * 1000000 +
  141. current_version_numbers.cap( 2 ).toInt() * 1000 +
  142. current_version_numbers.cap( 3 ).toInt();
  143. int online_version = online_version_numbers.cap( 1 ).toInt() * 1000000 +
  144. online_version_numbers.cap( 2 ).toInt() * 1000 +
  145. online_version_numbers.cap( 3 ).toInt();
  146. return online_version > current_version;
  147. }