bash-script-maker 1.1.0__py3-none-any.whl → 1.4.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- assets.py +27 -0
- {bash_script_maker-1.1.0.dist-info → bash_script_maker-1.4.2.dist-info}/METADATA +74 -10
- bash_script_maker-1.4.2.dist-info/RECORD +11 -0
- {bash_script_maker-1.1.0.dist-info → bash_script_maker-1.4.2.dist-info}/WHEEL +1 -1
- {bash_script_maker-1.1.0.dist-info → bash_script_maker-1.4.2.dist-info}/entry_points.txt +3 -0
- {bash_script_maker-1.1.0.dist-info → bash_script_maker-1.4.2.dist-info}/top_level.txt +3 -0
- bash_script_maker.py +5 -0
- custom_dialogs.py +270 -0
- localization.py +44 -0
- bash_script_maker-1.1.0.dist-info/RECORD +0 -8
- {bash_script_maker-1.1.0.dist-info/licenses → bash_script_maker-1.4.2.dist-info}/LICENSE +0 -0
assets.py
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
"""
|
4
|
+
Diese Datei enthält Base64-kodierte Assets (Bilder, Icons) für die Anwendung,
|
5
|
+
um zu vermeiden, dass lose Bilddateien mitgeliefert werden müssen.
|
6
|
+
"""
|
7
|
+
|
8
|
+
# Logos für die Support-Buttons (helle Varianten für dunkle Themes)
|
9
|
+
|
10
|
+
github_logo_b64 = """
|
11
|
+
R0lGODlhEAAQALMAAFpaXHBwcCAgIOPj47e3t/f395mZmWZmZlZWVuzs7GhoaP///wAAAAAAAAAA
|
12
|
+
ACH5BAEAAAAALAAAAAAQABAAAAQ98MkZpp7kQBCm1sU24uFUD4YDAM5S2bY59yv8LwQfDAoH4sEj
|
13
|
+
czgecwYDEBYAAYYyS4EAzGLTAnNEqsgpADs=
|
14
|
+
"""
|
15
|
+
|
16
|
+
patreon_logo_b64 = """
|
17
|
+
R0lGODlhEAAQAMQAAOr5+f/i4P/e3f/Y1//v7//h3//7+/+8vP/Rz//29/+gn//Mxf/fyf/l4v/q
|
18
|
+
6P/t7P/5+f/j3//9/f/f2f/c2P/Wyv/a1f/w7//U0P/g3P/Izf/Lw//6+v/UxCH5BAEAAB8ALAAA
|
19
|
+
AAAQABAAAAVW4CeOXumZM82smZ3f95k2WInaqe7t/x3I9sJDAxLplBAAOAbA0MIMB8dAsDgcA+N5
|
20
|
+
8ADBKxkA8C2SBAFAb81y5Zl2S5lMBwHw+z4/I5sCAgA7
|
21
|
+
"""
|
22
|
+
|
23
|
+
kofi_logo_b64 = """
|
24
|
+
R0lGODlhEAAQALMAAOnp6e/v7/n5+ff39/Hx8fLy8v39/erq6vv7+/7+/vj4+P///+fn5/Pz8wAA
|
25
|
+
ACH5BAEAAAAALAAAAAAQABAAAAQ58MkZpp7kQCENm433dmfwD0YDAM5S2bb55Cr2LwQfDAoH4sEj
|
26
|
+
czgecwYDEBYAAYYyS4EAjGLTAnNEqsgpADs=
|
27
|
+
"""
|
@@ -1,12 +1,12 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.1
|
2
2
|
Name: bash-script-maker
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.4.2
|
4
4
|
Summary: Ein GUI-Programm zur Erstellung von Bash-Scripts mit visueller Unterstützung
|
5
5
|
Home-page: https://github.com/securebitsorg/bash-script-maker
|
6
|
-
Author:
|
6
|
+
Author: Marcel Dellmann
|
7
7
|
Author-email: Marcel Dellmann <support@secure-bits.org>
|
8
8
|
Maintainer-email: Marcel Dellmann <support@secure-bits.org>
|
9
|
-
License
|
9
|
+
License: MIT
|
10
10
|
Project-URL: Homepage, https://github.com/securebitsorg/bash-script-maker
|
11
11
|
Project-URL: Documentation, https://github.com/securebitsorg/bash-script-maker#readme
|
12
12
|
Project-URL: Repository, https://github.com/securebitsorg/bash-script-maker
|
@@ -29,6 +29,8 @@ Classifier: Topic :: Software Development :: Code Generators
|
|
29
29
|
Requires-Python: >=3.8
|
30
30
|
Description-Content-Type: text/markdown
|
31
31
|
License-File: LICENSE
|
32
|
+
Requires-Dist: ttkbootstrap>=1.10.1
|
33
|
+
Requires-Dist: pygments>=2.15.1
|
32
34
|
Provides-Extra: dev
|
33
35
|
Requires-Dist: pytest>=6.0.0; extra == "dev"
|
34
36
|
Requires-Dist: pytest-cov>=2.10.0; extra == "dev"
|
@@ -38,10 +40,7 @@ Requires-Dist: mypy>=0.800; extra == "dev"
|
|
38
40
|
Requires-Dist: tox>=3.20.0; extra == "dev"
|
39
41
|
Requires-Dist: twine>=3.0.0; extra == "dev"
|
40
42
|
Requires-Dist: build>=0.7.0; extra == "dev"
|
41
|
-
|
42
|
-
Dynamic: home-page
|
43
|
-
Dynamic: license-file
|
44
|
-
Dynamic: requires-python
|
43
|
+
Requires-Dist: bandit>=1.7.0; extra == "dev"
|
45
44
|
|
46
45
|
# Bash-Script-Maker
|
47
46
|
|
@@ -109,7 +108,34 @@ Ein benutzerfreundliches GUI-Programm zur Erstellung von Bash-Scripts mit visuel
|
|
109
108
|
- Zenity (für Dialog-Funktionen)
|
110
109
|
- Linux-Distribution mit apt, dnf, pacman oder ähnlichem Paketmanager
|
111
110
|
|
112
|
-
###
|
111
|
+
### Flatpak-Installation (Empfohlen)
|
112
|
+
|
113
|
+
**Flatpak ist die modernste und sicherste Installationsmethode:**
|
114
|
+
|
115
|
+
```bash
|
116
|
+
# Flatpak installieren (falls noch nicht vorhanden)
|
117
|
+
sudo dnf install flatpak # Fedora/RHEL
|
118
|
+
sudo apt install flatpak # Ubuntu/Debian
|
119
|
+
sudo pacman -S flatpak # Arch Linux
|
120
|
+
|
121
|
+
# Flathub-Repository hinzufügen
|
122
|
+
flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
123
|
+
|
124
|
+
# App installieren (wenn verfügbar)
|
125
|
+
flatpak install flathub org.securebits.bashscriptmaker
|
126
|
+
|
127
|
+
# App starten
|
128
|
+
flatpak run org.securebits.bashscriptmaker
|
129
|
+
```
|
130
|
+
|
131
|
+
**Vorteile von Flatpak:**
|
132
|
+
- ✅ Vollständig sandboxed und sicher
|
133
|
+
- ✅ Automatische Updates
|
134
|
+
- ✅ Keine System-Abhängigkeiten
|
135
|
+
- ✅ Funktioniert auf allen Linux-Distributionen
|
136
|
+
- ✅ Desktop-Integration inklusive
|
137
|
+
|
138
|
+
### Automatische Installation mit Desktop-Integration
|
113
139
|
|
114
140
|
**Empfohlene Methode (automatische Erkennung):**
|
115
141
|
```bash
|
@@ -118,6 +144,8 @@ cd bash-script-maker
|
|
118
144
|
./install.sh
|
119
145
|
```
|
120
146
|
|
147
|
+
Das Script erkennt automatisch Ihren Paketmanager, installiert alle notwendigen Abhängigkeiten und richtet die Desktop-Integration ein.
|
148
|
+
|
121
149
|
**Spezifisch für Distributionen:**
|
122
150
|
|
123
151
|
Für Ubuntu/Debian-basierte Systeme:
|
@@ -130,6 +158,24 @@ Für Fedora/RHEL/CentOS-basierte Systeme:
|
|
130
158
|
./install_dnf.sh
|
131
159
|
```
|
132
160
|
|
161
|
+
### Flatpak-Paket selbst erstellen
|
162
|
+
|
163
|
+
```bash
|
164
|
+
# Flatpak-Paket lokal erstellen
|
165
|
+
./build_flatpak.sh
|
166
|
+
|
167
|
+
# Erstelltes Paket installieren
|
168
|
+
flatpak install build/flatpak/bash-script-maker.flatpak
|
169
|
+
```
|
170
|
+
|
171
|
+
### Nur Desktop-Integration installieren
|
172
|
+
|
173
|
+
Falls Sie die App bereits installiert haben und nur die Desktop-Integration hinzufügen möchten:
|
174
|
+
|
175
|
+
```bash
|
176
|
+
./install_desktop_integration.sh
|
177
|
+
```
|
178
|
+
|
133
179
|
### Manuelle Installation
|
134
180
|
|
135
181
|
Wenn die automatischen Scripts nicht funktionieren, installieren Sie die Pakete manuell:
|
@@ -185,10 +231,28 @@ Alle Scripts sind ausführbar und können direkt aufgerufen werden.
|
|
185
231
|
## Verwendung
|
186
232
|
|
187
233
|
### Programm starten
|
234
|
+
|
235
|
+
**Über das Anwendungsmenü:**
|
236
|
+
Nach der Installation finden Sie "Bash-Script-Maker" im Anwendungsmenü Ihrer Desktop-Umgebung.
|
237
|
+
|
238
|
+
**Über das Terminal:**
|
239
|
+
```bash
|
240
|
+
bash-script-maker
|
241
|
+
```
|
242
|
+
|
243
|
+
**Direkt aus dem Quellcode:**
|
188
244
|
```bash
|
189
|
-
|
245
|
+
python3 bash_script_maker.py
|
190
246
|
```
|
191
247
|
|
248
|
+
### Desktop-Integration
|
249
|
+
|
250
|
+
Die App wird automatisch mit einem benutzerdefinierten Icon und Desktop-Integration installiert:
|
251
|
+
- **Icon**: Ein modernes SVG-Icon mit Terminal-Design
|
252
|
+
- **Desktop-Datei**: Vollständige Integration in das Anwendungsmenü
|
253
|
+
- **Kategorien**: Development und Utility
|
254
|
+
- **Unterstützte Distributionen**: Alle Linux-Distributionen mit Desktop-Umgebung
|
255
|
+
|
192
256
|
### Script erstellen
|
193
257
|
1. Wählen Sie die gewünschten Befehlsbausteine aus der linken Palette
|
194
258
|
2. Klicken Sie auf einen Baustein, um ihn in den Editor einzufügen
|
@@ -0,0 +1,11 @@
|
|
1
|
+
assets.py,sha256=QMUllYA8CPAdu5ulDGRZm3opmimFSSAllUCol_RylmA,1012
|
2
|
+
bash_script_maker.py,sha256=nMd-rEuQ5hRKQYggBcBsrygudl7aSz_xqOB43szoxRQ,31010
|
3
|
+
custom_dialogs.py,sha256=Rr3jXuuZFRDNSBiM2sHcKhix3yiacvQkp6eluozwzmk,9243
|
4
|
+
localization.py,sha256=6Dbyf8qG-p6_vUDPoBTtVBnSixO7_gLVtPnuIC4Fchs,1344
|
5
|
+
syntax_highlighter.py,sha256=1umHO8lhhb_FxomXS3Yiub-KTWtBymt60ct5Www3boU,34954
|
6
|
+
bash_script_maker-1.4.2.dist-info/LICENSE,sha256=G-uFRliqQDtsMvClHiUhNBw84dKRzqodui4tIRPJta8,2334
|
7
|
+
bash_script_maker-1.4.2.dist-info/METADATA,sha256=1b5WksTxNUav3Nd-Zdt2BQRIQ6iVBAz1_d108GNlAaw,15785
|
8
|
+
bash_script_maker-1.4.2.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
9
|
+
bash_script_maker-1.4.2.dist-info/entry_points.txt,sha256=jof_Nbub3hvayvOeVKrYpFDadAkCSUA3rqT7n61WED8,119
|
10
|
+
bash_script_maker-1.4.2.dist-info/top_level.txt,sha256=aQp35H7s1JAeQ5IhRLDUS7D-u5ob4IEsGv4ItOv5Afo,72
|
11
|
+
bash_script_maker-1.4.2.dist-info/RECORD,,
|
bash_script_maker.py
CHANGED
@@ -4,6 +4,11 @@
|
|
4
4
|
Bash-Script-Maker - Ein GUI-Programm zur Erstellung von Bash-Scripts
|
5
5
|
"""
|
6
6
|
|
7
|
+
try:
|
8
|
+
from __version__ import __version__
|
9
|
+
except ImportError:
|
10
|
+
__version__ = "1.2.1"
|
11
|
+
|
7
12
|
import tkinter as tk
|
8
13
|
from tkinter import scrolledtext, messagebox
|
9
14
|
import ttkbootstrap as ttk
|
custom_dialogs.py
ADDED
@@ -0,0 +1,270 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
"""
|
4
|
+
Eigene, modern gestaltete Datei-Dialoge für den Bash-Script-Maker.
|
5
|
+
Diese ersetzen die nativen Tkinter-Dialoge, um ein konsistentes
|
6
|
+
Aussehen und Verhalten zu gewährleisten.
|
7
|
+
"""
|
8
|
+
import os
|
9
|
+
import tkinter as tk
|
10
|
+
from fnmatch import fnmatch
|
11
|
+
import ttkbootstrap as ttk
|
12
|
+
from ttkbootstrap.constants import *
|
13
|
+
from localization import _
|
14
|
+
from tkinter import messagebox
|
15
|
+
|
16
|
+
|
17
|
+
class CustomFileDialog(ttk.Toplevel):
|
18
|
+
"""
|
19
|
+
Ein benutzerdefinierter Datei-Dialog, der ttkbootstrap-Widgets verwendet.
|
20
|
+
"""
|
21
|
+
|
22
|
+
def __init__(
|
23
|
+
self,
|
24
|
+
parent,
|
25
|
+
title="Datei auswählen",
|
26
|
+
initialdir=os.path.expanduser("~"),
|
27
|
+
filetypes=[("Alle Dateien", "*.*")],
|
28
|
+
defaultextension=".sh",
|
29
|
+
mode="open",
|
30
|
+
):
|
31
|
+
super().__init__(parent)
|
32
|
+
self.title(title)
|
33
|
+
self.geometry("800x600")
|
34
|
+
self.result = None
|
35
|
+
self.current_path = os.path.abspath(initialdir)
|
36
|
+
self.filetypes = filetypes
|
37
|
+
self.defaultextension = defaultextension
|
38
|
+
self.mode = mode # 'open' oder 'save'
|
39
|
+
|
40
|
+
# --- UI Erstellen ---
|
41
|
+
container = ttk.Frame(self, padding=10)
|
42
|
+
container.pack(fill=BOTH, expand=YES)
|
43
|
+
container.grid_rowconfigure(1, weight=1)
|
44
|
+
container.grid_columnconfigure(0, weight=1)
|
45
|
+
|
46
|
+
# 1. Adressleiste und Navigation
|
47
|
+
path_frame = self._create_path_frame(container)
|
48
|
+
path_frame.grid(row=0, column=0, sticky="ew", pady=(0, 5))
|
49
|
+
|
50
|
+
# 2. Baumansicht für Dateien und Ordner
|
51
|
+
tree_frame = self._create_tree_frame(container)
|
52
|
+
tree_frame.grid(row=1, column=0, sticky="nsew")
|
53
|
+
|
54
|
+
# 3. Dateiname und Filter
|
55
|
+
entry_frame = self._create_entry_frame(container)
|
56
|
+
entry_frame.grid(row=2, column=0, sticky="ew", pady=(5, 0))
|
57
|
+
|
58
|
+
# 4. Buttons (Öffnen/Speichern, Abbrechen)
|
59
|
+
button_frame = self._create_button_frame(container)
|
60
|
+
button_frame.grid(row=3, column=0, sticky="e", pady=(10, 0))
|
61
|
+
|
62
|
+
self.update_path_entry()
|
63
|
+
self.populate_tree()
|
64
|
+
|
65
|
+
def _create_path_frame(self, parent):
|
66
|
+
frame = ttk.Frame(parent)
|
67
|
+
frame.grid_columnconfigure(1, weight=1)
|
68
|
+
|
69
|
+
up_btn = ttk.Button(
|
70
|
+
frame, text="↑", command=self.go_up, bootstyle="secondary"
|
71
|
+
)
|
72
|
+
up_btn.grid(row=0, column=0, padx=(0, 5))
|
73
|
+
|
74
|
+
self.path_var = tk.StringVar()
|
75
|
+
path_entry = ttk.Entry(frame, textvariable=self.path_var)
|
76
|
+
path_entry.grid(row=0, column=1, sticky="ew")
|
77
|
+
path_entry.bind("<Return>", self.path_entry_changed)
|
78
|
+
|
79
|
+
return frame
|
80
|
+
|
81
|
+
def _create_tree_frame(self, parent):
|
82
|
+
frame = ttk.Frame(parent)
|
83
|
+
frame.grid_rowconfigure(0, weight=1)
|
84
|
+
frame.grid_columnconfigure(0, weight=1)
|
85
|
+
|
86
|
+
self.tree = ttk.Treeview(
|
87
|
+
frame, columns=("type", "size"), show="tree headings"
|
88
|
+
)
|
89
|
+
self.tree.heading("#0", text=_("Name"))
|
90
|
+
self.tree.heading("type", text=_("Typ"))
|
91
|
+
self.tree.heading("size", text=_("Größe"))
|
92
|
+
self.tree.column("#0", stretch=YES)
|
93
|
+
self.tree.column("type", width=100, anchor="w")
|
94
|
+
self.tree.column("size", width=100, anchor="e")
|
95
|
+
|
96
|
+
scrollbar = ttk.Scrollbar(
|
97
|
+
frame, orient="vertical", command=self.tree.yview
|
98
|
+
)
|
99
|
+
self.tree.configure(yscrollcommand=scrollbar.set)
|
100
|
+
|
101
|
+
self.tree.grid(row=0, column=0, sticky="nsew")
|
102
|
+
scrollbar.grid(row=0, column=1, sticky="ns")
|
103
|
+
|
104
|
+
self.tree.bind("<<TreeviewSelect>>", self.on_tree_select)
|
105
|
+
self.tree.bind("<Double-1>", self.on_tree_double_click)
|
106
|
+
|
107
|
+
return frame
|
108
|
+
|
109
|
+
def _create_entry_frame(self, parent):
|
110
|
+
frame = ttk.Frame(parent)
|
111
|
+
frame.grid_columnconfigure(0, weight=1)
|
112
|
+
|
113
|
+
ttk.Label(frame, text=_("Dateiname:")).grid(
|
114
|
+
row=0, column=0, sticky="w", padx=(5, 0)
|
115
|
+
)
|
116
|
+
self.filename_var = tk.StringVar()
|
117
|
+
filename_entry = ttk.Entry(frame, textvariable=self.filename_var)
|
118
|
+
filename_entry.grid(row=1, column=0, sticky="ew")
|
119
|
+
|
120
|
+
self.filetype_var = tk.StringVar()
|
121
|
+
filetype_combo = ttk.Combobox(
|
122
|
+
frame,
|
123
|
+
textvariable=self.filetype_var,
|
124
|
+
values=[f"{desc} ({pat})" for desc, pat in self.filetypes],
|
125
|
+
)
|
126
|
+
filetype_combo.grid(row=1, column=1, padx=(5, 0))
|
127
|
+
filetype_combo.current(0)
|
128
|
+
filetype_combo.bind("<<ComboboxSelected>>", self.populate_tree)
|
129
|
+
|
130
|
+
return frame
|
131
|
+
|
132
|
+
def _create_button_frame(self, parent):
|
133
|
+
frame = ttk.Frame(parent)
|
134
|
+
ok_text = _("Speichern") if self.mode == "save" else _("Öffnen")
|
135
|
+
ok_btn = ttk.Button(
|
136
|
+
frame, text=ok_text, command=self.on_ok, bootstyle="success"
|
137
|
+
)
|
138
|
+
ok_btn.pack(side=RIGHT, padx=(5, 0))
|
139
|
+
|
140
|
+
cancel_btn = ttk.Button(
|
141
|
+
frame, text=_("Abbrechen"), command=self.on_cancel, bootstyle="secondary"
|
142
|
+
)
|
143
|
+
cancel_btn.pack(side=RIGHT)
|
144
|
+
return frame
|
145
|
+
|
146
|
+
def populate_tree(self, event=None):
|
147
|
+
for i in self.tree.get_children():
|
148
|
+
self.tree.delete(i)
|
149
|
+
|
150
|
+
try:
|
151
|
+
items = os.listdir(self.current_path)
|
152
|
+
# Verzeichnisse zuerst
|
153
|
+
dirs = sorted(
|
154
|
+
[d for d in items if os.path.isdir(os.path.join(self.current_path, d))]
|
155
|
+
)
|
156
|
+
# Dann Dateien
|
157
|
+
files = sorted(
|
158
|
+
[f for f in items if os.path.isfile(os.path.join(self.current_path, f))]
|
159
|
+
)
|
160
|
+
|
161
|
+
for d in dirs:
|
162
|
+
self.tree.insert("", "end", text=d, values=("Ordner", ""))
|
163
|
+
|
164
|
+
selected_filter = self.filetype_var.get()
|
165
|
+
filter_pattern = "*" # Default
|
166
|
+
if selected_filter:
|
167
|
+
try:
|
168
|
+
# Extrahiere das Muster aus "(Beschreibung (*.sh))"
|
169
|
+
filter_pattern = selected_filter.split('(')[1].split(')')[0]
|
170
|
+
except IndexError:
|
171
|
+
pass
|
172
|
+
|
173
|
+
for f in files:
|
174
|
+
if fnmatch(f, filter_pattern) or filter_pattern == "*.*":
|
175
|
+
try:
|
176
|
+
size = os.path.getsize(os.path.join(self.current_path, f))
|
177
|
+
self.tree.insert("", "end", text=f, values=("Datei", f"{size} B"))
|
178
|
+
except OSError:
|
179
|
+
pass # Datei könnte ein Broken Symlink sein
|
180
|
+
|
181
|
+
except OSError as e:
|
182
|
+
self.tree.insert("", "end", text=_("Fehler: {}").format(str(e)), values=("", ""))
|
183
|
+
|
184
|
+
def update_path_entry(self):
|
185
|
+
self.path_var.set(self.current_path)
|
186
|
+
|
187
|
+
def go_up(self):
|
188
|
+
new_path = os.path.dirname(self.current_path)
|
189
|
+
if os.path.isdir(new_path):
|
190
|
+
self.current_path = new_path
|
191
|
+
self.update_path_entry()
|
192
|
+
self.populate_tree()
|
193
|
+
|
194
|
+
def path_entry_changed(self, event=None):
|
195
|
+
new_path = self.path_var.get()
|
196
|
+
if os.path.isdir(new_path):
|
197
|
+
self.current_path = new_path
|
198
|
+
self.populate_tree()
|
199
|
+
else:
|
200
|
+
# Zurücksetzen auf den alten gültigen Pfad
|
201
|
+
self.update_path_entry()
|
202
|
+
|
203
|
+
def on_tree_select(self, event=None):
|
204
|
+
selected_items = self.tree.selection()
|
205
|
+
if selected_items:
|
206
|
+
item_text = self.tree.item(selected_items[0], "text")
|
207
|
+
self.filename_var.set(item_text)
|
208
|
+
|
209
|
+
def on_tree_double_click(self, event=None):
|
210
|
+
selected_items = self.tree.selection()
|
211
|
+
if not selected_items:
|
212
|
+
return
|
213
|
+
|
214
|
+
item = self.tree.item(selected_items[0])
|
215
|
+
item_text = item["text"]
|
216
|
+
item_type = item["values"][0]
|
217
|
+
|
218
|
+
if item_type == "Ordner":
|
219
|
+
new_path = os.path.join(self.current_path, item_text)
|
220
|
+
if os.path.isdir(new_path):
|
221
|
+
self.current_path = new_path
|
222
|
+
self.update_path_entry()
|
223
|
+
self.populate_tree()
|
224
|
+
else:
|
225
|
+
# Bei Doppelklick auf eine Datei wird der Dialog bestätigt
|
226
|
+
self.on_ok()
|
227
|
+
|
228
|
+
def on_ok(self):
|
229
|
+
filename = self.filename_var.get()
|
230
|
+
if not filename:
|
231
|
+
return
|
232
|
+
|
233
|
+
# Füge die Standard-Endung hinzu, falls sie fehlt (nur im Speichern-Modus)
|
234
|
+
if self.mode == "save":
|
235
|
+
_, ext = os.path.splitext(filename)
|
236
|
+
if not ext and self.defaultextension:
|
237
|
+
filename += self.defaultextension
|
238
|
+
|
239
|
+
self.result = os.path.join(self.current_path, filename)
|
240
|
+
|
241
|
+
# Prüfe im Speichern-Modus, ob die Datei existiert
|
242
|
+
if self.mode == "save" and os.path.exists(self.result):
|
243
|
+
if not messagebox.askyesno(
|
244
|
+
_("Bestätigen"), _("Die Datei existiert bereits. Möchten Sie sie ersetzen?")
|
245
|
+
):
|
246
|
+
self.result = None # Abbruch
|
247
|
+
return
|
248
|
+
|
249
|
+
self.destroy()
|
250
|
+
|
251
|
+
def on_cancel(self):
|
252
|
+
self.result = None
|
253
|
+
self.destroy()
|
254
|
+
|
255
|
+
def show(self):
|
256
|
+
"""Zeigt den Dialog an und wartet auf eine Benutzereingabe."""
|
257
|
+
self.transient(self.master)
|
258
|
+
self.grab_set()
|
259
|
+
self.wait_window(self)
|
260
|
+
return self.result
|
261
|
+
|
262
|
+
|
263
|
+
def askopenfilename(**kwargs):
|
264
|
+
dialog = CustomFileDialog(mode="open", **kwargs)
|
265
|
+
return dialog.show()
|
266
|
+
|
267
|
+
|
268
|
+
def asksaveasfilename(**kwargs):
|
269
|
+
dialog = CustomFileDialog(mode="save", **kwargs)
|
270
|
+
return dialog.show()
|
localization.py
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
import gettext
|
2
|
+
import os
|
3
|
+
import configparser
|
4
|
+
|
5
|
+
# Verzeichnis, in dem die Übersetzungen liegen
|
6
|
+
LOCALE_DIR = os.path.join(os.path.dirname(__file__), "locales")
|
7
|
+
DEFAULT_LANG = "de"
|
8
|
+
|
9
|
+
|
10
|
+
def get_translator():
|
11
|
+
"""
|
12
|
+
Liest die Konfigurationsdatei und gibt die korrekte Übersetzer-Funktion zurück.
|
13
|
+
"""
|
14
|
+
config = configparser.ConfigParser()
|
15
|
+
language_code = DEFAULT_LANG
|
16
|
+
config_path = "config.ini"
|
17
|
+
|
18
|
+
if os.path.exists(config_path):
|
19
|
+
config.read(config_path)
|
20
|
+
language_code = config.get("Settings", "language", fallback=DEFAULT_LANG)
|
21
|
+
|
22
|
+
try:
|
23
|
+
lang = gettext.translation(
|
24
|
+
"base", localedir=LOCALE_DIR, languages=[language_code], fallback=True
|
25
|
+
)
|
26
|
+
except FileNotFoundError:
|
27
|
+
# Fallback auf die Standardsprache, wenn die Übersetzungsdatei fehlt
|
28
|
+
lang = gettext.translation(
|
29
|
+
"base", localedir=LOCALE_DIR, languages=[DEFAULT_LANG], fallback=True
|
30
|
+
)
|
31
|
+
|
32
|
+
return lang.gettext
|
33
|
+
|
34
|
+
|
35
|
+
# Die globale Übersetzer-Funktion wird hier einmalig initialisiert
|
36
|
+
_ = get_translator()
|
37
|
+
|
38
|
+
|
39
|
+
def save_language_setting(language_code):
|
40
|
+
"""Speichert die ausgewählte Sprache in der Konfigurationsdatei."""
|
41
|
+
config = configparser.ConfigParser()
|
42
|
+
config["Settings"] = {"language": language_code}
|
43
|
+
with open("config.ini", "w") as configfile:
|
44
|
+
config.write(configfile)
|
@@ -1,8 +0,0 @@
|
|
1
|
-
bash_script_maker.py,sha256=EAQGLTWSKRg6VGDEDwPter4Hi1m0xL-M7Xk-oWv95UI,30918
|
2
|
-
syntax_highlighter.py,sha256=1umHO8lhhb_FxomXS3Yiub-KTWtBymt60ct5Www3boU,34954
|
3
|
-
bash_script_maker-1.1.0.dist-info/licenses/LICENSE,sha256=G-uFRliqQDtsMvClHiUhNBw84dKRzqodui4tIRPJta8,2334
|
4
|
-
bash_script_maker-1.1.0.dist-info/METADATA,sha256=rfTLrjnuJGR566EvtEF9GiCZVNg8kpdSoJDgHvKHJOY,13850
|
5
|
-
bash_script_maker-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
6
|
-
bash_script_maker-1.1.0.dist-info/entry_points.txt,sha256=tNHGw5xnqKF86fv9uWbQb6L603tEUQlDhxDoIjhImy8,61
|
7
|
-
bash_script_maker-1.1.0.dist-info/top_level.txt,sha256=kkNaOIVZy-Y7dDicN9ueDi33gBzbTnb4c-5FDHEke_I,37
|
8
|
-
bash_script_maker-1.1.0.dist-info/RECORD,,
|
File without changes
|