[magneto] add Gtk3 frontend

This commit is contained in:
Fabio Erculiani
2012-04-13 00:24:00 +02:00
parent 081f4b3aae
commit d2be035aba
5 changed files with 546 additions and 4 deletions
+164
View File
@@ -0,0 +1,164 @@
"""
@author: Fabio Erculiani <lxnay@sabayon.org>
@contact: lxnay@sabayon.org
@copyright: Fabio Erculiani
@license: GPL-2
B{Entropy Updates Notification Applet (Magneto) GTK3 components}
"""
# System imports
import os
from gi.repository import GObject, Gtk, GdkPixbuf
from entropy.i18n import _
# Magneto imports
from magneto.core.config import PIXMAPS_PATH, ICON_PATH
class AppletIconPixbuf:
def __init__(self):
self.images = {}
def add_file(self, name, filename):
if name not in self.images:
self.images[name] = []
filename = os.path.join(PIXMAPS_PATH, filename)
if not os.access(filename, os.R_OK):
raise AttributeError("Cannot open image file %s" % filename)
pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename)
self.add(name, pixbuf)
def add(self, name, pixbuf):
self.images[name].append(pixbuf)
def best_match(self, name, size):
best = None
for image in self.images[name]:
if not best:
best = image
continue
if abs(size - image.height) < abs(size - best.height):
best = image
return best
class GladeWindow:
def __init__(self, filename, window_name):
path = filename
if not os.path.isfile(filename):
path = "/usr/lib/entropy/magneto/magneto/gtk3/%s" % (filename,)
if not os.path.isfile(path):
path = "magneto/gtk3/%s" % (filename,)
self.filename = path
self.xml = Gtk.Builder()
self.xml.set_translation_domain("entropy")
self.xml.add_from_file(path)
self.window = self.get_widget(window_name)
def get_widget(self, widget):
return self.xml.get_object(widget)
class AppletNoticeWindow(GladeWindow):
def __init__(self, controller):
GladeWindow.__init__(self, "magneto.glade", "notice_window_2")
self.__controller = controller
self.window.connect('delete-event', self.on_close)
self.package_list = self.get_widget('update_clist')
self.package_list.append_column(
Gtk.TreeViewColumn(
_("Application"), Gtk.CellRendererText(), text=0))
self.package_list.append_column(
Gtk.TreeViewColumn(
_("Latest version"), Gtk.CellRendererText(), text=1))
self.package_list.get_selection().set_mode(Gtk.SelectionMode.NONE)
self.notebook = self.get_widget('notice_notebook')
self.critical_tab = None
self.critical_tab_contents = None
self.package_list_model = Gtk.ListStore(GObject.TYPE_STRING,
GObject.TYPE_STRING)
self.package_list.set_model(self.package_list_model)
self.xml.connect_signals (
{
"on_launch_pm_clicked": self.on_pm,
"on_close_clicked": self.on_close,
"on_close": self.on_close,
})
message_label = Gtk.Label()
message_label.set_line_wrap(True)
self.message_label = message_label
def hide(self):
self.window.hide()
def show(self):
self.window.show()
def on_pm(self, button):
self.__controller.launch_package_manager()
def on_close(self, *args):
self.__controller.trigger_notice_window()
return True
def __set_critical(self, text):
if not self.critical_tab_contents:
vb = Gtk.VBox()
vb.add(self.message_label)
tab_label = Gtk.Label(_("Critical Information"))
tab_label.show()
self.message_label.show()
vb.show()
self.critical_tab = self.notebook.prepend_page(vb, tab_label)
self.critical_tab_contents = vb
self.notebook.set_current_page(
self.notebook.page_num(self.critical_tab_contents))
self.message_label.set_markup(text)
else:
self.message_label.set_markup(text)
def __remove_critical(self):
if not self.critical_tab_contents:
return
self.notebook.remove_page(
self.notebook.page_num(self.critical_tab_contents))
def populate(self, pkg_data, critical_txt):
self.package_list_model.clear()
for name, avail in pkg_data:
self.package_list_model.append((name, avail,))
if critical_txt:
self.__set_critical(critical_txt)
else:
self.__remove_critical()
+208
View File
@@ -0,0 +1,208 @@
# -*- coding: utf-8 -*-
"""
@author: Fabio Erculiani <lxnay@sabayon.org>
@contact: lxnay@sabayon.org
@copyright: Fabio Erculiani
@license: GPL-2
B{Entropy Updates Notification Applet (Magneto) GTK3 application}
"""
# sys imports
import os
import sys
import time
import subprocess
# applet imports
from magneto.core import config
from magneto.core.interfaces import MagnetoCore
from magneto.gtk3.components import AppletNoticeWindow, AppletIconPixbuf
# Entropy imports
from entropy.i18n import _
import entropy.dep
from gi.repository import Gtk, GObject, GLib, Gdk, Notify
class Magneto(MagnetoCore):
def __init__(self):
from dbus.mainloop.glib import DBusGMainLoop
MagnetoCore.__init__(self, icon_loader_class = AppletIconPixbuf,
main_loop_class = DBusGMainLoop)
self.__setup_gtk_app()
def __setup_gtk_app(self):
self.menu = Gtk.Menu()
self.menu_items = {}
for i in self._menu_item_list:
if i is None:
self.menu.add(Gtk.SeparatorMenuItem())
else:
sid = None
myid = i[0]
if myid == "exit":
sid = "gtk-quit"
if sid:
w = Gtk.ImageMenuItem(stock_id = sid)
else:
w = Gtk.ImageMenuItem(i[1])
w.set_use_underline(True)
pix = self.get_menu_image(myid)
img = Gtk.Image()
img.set_from_pixbuf(pix)
w.set_image(img)
self.menu_items[myid] = w
w.connect('activate', i[3])
w.show()
self.menu.add(w)
self.menu.show_all()
self.status_icon = Gtk.StatusIcon.new_from_pixbuf(
self.icons.best_match("okay", 22))
self.status_icon.connect("popup-menu", self.applet_context_menu)
self.status_icon.connect("activate", self.applet_doubleclick)
def __do_first_check(self):
def _do_check():
self.send_check_updates_signal(startup_check = True)
return False
if self._dbus_service_available:
# after 10 seconds
GObject.timeout_add(10000, _do_check)
def startup(self):
self._dbus_service_available = self.setup_dbus()
if config.settings['APPLET_ENABLED'] and \
self._dbus_service_available:
self.enable_applet(do_check = False)
else:
self.disable_applet()
if not self._dbus_service_available:
GObject.timeout_add(30000, self.show_service_not_available)
else:
GObject.timeout_add(30000, self.show_service_available)
self.__do_first_check()
# Notice Window instance
self._notice_window = AppletNoticeWindow(self)
# enter main loop
GLib.threads_init()
Gdk.threads_enter()
Gtk.main()
Gdk.threads_leave()
def close_service(self):
MagnetoCore.close_service(self)
GObject.timeout_add(0, Gtk.main_quit)
def change_icon(self, image):
to_image = self.icons.best_match(image, self.applet_size)
self.status_icon.set_from_pixbuf(to_image)
def disable_applet(self, *args):
MagnetoCore.disable_applet(self)
self.menu_items['disable_applet'].hide()
self.menu_items['enable_applet'].show()
def enable_applet(self, w = None, do_check = True):
done = MagnetoCore.enable_applet(self, do_check = do_check)
if done:
self.menu_items['disable_applet'].show()
self.menu_items['enable_applet'].hide()
def applet_doubleclick(self, widget):
return MagnetoCore.applet_doubleclick(self)
def show_alert(self, title, text, urgency = None, force = False):
def do_show():
if ((title, text) == self.last_alert) and not force:
return False
Notify.init(_("System Updates"))
n = Notify.Notification.new(
title, text, "dialog-information")
if urgency == 'critical':
n.set_urgency(Notify.Urgency.CRITICAL)
elif urgency == 'low':
n.set_urgency(Notify.Urgency.LOW)
self.last_alert = (title, text)
try:
# this has been dropped from libnotify 0.7
n.attach_to_status_icon(self.status_icon)
except AttributeError:
pass
n.show()
return False
GObject.timeout_add(0, do_show)
def update_tooltip(self, tip):
self.tooltip_text = tip
self.status_icon.set_tooltip_markup(tip)
def applet_context_menu(self, icon, button, activate_time):
if button == 3:
self.menu.popup(None, None, None, None, 0, activate_time)
return
def hide_notice_window(self):
self.notice_window_shown = False
self._notice_window.hide()
def show_notice_window(self):
if self.notice_window_shown:
return
if not self.package_updates:
return
entropy_ver = None
packages = []
for atom in self.package_updates:
key = entropy.dep.dep_getkey(atom)
avail_rev = entropy.dep.dep_get_entropy_revision(atom)
avail_tag = entropy.dep.dep_gettag(atom)
my_pkg = entropy.dep.remove_entropy_revision(atom)
my_pkg = entropy.dep.remove_tag(my_pkg)
pkgcat, pkgname, pkgver, pkgrev = entropy.dep.catpkgsplit(
my_pkg)
ver = pkgver
if pkgrev != "r0":
ver += "-%s" % (pkgrev,)
if avail_tag:
ver += "#%s" % (avail_tag,)
if avail_rev:
ver += "~%s" % (avail_tag,)
if key == "sys-apps/entropy":
entropy_ver = ver
packages.append((key, ver,))
critical_txt = ''
if entropy_ver is not None:
critical_txt = "%s <b>sys-apps/entropy</b> %s, %s <b>%s</b>. %s." % (
_("Your system currently has an outdated version of"),
_("installed"),
_("the latest available version is"),
entropy_ver,
_("It is recommended that you upgrade to"
" the latest before updating any other packages")
)
self._notice_window.populate(packages, critical_txt)
self._notice_window.show()
self.notice_window_shown = True
+162
View File
@@ -0,0 +1,162 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.24"/>
<!-- interface-naming-policy toplevel-contextual -->
<object class="GtkDialog" id="notice_window_2">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Magneto Application Updates Notifier</property>
<property name="window_position">center</property>
<property name="default_width">600</property>
<property name="default_height">300</property>
<property name="type_hint">dialog</property>
<signal name="close" handler="on_close" swapped="no"/>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">8</property>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button9">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<signal name="clicked" handler="on_launch_pm_clicked" swapped="no"/>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<child>
<object class="GtkHBox" id="hbox4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<child>
<object class="GtkImage" id="image1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="stock">gtk-apply</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label8">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Load Package Manager</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button10">
<property name="label">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="use_stock">True</property>
<signal name="clicked" handler="on_close_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="GtkNotebook" id="notice_notebook">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="scrollable">True</property>
<child>
<object class="GtkVBox" id="vbox2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkScrolledWindow" id="checklist_window">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="update_clist">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="reorderable">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<child type="tab">
<object class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Available Updates</property>
<property name="justify">center</property>
</object>
<packing>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">button9</action-widget>
<action-widget response="0">button10</action-widget>
</action-widgets>
</object>
</interface>
+12 -4
View File
@@ -47,17 +47,25 @@ def _startup():
from magneto.kde.interfaces import Magneto
elif "--gtk" in sys.argv:
from magneto.gtk.interfaces import Magneto
elif "--gtk3" in sys.argv:
from magneto.gtk3.interfaces import Magneto
else:
if kde_env is not None:
# this is KDE!
try:
from magneto.kde.interfaces import Magneto
except (ImportError, RuntimeError,):
# try GTK
from magneto.gtk.interfaces import Magneto
# try GTK3, then GTK
try:
from magneto.gtk3.interfaces import Magneto
except ImportError:
from magneto.gtk.interfaces import Magneto
else:
# load GTK
from magneto.gtk.interfaces import Magneto
# load GTK3, fallback to GTK2
try:
from magneto.gtk3.interfaces import Magneto
except ImportError:
from magneto.gtk.interfaces import Magneto
import entropy.tools
magneto = Magneto()