Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Titles: Rewrite XML parsing/mods, add style_tools #3816

Merged
merged 6 commits into from
Jan 27, 2021

Conversation

ferdnyc
Copy link
Contributor

@ferdnyc ferdnyc commented Nov 1, 2020

Update

Just pushed a few more commits that re-work the title editor data handling and template parsing. Now:

  1. style_to_dict() is used for all style parsing (find_in_list() is now gone)
  2. The TitlesModel wrapper class is now a QObject, and gets parented to MainWindow
  3. The underlying QStandardItemModel-based data model now only has one column. Each "row" in the model holds a self-contained QStandardItem with all of the data for a given template.
    1. Former columns 0 and 1 (the icon and name) are combined
    2. The data from column 2 (the full path to the template) is instead stored in the main/only "column" under a data role which can be accessed by using TitleRoles.PathRole as the role
  4. The editor dialog now persists user-customized filenames for generated titles across launches of the Advanced Editor, instead of always resetting to the default name. Fixes a bug reported in a comment on Titles in Latest Daily Build Linux AppImage not Working in Linux #3832.

Original description

This PR grew out of my testing for the previous three PRs.

There was a lot of redundant code in the Title Editor source, most of it to do with the manipulation of the SVG file's contents to update the style= attribute on various nodes.

I hit on one major efficiency that really streamlined things.

The code was already doing the work to split() the style attribute's string on ;, to extract individual properties. But then it was doing a ton of laborious substring matching and whatnot to find the specific CSS properites it wanted to modify.

What I realized was, just like the property list could be split apart using ;, the properties themselves could be split at the first : to form key-value pairs, and then naturally the whole thing could be loaded into a dict which makes manipulation trivial.

So, this PR adds classes/style_tools.py, a module containing three functions:

def style_to_dict(style: str) -> dict:
    """Explode an SVG node style= attribute string into a dict representation"""

def dict_to_style(styledict: dict) -> str:
    """Turn an exploded style dictionary back into a string"""

def set_if_existing(d: dict, existing_key, new_value):

That last one (which I left out the docstring for, oops) has a pretty obvious name, and does what it says: It updates the value of a dictionary key ONLY IF that key already exists in the dictionary. If not, then it won't insert a new key. Some of the code in the Title Editor was concerned with only updating existing style attributes where they already existed.

Armed with the new style tools, I then rewrote the update-handling methods of the TitleEditor class to use them. The result is a drop of almost 100 lines of code, not to mention a ton of inefficiency and redundancy, from title_editor.py

ard = style_to_dict(s)
set_if_existing(ard, "font-style", self.font_style)
set_if_existing(ard, "font-family", self.font_family)
set_if_existing(ard, "font-size", f"{self.font_size_pixel}px")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, yes, purely by coincidence this PR also introduces the first f-string info the OpenShot codebase, making it officially require Python 3.6 or later to run.

It's time. Python 3.5 has actually been end-of-life since September. And f-strings are just too damn convenient not to use!

Comment on lines 447 to 451
def find_in_list(self, l, value):
'''when passed a partial value, function will return the list index'''
for item in l:
for i, item in enumerate(l):
if item.startswith(value):
return l.index(item)
return i
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also goosed the efficiency of find_in_list() a bit, since it's still used in a couple of parts of the code.

set_if_existing(ard, "font-family", self.font_family)
set_if_existing(ard, "font-family", f"'{self.font_family}'")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old code wasn't doing this either, and it admittedly seems to work fine without it, but technically font family names with a space are supposed to be inside single quotes, in CSS. (No real harm in doing it for all font family names, even one-word ones.)

- New model design uses only a single column, all data for each
  template is stored on the same QStandardItem under different roles
- TitleRoles.PathRole references the file path (former column 2)
- Dialog now preserves user-supplied filename across launches of the
  external Advanced Editor process
- TitlesModel is now a QObject, parented to MainWindow
@jonoomph
Copy link
Member

LGTM! For some reason I thought this was already merged in!? Any-who, it looks great. Nice work!

@jonoomph jonoomph merged commit 34e0bb9 into OpenShot:develop Jan 27, 2021
@ferdnyc ferdnyc deleted the style-tools branch January 7, 2022 02:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants