web-dev-qa-db-fra.com

Comment créer une applet Budgie, montrant un menu?

Vous trouverez ci-dessous le code d’une applet perruche en python, que j’ai créé. L’applet se déroule normalement.

#!/usr/bin/env python3

import gi.repository
gi.require_version('Budgie', '1.0')
from gi.repository import Budgie, GObject, Gtk, Gdk

class myapplet(GObject.GObject, Budgie.Plugin):

   __gtype_= "myapplet"

def __int__(self):

    GObject.Object.__init__(self)

def do_get_panel_widget(self, uuid):

    return myappletApplet(uuid)

class myappletApplet(Budgie.Applet):

    button = None
    manager = None

def __init__(self, uuid):

    Budgie.Applet.__init__(self)

    #create a toggle button in panel
    self.button = Gtk.ToggleButton.new()
    self.button.set_relief(Gtk.ReliefStyle.NONE)
    self.button.set_active(False)
    self.button.set_tooltip_text("Apple Menu")
    box1 = Gtk.EventBox()
    box1.add(self.button)
    self.add(box1)

    img = Gtk.Image.new_from_icon_name("Apple", Gtk.IconSize.BUTTON)
    self.button.add(img)
    box1.show_all()
    self.show_all()

    #create a popover
    self.popover = Budgie.Popover.new(self.button)


    #create a box
    box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
    self.popover.add(box)

    #create separators
    separator1 = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
    box.pack_start(separator1, True, True, 0)

    separator2 = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
    box.pack_start(separator2, True, True, 0)

    separator3 = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
    box.pack_start(separator3, True, True, 0)

    separator4 = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
    box.pack_start(separator4, True, True, 0)

    separator5 = Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL)
    box.pack_start(separator5, True, True, 0)

    #events
    def event_press(box2, event_press):
        self.popover.hide()
        self.button.set_active(False)
        import subprocess
        subprocess.call(["hardinfo"])

    def event_press1(box3, event_press1):
        self.popover.hide()
        self.button.set_active(False)
        import subprocess
        subprocess.call(["gnome-control-center"])

    def event_press2(box4, event_press2):
        self.popover.hide()
        self.button.set_active(False)
        import subprocess
        subprocess.call(["gnome-software"])

    def event_press3(box5, event_press3):
        if self.pop.get_visible():
            self.pop.hide()
        else:
            self.pop.show_all()

    def event_press4(box6, event_press4):
        self.popover.hide()
        self.button.set_active(False)
        import subprocess
        subprocess.run("xkill")

    def event_press5(box7, event_press5):
        self.popover.hide()
        self.button.set_active(False)
        import subprocess
        subprocess.call(["systemctl", "suspend"])

    def event_press6(box8, event_press6):
        self.popover.hide()
        self.button.set_active(False)
        import subprocess
        subprocess.call(["gnome-session-quit", "--reboot"])

    def event_press7(box9, event_press7):
        self.popover.hide()
        self.button.set_active(False)
        import subprocess
        subprocess.call(["gnome-session-quit", "--power-off"])

    def event_press8(box10, event_press8):
        self.popover.hide()
        self.button.set_active(False)
        import subprocess
        subprocess.call(["gnome-session-quit"])


    #create popover items
    box2 = Gtk.EventBox()
    label1 = Gtk.Label("About This Pc")
    label1.set_size_request(250, 30)
    label1.set_xalign(0.1)
    #label1.set_use_markup(True)
    box2.connect("button-press-event", event_press)
    box2.add(label1)
    box.pack_start(box2, True, True, 0)
    box.reorder_child(box2, 0)

    box3 = Gtk.EventBox()
    label2 = Gtk.Label("System Settings...")
    label2.set_size_request(250, 25)
    label2.set_xalign(0.12)
    #label2.set_use_markup(True)
    box3.connect("button-press-event", event_press1)
    box3.add(label2)
    box.pack_start(box3, True, True, 0)
    box.reorder_child(box3, 2)

    box4 = Gtk.EventBox()
    label3 = Gtk.Label("Software...")
    label3.set_size_request(250, 25)
    label3.set_xalign(0.09)
    label3.set_justify(Gtk.Justification.LEFT)
    box4.connect("button-press-event", event_press2)
    box4.add(label3)
    box.pack_start(box4, True, True, 0)
    box.reorder_child(box4, 3)

    box5 = Gtk.EventBox()
    label4 = Gtk.Label("Recent Items")
    label4.set_size_request(250, 30)
    label4.set_xalign(0.1)
    box5.connect("button-press-event", event_press3)
    box5.add(label4)
    box.pack_start(box5, True, True, 0)
    box.reorder_child(box5, 5)

    self.pop = Budgie.Popover.new(box5)
    self.pop.set_position(Gtk.PositionType.RIGHT)
    boxy = Gtk.Box()
    boxy = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
    boxy.set_size_request(250, 400)
    self.pop.add(boxy)
    recentchooserwidget = Gtk.RecentChooserWidget()
    boxy.add(recentchooserwidget)

    box6 = Gtk.EventBox()
    label5 = Gtk.Label("Force Quit")
    label5.set_size_request(250, 30)
    label5.set_xalign(0.09)
    box6.connect("button-press-event", event_press4)
    box6.add(label5)
    box.pack_start(box6, True, True, 0)
    box.reorder_child(box6, 7)

    box7 = Gtk.EventBox()
    label6 = Gtk.Label("Sleep")
    label6.set_size_request(250, 20)
    label6.set_xalign(0.08)
    box7.connect("button-press-event", event_press5)
    box7.add(label6)
    box.pack_start(box7, True, True, 0)
    box.reorder_child(box7, 9)

    box8 = Gtk.EventBox()
    label7 = Gtk.Label("Restart")
    label7.set_size_request(250, 20)
    label7.set_xalign(0.08)
    box8.connect("button-press-event", event_press6)
    box8.add(label7)
    box.pack_start(box8, True, True, 0)
    box.reorder_child(box8, 10)

    box9 = Gtk.EventBox()
    label8 = Gtk.Label("ShutDown")
    label8.set_size_request(250, 20)
    label8.set_xalign(0.09)
    box9.connect("button-press-event", event_press7)
    box9.add(label8)
    box.pack_start(box9, True, True, 0)
    box.reorder_child(box9, 11)

    box10 = Gtk.EventBox()
    label9 = Gtk.Label("LogOut\t\t\tCtrAltDel")
    label9.set_size_request(250, 30)
    label9.set_xalign(0.23)
    box10.connect("button-press-event", event_press8)
    box10.add(label9)
    box.pack_start(box10, True, True, 0)

    #button signal
    self.button.connect("toggled", self.on_button_toggled, self.popover)


def on_button_toggled(self, button, popover):

    if self.button.get_active():

        self.popover.show_all()


    else:

        self.popover.hide()
        self.pop.hide()

Cette applet ouvre un menu contextuel contenant des éléments pouvant être sélectionnés et exécutant chacun une commande distincte. Le menu contextuel s'ouvre et se ferme en appuyant sur un bouton à bascule. J'ai utilisé le constructeur Budgie.popover.new () pour cela. Il y a quelques problèmes que je veux affiner.

Premier numéro. Je veux que le popover se ferme automatiquement lorsque je clique quelque part en dehors du popover .Comment puis-je atteindre cet objectif? Maintenant, je dois appuyer à nouveau sur le bouton bascule.

Deuxième numéro. Lorsque je sélectionne, disons le premier élément en popover (élément "À propos de ce PC"), le bouton se fige en position poussée et je ne peux plus l'activer (le bouton Google). Je dois d'abord fermer l'application qui a été ouverte, puis Appuyez à nouveau sur le bouton bascule. Cela se produit pour les éléments "À propos de ce PC", "Paramètres système", "Redémarrage" et "Arrêter". Bizarrement, cela ne se produit pas pour les éléments "Logiciels", "Éléments récents" et "LogOut".

Troisième numéro. Lorsque je sélectionne l'élément "Éléments récents", un nouveau menu déroulant contenant des éléments récents se trouve juste en dessous de la boîte à événements (box5). Ce que je veux, c'est ouvrir ce nouveau fichier popover (self.pop) à droite du champ de l'événement.

Toute aide serait appréciée.

Merci d'avance.

2
cgiannakisis

Un exemple de base

enter image description here

Votre code semble surcomplexer à bien des égards. Quelques choses évidentes:

  • Vous pouvez simplement utiliser un Gtk.Menu, vous ne créez pas de menu avec une série de boutons.
  • N'utilisez pas un bouton à bascule pour appeler une applet, vous avez besoin d'un bouton normal. Si vous utilisez un EventBox, vous n'avez pas du tout besoin de bouton.
  • Il suffit d'importer subprocess une seule fois, en tête de l'applet

En bref, un exemple

Il serait peut-être préférable de simplement montrer un exemple de la façon dont cela peut être fait.

#!/usr/bin/env python3
import subprocess
import gi.repository
gi.require_version('Budgie', '1.0')
from gi.repository import Budgie, GObject, Gtk

class SomeApp(GObject.GObject, Budgie.Plugin):

    __gtype_= "SomeApp"

    def __int__(self):
        GObject.Object.__init__(self)

    def do_get_panel_widget(self, uuid):
        return SomeAppApplet(uuid)


class SomeAppApplet(Budgie.Applet):

    manager = None

    def __init__(self, uuid):

        Budgie.Applet.__init__(self)

        self.box = Gtk.EventBox()
        self.add(self.box)
        img = Gtk.Image.new_from_icon_name("firefox", Gtk.IconSize.MENU)
        self.box.add(img)
        self.menu = Gtk.Menu()
        self.create_menu()
        self.box.show_all()
        self.show_all()

    def run_command(self, menuitem):
        print(menuitem)
        subprocess.Popen(["gedit"])

    def create_menu(self):
        item1 = Gtk.MenuItem('Some item')
        item1.connect("activate", self.run_command)        
        item2 = Gtk.MenuItem('Another item')
        item3 = Gtk.MenuItem('I am on a roll, yet another item')
        for item in [item1, item2, item3]:
            self.menu.append(item)
        self.menu.show_all()
        self.box.connect("button-press-event", self.popup_menu)

    def popup_menu(self, *args):
        self.menu.popup(
            None, None, None, None, 0, Gtk.get_current_event_time()
        )

Et le fichier .plugin (SomeApp.plugin:

[Plugin]
Loader=python3
Module=someapp
Name=Some App
Description=Obviously an App
Authors=James Bond
Copyright=Copyright © 2018 007
Website=some_website
Icon=firefox

Autres astuces

Lors de la création du menu, vous pouvez ajouter les menus à une liste, combinés aux commandes que vous souhaitez qu'ils exécutent. De cette façon, vous n'avez pas besoin d'utiliser des fonctions distinctes pour chaque commande, mais simplement d'exécuter la commande en tant qu'argument pour exécuter run_command().

2
Jacob Vlijm