295
302
vbox_left.pack_start(self.scrolled_window, True, True)
296
303
self.install_button.props.sensitive = False
298
self.add_package(pkg)
299
def add_package(self, pkg, active=True, details="", score=0):
300
"""Show the package in the confirmation dialog.
305
self.add_confirm_package(pkg)
307
def add_confirm(self, name, summary, active=True, details="", score=0,
309
"""Add an entry to the confirmation dialog.
302
311
Keyword arguments:
303
pkg -- the apt.package.Package instance
312
name -- name of the package or file
313
summary -- short description of the package
304
314
active -- if the package should be selected by default
305
315
details -- additional information about the package
306
316
score -- the ranking of the package which should be used for ordering
317
restricted -- if the use or redistribution is restriceted
308
if pkg.name in RESTRICTED_PACKAGES or \
309
pkg.candidate.origins[0].component in ("non-free", "multiverse"):
319
if name in RESTRICTED_PACKAGES or restricted:
310
320
#TRANSLATORS: %s is the name of a piece of software
311
321
tooltip = _("The use of %s may be restricted in some "
312
322
"countries. You must verify that one of the following "
316
326
"• You have permission to use this software (for "
317
327
"example, a patent license)\n"
318
328
"• You are using this software for research "
319
"purposes only") % pkg.name
329
"purposes only") % name
320
330
# Set the dialog default to cancel if a restricted packages is
321
331
# selected for installation
323
333
self.set_default_response(gtk.RESPONSE_CANCEL)
326
self.pkg_store.append((pkg, active, details, tooltip, score))
336
desc = utils.get_package_desc(name, summary)
337
self.pkg_store.append((name, desc, active, details, tooltip, score))
328
339
self.install_button.props.sensitive = True
341
def add_confirm_package(self, pkg, active=True, details="", score=0):
342
"""Show an apt.package.Package instance in the confirmation dialog.
345
pkg -- the apt.package.Package instance
346
active -- if the package should be selected by default
347
details -- additional information about the package
348
score -- the ranking of the package which should be used for ordering
350
restricted = pkg.candidate.origins[0].component in ("non-free",
352
self.add_confirm(pkg.name, pkg.summary, active, details, score,
330
355
def get_selected_pkgs(self):
331
356
"""Return a list of the package names which are selected."""
332
return [pkg.name for \
333
pkg, active, _details, _tooltip, _score in self.pkg_store if
358
for pkg, _desc, active, _details, _tooltip, _score \
336
362
def _on_query_tooltip(self, treeview, x, y, keyboard_tip, tooltip):
337
363
"""Handle tooltips for restrcited packages."""
366
392
renderer.props.stock_id = 0
368
def _render_description(self, cell, renderer, model, iter):
369
"""Helper to render the package description."""
370
pkg = model.get_value(iter, COLUMN_PACKAGE)
371
markup = utils.get_package_desc(pkg)
372
renderer.set_property("markup", markup)
374
def _render_details(self, cell, renderer, model, iter):
375
"""Helper to render the package details."""
376
details = model.get_value(iter, COLUMN_DETAILS)
377
markup = "%s" % details
378
renderer.set_property("markup", details)
381
395
"""Run the dialog."""
382
396
if len(self.pkg_store) > 4:
428
443
if not self._cache:
429
444
self._cache = apt.Cache(GtkOpProgress(progress))
431
def _get_window_title(self, xid):
432
"""Get the title of the window by its window id."""
433
win = gtk.gdk.window_foreign_new(xid)
435
return win.property_get("WM_NAME")[2]
447
def _get_sender_name(self, sender):
448
"""Try to resolve the name of the calling application."""
449
pid = yield get_pid_from_dbus_name(sender, self.bus)
451
exe = os.readlink("/proc/%s/exe" % pid)
454
# Try to get the name of an interpreted script
455
if exe in ["/usr/bin/python", "/usr/bin/python2.6", "/usr/bin/perl"]:
457
fcmd = open("/proc/%s/cmdline" % pid)
458
exe = fcmd.read().split("\0")[1]
460
except (IndexError, OSError):
462
# Special case for the GStreamer codec installation via the helper
463
# gnome-packagekit returns the name of parent window in this case,
464
# But this could be misleading:
465
# return_value(parent.property_get("WM_NAME")[2])
466
if exe in ["/usr/libexec/pk-gstreamer-install",
467
"/usr/lib/pk-gstreamer-install",
468
"/usr/bin/gst-install"]:
470
# Return the application name in the case of an installed application
471
for app in gio.app_info_get_all():
472
if app.get_executable() == exe:
473
return_value(app.get_name())
474
return_value(os.path.basename(exe))
439
476
def _parse_interaction(self, interaction):
560
597
@dbus_deferred_method(PACKAGEKIT_MODIFY_DBUS_INTERFACE,
561
598
in_signature="uass", out_signature="",
599
sender_keyword="sender",
562
600
utf8_strings=True)
563
def InstallPackageFiles(self, xid, files, interaction):
601
def InstallPackageFiles(self, xid, files, interaction, sender):
564
602
"""Install local package files.
566
604
Keyword arguments:
567
605
xid -- the window id of the requesting application
568
606
files -- the list of package file paths
569
interaction -- the interaction mode: which ui elements shoudl be
607
interaction -- the interaction mode: which ui elements should be
570
608
shown e.g. hide-finished or hide-confirm-search
572
610
log.info("InstallPackageFiles was called: %s, %s, %s", xid, files,
574
return self._install_package_files(xid, files, interaction)
612
return self._install_package_files(xid, files, interaction, sender)
577
def _install_package_files(self, xid, files, interaction):
616
def _install_package_files(self, xid, files, interaction, sender):
617
parent = gtk.gdk.window_foreign_new(xid)
579
619
if len(files) != 1:
580
620
header = _("Failed to install multiple package files")
581
#FIXME: should provide some information about how to get fonts
582
621
message = _("Installing more than one package file at the same "
583
622
"time isn't supported. Please install one after the "
589
628
elif not files[0].endswith(".deb"):
590
629
header = _("Unsupported package format")
591
630
message = _("Only Debian packages are supported (*.deb)")
632
debfile = apt.debfile.DebPackage(files[0])
633
desc = debfile["Description"].split("\n", 1)[0]
635
header = _("Unsupported package format")
636
message = _("Only Debian packages are supported (*.deb)")
593
638
dia = ErrorDialog(header, message)
596
641
raise errors.ModifyFailed("%s - %s" % (header, message))
597
return self.backend.install_package_files(xid, files, interaction)
642
title = gettext.ngettext("Install package file?",
643
"Install package files?",
645
sender_name = yield self._get_sender_name(sender)
647
message = gettext.ngettext("%s requests to install the following "
649
"%s requests to install the following "
651
len(files)) % sender_name
655
message += _("Software from foreign sources could be malicious, "
656
"could contain security risks and or even break your "
658
"Install packages from your distribution's "
659
"repositories as far as possible.")
660
confirm = ConfirmInstallDialog(title, message, parent=parent)
661
confirm.add_confirm(files[0], desc)
662
if confirm.run() == gtk.RESPONSE_CANCEL:
663
raise errors.ModifyCancelled
664
yield self.backend.install_package_files(xid,
665
confirm.get_selected_pkgs(),
599
668
@dbus_deferred_method(PACKAGEKIT_MODIFY_DBUS_INTERFACE,
600
669
in_signature="uass", out_signature="",
670
sender_keyword="sender",
601
671
utf8_strings=True)
602
def InstallProvideFiles(self, xid, files, interaction,):
672
def InstallProvideFiles(self, xid, files, interaction, sender):
603
673
"""Install packages which provide the given files.
605
675
Keyword arguments:
606
676
xid -- the window id of the requesting application
607
677
files -- the list of package file paths
608
interaction -- the interaction mode: which ui elements shoudl be
678
interaction -- the interaction mode: which ui elements should be
609
679
shown e.g. hide-finished or hide-confirm-search
611
681
log.info("InstallProvideFiles() was called: %s, %s, %s", xid, files,
613
self._install_provide_files(xid, files, interaction)
683
return self._install_provide_files(xid, files, interaction, sender)
616
def _install_provide_files(self, xid, files, interaction):
687
def _install_provide_files(self, xid, files, interaction, sender):
617
688
header = _("Installing packages by files isn't supported")
618
689
message = _("This method hasn't yet been implemented.")
619
690
#FIXME: should provide some information about how to find apps
625
696
@dbus_deferred_method(PACKAGEKIT_MODIFY_DBUS_INTERFACE,
626
697
in_signature="uass", out_signature="",
698
sender_keyword="sender",
627
699
utf8_strings=True)
628
def InstallCatalogs(self, xid, files, interaction,):
700
def InstallCatalogs(self, xid, files, interaction, sender):
629
701
"""Install packages which provide the given files.
631
703
Keyword arguments:
632
704
xid -- the window id of the requesting application
633
705
files -- the list of catalog file paths
634
interaction -- the interaction mode: which ui elements shoudl be
706
interaction -- the interaction mode: which ui elements should be
635
707
shown e.g. hide-finished or hide-confirm-search
637
709
log.info("InstallCatalogs() was called: %s, %s, %s", xid, files,
639
return self._install_catalogs(xid, files, interaction)
711
return self._install_catalogs(xid, files, interaction, sender)
642
def _install_catalogs(self, xid, files, interaction):
715
def _install_catalogs(self, xid, files, interaction, sender):
716
parent = gtk.gdk.window_foreign_new(xid)
643
717
self._init_cache()
644
718
arch = os.popen("/usr/bin/dpkg --print-architecture").read().strip()
645
719
distro, code, release = os.popen("/usr/bin/lsb_release "
713
787
"available: %s", len(missing)) % pkgs
714
788
self._show_error(header, msg)
715
789
raise errors.ModifyNoPackagesFound(msg)
716
# Get parent title and window
717
790
parent = gtk.gdk.window_foreign_new(xid)
720
parent_title = parent.property_get("WM_NAME")[2]
721
791
# Create nice messages
792
sender_name = yield self._get_sender_name(sender)
722
793
title = gettext.ngettext("Install the following software package?",
723
794
"Install the following software packages?",
726
797
#TRANSLATORS: %s is the name of the application which requested
727
798
# the installation
728
799
message = gettext.ngettext("%s requires the installation of an "
729
800
"additional software package.",
730
801
"%s requires the installation of "
731
802
"additional software packages.",
732
len(pkgs)) % parent_title
803
len(pkgs)) % sender_name
734
805
#TRANSLATORS: %s is an absolute file path, e.g. /usr/bin/xterm
735
806
message = gettext.ngettext("The package catalog %s requests to "
742
813
confirm = ConfirmInstallDialog(title, message, pkgs, parent)
743
814
res = confirm.run()
744
815
if res == gtk.RESPONSE_OK:
745
return self.backend.install_packages(xid,
746
confirm.get_selected_pkgs(),
816
yield self.backend.install_packages(xid,
817
confirm.get_selected_pkgs(),
749
820
raise errors.ModifyCancelled
751
822
@dbus_deferred_method(PACKAGEKIT_MODIFY_DBUS_INTERFACE,
752
823
in_signature="uass", out_signature="",
824
sender_keyword="sender",
753
825
utf8_strings=True)
754
def InstallPackageNames(self, xid, packages, interaction):
826
def InstallPackageNames(self, xid, packages, interaction, sender):
755
827
"""Install packages from a preconfigured software source.
757
829
Keyword arguments:
758
830
xid -- the window id of the requesting application
759
831
packages -- the list of package names
760
interaction -- the interaction mode: which ui elements shoudl be
832
interaction -- the interaction mode: which ui elements should be
761
833
shown e.g. hide-finished or hide-confirm-search
763
835
log.info("InstallPackageNames() was called: %s, %s, %s", xid, packages,
765
return self._install_package_names(xid, packages, interaction)
837
return self._install_package_names(xid, packages, interaction, sender)
768
def _install_package_names(self, xid, packages, interaction):
769
deferred = self.backend.install_packages(xid, packages, interaction)
841
def _install_package_names(self, xid, packages, interaction, sender):
842
parent = gtk.gdk.window_foreign_new(xid)
843
title = gettext.ngettext("Install additional software package?",
844
"Install additional software packages?",
846
sender_name = yield self._get_sender_name(sender)
848
message = gettext.ngettext("%s requests to install the following "
849
"software package to provide additional "
851
"%s requests to install the following "
852
"software packages to provide "
853
"additional features.",
854
len(packages)) % sender_name
856
message = gettext.ngettext("The following software package is "
857
"required to provide additional "
859
"The following software packages are "
860
"required to provide additional "
862
len(packages)) % sender_name
863
confirm = ConfirmInstallDialog(title, message, parent=parent)
864
#FIXME: We should use the cache to provide additional information
866
confirm.add_confirm(pkg, "")
867
if confirm.run() == gtk.RESPONSE_CANCEL:
868
raise errors.ModifyCancelled
869
yield self.backend.install_packages(xid, packages, interaction)
772
871
@dbus_deferred_method(PACKAGEKIT_MODIFY_DBUS_INTERFACE,
773
872
in_signature="uass", out_signature="",
873
sender_keyword="sender",
774
874
utf8_strings=True)
775
def InstallMimeTypes(self, xid, mime_types, interaction,):
875
def InstallMimeTypes(self, xid, mime_types, interaction, sender):
776
876
"""Install mime type handler from a preconfigured software source.
778
878
Keyword arguments:
779
879
xid -- the window id of the requesting application
780
880
mime_types -- list of mime types whose handlers should be installed
781
interaction -- the interaction mode: which ui elements shoudl be
881
interaction -- the interaction mode: which ui elements should be
782
882
shown e.g. hide-finished or hide-confirm-search
784
884
log.info("InstallMimeTypes() was called: %s, %s, %s", xid, mime_types,
786
return self._install_mime_types(xid, mime_types, interaction)
886
return self._install_mime_types(xid, mime_types, interaction, sender)
789
def _install_mime_types(self, xid, mime_types_list, interaction):
890
def _install_mime_types(self, xid, mime_types_list, interaction, sender):
891
parent = gtk.gdk.window_foreign_new(xid)
790
892
if not os.path.exists(utils.APP_INSTALL_DATA):
791
893
#FIXME: should provide some information about how to find apps
792
894
header = _("Installing mime type handlers isn't supported")
799
901
raise errors.ModifyInternalError(message)
800
parent = gtk.gdk.window_foreign_new(xid)
803
parent_title = parent.property_get("WM_NAME")[2]
804
title = _("Searching for mime type handlers")
902
sender_name = yield self._get_sender_name(sender)
903
title = _("Searching for suitable software to open files")
805
904
mime_types = set(mime_types_list)
806
905
mime_names = [gio.content_type_get_description(mt) for mt in mime_types]
808
message = gettext.ngettext("%s requires to install additional "
809
"software which can open files of "
811
"%s requires to install additional "
812
"software which can open files of "
813
"the following mime types:\n%s",
814
len(mime_types)) % (parent_title,
815
", ".join(mime_names))
907
#TRANSLATORS: %s is an application
908
message = gettext.ngettext("%s requires to install software to "
909
"open files of the following file type:",
910
"%s requires to install software to "
911
"open files of the following file "
913
len(mime_types)) % sender_name
817
message = gettext.ngettext("You have to install additional "
818
"software to open files of the "
820
"You have to install additional "
821
"software to open files of the "
822
"following mime types:\n%s",
823
len(mime_types)) % (parent_title,
824
", ".join(mime_names))
915
message = gettext.ngettext("Software to open files of the "
916
"following file type is required "
917
"but is not installed:",
918
"Software to open files of the "
919
"following file types is required "
920
"but is not installed:",
922
mime_types_desc = [gio.content_type_get_description(mime_type) \
923
for mime_type in mime_types]
924
message += self._get_bullet_list(mime_types_desc)
825
925
progress = ProgressDialog(title, message, parent)
826
926
progress.show_all()
827
927
while gtk.events_pending():
866
966
if package_map[pkg_name][2] < popcon:
867
967
package_map[pkg_name][2] = popcon
868
968
unsatisfied.discard(mime_type)
970
not supported_mime_types.issuperset(mime_types):
870
973
progress.destroy()
872
details=_("Mime types")
974
if mixed or unsatisfied:
975
details = _("Supported file types")
875
title = _("Install mime type handler?")
978
title = _("Install software to open files?")
877
#TRANSLATORS: list separator
878
unsatisfied_str = _(", ").join(unsatisfied)
980
unsatisfied_desc = [gio.content_type_get_description(mime_type) \
981
for mime_type in unsatisfied]
982
unsatisfied_str = self._get_bullet_list(unsatisfied_desc)
879
983
message += "\n\n"
880
message += gettext.ngettext("%s isn't supported.",
881
"Unsupported mime types: %s",
984
#TRANSLATORS: %s is either a single file type or a bullet list of
986
message += gettext.ngettext("%s is not supported.",
987
"Unsupported file types: %s",
882
988
len(unsatisfied)) % unsatisfied_str
883
989
confirm = ConfirmInstallDialog(title, message, parent=parent,
885
991
selectable=len(package_map) > 1,
886
package_type=_("Handler"))
992
package_type=_("Application"))
887
993
for pkg, (entries, provides, score) in package_map.iteritems():
888
994
if len(provides) == len(mime_types):
889
995
details = _("All")
891
997
#TRANSLATORS: Separator for a list of plugins
892
998
details = _(",\n").join(provides)
893
confirm.add_package(self._cache[pkg], len(package_map) == 1,
999
confirm.add_confirm_package(self._cache[pkg], len(package_map) == 1,
895
1001
res = confirm.run()
896
1002
if res == gtk.RESPONSE_OK:
897
return self.backend.install_packages(xid,
898
confirm.get_selected_pkgs(),
1003
yield self.backend.install_packages(xid,
1004
confirm.get_selected_pkgs(),
901
1007
raise errors.ModifyCancelled
904
1009
@dbus_deferred_method(PACKAGEKIT_MODIFY_DBUS_INTERFACE,
905
1010
in_signature="uass", out_signature="",
906
1011
utf8_strings=True)
969
1075
xid -- the window id of the requesting application
970
1076
resources -- list of GStreamer structures, e.g.
971
1077
"gstreamer0.10(decoder-video/x-wmv)(wmvversion=3)"
972
interaction -- the interaction mode: which ui elements shoudl be
1078
interaction -- the interaction mode: which ui elements should be
973
1079
shown e.g. hide-finished or hide-confirm-search
975
1081
log.info("InstallGstreamerResources() was called: %s, %s, %s", xid,
976
1082
resources, interaction)
977
return self._install_gstreamer_resources(xid, resources, interaction)
1083
return self._install_gstreamer_resources(xid, resources, interaction,
980
def _install_gstreamer_resources(self, xid, resources, interaction):
1088
def _install_gstreamer_resources(self, xid, resources, interaction, sender):
981
1089
def parse_gstreamer_structure(resource):
982
1090
# E.g. "MS Video|gstreamer0.10(decoder-video/x-wmv)(wmvversion=3)"
983
1091
match = re.match("^(?P<name>.*)\|gstreamer(?P<version>[0-9\.]+)"
1008
1116
record, caps, element)
1010
1118
structures = [parse_gstreamer_structure(res) for res in resources]
1119
kinds = set([struct.kind for struct in structures])
1011
1120
# Show a progress dialog
1012
1121
parent = gtk.gdk.window_foreign_new(xid)
1013
title = "Searching for multimedia plugins"
1016
parent_title = parent.property_get("WM_NAME")[2]
1122
sender_name = yield self._get_sender_name(sender)
1123
title = _("Searching for multimedia plugins")
1017
1124
# Get a nice dialog message
1019
#TRANSLATORS: %s is the application requesting the plugins
1020
message = gettext.ngettext("%s requires extra plugins to handle "
1021
"the following media content type:",
1022
"%s requires extra plugins to handle "
1023
"following media content types:",
1024
len(structures)) % parent_title
1026
message = gettext.ngettext("Extra plugins to handle "
1027
"the following media content type are "
1029
"Extra plugins to handle "
1030
"following media content types are "
1033
if len(structures) == 1:
1035
message += structures[0].name
1037
for struct in structures:
1039
message += "\n• %s" % struct.name
1041
message += "\n• %s" % struct.data
1125
import pdb; pdb.set_trace()
1126
if kinds.issubset(set(["encoder"])):
1128
#TRANSLATORS: %s is the application requesting the plugins
1129
message = gettext.ngettext("%s requires to install plugins to "
1130
"create media files of the "
1132
"%s requires to install plugins to "
1133
"create files of the following "
1135
len(structures)) % sender_name
1137
message = gettext.ngettext("The plugin to create media files "
1138
"of the following type is not "
1140
"The plugin to create media files "
1141
"of the following types is not "
1144
elif kinds.issubset(set(["decoder"])):
1146
#TRANSLATORS: %s is the application requesting the plugins
1147
message = gettext.ngettext("%s requires to install plugins to "
1148
"play media files of the "
1150
"%s requires to install plugins to "
1151
"play files of the following "
1153
len(structures)) % sender_name
1155
message = gettext.ngettext("The plugin to play media files "
1156
"of the following type is not "
1158
"The plugin to play media files "
1159
"of the following types is not "
1162
elif kinds.issubset(set(["encoder", "decoder"])):
1164
#TRANSLATORS: %s is the application requesting the plugins
1165
message = gettext.ngettext("%s requires to install plugins to "
1166
"create and play media files of the "
1168
"%s requires to install plugins to "
1169
"create and play media files of the "
1171
len(structures)) % sender_name
1173
message = gettext.ngettext("The plugins to create and play "
1174
"media files of the following type "
1175
"are not installed:",
1176
"The plugins to create and play "
1177
"media files of the following types "
1178
"are not installed:",
1182
#TRANSLATORS: %s is the application requesting the plugins
1183
message = gettext.ngettext("%s requires to install plugins to "
1184
"support the following "
1185
"multimedia feature:",
1186
"%s requires to install plugins to "
1187
"support the following multimedia "
1189
len(structures)) % sender_name
1191
message = gettext.ngettext("Extra plugins to provide the "
1192
"following multimedia feature are "
1194
"Extra plugins to provide the "
1195
"following multimedia features are "
1198
message += self._get_bullet_list([struct.name or struct.record \
1199
for struct in structures])
1042
1200
progress = ProgressDialog(title, message, parent)
1043
1201
progress.show_all()
1044
1202
while gtk.events_pending():
1109
1267
title = gettext.ngettext("Install extra multimedia plugin?",
1110
1268
"Install extra multimedia plugins?",
1113
#TRANSLATORS: %s is the name of an application
1114
message = gettext.ngettext("Confirm the installation of the "
1115
"plugin which was requested by %s.",
1116
"Confirm the installation of "
1117
"the selected plugins which have been "
1119
len(pkgs)) % parent_title
1121
message = gettext.ngettext("Confirm the installation of the "
1122
"requested plugin.",
1123
"Confirm the installation of the "
1124
"selected plugins.", len(pkgs))
1125
1270
unsatisfied = [stru.name for stru in structures if not stru.satisfied]
1126
1271
if unsatisfied:
1127
1272
message += "\n\n"
1128
message += gettext.ngettext("The following plugin isn't available:",
1129
"The following plugins aren't "
1130
"available:", len(unsatisfied))
1273
message += gettext.ngettext("The following plugin is not "
1275
"The following plugins are not "
1132
1279
#TRANSLATORS: list separator
1133
message += _(", ").join(unsatisfied)
1280
message += self._get_bullet_list(unsatisfied)
1135
1282
# We only show the details if there are packages which would only
1136
1283
# provide a subset of the requests
1150
1297
#TRANSLATORS: Separator for a list of plugins
1151
1298
details = _(",\n").join(provides)
1152
1299
install = pkg.name in best_providers
1153
confirm.add_package(pkg, install, details, score)
1300
confirm.add_confirm_package(pkg, install, details, score)
1154
1301
res = confirm.run()
1155
1302
if res == gtk.RESPONSE_OK:
1156
return self.backend.install_packages(xid,
1157
[pkg.name for pkg in pkgs],
1303
yield self.backend.install_packages(xid,
1304
confirm.get_selected_pkgs(),
1160
1307
raise errors.ModifyCancelled
1162
1309
@dbus_deferred_method(PACKAGEKIT_MODIFY_DBUS_INTERFACE,
1163
1310
in_signature="uass", out_signature="",
1311
sender_keyword="sender",
1164
1312
utf8_strings=True)
1165
def RemovePackageByFiles(self, xid, files, interaction,):
1313
def RemovePackageByFiles(self, xid, files, interaction, sender):
1166
1314
"""Remove packages which provide the given files.
1168
1316
Keyword arguments:
1169
1317
xid -- the window id of the requesting application
1170
1318
files -- the list of file paths
1171
interaction -- the interaction mode: which ui elements shoudl be
1319
interaction -- the interaction mode: which ui elements should be
1172
1320
shown e.g. hide-finished or hide-confirm-search
1174
1322
log.info("RemovePackageByFiles() was called: %s, %s, %s", xid, files,
1176
return self._remove_package_by_files(xid, files, interaction)
1324
return self._remove_package_by_files(xid, files, interaction, sender)
1179
def _remove_package_by_files(self, xid, files, interaction):
1328
def _remove_package_by_files(self, xid, files, interaction, sender):
1329
parent = gtk.gdk.window_foreign_new(xid)
1330
sender_name = yield self._get_sender_name(sender)
1180
1331
if [filename for filename in files if not filename.startswith("/")]:
1181
1332
raise errors.ModifyFailed("Only absolute file names")
1334
title = _("Searching software to be removed")
1336
message = gettext.ngettext("%s wants to remove the software "
1337
"which provides the following file:",
1338
"%s wants to remove the software which "
1339
"provides the following files:",
1340
len(files)) % sender_name
1342
message = gettext.ngettext("The software which provides the "
1343
"following file is requested to be "
1345
"The software which provides the "
1346
"following files is requested to be "
1349
message += self._get_bullet_list(files)
1350
progress = ProgressDialog(title, message, parent)
1352
self._init_cache(progress)
1184
1353
for pkg in self._cache:
1185
# FIXME: Fix python-apt
1187
1355
for installed_file in pkg.installed_files:
1188
1356
if installed_file in files:
1189
pkgs.append(pkg.name)
1193
1362
self._show_error(_("Files are not installed"),
1194
1363
_("The files which should be removed are not "
1195
1364
"part of any installed software."))
1196
1365
raise errors.ModifyNoPackagesFound
1197
return self.backend.remove_packages(xid, pkgs, interaction)
1366
title = gettext.ngettext("Remove software package?",
1367
"Remove software packages?", len(pkgs))
1369
#TRANSLATORS: %s is the name of an application
1370
message = gettext.ngettext("%s wants to remove the following "
1371
"software package from your computer.",
1372
"%s wants to remove the following "
1373
"software packages from your computer.",
1374
len(pkgs)) % sender_name
1376
message = gettext.ngettext("The following software package "
1377
"will be removed from your computer.",
1378
"The following software packages "
1379
"will be removed from your computer.",
1381
confirm = ConfirmInstallDialog(title, message, parent=parent,
1382
selectable=len(pkgs) > 1, pkgs=pkgs,
1383
action=_("_Remove"))
1385
if res == gtk.RESPONSE_OK:
1386
yield self.backend.remove_packages(xid,
1387
confirm.get_selected_pkgs(),
1390
raise errors.ModifyCancelled
1199
1392
def _show_error(self, header, message):
1200
1393
"""Show an error dialog."""