Skip to content

Commit 06e6aa2

Browse files
committed
Fix bug on MacOS where selecting .app file wouldn't be recognized, by making user path selection more robust
1 parent f0106a5 commit 06e6aa2

File tree

3 files changed

+60
-19
lines changed

3 files changed

+60
-19
lines changed

gameScanner.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,37 @@ def scanForFullInstallConfigs(subModConfigList, possiblePaths=None):
274274
pass
275275

276276
return returnedFullConfigs
277+
278+
def scanUserSelectedPath(subModConfigList, gameExecutablePath):
279+
# type: (List[SubModConfig], [str]) -> ([FullInstallConfiguration], str)
280+
"""
281+
Scans a user-selected path for configs. Unlike the normal "scanForFullInstallConfigs()" function,
282+
this will attempt to search all parent directories, incase a user has selected a subdirectory of the game directory
283+
by accident.
284+
:param subModConfigList:
285+
:param gameExecutablePath:
286+
:return: A tuple - The first is an array of valid FullInstallConfigurations.
287+
- The second is an error message (on success a 'success' message is generated)
288+
"""
289+
if gameExecutablePath:
290+
if os.path.isfile(gameExecutablePath):
291+
gameExecutablePath = os.path.dirname(gameExecutablePath)
292+
293+
# Search upwards for the game path, in case user has selected a deep subfolder of the game path
294+
alreadyScanned = set()
295+
for scanAttempt in range(10):
296+
fullInstallConfigs = scanForFullInstallConfigs(subModConfigList=subModConfigList, possiblePaths=[gameExecutablePath])
297+
if fullInstallConfigs:
298+
return fullInstallConfigs, "scanUserSelectedPath(): Path [{}] Ok".format(gameExecutablePath)
299+
300+
alreadyScanned.add(gameExecutablePath)
301+
gameExecutablePath = os.path.dirname(gameExecutablePath)
302+
if gameExecutablePath in alreadyScanned:
303+
break
304+
305+
# Failed to find path. Notify user which paths tried to be searched to find the file.
306+
errorStrings = ["scanUserSelectedPath(): Can't install the mod. Searched:"] + sorted(list(alreadyScanned))
307+
errorMessage = '\n - '.join(errorStrings)
308+
return None, errorMessage
309+
310+
return None, "scanUserSelectedPath(): game executable path is falsey: [{}]".format(gameExecutablePath)

httpGUI.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import tkFileDialog as filedialog
3535

3636
collapseWhiteSpaceRegex = re.compile(r"[\s\b]+")
37-
def _TKAskGameExe(subMod):
37+
def _TKAskPath(subMod):
3838
# TODO: on 2.7 you can use .withdraw on the root window, but on python 3 it prevents the filedialog from showing!
3939
# TODO: for now, put up with the root window showing when choosing path manually
4040
root = Tk()
@@ -46,8 +46,6 @@ def _TKAskGameExe(subMod):
4646

4747
# returns empty string if user didn't select any file or folder. If a file is selected, convert it to the parent folder
4848
installFolder = filedialog.askopenfilename(filetypes=fileList)
49-
if os.path.isfile(installFolder):
50-
installFolder = os.path.normpath(os.path.join(installFolder, os.pardir))
5149

5250
root.destroy()
5351

@@ -271,12 +269,19 @@ def __init__(self, allSubModConfigs):
271269
self.messageBuffer = []
272270
self.threadHandle = None
273271

274-
def try_start_install(self, subMod, installPath):
272+
# TODO: this function should return an error message describing why the install couldn't be started
273+
def try_start_install(self, subMod, installPath, pathIsManual):
275274
import higurashiInstaller
276275
import uminekoInstaller
277276
import threading
278277

279-
fullInstallConfigs = gameScanner.scanForFullInstallConfigs([subMod], possiblePaths=[installPath])
278+
# if the path was user selected, do some extra processing on the path
279+
if pathIsManual:
280+
fullInstallConfigs, errorMessage = gameScanner.scanUserSelectedPath([subMod], installPath)
281+
print(errorMessage)
282+
else:
283+
fullInstallConfigs = gameScanner.scanForFullInstallConfigs([subMod], possiblePaths=[installPath])
284+
280285
if not fullInstallConfigs:
281286
return False
282287

@@ -359,11 +364,14 @@ def getGamePathsHandler(requestData):
359364
def startInstallHandler(requestData):
360365
id = requestData['id']
361366
subMod = self.idToSubMod[id]
367+
pathIsManual = False
362368
installPath = requestData.get('installPath', None)
369+
363370
if installPath is None:
364-
installPath = _TKAskGameExe(subMod)
371+
pathIsManual = True
372+
installPath = _TKAskPath(subMod)
365373

366-
return { 'installStarted' : self.try_start_install(subMod, installPath) }
374+
return { 'installStarted' : self.try_start_install(subMod, installPath, pathIsManual) }
367375

368376
# requestData: Not necessary - will be ignored
369377
# responseData: Returns a list of dictionaries. Each dictionary may have different fields depending on the

installerGUI.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,17 @@ def askGameExeAndValidate():
6363
fileList = [("Game Executable", x) for x in extensionList]
6464
fileList.append(("Any In Game Folder", "*.*"))
6565

66-
gameExecutablePath = filedialog.askopenfilename(filetypes=fileList)
67-
if gameExecutablePath:
68-
if not os.path.isdir(gameExecutablePath):
69-
gameExecutablePath= os.path.normpath(os.path.join(gameExecutablePath, os.pardir))
70-
71-
fullInstallConfigs = gameScanner.scanForFullInstallConfigs(subModConfigList=[subMod], possiblePaths=[gameExecutablePath])
72-
if fullInstallConfigs:
73-
print("Path Ok: ", gameExecutablePath)
74-
self.confirmationPage(fullInstallConfigs[0])
75-
else:
76-
print("Path INVALID:", gameExecutablePath)
77-
messagebox.showerror("Error", "Can't install the mod to the path\n" + gameExecutablePath)
66+
userSelectedPath = filedialog.askopenfilename(filetypes=fileList)
67+
if not userSelectedPath:
68+
return
69+
70+
fullInstallConfigs, errorMessage = gameScanner.scanUserSelectedPath(subModConfigList=[subMod], gameExecutablePath=userSelectedPath)
71+
print(errorMessage)
72+
if fullInstallConfigs:
73+
self.confirmationPage(fullInstallConfigs[0])
74+
return
75+
else:
76+
messagebox.showerror("Error", errorMessage)
7877

7978
# do search over all possible install locations that the selected submod can be installed.
8079
fullInstallConfigs = gameScanner.scanForFullInstallConfigs([subMod])

0 commit comments

Comments
 (0)