#!/usr/bin/perl -w # fixuifiles processes .ui files and removes some insanity: # * Too high minimum Qt version (see $minversion_* in the top of the script) # * Hardcoded untranslatable Alt+Letter accels (auto-added by Qt Designer) # * Captions that are equal to classname (auto-added by Qt Designer) # This script is licensed under the GPL version 2. # (c) 2004 David Faure # Based on fixkdeincludes, (c) 2001-2003 Dirk Mueller use strict; use File::Basename; use Cwd; # Fix the version number in .ui files if it's bigger than this: my $default_minversion_maj = 3; my $default_minversion_min = 3; # Known words which are ok as captions my %knowncaptions = ( 'Settings' => '', 'Statistics' => '', 'General' => '', 'Tracks' => '', 'Constants' => '', 'Preferences' => '', 'Encryption' => '' ); # declaration of useful subroutines sub process_ui_file($); sub find_ui_files($); sub read_required_version($); # some global variables my $verbose = 0; # turns on debugging my $omit_Qt_check = 0; # turns off Qt version checking my @explicitfiles = (); # filled in if passing files on the command line my $minversion_maj = $default_minversion_maj; my $minversion_min = $default_minversion_min; while (defined ($ARGV[0])) { $_ = shift; if (/^--help$|^-h$/) { print "Usage: fixuifiles [OPTIONS] files...\n"; print "Options are:\n"; print "\t-v, --verbose\tBe verbose\n"; print "\t--omitqtcheck\tDoes not check for Qt minimum version\n"; exit 0; } elsif (/^--verbose$|^-v$/) { $verbose = 1; }elsif (/^--omitqtcheck/) { $omit_Qt_check = 1; } elsif (!/^-/) { push @explicitfiles, $_; } } # Find .ui files in the given dir sub find_ui_files($) { my ( $dir ) = @_; opendir (DIR, "$dir") || die "Couldn't read '$dir'\n"; my @files = grep { /^.*\.ui$/ } readdir(DIR); closedir(DIR); #print "found files: [ " . join(' ', @files) . " ] in $dir\n" if ($verbose); # prefix them with $dir my @retfiles = (); foreach my $file(@files) { push @retfiles, "$dir/$file"; } return @retfiles; } # Ensure the version at the top of the file is not too high sub fix_version($) { my $srcfile = shift @_; open(SRC, "< $srcfile") || die "fix_version: couldn't open '$srcfile'\n"; my @contents = ; my @fixedcontents = (); close(SRC); my $needfix = 0; my $foundversion = 0; foreach my $line (@contents) { if (!$foundversion && $line =~ m/version=\"([0-9]+)\.([0-9]+)(\.[0-9]+)?\"/) { my $version_maj = $1; my $version_min = $2; if ( $version_maj > $minversion_maj || ( $version_maj == $minversion_maj && $version_min > $minversion_min ) ) { $line =~ s/version=\"[0-9]+\.[0-9]+\"/version=\"$minversion_maj.$minversion_min\"/o; $needfix = 1; print "$srcfile: version was $version_maj.$version_min, set to $minversion_maj.$minversion_min\n"; } $foundversion = 1; } push @fixedcontents, $line; } if (!$foundversion) { # TODO improve so that the script adds the necessary line print "$srcfile has no UI version, please fix it\n"; } if ($needfix) { open(SRC, "> $srcfile") || die "fix_version: couldn't open '$srcfile' for writing\n"; print SRC @fixedcontents; close(SRC); } } # Ensure no auto-added Alt+letter accel exists - those are untranslatable sub fix_accels($) { my $srcfile = shift @_; open(SRC, "< $srcfile") || die "fix_accels: couldn't open '$srcfile'\n"; my @contents = ; close(SRC); return if ( !grep( /Alt\+[A-Z]<\/string>/, @contents )); my @fixedcontents = (); my $firstline; my $accelsremoved = 0; my $inside_accel = 0; # inside_accel is 0 before # 1 after and before # 2 after if alt+letter, and before foreach my $line (@contents) { if ( $inside_accel == 1 ) { if ( $line =~ m/(Alt\+[A-Z])<\/string>/ ) { print "$srcfile: accel $1 removed\n" if ($verbose); $inside_accel = 2; $accelsremoved++; } else { # Not alt+letter, keep accel push @fixedcontents, $firstline; $inside_accel = 0; } } if ($line =~ m/property name=\"accel\"/) { $inside_accel = 1; $firstline = $line; } if ($inside_accel == 0) { push @fixedcontents, $line; } $inside_accel = 0 if ($inside_accel && $line =~ m/<\/property>/); } if ($accelsremoved) { print "$srcfile: $accelsremoved accels removed\n"; open(SRC, "> $srcfile") || die "fix_accels: couldn't open '$srcfile' for writing\n"; print SRC @fixedcontents; close(SRC); } } # Ensure no auto-added caption exists - it's pretty stupid to have to # translate Form1 or MyClassName sub fix_captions($) { my $srcfile = shift @_; open(SRC, "< $srcfile") || die "fix_captions: couldn't open '$srcfile'\n"; my @contents = ; close(SRC); my @fixedcontents = (); my $firstline; my $class = ""; my $captionsremoved = 0; my $inside_caption = 0; # inside_caption is 0 before # 1 after and before # 2 after if caption should be removed, and before foreach my $line (@contents) { $class = $1 if ($line =~ m/(.*)<\/class>/); if ( $inside_caption == 1 ) { $line =~ m/(.*)<\/string>/ || die "Malformed XML (no string under caption)"; my $caption = $1; print "$srcfile: caption='$caption' class='$class'\n" if ($verbose); if ( ( $caption eq $class && !defined $knowncaptions{$caption} ) || ($caption =~ m/Form[0-9]/) ) { if ( $caption =~ m/^[A-Z][a-z]*$/ ) { print "$srcfile: removing caption '$caption' (warning! could be real caption)\n"; } else { print "$srcfile: removing caption '$caption'\n"; } $inside_caption = 2; $captionsremoved++; } else { # Real caption, keep it print "$srcfile: keeping caption '$caption'\n" if ($verbose); push @fixedcontents, $firstline; $inside_caption = 0; } } if ($line =~ m/property name=\"caption\"/) { $inside_caption = 1; $firstline = $line; } if ($inside_caption == 0) { push @fixedcontents, $line; } $inside_caption = 0 if ($inside_caption && $line =~ m/<\/property>/); } if ($captionsremoved) { open(SRC, "> $srcfile") || die "fix_captions: couldn't open '$srcfile' for writing\n"; print SRC @fixedcontents; close(SRC); } } # Find a .qt_minversion in $dir or any parent directory. sub read_required_version($) { my $dir = Cwd::abs_path( shift @_ ); $minversion_maj = $default_minversion_maj; $minversion_min = $default_minversion_min; while ( length($dir) > 1 ) { my $versfile = "$dir/.qt_minversion"; my $version; if ( open (VERSFILE, "< $versfile") ) { while () { $version = $_ if (!/^#/); } close(VERSFILE); } else { $versfile = "$dir/configure.in.in"; if ( open (VERSFILE, "< $versfile") ) { while () { $version = $1 if m/^#MIN_CONFIG\(([0-9]+.[0-9]+)\)/; } close(VERSFILE); } } if (defined $version && $version =~ m/([0-9]+)\.([0-9]+)/) { $minversion_maj = $1; $minversion_min = $2; print "Found min version $1.$2 in $versfile\n" if ($verbose); return; } $dir = dirname($dir); } } # Process one .ui file sub process_ui_file($) { my $file = shift @_; &read_required_version( dirname($file) ); print "Checking: $file\n" if($verbose); &fix_version($file) if(!$omit_Qt_check); &fix_accels($file); &fix_captions($file); } ############################################################################# # here is the main logic # # process files from the command line, if any if ( $#explicitfiles >= 0 ) { foreach my $file( @explicitfiles ) { &process_ui_file( $file ); } exit 0; } # first generate a list of subdirectories my @dirlist = (); push @dirlist, "."; foreach my $dir ( @dirlist ) { opendir (DIR, "$dir") || warn "Couldn't read '$dir'"; my $subdir = ""; while( $subdir = readdir(DIR)) { next if ($subdir =~ /^\./); next if !( -d "$dir/$subdir"); push @dirlist, "$dir/$subdir"; } closedir(DIR); } # now iterate over all subdirs foreach my $dir(@dirlist) { my @uifile = find_ui_files($dir); foreach my $file(@uifile) { &process_ui_file($file); } }