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