fix merge conflict
This commit is contained in:
commit
95d36a1792
9 changed files with 224 additions and 42 deletions
|
@ -16,6 +16,7 @@ MOBILITY_PATH = HOME_PATH.joinpath("mobility")
|
||||||
XMLS_PATH = HOME_PATH.joinpath("xmls")
|
XMLS_PATH = HOME_PATH.joinpath("xmls")
|
||||||
CONFIG_PATH = HOME_PATH.joinpath("gui.yaml")
|
CONFIG_PATH = HOME_PATH.joinpath("gui.yaml")
|
||||||
LOG_PATH = HOME_PATH.joinpath("gui.log")
|
LOG_PATH = HOME_PATH.joinpath("gui.log")
|
||||||
|
SCRIPT_PATH = HOME_PATH.joinpath("scripts")
|
||||||
|
|
||||||
# local paths
|
# local paths
|
||||||
DATA_PATH = Path(__file__).parent.joinpath("data")
|
DATA_PATH = Path(__file__).parent.joinpath("data")
|
||||||
|
@ -25,17 +26,16 @@ LOCAL_XMLS_PATH = DATA_PATH.joinpath("xmls").absolute()
|
||||||
LOCAL_MOBILITY_PATH = DATA_PATH.joinpath("mobility").absolute()
|
LOCAL_MOBILITY_PATH = DATA_PATH.joinpath("mobility").absolute()
|
||||||
|
|
||||||
# configuration data
|
# configuration data
|
||||||
TERMINALS = [
|
TERMINALS = {
|
||||||
"$TERM",
|
"xterm": "xterm -e",
|
||||||
"gnome-terminal --window --",
|
"aterm": "aterm -e",
|
||||||
"lxterminal -e",
|
"eterm": "eterm -e",
|
||||||
"konsole -e",
|
"rxvt": "rxvt -e",
|
||||||
"xterm -e",
|
"konsole": "konsole -e",
|
||||||
"aterm -e",
|
"lxterminal": "lxterminal -e",
|
||||||
"eterm -e",
|
"xfce4-terminal": "xfce4-terminal -x",
|
||||||
"rxvt -e",
|
"gnome-terminal": "gnome-terminal --window --",
|
||||||
"xfce4-terminal -x",
|
}
|
||||||
]
|
|
||||||
EDITORS = ["$EDITOR", "vim", "emacs", "gedit", "nano", "vi"]
|
EDITORS = ["$EDITOR", "vim", "emacs", "gedit", "nano", "vi"]
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,6 +50,14 @@ def copy_files(current_path, new_path):
|
||||||
shutil.copy(current_file, new_file)
|
shutil.copy(current_file, new_file)
|
||||||
|
|
||||||
|
|
||||||
|
def find_terminal():
|
||||||
|
for term in sorted(TERMINALS):
|
||||||
|
cmd = TERMINALS[term]
|
||||||
|
if shutil.which(term):
|
||||||
|
return cmd
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def check_directory():
|
def check_directory():
|
||||||
if HOME_PATH.exists():
|
if HOME_PATH.exists():
|
||||||
return
|
return
|
||||||
|
@ -60,16 +68,14 @@ def check_directory():
|
||||||
ICONS_PATH.mkdir()
|
ICONS_PATH.mkdir()
|
||||||
MOBILITY_PATH.mkdir()
|
MOBILITY_PATH.mkdir()
|
||||||
XMLS_PATH.mkdir()
|
XMLS_PATH.mkdir()
|
||||||
|
SCRIPT_PATH.mkdir()
|
||||||
|
|
||||||
copy_files(LOCAL_ICONS_PATH, ICONS_PATH)
|
copy_files(LOCAL_ICONS_PATH, ICONS_PATH)
|
||||||
copy_files(LOCAL_BACKGROUND_PATH, BACKGROUNDS_PATH)
|
copy_files(LOCAL_BACKGROUND_PATH, BACKGROUNDS_PATH)
|
||||||
copy_files(LOCAL_XMLS_PATH, XMLS_PATH)
|
copy_files(LOCAL_XMLS_PATH, XMLS_PATH)
|
||||||
copy_files(LOCAL_MOBILITY_PATH, MOBILITY_PATH)
|
copy_files(LOCAL_MOBILITY_PATH, MOBILITY_PATH)
|
||||||
|
|
||||||
if "TERM" in os.environ:
|
terminal = find_terminal()
|
||||||
terminal = TERMINALS[0]
|
|
||||||
else:
|
|
||||||
terminal = TERMINALS[1]
|
|
||||||
if "EDITOR" in os.environ:
|
if "EDITOR" in os.environ:
|
||||||
editor = EDITORS[0]
|
editor = EDITORS[0]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -5,6 +5,7 @@ import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from tkinter import messagebox
|
||||||
from typing import TYPE_CHECKING, Dict, List
|
from typing import TYPE_CHECKING, Dict, List
|
||||||
|
|
||||||
import grpc
|
import grpc
|
||||||
|
@ -38,17 +39,6 @@ OBSERVERS = {
|
||||||
"IPSec policies": "setkey -DP",
|
"IPSec policies": "setkey -DP",
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_TERMS = {
|
|
||||||
"xterm": "xterm -e",
|
|
||||||
"aterm": "aterm -e",
|
|
||||||
"eterm": "eterm -e",
|
|
||||||
"rxvt": "rxvt -e",
|
|
||||||
"konsole": "konsole -e",
|
|
||||||
"lxterminal": "lxterminal -e",
|
|
||||||
"xfce4-terminal": "xfce4-terminal -x",
|
|
||||||
"gnome-terminal": "gnome-terminal --window--",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class CoreServer:
|
class CoreServer:
|
||||||
def __init__(self, name: str, address: str, port: int):
|
def __init__(self, name: str, address: str, port: int):
|
||||||
|
@ -571,11 +561,15 @@ class CoreClient:
|
||||||
def launch_terminal(self, node_id: int):
|
def launch_terminal(self, node_id: int):
|
||||||
try:
|
try:
|
||||||
terminal = self.app.guiconfig["preferences"]["terminal"]
|
terminal = self.app.guiconfig["preferences"]["terminal"]
|
||||||
|
if not terminal:
|
||||||
|
messagebox.showerror(
|
||||||
|
"Terminal Error",
|
||||||
|
"No terminal set, please set within the preferences menu",
|
||||||
|
parent=self.app,
|
||||||
|
)
|
||||||
|
return
|
||||||
response = self.client.get_node_terminal(self.session_id, node_id)
|
response = self.client.get_node_terminal(self.session_id, node_id)
|
||||||
output = os.popen(f"echo {terminal}").read()[:-1]
|
cmd = f"{terminal} {response.terminal} &"
|
||||||
if output in DEFAULT_TERMS:
|
|
||||||
terminal = DEFAULT_TERMS[output]
|
|
||||||
cmd = f'{terminal} "{response.terminal}" &'
|
|
||||||
logging.info("launching terminal %s", cmd)
|
logging.info("launching terminal %s", cmd)
|
||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
except grpc.RpcError as e:
|
except grpc.RpcError as e:
|
||||||
|
@ -1069,3 +1063,9 @@ class CoreClient:
|
||||||
|
|
||||||
def service_been_modified(self, node_id: int) -> bool:
|
def service_been_modified(self, node_id: int) -> bool:
|
||||||
return node_id in self.modified_service_nodes
|
return node_id in self.modified_service_nodes
|
||||||
|
|
||||||
|
def execute_script(self, script):
|
||||||
|
response = self.client.execute_script(script)
|
||||||
|
logging.info("execute python script %s", response)
|
||||||
|
if response.session_id != -1:
|
||||||
|
self.join_session(response.session_id)
|
||||||
|
|
85
daemon/core/gui/dialogs/executepython.py
Normal file
85
daemon/core/gui/dialogs/executepython.py
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
import logging
|
||||||
|
import tkinter as tk
|
||||||
|
from tkinter import filedialog, ttk
|
||||||
|
|
||||||
|
from core.gui.appconfig import SCRIPT_PATH
|
||||||
|
from core.gui.dialogs.dialog import Dialog
|
||||||
|
from core.gui.themes import FRAME_PAD, PADX
|
||||||
|
|
||||||
|
|
||||||
|
class ExecutePythonDialog(Dialog):
|
||||||
|
def __init__(self, master, app):
|
||||||
|
super().__init__(master, app, "Execute Python Script", modal=True)
|
||||||
|
self.app = app
|
||||||
|
self.with_options = tk.IntVar(value=0)
|
||||||
|
self.options = tk.StringVar(value="")
|
||||||
|
self.option_entry = None
|
||||||
|
self.file_entry = None
|
||||||
|
self.draw()
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
i = 0
|
||||||
|
frame = ttk.Frame(self.top, padding=FRAME_PAD)
|
||||||
|
frame.columnconfigure(0, weight=1)
|
||||||
|
frame.columnconfigure(1, weight=1)
|
||||||
|
frame.grid(row=i, column=0, sticky="nsew")
|
||||||
|
i = i + 1
|
||||||
|
var = tk.StringVar(value="")
|
||||||
|
self.file_entry = ttk.Entry(frame, textvariable=var)
|
||||||
|
self.file_entry.grid(row=0, column=0, sticky="ew")
|
||||||
|
button = ttk.Button(frame, text="...", command=self.select_file)
|
||||||
|
button.grid(row=0, column=1, sticky="ew")
|
||||||
|
|
||||||
|
self.top.columnconfigure(0, weight=1)
|
||||||
|
button = ttk.Checkbutton(
|
||||||
|
self.top,
|
||||||
|
text="With Options",
|
||||||
|
variable=self.with_options,
|
||||||
|
command=self.add_options,
|
||||||
|
)
|
||||||
|
button.grid(row=i, column=0, sticky="ew")
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
label = ttk.Label(
|
||||||
|
self.top, text="Any command-line options for running the Python script"
|
||||||
|
)
|
||||||
|
label.grid(row=i, column=0, sticky="ew")
|
||||||
|
i = i + 1
|
||||||
|
self.option_entry = ttk.Entry(
|
||||||
|
self.top, textvariable=self.options, state="disabled"
|
||||||
|
)
|
||||||
|
self.option_entry.grid(row=i, column=0, sticky="ew")
|
||||||
|
i = i + 1
|
||||||
|
|
||||||
|
frame = ttk.Frame(self.top, padding=FRAME_PAD)
|
||||||
|
frame.columnconfigure(0, weight=1)
|
||||||
|
frame.columnconfigure(1, weight=1)
|
||||||
|
frame.grid(row=i, column=0)
|
||||||
|
button = ttk.Button(frame, text="Execute", command=self.script_execute)
|
||||||
|
button.grid(row=0, column=0, sticky="ew", padx=PADX)
|
||||||
|
button = ttk.Button(frame, text="Cancel", command=self.destroy)
|
||||||
|
button.grid(row=0, column=1, sticky="ew", padx=PADX)
|
||||||
|
|
||||||
|
def add_options(self):
|
||||||
|
if self.with_options.get():
|
||||||
|
self.option_entry.configure(state="normal")
|
||||||
|
else:
|
||||||
|
self.option_entry.configure(state="disabled")
|
||||||
|
|
||||||
|
def select_file(self):
|
||||||
|
file = filedialog.askopenfilename(
|
||||||
|
parent=self.top,
|
||||||
|
initialdir=str(SCRIPT_PATH),
|
||||||
|
title="Open python script",
|
||||||
|
filetypes=((".py Files", "*.py"), ("All Files", "*")),
|
||||||
|
)
|
||||||
|
if file:
|
||||||
|
self.file_entry.delete(0, "end")
|
||||||
|
self.file_entry.insert("end", file)
|
||||||
|
|
||||||
|
def script_execute(self):
|
||||||
|
file = self.file_entry.get()
|
||||||
|
options = self.option_entry.get()
|
||||||
|
logging.info("Execute %s with options %s", file, options)
|
||||||
|
self.app.core.execute_script(file)
|
||||||
|
self.destroy()
|
|
@ -1,9 +1,11 @@
|
||||||
import logging
|
import logging
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from tkinter import ttk
|
from tkinter import messagebox, ttk
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import netaddr
|
||||||
|
|
||||||
from core.gui import nodeutils
|
from core.gui import nodeutils
|
||||||
from core.gui.appconfig import ICONS_PATH
|
from core.gui.appconfig import ICONS_PATH
|
||||||
from core.gui.dialogs.dialog import Dialog
|
from core.gui.dialogs.dialog import Dialog
|
||||||
|
@ -18,6 +20,58 @@ if TYPE_CHECKING:
|
||||||
from core.gui.graph.node import CanvasNode
|
from core.gui.graph.node import CanvasNode
|
||||||
|
|
||||||
|
|
||||||
|
def check_ip6(parent, name: str, value: str) -> bool:
|
||||||
|
title = f"IP6 Error for {name}"
|
||||||
|
if not value:
|
||||||
|
messagebox.showerror(title, "Empty Value", parent=parent)
|
||||||
|
return False
|
||||||
|
values = value.split("/")
|
||||||
|
if len(values) != 2:
|
||||||
|
messagebox.showerror(
|
||||||
|
title, "Must be in the format address/prefix", parent=parent
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
addr, mask = values
|
||||||
|
if not netaddr.valid_ipv6(addr):
|
||||||
|
messagebox.showerror(title, "Invalid IP6 address", parent=parent)
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
mask = int(mask)
|
||||||
|
if not (0 <= mask <= 128):
|
||||||
|
messagebox.showerror(title, "Mask must be between 0-128", parent=parent)
|
||||||
|
return False
|
||||||
|
except ValueError:
|
||||||
|
messagebox.showerror(title, "Invalid Mask", parent=parent)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def check_ip4(parent, name: str, value: str) -> bool:
|
||||||
|
title = f"IP4 Error for {name}"
|
||||||
|
if not value:
|
||||||
|
messagebox.showerror(title, "Empty Value", parent=parent)
|
||||||
|
return False
|
||||||
|
values = value.split("/")
|
||||||
|
if len(values) != 2:
|
||||||
|
messagebox.showerror(
|
||||||
|
title, "Must be in the format address/prefix", parent=parent
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
addr, mask = values
|
||||||
|
if not netaddr.valid_ipv4(addr):
|
||||||
|
messagebox.showerror(title, "Invalid IP4 address", parent=parent)
|
||||||
|
return False
|
||||||
|
try:
|
||||||
|
mask = int(mask)
|
||||||
|
if not (0 <= mask <= 32):
|
||||||
|
messagebox.showerror(title, "Mask must be between 0-32", parent=parent)
|
||||||
|
return False
|
||||||
|
except ValueError:
|
||||||
|
messagebox.showerror(title, "Invalid mask", parent=parent)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def mac_auto(is_auto: tk.BooleanVar, entry: ttk.Entry):
|
def mac_auto(is_auto: tk.BooleanVar, entry: ttk.Entry):
|
||||||
logging.info("mac auto clicked")
|
logging.info("mac auto clicked")
|
||||||
if is_auto.get():
|
if is_auto.get():
|
||||||
|
@ -203,7 +257,6 @@ class NodeConfigDialog(Dialog):
|
||||||
label.grid(row=row, column=0, padx=PADX, pady=PADY)
|
label.grid(row=row, column=0, padx=PADX, pady=PADY)
|
||||||
ip4 = tk.StringVar(value=f"{interface.ip4}/{interface.ip4mask}")
|
ip4 = tk.StringVar(value=f"{interface.ip4}/{interface.ip4mask}")
|
||||||
entry = ttk.Entry(tab, textvariable=ip4)
|
entry = ttk.Entry(tab, textvariable=ip4)
|
||||||
entry.bind("<FocusOut>", self.app.validation.ip_focus_out)
|
|
||||||
entry.grid(row=row, column=1, columnspan=2, sticky="ew")
|
entry.grid(row=row, column=1, columnspan=2, sticky="ew")
|
||||||
row += 1
|
row += 1
|
||||||
|
|
||||||
|
@ -211,7 +264,6 @@ class NodeConfigDialog(Dialog):
|
||||||
label.grid(row=row, column=0, padx=PADX, pady=PADY)
|
label.grid(row=row, column=0, padx=PADX, pady=PADY)
|
||||||
ip6 = tk.StringVar(value=f"{interface.ip6}/{interface.ip6mask}")
|
ip6 = tk.StringVar(value=f"{interface.ip6}/{interface.ip6mask}")
|
||||||
entry = ttk.Entry(tab, textvariable=ip6)
|
entry = ttk.Entry(tab, textvariable=ip6)
|
||||||
entry.bind("<FocusOut>", self.app.validation.ip_focus_out)
|
|
||||||
entry.grid(row=row, column=1, columnspan=2, sticky="ew")
|
entry.grid(row=row, column=1, columnspan=2, sticky="ew")
|
||||||
|
|
||||||
self.interfaces[interface.id] = InterfaceData(is_auto, mac, ip4, ip6)
|
self.interfaces[interface.id] = InterfaceData(is_auto, mac, ip4, ip6)
|
||||||
|
@ -240,6 +292,8 @@ class NodeConfigDialog(Dialog):
|
||||||
self.image_file = file_path
|
self.image_file = file_path
|
||||||
|
|
||||||
def config_apply(self):
|
def config_apply(self):
|
||||||
|
error = False
|
||||||
|
|
||||||
# update core node
|
# update core node
|
||||||
self.node.name = self.name.get()
|
self.node.name = self.name.get()
|
||||||
if NodeUtils.is_image_node(self.node.type):
|
if NodeUtils.is_image_node(self.node.type):
|
||||||
|
@ -255,7 +309,29 @@ class NodeConfigDialog(Dialog):
|
||||||
# update canvas node
|
# update canvas node
|
||||||
self.canvas_node.image = self.image
|
self.canvas_node.image = self.image
|
||||||
|
|
||||||
|
# update node interface data
|
||||||
|
for interface in self.canvas_node.interfaces:
|
||||||
|
data = self.interfaces[interface.id]
|
||||||
|
if check_ip4(self, interface.name, data.ip4.get()):
|
||||||
|
ip4, ip4mask = data.ip4.get().split("/")
|
||||||
|
interface.ip4 = ip4
|
||||||
|
interface.ip4mask = int(ip4mask)
|
||||||
|
else:
|
||||||
|
error = True
|
||||||
|
data.ip4.set(f"{interface.ip4}/{interface.ip4mask}")
|
||||||
|
break
|
||||||
|
if check_ip6(self, interface.name, data.ip6.get()):
|
||||||
|
ip6, ip6mask = data.ip6.get().split("/")
|
||||||
|
interface.ip6 = ip6
|
||||||
|
interface.ip6mask = int(ip6mask)
|
||||||
|
interface.mac = data.mac.get()
|
||||||
|
else:
|
||||||
|
error = True
|
||||||
|
data.ip6.set(f"{interface.ip6}/{interface.ip6mask}")
|
||||||
|
break
|
||||||
|
|
||||||
# redraw
|
# redraw
|
||||||
|
if not error:
|
||||||
self.canvas_node.redraw()
|
self.canvas_node.redraw()
|
||||||
self.destroy()
|
self.destroy()
|
||||||
|
|
||||||
|
|
|
@ -56,9 +56,8 @@ class PreferencesDialog(Dialog):
|
||||||
|
|
||||||
label = ttk.Label(frame, text="Terminal")
|
label = ttk.Label(frame, text="Terminal")
|
||||||
label.grid(row=2, column=0, pady=PADY, padx=PADX, sticky="w")
|
label.grid(row=2, column=0, pady=PADY, padx=PADX, sticky="w")
|
||||||
combobox = ttk.Combobox(
|
terminals = sorted(appconfig.TERMINALS.values())
|
||||||
frame, textvariable=self.terminal, values=appconfig.TERMINALS
|
combobox = ttk.Combobox(frame, textvariable=self.terminal, values=terminals)
|
||||||
)
|
|
||||||
combobox.grid(row=2, column=1, sticky="ew")
|
combobox.grid(row=2, column=1, sticky="ew")
|
||||||
|
|
||||||
label = ttk.Label(frame, text="3D GUI")
|
label = ttk.Label(frame, text="3D GUI")
|
||||||
|
|
|
@ -107,8 +107,7 @@ class CanvasEdge:
|
||||||
y = (y1 + y2) / 2
|
y = (y1 + y2) / 2
|
||||||
return x, y
|
return x, y
|
||||||
|
|
||||||
def draw_labels(self):
|
def create_labels(self):
|
||||||
x1, y1, x2, y2 = self.get_coordinates()
|
|
||||||
label_one = None
|
label_one = None
|
||||||
if self.link.HasField("interface_one"):
|
if self.link.HasField("interface_one"):
|
||||||
label_one = (
|
label_one = (
|
||||||
|
@ -121,6 +120,11 @@ class CanvasEdge:
|
||||||
f"{self.link.interface_two.ip4}/{self.link.interface_two.ip4mask}\n"
|
f"{self.link.interface_two.ip4}/{self.link.interface_two.ip4mask}\n"
|
||||||
f"{self.link.interface_two.ip6}/{self.link.interface_two.ip6mask}\n"
|
f"{self.link.interface_two.ip6}/{self.link.interface_two.ip6mask}\n"
|
||||||
)
|
)
|
||||||
|
return label_one, label_two
|
||||||
|
|
||||||
|
def draw_labels(self):
|
||||||
|
x1, y1, x2, y2 = self.get_coordinates()
|
||||||
|
label_one, label_two = self.create_labels()
|
||||||
self.text_src = self.canvas.create_text(
|
self.text_src = self.canvas.create_text(
|
||||||
x1,
|
x1,
|
||||||
y1,
|
y1,
|
||||||
|
@ -138,6 +142,11 @@ class CanvasEdge:
|
||||||
tags=tags.LINK_INFO,
|
tags=tags.LINK_INFO,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def redraw(self):
|
||||||
|
label_one, label_two = self.create_labels()
|
||||||
|
self.canvas.itemconfig(self.text_src, text=label_one)
|
||||||
|
self.canvas.itemconfig(self.text_dst, text=label_two)
|
||||||
|
|
||||||
def update_labels(self):
|
def update_labels(self):
|
||||||
"""
|
"""
|
||||||
Move edge labels based on current position.
|
Move edge labels based on current position.
|
||||||
|
|
|
@ -107,6 +107,8 @@ class CanvasNode:
|
||||||
def redraw(self):
|
def redraw(self):
|
||||||
self.canvas.itemconfig(self.id, image=self.image)
|
self.canvas.itemconfig(self.id, image=self.image)
|
||||||
self.canvas.itemconfig(self.text_id, text=self.core_node.name)
|
self.canvas.itemconfig(self.text_id, text=self.core_node.name)
|
||||||
|
for edge in self.edges:
|
||||||
|
edge.redraw()
|
||||||
|
|
||||||
def _get_label_y(self):
|
def _get_label_y(self):
|
||||||
image_box = self.canvas.bbox(self.id)
|
image_box = self.canvas.bbox(self.id)
|
||||||
|
|
|
@ -6,6 +6,7 @@ from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import core.gui.menuaction as action
|
import core.gui.menuaction as action
|
||||||
from core.gui.coreclient import OBSERVERS
|
from core.gui.coreclient import OBSERVERS
|
||||||
|
from core.gui.dialogs.executepython import ExecutePythonDialog
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from core.gui.app import Application
|
from core.gui.app import Application
|
||||||
|
@ -69,7 +70,7 @@ class Menubar(tk.Menu):
|
||||||
menu.add_cascade(label="Recent files", menu=self.recent_menu)
|
menu.add_cascade(label="Recent files", menu=self.recent_menu)
|
||||||
menu.add_separator()
|
menu.add_separator()
|
||||||
menu.add_command(label="Export Python script...", state=tk.DISABLED)
|
menu.add_command(label="Export Python script...", state=tk.DISABLED)
|
||||||
menu.add_command(label="Execute XML or Python script...", state=tk.DISABLED)
|
menu.add_command(label="Execute Python script...", command=self.execute_python)
|
||||||
menu.add_command(
|
menu.add_command(
|
||||||
label="Execute Python script with options...", state=tk.DISABLED
|
label="Execute Python script with options...", state=tk.DISABLED
|
||||||
)
|
)
|
||||||
|
@ -443,6 +444,10 @@ class Menubar(tk.Menu):
|
||||||
else:
|
else:
|
||||||
self.menuaction.file_save_as_xml()
|
self.menuaction.file_save_as_xml()
|
||||||
|
|
||||||
|
def execute_python(self):
|
||||||
|
dialog = ExecutePythonDialog(self.app, self.app)
|
||||||
|
dialog.show()
|
||||||
|
|
||||||
def change_menubar_item_state(self, is_runtime: bool):
|
def change_menubar_item_state(self, is_runtime: bool):
|
||||||
for i in range(self.edit_menu.index("end")):
|
for i in range(self.edit_menu.index("end")):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -19,7 +19,7 @@ PATH="/sbin:/bin:/usr/sbin:/usr/bin"
|
||||||
export PATH
|
export PATH
|
||||||
|
|
||||||
if [ "z$1" = "z-d" ]; then
|
if [ "z$1" = "z-d" ]; then
|
||||||
pypids=`pidof python python2`
|
pypids=`pidof python3 python`
|
||||||
for p in $pypids; do
|
for p in $pypids; do
|
||||||
grep -q core-daemon /proc/$p/cmdline
|
grep -q core-daemon /proc/$p/cmdline
|
||||||
if [ $? = 0 ]; then
|
if [ $? = 0 ]; then
|
||||||
|
|
Loading…
Add table
Reference in a new issue