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