Merge lp:~elachuni/software-center/pep8-test-part10 into lp:software-center

Proposed by Anthony Lenton
Status: Merged
Merged at revision: 2853
Proposed branch: lp:~elachuni/software-center/pep8-test-part10
Merge into: lp:software-center
Diff against target: 1214 lines (+179/-183)
2 files modified
softwarecenter/ui/gtk3/views/appdetailsview.py (+178/-182)
test/test_pep8.py (+1/-1)
To merge this branch: bzr merge lp:~elachuni/software-center/pep8-test-part10
Reviewer Review Type Date Requested Status
Gary Lasker (community) Approve
Review via email: mp+97540@code.launchpad.net

Description of the change

This branch makes a single (large) file pass the pep8 test, softwarecenter/ui/gtk3/views/appdetailsview.py.

There were a couple of places where splitting long lines got tricky:
 - Lines 120-125 of the diff, I chose to make a variable name shorter. I think my second option would have been to use a backslash to cut the line before the last period.
 - Lines 628-630 of the diff, here I preferred to create a new local variable. I think my second option again would have been to use a backslash before the last period. In both cases I'm a bit on the fence and open to suggestions, let me know what you think.

To post a comment you must log in.
Revision history for this message
Gary Lasker (gary-lasker) wrote :

I think the two cases you mention look just fine. Thanks as always, Anthony!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'softwarecenter/ui/gtk3/views/appdetailsview.py'
--- softwarecenter/ui/gtk3/views/appdetailsview.py 2012-02-27 16:05:43 +0000
+++ softwarecenter/ui/gtk3/views/appdetailsview.py 2012-03-14 23:52:20 +0000
@@ -38,11 +38,11 @@
38from softwarecenter.db import DebFileApplication38from softwarecenter.db import DebFileApplication
39from softwarecenter.backend.reviews import ReviewStats39from softwarecenter.backend.reviews import ReviewStats
40#from softwarecenter.backend.zeitgeist_simple import zeitgeist_singleton40#from softwarecenter.backend.zeitgeist_simple import zeitgeist_singleton
41from softwarecenter.enums import (AppActions, 41from softwarecenter.enums import (AppActions,
42 PkgStates,42 PkgStates,
43 Icons, 43 Icons,
44 SOFTWARE_CENTER_PKGNAME)44 SOFTWARE_CENTER_PKGNAME)
45from softwarecenter.utils import (is_unity_running, 45from softwarecenter.utils import (is_unity_running,
46 upstream_version,46 upstream_version,
47 get_exec_line_from_desktop,47 get_exec_line_from_desktop,
48 SimpleFileDownloader,48 SimpleFileDownloader,
@@ -82,10 +82,11 @@
82from softwarecenter.backend import get_install_backend82from softwarecenter.backend import get_install_backend
8383
8484
85LOG=logging.getLogger(__name__)85LOG = logging.getLogger(__name__)
86
8687
87class StatusBar(Gtk.Alignment):88class StatusBar(Gtk.Alignment):
88 """ Subclass of Gtk.Alignment that draws a small dash border 89 """ Subclass of Gtk.Alignment that draws a small dash border
89 around the rectangle.90 around the rectangle.
90 """91 """
9192
@@ -102,7 +103,6 @@
102 self._bg = [1, 1, 1, 0.3]103 self._bg = [1, 1, 1, 0.3]
103104
104 self.connect("style-updated", self.on_style_updated)105 self.connect("style-updated", self.on_style_updated)
105 return
106106
107 def on_style_updated(self, widget):107 def on_style_updated(self, widget):
108 context = self.get_style_context()108 context = self.get_style_context()
@@ -110,7 +110,6 @@
110 context = widget.get_style_context()110 context = widget.get_style_context()
111 border = context.get_border(Gtk.StateFlags.NORMAL)111 border = context.get_border(Gtk.StateFlags.NORMAL)
112 self._border_width = max(1, max(border.top, border.bottom))112 self._border_width = max(1, max(border.top, border.bottom))
113 return
114113
115 def do_draw(self, cr):114 def do_draw(self, cr):
116 cr.save()115 cr.save()
@@ -118,7 +117,7 @@
118 width = self._border_width117 width = self._border_width
119118
120 # fill bg119 # fill bg
121 cr.rectangle(-width, 0, a.width+2*width, a.height)120 cr.rectangle(-width, 0, a.width + 2 * width, a.height)
122 cr.set_source_rgba(*self._bg)121 cr.set_source_rgba(*self._bg)
123 cr.fill_preserve()122 cr.fill_preserve()
124123
@@ -130,14 +129,15 @@
130 context.restore()129 context.restore()
131130
132 Gdk.cairo_set_source_rgba(cr, bc)131 Gdk.cairo_set_source_rgba(cr, bc)
133 cr.set_dash((width, 2*width), 1)132 cr.set_dash((width, 2 * width), 1)
134 cr.set_line_width(2*width)133 cr.set_line_width(2 * width)
135 cr.stroke()134 cr.stroke()
136135
137 cr.restore()136 cr.restore()
138 for child in self: 137 for child in self:
139 self.propagate_draw(child, cr)138 self.propagate_draw(child, cr)
140139
140
141class WarningStatusBar(StatusBar):141class WarningStatusBar(StatusBar):
142142
143 def __init__(self, view):143 def __init__(self, view):
@@ -153,6 +153,7 @@
153 # override _bg153 # override _bg
154 self._bg = [1, 1, 0, 0.3]154 self._bg = [1, 1, 0, 0.3]
155155
156
156class PackageStatusBar(StatusBar):157class PackageStatusBar(StatusBar):
157 """ Package specific status bar that contains a state label,158 """ Package specific status bar that contains a state label,
158 a action button and a progress bar.159 a action button and a progress bar.
@@ -160,7 +161,7 @@
160161
161 def __init__(self, view):162 def __init__(self, view):
162 StatusBar.__init__(self, view)163 StatusBar.__init__(self, view)
163 self.installed_icon = Gtk.Image.new_from_icon_name(164 self.installed_icon = Gtk.Image.new_from_icon_name(
164 Icons.INSTALLED_OVERLAY, Gtk.IconSize.DIALOG)165 Icons.INSTALLED_OVERLAY, Gtk.IconSize.DIALOG)
165 self.label = Gtk.Label()166 self.label = Gtk.Label()
166 self.label.set_line_wrap(True)167 self.label.set_line_wrap(True)
@@ -242,20 +243,17 @@
242 app, addons_to_install, addons_to_remove)243 app, addons_to_install, addons_to_remove)
243 elif state == PkgStates.NEEDS_SOURCE:244 elif state == PkgStates.NEEDS_SOURCE:
244 app_manager.enable_software_source(app)245 app_manager.enable_software_source(app)
245 return
246246
247 def set_label(self, label):247 def set_label(self, label):
248 m = '<big><b>%s</b></big>' % label248 m = '<big><b>%s</b></big>' % label
249 self.label.set_markup(m)249 self.label.set_markup(m)
250 return
251250
252 def get_label(self):251 def get_label(self):
253 return self.label.get_text()252 return self.label.get_text()
254253
255 def set_button_label(self, label):254 def set_button_label(self, label):
256 self.button.set_label(label)255 self.button.set_label(label)
257 return256
258
259 def get_button_label(self):257 def get_button_label(self):
260 return self.button.get_label()258 return self.button.get_label()
261259
@@ -263,14 +261,14 @@
263 # the currently forced archive_suite for the given app261 # the currently forced archive_suite for the given app
264 app_version = self.app_details.version262 app_version = self.app_details.version
265 # all available not-automatic (version, archive_suits)263 # all available not-automatic (version, archive_suits)
266 not_automatic_suites = self.app_details.get_not_automatic_archive_versions()264 not_auto_suites = self.app_details.get_not_automatic_archive_versions()
267 # populat the combobox if 265 # populat the combobox if
268 if not_automatic_suites:266 if not_auto_suites:
269 combo = self.combo_multiple_versions267 combo = self.combo_multiple_versions
270 combo.disconnect_by_func(self._on_combo_multiple_versions_changed)268 combo.disconnect_by_func(self._on_combo_multiple_versions_changed)
271 model = self.combo_multiple_versions.get_model()269 model = self.combo_multiple_versions.get_model()
272 model.clear()270 model.clear()
273 for i, archive_suite in enumerate(not_automatic_suites):271 for i, archive_suite in enumerate(not_auto_suites):
274 # get the version, archive_suite272 # get the version, archive_suite
275 ver, archive_suite = archive_suite273 ver, archive_suite = archive_suite
276 # the string to display is something like:274 # the string to display is something like:
@@ -278,9 +276,9 @@
278 displayed_archive_suite = archive_suite276 displayed_archive_suite = archive_suite
279 if i == 0:277 if i == 0:
280 displayed_archive_suite = _("default")278 displayed_archive_suite = _("default")
281 s = "v%s (%s)" % (upstream_version(ver), 279 s = "v%s (%s)" % (upstream_version(ver),
282 displayed_archive_suite)280 displayed_archive_suite)
283 model.append( (s, archive_suite) )281 model.append((s, archive_suite))
284 if app_version == ver:282 if app_version == ver:
285 self.combo_multiple_versions.set_active(i)283 self.combo_multiple_versions.set_active(i)
286 # if nothing is found, set to default284 # if nothing is found, set to default
@@ -321,9 +319,9 @@
321 self.progress.hide()319 self.progress.hide()
322 self.installed_icon.hide()320 self.installed_icon.hide()
323321
324 # FIXME: Use a Gtk.Action for the Install/Remove/Buy/Add 322 # FIXME: Use a Gtk.Action for the Install/Remove/Buy/Add
325 # Source/Update Now action so that all UI controls323 # Source/Update Now action so that all UI controls
326 # (menu item, applist view button and appdetails view button) 324 # (menu item, applist view button and appdetails view button)
327 # are managed centrally: button text, button sensitivity,325 # are managed centrally: button text, button sensitivity,
328 # and the associated callback.326 # and the associated callback.
329 if state == PkgStates.INSTALLING:327 if state == PkgStates.INSTALLING:
@@ -340,32 +338,34 @@
340 self.set_label(_(u'Upgrading\u2026'))338 self.set_label(_(u'Upgrading\u2026'))
341 self.button.set_sensitive(False)339 self.button.set_sensitive(False)
342 elif state == PkgStates.INSTALLED or state == PkgStates.REINSTALLABLE:340 elif state == PkgStates.INSTALLED or state == PkgStates.REINSTALLABLE:
343 #special label only if the app being viewed is software centre itself341 # special label only if the app being viewed is software centre
342 # itself
344 self.installed_icon.show()343 self.installed_icon.show()
345 if app_details.pkgname== SOFTWARE_CENTER_PKGNAME:344 if app_details.pkgname == SOFTWARE_CENTER_PKGNAME:
346 self.set_label(_(u'Installed (you\u2019re using it right now)'))345 self.set_label(
346 _(u'Installed (you\u2019re using it right now)'))
347 else:347 else:
348 if app_details.purchase_date:348 if app_details.purchase_date:
349 # purchase_date is a string, must first convert to 349 # purchase_date is a string, must first convert to
350 # datetime.datetime350 # datetime.datetime
351 pdate = self._convert_purchase_date_str_to_datetime(351 pdate = self._convert_purchase_date_str_to_datetime(
352 app_details.purchase_date)352 app_details.purchase_date)
353 # TRANSLATORS : %Y-%m-%d formats the date as 2011-03-31, 353 # TRANSLATORS : %Y-%m-%d formats the date as 2011-03-31,
354 # please specify a format per your locale (if you prefer, 354 # please specify a format per your locale (if you prefer,
355 # %x can be used to provide a default locale-specific date 355 # %x can be used to provide a default locale-specific date
356 # representation)356 # representation)
357 self.set_label(pdate.strftime(_('Purchased on %Y-%m-%d')))357 self.set_label(pdate.strftime(_('Purchased on %Y-%m-%d')))
358 elif app_details.installation_date:358 elif app_details.installation_date:
359 # TRANSLATORS : %Y-%m-%d formats the date as 2011-03-31, 359 # TRANSLATORS : %Y-%m-%d formats the date as 2011-03-31,
360 # please specify a format per your locale (if you prefer, 360 # please specify a format per your locale (if you prefer,
361 # %x can be used to provide a default locale-specific date 361 # %x can be used to provide a default locale-specific date
362 # representation)362 # representation)
363 template = _('Installed on %Y-%m-%d')363 template = _('Installed on %Y-%m-%d')
364 self.set_label(app_details.installation_date.strftime(364 self.set_label(app_details.installation_date.strftime(
365 template))365 template))
366 else:366 else:
367 self.set_label(_('Installed'))367 self.set_label(_('Installed'))
368 if state == PkgStates.REINSTALLABLE: # only deb files atm368 if state == PkgStates.REINSTALLABLE: # only deb files atm
369 self.set_button_label(_('Reinstall'))369 self.set_button_label(_('Reinstall'))
370 elif state == PkgStates.INSTALLED:370 elif state == PkgStates.INSTALLED:
371 self.set_button_label(_('Remove'))371 self.set_button_label(_('Remove'))
@@ -374,7 +374,7 @@
374 # get that info from the software-center-agent/payments374 # get that info from the software-center-agent/payments
375 # service.375 # service.
376 # NOTE: the currency string for this label is purposely not376 # NOTE: the currency string for this label is purposely not
377 # translatable when hardcoded, since it (currently) 377 # translatable when hardcoded, since it (currently)
378 # won't vary based on locale and as such we don't want378 # won't vary based on locale and as such we don't want
379 # it translated379 # it translated
380 self.set_label("US$ %s" % app_details.price)380 self.set_label("US$ %s" % app_details.price)
@@ -389,11 +389,12 @@
389 PkgStates.PURCHASED_BUT_REPO_MUST_BE_ENABLED,389 PkgStates.PURCHASED_BUT_REPO_MUST_BE_ENABLED,
390 PkgStates.PURCHASED_BUT_NOT_AVAILABLE_FOR_SERIES):390 PkgStates.PURCHASED_BUT_NOT_AVAILABLE_FOR_SERIES):
391391
392 # purchase_date is a string, must first convert to datetime.datetime392 # purchase_date is a string, must first convert to
393 # datetime.datetime
393 pdate = self._convert_purchase_date_str_to_datetime(394 pdate = self._convert_purchase_date_str_to_datetime(
394 app_details.purchase_date)395 app_details.purchase_date)
395 # TRANSLATORS : %Y-%m-%d formats the date as 2011-03-31, please 396 # TRANSLATORS : %Y-%m-%d formats the date as 2011-03-31, please
396 # specify a format per your locale (if you prefer, %x can be used 397 # specify a format per your locale (if you prefer, %x can be used
397 # to provide a default locale-specific date representation)398 # to provide a default locale-specific date representation)
398 label = pdate.strftime(_('Purchased on %Y-%m-%d'))399 label = pdate.strftime(_('Purchased on %Y-%m-%d'))
399 self.set_button_label(_('Install'))400 self.set_button_label(_('Install'))
@@ -408,7 +409,7 @@
408 elif state == PkgStates.UNINSTALLED:409 elif state == PkgStates.UNINSTALLED:
409 #special label only if the app being viewed is software centre410 #special label only if the app being viewed is software centre
410 # itself411 # itself
411 if app_details.pkgname== SOFTWARE_CENTER_PKGNAME:412 if app_details.pkgname == SOFTWARE_CENTER_PKGNAME:
412 self.set_label(_(u'Removed (close it and it\u2019ll be gone)'))413 self.set_label(_(u'Removed (close it and it\u2019ll be gone)'))
413 else:414 else:
414 # TRANSLATORS: Free here means Gratis415 # TRANSLATORS: Free here means Gratis
@@ -436,12 +437,12 @@
436 self.set_label(_("Error"))437 self.set_label(_("Error"))
437 elif state == PkgStates.NOT_FOUND:438 elif state == PkgStates.NOT_FOUND:
438 # this is used when the pkg is not in the cache and there is no439 # this is used when the pkg is not in the cache and there is no
439 # request we display the error in the summary field and hide the 440 # request we display the error in the summary field and hide the
440 # rest441 # rest
441 pass442 pass
442 elif state == PkgStates.NEEDS_SOURCE:443 elif state == PkgStates.NEEDS_SOURCE:
443 channelfile = self.app_details.channelfile444 channelfile = self.app_details.channelfile
444 # it has a price and is not available 445 # it has a price and is not available
445 if channelfile:446 if channelfile:
446 self.set_button_label(_("Use This Source"))447 self.set_button_label(_("Use This Source"))
447 # check if it comes from a non-enabled component448 # check if it comes from a non-enabled component
@@ -460,13 +461,13 @@
460461
461 sensitive = network_state_is_connected()462 sensitive = network_state_is_connected()
462 self.button.set_sensitive(sensitive)463 self.button.set_sensitive(sensitive)
463 return464
464
465 def _convert_purchase_date_str_to_datetime(self, purchase_date):465 def _convert_purchase_date_str_to_datetime(self, purchase_date):
466 if purchase_date is not None:466 if purchase_date is not None:
467 return datetime.datetime.strptime(467 return datetime.datetime.strptime(
468 purchase_date, "%Y-%m-%d %H:%M:%S")468 purchase_date, "%Y-%m-%d %H:%M:%S")
469469
470
470class PackageInfo(Gtk.HBox):471class PackageInfo(Gtk.HBox):
471 """ Box with labels for package specific information like version info472 """ Box with labels for package specific information like version info
472 """473 """
@@ -485,14 +486,13 @@
485 self.a11y = self.get_accessible()486 self.a11y = self.get_accessible()
486487
487 self.connect('realize', self._on_realize)488 self.connect('realize', self._on_realize)
488 return
489489
490 def _on_realize(self, widget):490 def _on_realize(self, widget):
491 # key491 # key
492 k = Gtk.Label()492 k = Gtk.Label()
493 k.set_name("subtle-label")493 k.set_name("subtle-label")
494 key_markup = '<b>%s</b>'494 key_markup = '<b>%s</b>'
495 k.set_markup(key_markup % self.key)495 k.set_markup(key_markup % self.key)
496 k.set_alignment(1, 0)496 k.set_alignment(1, 0)
497497
498 # determine max width of all keys498 # determine max width of all keys
@@ -516,22 +516,23 @@
516516
517 self.set_property("can-focus", True)517 self.set_property("can-focus", True)
518 self.show_all()518 self.show_all()
519 return519
520
521 def set_width(self, width):520 def set_width(self, width):
522 return521 pass
523522
524 def set_value(self, value):523 def set_value(self, value):
525 self.value_label.set_markup(value)524 self.value_label.set_markup(value)
526 self.a11y.set_name(utf8(self.key) + ' ' + utf8(value))525 self.a11y.set_name(utf8(self.key) + ' ' + utf8(value))
527526
527
528class PackageInfoHW(PackageInfo):528class PackageInfoHW(PackageInfo):
529 """ special version of packageinfo that uses the custom 529 """ special version of packageinfo that uses the custom
530 HardwareRequirementsBox as the "label"530 HardwareRequirementsBox as the "label"
531 """531 """
532 def __init__(self, *args):532 def __init__(self, *args):
533 super(PackageInfoHW, self).__init__(*args)533 super(PackageInfoHW, self).__init__(*args)
534 self.value_label = HardwareRequirementsBox()534 self.value_label = HardwareRequirementsBox()
535
535 def set_value(self, value):536 def set_value(self, value):
536 self.value_label.set_hardware_requirements(value)537 self.value_label.set_hardware_requirements(value)
537538
@@ -553,7 +554,6 @@
553 self.checkbutton.pkgname = self.app.pkgname554 self.checkbutton.pkgname = self.app.pkgname
554 self.pack_start(self.checkbutton, False, False, 12)555 self.pack_start(self.checkbutton, False, False, 12)
555 self.connect('realize', self._on_realize, icons, pkgname)556 self.connect('realize', self._on_realize, icons, pkgname)
556 return
557557
558 def _on_realize(self, widget, icons, pkgname):558 def _on_realize(self, widget, icons, pkgname):
559 # icon559 # icon
@@ -610,15 +610,15 @@
610 self.checkbutton.set_active(is_active)610 self.checkbutton.set_active(is_active)
611611
612 def set_width(self, width):612 def set_width(self, width):
613 return613 pass
614614
615615
616class AddonsTable(Gtk.VBox):616class AddonsTable(Gtk.VBox):
617 """ Widget to display a table of addons. """617 """ Widget to display a table of addons. """
618618
619 __gsignals__ = {'table-built' : (GObject.SignalFlags.RUN_FIRST,619 __gsignals__ = {'table-built': (GObject.SignalFlags.RUN_FIRST,
620 None,620 None,
621 ()),621 ()),
622 }622 }
623623
624 def __init__(self, addons_manager):624 def __init__(self, addons_manager):
@@ -687,18 +687,18 @@
687 This will become visible if any addons are scheduled for install687 This will become visible if any addons are scheduled for install
688 or remove.688 or remove.
689 """689 """
690 690
691 def __init__(self, addons_manager):691 def __init__(self, addons_manager):
692 StatusBar.__init__(self, addons_manager.view)692 StatusBar.__init__(self, addons_manager.view)
693 self.addons_manager = addons_manager693 self.addons_manager = addons_manager
694 self.cache = self.addons_manager.view.cache694 self.cache = self.addons_manager.view.cache
695695
696 self.applying = False696 self.applying = False
697 697
698 # TRANSLATORS: Free here means Gratis698 # TRANSLATORS: Free here means Gratis
699 self.label_price = Gtk.Label(_("Free"))699 self.label_price = Gtk.Label(_("Free"))
700 self.hbox.pack_start(self.label_price, False, False, 0)700 self.hbox.pack_start(self.label_price, False, False, 0)
701 701
702 self.hbuttonbox = Gtk.HButtonBox()702 self.hbuttonbox = Gtk.HButtonBox()
703 self.hbuttonbox.set_layout(Gtk.ButtonBoxStyle.END)703 self.hbuttonbox.set_layout(Gtk.ButtonBoxStyle.END)
704 self.button_apply = Gtk.Button(_("Apply Changes"))704 self.button_apply = Gtk.Button(_("Apply Changes"))
@@ -711,9 +711,9 @@
711711
712 def configure(self):712 def configure(self):
713 LOG.debug("AddonsStatusBarConfigure")713 LOG.debug("AddonsStatusBarConfigure")
714 # FIXME: addons are not always free, but the old implementation 714 # FIXME: addons are not always free, but the old implementation
715 # of determining price was buggy715 # of determining price was buggy
716 if (not self.addons_manager.addons_to_install and 716 if (not self.addons_manager.addons_to_install and
717 not self.addons_manager.addons_to_remove):717 not self.addons_manager.addons_to_remove):
718 self.hide()718 self.hide()
719 else:719 else:
@@ -721,7 +721,7 @@
721 self.button_apply.set_sensitive(sensitive)721 self.button_apply.set_sensitive(sensitive)
722 self.button_cancel.set_sensitive(sensitive)722 self.button_cancel.set_sensitive(sensitive)
723 self.show_all()723 self.show_all()
724 724
725 def _on_button_apply_clicked(self, button):725 def _on_button_apply_clicked(self, button):
726 self.applying = True726 self.applying = True
727 self.button_apply.set_sensitive(False)727 self.button_apply.set_sensitive(False)
@@ -791,27 +791,28 @@
791791
792792
793_asset_cache = {}793_asset_cache = {}
794
795
794class AppDetailsView(Viewport):796class AppDetailsView(Viewport):
795 """ The view that shows the application details """797 """ The view that shows the application details """
796798
797 # the size of the icon on the left side799 # the size of the icon on the left side
798 APP_ICON_SIZE = 96 # Gtk.IconSize.DIALOG ?800 APP_ICON_SIZE = 96 # Gtk.IconSize.DIALOG ?
799 # art stuff801 # art stuff
800 BACKGROUND = os.path.join(softwarecenter.paths.datadir,802 BACKGROUND = os.path.join(softwarecenter.paths.datadir,
801 "ui/gtk3/art/itemview-background.png")803 "ui/gtk3/art/itemview-background.png")
802804
803805 # need to include application-request-action here also since we are
804 # need to include application-request-action here also since we are
805 # multiple-inheriting806 # multiple-inheriting
806 __gsignals__ = {'selected':(GObject.SignalFlags.RUN_FIRST,807 __gsignals__ = {'selected': (GObject.SignalFlags.RUN_FIRST,
807 None,808 None,
808 (GObject.TYPE_PYOBJECT,)),809 (GObject.TYPE_PYOBJECT,)),
809 "different-application-selected" : (GObject.SignalFlags.RUN_LAST,810 "different-application-selected": (
810 None,811 GObject.SignalFlags.RUN_LAST,
811 (GObject.TYPE_PYOBJECT, )),812 None,
813 (GObject.TYPE_PYOBJECT, )),
812 }814 }
813815
814
815 def __init__(self, db, distro, icons, cache, datadir):816 def __init__(self, db, distro, icons, cache, datadir):
816 Viewport.__init__(self)817 Viewport.__init__(self)
817 # basic stuff818 # basic stuff
@@ -856,7 +857,7 @@
856 self.backend.connect(857 self.backend.connect(
857 "transaction-finished", self._on_transaction_finished)858 "transaction-finished", self._on_transaction_finished)
858 self.backend.connect(859 self.backend.connect(
859 "transaction-progress-changed", 860 "transaction-progress-changed",
860 self._on_transaction_progress_changed)861 self._on_transaction_progress_changed)
861862
862 # network status watcher863 # network status watcher
@@ -874,7 +875,7 @@
874 self._reviews_server_language = None875 self._reviews_server_language = None
875 self._reviews_relaxed = False876 self._reviews_relaxed = False
876 self._review_sort_method = 0877 self._review_sort_method = 0
877 878
878 # switches879 # switches
879 self._show_overlay = False880 self._show_overlay = False
880881
@@ -883,14 +884,14 @@
883 self._cache_art_assets()884 self._cache_art_assets()
884 self.connect('realize', self._on_realize)885 self.connect('realize', self._on_realize)
885 self.loaded = True886 self.loaded = True
886 return
887887
888 def _on_destroy(self, widget):888 def _on_destroy(self, widget):
889 self.cache.disconnect_by_func(self._on_cache_ready)889 self.cache.disconnect_by_func(self._on_cache_ready)
890890
891 def _cache_art_assets(self):891 def _cache_art_assets(self):
892 global _asset_cache892 global _asset_cache
893 if _asset_cache: return _asset_cache893 if _asset_cache:
894 return _asset_cache
894 assets = _asset_cache895 assets = _asset_cache
895 # cache the bg pattern896 # cache the bg pattern
896 surf = cairo.ImageSurface.create_from_png(self.BACKGROUND)897 surf = cairo.ImageSurface.create_from_png(self.BACKGROUND)
@@ -911,8 +912,7 @@
911 self.addon_view.addons_set_sensitive(sensitive)912 self.addon_view.addons_set_sensitive(sensitive)
912 self.addons_statusbar.button_apply.set_sensitive(sensitive)913 self.addons_statusbar.button_apply.set_sensitive(sensitive)
913 self.addons_statusbar.button_cancel.set_sensitive(sensitive)914 self.addons_statusbar.button_cancel.set_sensitive(sensitive)
914 return915
915
916 def _update_recommendations(self, pkgname):916 def _update_recommendations(self, pkgname):
917 self.recommended_for_app_panel.set_pkgname(pkgname)917 self.recommended_for_app_panel.set_pkgname(pkgname)
918918
@@ -920,10 +920,9 @@
920 def _update_reviews(self, app_details):920 def _update_reviews(self, app_details):
921 self.reviews.clear()921 self.reviews.clear()
922 self._check_for_reviews()922 self._check_for_reviews()
923 return
924923
925 def _check_for_reviews(self):924 def _check_for_reviews(self):
926 # self.app may be undefined on network state change events 925 # self.app may be undefined on network state change events
927 # (LP: #742635)926 # (LP: #742635)
928 if not self.app:927 if not self.app:
929 return928 return
@@ -936,7 +935,7 @@
936 def _on_more_reviews_clicked(self, uilist):935 def _on_more_reviews_clicked(self, uilist):
937 self._reviews_server_page += 1936 self._reviews_server_page += 1
938 self._do_load_reviews()937 self._do_load_reviews()
939 938
940 def _on_review_sort_method_changed(self, uilist, sort_method):939 def _on_review_sort_method_changed(self, uilist, sort_method):
941 self._reviews_server_page = 1940 self._reviews_server_page = 1
942 self._reviews_relaxed = False941 self._reviews_relaxed = False
@@ -954,7 +953,7 @@
954 def _do_load_reviews(self):953 def _do_load_reviews(self):
955 self.reviews.show_spinner_with_message(_('Checking for reviews...'))954 self.reviews.show_spinner_with_message(_('Checking for reviews...'))
956 self.review_loader.get_reviews(955 self.review_loader.get_reviews(
957 self.app, self._reviews_ready_callback, 956 self.app, self._reviews_ready_callback,
958 page=self._reviews_server_page,957 page=self._reviews_server_page,
959 language=self._reviews_server_language,958 language=self._reviews_server_language,
960 sort=self._review_sort_method,959 sort=self._review_sort_method,
@@ -965,11 +964,10 @@
965 self.reviews.replace_review(review)964 self.reviews.replace_review(review)
966 elif action == 'remove':965 elif action == 'remove':
967 self.reviews.remove_review(review)966 self.reviews.remove_review(review)
968 return
969967
970 def _update_review_stats_widget(self, stats):968 def _update_review_stats_widget(self, stats):
971 if stats:969 if stats:
972 # ensure that the review UI knows about the stats 970 # ensure that the review UI knows about the stats
973 self.reviews.global_review_stats = stats971 self.reviews.global_review_stats = stats
974 # update the widget972 # update the widget
975 self.review_stats_widget.set_avg_rating(stats.ratings_average)973 self.review_stats_widget.set_avg_rating(stats.ratings_average)
@@ -988,7 +986,7 @@
988 """986 """
989 LOG.debug("_review_ready_callback: %s" % app)987 LOG.debug("_review_ready_callback: %s" % app)
990 # avoid possible race if we already moved to a new app when988 # avoid possible race if we already moved to a new app when
991 # the reviews become ready 989 # the reviews become ready
992 # (we only check for pkgname currently to avoid breaking on990 # (we only check for pkgname currently to avoid breaking on
993 # software-center totem)991 # software-center totem)
994 if self.app.pkgname != app.pkgname:992 if self.app.pkgname != app.pkgname:
@@ -1000,7 +998,7 @@
1000 self._reviews_relaxed = True998 self._reviews_relaxed = True
1001 self._reviews_server_page = 1999 self._reviews_server_page = 1
1002 self.review_loader.get_reviews(1000 self.review_loader.get_reviews(
1003 self.app, self._reviews_ready_callback, 1001 self.app, self._reviews_ready_callback,
1004 page=self._reviews_server_page,1002 page=self._reviews_server_page,
1005 language=self._reviews_server_language,1003 language=self._reviews_server_language,
1006 sort=self._review_sort_method,1004 sort=self._review_sort_method,
@@ -1020,15 +1018,16 @@
1020 if stats.ratings_total == 0:1018 if stats.ratings_total == 0:
1021 stats.ratings_average = 01019 stats.ratings_average = 0
1022 else:1020 else:
1023 stats.ratings_average = sum([x.rating for x in reviews_data]) / float(stats.ratings_total)1021 stats.ratings_average = (sum([x.rating for x in reviews_data])
1022 / float(stats.ratings_total))
1024 # update UI1023 # update UI
1025 self._update_review_stats_widget(stats)1024 self._update_review_stats_widget(stats)
1026 # update global stats cache as well1025 # update global stats cache as well
1027 self.review_loader.update_review_stats(app, stats)1026 self.review_loader.update_review_stats(app, stats)
1028 1027
1029 if my_votes:1028 if my_votes:
1030 self.reviews.update_useful_votes(my_votes)1029 self.reviews.update_useful_votes(my_votes)
1031 1030
1032 if action:1031 if action:
1033 self._review_update_single(action, single_review)1032 self._review_update_single(action, single_review)
1034 else:1033 else:
@@ -1042,7 +1041,7 @@
1042 # We retrieved data, but nothing new. Keep going.1041 # We retrieved data, but nothing new. Keep going.
1043 self._reviews_server_page += 11042 self._reviews_server_page += 1
1044 self.review_loader.get_reviews(1043 self.review_loader.get_reviews(
1045 self.app, self._reviews_ready_callback, 1044 self.app, self._reviews_ready_callback,
1046 page=self._reviews_server_page,1045 page=self._reviews_server_page,
1047 language=self._reviews_server_language,1046 language=self._reviews_server_language,
1048 sort=self._review_sort_method,1047 sort=self._review_sort_method,
@@ -1069,13 +1068,13 @@
10691068
1070 def on_weblive_exception(self, weblive, exception):1069 def on_weblive_exception(self, weblive, exception):
1071 """ When receiving an exception, reset button and show the error """1070 """ When receiving an exception, reset button and show the error """
1072 error(None,"WebLive exception", exception)1071 error(None, "WebLive exception", exception)
1073 self.test_drive.set_label(_("Test drive"))1072 self.test_drive.set_label(_("Test drive"))
1074 self.test_drive.set_sensitive(True)1073 self.test_drive.set_sensitive(True)
10751074
1076 def on_weblive_warning(self, weblive, warning):1075 def on_weblive_warning(self, weblive, warning):
1077 """ When receiving a warning, just show it """1076 """ When receiving a warning, just show it """
1078 error(None,"WebLive warning", warning)1077 error(None, "WebLive warning", warning)
10791078
1080 def on_test_drive_clicked(self, button):1079 def on_test_drive_clicked(self, button):
1081 if self.weblive.client.state == "disconnected":1080 if self.weblive.client.state == "disconnected":
@@ -1090,20 +1089,20 @@
10901089
1091 if len(servers) == 0:1090 if len(servers) == 0:
1092 error(None,1091 error(None,
1093 "No available server", 1092 "No available server",
1094 "There is currently no available WebLive server "1093 "There is currently no available WebLive server "
1095 "for this application.\nPlease try again later.")1094 "for this application.\nPlease try again later.")
1096 elif len(servers) == 1:1095 elif len(servers) == 1:
1097 self.weblive.create_automatic_user_and_run_session(1096 self.weblive.create_automatic_user_and_run_session(
1098 session=cmd,serverid=servers[0].name)1097 session=cmd, serverid=servers[0].name)
1099 button.set_sensitive(False)1098 button.set_sensitive(False)
1100 else:1099 else:
1101 d = ShowWebLiveServerChooserDialog(servers, self.app.pkgname)1100 d = ShowWebLiveServerChooserDialog(servers, self.app.pkgname)
1102 serverid=None1101 serverid = None
1103 if d.run() == Gtk.ResponseType.OK:1102 if d.run() == Gtk.ResponseType.OK:
1104 for server in d.servers_vbox:1103 for server in d.servers_vbox:
1105 if server.get_active():1104 if server.get_active():
1106 serverid=server.serverid1105 serverid = server.serverid
1107 break1106 break
1108 d.destroy()1107 d.destroy()
11091108
@@ -1122,13 +1121,11 @@
1122 self.info_vb.reorder_child(table, 0)1121 self.info_vb.reorder_child(table, 0)
1123 if not table.get_property('visible'):1122 if not table.get_property('visible'):
1124 table.show_all()1123 table.show_all()
1125 return
11261124
1127 def _on_realize(self, widget):1125 def _on_realize(self, widget):
1128 self.addons_statusbar.hide()1126 self.addons_statusbar.hide()
1129 # the install button gets initial focus1127 # the install button gets initial focus
1130 self.pkg_statusbar.button.grab_focus()1128 self.pkg_statusbar.button.grab_focus()
1131 return
11321129
1133 def _on_homepage_clicked(self, label, link):1130 def _on_homepage_clicked(self, label, link):
1134 import webbrowser1131 import webbrowser
@@ -1160,7 +1157,7 @@
1160 self.title.set_selectable(True)1157 self.title.set_selectable(True)
1161 self.subtitle.set_line_wrap(True)1158 self.subtitle.set_line_wrap(True)
1162 self.subtitle.set_selectable(True)1159 self.subtitle.set_selectable(True)
1163 vb_inner=Gtk.VBox()1160 vb_inner = Gtk.VBox()
1164 vb_inner.pack_start(self.title, False, False, 0)1161 vb_inner.pack_start(self.title, False, False, 0)
1165 vb_inner.pack_start(self.subtitle, False, False, 0)1162 vb_inner.pack_start(self.subtitle, False, False, 0)
11661163
@@ -1189,10 +1186,11 @@
1189 # installed where widget1186 # installed where widget
1190 self.installed_where_hbox = Gtk.HBox()1187 self.installed_where_hbox = Gtk.HBox()
1191 self.installed_where_hbox.set_spacing(6)1188 self.installed_where_hbox.set_spacing(6)
1192 self.installed_where_hbox.a11y = self.installed_where_hbox.get_accessible()1189 hbox_a11y = self.installed_where_hbox.get_accessible()
1190 self.installed_where_hbox.a11y = hbox_a11y
1193 vb.pack_start(self.installed_where_hbox, False, False, 0)1191 vb.pack_start(self.installed_where_hbox, False, False, 0)
11941192
1195 # the hbox that hold the description on the left and the screenshot 1193 # the hbox that hold the description on the left and the screenshot
1196 # thumbnail on the right1194 # thumbnail on the right
1197 body_hb = Gtk.HBox()1195 body_hb = Gtk.HBox()
1198 body_hb.set_spacing(12)1196 body_hb.set_spacing(12)
@@ -1240,7 +1238,7 @@
1240 self.homepage_btn = Gtk.Label()1238 self.homepage_btn = Gtk.Label()
1241 self.homepage_btn.set_name("subtle-label")1239 self.homepage_btn.set_name("subtle-label")
1242 self.homepage_btn.connect('activate-link', self._on_homepage_clicked)1240 self.homepage_btn.connect('activate-link', self._on_homepage_clicked)
1243 1241
1244 # support site1242 # support site
1245 self.support_btn = Gtk.Label()1243 self.support_btn = Gtk.Label()
1246 self.support_btn.set_name("subtle-label")1244 self.support_btn.set_name("subtle-label")
@@ -1275,10 +1273,12 @@
1275 self.datadir, None, self.cache, self.db, self.icons, None)1273 self.datadir, None, self.cache, self.db, self.icons, None)
1276 self.recommended_for_app_panel = RecommendationsPanelDetails(catview)1274 self.recommended_for_app_panel = RecommendationsPanelDetails(catview)
1277 self.recommended_for_app_panel.connect(1275 self.recommended_for_app_panel.connect(
1278 "application-activated", self._on_recommended_application_activated)1276 "application-activated",
1277 self._on_recommended_application_activated)
1279 self.recommended_for_app_panel.show_all()1278 self.recommended_for_app_panel.show_all()
1280 self.info_vb.pack_start(self.recommended_for_app_panel, False, False, 0)1279 self.info_vb.pack_start(self.recommended_for_app_panel, False,
1281 1280 False, 0)
1281
1282 # package info1282 # package info
1283 self.info_keys = []1283 self.info_keys = []
12841284
@@ -1310,14 +1310,15 @@
1310 # reviews cascade1310 # reviews cascade
1311 self.reviews.connect("new-review", self._on_review_new)1311 self.reviews.connect("new-review", self._on_review_new)
1312 self.reviews.connect("report-abuse", self._on_review_report_abuse)1312 self.reviews.connect("report-abuse", self._on_review_report_abuse)
1313 self.reviews.connect("submit-usefulness", self._on_review_submit_usefulness)1313 self.reviews.connect("submit-usefulness",
1314 self._on_review_submit_usefulness)
1314 self.reviews.connect("modify-review", self._on_review_modify)1315 self.reviews.connect("modify-review", self._on_review_modify)
1315 self.reviews.connect("delete-review", self._on_review_delete)1316 self.reviews.connect("delete-review", self._on_review_delete)
1316 self.reviews.connect("more-reviews-clicked",1317 self.reviews.connect("more-reviews-clicked",
1317 self._on_more_reviews_clicked)1318 self._on_more_reviews_clicked)
1318 self.reviews.connect("different-review-language-clicked", 1319 self.reviews.connect("different-review-language-clicked",
1319 self._on_reviews_in_different_language_clicked)1320 self._on_reviews_in_different_language_clicked)
1320 self.reviews.connect("review-sort-changed", 1321 self.reviews.connect("review-sort-changed",
1321 self._on_review_sort_method_changed)1322 self._on_review_sort_method_changed)
1322 if get_distro().REVIEWS_SERVER:1323 if get_distro().REVIEWS_SERVER:
1323 vb.pack_start(self.reviews, False, False, 0)1324 vb.pack_start(self.reviews, False, False, 0)
@@ -1325,15 +1326,14 @@
1325 self.show_all()1326 self.show_all()
13261327
1327 # signals!1328 # signals!
1328 self.connect('size-allocate', lambda w,a: w.queue_draw())1329 self.connect('size-allocate', lambda w, a: w.queue_draw())
1329 return
13301330
1331 def _on_recommended_application_activated(self, recwidget, app):1331 def _on_recommended_application_activated(self, recwidget, app):
1332 self.emit("different-application-selected", app)1332 self.emit("different-application-selected", app)
13331333
1334 def _on_review_new(self, button):1334 def _on_review_new(self, button):
1335 self._review_write_new()1335 self._review_write_new()
1336 1336
1337 def _on_review_modify(self, button, review_id):1337 def _on_review_modify(self, button, review_id):
1338 self._review_modify(review_id)1338 self._review_modify(review_id)
13391339
@@ -1347,7 +1347,7 @@
1347 self._review_submit_usefulness(review_id, is_useful)1347 self._review_submit_usefulness(review_id, is_useful)
13481348
1349 def _update_title_markup(self, appname, summary):1349 def _update_title_markup(self, appname, summary):
1350 # make title font size fixed as they should look good compared to the 1350 # make title font size fixed as they should look good compared to the
1351 # icon (also fixed).1351 # icon (also fixed).
1352 font_size = em(1.6) * Pango.SCALE1352 font_size = em(1.6) * Pango.SCALE
1353 markup = '<span font_size="%s"><b>%s</b></span>'1353 markup = '<span font_size="%s"><b>%s</b></span>'
@@ -1355,7 +1355,6 @@
1355 self.title.set_markup(markup)1355 self.title.set_markup(markup)
1356 self.title.a11y.set_name(appname + '. ' + summary)1356 self.title.a11y.set_name(appname + '. ' + summary)
1357 self.subtitle.set_markup(summary)1357 self.subtitle.set_markup(summary)
1358 return
13591358
1360 def _update_app_icon(self, app_details):1359 def _update_app_icon(self, app_details):
1361 pb = self._get_icon_as_pixbuf(app_details)1360 pb = self._get_icon_as_pixbuf(app_details)
@@ -1363,13 +1362,12 @@
1363# self._show_overlay = app_details.pkg_state == PkgStates.INSTALLED1362# self._show_overlay = app_details.pkg_state == PkgStates.INSTALLED
1364 w, h = pb.get_width(), pb.get_height()1363 w, h = pb.get_width(), pb.get_height()
13651364
1366 tw = self.APP_ICON_SIZE # target width1365 tw = self.APP_ICON_SIZE # target width
1367 if pb.get_width() < tw:1366 if pb.get_width() < tw:
1368 pb = pb.scale_simple(tw, tw, GdkPixbuf.InterpType.TILES)1367 pb = pb.scale_simple(tw, tw, GdkPixbuf.InterpType.TILES)
13691368
1370 self.icon.set_from_pixbuf(pb)1369 self.icon.set_from_pixbuf(pb)
1371 self.icon.set_size_request(self.APP_ICON_SIZE, self.APP_ICON_SIZE)1370 self.icon.set_size_request(self.APP_ICON_SIZE, self.APP_ICON_SIZE)
1372 return
13731371
1374 def _update_layout_error_status(self, pkg_error):1372 def _update_layout_error_status(self, pkg_error):
1375 # if we have an error or if we need to enable a source1373 # if we have an error or if we need to enable a source
@@ -1390,7 +1388,6 @@
1390 self.info_vb.show()1388 self.info_vb.show()
1391 for hbar in self._hbars:1389 for hbar in self._hbars:
1392 hbar.show()1390 hbar.show()
1393 return
13941391
1395 def _update_app_description(self, app_details, appname):1392 def _update_app_description(self, app_details, appname):
1396 # format new app description1393 # format new app description
@@ -1401,9 +1398,8 @@
14011398
1402 # a11y for description1399 # a11y for description
1403 self.desc.description.a11y.set_name(description)1400 self.desc.description.a11y.set_name(description)
1404 return
14051401
1406 def _update_description_footer_links(self, app_details): 1402 def _update_description_footer_links(self, app_details):
1407 # show or hide the homepage button and set uri if homepage specified1403 # show or hide the homepage button and set uri if homepage specified
1408 if app_details.website:1404 if app_details.website:
1409 self.homepage_btn.show()1405 self.homepage_btn.show()
@@ -1420,7 +1416,6 @@
1420 self.support_btn.set_tooltip_text(app_details.supportsite)1416 self.support_btn.set_tooltip_text(app_details.supportsite)
1421 else:1417 else:
1422 self.support_btn.hide()1418 self.support_btn.hide()
1423 return
14241419
1425 def _update_app_video(self, app_details):1420 def _update_app_video(self, app_details):
1426 self.videoplayer.uri = app_details.video_url1421 self.videoplayer.uri = app_details.video_url
@@ -1433,20 +1428,20 @@
1433 # get screenshot urls and configure the ScreenshotView...1428 # get screenshot urls and configure the ScreenshotView...
1434 if app_details.thumbnail and app_details.screenshot:1429 if app_details.thumbnail and app_details.screenshot:
1435 self.screenshot.fetch_screenshots(app_details)1430 self.screenshot.fetch_screenshots(app_details)
1436 return
14371431
1438 def _update_weblive(self, app_details):1432 def _update_weblive(self, app_details):
1439 if self.weblive.client is None: return1433 if self.weblive.client is None:
1434 return
1440 self.desktop_file = app_details.desktop_file1435 self.desktop_file = app_details.desktop_file
1441 # only enable test drive if we have a desktop file and exec line1436 # only enable test drive if we have a desktop file and exec line
1442 if (not self.weblive.ready or1437 if (not self.weblive.ready or
1443 not self.weblive.is_pkgname_available_on_server(app_details.pkgname) or1438 not self.weblive.is_pkgname_available_on_server(
1439 app_details.pkgname) or
1444 not os.path.exists(self.desktop_file) or1440 not os.path.exists(self.desktop_file) or
1445 not get_exec_line_from_desktop(self.desktop_file)):1441 not get_exec_line_from_desktop(self.desktop_file)):
1446 self.test_drive.hide()1442 self.test_drive.hide()
1447 else:1443 else:
1448 self.test_drive.show()1444 self.test_drive.show()
1449 return
14501445
1451 def _update_warning_bar(self, app_details):1446 def _update_warning_bar(self, app_details):
1452 # generic error wins over HW issue1447 # generic error wins over HW issue
@@ -1462,7 +1457,7 @@
1462 app_details.hardware_requirements)1457 app_details.hardware_requirements)
1463 if not app_details.region_requirements_satisfied:1458 if not app_details.region_requirements_satisfied:
1464 if len(s) > 0:1459 if len(s) > 0:
1465 s += "\n"+REGION_WARNING_STRING1460 s += "\n" + REGION_WARNING_STRING
1466 else:1461 else:
1467 s = REGION_WARNING_STRING1462 s = REGION_WARNING_STRING
1468 self.pkg_warningbar.label.set_text(s)1463 self.pkg_warningbar.label.set_text(s)
@@ -1494,7 +1489,6 @@
1494 self.hardware_info.show()1489 self.hardware_info.show()
1495 else:1490 else:
1496 self.hardware_info.hide()1491 self.hardware_info.hide()
1497 return
14981492
1499 def _update_addons(self, app_details):1493 def _update_addons(self, app_details):
1500 # refresh addons interface1494 # refresh addons interface
@@ -1511,7 +1505,6 @@
15111505
1512 # Update addons state bar1506 # Update addons state bar
1513 self.addons_statusbar.configure()1507 self.addons_statusbar.configure()
1514 return
15151508
1516 def _update_all(self, app_details, skip_update_addons=False):1509 def _update_all(self, app_details, skip_update_addons=False):
1517 # reset view to top left1510 # reset view to top left
@@ -1570,7 +1563,6 @@
15701563
1571 # async query zeitgeist and rnr1564 # async query zeitgeist and rnr
1572 self._update_usage_counter()1565 self._update_usage_counter()
1573 return
15741566
1575 def _update_minimal(self, app_details):1567 def _update_minimal(self, app_details):
1576 self._update_app_icon(app_details)1568 self._update_app_icon(app_details)
@@ -1583,12 +1575,11 @@
15831575
1584# # show where it is1576# # show where it is
1585 self._configure_where_is_it()1577 self._configure_where_is_it()
1586 return
15871578
1588 def _add_where_is_it_commandline(self, pkgname):1579 def _add_where_is_it_commandline(self, pkgname):
1589 cmdfinder = CmdFinder(self.cache)1580 cmdfinder = CmdFinder(self.cache)
1590 cmds = cmdfinder.find_cmds_from_pkgname(pkgname)1581 cmds = cmdfinder.find_cmds_from_pkgname(pkgname)
1591 if not cmds: 1582 if not cmds:
1592 return1583 return
1593 vb = Gtk.VBox()1584 vb = Gtk.VBox()
1594 vb.set_spacing(12)1585 vb.set_spacing(12)
@@ -1604,8 +1595,8 @@
1604 #~ title.set_size_request(self.get_allocation().width-24, -1)1595 #~ title.set_size_request(self.get_allocation().width-24, -1)
1605 vb.pack_start(title, False, False, 0)1596 vb.pack_start(title, False, False, 0)
1606 cmds_str = ", ".join(cmds)1597 cmds_str = ", ".join(cmds)
1607 cmd_label = Gtk.Label(label=1598 cmd_label = Gtk.Label(
1608 '<span font_desc="monospace bold 9">%s</span>' % cmds_str)1599 label='<span font_desc="monospace bold 9">%s</span>' % cmds_str)
1609 cmd_label.set_selectable(True)1600 cmd_label.set_selectable(True)
1610 cmd_label.set_use_markup(True)1601 cmd_label.set_use_markup(True)
1611 cmd_label.set_alignment(0, 0.5)1602 cmd_label.set_alignment(0, 0.5)
@@ -1650,9 +1641,10 @@
1650 label_name.set_text(app_info.get_name())1641 label_name.set_text(app_info.get_name())
16511642
1652 self.installed_where_hbox.pack_start(label_name, False, False, 0)1643 self.installed_where_hbox.pack_start(label_name, False, False, 0)
1653 if i+1 < len(where):1644 if i + 1 < len(where):
1654 right_arrow = Gtk.Arrow.new(Gtk.ArrowType.RIGHT, Gtk.ShadowType.NONE)1645 right_arrow = Gtk.Arrow.new(Gtk.ArrowType.RIGHT,
1655 self.installed_where_hbox.pack_start(right_arrow, 1646 Gtk.ShadowType.NONE)
1647 self.installed_where_hbox.pack_start(right_arrow,
1656 False, False, 0)1648 False, False, 0)
16571649
1658 # create our a11y text1650 # create our a11y text
@@ -1694,7 +1686,7 @@
1694 # see if we have the location if its installed1686 # see if we have the location if its installed
1695 if self.app_details.pkg_state == PkgStates.INSTALLED:1687 if self.app_details.pkg_state == PkgStates.INSTALLED:
1696 # first try the desktop file from the DB, then see if1688 # first try the desktop file from the DB, then see if
1697 # there is a local desktop file with the same name as 1689 # there is a local desktop file with the same name as
1698 # the package1690 # the package
1699 # try to show menu location if there is a desktop file, but1691 # try to show menu location if there is a desktop file, but
1700 # never show commandline programs for apps with a desktop file1692 # never show commandline programs for apps with a desktop file
@@ -1705,7 +1697,6 @@
1705 # if there is no desktop file, show commandline1697 # if there is no desktop file, show commandline
1706 else:1698 else:
1707 self._add_where_is_it_commandline(self.app_details.pkgname)1699 self._add_where_is_it_commandline(self.app_details.pkgname)
1708 return
17091700
1710 # public API1701 # public API
1711 def show_app(self, app, force=False):1702 def show_app(self, app, force=False):
@@ -1714,8 +1705,8 @@
1714 LOG.debug("no app selected")1705 LOG.debug("no app selected")
1715 return1706 return
17161707
1717 same_app = (self.app and 1708 same_app = (self.app and
1718 self.app.pkgname and 1709 self.app.pkgname and
1719 self.app.appname == app.appname and1710 self.app.appname == app.appname and
1720 self.app.pkgname == app.pkgname)1711 self.app.pkgname == app.pkgname)
1721 #print 'SameApp:', same_app1712 #print 'SameApp:', same_app
@@ -1745,8 +1736,9 @@
1745 # update all (but skip the addons calculation if this is a1736 # update all (but skip the addons calculation if this is a
1746 # DebFileApplication as this is not useful for this case and it1737 # DebFileApplication as this is not useful for this case and it
1747 # increases the view load time dramatically)1738 # increases the view load time dramatically)
1739 skip_update_addons = type(self.app) == DebFileApplication
1748 self._update_all(self.app_details,1740 self._update_all(self.app_details,
1749 skip_update_addons=(type(self.app)==DebFileApplication))1741 skip_update_addons=skip_update_addons)
17501742
1751 # this is a bit silly, but without it and self.title being selectable1743 # this is a bit silly, but without it and self.title being selectable
1752 # gtk will select the entire title (which looks ugly). this grab works1744 # gtk will select the entire title (which looks ugly). this grab works
@@ -1754,18 +1746,16 @@
1754 self.pkg_statusbar.button.grab_focus()1746 self.pkg_statusbar.button.grab_focus()
17551747
1756 self.emit("selected", self.app)1748 self.emit("selected", self.app)
1757 return
17581749
1759 def refresh_app(self):1750 def refresh_app(self):
1760 self.show_app(self.app)1751 self.show_app(self.app)
17611752
1762
1763 # common code1753 # common code
1764 def _review_write_new(self):1754 def _review_write_new(self):
1765 if (not self.app or1755 if (not self.app or
1766 not self.app.pkgname in self.cache or1756 not self.app.pkgname in self.cache or
1767 not self.cache[self.app.pkgname].candidate):1757 not self.cache[self.app.pkgname].candidate):
1768 dialogs.error(None, 1758 dialogs.error(None,
1769 _("Version unknown"),1759 _("Version unknown"),
1770 _("The version of the application can not "1760 _("The version of the application can not "
1771 "be detected. Entering a review is not "1761 "be detected. Entering a review is not "
@@ -1778,7 +1768,7 @@
17781768
1779 # FIXME: probably want to not display the ui if we can't review it1769 # FIXME: probably want to not display the ui if we can't review it
1780 if not origin:1770 if not origin:
1781 dialogs.error(None, 1771 dialogs.error(None,
1782 _("Origin unknown"),1772 _("Origin unknown"),
1783 _("The origin of the application can not "1773 _("The origin of the application can not "
1784 "be detected. Entering a review is not "1774 "be detected. Entering a review is not "
@@ -1787,7 +1777,8 @@
17871777
1788 if pkg.installed:1778 if pkg.installed:
1789 version = pkg.installed.version1779 version = pkg.installed.version
1790 # call the loader to do call out the right helper and collect the result1780 # call the loader to do call out the right helper and collect the
1781 # result
1791 parent_xid = ''1782 parent_xid = ''
1792 #parent_xid = get_parent_xid(self)1783 #parent_xid = get_parent_xid(self)
1793 self.reviews.new_review.disable()1784 self.reviews.new_review.disable()
@@ -1796,7 +1787,7 @@
1796 parent_xid, self.datadir,1787 parent_xid, self.datadir,
1797 self._reviews_ready_callback,1788 self._reviews_ready_callback,
1798 done_callback=self._submit_reviews_done_callback)1789 done_callback=self._submit_reviews_done_callback)
1799 1790
1800 def _review_report_abuse(self, review_id):1791 def _review_report_abuse(self, review_id):
1801 parent_xid = ''1792 parent_xid = ''
1802 #parent_xid = get_parent_xid(self)1793 #parent_xid = get_parent_xid(self)
@@ -1809,7 +1800,7 @@
1809 self.review_loader.spawn_submit_usefulness_ui(1800 self.review_loader.spawn_submit_usefulness_ui(
1810 review_id, is_useful, parent_xid, self.datadir,1801 review_id, is_useful, parent_xid, self.datadir,
1811 self._reviews_ready_callback)1802 self._reviews_ready_callback)
1812 1803
1813 def _review_modify(self, review_id):1804 def _review_modify(self, review_id):
1814 parent_xid = ''1805 parent_xid = ''
1815 #parent_xid = get_parent_xid(self)1806 #parent_xid = get_parent_xid(self)
@@ -1834,11 +1825,12 @@
1834 state = self.pkg_statusbar.pkg_state1825 state = self.pkg_statusbar.pkg_state
18351826
1836 # handle purchase: install purchased has multiple steps1827 # handle purchase: install purchased has multiple steps
1837 if (state == PkgStates.INSTALLING_PURCHASED and 1828 if (state == PkgStates.INSTALLING_PURCHASED and
1838 result and1829 result and
1839 not result.pkgname):1830 not result.pkgname):
1840 self.pkg_statusbar.configure(self.app_details, PkgStates.INSTALLING_PURCHASED)1831 self.pkg_statusbar.configure(self.app_details,
1841 elif (state == PkgStates.INSTALLING_PURCHASED and 1832 PkgStates.INSTALLING_PURCHASED)
1833 elif (state == PkgStates.INSTALLING_PURCHASED and
1842 result and1834 result and
1843 result.pkgname):1835 result.pkgname):
1844 self.pkg_statusbar.configure(self.app_details, PkgStates.INSTALLED)1836 self.pkg_statusbar.configure(self.app_details, PkgStates.INSTALLED)
@@ -1846,7 +1838,8 @@
1846 self.reviews.configure_reviews_ui()1838 self.reviews.configure_reviews_ui()
1847 # normal states1839 # normal states
1848 elif state == PkgStates.REMOVING:1840 elif state == PkgStates.REMOVING:
1849 self.pkg_statusbar.configure(self.app_details, PkgStates.UNINSTALLED)1841 self.pkg_statusbar.configure(self.app_details,
1842 PkgStates.UNINSTALLED)
1850 elif state == PkgStates.INSTALLING:1843 elif state == PkgStates.INSTALLING:
1851 self.pkg_statusbar.configure(self.app_details, PkgStates.INSTALLED)1844 self.pkg_statusbar.configure(self.app_details, PkgStates.INSTALLED)
1852 elif state == PkgStates.UPGRADING:1845 elif state == PkgStates.UPGRADING:
@@ -1862,15 +1855,16 @@
1862 # reset the reviews UI now that we have installed the package1855 # reset the reviews UI now that we have installed the package
1863 self.reviews.configure_reviews_ui()1856 self.reviews.configure_reviews_ui()
1864 elif state == PkgStates.UNINSTALLED:1857 elif state == PkgStates.UNINSTALLED:
1865 self.pkg_statusbar.configure(self.app_details, PkgStates.UNINSTALLED)1858 self.pkg_statusbar.configure(self.app_details,
1859 PkgStates.UNINSTALLED)
1866 self.adjustment_value = None1860 self.adjustment_value = None
1867 1861
1868 if self.addons_statusbar.applying:1862 if self.addons_statusbar.applying:
1869 self.addons_statusbar.applying = False1863 self.addons_statusbar.applying = False
18701864
1871 return False1865 return False
18721866
1873 def _on_transaction_started(self, backend, pkgname, appname, trans_id, 1867 def _on_transaction_started(self, backend, pkgname, appname, trans_id,
1874 trans_type):1868 trans_type):
1875 if self.addons_statusbar.applying:1869 if self.addons_statusbar.applying:
1876 self.pkg_statusbar.configure(self.app_details, AppActions.APPLY)1870 self.pkg_statusbar.configure(self.app_details, AppActions.APPLY)
@@ -1879,32 +1873,32 @@
1879 state = self.pkg_statusbar.pkg_state1873 state = self.pkg_statusbar.pkg_state
1880 LOG.debug("_on_transaction_started %s" % state)1874 LOG.debug("_on_transaction_started %s" % state)
1881 if state == PkgStates.NEEDS_PURCHASE:1875 if state == PkgStates.NEEDS_PURCHASE:
1882 self.pkg_statusbar.configure(self.app_details, 1876 self.pkg_statusbar.configure(self.app_details,
1883 PkgStates.INSTALLING_PURCHASED)1877 PkgStates.INSTALLING_PURCHASED)
1884 elif (state == PkgStates.UNINSTALLED or1878 elif (state == PkgStates.UNINSTALLED or
1885 state == PkgStates.FORCE_VERSION):1879 state == PkgStates.FORCE_VERSION):
1886 self.pkg_statusbar.configure(self.app_details, PkgStates.INSTALLING)1880 self.pkg_statusbar.configure(self.app_details,
1881 PkgStates.INSTALLING)
1887 elif state == PkgStates.INSTALLED:1882 elif state == PkgStates.INSTALLED:
1888 self.pkg_statusbar.configure(self.app_details, PkgStates.REMOVING)1883 self.pkg_statusbar.configure(self.app_details, PkgStates.REMOVING)
1889 elif state == PkgStates.UPGRADABLE:1884 elif state == PkgStates.UPGRADABLE:
1890 self.pkg_statusbar.configure(self.app_details, PkgStates.UPGRADING)1885 self.pkg_statusbar.configure(self.app_details, PkgStates.UPGRADING)
1891 elif state == PkgStates.REINSTALLABLE:1886 elif state == PkgStates.REINSTALLABLE:
1892 self.pkg_statusbar.configure(self.app_details, PkgStates.INSTALLING)1887 self.pkg_statusbar.configure(self.app_details,
1888 PkgStates.INSTALLING)
1893 # FIXME: is there a way to tell if we are installing/removing?1889 # FIXME: is there a way to tell if we are installing/removing?
1894 # we will assume that it is being installed, but this means that1890 # we will assume that it is being installed, but this means that
1895 # during removals we get the text "Installing.."1891 # during removals we get the text "Installing.."
1896 # self.pkg_statusbar.configure(self.app_details, PkgStates.REMOVING)1892 # self.pkg_statusbar.configure(self.app_details,
1897 return1893 # PkgStates.REMOVING)
18981894
1899 def _on_transaction_stopped(self, backend, result):1895 def _on_transaction_stopped(self, backend, result):
1900 self.pkg_statusbar.progress.hide()1896 self.pkg_statusbar.progress.hide()
1901 self._update_interface_on_trans_ended(result)1897 self._update_interface_on_trans_ended(result)
1902 return
19031898
1904 def _on_transaction_finished(self, backend, result):1899 def _on_transaction_finished(self, backend, result):
1905 self.pkg_statusbar.progress.hide()1900 self.pkg_statusbar.progress.hide()
1906 self._update_interface_on_trans_ended(result)1901 self._update_interface_on_trans_ended(result)
1907 return
19081902
1909 def _on_transaction_progress_changed(self, backend, pkgname, progress):1903 def _on_transaction_progress_changed(self, backend, pkgname, progress):
1910 if (self.app_details and1904 if (self.app_details and
@@ -1915,11 +1909,10 @@
1915 self.pkg_statusbar.combo_multiple_versions.hide()1909 self.pkg_statusbar.combo_multiple_versions.hide()
1916 self.pkg_statusbar.progress.show()1910 self.pkg_statusbar.progress.show()
1917 if pkgname in backend.pending_transactions:1911 if pkgname in backend.pending_transactions:
1918 self.pkg_statusbar.progress.set_fraction(progress/100.0)1912 self.pkg_statusbar.progress.set_fraction(progress / 100.0)
1919 if progress >= 100:1913 if progress >= 100:
1920 self.pkg_statusbar.progress.set_fraction(1)1914 self.pkg_statusbar.progress.set_fraction(1)
1921 self.adjustment_value = self.get_vadjustment().get_value()1915 self.adjustment_value = self.get_vadjustment().get_value()
1922 return
19231916
1924 def get_app_icon_details(self):1917 def get_app_icon_details(self):
1925 """ helper for unity dbus support to provide details about the1918 """ helper for unity dbus support to provide details about the
@@ -1941,7 +1934,7 @@
1941 else:1934 else:
1942 icon_size = pb.get_height()1935 icon_size = pb.get_height()
1943 return icon_size1936 return icon_size
1944 1937
1945 def _get_app_icon_xy_position_on_screen(self):1938 def _get_app_icon_xy_position_on_screen(self):
1946 """ helper for unity dbus support to get the x,y position of1939 """ helper for unity dbus support to get the x,y position of
1947 the application icon as it is displayed on-screen. if the icon's1940 the application icon as it is displayed on-screen. if the icon's
@@ -1954,15 +1947,15 @@
1954 parent = parent.get_parent()1947 parent = parent.get_parent()
1955 # get x, y relative to toplevel1948 # get x, y relative to toplevel
1956 try:1949 try:
1957 (x,y) = self.icon.translate_coordinates(parent, 0, 0)1950 (x, y) = self.icon.translate_coordinates(parent, 0, 0)
1958 except Exception as e:1951 except Exception as e:
1959 LOG.warning("couldn't translate icon coordinates on-screen "1952 LOG.warning("couldn't translate icon coordinates on-screen "
1960 "for unity dbus message: %s" % e)1953 "for unity dbus message: %s" % e)
1961 return (0,0)1954 return (0, 0)
1962 # get toplevel window position1955 # get toplevel window position
1963 (px, py) = parent.get_position()1956 (px, py) = parent.get_position()
1964 return (px+x, py+y)1957 return (px + x, py + y)
1965 1958
1966 def _get_icon_as_pixbuf(self, app_details):1959 def _get_icon_as_pixbuf(self, app_details):
1967 if app_details.icon:1960 if app_details.icon:
1968 if self.icons.has_icon(app_details.icon):1961 if self.icons.has_icon(app_details.icon):
@@ -1978,9 +1971,10 @@
1978 LOG.debug("did not find the icon locally, must download it")1971 LOG.debug("did not find the icon locally, must download it")
19791972
1980 def on_image_download_complete(downloader, image_file_path):1973 def on_image_download_complete(downloader, image_file_path):
1981 # when the download is complete, replace the icon in the 1974 # when the download is complete, replace the icon in the
1982 # view with the downloaded one1975 # view with the downloaded one
1983 logging.debug("_get_icon_as_pixbuf:image_downloaded() %s" % image_file_path)1976 logging.debug("_get_icon_as_pixbuf:image_downloaded() %s" %
1977 image_file_path)
1984 try:1978 try:
1985 pb = GdkPixbuf.Pixbuf.new_from_file(image_file_path)1979 pb = GdkPixbuf.Pixbuf.new_from_file(image_file_path)
1986 # fixes crash in testsuite if window is destroyed1980 # fixes crash in testsuite if window is destroyed
@@ -1989,15 +1983,17 @@
1989 if self.icon.get_property("visible"):1983 if self.icon.get_property("visible"):
1990 self.icon.set_from_pixbuf(pb)1984 self.icon.set_from_pixbuf(pb)
1991 except Exception as e:1985 except Exception as e:
1992 LOG.warning("couldn't load downloadable icon file '%s': %s" % (image_file_path, e))1986 LOG.warning(
1993 1987 "couldn't load downloadable icon file '%s': %s" %
1988 (image_file_path, e))
1989
1994 image_downloader = SimpleFileDownloader()1990 image_downloader = SimpleFileDownloader()
1995 image_downloader.connect(1991 image_downloader.connect(
1996 'file-download-complete', on_image_download_complete)1992 'file-download-complete', on_image_download_complete)
1997 image_downloader.download_file(1993 image_downloader.download_file(
1998 app_details.icon_url, app_details.cached_icon_file_path)1994 app_details.icon_url, app_details.cached_icon_file_path)
1999 return self.icons.load_icon(Icons.MISSING_APP, self.APP_ICON_SIZE, 0)1995 return self.icons.load_icon(Icons.MISSING_APP, self.APP_ICON_SIZE, 0)
2000 1996
2001 def update_totalsize(self):1997 def update_totalsize(self):
2002 if not self.totalsize_info.get_property('visible'):1998 if not self.totalsize_info.get_property('visible'):
2003 return False1999 return False
@@ -2013,7 +2009,7 @@
2013 self.addons_manager.addons_to_remove,2009 self.addons_manager.addons_to_remove,
2014 self.app.archive_suite)2010 self.app.archive_suite)
2015 total_download_size, total_install_size = res2011 total_download_size, total_install_size = res
2016 if res==(0,0) and type(self.app)==DebFileApplication:2012 if res == (0, 0) and type(self.app) == DebFileApplication:
2017 total_install_size = self.app_details.installed_size2013 total_install_size = self.app_details.installed_size
2018 if total_download_size > 0:2014 if total_download_size > 0:
2019 download_size = GLib.format_size(total_download_size)2015 download_size = GLib.format_size(total_download_size)
@@ -2032,22 +2028,21 @@
2032 elif total_install_size < 0:2028 elif total_install_size < 0:
2033 remove_size = GLib.format_size(-total_install_size)2029 remove_size = GLib.format_size(-total_install_size)
2034 label_string += _("%s to be freed") % (remove_size)2030 label_string += _("%s to be freed") % (remove_size)
2035 2031
2036 self.totalsize_info.set_value(label_string or _("Unknown"))2032 self.totalsize_info.set_value(label_string or _("Unknown"))
2037# self.totalsize_info.show_all()2033# self.totalsize_info.show_all()
2038 return False2034 return False
20392035
2040 def set_section(self, section):2036 def set_section(self, section):
2041 self.section = section2037 self.section = section
2042 return2038
2043
2044 def _update_usage_counter(self):2039 def _update_usage_counter(self):
2045 """ try to get the usage counter from zeitgeist """2040 """ try to get the usage counter from zeitgeist """
2046 def _zeitgeist_callback(counter):2041 def _zeitgeist_callback(counter):
2047 LOG.debug("zeitgeist usage: %s" % counter)2042 LOG.debug("zeitgeist usage: %s" % counter)
2048 if counter == 0:2043 if counter == 0:
2049 # this probably means we just have no idea about it,2044 # this probably means we just have no idea about it,
2050 # so instead of saying "Used: never" we just return 2045 # so instead of saying "Used: never" we just return
2051 # this can go away when zeitgeist captures more events2046 # this can go away when zeitgeist captures more events
2052 # --there are still cases when we really do want to hide this2047 # --there are still cases when we really do want to hide this
2053 self.usage.hide()2048 self.usage.hide()
@@ -2055,7 +2050,7 @@
2055 if counter <= 100:2050 if counter <= 100:
2056 label_string = gettext.ngettext("Used: one time",2051 label_string = gettext.ngettext("Used: one time",
2057 "Used: %(amount)s times",2052 "Used: %(amount)s times",
2058 counter) % { 'amount' : counter, }2053 counter) % {'amount': counter}
2059 else:2054 else:
2060 label_string = _("Used: over 100 times")2055 label_string = _("Used: over 100 times")
2061 self.usage.set_text('<small>%s</small>' % label_string)2056 self.usage.set_text('<small>%s</small>' % label_string)
@@ -2070,6 +2065,7 @@
2070 # LOG.warning("could not update the usage counter: %s " % e)2065 # LOG.warning("could not update the usage counter: %s " % e)
2071 # self.usage.hide()2066 # self.usage.hide()
20722067
2068
2073def get_test_window_appdetails():2069def get_test_window_appdetails():
20742070
2075 from softwarecenter.db.pkginfo import get_pkg_info2071 from softwarecenter.db.pkginfo import get_pkg_info
@@ -2082,7 +2078,7 @@
2082 db = StoreDatabase(pathname, cache)2078 db = StoreDatabase(pathname, cache)
2083 db.open()2079 db.open()
20842080
2085 import softwarecenter.paths 2081 import softwarecenter.paths
2086 datadir = softwarecenter.paths.datadir2082 datadir = softwarecenter.paths.datadir
20872083
2088 from softwarecenter.ui.gtk3.utils import get_sc_icon_theme2084 from softwarecenter.ui.gtk3.utils import get_sc_icon_theme
@@ -2090,7 +2086,7 @@
20902086
2091 import softwarecenter.distro2087 import softwarecenter.distro
2092 distro = softwarecenter.distro.get_distro()2088 distro = softwarecenter.distro.get_distro()
2093 2089
2094 # gui2090 # gui
2095 win = Gtk.Window()2091 win = Gtk.Window()
2096 scroll = Gtk.ScrolledWindow()2092 scroll = Gtk.ScrolledWindow()
@@ -2118,7 +2114,7 @@
2118 scroll.add(view)2114 scroll.add(view)
2119 scroll.show()2115 scroll.show()
2120 win.add(scroll)2116 win.add(scroll)
2121 win.set_size_request(600,800)2117 win.set_size_request(600, 800)
2122 win.show()2118 win.show()
2123 win.connect('destroy', Gtk.main_quit)2119 win.connect('destroy', Gtk.main_quit)
2124 win.set_data("view", view)2120 win.set_data("view", view)
@@ -2132,7 +2128,7 @@
2132 else:2128 else:
2133 view.show_app(Application("Movie Player", "totem"))2129 view.show_app(Application("Movie Player", "totem"))
2134 return True2130 return True
2135 2131
2136 win = get_test_window_appdetails()2132 win = get_test_window_appdetails()
21372133
2138 # keep it spinning to test for re-draw issues and memleaks2134 # keep it spinning to test for re-draw issues and memleaks
21392135
=== modified file 'test/test_pep8.py'
--- test/test_pep8.py 2012-03-14 16:34:56 +0000
+++ test/test_pep8.py 2012-03-14 23:52:20 +0000
@@ -18,7 +18,7 @@
18 softwarecenter.ui.gtk3.views,18 softwarecenter.ui.gtk3.views,
19 softwarecenter.ui.gtk3.widgets,19 softwarecenter.ui.gtk3.widgets,
20 softwarecenter.db.pkginfo_impl]20 softwarecenter.db.pkginfo_impl]
21 exclude = ['appdetailsview.py']21 exclude = []
2222
23 def message(self, text):23 def message(self, text):
24 self.errors.append(text)24 self.errors.append(text)