Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/gui/gui_update.cc @ 4866

Last change on this file since 4866 was 4836, checked in by bensch, 19 years ago

orxonox/trunk: renamed all the \param → @param and so on in Doxygen tags.
Thanks a lot to the kDevelop team. this took since the last commit :)

File size: 15.0 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3   Copyright (C) 2004 orx
4
5   This program is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 2, or (at your option)
8   any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program; if not, write to the Free Software Foundation,
17   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19
20   ### File Specific:
21   main-programmer: Benjamin Grauer
22
23*/
24
25#include "gui_update.h"
26#include <string.h>
27
28#include "gui.h"
29#include <stdio.h>
30#include <stdlib.h>
31
32using namespace std;
33
34/**
35 *  Creates an Update-Frame
36*/
37GuiUpdate::GuiUpdate()
38{
39  FileDialog* dataDirDialog;   //!< A FileDialog for the selection of the DataRepos
40  Button* dataDirButton;       //!< A Button for the selection of the DataRepos
41  OptionLabel* dataDirLabel;   //!< A Label fot the selection of the DataRepos
42
43
44  this->tmpDir = NULL;
45  this->homeDir = NULL;
46  this->installSourceDir = NULL;
47  this->userName = NULL;
48
49  this->getSystemInfo();
50
51  this->updateFrame = new Frame("Update-Options:");
52  this->updateFrame->setGroupName(CONFIG_SECTION_DATA);
53  this->updateBox = new Box('v');
54
55  dataDirButton = new Button(CONFIG_NAME_DATADIR);
56  dataDirLabel = new OptionLabel(CONFIG_NAME_DATADIR, "unknown");
57  dataDirLabel->setFlagName("data-dir", "d", 0);
58  dataDirLabel->setDescription("Sets the location of the orxonox' Data-Directory");
59  dataDirLabel->saveability();
60  dataDirDialog = new FileDialog("data-Repos-location");
61  dataDirDialog->setDefaultFileName("data");
62  dataDirDialog->setMask(DATA_IDENTIFIER);
63  this->checkDataDir(DEFAULT_DATA_DIR DATA_IDENTIFIER, dataDirLabel);
64  dataDirDialog->disableFileOpts();
65  dataDirDialog->setOpenUpButton(dataDirButton);
66  //dataDirDialog->setChangeOption(dataDirLabel);
67  dataDirDialog->setOKFunc(dataDirLabel, GuiUpdate::checkDataDir);
68  updateBox->fill(dataDirButton);
69  updateBox->fill(dataDirLabel);
70
71#ifdef HAVE_CURL
72
73  // the Button for autoUpdating
74  this->autoUpdate = new CheckButton(CONFIG_NAME_AUTO_UPDATE);
75  this->updateBox->fill(this->autoUpdate);
76  this->autoUpdate->setFlagName("update", "u", 0);
77  this->autoUpdate->setDescription("Updates orxonox", "When this option is selected orxonox automatically searches for updates, and if found installs them");
78  this->autoUpdate->saveability();
79
80
81
82
83  this->updateSourceWindowCreate();
84  this->updateBox->fill(this->updateSourceWindowGetButton());
85
86  this->updateDataWindowCreate();
87  this->updateBox->fill(this->updateDataWindowGetButton());
88
89#else /* HAVE_CURL */
90  Label* noCurlLabel = new Label("since you do not have cURL-support,\nupdate options are not availible");
91  this->updateBox->fill(noCurlLabel);
92#endif /* HAVE_CURL */
93  this->updateFrame->fill(this->updateBox);
94  this->setMainWidget(this->updateFrame);
95
96
97}
98
99/**
100 *  Destructs the Update-stuff
101*/
102GuiUpdate::~GuiUpdate()
103{
104
105}
106
107/**
108 *  checks if the Folder containing selected File is data.oxd, and if so sets it.
109 * @param
110*/
111bool GuiUpdate::checkDataDir(const char* fileName, void* object)
112{
113  if (!strcmp(fileName+(strlen(fileName)-strlen(DATA_IDENTIFIER)), DATA_IDENTIFIER))
114    {
115      char* tmpName = new char[strlen(fileName)-strlen(DATA_IDENTIFIER)+1];
116      strncpy(tmpName, fileName, strlen(fileName)-strlen(DATA_IDENTIFIER));
117      tmpName[strlen(fileName)-strlen(DATA_IDENTIFIER)] = '\0';
118      static_cast<OptionLabel*>(object)->setValue(tmpName);
119      delete tmpName;
120      return true;
121    }
122  else
123    return false;
124}
125
126
127/**
128  *  Look what info we can get from this system
129*/
130bool GuiUpdate::getSystemInfo()
131{
132  PRINTF(5)("Grabbing system information\n");
133  this->tmpDir = getenv("TMPDIR");
134  if(!tmpDir)
135    this->tmpDir = "/tmp";
136  PRINTF(5)("Temporary directory is: %s\n", this->tmpDir);
137
138#ifdef __WIN32__
139  this->homeDir = getenv("USERPROFILE");
140#else
141  this->homeDir = getenv("HOME");
142#endif
143  PRINTF(5)("Home directory is %s\n", homeDir);
144
145
146  this->installDataDir = DEFAULT_DATA_DIR;
147  PRINTF(5)("Installation of orxonox-data will go to this directory: %s\n", this->installDataDir);
148
149  this->installSourceDir = "/usr/games/bin";
150  PRINTF(5)("Installation of orxonox-source will go to this directory: %s\n", this->installSourceDir);
151
152  this->userName = getenv("USER");
153  PRINTF(5)("Logged in username is: %s\n", this->userName);
154}
155
156#ifdef HAVE_CURL
157bool* GuiUpdate::checkForUpdates()
158{
159  PRINTF(4)("checking for new version of orxonox\n");
160  FileInfo updateFileInfo;
161  updateFileInfo.fileName = "update_info";
162  updateFileInfo.webRoot = "http://www.orxonox.ethz.ch/files/data";
163  updateFileInfo.localRoot = this->tmpDir;
164
165  download(&updateFileInfo);
166}
167
168/**
169 *  Creates a window, and all it contains for the Data-update.
170*/
171void GuiUpdate::updateDataWindowCreate()
172{
173  this->updateDataWindow = new Window("update orxonox::Data");
174  this->updateDataBox = new Box('v');
175
176  // the close-Button of the Update Window.
177  //  updateWindowClose = new Button("close");
178#ifdef HAVE_GTK2
179  //  updateWindowClose->connectSignal("button_press_event", updateWindow, Window::windowClose);
180#endif /* HAVE_GTK2 */
181  //  updateWindowBox->fill(updateWindowClose);
182
183  this->updateDataBar = new ProgressBar();
184  this->updateDataBox->fill(this->updateDataBar);
185
186  FileInfo* dataInfo = new FileInfo;
187  dataInfo->bar = this->updateDataBar;
188
189  this->updateDataBegin = new Button("begin.");
190  dataInfo->stateButton = this->updateDataBegin;
191#ifdef HAVE_GTK2
192  dataInfo->buttonSignal = updateDataBegin->connectSignal("button_press_event", dataInfo, updateDataFunc);
193#endif /* HAVE_GTK2 */
194  this->updateDataBox->fill(this->updateDataBegin);
195
196  this->updateDataWindow->fill(this->updateDataBox);
197
198  this->updateDataWindowButton = new Button("update orxonox::Data");
199#ifdef HAVE_GTK2
200  this->updateDataWindowButton->connectSignal("button_press_event", this->updateDataWindow, Window::windowOpen);
201  this->updateDataWindow->connectSignal("destroy", this->updateDataWindow, Window::windowClose);
202  this->updateDataWindow->connectSignal("delete_event", this->updateDataWindow, Window::windowClose);
203#endif /* HAVE_GTK2 */
204
205}
206
207/**
208 * @returns A Pointer to the Button of the UpdaterDataWindow
209*/
210Button* GuiUpdate::updateDataWindowGetButton()
211{
212  return this->updateDataWindowButton;
213}
214
215/**
216 *  Creates a window, and all it contains for the Source-update.
217*/
218void GuiUpdate::updateSourceWindowCreate()
219{
220  // the button, that opens this Window.
221  this->updateSourceWindowButton = new Button("update orxonox::Source");
222
223  // the Window itself
224  this->updateSourceWindow = new Window("update orxonox::Source");
225
226  this->updateSourceBox = new Box();
227
228  this->updateSourceBar = new ProgressBar();
229  this->updateSourceBox->fill(this->updateSourceBar);
230  test = new Button("increment");
231
232#ifdef HAVE_GTK2
233  test->connectSignal("button_press_event", updateSourceBar, updateSourceFunc);
234#endif /* HAVE_GTK2 */
235
236  this->updateSourceBox->fill(test);
237  this->updateSourceWindow->fill(updateSourceBox);
238#ifdef HAVE_GTK2
239  this->updateSourceWindowButton->connectSignal("button_press_event", this->updateSourceWindow, Window::windowOpen);
240  this->updateSourceWindow->connectSignal("destroy", this->updateSourceWindow, Window::windowClose);
241  this->updateSourceWindow->connectSignal("delete_event", this->updateSourceWindow, Window::windowClose);
242#endif /* HAVE_GTK2 */
243
244}
245
246/**
247 * @returns A Pointer to the Button of the UpdaterSourceWindow
248*/
249Button* GuiUpdate::updateSourceWindowGetButton()
250{
251  return this->updateSourceWindowButton;
252}
253
254
255#ifdef HAVE_GTK2
256/**
257 *  updates the Data of orxonox.
258 * @param w The widget, that executed this Function.
259 * @param event The event that trigered this Function.
260 * @param button The Button, that triggered this event.
261*/
262gint GuiUpdate::updateDataFunc(GtkWidget* w, GdkEventKey* event, void* info)
263{
264  FileInfo* dataInfo =(FileInfo*)info;
265
266  dataInfo->fileName = "02%20orxonox%203.mp3";
267  dataInfo->webRoot  = "http://www.orxonox.ethz.ch/files/";
268  dataInfo->localRoot = "./";
269  PRINTF(4)("Preparing to download file %s.\n", dataInfo->fileName);
270  downloadWithStyle(dataInfo);
271}
272
273/**
274 *  updates the source of orxonox.
275 * @param w The widget, that executed this Function.
276 * @param event The event that trigered this Function.
277 * @param button The Button, that triggered this event.
278*/
279gint GuiUpdate::updateSourceFunc(GtkWidget* w, GdkEventKey* event, void* bar)
280{
281  ProgressBar* tmpBar = static_cast<ProgressBar*>(bar);
282  tmpBar->setTotalSize(20);
283  tmpBar->setProgress(tmpBar->getProgress()+1);
284}
285#endif /* HAVE_GTK2 */
286
287/**
288 *  The Function Curl calls to write out the File.
289 * @param ptr A Pointer to the date to write.
290 * @param size The size in bytes of one nmemb to write.
291 * @param nmemb The Count of size to write.
292 * @param stream Filehandler to write to.
293*/
294size_t GuiUpdate::curlWriteFunc(void* ptr, size_t size, size_t nmemb, FILE* stream)
295{
296  return fwrite(ptr, size, nmemb, stream);
297}
298
299/**
300 *  The Function Curl calls to write out the File.
301 * @param ptr A Pointer to the date to write to.
302 * @param size The size in bytes of one nmemb to write.
303 * @param nmemb The Count of size to write.
304 * @param stream Filehandler to get data from.
305*/
306size_t GuiUpdate::curlReadFunc(void* ptr, size_t size, size_t nmemb, FILE* stream)
307{
308  return fread(ptr, size, nmemb, stream);
309}
310
311
312/**
313 *  An update Function for the GUI, to show the progress.
314 * @param Bar th ProgressBar to update
315 * @param totalSize The total size of the download in bytes.
316 * @param progress The current Progress of the download in bytes.
317 * @param upTotal not needed
318 * @param upProgress not needed
319*/
320int GuiUpdate::curlProgressFunc(ProgressBar* bar, double totalSize, double progress, double upTotal, double upProgress)
321{
322  bar->setProgress(progress);
323  bar->setTotalSize(totalSize);
324#ifdef HAVE_GTK2
325  while(gtk_events_pending()) gtk_main_iteration();
326#endif
327  return 0;
328}
329
330/**
331 *  The Curl handle for only one CURL(static).
332*/
333CURL* GuiUpdate::curlHandle = NULL;
334
335//! A bool parameter that shows if we are downloading.
336bool GuiUpdate::isDownloading = false;
337
338//! A parameter to see, if downloading has been canceled
339bool GuiUpdate::downloadCanceled = false;
340
341/**
342 *  Initializes a Download without displaying it.
343 * @param fileInfo the FileInfo.
344
345   !! BE AWARE THIS WILL NOT BE THREADED. !!
346*/
347bool GuiUpdate::download(void* fileInfo)
348{
349  if(isDownloading)
350    {
351      PRINTF(2)("unable to Download. already getting some file\n");
352      return false;
353    }
354  PRINTF(4)("Downloading.\n");
355  FileInfo* info =(FileInfo*)fileInfo;
356  CURLcode res;
357  CURL* localCurl;
358  localCurl = curl_easy_init();
359  char* fileOnNet = new char [strlen(info->webRoot)+strlen(info->fileName)+2];
360  strcpy(fileOnNet, info->webRoot);
361  if(fileOnNet[strlen(fileOnNet)] != '/') //!< @todo windows-shit
362    strcat(fileOnNet, "/");
363  strcat(fileOnNet, info->fileName);
364  char* fileOnDisk = new char [strlen(info->localRoot)+strlen(info->fileName)+2];
365  strcpy(fileOnDisk, info->localRoot);
366  if(fileOnDisk[strlen(fileOnDisk)] != '/') //!< @todo windows-shit
367    strcat(fileOnDisk, "/");
368  strcat(fileOnDisk, info->fileName);
369
370  if(localCurl)
371    {
372
373      info->fileHandle = fopen(fileOnDisk, "w");
374
375      curl_easy_setopt(localCurl, CURLOPT_URL, fileOnNet);
376      curl_easy_setopt(localCurl, CURLOPT_WRITEDATA, info->fileHandle);
377      curl_easy_setopt(localCurl, CURLOPT_WRITEFUNCTION, curlWriteFunc);
378      curl_easy_setopt(localCurl, CURLOPT_READFUNCTION, curlReadFunc);
379      curl_easy_setopt(localCurl, CURLOPT_NOPROGRESS, true);
380
381      curl_easy_perform(localCurl);
382
383      curl_easy_cleanup(localCurl);
384      fclose(info->fileHandle);
385    }
386}
387
388/**
389 *  Initializes a Download with some style.
390 * @param fileInfo the FileInfo.
391   @todo release thread-lock.
392
393   Downloading with a Button that gets a different Name while downloading, and a Bar, that gets to be updated. More to be followed
394*/
395bool GuiUpdate::downloadWithStyle(void* fileInfo)
396{
397  if(isDownloading)
398    {
399      PRINTF(2)("unable to Download. already getting some file\n");
400      return false;
401    }
402  PRINTF(4)("Downloading.\n");
403  FileInfo* info =(FileInfo*)fileInfo;
404  CURLcode res;
405  curlHandle = curl_easy_init();
406  char* fileOnNet = new char [strlen(info->webRoot)+strlen(info->fileName)+1];
407  strcpy(fileOnNet, info->webRoot);
408  strcat(fileOnNet, info->fileName);
409  char* fileOnDisk = new char [strlen(info->localRoot)+strlen(info->fileName)+1];
410  strcpy(fileOnDisk, info->localRoot);
411  strcat(fileOnDisk, info->fileName);
412
413  if(curlHandle)
414    {
415
416      info->fileHandle = fopen(fileOnDisk, "w");
417
418      curl_easy_setopt(curlHandle, CURLOPT_URL, fileOnNet);
419      curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, info->fileHandle);
420      curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, curlWriteFunc);
421      curl_easy_setopt(curlHandle, CURLOPT_READFUNCTION, curlReadFunc);
422      curl_easy_setopt(curlHandle, CURLOPT_NOPROGRESS, false);
423      curl_easy_setopt(curlHandle, CURLOPT_PROGRESSFUNCTION, curlProgressFunc);
424      curl_easy_setopt(curlHandle, CURLOPT_PROGRESSDATA, info->bar);
425
426      if(!isDownloading)
427        {
428#ifdef HAVE_GTK2
429          info->stateButton->disconnectSignal(info->buttonSignal);
430          info->buttonSignal = info->stateButton->connectSignal("button_press_event", info, cancelDownload);
431#endif /* HAVE_GTK2 */
432          info->stateButton->setTitle("please wait");
433
434          downloadThread(info);
435          downloadThreadFinished(info);
436
437          //      res = curl_easy_perform(curlHandle);
438
439          //      fclose(outfile);
440        }
441      else
442        PRINTF(1)("thread already in use\n");
443
444    }
445  return true;
446}
447
448/**
449 *  The downloading process(either threaded or not).
450 * @param fileInfo the FileInfo.
451
452   @todo Threads get locked, if the cancel button is pressed in to small intervals.
453*/
454void* GuiUpdate::downloadThread(void* fileInfo)
455{
456  isDownloading = true;
457  curl_easy_perform(curlHandle);
458}
459
460/**
461 *  Finishes a downloading process.
462 * @param fileInfo the FileInfo.
463*/
464void* GuiUpdate::downloadThreadFinished(void* fileInfo)
465{
466  FileInfo* info =(FileInfo*)fileInfo;
467  if(curlHandle)
468    curl_easy_cleanup(curlHandle);
469
470  PRINTF(4)("Closing the downloaded file.\n");
471  fclose(info->fileHandle);
472
473  if(isDownloading)
474    info->stateButton->setTitle("go on");
475  //  else
476  //    info->stateButton->setTitle("done");
477#ifdef HAVE_GTK2
478  info->stateButton->disconnectSignal(info->buttonSignal);
479  info->buttonSignal = info->stateButton->connectSignal("button_press_event", info, updateDataFunc);
480#endif /* HAVE_GTK2 */
481  isDownloading = false;
482
483}
484
485#ifdef HAVE_GTK2
486/**
487 *  canceles a downloading session.
488 * @param w The widget, that executed this Function.
489 * @param event The event that trigered this Function.
490 * @param bar The Bar, that triggered this event.
491
492   @todo canceling a session in non-threaded mode.
493*/
494gint GuiUpdate::cancelDownload(GtkWidget* w, GdkEventKey* event, void* bar)
495{
496  PRINTF(3)("Cannot cancle the Downloading process until after this File\n");
497}
498#endif /* HAVE_GTK2 */
499
500#endif /* HAVE_CURL */
Note: See TracBrowser for help on using the repository browser.