-
-
Notifications
You must be signed in to change notification settings - Fork 790
[Qt] Add OptionContainer widget #3970
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
[Qt] Add OptionContainer widget #3970
Conversation
Use QIcon.cacheKey() for Icon IMPL_DICT: that's what it's for.
johnzhou721
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This mostly makes sense to me -- good job on enforcing minimum size in content_refreshed and using that to form the size hint.
Some notes, though.
|
Regarding the Icon question - We may need to add a layered approach here; i.e., looking for |
|
I think this is ready for re-review. |
|
@corranwebster Howdy! (just found out you're a former Texan... it's so hot here!) Ack; I've got some other work to do, but I'll take a look at this tomorrow. Also note that the core team (which I'm not a part of) is on holiday break, so expect official response times to be up to 8 days (as they will be checking weekly). |
johnzhou721
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly looks good; all functionality is fine.
Some final layout notes inline -- not sure if this'd be a requirement to merge because the stuff doesn't work reliably on all other backends either.
(This fix is also needed on Cocoa but I'll suggest it here since I'd rather new code we add be correct.)
| return self.native.setCurrentIndex(current_tab_index) | ||
|
|
||
| def rehint(self): | ||
| size = self.native.sizeHint() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be minimumSizeHint to take properly into account the minimum sizes of the child widgets, not just sizeHint.
| min_width = min( | ||
| sub_container.content.interface.layout.min_width | ||
| for sub_container in self.sub_containers | ||
| ) | ||
| min_height = min( | ||
| sub_container.content.interface.layout.min_height | ||
| for sub_container in self.sub_containers | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1 -- this should be maximum, not minimum to ensure that all tabs fit; 2 -- is this neccessary? Qt minimumSizeHint hinting already takes the maximum of all minimum sizes, so we could just set the minimum size of each subcontainer to the determined minimum size of that subcontainer only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After you set the minimum size of the native widget, I'd suggest
prev_intr_width, prev_intr_height = self.interface.intrinsic.width, self.interface.intrinsic.height
self.rehint()
intr_width, intr_height = self.interface.intrinsic.width, self.interface.intrinsic.height
if (prev_intr_width, prev_intr_height) != (intr_width, intr_height):
asyncio.get_running_loop().call_soon_threadsafe(self.interface.refresh)
-- this queues up a second refresh if the intrinsic size of the widget ever changes, so we could have appropriate sizing for the OptionContainer. The interface refresh will perform a layout on the entire tree outside the optioncontainer with correct minimum size for the OptionContianer widget, which will enforce the minimum size properly.
One refresh is queued in the interface code for adding/removing tabs; however, a second refresh is needed because the first refresh will use an outdated minimum size hint, but it's neccesary for that refresh to happen so we could refresh the widget's contents as well.
Along with the minimumSizeHint I mentioned and if I change content_refreshed to this with proper asyncio import and linting, size hinting shuold all work:
def content_refreshed(self, container):
container.native.setMinimumSize(container.content.interface.layout.min_width, container.content.interface.layout.min_height)
prev_intr_width, prev_intr_height = self.interface.intrinsic.width, self.interface.intrinsic.height
self.rehint()
intr_width, intr_height = self.interface.intrinsic.width, self.interface.intrinsic.height
if (prev_intr_width, prev_intr_height) != (intr_width, intr_height):
asyncio.get_running_loop().call_soon_threadsafe(self.interface.refresh)
I don't think we can arrange a change in intrinsic size easily with the current testbed app.
|
@corranwebster The code mostly looks good; I do have reservations about the no-cover though — however I think as part of this PR we can leave it as is and I’ll try to submit a PR with the equivalent fix for other platforms |
|
FYI -- the no-cover can be removed ocne #4010 lands. |
|
Hi @corranwebster and @johnzhou721. It looks like this is ready for the team to review. Can you please verify? Thanks! |
|
@kattni @johnzhou721 I've merged with main and removed the no-cover, so assuming tests pass this is ready for review by the core team, I think. |
Ooops, it looks like #4010 hasn't been merged. So coverage will fail. Although review by the core team would still be useful even with the known issue of coverage. |
freakboy3742
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just merged #4010, and merged this PR with main; assuming test pass, it looks great to me. Thanks for another piece of the Qt puzzle!
freakboy3742
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooof... so very close! Looks like the extra test for OptionContainer content added in #4010 is failing on this PR.
The easy fix is to pytest.fail() in the new assert_supports_content_based_rehint() call. That's what we've done on existing backends (like Winforms); however, that's because the test is a new test for old backends. Given this is a new widget, it's worth taking a quick look to see if there's an obvious fix.
|
Hold that thought... if I get the arguments to |
freakboy3742
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like adding a tolerance for content size (once I got the arguments right) is sufficient.
This adds the OptionContainer widget to the Qt backend.
Implementation seems fairly straightforward, as the Qt API matches the index-based approach to adding tabs.
To get Icon support working for the tabs we need to be able to do a reverse-lookup on the QIcons–we can't do this on the instances, because we get a new QIcon instance on the Python side when we ask for the icon from the tab–but Qt provides a
QIcon.cacheKey()method which provides an identifier based on the actual contents. So we change the IMPL_DICT lookup table to use this as the dictionary key.There is additional question related to #3923 which is whether icon files should search for a backend-related name rather than a platform-related name (ie. "new-tab-qt.png" instead of "new-tab-linux.png"). I'm not sure what's the right thing here.
This is split out from #3966 for ease of review.
Ref #3914.
To Do:
Comparison of internal widget layout with other backends.Internal container widgets aren't resizing to match size of OptionContainer.PR Checklist: