Frederic Bouvier:
I made some changes to current CVS : - the window is gently resizable, keeping the buttons' height unchanged, with a minimun size, - the current activity ( installation or removal ) is displayed in the progress bar, - the progress status is exact. For installation, I am using the total bytes read vs the file size. I had to hack untarka somehow and bzip2 and Z methods needs to be implemented. For removal, I am counting files by in-depth traversal, in the same way remove_dir is working. This seems very quick and the overhead is unnoticable. - the Quit button is the only way to quit the program, and it is deactivated during work. Otherwise, we can get the window hidden but the program still running in background. - cleanup on start options that seemed to be copied from fgrun. Valid options are now : --silent to write fgadmin.prefs and stop immediately --install-source=<DIR> --scenery-dest=<DIR>
This commit is contained in:
parent
00002357b3
commit
c16feaa963
6 changed files with 146 additions and 46 deletions
|
@ -1,6 +1,14 @@
|
|||
// generated by Fast Light User Interface Designer (fluid) version 1.0104
|
||||
|
||||
#include "fgadmin.h"
|
||||
#include <FL/fl_ask.H>
|
||||
|
||||
inline void FGAdminUI::cb_main_window_i(Fl_Double_Window*, void*) {
|
||||
fl_alert("Use the Quit button to exit fgadmin");
|
||||
}
|
||||
void FGAdminUI::cb_main_window(Fl_Double_Window* o, void* v) {
|
||||
((FGAdminUI*)(o->user_data()))->cb_main_window_i(o,v);
|
||||
}
|
||||
|
||||
inline void FGAdminUI::cb_quit_b_i(Fl_Button*, void*) {
|
||||
quit();
|
||||
|
@ -46,7 +54,7 @@ FGAdminUI::FGAdminUI() {
|
|||
Fl_Double_Window* w;
|
||||
{ Fl_Double_Window* o = main_window = new Fl_Double_Window(465, 435, "FlightGear Admin Wizard");
|
||||
w = o;
|
||||
o->user_data((void*)(this));
|
||||
o->callback((Fl_Callback*)cb_main_window, (void*)(this));
|
||||
{ Fl_Button* o = quit_b = new Fl_Button(360, 405, 85, 25, "Quit");
|
||||
o->callback((Fl_Callback*)cb_quit_b);
|
||||
}
|
||||
|
@ -58,8 +66,12 @@ FGAdminUI::FGAdminUI() {
|
|||
o->callback((Fl_Callback*)cb_dest_b);
|
||||
}
|
||||
dest_text = new Fl_Input(235, 35, 225, 25);
|
||||
install_box = new Fl_Check_Browser(5, 65, 225, 270, "Select Files to Install");
|
||||
remove_box = new Fl_Check_Browser(235, 65, 225, 270, "Select Files to Remove");
|
||||
{ Fl_Group* o = new Fl_Group(5, 65, 455, 270);
|
||||
install_box = new Fl_Check_Browser(5, 65, 225, 270, "Select Files to Install");
|
||||
remove_box = new Fl_Check_Browser(235, 65, 225, 270, "Select Files to Remove");
|
||||
o->end();
|
||||
Fl_Group::current()->resizable(o);
|
||||
}
|
||||
{ Fl_Button* o = install_b = new Fl_Button(20, 360, 195, 35, "Install Selected Files");
|
||||
o->labelfont(1);
|
||||
o->callback((Fl_Callback*)cb_install_b);
|
||||
|
@ -68,7 +80,7 @@ FGAdminUI::FGAdminUI() {
|
|||
o->labelfont(1);
|
||||
o->callback((Fl_Callback*)cb_remove_b);
|
||||
}
|
||||
{ Fl_Progress* o = progress = new Fl_Progress(20, 405, 195, 25);
|
||||
{ Fl_Progress* o = progress = new Fl_Progress(5, 405, 345, 25);
|
||||
o->color(FL_BACKGROUND_COLOR);
|
||||
o->selection_color((Fl_Color)175);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ decl {\#include <string>} {public
|
|||
decl {\#include <FL/Fl_Preferences.H>} {public
|
||||
}
|
||||
|
||||
decl {\#include <FL/fl_ask.H>} {}
|
||||
|
||||
decl {using std::string;} {public
|
||||
}
|
||||
|
||||
|
@ -19,8 +21,9 @@ class FGAdminUI {open
|
|||
Function {FGAdminUI()} {open
|
||||
} {
|
||||
Fl_Window main_window {
|
||||
label {FlightGear Admin Wizard} open
|
||||
xywh {294 195 465 435} type Double visible
|
||||
label {FlightGear Admin Wizard}
|
||||
callback {fl_alert("Use the Quit button to exit fgadmin");} open
|
||||
xywh {500 247 465 435} type Double resizable visible
|
||||
} {
|
||||
Fl_Button quit_b {
|
||||
label Quit
|
||||
|
@ -45,13 +48,17 @@ refresh_lists();}
|
|||
Fl_Input dest_text {
|
||||
xywh {235 35 225 25}
|
||||
}
|
||||
Fl_Check_Browser install_box {
|
||||
label {Select Files to Install}
|
||||
xywh {5 65 225 270}
|
||||
}
|
||||
Fl_Check_Browser remove_box {
|
||||
label {Select Files to Remove}
|
||||
xywh {235 65 225 270}
|
||||
Fl_Group {} {open
|
||||
xywh {5 65 455 270} resizable
|
||||
} {
|
||||
Fl_Check_Browser install_box {
|
||||
label {Select Files to Install}
|
||||
xywh {5 65 225 270}
|
||||
}
|
||||
Fl_Check_Browser remove_box {
|
||||
label {Select Files to Remove}
|
||||
xywh {235 65 225 270}
|
||||
}
|
||||
}
|
||||
Fl_Button install_b {
|
||||
label {Install Selected Files}
|
||||
|
@ -63,8 +70,8 @@ refresh_lists();}
|
|||
callback {remove_selected();}
|
||||
xywh {250 360 195 35} labelfont 1
|
||||
}
|
||||
Fl_Progress progress {selected
|
||||
xywh {20 405 195 25} color 49 selection_color 175
|
||||
Fl_Progress progress {
|
||||
xywh {5 405 345 25} color 49 selection_color 175
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +81,9 @@ refresh_lists();}
|
|||
}
|
||||
decl {void show();} {public
|
||||
}
|
||||
decl {static void step( void * );} {public
|
||||
decl {static void step( void * );} {selected public
|
||||
}
|
||||
decl {static void step( void *, int );} {public
|
||||
}
|
||||
decl {void refresh_lists();} {}
|
||||
decl {void quit();} {}
|
||||
|
@ -87,4 +96,5 @@ refresh_lists();}
|
|||
decl {Fl_Preferences *prefs;} {}
|
||||
decl {string source;} {}
|
||||
decl {string dest;} {}
|
||||
decl {string progress_label;} {}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ using std::string;
|
|||
#include <FL/Fl_Double_Window.H>
|
||||
#include <FL/Fl_Button.H>
|
||||
#include <FL/Fl_Input.H>
|
||||
#include <FL/Fl_Group.H>
|
||||
#include <FL/Fl_Check_Browser.H>
|
||||
#include <FL/Fl_Progress.H>
|
||||
|
||||
|
@ -16,6 +17,10 @@ class FGAdminUI {
|
|||
public:
|
||||
FGAdminUI();
|
||||
Fl_Double_Window *main_window;
|
||||
private:
|
||||
inline void cb_main_window_i(Fl_Double_Window*, void*);
|
||||
static void cb_main_window(Fl_Double_Window*, void*);
|
||||
public:
|
||||
Fl_Button *quit_b;
|
||||
private:
|
||||
inline void cb_quit_b_i(Fl_Button*, void*);
|
||||
|
@ -50,6 +55,7 @@ public:
|
|||
void init();
|
||||
void show();
|
||||
static void step( void * );
|
||||
static void step( void *, int );
|
||||
private:
|
||||
void refresh_lists();
|
||||
void quit();
|
||||
|
@ -62,5 +68,6 @@ private:
|
|||
Fl_Preferences *prefs;
|
||||
string source;
|
||||
string dest;
|
||||
string progress_label;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <direct.h>
|
||||
|
@ -42,6 +43,9 @@ using std::endl;
|
|||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
extern string def_install_source;
|
||||
extern string def_scenery_dest;
|
||||
|
||||
static const float min_progress = 0.0;
|
||||
static const float max_progress = 5000.0;
|
||||
|
||||
|
@ -57,11 +61,11 @@ void FGAdminUI::init() {
|
|||
"flightgear.org",
|
||||
"fgadmin" );
|
||||
char buf[FL_PATH_MAX];
|
||||
prefs->get( "install-source", buf, "", FL_PATH_MAX );
|
||||
prefs->get( "install-source", buf, def_install_source.c_str(), FL_PATH_MAX );
|
||||
source_text->value( buf );
|
||||
source = buf;
|
||||
|
||||
prefs->get( "scenery-dest", buf, "", FL_PATH_MAX );
|
||||
prefs->get( "scenery-dest", buf, def_scenery_dest.c_str(), FL_PATH_MAX );
|
||||
dest_text->value( buf );
|
||||
dest = buf;
|
||||
|
||||
|
@ -69,6 +73,8 @@ void FGAdminUI::init() {
|
|||
|
||||
progress->minimum( min_progress );
|
||||
progress->maximum( max_progress );
|
||||
|
||||
main_window->size_range( 465, 435 );
|
||||
}
|
||||
|
||||
// show our UI
|
||||
|
@ -249,6 +255,7 @@ void FGAdminUI::install_selected() {
|
|||
|
||||
install_b->deactivate();
|
||||
remove_b->deactivate();
|
||||
quit_b->deactivate();
|
||||
|
||||
// traverse install box and install each item
|
||||
for ( int i = 0; i <= install_box->nitems(); ++i ) {
|
||||
|
@ -256,14 +263,23 @@ void FGAdminUI::install_selected() {
|
|||
f = install_box->text( i );
|
||||
SGPath file( source );
|
||||
file.append( f );
|
||||
cout << "installing " << file.str() << endl;
|
||||
struct stat info;
|
||||
stat( file.str().c_str(), &info );
|
||||
float old_max = progress->maximum();
|
||||
progress->maximum( info.st_size );
|
||||
progress_label = "Installing ";
|
||||
progress_label += f;
|
||||
progress->label( progress_label.c_str() );
|
||||
progress->value( min_progress );
|
||||
main_window->cursor( FL_CURSOR_WAIT );
|
||||
tarextract( (char *)file.c_str(), (char *)dest.c_str(), true, &FGAdminUI::step, this );
|
||||
progress->value( min_progress );
|
||||
main_window->cursor( FL_CURSOR_DEFAULT );
|
||||
progress->label( "" );
|
||||
progress->maximum( old_max );
|
||||
}
|
||||
}
|
||||
quit_b->activate();
|
||||
install_b->activate();
|
||||
remove_b->activate();
|
||||
|
||||
|
@ -271,7 +287,28 @@ void FGAdminUI::install_selected() {
|
|||
}
|
||||
|
||||
|
||||
static void remove_dir( const char *dir_name, void (*step)(void*), void *data ) {
|
||||
static unsigned long count_dir( const char *dir_name ) {
|
||||
ulDir *dir = ulOpenDir( dir_name ) ;
|
||||
ulDirEnt *ent;
|
||||
unsigned long cnt = 0L;
|
||||
while ( ent = ulReadDir( dir ) ) {
|
||||
if ( strcmp( ent->d_name, "." ) == 0 ) {
|
||||
// ignore "."
|
||||
} else if ( strcmp( ent->d_name, ".." ) == 0 ) {
|
||||
// ignore ".."
|
||||
} else if ( ent->d_isdir ) {
|
||||
SGPath child( dir_name );
|
||||
child.append( ent->d_name );
|
||||
cnt += count_dir( child.c_str() );
|
||||
} else {
|
||||
cnt += 1;
|
||||
}
|
||||
}
|
||||
ulCloseDir( dir );
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static void remove_dir( const char *dir_name, void (*step)(void*,int), void *data ) {
|
||||
ulDir *dir = ulOpenDir( dir_name ) ;
|
||||
ulDirEnt *ent;
|
||||
while ( ent = ulReadDir( dir ) ) {
|
||||
|
@ -287,7 +324,7 @@ static void remove_dir( const char *dir_name, void (*step)(void*), void *data )
|
|||
SGPath child( dir_name );
|
||||
child.append( ent->d_name );
|
||||
unlink( child.c_str() );
|
||||
if (step) step( data );
|
||||
if (step) step( data, 1 );
|
||||
}
|
||||
}
|
||||
ulCloseDir( dir );
|
||||
|
@ -301,20 +338,28 @@ void FGAdminUI::remove_selected() {
|
|||
|
||||
install_b->deactivate();
|
||||
remove_b->deactivate();
|
||||
quit_b->deactivate();
|
||||
// traverse remove box and recursively remove each item
|
||||
for ( int i = 0; i <= remove_box->nitems(); ++i ) {
|
||||
if ( remove_box->checked( i ) ) {
|
||||
f = remove_box->text( i );
|
||||
SGPath dir( dest );
|
||||
dir.append( f );
|
||||
float old_max = progress->maximum();
|
||||
progress_label = "Removing ";
|
||||
progress_label += f;
|
||||
progress->label( progress_label.c_str() );
|
||||
progress->value( min_progress );
|
||||
main_window->cursor( FL_CURSOR_WAIT );
|
||||
cout << "removing " << dir.str() << endl;
|
||||
progress->maximum( count_dir( dir.c_str() ) );
|
||||
remove_dir( dir.c_str(), &FGAdminUI::step, this );
|
||||
progress->value( min_progress );
|
||||
main_window->cursor( FL_CURSOR_DEFAULT );
|
||||
progress->label( "" );
|
||||
progress->maximum( old_max );
|
||||
}
|
||||
}
|
||||
quit_b->activate();
|
||||
install_b->activate();
|
||||
remove_b->activate();
|
||||
|
||||
|
@ -322,7 +367,6 @@ void FGAdminUI::remove_selected() {
|
|||
|
||||
}
|
||||
|
||||
|
||||
void FGAdminUI::step(void *data)
|
||||
{
|
||||
Fl_Progress *p = ((FGAdminUI*)data)->progress;
|
||||
|
@ -338,3 +382,13 @@ void FGAdminUI::step(void *data)
|
|||
|
||||
Fl::check();
|
||||
}
|
||||
|
||||
void FGAdminUI::step(void *data, int n)
|
||||
{
|
||||
Fl_Progress *p = ((FGAdminUI*)data)->progress;
|
||||
|
||||
float tmp = p->value() + n;
|
||||
p->value( tmp );
|
||||
|
||||
Fl::check();
|
||||
}
|
||||
|
|
|
@ -27,41 +27,39 @@
|
|||
|
||||
#include <string>
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/filename.H>
|
||||
|
||||
#include "fgadmin.h"
|
||||
|
||||
std::string def_fg_exe = "";
|
||||
std::string def_fg_root = "";
|
||||
std::string def_fg_scenery = "";
|
||||
using std::string;
|
||||
|
||||
string def_install_source;
|
||||
string def_scenery_dest;
|
||||
bool silent = false;
|
||||
|
||||
/**
|
||||
* --fg-exe=<PATH>
|
||||
* --fg-root=<DIR>
|
||||
* --fg-scenery=<DIR>
|
||||
* --silent
|
||||
* --install-source=<DIR>
|
||||
* --scenery-dest=<DIR>
|
||||
*/
|
||||
static int
|
||||
parse_args( int, char** argv, int& i )
|
||||
{
|
||||
if (strncmp( argv[i], "--fg-exe=", 9 ) == 0)
|
||||
if (strcmp( argv[i], "--silent" ) == 0)
|
||||
{
|
||||
def_fg_exe.assign( &argv[i][9] );
|
||||
silent = true;
|
||||
++i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strncmp( argv[i], "--fg-root=", 10 ) == 0)
|
||||
else if (strncmp( argv[i], "--install-source=", 17 ) == 0)
|
||||
{
|
||||
def_fg_root.assign( &argv[i][10] );
|
||||
def_fg_scenery = def_fg_root;
|
||||
def_fg_scenery += "/Scenery";
|
||||
|
||||
def_install_source.assign( &argv[i][17] );
|
||||
++i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strncmp( argv[i], "--fg-scenery=", 13 ) == 0)
|
||||
else if (strncmp( argv[i], "--scenery-dest=", 15 ) == 0)
|
||||
{
|
||||
def_fg_scenery.assign( &argv[i][13] );
|
||||
def_scenery_dest.assign( &argv[i][15] );
|
||||
++i;
|
||||
return 1;
|
||||
}
|
||||
|
@ -75,7 +73,21 @@ main( int argc, char* argv[] )
|
|||
int i = 0;
|
||||
if (Fl::args( argc, argv, i, parse_args ) < argc)
|
||||
{
|
||||
Fl::fatal("Options are:\n --fg-exe=<PATH>\n --fg-root=<DIR>\n --fg-scenery=<DIR>\n%s", Fl::help );
|
||||
Fl::fatal("Options are:\n --silent\n --install-source=<DIR>\n --scenery-dest=<DIR>\n%s", Fl::help );
|
||||
}
|
||||
|
||||
if ( silent )
|
||||
{
|
||||
Fl_Preferences prefs( Fl_Preferences::USER, "flightgear.org", "fgadmin" );
|
||||
char abs_name[ FL_PATH_MAX ];
|
||||
|
||||
fl_filename_absolute( abs_name, def_install_source.c_str() );
|
||||
prefs.set( "install-source", abs_name );
|
||||
|
||||
fl_filename_absolute( abs_name, def_scenery_dest.c_str() );
|
||||
prefs.set( "scenery-dest", abs_name );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FGAdminUI ui;
|
||||
|
|
|
@ -101,6 +101,8 @@
|
|||
|
||||
static void error OF((const char *msg));
|
||||
|
||||
static unsigned long total_read;
|
||||
|
||||
/* #define TAR_GZ 1 */
|
||||
|
||||
typedef struct Readable {
|
||||
|
@ -117,10 +119,11 @@ typedef struct Readable {
|
|||
enum { FMT_U=1, FMT_Z=2, FMT_GZ=3, FMT_BZ2=4 };
|
||||
|
||||
/* #define xFILE FILE* */
|
||||
static int xU_Open4Read(struct Readable* self, char const* filename) { return NULL==(self->f=fopen(filename,"rb")); }
|
||||
static int xU_Open4Read(struct Readable* self, char const* filename) { total_read=0; return NULL==(self->f=fopen(filename,"rb")); }
|
||||
static int xU_Close(struct Readable* self) { return fclose((FILE*)self->f); }
|
||||
static unsigned xU_Read(struct Readable* self, void* buf, unsigned len) {
|
||||
unsigned got=fread(buf,1,len,(FILE*)self->f);
|
||||
total_read+=got;
|
||||
return got>0 ? got : ferror((FILE*)self->f) ? 0U-1 : 0;
|
||||
}
|
||||
static char const* xU_Error(struct Readable* self, int *errnum_ret) { return (*errnum_ret=ferror((FILE*)self->f))?"I/O error":"OK"; }
|
||||
|
@ -154,9 +157,9 @@ static char const* xZ_Error(struct Readable* self, int *errnum_ret) {
|
|||
#if HAVE_ZLIB
|
||||
#include "zlib.h"
|
||||
/* #define xFILE gzFile */
|
||||
static int xGZ_Open4Read(struct Readable* self, char const* filename) { return NULL==(self->f=gzopen(filename,"rb")); }
|
||||
static int xGZ_Open4Read(struct Readable* self, char const* filename) { total_read=0; return NULL==(self->f=gzopen(filename,"rb")); }
|
||||
static int xGZ_Close(struct Readable* self) { return gzclose((gzFile)self->f); }
|
||||
static unsigned xGZ_Read(struct Readable* self, void* buf, unsigned len) { return gzread((gzFile)self->f,buf,len); }
|
||||
static unsigned xGZ_Read(struct Readable* self, void* buf, unsigned len) { unsigned l=gzread((gzFile)self->f,buf,len); total_read=((z_streamp)self->f)->total_in; return l; }
|
||||
static char const* xGZ_Error(struct Readable* self, int *errnum_ret) { return gzerror((gzFile)self->f, errnum_ret); }
|
||||
#endif
|
||||
|
||||
|
@ -1166,7 +1169,7 @@ static int matchname (int arg,int argc,char **argv,char *fname)
|
|||
|
||||
/* Tar file list or extract */
|
||||
|
||||
static int tar (Readable* rin,int action,int arg,int argc,char **argv, char const* TGZfile, int verbose, void (*step)(void *), void *data) {
|
||||
static int tar (Readable* rin,int action,int arg,int argc,char **argv, char const* TGZfile, int verbose, void (*step)(void *,int), void *data) {
|
||||
union tar_buffer buffer;
|
||||
int is_tar_ok=0;
|
||||
int len;
|
||||
|
@ -1176,6 +1179,7 @@ static int tar (Readable* rin,int action,int arg,int argc,char **argv, char cons
|
|||
FILE *outfile = NULL;
|
||||
char fname[BLOCKSIZE];
|
||||
time_t tartime;
|
||||
unsigned long last_read;
|
||||
|
||||
#if 0
|
||||
while (0<(len=rin->xRead(rin, &buffer, BLOCKSIZE))) {
|
||||
|
@ -1184,6 +1188,7 @@ static int tar (Readable* rin,int action,int arg,int argc,char **argv, char cons
|
|||
exit(0);
|
||||
#endif
|
||||
|
||||
last_read = 0;
|
||||
if (action == TGZ_LIST)
|
||||
printf(" day time size file\n"
|
||||
" ---------- -------- --------- -------------------------------------\n");
|
||||
|
@ -1191,6 +1196,7 @@ static int tar (Readable* rin,int action,int arg,int argc,char **argv, char cons
|
|||
len = rin->xRead(rin, &buffer, BLOCKSIZE);
|
||||
if (len+1 == 0)
|
||||
error (rin->xError(rin, &err));
|
||||
if (step) { step(data,total_read - last_read); last_read = total_read; }
|
||||
if (!is_tar_ok && !(is_tar_ok=is_tar(buffer.buffer, len))) {
|
||||
fprintf(stderr, "%s: compressed file not tared: %s\n", prog, TGZfile);
|
||||
if (action == TGZ_EXTRACT) {
|
||||
|
@ -1341,7 +1347,6 @@ static int tar (Readable* rin,int action,int arg,int argc,char **argv, char cons
|
|||
outfile = NULL;
|
||||
utime(fname,&settime);
|
||||
#endif
|
||||
if (step) step(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue