Verified Kaydet (Commit) 16c1b9df authored tarafından Erdem Ersoy's avatar Erdem Ersoy

Rewrite Flatpak GUI mess (12/X):

* Remove "Install From Entry" and "Install From File" menu item functions.
  They are useless when a search bar is available.
üst c817bca9
This diff is collapsed.
#!/usr/bin/env python3
#
# Pardus Flatpak GUI install from entry first window module
# Copyright (C) 2020 Erdem Ersoy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from pardusflatpakgui.installfromentrywindow_2 import InstallFromEntryWindow2
import gettext
import locale
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Flatpak', '1.0')
gi.require_version('GLib', '2.0')
gi.require_version('Gio', '2.0')
gi.require_version('Gdk', '3.0')
from gi.repository import Gtk, Flatpak, GLib, Gio, Gdk
locale.setlocale(locale.LC_ALL, "")
gettext.bindtextdomain("pardus-flatpak-gui", "po/")
gettext.textdomain("pardus-flatpak-gui")
_ = gettext.gettext
gettext.install("pardus-flatpak-gui", "po/")
class InstallFromEntryWindow(object):
def __init__(self, application, flatpak_installation, tree_view, search_filter):
self.Application = application
self.FlatpakInstallation = flatpak_installation
self.TreeViewMain = tree_view
self.SearchFilter = search_filter
try:
install_input_gui_file = "ui/installfromentrywindow.glade"
self.install_input_builder = Gtk.Builder.new_from_file(
install_input_gui_file)
self.install_input_builder.connect_signals(self)
except GLib.GError:
print(_("Error reading GUI file: ") + install_input_gui_file)
raise
try:
messages_gui_file = "ui/messagedialogs.glade"
messages_builder = Gtk.Builder.new_from_file(messages_gui_file)
messages_builder.connect_signals(self)
except GLib.GError:
print(_("Error reading message dialogs GUI file: ") +
messages_gui_file)
raise
self.MessageDialogError = messages_builder.get_object(
"MessageDialogError")
self.InstallEntryLabel = self.install_input_builder.get_object(
"InstallEntryLabel")
self.InstallEntryLabel.set_text(
_("Please enter an application name (Ex: org.libreoffice.LibreOffice) what you want to install from "
"Flathub."))
self.InstallEntryLabel2 = self.install_input_builder.get_object(
"InstallEntryLabel2")
self.InstallEntryLabel2.set_text(
_("NOTE: Installing an application from third party remote repositories isn't secured as installing an "
"application from official repositories of your distribution."))
self.InstallEntryButton = self.install_input_builder.get_object(
"InstallEntryButton")
self.InstallEntryButton.set_label(_("I_nstall"))
self.InstallEntry = self.install_input_builder.get_object(
"InstallEntry")
self.InstallEntryWindow = \
self.install_input_builder.get_object("InstallEntryWindow")
self.InstallEntryWindow.set_title(_("Enter an application name"))
self.InstallEntryWindow.set_application(application)
self.InstallEntryWindow.show()
def on_install_at_install(self, button):
real_name = self.InstallEntry.get_text()
if len(real_name.split(".")) < 3:
self.MessageDialogError.set_markup(
_("<big><b>Input Error</b></big>"))
self.MessageDialogError.format_secondary_text(
_("Input entered is invalid."))
self.MessageDialogError.run()
self.MessageDialogError.hide()
return None
flathub_refs_list = self.FlatpakInstallation.list_remote_refs_sync("flathub", Gio.Cancellable.new())
installed_refs_list = self.FlatpakInstallation.list_installed_refs()
for item in flathub_refs_list:
if item.get_name() == real_name and \
item.get_arch() == Flatpak.get_default_arch() and \
item not in installed_refs_list:
ref = item
InstallFromEntryWindow2(self.Application, ref, self.FlatpakInstallation,
self.TreeViewMain, self.SearchFilter)
self.on_destroy(self.InstallEntryWindow, Gdk.Event.new(0))
def on_destroy(self, widget, event):
self.InstallEntry.set_text("")
widget.destroy()
#!/usr/bin/env python3
#
# Pardus Flatpak GUI install from entry second window module
# Copyright (C) 2020 Erdem Ersoy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import gettext
import locale
import threading
import time
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Flatpak', '1.0')
gi.require_version('GLib', '2.0')
gi.require_version('Gio', '2.0')
from gi.repository import Gtk, Flatpak, GLib, Gio
locale.setlocale(locale.LC_ALL, "")
gettext.bindtextdomain("pardus-flatpak-gui", "po/")
gettext.textdomain("pardus-flatpak-gui")
_ = gettext.gettext
gettext.install("pardus-flatpak-gui", "po/")
class InstallFromEntryWindow2(object):
def __init__(self, application, ref, flatpak_installation, tree_view, search_filter):
self.Application = application
self.Ref = ref
self.RealName = self.Ref.get_name()
self.Arch = self.Ref.get_arch()
self.Branch = self.Ref.get_branch()
self.FlatpakInstallation = flatpak_installation
self.FlatpakTransaction = \
Flatpak.Transaction.new_for_installation(
self.FlatpakInstallation,
Gio.Cancellable.new())
self.FlatpakTransaction.set_default_arch(self.Arch)
self.FlatpakTransaction.set_disable_dependencies(False)
self.FlatpakTransaction.set_disable_prune(False)
self.FlatpakTransaction.set_disable_related(False)
self.FlatpakTransaction.set_disable_static_deltas(False)
self.FlatpakTransaction.set_no_deploy(False)
self.FlatpakTransaction.set_no_pull(False)
self.FlatpakTransaction.add_install(
self.Ref.get_remote_name(),
self.Ref.format_ref(),
None)
self.TreeViewMain = tree_view
self.TreeModel = self.TreeViewMain.get_model()
self.TreeIter = self.TreeModel.get_iter_first()
while self.TreeIter:
if self.TreeModel.get_value(self.TreeIter, 0) == self.RealName and \
self.TreeModel.get_value(self.TreeIter, 1) == self.Arch and \
self.TreeModel.get_value(self.TreeIter, 2) == self.Branch:
break
self.TreeIter = self.TreeModel.iter_next(self.TreeIter)
self.Selection = self.TreeViewMain.get_selection()
self.SearchFilter = search_filter
self.handler_id = self.FlatpakTransaction.connect(
"new-operation",
self.install_progress_callback)
self.handler_id_2 = self.FlatpakTransaction.connect(
"operation-done",
self.install_progress_callback_disconnect)
self.handler_id_error = self.FlatpakTransaction.connect(
"operation-error",
self.install_progress_callback_error)
try:
install_gui_file = "ui/actionwindow.glade"
install_builder = Gtk.Builder.new_from_file(install_gui_file)
install_builder.connect_signals(self)
except GLib.GError:
print(_("Error reading GUI file: ") + install_gui_file)
raise
self.InstallWindow = install_builder.get_object("ActionWindow")
self.InstallWindow.set_application(application)
self.InstallWindow.set_title(_("Installing..."))
self.InstallWindow.show()
self.InstallProgressBar = install_builder.get_object(
"ActionProgressBar")
self.ProgressBarValue = int(
self.InstallProgressBar.get_fraction() * 100)
self.InstallLabel = install_builder.get_object("ActionLabel")
self.InstallTextBuffer = install_builder.get_object(
"ActionTextBuffer")
self.InstallTextBuffer.set_text("\0", -1)
self.StatusText = _("Installing...")
self.InstallLabel.set_text(self.StatusText)
self.InstallTextBuffer.set_text(self.StatusText)
self.InstallThread = threading.Thread(
target=self.install,
args=())
self.InstallThread.start()
GLib.threads_init()
def install(self):
try:
self.FlatpakTransaction.run(Gio.Cancellable.new())
except GLib.Error:
status_text = _("Error at installation!")
self.StatusText = self.StatusText + "\n" + status_text
GLib.idle_add(self.InstallLabel.set_text,
status_text,
priority=GLib.PRIORITY_DEFAULT)
GLib.idle_add(self.InstallTextBuffer.set_text,
self.StatusText,
priority=GLib.PRIORITY_DEFAULT)
else:
status_text = _("Installing completed!")
self.StatusText = self.StatusText + "\n" + status_text
GLib.idle_add(self.InstallLabel.set_text,
status_text,
priority=GLib.PRIORITY_DEFAULT)
GLib.idle_add(self.InstallTextBuffer.set_text,
self.StatusText,
priority=GLib.PRIORITY_DEFAULT)
self.FlatpakTransaction.disconnect(self.handler_id)
self.FlatpakTransaction.disconnect(self.handler_id_2)
self.FlatpakTransaction.disconnect(self.handler_id_error)
time.sleep(0.5)
installed_ref = Flatpak.InstalledRef()
for ref in self.FlatpakInstallation.list_installed_refs():
if ref.get_name() == self.Ref.get_name() and \
ref.get_arch() == self.Arch and \
ref.get_branch() == self.Branch:
installed_ref = ref
break
else:
continue
installed_ref_real_name = installed_ref.get_name()
installed_ref_arch = installed_ref.get_arch()
installed_ref_branch = installed_ref.get_branch()
installed_ref_remote = "flathub"
installed_size = installed_ref.get_installed_size()
installed_size_mib = installed_size / 1048576
installed_size_mib_str = \
f"{installed_size_mib:.2f}" + " MiB"
download_size_mib_str = ""
name = installed_ref.get_appdata_name()
GLib.idle_add(self.TreeModel.set_row,
self.TreeIter, [installed_ref_real_name,
installed_ref_arch,
installed_ref_branch,
installed_ref_remote,
installed_size_mib_str,
download_size_mib_str,
name],
priority=GLib.PRIORITY_DEFAULT)
time.sleep(0.2)
GLib.idle_add(self.Selection.unselect_all,
data=None,
priority=GLib.PRIORITY_DEFAULT)
time.sleep(0.2)
self.SearchFilter.refilter()
def install_progress_callback(self, transaction, operation, progress):
ref_to_install = Flatpak.Ref.parse(operation.get_ref())
ref_to_install_real_name = ref_to_install.get_name()
status_text = _("Installing: ") + ref_to_install_real_name
self.StatusText = self.StatusText + "\n" + status_text
GLib.idle_add(self.InstallLabel.set_text,
status_text,
priority=GLib.PRIORITY_DEFAULT)
GLib.idle_add(self.InstallTextBuffer.set_text,
self.StatusText,
priority=GLib.PRIORITY_DEFAULT)
self.TransactionProgress = progress # FIXME: Fix PyCharm warning
self.TransactionProgress.set_update_frequency(200)
self.handler_id_progress = self.TransactionProgress.connect(
"changed",
self.progress_bar_update) # FIXME: Fix PyCharm warning
def install_progress_callback_disconnect(self, transaction, operation, commit, result):
self.TransactionProgress.disconnect(self.handler_id_progress)
def install_progress_callback_error(self, transaction, operation, error, details):
ref_to_install = Flatpak.Ref.parse(operation.get_ref())
ref_to_install_real_name = ref_to_install.get_name()
status_text = _("Not installed: ") + ref_to_install_real_name
self.StatusText = self.StatusText + "\n" + status_text
GLib.idle_add(self.InstallLabel.set_text,
status_text,
priority=GLib.PRIORITY_DEFAULT)
GLib.idle_add(self.InstallTextBuffer.set_text,
self.StatusText,
priority=GLib.PRIORITY_DEFAULT)
if ref_to_install_real_name != self.RealName:
return True
else:
return False
def progress_bar_update(self, transaction_progress):
GLib.idle_add(self.InstallProgressBar.set_fraction,
float(transaction_progress.get_progress()) / 100.0,
priority=GLib.PRIORITY_DEFAULT)
def on_delete_action_window(self, widget, event):
widget.hide_on_delete()
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
from pardusflatpakgui.infowindow import InfoWindow from pardusflatpakgui.infowindow import InfoWindow
from pardusflatpakgui.installwindow import InstallWindow from pardusflatpakgui.installwindow import InstallWindow
from pardusflatpakgui.installfromentrywindow import InstallFromEntryWindow
from pardusflatpakgui.installfromfilewindow import InstallFromFileWindow
from pardusflatpakgui.uninstallwindow import UninstallWindow from pardusflatpakgui.uninstallwindow import UninstallWindow
from pardusflatpakgui.updateallwindow import UpdateAllWindow from pardusflatpakgui.updateallwindow import UpdateAllWindow
from pardusflatpakgui.version import Version from pardusflatpakgui.version import Version
...@@ -171,13 +169,6 @@ class MainWindow(object): ...@@ -171,13 +169,6 @@ class MainWindow(object):
self.ActionsMenu = main_builder.get_object("ActionsMenu") self.ActionsMenu = main_builder.get_object("ActionsMenu")
self.InstallFromFileMenuItem = main_builder.get_object(
"InstallFromFileMenuItem")
self.InstallFromFileMenuItem.set_label(_("Install From _File"))
self.InstallFromEntryMenuItem = main_builder.get_object("InstallFromEntryMenuItem")
self.InstallFromEntryMenuItem.set_label(_("Install From _Entry"))
self.UpdateAllMenuItem = main_builder.get_object("UpdateAllMenuItem") self.UpdateAllMenuItem = main_builder.get_object("UpdateAllMenuItem")
self.UpdateAllMenuItem.set_label(_("_Update All")) self.UpdateAllMenuItem.set_label(_("_Update All"))
...@@ -568,13 +559,6 @@ class MainWindow(object): ...@@ -568,13 +559,6 @@ class MainWindow(object):
InstallWindow(self.Application, self.FlatpakInstallation, real_name, arch, branch, InstallWindow(self.Application, self.FlatpakInstallation, real_name, arch, branch,
remote, tree_model, tree_iter, selection, self.SearchFilter) remote, tree_model, tree_iter, selection, self.SearchFilter)
def on_install_from_entry(self, menu_item):
InstallFromEntryWindow(self.Application, self.FlatpakInstallation, self.TreeViewMain, self.SearchFilter)
def on_install_from_file(self, menu_item):
InstallFromFileWindow(self.Application, self.FlatpakInstallation,
self.ListStoreMain)
def on_update_all(self, menu_item): def on_update_all(self, menu_item):
UpdateAllWindow(self.Application, self.FlatpakInstallation, UpdateAllWindow(self.Application, self.FlatpakInstallation,
self.ListStoreMain) self.ListStoreMain)
......
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1
Copyright (C) 2020 Erdem Ersoy
This file is part of Flatpak GUI.
Flatpak GUI is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Flatpak GUI is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Flatpak GUI. If not, see <http://www.gnu.org/licenses/>.
Author: Erdem Ersoy
-->
<interface>
<requires lib="gtk+" version="3.20"/>
<!-- interface-license-type gplv3 -->
<!-- interface-name Flatpak GUI -->
<!-- interface-description A GUI for Flatpak -->
<!-- interface-copyright 2020 Erdem Ersoy -->
<!-- interface-authors Erdem Ersoy -->
<object class="GtkImage" id="InstallEntryImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-save</property>
</object>
<object class="GtkWindow" id="InstallEntryWindow">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Enter an application name</property>
<property name="modal">True</property>
<property name="default_width">600</property>
<property name="default_height">400</property>
<property name="icon_name">document-save</property>
<property name="type_hint">dialog</property>
<signal name="delete-event" handler="on_destroy" swapped="no"/>
<child>
<placeholder/>
</child>
<child>
<object class="GtkBox" id="InstallEntryBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkLabel" id="InstallEntryLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Please enter an application name (Ex: org.libreoffice.LibreOffice) what you want to install from Flathub.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="InstallEntry">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="InstallEntryLabel2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">NOTE: Installing an application from third party remote repositories isn't secured as installing an application from official repositories of your distribution.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButtonBox" id="InstallEntryButtonBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkButton" id="InstallEntryButton">
<property name="label" translatable="yes">I_nstall</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">InstallEntryImage</property>
<property name="use_underline">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="on_install_at_install" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1
Copyright (C) 2020 Erdem Ersoy
This file is part of Flatpak GUI.
Flatpak GUI is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Flatpak GUI is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Flatpak GUI. If not, see <http://www.gnu.org/licenses/>.
Author: Erdem Ersoy
-->
<interface>
<requires lib="gtk+" version="3.20"/>
<!-- interface-license-type gplv3 -->
<!-- interface-name Flatpak GUI -->
<!-- interface-description A GUI for Flatpak -->
<!-- interface-copyright 2020 Erdem Ersoy -->
<!-- interface-authors Erdem Ersoy -->
<object class="GtkFileFilter" id="InstallFromFileInputFileFilter">
<mime-types>
<mime-type>application/vnd.flatpak.ref</mime-type>
</mime-types>
</object>
<object class="GtkWindow" id="InstallFromFileInputWindow">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Choose a file</property>
<property name="modal">True</property>
<property name="default_width">600</property>
<property name="default_height">400</property>
<property name="icon_name">document-save</property>
<property name="type_hint">dialog</property>
<signal name="destroy" handler="onDestroy" swapped="no"/>
<child>
<placeholder/>
</child>
<child>
<object class="GtkBox" id="InstallFromFileInputBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<child>
<object class="GtkLabel" id="InstallFromFileInputLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Please choose a Flatpak ref file.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkFileChooserButton" id="InstallFromFileInputFileChooser">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="filter">InstallFromFileInputFileFilter</property>
<property name="title" translatable="yes">Choose a file</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="InstallFromFileInputLabel2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">NOTE: Installing an application from third party remote repositories isn't secured as installing an application from official repositories of your distribution.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButtonBox" id="InstallFromFileInputButtonBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<property name="layout_style">end</property>
<child>
<placeholder/>
</child>
<child>
<object class="GtkButton" id="InstallFromFileInputButton">
<property name="label" translatable="yes">I_nstall</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="image">InstallFromFileInputImage</property>
<property name="use_underline">True</property>
<property name="always_show_image">True</property>
<signal name="clicked" handler="onInstallAtInstallFromFile" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkImage" id="InstallFromFileInputImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-save</property>
</object>
</interface>
...@@ -38,16 +38,6 @@ Author: Erdem Ersoy ...@@ -38,16 +38,6 @@ Author: Erdem Ersoy
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="stock">gtk-info</property> <property name="stock">gtk-info</property>
</object> </object>
<object class="GtkImage" id="InstallFromEntryImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-save</property>
</object>
<object class="GtkImage" id="InstallFromFileImage">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-save</property>
</object>
<object class="GtkImage" id="InstallImage"> <object class="GtkImage" id="InstallImage">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
...@@ -140,28 +130,6 @@ Author: Erdem Ersoy ...@@ -140,28 +130,6 @@ Author: Erdem Ersoy
<object class="GtkMenu" id="HeaderBarMenu"> <object class="GtkMenu" id="HeaderBarMenu">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<child>
<object class="GtkImageMenuItem" id="InstallFromEntryMenuItem">
<property name="label" translatable="yes">Install From _File</property>
<property name="visible">True</property>
<property name="can_focus">False</property>