File size: 8,400 Bytes
2695555
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
"""Atalho global: o openTARS cadastra "opentars-gui --rapido" como atalho
personalizado do ambiente (GNOME/Zorin, Cinnamon, MATE, XFCE), sem pisar
num atalho que já existe. Aqui o gsettings/xfconf são simulados."""

import os
import re
import sys

sys.path.insert(0, os.path.dirname(__file__))
import _util  # noqa: E402,F401  (idioma pt_BR e config temporária)

import tars_atalho as at  # noqa: E402
import tars_i18n as i18n  # noqa: E402

# ------------------------------------------------------------------
# Combinações
# ------------------------------------------------------------------
assert at.normalizar_combinacao("Ctrl+Alt+Space") == "<Primary><Alt>space"
assert at.normalizar_combinacao("<Control><Alt>space") == "<Primary><Alt>space"
assert at.normalizar_combinacao("super+t") == "<Super>t"
assert at.normalizar_combinacao("ctrl+alt+espaço") == "<Primary><Alt>space"
assert at.normalizar_combinacao("alt+F2") == "<Alt>F2"
assert at.normalizar_combinacao("banana") is None and at.normalizar_combinacao("ctrl+") is None
assert at.legivel("<Primary><Alt>space") == "Ctrl+Alt+Espaço"
i18n.definir_idioma("en", salvar=False)
assert at.legivel("<Primary><Alt>space") == "Ctrl+Alt+Space"
i18n.definir_idioma("pt_BR", salvar=False)
print("OK: 'Ctrl+Alt+Space', '<Control><Alt>space', 'ctrl+alt+espaço' -> <Primary><Alt>space")


# ------------------------------------------------------------------
# gsettings / xfconf de mentira
# ------------------------------------------------------------------
class Sistema:
    def __init__(self, esquemas, recursivos=None):
        self.esquemas = esquemas
        self.valores = {}
        self.recursivos = recursivos or {}
        self.xfconf = {}

    def padrao(self, esquema, chave):
        if chave in ("custom-keybindings", "custom-list") or (chave == "binding" and "cinnamon" in esquema):
            return "@as []"
        return "''"

    def rodar(self, *cmd):
        if cmd[0] == "gsettings":
            acao = cmd[1]
            if acao == "list-schemas":
                return 0, "\n".join(self.esquemas)
            if acao == "get":
                return 0, self.valores.get((cmd[2], cmd[3]), self.padrao(cmd[2], cmd[3]))
            if acao == "set":
                self.valores[(cmd[2], cmd[3])] = cmd[4]
                return 0, ""
            if acao == "reset":
                self.valores.pop((cmd[2], cmd[3]), None)
                return 0, ""
            if acao == "reset-recursively":
                for k in [k for k in self.valores if k[0] == cmd[2]]:
                    del self.valores[k]
                return 0, ""
            if acao == "list-recursively":
                linhas = self.recursivos.get(cmd[2])
                return (0, linhas) if linhas is not None else (1, "")
        if cmd[0] == "xfconf-query":
            args = list(cmd[3:])
            if args[:2] == ["-l", "-v"]:
                return 0, "\n".join(f"{k}  {v}" for k, v in self.xfconf.items())
            caminho = args[1]
            if "-s" in args:
                self.xfconf[caminho] = args[args.index("-s") + 1]
                return 0, ""
            if "-r" in args:
                self.xfconf.pop(caminho, None)
                return 0, ""
            return (0, self.xfconf[caminho]) if caminho in self.xfconf else (1, "")
        return 1, ""


def lista(texto):
    return re.findall(r"'([^']*)'", texto)


at.shutil.which = lambda nome: f"/usr/bin/{nome}"

# ------------------------------------------------------------------
# GNOME / Zorin
# ------------------------------------------------------------------
os.environ["XDG_CURRENT_DESKTOP"] = "zorin:GNOME"
assert at.ambiente() == "gnome"
gnome = Sistema(
    [at.GNOME_SCHEMA, "org.gnome.desktop.wm.keybindings"],
    {"org.gnome.desktop.wm.keybindings":
         "org.gnome.desktop.wm.keybindings switch-input-source ['<Super>space', 'XF86Keyboard']\n"
         "org.gnome.desktop.wm.keybindings activate-window-menu ['<Alt>space']"},
)
# o usuário já tem um atalho dele
gnome.valores[(at.GNOME_SCHEMA, "custom-keybindings")] = f"['{at.GNOME_CAMINHO}custom0/']"
seu = f"{at.GNOME_SCHEMA}.custom-keybinding:{at.GNOME_CAMINHO}custom0/"
gnome.valores[(seu, "command")] = "'flameshot gui'"
gnome.valores[(seu, "binding")] = "'Print'"
at._rodar = gnome.rodar

ok, mensagem = at.registrar()
assert ok, mensagem
nosso = f"{at.GNOME_SCHEMA}.custom-keybinding:{at.GNOME_CAMINHO}custom1/"
assert lista(gnome.valores[(at.GNOME_SCHEMA, "custom-keybindings")]) == [f"{at.GNOME_CAMINHO}custom0/", f"{at.GNOME_CAMINHO}custom1/"]
assert "--rapido" in gnome.valores[(nosso, "command")] and gnome.valores[(nosso, "binding")] == "'<Primary><Alt>space'"
assert gnome.valores[(seu, "command")] == "'flameshot gui'", "o atalho do usuário continua lá"
assert "Ctrl+Alt+Espaço" in mensagem and at.estado()["registrado"]
print("OK: GNOME/Zorin: cadastra Ctrl+Alt+Espaço num atalho novo, sem mexer nos do usuário")

ok, mensagem = at.registrar("super+space")
assert not ok and "switch-input-source" in mensagem, mensagem
print("OK: Super+Espaço é recusado: no GNOME já troca o layout do teclado")

gnome.valores[(seu, "binding")] = "'<Primary><Alt>t'"
ok, mensagem = at.registrar("ctrl+alt+t")
assert not ok and "flameshot" in mensagem, mensagem
ok, _ = at.registrar("ctrl+alt+o")
assert ok and gnome.valores[(nosso, "binding")] == "'<Primary><Alt>o'"
assert len(lista(gnome.valores[(at.GNOME_SCHEMA, "custom-keybindings")])) == 2, "trocar não duplica"
print("OK: combinação de outro atalho é recusada; trocar a nossa não cria outra entrada")

ok, _ = at.remover()
assert ok and lista(gnome.valores[(at.GNOME_SCHEMA, "custom-keybindings")]) == [f"{at.GNOME_CAMINHO}custom0/"]
assert (nosso, "command") not in gnome.valores and at.garantir_registrado() is None
print("OK: --atalho off remove só o nosso, e a janela não cadastra de novo sozinha")

# ------------------------------------------------------------------
# Primeira abertura da janela: cadastra uma vez só
# ------------------------------------------------------------------
os.environ.pop("TARS_SEM_ATALHO", None)
i18n.salvar_config(atalho_tentado=False, atalho_desligado=False, atalho=None)
gnome.valores = {}
assert at.garantir_registrado()[0] is True
assert at.garantir_registrado() is None
print("OK: na primeira abertura a janela cadastra o atalho; depois não tenta de novo")

# ------------------------------------------------------------------
# Cinnamon, XFCE e KDE
# ------------------------------------------------------------------
os.environ["XDG_CURRENT_DESKTOP"] = "X-Cinnamon"
cinnamon = Sistema([at.CINNAMON_SCHEMA])
at._rodar = cinnamon.rodar
ok, _ = at.registrar("ctrl+alt+space")
nosso = f"{at.CINNAMON_SCHEMA}.custom-keybinding:{at.CINNAMON_CAMINHO}custom0/"
assert ok and lista(cinnamon.valores[(at.CINNAMON_SCHEMA, "custom-list")]) == ["custom0"]
assert lista(cinnamon.valores[(nosso, "binding")]) == ["<Primary><Alt>space"]
print("OK: Cinnamon (Linux Mint)")

os.environ["XDG_CURRENT_DESKTOP"] = "XFCE"
xfce = Sistema([])
at._rodar = xfce.rodar
xfce.xfconf["/commands/custom/<Primary><Alt>t"] = "xfce4-terminal"
ok, mensagem = at.registrar("ctrl+alt+t")
assert not ok and "xfce4-terminal" in mensagem
ok, _ = at.registrar("ctrl+alt+space")
assert ok and "--rapido" in xfce.xfconf["/commands/custom/<Primary><Alt>space"]
at.remover()
assert "/commands/custom/<Primary><Alt>space" not in xfce.xfconf and "/commands/custom/<Primary><Alt>t" in xfce.xfconf
print("OK: XFCE (respeita o Ctrl+Alt+T do terminal)")

os.environ["XDG_CURRENT_DESKTOP"] = "KDE"
ok, mensagem = at.registrar()
assert not ok and "opentars-gui --rapido" in mensagem and "KDE" in mensagem
print("OK: KDE e outros: explica o comando pra cadastrar à mão")

# 5.2: o atalho das ações de texto convive com o da barra rápida (cada um reconhece só o seu comando)
assert at._eh_nosso("/usr/bin/opentars-gui --acoes", at.ACOES_MARCA) and not at._eh_nosso("/usr/bin/opentars-gui --acoes")
assert at._eh_nosso("/usr/bin/opentars-gui --rapido") and not at._eh_nosso("/usr/bin/opentars-gui --rapido", at.ACOES_MARCA)
assert at.comando_barra_rapida(at.ACOES_MARCA).endswith(" --acoes")
ok, mensagem = at.registrar_acoes()
assert not ok and "opentars-gui --acoes" in mensagem, mensagem
print("OK: atalho das ações de texto separado do da barra rápida; fora do GNOME, explica o comando")

print("\nTUDO OK.")