Пример #1
0
def processArguments(arguments):
	parser = QCommandLineParser()
	parser.addHelpOption()
	parser.addVersionOption()

	delayOption = QCommandLineOption(["d", "delay"],
	    "Take a screenshot after NUM seconds", "NUM")
	fullscreenOption = QCommandLineOption(["f", "fullscreen"],
	    "Take a screenshot of the whole screen")
	topWindowOption = QCommandLineOption(["w", "top-window"],
	    "Take a screenshot of the most top window")
	savePathOption = QCommandLineOption(["s", "save-path"],
	    "Specify a path to save the screenshot", "PATH")
	startFromDesktopOption = QCommandLineOption(["i", "icon"],
	    "Indicate that this program's started by clicking desktop file.")

	parser.addOption(delayOption)
	parser.addOption(fullscreenOption)
	parser.addOption(topWindowOption)
	parser.addOption(savePathOption)
	parser.addOption(startFromDesktopOption)
	parser.process(arguments)

	delay = int(parser.value(delayOption) or 0)
	fullscreen = bool(parser.isSet(fullscreenOption) or False)
	topWindow = bool(parser.isSet(topWindowOption) or False)
	savePath = str(parser.value(savePathOption) or "")
	startFromDesktop = bool(parser.isSet(startFromDesktopOption) or False)

	return {"delay": delay,
			"fullscreen": fullscreen,
			"topWindow": topWindow,
			"savePath": savePath,
			"startFromDesktop": startFromDesktop}
Пример #2
0
class CliParser:
    def __init__(self, app):
        self.log = logs.logger.add_module("CliParser")
        QApplication.setApplicationName("fotobox")
        QApplication.setApplicationVersion("1.0")

        self.parser = QCommandLineParser()
        self.parser.setApplicationDescription("Fotobox")
        self.parser.addHelpOption()
        self.parser.addVersionOption()

        self.cursorOption = QCommandLineOption(["m", "mouse-cursor"],
                                               "Maus anzeigen")
        self.parser.addOption(self.cursorOption)

        self.configOption = QCommandLineOption(["c", "config"],
                                               "Systemkonfiguration setzen")
        self.parser.addOption(self.configOption)

        self.loggingOption = QCommandLineOption(["log"], "Logging aktivieren",
                                                "level", "INFO")
        self.parser.addOption(self.loggingOption)

        self.parser.process(app)

    def is_mouse_cursor(self):
        return self.parser.isSet(self.cursorOption)

    def is_config_mode(self):
        return self.parser.isSet(self.configOption)

    def log_level(self):
        return self.parser.value(self.loggingOption).lower()
def runmain():
    import sys

    app = QApplication(sys.argv)

    cmdParser = QCommandLineParser()
    cmdParser.setApplicationDescription(
        'Room file merger utility script for Basement Renovator. Takes a config file and feeds it to the cli roommerger script'
    )
    cmdParser.addHelpOption()

    cmdParser.addPositionalArgument(
        'configFile',
        '''json config file to grab configuration from; sets current working directory to its directory. Format:
    {
        files: [
            {
                outputFile: path to file to output,
                paths: [ path to file/folder to replace, ... ],
                skipSTB: optional, true to skip generating the stb,
                noRecomputeIds: optional, true to skip recompute room ids,
                startingId: starting room id to recompute from
            }...
        ]
    }
    ''')

    fileEditedOpt = QCommandLineOption(
        'fileEdited',
        'optional file to limit which rooms get merged from the config',
        'file')
    cmdParser.addOption(fileEditedOpt)

    cmdParser.process(app)

    configArg = cmdParser.positionalArguments()[0]
    configPath = Path(configArg).absolute().resolve()
    if not configArg or not configPath.is_file():
        print('Invalid config path!')
        return

    fileEditedArg = cmdParser.value(fileEditedOpt)
    fileEditedPath = None
    if fileEditedArg:
        fileEditedPath = Path(fileEditedArg).absolute().resolve()
        if not fileEditedPath.is_file():
            print('Invalid edited file path!')
            return

    scriptPath = Path(__file__ + '/../roommerger.py').absolute().resolve()

    with open(configPath) as configFile:
        config = json.load(configFile)

        mergeRooms(config['files'],
                   str(scriptPath),
                   configPath.parent,
                   fileEdited=fileEditedPath)

    print('Success! Merged all.')
Пример #4
0
def process_args(app):
    args = {}

    parser = QCommandLineParser()
    parser.setApplicationDescription(
        ('PyMemorise is a tool to help memorise tables of data.' +
         ' It was built as an exam revision aid.'))
    parser.addHelpOption()
    parser.addVersionOption()

    dbOption = QCommandLineOption(
        ["database-file", "d"],
        "path to database, will be created if does not exist", "db",
        str(Path.home().joinpath(".pymem.db")))
    parser.addOption(dbOption)

    parser.process(app)

    args["database"] = parser.value(dbOption)

    if parser.positionalArguments():
        print(parser.positionalArguments())
        parser.showHelp()

    return args
Пример #5
0
def processArguments(arguments):
    parser = QCommandLineParser()
    parser.addHelpOption()
    parser.addVersionOption()

    delayOption = QCommandLineOption(["d", "delay"],
                                     "Take a screenshot after NUM seconds",
                                     "NUM")
    fullscreenOption = QCommandLineOption(
        ["f", "fullscreen"], "Take a screenshot of the whole screen")
    topWindowOption = QCommandLineOption(
        ["w", "top-window"], "Take a screenshot of the most top window")
    savePathOption = QCommandLineOption(
        ["s", "save-path"], "Specify a path to save the screenshot", "PATH")
    startFromDesktopOption = QCommandLineOption(
        ["i", "icon"],
        "Indicate that this program's started by clicking desktop file.")
    noNotificationOption = QCommandLineOption(["n", "no-notification"],
                                              "Don't send notifications.")

    parser.addOption(delayOption)
    parser.addOption(fullscreenOption)
    parser.addOption(topWindowOption)
    parser.addOption(savePathOption)
    parser.addOption(noNotificationOption)
    parser.addOption(startFromDesktopOption)
    parser.process(arguments)

    delay = int(parser.value(delayOption) or 0)
    fullscreen = bool(parser.isSet(fullscreenOption) or False)
    topWindow = bool(parser.isSet(topWindowOption) or False)
    savePath = str(parser.value(savePathOption) or "")
    startFromDesktop = bool(parser.isSet(startFromDesktopOption) or False)
    noNotification = bool(parser.isSet(noNotificationOption) or False)

    return {
        "delay": delay,
        "fullscreen": fullscreen,
        "topWindow": topWindow,
        "savePath": savePath,
        "startFromDesktop": startFromDesktop,
        "noNotification": noNotification
    }
Пример #6
0
def main(use_resources=False):

    parser = QCommandLineParser()
    geometryOpt = QCommandLineOption('geometry', 'Main window geometry',
                                     'geometry')
    parser.addOption(geometryOpt)
    parser.process(sys.argv)
    if parser.isSet('geometry'):
        try:
            geometry = tuple(
                int(val) for val in parser.value('geometry').split('x'))
            if len(geometry) != 4:
                raise
            if any(val < 1 for val in geometry):
                raise
        except:
            print(
                'The --geometry argument value must have a format such as 1x1x640x320 (x, y, width, height).'
            )
            exit(0)
    else:
        geometry = None

    app = QApplication(sys.argv)
    app.setApplicationName('pyrMExplorer')
    app.setOrganizationName('rMTools')
    if use_resources:
        icon_path = resource_path('icon.ico')
    else:
        icon_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                 'icon.ico')
    app.setWindowIcon(QIcon(icon_path))
    mainWindow = RmExplorerWindow()
    if geometry:
        mainWindow.setGeometry(*geometry)
    mainWindow.show()
    sys.exit(app.exec_())
Пример #7
0
    fullscreenOption = QCommandLineOption(["f", "fullscreen"],
        "Take a screenshot of the whole screen")
    topWindowOption = QCommandLineOption(["w", "top-window"],
        "Take a screenshot of the most top window")
    savePathOption = QCommandLineOption(["s", "save-path"],
        "Specify a path to save the screenshot", "PATH")
    startFromDesktopOption = QCommandLineOption(["i", "icon"],
        "Indicate that this program's started by clicking desktop file.")

    parser.addOption(delayOption)
    parser.addOption(fullscreenOption)
    parser.addOption(topWindowOption)
    parser.addOption(savePathOption)
    parser.addOption(startFromDesktopOption)
    parser.process(app)

    delayValue = int(parser.value(delayOption) or 0)
    fullscreenValue = bool(parser.isSet(fullscreenOption) or False)
    topWindowValue = bool(parser.isSet(topWindowOption) or False)
    savePathValue = str(parser.value(savePathOption) or "")
    startFromDesktopValue = bool(parser.isSet(startFromDesktopOption) or False)

    if is_service_exist():
        notificationsInterface.notify("Deepin Screenshot",
            _("Deepin Screenshot has been started!"))
    else:
        QTimer.singleShot(max(0, delayValue * 1000), main)

        signal.signal(signal.SIGINT, signal.SIG_DFL)
        sys.exit(app.exec_())
Пример #8
0
def runmain():
    import sys

    app = QApplication(sys.argv)

    cmdParser = QCommandLineParser()
    cmdParser.setApplicationDescription(
        'Room file merger utility script for Basement Renovator. Takes a set of file paths'
    )
    cmdParser.addHelpOption()

    cmdParser.addPositionalArgument('file', 'xml files to merge')

    outputFileOpt = QCommandLineOption('output',
                                       'output filename, must be xml', 'file')
    cmdParser.addOption(outputFileOpt)

    stbOpt = QCommandLineOption(
        'stb', 'whether to save an stb version of the file next to it')
    cmdParser.addOption(stbOpt)

    noRecompIdsOpt = QCommandLineOption(
        'noRecomputeIds',
        'turn off recomputing room ids; useful for special room merging')
    cmdParser.addOption(noRecompIdsOpt)

    idOpt = QCommandLineOption(
        'startingId', 'optional starting id to use when recomputing room ids',
        'id')
    cmdParser.addOption(idOpt)

    skipOpt = QCommandLineOption(
        'roommerge',
        'placeholder argument used to prevent recursive execution')
    cmdParser.addOption(skipOpt)

    cmdParser.process(app)

    if cmdParser.isSet(skipOpt):
        print('Recursive execution from save hook, skipping')
        return

    paths = cmdParser.positionalArguments()
    if not paths:
        print('Must specify at least one file to merge!')
        return

    outputFileArg = cmdParser.value(outputFileOpt)
    outputFilePath = Path(outputFileArg).absolute().resolve()
    if not outputFileArg or outputFilePath.suffix != '.xml':
        print('Must specify xml output file!')
        return

    lastModified = None
    if outputFilePath.exists():
        lastModified = outputFilePath.stat().st_mtime

    idArg = cmdParser.value(idOpt)

    noRecompIdsArg = cmdParser.isSet(noRecompIdsOpt)
    stbArg = cmdParser.isSet(stbOpt)

    mergeRoomFile = None
    i = -1
    while (i + 1) < len(paths):
        i += 1

        file = paths[i]

        path = Path(file)
        if path.is_dir():
            files = list(filter(lambda f: f.suffix == '.xml', path.iterdir()))
            print('Adding xml files to queue from: ', path)
            del paths[i]
            i -= 1
            paths.extend(files)

    paths = list(filter(lambda f: Path(f).exists(), paths))

    if lastModified:
        anyModified = next(
            (file for file in paths if file.stat().st_mtime > lastModified),
            None) is not None
        if not anyModified:
            print('----')
            print(
                'Skipping since no xmls in folder have been modified since last update'
            )
            return

    for file in paths:
        print('----')
        print('Path:', file)

        path = Path(file)

        print('Merging file...')
        if path.suffix != '.xml':
            print('Must be xml! Skipping!')
            continue

        roomFile = cvt.xmlToCommon(path)
        if not mergeRoomFile:
            mergeRoomFile = roomFile
        else:
            mergeRoomFile.rooms.extend(roomFile.rooms)

    print('----')

    if not mergeRoomFile:
        print('No rooms files to merge')
        return

    if not noRecompIdsArg:
        recomputeRoomIDs(mergeRoomFile.rooms, idArg and int(idArg))

    cvt.commonToXML(outputFilePath, mergeRoomFile.rooms, file=mergeRoomFile)
    if stbArg:
        cvt.commonToSTBAB(outputFileArg.replace('.xml', '.stb'),
                          mergeRoomFile.rooms)

    settings = QSettings(__file__ + '/../../settings.ini', QSettings.IniFormat)
    saveHooks = settings.value('HooksSave')
    if saveHooks:
        fullPath = str(outputFilePath)
        for hook in saveHooks:
            hook = Path(hook).absolute().resolve()
            try:
                subprocess.run([str(hook), fullPath, '--save', '--roommerge'],
                               cwd=hook.parent,
                               timeout=60)
            except Exception as e:
                print('Save hook failed! Reason:', e)

    print('Success! Merged to', outputFileArg)
Пример #9
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.edl, self.video = '', ''
        self.parse_cmdline()
        self.init_logger()
        self.init_cutter()
        self.setWindowTitle('%s' % qApp.applicationName())
        self.setContentsMargins(0, 0, 0, 0)
        self.statusBar().showMessage('Ready')
        statuslogo = QLabel(pixmap=QPixmap(':/images/vidcutter-emboss.png'),
                            objectName='logowidget')
        self.statusBar().addPermanentWidget(statuslogo)
        self.statusBar().setStyleSheet('border:none;')
        self.setAcceptDrops(True)
        self.setMinimumSize(900, 640)
        self.show()
        try:
            if len(self.video):
                self.cutter.loadMedia(self.video)
            if len(self.edl):
                self.cutter.openEDL(edlfile=self.edl)
        except (FileNotFoundError, PermissionError) as e:
            QMessageBox.critical(self, 'Error loading file', sys.exc_info()[0])
            logging.exception('Error loading file')
            qApp.restoreOverrideCursor()
            self.cutter.startNew()
        if not self.cutter.ffmpeg_check():
            self.close()
            sys.exit(1)

    def init_logger(self) -> None:
        try:
            log_path = QStandardPaths.writableLocation(
                QStandardPaths.AppConfigLocation).lower()
        except AttributeError:
            if sys.platform == 'win32':
                log_path = os.path.join(QDir.homePath(), 'AppData', 'Local',
                                        qApp.applicationName().lower())
            elif sys.platform == 'darwin':
                log_path = os.path.join(QDir.homePath(),
                                        'Library', 'Preferences',
                                        qApp.applicationName()).lower()
            else:
                log_path = os.path.join(QDir.homePath(), '.config',
                                        qApp.applicationName()).lower()

        os.makedirs(log_path, exist_ok=True)
        handlers = [
            logging.handlers.RotatingFileHandler(os.path.join(
                log_path, '%s.log' % qApp.applicationName().lower()),
                                                 maxBytes=1000000,
                                                 backupCount=1)
        ]
        if os.getenv('DEBUG', False):
            handlers.append(logging.StreamHandler())
        logging.basicConfig(
            handlers=handlers,
            format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            datefmt='%Y-%m-%d %H:%M',
            level=logging.INFO)
        logging.captureWarnings(capture=True)
        sys.excepthook = self.log_uncaught_exceptions

    @staticmethod
    def log_uncaught_exceptions(cls, exc, tb) -> None:
        logging.critical(''.join(traceback.format_tb(tb)))
        logging.critical('{0}: {1}'.format(cls, exc))

    def parse_cmdline(self) -> None:
        self.parser = QCommandLineParser()
        self.parser.setApplicationDescription(
            'The simply FAST & ACCURATE video cutter & joiner')
        self.parser.addPositionalArgument('video',
                                          'Preloads the video file in app.',
                                          '[video]')
        self.edl_option = QCommandLineOption(
            'edl', 'Preloads clip index from a previously saved EDL file.\n' +
            'NOTE: You must also set the video argument for this to work.',
            'edl file')
        self.debug_option = QCommandLineOption(
            ['d', 'debug'],
            'Output all info, warnings and errors to the console. ' +
            'This will basically output what is being logged to file to the ' +
            'console stdout. Mainly useful for debugging problems with your ' +
            'system video and/or audio stack and codec configuration.')

        self.parser.addOption(self.edl_option)
        self.parser.addOption(self.debug_option)
        self.parser.addVersionOption()
        self.parser.addHelpOption()
        self.parser.process(qApp)
        self.args = self.parser.positionalArguments()
        if self.parser.value('edl').strip() and not os.path.exists(
                self.parser.value('edl')):
            print('\n    ERROR: EDL file not found.\n', file=sys.stderr)
            self.close()
            sys.exit(1)
        if self.parser.value('edl').strip() and len(self.args) == 0:
            print('\n    ERROR: Video file argument is missing.\n',
                  file=sys.stderr)
            self.close()
            sys.exit(1)
        if self.parser.value('edl').strip():
            self.edl = self.parser.value('edl')
        if self.parser.isSet(self.debug_option):
            os.environ['DEBUG'] = '1'
        if len(self.args) > 0 and not os.path.exists(self.args[0]):
            print('\n    ERROR: Video file not found.\n', file=sys.stderr)
            self.close()
            sys.exit(1)
        if len(self.args) > 0:
            self.video = self.args[0]

    def init_cutter(self) -> None:
        self.cutter = VideoCutter(self)
        qApp.setWindowIcon(self.cutter.appIcon)
        self.setCentralWidget(self.cutter)

    @staticmethod
    def get_bitness() -> int:
        from struct import calcsize
        return calcsize('P') * 8

    def restart(self) -> None:
        self.cutter.deleteLater()
        self.init_cutter()

    @staticmethod
    def get_path(path: str = None, override: bool = False) -> str:
        if override:
            if getattr(sys, 'frozen', False):
                return os.path.join(sys._MEIPASS, path)
            return os.path.join(QFileInfo(__file__).absolutePath(), path)
        return ':%s' % path

    @staticmethod
    def load_stylesheet(qssfile: str) -> None:
        if QFileInfo(qssfile).exists():
            qss = QFile(qssfile)
            qss.open(QFile.ReadOnly | QFile.Text)
            qApp.setStyleSheet(QTextStream(qss).readAll())

    @staticmethod
    def get_version(filename: str = '__init__.py') -> str:
        with open(MainWindow.get_path(filename, override=True),
                  'r',
                  encoding='utf-8') as initfile:
            for line in initfile.readlines():
                m = re.match('__version__ *= *[\'](.*)[\']', line)
                if m:
                    return m.group(1)

    def contextMenuEvent(self, event: QContextMenuEvent) -> None:
        if event.reason() == QContextMenuEvent.Mouse:
            self.cutter.appMenu.exec_(event.globalPos())
            event.accept()
        super(MainWindow, self).contextMenuEvent(event)

    def mousePressEvent(self, event: QMouseEvent):
        if event.button() == Qt.LeftButton:
            self.cutter.cliplist.clearSelection()

    def dragEnterEvent(self, event: QDragEnterEvent) -> None:
        if event.mimeData().hasUrls():
            event.accept()

    def dropEvent(self, event: QDropEvent) -> None:
        filename = event.mimeData().urls()[0].toLocalFile()
        self.cutter.loadMedia(filename)
        event.accept()

    def closeEvent(self, event: QCloseEvent) -> None:
        if hasattr(self, 'cutter'):
            if hasattr(self.cutter, 'mediaPlayer'):
                self.cutter.mediaPlayer.terminate()
        qApp.quit()
Пример #10
0
        ["of", "overlay-frame"],
        "frame in the overlay animation to use, defaults to 0",
        "of",
        "0",
    )
    cmdParser.addOption(overlayFrameOpt)

    noScaleOpt = QCommandLineOption("noscale", "turns off scaling in anm2")
    cmdParser.addOption(noScaleOpt)

    cmdParser.process(app)

    args = cmdParser.positionalArguments()
    fileArg = args[0]

    frameArg = int(cmdParser.value(frameOpt))
    animArg = cmdParser.value(animOpt)

    overlayArg = cmdParser.value(overlayOpt)
    overlayFrameArg = int(cmdParser.value(overlayFrameOpt))

    noScaleArg = cmdParser.isSet(noScaleOpt)

    settings = QSettings("../settings.ini", QSettings.IniFormat)

    resources = settings.value("ResourceFolder", "")
    print("Resource Path:", resources)

    createIcon(
        fileArg, animArg, frameArg, overlayArg, overlayFrameArg, noScaleArg, resources
    )
Пример #11
0
class PyCirkuitParser(QObject):
    def _initStrings(self):
        self._appDescriptionStr = _translate(
            "CommandLine", "\n"
            "{productName} is a front-end for Circuit Macros by Dwight Aplevich,\n"
            "which are a set of macros for drawing high-quality line diagrams\n"
            "to be included in TeX, LaTeX, web or similar documents.",
            "Commandline application description. Don't translate '{productName}'."
        )
        self._batchOptionStr = _translate(
            "CommandLine",
            "Activates batch (unattended) mode, and convert files specified by <path> to {formatID} format. Several output formats can be used together.",
            "Commandline option description. Don't translate the '{formatID}' variable."
        )
        self._dpiOptionStr = _translate(
            "CommandLine",
            "Sets the resolution of output raster images (png, jpg), in dots per inch. Value <N> is mandatory. If option is not set, default is {defaultDPI}dpi (defined in 'settings' dialog).",
            "Commandline argument description. Don't translate the '{defaultDPI}' variable."
        )
        self._qualityOptionStr = _translate(
            "CommandLine",
            "Sets the quality of output raster lossy images (jpg), in percent. Value <Q> is mandatory. If option is not set, default is {defaultQuality}% (defined in 'settings' dialog).",
            "Commandline option description. Don't translate the '{defaultQuality}' variable."
        )
        self._overwriteOptionStr = _translate(
            "CommandLine",
            "Overwrite by default the converted files if they are present. If not set, user will be asked at runtime.",
            "Commandline option description.")
        self._followLinksOptionStr = _translate(
            "CommandLine", "Follow symbolic links.\n"
            "- If not set, destination file will be saved into the same directory where the source file is, whether it's a real file or a symbolic link.\n"
            "- If set, destination file will be saved into the directory where the real source file is located.",
            "Commandline option description.")
        self._destDirOptionStr = _translate(
            "CommandLine",
            "Save all converted files into the same destination directory <D> (value is mandatory).",
            "Commandline option description. Don't translate '<D>'.")
        self._recurseOptionStr = _translate(
            "CommandLine",
            "Using this option the pattern '**' will match any files and zero or more subdirs, so '**/*.ckt' will match all files with 'ckt' extension in the current directory and all its subdirectories.",
            "Commandline option description.")
        self._pathDescriptionStr = _translate(
            "CommandLine",
            "Path to source drawing file(s) to process. Wildcards accepted.\n"
            "- If no <path> is given, the GUI is opened.\n"
            "- If <path> points to only one file and no batch conversion options are present, this file is opened into the GUI for editing.\n"
            "- If <path>s point to more than one valid file and a combination of output formats options are present, these source files are processed sequentially in batch (unattended) mode and converted into the requested formats.\n"
            "- Specifying more than one file to process with no output format options present is not allowed.",
            "Commandline argument description. If you translate <path>, translate the name and path syntax accordingly."
        )
        self._seeHelpStr = _translate(
            "CommandLine", 'Try "{appName} --help" to get more information.',
            "Command-line error message. Don't translate '{appName}'.")

    def __init__(self, args):
        super().__init__()
        self.args = args
        settings = QSettings()
        self.imageParam = {
            Option.DPI: settings.value("Export/exportDPI", 150, type=int),
            Option.QUAL: settings.value("Export/exportQuality", 80, type=int),
        }
        self.cli_mode = False
        self.requestedRecursive = False
        self.overwrite = Overwrite.UNSET
        self.dstDir = ""
        self._initStrings()
        self.parser = QCommandLineParser()
        #self.parser.setSingleDashWordOptionMode(QCommandLineself.parser.ParseAsLongOptions)
        self.parser.setApplicationDescription(
            self._appDescriptionStr.format(productName=__productname__))
        # Adding the '-h, --help' option
        self.parser.addHelpOption()
        # Adding the '-v --version' option
        self.parser.addVersionOption()
        # Allowing positional arguments (the file/files to open or process)
        self.parser.addPositionalArgument(
            _translate(
                "CommandLine", "path",
                "Commandline argument name. If you translate this name, translate it accordingly into the path description and path syntax."
            ), self._pathDescriptionStr,
            _translate(
                "CommandLine", "[<path> [ <path2>...]]",
                "Commandline argument syntax. If you translate <path>, translate the name and path description accordingly."
            ))
        # Adding command line options
        self.options = {
            Option.TIKZ:
            QCommandLineOption(
                ["t", "tikz"],
                self._batchOptionStr.format(formatID='TIkZ'),
            ),
            Option.PDF:
            QCommandLineOption(
                ["f", "pdf"],
                self._batchOptionStr.format(formatID='PDF'),
            ),
            Option.PNG:
            QCommandLineOption(
                ["p", "png"],
                self._batchOptionStr.format(formatID='PNG'),
            ),
            Option.JPEG:
            QCommandLineOption(
                ["j", "jpeg"],
                self._batchOptionStr.format(formatID='JPEG'),
            ),
            Option.SVG:
            QCommandLineOption(
                ["s", "svg"],
                self._batchOptionStr.format(formatID='SVG'),
            ),
            Option.DPI:
            QCommandLineOption(
                ["dpi"],
                self._dpiOptionStr.format(
                    defaultDPI=self.imageParam[Option.DPI]),
                "N",
            ),
            Option.QUAL:
            QCommandLineOption(
                ["quality"],
                self._qualityOptionStr.format(
                    defaultQuality=self.imageParam[Option.QUAL]),
                "Q",
            ),
            Option.DEST:
            QCommandLineOption(
                ["destination"],
                self._destDirOptionStr,
                "D",
            ),
            Option.LINK:
            QCommandLineOption(
                ["links"],
                self._followLinksOptionStr,
            ),
            Option.OVER:
            QCommandLineOption(
                ["overwrite"],
                self._overwriteOptionStr,
            ),
            Option.REC:
            QCommandLineOption(
                ["r"],
                self._recurseOptionStr,
            ),
        }
        # Adding the options in the list
        for option in self.options.values():
            self.parser.addOption(option)

    def _checkFiles(self):
        # Test for some path passed as parameters, or none
        paths = self.parser.positionalArguments()
        # User gave some filespec to process?
        pathPresent = (len(paths) > 0)
        # User may have entered more than one path, and these can contain wildcards
        # We have to expand them into files prior to process
        self.requestedFilesToProcess = list()
        for pathSpec in paths:
            for f in glob.iglob(pathSpec, recursive=self.requestedRecursive):
                if isfile(realpath(f)):
                    f = realpath(f) if self.followSymlinks else abspath(f)
                    self.requestedFilesToProcess.append(f)
        NumFiles = len(self.requestedFilesToProcess)
        if (NumFiles == 0) and pathPresent:
            print(
                QCoreApplication.applicationName() + ": " +
                _translate("CommandLine",
                           "The given path does not match any existing file.",
                           "Commandline error message"))
            print(
                self._seeHelpStr.format(
                    appName=QCoreApplication.applicationName()))
            sys.exit(-1)
        return NumFiles

    def _checkFileOptions(self):
        self.followSymlinks = self.parser.isSet(self.options[Option.LINK])
        self.overwrite = Overwrite.ALL if self.parser.isSet(
            self.options[Option.OVER]) else Overwrite.UNSET
        if self.parser.isSet(self.options[Option.DEST]):
            self.dstDir = abspath(
                self.parser.value((self.options[Option.DEST])))
            if not isdir(self.dstDir):
                print(QCoreApplication.applicationName() + ": " + _translate(
                    "CommandLine",
                    "The given path does not match any existing file.",
                    "Commandline error message"))
                print(
                    self._seeHelpStr.format(
                        appName=QCoreApplication.applicationName()))
                sys.exit(-1)
        else:
            self.dstDir = ""

    def _checkFormats(self):
        # Test for requested output formats. If any, cli_mode is set.
        validOutputFormats = {
            Option.TIKZ, Option.PNG, Option.PDF, Option.JPEG, Option.SVG
        }
        self.requestedOutputFormats = set()
        for outputFormat in validOutputFormats:
            if self.parser.isSet(self.options[outputFormat]):
                self.cli_mode = True
                self.requestedOutputFormats.add(outputFormat)
        NumFormats = len(self.requestedOutputFormats)
        return NumFormats

    def _checkRecursive(self):
        self.requestedRecursive = self.parser.isSet(self.options[Option.REC])

    def _checkRasterOptions(self):
        # Set the "dpi" and "quality" parameters to the values provided by user, if any
        # process the "dpi" option
        if self.parser.isSet(self.options[Option.DPI]):
            try:
                self.imageParam[Option.DPI] = int(
                    self.parser.value(self.options[Option.DPI]))
                if self.imageParam[Option.DPI] not in range(25, 3001):
                    raise Exception()
            except:
                print(QCoreApplication.applicationName() + ": " + _translate(
                    "CommandLine",
                    "The --dpi parameter must be an integer between 25 and 3000.",
                    "Error message"))
                print(
                    self._seeHelpStr.format(
                        appName=QCoreApplication.applicationName()))
                sys.exit(-1)
        # Process the "quality" option
        if self.parser.isSet(self.options[Option.QUAL]):
            try:
                self.imageParam[Option.QUAL] = int(
                    self.parser.value(self.options[Option.QUAL]))
                if self.imageParam[Option.QUAL] not in range(0, 101):
                    raise Exception()
            except:
                print(QCoreApplication.applicationName() + ": " + _translate(
                    "CommandLine",
                    "The --quality parameter must be an integer between 0 and 100.",
                    "Error message"))
                print(
                    self._seeHelpStr.format(
                        appName=QCoreApplication.applicationName()))
                sys.exit(-1)

    def parseCmdLine(self):
        self.parser.process(self.args)
        ##### FETCH OPTIONS AND ARGUMENTS
        # Test if "recursive" flag is set
        self._checkRecursive()
        # Check if user set some image raster parameters
        self._checkRasterOptions()
        # Test how many output formats were requested.
        self._checkFormats()
        # Test for various file options
        self._checkFileOptions()
        # Find files to process
        NumFiles = self._checkFiles()

        ##### Process CLI mode
        if self.cli_mode:
            # Is an error to call pycirkuit with a batch option and no filenames
            if (NumFiles == 0):
                print(QCoreApplication.applicationName() + ": " + _translate(
                    "CommandLine", "Batch processing requested with no files.",
                    "Commandline error message"))
                print(
                    self._seeHelpStr.format(
                        appName=QCoreApplication.applicationName()))
                sys.exit(-1)
            # Instantiate a processor object for this CLI session
            try:
                processor = PyCirkuitProcessor()
                for fileName in self.requestedFilesToProcess:
                    processed = False
                    print(
                        _translate(
                            "CommandLine", "Processing file:",
                            "Command line message. Will be followed by an absolute file path"
                        ), fileName)
                    while not processed:
                        processor.beginProcessing(fileName)
                        for format in self.requestedOutputFormats:
                            try:
                                processor.requestResult(
                                    format,
                                    dstDir=self.dstDir,
                                    overwrite=self.overwrite,
                                    dpi=self.imageParam[Option.DPI],
                                    quality=self.imageParam[Option.QUAL])
                            except PyCktToolExecutionError as err:
                                answer = self._askOnError(err)
                                if answer == Decision.ABORT:
                                    # Terminate program
                                    sys.exit(-1)
                                elif answer == Decision.SKIP:
                                    # Consider file processed and jump to the next one
                                    processed = True
                                    continue
                                elif answer == Decision.OPEN:
                                    # Open a IGU
                                    try:
                                        run(["pycirkuit", fileName],
                                            shell=False,
                                            check=False)
                                        # Breaking here puts us out of the "for" loop and source is re-read in "beginProcesing"
                                        break
                                    except:
                                        processed = True
                        else:
                            processed = True
                    print("")
            except PyCirkuitError as err:
                print("\npycirkuit:", err)
                sys.exit(-1)
            print(
                _translate(
                    "CommandLine", "Files processed: {N}.",
                    "Command line message. {N} will be an integer, don't translate it."
                ).format(N=NumFiles))
            sys.exit(0)

        ##### Process GUI mode. Perform some final checks and exit.
        if NumFiles == 0:
            return None
        elif NumFiles == 1:
            return abspath(self.requestedFilesToProcess[0])
        else:
            print(QCoreApplication.applicationName() + ": " + _translate(
                "CommandLine",
                "More than one file to process with no batch option given.",
                "Commandline error message"))
            print(
                self._seeHelpStr.format(
                    appName=QCoreApplication.applicationName()))
            sys.exit(-1)

    def _askOnError(self, err):
        # Test if we have GUI or not, and ask accordingly
        print("\npycirkuit:", err)
        question = _translate(
            "CommandLine-UserInput2",
            "Please choose what to do: [a]bort processing, [s]kip file, [o]pen in GUI for editing: ",
            "WARNING!! Critical translation. You should translate this message to your language, enclosing into brackets one single DIFFERENT character for each option, and translate accordingly the characters in the next message."
        )
        answerAbort = _translate(
            "CommandLine-UserInput2", "a",
            "WARNING!! Critical translation. This char must match one of those of the message 'Please choose what to do:'"
        )
        answerSkip = _translate(
            "CommandLine-UserInput2", "s",
            "WARNING!! Critical translation. This char must match one of those of the message 'Please choose what to do:'"
        )
        answerOpen = _translate(
            "CommandLine-UserInput2", "o",
            "WARNING!! Critical translation. This char must match one of those of the message 'Please choose what to do:'"
        )
        if pycirkuit.__haveGUI__:
            question = _translate(
                "CommandLine-UserInput2",
                "Please choose what to do: [a]bort processing, [s]kip file, [o]pen in GUI for editing: ",
                "WARNING!! Critical translation. You should translate this message to your language, enclosing into brackets one single DIFFERENT character for each option, and translate accordingly the characters in the next message."
            )
            answers = {
                answerAbort: Decision.ABORT,
                answerSkip: Decision.SKIP,
                answerOpen: Decision.OPEN
            }
        else:
            question = _translate(
                "CommandLine-UserInput2",
                "Please choose what to do: [a]bort processing, [s]kip file: ",
                "WARNING!! Critical translation. You should translate this message to your language, enclosing into brackets one single DIFFERENT character for each option, and translate accordingly the characters in the next message."
            )
            answers = {
                answerAbort: Decision.ABORT,
                answerSkip: Decision.SKIP,
            }
        # Ask for user decision, loop until answered
        while True:
            answer = input(question)
            if answer.lower() in answers:
                return answers[answer]