Compare commits
No commits in common. "507747d5bef500926a11ceca0a641a52fb7ed546" and "6a1386f15c787e4f7e0a658aa06b554efa40a68b" have entirely different histories.
507747d5be
...
6a1386f15c
11
config.py
11
config.py
|
@ -1,8 +1,7 @@
|
||||||
import os, sys, json
|
import os, sys, json
|
||||||
#TODO: port to QT once that little mainloop issue has been resolved...
|
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
import util
|
import gui_helper, util
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
def __init__(self, file_path, default_config):
|
def __init__(self, file_path, default_config):
|
||||||
|
@ -19,19 +18,19 @@ class Config:
|
||||||
util.error("An exception occurred while trying to load the configuration.", handle_gracefully=False)
|
util.error("An exception occurred while trying to load the configuration.", handle_gracefully=False)
|
||||||
else:
|
else:
|
||||||
# config not found
|
# config not found
|
||||||
dialog_communication = util.Communication()
|
dialog_interaction_handler = gui_helper.Window_Interaction_Handler()
|
||||||
|
|
||||||
dialog = tk.Tk()
|
dialog = tk.Tk()
|
||||||
dialog.title("No configuration found")
|
dialog.title("No configuration found")
|
||||||
ttk.Label(dialog, text="No configuration found!").pack()
|
ttk.Label(dialog, text="No configuration found!").pack()
|
||||||
buttons_frame = tk.Frame(dialog)
|
buttons_frame = tk.Frame(dialog)
|
||||||
buttons_frame.pack()
|
buttons_frame.pack()
|
||||||
ttk.Button(buttons_frame, text="Create", command=lambda: dialog_communication.send("create", True, additional_action=dialog.destroy)).grid(column=0, row=0)
|
ttk.Button(buttons_frame, text="Create", command=lambda: dialog_interaction_handler.interact("create", True, additional_action=dialog.destroy)).grid(column=0, row=0)
|
||||||
ttk.Button(buttons_frame, text="Quit", command=lambda: dialog_communication.send("create", False, additional_action=dialog.destroy)).grid(column=1, row=0)
|
ttk.Button(buttons_frame, text="Quit", command=lambda: dialog_interaction_handler.interact("create", False, additional_action=dialog.destroy)).grid(column=1, row=0)
|
||||||
dialog.resizable(0,0)
|
dialog.resizable(0,0)
|
||||||
dialog.mainloop()
|
dialog.mainloop()
|
||||||
|
|
||||||
if dialog_communication.get("create"):
|
if dialog_interaction_handler.get_result("create"):
|
||||||
self.__current_config = default_config
|
self.__current_config = default_config
|
||||||
try:
|
try:
|
||||||
config_file = open(self.__file_path, "w")
|
config_file = open(self.__file_path, "w")
|
||||||
|
|
|
@ -1,40 +1,13 @@
|
||||||
from PySide6 import QtWidgets
|
class window:
|
||||||
import util
|
def __init__(self):
|
||||||
|
pass
|
||||||
gui_handler_communication = util.Communication()
|
def __del__(self):
|
||||||
app = QtWidgets.QApplication([])
|
|
||||||
|
|
||||||
class Window:
|
|
||||||
def __init__(self, title="Concorde", size_x=640, size_y=480):
|
|
||||||
self.window = QtWidgets.QWidget()
|
|
||||||
self.window.setWindowTitle(title)
|
|
||||||
self.window.resize(size_x, size_y)
|
|
||||||
self.window.show()
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
#TODO: whatever needs to be done here
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def set_title(self, title):
|
def set_title(self, title):
|
||||||
self.window.setWindowTitle(title)
|
pass
|
||||||
|
def get_geometry(self):
|
||||||
def get_size(self):
|
|
||||||
#TODO: implement
|
|
||||||
util.warn("Not implemented!")
|
|
||||||
return None
|
return None
|
||||||
|
def set_geometry(self, geometry):
|
||||||
def set_size(self, size_x, size_y):
|
pass
|
||||||
self.window.resize(size_x, size_y)
|
|
||||||
|
|
||||||
def update_menus(self, menu_dict):
|
def update_menus(self, menu_dict):
|
||||||
#TODO: implement
|
pass
|
||||||
util.warn("Not implemented!")
|
|
||||||
|
|
||||||
#TODO: This needs to run in a thread but Qt really doesn't want it to. There are two ways around this:
|
|
||||||
# - create the QtWidgets.QApplication inside a thread and run all QT stuff inside that thread
|
|
||||||
# - make a generic wrapper for window mainloop that will always run in the main thread while the actual main control flow of the program gets moved to another thread
|
|
||||||
# There are some issues with these workarounds though; mainly that QT isn't thread safe.
|
|
||||||
# I really want to keep QT running in its own thread because I want to retain the ability to arbitrarily spawn and manipulate windows while other windows are running.
|
|
||||||
# Another issue that is probably easily worked around / fixed is that app.exec() will return once all running windows are closed.
|
|
||||||
def fixme_window_mainloop_workaround_to_just_get_a_window_started_really_should_not_be_implemented_this_way_for_reasons_stated_in_the_comment_above_the_definition_of_this_function():
|
|
||||||
app.exec()
|
|
||||||
|
|
|
@ -1,6 +1,56 @@
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
import util
|
import util
|
||||||
|
|
||||||
|
# easy way to get data out of window events
|
||||||
|
class Window_Interaction_Handler:
|
||||||
|
# constructor
|
||||||
|
def __init__(self):
|
||||||
|
self.__window_interactions = {}
|
||||||
|
|
||||||
|
# add a result for an interaction event, saves results in reverse order by default, can optionally call another function
|
||||||
|
def interact(self, name, result, reverse_order=True, additional_action=None, additional_action_parameters=()):
|
||||||
|
if name in self.__window_interactions:
|
||||||
|
if reverse_order:
|
||||||
|
self.__window_interactions[name] = [result] + self.__window_interactions[name]
|
||||||
|
else:
|
||||||
|
self.__window_interactions[name] = self.__window_interactions[name] + [result]
|
||||||
|
else:
|
||||||
|
self.__window_interactions[name] = [result]
|
||||||
|
|
||||||
|
if not additional_action==None:
|
||||||
|
additional_action(*additional_action_parameters)
|
||||||
|
|
||||||
|
# get first result for a given event from the list of results (newest (default) or oldest), removes the returned result from the list by default
|
||||||
|
def get_result(self, name, remove=True):
|
||||||
|
if name in self.__window_interactions and len(self.__window_interactions[name])>0:
|
||||||
|
if remove:
|
||||||
|
result = self.__window_interactions[name].pop(0)
|
||||||
|
if len(self.__window_interactions[name])==0:
|
||||||
|
del self.__window_interactions[name]
|
||||||
|
return result
|
||||||
|
else:
|
||||||
|
return self.__window_interactions[name][0]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# get all results for a given event
|
||||||
|
def get_results(self, name, clear=False):
|
||||||
|
if name in self.__window_interactions and len(self.__window_interactions[name])>0:
|
||||||
|
results = self.__window_interactions[name]
|
||||||
|
if clear:
|
||||||
|
del self.__window_interactions[name]
|
||||||
|
return results
|
||||||
|
|
||||||
|
# clear results for a given event
|
||||||
|
def clear(self, name):
|
||||||
|
if name in self.__window_interactions:
|
||||||
|
del self.__window_interactions[name]
|
||||||
|
|
||||||
|
# destructor
|
||||||
|
def __del__(self):
|
||||||
|
if len(self.__window_interactions)>0:
|
||||||
|
util.warn("__window_interactions not empty upon destruction of Window_Interaction_Handler:\n"+str(self.__window_interactions))
|
||||||
|
|
||||||
|
|
||||||
def not_implemented():
|
def not_implemented():
|
||||||
util.warn("Not implemented!")
|
util.warn("Not implemented!")
|
||||||
|
|
22
main.py
22
main.py
|
@ -1,6 +1,9 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
import os
|
import os
|
||||||
import gui_helper, gui_handler
|
import tkinter as tk
|
||||||
|
from tkinter import ttk
|
||||||
|
import gui_helper
|
||||||
|
import gui_handler
|
||||||
from config import Config
|
from config import Config
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
@ -8,13 +11,9 @@ from config import Config
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
default_configuration = {
|
default_configuration = {
|
||||||
"window size": {
|
"window geometry": "640x480"
|
||||||
"x": 800,
|
|
||||||
"y": 600
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#TODO: make this a hidden file once development is far enough along that it doesn’t need to be recreated constantly
|
configuration_file_path = os.path.join(os.path.expanduser("~"), "some_ide_config.json")
|
||||||
configuration_file_path = os.path.join(os.path.expanduser("~"), "concorde.json")
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# PROGRAM STARTUP
|
# PROGRAM STARTUP
|
||||||
|
@ -26,13 +25,8 @@ configuration = Config(configuration_file_path, default_configuration)
|
||||||
# PROGRAM MAIN WINDOW
|
# PROGRAM MAIN WINDOW
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
main_window = gui_handler.Window()
|
main_window = gui_handler.window()
|
||||||
main_window.set_title("Concorde IDE")
|
main_window.set_title("Concorde IDE")
|
||||||
main_window.set_size(configuration.get_configuration_value("window size")["x"], configuration.get_configuration_value("window size")["y"])
|
main_window.set_geometry(configuration.get_configuration_value("window geometry"))
|
||||||
|
|
||||||
main_window.update_menus(gui_helper.menu_structure)
|
main_window.update_menus(gui_helper.menu_structure)
|
||||||
|
|
||||||
#TODO: get resolution of main window on exit and save it back to the configuration
|
|
||||||
#TODO: check if the GUI encountered an error in a toolkit agnostic way
|
|
||||||
|
|
||||||
gui_handler.fixme_window_mainloop_workaround_to_just_get_a_window_started_really_should_not_be_implemented_this_way_for_reasons_stated_in_the_comment_above_the_definition_of_this_function()
|
|
||||||
|
|
50
util.py
50
util.py
|
@ -25,53 +25,3 @@ def error(message, is_exception=True, handle_gracefully=True):
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
sys.exit(EXIT_ERROR)
|
sys.exit(EXIT_ERROR)
|
||||||
|
|
||||||
# easy way to communicate across events
|
|
||||||
#TODO: make thread safe
|
|
||||||
class Communication:
|
|
||||||
def __init__(self):
|
|
||||||
self.__messages = {}
|
|
||||||
|
|
||||||
# send a message tagged with name and containing content, adds to the beginning of the list of messages with the same tag by default, a function to run as an additional action can be provided
|
|
||||||
def send(self, name, content, reverse_order=True, additional_action=None):
|
|
||||||
if name in self.__messages:
|
|
||||||
if reverse_order:
|
|
||||||
self.__messages[name] = [content] + self.__messages[name]
|
|
||||||
else:
|
|
||||||
self.__messages[name] = self.__messages[name] + [content]
|
|
||||||
else:
|
|
||||||
self.__messages[name] = [content]
|
|
||||||
if additional_action == None:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
additional_action()
|
|
||||||
|
|
||||||
# get the content of the first message tagged with name, removes the returned message by default
|
|
||||||
def get(self, name, remove=True):
|
|
||||||
if name in self.__messages and len(self.__messages[name])>0:
|
|
||||||
if remove:
|
|
||||||
content = self.__messages[name].pop(0)
|
|
||||||
if len(self.__messages[name])==0:
|
|
||||||
del self.__messages[name]
|
|
||||||
return content
|
|
||||||
else:
|
|
||||||
return self.__messages[name][0]
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# get the contents for all messages tagged with name
|
|
||||||
def get_all(self, name, clear=False):
|
|
||||||
if name in self.__messages and len(self.__messages[name])>0:
|
|
||||||
contents = self.__messages[name]
|
|
||||||
if clear:
|
|
||||||
del self.__messages[name]
|
|
||||||
return contents
|
|
||||||
|
|
||||||
# deletes all messages tagged with name
|
|
||||||
def clear(self, name):
|
|
||||||
if name in self.__messages:
|
|
||||||
del self.__messages[name]
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
if len(self.__messages)>0:
|
|
||||||
warn("__messages not empty upon destruction of Communication object:\n"+str(self.__messages))
|
|
||||||
|
|
Reference in New Issue