~mvo/software-center/lp957599

« back to all changes in this revision

Viewing changes to softwarecenter/ui/gtk3/models/appstore2.py

  • Committer: Gary Lasker
  • Date: 2012-03-15 02:43:20 UTC
  • mfrom: (2851.1.6 pep8-test)
  • Revision ID: gary.lasker@canonical.com-20120315024320-9zu3c3enz1oa5lyb
pep8 fixes for many more files in ui.gtk3.{*}

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
 
25
25
from gettext import gettext as _
26
26
 
27
 
from softwarecenter.enums import (Icons, 
 
27
from softwarecenter.enums import (Icons,
28
28
                                  XapianValues)
29
29
 
30
30
 
31
 
from softwarecenter.utils import ExecutionTime, SimpleFileDownloader, split_icon_ext
 
31
from softwarecenter.utils import (
 
32
    ExecutionTime,
 
33
    SimpleFileDownloader,
 
34
    split_icon_ext,
 
35
    )
32
36
from softwarecenter.backend import get_install_backend
33
37
from softwarecenter.backend.reviews import get_review_loader
34
38
from softwarecenter.paths import SOFTWARE_CENTER_ICON_CACHE_DIR
44
48
LOG = logging.getLogger(__name__)
45
49
_FREE_AS_IN_BEER = ("0.00", "")
46
50
 
 
51
 
47
52
class CategoryRowReference:
48
 
    """ A simple container for Category properties to be 
 
53
    """ A simple container for Category properties to be
49
54
        displayed in a AppListStore or AppTreeStore
50
55
    """
51
56
 
55
60
        #self.subcategories = subcats
56
61
        self.pkg_count = pkg_count
57
62
        self.vis_count = pkg_count
58
 
        return
59
63
 
60
64
 
61
65
class UncategorisedRowRef(CategoryRowReference):
70
74
                                      untranslated_name,
71
75
                                      display_name,
72
76
                                      None, pkg_count)
73
 
        return
74
77
 
75
78
 
76
79
class AppPropertiesHelper(GObject.GObject):
79
82
    """
80
83
 
81
84
    __gsignals__ = {
82
 
        "needs-refresh" : (GObject.SignalFlags.RUN_LAST,
83
 
                          None, 
84
 
                           (str, ),
85
 
                           ),
 
85
        "needs-refresh": (GObject.SignalFlags.RUN_LAST,
 
86
                         None,
 
87
                          (str, ),
 
88
                          ),
86
89
        }
87
90
 
88
 
    def __init__(self, db, cache, icons, icon_size=48, global_icon_cache=False):
 
91
    def __init__(self, db, cache, icons, icon_size=48,
 
92
        global_icon_cache=False):
89
93
        GObject.GObject.__init__(self)
90
94
        self.db = db
91
95
        self.cache = cache
102
106
        self.icons = icons
103
107
        self.icon_size = icon_size
104
108
 
105
 
        # cache the 'missing icon' used in the treeview for apps without an icon
 
109
        # cache the 'missing icon' used in the treeview for apps without an
 
110
        # icon
106
111
        self._missing_icon = icons.load_icon(Icons.MISSING_APP, icon_size, 0)
107
112
        if global_icon_cache:
108
113
            self.icon_cache = _app_icon_cache
109
114
        else:
110
115
            self.icon_cache = {}
111
 
        return
112
116
 
113
117
    def _download_icon_and_show_when_ready(self, url, pkgname, icon_file_name):
114
 
        LOG.debug("did not find the icon locally, must download %s" % icon_file_name)
 
118
        LOG.debug("did not find the icon locally, must download %s" %
 
119
            icon_file_name)
115
120
 
116
121
        def on_image_download_complete(downloader, image_file_path, pkgname):
117
122
            LOG.debug("download for '%s' complete" % image_file_path)
118
123
            pb = GdkPixbuf.Pixbuf.new_from_file_at_size(icon_file_path,
119
124
                                                        self.icon_size,
120
125
                                                        self.icon_size)
121
 
            # replace the icon in the icon_cache now that we've got the real one
 
126
            # replace the icon in the icon_cache now that we've got the real
 
127
            # one
122
128
            icon_file = split_icon_ext(os.path.basename(image_file_path))
123
129
            self.icon_cache[icon_file] = pb
124
130
            self.emit("needs-refresh", pkgname)
125
 
        
 
131
 
126
132
        if url is not None:
127
 
            icon_file_path = os.path.join(SOFTWARE_CENTER_ICON_CACHE_DIR, icon_file_name)
 
133
            icon_file_path = os.path.join(SOFTWARE_CENTER_ICON_CACHE_DIR,
 
134
                icon_file_name)
128
135
            image_downloader = SimpleFileDownloader()
129
 
            image_downloader.connect('file-download-complete', on_image_download_complete, pkgname)
 
136
            image_downloader.connect('file-download-complete',
 
137
                on_image_download_complete, pkgname)
130
138
            image_downloader.download_file(url, icon_file_path)
131
139
 
132
140
    def update_availability(self, doc):
134
142
        doc.installed = None
135
143
        doc.purchasable = None
136
144
        self.is_installed(doc)
137
 
        return
138
145
 
139
146
    def is_available(self, doc):
140
147
        if doc.available is None:
152
159
 
153
160
    def is_purchasable(self, doc):
154
161
        if doc.purchasable is None:
155
 
            doc.purchasable = doc.get_value(XapianValues.PRICE) not in _FREE_AS_IN_BEER
 
162
            doc.purchasable = (doc.get_value(XapianValues.PRICE) not in
 
163
                _FREE_AS_IN_BEER)
156
164
        return doc.purchasable
157
165
 
158
166
    def get_pkgname(self, doc):
195
203
                # icons.load_icon takes between 0.001 to 0.01s on my
196
204
                # machine, this is a significant burden because get_value
197
205
                # is called *a lot*. caching is the only option
198
 
                
 
206
 
199
207
                # look for the icon on the iconpath
200
208
                if self.icons.has_icon(icon_name):
201
209
                    icon = self.icons.load_icon(icon_name, self.icon_size, 0)
224
232
        return -1
225
233
 
226
234
    def _category_translate(self, catname):
227
 
        """ helper that will look into the categories we got from the 
 
235
        """ helper that will look into the categories we got from the
228
236
            parser and returns the translated name if it find it,
229
237
            otherwise it resorts to plain gettext
230
238
        """
231
 
        # look into parsed categories that use .directory translation 
 
239
        # look into parsed categories that use .directory translation
232
240
        for cat in self.all_categories:
233
241
            if cat.untranslated_name == catname:
234
242
                return cat.name
271
279
    ICON_SIZE = 32
272
280
 
273
281
    # the amount of items to initially lo
274
 
    LOAD_INITIAL   = 75
 
282
    LOAD_INITIAL = 75
275
283
 
276
284
    def __init__(self, db, cache, icons, icon_size, global_icon_cache):
277
 
        AppPropertiesHelper.__init__(self, db, cache, icons, icon_size, 
 
285
        AppPropertiesHelper.__init__(self, db, cache, icons, icon_size,
278
286
                                     global_icon_cache)
279
287
 
280
288
        # backend stuff
281
289
        self.backend = get_install_backend()
282
 
        self.backend.connect("transaction-progress-changed", self._on_transaction_progress_changed)
283
 
        self.backend.connect("transaction-started", self._on_transaction_started)
284
 
        self.backend.connect("transaction-finished", self._on_transaction_finished)
 
290
        self.backend.connect("transaction-progress-changed",
 
291
            self._on_transaction_progress_changed)
 
292
        self.backend.connect("transaction-started",
 
293
            self._on_transaction_started)
 
294
        self.backend.connect("transaction-finished",
 
295
            self._on_transaction_finished)
285
296
 
286
297
        # keep track of paths for transactions in progress
287
298
        self.transaction_path_map = {}
294
305
 
295
306
        # other stuff
296
307
        self.active = False
297
 
        return
298
308
 
299
 
    # FIXME: port from 
 
309
    # FIXME: port from
300
310
    @property
301
311
    def installable_apps(self):
302
312
        return []
 
313
 
303
314
    @property
304
315
    def existing_apps(self):
305
316
        return []
307
318
    def notify_action_request(self, doc, path):
308
319
        pkgname = str(self.get_pkgname(doc))
309
320
        self.transaction_path_map[pkgname] = (path, self.get_iter(path))
310
 
        return
311
321
 
312
322
    def set_from_matches(self, matches):
313
323
        # stub
314
324
        raise NotImplementedError
315
325
 
316
326
    # the following methods ensure that the contents data is refreshed
317
 
    # whenever a transaction potentially changes it: 
318
 
    def _on_transaction_started(self, backend, pkgname, appname, trans_id, trans_type):
 
327
    # whenever a transaction potentially changes it:
 
328
    def _on_transaction_started(self, backend, pkgname, appname, trans_id,
 
329
        trans_type):
319
330
        #~ self._refresh_transaction_map()
320
331
        pass
321
332
 
323
334
        if pkgname in self.transaction_path_map:
324
335
            path, it = self.transaction_path_map[pkgname]
325
336
            self.row_changed(path, it)
326
 
        return
327
337
 
328
338
    def _on_transaction_finished(self, backend, result):
329
339
        pkgname = str(result.pkgname)
356
366
            #~ print "Appstore buffered icons in %s seconds" % t_lapsed
357
367
            #from softwarecenter.utils import get_nice_size
358
368
            #~ cache_size = get_nice_size(sys.getsizeof(_app_icon_cache))
359
 
            #~ print "Number of icons in cache: %s consuming: %sb" % (len(_app_icon_cache), cache_size)
 
369
            #~ print "Number of icons in cache: %s consuming: %sb" % (
 
370
                #~ len(_app_icon_cache), cache_size)
360
371
            return False    # remove from sources on completion
361
372
 
362
373
        if self.current_matches is not None:
363
374
            GObject.idle_add(buffer_icons)
364
 
        return
365
375
 
366
376
    def load_range(self, indices, step):
367
377
        # stub
368
 
        return
 
378
        pass
 
379
 
369
380
 
370
381
class AppListStore(Gtk.ListStore, AppGenericStore):
371
382
    """ use for flat applist views. for large lists this appends rows approx
373
384
    """
374
385
 
375
386
    __gsignals__ = {
376
 
        "appcount-changed" : (GObject.SignalFlags.RUN_LAST,
377
 
                              None, 
378
 
                              (GObject.TYPE_PYOBJECT, ),
379
 
                             ),
 
387
        "appcount-changed": (GObject.SignalFlags.RUN_LAST,
 
388
                             None,
 
389
                             (GObject.TYPE_PYOBJECT, ),
 
390
                            ),
380
391
        # meh, this is a signal from AppPropertiesHelper
381
 
        "needs-refresh" : (GObject.SignalFlags.RUN_LAST,
382
 
                              None, 
383
 
                              (str, ),
384
 
                             ),
 
392
        "needs-refresh": (GObject.SignalFlags.RUN_LAST,
 
393
                             None,
 
394
                             (str, ),
 
395
                            ),
385
396
        }
386
397
 
387
 
    def __init__(self, db, cache, icons, icon_size=AppGenericStore.ICON_SIZE, 
 
398
    def __init__(self, db, cache, icons, icon_size=AppGenericStore.ICON_SIZE,
388
399
                 global_icon_cache=True):
389
400
        AppGenericStore.__init__(
390
401
            self, db, cache, icons, icon_size, global_icon_cache)
392
403
        self.set_column_types(self.COL_TYPES)
393
404
 
394
405
        self.current_matches = None
395
 
        return
396
 
 
397
406
 
398
407
    def set_from_matches(self, matches):
399
408
        """ set the content of the liststore based on a list of
401
410
        """
402
411
        self.current_matches = matches
403
412
        n_matches = len(matches)
404
 
        if n_matches == 0: 
 
413
        if n_matches == 0:
405
414
            return
406
 
    
 
415
 
407
416
        extent = min(self.LOAD_INITIAL, n_matches)
408
417
 
409
418
        with ExecutionTime("store.append_initial"):
411
420
                doc.available = doc.installed = doc.purchasable = None
412
421
                self.append((doc,))
413
422
 
414
 
        if n_matches == extent: 
 
423
        if n_matches == extent:
415
424
            return
416
425
 
417
426
        with ExecutionTime("store.append_placeholders"):
420
429
 
421
430
        self.emit('appcount-changed', len(matches))
422
431
        self.buffer_icons()
423
 
        return
424
432
 
425
433
    def load_range(self, indices, step):
426
434
        db = self.db.xapiandb
440
448
            except IndexError:
441
449
                break
442
450
 
443
 
            if row_content: continue
 
451
            if row_content:
 
452
                continue
444
453
            doc = db.get_document(matches[i].docid)
445
454
            doc.available = doc.installed = doc.purchasable = None
446
455
            self[(i,)][0] = doc
447
 
        return
448
456
 
449
457
    def clear(self):
450
458
        # reset the tranaction map because it will now be invalid
451
459
        self.transaction_path_map = {}
452
460
        self.current_matches = None
453
461
        Gtk.ListStore.clear(self)
454
 
        return
455
462
 
456
463
 
457
464
class AppTreeStore(Gtk.TreeStore, AppGenericStore):
458
465
    """ A treestore based application model
459
466
    """
460
467
 
461
 
    def __init__(self, db, cache, icons, icon_size=AppGenericStore.ICON_SIZE, 
 
468
    def __init__(self, db, cache, icons, icon_size=AppGenericStore.ICON_SIZE,
462
469
                 global_icon_cache=True):
463
470
        AppGenericStore.__init__(
464
471
            self, db, cache, icons, icon_size, global_icon_cache)
465
472
        Gtk.TreeStore.__init__(self)
466
473
        self.set_column_types(self.COL_TYPES)
467
 
        return
468
474
 
469
475
    def set_documents(self, parent, documents):
470
476
        for doc in documents:
471
 
            doc.available = None; doc.installed = doc.purchasable = None
 
477
            doc.available = None
 
478
            doc.installed = doc.purchasable = None
472
479
            self.append(parent, (doc,))
473
480
 
474
481
        self.transaction_path_map = {}
475
 
        return
476
482
 
477
483
    def set_category_documents(self, cat, documents):
478
484
        category = CategoryRowReference(cat.untranslated_name,
484
490
        self.set_documents(it, documents)
485
491
        return it
486
492
 
487
 
    def set_nocategory_documents(self, documents, untranslated_name=None, display_name=None):
 
493
    def set_nocategory_documents(self, documents, untranslated_name=None,
 
494
        display_name=None):
488
495
        category = UncategorisedRowRef(untranslated_name,
489
496
                                       display_name,
490
497
                                       len(documents))
496
503
        # reset the tranaction map because it will now be invalid
497
504
        self.transaction_path_map = {}
498
505
        Gtk.TreeStore.clear(self)
499
 
        return
500