~flimm/epidermis/icon-theme-bugfix

« back to all changes in this revision

Viewing changes to epidermis/pigments/pigment.py

  • Committer: David D Lowe
  • Date: 2011-01-04 22:50:19 UTC
  • Revision ID: daviddlowe.flimm@gmail.com-20110104225019-uo31kb54cbxjt5vt
Tidy up code with better comments.
Deleted unused functions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
from shell import SubprocessShell
24
24
import ep_exceptions
25
25
import handy
 
26
from handy import get_first_text
26
27
import const
27
28
from const import PIGMENT_TYPES
28
29
import managepigments
29
30
 
30
 
 
31
31
TEMP_DIR = "TEMP"
32
32
 
33
33
QUERY_OVERWRITE = 1
34
34
QUERY_OVERWRITE_DATA = 2
35
35
 
36
36
STATE_EMPTY = 0
 
37
"""The state that the pigment initializes in"""
37
38
STATE_INFO = 2
 
39
"""the pigment only contains essential meta-data, for example, pigments
 
40
viewed in the repo browser are in this state, no attachments"""
38
41
STATE_INSTALLED = 3
 
42
"""the pigment has been installed in its installationDirectory, all 
 
43
necessary attachments are saved"""
39
44
STATE_TEMP = 4
 
45
"""the pigment has been extracted to a temporary directory, including 
 
46
attachments"""
40
47
STATE_INCOMPLETE = 1
41
 
#STATE_EMPTY: this is the state that the pigment initializes in
42
 
#STATE_INFO: the pigment only contains essential meta-data, for example, pigments
43
 
# viewed in the repo browser are in this state, no attachments
44
 
#STATE_INSTALLED: the pigment has been installed in its installationDirectory,
45
 
# all necessary attachments are saved
46
 
#STATE_TEMP: the pigment has been extracted to a temporary directory,
47
 
# including attachments
48
 
#STATE_INCOMPLETE: the pigment doesn't contain enough meta-data to qualify
49
 
#  as STATE_INFO, but it is not empty"""
 
48
"""the pigment doesn't contain enough meta-data to qualify as STATE_INFO, 
 
49
but it is not empty"""
50
50
 
51
51
class PigmentType():
52
52
    """The class for the type of pigment, has the following
53
53
    attributes: humanName, humanPluralName, codeName, abbreviation,
54
54
    directoryName
55
 
    humanName: human readable and translatable capitalised name of the pigment
56
 
    type
57
 
    humanPluralName: similar to humanName, but in the plural
58
 
    This class is an "abstract" class, it's meant to be subclassed"""
 
55
    
 
56
    humanName -- human readable and translatable capitalised name of the
 
57
                 pigment type
 
58
    humanPluralName -- similar to humanName, but in the plural
 
59
    
 
60
    This class is an abstract class, it's meant to be subclassed
 
61
    
 
62
    """
59
63
    humanName = {"en":""}
60
64
    humanPluralName = {"en":""}
61
65
    codeName = ""
80
84
    
81
85
    @staticmethod
82
86
    def get_Pigment():
83
 
        return Pigment
 
87
        handy.abstract()
84
88
    
85
89
    @classmethod
86
90
    def does_system_support_me(klass):
87
 
        """Returns whether the system can install and activate this type
88
 
        of pigment. For example, not all systems have Xsplash installed."""
89
 
        return True
 
91
        """Return whether the system can install and activate this type
 
92
        of pigment. For example, not all systems have Xsplash installed.
 
93
        
 
94
        """
 
95
        handy.abstract()
90
96
 
91
97
 
92
98
 
100
106
    def __init__(self):
101
107
        """Initilises Psigment object, including the humanName, codeName, copyright,
102
108
        author, authorContact, description, preview, listStore,
103
 
        installationDirectory and type attributes"""
 
109
        installationDirectory and type attributes
 
110
        
 
111
        """
104
112
        # TODO: add version
105
113
        self.humanName = {"en":""}
106
114
        self.codeName = "" #: moohoo
123
131
    
124
132
    def set_human_name(self, humanName, language="en"):
125
133
        """Set a human name for this pigment in specified language,
126
 
        by default, en"""
 
134
        by default, en
 
135
        
 
136
        Keyword arguments:
 
137
        humanName -- string
 
138
        language -- string
 
139
        
 
140
        """
127
141
        if len(language) == 0:
128
142
            language = "en"
129
143
        self.humanName[language] = humanName
136
150
    
137
151
    def set_description(self, description, language="en"):
138
152
        """Set a human readable description for this pigment in specified language,
139
 
        by default, en"""
 
153
        by default, en
 
154
        
 
155
        """
140
156
        self.description[language] = description
141
157
    
142
158
    def get_description(self, language="en"):
143
159
        """Get the human readable description for this pigment in specified
144
 
        language""" 
 
160
        language
 
161
        
 
162
        """ 
145
163
        return self.description[language]
146
164
    
147
165
    def add_attachment(self, attachment):
148
166
        """Add a file or a directory that may be needed for the installation
149
167
        and activation of the pigment. When saved, the file or directory will
150
168
        be found under data in the pigment compressed archive.
 
169
        
151
170
        Please note that the order of attachments cannot be relied upon.
152
171
        Use this function instead of appending to self.attachments directly.
 
172
        
153
173
        If attachment is not an absolute path, the pigment will look for it
154
 
        automatically based on installationDirectory"""
 
174
        automatically based on installationDirectory.
 
175
        
 
176
        """
155
177
        if not os.path.exists(attachment):
156
178
            raise(ep_exceptions.AttachmentNotFoundException(attachment, pigment=self))
157
179
        self.attachments.append(attachment)
158
180
    
159
181
    
160
182
    def get_state(self):
161
 
        """Returns the state of the pigment, a number corresponding to one of
 
183
        """Return the state of the pigment, a number corresponding to one of
162
184
        these constants:
 
185
        
163
186
        STATE_EMPTY: this is the state that the pigment initializes in
164
187
        STATE_INFO: the pigment only contains essential meta-data, for example, pigments
165
188
            viewed in the repo browser are in this state, no attachments
168
191
        STATE_TEMP: the pigment has been extracted to a temporary directory,
169
192
            including attachments
170
193
        STATE_INCOMPLETE: the pigment doesn't contain enough meta-data to qualify
171
 
            as STATE_INFO, but it is not empty"""
 
194
            as STATE_INFO, but it is not empty
 
195
        
 
196
        """
172
197
        # check to see if pigment's essential meta-data is completed
173
198
        # only skins are excluded from the preview check
174
199
        if self.humanName != {"en":""} and \
223
248
    
224
249
    def set_preview_file(self, filename):
225
250
        """Set the preview file. If an absolute path is given, the
226
 
        pigment will load it"""
 
251
        pigment will load it.
 
252
        
 
253
        Keyword arguments:
 
254
        filename -- string
 
255
        
 
256
        """
227
257
        if os.path.isabs(os.path.expanduser(filename)):
228
258
            if not os.path.exists(filename):
229
259
                raise(ep_exceptions.PreviewFileNotFoundException(filename))
237
267
            self.preview = None
238
268
    
239
269
    def _give_preview_file(self):
240
 
        """Returns the absolute path to a preview file for this pigment.
 
270
        """Return the absolute path to a preview file for this pigment.
241
271
        If the preview filename hasn't been set, but a Pixbuf has, this
242
 
        will save a temporary file named preview.png and return its path"""
 
272
        will save a temporary file named preview.png and return its path.
 
273
        
 
274
        """
243
275
        subprocess.call(["mkdir", "-p", "/tmp/epidermis/preview"])
244
276
        if len(self.previewFilename) > 0 and len(self.previewPath) == 0:
245
277
            self.preview.save("/tmp/epidermis/preview" + self.previewFilename, self.previewFilename.split(".")[-1].lower())
251
283
            return self.previewPath
252
284
    
253
285
    def get_preview(self):
254
 
        """Returns a Pixbuf for the preview"""
 
286
        """Return a Pixbuf for the preview."""
255
287
        if not self.preview is None:
256
288
            return self.preview
257
289
        elif len(self.previewPath) > 0:
267
299
            return None
268
300
    
269
301
    def generate_preview(self):
270
 
        """Automatically generate a preview pixbuf based on attachments and save it to self.preview
 
302
        """Automatically generate a preview pixbuf based on attachments 
 
303
        and save it to self.preview.
271
304
        Returning None means the method was not successful, otherwise, the method will return
272
 
        the newly generated self.preview"""
273
 
        return None
 
305
        the newly generated self.preview
 
306
        
 
307
        """
 
308
        handy.abstract()
274
309
    
275
310
    def _extract_in_temp(self, filePath, shell=None):
276
 
        """Extracts the downloaded pigment to /tmp/epidermis/pigments/TYPE/CODENAME
 
311
        """Extract the downloaded pigment to /tmp/epidermis/pigments/TYPE/CODENAME
 
312
        
 
313
        
277
314
        Returns the directory where the pigment has been extracted to.
278
 
        filePath: the path of the downloaded .pigment (string)
279
 
        shell: the Shell object that should be used, defaults to subprocess shell"""
 
315
        
 
316
        Keyword arguments:
 
317
        filePath -- the path of the downloaded .pigment (string)
 
318
        shell -- the Shell object that should be used, defaults to subprocess shell
 
319
        
 
320
        """
280
321
        if not os.path.exists(filePath):
281
322
            raise(ep_exceptions.FileNotFoundException(filePath))
282
323
        if shell is None:
299
340
        return mytmp
300
341
    
301
342
    def _rearrange_temp(self, dir, shell=None):
302
 
        """Moves temp dir from dir to /tmp/epidermis/pigments/TYPE/CODENAME
303
 
        If preview file is in dir, it is also moved
 
343
        """Move temp dir from dir to /tmp/epidermis/pigments/TYPE/CODENAME
 
344
        If preview file is in dir, it is also moved.
304
345
        If any attachments are in /tmp, they're moved and re-added to attachments using self.add_attachment
305
346
        Sets self.installationDirectory to /tmp/epidermis/pigments/
306
 
        Returns temp dir"""
 
347
        
 
348
        Returns temp dir.
 
349
        
 
350
        """
307
351
        if shell is None:
308
352
            shell = SubprocessShell()
309
353
            shell.prepare()
344
388
 
345
389
    
346
390
    def install(self, installationDirectory, progressCallback=None, shell=None):
347
 
        """Installs Pigment, ie, copies the information to installationDirectory/type/codename
 
391
        """Install Pigment, ie, copies the information to installationDirectory/type/codename
348
392
        and copies the data to the appropriate place.
349
 
        installationDirectory: which base directory should be used to install
350
 
        the pigment (for example, MY_DATA_HOME)
351
 
        progressCallback: a function which accept two argument: progress: a
352
 
        float varying between 0.0 and 1.0, and query: a integer defaulting to None.
353
 
        If the function returns True then the installation will be aborted.
354
 
        query can be QUERY_OVERWRITE, which means that this method is asking
355
 
        whether it can overwrite
356
 
        shell: the Shell object that should be used to call commands as root
357
 
        Returns whether the installation was successfull, True or False"""
 
393
        
 
394
        Returns whether the installation was successfull, True or False
 
395
        
 
396
        Keyword arguments:
 
397
        installationDirectory -- which base directory should be used to install
 
398
                                 the pigment (for example, MY_DATA_HOME)
 
399
        progressCallback -- a function which accept two argument: progress: a
 
400
                            float varying between 0.0 and 1.0, and query:
 
401
                            a integer defaulting to None.
 
402
                            If the function returns True then the 
 
403
                            installation will be aborted.
 
404
                            query can be QUERY_OVERWRITE, which means 
 
405
                            that this method is asking whether it can 
 
406
                            overwrite
 
407
        shell -- the Shell object that should be used to call commands as root
 
408
        
 
409
        """
358
410
        
359
411
        # use subprocess shell if not specified
360
412
        if shell is None:
397
449
            
398
450
    
399
451
    def remove(self, progressCallback=None, shell=None):
400
 
        """Uninstalls pigment.
401
 
        progressCallback: a function which accept one argument: progress: a
402
 
        float varying between 0.0 and 1.0. If the function returns True then 
403
 
        the uninstallation will be aborted
404
 
        shell: the Shell object that should be used to call commands as root"""
 
452
        """Uninstall pigment.
 
453
        
 
454
        Keyword arguments:
 
455
        progressCallback -- a function which accept one argument: progress: a
 
456
                            float varying between 0.0 and 1.0. If the 
 
457
                            function returns True then the uninstallation
 
458
                            will be aborted
 
459
        shell -- the Shell object that should be used to call commands 
 
460
                 as root
 
461
        
 
462
        """
405
463
        # use subprocess shell if not specified
406
464
        if shell is None:
407
465
            shell = SubprocessShell()
419
477
        progressCallback(1.0)
420
478
    
421
479
    def activate(self, progressCallback=None, shell=None):
422
 
        """Applies the pigment to current user, and possibly system-wide
423
 
        progressCallback: a function which accepts one argument: progress: a
424
 
        float varying between 0.0 and 1.0 . If the function returns True then
425
 
        the activation will be aborted
426
 
        shell: the Shell object that should be used to call commands as root"""
427
 
        if not progressCallback is None:
428
 
            progressCallback(1.0)
429
 
        pass
 
480
        """Apply the pigment to current user, and possibly system-wide.
 
481
        
 
482
        Keyword arguments:
 
483
        progressCallback -- a function which accepts one argument: progress: a
 
484
                            float varying between 0.0 and 1.0 . If the 
 
485
                            function returns True then the activation 
 
486
                            will be aborted
 
487
        shell -- the Shell object that should be used to call commands 
 
488
                 as root
 
489
        """
 
490
        handy.abstract()
430
491
    
431
492
    def save(self, filePath, shell=None):
432
 
        """Saves the pigment to filename as .pigment archive"""
 
493
        """Save the pigment to filename as .pigment archive"""
433
494
        # TODO: save needs to be more easily 'sub-classed'
434
495
        # for example, the gtk_ pigment saves with it metacity
435
496
        doc = self.information_xml()
466
527
    
467
528
    def read(self, filePath):
468
529
        """Load the Pigment object from an xml file (.xml)
 
530
        
469
531
        This function will look for the preview file and for attachments, if required
470
532
        NOTE: this function will look for attachments in places other than filePath, 
471
 
        #TODO: change this?"""
 
533
        #TODO: change this?
 
534
        
 
535
        """
472
536
        if not os.path.exists(filePath):
473
537
            raise(ep_exceptions.FileNotFoundException(filePath))
474
538
        doc = minidom.parse(filePath)
521
585
    
522
586
    def write(self, filePath, shell=None):
523
587
        """Write the XML file to filePath
524
 
        Doesn't save preview"""
 
588
        Doesn't save preview
 
589
        
 
590
        """
525
591
        # TODO: fixme ? write doesn't save preview
526
592
        subprocess.call(["rm", "/tmp/epidermis/pigment.xml"])
527
593
        subprocess.call(["mkdir", "-p", "/tmp/epidermis"])
536
602
        shell.do(["mv", "/tmp/epidermis/pigment.xml", filePath])
537
603
    
538
604
    def information_xml(self):
539
 
        """Returns the XML document describing the pigment, this document is
540
 
        usually saved as pigment.xml"""
 
605
        """Return the XML document describing the pigment, this document is
 
606
        usually saved as pigment.xml
 
607
        
 
608
        """
541
609
        doc = minidom.Document()
542
610
        root = doc.createElement("pigment")
543
611
        doc.appendChild(root)
572
640
    def is_attachment_correct(self, attachmentIndex=None):
573
641
        """Return whether the attachment number attachmentIndex or all the attachments
574
642
        if None is passed are correct.
 
643
        
575
644
        For example, a Metacity pigment would verify that the attachment is a
576
645
        directory with a metacity-1 subdirectory
577
 
        It does not verify the location of the attachment"""
 
646
        It does not verify the location of the attachment
 
647
        
 
648
        """
578
649
        if attachmentIndex is None:
579
650
            for att in self.attachments:
580
651
                if not os.path.exists(att):
594
665
##        return
595
666
    
596
667
    def summary(self):
597
 
        """Returns a string: summary of the Pigment object"""
 
668
        """Return a string: summary of the Pigment object"""
598
669
        return "Pigment codename: " + self.codeName \
599
670
            + "\nhumanName: " + str(self.humanName) \
600
671
            + "\ncopyright: " + self.copyright \
623
694
##        return
624
695
    
625
696
    def does_activation_require_root(self):
626
 
        """Returns whether the activation requires root rights.
 
697
        """Return whether the activation requires root rights.
627
698
        If it does, the Pigment object will need a Shell running as root
628
 
        to be passed to some of its methods"""
629
 
        return False
 
699
        to be passed to some of its methods
 
700
        
 
701
        """
 
702
        handy.abstract()
630
703
    
631
704
    def does_uninstallation_require_root(self):
632
 
        """Returns whether the activation requires root's rights.
 
705
        """Return whether the activation requires root's rights.
633
706
        If it does, the Pigment object will need a Shell running as root
634
 
        to be passed to the remove method"""
 
707
        to be passed to the remove method
 
708
        
 
709
        """
635
710
        # TODO: check permissions of files and attachments to determine
636
711
        # whether uninstallation requires root
637
712
        return True
638
713
    
639
714
    def match_filter(self, matchString, lang="en"):
640
 
        """Returns whether this pigment should be a result for a search for the
641
 
        string passed"""
 
715
        """Return whether this pigment should be a result for a search for the
 
716
        string passed
 
717
        
 
718
        Keyword arguments:
 
719
        matchString -- the search string
 
720
        lang -- the language code
 
721
        
 
722
        """
642
723
        for ii in (self.get_human_name(lang), self.get_description(lang)):
643
724
            if matchString.lower() in ii.lower():
644
725
                return True
645
726
        return False
646
 
 
647
 
get_first_text = handy.get_first_text
648
 
 
649
 
def main():
650
 
    print >> sys.stderr, "don't run this file"
651
 
 
652
 
 
653
 
if __name__ == "__main__":
654
 
    main()
 
727
        
 
728