class_IconTheme.inc 12.2 KB
Newer Older
1
<?php
2
3
/*
  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
4
  Copyright (C) 2011-2016  FusionDirectory
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
20

21
class ThemeFileParsingException extends Exception {}
22

23
24
class IconThemeDir
{
25
26
  /* Nominal (unscaled) size of the icons in this directory.
   * Required. */
27
  private $Size;
28
29
30

  /* Specifies the minimum (unscaled) size that the icons in this directory can be scaled to.
   * Defaults to the value of Size if not present. */
31
  private $MinSize;
32
33
34

  /* Specifies the maximum (unscaled) size that the icons in this directory can be scaled to.
   * Defaults to the value of Size if not present. */
35
  private $MaxSize;
36
37
38
39
40

  /* The type of icon sizes for the icons in this directory.
   * Valid types are Fixed, Scalable and Threshold.
   * The type decides what other keys in the section are used.
   * If not specified, the default is Threshold. */
41
  private $Type      = 'Threshold';
42
43
44

  /* The icons in this directory can be used if the size differ at most this much from the desired (unscaled) size.
   * Defaults to 2 if not present. */
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  private $Threshold = 2;

  function __construct($infos)
  {
    $this->Size     = $infos['Size'];
    $this->MinSize  = $infos['Size'];
    $this->MaxSize  = $infos['Size'];
    foreach (array('Type', 'MaxSize', 'MinSize', 'Threshold') as $key) {
      if (isset($infos[$key])) {
        $this->$key = $infos[$key];
      }
    }
    /* Thanks to this Threshold and Scaled are the same */
    if ($this->Type == 'Threshold') {
      $this->MinSize = $this->Size - $this->Threshold;
      $this->MaxSize = $this->Size + $this->Threshold;
    }
  }

  function MatchesSize($size)
  {
    switch ($this->Type) {
      case 'Fixed':
        return ($this->Size == $size);
69
      default:
70
71
72
73
74
75
76
77
78
79
80
      case 'Threshold':
      case 'Scalable':
        return (($this->MinSize <= $size) && ($size <= $this->MaxSize));
    }
  }

  function SizeDistance($size)
  {
    switch ($this->Type) {
      case 'Fixed':
        return abs($this->Size - $size);
81
      default:
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
      case 'Threshold':
      case 'Scalable':
        if ($size < $this->MinSize) {
          return $this->MinSize - $size;
        }
        if ($size > $this->MaxSize) {
          return $size - $this->MaxSize;
        }
        return 0;
    }
  }
}

class IconTheme
{
  private $subdirs = array();
  private $path;
  private $parent;

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
109
110
111
112
    if (isset($datas['Icon Theme']['Directories']) && !empty($datas['Icon Theme']['Directories'])) {
      $dirs   = preg_split('/,/', $datas['Icon Theme']['Directories']);
      foreach ($dirs as $name) {
        $this->subdirs[strtolower($datas[$name]['Context'])][$name] = new IconThemeDir($datas[$name]);
      }
113
114
    }

115
116
    if (isset($datas['Icon Theme']['Inherits'])) {
      $this->parent = $datas['Icon Theme']['Inherits'];
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
    } else {
      $this->parent = $default_parent;
    }
  }

  function FindIcon($context, $icon, $size)
  {
    $context = strtolower($context);
    return $this->FindIconHelper($context, $icon, $size);
  }

  function FindIconHelper($context, $icon, $size)
  {
    $filename = $this->LookupIcon($context, $icon, $size);
    if ($filename != NULL) {
      return $filename;
    }
134
135
    if (isset(static::$fallbacks[$context.'/'.$icon])) {
      foreach (static::$fallbacks[$context.'/'.$icon] as $fallback) {
136
137
138
139
140
141
        $filename = $this->LookupIcon($fallback[0], $fallback[1], $size);
        if ($filename != NULL) {
          return $filename;
        }
      }
    }
142
143

    if ($this->parent !== NULL) {
144
145
      $parent = $this->findTheme($this->parent);
      if ($parent === NULL) {
146
        $parent = $this->findTheme(static::$default_theme);
147
148
149
150
151
152
153
154
155
      }
      return $parent->FindIconHelper($context, $icon, $size);
    }

    return NULL;
  }

  function LookupIcon($context, $iconname, $size)
  {
156
157
158
    if (!isset($this->subdirs[$context])) {
      return NULL;
    }
159
160
    foreach ($this->subdirs[$context] as $path => &$subdir) {
      if ($subdir->MatchesSize($size)) {
161
        foreach (static::$extensions as $extension) {
162
163
164
165
166
167
168
169
          $filename = $this->path.'/'.$path.'/'.$iconname.'.'.$extension;
          if (file_exists($filename)) {
            return $filename;
          }
        }
      }
    }
    unset($subdir);
170
    if (static::$find_closest) {
171
172
173
      $minimal_size = PHP_INT_MAX;
      foreach ($this->subdirs[$context] as $path => &$subdir) {
        if (($sizedistance = $subdir->SizeDistance($size)) < $minimal_size) {
174
          foreach (static::$extensions as $extension) {
175
176
177
178
179
            $filename = $this->path.'/'.$path.'/'.$iconname.'.'.$extension;
            if (file_exists($filename)) {
              $closest_filename = $filename;
              $minimal_size     = $sizedistance;
            }
180
181
182
          }
        }
      }
183
184
185
186
      unset($subdir);
      if (isset($closest_filename)) {
        return $closest_filename;
      }
187
188
189
190
    }
    return NULL;
  }

191
  static public $default_theme  = 'breezy';
192
  static public $extensions     = array('png', 'xpm', 'svg');
193
  static public $find_closest   = FALSE;
194
195
196

  /* We store themes in the session. To do otherwise, override these methods. */
  static public $session_var    = 'IconThemes';
197
198
  static public function loadThemes($path)
  {
199
    $themes = array();
200
201
202
203
    if ($dir = opendir("$path")) {
      while (($file = readdir($dir)) !== FALSE) {
        if (file_exists("$path/$file/index.theme") && !preg_match("/^\./", $file)) {
          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
210
          } catch (ThemeFileParsingException $e) {
            continue;
211
212
213
214
          }
        }
      }
    }
215
    $_SESSION[static::$session_var] = $themes;
216
217
218
  }
  static public function findThemeIcon($theme, $context, $icon, $size)
  {
219
    if (!isset($_SESSION[static::$session_var])) {
220
221
      die('Error: no theme found in session');
    }
222
223
    if (isset($_SESSION[static::$session_var][$theme])) {
      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
228
  }
  public function findTheme($theme)
  {
229
230
    if (isset($_SESSION[static::$session_var][$theme])) {
      $ret = &$_SESSION[static::$session_var][$theme];
231
232
233
      return $ret;
    }
    return NULL;
234
  }
235
236
237
238
239
240
241
242
243
244
245
246
247

  /* Fallback system */
  static public $fallbacks = array(
    'types/user-group'              => array(
      array('applications','system-users')
    ),
    'types/resource-group'          => array(
      array('actions','resource-group')
    ),
    'types/user'                    => array(
      array('places','user-identity'),
      array('status','avatar-default'),
    ),
248
249
250
    'types/contact'                 => array(
      array('mimetypes','x-office-contact'),
    ),
251
252
253
254
255
    'types/certificate'             => array(
      array('mimetypes','stock_certificate'),
      array('mimetypes','application-certificate'),
      array('actions','view-certificate'),
    ),
256
257
258
259
    'applications/user-info'        => array(
      array('actions','user-properties'),
      array('types','contact'),
      array('mimetypes','x-office-contact'),
260
261
262
      array('types','user'),
      array('places','user-identity'),
      array('status','avatar-default'),
263
264
265
266
    ),
    'applications/office-calendar'  => array(
      array('mimetypes','x-office-calendar'),
    ),
267
    'applications/os-linux'         => array(
268
269
      array('applications','linux'),
    ),
270
    'applications/os-windows'       => array(
271
272
      array('applications','windows'),
    ),
273
    'applications/samba'            => array(
274
275
      array('applications','os-windows'),
      array('applications','windows'),
276
    ),
277
278
279
280
    'applications/config-language'  => array(
      array('applications','locale'),
      array('applications','preferences-desktop-locale'),
    ),
281
282
283
284
285
286
287
    'mimetypes/text-csv'            => array(
      array('mimetypes','x-office-spreadsheet'),
      array('mimetypes','text-x-generic'),
    ),
    'mimetypes/application-pdf'     => array(
      array('mimetypes','x-office-document'),
    ),
288
289
290
    'actions/application-exit'      => array(
      array('actions','system-log-out'),
    ),
291
    'actions/document-export'       => array(
292
293
      array('actions','document-send'),
    ),
294
    'actions/download'              => array(
295
296
297
298
299
300
      array('actions','document-save'),
    ),
    'actions/document-restore'      => array(
      array('actions','document-import'),
      array('actions','document-open'),
    ),
301
    'actions/document-edit'         => array(
302
303
304
305
306
      array('actions','edit'),
      array('applications','text-editor'),
      array('applications','accessories-text-editor'),
      array('actions','document-open'),
    ),
307
    'actions/snapshot'              => array(
308
309
      array('actions','document-save'),
    ),
310
    'actions/system-reboot'         => array(
311
312
      array('actions','view-refresh'),
    ),
313
    'actions/system-update'         => array(
314
315
      array('applications','system-software-update'),
    ),
316
    'actions/system-reinstall'      => array(
317
318
      array('applications','system-installer'),
    ),
319
320
321
322
323
324
325
326
327
328
    'actions/task-start'            => array(
      array('actions','media-playback-start'),
    ),
    'actions/task-stop'             => array(
      array('actions','media-playback-stop'),
    ),
    'actions/task-schedule'         => array(
      array('actions','chronometer'),
      array('actions','smallclock'),
    ),
329
    'actions/up'                    => array(
330
331
332
      array('actions','go-up'),
      array('actions','arrow-up'),
    ),
333
334
335
336
    'actions/upload'                => array(
      array('actions','document-import'),
      array('actions','up'),
    ),
337
    'actions/down'                  => array(
338
339
340
      array('actions','go-down'),
      array('actions','arrow-down'),
    ),
341
    'actions/previous'              => array(
342
343
344
      array('actions','go-previous'),
      array('actions','arrow-left'),
    ),
345
    'actions/next'                  => array(
346
347
348
      array('actions','go-next'),
      array('actions','arrow-right'),
    ),
349
350
351
352
    'actions/submit'                => array(
      array('actions','go-jump'),
    ),
    'categories/settings'           => array(
353
354
355
356
      array('categories','gnome-settings'),
      array('categories','preferences-other'),
      array('categories','preferences-system'),
    ),
357
    'categories/checks'             => array(
358
359
360
361
362
      array('actions','view-task'),
      array('actions','view-calendar-tasks'),
      array('actions','checkbox'),
      array('status','task-complete'),
    ),
363
    'devices/server'                => array(
364
365
366
      array('places','server'),
      array('places','network-server'),
    ),
367
    'devices/media-cdrom'           => array(
368
369
      array('devices','media-optical'),
    ),
370
    'devices/terminal'              => array(
371
372
373
374
375
376
      array('applications','utilities-terminal'),
    ),
    'devices/computer-windows'      => array(
      array('applications','os-windows'),
      array('applications','windows'),
    ),
377
    'status/object-locked'          => array(
378
379
      array('status','changes-prevent'),
    ),
380
    'status/object-unlocked'        => array(
381
382
      array('status','changes-allow'),
    ),
383
384
385
    'status/task-waiting'        => array(
      array('status','task-schedule'),
    ),
386
387
388
    'places/folder-network'        => array(
      array('places','folder-remote'),
    ),
389
  );
390
391
392
}

?>