Пример #1
0
    def __init__(self, config=None, filename=None, output=None):
        # see labelme/config/default_config.yaml for valid configuration
        if config is None:
            config = get_config()
        self._config = config

        super(MainWindow, self).__init__()
        self.setWindowTitle(__appname__)

        # Whether we need to save or not.
        self.dirty = False

        self._noSelectionSlot = False

        # Main widgets and related state.
        self.labelDialog = LabelDialog(
            parent=self,
            labels=self._config['labels'],
            sort_labels=self._config['sort_labels'],
            show_text_field=self._config['show_label_text_field'],
        )

        self.labelList = LabelQListWidget()
        self.lastOpenDir = None

        self.labelList.itemActivated.connect(self.labelSelectionChanged)
        self.labelList.itemSelectionChanged.connect(self.labelSelectionChanged)
        self.labelList.itemDoubleClicked.connect(self.editLabel)
        # Connect to itemChanged to detect checkbox changes.
        self.labelList.itemChanged.connect(self.labelItemChanged)
        self.labelList.setDragDropMode(
            QtWidgets.QAbstractItemView.InternalMove)
        self.labelList.setParent(self)

        listLayout = QtWidgets.QVBoxLayout()
        listLayout.setContentsMargins(0, 0, 0, 0)
        self.editButton = QtWidgets.QToolButton()
        self.editButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        listLayout.addWidget(self.editButton)  # 0, Qt.AlignCenter)
        listLayout.addWidget(self.labelList)
        self.labelListContainer = QtWidgets.QWidget()
        self.labelListContainer.setLayout(listLayout)

        self.uniqLabelList = EscapableQListWidget()
        self.uniqLabelList.setToolTip(
            "Select label to start annotating for it. "
            "Press 'Esc' to deselect.")
        if self._config['labels']:
            self.uniqLabelList.addItems(self._config['labels'])
            self.uniqLabelList.sortItems()
        self.labelsdock = QtWidgets.QDockWidget(u'Label List', self)
        self.labelsdock.setObjectName(u'Label List')
        self.labelsdock.setWidget(self.uniqLabelList)

        self.dock = QtWidgets.QDockWidget('Polygon Labels', self)
        self.dock.setObjectName('Labels')
        self.dock.setWidget(self.labelListContainer)

        self.fileListWidget = QtWidgets.QListWidget()
        self.fileListWidget.itemSelectionChanged.connect(
            self.fileSelectionChanged)
        filelistLayout = QtWidgets.QVBoxLayout()
        filelistLayout.setContentsMargins(0, 0, 0, 0)
        filelistLayout.addWidget(self.fileListWidget)
        fileListContainer = QtWidgets.QWidget()
        fileListContainer.setLayout(filelistLayout)
        self.filedock = QtWidgets.QDockWidget(u'File List', self)
        self.filedock.setObjectName(u'Files')
        self.filedock.setWidget(fileListContainer)

        self.zoomWidget = ZoomWidget()
        self.colorDialog = ColorDialog(parent=self)

        self.canvas = self.labelList.canvas = Canvas()
        self.canvas.zoomRequest.connect(self.zoomRequest)

        scrollArea = QtWidgets.QScrollArea()
        scrollArea.setWidget(self.canvas)
        scrollArea.setWidgetResizable(True)
        self.scrollBars = {
            Qt.Vertical: scrollArea.verticalScrollBar(),
            Qt.Horizontal: scrollArea.horizontalScrollBar(),
        }
        self.canvas.scrollRequest.connect(self.scrollRequest)

        self.canvas.newShape.connect(self.newShape)
        self.canvas.shapeMoved.connect(self.setDirty)
        self.canvas.selectionChanged.connect(self.shapeSelectionChanged)
        self.canvas.drawingPolygon.connect(self.toggleDrawingSensitive)

        self.setCentralWidget(scrollArea)

        self.addDockWidget(Qt.RightDockWidgetArea, self.labelsdock)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock)
        self.addDockWidget(Qt.RightDockWidgetArea, self.filedock)
        self.filedock.setFeatures(QtWidgets.QDockWidget.DockWidgetFloatable)

        self.dockFeatures = (QtWidgets.QDockWidget.DockWidgetClosable
                             | QtWidgets.QDockWidget.DockWidgetFloatable)
        self.dock.setFeatures(self.dock.features() ^ self.dockFeatures)

        # Actions
        action = functools.partial(newAction, self)
        shortcuts = self._config['shortcuts']
        quit = action('&Quit', self.close, shortcuts['quit'], 'quit',
                      'Quit application')
        open_ = action('&Open', self.openFile, shortcuts['open'], 'open',
                       'Open image or label file')
        opendir = action('&Open Dir', self.openDirDialog,
                         shortcuts['open_dir'], 'open', u'Open Dir')
        openNextImg = action('&Next Image', self.openNextImg,
                             shortcuts['open_next'], 'next', u'Open Next')

        openPrevImg = action('&Prev Image', self.openPrevImg,
                             shortcuts['open_prev'], 'prev', u'Open Prev')
        save = action('&Save',
                      self.saveFile,
                      shortcuts['save'],
                      'save',
                      'Save labels to file',
                      enabled=False)
        saveAs = action('&Save As',
                        self.saveFileAs,
                        shortcuts['save_as'],
                        'save-as',
                        'Save labels to a different file',
                        enabled=False)
        close = action('&Close', self.closeFile, shortcuts['close'], 'close',
                       'Close current file')
        color1 = action('Polygon &Line Color', self.chooseColor1,
                        shortcuts['edit_line_color'], 'color_line',
                        'Choose polygon line color')
        color2 = action('Polygon &Fill Color', self.chooseColor2,
                        shortcuts['edit_fill_color'], 'color',
                        'Choose polygon fill color')

        createMode = action('Create\nPolygo&ns',
                            self.setCreateMode,
                            shortcuts['create_polygon'],
                            'objects',
                            'Start drawing polygons',
                            enabled=True)
        editMode = action('&Edit\nPolygons',
                          self.setEditMode,
                          shortcuts['edit_polygon'],
                          'edit',
                          'Move and edit polygons',
                          enabled=True)

        delete = action('Delete\nPolygon',
                        self.deleteSelectedShape,
                        shortcuts['delete_polygon'],
                        'cancel',
                        'Delete',
                        enabled=False)
        copy = action('&Duplicate\nPolygon',
                      self.copySelectedShape,
                      shortcuts['duplicate_polygon'],
                      'copy',
                      'Create a duplicate of the selected polygon',
                      enabled=False)
        undoLastPoint = action('Undo last point',
                               self.canvas.undoLastPoint,
                               shortcuts['undo_last_point'],
                               'undo',
                               'Undo last drawn point',
                               enabled=False)

        undo = action('Undo',
                      self.undoShapeEdit,
                      shortcuts['undo'],
                      'undo',
                      'Undo last add and edit of shape',
                      enabled=False)

        hideAll = action('&Hide\nPolygons',
                         functools.partial(self.togglePolygons, False),
                         icon='eye',
                         tip='Hide all polygons',
                         enabled=False)
        showAll = action('&Show\nPolygons',
                         functools.partial(self.togglePolygons, True),
                         icon='eye',
                         tip='Show all polygons',
                         enabled=False)

        help = action('&Tutorial',
                      self.tutorial,
                      icon='help',
                      tip='Show tutorial page')

        zoom = QtWidgets.QWidgetAction(self)
        zoom.setDefaultWidget(self.zoomWidget)
        self.zoomWidget.setWhatsThis(
            "Zoom in or out of the image. Also accessible with"
            " %s and %s from the canvas." %
            (fmtShortcut('%s,%s' %
                         (shortcuts['zoom_in'], shortcuts['zoom_out'])),
             fmtShortcut("Ctrl+Wheel")))
        self.zoomWidget.setEnabled(False)

        zoomIn = action('Zoom &In',
                        functools.partial(self.addZoom, 10),
                        shortcuts['zoom_in'],
                        'zoom-in',
                        'Increase zoom level',
                        enabled=False)
        zoomOut = action('&Zoom Out',
                         functools.partial(self.addZoom, -10),
                         shortcuts['zoom_out'],
                         'zoom-out',
                         'Decrease zoom level',
                         enabled=False)
        zoomOrg = action('&Original size',
                         functools.partial(self.setZoom, 100),
                         shortcuts['zoom_to_original'],
                         'zoom',
                         'Zoom to original size',
                         enabled=False)
        fitWindow = action('&Fit Window',
                           self.setFitWindow,
                           shortcuts['fit_window'],
                           'fit-window',
                           'Zoom follows window size',
                           checkable=True,
                           enabled=False)
        fitWidth = action('Fit &Width',
                          self.setFitWidth,
                          shortcuts['fit_width'],
                          'fit-width',
                          'Zoom follows window width',
                          checkable=True,
                          enabled=False)
        # Group zoom controls into a list for easier toggling.
        zoomActions = (self.zoomWidget, zoomIn, zoomOut, zoomOrg, fitWindow,
                       fitWidth)
        self.zoomMode = self.MANUAL_ZOOM
        self.scalers = {
            self.FIT_WINDOW:
            self.scaleFitWindow,
            self.FIT_WIDTH:
            self.scaleFitWidth,
            # Set to one to scale to 100% when loading files.
            self.MANUAL_ZOOM:
            lambda: 1,
        }

        edit = action('&Edit Label',
                      self.editLabel,
                      shortcuts['edit_label'],
                      'edit',
                      'Modify the label of the selected polygon',
                      enabled=False)
        self.editButton.setDefaultAction(edit)

        shapeLineColor = action(
            'Shape &Line Color',
            self.chshapeLineColor,
            icon='color-line',
            tip='Change the line color for this specific shape',
            enabled=False)
        shapeFillColor = action(
            'Shape &Fill Color',
            self.chshapeFillColor,
            icon='color',
            tip='Change the fill color for this specific shape',
            enabled=False)

        labels = self.dock.toggleViewAction()
        labels.setText('Show/Hide Label Panel')

        # Lavel list context menu.
        labelMenu = QtWidgets.QMenu()
        addActions(labelMenu, (edit, delete))
        self.labelList.setContextMenuPolicy(Qt.CustomContextMenu)
        self.labelList.customContextMenuRequested.connect(
            self.popLabelListMenu)

        # Store actions for further handling.
        self.actions = struct(
            save=save,
            saveAs=saveAs,
            open=open_,
            close=close,
            lineColor=color1,
            fillColor=color2,
            delete=delete,
            edit=edit,
            copy=copy,
            undoLastPoint=undoLastPoint,
            undo=undo,
            createMode=createMode,
            editMode=editMode,
            shapeLineColor=shapeLineColor,
            shapeFillColor=shapeFillColor,
            zoom=zoom,
            zoomIn=zoomIn,
            zoomOut=zoomOut,
            zoomOrg=zoomOrg,
            fitWindow=fitWindow,
            fitWidth=fitWidth,
            zoomActions=zoomActions,
            fileMenuActions=(open_, opendir, save, saveAs, close, quit),
            tool=(),
            editMenu=(edit, copy, delete, None, undo, undoLastPoint, None,
                      color1, color2),
            menu=(
                createMode,
                editMode,
                edit,
                copy,
                delete,
                shapeLineColor,
                shapeFillColor,
                undo,
                undoLastPoint,
            ),
            onLoadActive=(close, createMode, editMode),
            onShapesPresent=(saveAs, hideAll, showAll),
        )

        self.menus = struct(
            file=self.menu('&File'),
            edit=self.menu('&Edit'),
            view=self.menu('&View'),
            help=self.menu('&Help'),
            recentFiles=QtWidgets.QMenu('Open &Recent'),
            labelList=labelMenu,
        )

        addActions(self.menus.file, (open_, opendir, self.menus.recentFiles,
                                     save, saveAs, close, None, quit))
        addActions(self.menus.help, (help, ))
        addActions(self.menus.view,
                   (labels, None, hideAll, showAll, None, zoomIn, zoomOut,
                    zoomOrg, None, fitWindow, fitWidth))

        self.menus.file.aboutToShow.connect(self.updateFileMenu)

        # Custom context menu for the canvas widget:
        addActions(self.canvas.menus[0], self.actions.menu)
        addActions(self.canvas.menus[1],
                   (action('&Copy here', self.copyShape),
                    action('&Move here', self.moveShape)))

        self.tools = self.toolbar('Tools')
        self.actions.tool = (open_, opendir, openNextImg, openPrevImg, save,
                             None, createMode, copy, delete, editMode, undo,
                             None, zoomIn, zoom, zoomOut, fitWindow, fitWidth)

        self.statusBar().showMessage('%s started.' % __appname__)
        self.statusBar().show()

        # Application state.
        self.image = QtGui.QImage()
        self.imagePath = None
        if self._config['auto_save'] and output is not None:
            warnings.warn('If `auto_save` argument is True, `output` argument '
                          'is ignored and output filename is automatically '
                          'set as IMAGE_BASENAME.json.')
        self.labeling_once = output is not None
        self.output = output
        self.recentFiles = []
        self.maxRecent = 7
        self.lineColor = None
        self.fillColor = None
        self.otherData = None
        self.zoom_level = 100
        self.fit_window = False

        if filename is not None and os.path.isdir(filename):
            self.importDirImages(filename, load=False)
        else:
            self.filename = filename

        # XXX: Could be completely declarative.
        # Restore application settings.
        self.settings = QtCore.QSettings('labelme', 'labelme')
        # FIXME: QSettings.value can return None on PyQt4
        self.recentFiles = self.settings.value('recentFiles', []) or []
        size = self.settings.value('window/size', QtCore.QSize(600, 500))
        position = self.settings.value('window/position', QtCore.QPoint(0, 0))
        self.resize(size)
        self.move(position)
        # or simply:
        # self.restoreGeometry(settings['window/geometry']
        self.restoreState(
            self.settings.value('window/state', QtCore.QByteArray()))
        self.lineColor = QtGui.QColor(
            self.settings.value('line/color', Shape.line_color))
        self.fillColor = QtGui.QColor(
            self.settings.value('fill/color', Shape.fill_color))
        Shape.line_color = self.lineColor
        Shape.fill_color = self.fillColor

        # Populate the File menu dynamically.
        self.updateFileMenu()
        # Since loading the file may take some time,
        # make sure it runs in the background.
        if self.filename is not None:
            self.queueEvent(functools.partial(self.loadFile, self.filename))

        # Callbacks:
        self.zoomWidget.valueChanged.connect(self.paintCanvas)

        self.populateModeActions()
Пример #2
0
 def setData(self, mime, data):
     super(PyMimeData, self).setData(mime, QtCore.QByteArray(1, '1'))
     self._instances[mime] = data
Пример #3
0
    def __init__(
        self,
        file_or_folder,
        output_file=None,
        output_dir=None,
    ):
        super(MainWindow, self).__init__()

        self.action_storage = utils.ActionStorage(self)
        # Whether we need to save or not.
        self.dirty = False
        self.label_file = None
        if output_file:
            if Config.get('auto_save'):
                logger.warn(
                    'If `auto_save` argument is True, `output_file` argument '
                    'is ignored and output filename is automatically '
                    'set as IMAGE_BASENAME.json.')
            self.label_file = output_file
        # Ignore signal flags
        self._noSelectionSlot = False
        # Last open directory
        self.lastOpenDir = None
        self._uri = None
        self.output_dir = output_dir
        self.zoomMode = self.FIT_WINDOW
        self.scalers = {
            self.FIT_WINDOW:
            self.scaleFitWindow,
            self.FIT_WIDTH:
            self.scaleFitWidth,
            # Set to one to scale to 100% when loading files.
            self.MANUAL_ZOOM:
            lambda: 1,
        }

        # Application state.
        # Restore application settings.
        # FIXME: QSettings.value can return None on PyQt4
        self.settings = QtCore.QSettings('labelme_client', 'labelme_client')
        self.recentFiles = self.settings.value('recentFiles', []) or []
        self.lineColor = self.settings.value('line/color', None)
        self.fillColor = self.settings.value('fill/color', None)
        geometry = self.settings.value('window/geometry')
        if geometry:
            self.restoreGeometry(geometry)
        self.restoreState(
            self.settings.value('window/state', QtCore.QByteArray()))

        self.ui = UIMainWindow()
        self.ui.setup_ui(self)

        self.statusBar().showMessage('%s started.' % __appname__)
        self.statusBar().show()
        if Config.get('file_search'):
            self.fileSearch.setText(Config.get('file_search'))
        # Populate actions in menus
        self.populate_actions()
        # Populate the File menu dynamically.
        self.updateFileMenu()
        # Set and load URI
        self.uri = URI.from_file_or_folder(file_or_folder, output_dir) \
            if file_or_folder else None
Пример #4
0
	from libqtopensesame.misc.config import cfg
	cfg.my_setting = 'my_value' # set
	print(cfg.my_setting) # get
"""

from libopensesame.py3compat import *
from libopensesame.exceptions import osexception
from qtpy import QtCore
import libopensesame.misc
from libopensesame import debug
import platform
import sys

DEFAULT_CONFIG = {
    u"cfg_ver": 0,
    u"_initial_window_geometry": QtCore.QByteArray(),
    u"_initial_window_state": QtCore.QByteArray(),
    u"auto_update_check": True,
    u"auto_response": False,
    u"default_logfile_folder": libopensesame.misc.home_folder(),
    u"default_pool_folder": libopensesame.misc.home_folder(),
    u"disabled_plugins": "",
    u"disabled_extensions": "",
    u"file_dialog_path": "",
    u"file_pool_size_warning": 104857600,
    u"loop_wizard": None,
    u"onetabmode": False,
    u"qProgEditCommentShortcut": u'Ctrl+M',
    u"qProgEditUncommentShortcut": u'Ctrl+Shift+M',
    u'qProgEditFontFamily': u'Roboto Mono',
    u'qProgEditFontSize': 10,
Пример #5
0
    def __init__(self, **kwargs):
        super(MainWindow, self).__init__()
        self.setWindowTitle(__appname__)

        config = kwargs['config'] if 'config' in kwargs else get_config()
        filename = kwargs['filename'] if 'filename' in kwargs else None
        output = kwargs['output'] if 'output' in kwargs else None
        output_file = kwargs['output_file'] if 'output_file' in kwargs else None
        output_dir = kwargs['output_dir'] if 'output_dir' in kwargs else None

        self._config = config

        if filename is not None and osp.isdir(filename):
            self.importDirImages(filename, load=False)
        else:
            self.filename = filename

        if output is not None:
            logger.warning(
                'argument output is deprecated, use output_file instead')
            if output_file is None:
                output_file = output

        self.output_file = output_file
        self.output_dir = output_dir

        self._selectedAll = False
        self._noSelectionSlot = False
        self.lastOpenDir = None
        self.dirty = False

        # widgets
        self.flag_widget = QtWidgets.QListWidget()
        self.flag_widget.itemChanged.connect(self.setDirty)

        self.zoomWidget = ZoomWidget()
        self.zoomWidget.valueChanged.connect(self.paintCanvas)

        self.labelList = LabelQListWidget()
        self.labelList.setParent(self)

        # canvas
        self.canvasInit = CanvasInit(parent=self,
                                     epsilon=self._config['epsilon'])
        self.canvas = self.canvasInit.canvas
        self.labelList.canvas = self.canvas
        self.setCentralWidget(self.canvasInit.canvasWidget)

        # docks
        self.inference = InferenceDock()
        self.inference_dock = self.inference.inference_dock
        self.property = PropertyDock(config=self._config)
        self.property_dock = self.property.property_dock
        self.defect = DefectDock(path_info=self._config['paths'])
        self.defect_dock = self.defect.defect_dock
        self.file = FileDock(parent=self)
        self.file_dock = self.file.file_dock
        self.category = CategoryDock()
        self.category_dock = self.category.category_dock

        features = QtWidgets.QDockWidget.DockWidgetFeatures()
        for dock in [
                'inference_dock', 'property_dock', 'defect_dock', 'file_dock',
                'category_dock'
        ]:
            if self._config[dock]['closable']:
                features = features | QtWidgets.QDockWidget.DockWidgetClosable
            if self._config[dock]['floatable']:
                features = features | QtWidgets.QDockWidget.DockWidgetFloatable
            if self._config[dock]['movable']:
                features = features | QtWidgets.QDockWidget.DockWidgetMovable
            getattr(self, dock).setFeatures(features)
            if self._config[dock]['show'] is False:
                getattr(self, dock).setVisible(False)

        self.addDockWidget(Qt.RightDockWidgetArea, self.category_dock)
        self.addDockWidget(Qt.RightDockWidgetArea, self.inference_dock)
        self.addDockWidget(Qt.RightDockWidgetArea, self.property_dock)
        self.addDockWidget(Qt.RightDockWidgetArea, self.defect_dock)
        self.addDockWidget(Qt.RightDockWidgetArea, self.file_dock)

        self.labelDialog = LabelDialog(
            parent=self,
            labels=self._config['labels'],
            sort_labels=self._config['sort_labels'],
            show_text_field=self._config['show_label_text_field'],
            completion=self._config['label_completion'],
            fit_to_content=self._config['fit_to_content'],
            flags=self._config['label_flags'])

        if config['flags']:
            self.loadFlags({k: False for k in config['flags']})

        if config['file_search']:
            self.file.fileSearch.setText(config['file_search'])
            self.file.fileSearchChanged()

        # Actions, menu
        self.init_action()
        self.init_menu()

        # Application state.
        self.image = QtGui.QImage()
        self.imagePath = None
        self.recentFiles = []
        self.maxRecent = 7
        self.lineColor = None
        self.fillColor = None
        self.otherData = None
        self.zoom_level = 100
        self.fit_window = False

        # Restore application settings.
        self.settings = QtCore.QSettings('ImageDefectAnalytics',
                                         'ImageDefectAnalytics')
        self.recentFiles = self.settings.value('recentFiles', []) or []
        self.resize(self.settings.value('window/size', QtCore.QSize(600, 500)))
        self.move(self.settings.value('window/position', QtCore.QPoint(0, 0)))
        self.restoreState(
            self.settings.value('window/state', QtCore.QByteArray()))

        self.populateModeActions()
        self.updateFileMenu()

        if self.filename is not None:
            self.queueEvent(functools.partial(self.loadFile, self.filename))
        self.statusBar().showMessage('%s started.' % __appname__)
        self.statusBar().show()
Пример #6
0
    def __init__(
        self,
        config=None,
        filename=None,
        output_dir=None,
    ):

        super(MainWindow, self).__init__()
        self.setWindowTitle(self.__appname__)

        # Whether we need to save or not.
        self.dirty = False

        config = get_config()
        self._config = config
        self.labelList = LabelQListWidget()
        self.labelList.setParent(self)
        self.canvas = self.labelList.canvas = Canvas(
            epsilon=self._config['epsilon'], )
        self.canvas.zoomRequest.connect(self.zoomRequest)
        scrollArea = QtWidgets.QScrollArea()
        scrollArea.setWidget(self.canvas)
        scrollArea.setWidgetResizable(True)
        self.scrollBars = {
            Qt.Vertical: scrollArea.verticalScrollBar(),
            Qt.Horizontal: scrollArea.horizontalScrollBar(),
        }
        self.canvas.scrollRequest.connect(self.scrollRequest)
        self.setCentralWidget(scrollArea)

        self.zoomWidget = ZoomWidget()
        # Actions
        action = functools.partial(utils.newAction, self)
        shortcuts = self._config['shortcuts']
        quit = action('&Quit', self.close, shortcuts['quit'], 'quit',
                      'Quit application')
        open_ = action('&Open', self.openFile, shortcuts['open'], 'open',
                       'Open image or label file')

        zoom = QtWidgets.QWidgetAction(self)
        zoom.setDefaultWidget(self.zoomWidget)
        self.zoomWidget.setWhatsThis(
            'Zoom in or out of the image. Also accessible with '
            '{} and {} from the canvas.'.format(
                utils.fmtShortcut('{},{}'.format(shortcuts['zoom_in'],
                                                 shortcuts['zoom_out'])),
                utils.fmtShortcut("Ctrl+Wheel"),
            ))
        self.zoomWidget.setEnabled(False)

        zoomIn = action('Zoom &In',
                        functools.partial(self.addZoom, 1.1),
                        shortcuts['zoom_in'],
                        'zoom-in',
                        'Increase zoom level',
                        enabled=False)
        zoomOut = action('&Zoom Out',
                         functools.partial(self.addZoom, 0.9),
                         shortcuts['zoom_out'],
                         'zoom-out',
                         'Decrease zoom level',
                         enabled=False)
        zoomOrg = action('&Original size',
                         functools.partial(self.setZoom, 100),
                         shortcuts['zoom_to_original'],
                         'zoom',
                         'Zoom to original size',
                         enabled=False)
        fitWindow = action('&Fit Window',
                           self.setFitWindow,
                           shortcuts['fit_window'],
                           'fit-window',
                           'Zoom follows window size',
                           checkable=True,
                           enabled=False)
        fitWidth = action('Fit &Width',
                          self.setFitWidth,
                          shortcuts['fit_width'],
                          'fit-width',
                          'Zoom follows window width',
                          checkable=True,
                          enabled=False)
        # Group zoom controls into a list for easier toggling.
        zoomActions = (self.zoomWidget, zoomIn, zoomOut, zoomOrg, fitWindow,
                       fitWidth)
        self.zoomMode = self.FIT_WINDOW
        fitWindow.setChecked(Qt.Checked)
        self.scalers = {
            self.FIT_WINDOW:
            self.scaleFitWindow,
            self.FIT_WIDTH:
            self.scaleFitWidth,
            # Set to one to scale to 100% when loading files.
            self.MANUAL_ZOOM:
            lambda: 1,
        }

        # Store actions for further handling.
        self.actions = utils.struct(
            pen=open_,
            zoom=zoom,
            zoomIn=zoomIn,
            zoomOut=zoomOut,
            zoomOrg=zoomOrg,
            fitWindow=fitWindow,
            fitWidth=fitWidth,
            zoomActions=zoomActions,
            fileMenuActions=(open_, quit),
            tool=(),
            # menu shown at right click
        )

        self.menus = utils.struct(
            file=self.menu('&File'),
            edit=self.menu('&Edit'),
            view=self.menu('&View'),
            recentFiles=QtWidgets.QMenu('Open &Recent'),
        )
        utils.addActions(
            self.menus.file,
            (
                open_,
                None,
                quit,
            ),
        )
        self.menus.file.aboutToShow.connect(self.updateFileMenu)

        self.tools = self.toolbar('Tools')
        # Menu buttons on Left
        self.actions.tool = (
            open_,
            None,
            zoomIn,
            zoom,
            zoomOut,
            fitWindow,
            fitWidth,
        )

        self.statusBar().showMessage('%s started.' % self.__appname__)
        self.statusBar().show()

        self.output_dir = output_dir
        # Application state.
        self.image = QtGui.QImage()
        self.imagePath = None
        self.recentFiles = []
        self.maxRecent = 7
        self.lineColor = None
        self.fillColor = None
        self.otherData = None
        self.zoom_level = 100
        self.fit_window = False
        self.filename = filename

        # XXX: Could be completely declarative.
        # Restore application settings.
        self.settings = QtCore.QSettings('rstools', 'rstools')
        self.recentFiles = self.settings.value('recentFiles', []) or []
        size = self.settings.value('window/size', QtCore.QSize(800, 500))
        position = self.settings.value('window/position', QtCore.QPoint(0, 0))
        self.resize(size)
        self.move(position)
        # self.restoreGeometry(settings['window/geometry']
        self.restoreState(
            self.settings.value('window/state', QtCore.QByteArray()))

        self.updateFileMenu()

        # Callbacks:
        self.zoomWidget.valueChanged.connect(self.paintCanvas)
        self.populateModeActions()
Пример #7
0
    def _get_image_tag(self, match, path=None, format="png"):
        """ Return (X)HTML mark-up for the image-tag given by match.

        Parameters
        ----------
        match : re.SRE_Match
            A match to an HTML image tag as exported by Qt, with
            match.group("Name") containing the matched image ID.

        path : string|None, optional [default None]
            If not None, specifies a path to which supporting files may be
            written (e.g., for linked images).  If None, all images are to be
            included inline.

        format : "png"|"svg"|"jpg", optional [default "png"]
            Format for returned or referenced images.
        """
        if format in ("png", "jpg"):
            try:
                image = self._get_image(match.group("name"))
            except KeyError:
                return "<b>Couldn't find image %s</b>" % match.group("name")

            if path is not None:
                ensure_dir_exists(path)
                relpath = os.path.basename(path)
                if image.save(
                        "%s/qt_img%s.%s" % (path, match.group("name"), format),
                        "PNG"):
                    return '<img src="%s/qt_img%s.%s">' % (
                        relpath, match.group("name"), format)
                else:
                    return "<b>Couldn't save image!</b>"
            else:
                ba = QtCore.QByteArray()
                buffer_ = QtCore.QBuffer(ba)
                buffer_.open(QtCore.QIODevice.WriteOnly)
                image.save(buffer_, format.upper())
                buffer_.close()
                return '<img src="data:image/%s;base64,\n%s\n" />' % (
                    format,
                    re.sub(r'(.{60})', r'\1\n',
                           str(ba.toBase64().data().decode())))

        elif format == "svg":
            try:
                svg = str(self._name_to_svg_map[match.group("name")])
            except KeyError:
                if not self._svg_warning_displayed:
                    QtWidgets.QMessageBox.warning(
                        self, 'Error converting PNG to SVG.',
                        'Cannot convert PNG images to SVG, export with PNG figures instead. '
                        'If you want to export matplotlib figures as SVG, add '
                        'to your ipython config:\n\n'
                        '\tc.InlineBackend.figure_format = \'svg\'\n\n'
                        'And regenerate the figures.',
                        QtWidgets.QMessageBox.Ok)
                    self._svg_warning_displayed = True
                return (
                    "<b>Cannot convert  PNG images to SVG.</b>  "
                    "You must export this session with PNG images. "
                    "If you want to export matplotlib figures as SVG, add to your config "
                    "<span>c.InlineBackend.figure_format = 'svg'</span> "
                    "and regenerate the figures.")

            # Not currently checking path, because it's tricky to find a
            # cross-browser way to embed external SVG images (e.g., via
            # object or embed tags).

            # Chop stand-alone header from matplotlib SVG
            offset = svg.find("<svg")
            assert (offset > -1)

            return svg[offset:]

        else:
            return '<b>Unrecognized image format</b>'
Пример #8
0
 def set_data(self, mime_type, data):
     self.setData(mime_type, QtCore.QByteArray(data.encode()))
Пример #9
0
 def __getstate__(self):
     ba = QtCore.QByteArray()
     stream = QtCore.QDataStream(ba, QtCore.QIODevice.WriteOnly)
     pixmap = self.pixmap(QtCore.QSize(256, 256))
     stream << pixmap
     return ba
Пример #10
0
def arrayToQPath(x, y, connect='all'):
    """Convert an array of x,y coordinats to QPainterPath as efficiently as possible.
    The *connect* argument may be 'all', indicating that each point should be
    connected to the next; 'pairs', indicating that each pair of points
    should be connected, or an array of int32 values (0 or 1) indicating
    connections.
    """

    #CODE IS COPIED FROM PYQTGRAPH

    ## Create all vertices in path. The method used below creates a binary format so that all
    ## vertices can be read in at once. This binary format may change in future versions of Qt,
    ## so the original (slower) method is left here for emergencies:
    #path.moveTo(x[0], y[0])
    #if connect == 'all':
    #for i in range(1, y.shape[0]):
    #path.lineTo(x[i], y[i])
    #elif connect == 'pairs':
    #for i in range(1, y.shape[0]):
    #if i%2 == 0:
    #path.lineTo(x[i], y[i])
    #else:
    #path.moveTo(x[i], y[i])
    #elif isinstance(connect, np.ndarray):
    #for i in range(1, y.shape[0]):
    #if connect[i] == 1:
    #path.lineTo(x[i], y[i])
    #else:
    #path.moveTo(x[i], y[i])
    #else:
    #raise Exception('connect argument must be "all", "pairs", or array')

    ## Speed this up using >> operator
    ## Format is:
    ##    numVerts(i4)   0(i4)
    ##    x(f8)   y(f8)   0(i4)    <-- 0 means this vertex does not connect
    ##    x(f8)   y(f8)   1(i4)    <-- 1 means this vertex connects to the previous vertex
    ##    ...
    ##    0(i4)
    ##
    ## All values are big endian--pack using struct.pack('>d') or struct.pack('>i')

    path = QtGui.QPainterPath()

    #profiler = debug.Profiler()
    n = x.shape[0]
    # create empty array, pad with extra space on either end
    arr = np.empty(n + 2, dtype=[('x', '>f8'), ('y', '>f8'), ('c', '>i4')])
    # write first two integers
    #profiler('allocate empty')
    byteview = arr.view(dtype=np.ubyte)
    byteview[:12] = 0
    byteview.data[12:20] = struct.pack('>ii', n, 0)
    #profiler('pack header')
    # Fill array with vertex values
    arr[1:-1]['x'] = x
    arr[1:-1]['y'] = y

    # decide which points are connected by lines
    #I replaced eq function by ==
    if connect == 'all':
        arr[1:-1]['c'] = 1
    elif connect == 'pairs':
        arr[1:-1]['c'][::2] = 1
        arr[1:-1]['c'][1::2] = 0
    elif connect == 'finite':
        arr[1:-1]['c'] = np.isfinite(x) & np.isfinite(y)
    elif isinstance(connect, np.ndarray):
        arr[1:-1]['c'] = connect
    else:
        raise Exception(
            'connect argument must be "all", "pairs", "finite", or array')

    #profiler('fill array')
    # write last 0
    lastInd = 20 * (n + 1)
    byteview.data[lastInd:lastInd + 4] = struct.pack('>i', 0)
    #profiler('footer')
    # create datastream object and stream into path

    ## Avoiding this method because QByteArray(str) leaks memory in PySide
    #buf = QtCore.QByteArray(arr.data[12:lastInd+4])  # I think one unnecessary copy happens here

    path.strn = byteview.data[12:lastInd +
                              4]  # make sure data doesn't run away
    try:
        buf = QtCore.QByteArray.fromRawData(path.strn)
    except TypeError:
        buf = QtCore.QByteArray(bytes(path.strn))
    #profiler('create buffer')
    ds = QtCore.QDataStream(buf)

    ds >> path
    #profiler('load')

    return path
Пример #11
0
class config(object):

    config = {
        u"cfg_ver": 0,
        u"_initial_window_geometry": QtCore.QByteArray(),
        u"_initial_window_state": QtCore.QByteArray(),
        u"auto_update_check": True,
        u"auto_response": False,
        u"default_logfile_folder": libopensesame.misc.home_folder(),
        u"default_pool_folder": libopensesame.misc.home_folder(),
        u"disabled_plugins": "",
        u"disabled_extensions": "",
        u"file_dialog_path": "",
        u"file_pool_size_warning": 104857600,
        u"locale": u"default",
        u"loop_wizard": None,
        u"onetabmode": False,
        u"qProgEditCommentShortcut": u'Ctrl+M',
        u"qProgEditUncommentShortcut": u'Ctrl+Shift+M',
        u'qProgEditFontFamily': u'Roboto Mono',
        u'qProgEditFontSize': 10,
        u'qProgEditLineNumbers': True,
        u'qProgEditHighlightCurrentLine': False,
        u'qProgEditHighlightMatchingBrackets': True,
        u'qProgEditWordWrapMarker': 80,
        u'qProgEditWordWrap': True,
        u'qProgEditTabWidth': 4,
        u'qProgEditAutoIndent': True,
        u'qProgEditShowEol': False,
        u'qProgEditShowWhitespace': False,
        u'qProgEditShowIndent': False,
        u'qProgEditShowFolding': True,
        u'qProgEditAutoComplete': True,
        u'qProgEditColorScheme': u'Monokai',
        u'qProgEditValidate': False,
        u"quick_run_logfile": u"quickrun.csv",
        u"recent_files": u"",
        u"reset_console_on_experiment_start": True,
        u"shortcut_itemtree": u"Ctrl+1",
        u"shortcut_tabwidget": u"Ctrl+2",
        u"shortcut_stdout": u"Ctrl+3",
        u"shortcut_pool": u"Ctrl+4",
        u"shortcut_copy_clipboard_unlinked": u"Ctrl+C",
        u"shortcut_copy_clipboard_linked": u"Ctrl+Shift+C",
        u"shortcut_paste_clipboard": u"Ctrl+V",
        u"shortcut_delete": u"Del",
        u"shortcut_permanently_delete": u"Shift+Del",
        u"shortcut_context_menu": u"+",
        u"shortcut_rename": u"F2",
        u"shortcut_edit_runif": u"F3",
        u"style": u"",
        u"theme": u"default",
        u"toolbar_size": 32,
        u"toolbar_text": False,
        u"runner": u"multiprocess",
        u"opensesamerun_exec": u"",
        u"start_drag_delay": 300,
        u"pos": QtCore.QPoint(200, 200),
        u"size": QtCore.QSize(1000, 600),
        u"_initial_window_geometry": QtCore.QByteArray(),
        u"_initial_window_state": QtCore.QByteArray(),
        u"url_website": u"http://www.cogsci.nl/opensesame",
        u"url_facebook": u"http://www.facebook.com/cognitivescience",
        u"url_twitter": u"http://www.twitter.com/cogscinl",
        u'sketchpad_placeholder_color': u'#00FF00',
        u'sketchpad_grid_color': u'#00FF00',
        u'sketchpad_grid_thickness_thin': 2,
        u'sketchpad_grid_thickness_thick': 4,
        u'sketchpad_grid_opacity': 32,
        u'sketchpad_preview_color': u'#00FF00',
        u'sketchpad_preview_penwidth': 2,
        u'qProgEditSwitchLeftShortcut': u'Alt+Left',
        u'qProgEditSwitchRightShortcut': u'Alt+Right',
        u'qProgEditShowFindShortcut': u'Ctrl+F',
        u'qProgEditHideFindShortcut': u'Escape',
        u'qProgEditTogglePrefsShortcut': u'Ctrl+Shift+P',
        u'qProgEditRunSelectedShortcut': u'Alt+R',
        u'qProgEditRunAllShortcut': u'Shift+Alt+R',
        u'qProgEditSymbolTreeWidgetItemIcon': u'text-x-script',
        u'locale': u'',
    }

    # OS specific override settings
    config_linux = {u"theme": u"gnome"}
    config_mac = {u"runner": u"inprocess"}
    config_windows = {}

    def __init__(self):
        """Constructor"""

        # Apply OS specific override settings
        if platform.system() == u"Windows":
            for key, value in self.config_windows.items():
                self.config[key] = value
        elif platform.system() == u"Darwin":
            for key, value in self.config_mac.items():
                self.config[key] = value
        elif platform.system() == u"Linux":
            for key, value in self.config_linux.items():
                self.config[key] = value

    def __str__(self):

        if py3:
            return self.__unicode__()
        return safe_encode(self.__unicode__())

    def __unicode__(self):

        s = u''
        for key, val in self.config.items():
            if not isinstance(val, basestring) and not isinstance(val, int) \
             and not isinstance(val, float):
                val = type(val)
            s += u'%s: %s\n' % (key, val)
        return s

    def __getattr__(self, setting):
        """
		A getter for settings, to allow for easy access

		Argument:
		setting -- the setting to get
		"""

        if setting not in self.config:
            raise osexception(u'The setting "%s" does not exist' \
             % setting)
        return self.config[setting]

    def __setattr__(self, setting, value):
        """
		A setter for settings, to allow for easy access

		Argument:
		setting -- the setting to set
		value -- the value to set
		"""
        if setting not in self.config:
            raise osexception(u'The setting "%s" does not exist' \
             % setting)
        self.config[setting] = value
        self.config[u'cfg_ver'] += 1

    def __setitem__(self, setting, value):
        """
		desc:
			Emulate dict API.
		"""

        self.__setattr__(setting, value)

    def __getitem__(self, setting):
        """
		desc:
			Emulate dict API.
		"""

        return self.__getattr__(setting)

    def __contains__(self, setting):
        """
		returns:
			True if setting exists, False otherwise.
		"""

        return setting in self.config

    def register(self, setting, default):
        """
		desc:
			Registers a new setting, if it doesn't already exist.

		arguments:
			setting:	The setting name.
			default:	A default value, which is used if the setting doesn't
						already exist.
		"""

        qsettings = QtCore.QSettings(u"cogscinl", u"opensesame")
        qsettings.beginGroup(u"MainWindow")
        if '--start-clean' in sys.argv:
            self.config[setting] = default
        elif setting not in self.config:
            value = qsettings.value(setting, default)
            value = self.type_qvariant(value, default)
            self.config[setting] = value
        qsettings.endGroup()

    def parse_cmdline_args(self, args):
        """
		Apply settings that were specified on the command line. The expected
		format is as follows: [name]=[val];[name]=[val];...

		Arguments:
		args -- the string of command line arguments
		"""

        if args is None:
            return
        for arg in args.split(u";"):
            a = arg.split(u"=")
            if len(a) == 2:
                # Automagically determine the data type
                if a[1] == u"True":
                    val = True
                elif a[1] == u"False":
                    val = False
                else:
                    try:
                        val = int(a[1])
                    except:
                        try:
                            val = float(a[1])
                        except:
                            val = a[1]
                # Apply the argument
                try:
                    self.__setattr__(a[0], val)
                    debug.msg(u"%s = %s" % (a[0], val))
                except:
                    debug.msg(u"Failed to parse argument: %s" % arg)

    def type_qvariant(self, value, default):
        """
		desc:
			Typecasts a value to a normal type that matches the type of a
			default value. This is necessary, because under some combinations
			of Python 2/3 and PyQt 4/5 settings are returned as QVariant
			objects, whereas on other combinations the type casting occurs
			automatically.

		arguments:
			value:		A value.
			default:	A default value.

		returns:
			A value.
		"""

        if hasattr(QtCore, u'QPyNullVariant') and \
          isinstance(value, QtCore.QPyNullVariant):
            return default
        if isinstance(default, bool):
            if isinstance(value, basestring):
                return value == u'true'
            try:
                return bool(value)
            except:
                print('Failed to convert %s' % value)
                return default
        if isinstance(default, int):
            try:
                return int(value)
            except:
                print('Failed to convert %s' % value)
                return default
        if isinstance(default, float):
            try:
                return float(value)
            except:
                print('Failed to convert %s' % value)
                return default
        return value

    def restore(self):
        """
		desc:
			Restore settings from a QSettings.
		"""

        qsettings = QtCore.QSettings(u"cogscinl", u"opensesame")
        qsettings.beginGroup(u"MainWindow")
        for setting, default in self.config.items():
            try:
                value = qsettings.value(setting, default)
            except TypeError:
                continue
            value = self.type_qvariant(value, default)
            self.config[setting] = value
        qsettings.endGroup()

    def save(self):
        """
		desc:
			Save settings to a QSettings.
		"""

        qsettings = QtCore.QSettings(u"cogscinl", u"opensesame")
        qsettings.beginGroup(u"MainWindow")
        for setting, value in self.config.items():
            if setting != u"cfg_ver":
                qsettings.setValue(setting, value)
        qsettings.endGroup()

    def clear(self):
        """
		desc:
			Clears all settings.
		"""

        qsettings = QtCore.QSettings(u"cogscinl", u"opensesame")
        qsettings.beginGroup(u"MainWindow")
        qsettings.clear()
        qsettings.endGroup()

    def version(self):
        """
		Gets the current version of the config.

		Returns:
		The config version.
		"""

        return self.cfg_ver
Пример #12
0
from qtpy import QtCore, QtGui, QtWidgets
from PyQt5 import sip

authorized_classes = [sip._unpickle_type]
objects = {
    "QtWidgets": {
        "QWidget": QtWidgets.QWidget(),
        "QCheckBox": QtWidgets.QCheckBox(checked=True),
        "QDoubleSpinBox": QtWidgets.QDoubleSpinBox(value=10.0),
        "QLineEdit": QtWidgets.QLineEdit("coucou"),
        "QPlainTextEdit": QtWidgets.QPlainTextEdit("coucou"),
        "QSpinBox": QtWidgets.QSpinBox(value=20),
        "QPushButton": QtWidgets.QPushButton(),
    },
    "PyQt_pickable": {
        "QByteArray": QtCore.QByteArray(bytes(range(256))),
        "QColor": QtGui.QColor(10, 20, 30, 40),
        ## "QChar": # n'a plus l'air d'exister dans PyQt5
        "QDate": QtCore.QDate(2020, 10, 31),
        "QDateTime": QtCore.QDateTime(2020, 10, 31, 20, 30),
        "QKeySequence": QtGui.QKeySequence(),
        ## "QLatin1Char": # n'a plus l'air d'exister dans PyQt5
        ## "QLatin1String"# n'a plus l'air d'exister dans PyQt5
        "QLine": QtCore.QLine(QtCore.QPoint(0, 1), QtCore.QPoint(2, 3)),
        "QLineF": QtCore.QLineF(QtCore.QPoint(0.0, 1.1), QtCore.QPoint(2.2, 3.3)),
        "QPen": QtGui.QPen(),
        "QBrush": QtGui.QBrush(),
        "QPoint": QtCore.QPoint(0, 1),
        "QPointF": QtCore.QPointF(0.0, 1.1),
        "QPolygon": QtGui.QPolygon([QtCore.QPoint(0, 1), QtCore.QPoint(2, 3)]),
        "QPolygonF": QtGui.QPolygonF([QtCore.QPoint(0.0, 1.1), QtCore.QPoint(2.2, 3.3)]),