Skip to content

Multi read style #629

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

Merged
merged 30 commits into from
May 10, 2024
Merged

Multi read style #629

merged 30 commits into from
May 10, 2024

Conversation

mizaki
Copy link
Contributor

@mizaki mizaki commented Apr 11, 2024

There's a bit to explain...

I tried a few ways to get the dropdown (delegate "widget" built using other widgets). I went with the QTableWidget as I think the headers (the order/# at least) is needed and so a table view was the easiest there. The model could be a list view but as the QTableWidget comes with a table model it was easier than having to create a new model and a QTableView.

Currently the selection is stored as a dict[str, int], I'm not sure on the best way to go: A list could work using the index for the order. A list of tuples was another option I considered. I went with the dict[str, int] for the JSON saving (although the other options didn't seem to be much of a problem with JSON either).

I went with the custom QTableWidgetItem for sorting as using a QSortFilterProxyModel because it seems the QTableWidget won't allow a proxy model. It may be better to split the data of the dict between the order/# column (data: -1) and the style name (data: "cr") on the read style column. Then the display and data should make sorting easier.

The QProxyStyle to centre the check boxes had to be done because it was annoying me... :) Still need to change the background of the table to match the other QComboBox.

I went with sub-classing the standard QComboBox as the quite extensive changes didn't seem to make sense to subclass CheckableComboBox

The QButtons for moving the read style up and down seemed like the best solution (although I'm sure it's probably bad UX). I plan to add to the settings window a way to set the read and modify styles too.

The command line -t --ttype help message should populate the styles from metadata_styles similar to the metavar?

There are TODO questions which should (hopefully) make sense.

I expect I've forgotten some things too but I'm sure there's still plenty wrong I've missed.

@lordwelch
Copy link
Member

I tried a few ways to get the dropdown (delegate "widget" built using other widgets). I went with the QTableWidget as I think the headers (the order/# at least) is needed and so a table view was the easiest there. The model could be a list view but as the QTableWidget comes with a table model it was easier than having to create a new model and a QTableView.

Have you tried using a item delegate? https://doc.qt.io/qt-5/qitemdelegate.html

Currently the selection is stored as a dict[str, int], I'm not sure on the best way to go: A list could work using the index for the order. A list of tuples was another option I considered. I went with the dict[str, int] for the JSON saving (although the other options didn't seem to be much of a problem with JSON either).

Going with a list will be better and currently things can end up out-of order as the dict is never sorted.

I went with the custom QTableWidgetItem for sorting as using a QSortFilterProxyModel because it seems the QTableWidget won't allow a proxy model. It may be better to split the data of the dict between the order/# column (data: -1) and the style name (data: "cr") on the read style column. Then the display and data should make sorting easier.

I'm not sure any sorting is really needed. I don't like that they re-sort whenever I enable one. Also since merging happens as an overlay the "top" item should be the last in the list when it is overlayed as the last item overlayed is what takes priority.

The QProxyStyle to centre the check boxes had to be done because it was annoying me... :) Still need to change the background of the table to match the other QComboBox.

Most good things happen because someone is annoyed

The QButtons for moving the read style up and down seemed like the best solution (although I'm sure it's probably bad UX). I plan to add to the settings window a way to set the read and modify styles too.

The command line -t --ttype help message should populate the styles from metadata_styles similar to the metavar?

I have an updated message in #616

Also can you rebase this on the current develop branch

@lordwelch
Copy link
Member

And one of your todo's was to make a separate load and save arguments for the cli, yes that will be needed to merge this

@mizaki
Copy link
Contributor Author

mizaki commented Apr 14, 2024

Have you tried using a item delegate? https://doc.qt.io/qt-5/qitemdelegate.html

I'll give it another look. I did try using QStyledItemDelegate. It was really the header that made me switch to QTableWidget but with the extra knowledge I have no I might find it better.

Going with a list will be better and currently things can end up out-of order as the dict is never sorted.

Because the dict has the order it doesn't need to be sorted as the view sorts. It's only re-ordered _setOrderNumbers when an item is unchecked. Otherwise, _move_item alters the dict values. Anyway, using a list for the JSON should be easy enough. For the UserRole data, depending on the sorting, I'm thinking that it might need to store the order number as the list index might not be correct. Would a tuple be better in that case? ("cr", 1)

I'm not sure any sorting is really needed. I don't like that they re-sort whenever I enable one. Also since merging happens as an overlay the "top" item should be the last in the list when it is overlayed as the last item overlayed is what takes priority.

The re-sort made the most sense as they are numbered. Would you rather they stayed in the same location and it's the #/order/priority label changes only? E.g.

- {unchecked} CoMet
2 {checked} Comic Rack
- {unchecked} XML
1 {checked} ComicBookInfo
1 {checked} CoMet
3 {checked} Comic Rack
4 {checked} XML
2 {checked} ComicBookInfo

I went back and forth on the ordering and reasoned that the average user would expect 1 to be the top priority. Naming the column "Priority" (although that takes up extra space) might help? It is "overlay-ed" but I don't think the average user would expect the data in "3" to overwrite the data in "1" etc. Or was it the visual order and not the numbering: "1, 2, 3" (top to bottom) but it should be displayed "3, 2, 1" (top to bottom)?

Also can you rebase this on the current develop branch

Yep. I'll do the same for the OverlayModes too.

@mizaki
Copy link
Contributor Author

mizaki commented Apr 14, 2024

And one of your todo's was to make a separate load and save arguments for the cli, yes that will be needed to merge this

--type-modify and --type-read? Is there any single letters that would make sense?

Should the naming between the CLI and GUI be unified as well? "type" vs "style"

@mizaki
Copy link
Contributor Author

mizaki commented Apr 27, 2024

I have a delegate QListView version in the works too which would be easier now read styles are kept as a list.

Ordering kind of has to come with a list? I altered it so the selection now resets which is more obvious that a change has taken place. Hopefully this helps with the auto-ordering? If not, some idea of how you see it would be helpful. And the order/priority is still outstanding but I'm still of a mind that 1 although it is last still "human logically" is the most understandable without knowing the internal mechanics.

@lordwelch
Copy link
Member

I'm not sure any sorting is really needed. I don't like that they re-sort whenever I enable one. Also since merging happens as an overlay the "top" item should be the last in the list when it is overlayed as the last item overlayed is what takes priority.

I went back and forth on the ordering and reasoned that the average user would expect 1 to be the top priority. Naming the column "Priority" (although that takes up extra space) might help? It is "overlay-ed" but I don't think the average user would expect the data in "3" to overwrite the data in "1" etc. Or was it the visual order and not the numbering: "1, 2, 3" (top to bottom) but it should be displayed "3, 2, 1" (top to bottom)?

Ordering kind of has to come with a list? I altered it so the selection now resets which is more obvious that a change has taken place. Hopefully this helps with the auto-ordering? If not, some idea of how you see it would be helpful. And the order/priority is still outstanding but I'm still of a mind that 1 although it is last still "human logically" is the most understandable without knowing the internal mechanics.

See renamewindow.py line 89 where it isn't reversed

Copy link
Member

@lordwelch lordwelch left a comment

Choose a reason for hiding this comment

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

Also you still have 20+ commits to rebase out

@lordwelch
Copy link
Member

Same with altering the order, they do not move so the numbers will be listed "out of order" but the user put them that way so it's all good (and sorts on dropdown close)?

I think now then that a spinbox for the "order" will work better. Just need a bit of logic to alter the other numbers.

I'm not sure we need to show the number. It already has the order by being able to position the styles. If you really want a number to show the user which item is first, make it based on the row number and update it when an item is moved.
There are only a few cases when being able to move a style to an exact index is going to be useful and there aren't enough separate styles for that.

In this case it also makes senses to change itemChanged to dropdownClosed and do the dirty flag check and update the overlay'ed data in the tagger window etc. then?

Yes, you'll have to make your own signal and trigger it when the dropdown is closed

@mizaki
Copy link
Contributor Author

mizaki commented May 6, 2024

Using item delegate:
image
Still a few small tweaks could be done but overall it's mostly there.

It requires a little merry-go-round with signals but otherwise it gets to a custom rolled view/model to just re-implement what the combox already does.

I believe for you the modify style dropdown checkbox are the normal size but for me they are massive. Not sure on windows so a unifying pass is probably needed.

The movement arrows are only shown for checked items but it may be as well to show them for all.

Comment on lines 87 to 91
md, error = self.parent().overlay_ca_read_style(self.load_data_styles, ca)
# How much should we care about this error? Notify user or not?
if error is not None:
logger.error("Failed to load metadata for %s: %s", ca.path, error)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Should the user be informed in a window or is it not all that relevant here?

Copy link
Member

Choose a reason for hiding this comment

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

The user should have already been informed but we should still let them know here

@mizaki
Copy link
Contributor Author

mizaki commented May 6, 2024

The CheckableOrderComboBox I subbed from QComboBox for initial ease. I'm not sure if much would be gained from sub-classing CheckableComboBox instead?

@mizaki mizaki marked this pull request as ready for review May 6, 2024 20:27
@lordwelch
Copy link
Member

Nope their also bigger for me
Screenshot 2024-05-06 at 6 39 38 PM

But it also doesn't match the style of the other combobox
Screenshot 2024-05-06 at 6 56 25 PM

@mizaki
Copy link
Contributor Author

mizaki commented May 7, 2024

Nope their also bigger for me

Seems to be known. Wonder about PyQt6...? Need to switch to 6 or work around the combobox placeholder text issue too.

Use the same delegate for both modify and read and hide the arrows might be the best answer?

@mizaki
Copy link
Contributor Author

mizaki commented May 8, 2024

PyQt6 does do the same drawing the checkbox differently so I'll unify CheckableComboBox and CheckableOrderComboBox to look the same.

@lordwelch
Copy link
Member

So I found out why it's different.
The combobox uses a menu for displaying the items by default https://github.com/qt/qtbase/blob/9a61bc5dfc3c68200dbf48fd79771a856fae26d5/src/widgets/widgets/qcombobox_p.h#L237
For macos they use a menu check https://github.com/qt/qtbase/blob/9a61bc5dfc3c68200dbf48fd79771a856fae26d5/src/plugins/styles/mac/qmacstyle_mac.mm#L4164C1-L4185C14

Here's a patch. I also removed the sizeHint and it went down to a normal size.
checkbox-fix.patch

@mizaki
Copy link
Contributor Author

mizaki commented May 9, 2024

So I found out why it's different. The combobox uses a menu for displaying the items by default https://github.com/qt/qtbase/blob/9a61bc5dfc3c68200dbf48fd79771a856fae26d5/src/widgets/widgets/qcombobox_p.h#L237 For macos they use a menu check https://github.com/qt/qtbase/blob/9a61bc5dfc3c68200dbf48fd79771a856fae26d5/src/plugins/styles/mac/qmacstyle_mac.mm#L4164C1-L4185C14

Here's a patch. I also removed the sizeHint and it went down to a normal size. checkbox-fix.patch

The CheckableComboBox and CheckableOrderComboBox both look the same for you now?

My issue was CheckableComboBox making the checkbox big:
image
(And going by the cut off text the sizeHint is using the small/correct size box for the calc.)

Using CheckableOrderComboBox gives me this by default (which is the "correct" size checkbox):
image

Copy link
Member

@lordwelch lordwelch left a comment

Choose a reason for hiding this comment

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

I think the best option would be to re-create QComboMenuDelegate in python and then add the buttons onto the end and extend the sizehint width to include the buttons.

But I don't really care I'll merge how it looks as is.
There are 4 comments that I want taken care of first before I merge.

self.save_data_styles: list[str] = config[0].internal__save_data_style
self.load_data_style: str = config[0].internal__load_data_style
self.load_data_styles: list[str] = list(reversed(config[0].internal__load_data_style))
Copy link
Member

Choose a reason for hiding this comment

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

This shouldn't be reversed here. Why is it being saved in the wrong order

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted.

I thought it made sense to save in the user facing order but it doesn't really.

@@ -2065,6 +2097,7 @@ def closeEvent(self, event: QtGui.QCloseEvent) -> None:
self.config[0].internal__sort_column,
self.config[0].internal__sort_direction,
) = self.fileSelectionList.get_sorting()
self.config[0].internal__load_data_style = self.cbLoadDataStyle.currentData()
Copy link
Member

Choose a reason for hiding this comment

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

Why is this added here? why isn't this set in the equivalent place that the save data style is set

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted.

This was because of the whole "reversed" thing.

):
self.load_data_style = self.cbLoadDataStyle.itemData(s)
self.config[0].internal__load_data_style = self.load_data_style
Copy link
Member

Choose a reason for hiding this comment

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

Why was this removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted.

It was because the self.config[0].internal__load_data_style is only used when saving and it had to be unreversed and so was set on closeEvent it didn't need to be set. Thinking on it, that may have caused issues with the settings window saving.

@lordwelch
Copy link
Member

The only last thing is the calls to reversed it should be consistent you need to have the reversed calls either both in customwidgets.py or both in taggerwindow.py. Putting them both in taggerwindow.py and putting a comment in set_load_data_style and adjust_load_style_combo explaining why it's reversed should be good. I mainly don't want anyone in 6 months or longer looking at this and getting confused about why the list gets reversed on them

@mizaki
Copy link
Contributor Author

mizaki commented May 10, 2024

The only last thing is the calls to reversed it should be consistent you need to have the reversed calls either both in customwidgets.py or both in taggerwindow.py. Putting them both in taggerwindow.py and putting a comment in set_load_data_style and adjust_load_style_combo explaining why it's reversed should be good. I mainly don't want anyone in 6 months or longer looking at this and getting confused about why the list gets reversed on them

I used your comments and reverse only in taggerwindow. I didn't use the eventClose for self.config[0].internal__load_data_style = self.load_data_styles and left it in set_load_data_style because I think it'll cause problems with saving of settings in the settings window (using the old value).

@lordwelch lordwelch merged commit 851339d into comictagger:develop May 10, 2024
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