Пример #1
0
class AllAppsListItems(QObject):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._model = QStringListModel()

    # Just guessing that it's Property instead of pyqtProperty.
    @Property(QObject, constant=True)
    def model(self):
        return self._model

    # I'm not passing anything to the code, so
    # this has to be a "Slot()" instead of "Slot(str)".
    @Slot()
    def getDotDesktopFilesInList(self):
        #self._model.setStringList(['Firefox Launcher.desktop', 'top-exec.desktop'])
        self._model.setStringList(AppsList.getDotDesktopFiles())
Пример #2
0
    def __init__(self, sizes: List[inventory.JKSize.Size] = [], parent=None):
        super(AddJKStock, self).__init__(parent)

        self.ui = Ui_AddJKStock()
        self.ui.setupUi(self)

        self._sizes = sizes
        self.ui.sel_size.setModel(
            QStringListModel([x.name for x in self._sizes]))
Пример #3
0
 def __init__(self,
              goods_types: List[goods.GoodsType._Type] = [],
              parent=None):
     super(AddNewGoodsDialog, self).__init__(parent)
     self.ui = Ui_AddNewGoodsDialog()
     self.ui.setupUi(self)
     self._goods_types = goods_types
     self.ui.sel_goods_type.setModel(
         QStringListModel([x.name for x in self._goods_types]))
Пример #4
0
    def __init__(self):
        QObject.__init__(self)

        self._tableModel = DHLTableModel()
        #self._slectionModel=self.
        #self._currentList=None  # type: QStringListModel
        self._channelCount = 0  # type: int
        self._active_channel = 0  # type: int
        self._figure = None  # type: Figure
        #self._tableModelSelectIndex=0 #

        self._acqs = []  # type: typing.List[ismrmrd.Acquisition]

        # 当前行/当前通道原始数据
        self._currentLineData = None  # type: np.array

        # 当前行用于渲染的数据
        self._currentLineListModel = QStringListModel(
        )  # type: QStringListModel
        #self._currentLineListModel.setStringList(['1','2','3'])

        #self.channelCountChanged.connect(self.safe_update_list_model)
        #self.currentChannelIndexChanged.connect(self.safe_update_list_model)

        self._canvas = None  # type: FigureCanvas
        self._figure = None  # type: Figure
        self._axes = None

        self._tableview = None  # type: QTableView

        self._selectionModel = None  # type: QItemSelectionModel

        self._listview = None  # type: QListView
        self._listViewSelectionModel = None  # type: QItemSelectionModel
        self._tableModelSelectIndex = 0  # ?
        self.stop_update_whole_view = False  # global backend data fix in progress
        self.stop_update_list_data = False

        pass
Пример #5
0
    def __init__(self, model):
        """Initialize MNELAB main window.

        Parameters
        ----------
        model : mnelab.model.Model instance
            The main window needs to connect to a model containing all data sets. This
            decouples the GUI from the data (model/view).
        """
        super().__init__()
        self.model = model  # data model
        self.setWindowTitle("MNELAB")

        # restore settings
        settings = read_settings()
        self.recent = settings["recent"]  # list of recent files
        self.resize(settings["size"])
        self.move(settings["pos"])

        # remove None entries from self.recent
        self.recent = [recent for recent in self.recent if recent is not None]

        # trigger theme setting
        QIcon.setThemeSearchPaths([str(Path(__file__).parent / "icons")])
        self.event(QEvent(QEvent.PaletteChange))

        self.actions = {}  # contains all actions

        # initialize menus
        file_menu = self.menuBar().addMenu("&File")
        icon = QIcon.fromTheme("open-file")
        self.actions["open_file"] = file_menu.addAction(
            icon, "&Open...", self.open_data, QKeySequence.Open)
        self.recent_menu = file_menu.addMenu("Open recent")
        self.recent_menu.aboutToShow.connect(self._update_recent_menu)
        self.recent_menu.triggered.connect(self._load_recent)
        if not self.recent:
            self.recent_menu.setEnabled(False)
        self.actions["close_file"] = file_menu.addAction(
            "&Close", self.model.remove_data, QKeySequence.Close)
        self.actions["close_all"] = file_menu.addAction(
            "Close all", self.close_all)
        file_menu.addSeparator()
        icon = QIcon.fromTheme("meta-info")
        self.actions["meta_info"] = file_menu.addAction(
            icon, "Show information...", self.meta_info)
        file_menu.addSeparator()
        self.actions["import_bads"] = file_menu.addAction(
            "Import bad channels...", lambda: self.import_file(
                model.import_bads, "Import bad channels", "*.csv"))
        self.actions["import_events"] = file_menu.addAction(
            "Import events...", lambda: self.import_file(
                model.import_events, "Import events", "*.csv"))
        self.actions["import_annotations"] = file_menu.addAction(
            "Import annotations...", lambda: self.import_file(
                model.import_annotations, "Import annotations", "*.csv"))
        self.actions["import_ica"] = file_menu.addAction(
            "Import &ICA...", lambda: self.open_file(
                model.import_ica, "Import ICA", "*.fif *.fif.gz"))
        file_menu.addSeparator()
        self.export_menu = file_menu.addMenu("Export data")
        for ext, description in writers.items():
            action = "export_data" + ext.replace(".", "_")
            self.actions[action] = self.export_menu.addAction(
                f"{ext[1:].upper()} ({description[1]})...",
                partial(self.export_file, model.export_data, "Export data",
                        "*" + ext))
        self.actions["export_bads"] = file_menu.addAction(
            "Export &bad channels...", lambda: self.export_file(
                model.export_bads, "Export bad channels", "*.csv"))
        self.actions["export_events"] = file_menu.addAction(
            "Export &events...", lambda: self.export_file(
                model.export_events, "Export events", "*.csv"))
        self.actions["export_annotations"] = file_menu.addAction(
            "Export &annotations...", lambda: self.export_file(
                model.export_annotations, "Export annotations", "*.csv"))
        self.actions["export_ica"] = file_menu.addAction(
            "Export ICA...", lambda: self.export_file(
                model.export_ica, "Export ICA", "*.fif *.fif.gz"))
        file_menu.addSeparator()
        self.actions["xdf_chunks"] = file_menu.addAction(
            "Show XDF chunks...", self.xdf_chunks)
        file_menu.addSeparator()
        self.actions["quit"] = file_menu.addAction("&Quit", self.close,
                                                   QKeySequence.Quit)

        edit_menu = self.menuBar().addMenu("&Edit")
        self.actions["pick_chans"] = edit_menu.addAction(
            "P&ick channels...", self.pick_channels)
        icon = QIcon.fromTheme("chan-props")
        self.actions["chan_props"] = edit_menu.addAction(
            icon, "Channel &properties...", self.channel_properties)
        self.actions["set_montage"] = edit_menu.addAction(
            "Set &montage...", self.set_montage)
        edit_menu.addSeparator()
        self.actions["set_ref"] = edit_menu.addAction("Set &reference...",
                                                      self.set_reference)
        edit_menu.addSeparator()
        self.actions["annotations"] = edit_menu.addAction(
            "&Annotations...", self.edit_annotations)
        self.actions["events"] = edit_menu.addAction("&Events...",
                                                     self.edit_events)

        edit_menu.addSeparator()
        self.actions["crop"] = edit_menu.addAction("&Crop data...", self.crop)
        self.actions["append_data"] = edit_menu.addAction(
            "Appen&d data...", self.append_data)

        plot_menu = self.menuBar().addMenu("&Plot")
        icon = QIcon.fromTheme("plot-data")
        self.actions["plot_data"] = plot_menu.addAction(
            icon, "&Data", self.plot_data)
        icon = QIcon.fromTheme("plot-psd")
        self.actions["plot_psd"] = plot_menu.addAction(
            icon, "&Power spectral density", self.plot_psd)
        icon = QIcon.fromTheme("plot-locations")
        self.actions["plot_locations"] = plot_menu.addAction(
            icon, "&Channel locations", self.plot_locations)
        self.actions["plot_erds"] = plot_menu.addAction(
            "&ERDS maps...", self.plot_erds)
        plot_menu.addSeparator()
        self.actions["plot_ica_components"] = plot_menu.addAction(
            "ICA &components...", self.plot_ica_components)
        self.actions["plot_ica_sources"] = plot_menu.addAction(
            "ICA &sources...", self.plot_ica_sources)

        tools_menu = self.menuBar().addMenu("&Tools")
        icon = QIcon.fromTheme("filter-data")
        self.actions["filter"] = tools_menu.addAction(icon, "&Filter data...",
                                                      self.filter_data)
        icon = QIcon.fromTheme("find-events")
        self.actions["find_events"] = tools_menu.addAction(
            icon, "Find &events...", self.find_events)
        self.actions["events_from_annotations"] = tools_menu.addAction(
            "Create events from annotations", self.events_from_annotations)
        self.actions["annotations_from_events"] = tools_menu.addAction(
            "Create annotations from events", self.annotations_from_events)
        tools_menu.addSeparator()
        nirs_menu = tools_menu.addMenu("NIRS")
        self.actions["convert_od"] = nirs_menu.addAction(
            "Convert to &optical density", self.convert_od)
        self.actions["convert_bl"] = nirs_menu.addAction(
            "Convert to &haemoglobin", self.convert_bl)

        tools_menu.addSeparator()
        icon = QIcon.fromTheme("run-ica")
        self.actions["run_ica"] = tools_menu.addAction(icon, "Run &ICA...",
                                                       self.run_ica)
        self.actions["apply_ica"] = tools_menu.addAction(
            "Apply &ICA", self.apply_ica)
        tools_menu.addSeparator()
        self.actions["interpolate_bads"] = tools_menu.addAction(
            "Interpolate bad channels...", self.interpolate_bads)
        tools_menu.addSeparator()
        icon = QIcon.fromTheme("epoch-data")
        self.actions["epoch_data"] = tools_menu.addAction(
            icon, "Create epochs...", self.epoch_data)

        view_menu = self.menuBar().addMenu("&View")
        self.actions["history"] = view_menu.addAction("&History...",
                                                      self.show_history)
        self.actions["toolbar"] = view_menu.addAction("&Toolbar",
                                                      self._toggle_toolbar)
        self.actions["toolbar"].setCheckable(True)
        self.actions["statusbar"] = view_menu.addAction(
            "&Statusbar", self._toggle_statusbar)
        self.actions["statusbar"].setCheckable(True)

        help_menu = self.menuBar().addMenu("&Help")
        self.actions["about"] = help_menu.addAction("&About", self.show_about)
        self.actions["about_qt"] = help_menu.addAction("About &Qt",
                                                       self.show_about_qt)

        # actions that are always enabled
        self.always_enabled = [
            "open_file", "about", "about_qt", "quit", "xdf_chunks", "toolbar",
            "statusbar"
        ]

        # set up toolbar
        self.toolbar = self.addToolBar("toolbar")
        self.toolbar.setObjectName("toolbar")
        self.toolbar.addAction(self.actions["open_file"])
        self.toolbar.addAction(self.actions["meta_info"])
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.actions["chan_props"])
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.actions["plot_data"])
        self.toolbar.addAction(self.actions["plot_psd"])
        self.toolbar.addAction(self.actions["plot_locations"])
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.actions["filter"])
        self.toolbar.addAction(self.actions["find_events"])
        self.toolbar.addAction(self.actions["epoch_data"])
        self.toolbar.addAction(self.actions["run_ica"])
        self.toolbar.setMovable(False)
        self.setUnifiedTitleAndToolBarOnMac(True)
        if settings["toolbar"]:
            self.toolbar.show()
            self.actions["toolbar"].setChecked(True)
        else:
            self.toolbar.hide()
            self.actions["toolbar"].setChecked(False)

        # set up data model for sidebar (list of open files)
        self.names = QStringListModel()
        self.names.dataChanged.connect(self._update_names)
        splitter = QSplitter()
        self.sidebar = QListView()
        self.sidebar.setFrameStyle(QFrame.NoFrame)
        self.sidebar.setFocusPolicy(Qt.NoFocus)
        self.sidebar.setModel(self.names)
        self.sidebar.clicked.connect(self._update_data)
        splitter.addWidget(self.sidebar)
        self.infowidget = InfoWidget()
        splitter.addWidget(self.infowidget)
        width = splitter.size().width()
        splitter.setSizes((int(width * 0.3), int(width * 0.7)))
        self.setCentralWidget(splitter)

        self.status_label = QLabel()
        self.statusBar().addPermanentWidget(self.status_label)
        if settings["statusbar"]:
            self.statusBar().show()
            self.actions["statusbar"].setChecked(True)
        else:
            self.statusBar().hide()
            self.actions["statusbar"].setChecked(False)

        self.setAcceptDrops(True)
        self.data_changed()
Пример #6
0
class MainWindow(QMainWindow):
    """MNELAB main window."""
    def __init__(self, model):
        """Initialize MNELAB main window.

        Parameters
        ----------
        model : mnelab.model.Model instance
            The main window needs to connect to a model containing all data sets. This
            decouples the GUI from the data (model/view).
        """
        super().__init__()
        self.model = model  # data model
        self.setWindowTitle("MNELAB")

        # restore settings
        settings = read_settings()
        self.recent = settings["recent"]  # list of recent files
        self.resize(settings["size"])
        self.move(settings["pos"])

        # remove None entries from self.recent
        self.recent = [recent for recent in self.recent if recent is not None]

        # trigger theme setting
        QIcon.setThemeSearchPaths([str(Path(__file__).parent / "icons")])
        self.event(QEvent(QEvent.PaletteChange))

        self.actions = {}  # contains all actions

        # initialize menus
        file_menu = self.menuBar().addMenu("&File")
        icon = QIcon.fromTheme("open-file")
        self.actions["open_file"] = file_menu.addAction(
            icon, "&Open...", self.open_data, QKeySequence.Open)
        self.recent_menu = file_menu.addMenu("Open recent")
        self.recent_menu.aboutToShow.connect(self._update_recent_menu)
        self.recent_menu.triggered.connect(self._load_recent)
        if not self.recent:
            self.recent_menu.setEnabled(False)
        self.actions["close_file"] = file_menu.addAction(
            "&Close", self.model.remove_data, QKeySequence.Close)
        self.actions["close_all"] = file_menu.addAction(
            "Close all", self.close_all)
        file_menu.addSeparator()
        icon = QIcon.fromTheme("meta-info")
        self.actions["meta_info"] = file_menu.addAction(
            icon, "Show information...", self.meta_info)
        file_menu.addSeparator()
        self.actions["import_bads"] = file_menu.addAction(
            "Import bad channels...", lambda: self.import_file(
                model.import_bads, "Import bad channels", "*.csv"))
        self.actions["import_events"] = file_menu.addAction(
            "Import events...", lambda: self.import_file(
                model.import_events, "Import events", "*.csv"))
        self.actions["import_annotations"] = file_menu.addAction(
            "Import annotations...", lambda: self.import_file(
                model.import_annotations, "Import annotations", "*.csv"))
        self.actions["import_ica"] = file_menu.addAction(
            "Import &ICA...", lambda: self.open_file(
                model.import_ica, "Import ICA", "*.fif *.fif.gz"))
        file_menu.addSeparator()
        self.export_menu = file_menu.addMenu("Export data")
        for ext, description in writers.items():
            action = "export_data" + ext.replace(".", "_")
            self.actions[action] = self.export_menu.addAction(
                f"{ext[1:].upper()} ({description[1]})...",
                partial(self.export_file, model.export_data, "Export data",
                        "*" + ext))
        self.actions["export_bads"] = file_menu.addAction(
            "Export &bad channels...", lambda: self.export_file(
                model.export_bads, "Export bad channels", "*.csv"))
        self.actions["export_events"] = file_menu.addAction(
            "Export &events...", lambda: self.export_file(
                model.export_events, "Export events", "*.csv"))
        self.actions["export_annotations"] = file_menu.addAction(
            "Export &annotations...", lambda: self.export_file(
                model.export_annotations, "Export annotations", "*.csv"))
        self.actions["export_ica"] = file_menu.addAction(
            "Export ICA...", lambda: self.export_file(
                model.export_ica, "Export ICA", "*.fif *.fif.gz"))
        file_menu.addSeparator()
        self.actions["xdf_chunks"] = file_menu.addAction(
            "Show XDF chunks...", self.xdf_chunks)
        file_menu.addSeparator()
        self.actions["quit"] = file_menu.addAction("&Quit", self.close,
                                                   QKeySequence.Quit)

        edit_menu = self.menuBar().addMenu("&Edit")
        self.actions["pick_chans"] = edit_menu.addAction(
            "P&ick channels...", self.pick_channels)
        icon = QIcon.fromTheme("chan-props")
        self.actions["chan_props"] = edit_menu.addAction(
            icon, "Channel &properties...", self.channel_properties)
        self.actions["set_montage"] = edit_menu.addAction(
            "Set &montage...", self.set_montage)
        edit_menu.addSeparator()
        self.actions["set_ref"] = edit_menu.addAction("Set &reference...",
                                                      self.set_reference)
        edit_menu.addSeparator()
        self.actions["annotations"] = edit_menu.addAction(
            "&Annotations...", self.edit_annotations)
        self.actions["events"] = edit_menu.addAction("&Events...",
                                                     self.edit_events)

        edit_menu.addSeparator()
        self.actions["crop"] = edit_menu.addAction("&Crop data...", self.crop)
        self.actions["append_data"] = edit_menu.addAction(
            "Appen&d data...", self.append_data)

        plot_menu = self.menuBar().addMenu("&Plot")
        icon = QIcon.fromTheme("plot-data")
        self.actions["plot_data"] = plot_menu.addAction(
            icon, "&Data", self.plot_data)
        icon = QIcon.fromTheme("plot-psd")
        self.actions["plot_psd"] = plot_menu.addAction(
            icon, "&Power spectral density", self.plot_psd)
        icon = QIcon.fromTheme("plot-locations")
        self.actions["plot_locations"] = plot_menu.addAction(
            icon, "&Channel locations", self.plot_locations)
        self.actions["plot_erds"] = plot_menu.addAction(
            "&ERDS maps...", self.plot_erds)
        plot_menu.addSeparator()
        self.actions["plot_ica_components"] = plot_menu.addAction(
            "ICA &components...", self.plot_ica_components)
        self.actions["plot_ica_sources"] = plot_menu.addAction(
            "ICA &sources...", self.plot_ica_sources)

        tools_menu = self.menuBar().addMenu("&Tools")
        icon = QIcon.fromTheme("filter-data")
        self.actions["filter"] = tools_menu.addAction(icon, "&Filter data...",
                                                      self.filter_data)
        icon = QIcon.fromTheme("find-events")
        self.actions["find_events"] = tools_menu.addAction(
            icon, "Find &events...", self.find_events)
        self.actions["events_from_annotations"] = tools_menu.addAction(
            "Create events from annotations", self.events_from_annotations)
        self.actions["annotations_from_events"] = tools_menu.addAction(
            "Create annotations from events", self.annotations_from_events)
        tools_menu.addSeparator()
        nirs_menu = tools_menu.addMenu("NIRS")
        self.actions["convert_od"] = nirs_menu.addAction(
            "Convert to &optical density", self.convert_od)
        self.actions["convert_bl"] = nirs_menu.addAction(
            "Convert to &haemoglobin", self.convert_bl)

        tools_menu.addSeparator()
        icon = QIcon.fromTheme("run-ica")
        self.actions["run_ica"] = tools_menu.addAction(icon, "Run &ICA...",
                                                       self.run_ica)
        self.actions["apply_ica"] = tools_menu.addAction(
            "Apply &ICA", self.apply_ica)
        tools_menu.addSeparator()
        self.actions["interpolate_bads"] = tools_menu.addAction(
            "Interpolate bad channels...", self.interpolate_bads)
        tools_menu.addSeparator()
        icon = QIcon.fromTheme("epoch-data")
        self.actions["epoch_data"] = tools_menu.addAction(
            icon, "Create epochs...", self.epoch_data)

        view_menu = self.menuBar().addMenu("&View")
        self.actions["history"] = view_menu.addAction("&History...",
                                                      self.show_history)
        self.actions["toolbar"] = view_menu.addAction("&Toolbar",
                                                      self._toggle_toolbar)
        self.actions["toolbar"].setCheckable(True)
        self.actions["statusbar"] = view_menu.addAction(
            "&Statusbar", self._toggle_statusbar)
        self.actions["statusbar"].setCheckable(True)

        help_menu = self.menuBar().addMenu("&Help")
        self.actions["about"] = help_menu.addAction("&About", self.show_about)
        self.actions["about_qt"] = help_menu.addAction("About &Qt",
                                                       self.show_about_qt)

        # actions that are always enabled
        self.always_enabled = [
            "open_file", "about", "about_qt", "quit", "xdf_chunks", "toolbar",
            "statusbar"
        ]

        # set up toolbar
        self.toolbar = self.addToolBar("toolbar")
        self.toolbar.setObjectName("toolbar")
        self.toolbar.addAction(self.actions["open_file"])
        self.toolbar.addAction(self.actions["meta_info"])
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.actions["chan_props"])
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.actions["plot_data"])
        self.toolbar.addAction(self.actions["plot_psd"])
        self.toolbar.addAction(self.actions["plot_locations"])
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.actions["filter"])
        self.toolbar.addAction(self.actions["find_events"])
        self.toolbar.addAction(self.actions["epoch_data"])
        self.toolbar.addAction(self.actions["run_ica"])
        self.toolbar.setMovable(False)
        self.setUnifiedTitleAndToolBarOnMac(True)
        if settings["toolbar"]:
            self.toolbar.show()
            self.actions["toolbar"].setChecked(True)
        else:
            self.toolbar.hide()
            self.actions["toolbar"].setChecked(False)

        # set up data model for sidebar (list of open files)
        self.names = QStringListModel()
        self.names.dataChanged.connect(self._update_names)
        splitter = QSplitter()
        self.sidebar = QListView()
        self.sidebar.setFrameStyle(QFrame.NoFrame)
        self.sidebar.setFocusPolicy(Qt.NoFocus)
        self.sidebar.setModel(self.names)
        self.sidebar.clicked.connect(self._update_data)
        splitter.addWidget(self.sidebar)
        self.infowidget = InfoWidget()
        splitter.addWidget(self.infowidget)
        width = splitter.size().width()
        splitter.setSizes((int(width * 0.3), int(width * 0.7)))
        self.setCentralWidget(splitter)

        self.status_label = QLabel()
        self.statusBar().addPermanentWidget(self.status_label)
        if settings["statusbar"]:
            self.statusBar().show()
            self.actions["statusbar"].setChecked(True)
        else:
            self.statusBar().hide()
            self.actions["statusbar"].setChecked(False)

        self.setAcceptDrops(True)
        self.data_changed()

    def data_changed(self):
        # update sidebar
        self.names.setStringList(self.model.names)
        self.sidebar.setCurrentIndex(self.names.index(self.model.index))

        # update info widget
        if self.model.data:
            self.infowidget.set_values(self.model.get_info())
        else:
            self.infowidget.clear()

        # update status bar
        if self.model.data:
            mb = self.model.nbytes / 1024**2
            self.status_label.setText(f"Total Memory: {mb:.2f} MB")
        else:
            self.status_label.clear()

        # toggle actions
        if len(self.model) == 0:  # disable if no data sets are currently open
            enabled = False
        else:
            enabled = True

        for name, action in self.actions.items():  # toggle
            if name not in self.always_enabled:
                action.setEnabled(enabled)

        if self.model.data:  # toggle if specific conditions are met
            bads = bool(self.model.current["data"].info["bads"])
            self.actions["export_bads"].setEnabled(enabled and bads)
            events = self.model.current["events"] is not None
            self.actions["export_events"].setEnabled(enabled and events)
            if self.model.current["dtype"] == "raw":
                annot = bool(self.model.current["data"].annotations)
            else:
                annot = False
            self.actions["export_annotations"].setEnabled(enabled and annot)
            self.actions["annotations"].setEnabled(enabled and annot)
            locations = has_locations(self.model.current["data"].info)
            self.actions["plot_locations"].setEnabled(enabled and locations)
            ica = bool(self.model.current["ica"])
            self.actions["apply_ica"].setEnabled(enabled and ica)
            self.actions["export_ica"].setEnabled(enabled and ica)
            self.actions["plot_erds"].setEnabled(
                enabled and self.model.current["dtype"] == "epochs")
            self.actions["plot_ica_components"].setEnabled(enabled and ica
                                                           and locations)
            self.actions["plot_ica_sources"].setEnabled(enabled and ica)
            self.actions["interpolate_bads"].setEnabled(enabled and locations
                                                        and bads)
            self.actions["events"].setEnabled(enabled and events)
            self.actions["events_from_annotations"].setEnabled(enabled
                                                               and annot)
            self.actions["annotations_from_events"].setEnabled(enabled
                                                               and events)
            self.actions["find_events"].setEnabled(
                enabled and self.model.current["dtype"] == "raw")
            self.actions["epoch_data"].setEnabled(
                enabled and events and self.model.current["dtype"] == "raw")
            self.actions["crop"].setEnabled(
                enabled and self.model.current["dtype"] == "raw")
            append = bool(self.model.get_compatibles())
            self.actions["append_data"].setEnabled(
                enabled and append
                and (self.model.current["dtype"] in ("raw", "epochs")))
            self.actions["meta_info"].setEnabled(
                enabled
                and self.model.current["ftype"] in ["XDF", "XDFZ", "XDF.GZ"])
            self.actions["convert_od"].setEnabled(
                len(
                    mne.pick_types(self.model.current["data"].info,
                                   fnirs="fnirs_cw_amplitude")))
            self.actions["convert_bl"].setEnabled(
                len(
                    mne.pick_types(self.model.current["data"].info,
                                   fnirs="fnirs_od")))
            # disable unsupported exporters for epochs (all must support raw)
            if self.model.current["dtype"] == "epochs":
                for ext, description in writers.items():
                    action = "export_data" + ext.replace(".", "_")
                    if "epoch" in description[2]:
                        self.actions[action].setEnabled(True)
                    else:
                        self.actions[action].setEnabled(False)
        # add to recent files
        if len(self.model) > 0:
            self._add_recent(self.model.current["fname"])

    def open_data(self, fname=None):
        """Open raw file."""
        if fname is None:
            fname = QFileDialog.getOpenFileName(self, "Open raw")[0]
        if fname:
            if not (Path(fname).is_file() or Path(fname).is_dir()):
                self._remove_recent(fname)
                QMessageBox.critical(self, "File does not exist",
                                     f"File {fname} does not exist anymore.")
                return

            ext = "".join(Path(fname).suffixes)

            if any([ext.endswith(e) for e in (".xdf", ".xdfz", ".xdf.gz")]):
                rows, disabled = [], []
                for idx, s in enumerate(resolve_streams(fname)):
                    rows.append([
                        s["stream_id"], s["name"], s["type"],
                        s["channel_count"], s["channel_format"],
                        s["nominal_srate"]
                    ])
                    is_marker = (s["nominal_srate"] == 0
                                 or s["channel_format"] == "string")
                    if is_marker:  # disable marker streams
                        disabled.append(idx)

                enabled = list(set(range(len(rows))) - set(disabled))
                if enabled:
                    selected = enabled[0]
                else:
                    selected = None
                dialog = XDFStreamsDialog(self,
                                          rows,
                                          selected=selected,
                                          disabled=disabled)
                if dialog.exec():
                    row = dialog.view.selectionModel().selectedRows()[0].row()
                    stream_id = dialog.model.data(dialog.model.index(row, 0))
                    srate = "effective" if dialog.effective_srate else "nominal"
                    prefix_markers = dialog.prefix_markers
                    kwargs = {}
                    if srate == "nominal":
                        kwargs["srate"] = srate
                    if prefix_markers:
                        kwargs["prefix_markers"] = prefix_markers
                    self.model.load(fname, stream_id=stream_id, **kwargs)
            else:  # all other file formats
                try:
                    self.model.load(fname)
                except FileNotFoundError as e:
                    QMessageBox.critical(self, "File not found", str(e))
                except ValueError as e:
                    QMessageBox.critical(self, "Unknown file type", str(e))

    def open_file(self, f, text, ffilter="*"):
        """Open file."""
        fname = QFileDialog.getOpenFileName(self, text, filter=ffilter)[0]
        if fname:
            f(fname)

    def xdf_chunks(self):
        """Show XDF chunks."""
        fname = QFileDialog.getOpenFileName(self,
                                            "Select XDF file",
                                            filter="*.xdf *.xdfz *.xdf.gz")[0]
        if fname:
            chunks = list_chunks(fname)
            dialog = XDFChunksDialog(self, chunks, fname)
            dialog.exec_()

    def export_file(self, f, text, ffilter="*"):
        """Export to file."""
        fname = QFileDialog.getSaveFileName(self, text, filter=ffilter)[0]
        if fname:
            if ffilter != "*":
                exts = [ext.replace("*", "") for ext in ffilter.split()]

                maxsuffixes = max([ext.count(".") for ext in exts])
                suffixes = Path(fname).suffixes
                for i in range(-maxsuffixes, 0):
                    ext = "".join(suffixes[i:])
                    if ext in exts:
                        return f(fname)
                fname = fname + exts[0]
                return f(fname)

    def import_file(self, f, text, ffilter="*"):
        """Import file."""
        fname = QFileDialog.getOpenFileName(self, text, filter=ffilter)[0]
        if fname:
            try:
                f(fname)
            except LabelsNotFoundError as e:
                QMessageBox.critical(self, "Channel labels not found", str(e))
            except InvalidAnnotationsError as e:
                QMessageBox.critical(self, "Invalid annotations", str(e))

    def close_all(self):
        """Close all currently open data sets."""
        msg = QMessageBox.question(self, "Close all data sets",
                                   "Close all data sets?")
        if msg == QMessageBox.Yes:
            while len(self.model) > 0:
                self.model.remove_data()

    def meta_info(self):
        """Show XDF meta info."""
        xml = get_xml(self.model.current["fname"])
        dialog = MetaInfoDialog(self, xml)
        dialog.exec()

    def pick_channels(self):
        """Pick channels in current data set."""
        channels = self.model.current["data"].info["ch_names"]
        dialog = PickChannelsDialog(self, channels, selected=channels)
        if dialog.exec():
            picks = [item.data(0) for item in dialog.channels.selectedItems()]
            drops = list(set(channels) - set(picks))
            if drops:
                self.auto_duplicate()
                self.model.drop_channels(drops)
                self.model.history.append(f"data.drop_channels({drops})")

    def channel_properties(self):
        """Show channel properties dialog."""
        info = self.model.current["data"].info
        dialog = ChannelPropertiesDialog(self, info)
        if dialog.exec():
            dialog.model.sort(0)
            bads = []
            renamed = {}
            types = {}
            for i in range(dialog.model.rowCount()):
                new_label = dialog.model.item(i, 1).data(Qt.DisplayRole)
                old_label = info["ch_names"][i]
                if new_label != old_label:
                    renamed[old_label] = new_label
                new_type = dialog.model.item(i, 2).data(Qt.DisplayRole).lower()
                old_type = channel_type(info, i).lower()
                if new_type != old_type:
                    types[new_label] = new_type
                if dialog.model.item(i, 3).checkState() == Qt.Checked:
                    bads.append(info["ch_names"][i])
            self.model.set_channel_properties(bads, renamed, types)

    def set_montage(self):
        """Set montage."""
        montages = mne.channels.get_builtin_montages()
        # TODO: currently it is not possible to remove an existing montage
        dialog = MontageDialog(self, montages)
        if dialog.exec():
            name = dialog.montages.selectedItems()[0].data(0)
            montage = mne.channels.make_standard_montage(name)
            ch_names = self.model.current["data"].info["ch_names"]
            # check if at least one channel name matches a name in the montage
            if set(ch_names) & set(montage.ch_names):
                self.model.set_montage(name)
            else:
                QMessageBox.critical(
                    self, "No matching channel names",
                    "Channel names defined in the "
                    "montage do not match any channel name in the data.")

    def edit_annotations(self):
        fs = self.model.current["data"].info["sfreq"]
        pos = self.model.current["data"].annotations.onset
        pos = (pos * fs).astype(int).tolist()
        dur = self.model.current["data"].annotations.duration
        dur = (dur * fs).astype(int).tolist()
        desc = self.model.current["data"].annotations.description.tolist()
        dialog = AnnotationsDialog(self, pos, dur, desc)
        if dialog.exec():
            rows = dialog.table.rowCount()
            onset, duration, description = [], [], []
            for i in range(rows):
                data = dialog.table.item(i, 0).data(Qt.DisplayRole)
                onset.append(float(data) / fs)
                data = dialog.table.item(i, 1).data(Qt.DisplayRole)
                duration.append(float(data) / fs)
                data = dialog.table.item(i, 2).data(Qt.DisplayRole)
                description.append(data)
            self.model.set_annotations(onset, duration, description)

    def edit_events(self):
        pos = self.model.current["events"][:, 0].tolist()
        desc = self.model.current["events"][:, 2].tolist()
        dialog = EventsDialog(self, pos, desc)
        if dialog.exec():
            rows = dialog.table.rowCount()
            events = np.zeros((rows, 3), dtype=int)
            for i in range(rows):
                pos = int(dialog.table.item(i, 0).data(Qt.DisplayRole))
                desc = int(dialog.table.item(i, 1).data(Qt.DisplayRole))
                events[i] = pos, 0, desc
            self.model.set_events(events)

    def crop(self):
        """Crop data."""
        fs = self.model.current["data"].info["sfreq"]
        length = self.model.current["data"].n_times / fs
        dialog = CropDialog(self, 0, length)
        if dialog.exec():
            self.auto_duplicate()
            self.model.crop(dialog.start or 0, dialog.stop)

    def append_data(self):
        """Concatenate raw data objects to current one."""
        compatibles = self.model.get_compatibles()
        dialog = AppendDialog(self, compatibles)
        if dialog.exec():
            self.auto_duplicate()
            self.model.append_data(dialog.names)

    def plot_data(self):
        """Plot data."""
        # self.bad is needed to update history if bad channels are selected in
        # the interactive plot window (see also self.eventFilter)
        self.bads = self.model.current["data"].info["bads"]
        events = self.model.current["events"]
        nchan = self.model.current["data"].info["nchan"]
        fig = self.model.current["data"].plot(events=events,
                                              n_channels=nchan,
                                              title=self.model.current["name"],
                                              scalings="auto",
                                              show=False)
        if events is not None:
            hist = f"data.plot(events=events, n_channels={nchan})"
        else:
            hist = f"data.plot(n_channels={nchan})"
        self.model.history.append(hist)
        win = fig.canvas.manager.window
        win.setWindowTitle(self.model.current["name"])
        win.statusBar().hide()  # not necessary since matplotlib 3.3
        win.installEventFilter(self)  # detect if the figure is closed

        # prevent closing the window with the escape key
        try:
            fig._mne_params["close_key"] = None
        except AttributeError:  # does not exist in older MNE versions
            pass

        fig.show()

    def plot_psd(self):
        """Plot power spectral density (PSD)."""
        kwds = {}
        if self.model.current["dtype"] == "raw":
            kwds.update({"average": False, "spatial_colors": False})
        fig = self.model.current["data"].plot_psd(show=False, **kwds)
        if kwds:
            tmp = ", ".join(f"{key}={value}" for key, value in kwds.items())
            hist = f"data.plot_psd({tmp})"
        else:
            hist = "data.plot_psd()"
        self.model.history.append(hist)
        win = fig.canvas.manager.window
        win.setWindowTitle("Power spectral density")
        fig.show()

    def plot_locations(self):
        """Plot current montage."""
        fig = self.model.current["data"].plot_sensors(show_names=True,
                                                      show=False)
        win = fig.canvas.manager.window
        win.setWindowTitle("Montage")
        win.statusBar().hide()  # not necessary since matplotlib 3.3
        fig.show()

    def plot_ica_components(self):
        self.model.current["ica"].plot_components(
            inst=self.model.current["data"])

    def plot_ica_sources(self):
        self.model.current["ica"].plot_sources(inst=self.model.current["data"])

    def plot_erds(self):
        """Plot ERDS maps."""
        data = self.model.current["data"]
        t_range = [data.tmin, data.tmax]
        f_range = [1, data.info["sfreq"] / 2]

        dialog = ERDSDialog(self, t_range, f_range)

        if dialog.exec():
            freqs = np.arange(dialog.f1, dialog.f2, dialog.step)
            baseline = [dialog.b1, dialog.b2]
            times = [dialog.t1, dialog.t2]
            figs = plot_erds(data, freqs, freqs, baseline, times)
            for fig in figs:
                fig.show()

    def run_ica(self):
        """Run ICA calculation."""

        methods = ["Infomax"]
        if have["picard"]:
            methods.insert(0, "Picard")
        if have["sklearn"]:
            methods.append("FastICA")

        dialog = RunICADialog(self, self.model.current["data"].info["nchan"],
                              methods)

        if dialog.exec():
            calc = CalcDialog(self, "Calculating ICA", "Calculating ICA.")

            method = dialog.method.currentText().lower()
            exclude_bad_segments = dialog.exclude_bad_segments.isChecked()

            fit_params = {}
            if dialog.extended.isEnabled():
                fit_params["extended"] = dialog.extended.isChecked()
            if dialog.ortho.isEnabled():
                fit_params["ortho"] = dialog.ortho.isChecked()

            ica = mne.preprocessing.ICA(method=method, fit_params=fit_params)
            history = f"ica = mne.preprocessing.ICA(method='{method}'"
            if fit_params:
                history += f", fit_params={fit_params})"
            else:
                history += ")"
            self.model.history.append(history)

            pool = mp.Pool(processes=1)

            def callback(x):
                QMetaObject.invokeMethod(calc, "accept", Qt.QueuedConnection)

            res = pool.apply_async(
                func=ica.fit,
                args=(self.model.current["data"], ),
                kwds={"reject_by_annotation": exclude_bad_segments},
                callback=callback)
            pool.close()

            if not calc.exec():
                pool.terminate()
                print("ICA calculation aborted...")
            else:
                self.model.current["ica"] = res.get(timeout=1)
                self.model.history.append(
                    f"ica.fit(inst=raw, reject_by_annotation="
                    f"{exclude_bad_segments})")
                self.data_changed()

    def apply_ica(self):
        """Apply current fitted ICA."""
        self.auto_duplicate()
        self.model.apply_ica()

    def interpolate_bads(self):
        """Interpolate bad channels"""
        dialog = InterpolateBadsDialog(self)
        if dialog.exec():
            duplicated = self.auto_duplicate()
            try:
                self.model.interpolate_bads(dialog.reset_bads, dialog.mode,
                                            dialog.origin)
            except ValueError as e:
                if duplicated:  # undo
                    self.model.remove_data()
                    self.model.index -= 1
                    self.data_changed()
                msgbox = ErrorMessageBox(self,
                                         "Could not interpolate bad channels",
                                         str(e), traceback.format_exc())
                msgbox.show()

    def filter_data(self):
        """Filter data."""
        dialog = FilterDialog(self)
        if dialog.exec():
            self.auto_duplicate()
            self.model.filter(dialog.low, dialog.high)

    def find_events(self):
        info = self.model.current["data"].info

        # use first stim channel as default in dialog
        default_stim = 0
        for i in range(info["nchan"]):
            if mne.io.pick.channel_type(info, i) == "stim":
                default_stim = i
                break
        dialog = FindEventsDialog(self, info["ch_names"], default_stim)
        if dialog.exec():
            stim_channel = dialog.stimchan.currentText()
            consecutive = dialog.consecutive.isChecked()
            initial_event = dialog.initial_event.isChecked()
            uint_cast = dialog.uint_cast.isChecked()
            min_dur = dialog.minduredit.value()
            shortest_event = dialog.shortesteventedit.value()
            self.model.find_events(stim_channel=stim_channel,
                                   consecutive=consecutive,
                                   initial_event=initial_event,
                                   uint_cast=uint_cast,
                                   min_duration=min_dur,
                                   shortest_event=shortest_event)

    def events_from_annotations(self):
        self.model.events_from_annotations()

    def annotations_from_events(self):
        self.model.annotations_from_events()

    def epoch_data(self):
        """Epoch raw data."""
        dialog = EpochDialog(self, self.model.current["events"])
        if dialog.exec():
            events = [
                int(item.text()) for item in dialog.events.selectedItems()
            ]
            tmin = dialog.tmin.value()
            tmax = dialog.tmax.value()

            if dialog.baseline.isChecked():
                baseline = dialog.a.value(), dialog.b.value()
            else:
                baseline = None

            duplicated = self.auto_duplicate()
            try:
                self.model.epoch_data(events, tmin, tmax, baseline)
            except ValueError as e:
                if duplicated:  # undo
                    self.model.remove_data()
                    self.model.index -= 1
                    self.data_changed()
                msgbox = ErrorMessageBox(self, "Could not create epochs",
                                         str(e), traceback.format_exc())
                msgbox.show()

    def convert_od(self):
        """Convert to optical density."""
        self.auto_duplicate()
        self.model.convert_od()

    def convert_bl(self):
        """Convert to haemoglobin."""
        self.auto_duplicate()
        self.model.convert_beer_lambert()

    def set_reference(self):
        """Set reference."""
        dialog = ReferenceDialog(self)
        if dialog.exec():
            self.auto_duplicate()
            if dialog.average.isChecked():
                self.model.set_reference("average")
            else:
                ref = [c.strip() for c in dialog.channellist.text().split(",")]
                self.model.set_reference(ref)

    def show_history(self):
        """Show history."""
        dialog = HistoryDialog(self, "\n".join(self.model.history))
        dialog.exec()

    def show_about(self):
        """Show About dialog."""
        from . import __version__

        msg_box = QMessageBox(self)
        text = (
            f"<img src='{image_path('mnelab_logo.png')}'><p>MNELAB {__version__}</p>"
        )
        msg_box.setText(text)

        mnelab_url = "github.com/cbrnr/mnelab"
        mne_url = "github.com/mne-tools/mne-python"

        pkgs = []
        for key, value in have.items():
            if value:
                pkgs.append(f"{key}&nbsp;({value})")
            else:
                pkgs.append(f"{key}&nbsp;(not installed)")
        version = ".".join(str(k) for k in version_info[:3])
        text = (
            f"<nobr><p>This program uses Python {version} and the following packages:"
            f"</p></nobr><p>{', '.join(pkgs)}</p>"
            f"<nobr><p>MNELAB repository: <a href=https://{mnelab_url}>{mnelab_url}</a>"
            f"</p></nobr><nobr><p>MNE repository: "
            f"<a href=https://{mne_url}>{mne_url}</a></p></nobr>"
            f"<p>Licensed under the BSD 3-clause license.</p>"
            f"<p>Copyright 2017&ndash;2021 by Clemens Brunner.</p>")
        msg_box.setInformativeText(text)
        msg_box.exec()

    def show_about_qt(self):
        """Show About Qt dialog."""
        QMessageBox.aboutQt(self, "About Qt")

    def auto_duplicate(self):
        """Automatically duplicate current data set.

        If the current data set is stored in a file (i.e. was loaded directly from a file),
        a new data set is automatically created. If the current data set is not stored in a
        file (i.e. was created by operations in MNELAB), a dialog box asks the user if the
        current data set should be overwritten or duplicated.

        Returns
        -------
        duplicated : bool
            True if the current data set was automatically duplicated, False if the current
            data set was overwritten.
        """
        # if current data is stored in a file create a new data set
        if self.model.current["fname"]:
            self.model.duplicate_data()
            return True
        # otherwise ask the user
        else:
            msg = QMessageBox.question(self, "Overwrite existing data set",
                                       "Overwrite existing data set?")
            if msg == QMessageBox.No:  # create new data set
                self.model.duplicate_data()
                return True
        return False

    def _add_recent(self, fname):
        """Add a file to recent file list.

        Parameters
        ----------
        fname : str
            File name.
        """
        if fname in self.recent:  # avoid duplicates
            self.recent.remove(fname)
        self.recent.insert(0, fname)
        while len(self.recent) > MAX_RECENT:  # prune list
            self.recent.pop()
        write_settings(recent=self.recent)
        if not self.recent_menu.isEnabled():
            self.recent_menu.setEnabled(True)

    def _remove_recent(self, fname):
        """Remove file from recent file list.

        Parameters
        ----------
        fname : str
            File name.
        """
        if fname in self.recent:
            self.recent.remove(fname)
            write_settings(recent=self.recent)
            if not self.recent:
                self.recent_menu.setEnabled(False)

    @Slot(QModelIndex)
    def _update_data(self, selected):
        """Update index and information based on the state of the sidebar.

        Parameters
        ----------
        selected : QModelIndex
            Index of the selected row.
        """
        if selected.row() != self.model.index:
            self.model.index = selected.row()
            self.data_changed()
            self.model.history.append(f"data = datasets[{self.model.index}]")

    @Slot(QModelIndex, QModelIndex)
    def _update_names(self, start, stop):
        """Update names in DataSets after changes in sidebar."""
        for index in range(start.row(), stop.row() + 1):
            self.model.data[index]["name"] = self.names.stringList()[index]

    @Slot()
    def _update_recent_menu(self):
        self.recent_menu.clear()
        for recent in self.recent:
            self.recent_menu.addAction(recent)

    @Slot(QAction)
    def _load_recent(self, action):
        self.open_data(fname=action.text())

    @Slot()
    def _toggle_toolbar(self):
        if self.toolbar.isHidden():
            self.toolbar.show()
        else:
            self.toolbar.hide()
        write_settings(toolbar=not self.toolbar.isHidden())

    @Slot()
    def _toggle_statusbar(self):
        if self.statusBar().isHidden():
            self.statusBar().show()
        else:
            self.statusBar().hide()
        write_settings(statusbar=not self.statusBar().isHidden())

    @Slot(QDropEvent)
    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.acceptProposedAction()

    @Slot(QDropEvent)
    def dropEvent(self, event):
        mime = event.mimeData()
        if mime.hasUrls():
            urls = mime.urls()
            for url in urls:
                try:
                    self.open_data(url.toLocalFile())
                except FileNotFoundError as e:
                    QMessageBox.critical(self, "File not found", str(e))

    @Slot(QEvent)
    def closeEvent(self, event):
        """Close application.

        Parameters
        ----------
        event : QEvent
            Close event.
        """
        write_settings(size=self.size(), pos=self.pos())
        if self.model.history:
            print("\n# Command History\n")
            print("\n".join(self.model.history))
        QApplication.quit()

    def eventFilter(self, source, event):
        # currently the only source is the raw plot window
        if event.type() == QEvent.Close:
            self.data_changed()
            bads = self.model.current["data"].info["bads"]
            if self.bads != bads:
                self.model.history.append(f'data.info["bads"] = {bads}')
        return QObject.eventFilter(self, source, event)

    def event(self, ev):
        """Catch system events."""
        if ev.type() == QEvent.PaletteChange:  # detect theme switches
            style = interface_style()  # light or dark
            if style is not None:
                QIcon.setThemeName(style)
            else:
                QIcon.setThemeName("light")  # fallback
        return super().event(ev)
Пример #7
0
  def __init__(self):
    ## Initialize the application
    self.app = QApplication(sys.argv)
    super().__init__(None)
    self.setWindowTitle("Voice Conversion app")


    ## Main layouts
    # Root
    root_layout = QGridLayout()
    self.setLayout(root_layout)

    # Browser
    browser_layout = QGridLayout()
    root_layout.addLayout(browser_layout, 0, 0, 1, 2)

    # Generation
    gen_layout = QVBoxLayout()
    root_layout.addLayout(gen_layout, 1, 0, 1, 2)

    # Projections
    self.projections_layout = QVBoxLayout()
    root_layout.addLayout(self.projections_layout, 1, 2, 1, 1)

    # Visualizations
    vis_layout = QVBoxLayout()
    root_layout.addLayout(vis_layout, 0, 2, 1, 1)


    ## Projections
    # UMap
    fig, self.umap_ax = plt.subplots(figsize=(3, 3), facecolor="#F0F0F0")
    fig.subplots_adjust(left=0.02, bottom=0.02, right=0.98, top=0.98)
    self.projections_layout.addWidget(get_figure_widget(fig))
    self.umap_hot = False
    self.clear_button = QPushButton("Clear")
    self.projections_layout.addWidget(self.clear_button)


    ## Browser
    # Dataset, speaker and utterance selection
    i = 0
    self.dataset_box = QComboBox()
    browser_layout.addWidget(QLabel("<b>Dataset</b>"), i, 0)
    browser_layout.addWidget(self.dataset_box, i + 1, 0)
    self.src_spk_box = QComboBox()
    browser_layout.addWidget(QLabel("<b>Source speaker</b>"), i, 1)
    browser_layout.addWidget(self.src_spk_box, i + 1, 1)
    self.utterance_box = QComboBox()
    browser_layout.addWidget(QLabel("<b>Utterance</b>"), i, 2)
    browser_layout.addWidget(self.utterance_box, i + 1, 2)
    self.browser_load_button = QPushButton("Load")
    browser_layout.addWidget(self.browser_load_button, i + 1, 3)
    i += 2

    # Random buttons
    self.random_dataset_button = QPushButton("Random")
    browser_layout.addWidget(self.random_dataset_button, i, 0)
    self.random_speaker_button = QPushButton("Random")
    browser_layout.addWidget(self.random_speaker_button, i, 1)
    self.random_utterance_button = QPushButton("Random")
    browser_layout.addWidget(self.random_utterance_button, i, 2)
    self.auto_next_checkbox = QCheckBox("Auto select next")
    self.auto_next_checkbox.setChecked(True)
    browser_layout.addWidget(self.auto_next_checkbox, i, 3)
    i += 1

    # Utterance box
    browser_layout.addWidget(QLabel("<b>Use source from:</b>"), i, 0)
    self.utterance_history = QComboBox()
    browser_layout.addWidget(self.utterance_history, i, 1, 1, 3)
    i += 1

    # Random & next utterance buttons
    self.browser_browse_button = QPushButton("Browse")
    browser_layout.addWidget(self.browser_browse_button, i, 0)
    self.record_button = QPushButton("Record")
    browser_layout.addWidget(self.record_button, i, 1)
    self.play_button = QPushButton("Play")
    browser_layout.addWidget(self.play_button, i, 2)
    self.stop_button = QPushButton("Stop")
    browser_layout.addWidget(self.stop_button, i, 3)
    i += 1


    # Model and audio output selection
    self.tgt_spk_box = QComboBox()
    browser_layout.addWidget(QLabel("<b>Target speaker</b>"), i, 0)
    browser_layout.addWidget(self.tgt_spk_box, i + 1, 0)

    self.audio_out_devices_cb=QComboBox()
    browser_layout.addWidget(QLabel("<b>Audio Output</b>"), i, 1)
    browser_layout.addWidget(self.audio_out_devices_cb, i + 1, 1)
    i += 2

    #Replay & Save Audio
    browser_layout.addWidget(QLabel("<b>Toolbox Output:</b>"), i, 0)
    self.wavs_cb = QComboBox()
    self.wavs_cb_model = QStringListModel()
    self.wavs_cb.setModel(self.wavs_cb_model)
    self.wavs_cb.setToolTip("Select one of the last generated wavs in this section for replaying or exporting")
    browser_layout.addWidget(self.wavs_cb, i, 1)
    self.replay_wav_button = QPushButton("Replay")
    self.replay_wav_button.setToolTip("Replay last generated vocoder")
    browser_layout.addWidget(self.replay_wav_button, i, 2)
    self.export_wav_button = QPushButton("Export")
    self.export_wav_button.setToolTip("Save last generated vocoder audio in filesystem as a wav file")
    browser_layout.addWidget(self.export_wav_button, i, 3)
    i += 1


    ## Embed & spectrograms
    vis_layout.addStretch()

    gridspec_kw = {"width_ratios": [1]}
    fig, cur_ax = plt.subplots(
      1, 1, figsize=(5, 2), gridspec_kw=gridspec_kw
    )
    fig.subplots_adjust(left=0, bottom=0.1, right=1, top=0.8)
    self.cur_ax_widget = FigureWidget(fig, cur_ax)
    vis_layout.addWidget(self.cur_ax_widget)

    fig, gen_ax = plt.subplots(
      1, 1, figsize=(5, 2), gridspec_kw=gridspec_kw
    )
    fig.subplots_adjust(left=0, bottom=0.1, right=1, top=0.8)
    self.gen_ax_widget = FigureWidget(fig, gen_ax)
    vis_layout.addWidget(self.gen_ax_widget)

    # for ax in self.cur_ax_widget.axis.tolist() + self.gen_ax_widget.axis.tolist():
    for ax in [self.cur_ax_widget.axis, self.gen_ax_widget.axis]:
      ax.set_facecolor("#F0F0F0")
      for side in ["top", "right", "bottom", "left"]:
        ax.spines[side].set_visible(False)


    ## Generation
    layout = QHBoxLayout()
    self.generate_button = QPushButton("Synthesize and vocode")
    layout.addWidget(self.generate_button)
    self.synthesize_button = QPushButton("Synthesize only")
    layout.addWidget(self.synthesize_button)
    self.vocode_button = QPushButton("Vocode only")
    layout.addWidget(self.vocode_button)
    gen_layout.addLayout(layout)

    layout_seed = QGridLayout()
    self.random_seed_checkbox = QCheckBox("Random seed:")
    self.random_seed_checkbox.setToolTip("When checked, makes the synthesizer and vocoder deterministic.")
    layout_seed.addWidget(self.random_seed_checkbox, 0, 0)
    self.seed_textbox = QLineEdit()
    self.seed_textbox.setMaximumWidth(80)
    layout_seed.addWidget(self.seed_textbox, 0, 1)
    gen_layout.addLayout(layout_seed)

    self.loading_bar = QProgressBar()
    gen_layout.addWidget(self.loading_bar)

    self.log_window = QLabel()
    self.log_window.setAlignment(Qt.AlignBottom | Qt.AlignLeft)
    gen_layout.addWidget(self.log_window)
    self.logs = []
    gen_layout.addStretch()


    ## Set the size of the window and of the elements
    max_size = self.screen().availableGeometry().size() * 0.7
    self.resize(max_size)

    ## Finalize the display
    self.reset_interface()
    self.show()
Пример #8
0
    #get our data
    url = "http://country.io/names.json"
    response = urllib.request.urlopen(url)
    data = json.loads(response.read().decode('utf-8'))

    #Format and sort the data
    data_list = list(data.values())
    data_list.sort()

    #Set up the application window
    app = QGuiApplication(sys.argv)
    view = QQuickView()
    view.setResizeMode(QQuickView.SizeRootObjectToView)

    #Expose the list to the Qml code
    my_model = QStringListModel()
    my_model.setStringList(data_list)
    view.rootContext().setContextProperty("myModel",my_model)

     #Load the QML file
    qml_file = os.path.join(os.path.dirname(__file__),"view.qml")
    view.setSource(QUrl.fromLocalFile(os.path.abspath(qml_file)))

         #Show the window
    if view.status() == QQuickView.Error:
       sys.exit(-1)
    view.show()

     #execute and cleanup
    app.exec_()
    del view
Пример #9
0
class AppViewModel(QObject):
    #select_line_changed=Signal(int)
    #select_point_changed=Signal(int)

    #  当前数据列表的值
    #currentLineListModelChanged=Signal()
    # 当前选中项
    #tableModelSelectIndexChanged=Signal()
    def __init__(self):
        QObject.__init__(self)

        self._tableModel = DHLTableModel()
        #self._slectionModel=self.
        #self._currentList=None  # type: QStringListModel
        self._channelCount = 0  # type: int
        self._active_channel = 0  # type: int
        self._figure = None  # type: Figure
        #self._tableModelSelectIndex=0 #

        self._acqs = []  # type: typing.List[ismrmrd.Acquisition]

        # 当前行/当前通道原始数据
        self._currentLineData = None  # type: np.array

        # 当前行用于渲染的数据
        self._currentLineListModel = QStringListModel(
        )  # type: QStringListModel
        #self._currentLineListModel.setStringList(['1','2','3'])

        #self.channelCountChanged.connect(self.safe_update_list_model)
        #self.currentChannelIndexChanged.connect(self.safe_update_list_model)

        self._canvas = None  # type: FigureCanvas
        self._figure = None  # type: Figure
        self._axes = None

        self._tableview = None  # type: QTableView

        self._selectionModel = None  # type: QItemSelectionModel

        self._listview = None  # type: QListView
        self._listViewSelectionModel = None  # type: QItemSelectionModel
        self._tableModelSelectIndex = 0  # ?
        self.stop_update_whole_view = False  # global backend data fix in progress
        self.stop_update_list_data = False

        pass

    @property
    def tableModel(self):
        return self._tableModel
        pass

    # figure
    def update_canvas(self, canvas):
        # if self._figure != figure:
        #     self._figure=figure
        #     self.update_view()
        #     pass
        self._canvas = canvas
        self._figure = self._canvas.figure
        self._axes = self._figure.subplots(2, 2, sharex='all')
        pass

    def update_tableview(self, tableview: QTableView):
        self._tableview = tableview
        self._tableview.setModel(self._tableModel)
        self._selectionModel = self._tableview.selectionModel()

        self._selectionModel.currentRowChanged.connect(
            self.on_tableview_currentRowChanged)

        pass

    def update_listview(self, listView: QListView):
        self._listview = listView
        self._listview.setModel(self._currentLineListModel)
        self._listViewSelectionModel = self._listview.selectionModel()
        self._listViewSelectionModel.currentRowChanged.connect(
            self.on_listview_point_select)
        pass

    def on_tableview_currentRowChanged(self, current: QModelIndex,
                                       previous: QModelIndex):
        if current.isValid():
            row = current.row()
            self._on_currentListDataChanged(self._acqs[row])
            pass
        pass

    def on_listview_point_select(self, current: QModelIndex,
                                 previous: QModelIndex):
        if current.isValid():
            row = current.row()
            print(rf'some point be selected {row}')
            #todo sync with four axes and right list?
            #save to local ?
            #self._on_currentListDataChanged(self._acqs[row])
            pass
        pass

    def _on_currentListDataChanged(self, newAcq: ismrmrd.Acquisition):
        if self._currentLineData is not newAcq.data:
            self._currentLineData = newAcq.data
            header = newAcq.getHead()  # type: ismrmrd.AcquisitionHeader
            #channelNum=getattr(header, 'active_channels')
            channelNum = header.active_channels

            with self.stop_update_scope():
                old_active_channel = self._active_channel
                self.on_channelCountChanged(channelNum)
                if old_active_channel < channelNum:
                    #self.on_active_channel_changed(old_active_channel)
                    self._active_channel = old_active_channel
                    pass

            #self.update_view()
            #how about active channel
        pass

    #--begin-- active channel
    activeChannelChangedSignal = Signal(int)  # use to notify ui?

    @Slot(int)
    def activeChannelChangeSlot(self, new_active_channel: int):
        self.on_active_channel_changed(new_active_channel)
        pass

    def on_active_channel_changed(self, new_active_channel: int):
        if not self._active_channel == new_active_channel and new_active_channel < self._channelCount:
            self._active_channel = new_active_channel
            self.activeChannelChangedSignal.emit(new_active_channel)
            #self.safe_update_list_model()
            self.update_view()
            pass
        pass

    @Slot(int)
    def SetActiveChannel(self, new_active_channel: int):
        self.on_active_channel_changed(new_active_channel)
        pass

    #--end-- active channel

    channelCountChangedSignal = Signal(int)

    def on_channelCountChanged(self, newChannelNum: int):
        if newChannelNum != self._channelCount:
            self._channelCount = newChannelNum
            self.channelCountChangedSignal.emit(newChannelNum)
        pass

    def open_file(self, file_path: str):

        dataset = ismrmrd.Dataset(file_path)
        self._acqs = []
        for i in range(dataset.number_of_acquisitions()):
            self._acqs.append(dataset.read_acquisition(i))

        with self.stop_update_scope():
            self._tableModel.reset_dhls(self._acqs)
        #self.update_view()
        pass

    @contextlib.contextmanager
    def stop_update_scope(self):
        self.stop_update_whole_view = True
        yield
        self.stop_update_whole_view = False
        self.update_view()

    def update_view(self):
        """
            1. 更新绘图面板
            2. 更新数据列表

        :return:
        """

        if self.stop_update_whole_view:
            return

        if self._figure == None:
            print(rf'_figure is None')
            return

        if self._channelCount is None or self._channelCount < 0:
            print(rf'channel count less than 0: {self._channelCount}')
            return
            pass

        if self.tableModel == None:
            print(rf'table model is None')
            return
            pass

        if self._tableModelSelectIndex < 0 or self._tableModelSelectIndex > self.tableModel.rowCount(
        ):
            print(
                rf'table model select index out of range, tableModelSelectIndex:{ self._tableModelSelectIndex}, tableModelRowCount:{self.tableModel.rowCount()}'
            )
            return
            pass

        if self._acqs is None:
            print(rf'dls is None')
            return
            pass

        # self.pull_list_value()
        # self.draw_impl()

        self.safe_update_list_model()

        self.safe_draw_matplotlib()

        pass

    # @contextlib.contextmanager
    # def update_list_model_paritial_state(self):
    #     self.stop_update_list_data=True
    #     yield
    #     self.stop_update_list_data=False
    #     self.safe_update_list_model()

    def safe_update_list_model(self):
        #if not self.stop_update_list_data:
        acq = self._acqs[self._tableModelSelectIndex]
        self._currentLineData = acq.data[
            self._active_channel - 1, :]  # type: typing.List[np.complex64]
        #self._currentLineListModel.clearItemData()
        self._currentLineListModel.setStringList(
            [rf'{c.real}, {c.imag}' for c in self._currentLineData])
        pass

    @Slot()
    def safe_draw_matplotlib(self):
        axes = self._axes  # type: typing.Tuple[typing.Tuple[Axes, Axes],typing.Tuple[Axes, Axes]]
        (ax_real, ax_img), (ax_mag, ax_phase) = axes

        ax_real.clear()
        ax_real.set_title('Real')
        ax_real.plot(np.real(self._currentLineData))
        #ax_real.plot([1,2,3,4,5])
        ax_img.clear()
        ax_img.set_title('Image')
        ax_img.plot(np.imag(self._currentLineData))

        ax_mag.clear()
        ax_mag.set_title('Mag')
        ax_mag.plot(np.abs(self._currentLineData))

        #self._figure.show()
        ax_phase.clear()
        ax_phase.set_title('Phase')
        ax_phase.plot(np.angle(self._currentLineData))
        #self._figure.canvas
        #self._canvas.update()
        #self._figure.tight_layout()
        #self._canvas.resizeEvent()
        dpi = 100
        #self._canvas.setFixedSize(self._canvas.parent().size())
        self._figure.set_size_inches(self._canvas.width() / dpi,
                                     self._canvas.height() / dpi)
        self._figure.set_dpi(dpi)
        self._figure.tight_layout()
        self._canvas.draw_idle()

        pass

    pass
Пример #10
0
    def __init__(self, parent=None):
        AbstractOperationDetails.__init__(self, parent)
        self.name = "Dividend"
        self.operation_type = LedgerTransaction.Dividend
        self.combo_model = None

        self.date_label = QLabel(self)
        self.ex_date_label = QLabel(self)
        self.number_label = QLabel(self)
        self.type_label = QLabel(self)
        self.account_label = QLabel(self)
        self.symbol_label = QLabel(self)
        self.amount_label = QLabel(self)
        self.price_label = QLabel(self)
        self.tax_label = QLabel(self)
        self.comment_label = QLabel(self)

        self.main_label.setText(self.tr("Dividend"))
        self.date_label.setText(self.tr("Date/Time"))
        self.ex_date_label.setText(self.tr("Ex-Date"))
        self.type_label.setText(self.tr("Type"))
        self.number_label.setText(self.tr("#"))
        self.account_label.setText(self.tr("Account"))
        self.symbol_label.setText(self.tr("Asset"))
        self.amount_label.setText(self.tr("Dividend"))
        self.price_label.setText(self.tr("Price"))
        self.tax_label.setText(self.tr("Tax"))
        self.comment_label.setText(self.tr("Note"))

        self.timestamp_editor = QDateTimeEdit(self)
        self.timestamp_editor.setCalendarPopup(True)
        self.timestamp_editor.setTimeSpec(Qt.UTC)
        self.timestamp_editor.setFixedWidth(self.timestamp_editor.fontMetrics().horizontalAdvance("00/00/0000 00:00:00") * 1.25)
        self.timestamp_editor.setDisplayFormat("dd/MM/yyyy hh:mm:ss")
        self.ex_date_editor = QDateEdit(self)
        self.ex_date_editor.setCalendarPopup(True)
        self.ex_date_editor.setTimeSpec(Qt.UTC)
        self.ex_date_editor.setFixedWidth(self.ex_date_editor.fontMetrics().horizontalAdvance("00/00/0000") * 1.5)
        self.ex_date_editor.setDisplayFormat("dd/MM/yyyy")
        self.type = QComboBox(self)
        self.account_widget = AccountSelector(self)
        self.asset_widget = AssetSelector(self)
        self.dividend_edit = QLineEdit(self)
        self.dividend_edit.setAlignment(Qt.AlignRight)
        self.price_edit = QLineEdit(self)
        self.price_edit.setAlignment(Qt.AlignRight)
        self.price_edit.setReadOnly(True)
        self.tax_edit = QLineEdit(self)
        self.tax_edit.setAlignment(Qt.AlignRight)
        self.number = QLineEdit(self)
        self.comment = QLineEdit(self)

        self.layout.addWidget(self.date_label, 1, 0, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.account_label, 2, 0, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.symbol_label, 3, 0, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.comment_label, 4, 0, 1, 1, Qt.AlignLeft)

        self.layout.addWidget(self.timestamp_editor, 1, 1, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.account_widget, 2, 1, 1, 4)
        self.layout.addWidget(self.asset_widget, 3, 1, 1, 4)
        self.layout.addWidget(self.comment, 4, 1, 1, 8)

        self.layout.addWidget(self.ex_date_label, 1, 2, 1, 1, Qt.AlignRight)
        self.layout.addWidget(self.ex_date_editor, 1, 3, 1, 1, Qt.AlignLeft)

        self.layout.addWidget(self.type_label, 1, 5, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.amount_label, 2, 5, 1, 1, Qt.AlignRight)
        self.layout.addWidget(self.tax_label, 3, 5, 1, 1, Qt.AlignRight)

        self.layout.addWidget(self.type, 1, 6, 1, 1)
        self.layout.addWidget(self.dividend_edit, 2, 6, 1, 1)
        self.layout.addWidget(self.tax_edit, 3, 6, 1, 1)

        self.layout.addWidget(self.number_label, 1, 7, 1, 1, Qt.AlignRight)
        self.layout.addWidget(self.price_label, 2, 7, 1, 1, Qt.AlignRight)

        self.layout.addWidget(self.number, 1, 8, 1, 1)
        self.layout.addWidget(self.price_edit, 2, 8, 1, 1)

        self.layout.addWidget(self.commit_button, 0, 9, 1, 1)
        self.layout.addWidget(self.revert_button, 0, 10, 1, 1)

        self.layout.addItem(self.verticalSpacer, 5, 0, 1, 1)
        self.layout.addItem(self.horizontalSpacer, 1, 8, 1, 1)

        super()._init_db("dividends")
        self.combo_model = QStringListModel([self.tr("N/A"),
                                             self.tr("Dividend"),
                                             self.tr("Bond Interest"),
                                             self.tr("Stock Dividend")])
        self.type.setModel(self.combo_model)

        self.mapper.setItemDelegate(DividendWidgetDelegate(self.mapper))

        self.account_widget.changed.connect(self.mapper.submit)
        self.asset_widget.changed.connect(self.assetChanged)
        self.type.currentIndexChanged.connect(self.typeChanged)
        self.timestamp_editor.dateTimeChanged.connect(self.refreshAssetPrice)

        self.mapper.addMapping(self.timestamp_editor, self.model.fieldIndex("timestamp"))
        self.mapper.addMapping(self.ex_date_editor, self.model.fieldIndex("ex_date"))
        self.mapper.addMapping(self.account_widget, self.model.fieldIndex("account_id"))
        self.mapper.addMapping(self.asset_widget, self.model.fieldIndex("asset_id"))
        self.mapper.addMapping(self.type, self.model.fieldIndex("type"), QByteArray().setRawData("currentIndex", 12))
        self.mapper.addMapping(self.number, self.model.fieldIndex("number"))
        self.mapper.addMapping(self.dividend_edit, self.model.fieldIndex("amount"))
        self.mapper.addMapping(self.tax_edit, self.model.fieldIndex("tax"))
        self.mapper.addMapping(self.comment, self.model.fieldIndex("note"))

        self.model.select()
    def __init__(self, parent=None):
        AbstractOperationDetails.__init__(self, parent)
        self.name = "Corporate action"
        self.combo_model = None

        self.date_label = QLabel(self)
        self.account_label = QLabel(self)
        self.type_label = QLabel(self)
        self.number_label = QLabel(self)
        self.before_label = QLabel(self)
        self.asset_b_label = QLabel(self)
        self.qty_b_label = QLabel(self)
        self.after_label = QLabel(self)
        self.asset_a_label = QLabel(self)
        self.qty_a_label = QLabel(self)
        self.ratio_label = QLabel(self)
        self.comment_label = QLabel(self)
        self.arrow_asset = QLabel(self)
        self.arrow_amount = QLabel(self)

        self.main_label.setText(self.tr("Corporate Action"))
        self.date_label.setText(self.tr("Date/Time"))
        self.account_label.setText(self.tr("Account"))
        self.type_label.setText(self.tr("Type"))
        self.number_label.setText(self.tr("#"))
        self.asset_b_label.setText(self.tr("Asset"))
        self.qty_b_label.setText(self.tr("Qty"))
        self.asset_a_label.setText(self.tr("Asset"))
        self.qty_a_label.setText(self.tr("Qty"))
        self.ratio_label.setText(self.tr("% of basis"))
        self.comment_label.setText(self.tr("Note"))
        self.arrow_asset.setText(" ➜ ")
        self.arrow_amount.setText(" ➜ ")

        self.timestamp_editor = QDateTimeEdit(self)
        self.timestamp_editor.setCalendarPopup(True)
        self.timestamp_editor.setTimeSpec(Qt.UTC)
        self.timestamp_editor.setFixedWidth(
            self.timestamp_editor.fontMetrics().horizontalAdvance(
                "00/00/0000 00:00:00") * 1.25)
        self.timestamp_editor.setDisplayFormat("dd/MM/yyyy hh:mm:ss")
        self.type = QComboBox(self)
        self.account_widget = AccountSelector(self)
        self.asset_b_widget = AssetSelector(self)
        self.asset_a_widget = AssetSelector(self)
        self.qty_b_edit = QLineEdit(self)
        self.qty_a_edit = QLineEdit(self)
        self.ratio_edit = QLineEdit(self)
        self.number = QLineEdit(self)
        self.comment = QLineEdit(self)

        self.layout.addWidget(self.date_label, 1, 0, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.type_label, 2, 0, 1, 1, Qt.AlignLeft)
        self.layout.addWidget(self.number_label, 3, 0, 1, 1, Qt.AlignRight)
        self.layout.addWidget(self.comment_label, 5, 0, 1, 6, Qt.AlignLeft)

        self.layout.addWidget(self.timestamp_editor, 1, 1, 1, 1)
        self.layout.addWidget(self.type, 2, 1, 1, 1)
        self.layout.addWidget(self.number, 3, 1, 1, 1)
        self.layout.addWidget(self.comment, 5, 1, 1, 6)

        self.layout.addWidget(self.account_label, 1, 2, 1, 1, Qt.AlignRight)
        self.layout.addWidget(self.asset_b_label, 2, 2, 1, 1, Qt.AlignRight)
        self.layout.addWidget(self.qty_b_label, 3, 2, 1, 1, Qt.AlignRight)

        self.layout.addWidget(self.account_widget, 1, 3, 1, 4)
        self.layout.addWidget(self.asset_b_widget, 2, 3, 1, 1)
        self.layout.addWidget(self.qty_b_edit, 3, 3, 1, 1)

        self.layout.addWidget(self.arrow_asset, 2, 4, 1, 1)
        self.layout.addWidget(self.arrow_amount, 3, 4, 1, 1)

        self.layout.addWidget(self.asset_a_label, 2, 5, 1, 1, Qt.AlignRight)
        self.layout.addWidget(self.qty_a_label, 3, 5, 1, 1, Qt.AlignRight)
        self.layout.addWidget(self.ratio_label, 4, 5, 1, 1, Qt.AlignRight)

        self.layout.addWidget(self.asset_a_widget, 2, 6, 1, 1)
        self.layout.addWidget(self.qty_a_edit, 3, 6, 1, 1)
        self.layout.addWidget(self.ratio_edit, 4, 6, 1, 1)

        self.layout.addWidget(self.commit_button, 0, 8, 1, 1)
        self.layout.addWidget(self.revert_button, 0, 9, 1, 1)

        self.layout.addItem(self.verticalSpacer, 6, 0, 1, 1)
        self.layout.addItem(self.horizontalSpacer, 1, 7, 1, 1)

        super()._init_db("corp_actions")
        self.combo_model = QStringListModel([
            self.tr("N/A"),
            self.tr("Merger"),
            self.tr("Spin-Off"),
            self.tr("Symbol change"),
            self.tr("Split"),
            self.tr("Stock dividend")
        ])
        self.type.setModel(self.combo_model)

        self.mapper.setItemDelegate(CorporateActionWidgetDelegate(self.mapper))

        self.account_widget.changed.connect(self.mapper.submit)
        self.asset_b_widget.changed.connect(self.mapper.submit)
        self.asset_a_widget.changed.connect(self.mapper.submit)

        self.mapper.addMapping(self.timestamp_editor,
                               self.model.fieldIndex("timestamp"))
        self.mapper.addMapping(self.account_widget,
                               self.model.fieldIndex("account_id"))
        self.mapper.addMapping(self.asset_b_widget,
                               self.model.fieldIndex("asset_id"))
        self.mapper.addMapping(self.asset_a_widget,
                               self.model.fieldIndex("asset_id_new"))
        self.mapper.addMapping(self.number, self.model.fieldIndex("number"))
        self.mapper.addMapping(self.qty_b_edit, self.model.fieldIndex("qty"))
        self.mapper.addMapping(self.qty_a_edit,
                               self.model.fieldIndex("qty_new"))
        self.mapper.addMapping(self.ratio_edit,
                               self.model.fieldIndex("basis_ratio"))
        self.mapper.addMapping(self.comment, self.model.fieldIndex("note"))
        self.mapper.addMapping(self.type, self.model.fieldIndex("type"),
                               QByteArray().setRawData("currentIndex", 12))

        self.model.select()
Пример #12
0
 def __init__(self, parent=None):
     super().__init__(parent)
     self._model = QStringListModel()