BuildmLearn Toolkit  2.0.4
BuildmLearn Toolkit is an easy-to-use program that helps users make mobile apps without any knowledge of application development.
 All Classes Functions Enumerations Groups Pages
formupdate.cpp
1 /*
2  Copyright (c) 2012, BuildmLearn Contributors listed at http://buildmlearn.org/people/
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are met:
7 
8  * Redistributions of source code must retain the above copyright notice, this
9  list of conditions and the following disclaimer.
10 
11  * Redistributions in binary form must reproduce the above copyright notice,
12  this list of conditions and the following disclaimer in the documentation
13  and/or other materials provided with the distribution.
14 
15  * Neither the name of the BuildmLearn nor the names of its
16  contributors may be used to endorse or promote products derived from
17  this software without specific prior written permission.
18 
19  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 
31 #include "gui/formupdate.h"
32 
33 #include "definitions/definitions.h"
34 #include "miscellaneous/systemfactory.h"
35 #include "miscellaneous/iconfactory.h"
36 #include "network-web/webfactory.h"
37 #include "network-web/downloader.h"
38 #include "network-web/networkfactory.h"
39 #include "gui/custommessagebox.h"
40 #include "gui/systemtrayicon.h"
41 
42 #include <QNetworkReply>
43 #include <QDesktopServices>
44 #include <QProcess>
45 
46 
47 FormUpdate::FormUpdate(QWidget *parent)
48  : QDialog(parent), m_downloader(NULL), m_readyToInstall(false), m_ui(new Ui::FormUpdate) {
49  m_ui->setupUi(this);
50 
51  // Set flags and attributes.
52  setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog | Qt::WindowSystemMenuHint | Qt::WindowTitleHint);
53  setWindowIcon(IconFactory::instance()->fromTheme("application-about"));
54 
55  m_btnUpdate = m_ui->m_buttonBox->addButton(tr("Update"), QDialogButtonBox::ActionRole);
56  m_btnUpdate->setToolTip(tr("Download new installation files."));
57 
58  connect(m_btnUpdate, SIGNAL(clicked()), this, SLOT(startUpdate()));
59 
60 
61  m_ui->m_lblCurrentRelease->setText(APP_VERSION);
62  checkForUpdates();
63 }
64 
65 FormUpdate::~FormUpdate() {
66  delete m_ui;
67 }
68 
70  return m_updateInfo.m_urls.keys().contains(OS_ID);
71 }
72 
74  // DO NOT allow self-updating for now.
75 #if defined(Q_OS_WIN) || defined(Q_OS_OS2)
76  return false;
77 #else
78  return false;
79 #endif
80 }
81 
83  UpdateCheck update = qApp->checkForUpdates();
84 
85  m_updateInfo = update.first;
86 
87  if (update.second != QNetworkReply::NoError) {
88  //: Unknown release.
89  m_ui->m_lblAvailableRelease->setText(tr("unknown"));
90  m_ui->m_txtChanges->clear();
91  m_ui->m_lblStatus->setStatus(WidgetWithStatus::Error,
92  tr("Error: '%1'.").arg(NetworkFactory::networkErrorText(update.second)),
93  tr("List with updates was "
94  "not\ndownloaded successfully."));
95  m_btnUpdate->setEnabled(false);
96  m_btnUpdate->setToolTip(tr("Checking for updates failed."));
97  }
98  else {
99  m_ui->m_lblAvailableRelease->setText(update.first.m_availableVersion);
100  m_ui->m_txtChanges->setText(update.first.m_changes);
101 
102  if (update.first.m_availableVersion > APP_VERSION) {
103  m_ui->m_lblStatus->setStatus(WidgetWithStatus::Ok,
104  tr("New release available."),
105  tr("This is new version which can be\ndownloaded and installed."));
106  m_btnUpdate->setEnabled(true);
107  m_btnUpdate->setToolTip(isUpdateForThisSystem() ?
108  tr("Download installation file for your OS.") :
109  tr("Installation file is not available directly.\n"
110  "Go to application website to obtain it manually."));
111 
112  if (isUpdateForThisSystem() /* && isSelfUpdateSupported() */ ) {
113  m_btnUpdate->setText(tr("Download update"));
114  }
115  }
116  else {
117  m_ui->m_lblStatus->setStatus(WidgetWithStatus::Warning,
118  tr("No new release available."),
119  tr("This release is not newer than\ncurrently installed one."));
120  m_btnUpdate->setEnabled(false);
121  m_btnUpdate->setToolTip(tr("No new update available."));
122  }
123  }
124 }
125 
126 void FormUpdate::updateProgress(qint64 bytes_received, qint64 bytes_total) {
127  qApp->processEvents();
128  m_ui->m_lblStatus->setStatus(WidgetWithStatus::Information,
129  tr("Downloaded %1% (update size is %2 kB).").arg(QString::number((bytes_received * 100.0) / bytes_total,
130  'f',
131  2),
132  QString::number(bytes_total / 1000,
133  'f',
134  2)),
135  tr("Downloading update..."));
136 }
137 
138 void FormUpdate::saveUpdateFile(const QByteArray &file_contents) {
139  QString url_file = m_updateInfo.m_urls.value(OS_ID).m_fileUrl;;
140 
141 #if QT_VERSION >= 0x050000
142  QString temp_directory = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
143 #else
144  QString temp_directory = QDesktopServices::storageLocation(QDesktopServices::TempLocation);
145 #endif
146 
147  if (!temp_directory.isEmpty()) {
148  QString output_file_name = url_file.mid(url_file.lastIndexOf('/') + 1);
149  QFile output_file(temp_directory + QDir::separator() + output_file_name);
150 
151  if (output_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
152  qDebug("Storing update file to temporary location '%s'.",
153  qPrintable(output_file.fileName()));
154 
155  output_file.write(file_contents);
156  output_file.flush();
157  output_file.close();
158 
159  qDebug("Update file contents was successfuly saved.");
160 
161  m_updateFilePath = output_file.fileName();
162  m_readyToInstall = true;
163  }
164  else {
165  qDebug("Cannot save downloaded update file because target temporary file '%s' cannot be "
166  "opened for writing.", qPrintable(output_file_name));
167  }
168  }
169  else {
170  qDebug("Cannot save downloaded update file because no TEMP folder is available.");
171  }
172 }
173 
174 void FormUpdate::updateCompleted(QNetworkReply::NetworkError status, QByteArray contents) {
175  qDebug("Download of application update file was completed with code '%d'.",
176  status);
177 
178  switch (status) {
179  case QNetworkReply::NoError:
180  saveUpdateFile(contents);
181 
182  m_ui->m_lblStatus->setStatus(WidgetWithStatus::Ok,
183  tr("Downloaded successfully, stored in file '%1'.").arg(m_updateFilePath),
184  tr("Package was downloaded successfully."));
185  m_btnUpdate->setText(tr("Open update file"));
186  m_btnUpdate->setEnabled(true);
187  break;
188 
189  default:
190  m_ui->m_lblStatus->setStatus(WidgetWithStatus::Error,
191  tr("Error occured."),
192  tr("Error occured during downloading of the package."));
193  m_btnUpdate->setText(tr("Error occured"));
194  break;
195  }
196 }
197 
198 void FormUpdate::startUpdate() {
199  QString url_file;
200  bool update_for_this_system = isUpdateForThisSystem();
201 
202  if (update_for_this_system) {
203  url_file = m_updateInfo.m_urls.value(OS_ID).m_fileUrl;
204  }
205  else {
206  url_file = APP_URL_DOWNLOADS;
207  }
208 
209  if (!WebFactory::instance()->openUrlInExternalBrowser(url_file)) {
211  qApp->trayIcon()->showMessage(tr("Cannot update application"),
212  tr("Cannot navigate to installation file. Check new installation downloads "
213  "manually on project website."),
214  QSystemTrayIcon::Warning);
215  }
216  else {
218  QMessageBox::Warning,
219  tr("Cannot update application"),
220  tr("Cannot navigate to installation file. Check new installation downloads "
221  "manually on project website."));
222  }
223  }
224 }
Dialog for showing update details.
Definition: formupdate.h:51
void checkForUpdates()
Check for updates and interprets the results.
Definition: formupdate.cpp:82
static QString networkErrorText(QNetworkReply::NetworkError error_code)
Gets human readable text for given network error.
bool isSelfUpdateSupported() const
Indication of presence of self-update feature.
Definition: formupdate.cpp:73
static bool isSystemTrayAvailable()
Indicates whether tray icon is supported.
static QMessageBox::StandardButton show(QWidget *parent, QMessageBox::Icon icon, const QString &title, const QString &text, const QString &informative_text=QString(), const QString &detailed_text=QString(), QMessageBox::StandardButtons buttons=QMessageBox::Ok, QMessageBox::StandardButton default_button=QMessageBox::Ok)
Displays custom message box.
bool isUpdateForThisSystem() const
Indication of update/platform suitability.
Definition: formupdate.cpp:69
static IconFactory * instance()
Singleton getter.
Definition: iconfactory.cpp:48