mostly worked around annoying Qt bug
This commit is contained in:
@@ -36,7 +36,12 @@ class InstallerWizard(QtWidgets.QWizard):
|
|||||||
self.intro.anchorClicked.connect(self._link_clicked)
|
self.intro.anchorClicked.connect(self._link_clicked)
|
||||||
self.license.anchorClicked.connect(self._link_clicked)
|
self.license.anchorClicked.connect(self._link_clicked)
|
||||||
self.selection_menu.itemClicked.connect(self._enforce_dependencies)
|
self.selection_menu.itemClicked.connect(self._enforce_dependencies)
|
||||||
self.install_location.setValidator(Location_Validator(self))
|
self._location_validator = Location_Validator(self)
|
||||||
|
try:
|
||||||
|
self.install_location.inputRejected.connect(self.install_location.clear)
|
||||||
|
except AttributeError:
|
||||||
|
pass #inputRejected signal added in Qt 5.12, I have 5.9
|
||||||
|
self.install_location.setValidator(self._location_validator)
|
||||||
self.location_page.registerField("Location*", self.install_location)
|
self.location_page.registerField("Location*", self.install_location)
|
||||||
self.browse_button.clicked.connect(self._select_location)
|
self.browse_button.clicked.connect(self._select_location)
|
||||||
self.selection_menu.itemClicked.connect(self._open_homepage)
|
self.selection_menu.itemClicked.connect(self._open_homepage)
|
||||||
|
|||||||
@@ -3,21 +3,24 @@ import psutil
|
|||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from threading import Lock, Condition, Event
|
||||||
|
|
||||||
class Location_Validator(QtGui.QValidator):
|
class Location_Validator(QtGui.QValidator):
|
||||||
|
_disposition = QtGui.QValidator.Intermediate
|
||||||
|
_pos = 0
|
||||||
|
_location = ""
|
||||||
|
_ntfs_location_selected = False
|
||||||
|
_previous_location = None
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
"""for some reason on my Linux system, selecting a directory validates the same location repatedly,
|
"""for some reason on my Linux system, selecting a directory validates the same location repatedly,
|
||||||
once for each subdir of the location. The only way to keep it from repeatedly validating and potentially
|
once for each subdir of the location. The only way to keep it from repeatedly validating and potentially
|
||||||
opening a warning window for each subdirectory in the location path was to track this and return the same
|
opening a warning window for each subdirectory in the location path was to track this and return the same
|
||||||
value that was returned the last time it was validated."""
|
value that was returned the last time it was validated."""
|
||||||
self._previous = {"location":"", "disposition":(QtGui.QValidator.Intermediate, "", 0,)}
|
|
||||||
self._ntfs_location_selected = False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ntfs_location_selected(self):
|
def ntfs_location_selected(self):
|
||||||
return self._ntfs_location_selected
|
return Location_Validator._ntfs_location_selected
|
||||||
|
|
||||||
def _onNTFSDrive(self, location):
|
def _onNTFSDrive(self, location):
|
||||||
"""Tests if location is a path on an NTFS-formatted drive. Returns True if path is on NTFS-formatted drive.
|
"""Tests if location is a path on an NTFS-formatted drive. Returns True if path is on NTFS-formatted drive.
|
||||||
@@ -32,11 +35,10 @@ class Location_Validator(QtGui.QValidator):
|
|||||||
#elif platform.system() == "Linux":
|
#elif platform.system() == "Linux":
|
||||||
# pass
|
# pass
|
||||||
else:
|
else:
|
||||||
self._ntfs_location_selected = False
|
if QtWidgets.QApplication.instance().activeModalWidget():
|
||||||
if QtWidgets.QMessageBox.question(self.parent(), "", f"{Path(location)} is not an NTFS-formatted volume. Tools which require a NTFS filesystem to function will not be available. Continue anyway?") in (QtWidgets.QMessageBox.No, 0):
|
|
||||||
return False
|
return False
|
||||||
else:
|
self._ntfs_location_selected = False
|
||||||
return True
|
return not QtWidgets.QMessageBox.question(self.parent(), "", f"{Path(location)} is not an NTFS-formatted volume. Tools which require a NTFS filesystem to function will not be available. Continue anyway?") in (QtWidgets.QMessageBox.No, 0)
|
||||||
|
|
||||||
def validate(self, input_, pos):
|
def validate(self, input_, pos):
|
||||||
"""Called by InstallerWizard via QtWidget.QLineEdit.TextChanged signal to validate installation location input of user
|
"""Called by InstallerWizard via QtWidget.QLineEdit.TextChanged signal to validate installation location input of user
|
||||||
@@ -46,48 +48,42 @@ class Location_Validator(QtGui.QValidator):
|
|||||||
pos {int} -- The current location of the cursor in the QLineEdit widget
|
pos {int} -- The current location of the cursor in the QLineEdit widget
|
||||||
"""
|
"""
|
||||||
if not input_.strip():
|
if not input_.strip():
|
||||||
self._previous["location"] = Path(input_.strip())
|
_previous_location = input_
|
||||||
self._previous["disposition"] = (QtGui.QValidator.Intermediate, input_, pos,)
|
return (QtGui.QValidator.Intermediate, input_, pos)
|
||||||
return (QtGui.QValidator.Intermediate, input_, pos,)
|
|
||||||
elif Path(input_.strip()) == self._previous["location"]:
|
elif input_.strip() == self._previous_location:
|
||||||
#I really hate that I have to do this
|
return (self._disposition, self._previous_location, self._pos)
|
||||||
return self._previous["disposition"]
|
|
||||||
elif input_.strip().endswith(r":"):
|
elif input_.strip().endswith(r":"):
|
||||||
self._previous["location"] = Path(input_.strip())
|
#if nothing entered or location ends with : e.g. C: which will cause _onNTFSDrive to trigger unwanted messages
|
||||||
self._previous["disposition"] = (QtGui.QValidator.Intermediate, input_, pos,)
|
self._location = input_
|
||||||
# bugfix. _onNTFSDrive triggers when typing the : in a drive name e.g. C:\
|
self._disposition = QtGui.QValidator.Intermediate
|
||||||
return (QtGui.QValidator.Intermediate, input_, pos,)
|
|
||||||
else:
|
else:
|
||||||
# because this class method is invoked via signal, it cannot handle python exceptions
|
expanded_input = os.path.expandvars(input_.strip()) # expand any environment variables in input
|
||||||
# testing writability in Python is difficult and involves actually writing a temporary file
|
location = QtCore.QFileInfo(expanded_input)
|
||||||
# to the directory, however, if that fails and raises an exception, it happens in Qt/C++ world
|
|
||||||
# and the python interpreter can't catch it, the program just crashes without any output,
|
|
||||||
# therefore, we will use Qt to do checking
|
|
||||||
input_ = os.path.expandvars(input_.strip()) # expand any environment variables in input
|
|
||||||
location = QtCore.QFileInfo(input_)
|
|
||||||
if location.exists() and location.isDir():
|
if location.exists() and location.isDir():
|
||||||
if input_ and not self._onNTFSDrive(input_):
|
if not self._onNTFSDrive(expanded_input):
|
||||||
self._previous["location"] = Path(input_)
|
|
||||||
self._previous["disposition"] = (QtGui.QValidator.Intermediate, "", 0)
|
|
||||||
# clear the location, reset cursor, but allow continued edits
|
# clear the location, reset cursor, but allow continued edits
|
||||||
return (QtGui.QValidator.Intermediate, "", 0)
|
self._location = ""
|
||||||
|
self._disposition = QtGui.QValidator.Intermediate
|
||||||
test_file = QtCore.QTemporaryFile(f"{Path(input_)/'testXXXXXX.tmp'}")
|
|
||||||
|
|
||||||
if test_file.open(QtCore.QIODevice.ReadWrite):
|
|
||||||
test_file.close()
|
|
||||||
test_file.remove()
|
|
||||||
self._previous["location"] = Path(input_)
|
|
||||||
self._previous["disposition"] = (QtGui.QValidator.Acceptable, input_, pos,)
|
|
||||||
return (QtGui.QValidator.Acceptable, input_, pos,)
|
|
||||||
else:
|
else:
|
||||||
self._previous["location"] = Path(input_)
|
test_file = QtCore.QTemporaryFile(f"{Path(expanded_input)/'testXXXXXX.tmp'}")
|
||||||
self._previous["disposition"] = (QtGui.QValidator.Intermediate, input_, pos,)
|
|
||||||
return (QtGui.QValidator.Intermediate, input_, pos,)
|
|
||||||
|
|
||||||
|
if test_file.open(QtCore.QIODevice.ReadWrite):
|
||||||
|
test_file.close()
|
||||||
|
test_file.remove()
|
||||||
|
self._location = input_
|
||||||
|
self._disposition = QtGui.QValidator.Acceptable
|
||||||
|
else:
|
||||||
|
self._location = input_
|
||||||
|
self._disposition = QtGui.QValidator.Intermediate
|
||||||
else:
|
else:
|
||||||
self._previous["location"] = Path(input_)
|
|
||||||
self._previous["disposition"] = (QtGui.QValidator.Intermediate, input_, pos,)
|
|
||||||
# I wanted to return invalid, but that would prevent input of anything not instantly acceptable
|
# I wanted to return invalid, but that would prevent input of anything not instantly acceptable
|
||||||
# or editing something acceptable to something else acceptable, passing through an invalid on the way
|
# or editing something acceptable to something else acceptable, passing through an invalid on the way
|
||||||
return (QtGui.QValidator.Intermediate, input_, pos,)
|
self._location = input_
|
||||||
|
self._disposition = QtGui.QValidator.Intermediate
|
||||||
|
|
||||||
|
self._pos = pos
|
||||||
|
self._previous_location = self._location
|
||||||
|
|
||||||
|
return (self._disposition, self._location, self._pos,)
|
||||||
|
|||||||
Reference in New Issue
Block a user