Adding debian version 0.0.1+svn20091206-2.
[debian/lxde-icon-theme.git] / icon-migrate2.py
CommitLineData
f4969c35
DB
1#!/usr/bin/env python
2#
3# icon-migrate.py
4#
5# Copyright 2009 PCMan <pcman.tw@gmail.com>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20# MA 02110-1301, USA.
21
22import xml.dom.minidom, os, sys, os.path, shutil
23from ConfigParser import *
24import filecmp
25import pygtk
26import gtk
27
28icon_theme_dir = ''
29size_dirs = []
30contexts = []
31
32all_mappings=[]
33
34subdirs = None
35
36exts = ['.png', '.svg', '.xpm']
37
38class Mapping:
39 def __init__(self, xml_icon_node):
40 self.new_name = xml_icon_node.getAttribute('name')
41 self.old_names = []
42 links = xml_icon_node.getElementsByTagName('link')
43 for link in links:
44 self.old_names.append(link.childNodes[0].data)
45
46class Context:
47 def __init__(self, xml_context_node):
48 self.name = xml_context_node.getAttribute('dir')
49 self.mappings = []
50 icon_nodes = xml_context_node.getElementsByTagName('icon')
51 for icon_node in icon_nodes:
52 mapping = Mapping(icon_node)
53 self.mappings.append(mapping)
54
55
56def find_icon_file_in_context_dir(context_dir, icon_name):
57 prefix = os.path.join(context_dir, icon_name)
58 for ext in exts:
59 file = prefix + ext
60 if os.path.exists(file):
61 return file
62 return None
63
64def find_icon_file_in_all_contexts(icon_name):
65 for size_dir in size_dirs:
66 sub_dirs = os.listdir(size_dir)
67 for sub_dir in sub_dirs:
68 if sub_dir[0] == '.':
69 continue
70 full_dir_name = os.path.join(size_dir, sub_dir)
71 ret = find_icon_file_in_context_dir(full_dir_name, icon_name)
72 if ret:
73 return ret
74 return None
75
76def replace_link_with_real_file(file):
77 real_path = os.path.realpath(file)
78 os.unlink(file)
79 shutil.copy2(real_path, file)
80 print 'convert link to real file => copy %s to %s' % (real_path, file)
81
82
83def convert_links_to_copies():
84 for size in sizes:
85 dirs = sizes[size]
86 for dir in dirs: # dirs of different contexts
87 dir = os.path.join(icon_theme_dir, dir)
88 files = os.listdir(dir)
89 for file in files:
90 for ext in exts:
91 if file.endswith(ext): # it's an image file
92 if os.path.islink(file):
93 replace_link_with_real_file(file)
94 break
95
96def is_icon_new_name(icon_name):
97 for context in contexts:
98 for mapping in context.mappings:
99 if mapping.new_name == icon_name:
100 return True
101 return False
102
103def convert_duplicated_files_to_symlinks():
104 # find duplicated files with fdupes
105 os.system( 'fdupes --nohidden -r nuoveXT2 > dups.txt' )
106 files = []
107 links = []
108
109 print '\n\n--- svn commands ---\n'
110
111 f = open( 'dups.txt', 'r' )
112 for line in f:
113 file = line.rstrip()
114 if file != '':
115 files.append(file)
116 else:
117 if len(files) == 0:
118 continue
119
120 files.sort( lambda x, y:len(x)-len(y) )
121
122 primary = ''
123 for file in files:
124 # if the file has a valid new name,
125 # symlink other duplicates to it
126 basename = os.path.basename(file)
127 (icon_name, ext) = os.path.splitext(basename)
128 # print 'is_icon_new_name %s' % icon_name
129 if is_icon_new_name(icon_name):
130 primary = file
131 break
132 if primary == '':
133 primary = files[0]
134 print 'svn --force add %s' % primary
135
136 for file in files:
137 if file != primary:
138 # os.path.unlink(file)
139
140 print 'svn --force rm %s' % file
141 dir = os.path.dirname(file)
142 rel_path = os.path.relpath(primary, dir)
143 # os.path.symlink(rel_path, file)
144
145 links.append( (rel_path, file) )
146 # print 'need to symlink(%s %s)' % (rel_path, file)
147
148 files = []
149
150 print '---------- symlinks ------------'
151 for link in links:
152 print '$(LN_S) -f %s $(DESTDIR)$(datadir)/icons/%s' % (link[0], link[1])
153
154
155def find_icon_file_in_dir(dir, icon_name):
156 for ext in exts: # try .png, .svg, and .xpm
157 base_name = icon_name + ext
158 fpath=os.path.join(dir, base_name)
159 if os.path.exists(fpath):
160 return fpath, ext
161 return None, None
162
163symlinks=[]
164files_to_del=[]
165
166sizes = {}
167
168def choose_icon(new_name, icons):
169 dlg=gtk.Dialog()
170 dlg.vbox.add(gtk.Label('Choose an icon for %s' % new_name))
171 idx = 0
172 for icon in icons:
173 btn = gtk.Button(icon[0])
174 btn.set_image(gtk.image_new_from_file(icon[0]))
175 btn.connect('clicked', lambda btn, dlg, idx: dlg.response(idx), dlg, idx)
176 idx = idx + 1
177 dlg.vbox.add(btn)
178 dlg.show_all()
179 ret = dlg.run()
180 dlg.destroy()
181 return ret if ret >= 0 else -1
182
183def find_icon_file_of_size(size, icon_name):
184 subdirs=sizes[size]
185 for sizedir in subdirs:
186 dir = os.path.join(icon_theme_dir, sizedir)
187 filename, ext = find_icon_file_in_dir(dir, icon_name)
188 if filename:
189 return filename, ext
190 return None, None
191
192def fix_icons_of_specified_size(size, subdir, mappings):
193 print 'fix icons in %s of size %d' % (subdir, size)
194 for mapping in mappings:
195 print 'new_name: %s, %s', (subdir, mapping.new_name)
196 dir = os.path.join(icon_theme_dir, subdir)
197 (fpath, ext) = find_icon_file_in_dir(dir, mapping.new_name)
198 if not fpath: # icon with new_name is not found, choose one icon from old_names
199 choices=[]
200 for old_name in mapping.old_names:
201 for subdir2 in sizes[size]:
202 dir = os.path.join(icon_theme_dir, subdir2)
203 (fpath2, ext2) = find_icon_file_in_dir(dir, old_name)
204 if fpath2:
205 choices.append((fpath2, ext2))
206 if not choices:
207 print '%s is missing, need a new icon for it' % mapping.new_name
208 elif len(choices) == 1:
209 (fpath2, ext2) = choices[0]
210 fpath = os.path.join(icon_theme_dir, subdir, (mapping.new_name + ext2))
211 # copy old file name to new one
212 shutil.copy2(fpath2, fpath)
213 # print 'ls -s %s to %s' % (fpath, fpath2) # auto-choice
214 # rel = os.path.relpath(fpath, os.path.dirname(fpath2))
215 # symlinks.append((rel, fpath2))
216 else:
217 same = True
218 for i in range(len(choices) - 1):
219 # different file extensions
220 if choices[i][1] != choices[i+1][1]:
221 same = False
222 break
223 # different file content
224 if not filecmp.cmp(choices[i][0], choices[i+1][0], False):
225 same = False
226 break
227 if same: # they are actually the same image, can auto-choose
228 (fpath2, ext2) = choices[0]
229 fpath = os.path.join(icon_theme_dir, subdir, (mapping.new_name + ext2))
230 # copy old file name to new one
231 shutil.copy2(fpath2, fpath)
232 # print 'same img, symlink %s to %s' % (fpath, fpath2) # auto-choice
233 # rel = os.path.relpath(fpath, os.path.dirname(fpath2))
234 # symlinks.append((rel, fpath2))
235 else:
236 print 'choices:', choices
237 ret = choose_icon(mapping.new_name, choices)
238 if ret >=0:
239 fpath = os.path.join(icon_theme_dir, subdir, (mapping.new_name + choices[ret][1]))
240 shutil.copy2(choices[ret][0], fpath)
241 else:
242 print '%s is missing, need a new icon for it' % mapping.new_name
243 else:
244 print '%s is found: %s' % (mapping.new_name, fpath)
245 # create symlinks for old_names if they don't exist
246 for old_name in mapping.old_names:
247 # print 'find oldname:', old_name
248 (fpath2, ext2) = find_icon_file_of_size(size, old_name)
249 if not fpath2:
250 fpath2 = os.path.join(os.path.dirname(fpath), old_name + ext)
251 print 'copy newname to oldname: %s => %s' % (fpath, fpath2)
252 shutil.copy2(fpath, fpath2)
253
254# ----------------------------------------------------------------
255# start
256
257if len(sys.argv) < 2:
258 sys.exit()
259
260icon_theme_dir = sys.argv[1]
261cfg = SafeConfigParser()
262cfg.read(os.path.join(icon_theme_dir, 'index.theme'))
263subdirs = cfg.get('Icon Theme', 'Directories').split(',')
264
265for subdir in subdirs:
266 size=cfg.getint(subdir, 'Size')
267 if size in sizes:
268 sizes[size].append(subdir)
269 else:
270 l=[]
271 l.append(subdir)
272 sizes[size] = l
273
274sizes.keys().sort()
275
276# load the mappings
277doc = xml.dom.minidom.parse('legacy-icon-mapping.xml')
278context_nodes = doc.getElementsByTagName('context')
279for context_node in context_nodes:
280 context = Context(context_node)
281 contexts.append(context)
282
283# create a flat list of all available mappings
284for ctx in contexts:
285 for mapping in ctx.mappings:
286 all_mappings.append(mapping)
287
288# convert symlinks to real files
289convert_links_to_copies()
290# now, there is no symlink under the icon theme dir
291
292for size in sizes:
293 print 'for size: %d' % size
294 # all sub dirs containing icons of specified size
295 subdirs = sizes[size]
296
297 for ctx in contexts:
298 sub = None
299 # find subdir corresponding speficied context
300 for subdir in subdirs:
301 ctx_dirname = os.path.basename(subdir)
302 if ctx_dirname == ctx.name:
303 sub = subdir
304 print 'sub: %s' % sub
305 break
306 if not sub:
307 sub = ctx.name
308 print 'missing context: %s' % sub
309
310 fix_icons_of_specified_size(size, sub, ctx.mappings)
311
312
313print '\n\n--------------------symlinks----------------------\n\n'
314
315convert_duplicated_files_to_symlinks()