Mana
Loading...
Searching...
No Matches
updaterwindow.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2004-2009 The Mana World Development Team
4 * Copyright (C) 2009-2012 The Mana Developers
5 *
6 * This file is part of The Mana Client.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "gui/updaterwindow.h"
23
24#include "client.h"
25#include "configuration.h"
26#include "log.h"
27
28#include "gui/sdlinput.h"
29
31#include "gui/widgets/button.h"
32#include "gui/widgets/label.h"
33#include "gui/widgets/layout.h"
37
38#include "net/download.h"
39
41
42#include "utils/gettext.h"
43#include "utils/stringutils.h"
44#include "utils/xml.h"
45
46#include <iostream>
47#include <fstream>
48
49constexpr char xmlUpdateFile[] = "resources.xml";
50constexpr char txtUpdateFile[] = "resources2.txt";
51
55std::vector<UpdateFile> loadXMLFile(const std::string &fileName)
56{
57 std::vector<UpdateFile> files;
58 XML::Document doc(fileName, false);
59 XML::Node rootNode = doc.rootNode();
60
61 if (!rootNode || rootNode.name() != "updates")
62 {
63 Log::info("Error loading update file: %s", fileName.c_str());
64 return files;
65 }
66
67 for (auto fileNode : rootNode.children())
68 {
69 // Ignore all tags except for the "update" tags
70 if (fileNode.name() != "update")
71 continue;
72
73 UpdateFile file;
74 file.name = fileNode.getProperty("file", std::string());
75 file.hash = fileNode.getProperty("hash", std::string());
76 file.type = fileNode.getProperty("type", "data");
77 file.desc = fileNode.getProperty("description", std::string());
78 file.required = fileNode.getProperty("required", "yes") == "yes";
79
80 files.push_back(file);
81 }
82
83 return files;
84}
85
86std::vector<UpdateFile> loadTxtFile(const std::string &fileName)
87{
88 std::vector<UpdateFile> files;
89 std::ifstream fileHandler;
90 fileHandler.open(fileName, std::ios::in);
91
92 if (fileHandler.is_open())
93 {
94 while (fileHandler.good())
95 {
96 char name[256];
97 char hash[50];
98 fileHandler.getline(name, 256, ' ');
99 fileHandler.getline(hash, 50);
100
101 UpdateFile thisFile;
102 thisFile.name = name;
103 thisFile.hash = hash;
104 thisFile.type = "data";
105 thisFile.required = true;
106
107 if (!thisFile.name.empty())
108 files.push_back(thisFile);
109 }
110 }
111 else
112 {
113 Log::info("Error loading update file: %s", fileName.c_str());
114 }
115 fileHandler.close();
116
117 return files;
118}
119
120UpdaterWindow::UpdaterWindow(const std::string &updateHost,
121 const std::string &updatesDir,
122 bool applyUpdates):
123 Window(_("Updating...")),
124 mUpdateHost(updateHost),
125 mUpdatesDir(updatesDir),
126 mLoadUpdates(applyUpdates),
127 mLinkHandler(std::make_unique<ItemLinkHandler>(this))
128{
129 setWindowName("UpdaterWindow");
130 setResizable(true);
132 setMinWidth(320);
133 setMinHeight(240);
134
137 mLabel = new Label(_("Connecting..."));
138 mProgressBar = new ProgressBar(0.0, 310, 20);
139 mCancelButton = new Button(_("Cancel"), "cancel", this);
140 mPlayButton = new Button(_("Play"), "play", this);
141
144 mScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
145 mPlayButton->setEnabled(false);
146
147 place(0, 0, mScrollArea, 5, 3).setPadding(3);
148 place(0, 3, mLabel, 5);
149 place(0, 4, mProgressBar, 5);
150 place(3, 5, mCancelButton);
151 place(4, 5, mPlayButton);
152
153 Layout &layout = getLayout();
155
156 addKeyListener(this);
157
159 setVisible(true);
160 mCancelButton->requestFocus();
161
162 startDownload("news.txt", true);
163}
164
170
171void UpdaterWindow::setLabel(const std::string &str)
172{
173 mLabel->setCaption(str);
174 mLabel->adjustSize();
175}
176
178{
179 mCancelButton->setEnabled(false);
180 mPlayButton->setEnabled(true);
181 mPlayButton->requestFocus();
182}
183
184void UpdaterWindow::action(const gcn::ActionEvent &event)
185{
186 if (event.getId() == "cancel")
187 cancel();
188 else if (event.getId() == "play")
189 play();
190}
191
192void UpdaterWindow::keyPressed(gcn::KeyEvent &keyEvent)
193{
194 gcn::Key key = keyEvent.getKey();
195
196 if (key.getValue() == Key::ESCAPE)
197 {
198 if (!cancel())
199 {
200 mLoadUpdates = false;
202 }
203 }
204 else if (key.getValue() == Key::ENTER)
205 {
206 play();
207 }
208}
209
211{
212 // Skip the updating process
214 {
215 mDownload->cancel();
216 return true;
217 }
218 return false;
219}
220
222{
223 if (mPlayButton->isEnabled())
225}
226
228{
230 mBrowserBox->addRows(mDownload->getBuffer());
231
232 mScrollArea->setVerticalScrollAmount(0);
233}
234
235void UpdaterWindow::startDownload(const std::string &fileName,
236 bool storeInMemory,
237 std::optional<unsigned long> adler32)
238{
239 mDownload = std::make_unique<Net::Download>(mUpdateHost + "/" + fileName);
240 mCurrentFile = fileName;
241
242 if (storeInMemory)
243 mDownload->setUseBuffer();
244 else
245 mDownload->setFile(mUpdatesDir + "/" + fileName, adler32);
246
248 mDownload->noCache();
249
250 mDownload->start();
251}
252
254{
255 if (mUpdateFiles.empty())
256 {
257 // updates not downloaded
259 if (mUpdateFiles.empty())
260 {
261 Log::warn("This server does not have a"
262 " %s file falling back to %s", xmlUpdateFile,
265 }
266 }
267
268 for (const UpdateFile &file : mUpdateFiles)
269 ResourceManager::addToSearchPath(mUpdatesDir + "/" + file.name, false);
270}
271
273{
274 Window::logic();
275
277 return;
278
279 const auto state = mDownload->getState();
280 float progress = 0.0f;
281
282 switch (state.status) {
284 setLabel(mCurrentFile + " (" + toString((int) (state.progress * 100)) + "%)");
285 progress = state.progress;
286 break;
287 }
288
291
292 enablePlay();
293 setLabel(_("Download canceled"));
294 break;
295
298
299 std::string error = "##1";
300 error += mDownload->getError();
301 error += "\n\n##1";
302 error += _("The update process is incomplete. "
303 "It is strongly recommended that you try again later.");
304 mBrowserBox->addRows(error);
305
306 int maxScroll = mScrollArea->getVerticalMaxScroll();
307 mScrollArea->setVerticalScrollAmount(maxScroll);
308
309 enablePlay();
310 setLabel(_("Error while downloading"));
311 break;
312 }
313
316 break;
317 }
318
319 mProgressBar->setProgress(progress);
320}
321
323{
324 switch (mDialogState)
325 {
327 loadNews();
328
331 break;
332
335 {
337 if (mUpdateFiles.empty())
338 {
339 Log::warn("This server does not have a %s"
340 " file falling back to %s",
342
343 // If the resources.xml file fails, fall back onto a older version
346 break;
347 }
348 }
349 else if (mCurrentFile == txtUpdateFile)
350 {
352 }
353
355 break;
356
358 if (mUpdateIndex < mUpdateFiles.size())
359 {
360 const UpdateFile &thisFile = mUpdateFiles[mUpdateIndex];
361 if (!thisFile.required)
362 {
363 if (!(thisFile.type == "music" && config.downloadMusic))
364 {
365 mUpdateIndex++;
366 break;
367 }
368 }
369
370 unsigned long checksum;
371 std::stringstream ss(thisFile.hash);
372 ss >> std::hex >> checksum;
373
374 std::string filename = mUpdatesDir + "/" + thisFile.name;
375 FILE *file = fopen(filename.c_str(), "r+b");
376
377 if (!file || Net::Download::fadler32(file) != checksum)
378 {
379 if (file)
380 fclose(file);
381 startDownload(thisFile.name, false, checksum);
382 }
383 else
384 {
385 fclose(file);
386 Log::info("%s already here", thisFile.name.c_str());
387 }
388 mUpdateIndex++;
389 }
390 else
391 {
392 // Download of updates completed
394 enablePlay();
395 setLabel(_("Completed"));
396 }
397 break;
398
400 break;
401 }
402}
A simple browser box able to handle links and forward events to the parent conteiner.
Definition browserbox.h:74
void addRows(std::string_view rows)
Adds one or more text rows to the browser, separated by ' '.
void setLinkHandler(LinkHandler *handler)
Sets the handler for links.
Definition browserbox.h:88
void clearRows()
Remove all rows.
@ AUTO_WRAP
Maybe it needs a fix or to be redone.
Definition browserbox.h:79
Button widget.
Definition button.h:38
static void setState(State state)
Definition client.h:169
Label widget.
Definition label.h:34
void setRowHeight(int n, int h)
Definition layout.h:221
LayoutCell & setPadding(int p)
Sets the padding around the cell content.
Definition layout.h:179
This class is an helper for setting the position of widgets.
Definition layout.h:281
@ AUTO_SET
Uses the share as the new size.
Definition layout.h:304
static unsigned long fadler32(FILE *file)
Calculates the Alder-32 checksum for the given file.
Definition download.cpp:41
A progress bar.
Definition progressbar.h:34
void setProgress(float progress)
Sets the current progress.
void setSmoothProgress(bool smoothProgress)
Set whether the progress is moved smoothly.
Definition progressbar.h:94
static bool addToSearchPath(const std::string &path, bool append)
Adds a directory or archive to the search path.
A scroll area.
Definition scrollarea.h:38
unsigned int mUpdateIndex
Index of the file to be downloaded.
Button * mPlayButton
Button to start playing.
std::string mUpdatesDir
Place where the updates are stored (absolute path).
std::unique_ptr< LinkHandler > mLinkHandler
std::vector< UpdateFile > mUpdateFiles
List of files to download.
BrowserBox * mBrowserBox
Box to display news.
std::unique_ptr< Net::Download > mDownload
Download handle.
std::string mCurrentFile
The file currently downloading.
void loadNews()
Loads and display news.
std::string mUpdateHost
Host where we get the updated files.
DialogState mDialogState
Status of the current download.
ScrollArea * mScrollArea
Used to scroll news box.
void startDownload(const std::string &fileName, bool storeInMemory, std::optional< unsigned long > adler32={})
ProgressBar * mProgressBar
Update progress bar.
~UpdaterWindow() override
void loadUpdates()
Loads the updates this window has gotten into the resource manager.
Button * mCancelButton
Button to stop the update process.
void action(const gcn::ActionEvent &event) override
void setLabel(const std::string &)
void keyPressed(gcn::KeyEvent &keyEvent) override
bool mLoadUpdates
Tells ~UpdaterWindow() if it should load updates.
gcn::Label * mLabel
Progress bar caption.
void logic() override
UpdaterWindow(const std::string &updateHost, const std::string &updatesDir, bool applyUpdates)
Constructor.
A window.
Definition window.h:59
virtual void setVisible(bool visible)
Overloads window setVisible by Guichan to allow sticky window handling.
Definition window.cpp:282
void setMinHeight(int height)
Sets the minimum height of the window.
Definition window.cpp:197
Layout & getLayout()
Gets the layout handler for this window.
Definition window.cpp:714
void setWindowName(const std::string &name)
Sets the name of the window.
Definition window.h:272
void setResizable(bool resize)
Sets whether or not the window can be resized.
Definition window.cpp:212
LayoutCell & place(int x, int y, gcn::Widget *, int w=1, int h=1)
Adds a widget to the window and sets it at given cell.
Definition window.cpp:737
void setDefaultSize()
Set the default win pos and size to the current ones.
Definition window.cpp:545
void loadWindowState()
Reads the position (and the size for resizable windows) in the configuration based on the given strin...
Definition window.cpp:467
void setMinWidth(int width)
Sets the minimum width of the window.
Definition window.cpp:192
A helper class for parsing an XML document, which also cleans it up again (RAII).
Definition xml.h:190
Node rootNode() const
Returns the root node of the document (or NULL if there was a load error).
Definition xml.h:213
std::string_view name() const
Definition xml.h:46
Children children() const
Definition xml.h:97
Config config
Global settings (config.xml)
Definition client.cpp:97
@ STATE_LOAD_DATA
Definition client.h:69
@ STATE_WORLD_SELECT
Definition client.h:66
#define _(s)
Definition gettext.h:38
@ ENTER
Definition sdlinput.h:78
@ ESCAPE
Definition sdlinput.h:96
void warn(const char *log_text,...) LOG_PRINTF_ATTR
void info(const char *log_text,...) LOG_PRINTF_ATTR
std::string toString(const T &arg)
Converts the given value to a string using std::stringstream.
Definition stringutils.h:68
bool downloadMusic
std::string type
std::string hash
std::string name
std::string desc
std::vector< UpdateFile > loadTxtFile(const std::string &fileName)
std::vector< UpdateFile > loadXMLFile(const std::string &fileName)
Load the given file into a vector of updateFiles.
constexpr char xmlUpdateFile[]
constexpr char txtUpdateFile[]