web-dev-qa-db-fra.com

Comment puis-je attribuer à un script sa propre icône dans le lanceur Unity?

Avec Ubuntu 16.04, si vous créez un programme de lancement (fichier de bureau dans ~/.local/share/applications) avec une icône personnalisée pour une application de terminal (donc avec Terminal=true), il générera une nouvelle icône de terminal standard. et votre icône personnalisée s’éteindra en quelques secondes.

En 14.04, cela a fonctionné comme prévu. (cela ne créerait pas une nouvelle icône de terminal standard).

Une idée de ce qu'il faut faire pour changer ce comportement? J'ai quelques applications de terminal que je veux lancer à partir de l'unité et le nouveau comportement est problématique (je perds la trace de ce qui est le cas puisqu'elles se retrouvent toutes avec l'icône du terminal standard) ...

5
Se6

Pourquoi ça ne marche pas comme toi

Comme mentionné dans le commentaire, une application ne peut en principe être représentée que par une icône dans le lanceur à la fois . Cela a toujours été le cas.

Vous faites probablement allusion au fait que Unity est devenu "plus intelligent" pour déterminer lequel des fichiers .desktop est le plus représentatif de la fenêtre de l'application. Par conséquent, votre script, exécutant une fenêtre de terminal, sera représenté par l'icône gnome-terminal:

enter image description here

Par conséquent, ce qui fonctionnait auparavant dans votre configuration, la création d'un lanceur, le démarrage de votre script, ne trompe plus Unity et sélectionne le lanceur existant gnome-terminal pour représenter votre fenêtre.

La mauvaise solution

... consiste à annuler le choix de Unity en ajoutant une ligne à votre programme de lancement (pour 16.04):

StartupWMClass=gnome-terminal-server

enter image description here

... mais alors all == les fenêtres de terminal, qu'elles exécutent votre script ou non, sont regroupées sous cette icône.

De plus, en général, avoir plusieurs fichiers .desktop et appeler la même application dans leur commande principale est une pratique douteuse et malpropre.


MODIFIER

Comment avoir une (des) icône (s) distincte (s) pour un script en cours d'exécution

Cela prend un peu de ruse et de tromperie, mais il est il est possible d'avoir une icône distincte pour plusieurs scripts, s'exécutant dans différentes fenêtres de terminaux.

Comment ça marche en pratique

  • Supposons que vous ayez un script, somscript.sh, que vous souhaitez exécuter dans une fenêtre de terminal, affichant son icône dédiée dans le lanceur Unity pendant son exécution.
  • Exécutez la commande:

    showicon somescript.sh someicon.png
    

    et le script s'exécutera dans une nouvelle fenêtre gnome-terminal récemment ouverte, affichant l'icône: someicon.png

  • Si la fenêtre est fermée, l’icône est à nouveau supprimée du lanceur.

Un exemple

  • Je veux un script, /home/jacob/Bureaublad/script.sh, lancé dans le lanceur Unity avec l’icône: /home/jacob/Thema/icon/ubu.png. Exécution de la commande:

    showicon '/home/jacob/Bureaublad/script.sh' '/home/jacob/Thema/icon/ubu.png'
    

    fera cela:

    enter image description here

    Ajoutons maintenant un autre:

    showicon '/home/jacob/Bureaublad/script2.sh' '/home/jacob/Thema/icon/banaan.png'
    

    Le résultat:

    enter image description here

    Une fois les fenêtres fermées, les icônes sont à nouveau supprimées.

Comment configurer

  1. Le script a besoin de wmctrl

    Sudo apt-get install wmctrl
    
  2. Créez, s'il n'existe pas encore, le répertoire ~/bin

  3. Copiez le script ci-dessous dans un fichier vide, enregistrez-le sous le nom showicon (sans extension) dans ~/bin et le rendre exécutable
  4. Déconnectez-vous et reconnectez-vous, votre configuration devrait fonctionner. Testez-le avec la commande

    showicon </path/to/script.sh> </path/to/icon.png>
    

    avoir script.sh exécuté dans un terminal, affichant icon.png dans le lanceur Unity.

Le scénario

#!/usr/bin/env python3
import subprocess
import os
import sys
import time

terminal = "gnome-terminal"
key = "com.canonical.Unity.Launcher"
script = sys.argv[1]
icon = sys.argv[2]

curr = os.path.dirname(os.path.realpath(__file__))
scriptname = script.split("/")[-1]

def get(command):
    try:
        return subprocess.check_output(command).decode("utf-8")
    except subprocess.CalledProcessError:
        pass

# --- edit Unity launcher section

def current_launcher():
    return eval(get(["gsettings", "get", key, "favorites"]))

def set_launcher(desktopfile, arg):
    curr_launcher = current_launcher()
    last = [i for i, x in enumerate(curr_launcher) if x.startswith("application://")][-1]
    new_icon = "application://"+desktopfile
    if arg == "a":
        if not new_icon in curr_launcher:
            curr_launcher.insert(0, new_icon)
            subprocess.Popen(["gsettings", "set", key,"favorites",str(curr_launcher)])
    Elif arg == "r":
        curr_launcher.remove(new_icon)
        subprocess.Popen(["gsettings", "set", key,"favorites",str(curr_launcher)])

# --- end section

def create_launcher(w, scriptname, icon):
    launcher = ["[Desktop Entry]", "Type=Application",
            "Exec=wmctrl -ia "+w, "Name="+scriptname, "Icon="+icon,
            "StartupNotify=False"]
    with open(l_name, "wt") as newlauncher:
        for l in launcher:
            newlauncher.write(l+"\n")

def getname():
    # create unique launcher name
    n = 1
    while True:
        nm = os.path.join(curr, "scriptlauncher_"+str(n)+".desktop")
        if os.path.exists(nm):
            n += 1
        else:
            break
    return nm    

wlist1 = [l.split()[0] for l in get(["wmctrl", "-l"]).splitlines()]
subprocess.Popen(["gnome-terminal", "-e", script])

while True:
    time.sleep(1)
    wdata = get(["wmctrl", "-l"]).splitlines()
    if wdata:
        try:
            wlist2 = [l.split()[0] for l in wdata]
            w = [w for w in wlist2 if not w in wlist1][0]
        except IndexError:
            pass
        else:
            # check if the new window belongs to the terminal
            if terminal in get(["xprop", "-id", w]):
                # create launcher
                l_name = getname()
                create_launcher(w, scriptname, icon)
                set_launcher(l_name, "a")
                break
    wlist1 = wlist2

while True:
    time.sleep(2)
    wdata = get(["wmctrl", "-l"])
    if wdata:
        if not w in wdata:
            os.remove(l_name)
            set_launcher(l_name, "r")
            break 

Remarque

  • Que fait l'icône?

    • Il représente la fenêtre gnome-terminal, exécutant votre script.
    • En cliquant dessus, la fenêtre s’ouvre, comme d’habitude. La commande à faire est automatiquement ajoutée au lanceur temporaire:

      wmctrl -ia <window_id>
      
  • Ce qu'il fait not :

    • Le seul inconvénient de cette solution est que l'icône n'affiche pas la flèche habituelle à gauche pour les applications en cours d'exécution, car la représentation est indirecte.

Explication

Sans trop entrer dans les détails:

  • Le script est un wrapper. Si vous lancez votre script via showicon, une instance de showicon exécute votre script dans une fenêtre gnome-terminal, similaire à Terminal=true.
  • Par la suite, showicon attend que la nouvelle fenêtre gnome-terminal apparaisse et lit son identifiant de fenêtre.
  • Un programme de lancement temporaire est ensuite créé, à l'aide de l'ID de fenêtre pour créer la commande permettant d'afficher la fenêtre dans sa ligne Exec=. L'icône que vous définissez en tant qu'argument dans la commande pour exécuter showicon est automatiquement définie en tant qu'icône de ce programme de lancement temporaire (défini dans la ligne Icon=).

    Exemple d'un tel lanceur (temporaire) créé automatiquement:

    [Desktop Entry]
    Type=Application
    Exec=wmctrl -ia 0x04400b7f
    Name=script2.sh
    Icon=/home/jacob/Thema/icon/ubu.png
    StartupNotify=False
    
  • En utilisant la même procédure que dans cette réponse , le programme de lancement temporaire est ajouté au programme de lancement Unity, en première position, pour représenter votre script en cours d'exécution.

  • Entre-temps, showicon vérifie si la fenêtre existe. Sinon, le programme de lancement temporaire est supprimé du programme de lancement d'Unity et supprimé de l'existence du tout , et l'instance showicon est terminée.
5
Jacob Vlijm

Un autre ne répond pas mais solution.

J'utilise des listes rapides pour créer des lanceurs pour les sessions de terminal les plus utilisées. Je crée ensuite des profils pour chacun dans gnome-terminal afin de changer des couleurs, ce qui permet de savoir facilement quel serveur vous utilisez.

Vous pouvez le faire en modifiant votre fichier gnome-terminal.desktop dans ~/.local/share/applications/gnome-terminal.desktop.

le mien ressemble à ça

[Desktop Entry]
Name=Terminal
Comment=Use the command line
Keywords=Shell;Prompt;command;commandline;
TryExec=gnome-terminal
Exec=gnome-terminal
Icon=utilities-terminal
Type=Application
X-GNOME-DocPath=gnome-terminal/index.html
X-GNOME-Bugzilla-Bugzilla=GNOME
X-GNOME-Bugzilla-Product=gnome-terminal
X-GNOME-Bugzilla-Component=BugBuddyBugs
X-GNOME-Bugzilla-Version=3.16.2
Categories=GNOME;GTK;System;TerminalEmulator;
StartupNotify=true
X-GNOME-SingleWindow=false
OnlyShowIn=GNOME;Unity;
Actions=New;Item1;Item2
X-Ubuntu-Gettext-Domain=gnome-terminal

[Desktop Action New]
Name=New Terminal
Exec=gnome-terminal
OnlyShowIn=Unity

[Desktop Action Item1]
Name=SSH Shell type 1
Exec=gnome-terminal -e 'ssh item1' --profile 'Item1'
OnlyShowIn=Unity


[Desktop Action Item2]
Name=SSH Shell type 2
Exec=gnome-terminal -e 'ssh item2' --profile 'Item2'
OnlyShowIn=Unity

J'ai aussi écrit un script il y a quelque temps pour automatiser l'ajout d'entrées à votre liste rapide à partir du fichier hôtes afin que toute commande ssh obtienne une entrée dans la liste rapide. Je l'ai écrite quand les listes rapides n'étaient pas mises à jour automatiquement et j'ai abandonné parce que cela rendait les choses difficiles, elles sont maintenant instantanées et peuvent être exécutées via un travail cron.

http://blog.amias.net/articles/114

1
Amias

Une solution ponctuelle consisterait à écrire un petit programme exécutable exécutant votre script et à affecter une icône de lanceur unique à l'exécutable.

0
Michael Clayton