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

Fixed dialog windows tiling like main windows on tiling window managers. #464

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

ChloeZamorano
Copy link
Contributor

I could not find in the documentation a list of what files are for dialog windows or anything along those lines, so I searched for instances of self.setWindowModality and as far as I'm seeing, it looks like that's all of them? In any case, all I did was add self.setWindowFlags(Qt.Dialog) to the init functions of every modal I found that calls setWindowModality, the files affected are:

  • add_field.py
  • file_extension.py
  • fix_dupes.py
  • fix_unlinked.py
  • folders_to_tags.py
  • mirror_entities.py
  • panel.py
  • progress.py

Do let me know if I missed any or if some of these shouldn't be changed, as I'm not familiar with this code base or this style of making GUIs.

This fix has not been tested on Wayland yet, but based on the assumption that Qt behaves the same on both display servers, it should work the same, as this is a very basic feature that both display servers should have.

This fix is for issue #392

For any discussions or comments, use my Discord (chloevz) if a quick reply is desired, as I don't tend to check Github daily.

@CyanVoxel CyanVoxel added Type: Bug Something isn't working as intended Type: UI/UX User interface and/or user experience Status: Review Needed A review of this is needed labels Sep 7, 2024
@eivl
Copy link
Collaborator

eivl commented Sep 7, 2024

Qt.Qdialog does not exist, Qdialog under Pyside6.QtWidget does exist.

@ChloeZamorano
Copy link
Contributor Author

I am genuinely out of words about that, the program worked just fine on my end with Qt.Dialog and it didn't seem to print any warnings or anything different from otherwise. Whatever though, inheriting QDialog instead of QWidget seems to work fine as well, at least I hope it does.

@yedpodtrzitko
Copy link
Collaborator

@ChloeZamorano can you please fix the failing pipeline?

@CyanVoxel CyanVoxel added Status: Changes Requested Changes are quested to this and removed Status: Review Needed A review of this is needed labels Sep 9, 2024
@CyanVoxel
Copy link
Member

@ChloeZamorano Any updates on this?

@ChloeZamorano
Copy link
Contributor Author

@CyanVoxel Hi, sorry, I forgot about this and hadn't used Github in a while (Been using Codeberg for a while now). No updates whatsoever, but let me elaborate a little.

So the stuff in the issue itself is all correct as far as I can tell, and both things I tried doing to fix it actually worked fine on my machine. I just don't know what this "failing pipeline" means on a functional level, I don't really ever work with interpreted languages, and I don't remember exactly what the errors in the "checks" were (Which are not showing up anymore for some reason?) but I think it said something about the class being missing?

In any case, I'm pretty sure the changes I made should work fine according to the documentation I found online, and it did when I tested it on a real case scenario. So unless it's some dependency versioning shenanigans or I just messed up massively and used the wrong API? Because with how Python works, I think two different APIs for the same thing could potentially have interchangeable components? I just don't really know what actually happened here and my memory's bad, but I'd be glad to help out in some way if it's still an issue in the main repo.

@CyanVoxel
Copy link
Member

@ChloeZamorano Since this PR is quite a bit behind main now it's hard to tell exactly what's going on, you'll need to rebase or update from main in order to clear up the merge conflicts and get a better idea of what the issues are, if any remain afterwards. It would also be a good idea to reinstall your PIP dependencies since those have likely updated as well.

Also make sure that you're formatting and checking your code with Ruff and MyPy, as talked about in the CONTRIBUTING.md. The "failing pipeline" is in reference to our automated CI checks for these on the GitHub side, nothing to do with interpreted languages.

This commit was made in order to account for users who may already have
a Python installation that isn't 3.12.

A good real world scenario where this may be a problem is users running
on rolling release Linux distributions, such as Arch Linux which
provides bleeding edge updates in a weekly basis.

Continuing with Arch Linux as an example, it provides Python 3.13, which
the current version of TagStudio doesn't seem to work with, an issue I
encountered myself this morning.

In some systems like Windows, this may not matter, but it is an issue
nonetheless, and users using a package manager centric system can't be
expected to downgrade/upgrade their Python version for TagStudio, as
this may cause issues in their system.

The easiest way to solve this is with pyenv, which enables users to
install other Python versions independent from each other, aside from
the system install, and allows specifying a version to use for a
directory (And its subdirectories), the current terminal session, or the
entire system if desired.

Here is a short, technical and objective summary of the changes:
- Updated `.gitignore` to to ignore `.python-version` which pyenv uses.
- Updated CONTRIBUTING.md to refer to pyenv for versioning issues.
    - pyenv is listed as a prerequisite, specifying in parenthesis that it's only for when your Python install isn't 3.12.
    - The "Creating a Python Virtual Environment" section now has an additional step at the beginning, to check that the current Python installation is 3.12.
        - As part of this added step, there are steps to use pyenv to install Python 3.12 separately from the existing Python installation, and activate it for the TagStudio root folder, in case it's not the appropriate version.
    - The numbering of the other steps was offset accordingly.
    - The "Manually Launching (Outside of an IDE)" section now refers to the above first step, should the user encounter some kind of error.
Some users may not be using the default shell for their system, and
Linux users are the most likely to do this, though this can be seen in
macOS as well. People will often use shells like fish which is not POSIX
compliant but works very well and has great auto-completion, it's very
user friendly.

The reason why I care about this is that the instructions specify to use
.venv/bin/activate which is a bash script and will not run on fish or
csh, and if you take a look at the script, indeed it says it will only
run with bash.

Python will provide alternate scripts for other shells, and at least on
my system (CachyOS), those are scripts for Powershell, bash, fish and
csh. People using these alternate shells, who don't know this may be
confused when running the script referenced in CONTRIBUTING.md and
seeing it fail completely.

The only real change in this commit was adding under the "Linux/macOS"
command in step 3 (step 2 prior to my last commit) of the "Creating a
Python Virtual Environment" section, a short instruction to switch to
the default shell, or use the appropriate script for the user's
preferred shell if any (Since, at least on my system, there aren't
scripts for every shell, for example there is no activate.zsh file).
@ChloeZamorano
Copy link
Contributor Author

After snooping around the internet, and messing with Ruff and MyPy, I think it's just never gonna pass a test without patching PySide6 itself??

I looked around, and triple check that I'm following the right documentation for the right version of the right API, and it seems fine, and still the program will run fine with no warnings or anything and do what I expect it to do with these windows, but still it won't pass MyPy.

I looked around my .venv folder for a little bit and found Pyside6.QtCoer.Qt.Dialog does exist:
image

Pyside6.QtWidget.Qdialog doesn't seem to be a thing on the other hand?

I also looked around for similar issues and came across these examples:
https://stackoverflow.com/questions/70228015/mypy-complains-about-qt-alignmentflag
freedomofpress/dangerzone#320

To me, it looks like it's a case of PySide6 missing type hints for apparently several things that do function fine; using self.setWindowFlag(Qt.Dialog, on=True) # type: ignore doesn't seem to trip MyPy or Ruff at all, and again, works perfectly fine when actually running the application itself. People also talk about using PySide2 stubs for PySide6 to fix some of these issues, but I think that kind of fix is outside the scope of this pull request.

I guess using # type: ignore works? As much of a band-aid that is for a fix? I also tried what @eivl suggested, but that didn't run and didn't pass MyPy, I tried a couple other similar things, but just what I did initially with # type: ignore seems to be the only immediate solution that actually works at all so far, unless I'm stupid and missed yet another really obvious thing?

Also, running PyTest gave me some errors that are unrelated, even with no changes whatsoever from upstream, and I don't know what that's actually about, if not some mismatch of implementation or something, just thought I'd bring that up because I did rebase to the latest upstream commit. So here's an screenshot of an small bit of that, and I guess just ask if that's supposed to happen?
image

I also committed some minor changes to the documentation, just regarding using different Python versions with pyenv and venv activation scripts for shells that aren't bash.

I'll reopen the pull request when we decide on what to do about the MyPy error with the window flags, if anything, but for now I think I'll just leave this comment here.

@CyanVoxel
Copy link
Member

Could you commit your changes so I could see what's going on with the PR? It's currently empty for me so I can't test or investigate. You can also open the PR as a draft instead of having it closed.

This may be an issue where we can just use # type: ignore, though I don't know if mypy is actually giving a valid warning at the moment.

As for the pytests, they shouldn't be giving those errors if you haven't purposely modified them. There's a --snapshot-update flag to use with pytest if you are intending to update the tests, but that doesn't seem to be the case here. For these tests we've ran into an issue once in the past where the rendered output of the vector tests would differ from machine to machine due to minute differences in anti-aliasing techniques. I thought the tests were fixed at this point, but maybe the issue was just made more unlikely to occur. In any case, as long as the tests pass on the GitHub side and no changes are accidentally committed then it should be fine.

Set the Qt.Dialog flag for modal windows, such as "Add Field" so that
they will be seen as dialogs in the backend. This change is unlikely to
be at all noticeable in systems like Windows, but for users running
tiling window managers like bspwm or Sway, this will prevent these modal
windows from being tiled alongside the main window, instead they will be
floating on top, which is the expected behaviour seen on floating window
managers, like the ones used by Windows and macOS.

Added self.setWindowFlag(Qt.Dialog, on=True) # type: ignore to the
following files:
- tagstudio/src/qt/modals/add_field.py
- tagstudio/src/qt/modals/delete_unlinked.py
- tagstudio/src/qt/modals/drop_import.py
- tagstudio/src/qt/modals/file_extension.py
- tagstudio/src/qt/modals/fix_dupes.py
- tagstudio/src/qt/modals/fix_unlinked.py
- tagstudio/src/qt/modals/folders_to_tags.py
- tagstudio/src/qt/modals/mirror_entities.py
- tagstudio/src/qt/widgets/paged_panel/paged_panel.py
- tagstudio/src/qt/widgets/panel.py
- tagstudio/src/qt/widgets/progress.py

Note that without adding # type: ignore, MyPy *will* give out an error,
presumably because PySide6 is missing type hints for several things, and
this may *or* may not be a justifiable use of # type: ignore, which
throws the MyPy type checking for that line out the window.

Ref: TagStudioDev#392, TagStudioDev#464
@ChloeZamorano ChloeZamorano reopened this Jan 18, 2025
@ChloeZamorano ChloeZamorano marked this pull request as draft January 18, 2025 02:07
@ChloeZamorano
Copy link
Contributor Author

I made the corresponding changes and committed them to my fork, now I'll make dinner though, so I probably won't reply until tomorrow.

I also checked the PyTest thing and yeah, sure enough that does work perfectly fine with --snapshot-update. If the algorithm for checking that can be altered from a simple hash check, perhaps it'd be viable to test for some "image difference index" type of thing? Just throwing an idea but really, knowing it doesn't seem to actually matter, I'm gonna leave it alone for now. Though, maybe it has something to do with the borders that I configured bspwm to add to windows?
image

@ChloeZamorano
Copy link
Contributor Author

@CyanVoxel any updates on the mypy ignore thing?

@CyanVoxel
Copy link
Member

Hello! Sorry for the delay, I've been busy getting things shaped up for the current pre-releases.

The good news is that yes, it looks like that mypy is incorrect here and self.setWindowFlag(Qt.Dialog, on=True) is perfectly valid, so the # type: ignore comment is warranted here. I haven't pulled this PR and instead just added the line to some of the modal widgets and don't notice any immediate issues, which is a good sign.

Since main has changed a lot it may be worth it to start fresh - alternatively I could open a new PR with the dialog lines added to all the new and existing modals. Assuming my old Arch/Hyprland partition will boot then I can probably test these changes on Windows/Mac/Linux, though if not then I won't be able to verify that the changes work for tiling WMs myself.

@ChloeZamorano
Copy link
Contributor Author

Excellent, if I did miss any modals that should be dialogues, it's because the way I looked for them was by searching for setWindowModality calls, so if anything's missing that, it's not gonna be fixed in my fork, but at this point it'd just be a matter of adding the setWindowFlag there, and that would be that.

Also, if you got an spare pendrive, you can just boot your main machine off of that in some distro with a graphical installer, like Mint or some of the Arch forks. It's not gonna be recorded into the pendrive, but I know at least some of those let you install packages in the live image. Otherwise, a virtual machine may suffice, even on an slow machine, a default Arch install shouldn't be hard to virtualize. I can also go fetch my friends to see if they wanna test the pull request, which I probably will later today.

I'm also hoping for input on the small additions I made to the documentation, though maybe that should be a separate pull request.

@CyanVoxel
Copy link
Member

I'm also hoping for input on the small additions I made to the documentation, though maybe that should be a separate pull request.

There's some good additions in there, but yes that would be better served in a new PR if possible. I could give some input here and now or I could wait for if you'd like to split that off into a new PR

@ChloeZamorano
Copy link
Contributor Author

I'd like to have input on it and then split it to a dedicated PR, so that PR can be a single commit in contrast to the mess this one ended up being.

This revert is for moving the referenced changes to their own pull request.

Refs: 15f4f38, a25ef8c
@ChloeZamorano ChloeZamorano marked this pull request as ready for review February 4, 2025 23:27
ChloeZamorano added a commit to ChloeZamorano/TagStudio that referenced this pull request Feb 6, 2025
CyanVoxel pushed a commit that referenced this pull request Feb 7, 2025
…791)

* docs: refer to pyenv in CONTRIBUTING.md

This commit was made in order to account for users who may already have
a Python installation that isn't 3.12.

A good real world scenario where this may be a problem is users running
on rolling release Linux distributions, such as Arch Linux which
provides bleeding edge updates in a weekly basis.

Continuing with Arch Linux as an example, it provides Python 3.13, which
the current version of TagStudio doesn't seem to work with, an issue I
encountered myself this morning.

In some systems like Windows, this may not matter, but it is an issue
nonetheless, and users using a package manager centric system can't be
expected to downgrade/upgrade their Python version for TagStudio, as
this may cause issues in their system.

The easiest way to solve this is with pyenv, which enables users to
install other Python versions independent from each other, aside from
the system install, and allows specifying a version to use for a
directory (And its subdirectories), the current terminal session, or the
entire system if desired.

Here is a short, technical and objective summary of the changes:
- Updated `.gitignore` to to ignore `.python-version` which pyenv uses.
- Updated CONTRIBUTING.md to refer to pyenv for versioning issues.
    - pyenv is listed as a prerequisite, specifying in parenthesis that it's only for when your Python install isn't 3.12.
    - The "Creating a Python Virtual Environment" section now has an additional step at the beginning, to check that the current Python installation is 3.12.
        - As part of this added step, there are steps to use pyenv to install Python 3.12 separately from the existing Python installation, and activate it for the TagStudio root folder, in case it's not the appropriate version.
    - The numbering of the other steps was offset accordingly.
    - The "Manually Launching (Outside of an IDE)" section now refers to the above first step, should the user encounter some kind of error.

* docs: refer to alternate shells in CONTRIBUTING.md

Some users may not be using the default shell for their system, and
Linux users are the most likely to do this, though this can be seen in
macOS as well. People will often use shells like fish which is not POSIX
compliant but works very well and has great auto-completion, it's very
user friendly.

The reason why I care about this is that the instructions specify to use
.venv/bin/activate which is a bash script and will not run on fish or
csh, and if you take a look at the script, indeed it says it will only
run with bash.

Python will provide alternate scripts for other shells, and at least on
my system (CachyOS), those are scripts for Powershell, bash, fish and
csh. People using these alternate shells, who don't know this may be
confused when running the script referenced in CONTRIBUTING.md and
seeing it fail completely.

The only real change in this commit was adding under the "Linux/macOS"
command in step 3 (step 2 prior to my last commit) of the "Creating a
Python Virtual Environment" section, a short instruction to switch to
the default shell, or use the appropriate script for the user's
preferred shell if any (Since, at least on my system, there aren't
scripts for every shell, for example there is no activate.zsh file).

* fix: modal windows now have the Qt.Dialog flag

Set the Qt.Dialog flag for modal windows, such as "Add Field" so that
they will be seen as dialogs in the backend. This change is unlikely to
be at all noticeable in systems like Windows, but for users running
tiling window managers like bspwm or Sway, this will prevent these modal
windows from being tiled alongside the main window, instead they will be
floating on top, which is the expected behaviour seen on floating window
managers, like the ones used by Windows and macOS.

Added self.setWindowFlag(Qt.Dialog, on=True) # type: ignore to the
following files:
- tagstudio/src/qt/modals/add_field.py
- tagstudio/src/qt/modals/delete_unlinked.py
- tagstudio/src/qt/modals/drop_import.py
- tagstudio/src/qt/modals/file_extension.py
- tagstudio/src/qt/modals/fix_dupes.py
- tagstudio/src/qt/modals/fix_unlinked.py
- tagstudio/src/qt/modals/folders_to_tags.py
- tagstudio/src/qt/modals/mirror_entities.py
- tagstudio/src/qt/widgets/paged_panel/paged_panel.py
- tagstudio/src/qt/widgets/panel.py
- tagstudio/src/qt/widgets/progress.py

Note that without adding # type: ignore, MyPy *will* give out an error,
presumably because PySide6 is missing type hints for several things, and
this may *or* may not be a justifiable use of # type: ignore, which
throws the MyPy type checking for that line out the window.

Ref: #392, #464

* fix: I forgot to run ruff format

* revert: changes to docs and gitignore

This revert is for moving the referenced changes to their own pull request.

Refs: 15f4f38, a25ef8c

* docs: other shells and pyenv in CONTRIBUTING.md

This commit changes CONTRIBUTING.md to refer to pyenv in the case of
issues with Python versions, as well as downloading the correct version
off of the Python website alternatively. It also now elaborates on the
process of running the Python virtual environment on Linux and macOS, by
referencing activation scripts for alternative shells such as fish and
CSH.

The table added to CONTRIBUTING.md is taken from the official Python
documentation: https://docs.python.org/3.12/library/venv.html

* revert: accidental inclution of #464

Refs: a51550f, 5854ccc
@ChloeZamorano
Copy link
Contributor Author

Any updates on this? Really, I would just like it to be merged so I can have the main branch always updated in my bin directory with this fix.

@CyanVoxel
Copy link
Member

Any updates on this? Really, I would just like it to be merged so I can have the main branch always updated in my bin directory with this fix.

Sorry, I was under the impression that you were going to rebase/update this PR since it's quite far behind main now. There's also been new modal windows added that aren't currently covered by this PR.

In the meantime, someone over on the Discord pulled this to test it out and noted that it wasn't making a different on their machine after applying the changes to main to test:
image

Could also be user error, but I'm just passing the information along. They mentioned they're on niri which is a wayland tiling compositor I'm not familiar with, so the issue could also just be isolated to that compositor if there is indeed an issue.

@CyanVoxel CyanVoxel linked an issue Feb 19, 2025 that may be closed by this pull request
3 tasks
@ChloeZamorano
Copy link
Contributor Author

Right, sorry for being kind of reactionary about this, if that wording makes sense.

I just synced my fork to look into the new modals, and I'm gonna be trying this and other applications in that compositor to see what's going on, and hopefully figure out a solution. It says in the README that they have floating windows as of 25.01 so if this person hasn't updated in some time, then that would be why, but I doubt it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Changes Requested Changes are quested to this Type: Bug Something isn't working as intended Type: UI/UX User interface and/or user experience
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Some dialogue windows are not floating in tiling window managers
4 participants