Compare commits
9 Commits
739ce9d8d8
...
33e42e411c
Author | SHA1 | Date |
---|---|---|
Milan Suman | 33e42e411c | |
BodgeMaster | 34176805d2 | |
BodgeMaster | 3f1103d3b8 | |
BodgeMaster | cfa7117d8a | |
BodgeMaster | e0966570f6 | |
BodgeMaster | bddd43e51b | |
BodgeMaster | 8c4f0a02bc | |
BodgeMaster | 86604b1f04 | |
BodgeMaster | a9e31d01f9 |
18
README.md
18
README.md
|
@ -1,3 +1,17 @@
|
||||||
# IDE_or_something_Idk
|
# Concorde IDE
|
||||||
|
|
||||||
Me trying to make an IDE
|
Concorde is a currently WIP IDE made by BodgeMaster and Shwoomple.
|
||||||
|
|
||||||
|
Planned features:
|
||||||
|
- can operate as a single window or components of the IDE (like the console) can be undocked and run in separate windows to allow for better use of multiple monitors
|
||||||
|
- all GUI elements have to be controlled in a toolkit independent way so that `gui_handler.py` can be yoinked and replaced with a different implementation without changing any other code
|
||||||
|
- only barebones internals, relying on external tools to provide most of the traditional IDE features
|
||||||
|
- project management
|
||||||
|
- preferably rely on standard tools to do that and just provide a nice way of interacting with them in the IDE
|
||||||
|
- code editor
|
||||||
|
- integration for syntax checking, warnings, etc. (if provided by external tool)
|
||||||
|
- integration for syntax highlighting (if provided by external tool)
|
||||||
|
- integration for project-wide renaming of variables (if provided by external tool)
|
||||||
|
- console / terminal
|
||||||
|
- file explorer / project explorer
|
||||||
|
- some sort of extension API to both unify the integration of external tools and add functionality to the IDE (low priority goal)
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
from email import message
|
|
||||||
from PySide6 import QtWidgets
|
from PySide6 import QtWidgets
|
||||||
import util
|
import util
|
||||||
|
|
||||||
app = QtWidgets.QApplication([])
|
app = QtWidgets.QApplication([])
|
||||||
|
|
||||||
|
#TODO: Implement separate editor, terminal and main_window classes using Window as a parent
|
||||||
|
|
||||||
class Window(QtWidgets.QMainWindow):
|
class Window(QtWidgets.QMainWindow):
|
||||||
def __init__(self, size=(640, 480), title="Concorde"):
|
def __init__(self, size=(640, 480), title="Concorde"):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.setWindowTitle(title)
|
self.setWindowTitle(title)
|
||||||
self.resize(size[0], size[1])
|
self.resize(size[0], size[1])
|
||||||
self.show()
|
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
#TODO: whatever needs to be done here
|
#TODO: whatever needs to be done here
|
||||||
|
@ -52,6 +52,10 @@ class Window(QtWidgets.QMainWindow):
|
||||||
menu_item = menu.addAction(entry)
|
menu_item = menu.addAction(entry)
|
||||||
menu_item.triggered.connect(menu_dict[entry])
|
menu_item.triggered.connect(menu_dict[entry])
|
||||||
|
|
||||||
|
class Editor(Window):
|
||||||
|
def __init__(self, size=(640, 480)):
|
||||||
|
super().__init__(size, "Editor")
|
||||||
|
|
||||||
|
|
||||||
class Message(QtWidgets.QMessageBox):
|
class Message(QtWidgets.QMessageBox):
|
||||||
def __init__(self, title, text):
|
def __init__(self, title, text):
|
||||||
|
@ -72,5 +76,6 @@ class Message(QtWidgets.QMessageBox):
|
||||||
# Idea for a workaround for both:
|
# Idea for a workaround for both:
|
||||||
# Maybe Qt has scheduled events in which case a scheduled polling event could run a function inside the Qt thread that fetches commands and executes them.
|
# Maybe Qt has scheduled events in which case a scheduled polling event could run a function inside the Qt thread that fetches commands and executes them.
|
||||||
# This could work by passing (lambda) functions through a Communication object.
|
# This could work by passing (lambda) functions through a Communication object.
|
||||||
|
#UPDATE: Tried implementing both approaches, neither worked. :(
|
||||||
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():
|
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()
|
app.exec()
|
||||||
|
|
10
main.py
10
main.py
|
@ -26,14 +26,14 @@ configuration = Config(configuration_file_path, default_configuration)
|
||||||
# PROGRAM MAIN WINDOW
|
# PROGRAM MAIN WINDOW
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
# It seems like opening multiple instances already works as intended
|
#Commented out so that I can work on the dockable windows
|
||||||
|
|
||||||
main_window = gui_handler.Window()
|
"""
|
||||||
|
main_window = gui_handler.Window((configuration.get_configuration_value("window size")["x"], configuration.get_configuration_value("window size")["y"]))
|
||||||
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.update_menus(gui_helper.menu_structure)
|
main_window.update_menus(gui_helper.menu_structure)
|
||||||
|
main_window.show()
|
||||||
|
"""
|
||||||
|
|
||||||
#TODO: get resolution of main window on exit and save it back to the configuration
|
#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
|
#TODO: check if the GUI encountered an error in a toolkit agnostic way
|
||||||
|
|
17
util.py
17
util.py
|
@ -1,4 +1,4 @@
|
||||||
import sys, traceback
|
import sys, traceback, threading
|
||||||
|
|
||||||
EXIT_SUCCESS=0
|
EXIT_SUCCESS=0
|
||||||
EXIT_ERROR=1
|
EXIT_ERROR=1
|
||||||
|
@ -27,13 +27,14 @@ def error(message, is_exception=True, handle_gracefully=True):
|
||||||
sys.exit(EXIT_ERROR)
|
sys.exit(EXIT_ERROR)
|
||||||
|
|
||||||
# easy way to communicate across events
|
# easy way to communicate across events
|
||||||
#TODO: make thread safe
|
|
||||||
class Communication:
|
class Communication:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.lock = threading.Lock()
|
||||||
self.__messages = {}
|
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
|
# 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):
|
def send(self, name, content, reverse_order=True, additional_action=None):
|
||||||
|
self.lock.acquire()
|
||||||
if name in self.__messages:
|
if name in self.__messages:
|
||||||
if reverse_order:
|
if reverse_order:
|
||||||
self.__messages[name] = [content] + self.__messages[name]
|
self.__messages[name] = [content] + self.__messages[name]
|
||||||
|
@ -45,32 +46,44 @@ class Communication:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
additional_action()
|
additional_action()
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
# get the content of the first message tagged with name, removes the returned message by default
|
# get the content of the first message tagged with name, removes the returned message by default
|
||||||
def get(self, name, remove=True):
|
def get(self, name, remove=True):
|
||||||
|
self.lock.acquire()
|
||||||
if name in self.__messages and len(self.__messages[name])>0:
|
if name in self.__messages and len(self.__messages[name])>0:
|
||||||
if remove:
|
if remove:
|
||||||
content = self.__messages[name].pop(0)
|
content = self.__messages[name].pop(0)
|
||||||
if len(self.__messages[name])==0:
|
if len(self.__messages[name])==0:
|
||||||
del self.__messages[name]
|
del self.__messages[name]
|
||||||
|
self.lock.release()
|
||||||
return content
|
return content
|
||||||
else:
|
else:
|
||||||
|
self.lock.release()
|
||||||
return self.__messages[name][0]
|
return self.__messages[name][0]
|
||||||
else:
|
else:
|
||||||
|
self.lock.release()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# get the contents for all messages tagged with name
|
# get the contents for all messages tagged with name
|
||||||
def get_all(self, name, clear=False):
|
def get_all(self, name, clear=False):
|
||||||
|
self.lock.acquire()
|
||||||
if name in self.__messages and len(self.__messages[name])>0:
|
if name in self.__messages and len(self.__messages[name])>0:
|
||||||
contents = self.__messages[name]
|
contents = self.__messages[name]
|
||||||
if clear:
|
if clear:
|
||||||
del self.__messages[name]
|
del self.__messages[name]
|
||||||
|
self.lock.release()
|
||||||
return contents
|
return contents
|
||||||
|
else:
|
||||||
|
self.lock.release()
|
||||||
|
return None
|
||||||
|
|
||||||
# deletes all messages tagged with name
|
# deletes all messages tagged with name
|
||||||
def clear(self, name):
|
def clear(self, name):
|
||||||
|
self.lock.acquire()
|
||||||
if name in self.__messages:
|
if name in self.__messages:
|
||||||
del self.__messages[name]
|
del self.__messages[name]
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
if len(self.__messages)>0:
|
if len(self.__messages)>0:
|
||||||
|
|
Reference in New Issue