Exemple #1
0
    def initConfig(self, confPath=None, dataPath=None):
        """Initialise the config class. The manual setting of confPath
        and dataPath is mainly intended for the test suite.
        """
        logger.debug("Initialising Config ...")
        if confPath is None:
            confRoot = QStandardPaths.writableLocation(
                QStandardPaths.ConfigLocation)
            self.confPath = os.path.join(os.path.abspath(confRoot),
                                         self.appHandle)
        else:
            logger.info("Setting config from alternative path: %s" % confPath)
            self.confPath = confPath

        if dataPath is None:
            if self.verQtValue >= 50400:
                dataRoot = QStandardPaths.writableLocation(
                    QStandardPaths.AppDataLocation)
            else:
                dataRoot = QStandardPaths.writableLocation(
                    QStandardPaths.DataLocation)
            self.dataPath = os.path.join(os.path.abspath(dataRoot),
                                         self.appHandle)
        else:
            logger.info("Setting data path from alternative path: %s" %
                        dataPath)
            self.dataPath = dataPath

        logger.verbose("Config path: %s" % self.confPath)
        logger.verbose("Data path: %s" % self.dataPath)

        self.confFile = self.appHandle + ".conf"
        self.lastPath = os.path.expanduser("~")
        self.appPath = getattr(sys, "_MEIPASS",
                               os.path.abspath(os.path.dirname(__file__)))
        self.appRoot = os.path.abspath(
            os.path.join(self.appPath, os.path.pardir))

        if os.path.isfile(self.appRoot):
            # novelWriter is packaged as a single file, so the app and
            # root paths are the same, and equal to the folder that
            # contains the single executable.
            self.appRoot = os.path.dirname(self.appRoot)
            self.appPath = self.appRoot

        # Assets
        self.assetPath = os.path.join(self.appPath, "assets")
        self.themeRoot = os.path.join(self.assetPath, "themes")
        self.dictPath = os.path.join(self.assetPath, "dict")
        self.iconPath = os.path.join(self.assetPath, "icons")
        self.appIcon = os.path.join(self.iconPath, "novelwriter.svg")

        # Internationalisation
        self.nwLangPath = os.path.join(self.appRoot, "i18n")

        logger.verbose("App path: %s" % self.appPath)
        logger.verbose("Last path: %s" % self.lastPath)

        # If config folder does not exist, create it.
        # This assumes that the os config folder itself exists.
        if not os.path.isdir(self.confPath):
            try:
                os.mkdir(self.confPath)
            except Exception as e:
                logger.error("Could not create folder: %s" % self.confPath)
                logException()
                self.hasError = True
                self.errData.append("Could not create folder: %s" %
                                    self.confPath)
                self.errData.append(str(e))
                self.confPath = None

        # Check if config file exists
        if self.confPath is not None:
            if os.path.isfile(os.path.join(self.confPath, self.confFile)):
                # If it exists, load it
                self.loadConfig()
            else:
                # If it does not exist, save a copy of the default values
                self.saveConfig()

        # If data folder does not exist, make it.
        # This assumes that the os data folder itself exists.
        if self.dataPath is not None:
            if not os.path.isdir(self.dataPath):
                try:
                    os.mkdir(self.dataPath)
                except Exception as e:
                    logger.error("Could not create folder: %s" % self.dataPath)
                    logException()
                    self.hasError = True
                    self.errData.append("Could not create folder: %s" %
                                        self.dataPath)
                    self.errData.append(str(e))
                    self.dataPath = None

        # Host and Kernel
        if self.verQtValue >= 50600:
            self.hostName = QSysInfo.machineHostName()
            self.kernelVer = QSysInfo.kernelVersion()

        # Load recent projects cache
        self.loadRecentCache()

        # Check the availability of optional packages
        self._checkOptionalPackages()

        if self.spellTool is None:
            self.spellTool = nwConst.SP_INTERNAL
        if self.spellLanguage is None:
            self.spellLanguage = "en"

        # Check if local help files exist
        self.helpPath = os.path.join(self.assetPath, "help", "novelWriter.qhc")
        self.hasHelp = os.path.isfile(self.helpPath)
        self.hasHelp &= os.path.isfile(
            os.path.join(self.assetPath, "help", "novelWriter.qch"))

        logger.debug("Config initialisation complete")

        return True
Exemple #2
0
def get_default_device():
    device = QSysInfo.machineHostName()
    if device.lower() == "localhost":
        device = QSysInfo.productType()
    return "".join([c for c in device if DeviceName.regex.match(c)])
Exemple #3
0
IS_APPLE = os.platform() == 'Darwin'
IS_IOS = not (not hasattr(QSysInfo, 'macVersion') or not QSysInfo.macVersion() & QSysInfo.MV_IOS))
IS_APPLE_DARK_MODE = False # you have to figure out a way to change this if possible. I did it in C++


if IS_IOS:
    HARDWARE_UUID = '<ios>' # no device-id protection required on iOS
elif 'nt' in os.name:
    #s = subprocess.check_output('wmic csproduct get uid')
    #self.hardwareUUID = s.split('\n')[1].strip().decode('utf-8').strip()
    HARDWARE_UUID = subprocess.check_output('wmic csproduct get name,identifyingnumber,uuid').decode('utf-8').split()[-1]
elif os.uname()[0] == 'Darwin':
    HARDWARE_UUID = subprocess.check_output("system_profiler SPHardwareDataType | awk '/UUID/ { print $3; }'", shell=True).decode('utf-8').strip()
else:
    HARDWARE_UUID = None
MACHINE_NAME = QSysInfo.machineHostName()



##
## Constants
##


EXTENSION = 'xx'
DOT_EXTENSION = '.' + EXTENSION

#
FONT_FAMILY = 'SF Pro Text'
FONT_FAMILY_TITLE = 'SF Pro Display'
TEXT_FONT_SIZE = IS_IOS and 14 or 12 # ios default: 17
Exemple #4
0
def get_default_device():
    device = QSysInfo.machineHostName()
    if device.lower() == "localhost":
        device = QSysInfo.productType()
    return "".join([c for c in device if re.match(r"[\w\-]", c)])
Exemple #5
0
    def __init__(self):

        # Set Application Variables
        self.appName = "novelWriter"
        self.appHandle = self.appName.lower()

        # Debug Settings
        self.showGUI = True  # Allow blocking the GUI (disabled for testing)
        self.debugInfo = False  # True if log level is DEBUG or VERBOSE

        # Config Error Handling
        self.hasError = False  # True if the config class encountered an error
        self.errData = []  # List of error messages

        # Set Paths
        self.cmdOpen = None  # Path from command line for project to be opened on launch
        self.confPath = None  # Folder where the config is saved
        self.confFile = None  # The config file name
        self.dataPath = None  # Folder where app data is stored
        self.lastPath = None  # The last user-selected folder (browse dialogs)
        self.appPath = None  # The full path to the novelwriter package folder
        self.appRoot = None  # The full path to the novelwriter root folder
        self.appIcon = None  # The full path to the novelwriter icon file
        self.assetPath = None  # The full path to the nw/assets folder
        self.themeRoot = None  # The full path to the nw/assets/themes folder
        self.dictPath = None  # The full path to the nw/assets/dict folder
        self.iconPath = None  # The full path to the nw/assets/icons folder
        self.helpPath = None  # The full path to the novelwriter .qhc help file

        # Runtime Settings and Variables
        self.confChanged = False  # True whenever the config has chenged, false after save
        self.hasHelp = False  # True if the Qt help files are present in the assets folder

        ## General
        self.guiTheme = "default"
        self.guiSyntax = "default_light"
        self.guiIcons = "typicons_colour_light"
        self.guiDark = False  # Load icons for dark backgrounds, if available
        self.guiLang = "en"  # Hardcoded for now since the GUI is only in English
        self.guiFont = ""  # Defaults to system defualt font
        self.guiFontSize = 11
        self.guiScale = 1.0  # Set automatically by Theme class

        ## Sizes
        self.winGeometry = [1100, 650]
        self.treeColWidth = [120, 30, 50]
        self.projColWidth = [140, 55, 140]
        self.mainPanePos = [300, 800]
        self.docPanePos = [400, 400]
        self.viewPanePos = [500, 150]
        self.outlnPanePos = [500, 150]
        self.isFullScreen = False

        ## Features
        self.hideVScroll = False  # Hide vertical scroll bars on main widgets
        self.hideHScroll = False  # Hide horizontal scroll bars on main widgets

        ## Project
        self.autoSaveProj = 60  # Interval for auto-saving project in seconds
        self.autoSaveDoc = 30  # Interval for auto-saving document in seconds

        ## Text Editor
        self.textFont = None  # Editor font
        self.textSize = 12  # Editor font size
        self.textFixedW = True  # Keep editor text fixed width
        self.textWidth = 600  # Editor text width
        self.textMargin = 40  # Editor/viewer text margin
        self.tabWidth = 40  # Editor tabulator width

        self.focusWidth = 800  # Focus Mode text width
        self.hideFocusFooter = False  # Hide document footer in Focus Mode
        self.showFullPath = True  # Show full document path in editor header
        self.autoSelect = True  # Auto-select word when applying format with no selection

        self.doJustify = False  # Justify text
        self.showTabsNSpaces = False  # Show tabs and spaces in edior
        self.showLineEndings = False  # Show line endings in editor

        self.doReplace = True  # Enable auto-replace as you type
        self.doReplaceSQuote = True  # Smart single quotes
        self.doReplaceDQuote = True  # Smart double quotes
        self.doReplaceDash = True  # Replace multiple hyphens with dashes
        self.doReplaceDots = True  # Replace three dots with ellipsis

        self.scrollPastEnd = True  # Allow scrolling past end of document
        self.autoScroll = False  # Typewriter-like scrolling
        self.autoScrollPos = 30  # Start point for typewriter-like scrolling

        self.wordCountTimer = 5.0  # Interval for word count update in seconds
        self.bigDocLimit = 800  # Size threshold for heavy editor features in kilobytes

        self.highlightQuotes = True  # Highlight text in quotes
        self.highlightEmph = True  # Add colour to text emphasis

        ## User-Selected Symbols
        self.fmtApostrophe = nwUnicode.U_RSQUO
        self.fmtSingleQuotes = [nwUnicode.U_LSQUO, nwUnicode.U_RSQUO]
        self.fmtDoubleQuotes = [nwUnicode.U_LDQUO, nwUnicode.U_RDQUO]

        ## Spell Checking
        self.spellTool = None
        self.spellLanguage = None

        ## Search Bar Switches
        self.searchCase = False
        self.searchWord = False
        self.searchRegEx = False
        self.searchLoop = False
        self.searchNextFile = False
        self.searchMatchCap = False

        ## Backup
        self.backupPath = ""
        self.backupOnClose = False
        self.askBeforeBackup = True

        ## State
        self.showRefPanel = True
        self.viewComments = True
        self.viewSynopsis = True

        # Check Qt5 Versions
        verQt = splitVersionNumber(QT_VERSION_STR)
        self.verQtString = QT_VERSION_STR
        self.verQtMajor = verQt[0]
        self.verQtMinor = verQt[1]
        self.verQtPatch = verQt[2]
        self.verQtValue = verQt[3]

        verQt = splitVersionNumber(PYQT_VERSION_STR)
        self.verPyQtString = PYQT_VERSION_STR
        self.verPyQtMajor = verQt[0]
        self.verPyQtMinor = verQt[1]
        self.verPyQtPatch = verQt[2]
        self.verPyQtValue = verQt[3]

        # Check Python Version
        self.verPyString = sys.version.split()[0]
        self.verPyMajor = sys.version_info[0]
        self.verPyMinor = sys.version_info[1]
        self.verPyPatch = sys.version_info[2]
        self.verPyHexVal = sys.hexversion

        # Check OS Type
        self.osType = sys.platform
        self.osLinux = False
        self.osWindows = False
        self.osDarwin = False
        self.osUnknown = False
        if self.osType.startswith("linux"):
            self.osLinux = True
        elif self.osType.startswith("darwin"):
            self.osDarwin = True
        elif self.osType.startswith("win32"):
            self.osWindows = True
        elif self.osType.startswith("cygwin"):
            self.osWindows = True
        else:
            self.osUnknown = True

        # Other System Info
        if self.verQtValue >= 50600:
            self.hostName = QSysInfo.machineHostName()
            self.kernelVer = QSysInfo.kernelVersion()
        else:
            self.hostName = "Unknown"
            self.kernelVer = "Unknown"

        # Packages
        self.hasEnchant = False  # The pyenchant package
        self.hasAssistant = False  # The Qt Assistant executable

        # Recent Cache
        self.recentProj = {}

        return