relaxing requirements check since most tools don't actually require ntfs

This commit is contained in:
Brennen Raimer
2019-05-05 16:57:28 -04:00
parent 9946330fa5
commit 20801e9872
3 changed files with 71 additions and 44 deletions

View File

@@ -52,6 +52,7 @@
"category": "development.languages.c and c++", "category": "development.languages.c and c++",
"homepage": "https://www.msys2.org", "homepage": "https://www.msys2.org",
"icon url": "https://avatars1.githubusercontent.com/u/6759993?s=200&v=4", "icon url": "https://avatars1.githubusercontent.com/u/6759993?s=200&v=4",
"ntfs_required": true,
"search": { "search": {
"selector": "", "selector": "",
"filename regex": "", "filename regex": "",

View File

@@ -37,7 +37,7 @@ 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(parent=self)) self.install_location.setValidator(Location_Validator(self))
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)

View File

@@ -5,8 +5,18 @@ import pathlib
class Location_Validator(QtGui.QValidator): class Location_Validator(QtGui.QValidator):
def __init__(self, parent=None): 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,
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
value that was returned the last time it was validated."""
self._previous = {"location":"", "disposition":(QtGui.QValidator.Intermediate, "", 0,)}
self._ntfs_location_selected = False
@property
def ntfs_location_selected(self):
return self._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.
@@ -14,54 +24,70 @@ class Location_Validator(QtGui.QValidator):
Arguments: Arguments:
location {str} -- A string representing a folder path location {str} -- A string representing a folder path
""" """
match = [drive for drive in psutil.disk_partitions() if (drive.device == pathlib.Path(location).anchor and drive.fstype == "NTFS")] parent_dirs = [str(parent_dir) for parent_dir in pathlib.Path(location).parents]
if not match: match = [drive for drive in psutil.disk_partitions() if (drive.mountpoint in parent_dirs and drive.fstype == "NTFS")]
QtWidgets.QMessageBox( if match:
icon=QtWidgets.QMessageBox.Critical, self._ntfs_location_selected = True
parent=self.parent(),
text=f"{pathlib.Path(location).anchor} is not an NTFS-formatted volume. Please reformat your drive to NTFS or pick an install path on a different volume"
).show()
return False
else:
return True return True
else:
if QtWidgets.QMessageBox.question(self.parent(), "", f"{pathlib.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):
self._ntfs_location_selected = False
return False
else:
self._ntfs_location_selected = False
return True
def validate(self, input_, pos): def validate(self, input_, pos):
"""Called by Portable_CS_Toolkit_Installer 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
Arguments: Arguments:
input_ {str} -- The text entered in the installation location QLineEdit widget input_ {str} -- The text entered in the installation location QLineEdit widget
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 input_.endswith(r":"): if not input_.strip():
return ( self._previous["location"] = input_
QtGui.QValidator.Intermediate, self._previous["disposition"] = (QtGui.QValidator.Intermediate, input_, pos,)
input_, return (QtGui.QValidator.Intermediate, input_, pos,)
pos, elif input_.strip() == self._previous["location"]:
) # bugfix. _onNTFSDrive triggers when typing the : in a drive name e.g. C:\ #I really hate that I have to do this
return self._previous["disposition"]
# because this class method is invoked via signal, it cannot handle python exceptions elif input_.strip().endswith(r":"):
# testing writability in Python is difficult and involves actually writing a temporary file self._previous["location"] = input_
# to the directory, however, if that fails and raises an exception, it happens in Qt/C++ world self._previous["disposition"] = (QtGui.QValidator.Intermediate, input_, pos,)
# and the python interpreter can't catch it, the program just crashes without any output, # bugfix. _onNTFSDrive triggers when typing the : in a drive name e.g. C:\
# therefore, we will use Qt to do checking return (QtGui.QValidator.Intermediate, input_, pos,)
input_ = os.path.expandvars(input_) # expand any environment variables in input
location = QtCore.QFileInfo(input_)
if location.exists() and location.isDir():
if input_ and not self._onNTFSDrive(input_):
# clear the location, reset cursor, but allow continued edits
return (QtGui.QValidator.Intermediate, "", 0)
test_file = QtCore.QTemporaryFile(input_ + r"\testXXXXXX.tmp")
if test_file.open(QtCore.QIODevice.ReadWrite):
test_file.close()
test_file.remove()
return (QtGui.QValidator.Acceptable, input_, pos)
else:
return (QtGui.QValidator.Intermediate, input_, pos)
else: else:
# I wanted to return invalid, but that would prevent input of anything not instantly acceptable # because this class method is invoked via signal, it cannot handle python exceptions
# or editing something acceptable to something else acceptable, passing through an invalid on the way # testing writability in Python is difficult and involves actually writing a temporary file
return (QtGui.QValidator.Intermediate, input_, pos) # 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 input_ and not self._onNTFSDrive(input_):
self._previous["location"] = input_
self._previous["disposition"] = (QtGui.QValidator.Intermediate, "", 0)
# clear the location, reset cursor, but allow continued edits
return (QtGui.QValidator.Intermediate, "", 0)
test_file = QtCore.QTemporaryFile(input_ + r"\testXXXXXX.tmp")
if test_file.open(QtCore.QIODevice.ReadWrite):
test_file.close()
test_file.remove()
self._previous["location"] = input_
self._previous["disposition"] = (QtGui.QValidator.Acceptable, input_, pos,)
return (QtGui.QValidator.Acceptable, input_, pos,)
else:
self._previous["location"] = input_
self._previous["disposition"] = (QtGui.QValidator.Intermediate, input_, pos,)
return (QtGui.QValidator.Intermediate, input_, pos,)
else:
self._previous["location"] = input_
self._previous["disposition"] = (QtGui.QValidator.Intermediate, input_, pos,)
# 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
return (QtGui.QValidator.Intermediate, input_, pos,)