Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/gui/gui_exec.cc @ 5015

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

orxonox/trunk: robust IniParser

File size: 13.2 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software Foundation,
18   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
20
21   ### File Specific:
22   main-programmer: Benjamin Grauer
23
24*/
25
26#include "gui_exec.h"
27
28#include "resource_manager.h"
29#include "ini_parser.h"
30
31#include <string.h>
32#include <stdlib.h>
33#include <sys/stat.h>
34#include <sys/types.h>
35
36
37#ifdef __WIN32__
38#include <direct.h>
39#endif /* __WIN32__ */
40HashTable* orxonoxFlagHash;
41
42/**
43  *  Creates the Exec-Frame
44*/
45GuiExec::GuiExec()
46{
47  Frame* execFrame;            //!< The Frame that holds the ExecutionOptions.
48
49  this->confFile = NULL;
50  this->confDir = NULL;
51
52  execFrame = new Frame("Execute-Tags:");
53  {
54    Box* execBox;                //!< The Box that holds the ExecutionOptions.
55
56    execBox = new Box('v');
57    execFrame->setGroupName(CONFIG_SECTION_MISC);
58    {
59      Button* start;               //!< The start Button of orxonox.
60      Menu* verboseMode;           //!< A Menu for setting the verbose-Mode. @todo setting up a verbose-class.
61      CheckButton* alwaysShow;     //!< A CheckButton, for if orxonox should start with or without gui.
62      Button* quit;                //!< A Button to quit the Gui without starting orxonox.
63
64      start = new Button("Start");
65#ifdef HAVE_GTK2
66      start->connectSignal("clicked", this, startOrxonox);
67#endif /* HAVE_GTK2 */
68      execBox->fill(start);
69      this->saveSettings = new CheckButton(CONFIG_NAME_SAVE_SETTINGS);
70      this->saveSettings->value = 1;
71      this->saveSettings->saveability();
72      execBox->fill(this->saveSettings);
73
74#ifdef DEBUG
75      verboseMode = new Menu(CONFIG_NAME_VERBOSE_MODE, "nothing",
76#if DEBUG >=1
77                             "error",
78#endif
79#if DEBUG >=2
80                             "warning",
81#endif
82#if DEBUG >=3
83                             "info",
84#endif
85#if DEBUG >=4
86                             "debug",
87#endif
88#if DEBUG >=5
89                             "heavydebug",
90#endif
91                             "lastItem");
92      verboseMode->setFlagName("verbose", "v", 2);
93      verboseMode->setDescription("Sets the Output Mode", "This Enables Outbug messages\n"
94                                  "0: nothing will be displayed, but stuff one cannot do without (eg.GUI)\n"
95#if DEBUG >=1
96                                  "1: error: outputs all the above and errors"
97#endif
98#if DEBUG >=2
99                                  "2: warning: outputs all the above plus warnings"
100#endif
101#if DEBUG >=3
102                                  "3: info: outputs all the above plus Information"
103#endif
104#if DEBUG >=4
105                                  "4: debug: displays all the above plus debug information"
106#endif
107#if DEBUG >=5
108                                  "5: heavydebug: displays all the above plus heavy debug information: WARNING: the game will run very slow with this."
109#endif
110                                  );
111      verboseMode->saveability();
112      execBox->fill(verboseMode);
113#endif
114
115      alwaysShow = new CheckButton(CONFIG_NAME_ALWAYS_SHOW_GUI);
116      alwaysShow->setFlagName("gui", "g", 0);
117      alwaysShow->setDescription("shows the gui when starting orxonox");
118      alwaysShow->saveability();
119      execBox->fill(alwaysShow);
120
121      quit = new Button("Quit");
122#ifdef HAVE_GTK2
123      quit->connectSignal("clicked", this, GuiExec::quitGui);
124      //  Window::mainWindow->connectSignal("remove", this, GuiExec::quitGui);
125      Window::mainWindow->connectSignal("destroy", this, GuiExec::quitGui);
126#endif /* HAVE_GTK2 */
127      execBox->fill(quit);
128    }
129    execFrame->fill(execBox);
130  }
131  setMainWidget(execFrame);
132}
133
134/**
135 *  Destructs the Execution-stuff
136*/
137GuiExec::~GuiExec()
138{
139  if(this->confFile)
140    delete []this->confFile;
141  if(this->confDir)
142    delete []this->confDir;
143}
144
145/* FILE HANDLING */
146
147/**
148 *  sets the Directory of the configuration files
149 * @param confDir the Directory for the configuration files
150*/
151void GuiExec::setConfDir(const char* confDir)
152{
153  this->confDir = ResourceManager::homeDirCheck(confDir);
154
155  PRINTF(5)("Config Directory is: %s.\n", this->confDir);
156  //! @todo F** Windows-support
157#ifndef __WIN32__
158  mkdir(this->confDir, 0755);
159#else /* __WiN32__ */
160  mkdir(this->confDir);
161#endif /* __WIN32__ */
162}
163
164/**
165 *  Sets the location of the configuration File.
166 * @param fileName the location of the configFile
167
168   The name will be parsed from ~/ to /home/[username] on unix and c:/Documents and Settings/username/Settings/ on Windows
169*/
170void GuiExec::setConfFile(const char* fileName)
171{
172  if (!this->confDir)
173    this->setConfDir("~/");
174  this->confFile = new char[strlen(this->confDir)+strlen(fileName)+2];
175  sprintf(this->confFile, "%s/%s", this->confDir, fileName);
176  PRINTF(5)("ConfigurationFile is %s.\n", this->confFile);
177}
178
179/**
180 * @returns The name of the Configuration-File
181*/
182const char* GuiExec::getConfigFile() const
183{
184  return this->confFile;
185}
186
187/**
188 *  checks if a option should be saved.
189 * @return 1 if it should 0 if not/
190*/
191int GuiExec::shouldsave()
192{
193  return(static_cast<Option*>(this->saveSettings)->value);
194}
195
196/**
197  *  Saves the configuration-file to the Disk.\n
198  * @param widget from which Widget on should be saved.
199
200    this Function only opens and closes the file, in between GuiExec::writeFileText(Widget* widget) will execute the real writing process.
201*/
202void GuiExec::writeToFile(Widget* widget)
203{
204  this->CONFIG_FILE = fopen(this->confFile, "w");
205  if(this->CONFIG_FILE)
206    this->writeFileText(widget, 0);
207  fclose(this->CONFIG_FILE);
208}
209
210/**
211 *  Actually writes into the configuration file to the disk.
212 * @param widget from which Widget on should be saved.
213 * @param depth initially "0", and grows higher, while new Groups are bundeled.
214*/
215void GuiExec::writeFileText(Widget* widget, int depth)
216{
217  int counter = 0;
218  while(counter < depth &&((widget->optionType > GUI_NOTHING
219                              &&(static_cast<Option*>(widget)->isSaveable()))
220                             ||(widget->optionType < GUI_NOTHING
221                                && static_cast<Packer*>(widget)->getGroupName())))
222    {
223      fprintf(this->CONFIG_FILE, "  ", depth);
224      counter++;
225    }
226
227  // check if it is a Packer, and if it is, check if it has a name and if there is something in it.
228  if(widget->optionType < GUI_NOTHING)
229    {
230      if(static_cast<Packer*>(widget)->getGroupName())
231        {
232          fprintf(CONFIG_FILE, "[%s]\n", static_cast<Packer*>(widget)->getGroupName());
233          this->writeFileText(static_cast<Packer*>(widget)->down, depth+1);
234          fprintf(CONFIG_FILE, "\n");
235        }
236      else
237        {
238          this->writeFileText(static_cast<Packer*>(widget)->down, depth);
239        }
240    }
241
242  if(widget->optionType > GUI_NOTHING)
243    if (static_cast<Option*>(widget)->isSaveable())
244      {
245        char Buffer[256];
246        char* space2under;
247        strcpy(Buffer, static_cast<Option*>(widget)->title);
248        if(strchr(Buffer, '_'))
249          PRINTF(2)("Optionname %s is not Valid for Saving, because it includes an underscore\n", Buffer);
250        while(space2under = strchr(Buffer, ' '))
251          {
252            space2under[0] = '_';
253          }
254          fprintf(CONFIG_FILE, "%s = %s\n", Buffer, static_cast<Option*>(widget)->save());
255      }
256
257  if(widget->next != NULL)
258    this->writeFileText(widget->next, depth);
259}
260
261/**
262 *  Reads in Configuration Data.
263 * @param widget from which Widget on should be saved.
264*/
265void GuiExec::readFromFile(Widget* widget)
266{
267
268  char* fileName = ResourceManager::homeDirCheck(confFile);
269  IniParser iniParser(fileName);
270  delete fileName;
271  if (!iniParser.isOpen())
272    return;
273
274  iniParser.getFirstSection();
275  Widget* groupWidget = widget;
276  const char* groupName;
277  const char* widgetName;
278  VarInfo varInfo;
279  while (groupName = iniParser.getCurrentSection())
280  {
281    if((groupWidget = locateGroup(widget, groupName, 1))==NULL)
282    {
283      PRINTF(2)("!!There is no group called %s in this GUI.\n First best Widget will get the Infos assigned.\n Config-File will be updated in next Save\n", groupName);
284      groupWidget = widget;
285      continue;
286    }
287    else
288      PRINT(0)("Group %s located.\n", static_cast<Packer*>(groupWidget)->groupName);
289
290    iniParser.getFirstVar();
291    while(iniParser.getCurrentName())
292    {
293      varInfo.variableName = iniParser.getCurrentName();
294      varInfo.variableValue = iniParser.getCurrentValue();
295      groupWidget->walkThrough(this->readFileText, &varInfo, 0);
296      iniParser.nextVar();
297    }
298
299    iniParser.nextSection();
300  }
301  widget->walkThrough(widget->setOptions, 0);
302
303//
304//
305//   this->CONFIG_FILE = fopen(this->confFile, "r");
306//   VarInfo varInfo;
307//   if(this->CONFIG_FILE)
308//     {
309//       Widget* groupWidget = widget;
310//       char Buffer[256] = "";
311//       char Variable[256]= "";
312//       char* Value;
313//       while(fscanf(this->CONFIG_FILE, "%s", Buffer) != EOF)
314//         {
315//           // group-search //
316//           if(!strncmp(Buffer, "[", 1))
317//             {
318//               if((groupWidget = locateGroup(widget, Buffer, 1))==NULL)
319//                 {
320//                   PRINTF(2)("!!There is no group called %s in this GUI.\n First best Widget will get the Infos assigned.\n Config-File will be updated in next Save\n", Buffer);
321//                   groupWidget = widget;
322//                 }
323//               else
324//                 PRINT(5)("Group %s located.\n", static_cast<Packer*>(groupWidget)->groupName);
325//             }
326//           // option-setting //
327//           if(!strcmp(Buffer, "="))
328//             {
329//               char* under2space;
330//               while(under2space = strchr(Variable, '_'))
331//                 {
332//                   sprintf(under2space, " %s", under2space+1);
333//                 }
334//
335//               fscanf(this->CONFIG_FILE, "%s", Buffer);
336//               varInfo.variableName = Variable;
337//               varInfo.variableValue = Buffer;
338//               groupWidget->walkThrough(this->readFileText, &varInfo, 0);
339//               sprintf(Variable, "");
340//             }
341//           sprintf(Variable, "%s", Buffer);
342//         }
343//       widget->walkThrough(widget->setOptions, 0);
344//     }
345//     fclose(this->CONFIG_FILE);
346}
347
348/**
349 *  Maps Confugurations to the Options.
350 * @param widget which widget downwards
351 * @param varInfo Information about the Variable to read
352*/
353void GuiExec::readFileText(Widget* widget, void* varInfo)
354{
355  VarInfo* info =(VarInfo*)varInfo;
356  if(widget->title && !strcmp(widget->title, info->variableName))
357    {
358      PRINT(5)("Located Option %s.\n", widget->title);
359      if(widget->optionType > GUI_NOTHING)
360        static_cast<Option*>(widget)->load(info->variableValue);
361    }
362}
363
364/**
365 *  Locates a Group.
366 * @param widget The Widget from where to search from
367 * @param groupName The GroupName for which to search.
368 * @param depth The Depth of the search seen from the first widget we searched from.
369 * @returns The Widget that holds the Group, or the NULL if the Group wasn't found.
370
371   @todo do this in gui-gtk.
372*/
373Widget* GuiExec::locateGroup(Widget* widget, const char* groupName, int depth)
374{
375  Widget* tmp;
376
377  if(widget->optionType < GUI_NOTHING)
378    {
379      if(static_cast<Packer*>(widget)->getGroupName() &&
380         !strcmp(groupName, static_cast<Packer*>(widget)->getGroupName()))
381        {
382          return widget;
383        }
384      else
385        {
386          if((tmp = locateGroup(static_cast<Packer*>(widget)->down, groupName, depth+1)) != NULL)
387            return tmp;
388        }
389    }
390
391  if(widget->next != NULL && depth != 0)
392    {
393      if((tmp = locateGroup(widget->next, groupName, depth)) != NULL)
394        return tmp;
395    }
396  return NULL;
397}
398
399/**
400 *  Starts ORXONOX.(not really implemented yet, but the function is there.\n
401 * @param widget the widget that executed the start command
402 * @param data additional data
403
404   This is a Signal and can be executed through Widget::signal_connect
405*/
406#ifdef HAVE_GTK2
407int GuiExec::startOrxonox(GtkWidget* widget, void* data)
408#else /* HAVE_GTK2 */
409int GuiExec::startOrxonox(void* widget, void* data)
410#endif /* HAVE_GTK2 */
411{
412  Window::mainWindow->hide();
413
414#ifdef HAVE_GTK2
415  gtk_widget_destroy(Window::mainWindow->widget);
416#else
417  quitGui(widget, data);
418#endif /* HAVE_GTK2 */
419
420  PRINT(3)("Starting Orxonox\n");
421  Gui::startOrxonox = true;
422}
423
424/**
425 *  Starts ORXONOX.(not really implemented yet, but the function is there.\n
426 * @param widget the widget that executed the start command
427 * @param data additional data
428
429   This is a Signal and can be executed through Widget::signal_connect
430*/
431#ifdef HAVE_GTK2
432int GuiExec::quitGui(GtkWidget* widget, void* data)
433#else /* HAVE_GTK2 */
434int GuiExec::quitGui(void* widget, void* data)
435#endif /* HAVE_GTK2 */
436{
437  GuiExec* exec = (GuiExec*)data;
438  if(exec->shouldsave())
439    exec->writeToFile(Window::mainWindow);
440#ifdef HAVE_GTK2
441  gtk_main_quit();
442  while(gtk_events_pending()) gtk_main_iteration();
443#endif /* HAVE_GTK2 */
444}
Note: See TracBrowser for help on using the repository browser.