Пример #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
def main():
    global app
    # register representation factories
    baseRepresentationFactories.registerAllFactories()
    representationFactories.registerAllFactories()
    # initialize the app
    app = Application(sys.argv)
    app.setOrganizationName("TruFont")
    app.setOrganizationDomain("trufont.github.io")
    app.setApplicationName("TruFont")
    app.setApplicationVersion(__version__)
    app.setWindowIcon(QIcon(":app.png"))
    app.setAttribute(Qt.AA_UseHighDpiPixmaps, True)

    # Install stream redirection
    app.outputWindow = OutputWindow()
    # Exception handling
    sys.excepthook = exceptionCallback

    # Qt's translation for itself. May not be installed.
    qtTranslator = QTranslator()
    qtTranslator.load("qt_" + QLocale.system().name(),
                      QLibraryInfo.location(QLibraryInfo.TranslationsPath))
    app.installTranslator(qtTranslator)

    appTranslator = QTranslator()
    appTranslator.load("trufont_" + QLocale.system().name(),
                       os.path.dirname(os.path.realpath(__file__)) +
                       "/resources")
    app.installTranslator(appTranslator)

    # parse options and open fonts
    parser = QCommandLineParser()
    parser.setApplicationDescription(QApplication.translate(
        "Command-line parser", "The TruFont font editor."))
    parser.addHelpOption()
    parser.addVersionOption()
    parser.addPositionalArgument(QApplication.translate(
        "Command-line parser", "files"), QApplication.translate(
        "Command-line parser", "The UFO files to open."))
    parser.process(app)
    args = parser.positionalArguments()
    if not args:
        fontPath = None
        # maybe load recent file
        settings = QSettings()
        loadRecentFile = settings.value("misc/loadRecentFile", False, bool)
        if loadRecentFile:
            recentFiles = settings.value("core/recentFiles", [], type=str)
            if len(recentFiles) and os.path.exists(recentFiles[0]):
                fontPath = recentFiles[0]
                app.openFile(fontPath)
        # otherwise, create a new file
        if fontPath is None:
            app.newFile()
    else:
        for fontPath in args:
            app.openFile(fontPath)
    sys.exit(app.exec_())
Пример #3
0
def main():
    app = QCoreApplication(sys.argv)

    # Set some application details.
    app.setApplicationName("MyApp")
    app.setApplicationVersion("0.1.0")
    app.setOrganizationName("My Organization")
    app.setOrganizationDomain("www.my-organization.org")

    # Create a verbosity command line option.
    verbose_option = QCommandLineOption("verbose", "Verbose mode. Print out debug messages.")

    # Setup the commandline parser.
    command_parser = QCommandLineParser()
    command_parser.addHelpOption()
    command_parser.addVersionOption()

    # Add the commandline options.
    command_parser.addOption(verbose_option)

    # Process the command line.
    command_parser.process(app)

    # Set the basic logger mnessage format and verbosity level.
    logger = logging.getLogger()

    # This dictates how the messages are formatted.
    formatter = logging.Formatter(fmt=MESSAGE_FORMAT, style="{")

    # This handler sends everything to stdout.
    handler = logging.StreamHandler()
    handler.setFormatter(formatter)

    # Add the handler to the logger.
    logger.addHandler(handler)

    # Check if the verbosity flag is set and set the log level to debug if it is.
    if command_parser.isSet(verbose_option):
        logger.setLevel(logging.DEBUG)
        logger.debug("Setting loglevel to debug.")

    else:
        logger.setLevel(logging.ERROR)

    # Start the event loop.
    sys.exit(app.exec())
Пример #4
0
def main():
    # register representation factories
    representationFactories.registerAllFactories()
    # initialize the app
    app = Application(sys.argv)
    app.setOrganizationName("TruFont")
    app.setOrganizationDomain("trufont.github.io")
    app.setApplicationName("TruFont")
    app.setApplicationVersion(__version__)
    app.setWindowIcon(QIcon(":/resources/app.png"))
    settings = QSettings()
    glyphListPath = settings.value("settings/glyphListPath", "", type=str)
    if glyphListPath and os.path.exists(glyphListPath):
        from defconQt.util import glyphList
        try:
            glyphList = glyphList.parseGlyphList(glyphListPath)
        except Exception as e:
            print(e)
        else:
            app.GL2UV = glyphList
    # parse options and open fonts
    parser = QCommandLineParser()
    parser.setApplicationDescription("The TruFont font editor.")
    parser.addHelpOption()
    parser.addVersionOption()
    parser.addPositionalArgument("files", "The UFO files to open.")
    parser.process(app)
    args = parser.positionalArguments()
    if not len(args):
        fontPath = None
        # maybe load recent file
        settings = QSettings()
        loadRecentFile = settings.value("misc/loadRecentFile", False, bool)
        if loadRecentFile:
            recentFiles = settings.value("core/recentFiles", [], type=str)
            if len(recentFiles):
                fontPath = recentFiles[0]
                app.openFile(fontPath)
        # otherwise, create a new file
        if fontPath is None:
            app.newFile()
    else:
        for fontPath in args:
            app.openFile(fontPath)
    sys.exit(app.exec_())
Пример #5
0
def main():
	multiprocessing.set_start_method('spawn')

	if markups.__version_tuple__ < (2, ):
		sys.exit('Error: ReText needs PyMarkups 2.0 or newer to run.')

	# If we're running on Windows without a console, then discard stdout
	# and save stderr to a file to facilitate debugging in case of crashes.
	if sys.executable.endswith('pythonw.exe'):
		sys.stdout = open(devnull, 'w')
		sys.stderr = open('stderr.log', 'w')

	try:
		# See https://github.com/retext-project/retext/issues/399
		# and https://launchpad.net/bugs/941826
		ctypes.CDLL('libGL.so.1', ctypes.RTLD_GLOBAL)
	except OSError:
		pass

	# Needed for Qt WebEngine on Windows
	QApplication.setAttribute(Qt.ApplicationAttribute.AA_ShareOpenGLContexts)
	QApplication.setAttribute(Qt.ApplicationAttribute.AA_UseHighDpiPixmaps)
	app = QApplication(sys.argv)
	app.setOrganizationName("ReText project")
	app.setApplicationName("ReText")
	app.setApplicationDisplayName("ReText")
	app.setApplicationVersion(app_version)
	app.setOrganizationDomain('mitya57.me')
	app.setDesktopFileName('me.mitya57.ReText.desktop')
	QNetworkProxyFactory.setUseSystemConfiguration(True)

	initializeDataDirs()
	RtTranslator = QTranslator()
	for path in datadirs:
		if RtTranslator.load('retext_' + globalSettings.uiLanguage,
		                     join(path, 'locale')):
			break
	QtTranslator = QTranslator()
	QtTranslator.load("qtbase_" + globalSettings.uiLanguage,
		QLibraryInfo.location(QLibraryInfo.LibraryLocation.TranslationsPath))
	app.installTranslator(RtTranslator)
	app.installTranslator(QtTranslator)

	parser = QCommandLineParser()
	parser.addHelpOption()
	parser.addVersionOption()
	previewOption = QCommandLineOption('preview',
		QApplication.translate('main', 'Open the files in preview mode'))
	newWindowOption = QCommandLineOption('new-window',
		QApplication.translate('main', 'Create a new window even if there is an existing one'))
	parser.addOption(previewOption)
	parser.addOption(newWindowOption)
	parser.addPositionalArgument('files',
		QApplication.translate('main', 'List of files to open'),
		'[files...]')

	parser.process(app)
	filesToOpen = parser.positionalArguments()

	print('Using configuration file:', settings.fileName())
	if globalSettings.appStyleSheet:
		sheetfile = QFile(globalSettings.appStyleSheet)
		sheetfile.open(QIODevice.OpenModeFlag.ReadOnly)
		app.setStyleSheet(QTextStream(sheetfile).readAll())
		sheetfile.close()
	window = ReTextWindow()

	openInExistingWindow = (globalSettings.openFilesInExistingWindow
		and not parser.isSet(newWindowOption))
	connection = QDBusConnection.sessionBus()
	if connection.isConnected() and openInExistingWindow:
		connection.registerObject('/', window, QDBusConnection.RegisterOption.ExportAllSlots)
		serviceName = 'me.mitya57.ReText'
		if not connection.registerService(serviceName) and filesToOpen:
			print('Opening the file(s) in the existing window of ReText.')
			iface = QDBusInterface(serviceName, '/', '', connection)
			for fileName in filesToOpen:
				iface.call('openFileWrapper', fileName)
			qWidgetIface = QDBusInterface(serviceName, '/', 'org.qtproject.Qt.QWidget', connection)
			qWidgetIface.call('raise')
			sys.exit(0)

	window.show()
	# ReText can change directory when loading files, so we
	# need to have a list of canonical names before loading
	fileNames = list(map(canonicalize, filesToOpen))
	readStdIn = False

	if globalSettings.openLastFilesOnStartup:
		window.restoreLastOpenedFiles()
	for fileName in fileNames:
		if QFile.exists(fileName):
			window.openFileWrapper(fileName)
			if parser.isSet(previewOption):
				window.actionPreview.setChecked(True)
				window.preview(True)
		elif fileName == '-':
			readStdIn = True

	inputData = ''
	if readStdIn and sys.stdin is not None:
		if sys.stdin.isatty():
			print('Reading stdin, press ^D to end...')
		inputData = sys.stdin.read()
	if inputData or not window.tabWidget.count():
		window.createNew(inputData)
	signal.signal(signal.SIGINT, lambda sig, frame: window.close())
	sys.exit(app.exec())
Пример #6
0
def main():
    global app
    # register representation factories
    baseRepresentationFactories.registerAllFactories()
    representationFactories.registerAllFactories()
    if hasattr(Qt, "AA_EnableHighDpiScaling"):
        QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
    # initialize the app
    app = Application(sys.argv)
    app.setOrganizationName("TruFont")
    app.setOrganizationDomain("trufont.github.io")
    app.setApplicationName("TruFont")
    app.setApplicationVersion(__version__)
    app.setWindowIcon(QIcon(":app.png"))
    app.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
    app.setStyleSheet(platformSpecific.appStyleSheet())

    # Install stream redirection
    app.outputWindow = OutputWindow()
    # Exception handling
    sys.excepthook = errorReports.exceptionCallback

    # Qt's translation for itself. May not be installed.
    qtTranslator = QTranslator()
    qtTranslator.load("qt_" + QLocale.system().name(),
                      QLibraryInfo.location(QLibraryInfo.TranslationsPath))
    app.installTranslator(qtTranslator)

    appTranslator = QTranslator()
    appTranslator.load("trufont_" + QLocale.system().name(),
                       os.path.dirname(os.path.realpath(__file__)) +
                       "/resources")
    app.installTranslator(appTranslator)

    # parse options and open fonts
    parser = QCommandLineParser()
    parser.setApplicationDescription(QApplication.translate(
        "Command-line parser", "The TruFont font editor."))
    parser.addHelpOption()
    parser.addVersionOption()
    parser.addPositionalArgument(QApplication.translate(
        "Command-line parser", "files"), QApplication.translate(
        "Command-line parser", "The UFO files to open."))
    parser.process(app)
    # bootstrap extensions
    folder = app.getExtensionsDirectory()
    for file in os.listdir(folder):
        if not file.rstrip("\\/ ").endswith(".tfExt"):
            continue
        path = os.path.join(folder, file)
        try:
            extension = TExtension(path)
            if extension.launchAtStartup:
                extension.run()
        except Exception as e:
            msg = QApplication.translate(
                "Extensions", "The extension at {0} could not be run.".format(
                    path))
            errorReports.showWarningException(e, msg)
            continue
        app.registerExtension(extension)
    # load menu
    if platformSpecific.useGlobalMenuBar():
        menuBar = app.fetchMenuBar()  # noqa
        app.setQuitOnLastWindowClosed(False)
    # process files
    args = parser.positionalArguments()
    if not args:
        fontPath = None
        # maybe load recent file
        settings = QSettings()
        loadRecentFile = settings.value("misc/loadRecentFile", False, bool)
        if loadRecentFile:
            recentFiles = settings.value("core/recentFiles", [], type=str)
            if len(recentFiles) and os.path.exists(recentFiles[0]):
                fontPath = recentFiles[0]
                app.openFile(fontPath)
        # otherwise, create a new file
        if fontPath is None:
            app.newFile()
    else:
        for fontPath in args:
            app.openFile(fontPath)
    sys.exit(app.exec_())
Пример #7
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()
Пример #8
0
def main():
    global app

    # register representation factories
    baseRepresentationFactories.registerAllFactories()
    representationFactories.registerAllFactories()
    if hasattr(Qt, "AA_EnableHighDpiScaling"):
        QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
    platformSpecific.setAppName()
    # initialize the app
    app = Application(sys.argv)
    app.setOrganizationName("TruFont")
    app.setOrganizationDomain("trufont.github.io")
    app.setApplicationName("TruFont")
    app.setApplicationVersion(__version__)
    app.setWindowIcon(QIcon(":app.png"))
    app.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
    appFont = platformSpecific.UIFontOverride()
    if appFont is not None:
        app.setFont(appFont)
    app.setStyleSheet(platformSpecific.appStyleSheet())

    # Install stream redirection
    app.outputWindow = OutputWindow()
    # Exception handling
    sys.excepthook = errorReports.exceptionCallback

    # Qt's translation for itself. May not be installed.
    qtTranslator = QTranslator()
    qtTranslator.load(
        "qt_" + QLocale.system().name(),
        QLibraryInfo.location(QLibraryInfo.TranslationsPath),
    )
    app.installTranslator(qtTranslator)

    appTranslator = QTranslator()
    appTranslator.load(
        "trufont_" + QLocale.system().name(),
        os.path.dirname(os.path.realpath(__file__)) + "/resources",
    )
    app.installTranslator(appTranslator)

    # parse options and open fonts
    parser = QCommandLineParser()
    parser.setApplicationDescription(
        QApplication.translate("Command-line parser", "The TruFont font editor.")
    )
    parser.addHelpOption()
    parser.addVersionOption()
    parser.addPositionalArgument(
        QApplication.translate("Command-line parser", "files"),
        QApplication.translate("Command-line parser", "The UFO files to open."),
    )
    parser.process(app)
    # load menu
    if platformSpecific.useGlobalMenuBar():
        app.fetchMenuBar()
        app.setQuitOnLastWindowClosed(False)
    # bootstrap extensions
    folder = app.getExtensionsDirectory()
    for file in os.listdir(folder):
        if not file.rstrip("\\/ ").endswith(".tfExt"):
            continue
        path = os.path.join(folder, file)
        try:
            extension = TExtension(path)
            if extension.launchAtStartup:
                extension.run()
        except Exception as e:
            msg = QApplication.translate(
                "Extensions", f"The extension at {path} could not be run."
            )
            errorReports.showWarningException(e, msg)
            continue
        app.registerExtension(extension)
    # process files
    args = parser.positionalArguments()
    if not args:
        # maybe load recent file
        loadRecentFile = settings.loadRecentFile()
        if loadRecentFile:
            recentFiles = settings.recentFiles()
            if len(recentFiles) and os.path.exists(recentFiles[0]):
                app.openFile(recentFiles[0])
    else:
        for fontPath in args:
            app.openFile(fontPath)
    # if we did not open a font, spawn new font or go headless
    if not app.allFonts():
        if platformSpecific.shouldSpawnDocument():
            app.newFile()
        else:
            # HACK: on OSX we may want to trigger native QMenuBar display
            # without opening any window. Since Qt infers new menu bar on
            # focus change, fire the signal.
            app.focusWindowChanged.emit(None)
    sys.exit(app.exec_())
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.")
Пример #10
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)
Пример #11
0
class MainWindow(QMainWindow):
    EXIT_CODE_REBOOT = 666

    def __init__(self):
        super(MainWindow, self).__init__()
        self.video, self.devmode = '', False
        self.parse_cmdline()
        self.init_logger()
        self.init_settings()
        self.init_scale()
        self.init_cutter()
        self.setWindowTitle('%s' % qApp.applicationName())
        self.setContentsMargins(0, 0, 0, 0)
        self.statusBar().showMessage('Ready')
        self.statusBar().setStyleSheet('border: none; padding: 0; margin: 0;')
        self.setAcceptDrops(True)
        self.show()
        self.console.setGeometry(int(self.x() - (self.width() / 2)), self.y() + int(self.height() / 3), 750, 300)
        try:
            if len(self.video):
                if QFileInfo(self.video).suffix() == 'vcp':
                    self.cutter.openProject(project_file=self.video)
                else:
                    self.cutter.loadMedia(self.video)
        except (FileNotFoundError, PermissionError) as e:
            QMessageBox.critical(self, 'Error loading file', sys.exc_info()[0])
            logging.exception('Error loading file')
            qApp.restoreOverrideCursor()
            self.restart()
        if not self.cutter.ffmpeg_check():
            qApp.exit(1)

    def init_scale(self) -> None:
        screen_size = qApp.desktop().availableGeometry(-1)
        self.scale = 'LOW' if screen_size.width() <= 1024 else 'NORMAL'
        self.setMinimumSize(self.get_size(self.scale))
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

    @staticmethod
    def get_size(mode: str = 'NORMAL') -> QSize:
        modes = {
            'LOW': QSize(800, 425),
            'NORMAL': QSize(915, 680),
            'HIGH': QSize(1850, 1300)
        }
        return modes[mode]

    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)
        self.console = ConsoleWidget(self)
        self.consoleLogger = ConsoleHandler(self.console)
        handlers = [logging.handlers.RotatingFileHandler(os.path.join(log_path, '%s.log'
                                                                      % qApp.applicationName().lower()),
                                                         maxBytes=1000000, backupCount=1),
                    self.consoleLogger]
        if self.parser.isSet(self.debug_option):
            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

    def init_settings(self) -> None:
        if sys.platform == 'darwin':
            QSettings.setDefaultFormat(QSettings.IniFormat)
            self.settings = QSettings(self)
        else:
            try:
                settings_path = QStandardPaths.writableLocation(QStandardPaths.AppConfigLocation).lower()
            except AttributeError:
                if sys.platform == 'win32':
                    settings_path = os.path.join(QDir.homePath(), 'AppData', 'Local', qApp.applicationName().lower())
                elif sys.platform == 'darwin':
                    settings_path = os.path.join(QDir.homePath(), 'Library', 'Preferences',
                                                 qApp.applicationName()).lower()
                else:
                    settings_path = os.path.join(QDir.homePath(), '.config', qApp.applicationName()).lower()
            os.makedirs(settings_path, exist_ok=True)
            settings_file = '%s.ini' % qApp.applicationName().lower()
            self.settings = QSettings(os.path.join(settings_path, settings_file), QSettings.IniFormat)
        if self.settings.value('geometry') is not None:
            self.restoreGeometry(self.settings.value('geometry'))
        if self.settings.value('windowState') is not None:
            self.restoreState(self.settings.value('windowState'))
        self.theme = self.settings.value('theme', 'light', type=str)
        self.startupvol = self.settings.value('volume', 100, type=int)

    @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('\nVidCutter - the simplest + fastest video cutter & joiner')
        self.parser.addPositionalArgument('video', 'Preload video file', '[video]')
        self.parser.addPositionalArgument('project', 'Open VidCutter project file (.vcp)', '[project]')
        self.debug_option = QCommandLineOption(['debug'], 'debug mode; verbose console output & logging. ' +
                                               '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.dev_option = QCommandLineOption(['dev'], 'developer mode; disables the use of compiled resource files ' +
                                             'so that all app resources & assets are accessed directly from the file ' +
                                             'system allowing you to see UI changes immediately. this typically ' +
                                             'relates to changes made to Qt stylesheets (.qss), layout/templates, ' +
                                             'content includes and images. basically all assets defined in .qrc ' +
                                             'files throughout the codebase.')
        self.parser.addOption(self.debug_option)
        self.parser.addOption(self.dev_option)
        self.parser.addVersionOption()
        self.parser.addHelpOption()
        self.parser.process(qApp)
        self.args = self.parser.positionalArguments()
        if self.parser.isSet(self.debug_option):
            os.environ['DEBUG'] = '1'
        if self.parser.isSet(self.dev_option):
            self.devmode = True
        if len(self.args) > 0:
            file_path = QFileInfo(self.args[0]).absoluteFilePath()
            if not os.path.exists(file_path):
                sys.stderr.write('\nERROR: File not found: %s\n' % file_path)
                self.close()
                sys.exit(1)
            self.video = file_path

    def init_cutter(self) -> None:
        self.cutter = VideoCutter(self)
        self.cutter.errorOccurred.connect(self.errorHandler)
        # qApp.setWindowIcon(QIcon(':/images/vidcutter.png'))
        qApp.setWindowIcon(QIcon.fromTheme(qApp.applicationName().lower(), QIcon(':/images/vidcutter.png')))
        self.setCentralWidget(self.cutter)

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

    @pyqtSlot()
    def reboot(self) -> None:
        self.save_settings()
        qApp.exit(MainWindow.EXIT_CODE_REBOOT)

    def save_settings(self) -> None:
        self.settings.setValue('lastFolder', self.cutter.lastFolder)
        self.settings.setValue('geometry', self.saveGeometry())
        self.settings.setValue('windowState', self.saveState())
        self.settings.sync()

    @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 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)

    @pyqtSlot(str)
    def errorHandler(self, msg: str) -> None:
        QMessageBox.critical(self, 'An error occurred', msg, QMessageBox.Ok)
        logging.error(msg)

    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) -> None:
        if event.button() == Qt.LeftButton and self.cutter.mediaAvailable:
            self.cutter.cliplist.clearSelection()
            self.cutter.timeCounter.clearFocus()
            self.cutter.frameCounter.clearFocus()

    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 resizeEvent(self, event: QResizeEvent) -> None:
        try:
            if self.cutter.mediaAvailable and self.cutter.thumbnailsButton.isChecked():
                self.cutter.seekSlider.reloadThumbs()
        except AttributeError:
            pass

    def closeEvent(self, event: QCloseEvent) -> None:
        event.accept()
        self.console.deleteLater()
        if hasattr(self, 'cutter'):
            self.save_settings()
            if hasattr(self.cutter, 'mpvWidget'):
                self.cutter.mpvWidget.shutdown()
        qApp.quit()
Пример #12
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]
Пример #13
0
    - create instance of application class (ui)
    - call setupUi to set dialog properties (calls retranslateUi)
    - call parseConfigFile
    - show the QDialog
    - the application will process messages until it is told to exit
    """
    import sys, os
    from subprocess import Popen, PIPE
    from configparser import ConfigParser

    app = QApplication(sys.argv)
    app.setApplicationName("gitStatus.py")
    app.setApplicationVersion("1.0.0")

    clp = QCommandLineParser()  # handle command line options
    clp.addHelpOption()
    clp.addVersionOption()
    verboseOption = QCommandLineOption("verbose",
                                       "Issue progress messages to console.")
    clp.addOption(verboseOption)
    clp.process(sys.argv)

    GitStatus = QtWidgets.QDialog()  # create QDialog
    ui = Ui_GitStatus()  # instantiate ui
    ui.setupUi(GitStatus)  # configure all widgets
    ui.isVerbose = clp.isSet(verboseOption)

    if not ui.parseConfigFile():  # read the .ini file
        sys.exit(1)

    ui.populateDialog()  # populate the dialog's widgets
Пример #14
0
class MainWindow(QMainWindow):
    EXIT_CODE_REBOOT = 666
    TEMP_PROJECT_FILE = 'vidcutter_reboot.vcp'
    WORKING_FOLDER = os.path.join(QDir.tempPath(), 'vidcutter')

    def __init__(self):
        super(MainWindow, self).__init__()
        self.video, self.resizeTimer = '', 0
        self.parse_cmdline()
        self.init_settings()
        self.init_logger()
        self.init_scale()
        self.init_cutter()
        self.setWindowTitle(qApp.applicationName())
        self.setContentsMargins(0, 0, 0, 0)
        self.statusBar().showMessage('Ready')
        self.statusBar().setStyleSheet('border: none; padding: 0; margin: 0;')
        self.setAcceptDrops(True)
        self.show()
        if sys.platform == 'win32' and TaskbarProgress.isValidWinVer():
            self.win_taskbar_button = QWinTaskbarButton(self)
            self.win_taskbar_button.setWindow(self.windowHandle())
            self.win_taskbar_button.progress().setVisible(True)
            self.win_taskbar_button.progress().setValue(0)
        self.console.setGeometry(int(self.x() - (self.width() / 2)), self.y() + int(self.height() / 3), 750, 300)
        if not self.video and os.path.isfile(os.path.join(QDir.tempPath(), MainWindow.TEMP_PROJECT_FILE)):
            self.video = os.path.join(QDir.tempPath(), MainWindow.TEMP_PROJECT_FILE)
        if self.video:
            self.file_opener(self.video)

    def init_scale(self) -> None:
        screen_size = qApp.desktop().availableGeometry(-1)
        self.scale = 'LOW' if screen_size.width() <= 1024 else 'NORMAL'
        self.setMinimumSize(self.get_size(self.scale))
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

    @pyqtSlot(str)
    def file_opener(self, filename: str) -> None:
        try:
            if QFileInfo(filename).suffix() == 'vcp':
                self.cutter.openProject(project_file=filename)
                if filename == os.path.join(QDir.tempPath(), MainWindow.TEMP_PROJECT_FILE):
                    os.remove(os.path.join(QDir.tempPath(), MainWindow.TEMP_PROJECT_FILE))
            else:
                self.cutter.loadMedia(filename)
        except (FileNotFoundError, PermissionError):
            QMessageBox.critical(self, 'Error loading file', sys.exc_info()[0])
            logging.exception('Error loading file')
            qApp.restoreOverrideCursor()
            self.restart()

    @staticmethod
    def get_size(mode: str='NORMAL') -> QSize:
        modes = {
            'LOW': QSize(800, 425),
            'NORMAL': QSize(930, 680),
            'HIGH': QSize(1850, 1300)
        }
        return modes[mode]

    def init_logger(self) -> None:
        try:
            log_path = QStandardPaths.writableLocation(QStandardPaths.AppConfigLocation).replace(
                qApp.applicationName(), qApp.applicationName().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)
        self.console = ConsoleWidget(self)
        self.consoleLogger = ConsoleHandler(self.console)
        handlers = [logging.handlers.RotatingFileHandler(os.path.join(log_path, '%s.log'
                                                                      % qApp.applicationName().lower()),
                                                         maxBytes=1000000, backupCount=1),
                    self.consoleLogger]
        if self.parser.isSet(self.debug_option) or self.verboseLogs:
            # noinspection PyTypeChecker
            handlers.append(logging.StreamHandler())
        logging.setLoggerClass(VideoLogger)
        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 = MainWindow.log_uncaught_exceptions

    def init_settings(self) -> None:
        try:
            settings_path = QStandardPaths.writableLocation(QStandardPaths.AppConfigLocation).replace(
                qApp.applicationName(), qApp.applicationName().lower())
        except AttributeError:
            if sys.platform == 'win32':
                settings_path = os.path.join(QDir.homePath(), 'AppData', 'Local', qApp.applicationName().lower())
            elif sys.platform == 'darwin':
                settings_path = os.path.join(QDir.homePath(), 'Library', 'Preferences',
                                             qApp.applicationName().lower())
            else:
                settings_path = os.path.join(QDir.homePath(), '.config', qApp.applicationName().lower())
        os.makedirs(settings_path, exist_ok=True)
        settings_file = '%s.ini' % qApp.applicationName().lower()
        self.settings = QSettings(os.path.join(settings_path, settings_file), QSettings.IniFormat)
        if self.settings.value('geometry') is not None:
            self.restoreGeometry(self.settings.value('geometry'))
        if self.settings.value('windowState') is not None:
            self.restoreState(self.settings.value('windowState'))
        self.theme = self.settings.value('theme', 'light', type=str)
        self.startupvol = self.settings.value('volume', 100, type=int)
        self.verboseLogs = self.settings.value('verboseLogs', 'off', type=str) in {'on', 'true'}

    @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('\nVidCutter - the simplest + fastest media cutter & joiner')
        self.parser.addPositionalArgument('video', 'Preload video file', '[video]')
        self.parser.addPositionalArgument('project', 'Open VidCutter project file (.vcp)', '[project]')
        self.debug_option = QCommandLineOption(['debug'], 'debug mode; verbose console output & logging. '
                                               '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.debug_option)
        self.parser.addVersionOption()
        self.parser.addHelpOption()
        self.parser.process(qApp)
        self.args = self.parser.positionalArguments()
        if self.parser.isSet(self.debug_option):
            os.environ['DEBUG'] = '1'
        if len(self.args) > 0:
            file_path = QFileInfo(self.args[0]).absoluteFilePath()
            if not os.path.exists(file_path):
                sys.stderr.write('\nERROR: File not found: %s\n' % file_path)
                self.close()
                qApp.exit(1)
            self.video = file_path

    def init_cutter(self) -> None:
        self.cutter = VideoCutter(self)
        self.cutter.errorOccurred.connect(self.errorHandler)
        self.setCentralWidget(self.cutter)
        qApp.setWindowIcon(VideoCutter.getAppIcon(encoded=False))

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

    @pyqtSlot()
    def reboot(self) -> None:
        if self.cutter.mediaAvailable:
            self.cutter.saveProject(reboot=True)
        self.save_settings()
        qApp.exit(MainWindow.EXIT_CODE_REBOOT)

    def save_settings(self) -> None:
        self.settings.setValue('lastFolder', self.cutter.lastFolder)
        self.settings.setValue('geometry', self.saveGeometry())
        self.settings.setValue('windowState', self.saveState())
        self.settings.sync()

    @staticmethod
    def get_path(path: str=None, override: bool=False) -> str:
        if override:
            if getattr(sys, 'frozen', False) and getattr(sys, '_MEIPASS', False):
                # noinspection PyProtectedMember, PyUnresolvedReferences
                return os.path.join(sys._MEIPASS, path)
            return os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), path)
        return ':%s' % path

    @pyqtSlot(str)
    def errorHandler(self, msg: str, title: str=None) -> None:
        qApp.restoreOverrideCursor()
        QMessageBox.critical(self, 'An error occurred' if title is None else title, msg, QMessageBox.Ok)
        logging.error(msg)

    @staticmethod
    @pyqtSlot()
    def cleanup():
        shutil.rmtree(MainWindow.WORKING_FOLDER, ignore_errors=True)

    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) -> None:
        if event.button() == Qt.LeftButton and self.cutter.mediaAvailable:
            self.cutter.cliplist.clearSelection()
            self.cutter.timeCounter.clearFocus()
            self.cutter.frameCounter.clearFocus()
            # noinspection PyBroadException
            try:
                if hasattr(self.cutter, 'notify'):
                    self.cutter.notify.close()
            except BaseException:
                pass
            event.accept()

    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.file_opener(filename)
        event.accept()

    def resizeEvent(self, event: QResizeEvent) -> None:
        try:
            if self.isEnabled() and self.cutter.mediaAvailable and self.cutter.thumbnailsButton.isChecked():
                if self.cutter.seekSlider.thumbnailsOn:
                    self.cutter.sliderWidget.setLoader(True)
                    self.cutter.sliderWidget.hideThumbs()
                if self.resizeTimer:
                    self.killTimer(self.resizeTimer)
                self.resizeTimer = self.startTimer(500)
        except AttributeError:
            pass

    def timerEvent(self, event: QTimerEvent) -> None:
        try:
            self.cutter.seekSlider.reloadThumbs()
            self.killTimer(self.resizeTimer)
            self.resizeTimer = 0
        except AttributeError:
            pass

    def closeEvent(self, event: QCloseEvent) -> None:
        try:
            if not self.isEnabled():
                warntext = '''
                    <style>
                        h2 {{
                            color: {};
                            font-family: "Futura-Light", sans-serif;
                            font-weight: 400;
                        }}
                    </style>
                    <table border="0" cellpadding="6" cellspacing="0" width="350">
                        <tr>
                            <td><h2>Video is currently being processed</h2></td>
                        </tr>
                        <tr>
                            <td>Are you sure you wish to exit right now?</td>
                        </tr>
                    </table>'''.format('#C681D5' if self.theme == 'dark' else '#642C68')
                exitwarn = QMessageBox(QMessageBox.Warning, 'Warning', warntext, parent=self)
                exitwarn.setIconPixmap(QPixmap(':images/warning.png'))
                exitwarn.addButton('Yes', QMessageBox.NoRole)
                cancelbutton = exitwarn.addButton('No', QMessageBox.RejectRole)
                exitwarn.exec_()
                res = exitwarn.clickedButton()
                if res == cancelbutton:
                    event.ignore()
                    return
            elif self.cutter.mediaAvailable and self.cutter.projectDirty and not self.cutter.projectSaved:
                warntext = '''
                    <style>
                        h2 {{
                            color: {};
                            font-family: "Futura-Light", sans-serif;
                            font-weight: 400;
                        }}
                    </style>
                    <table border="0" cellpadding="6" cellspacing="0" width="350">
                        <tr>
                            <td><h2>There are unsaved changes in your project</h2></td>
                        </tr>
                        <tr>
                            <td>Would you like to save the project now?</td>
                        </tr>
                    </table>'''.format('#C681D5' if self.theme == 'dark' else '#642C68')
                savewarn = QMessageBox(QMessageBox.Warning, 'Warning', warntext, parent=self)
                savewarn.setIconPixmap(QPixmap(':images/warning.png'))
                savebutton = savewarn.addButton('Save project', QMessageBox.YesRole)
                savewarn.addButton('Do not save', QMessageBox.NoRole)
                cancelbutton = savewarn.addButton('Cancel', QMessageBox.RejectRole)
                savewarn.exec_()
                res = savewarn.clickedButton()
                if res == savebutton:
                    event.ignore()
                    self.cutter.saveProject()
                    return
                elif res == cancelbutton:
                    event.ignore()
                    return
        except AttributeError:
            pass
        event.accept()
        self.console.deleteLater()
        if hasattr(self, 'cutter'):
            self.save_settings()
            try:
                if hasattr(self.cutter.videoService, 'smartcut_jobs'):
                    [
                        self.cutter.videoService.cleanup(job.files.values())
                        for job in self.cutter.videoService.smartcut_jobs
                    ]
                if hasattr(self.cutter, 'mpvWidget'):
                    self.cutter.mpvWidget.shutdown()
            except AttributeError:
                pass
        try:
            qApp.quit()
        except mpv.MPVError:
            pass
Пример #15
0
    filename = "resources/Entities/questionmark.png"
    if img:
        filename = f"{os.path.splitext(anim.file)[0]}.png"
    img.save(filename, "PNG")


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)

    cmdParser = QCommandLineParser()
    cmdParser.setApplicationDescription(
        "Icon generator utility script for Basement Renovator. Takes an anm2 "
    )
    cmdParser.addHelpOption()

    cmdParser.addPositionalArgument("file", "anm2 file to generate the icon from")

    frameOpt = QCommandLineOption(
        ["f", "frame"], "frame in the anm2 to use, defaults to 0", "f", "0"
    )
    cmdParser.addOption(frameOpt)

    animOpt = QCommandLineOption(
        ["n", "anim"],
        "name of the animation in the anm2 to use, defaults to the default anim",
        "n",
    )
    cmdParser.addOption(animOpt)
Пример #16
0
        qml_context.setContextProperty("windowView", view)
        qml_context.setContextProperty("qApp", qApp)
        qml_context.setContextProperty("screenWidth", view.window_info.screen_width)
        qml_context.setContextProperty("screenHeight", view.window_info.screen_height)
        qml_context.setContextProperty("_menu_controller", menu_controller)

        view.setSource(QUrl.fromLocalFile(MAIN_QML))
        view.disable_zone()
        view.showWindow()

        menu_controller.preMenuShow.connect(view.ungrabFocus)
        menu_controller.postMenuHide.connect(view.grabFocus)

if __name__ == "__main__":
    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)
Пример #17
0
def main():
    global app

    # Register representation factories
    baseRepresentationFactories.registerAllFactories()
    representationFactories.registerAllFactories()

    # initialize the app
    app = Application(sys.argv)
    app.setOrganizationName("SimpleFont")
    app.setOrganizationDomain("elih.blog/simplefont")
    app.setApplicationName("SimpleFont")
    app.setApplicationVersion(__version__)
    app.setWindowIcon(QIcon(":app.png"))
    app.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
    appFont = platformSpecific.UIFontOverride()
    if appFont is not None:
        app.setFont(appFont)
    # app.setStyleSheet(platformSpecific.appStyleSheet())
    app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())

    # Install stream redirection
    app.outputWindow = OutputWindow()
    # Exception handling
    sys.excepthook = errorReports.exceptionCallback

    # Qt's translation for itself. May not be installed.
    # qtTranslator = QTranslator()
    # qtTranslator.load("qt_" + QLocale.system().name(),
    #                   QLibraryInfo.location(QLibraryInfo.TranslationsPath))
    # app.installTranslator(qtTranslator)

    # appTranslator = QTranslator()
    # appTranslator.load("simplefont_" + QLocale.system().name(),
    #                    os.path.dirname(os.path.realpath(__file__)) +
    #                    "/resources")
    # app.installTranslator(appTranslator)

    # parse options and open fonts
    parser = QCommandLineParser()
    parser.setApplicationDescription(QApplication.translate(
        "Command-line parser", "The SimpleFont font editor."))
    parser.addHelpOption()
    parser.addVersionOption()
    parser.addPositionalArgument(QApplication.translate(
        "Command-line parser", "files"), QApplication.translate(
        "Command-line parser", "The UFO files to open."))
    parser.process(app)
    
    # load menu
    if platformSpecific.useGlobalMenuBar():
        app.fetchMenuBar()
        app.setQuitOnLastWindowClosed(False)

    # bootstrap extensions

    # process files
    args = parser.positionalArguments()
    if not args:
        # maybe load recent file
        loadRecentFile = settings.loadRecentFile()
        if loadRecentFile:
            recentFiles = settings.recentFiles()
            if len(recentFiles) and os.path.exists(recentFiles[0]):
                app.openFile(recentFiles[0])
    else:
        for fontPath in args:
            app.openFile(fontPath)
    # if we did not open a font, spawn new font or go headless
    if not app.allFonts():
        if platformSpecific.shouldSpawnDocument():
            app.newFile()
        else:
            # HACK: on OSX we may want to trigger native QMenuBar display
            # without opening any window. Since Qt infers new menu bar on
            # focus change, fire the signal.
            app.focusWindowChanged.emit(None)
    sys.exit(app.exec_())