cea05c8070cd3d8a889cc3dfcc971e8bcfaae748
[quassel.git] / icons / import / import_theme.pl
1 #!/usr/bin/perl
2
3 # This script scans the Quassel source for requested icons and imports the needed
4 # icons (and only them) from a KDE theme (by default Oxygen).
5 # This relies on all icons being requested using one of the convenience constructors in
6 # (K)IconLoader, like this:
7 #   widget->setIcon(SmallIcon("fubar"));
8 # Additional icons can be specified in whitelist-icons; you can also blacklist icons.
9 #
10 # NOTE: Unless you are a Quassel developer and need to bump the icons we ship, you shouldn't
11 #       need to use this script!
12
13 # USAGE: ./import/import_theme.pl $systhemefolder $themename
14 # Run from the icon/ directory.
15
16 use strict;
17 use warnings;
18 use Data::Dumper;
19 use File::Find;
20
21 my $themefolder = shift;
22
23 my $source = "../src";
24 my $themename = shift;
25 $themename = $themename ? $themename : "oxygen";
26 my $qrcfile_kde = $themename . ".qrc";
27
28 my $whitelistfile = "import/whitelist-icons";
29 my $blacklistfile = "import/blacklisted-icons";
30 my $extrafile = "import/extra-icons.qrc." . $themename;
31
32 my %req_icons;
33 my %found_icons;
34 my %blacklist;
35 my %themeblacklist;
36 my %whitelist;
37 my $extrafilecontent;
38
39 # First, load the icon blacklist
40 open BLACKLIST, "<$blacklistfile" or die "Could not open $blacklistfile\n";
41 while(<BLACKLIST>) {
42   s/#.*//;
43   next unless my ($name) = /([-\w]+)\s*/;
44   $blacklist{$name} = 1;
45 }
46 close BLACKLIST;
47
48 my $hasthemeblacklist = 1;
49 open BLACKLIST, "<$blacklistfile.$themename" or $hasthemeblacklist = 0;
50 if ($hasthemeblacklist) {
51   while(<BLACKLIST>) {
52     s/#.*//;
53     next unless my ($name) = /([-\w]+)\s*/;
54     $blacklist{$name} = 1;
55     $themeblacklist{$name} = 1;
56   }
57   close BLACKLIST;
58 } else {
59   print "Info: No theme specific blacklist found...\n";
60 }
61
62 # We now grep the source for things like SmallIcon("fubar") and generate size and name from that
63 print "Grepping $source for requested icons...\n";
64 my @results = `grep -r QIcon::fromTheme\\(\\" $source`;
65 foreach(@results) {
66   next unless my ($name) = /\W+QIcon::fromTheme\(\"([-\w]+)/;
67   $req_icons{$name} = 1
68     unless exists $blacklist{$name};
69 }
70
71 # Add whitelist icons
72 open WHITELIST, "<$whitelistfile" or die "Could not open $whitelistfile\n";
73 while(<WHITELIST>) {
74   s/#.*//;
75   next unless my ($name) = /([-\w]+)\s*/;
76   $req_icons{$name} = 1
77     unless exists $themeblacklist{$name};
78 }
79 close WHITELIST;
80
81 # Read in extra-icons
82 my $hasthemeextrafile = 1;
83 local $/;
84 open EXTRAFILE, "<$extrafile" or $hasthemeextrafile = 0;
85 if($hasthemeextrafile) {
86   binmode EXTRAFILE;
87   $extrafilecontent = <EXTRAFILE>;
88   close EXTRAFILE;
89 } else {
90   $extrafilecontent = "";
91 }
92
93 # Clean old output dir
94 print "Removing old $themename...\n";
95 system("rm -rf $themename");
96
97 # Now copy the icons
98 my %scalables;
99
100 print "Copying icons from $themefolder...\n";
101 opendir (BASEDIR, "$themefolder") or die "Could not open theme basedir\n";
102 my $scalableFound = 0;
103 foreach my $parent (readdir BASEDIR) {
104   next unless (-d "$themefolder/$parent");
105   $scalableFound = $scalableFound ? 1 : $parent eq 'scalable';
106   next if $parent eq '.' or $parent eq '..' or $parent eq 'scalable' or $parent =~ /\..*/;
107   my $ischildcat = $parent =~ /\d+x\d+/ ? 1 : 0;
108   opendir (SIZEDIR, "$themefolder/$parent") or die "Could not open dir $parent\n";
109   foreach my $child (readdir SIZEDIR) {
110     next if $child eq '.' or $child eq '..';
111     my $cat = $ischildcat ? $child : $parent;
112     opendir (CATDIR, "$themefolder/$parent/$child") or die "Could not open category dir\n";
113     foreach my $icon (readdir CATDIR) {
114       my $iconname = $icon;
115       $iconname =~ s/\.png$//;
116       $iconname =~ s/\.svg$//;
117       next unless exists $req_icons{$iconname};
118       $scalables{$cat}{$iconname} = 1;
119       system "mkdir -p $themename/$parent/$child" and die "Could not create category dir\n";
120       system "cp -aL $themefolder/$parent/$child/$icon $themename/$parent/$child"
121         and die "Error while copying file $parent/$child/$icon\n";
122       #print "Copy: $themefolder/$parent/$child/$icon\n";
123       $found_icons{$iconname} = 1;
124     }
125     closedir CATDIR;
126   }
127   closedir SIZEDIR;
128 }
129 closedir BASEDIR;
130
131 # Copy scalables
132 if ($scalableFound) {
133   foreach my $cat (keys %scalables) {
134     system "mkdir -p $themename/scalable/$cat" and die "Could not create category dir\n";
135     foreach my $scalable (keys %{$scalables{$cat}}) {
136       system "cp -aL $themefolder/scalable/$cat/$scalable.svgz $themename/scalable/$cat/$scalable.svgz";
137     }
138   }
139 }
140
141 # Warn if we have still icons left
142 foreach my $icon (keys %req_icons) {
143   next if defined $found_icons{$icon};
144   print "Warning: Missing icon $icon\n";
145 }
146
147 # Copy license etc.
148 system "cp $themefolder/AUTHORS $themefolder/CONTRIBUTING $themefolder/COPYING* $themefolder/index.theme $themename/";
149
150 # Generate .qrc
151 my @file_list;
152 generate_qrc($themename, $qrcfile_kde, $extrafilecontent);
153
154 print "Done.\n";
155
156 ########################################################################################
157 sub generate_qrc {
158   my $dir = shift;
159   my $qrcfile = shift;
160
161   @file_list = ();
162   find(\&push_icon_path, $dir);
163   @file_list = sort(@file_list );
164   my $files = join "\n", @file_list;
165
166   my $qrc = "<RCC>\n"
167            ."  <qresource prefix=\"/icons\">\n"
168            ."$files\n"
169            ."$extrafilecontent\n"
170            ."  </qresource>\n"
171            ."</RCC>\n";
172
173   open QRC, ">$qrcfile" or die "Could not open $qrcfile for writing!\n";
174   print QRC $qrc;
175   close QRC;
176 }
177
178 sub push_icon_path {
179   return unless /\.png$/ or /\.svg$/ or /^index.theme$/;
180
181   push @file_list, "    <file>$File::Find::name</file>";
182 }