Source code for spinetoolbox.widgets.import_preview_window

######################################################################################################################
# Copyright (C) 2017-2020 Spine project consortium
# This file is part of Spine Toolbox.
# Spine Toolbox is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General
# Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
# any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
# Public License for more details. You should have received a copy of the GNU Lesser General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
######################################################################################################################

"""
Contains ImportPreviewWindow class.

:authors: P. Savolainen (VTT), A. Soininen (VTT), P. Vennström (VTT)
:date:   10.6.2019
"""

import json
from PySide2.QtCore import Qt, Signal
from PySide2.QtGui import QGuiApplication
from PySide2.QtWidgets import QMainWindow, QDialogButtonBox, QSplitter, QFileDialog
from ..spine_io.connection_manager import ConnectionManager
from .import_preview_widget import ImportPreviewWidget


[docs]class ImportPreviewWindow(QMainWindow): """A QMainWindow to let users define Mappings for an Importer item. Args: importer (spinetoolbox.project_items.importer.importer.Importer): Project item that owns this preview window filepath (str): Importee path connector (SourceConnection): Asynchronous data reader settings (dict): Default mapping specification toolbox (QMainWindow): ToolboxUI class """
[docs] settings_updated = Signal(dict)
[docs] connection_failed = Signal(str)
def __init__(self, importer, filepath, connector, settings, toolbox): from ..ui.import_preview_window import Ui_MainWindow super().__init__(parent=toolbox, flags=Qt.Window) self._importer = importer self._toolbox = toolbox self._qsettings = self._toolbox.qsettings() self._connection_manager = ConnectionManager(connector) self._connection_manager.source = filepath self._ui = Ui_MainWindow() self._ui.setupUi(self) self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowTitle("Import Editor -- {} --".format(importer.name)) self._preview_widget = ImportPreviewWidget(self._connection_manager, parent=self) self._preview_widget.use_settings(settings) self._ui.centralwidget.layout().insertWidget(0, self._preview_widget) self.settings_group = "mappingPreviewWindow" self.restore_ui() self._ui.buttonBox.button(QDialogButtonBox.Ok).clicked.connect(self.apply_and_close) self._ui.buttonBox.button(QDialogButtonBox.Cancel).clicked.connect(self.close) self._ui.actionExportMappings.triggered.connect(self.export_mapping_to_file) self._ui.actionImportMappings.triggered.connect(self.import_mapping_from_file) self._ui.actionClose.triggered.connect(self.close) self._connection_manager.connectionReady.connect(self.show) self._connection_manager.connectionFailed.connect(self.connection_failed.emit)
[docs] def import_mapping_from_file(self): """Imports mapping spec from a user selected .json file to the preview window.""" start_dir = self._toolbox.project().project_dir # noinspection PyCallByClass filename = QFileDialog.getOpenFileName( self, "Import mapping specification", start_dir, "Mapping options (*.json)" ) if not filename[0]: return with open(filename[0]) as file_p: try: settings = json.load(file_p) except json.JSONDecodeError: self._ui.statusbar.showMessage(f"Could not open {filename[0]}", 10000) return expected_options = ("table_mappings", "table_types", "table_row_types", "table_options", "selected_tables") if not isinstance(settings, dict) or not any(key in expected_options for key in settings.keys()): self._ui.statusbar.showMessage(f"{filename[0]} does not contain mapping options", 10000) self._preview_widget.use_settings(settings) self._ui.statusbar.showMessage(f"Mapping loaded from {filename[0]}", 10000)
[docs] def export_mapping_to_file(self): """Exports all mapping specs in current preview window to .json file.""" start_dir = self._toolbox.project().project_dir # noinspection PyCallByClass filename = QFileDialog.getSaveFileName( self, "Export mapping spec to a file", start_dir, "Mapping options (*.json)" ) if not filename[0]: return with open(filename[0], 'w') as file_p: settings = self._preview_widget.get_settings_dict() json.dump(settings, file_p) self._ui.statusbar.showMessage(f"Mapping saved to: {filename[0]}", 10000)
[docs] def apply_and_close(self): """Apply changes to mappings and close preview window.""" settings = self._preview_widget.get_settings_dict() self.settings_updated.emit(settings) self.close()
[docs] def start_ui(self): self._connection_manager.init_connection()
[docs] def restore_ui(self): """Restore UI state from previous session.""" qsettings = self._qsettings qsettings.beginGroup(self.settings_group) window_size = qsettings.value("windowSize") window_pos = qsettings.value("windowPosition") window_state = qsettings.value("windowState") window_maximized = qsettings.value("windowMaximized", defaultValue='false') n_screens = qsettings.value("n_screens", defaultValue=1) splitter_state = {} for splitter in self.findChildren(QSplitter): splitter_state[splitter] = qsettings.value(splitter.objectName() + "_splitterState") qsettings.endGroup() if window_size: self.resize(window_size) if window_pos: self.move(window_pos) if window_state: self.restoreState(window_state, version=1) # Toolbar and dockWidget positions if window_maximized == 'true': self.setWindowState(Qt.WindowMaximized) for splitter, state in splitter_state.items(): if state: splitter.restoreState(state) # noinspection PyArgumentList if len(QGuiApplication.screens()) < int(n_screens): # There are less screens available now than on previous application startup self.move(0, 0) # Move this widget to primary screen position (0,0)
[docs] def closeEvent(self, event=None): """Handle close window. Args: event (QEvent): Closing event if 'X' is clicked. """ qsettings = self._qsettings qsettings.beginGroup(self.settings_group) for splitter in self.findChildren(QSplitter): qsettings.setValue(splitter.objectName() + "_splitterState", splitter.saveState()) qsettings.setValue("windowSize", self.size()) qsettings.setValue("windowPosition", self.pos()) qsettings.setValue("windowState", self.saveState(version=1)) if self.windowState() == Qt.WindowMaximized: qsettings.setValue("windowMaximized", True) else: qsettings.setValue("windowMaximized", False) qsettings.endGroup() if event: event.accept()