Advanced Strategic Command
fileselector.cpp
Go to the documentation of this file.
1 /*
2  This file is part of Advanced Strategic Command; http://www.asc-hq.de
3  Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
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 of the License, or
8  (at your option) 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; see the file COPYING. If not, write to the
17  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  Boston, MA 02111-1307 USA
19 */
20 
21 
22 #include "fileselector.h"
23 #include "../dialog.h"
24 #include "../iconrepository.h"
25 
26 #include "../widgets/textrenderer.h"
27 #include "../graphics/blitter.h"
28 #include "../graphics/drawing.h"
29 #include "../loaders.h"
30 
31 
32 
34 {
35  FileInfo fileInfo;
36  ASCString time;
37  public:
38  FileWidget( PG_Widget* parent, const PG_Point& pos, int width, const FileInfo* fi ) : SelectionWidget( parent, PG_Rect( pos.x, pos.y, width, 18 )), fileInfo( *fi ) {
39 #ifndef ctime_r
40  char* c = ctime( &fileInfo.modificationTime );
41  if ( c )
42  time = c;
43  else
44  time = "-";
45 #else
46 
47  char c[100];
48  ctime_r( &fileInfo.modificationTime, c );
49  time = c;
50 #endif
51  int col1 = width * 3 / 9;
52  int col2 = col1 + width * 3 / 9;
53 
54  PG_Label* lbl1 = new PG_Label( this, PG_Rect( 0, 0, col1 - 10, Height() ), fileInfo.name );
55  lbl1->SetFontSize( lbl1->GetFontSize() -2 );
56 
57  PG_Label* lbl2 = new PG_Label( this, PG_Rect( col1, 0, col2-col1-10, Height() ), time );
58  lbl2->SetFontSize( lbl2->GetFontSize() -2 );
59 
60  PG_Label* lbl3 = new PG_Label( this, PG_Rect( col2, 0, Width() - col2, Height() ), fileInfo.location );
61  lbl3->SetFontSize( lbl3->GetFontSize() -2 );
62 
63  SetTransparency( 255 );
64  };
65 
66  ASCString getName() const {
67  return fileInfo.name;
68  };
69 
70  protected:
71 
72  void display( SDL_Surface * surface, const PG_Rect & src, const PG_Rect & dst ) {
73  }
74  ;
75 };
76 
77 SavegameWidget::SavegameWidget( PG_Widget* parent, const PG_Point& pos, int width, const FileInfo* fi )
78  : SelectionWidget( parent, PG_Rect( pos.x, pos.y, width, 110 )), fileInfo( *fi ), fileInformationLoaded(false)
79 {
80 #ifndef ctime_r
81  char* c = ctime( &fileInfo.modificationTime );
82  if ( c )
83  time = c;
84  else
85  time = "-";
86 #else
87 
88  char c[100];
89  ctime_r( &fileInfo.modificationTime, c );
90  time = c;
91 #endif
92 
93 
94  int col2 = 120;
95  int HeightRow = 20;
96 
97  new Emboss( this, PG_Rect( 1, 1, Width()-5, Height()-2), true );
98 
99  PG_Label* lbl1 = new PG_Label( this, PG_Rect( col2, 10, Width()-col2-10, HeightRow ), fileInfo.name );
100  lbl1->SetFontSize( lbl1->GetFontSize()+2 );
101 
102  mapTitleLabel = new PG_Label( this, PG_Rect( col2, 10+HeightRow, Width()-col2-10, HeightRow ), "" );
103  mapTitleLabel->SetFontSize( mapTitleLabel->GetFontSize() -2 );
104 
105 
106  PG_Label* lbl2 = new PG_Label( this, PG_Rect( col2, 10+HeightRow*2, Width()-col2-10, HeightRow ), time );
107  lbl2->SetFontSize( lbl2->GetFontSize() -2 );
108 
109  PG_Label* lbl3 = new PG_Label( this, PG_Rect( col2, 10+HeightRow*3, Width()-col2-10, HeightRow ), fileInfo.location );
110  lbl3->SetFontSize( lbl3->GetFontSize() -2 );
111 
112  if ( !alternateImage.valid() )
113  alternateImage = IconRepository::getIcon("nomappicture.png");
114 
115  SetTransparency( 255 );
116 };
117 
119 {
120  return fileInfo.name;
121 };
122 
123 
124 Surface SavegameWidget::alternateImage;
125 
126 
127 void SavegameWidget::display( SDL_Surface * surface, const PG_Rect & src, const PG_Rect & dst )
128 {
129  if ( !fileInformationLoaded ) {
130  tsavegameloaders loader;
131  gfi = loader.loadMapimageFromFile( fileInfo.name );
132  fileInformationLoaded = true;
133  ASCString s = gfi.maptitle + " - " + gfi.playername + " turn " + ASCString::toString( gfi.turn );
134  mapTitleLabel->SetText( s );
135  }
136  if ( !gfi.image.valid()) {
137  PG_Draw::BlitSurface( alternateImage.getBaseSurface(), src, surface, PG_Rect( dst.x+10, dst.y+5, dst.Width(), dst.Height() ));
138  } else {
139  PG_Draw::BlitSurface( gfi.image.getBaseSurface(), src, surface, PG_Rect( dst.x+10, dst.y+5, dst.Width(), dst.Height() ));
140  }
141 };
142 
143 
144 
146 {
147  ASCString::size_type begin = 0;
148  ASCString::size_type pos = wildcard.find( ";" );
149  do {
150  ASCString w = wildcard.substr( begin, pos );
151  if ( pos != ASCString::npos && pos+1 < wildcard.length() ) {
152  begin = pos + 1;
153  pos = wildcard.find( ";", begin );
154  } else
155  begin = pos = ASCString::npos;
156 
157  tfindfile ff ( w );
158 
160  while ( ff.getnextname( fi) ) {
161  FileInfo* fi2 = new FileInfo( fi.name, fi.location, fi.date, fi.directoryLevel );
162  items.push_back ( fi2 );
163  }
164  } while ( begin != ASCString::npos );
165 
166  sort( items.begin(), items.end(), comp );
167  restart();
168 };
169 
170 bool FileSelectionItemFactory::comp ( const FileInfo* i1, const FileInfo* i2 )
171 {
172  return i1->modificationTime > i2->modificationTime || ( (i1->modificationTime == i2->modificationTime) && (i1->name < i2->name) );
173  // return i1->name < i2->name;
174 };
175 
177 {
178  it = items.begin();
179 };
180 
182 {
183  for ( Items::iterator it = items.begin(); it != items.end(); ++it )
184  if ( (*it)->name == name )
185  return (*it)->level;
186  return -1;
187 };
188 
189 
190 SelectionWidget* FileSelectionItemFactory::spawnNextItem( PG_Widget* parent, const PG_Point& pos )
191 {
192  if ( it != items.end() )
193  return new FileWidget( parent, pos, parent->Width() - 15, *(it++) );
194  else
195  return NULL;
196 };
197 
198 
200 {
201  if ( !widget )
202  return;
203 
204  const FileWidget* fw = dynamic_cast<const FileWidget*>(widget);
205  assert( fw );
206  filenameMarked( fw->getName() );
207 }
208 
210 {
211  if ( !widget )
212  return;
213 
214  const FileWidget* fw = dynamic_cast<const FileWidget*>(widget);
215  assert( fw );
216  if ( mouse )
218  else
219  filenameSelectedKeyb( fw->getName() );
220 }
221 
222 
223 
225 {
226  // if ( !patimat ( wildcard.c_str(), filename.c_str() ))
227  this->filename = filename;
228  if ( this->filename.find('.') == ASCString::npos )
229  this->filename += wildcard.substr( wildcard.find_first_not_of("*") );
230 
231  if ( saveFile && factory ) {
232  if ( factory->getLevel( this->filename ) == 0 )
233  if ( !overwriteMessage || choice_dlg( "overwrite " + this->filename +" ?", "~y~es","~n~o") == 2) {
234  // isw->resetNamesearch();
235  this->filename = "";
236  return;
237  }
238  }
239 
240  quitModalLoop(0);
241 };
242 
244 {
245  if ( !patimat( wildcard, filename ))
246  filename += wildcard.substr(1);
247  fileNameSelected(filename);
248 };
249 
250 FileSelectionWindow::FileSelectionWindow( PG_Widget *parent, const PG_Rect &r, const ASCString& fileWildcard, bool save, bool overwriteMessage ) : ASC_PG_Dialog( parent, r, "" ), wildcard( fileWildcard), saveFile(save)
251 {
252  if ( save )
253  SetTitle( "Enter Filename" );
254  else
255  SetTitle( "Choose File" );
256 
257  this->overwriteMessage = overwriteMessage;
258 
259  factory = new FileSelectionItemFactory( fileWildcard );
260  factory->filenameSelectedMouse.connect ( sigc::mem_fun( *this, &FileSelectionWindow::fileNameSelected ));
261  factory->filenameSelectedKeyb.connect ( sigc::mem_fun( *this, &FileSelectionWindow::fileNameSelected ));
262  // factory->filenameMarked.connect ( sigc::mem_fun( *this, &FileSelectionWindow::fileNameSelected ));
263  ItemSelectorWidget* isw = new ItemSelectorWidget( this, PG_Rect(10, GetTitlebarHeight(), r.Width() - 20, r.Height() - GetTitlebarHeight()), factory );
264  if ( save ) {
265  isw->constrainNames( false );
266  isw->nameEntered.connect( sigc::mem_fun( *this, &FileSelectionWindow::fileNameEntered ));
267  }
268  isw->sigQuitModal.connect( sigc::mem_fun( *this, &ItemSelectorWindow::QuitModal));
269 
270 };
271 
272 
273 
274 ASCString selectFile( const ASCString& ext, bool load, bool overwriteMessage )
275 {
276  FileSelectionWindow fsw( NULL, PG_Rect( 10, 10, 700, 500 ), ext, !load, overwriteMessage );
277  fsw.Show();
278  fsw.RunModal();
279  return fsw.getFilename();
280 }
281 
282 
284 {
285  ASCString::size_type begin = 0;
286  ASCString::size_type pos = wildcard.find( ";" );
287  do {
288  ASCString w = wildcard.substr( begin, pos );
289  if ( pos != ASCString::npos && pos+1 < wildcard.length() ) {
290  begin = pos + 1;
291  pos = wildcard.find( ";", begin );
292  } else
293  begin = pos = ASCString::npos;
294 
295  tfindfile ff ( w );
296 
298  while ( ff.getnextname( fi) ) {
299  FileInfo* fi2 = new FileInfo( fi.name, fi.location, fi.date, fi.directoryLevel );
300  items.push_back ( fi2 );
301  }
302  } while ( begin != ASCString::npos );
303 
304  sort( items.begin(), items.end(), comp );
305  restart();
306 };
307 
309 {
310  return i1->modificationTime > i2->modificationTime || ( (i1->modificationTime == i2->modificationTime) && (i1->name < i2->name) );
311  // return i1->name < i2->name;
312 };
313 
315 {
316  it = items.begin();
317 };
318 
320 {
321  for ( Items::iterator it = items.begin(); it != items.end(); ++it )
322  if ( (*it)->name == name )
323  return (*it)->level;
324  return -1;
325 };
326 
327 
328 SelectionWidget* SavegameSelectionItemFactory::spawnNextItem( PG_Widget* parent, const PG_Point& pos )
329 {
330  if ( it != items.end() )
331  return new SavegameWidget( parent, pos, parent->Width() - 15, *(it++) );
332  else
333  return NULL;
334 };
335 
336 
338 {
339  if ( !widget )
340  return;
341 
342  const SavegameWidget* fw = dynamic_cast<const SavegameWidget*>(widget);
343  assert( fw );
344  filenameMarked( fw->getName() );
345 }
346 
348 {
349  if ( !widget )
350  return;
351 
352  const SavegameWidget* fw = dynamic_cast<const SavegameWidget*>(widget);
353  assert( fw );
354  if ( mouse )
356  else
357  filenameSelectedKeyb( fw->getName() );
358 }
359 
360 
361 
362 
364 {
365  // if ( !patimat ( wildcard.c_str(), filename.c_str() ))
366  this->filename = filename;
367  if ( this->filename.find('.') == ASCString::npos )
368  this->filename += wildcard.substr( wildcard.find_first_not_of("*") );
369 
370  if ( saveFile && factory ) {
371  if ( factory->getLevel( this->filename ) == 0 )
372  if ( !overwriteMessage || choice_dlg( "overwrite " + this->filename +" ?", "~y~es","~n~o") == 2) {
373  // isw->resetNamesearch();
374  this->filename = "";
375  return;
376  }
377  }
378 
379  quitModalLoop(0);
380 };
381 
383 {
384  if ( !patimat( wildcard, filename ))
385  filename += wildcard.substr(1);
386  fileNameSelected(filename);
387 };
388 
389 SavegameSelectionWindow::SavegameSelectionWindow( PG_Widget *parent, const PG_Rect &r, const ASCString& fileWildcard, bool save, bool overwriteMessage ) : ASC_PG_Dialog( parent, r, "" ), wildcard( fileWildcard), saveFile(save)
390 {
391  if ( save )
392  SetTitle( "Enter Filename" );
393  else
394  SetTitle( "Choose File" );
395 
396  this->overwriteMessage = overwriteMessage;
397 
398  factory = new SavegameSelectionItemFactory( fileWildcard );
399  factory->filenameSelectedMouse.connect ( sigc::mem_fun( *this, &SavegameSelectionWindow::fileNameSelected ));
400  factory->filenameSelectedKeyb.connect ( sigc::mem_fun( *this, &SavegameSelectionWindow::fileNameSelected ));
401  // factory->filenameMarked.connect ( sigc::mem_fun( *this, &SavegameSelectionWindow::fileNameSelected ));
402  ItemSelectorWidget* isw = new ItemSelectorWidget( this, PG_Rect(10, GetTitlebarHeight(), r.Width() - 20, r.Height() - GetTitlebarHeight()), factory );
403  if ( save ) {
404  isw->constrainNames( false );
405  isw->nameEntered.connect( sigc::mem_fun( *this, &SavegameSelectionWindow::fileNameEntered ));
406  }
407  isw->sigQuitModal.connect( sigc::mem_fun( *this, &ItemSelectorWindow::QuitModal));
408 
409 };
410 
411 
412 ASCString selectSavegame( const ASCString& ext, bool load, bool overwriteMessage )
413 {
414  SavegameSelectionWindow ssw( NULL, PG_Rect( -1, 10, 700, PG_Application::GetScreenHeight()-20), ext, !load, overwriteMessage );
415  ssw.Show();
416  ssw.RunModal();
417  return ssw.getFilename();
418 }
void display(SDL_Surface *surface, const PG_Rect &src, const PG_Rect &dst)
SelectionWidget * spawnNextItem(PG_Widget *parent, const PG_Point &pos)
void itemSelected(const SelectionWidget *widget, bool mouse)
Items::iterator it
Definition: fileselector.h:82
sigc::signal< void, const ASCString & > filenameSelectedKeyb
Definition: fileselector.h:100
void display(SDL_Surface *surface, const PG_Rect &src, const PG_Rect &dst)
void itemMarked(const SelectionWidget *widget)
void fileNameSelected(const ASCString &filename)
ASCString getnextname(int *loc=NULL, bool *inContainer=NULL, ASCString *location=NULL)
Returns the next entry of the internal file list.
Definition: basestrm.cpp:2211
time_t modificationTime
Definition: fileselector.h:37
sigc::signal< void, const ASCString & > filenameSelectedMouse
Definition: fileselector.h:99
static bool comp(const FileInfo *i1, const FileInfo *i2)
static bool comp(const FileInfo *i1, const FileInfo *i2)
sigc::signal< bool > sigQuitModal
SavegameSelectionItemFactory(const ASCString &wildcard)
SDL_Surface * getBaseSurface()
Definition: surface.h:116
sigc::signal< void, ASCString > nameEntered
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
ASCString getName() const
void constrainNames(bool constrain)
sigc::signal< void, const ASCString & > filenameSelectedMouse
Definition: fileselector.h:148
static ASCString toString(int i)
converts the parameter to a String
Definition: ascstring.cpp:193
SavegameSelectionWindow(PG_Widget *parent, const PG_Rect &r, const ASCString &fileWildcard, bool save, bool overwriteMessage)
SavegameWidget(PG_Widget *parent, const PG_Point &pos, int width, const FileInfo *fi)
sigc::signal< void, const ASCString & > filenameMarked
Definition: fileselector.h:101
SelectionWidget * spawnNextItem(PG_Widget *parent, const PG_Point &pos)
bool quitModalLoop(int value)
Definition: paradialog.cpp:545
int getLevel(const ASCString &name)
Adapter class for using Paragui Dialogs in ASC. This class transfers the event control from ASC to Pa...
Definition: paradialog.h:127
ASCString name
Definition: fileselector.h:35
Searching for files.
Definition: basestrm.h:484
ASCString name
Definition: basestrm.h:489
ASCString location
Definition: basestrm.h:492
ASCString playername
Definition: loaders.h:134
ASCString maptitle
Definition: loaders.h:132
GameFileInformation loadMapimageFromFile(const ASCString &filename)
Definition: loaders.cpp:1109
ASCString selectSavegame(const ASCString &ext, bool load, bool overwriteMessage)
void fileNameEntered(ASCString filename)
ASCString selectFile(const ASCString &ext, bool load, bool overwriteMessage)
void itemMarked(const SelectionWidget *widget)
FileSelectionItemFactory(const ASCString &wildcard)
static Surface & getIcon(const ASCString &name)
sigc::signal< void, const ASCString & > filenameSelectedKeyb
Definition: fileselector.h:149
FileSelectionWindow(PG_Widget *parent, const PG_Rect &r, const ASCString &fileWildcard, bool save, bool overwriteMessage)
FileWidget(PG_Widget *parent, const PG_Point &pos, int width, const FileInfo *fi)
void fileNameEntered(ASCString filename)
int getLevel(const ASCString &name)
ASCString getFilename()
Definition: fileselector.h:75
ASCString location
Definition: fileselector.h:36
int choice_dlg(const ASCString &title, const ASCString &leftButton, const ASCString &rightButton)
Definition: dialog.cpp:616
bool patimat(const char *pat, const char *str, bool forceCaseInsensitivity)
Definition: basestrm.cpp:1997
sigc::signal< void, const ASCString & > filenameMarked
Definition: fileselector.h:150
ASCString getName() const
void fileNameSelected(const ASCString &filename)
void itemSelected(const SelectionWidget *widget, bool mouse)