FusionDirectory
 All Data Structures Files Functions Variables
class_IconTheme.inc
1 <?php
2 /*
3  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
4  Copyright (C) 2011-2016 FusionDirectory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20 
22 
24 {
25  /* Nominal (unscaled) size of the icons in this directory.
26  * Required. */
27  private $Size;
28 
29  /* Specifies the minimum (unscaled) size that the icons in this directory can be scaled to.
30  * Defaults to the value of Size if not present. */
31  private $MinSize;
32 
33  /* Specifies the maximum (unscaled) size that the icons in this directory can be scaled to.
34  * Defaults to the value of Size if not present. */
35  private $MaxSize;
36 
37  /* The type of icon sizes for the icons in this directory.
38  * Valid types are Fixed, Scalable and Threshold.
39  * The type decides what other keys in the section are used.
40  * If not specified, the default is Threshold. */
41  private $Type = 'Threshold';
42 
43  /* The icons in this directory can be used if the size differ at most this much from the desired (unscaled) size.
44  * Defaults to 2 if not present. */
45  private $Threshold = 2;
46 
47  function __construct($infos)
48  {
49  $this->Size = $infos['Size'];
50  $this->MinSize = $infos['Size'];
51  $this->MaxSize = $infos['Size'];
52  foreach (array('Type', 'MaxSize', 'MinSize', 'Threshold') as $key) {
53  if (isset($infos[$key])) {
54  $this->$key = $infos[$key];
55  }
56  }
57  /* Thanks to this Threshold and Scaled are the same */
58  if ($this->Type == 'Threshold') {
59  $this->MinSize = $this->Size - $this->Threshold;
60  $this->MaxSize = $this->Size + $this->Threshold;
61  }
62  }
63 
64  function MatchesSize($size)
65  {
66  switch ($this->Type) {
67  case 'Fixed':
68  return ($this->Size == $size);
69  default:
70  case 'Threshold':
71  case 'Scalable':
72  return (($this->MinSize <= $size) && ($size <= $this->MaxSize));
73  }
74  }
75 
76  function SizeDistance($size)
77  {
78  switch ($this->Type) {
79  case 'Fixed':
80  return abs($this->Size - $size);
81  default:
82  case 'Threshold':
83  case 'Scalable':
84  if ($size < $this->MinSize) {
85  return $this->MinSize - $size;
86  }
87  if ($size > $this->MaxSize) {
88  return $size - $this->MaxSize;
89  }
90  return 0;
91  }
92  }
93 }
94 
95 class IconTheme
96 {
97  private $subdirs = array();
98  private $path;
99  private $parent;
100 
101  function __construct($folder, $default_parent)
102  {
103  $this->path = $folder;
104  $datas = @parse_ini_file($folder.'/index.theme', TRUE, INI_SCANNER_RAW);
105  if ($datas === FALSE) {
106  throw new ThemeFileParsingException('Error while parsing theme file');
107  }
108  if (isset($datas['Icon Theme']['Directories']) && !empty($datas['Icon Theme']['Directories'])) {
109  $dirs = preg_split('/,/', $datas['Icon Theme']['Directories']);
110  foreach ($dirs as $name) {
111  $this->subdirs[strtolower($datas[$name]['Context'])][$name] = new IconThemeDir($datas[$name]);
112  }
113  }
114 
115  if (isset($datas['Icon Theme']['Inherits'])) {
116  $this->parent = $datas['Icon Theme']['Inherits'];
117  } else {
118  $this->parent = $default_parent;
119  }
120  }
121 
122  function FindIcon($context, $icon, $size)
123  {
124  $context = strtolower($context);
125  return $this->FindIconHelper($context, $icon, $size);
126  }
127 
128  function FindIconHelper($context, $icon, $size)
129  {
130  $filename = $this->LookupIcon($context, $icon, $size);
131  if ($filename != NULL) {
132  return $filename;
133  }
134  if (isset(static::$fallbacks[$context.'/'.$icon])) {
135  foreach (static::$fallbacks[$context.'/'.$icon] as $fallback) {
136  $filename = $this->LookupIcon($fallback[0], $fallback[1], $size);
137  if ($filename != NULL) {
138  return $filename;
139  }
140  }
141  }
142 
143  if ($this->parent !== NULL) {
144  $parent = $this->findTheme($this->parent);
145  if ($parent === NULL) {
146  $parent = $this->findTheme(static::$default_theme);
147  }
148  return $parent->FindIconHelper($context, $icon, $size);
149  }
150 
151  return NULL;
152  }
153 
154  function LookupIcon($context, $iconname, $size)
155  {
156  if (!isset($this->subdirs[$context])) {
157  return NULL;
158  }
159  foreach ($this->subdirs[$context] as $path => &$subdir) {
160  if ($subdir->MatchesSize($size)) {
161  foreach (static::$extensions as $extension) {
162  $filename = $this->path.'/'.$path.'/'.$iconname.'.'.$extension;
163  if (file_exists($filename)) {
164  return $filename;
165  }
166  }
167  }
168  }
169  unset($subdir);
170  if (static::$find_closest) {
171  $minimal_size = PHP_INT_MAX;
172  foreach ($this->subdirs[$context] as $path => &$subdir) {
173  if (($sizedistance = $subdir->SizeDistance($size)) < $minimal_size) {
174  foreach (static::$extensions as $extension) {
175  $filename = $this->path.'/'.$path.'/'.$iconname.'.'.$extension;
176  if (file_exists($filename)) {
177  $closest_filename = $filename;
178  $minimal_size = $sizedistance;
179  }
180  }
181  }
182  }
183  unset($subdir);
184  if (isset($closest_filename)) {
185  return $closest_filename;
186  }
187  }
188  return NULL;
189  }
190 
191  static public $default_theme = 'breezy';
192  static public $extensions = array('png', 'xpm', 'svg');
193  static public $find_closest = FALSE;
194 
195  /* We store themes in the session. To do otherwise, override these methods. */
196  static public $session_var = 'IconThemes';
197  static public function loadThemes($path)
198  {
199  $themes = array();
200  if ($dir = opendir("$path")) {
201  while (($file = readdir($dir)) !== FALSE) {
202  if (file_exists("$path/$file/index.theme") && !preg_match("/^\./", $file)) {
203  try {
204  if ($file == static::$default_theme) {
205  $themes[$file] = new IconTheme("$path/$file", NULL);
206  } else {
207  $themes[$file] = new IconTheme("$path/$file", static::$default_theme);
208  }
209  } catch (ThemeFileParsingException $e) {
210  continue;
211  }
212  }
213  }
214  }
215  $_SESSION[static::$session_var] = $themes;
216  }
217  static public function findThemeIcon($theme, $context, $icon, $size)
218  {
219  if (!isset($_SESSION[static::$session_var])) {
220  die('Error: no theme found in session');
221  }
222  if (isset($_SESSION[static::$session_var][$theme])) {
223  return $_SESSION[static::$session_var][$theme]->FindIcon($context, $icon, $size);
224  }
225  return $_SESSION[static::$session_var][static::$default_theme]->FindIcon($context, $icon, $size);
226  }
227  public function findTheme($theme)
228  {
229  if (isset($_SESSION[static::$session_var][$theme])) {
230  $ret = &$_SESSION[static::$session_var][$theme];
231  return $ret;
232  }
233  return NULL;
234  }
235 
236  /* Fallback system */
237  static public $fallbacks = array(
238  'types/user-group' => array(
239  array('applications','system-users')
240  ),
241  'types/resource-group' => array(
242  array('actions','resource-group')
243  ),
244  'types/user' => array(
245  array('places','user-identity'),
246  array('status','avatar-default'),
247  ),
248  'types/contact' => array(
249  array('mimetypes','x-office-contact'),
250  ),
251  'types/certificate' => array(
252  array('mimetypes','stock_certificate'),
253  array('mimetypes','application-certificate'),
254  array('actions','view-certificate'),
255  ),
256  'applications/user-info' => array(
257  array('actions','user-properties'),
258  array('types','contact'),
259  array('mimetypes','x-office-contact'),
260  array('types','user'),
261  array('places','user-identity'),
262  array('status','avatar-default'),
263  ),
264  'applications/office-calendar' => array(
265  array('mimetypes','x-office-calendar'),
266  ),
267  'applications/os-linux' => array(
268  array('applications','linux'),
269  ),
270  'applications/os-windows' => array(
271  array('applications','windows'),
272  ),
273  'applications/samba' => array(
274  array('applications','os-windows'),
275  array('applications','windows'),
276  ),
277  'applications/config-language' => array(
278  array('applications','locale'),
279  array('applications','preferences-desktop-locale'),
280  ),
281  'mimetypes/text-csv' => array(
282  array('mimetypes','x-office-spreadsheet'),
283  array('mimetypes','text-x-generic'),
284  ),
285  'mimetypes/application-pdf' => array(
286  array('mimetypes','x-office-document'),
287  ),
288  'actions/application-exit' => array(
289  array('actions','system-log-out'),
290  ),
291  'actions/document-export' => array(
292  array('actions','document-send'),
293  ),
294  'actions/download' => array(
295  array('actions','document-save'),
296  ),
297  'actions/document-restore' => array(
298  array('actions','document-import'),
299  array('actions','document-open'),
300  ),
301  'actions/document-edit' => array(
302  array('actions','edit'),
303  array('applications','text-editor'),
304  array('applications','accessories-text-editor'),
305  array('actions','document-open'),
306  ),
307  'actions/snapshot' => array(
308  array('actions','document-save'),
309  ),
310  'actions/system-reboot' => array(
311  array('actions','view-refresh'),
312  ),
313  'actions/system-update' => array(
314  array('applications','system-software-update'),
315  ),
316  'actions/system-reinstall' => array(
317  array('applications','system-installer'),
318  ),
319  'actions/task-start' => array(
320  array('actions','media-playback-start'),
321  ),
322  'actions/task-stop' => array(
323  array('actions','media-playback-stop'),
324  ),
325  'actions/task-schedule' => array(
326  array('actions','chronometer'),
327  array('actions','smallclock'),
328  ),
329  'actions/up' => array(
330  array('actions','go-up'),
331  array('actions','arrow-up'),
332  ),
333  'actions/upload' => array(
334  array('actions','document-import'),
335  array('actions','up'),
336  ),
337  'actions/down' => array(
338  array('actions','go-down'),
339  array('actions','arrow-down'),
340  ),
341  'actions/previous' => array(
342  array('actions','go-previous'),
343  array('actions','arrow-left'),
344  ),
345  'actions/next' => array(
346  array('actions','go-next'),
347  array('actions','arrow-right'),
348  ),
349  'actions/submit' => array(
350  array('actions','go-jump'),
351  ),
352  'categories/settings' => array(
353  array('categories','gnome-settings'),
354  array('categories','preferences-other'),
355  array('categories','preferences-system'),
356  ),
357  'categories/checks' => array(
358  array('actions','view-task'),
359  array('actions','view-calendar-tasks'),
360  array('actions','checkbox'),
361  array('status','task-complete'),
362  ),
363  'devices/server' => array(
364  array('places','server'),
365  array('places','network-server'),
366  ),
367  'devices/media-cdrom' => array(
368  array('devices','media-optical'),
369  ),
370  'devices/terminal' => array(
371  array('applications','utilities-terminal'),
372  ),
373  'devices/computer-windows' => array(
374  array('applications','os-windows'),
375  array('applications','windows'),
376  ),
377  'devices/template' => array(
378  array('actions','document-new'),
379  ),
380  'status/object-locked' => array(
381  array('status','changes-prevent'),
382  ),
383  'status/object-unlocked' => array(
384  array('status','changes-allow'),
385  ),
386  'status/task-waiting' => array(
387  array('actions','task-schedule'),
388  ),
389  'places/folder-network' => array(
390  array('places','folder-remote'),
391  ),
392  );
393 }
394 
395 ?>