-
Notifications
You must be signed in to change notification settings - Fork 5
/
gnome-exe-thumbnailer
executable file
·424 lines (344 loc) · 9.82 KB
/
gnome-exe-thumbnailer
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
#!/bin/bash
shopt -s nocasematch
INPUTFILE="$1"
OUTPUTFILE="$2"
# application/x-ms-shortcut (.lnk) support, thanks to jopka (https://launchpad.net/~jopka)
if [[ ${INPUTFILE##*.} = 'lnk' ]]
then
which winepath >&2 || exit
INPUTFILE="$(
winepath -u "$(winedump "$INPUTFILE" \
| sed -n -r '/^LocalPath of/s/.*\("(.*\.[Ee][Xx][Ee])"\)$/\1/p')"
)"
[ ! "$INPUTFILE" ] && exit
SHORTCUT='TRUE'
fi
if ! TEMPDIR="$(mktemp -d)"
then
echo "gnome-exe-thumbnailer: Failed to make a temporary folder, quitting..." && exit 1
fi
TEMPFILE1="$TEMPDIR/group_icon_res"
TEMPFILE2="$TEMPDIR/extracted_icon.png"
TEMPTHUMB="$TEMPDIR/thumbnail.png"
# Get the current icon theme (or override it by 4th parameter):
case "$XDG_CURRENT_DESKTOP" in
'XFCE')
ACTIVE_THEME="$(xfconf-query -c xsettings -p /Net/IconThemeName)"
;;
'Cinnamon'*)
ACTIVE_THEME="$(gsettings get org.cinnamon.desktop.interface icon-theme)"
;;
'MATE'*)
ACTIVE_THEME="$(gsettings get org.mate.interface icon-theme)"
;;
*) # GNOME, Unity, Budgie, etc.
ACTIVE_THEME="$(gsettings get org.gnome.desktop.interface icon-theme)"
;;
esac
eval THEME="${4:-$ACTIVE_THEME}"
if [ ! -z "$XDG_CACHE_HOME" ]
then
THUMBNAILS_PATH="$XDG_CACHE_HOME/thumbnails"
else
THUMBNAILS_PATH="$HOME/.cache/thumbnails"
fi
mkdir -p "$THUMBNAILS_PATH"
# Delete previously created thumbnails if icon theme has been changed since last run
if [ -s "$THUMBNAILS_PATH/gnome-exe-thumbnailer.cfg" ] && [ ! "$THEME" = "$(cat $THUMBNAILS_PATH/gnome-exe-thumbnailer.cfg)" ]
then
rm $(cat $THUMBNAILS_PATH/gnome-exe-thumbnailer.files)
> $THUMBNAILS_PATH/gnome-exe-thumbnailer.files
echo "$THEME" > $THUMBNAILS_PATH/gnome-exe-thumbnailer.cfg
fi
echo "$THUMBNAILS_PATH/*/$(echo -n "$3" | md5sum | cut -d' ' -f1).png" \
>> "$THUMBNAILS_PATH/gnome-exe-thumbnailer.files"
case "$THEME" in
Faience*)
THEME='faience'
DRAW='roundRectangle 2,2 45,45 3,3'
SHADOW='+1'
;;
elementary*|Ubuntu-Mono*|Humanity*)
THEME='elementary'
DRAW='roundRectangle 2,2 45,45 3,3'
SHADOW='+1'
;;
Faenza*)
THEME='faenza'
DRAW='roundRectangle 2,2 45,45 3,3'
SHADOW='+1'
;;
elementary*|Ubuntu-Mono*|Humanity*)
THEME='elementary'
DRAW='roundRectangle 2,2 45,45 3,3'
SHADOW='+1'
;;
AwOken)
THEME='awoken'
DRAW='roundRectangle 3,3 44,44 3,3'
SHADOW='-1'
;;
AwOkenWhite)
THEME='awoken-white'
DRAW='roundRectangle 3,3 44,44 3,3'
SHADOW='-1'
;;
AwOkenDark)
THEME='awoken-dark'
DRAW='roundRectangle 4,4 43,43 3,3'
SHADOW='-1'
;;
gnome|Human)
THEME='gnome'
DRAW='roundRectangle 2,2 45,45 4,4'
SHADOW='+0'
;;
Breathe)
THEME='breathe'
DRAW='roundRectangle 1,2 46,45 2,2'
SHADOW='+1'
;;
NITRUX-Buttons)
THEME='nitrux-buttons'
DRAW='roundRectangle 1,1 46,46 6,6'
SHADOW='+0'
;;
NITRUX-Buttons-2)
THEME='nitrux-buttons-2'
DRAW='roundRectangle 1,1 46,46 6,6'
SHADOW='+0'
;;
NITRUX*)
THEME='nitrux'
DRAW='roundRectangle 2,2 45,45 1,1'
SHADOW='+0'
;;
Captiva)
THEME='captiva'
DRAW='roundRectangle 2,1 45,43 15,15'
SHADOW='+0'
;;
Paper)
THEME='paper'
DRAW='roundRectangle 4,4 43,43 1,1'
SHADOW='+0'
;;
Square-Beam)
THEME='square-beam'
DRAW='roundRectangle 0,0 47,44 1,1'
SHADOW='+0'
;;
box)
THEME='box'
DRAW='roundRectangle 5,5 42,42 1,1'
SHADOW='+0'
;;
Moka)
THEME='moka'
DRAW='roundRectangle 2,3 44,45 8,8'
SHADOW='+0'
;;
Evolvere-*vivid*)
THEME='evolvere-vivid'
DRAW='roundRectangle 0,0 47,47, 1,1'
SHADOW='+0'
;;
Evolvere)
THEME='evolvere'
DRAW='roundRectangle 0,0 47,47, 1,1'
SHADOW='+0'
;;
Compass)
THEME='compass'
DRAW='roundRectangle 3,3 44,44 5,5'
SHADOW='+0'
;;
Vibrancy*)
THEME='vibrancy'
DRAW='roundRectangle 3,3 44,44 8,8'
SHADOW='+0'
;;
Tango*|*)
THEME='tango'
DRAW='roundRectangle 2,2 45,45 4,4'
SHADOW='+1'
;;
esac
INPUTFILE_SIZE=$(du -b "$INPUTFILE" | cut -f1 -d$'\t')
# Try to fetch the max. size for thumbnailed executables from gsettings, but fall back to 10485760 bytes if that fails.
THUMBNAIL_LIMIT=$(gsettings get org.gnome.nautilus.preferences thumbnail-limit | cut -f2 -d' ')
if [[ ! "$THUMBNAIL_LIMIT" ]]
then
THUMBNAIL_LIMIT=10485760
fi
if [[ ${INPUTFILE##*.} = 'msi' ]]
then
# Use generic installer icon for a .msi package:
ICON=/usr/share/pixmaps/gnome-exe-thumbnailer/$THEME/installer.png
TUNE='-modulate 120,100,0'
elif [ $INPUTFILE_SIZE -lt $THUMBNAIL_LIMIT ]
then
# Extract group_icon resource. If we get the "wrestool: $INPUTFILE could not find `1' in
# `group_icon' resource." error, there is a 99.9% chance that input file is an installer.
# Warning: Some redirection magic ahead.
if wrestool --extract --type=group_icon "$INPUTFILE" 2>&1 >$TEMPFILE1 \
| grep "could not find \`1' in \`group_icon' resource"
then
# Use generic installer icon:
ICON=/usr/share/pixmaps/gnome-exe-thumbnailer/$THEME/installer.png
TUNE='-modulate 120'
else
# Process extracted data, if we have some:
if [ -s $TEMPFILE1 ]
then
# Look for the best usable icon. 32x32x32 is the first choice, but sometimes is that icon only
# an empty box with no visible pixels (e.g. in Simon Tatham's Portable Puzzle Collection).
# In that case we can try to lower the bit depth and look again.
for BITDEPTH in 32 24 8 4 1
do
read OFFSET INDEX < <(
icotool --list $TEMPFILE1 | awk '{
ci=int(substr($2,index($2,"=") + 1));
cw=int(substr($3,index($3,"=") + 1));
cb=int(substr($5,index($5,"=") + 1));
if (((cw > w && cw <= 32) || (cw == w && cb > b)) && cb <= '$BITDEPTH') {
b = cb;
w = cw;
i = ci;
}
}
END {
print (32 - w) / 2, i;
}'
)
# Use a resized 48x48 icon if 32x32 or smaller isn't available.
# This is very rare (e.g. peazip.exe), but it happens sometimes:
if [ "$INDEX" = '' ]
then
INDEX=1
RESIZE=yes
OFFSET=$(($OFFSET - 16))
fi
# Finally try to extract chosen icon:
icotool --extract --index=$INDEX $TEMPFILE1 -o $TEMPFILE2
if [ -s $TEMPFILE2 ]
then
ICON=$TEMPFILE2
[ "$RESIZE" ] && mogrify -resize 32x32 $ICON
else
# This case generally happens when the hi-res icons are in new "Vista" icon format (bunch of compressed PNGs).
# Icotool from icoutils 0.29.1 supports it already, but is unable to extract the one selected icon only.
# Try to extract all icons:
icotool --extract $TEMPFILE1 -o "$TEMPDIR"
# There's always a 32x32x32 icon in "Vista" icons, but just to be sure:
[ -s ${TEMPFILE1}_${INDEX}_32x32x${BITDEPTH}.png ] && ICON=${TEMPFILE1}_${INDEX}_32x32x${BITDEPTH}.png
fi
if [ "$ICON" ]
then
# Verify that the selected icon is not just an empty box:
if [ "$(convert $ICON -filter box -resize 1x1! -format "%[fx:u]" info:)" = '0' ]
then
# Take next iteration with lower bit depth
unset ICON
continue
else
break
fi
else
break
fi
done
fi
fi
fi
# Create the basic thumbnail:
if [ "$ICON" ]
then
# Calculate the backgroud color:
COLOR=$(
convert $ICON -background white -flatten -fill white \
-fuzz 40% -opaque black -level 33%,66% -scale 1x1! $TUNE txt:- \
| tail -1 \
| grep -o '#......'
)
else
# Just use the generic icon with backgroud color based on md5sum:
HUE=$(md5sum "$INPUTFILE" | cut -c 1-2)
HUE=$(printf "%d" 0x$HUE)
COLOR="hsb($HUE, 50%, 90%)"
LABEL=${INPUTFILE##*/}
LABEL=$(sed 's/^./\U&/; s/.$/\L&/' <<< "${LABEL:0:2}")
# Dim color for non-executable files:
if [[ ! ${INPUTFILE##*.} = 'exe' ]]
then
LIGHT=80
TUNE_NX='-modulate 100,20'
fi
convert -size 48x48 xc:none -gravity center -font Helvetica-Narrow-Bold -pointsize 24 \
-fill '#0000005C' -annotate $SHADOW+3 "$LABEL" \
-fill "hsb($HUE, 3%, ${LIGHT:-100}%)" -annotate +0+2 "$LABEL" \
png:$TEMPFILE1
ICON=$TEMPFILE1
OFFSET=-8
fi
# Create the final thumbnail:
OFFSET=$(($OFFSET + 8))
if [ "$SHORTCUT" ]
then
# Variant with MS shortcut emblem in bottom left corner for .lnk files
convert -size 48x48 xc:none -fill "$COLOR" -draw "$DRAW" $TUNE_NX miff:- \
| composite -compose multiply /usr/share/pixmaps/gnome-exe-thumbnailer/$THEME/template.png - miff:- \
| composite -geometry +$OFFSET+$OFFSET $ICON - png:- \
| composite -gravity southwest /usr/share/pixmaps/gnome-exe-thumbnailer/shortcut.png - $TEMPTHUMB
else
# Plain variant
convert -size 48x48 xc:none -fill "$COLOR" -draw "$DRAW" $TUNE_NX miff:- \
| composite -compose multiply /usr/share/pixmaps/gnome-exe-thumbnailer/$THEME/template.png - png:- \
| composite -geometry +$OFFSET+$OFFSET $ICON - $TEMPTHUMB
fi
# Get the version number:
if [[ ${INPUTFILE##*.} = 'msi' ]]
then
# Look for the ProductVersion property using msitools' msiinfo if present
if which msiinfo
then
VERSION=$(msiinfo export "$INPUTFILE" 'Property' | grep 'ProductVersion' | cut -f 2)
else
# Try to get the version number from extended file properties at least:
VERSION=$(
file "$INPUTFILE" \
| grep -o ', Subject: .*, Author: ' \
| egrep -o '[0-9]+\.[0-9]+(\.[0-9][0-9]?)?(beta)?' \
| head -1
)
fi
elif [ $INPUTFILE_SIZE -lt $THUMBNAIL_LIMIT ]
then
# Extract raw version resource:
wrestool --extract --raw --type=version "$INPUTFILE" > $TEMPFILE1
if [ -s $TEMPFILE1 ]
then
# Search for a sane version string.
# This (especially the final regexp) took me really long time to figure out. Am I that lame?
VERSION=$(< $TEMPFILE1 \
tr '\0, ' '\t.\0' \
| sed 's/\t\t/_/g' \
| tr -c -d '[:print:]' \
| sed -r -n 's/.*Version[^0-9]*([0-9]+\.[0-9]+(\.[0-9][0-9]?)?).*/\1/p'
)
fi
fi
# Put a version label on the thumbnail:
if [ "$VERSION" ]
then
convert -font -*-clean-medium-r-*-*-6-*-*-*-*-*-*-* \
-background '#00001090' -fill white label:"$VERSION" \
-trim -bordercolor '#00001090' -border 2 \
-fill '#00001048' \
-draw $'color 0,0 point\ncolor 0,8 point' -flop \
-draw $'color 0,0 point\ncolor 0,8 point' -flop \
miff:- | composite -gravity southeast - $TEMPTHUMB $OUTPUTFILE
else
cp $TEMPTHUMB $OUTPUTFILE
fi
rm -r "$TEMPDIR"