Beispiel #1
0
	def data(self, role, column):
		if role == Qt.TextColorRole:
			return QGuiApplication.palette().text().color()
		elif role == Qt.FontRole:
			return QApplication.font()
		elif role == Qt.TextAlignmentRole:
			if column==0:
				return Qt.AlignLeft | Qt.AlignVCenter
			else:
				return Qt.AlignCenter | Qt.AlignVCenter
		elif role == Qt.SizeHintRole:
			return QSize(0, self.ITEM_ROW_HEIGHT)
		elif role == ITEM_ROLE_TYPE:
			return self.typeId()
		elif role == Qt.EditRole:
			return self.getAttributeByIndex(column)
		elif role == Qt.DisplayRole:
			return self.getAttributeByIndex(column)
		elif role == ITEM_ROLE_ENABLED:
			return self.getAttributeByLabel("Enable")
		elif role == ITEM_ROLE_ISOLATED:
			return self.getAttributeByLabel("Isolate")
		elif role == ITEM_ROLE_ATTR_TYPE:
			return self.attributeType(column)
		elif role == ITEM_ROLE_ATTR_HIDDEN:
			return self.attributeHidden(column)
		elif role == ITEM_ROLE_IS_LAYER_MEMBER:
			return self._isMemberOfVisibleLayer()
		return None
    def init_font_config(self):
        self.ui_default_font = QApplication.font("QMenu")
        self.tabular_view_font = QApplication.font("QMenu")

        self.disasm_font = QFont("DejaVu Sans Mono", 10)
        self.disasm_font_metrics = QFontMetricsF(self.disasm_font)
        self.disasm_font_height = self.disasm_font_metrics.height()
        self.disasm_font_width = self.disasm_font_metrics.width('A')
        self.disasm_font_ascent = self.disasm_font_metrics.ascent()

        self.symexec_font = QFont("DejaVu Sans Mono", 10)
        self.symexec_font_metrics = QFontMetricsF(self.symexec_font)
        self.symexec_font_height = self.symexec_font_metrics.height()
        self.symexec_font_width = self.symexec_font_metrics.width('A')
        self.symexec_font_ascent = self.symexec_font_metrics.ascent()

        self.code_font = QFont("Source Code Pro", 10)
        self.code_font_metrics = QFontMetricsF(self.code_font)
        self.code_font_height = self.code_font_metrics.height()
        self.code_font_width = self.code_font_metrics.width('A')
        self.code_font_ascent = self.code_font_metrics.ascent()
Beispiel #3
0
def main():
    path_icon = str(Path(__file__).parent / 'assets/openmc_logo.png')
    path_splash = str(Path(__file__).parent / 'assets/splash.png')

    app = QApplication(sys.argv)
    app.setOrganizationName("OpenMC")
    app.setOrganizationDomain("openmc.org")
    app.setApplicationName("OpenMC Plot Explorer")
    app.setWindowIcon(QtGui.QIcon(path_icon))
    app.setAttribute(QtCore.Qt.AA_DontShowIconsInMenus, True)

    splash_pix = QtGui.QPixmap(path_splash)
    splash = QSplashScreen(splash_pix, QtCore.Qt.WindowStaysOnTopHint)
    splash.setMask(splash_pix.mask())
    splash.show()
    app.processEvents()
    splash.setMask(splash_pix.mask())
    splash.showMessage("Loading Model...",
                       QtCore.Qt.AlignHCenter | QtCore.Qt.AlignBottom)
    app.processEvents()
    # load OpenMC model on another thread
    loader_thread = Thread(target=_openmcReload)
    loader_thread.start()
    # while thread is working, process app events
    while loader_thread.is_alive():
        app.processEvents()

    splash.clearMessage()
    splash.showMessage("Starting GUI...",
                       QtCore.Qt.AlignHCenter | QtCore.Qt.AlignBottom)
    app.processEvents()

    font_metric = QtGui.QFontMetrics(app.font())
    screen_size = app.primaryScreen().size()
    mainWindow = MainWindow(font_metric, screen_size)
    # connect splashscreen to main window, close when main window opens
    mainWindow.loadGui()
    mainWindow.show()
    splash.close()

    # connect interrupt signal to close call
    signal.signal(signal.SIGINT, lambda *args: mainWindow.close())
    # create timer that interrupts the Qt event loop
    # to check for a signal
    timer = QtCore.QTimer()
    timer.start(500)
    timer.timeout.connect(lambda: None)

    sys.exit(app.exec_())
Beispiel #4
0
def setDefaultFont(app: QApplication) -> None:
    """save and set default font point size"""

    strSystemFont = data.get(ConfigKey.SystemFont)
    if strSystemFont is None:
        systemFont = app.font()
        systemFont.setPointSize(14)
        data.set(ConfigKey.SystemFont, systemFont.toString())
    else:
        systemFont = QFont()
        systemFont.fromString(strSystemFont)
    strFont = data.get(ConfigKey.Font)
    if strFont is None:
        font = systemFont
        font.setPointSize(14)
        data.set(ConfigKey.Font, font.toString())
Beispiel #5
0
def compute_font_size():
    screen_rect = QApplication.desktop().availableGeometry()

    font_size = 14

    while True:
        font = QApplication.font()
        font.setPixelSize(font_size)
        fm = QFontMetrics(font)

        byte_height = fm.boundingRect("0").height()
        byte_view_height = byte_height * 64

        if byte_view_height < screen_rect.height():
            return font_size
        else:
            font_size -= 1
Beispiel #6
0
 def data(self, role):
     if role == Qt.DisplayRole:
         return self.name
     elif role == Qt.EditRole:
         return self.name
     elif role == Qt.TextAlignmentRole:
         return Qt.AlignLeft | Qt.AlignVCenter
     elif role == Qt.TextColorRole:
         return QGuiApplication.palette().text().color()
     elif role == Qt.FontRole:
         return QApplication.font()
     elif role == Qt.SizeHintRole:
         return QSize(0, utils.dpiScale(ROW_HEIGHT))
     elif role == NODE_ACCEPTS_DRAG:
         return False
     elif role == NODE_ACTIVE_FRAME:
         return QColor(150, 150, 150)
     else:
         return super(ModelProxyItem, self).data(role)
Beispiel #7
0
    def __init__(self, entity_item):
        """Initializes item.

        Args:
            entity_item (spinetoolbox.widgets.graph_view_graphics_items.EntityItem): The parent item.
        """
        super().__init__(entity_item)
        self.entity_item = entity_item
        self._font = QApplication.font()
        self._font.setPointSize(11)
        self.setFont(self._font)
        self.bg = QGraphicsRectItem(self)
        self.bg_color = QGuiApplication.palette().color(
            QPalette.Normal, QPalette.ToolTipBase)
        self.bg_color.setAlphaF(0.8)
        self.bg.setBrush(QBrush(self.bg_color))
        self.bg.setPen(Qt.NoPen)
        self.bg.setFlag(QGraphicsItem.ItemStacksBehindParent)
        self.setFlag(QGraphicsItem.ItemIsSelectable, enabled=False)
        self.setAcceptHoverEvents(False)
Beispiel #8
0
    def initialize(self):
        font_size = compute_font_size()

        font = QApplication.font()
        font.setPixelSize(font_size)
        # font.setBold(True)
        self.font = font

        self.font_bold = QFont(font)
        self.font_bold.setBold(True)

        self.byte_rect = self.compute_byte_rect()
        self.byte_advance = self.compute_byte_advance()
        self.bytes_pixmap = self.create_pixmap(transparent=False)
        self.bytes_field = self.build_bytes_field()
        self.cursors_pixmap = self.create_pixmap(transparent=True)

        self.setMinimumWidth(self.bytes_pixmap.width())
        self.setMinimumHeight(self.bytes_pixmap.height())

        self.render_empty_bytes_to_pixmap()

        self.prev_msg_lines = MsgLines(0, 0)
        settings.setValue("mainWindow/Position", self.pos())
        settings.setValue("mainWindow/State", self.saveState())

        settings.setValue("colorDialog/Size", self.colorDialog.size())
        settings.setValue("colorDialog/Position", self.colorDialog.pos())
        visible = int(self.colorDialog.isVisible())
        settings.setValue("colorDialog/Visible", visible)

        if len(self.model.previousViews) > 10:
            self.model.previousViews = self.model.previousViews[-10:]
        if len(self.model.subsequentViews) > 10:
            self.model.subsequentViews = self.model.subsequentViews[-10:]

        with open('plot_settings.pkl', 'wb') as file:
            pickle.dump(self.model, file)


if __name__ == '__main__':

    app = QApplication(sys.argv)
    app.setOrganizationName("OpenMC")
    app.setOrganizationDomain("xxxxxgithub.com/openmc-dev/")
    app.setApplicationName("xxxxxOpenMC Plot Explorer")
    app.setWindowIcon(QtGui.QIcon('openmc_logo.png'))
    app.setAttribute(QtCore.Qt.AA_DontShowIconsInMenus, True)

    FM = QtGui.QFontMetricsF(app.font())
    mainWindow = MainWindow()
    mainWindow.show()
    sys.exit(app.exec_())
Beispiel #10
0
    def __init__(self):
        super().__init__()
        self.setAttribute(
            Qt.WA_DeleteOnClose
        )  # let Qt delete stuff before the python garbage-collector gets to work
        self.repo = None
        self.branches_model = None

        # instantiate main window
        self.ui = ui.Ui_MainWindow()
        self.ui.setupUi(self)

        self.fs_watch = QFileSystemWatcher(self)
        self.fs_watch.fileChanged.connect(self.on_file_changed)
        self.fs_watch.directoryChanged.connect(self.on_dir_changed)

        self.settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                                  'pqgit', 'config')

        # for comparison
        self.new_c_id, self.old_c_id = None, None

        # window icon
        cwd = os.path.dirname(os.path.realpath(__file__))
        self.setWindowIcon(QIcon(os.path.join(cwd, 'Git-Icon-White.png')))
        self.setWindowTitle('pqgit')

        # size and position
        self.move(self.settings.value('w/pos', QPoint(200, 200)))
        self.resize(self.settings.value('w/size', QSize(1000, 1000)))
        self.ui.hist_splitter.setSizes([
            int(s) for s in self.settings.value('w/hist_splitter', [720, 360])
        ])
        self.ui.cinf_splitter.setSizes([
            int(s) for s in self.settings.value('w/cinf_splitter', [360, 360])
        ])
        self.ui.diff_splitter.setSizes([
            int(s)
            for s in self.settings.value('w/diff_splitter', [150, 1200, 230])
        ])

        # open repo dir
        open_shortcut = QShortcut(QKeySequence('Ctrl+O'), self)
        open_shortcut.activated.connect(self.open_dir)

        # set-up ui
        self.branches_model = BranchesModel()
        self.ui.tvBranches.setModel(self.branches_model)
        self.ui.tvBranches.selectionModel().selectionChanged.connect(
            self.branches_selection_changed)
        self.ui.tvBranches.resizeColumnsToContents()

        self.history_model = HistoryModel()
        self.ui.tvHistory.setModel(self.history_model)
        self.ui.tvHistory.selectionModel().selectionChanged.connect(
            self.history_selection_changed)

        self.files_model = FilesModel()
        self.ui.tvFiles.setModel(self.files_model)
        self.ui.tvFiles.selectionModel().selectionChanged.connect(
            self.files_selection_changed)

        self.ui.tvFiles.doubleClicked.connect(self.on_file_doubleclicked)

        for view in (self.ui.tvBranches, self.ui.tvHistory, self.ui.tvFiles):
            view.horizontalHeader().setSectionResizeMode(
                1, QHeaderView.Stretch)
            view.setSelectionBehavior(QAbstractItemView.SelectRows)
            view.setShowGrid(False)
            view.verticalHeader().setDefaultSectionSize(
                QApplication.font().pointSize() + 2)
            view.verticalHeader().hide()

        self.ui.teDiff.setFont(QFont('Monospace'))

        self.difftools = []

        timer = QTimer(self)
        timer.timeout.connect(self.on_timer)
        timer.start(5000)

        self.dir_name = self.settings.value('last_opened_repo', None)

        try:
            pygit2.Repository(self.dir_name)
        except Exception:  #pylint: disable=broad-except
            self.open_dir()
            return

        self.open_repo()
Beispiel #11
0
 def init_font_config(self):
     if self.ui_default_font is None:
         self.ui_default_font = QApplication.font("QMenu")
     if self.tabular_view_font is None:
         self.tabular_view_font = QApplication.font("QMenu")
Beispiel #12
0
    signal.signal(signal.SIGINT, signal.SIG_DFL)

    app = QApplication(sys.argv)

    app.setAttribute(Qt.AA_EnableHighDpiScaling)

    c = Connector()
    d = Num()
    # c.text = "TOTO"
    print("Python: " + c.text)
    print("Python: " + d.number)
    # c._text = "TOTO"
    # c.setText("TOTO")
    # print(c.getText())

    font = app.font()
    font.setPointSize(10)
    app.setFont(font)

    pwd = os.path.dirname(__file__)
    qmlDir = os.path.join(pwd, "qml")
    url = os.path.join(qmlDir, "main.qml")

    engine = QmlInstantEngine()
    engine.addFilesFromDirectory(qmlDir, recursive=True)
    engine.setWatching(os.environ.get("MESHROOM_INSTANT_CODING", True))
    engine.addImportPath(qmlDir)

    engine.rootContext().setContextProperty("_Connector", c)
    engine.rootContext().setContextProperty("_Num", d)
    engine.load(os.path.normpath(url))
Beispiel #13
0
                print(err)

    def exit(self, event):
        self.close()

    def partQuery(self, event):
        pd = PartsDialog(self, self.cnx)

    def partManage(self, event):
        pm = PartsManageDialog(self, self.cnx)

    def catManage(self, event):
        cm = CatManageDialog(self, self.cnx)

    def placeManage(self, event):
        pm = PlaceManageDialog(self, self.cnx)

    def closeEvent(self, event):
        if hasattr(self, 'cnx') and self.cnx:
            self.cnx.close()


if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    f = app.font()
    f.setPixelSize(14)
    app.setFont(f)
    window.show()
    sys.exit(app.exec_())
Beispiel #14
0
    parser.add_argument('--allow-resizing', default=False, action='store_true')
    parser.add_argument('--larger-font', default=False, action='store_true')
    args = parser.parse_args()

    if not sys.platform.startswith('win'):
        print("Unsupported Platform. This application is tested on Windows Only")
        if args.ignore_platform:
            print("The application will continue to run but may crash or not function as intended")
        else:
            exit(1)
    
    app = QApplication(sys.argv)
    app.setStyle("Fusion")

    if args.larger_font:
        font = app.font()
        font.setPointSize(app.font().pointSize()*1.5)
        font.setWeight(app.font().weight()*1.5)
        app.setFont(font)
        args.allow_resizing = True

    mainWindow = MainWindow()

    if not args.allow_resizing:
        mainWindow.setFixedSize(mainWindow.size())

    mainWindow.show()

    # Project Stuff
    mainWindow.refreshSerialPortsButton.click()
    mainWindow.serialPortComboBox.setCurrentIndex(0)
Beispiel #15
0
    def __init__(self, parent, data):
        if not type(data) == binaryninja.binaryview.BinaryView:
            raise Exception('expected widget data to be a BinaryView')

        self.bv = data

        self.debug_state = binjaplug.get_state(data)
        memory_view = self.debug_state.memory_view
        self.debug_state.ui.debug_view = self

        QWidget.__init__(self, parent)
        View.__init__(self)

        self.setupView(self)

        self.current_offset = 0

        self.splitter = QSplitter(Qt.Orientation.Horizontal, self)

        frame = ViewFrame.viewFrameForWidget(self)
        self.memory_editor = LinearView(memory_view, frame)
        self.binary_editor = DisassemblyContainer(frame, data, frame)

        self.binary_text = TokenizedTextView(self, memory_view)
        self.is_raw_disassembly = False

        # TODO: Handle these and change views accordingly
        # Currently they are just disabled as the DisassemblyContainer gets confused
        # about where to go and just shows a bad view
        self.binary_editor.getDisassembly().actionHandler().bindAction(
            "View in Hex Editor", UIAction())
        self.binary_editor.getDisassembly().actionHandler().bindAction(
            "View in Linear Disassembly", UIAction())
        self.binary_editor.getDisassembly().actionHandler().bindAction(
            "View in Types View", UIAction())

        self.memory_editor.actionHandler().bindAction("View in Hex Editor",
                                                      UIAction())
        self.memory_editor.actionHandler().bindAction(
            "View in Disassembly Graph", UIAction())
        self.memory_editor.actionHandler().bindAction("View in Types View",
                                                      UIAction())

        small_font = QApplication.font()
        small_font.setPointSize(11)

        bv_layout = QVBoxLayout()
        bv_layout.setSpacing(0)
        bv_layout.setContentsMargins(0, 0, 0, 0)

        bv_label = QLabel("Loaded File")
        bv_label.setFont(small_font)
        bv_layout.addWidget(bv_label)
        bv_layout.addWidget(self.binary_editor)

        self.bv_widget = QWidget()
        self.bv_widget.setLayout(bv_layout)

        disasm_layout = QVBoxLayout()
        disasm_layout.setSpacing(0)
        disasm_layout.setContentsMargins(0, 0, 0, 0)

        disasm_label = QLabel("Raw Disassembly at PC")
        disasm_label.setFont(small_font)
        disasm_layout.addWidget(disasm_label)
        disasm_layout.addWidget(self.binary_text)

        self.disasm_widget = QWidget()
        self.disasm_widget.setLayout(disasm_layout)

        memory_layout = QVBoxLayout()
        memory_layout.setSpacing(0)
        memory_layout.setContentsMargins(0, 0, 0, 0)

        memory_label = QLabel("Debugged Process")
        memory_label.setFont(small_font)
        memory_layout.addWidget(memory_label)
        memory_layout.addWidget(self.memory_editor)

        self.memory_widget = QWidget()
        self.memory_widget.setLayout(memory_layout)

        self.splitter.addWidget(self.bv_widget)
        self.splitter.addWidget(self.memory_widget)

        # Equally sized
        self.splitter.setSizes([0x7fffffff, 0x7fffffff])

        self.controls = ControlsWidget.DebugControlsWidget(
            self, "Controls", data, self.debug_state)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        layout.addWidget(self.controls)
        layout.addWidget(self.splitter, 100)
        self.setLayout(layout)

        self.needs_update = True
        self.update_timer = QTimer(self)
        self.update_timer.setInterval(200)
        self.update_timer.setSingleShot(False)
        self.update_timer.timeout.connect(lambda: self.updateTimerEvent())

        # Add debugger state to the interpreter as `dbg`
        main_window = parent.window()
        dock_handler = main_window.findChild(DockHandler, '__DockHandler')
        if dock_handler:
            console = dock_handler.getDockWidget('Python Console')
            if console:
                # Hack: Currently no way to access the scripting provider directly
                # So just run the commands through the ui
                console.widget().addInput(
                    "import debugger\ndbg = debugger.get(bv)")
Beispiel #16
0
	def __init__(self, parent, data):
		if not type(data) == BinaryView:
			raise Exception('expected widget data to be a BinaryView')

		self.bv = data

		self.debug_state = binjaplug.get_state(data)
		memory_view = self.debug_state.memory_view
		self.debug_state.ui.debug_view = self

		QWidget.__init__(self, parent)
		self.controls = ControlsWidget.DebugControlsWidget(self, "Controls", data, self.debug_state)
		View.__init__(self)

		self.setupView(self)

		self.current_offset = 0

		self.splitter = QSplitter(Qt.Orientation.Horizontal, self)

		frame = ViewFrame.viewFrameForWidget(self)
		self.memory_editor = LinearView(memory_view, frame)
		self.binary_editor = DisassemblyContainer(frame, data, frame)

		self.binary_text = TokenizedTextView(self, memory_view)
		self.is_raw_disassembly = False
		self.raw_address = 0

		self.is_navigating_history = False
		self.memory_history_addr = 0

		# TODO: Handle these and change views accordingly
		# Currently they are just disabled as the DisassemblyContainer gets confused
		# about where to go and just shows a bad view
		self.binary_editor.getDisassembly().actionHandler().bindAction("View in Hex Editor", UIAction())
		self.binary_editor.getDisassembly().actionHandler().bindAction("View in Linear Disassembly", UIAction())
		self.binary_editor.getDisassembly().actionHandler().bindAction("View in Types View", UIAction())

		self.memory_editor.actionHandler().bindAction("View in Hex Editor", UIAction())
		self.memory_editor.actionHandler().bindAction("View in Disassembly Graph", UIAction())
		self.memory_editor.actionHandler().bindAction("View in Types View", UIAction())

		small_font = QApplication.font()
		small_font.setPointSize(11)

		bv_layout = QVBoxLayout()
		bv_layout.setSpacing(0)
		bv_layout.setContentsMargins(0, 0, 0, 0)

		bv_label = QLabel("Loaded File")
		bv_label.setFont(small_font)
		bv_layout.addWidget(bv_label)
		bv_layout.addWidget(self.binary_editor)

		self.bv_widget = QWidget()
		self.bv_widget.setLayout(bv_layout)

		disasm_layout = QVBoxLayout()
		disasm_layout.setSpacing(0)
		disasm_layout.setContentsMargins(0, 0, 0, 0)

		disasm_label = QLabel("Raw Disassembly at PC")
		disasm_label.setFont(small_font)
		disasm_layout.addWidget(disasm_label)
		disasm_layout.addWidget(self.binary_text)

		self.disasm_widget = QWidget()
		self.disasm_widget.setLayout(disasm_layout)

		memory_layout = QVBoxLayout()
		memory_layout.setSpacing(0)
		memory_layout.setContentsMargins(0, 0, 0, 0)

		memory_label = QLabel("Debugged Process")
		memory_label.setFont(small_font)
		memory_layout.addWidget(memory_label)
		memory_layout.addWidget(self.memory_editor)

		self.memory_widget = QWidget()
		self.memory_widget.setLayout(memory_layout)

		self.splitter.addWidget(self.bv_widget)
		self.splitter.addWidget(self.memory_widget)

		# Equally sized
		self.splitter.setSizes([0x7fffffff, 0x7fffffff])

		layout = QVBoxLayout()
		layout.setContentsMargins(0, 0, 0, 0)
		layout.setSpacing(0)
		layout.addWidget(self.controls)
		layout.addWidget(self.splitter, 100)
		self.setLayout(layout)

		self.needs_update = True
		self.update_timer = QTimer(self)
		self.update_timer.setInterval(200)
		self.update_timer.setSingleShot(False)
		self.update_timer.timeout.connect(lambda: self.updateTimerEvent())

		self.add_scripting_ref()
Beispiel #17
0
class PySeus():  # pylint: disable=R0902
    """The main application class acts as front controller."""
    def __init__(self, gui=True):
        # set gui = false for testing

        self.qt_app = None
        """The QApplication instance for interaction with the Qt framework."""

        if isinstance(QApplication.instance(), type(None)):
            self.qt_app = QApplication([])
        else:
            self.qt_app = QApplication.instance()

        self.formats = [H5, DICOM, NIfTI, NumPy, Raw]
        """List of all avaiable data formats.
        See `Formats <formats.html>`_."""

        self.modes = [Grayscale]
        """List of all avaiable display modes.
        See `Display <modes.html>`_."""

        self.tools = [AreaTool, LineTool]
        """List of all avaiable evaluation tools.
        See `Tools <tools.html>`_."""

        self.dataset = None
        """The current dataset object.
        See `Formats <formats.html>`_."""

        self.mode = Grayscale()
        """The display mode object.
        See `Display <modes.html>`_."""

        self.tool = None
        """The current tool object.
        See `Tools <tools.html>`_."""

        self.window = MainWindow(self)
        """The main window object.
        See `Interface <interface.html>`_."""

        self.meta_window = None
        """Holds the meta window object."""

        self.slice = -1
        """Index of the current slice."""

        self.timer = QTimer()
        """Timer for cine view."""

        self.gui = gui
        """Flag wheter to use the GUI or not."""

        # Stylesheet
        style_path = "./ui/" + settings["ui"]["style"] + ".qss"
        style_path = os.path.join(os.path.dirname(__file__), style_path)
        with open(style_path, "r") as stylesheet:
            self.qt_app.setStyleSheet(stylesheet.read())

        self.qt_app.font().setPixelSize(int(settings["ui"]["font_size"]))

        if self.gui:
            self.window.show()

    def show(self):
        """Show the main window, even if initialized without the GUI."""
        if not self.gui:
            self.window.show()
            self.gui = True

        self.qt_app.exec_()

    def load_file(self, path):
        """Try to load the file at *path*. See also *setup_dataset*."""
        new_dataset = None
        for format_ in self.formats:
            if format_.can_handle(path):
                new_dataset = format_()
                break

        if new_dataset is not None:
            self.setup_dataset(path, new_dataset)

        else:
            QMessageBox.warning(self.window, "Pyseus", "Unknown file format.")

    def load_data(self, data):
        """Try to load *data*. See also *setup_dataset*."""
        new_dataset = Raw()
        self.setup_dataset(data, new_dataset)

    def setup_dataset(self, arg, dataset=None):
        """Setup a new dataset: Load scan list, generate thumbnails and load
        default scan."""
        if dataset is None:
            dataset = self.dataset

        try:
            if not dataset.load(arg):  # canceled by user
                return

            self.clear()
            self.dataset = dataset

            if self.dataset.scan_count() > 1:
                message = "{} scans detected. Do you want to load all?" \
                        .format(self.dataset.scan_count())
                load_all = QMessageBox.question(None, "Pyseus", message)

                self.window.thumbs.clear()
                if load_all is QMessageBox.StandardButton.Yes:
                    for scan_id in range(0, self.dataset.scan_count()):
                        thumb = self.mode.generate_thumb(
                            self.dataset.get_scan_thumbnail(scan_id),
                            int(settings["ui"]["thumb_size"]))
                        pixmap = self.mode.get_pixmap(thumb)
                        self.window.thumbs.add_thumb(pixmap)
                else:
                    single_scan = self.dataset.scans[self.dataset.scan]
                    self.dataset.scans = [single_scan]
                    self.dataset.scan = 0

            self.load_scan()

        except LoadError as error:
            QMessageBox.warning(self.window, "Pyseus", str(error))

        except OSError as error:
            QMessageBox.warning(self.window, "Pyseus", str(error))

        else:
            self.window.info.update_path(self.dataset.path)

    def refresh(self):
        """Refresh the displayed image."""
        if self.slice == -1:
            return

        data = self.dataset.get_pixeldata(self.slice)

        # @TODO move to FormatBase (get_pixeldata_adjusted)
        spacing = self.dataset.get_spacing()
        if spacing[0] != spacing[1]:
            if spacing[0] > spacing[1]:
                size = (int(data.shape[0] * spacing[0] / spacing[1]),
                        int(data.shape[1]))
            else:
                size = (int(data.shape[0]),
                        int(data.shape[1] * spacing[1] / spacing[0]))

            data = cv2.resize(data, size)

        pixmap = self.mode.get_pixmap(data)

        if self.tool is not None:
            pixmap = self.tool.draw_overlay(pixmap)

        self.window.view.set(pixmap)

    def recalculate(self):
        """Refresh the active evaluation tool."""
        if self.tool is not None:
            slice_ = self.dataset.get_pixeldata(self.slice)
            self.tool.recalculate(self.mode.prepare_raw(slice_))

    def select_scan(self, sid, relative=False):
        """Select and load a scan from the current dataset.
        See also *load_scan*."""
        if self.dataset is None:
            return

        new_scan = self.dataset.scan + sid if relative is True else sid
        if 0 <= new_scan < self.dataset.scan_count():
            self.clear_tool()
            self.load_scan(new_scan)

    def load_scan(self, sid=None):
        """Load a scan from the current dataset."""
        old_sid = self.dataset.scan

        if sid is None:
            sid = self.dataset.scan
        self.dataset.load_scan(sid)

        if self.slice >= self.dataset.slice_count() or self.slice == -1:
            self._set_slice(self.dataset.slice_count() // 2)

        if self.dataset.scan_count() > 1:
            old_thumb = self.window.thumbs.thumbs[old_sid]
            new_thumb = self.window.thumbs.thumbs[sid]
            old_thumb.setStyleSheet("border: 1px solid transparent")
            new_thumb.setStyleSheet("border: 1px solid #aaa")

        default_metadata = self.dataset.get_metadata("DEFAULT")
        self.window.meta.update_meta(default_metadata,
                                     len(default_metadata) > 0)
        self.window.info.update_scan(self.dataset.scans[sid])

        self.mode.setup_window(self.dataset.get_pixeldata())
        self.refresh()
        self.window.view.zoom_fit()

    def select_slice(self, sid, relative=False):
        """Select and display a slice from the current scan."""
        if self.dataset is None:
            return

        new_slice = self.slice + sid if relative is True else sid
        if 0 <= new_slice < self.dataset.slice_count():
            self._set_slice(new_slice)
            self.refresh()
            self.recalculate()

    def _set_slice(self, sid):
        """Set the current slice index."""
        self.window.info.update_slice(sid, self.dataset.slice_count())
        self.slice = sid

    def show_metadata_window(self):
        """Show the metadata window.
        See `Interface <interface.html>`_."""
        self.meta_window = MetaWindow(self, self.dataset.get_metadata())
        self.meta_window.show()

    def clear(self):
        """Reset the application."""
        self.dataset = None
        self.slice = -1
        self.window.view.set(None)
        self.window.thumbs.clear()
        self.clear_tool()

    def clear_tool(self):
        """Reset the active evaluation tool."""
        if self.tool is not None:
            self.tool.clear()

    def rotate(self, axis):
        """Rotate the pixeldata of the current scan in 3D."""
        self.dataset.rotate(axis)
        if not axis == 2:
            self._set_slice(self.dataset.slice_count() // 2)

        self.refresh()
        self.window.view.zoom_fit()
        self.clear_tool()

    def flip(self, direction):
        """Flip the pixeldata of the current scan."""
        self.dataset.flip(direction)

        self.refresh()
        self.clear_tool()

    def toggle_cine(self):
        """Toggle automatic loading of next scans."""
        if self.timer.isActive():
            self.timer.stop()
        else:
            self.timer.timeout.connect(self._cine_next)
            self.timer.start(int(settings["cine"]["interval"]))

    def _cine_next(self):
        self.select_scan(1, True)