Create attractive VASL scenarios, with loads of useful information embedded to assist with game play.
https://vasl-templates.org
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
96 lines
3.5 KiB
96 lines
3.5 KiB
""" Manage loading and saving files. """
|
|
|
|
import os
|
|
|
|
from PyQt5.QtWidgets import QFileDialog
|
|
|
|
# ---------------------------------------------------------------------
|
|
|
|
# NOTE: While loading/saving files works fine when handled by the embedded browser,
|
|
# we can't get the full path of the file loaded (because of browser security).
|
|
# This means that we can't do things like default to saving a scenario to the same file
|
|
# it was loaded from, or retrying a failed save. This is such a lousy UX,
|
|
# we handle load/save operations ourself, where we can manage things like this.
|
|
|
|
class FileDialog:
|
|
"""Manage loading and saving files."""
|
|
|
|
def __init__( self, parent, object_name, default_extn, filters, default_fname ):
|
|
self.parent = parent
|
|
self.object_name = object_name
|
|
self.default_extn = default_extn
|
|
self.filters = filters
|
|
self.curr_fname = default_fname
|
|
# NOTE: We can't just use the directory of self.curr_fname, since this gets reset
|
|
# when the user chooses "new scenario", but we want to remember the current directory.
|
|
self._curr_dir = os.path.dirname( default_fname ) if default_fname else None
|
|
|
|
def load_file( self, binary ):
|
|
"""Load a file."""
|
|
|
|
# ask the user which file to load
|
|
fname, _ = QFileDialog.getOpenFileName(
|
|
self.parent, "Load {}".format( self.object_name ),
|
|
self._get_start_path(),
|
|
self.filters
|
|
)
|
|
if not fname:
|
|
return None
|
|
|
|
# load the file
|
|
try:
|
|
with open( fname, "rb" ) as fp:
|
|
data = fp.read()
|
|
except Exception as ex: #pylint: disable=broad-except
|
|
self.parent.showErrorMsg( "Can't load the {}:\n\n{}".format( self.object_name, ex ) )
|
|
return None
|
|
if not binary:
|
|
data = data.decode( "utf-8" )
|
|
self.curr_fname = fname
|
|
self._curr_dir = os.path.dirname( fname )
|
|
|
|
return data
|
|
|
|
def save_file( self, data ):
|
|
"""Save data to a file."""
|
|
|
|
# initialize
|
|
if isinstance( data, str ):
|
|
data = data.encode( "utf-8" )
|
|
|
|
while True: # nb: keep trying until the save succeeds or the user cancels the operation
|
|
|
|
# ask the user where to save the file
|
|
fname, _ = QFileDialog.getSaveFileName(
|
|
self.parent, "Save {}".format( self.object_name ),
|
|
self._get_start_path(),
|
|
self.filters
|
|
)
|
|
if not fname:
|
|
return False
|
|
|
|
# check the file extension
|
|
extn = os.path.splitext( fname )[1]
|
|
if not extn:
|
|
fname += self.default_extn
|
|
elif fname.endswith( "." ):
|
|
fname = fname[:-1]
|
|
|
|
# save the file
|
|
try:
|
|
with open( fname, "wb", ) as fp:
|
|
fp.write( data )
|
|
except Exception as ex: #pylint: disable=broad-except
|
|
self.parent.showErrorMsg( "Can't save the {}:\n\n{}".format( self.object_name, ex ) )
|
|
continue
|
|
self.curr_fname = fname
|
|
self._curr_dir = os.path.dirname( fname )
|
|
return True
|
|
|
|
def _get_start_path( self ):
|
|
"""Get the start filename or directory path for saving/loading files."""
|
|
if self.curr_fname and os.path.isabs( self.curr_fname ):
|
|
return self.curr_fname
|
|
if self._curr_dir and self.curr_fname:
|
|
return os.path.join( self._curr_dir, self.curr_fname )
|
|
return self.curr_fname
|
|
|