Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 5766 was 5766, checked in by bensch, 18 years ago

orxonox/trunk: merged the GuidedMissiles to the trunk, without the changed aiming_turret

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