Closed dstroy0 closed 2 years ago
os.uname
is platform specific. Its better to use platform.uname()
. It was designed to be a drop-in replacement for better cross-platform code. Here's a test from a python interactive REPL:
>>> import platform
>>> uname_tuple = platform.uname()
>>> print(uname_tuple)
uname_result(system='Windows', node='B-DESKTOP', release='10', version='10.0.22000', machine='AMD64')
>>> print(uname_tuple.system)
Windows
I'm working on the tab button dialog boxes today.
Got a bit done today, it's pretty neat! I'm figuring out how to use the signals, had to do that to auto update the command length.
I made an object to put commandParameters into when we pull in all fields in the command settings menu with apply.
Input validation is very nice, I made it for the function name, command string, and the ids. the regexp are just temporary until I get the settings_tree menu complete, I'm planning on generating that from config.h after I smoosh config and advanced_config together. Then parsing that file, and setting those regexp based off of that input.
We can add items to the tree on InputHandler settings tab, and only the 3rd col is editable by double clicking. Now I'm going to work on parsing user settings out of config.h.
Figuring out little bits at a time, this thing is really cool. I keep getting distracted and going on little tangents. I'm having so much fun when I'm working on it. I'm really close to being able to parse the config file the way I want to; but then I learn something new and refactor things. I absolutely love this part of learning, when everything is new and fresh. It's like leveling up in a really good rpg or something. I hope you've been well. If you've got any thoughts on anything please let me know. Happy belated father's day if you're a dad.
parsing the settings out of the config file, they're going to be the 4th match group
(\s*[\/]*\s*)(\s*#define\s*)(UI_\S*\s*)(\d*)
and progmem is differentiated like so
(\s*[\/]*\s*)(\s*#define\s*)(UI_\S*PGM_LEN\s*)(\d*)
The settings tree is populating from config.h. I'm going to put the whole tree into a dict. Now I have to connect up the edit to the list of strings that makes up config.h, and save everything to the session json. Pretty cool!
Will there also be an option to import a config from json?
Yes, that's the idea, speed and ease of setup.
Awesome! That would definitely help with sharing/tweaking known-good configs. 😃
I'm adding cli_gen_tool.json
(the session json) to the ignore list so that a new one is generated on first run. Also so I don't accidentally push mine out after messing with unimplemented things.
Couldn't you just use a virtual json if a json file does not exist? I like the gitignore idea.
import json, os
default_config = dict(
key="value",
# ...
)
if os.path.isfile("config.json"):
with open("config.json", "r", encoding="utf_8") as conf:
config = json.load(conf)
else:
config = default_config.copy()
Yes, it's a QFile so I can just https://doc.qt.io/qt-6/qfile.html#exists-1
file = QFile(path)
if not file.exists():
self.session = json.loads(self.defaultGuiOpt)
Yeah, that's sounds right. I'm so used to working with python std libs. 😊
I really like how I can shorten variable access in python it makes it much more readable
combo boxes for true/false fields pass their sub dict that contains text fields and the qtreewidgetitem and qcombobox objects on index change. Everything emits a signal when edited in the settings tree now. Time to work on the code preview for config.h
. It will be updated with every item change, which is nice!
config.h
file preview is working
I just did it quick and dirty to get an idea of how to work with the QPlainTextEdit
object that's doing the preview for us. It's a one way preview.
I need to add an output category as another root object so that setup.h can be generated
This is starting to look close to finished or at least a working proof of concept. I wish the QT implementation for desktops supported the OS's color scheme (light vs dark). It'd also be nice if the text viewer had some syntax highlighting incorporated, but I don't know if that's a task for other libraries like pygments.
There are rich text widgets and a browser so I think that's possible, the backend is a little messy and needs organized to make it easy but highlighting what the user has changed is possible based on other projects I've looked at, it would just hook into the dict and make a has_changed field true/false or something. I've been thinking about that and I think that if I can change the copy action to just pick up the plain text that would be best. Because even though we would like people to press the generate button they might want to copy paste and do their own thing.
We can change the theme from light to dark as well I don't know if there's a toggle for it programmatically but it's an option I can set in the designer
We can change the theme from light to dark as well I don't know if there's a toggle for it programmatically but it's an option I can set in the designer
If it needs to be hard coded, then I'd vote for dark theme. Its better for those of us spending extraordinary amounts of time looking at screens. Of course, this is your app, so the final decision should be your preference.
Everything I use is set to dark theme (when possible).
Yeah all of mine are as well I just hadn't even thought about doing it.
I can do it with a stylesheet or by setting up a palette manually and passing that to the app in main with setStyleSheet
or setPalette
respectively
That may be more work than it is worth at this stage. The QT docs have a page with some options: https://wiki.qt.io/Gallery_of_Qt_CSS_Based_Styles
After a quick look, I think
I just used someone's module. The geometry needs adjusting but it looks pretty good. Dark theme it up.
There's a ton of little things to do but the basic poc for most things are in place. I'm going to work on that output section in settings_tree to generate setup.h and then it'll be time to work on generating commands and functions. Separately, I think everything needs like 5 pixels because of the rounded corners some text is getting cut off.
the code preview update is updating the wrong text widgets I'll have to look into that tomorrow
something is happening here:
# build code preview trees
def build_code_preview_tree(self):
for key in self.code_preview_dict['files']:
self.code_preview_dict['files'][key]['filename'] = key
for tab in range(0,2):
if tab == 0:
tree = self.ui.codePreview_1
else:
tree = self.ui.codePreview_2
tree.setHeaderLabels(['File', 'Contents'])
tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
tree.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
tree.setColumnCount(2)
for key in self.code_preview_dict['files']:
self.code_preview_dict['files'][key]['tree_item'][tab] = QTreeWidgetItem(tree, [key,''])
self.code_preview_dict['files'][key]['tree_item'][tab].setIcon(0, self.ui.fileIcon)
self.code_preview_dict['files'][key]['text_widget'][tab] = QPlainTextEdit()
self.code_preview_dict['files'][key]['text_widget'][tab].setObjectName(str(key))
self.code_preview_dict['files'][key]['contents_item'][tab] = QTreeWidgetItem(self.code_preview_dict['files'][key]['tree_item'][tab])
tree.setItemWidget(self.code_preview_dict['files'][key]['contents_item'][tab], 0, self.code_preview_dict['files'][key]['text_widget'][tab])
print(self.code_preview_dict['files'][key]['text_widget'][tab])
self.code_preview_dict['files'][key]['contents_item'][tab].setFirstColumnSpanned(True)
self.code_preview_dict['files'][key]['file_lines_list'] = self.cliOpt['config']['file_lines']
if key == 'config.h':
new_line_list = []
code_string = ''
for line in self.code_preview_dict['files']['config.h']['file_lines_list']:
new_line_list.append(line+'\n')
code_string = code_string + line + '\n'
self.code_preview_dict['files']['config.h']['file_lines_list'] = new_line_list
self.code_preview_dict['files']['config.h']['text_widget'][tab].setPlainText(code_string)
for key in self.code_preview_dict['files']:
print(key)
print(self.code_preview_dict['files'][key]['text_widget'])
# end build_code_preview_tree()
this is the term out:
<PySide6.QtWidgets.QPlainTextEdit(0x20a05478840, name="config.h") at 0x0000020A05AAEAC0>
<PySide6.QtWidgets.QPlainTextEdit(0x20a054e2a70, name="setup.h") at 0x0000020A05AB3040>
<PySide6.QtWidgets.QPlainTextEdit(0x20a054e4360, name="parameters.h") at 0x0000020A05AB30C0>
<PySide6.QtWidgets.QPlainTextEdit(0x20a054e42f0, name="functions.h") at 0x0000020A05AB3200>
<PySide6.QtWidgets.QPlainTextEdit(0x20a054e6900, name="functions.cpp") at 0x0000020A05AB3340>
<PySide6.QtWidgets.QPlainTextEdit(0x20a054e0a10, name="config.h") at 0x0000020A05AB3500>
<PySide6.QtWidgets.QPlainTextEdit(0x20a055b4630, name="setup.h") at 0x0000020A05AB3640>
<PySide6.QtWidgets.QPlainTextEdit(0x20a055b6af0, name="parameters.h") at 0x0000020A05AB3780>
<PySide6.QtWidgets.QPlainTextEdit(0x20a055b6d20, name="functions.h") at 0x0000020A05AB38C0>
<PySide6.QtWidgets.QPlainTextEdit(0x20a055baf30, name="functions.cpp") at 0x0000020A05AB3A00>
config.h
{0: <PySide6.QtWidgets.QPlainTextEdit(0x20a054e6900, name="functions.cpp") at 0x0000020A05AB3340>, 1: <PySide6.QtWidgets.QPlainTextEdit(0x20a055baf30, name="functions.cpp") at 0x0000020A05AB3A00>}
setup.h
{0: <PySide6.QtWidgets.QPlainTextEdit(0x20a054e6900, name="functions.cpp") at 0x0000020A05AB3340>, 1: <PySide6.QtWidgets.QPlainTextEdit(0x20a055baf30, name="functions.cpp") at 0x0000020A05AB3A00>}
parameters.h
{0: <PySide6.QtWidgets.QPlainTextEdit(0x20a054e6900, name="functions.cpp") at 0x0000020A05AB3340>, 1: <PySide6.QtWidgets.QPlainTextEdit(0x20a055baf30, name="functions.cpp") at 0x0000020A05AB3A00>}
functions.h
{0: <PySide6.QtWidgets.QPlainTextEdit(0x20a054e6900, name="functions.cpp") at 0x0000020A05AB3340>, 1: <PySide6.QtWidgets.QPlainTextEdit(0x20a055baf30, name="functions.cpp") at 0x0000020A05AB3A00>}
functions.cpp
{0: <PySide6.QtWidgets.QPlainTextEdit(0x20a054e6900, name="functions.cpp") at 0x0000020A05AB3340>, 1: <PySide6.QtWidgets.QPlainTextEdit(0x20a055baf30, name="functions.cpp") at 0x0000020A05AB3A00>}
Whatever is happening is what's causing the text to get refreshed in the incorrect QPlainTextEdit
widget.
I think it might have something to do with the way I built the dict
Is this a nono?
generated_filename_subdict = {'filename':'',
'file_lines_list':[],
'tree_item':{},
'contents_item':{},
'text_widget':{0:'',1:''}}
#generated_filename_dict = OrderedDict()
generated_filename_dict = {'config.h':generated_filename_subdict,
'setup.h':generated_filename_subdict,
'parameters.h':generated_filename_subdict,
'functions.h':generated_filename_subdict,
'functions.cpp':generated_filename_subdict}
Yeah, it looks like the generated_filename_subdict
is pointed at by all of the keys
Yes, that was it.
Now that's all fixed, I made it so the text pops to where the user made a change like you were talking about, and we can highlight the change individually so that's probably where we can wrap it with some html to change the color.
All Python objects are just pointers under the hood. If you want to use a copy of a dict, then call <dict_name>.copy()
.
I tried that, it didn't work. I think because copy only makes a shallow copy.
What would have worked is probably generated_filename_dict['config.h'] = generated_filename_subdict.copy()
but I think the copy would be redundant since the assignment operator does the deep copy right?
There is also a deepcopy()
method in a std lib called copy. So
from copy import deepcopy
some_dict = dict(key="value")
copied_dict = deepcopy(some_dict)
Assignment operators are actually storing the pointer to an object and increasing the object's internal reference counter by 1. The reference counter is how python does garbage collection.
The method organization is driving me nuts; I keep hesitating organizing them because I merge, cut and paste them constantly but there are so many now it's slowing me down. I think by reference order in init would probably make the most sense?
Yeah I figured the file length was eventually going to be a problem. You could split it up into classes (which could be imported) or just put functions into separate files that are imported as modules.
Using pylint helped me a lot when I was getting the hang of python. Some rules seem ridiculous, but they are born of best practices. There is a way to have vscode use pylint in the python extension settings.
Pylint also has duplicate code checking, just as a warning.
BTW, It is pretty common to use black as a code formatter tool in python. In fact if you right click the python code (anywhere) and select "Format Document", then vscode should automatically ask you if it is ok to install black.
Cool, I installed the black extension and used it on the code.
You'll notice that the indentation is not the same as C++ convention. This is because whitespace is not ignore by the python interpreter (though a C++ compiler does ignore whitespace). So, indentation is rather important, thus it is a part of the PEP8 conventional standards.
Using black will let you get on with your life and still adhere to PEP8 standards.
I found that using a stub lib for c-extensions (like pyside) will help with auto-completion in vscode. Installing https://pypi.org/project/IceSpringPySideStubs-PySide6/ will help with that when using pyside6 API. You may have to restart vscode (or do a window reload) for the stub lib to get loaded properly.
A sub lib tells IDEs what data type is used for objects in python code. They also have the benefit of listing the exposing members of modules and data structures.
I'm going to start work on one in python, since I don't know much python this'll be fun. It'll be aimed at user commands.
I'm looking at using tkinter to build the gui, again I don't know how to yet so this may change.
Require the user to copy/paste local/local include the library, add one line to their setup and loop functions. It should generate/edit: InputHandler/src/config/config.h - e ih_cli/ - g ih_cli/cli_setup.h - g ih_cli/cli_commandparameters.h - g ih_cli/cli_functions.h - g ih_cli/cli_functions.cpp - g