Пример #1
0
class PolymaskGeneratorWindow(QWidget):
    def __init__(self, splines=[]):
        super().__init__()
        self.setMinimumSize(1628, 742)  # 1600 plus margins
        self.setMaximumSize(1628, 742)
        self.setGeometry(100, 100, 1628, 742)

        layout = QGridLayout(self)
        self.setLayout(layout)
        self.setWindowTitle("Polymask Generator")

        panelStyleSheet = """
        .QWidget {
            border: 2px solid black;
            }
        """

        right_panel = QSplitter(self)
        right_panel.setChildrenCollapsible(False)

        generate_panel = QWidget(right_panel)
        generate_panel.setStyleSheet(panelStyleSheet)
        generate_layout = QVBoxLayout(generate_panel)
        generate_panel.setLayout(generate_layout)

        control_polygon_panel = QWidget(right_panel)
        control_polygon_panel.setStyleSheet(panelStyleSheet)
        control_polygon_layout = QVBoxLayout(control_polygon_panel)
        control_polygon_panel.setLayout(control_polygon_layout)

        control_splines_panel = QWidget(right_panel)
        control_splines_panel.setStyleSheet(panelStyleSheet)
        control_splines_layout = QVBoxLayout(control_splines_panel)
        control_splines_panel.setLayout(control_splines_layout)

        saveButton = QPushButton("Save", right_panel)
        saveButton.clicked.connect(self.save)
        generate_layout.addWidget(saveButton)

        generateButton = QPushButton("Show filled polygons", right_panel)
        generateButton.clicked.connect(self.generateTriangles)
        generate_layout.addWidget(generateButton)

        backgroundButton = QPushButton("Select background image", right_panel)
        backgroundButton.clicked.connect(self.setBackground)
        generate_layout.addWidget(backgroundButton)

        colorGrid = QWidget(right_panel)
        colorGrid.setStyleSheet("""
        .QWidget {
            border: 0px solid black;
            }
        """)
        colorLayout = QGridLayout(colorGrid)
        colorLayout.setColumnStretch(1, 1)
        colorLayout.setSpacing(1)

        wnd = self
        splineColorButton = QPushButton("Set spline color", colorGrid)
        splineColorButton.clicked.connect(
            lambda: wnd.setSplineColor("splineColor"))
        colorLayout.addWidget(splineColorButton)
        splineColorButton = QPushButton("Set selected spline color", colorGrid)
        splineColorButton.clicked.connect(
            lambda: wnd.setSplineColor("selectedSplineColor"))
        colorLayout.addWidget(splineColorButton, 0, 1)
        splineColorButton = QPushButton("Set control point color", colorGrid)
        splineColorButton.clicked.connect(
            lambda: wnd.setSplineColor("CPColor"))
        colorLayout.addWidget(splineColorButton, 1, 0)
        splineColorButton = QPushButton("Set selected control point color",
                                        colorGrid)
        splineColorButton.clicked.connect(
            lambda: wnd.setSplineColor("selectedCPColor"))
        colorLayout.addWidget(splineColorButton, 1, 1)

        colorGrid.setLayout(colorLayout)
        generate_layout.addWidget(colorGrid)

        self.cp_list = QListWidget()
        self.cp_list.setFixedHeight(100)
        self.cp_list.currentItemChanged.connect(self.currentPointChanged)
        control_polygon_layout.addWidget(self.cp_list)

        addBeforeButton = QPushButton("Add Controlpoint before selected",
                                      right_panel)
        addBeforeButton.clicked.connect(self.addBefore)
        control_polygon_layout.addWidget(addBeforeButton)

        addAfterButton = QPushButton("Add Controlpoint after selected",
                                     right_panel)
        addAfterButton.clicked.connect(self.addAfter)
        control_polygon_layout.addWidget(addAfterButton)

        removeButton = QPushButton("Remove selected Controlpoint", right_panel)
        removeButton.clicked.connect(self.removeCurrent)
        control_polygon_layout.addWidget(removeButton)

        self.curve_list = QListWidget()
        self.curve_list.setFixedHeight(100)

        splines = self.set_control_points(splines)

        self.curve_list.currentItemChanged.connect(self.currentSplineChanged)
        control_splines_layout.addWidget(self.curve_list)

        addSplineButton = QPushButton("Add New Spline", right_panel)
        addSplineButton.clicked.connect(self.addSpline)
        control_splines_layout.addWidget(addSplineButton)

        removeSplineButton = QPushButton("Remove selected Spline", right_panel)
        removeSplineButton.clicked.connect(self.removeSpline)
        control_splines_layout.addWidget(removeSplineButton)

        right_panel.setOrientation(Qt.Vertical)
        right_panel.addWidget(generate_panel)
        right_panel.addWidget(control_polygon_panel)
        right_panel.addWidget(control_splines_panel)

        self.polymaskGenerator = PolymaskGenerator(self, self.winId(), splines,
                                                   self.dataChanged)
        layout.addWidget(self.polymaskGenerator)
        layout.setColumnStretch(0, 4)

        self.cp_list.setCurrentRow(0)
        self.curve_list.setCurrentRow(0)

        layout.addWidget(right_panel, 0, 1)
        layout.setColumnStretch(1, 1)

    def set_control_points(self, splines):
        self.cp_list.clear()
        self.curve_list.clear()
        if len(splines) == 0:
            controlPoints = [
                ar([-0.25, -0.25]),
                ar([-0.25, 0.25]),
                ar([0.25, 0.25]),
                ar([0.25, -0.25])
            ]

            splines = [controlPoints]

        idx = 0
        for npcp in splines[0]:
            cp = npcp.tolist()
            if len(cp) < 2:
                print("Error: controlPoint size less then 2")
                continue
            self.cp_list.addItem(self.pointToString(cp))
            idx += 1

        for idx in range(len(splines)):
            self.curve_list.addItem("Spline " + str(idx))

        return splines

    def pointToString(self, point):
        return "( " + "{:.4f}".format(point[0]) + ", " + "{:.4f}".format(
            point[1]) + " )"

    def save(self):
        if self.generateTriangles():
            self.saveFunction(self.polymaskGenerator.fill,
                              self.polymaskGenerator.splines)
            self.close()

    def addBefore(self):
        self.polymaskGenerator.addBefore(self.cp_list.currentRow())

    def addAfter(self):
        self.polymaskGenerator.addAfter(self.cp_list.currentRow())

    def removeCurrent(self):
        self.polymaskGenerator.removeCurrent(self.cp_list.currentRow())

    def generateTriangles(self):
        return self.polymaskGenerator.generateTriangles()

    def set(self, saveFunction, splines):
        self.saveFunction = saveFunction
        if len(splines) > 0:
            self.set_control_points(splines)
            self.polymaskGenerator.splines = splines

            self.cp_list.setCurrentRow(0)
            self.curve_list.setCurrentRow(0)

    def dataChanged(self, type, data):
        if type == PolymaskChangeEvent.SelectionChanged:
            if self.curve_list.currentRow() != data["s_idx"]:
                self.changeSpline(data["s_idx"])
            self.cp_list.setCurrentRow(data["idx"])
        elif type == PolymaskChangeEvent.ItemChanged:
            self.cp_list.item(data["idx"]).setText(
                self.pointToString(data["value"]))
        elif type == PolymaskChangeEvent.ItemAdded:
            self.cp_list.insertItem(data["idx"],
                                    self.pointToString(data["value"]))
        elif type == PolymaskChangeEvent.ItemRemoved:
            self.cp_list.takeItem(data["idx"])

    def changeSpline(self, idx):
        self.curve_list.setCurrentRow(idx)
        self.cp_list.clear()
        for s in self.polymaskGenerator.splines[idx]:
            self.cp_list.addItem(self.pointToString(s.tolist()))

    def currentPointChanged(self):
        self.polymaskGenerator.currentPointChanged(self.cp_list.currentRow())

    def closeEvent(self, event):
        self.saveFunction = None
        event.accept()

    def addSpline(self):
        points = [[-0.25, -0.25], [-0.25, 0.25], [0.25, 0.25], [0.25, -0.25]]
        self.curve_list.addItem("Spline " +
                                str(len(self.polymaskGenerator.splines)))
        self.polymaskGenerator.addSpline(points)

    def removeSpline(self):
        current = self.curve_list.currentRow()
        if current >= 0:
            self.curve_list.takeItem(current)
            self.polymaskGenerator.removeSpline(current,
                                                self.curve_list.currentRow())

    def currentSplineChanged(self):
        self.polymaskGenerator.currentSplineChanged(
            self.curve_list.currentRow())

    def setBackground(self):
        fname = QFileDialog.getOpenFileName(
            self, 'Select Background Image', "",
            "Image files(*.jpg *.png *.gif *.bmp);;All Files (*)")
        self.polymaskGenerator.setBackground(fname[0])

    def setSplineColor(self, obj):
        color = QColorDialog().getColor()
        self.polymaskGenerator.setSplineColor(obj, color.red(), color.green(),
                                              color.blue())
Пример #2
0
class SimulationGui(QMainWindow):
    """
    class for the graphical user interface
    """
    # TODO enable closing plot docks by right-clicking their name

    runSimulation = pyqtSignal()
    stopSimulation = pyqtSignal()
    playbackTimeChanged = pyqtSignal()
    regimeFinished = pyqtSignal()
    finishedRegimeBatch = pyqtSignal(bool)

    def __init__(self):
        # constructor of the base class
        QMainWindow.__init__(self)

        QCoreApplication.setOrganizationName("RST")
        QCoreApplication.setOrganizationDomain("https://tu-dresden.de/rst")
        QCoreApplication.setApplicationVersion(
            pkg_resources.require("PyMoskito")[0].version)
        QCoreApplication.setApplicationName(globals()["__package__"])

        # load settings
        self._settings = QSettings()
        self._read_settings()

        # initialize logger
        self._logger = logging.getLogger(self.__class__.__name__)

        # Create Simulation Backend
        self.guiProgress = None
        self.cmdProgress = None
        self.sim = SimulatorInteractor(self)
        self.runSimulation.connect(self.sim.run_simulation)
        self.stopSimulation.connect(self.sim.stop_simulation)
        self.sim.simulation_finalized.connect(self.new_simulation_data)
        self.currentDataset = None
        self.interpolator = None

        # sim setup viewer
        self.targetView = SimulatorView(self)
        self.targetView.setModel(self.sim.target_model)
        self.targetView.expanded.connect(self.target_view_changed)
        self.targetView.collapsed.connect(self.target_view_changed)

        # sim results viewer
        self.result_view = QTreeView()

        # the docking area allows to rearrange the user interface at runtime
        self.area = pg.dockarea.DockArea()

        # Window properties
        icon_size = QSize(25, 25)
        self.setCentralWidget(self.area)
        self.resize(1000, 700)
        self.setWindowTitle("PyMoskito")
        res_path = get_resource("mosquito.png")
        icon = QIcon(res_path)
        self.setWindowIcon(icon)

        # create docks
        self.propertyDock = pg.dockarea.Dock("Properties")
        self.animationDock = pg.dockarea.Dock("Animation")
        self.regimeDock = pg.dockarea.Dock("Regimes")
        self.dataDock = pg.dockarea.Dock("Data")
        self.logDock = pg.dockarea.Dock("Log")
        self.plotDockPlaceholder = pg.dockarea.Dock("Placeholder")

        # arrange docks
        self.area.addDock(self.animationDock, "right")
        self.area.addDock(self.regimeDock, "left", self.animationDock)
        self.area.addDock(self.propertyDock, "bottom", self.regimeDock)
        self.area.addDock(self.dataDock, "bottom", self.propertyDock)
        self.area.addDock(self.plotDockPlaceholder, "bottom",
                          self.animationDock)
        self.area.addDock(self.logDock, "bottom", self.dataDock)
        self.non_plotting_docks = list(self.area.findAll()[1].keys())

        # add widgets to the docks
        self.propertyDock.addWidget(self.targetView)

        if not vtk_available:
            self._logger.error(
                "loading vtk failed with:{}".format(vtk_error_msg))

        # check if there is a registered visualizer
        available_vis = get_registered_visualizers()
        self._logger.info("found visualizers: {}".format(
            [name for cls, name in available_vis]))
        if available_vis:
            # instantiate the first visualizer
            self._logger.info("loading visualizer '{}'".format(
                available_vis[0][1]))
            self.animationLayout = QVBoxLayout()

            if issubclass(available_vis[0][0], MplVisualizer):
                self.animationWidget = QWidget()
                self.visualizer = available_vis[0][0](self.animationWidget,
                                                      self.animationLayout)
                self.animationDock.addWidget(self.animationWidget)
            elif issubclass(available_vis[0][0], VtkVisualizer):
                if vtk_available:
                    # vtk window
                    self.animationFrame = QFrame()
                    self.vtkWidget = QVTKRenderWindowInteractor(
                        self.animationFrame)
                    self.animationLayout.addWidget(self.vtkWidget)
                    self.animationFrame.setLayout(self.animationLayout)
                    self.animationDock.addWidget(self.animationFrame)
                    self.vtk_renderer = vtkRenderer()
                    self.vtkWidget.GetRenderWindow().AddRenderer(
                        self.vtk_renderer)
                    self.visualizer = available_vis[0][0](self.vtk_renderer)
                    self.vtkWidget.Initialize()
                else:
                    self._logger.warning("visualizer depends on vtk which is "
                                         "not available on this system!")
            elif available_vis:
                raise NotImplementedError
        else:
            self.visualizer = None

        # regime window
        self.regime_list = QListWidget(self)
        self.regime_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.regimeDock.addWidget(self.regime_list)
        self.regime_list.itemDoubleClicked.connect(self.regime_dclicked)
        self._regimes = []
        self.regime_file_name = ""

        self.actDeleteRegimes = QAction(self.regime_list)
        self.actDeleteRegimes.setText("&Delete Selected Regimes")
        # TODO shortcut works always, not only with focus on the regime list
        # self.actDeleteRegimes.setShortcutContext(Qt.WindowShortcut)
        self.actDeleteRegimes.setShortcut(QKeySequence(Qt.Key_Delete))
        self.actDeleteRegimes.triggered.connect(self.remove_regime_items)

        self.actSave = QAction(self)
        self.actSave.setText('Save Results As')
        self.actSave.setIcon(QIcon(get_resource("save.png")))
        self.actSave.setDisabled(True)
        self.actSave.setShortcut(QKeySequence.Save)
        self.actSave.triggered.connect(self.export_simulation_data)

        self.actLoadRegimes = QAction(self)
        self.actLoadRegimes.setText("Load Regimes from File")
        self.actLoadRegimes.setIcon(QIcon(get_resource("load.png")))
        self.actLoadRegimes.setDisabled(False)
        self.actLoadRegimes.setShortcut(QKeySequence.Open)
        self.actLoadRegimes.triggered.connect(self.load_regime_dialog)

        self.actExitOnBatchCompletion = QAction(self)
        self.actExitOnBatchCompletion.setText("&Exit On Batch Completion")
        self.actExitOnBatchCompletion.setCheckable(True)
        self.actExitOnBatchCompletion.setChecked(
            self._settings.value("control/exit_on_batch_completion") == "True")
        self.actExitOnBatchCompletion.changed.connect(
            self.update_exit_on_batch_completion_setting)

        # regime management
        self.runningBatch = False
        self._current_regime_index = None
        self._current_regime_name = None
        self._regimes = []

        self.regimeFinished.connect(self.run_next_regime)
        self.finishedRegimeBatch.connect(self.regime_batch_finished)

        # data window
        self.dataList = QListWidget(self)
        self.dataDock.addWidget(self.dataList)
        self.dataList.itemDoubleClicked.connect(self.create_plot)

        # actions for simulation control
        self.actSimulateCurrent = QAction(self)
        self.actSimulateCurrent.setText("&Simulate Current Regime")
        self.actSimulateCurrent.setIcon(QIcon(get_resource("simulate.png")))
        self.actSimulateCurrent.setShortcut(QKeySequence("F5"))
        self.actSimulateCurrent.triggered.connect(self.start_simulation)

        self.actSimulateAll = QAction(self)
        self.actSimulateAll.setText("Simulate &All Regimes")
        self.actSimulateAll.setIcon(QIcon(get_resource("execute_regimes.png")))
        self.actSimulateAll.setShortcut(QKeySequence("F6"))
        self.actSimulateAll.setDisabled(True)
        self.actSimulateAll.triggered.connect(self.start_regime_execution)

        # actions for animation control
        self.actAutoPlay = QAction(self)
        self.actAutoPlay.setText("&Autoplay Simulation")
        self.actAutoPlay.setCheckable(True)
        self.actAutoPlay.setChecked(
            self._settings.value("control/autoplay_animation") == "True")
        self.actAutoPlay.changed.connect(self.update_autoplay_setting)

        self.actPlayPause = QAction(self)
        self.actPlayPause.setText("Play Animation")
        self.actPlayPause.setIcon(QIcon(get_resource("play.png")))
        self.actPlayPause.setDisabled(True)
        self.actPlayPause.setShortcut(QKeySequence(Qt.Key_Space))
        self.actPlayPause.triggered.connect(self.play_animation)

        self.actStop = QAction(self)
        self.actStop.setText("Stop")
        self.actStop.setIcon(QIcon(get_resource("stop.png")))
        self.actStop.setDisabled(True)
        self.actStop.triggered.connect(self.stop_animation)

        self.actSlow = QAction(self)
        self.actSlow.setText("Slowest")
        self.actSlow.setIcon(QIcon(get_resource("slow.png")))
        self.actSlow.setDisabled(False)
        self.actSlow.triggered.connect(self.set_slowest_playback_speed)

        self.actFast = QAction(self)
        self.actFast.setText("Fastest")
        self.actFast.setIcon(QIcon(get_resource("fast.png")))
        self.actFast.setDisabled(False)
        self.actFast.triggered.connect(self.set_fastest_playback_speed)

        self.speedControl = QSlider(Qt.Horizontal, self)
        self.speedControl.setMaximumSize(200, 25)
        self.speedControl.setTickPosition(QSlider.TicksBothSides)
        self.speedControl.setDisabled(False)
        self.speedControl.setMinimum(0)
        self.speedControl.setMaximum(12)
        self.speedControl.setValue(6)
        self.speedControl.setTickInterval(6)
        self.speedControl.setSingleStep(2)
        self.speedControl.setPageStep(3)
        self.speedControl.valueChanged.connect(self.update_playback_speed)

        self.timeSlider = QSlider(Qt.Horizontal, self)
        self.timeSlider.setMinimum(0)
        self.timeSliderRange = 1000
        self.timeSlider.setMaximum(self.timeSliderRange)
        self.timeSlider.setTickInterval(1)
        self.timeSlider.setTracking(True)
        self.timeSlider.setDisabled(True)
        self.timeSlider.valueChanged.connect(self.update_playback_time)

        self.playbackTime = .0
        self.playbackGain = 1
        self.currentStepSize = .0
        self.currentEndTime = .0
        self.playbackTimer = QTimer()
        self.playbackTimer.timeout.connect(self.increment_playback_time)
        self.playbackTimeChanged.connect(self.update_gui)
        self.playbackTimeout = 33  # in [ms] -> 30 fps

        self.actResetCamera = QAction(self)
        self.actResetCamera.setText("Reset Camera")
        self.actResetCamera.setIcon(QIcon(get_resource("reset_camera.png")))
        self.actResetCamera.setDisabled(True)
        if available_vis:
            self.actResetCamera.setEnabled(self.visualizer.can_reset_view)
        self.actResetCamera.triggered.connect(self.reset_camera_clicked)

        # postprocessing
        self.actPostprocessing = QAction(self)
        self.actPostprocessing.setText("Launch Postprocessor")
        self.actPostprocessing.setIcon(QIcon(get_resource("processing.png")))
        self.actPostprocessing.setDisabled(False)
        self.actPostprocessing.triggered.connect(self.postprocessing_clicked)
        self.actPostprocessing.setShortcut(QKeySequence("F7"))

        self.postprocessor = None

        # toolbar
        self.toolbarSim = QToolBar("Simulation")
        self.toolbarSim.setContextMenuPolicy(Qt.PreventContextMenu)
        self.toolbarSim.setMovable(False)
        self.toolbarSim.setIconSize(icon_size)
        self.addToolBar(self.toolbarSim)
        self.toolbarSim.addAction(self.actLoadRegimes)
        self.toolbarSim.addAction(self.actSave)
        self.toolbarSim.addSeparator()
        self.toolbarSim.addAction(self.actSimulateCurrent)
        self.toolbarSim.addAction(self.actSimulateAll)
        self.toolbarSim.addSeparator()
        self.toolbarSim.addAction(self.actPlayPause)
        self.toolbarSim.addAction(self.actStop)
        self.toolbarSim.addWidget(self.timeSlider)
        self.toolbarSim.addSeparator()
        self.toolbarSim.addAction(self.actSlow)
        self.toolbarSim.addWidget(self.speedControl)
        self.toolbarSim.addAction(self.actFast)
        self.toolbarSim.addSeparator()
        self.toolbarSim.addAction(self.actPostprocessing)
        self.toolbarSim.addAction(self.actResetCamera)
        self.postprocessor = None

        # log dock
        self.logBox = QPlainTextEdit(self)
        self.logBox.setReadOnly(True)
        self.logDock.addWidget(self.logBox)

        # init logger for logging box
        self.textLogger = PlainTextLogger(logging.INFO)
        self.textLogger.set_target_cb(self.logBox.appendPlainText)
        logging.getLogger().addHandler(self.textLogger)

        # menu bar
        fileMenu = self.menuBar().addMenu("&File")
        fileMenu.addAction(self.actLoadRegimes)
        fileMenu.addAction(self.actSave)
        fileMenu.addAction("&Quit", self.close)

        editMenu = self.menuBar().addMenu("&Edit")
        editMenu.addAction(self.actDeleteRegimes)

        simMenu = self.menuBar().addMenu("&Simulation")
        simMenu.addAction(self.actSimulateCurrent)
        simMenu.addAction(self.actSimulateAll)
        simMenu.addAction(self.actExitOnBatchCompletion)
        simMenu.addAction(self.actPostprocessing)

        animMenu = self.menuBar().addMenu("&Animation")
        animMenu.addAction(self.actPlayPause)
        animMenu.addAction("&Increase Playback Speed",
                           self.increment_playback_speed,
                           QKeySequence(Qt.CTRL + Qt.Key_Plus))
        animMenu.addAction("&Decrease Playback Speed",
                           self.decrement_playback_speed,
                           QKeySequence(Qt.CTRL + Qt.Key_Minus))
        animMenu.addAction("&Reset Playback Speed", self.reset_playback_speed,
                           QKeySequence(Qt.CTRL + Qt.Key_0))
        animMenu.addAction(self.actAutoPlay)
        animMenu.addAction(self.actResetCamera)

        helpMenu = self.menuBar().addMenu("&Help")
        helpMenu.addAction("&Online Documentation", self.show_online_docs)
        helpMenu.addAction("&About", self.show_info)

        # status bar
        self.status = QStatusBar(self)
        self.setStatusBar(self.status)
        self.statusLabel = QLabel("Ready.")
        self.statusBar().addPermanentWidget(self.statusLabel)
        self.timeLabel = QLabel("current time: 0.0")
        self.statusBar().addPermanentWidget(self.timeLabel)

        self._logger.info("Simulation GUI is up and running.")

    def _read_settings(self):

        # add default settings if none are present
        if not self._settings.contains("path/simulation_results"):
            self._settings.setValue(
                "path/simulation_results",
                os.path.join(os.path.curdir, "results", "simulation"))
        if not self._settings.contains("path/postprocessing_results"):
            self._settings.setValue(
                "path/postprocessing_results",
                os.path.join(os.path.curdir, "results", "postprocessing"))
        if not self._settings.contains("path/metaprocessing_results"):
            self._settings.setValue(
                "path/metaprocessing_results",
                os.path.join(os.path.curdir, "results", "metaprocessing"))

        if not self._settings.contains("control/autoplay_animation"):
            self._settings.setValue("control/autoplay_animation", "False")

        if not self._settings.contains("control/exit_on_batch_completion"):
            self._settings.setValue("control/exit_on_batch_completion",
                                    "False")

    def _write_settings(self):
        """ Store the application state. """
        pass

    @pyqtSlot()
    def update_autoplay_setting(self):
        self._settings.setValue("control/autoplay_animation",
                                str(self.actAutoPlay.isChecked()))

    @pyqtSlot()
    def update_exit_on_batch_completion_setting(self, state=None):
        if state is None:
            state = self.actExitOnBatchCompletion.isChecked()
        self._settings.setValue("control/exit_on_batch_completion", str(state))

    def set_visualizer(self, vis):
        self.visualizer = vis
        self.vtkWidget.Initialize()

    @pyqtSlot()
    def play_animation(self):
        """
        play the animation
        """
        self._logger.debug("Starting Playback")

        # if we are at the end, start from the beginning
        if self.playbackTime == self.currentEndTime:
            self.timeSlider.setValue(0)

        self.actPlayPause.setText("Pause Animation")
        self.actPlayPause.setIcon(QIcon(get_resource("pause.png")))
        self.actPlayPause.triggered.disconnect(self.play_animation)
        self.actPlayPause.triggered.connect(self.pause_animation)
        self.playbackTimer.start(self.playbackTimeout)

    @pyqtSlot()
    def pause_animation(self):
        """
        pause the animation
        """
        self._logger.debug("Pausing Playback")
        self.playbackTimer.stop()
        self.actPlayPause.setText("Play Animation")
        self.actPlayPause.setIcon(QIcon(get_resource("play.png")))
        self.actPlayPause.triggered.disconnect(self.pause_animation)
        self.actPlayPause.triggered.connect(self.play_animation)

    def stop_animation(self):
        """
        Stop the animation if it is running and reset the playback time.
        """
        self._logger.debug("Stopping Playback")
        if self.actPlayPause.text() == "Pause Animation":
            # animation is playing -> stop it
            self.playbackTimer.stop()
            self.actPlayPause.setText("Play Animation")
            self.actPlayPause.setIcon(QIcon(get_resource("play.png")))
            self.actPlayPause.triggered.disconnect(self.pause_animation)
            self.actPlayPause.triggered.connect(self.play_animation)

        self.timeSlider.setValue(0)

    @pyqtSlot()
    def start_simulation(self):
        """
        start the simulation and disable start button
        """
        if self._current_regime_index is None:
            regime_name = ""
        else:
            regime_name = str(
                self.regime_list.item(self._current_regime_index).text())

        self.statusLabel.setText("simulating {}".format(regime_name))
        self._logger.info("Simulating: {}".format(regime_name))

        self.actSimulateCurrent.setIcon(
            QIcon(get_resource("stop_simulation.png")))
        self.actSimulateCurrent.setText("Abort &Simulation")
        self.actSimulateCurrent.triggered.disconnect(self.start_simulation)
        self.actSimulateCurrent.triggered.connect(self.stop_simulation)

        if not self.runningBatch:
            self.actSimulateAll.setDisabled(True)

        self.guiProgress = QProgressBar(self)
        self.sim.simulationProgressChanged.connect(self.guiProgress.setValue)
        self.statusBar().addWidget(self.guiProgress)
        self.runSimulation.emit()

    @pyqtSlot()
    def stop_simulation(self):
        self.stopSimulation.emit()

    def export_simulation_data(self, ok):
        """
        Query the user for a custom name and export the current simulation
        results.

        :param ok: unused parameter from QAction.triggered() Signal
        """
        self._save_data()

    def _save_data(self, file_path=None):
        """
        Save the current simulation results.

        If *fie_name* is given, the result will be saved to the specified
        location, making automated exporting easier.

        Args:
            file_path(str): Absolute path of the target file. If `None` the
                use will be asked for a storage location.
        """
        regime_name = self._regimes[self._current_regime_index]["Name"]

        if file_path is None:
            # get default path
            path = self._settings.value("path/simulation_results")

            # create canonic file name
            suggestion = self._simfile_name(regime_name)
        else:
            path = os.path.dirname(file_path)
            suggestion = os.path.basename(file_path)

        # check if path exists otherwise create it
        if not os.path.isdir(path):
            box = QMessageBox()
            box.setText("Export Folder does not exist yet.")
            box.setInformativeText("Do you want to create it? \n"
                                   "{}".format(os.path.abspath(path)))
            box.setStandardButtons(QMessageBox.Ok | QMessageBox.No)
            box.setDefaultButton(QMessageBox.Ok)
            ret = box.exec_()
            if ret == QMessageBox.Ok:
                os.makedirs(path)
            else:
                path = os.path.abspath(os.path.curdir)
                file_path = None

        # If no path was given, present the default and let the user choose
        if file_path is None:
            dialog = QFileDialog(self)
            dialog.setAcceptMode(QFileDialog.AcceptSave)
            dialog.setFileMode(QFileDialog.AnyFile)
            dialog.setDirectory(path)
            dialog.setNameFilter("PyMoskito Results (*.pmr)")
            dialog.selectFile(suggestion)

            if dialog.exec_():
                file_path = dialog.selectedFiles()[0]
            else:
                self._logger.warning("Export Aborted")
                return -1

        # ask whether this should act as new default
        path = os.path.abspath(os.path.dirname(file_path))
        if path != self._settings.value("path/simulation_results"):
            box = QMessageBox()
            box.setText("Use this path as new default?")
            box.setInformativeText("{}".format(path))
            box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            box.setDefaultButton(QMessageBox.Yes)
            ret = box.exec_()
            if ret == QMessageBox.Yes:
                self._settings.setValue("path/simulation_results", path)

        self.currentDataset.update({"regime name": regime_name})
        with open(file_path, "wb") as f:
            pickle.dump(self.currentDataset, f, protocol=4)

        self.statusLabel.setText("results saved to {}".format(file_path))
        self._logger.info("results saved to {}".format(file_path))

    def _simfile_name(self, regime_name):
        """ Create a canonical name for a simulation result file
        """
        suggestion = (time.strftime("%Y%m%d-%H%M%S") + "_" + regime_name +
                      ".pmr")
        return suggestion

    def load_regime_dialog(self):
        regime_path = os.path.join(os.curdir)

        dialog = QFileDialog(self)
        dialog.setFileMode(QFileDialog.ExistingFile)
        dialog.setDirectory(regime_path)
        dialog.setNameFilter("Simulation Regime files (*.sreg)")

        if dialog.exec_():
            file = dialog.selectedFiles()[0]
            self.load_regimes_from_file(file)

    def load_regimes_from_file(self, file_name):
        """
        load simulation regime from file
        :param file_name:
        """
        self.regime_file_name = os.path.split(file_name)[-1][:-5]
        self._logger.info("loading regime file: {0}".format(
            self.regime_file_name))
        with open(file_name.encode(), "r") as f:
            self._regimes += yaml.load(f)

        self._update_regime_list()

        if self._regimes:
            self.actSimulateAll.setDisabled(False)

        self._logger.info("loaded {} regimes".format(len(self._regimes)))
        self.statusBar().showMessage(
            "loaded {} regimes.".format(len(self._regimes)), 1000)
        return

    def _update_regime_list(self):
        self.regime_list.clear()
        for reg in self._regimes:
            self._logger.debug("adding '{}' to regime list".format(
                reg["Name"]))
            self.regime_list.addItem(reg["Name"])

    def remove_regime_items(self):
        if self.regime_list.currentRow() >= 0:
            # flag all selected files as invalid
            items = self.regime_list.selectedItems()
            for item in items:
                del self._regimes[self.regime_list.row(item)]
                self.regime_list.takeItem(self.regime_list.row(item))

    @pyqtSlot(QListWidgetItem)
    def regime_dclicked(self, item):
        """
        Apply the selected regime to the current target.
        """
        self.apply_regime_by_name(str(item.text()))

    def apply_regime_by_name(self, regime_name):
        """
        Apply the regime given by `regime_name` und update the regime index.

        Returns:
            bool: `True` if successful, `False` if errors occurred.
        """
        # get regime idx
        try:
            idx = list(map(itemgetter("Name"),
                           self._regimes)).index(regime_name)
        except ValueError as e:
            self._logger.error(
                "apply_regime_by_name(): Error no regime called "
                "'{0}'".format(regime_name))
            return False

        # apply
        return self._apply_regime_by_idx(idx)

    def _apply_regime_by_idx(self, index=0):
        """
        Apply the given regime.

        Args:
            index(int): Index of the regime in the `RegimeList` .

        Returns:
            bool: `True` if successful, `False` if errors occurred.
        """
        if index >= len(self._regimes):
            self._logger.error("applyRegime: index error! ({})".format(index))
            return False

        reg_name = self._regimes[index]["Name"]
        self.statusBar().showMessage("regime {} applied.".format(reg_name),
                                     1000)
        self._logger.info("applying regime '{}'".format(reg_name))

        self._current_regime_index = index
        self._current_regime_name = reg_name

        return self.sim.set_regime(self._regimes[index])

    @pyqtSlot()
    def start_regime_execution(self):
        """
        Simulate all regimes in the regime list.
        """
        self.actSimulateAll.setText("Stop Simulating &All Regimes")
        self.actSimulateAll.setIcon(QIcon(get_resource("stop_batch.png")))
        self.actSimulateAll.triggered.disconnect(self.start_regime_execution)
        self.actSimulateAll.triggered.connect(self.stop_regime_excecution)

        self.runningBatch = True
        self._current_regime_index = -1
        self.regimeFinished.emit()

    def run_next_regime(self):
        """
        Execute the next regime in the regime batch.
        """
        # are we finished?
        if self._current_regime_index == len(self._regimes) - 1:
            self.finishedRegimeBatch.emit(True)
            return

        suc = self._apply_regime_by_idx(self._current_regime_index + 1)
        if not suc:
            self.finishedRegimeBatch.emit(False)
            return

        self.start_simulation()

    @pyqtSlot()
    def stop_regime_excecution(self):
        """ Stop the batch process.
        """
        self.stopSimulation.emit()
        self.finishedRegimeBatch.emit(False)

    def regime_batch_finished(self, status):
        self.runningBatch = False
        self.actSimulateAll.setDisabled(False)
        self.actSave.setDisabled(True)

        self.actSimulateAll.setText("Simulate &All Regimes")
        self.actSimulateAll.setIcon(QIcon(get_resource("execute_regimes.png")))
        self.actSimulateAll.triggered.disconnect(self.stop_regime_excecution)
        self.actSimulateAll.triggered.connect(self.start_regime_execution)

        if status:
            self.statusLabel.setText("All regimes have been simulated")
            self._logger.info("All Regimes have been simulated")
        else:
            self._logger.error("Batch simulation has been aborted")

        if self._settings.value("control/exit_on_batch_completion") == "True":
            self._logger.info("Shutting down SimulationGUI")
            self.close()

    @pyqtSlot(str, dict, name="new_simulation_data")
    def new_simulation_data(self, status, data):
        """
        Slot to be called when the simulation interface has completed the
        current job and new data is available.

        Args:
            status (str): Status of the simulation, either
                - `finished` : Simulation has been finished successfully or
                - `failed` : Simulation has failed.
            data (dict): Dictionary, holding the simulation data.
        """
        self._logger.info("Simulation {}".format(status))
        self.statusLabel.setText("Simulation {}".format(status))

        self.actSimulateCurrent.setText("&Simulate Current Regime")
        self.actSimulateCurrent.setIcon(QIcon(get_resource("simulate.png")))
        self.actSimulateCurrent.triggered.disconnect(self.stop_simulation)
        self.actSimulateCurrent.triggered.connect(self.start_simulation)

        self.actPlayPause.setDisabled(False)
        self.actStop.setDisabled(False)
        self.actSave.setDisabled(False)
        self.speedControl.setDisabled(False)
        self.timeSlider.setDisabled(False)

        self.sim.simulationProgressChanged.disconnect(
            self.guiProgress.setValue)
        self.statusBar().removeWidget(self.guiProgress)

        self.stop_animation()

        self.currentDataset = data
        if data:
            self._read_results()
            self._update_data_list()
            self._update_plots()

        if self._settings.value("control/autoplay_animation") == "True":
            self.actPlayPause.trigger()

        if self.runningBatch:
            regime_name = self._regimes[self._current_regime_index]["Name"]
            file_name = self._simfile_name(regime_name)
            self._save_data(
                os.path.join(self._settings.value("path/simulation_results"),
                             file_name))
            self.regimeFinished.emit()
        else:
            self.actSimulateAll.setDisabled(False)

    def _read_results(self):
        state = self.currentDataset["results"]["Solver"]
        self.interpolator = interp1d(self.currentDataset["results"]["time"],
                                     state,
                                     axis=0,
                                     bounds_error=False,
                                     fill_value=(state[0], state[-1]))
        self.currentStepSize = 1.0 / self.currentDataset["simulation"][
            "measure rate"]
        self.currentEndTime = self.currentDataset["simulation"]["end time"]
        self.validData = True

    def increment_playback_speed(self):
        self.speedControl.setValue(self.speedControl.value() +
                                   self.speedControl.singleStep())

    def decrement_playback_speed(self):
        self.speedControl.setValue(self.speedControl.value() -
                                   self.speedControl.singleStep())

    def reset_playback_speed(self):
        self.speedControl.setValue(
            (self.speedControl.maximum() - self.speedControl.minimum()) / 2)

    def set_slowest_playback_speed(self):
        self.speedControl.setValue(self.speedControl.minimum())

    def set_fastest_playback_speed(self):
        self.speedControl.setValue(self.speedControl.maximum())

    def update_playback_speed(self, val):
        """
        adjust playback time to slider value

        :param val:
        """
        maximum = self.speedControl.maximum()
        self.playbackGain = 10**(3.0 * (val - maximum / 2) / maximum)

    @pyqtSlot()
    def increment_playback_time(self):
        """
        go one time step forward in playback
        """
        if self.playbackTime == self.currentEndTime:
            self.pause_animation()
            return

        increment = self.playbackGain * self.playbackTimeout / 1000
        self.playbackTime = min(self.currentEndTime,
                                self.playbackTime + increment)
        pos = int(self.playbackTime / self.currentEndTime *
                  self.timeSliderRange)
        self.timeSlider.blockSignals(True)
        self.timeSlider.setValue(pos)
        self.timeSlider.blockSignals(False)
        self.playbackTimeChanged.emit()

    def update_playback_time(self):
        """
        adjust playback time to slider value
        """
        self.playbackTime = self.timeSlider.value(
        ) / self.timeSliderRange * self.currentEndTime
        self.playbackTimeChanged.emit()
        return

    def update_gui(self):
        """
        updates the graphical user interface, including:
            - timestamp
            - visualisation
            - time cursor in diagrams
        """
        if not self.validData:
            return

        self.timeLabel.setText("current time: %4f" % self.playbackTime)

        # update time cursor in plots
        self._update_time_cursors()

        # update state of rendering
        if self.visualizer:
            state = self.interpolator(self.playbackTime)
            self.visualizer.update_scene(state)
            if isinstance(self.visualizer, MplVisualizer):
                pass
            elif isinstance(self.visualizer, VtkVisualizer):
                self.vtkWidget.GetRenderWindow().Render()

    def _update_data_list(self):
        self.dataList.clear()
        for module_name, results in self.currentDataset["results"].items():
            if not isinstance(results, np.ndarray):
                continue
            if len(results.shape) == 1:
                self.dataList.insertItem(0, module_name)
            elif len(results.shape) == 2:
                for col in range(results.shape[1]):
                    self.dataList.insertItem(
                        0, self._build_entry_name(module_name, (col, )))
            elif len(results.shape) == 3:
                for col in range(results.shape[1]):
                    for der in range(results.shape[2]):
                        self.dataList.insertItem(
                            0, self._build_entry_name(module_name, (col, der)))

    def _build_entry_name(self, module_name, idx):
        """
        Construct an identifier for a given entry of a module.
        Args:
            module_name (str): name of the module the entry belongs to.
            idx (tuple): Index of the entry.

        Returns:
            str: Identifier to use for display.
        """
        # save the user from defining 1d entries via tuples
        if len(idx) == 1:
            m_idx = idx[0]
        else:
            m_idx = idx

        mod_settings = self.currentDataset["modules"]
        info = mod_settings.get(module_name, {}).get("output_info", None)
        if info:
            if m_idx in info:
                return ".".join([module_name, info[m_idx]["Name"]])

        return ".".join([module_name] + [str(i) for i in idx])

    def _get_index_from_suffix(self, module_name, suffix):
        info = self.currentDataset["modules"].get(module_name,
                                                  {}).get("output_info", None)
        idx = next((i for i in info if info[i]["Name"] == suffix), None)
        return idx

    def _get_units(self, entry):
        """
        Return the unit that corresponds to a given entry.

        If no information is available, None is returned.

        Args:
            entry (str): Name of the entry. This can either be "Model.a.b" where
                a and b are numbers or if information is available "Model.Signal"
                where signal is the name of that part.

        Returns:

        """
        args = entry.split(".")
        module_name = args.pop(0)
        info = self.currentDataset["modules"].get(module_name,
                                                  {}).get("output_info", None)
        if info is None:
            return None

        if len(args) == 1:
            try:
                idx = int(args[0])
            except ValueError:
                idx = next((i for i in info if info[i]["Name"] == args[0]),
                           None)
        else:
            idx = (int(a) for a in args)

        return info[idx]["Unit"]

    def create_plot(self, item):
        """
        Creates a plot widget based on the given item.

        If a plot for this item is already open no new plot is created but the
        existing one is raised up again.

        Args:
            item(Qt.ListItem): Item to plot.
        """
        title = str(item.text())
        if title in self.non_plotting_docks:
            self._logger.error("Title '{}' not allowed for a plot window since"
                               "it would shadow on of the reserved "
                               "names".format(title))

        # check if plot has already been opened
        if title in self.area.findAll()[1]:
            self.area.docks[title].raiseDock()
            return

        # collect data
        data = self._get_data_by_name(title)
        t = self.currentDataset["results"]["time"]
        unit = self._get_units(title)
        if "." in title:
            name = title.split(".")[1]
        else:
            name = title

        # create plot widget
        widget = pg.PlotWidget(title=title)
        widget.showGrid(True, True)
        widget.plot(x=t, y=data)
        widget.getPlotItem().getAxis("bottom").setLabel(text="Time", units="s")
        widget.getPlotItem().getAxis("left").setLabel(text=name, units=unit)

        # add a time line
        time_line = pg.InfiniteLine(self.playbackTime,
                                    angle=90,
                                    movable=False,
                                    pen=pg.mkPen("#FF0000", width=2.0))
        widget.getPlotItem().addItem(time_line)

        # create dock container and add it to dock area
        dock = pg.dockarea.Dock(title, closable=True)
        dock.addWidget(widget)
        self.area.addDock(dock, "above", self.plotDockPlaceholder)

    def _get_data_by_name(self, name):
        tmp = name.split(".")
        module_name = tmp[0]
        if len(tmp) == 1:
            data = np.array(self.currentDataset["results"][module_name])
        elif len(tmp) == 2:
            try:
                idx = int(tmp[1])
            except ValueError:
                idx = self._get_index_from_suffix(module_name, tmp[1])
            finally:
                data = self.currentDataset["results"][module_name][..., idx]
        elif len(tmp) == 3:
            idx = int(tmp[1])
            der = int(tmp[2])
            data = self.currentDataset["results"][module_name][..., idx, der]
        else:
            raise ValueError("Format not supported")

        return data

    def _update_time_cursors(self):
        """
        Update the time lines of all plot windows
        """
        for title, dock in self.area.findAll()[1].items():
            if title in self.non_plotting_docks:
                continue
            for widget in dock.widgets:
                for item in widget.getPlotItem().items:
                    if isinstance(item, pg.InfiniteLine):
                        item.setValue(self.playbackTime)

    def _update_plots(self):
        """
        Update the data in all plot windows
        """
        for title, dock in self.area.findAll()[1].items():
            if title in self.non_plotting_docks:
                continue

            if not self.dataList.findItems(dock.name(), Qt.MatchExactly):
                # no data for this plot -> remove it
                dock.close()
                continue

            for widget in dock.widgets:
                for item in widget.getPlotItem().items:
                    if isinstance(item, pg.PlotDataItem):
                        x_data = self.currentDataset["results"]["time"]
                        y_data = self._get_data_by_name(dock.name())
                        item.setData(x=x_data, y=y_data)

    @pyqtSlot(QModelIndex)
    def target_view_changed(self, index):
        self.targetView.resizeColumnToContents(0)

    def postprocessing_clicked(self):
        """
        starts the post- and metaprocessing application
        """
        self._logger.info("launching postprocessor")
        self.statusBar().showMessage("launching postprocessor", 1000)
        if self.postprocessor is None:
            self.postprocessor = PostProcessor()

        self.postprocessor.show()

    def reset_camera_clicked(self):
        """
        reset camera in vtk window
        """
        self.visualizer.reset_camera()
        self.vtkWidget.GetRenderWindow().Render()

    def show_info(self):
        icon_lic = open(get_resource("license.txt"), "r").read()
        text = "This application was build using PyMoskito ver. {} .<br />" \
               "PyMoskito is free software distributed under GPLv3. <br />" \
               "It is developed by members of the " \
               "<a href=\'https://tu-dresden.de/ing/elektrotechnik/rst'>" \
               "Institute of Control Theory</a>" \
               " at the <a href=\'https://tu-dresden.de'>" \
               "Dresden University of Technology</a>. <br />" \
               "".format(pkg_resources.require("PyMoskito")[0].version) \
               + "<br />" + icon_lic
        box = QMessageBox.about(self, "PyMoskito", text)

    def show_online_docs(self):
        webbrowser.open("https://pymoskito.readthedocs.org")

    def closeEvent(self, QCloseEvent):
        self._logger.info("Close Event received, shutting down.")
        logging.getLogger().removeHandler(self.textLogger)
        super().closeEvent(QCloseEvent)
Пример #3
0
class ContentTwoListGUI(QWidget):
    def __init__(self, working_directory, _option_gui, parent=None):
        super(QWidget, self).__init__(parent)
        self.cfg = HF.LittleHelpers.load_config(ROOTDIR)
        self.option_gui = _option_gui

        # ============================    Different options available   ============================
        if self.option_gui == 'dcm2niix':
            if os.path.isdir(self.cfg["folders"]["dicom"]):
                self.working_dir = self.cfg["folders"]["dicom"]
            else:
                self.working_dir = os.getcwd()

            options = {
                'folderbox_title': "Directory (DICOM-files)",
                'str_labelDir': 'DICOM DIR: {}'.format(self.working_dir),
                'runBTN_label': 'Run processing'
            }

        elif self.option_gui == "displayNiftiFiles":
            if not working_directory:
                HF.msg_box(
                    text='Please provide a valid folder. Terminating this GUI.',
                    title='No folder provided')
                self.close()
                return
            else:
                self.working_dir = working_directory
            options = {
                'folderbox_title': "Directory (nifti-files)",
                'str_labelDir': 'subjects\' DIR: {}'.format(self.working_dir),
                'runBTN_label': 'View files'
            }
        else:
            HF.msg_box(
                text=
                'Please provide a valid option such as "dcm2niix" or "displayNiftiFiles". '
                'Terminating the GUI',
                title='Wrong input as option')
            self.close()
            return

        # Create general layout
        self.tot_layout = QVBoxLayout(self)
        self.mid_layout = QHBoxLayout(self)

        # ============================    Create upper of  GUI, i.e. working directory   ============================
        self.label_folderbox = QGroupBox(options["folderbox_title"])
        self.HBoxUpperTwoListGUI = QVBoxLayout(self.label_folderbox)
        self.label_workingdir = QLabel(options["str_labelDir"])
        self.HBoxUpperTwoListGUI.addWidget(self.label_workingdir)

        self.btn_workingdir = QPushButton('Change working \ndirectory')
        self.btn_workingdir.setFixedSize(150, 40)
        self.btn_workingdir.setDisabled(True)
        if self.option_gui == "dcm2niix":
            self.btn_workingdir.setEnabled(True)
        self.btn_workingdir.clicked.connect(self.change_workingdir)

        self.btn_savedir = QPushButton('Save directory \nto config file')
        self.btn_savedir.setFixedSize(150, 40)
        self.btn_savedir.setDisabled(True)
        if self.option_gui == "dcm2niix":
            self.btn_savedir.setEnabled(True)
            self.btn_savedir.setToolTip(
                HF.LittleHelpers.split_lines(setToolTips.saveDirButton()))
        self.btn_savedir.clicked.connect(self.save_cfg_dicomdir)

        hlay_upper = QHBoxLayout()
        hlay_upper.addWidget(self.btn_workingdir)
        hlay_upper.addWidget(self.btn_savedir)
        hlay_upper.addStretch(1)
        self.HBoxUpperTwoListGUI.addLayout(hlay_upper)

        # ====================    Create Content for Lists, i.e. input/output      ====================
        self.listboxInputGUITwoList = QGroupBox(
            'Available items in working directory')
        self.listboxInput = QVBoxLayout(self.listboxInputGUITwoList)
        self.mInput = QListWidget()
        self.listboxInput.addWidget(self.mInput)

        self.mButtonToAvailable = QPushButton("<<")
        self.mBtnMoveToAvailable = QPushButton(">")
        self.mBtnMoveToSelected = QPushButton("<")
        self.mButtonToSelected = QPushButton(">>")
        self.mBtnUp = QPushButton("Up")
        self.mBtnDown = QPushButton("Down")

        self.listboxOutputGUITwoLIst = QGroupBox('Items to process')
        self.listboxOutput = QVBoxLayout(self.listboxOutputGUITwoLIst)
        self.mOutput = QListWidget()
        self.listboxOutput.addWidget(self.mOutput)

        # First column (Left side)
        vlay = QVBoxLayout()
        vlay.addStretch()
        vlay.addWidget(self.mBtnMoveToAvailable)
        vlay.addWidget(self.mBtnMoveToSelected)
        vlay.addStretch()
        vlay.addWidget(self.mButtonToAvailable)
        vlay.addWidget(self.mButtonToSelected)
        vlay.addStretch()

        # Second column (Right side)
        vlay2 = QVBoxLayout()
        vlay2.addStretch()
        vlay2.addWidget(self.mBtnUp)
        vlay2.addWidget(self.mBtnDown)
        vlay2.addStretch()

        # ====================    Lower part of GUI, i.e. Preferences/Start estimation      ====================
        self.btn_preferences = QPushButton("Preferences")
        self.btn_preferences.setDisabled(True)
        self.btn_preferences.clicked.connect(self.settings_show)
        if self.option_gui == "dcm2niix":
            self.btn_preferences.setEnabled(True)

        self.btn_run_command = QPushButton(options["runBTN_label"])
        if self.option_gui == "dcm2niix":
            self.btn_run_command.setToolTip(setToolTips.run_dcm2niix())
        else:
            self.btn_run_command.setToolTip(
                setToolTips.run_CheckRegistration())
        self.btn_run_command.clicked.connect(self.start_process)

        hlay_bottom = QHBoxLayout()
        hlay_bottom.addStretch(1)
        hlay_bottom.addWidget(self.btn_preferences)
        hlay_bottom.addWidget(self.btn_run_command)
        hlay_bottom.addStretch()

        # ====================    Set all contents to general Layout     =======================
        self.mid_layout.addWidget(self.listboxInputGUITwoList)
        self.mid_layout.addLayout(vlay)
        self.mid_layout.addWidget(self.listboxOutputGUITwoLIst)
        self.mid_layout.addLayout(vlay2)

        self.tot_layout.addWidget(self.label_folderbox)
        self.tot_layout.addLayout(self.mid_layout)
        self.tot_layout.addLayout(hlay_bottom)

        try:
            self.mInput.clear()
            if self.option_gui == 'dcm2niix':
                items = HF.list_folders(self.working_dir, prefix='')
            else:
                items = HF.list_files_in_folder(inputdir=self.working_dir,
                                                contains='',
                                                suffix='nii')
            self.addAvailableItems(items)
        except FileExistsError:
            print('{} without any valid files/folders, continuing ...'.format(
                self.working_dir))

        self.update_buttons_status()
        self.connections()

    def addAvailableItems(self, items):
        """adds the available Items in the directory to read from into list; error message is dropped if 0 available"""

        if len(items) == 0:
            buttonReply = QMessageBox.question(
                self, 'No files/folders in the selected directory',
                'There are no subjects available in the current working directory ({}). '
                'Do you want to change to a different one?'.format(
                    self.working_dir), QMessageBox.Yes | QMessageBox.No,
                QMessageBox.Yes)
            if buttonReply == QMessageBox.Yes:
                self.change_workingdir()
        else:
            self.mInput.addItems(items)

    def change_workingdir(self):
        """A new window appears in which the working directory can be set; besides, data is stored in the preferences
        file so that they will be loaded automatically next time"""

        self.working_dir = QFileDialog.getExistingDirectory(
            self,
            directory=self.working_dir,
            caption='Change working directory')
        self.label_workingdir.setText('Working DIR: {}'.format(
            self.working_dir))
        self.mInput.clear()

        items = HF.list_folders(self.working_dir, prefix='')
        self.addAvailableItems(items)
        if self.option_gui == "dcm2niix":
            self.cfg["folders"]["dicom"] = self.working_dir
            HF.LittleHelpers.save_config(self.cfg["folders"]["rootdir"],
                                         self.cfg)

    def save_cfg_dicomdir(self):
        """Function intended to save the DICOM directory once button is pressed"""
        self.cfg["folders"]["dicom"] = self.working_dir
        HF.LittleHelpers.save_config(self.cfg["folders"]["rootdir"], self.cfg)
        HF.LittleHelpers.msg_box(
            text="Folder changed in the configuration file to {}".format(
                self.working_dir),
            title='Changed folder')

    def settings_show(self):
        """Opens a new GUI in which the settings for the transformation con be changed and saved to config file"""
        self.settingsGUI = GuiSettingsDCM2NII()
        self.settingsGUI.show()

    def start_process(self):
        """starts the process linked to the module selected; that is in case of dcm2nii it runs the extraction of nifti-
        files from the DICOM folder or in case of displayN4corr it displays all nifti files available in the folder"""

        input = []
        [
            input.append(self.mOutput.item(x).text())
            for x in range(self.mOutput.count())
        ]

        if not input:
            HF.LittleHelpers.msg_box(
                text="At least one folder with data must be selected!",
                title='No directory selected')
        elif len(input) != 0 and self.option_gui == "dcm2niix":
            print('in total, {} folders were selected'.format(len(input)))
            preprocDCM2NII.PreprocessDCM(input)
        elif len(input) != 0 and self.option_gui == "displayNiftiFiles":
            input_with_path = []
            [
                input_with_path.extend(
                    glob.glob(self.working_dir + '/**/' + x, recursive=True))
                for x in input
            ]

            viewer = 'itk-snap'  # to-date, only one viewer is available. May be changed in a future
            HF.LittleHelpers.load_imageviewer(viewer, input_with_path)

    @QtCore.pyqtSlot()
    def update_buttons_status(self):
        self.mBtnUp.setDisabled(not bool(self.mOutput.selectedItems())
                                or self.mOutput.currentRow() == 0)
        self.mBtnDown.setDisabled(
            not bool(self.mOutput.selectedItems())
            or self.mOutput.currentRow() == (self.mOutput.count() - 1))
        self.mBtnMoveToAvailable.setDisabled(
            not bool(self.mInput.selectedItems())
            or self.mOutput.currentRow() == 0)
        self.mBtnMoveToSelected.setDisabled(
            not bool(self.mOutput.selectedItems()))
        self.mButtonToAvailable.setDisabled(
            not bool(self.mOutput.selectedItems()))
        self.mButtonToSelected.setDisabled(
            not bool(self.mInput.selectedItems()))

    def connections(self):
        self.mInput.itemSelectionChanged.connect(self.update_buttons_status)
        self.mOutput.itemSelectionChanged.connect(self.update_buttons_status)
        self.mBtnMoveToAvailable.clicked.connect(
            self.on_mBtnMoveToAvailable_clicked)
        self.mBtnMoveToSelected.clicked.connect(
            self.on_mBtnMoveToSelected_clicked)
        self.mButtonToAvailable.clicked.connect(
            self.on_mButtonToAvailable_clicked)
        self.mButtonToSelected.clicked.connect(
            self.on_mButtonToSelected_clicked)
        self.mBtnUp.clicked.connect(self.on_mBtnUp_clicked)
        self.mBtnDown.clicked.connect(self.on_mBtnDown_clicked)

    @QtCore.pyqtSlot()
    def on_mBtnMoveToAvailable_clicked(self):
        self.mOutput.addItem(self.mInput.takeItem(self.mInput.currentRow()))

    @QtCore.pyqtSlot()
    def on_mBtnMoveToSelected_clicked(self):
        self.mInput.addItem(self.mOutput.takeItem(self.mOutput.currentRow()))

    @QtCore.pyqtSlot()
    def on_mButtonToAvailable_clicked(self):
        while self.mOutput.count() > 0:
            self.mInput.addItem(self.mOutput.takeItem(0))

    @QtCore.pyqtSlot()
    def on_mButtonToSelected_clicked(self):
        while self.mInput.count() > 0:
            self.mOutput.addItem(self.mInput.takeItem(0))

    @QtCore.pyqtSlot()
    def on_mBtnUp_clicked(self):
        row = self.mOutput.currentRow()
        currentItem = self.mOutput.takeItem(row)
        self.mOutput.insertItem(row - 1, currentItem)
        self.mOutput.setCurrentRow(row - 1)

    @QtCore.pyqtSlot()
    def on_mBtnDown_clicked(self):
        row = self.mOutput.currentRow()
        currentItem = self.mOutput.takeItem(row)
        self.mOutput.insertItem(row + 1, currentItem)
        self.mOutput.setCurrentRow(row + 1)

    def addSelectedItems(self, items):
        self.mOutput.addItems(items)

    def closeEvent(self, event):
        """saves the settings found here as a yaml file and closes the GUI"""
        event.accept()
Пример #4
0
class App(QMainWindow):
    def __init__(self):
        super().__init__()

        self.instance = vlc.Instance('--novideo')
        #self.mediaplayer = self.instance.media_player_new()
        self.medialist = self.instance.media_list_new()
        self.mediaplayer = self.instance.media_list_player_new()

        self.title = 'Player'
        self.left = 500
        self.top = 200
        self.width = 600
        self.height = 400
        self.color = 0  # 0- toggle to dark 1- toggle to light
        self.initUI()

    def initUI(self):
        self.addControls()
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.toggleColors()
        #self.show()
        self.showFullScreen()
        self.Wellcome()

    def addControls(self):
        wid = QWidget(self)
        self.setCentralWidget(wid)
        # Status
        self.status = QLabel()
        self.status.setAlignment(QtCore.Qt.AlignCenter)
        self.status.setStyleSheet('color: #1DB954')
        self.status.setText('Xin chào')
        # List
        self.result_label = QLabel()
        self.result_label.setAlignment(QtCore.Qt.AlignCenter)
        self.result_label.setStyleSheet('color: #1DB954')
        self.result_label.setText('Danh sách phát')
        # Search
        self.searchInput = QLineEdit()
        self.searchInput.setFixedHeight(22)
        #self.searchInput.setText("am tham ben em")
        self.searchBtn = QPushButton('Tìm kiếm')
        self.searchBtn.setFixedHeight(40)
        self.searchBtn.clicked.connect(self.Search)

        self.voicesearchBtn = QPushButton('Tìm bằng giọng nói')
        self.voicesearchBtn.setFixedHeight(40)
        self.voicesearchBtn.clicked.connect(self.VoiceSearch)

        self.listAudio = QListWidget()
        self.listAudio.setFixedHeight(125)

        self.current_vol = 60
        self.mediaplayer.get_media_player().audio_set_volume(self.current_vol)

        self.voldown = QPushButton('-')
        self.volup = QPushButton('+')
        self.volup.setFixedHeight(50)
        self.volup.setFixedWidth(50)
        self.voldown.setFixedHeight(50)
        self.voldown.setFixedWidth(50)

        self.playbutton = QPushButton('Phát/Tạm dừng')  # play button
        self.playbutton.setFixedHeight(50)
        self.stopbutton = QPushButton('Phát lại')  # Stop button
        self.stopbutton.setFixedHeight(50)
        self.nextbutton = QPushButton('Tiếp theo')  # Next button
        self.nextbutton.setFixedHeight(50)
        self.nextbutton2 = QPushButton('Tiếp theo')  # Next button
        self.nextbutton2.setFixedHeight(50)
        self.command = QPushButton('Ra lệnh bằng giọng nói')  # Next button
        self.command.setFixedHeight(40)

        self.shortcut = QShortcut(QKeySequence("Space"), self)
        self.shortcut.activated.connect(self.excCommand)

        self.exit = QPushButton('Thoát')  # Next button
        self.exit.setFixedHeight(40)
        # Add button layouts
        mainLayout = QVBoxLayout()

        controls = QHBoxLayout()
        controls.addWidget(self.voldown)
        controls.addWidget(self.playbutton)
        controls.addWidget(self.nextbutton2)
        controls.addWidget(self.stopbutton)
        controls.addWidget(self.volup)

        # Add to vertical layout
        mainLayout.addWidget(self.status)
        mainLayout.addWidget(self.searchInput)
        mainLayout.addWidget(self.result_label)
        mainLayout.addWidget(self.listAudio)
        mainLayout.addWidget(self.searchBtn)
        mainLayout.addWidget(self.voicesearchBtn)
        mainLayout.addLayout(controls)
        mainLayout.addWidget(self.command)
        mainLayout.addWidget(self.exit)
        wid.setLayout(mainLayout)

        self.playbutton.clicked.connect(self.PlayPause)
        self.stopbutton.clicked.connect(self.Stop)
        self.nextbutton2.clicked.connect(self.Next)
        self.volup.clicked.connect(self.volUp)
        self.voldown.clicked.connect(self.volDown)

        self.command.clicked.connect(self.excCommand)
        self.exit.clicked.connect(self.exitApp)
        self.statusBar()

    def Wellcome(self):
        t2s("Xin chào tôi là Pi")

    def exitApp(self):
        exit()

    def setVolume(self, Volume):
        self.mediaplayer.get_media_player().audio_set_volume(Volume)

    def volUp(self):
        if self.current_vol < 100:
            self.current_vol = self.current_vol + 20
            self.mediaplayer.get_media_player().audio_set_volume(
                self.current_vol)

    def volDown(self):
        if self.current_vol > 20:
            self.current_vol = self.current_vol - 20
            self.mediaplayer.get_media_player().audio_set_volume(
                self.current_vol)

    def PlayPause(self):
        if self.mediaplayer.is_playing():
            self.mediaplayer.pause()
            self.playbutton.setText("Phát")
        else:
            self.mediaplayer.play()
            self.playbutton.setText("Tạm dừng")

    def Pause(self):
        if self.mediaplayer.is_playing():
            self.mediaplayer.pause()
            self.playbutton.setText("Phát")

    def Stop(self):
        self.mediaplayer.stop()
        self.mediaplayer.play()
        self.playbutton.setText("Tạm dừng")

    def setMediaList(self):
        self.mediaplayer.set_media_list(self.medialist)

    def addMediaPlayerUrl(self, url):
        self.medialist.add_media(self.instance.media_new(url))

    def resetMediaPlayList(self):
        self.medialist = self.instance.media_list_new()
        self.mediaplayer = self.instance.media_list_player_new()

    def getListSearch(self):
        self.status.setText('Đang tìm')
        if self.searchInput.text() == '':
            self.status.setText('Nhập từ khóa hoặc tìm bằng giọng nói')
            t2s('Vui lòng nhập từ khóa hoặc tìm kiếm bằng giọng nói')
        else:
            print('keyword:', self.searchInput.text())
            results = searchYoutube(self.searchInput.text(),
                                    offset=1,
                                    mode="json",
                                    max_results=5).result()
            results = json.loads(results)
            results = results["search_result"]
            #print(results)
            if len(results) == 0:
                if self.fornext:
                    self.listAudio.clear()
                    #self.resetMediaPlayList()
                    self.idx_audio = self.idx_audio + 1
                    self.listAudio.insertItem(
                        0, 'Tiếp theo: ' + self.list_title[self.idx_audio])
                    self.listAudio.repaint()
                else:
                    self.status.setText('Không có kết quả hoặc lỗi')
                    t2s('Tôi không thể tìm kiếm Hãy thử lại')
                #pass
            else:
                #tìm kiếm mới
                self.listAudio_text = {}
                self.listAudio.clear()
                self.list_title = [e["title"] for e in results]
                print("list_title:", self.list_title[0])

                for i, item in enumerate(results):
                    itemlink = item['link']
                    self.listAudio_text[self.list_title[i]] = itemlink
                    self.status.setText('Kết quả cho: "{}"'.format(
                        self.searchInput.text()))

                for i, item in enumerate(results):
                    #nếu search gợi ý cho next thì chỉ hiển thị 1 bài tiếp theo
                    if self.fornext:
                        self.listAudio.insertItem(
                            i + 1, 'Tiếp theo: ' + self.list_title[i])
                        self.idx_audio = 0
                        self.listAudio.repaint()
                        break
                    else:
                        self.listAudio.insertItem(
                            i + 1,
                            str(i + 1) + ': ' + self.list_title[i])

                self.listAudio.repaint()
        self.listAudio.repaint()
        print("end search")

    def Search(self):
        self.Stop()
        self.resetMediaPlayList()
        self.fornext = False
        t2s("Tôi sẽ tìm những kết quả cho")
        t2s(self.searchInput.text())
        self.getListSearch()
        try:
            _ = len(self.listAudio_text)
            t2s("Đây là kết quả Chọn bài muốn phát")
            self.idx_audio = select_by_speech()
            self.fornext = True
            self.selectAndPlaySongByIndex()
        except:
            self.status.setText('Không có kết quả hoặc lỗi. Thử lại')
            t2s('Không có kết quả hoặc lỗi Hãy thử lại')

    def VoiceSearch(self):
        self.Stop()
        t2s('Chức năng tìm kiếm bằng giọng nói sẵn sàng')
        self.status.setText('Tìm kiếm giọng nói')
        keyword = getVoiceKeyWord()  # có xác nhận key
        self.status.setText('Tìm kiếm cho: "{}"'.format(keyword))
        self.searchInput.setText(keyword)
        self.Search()

    def selectAndPlaySongByIndex(self):
        title_audio = list(self.listAudio_text.keys())[self.idx_audio]
        link_audio = list(self.listAudio_text.values())[self.idx_audio]
        link_audio = getLinkAudio(link_audio)
        t2s('Bắt đầu phát')
        t2s(title_audio)

        self.addMediaPlayerUrl(link_audio)
        #self.setMediaList()

        next_key = next_keyword(self.list_title)
        self.searchInput.setText(next_key)
        self.getListSearch()

        title_audio2 = list(self.listAudio_text.keys())[self.idx_audio]
        link_audio2 = list(self.listAudio_text.values())[self.idx_audio]
        link_audio2 = getLinkAudio(link_audio2)
        self.addMediaPlayerUrl(link_audio2)
        self.setMediaList()

        print("=" * 20)
        print("hiện tại:", title_audio)
        print("tiếp theo", title_audio2)
        print("=" * 20)
        self.PlayPause()
        self.status.setText('Đang phát: {}'.format(title_audio))

    def Next(self):
        self.Pause()
        self.status.setText("Tiếp theo")
        t2s("Tiếp theo")
        self.resetMediaPlayList()
        #self.idx_audio += 1
        self.selectAndPlaySongByIndex()
        print("sau next:", self.medialist.count())

    def excCommand(self):
        self.Pause()
        command = listen_command()
        if command == 0:
            self.PlayPause()
        elif command == 1:
            self.Next()
        elif command == 2:
            self.Stop()
            t2s("Phát lại")
        elif command == 3:
            self.VoiceSearch()
        elif command == 4:
            self.volUp()
            t2s("đã tăng")
            self.PlayPause()
        elif command == 6:
            self.volDown()
            t2s("đã giảm")
            self.PlayPause()

        elif command == 5:
            t2s('Bạn chắc chắn muốn thoát không')
            t2s('Xác nhận bằng cách nói ok')
            cf_exit = recognize('')
            if cf_exit == 'yes' or cf_exit == 'ok' or cf_exit == 'oke':
                t2s("Chào bạn hẹn gặp lại bạn hihi")
                exit()
            else:
                print('no exit')

    def toggleColors(self):
        app.setStyle("Fusion")
        palette = QPalette()
        palette.setColor(QPalette.Window, QColor(41, 41, 41))
        palette.setColor(QPalette.WindowText, Qt.white)
        palette.setColor(QPalette.Base, QColor(41, 41, 41))
        palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
        palette.setColor(QPalette.ToolTipBase, Qt.white)
        palette.setColor(QPalette.ToolTipText, Qt.white)
        palette.setColor(QPalette.Text, Qt.white)
        palette.setColor(QPalette.Button, QColor(29, 185, 84))
        palette.setColor(QPalette.ButtonText, Qt.white)
        palette.setColor(QPalette.BrightText, Qt.red)
        palette.setColor(QPalette.Link, QColor(235, 101, 54))
        palette.setColor(QPalette.Highlight, Qt.white)
        palette.setColor(QPalette.HighlightedText, QColor(29, 185, 84))
        app.setPalette(palette)
Пример #5
0
class MainWindow(QMainWindow):
    htmlReady = pyqtSignal(str)

    def __init__(self, app):
        QMainWindow.__init__(self)
        self.install_directory = os.getcwd()
        self.app = app
        self.book = None
        self.last_book = ""
        self.filename = ""
        self._part_is_new = False
        self.tread_running = False
        self.initTheme()
        self.createUi()
        self.createMenus()
        self.createStatusBar()
        self.readSettings()
        self.text_edit.textChanged.connect(self.textChanged)

    def initTheme(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        self.theme = settings.value("theme", "Fusion")
        hilite_color = settings.value(
            "hiliteColor",
            self.palette().highlight().color().name())
        self.changeStyle(self.theme, hilite_color)

    def showEvent(self, event):
        if self.last_book:
            self.loadBook(self.last_book)

    def changeStyle(self, theme, hilite_color):
        self.theme = theme
        if theme == "DarkFusion":
            QApplication.setStyle(DarkFusion(hilite_color))
        else:
            QApplication.setStyle(QStyleFactory.create(theme))
            pal = self.app.palette()
            pal.setColor(QPalette.Highlight, QColor(hilite_color))
            self.app.setPalette(pal)

    def createUi(self):
        self.content = Expander("Content", ":/images/parts.svg")
        self.images = Expander("Images", ":/images/images.svg")
        self.settings = Expander("Settings", ":/images/settings.svg")

        self.setWindowTitle(QCoreApplication.applicationName() + " " +
                            QCoreApplication.applicationVersion())
        vbox = QVBoxLayout()
        vbox.addWidget(self.content)
        vbox.addWidget(self.images)
        vbox.addWidget(self.settings)
        vbox.addStretch()

        self.content_list = QListWidget()
        self.content_list.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        content_box = QVBoxLayout()
        content_box.addWidget(self.content_list)
        self.item_edit = QLineEdit()
        self.item_edit.setMaximumHeight(0)
        self.item_edit.editingFinished.connect(self.editItemFinished)
        self.item_anim = QPropertyAnimation(self.item_edit,
                                            "maximumHeight".encode("utf-8"))
        content_box.addWidget(self.item_edit)
        button_layout = QHBoxLayout()
        plus_button = FlatButton(":/images/plus.svg")
        self.edit_button = FlatButton(":/images/edit.svg")
        self.trash_button = FlatButton(":/images/trash.svg")
        self.up_button = FlatButton(":/images/up.svg")
        self.down_button = FlatButton(":/images/down.svg")
        self.trash_button.enabled = False
        self.up_button.enabled = False
        self.down_button.enabled = False
        button_layout.addWidget(plus_button)
        button_layout.addWidget(self.up_button)
        button_layout.addWidget(self.down_button)
        button_layout.addWidget(self.edit_button)
        button_layout.addWidget(self.trash_button)
        content_box.addLayout(button_layout)
        self.content.addLayout(content_box)
        plus_button.clicked.connect(self.addPart)
        self.trash_button.clicked.connect(self.dropPart)
        self.up_button.clicked.connect(self.partUp)
        self.down_button.clicked.connect(self.partDown)
        self.edit_button.clicked.connect(self.editPart)

        self.image_list = QListWidget()
        self.image_list.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed)
        image_box = QVBoxLayout()
        image_box.addWidget(self.image_list)
        image_button_layout = QHBoxLayout()
        image_plus_button = FlatButton(":/images/plus.svg")
        self.image_trash_button = FlatButton(":/images/trash.svg")
        self.image_trash_button.enabled = False
        image_button_layout.addWidget(image_plus_button)
        image_button_layout.addWidget(self.image_trash_button)
        image_box.addLayout(image_button_layout)
        self.images.addLayout(image_box)
        image_plus_button.clicked.connect(self.addImage)
        self.image_trash_button.clicked.connect(self.dropImage)

        scroll_content = QWidget()
        scroll_content.setLayout(vbox)
        scroll = QScrollArea()
        scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        scroll.setWidget(scroll_content)
        scroll.setWidgetResizable(True)
        scroll.setMaximumWidth(200)
        scroll.setMinimumWidth(200)

        self.navigationdock = QDockWidget("Navigation", self)
        self.navigationdock.setAllowedAreas(Qt.LeftDockWidgetArea
                                            | Qt.RightDockWidgetArea)
        self.navigationdock.setWidget(scroll)
        self.navigationdock.setObjectName("Navigation")
        self.addDockWidget(Qt.LeftDockWidgetArea, self.navigationdock)

        self.splitter = QSplitter()
        self.text_edit = MarkdownEdit()
        self.text_edit.setFont(QFont("Courier", 11))
        self.preview = QWebEngineView()
        self.preview.setMinimumWidth(300)
        self.setWindowTitle(QCoreApplication.applicationName())

        self.splitter.addWidget(self.text_edit)
        self.splitter.addWidget(self.preview)
        self.setCentralWidget(self.splitter)

        self.content.expanded.connect(self.contentExpanded)
        self.images.expanded.connect(self.imagesExpanded)
        self.settings.expanded.connect(self.settingsExpanded)
        self.settings.clicked.connect(self.openSettings)
        self.content_list.currentItemChanged.connect(self.partSelectionChanged)
        self.image_list.currentItemChanged.connect(self.imageSelectionChanged)
        self.image_list.itemDoubleClicked.connect(self.insertImage)

        self.text_edit.undoAvailable.connect(self.undoAvailable)
        self.text_edit.redoAvailable.connect(self.redoAvailable)
        self.text_edit.copyAvailable.connect(self.copyAvailable)

        QApplication.clipboard().dataChanged.connect(self.clipboardDataChanged)

    def undoAvailable(self, value):
        self.undo_act.setEnabled(value)

    def redoAvailable(self, value):
        self.redo_act.setEnabled(value)

    def copyAvailable(self, value):
        self.copy_act.setEnabled(value)
        self.cut_act.setEnabled(value)

    def clipboardDataChanged(self):
        md = QApplication.clipboard().mimeData()
        self.paste_act.setEnabled(md.hasText())

    def openSettings(self):
        dlg = Settings(self.book)
        dlg.exec()
        if dlg.saved:
            self.setWindowTitle(QCoreApplication.applicationName() + " - " +
                                self.book.name)

    def addPart(self):
        self.item_edit.setText("")
        self.item_edit.setFocus()
        self.item_anim.setStartValue(0)
        self.item_anim.setEndValue(23)
        self.item_anim.start()
        self._part_is_new = True

    def addItem(self):
        text = self.item_edit.text()
        if text:
            if not self.book.getPart(text):
                self.book.addPart(text)
                self.loadBook(self.last_book)

    def updateItem(self):
        text = self.item_edit.text()
        if text:
            if not self.book.getPart(text):
                self.book.updatePart(
                    self.content_list.currentItem().data(1).name, text)
                self.loadBook(self.last_book)

    def editItemFinished(self):
        if self._part_is_new:
            self.addItem()
        else:
            self.updateItem()
        self.item_anim.setStartValue(23)
        self.item_anim.setEndValue(0)
        self.item_anim.start()

    def editPart(self):
        item = self.content_list.currentItem().data(1).name
        self.item_edit.setText(item)
        self.item_edit.setFocus()
        self.item_anim.setStartValue(0)
        self.item_anim.setEndValue(23)
        self.item_anim.start()
        self._part_is_new = False

    def dropPart(self):
        item = self.content_list.currentItem().data(1).name
        msgBox = QMessageBox()
        msgBox.setText("You are about to delete the part <i>" + item + "</i>")
        msgBox.setInformativeText("Do you really want to delete the item?")
        msgBox.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel)
        msgBox.setDefaultButton(QMessageBox.Cancel)
        ret = msgBox.exec()
        if ret == QMessageBox.Yes:
            self.book.dropPart(item)
            self.loadBook(self.last_book)

    def addImage(self):
        fileName = ""
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setNameFilter("Image Files(*.png *.jpg *.bmp *.gif);;All (*)")
        dialog.setWindowTitle("Load Image")
        dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        if dialog.exec_():
            fileName = dialog.selectedFiles()[0]
        del dialog
        if not fileName:
            return

        base = os.path.basename(fileName)
        if not os.path.exists(
                os.path.join(self.book.source_path, "images", base)):
            copy(fileName, os.path.join(self.book.source_path, "images"))
        item = QListWidgetItem()
        item.setText(Path(fileName).name)
        item.setData(
            1,
            os.path.join(self.book.source_path, "images",
                         Path(fileName).name))
        self.image_list.addItem(item)

    def dropImage(self):
        item = self.image_list.currentItem()
        image = item.data(1)
        filename = os.path.join(self.book.source_path, "parts", image)
        os.remove(filename)
        self.loadImages()

    def loadImages(self):
        self.image_list.clear()
        for root, dir, files in os.walk(
                os.path.join(self.book.source_path, "images")):
            for file in files:
                filename = os.path.join(self.book.source_path, "images",
                                        Path(file).name)
                item = QListWidgetItem()
                item.setToolTip("Doubleclick image to insert into text")
                item.setText(Path(file).name)
                item.setData(1, filename)
                self.image_list.addItem(item)

    def partUp(self):
        pos = self.content_list.currentRow()
        item = self.content_list.takeItem(pos)
        self.content_list.insertItem(pos - 1, item)
        self.content_list.setCurrentRow(pos - 1)
        self.book.partUp(item.data(1).name)

    def partDown(self):
        pos = self.content_list.currentRow()
        item = self.content_list.takeItem(pos)
        self.content_list.insertItem(pos + 1, item)
        self.content_list.setCurrentRow(pos + 1)
        self.book.partDown(item.data(1).name)

    def partSelectionChanged(self, item):
        if item:
            part = item.data(1)
            self.filename = os.path.join(self.book.source_path, "parts",
                                         part.src)
            with open(self.filename, "r") as f:
                self.text_edit.setText(f.read())
            self.trash_button.enabled = True
            self.up_button.enabled = self.content_list.currentRow() > 0
            self.down_button.enabled = self.content_list.currentRow(
            ) < self.content_list.count() - 1
            self.edit_button.enabled = True
        else:
            self.text_edit.setText("")
            self.trash_button.enabled = False
            self.up_button.enabled = False
            self.down_button.enabled = False
            self.edit_button.enabled = False

    def imageSelectionChanged(self, item):
        if item:
            self.image_trash_button.enabled = True
        else:
            self.image_trash_button.enabled = False

    def contentExpanded(self, value):
        if value:
            self.images.setExpanded(False)
            self.settings.setExpanded(False)

    def imagesExpanded(self, value):
        if value:
            self.content.setExpanded(False)
            self.settings.setExpanded(False)

    def appearanceExpanded(self, value):
        if value:
            self.content.setExpanded(False)
            self.images.setExpanded(False)
            self.settings.setExpanded(False)

    def settingsExpanded(self, value):
        if value:
            self.content.setExpanded(False)
            self.images.setExpanded(False)

    def closeEvent(self, event):
        self.writeSettings()
        event.accept()

    def createMenus(self):
        new_icon = QIcon(QPixmap(":/images/new.svg"))
        open_icon = QIcon(QPixmap(":/images/open.svg"))
        book_icon = QIcon(QPixmap(":/images/book.svg"))
        bold_icon = QIcon(QPixmap(":/images/bold.svg"))
        italic_icon = QIcon(QPixmap(":/images/italic.svg"))
        image_icon = QIcon(QPixmap(":/images/image.svg"))
        table_icon = QIcon(QPixmap(":/images/table.svg"))

        new_act = QAction(new_icon, "&New", self)
        new_act.setShortcuts(QKeySequence.New)
        new_act.setStatusTip("Create a new ebook project")
        new_act.triggered.connect(self.newFile)
        new_act.setToolTip("Create new ebook project")

        open_act = QAction(open_icon, "&Open", self)
        open_act.setShortcuts(QKeySequence.Open)
        open_act.setStatusTip("Open an existing ebook project")
        open_act.triggered.connect(self.open)
        open_act.setToolTip("Open an existing ebook project")

        book_act = QAction(book_icon, "&Create Book", self)
        book_act.setShortcuts(QKeySequence.SaveAs)
        book_act.setStatusTip("Create an ebook")
        book_act.triggered.connect(self.create)
        book_act.setToolTip("Create an ebook")

        pdf_act = QAction("Create &PDF", self)
        pdf_act.setStatusTip("Create PDF")
        pdf_act.setToolTip("Create PDF")
        pdf_act.triggered.connect(self.pdfExport)

        settings_act = QAction("&Settings", self)
        settings_act.setStatusTip("Open settings dialog")
        settings_act.triggered.connect(self.settingsDialog)
        settings_act.setToolTip("Open settings dialog")

        exit_act = QAction("E&xit", self)
        exit_act.setShortcuts(QKeySequence.Quit)
        exit_act.setStatusTip("Exit the application")
        exit_act.triggered.connect(self.close)

        self.undo_act = QAction("Undo", self)
        self.undo_act.setShortcut(QKeySequence.Undo)
        self.undo_act.setEnabled(False)
        self.undo_act.triggered.connect(self.doUndo)

        self.redo_act = QAction("Redo", self)
        self.redo_act.setShortcut(QKeySequence.Redo)
        self.redo_act.setEnabled(False)
        self.undo_act.triggered.connect(self.doRedo)

        self.cut_act = QAction("Cu&t", self)
        self.cut_act.setShortcut(QKeySequence.Cut)
        self.cut_act.triggered.connect(self.doCut)
        self.cut_act.setEnabled(False)

        self.copy_act = QAction("&Copy", self)
        self.copy_act.setShortcut(QKeySequence.Copy)
        self.copy_act.triggered.connect(self.doCopy)
        self.copy_act.setEnabled(False)

        self.paste_act = QAction("&Paste", self)
        self.paste_act.setShortcut(QKeySequence.Paste)
        self.paste_act.triggered.connect(self.doPaste)
        self.paste_act.setEnabled(False)

        bold_act = QAction(bold_icon, "Bold", self)
        bold_act.setShortcut(Qt.CTRL + Qt.Key_B)
        bold_act.triggered.connect(self.bold)

        italic_act = QAction(italic_icon, "Italic", self)
        italic_act.setShortcut(Qt.CTRL + Qt.Key_I)
        italic_act.triggered.connect(self.italic)

        image_act = QAction(image_icon, "Image", self)
        image_act.setShortcut(Qt.CTRL + Qt.Key_G)
        image_act.triggered.connect(self.insertImage)
        image_act.setToolTip("Insert an image")

        table_act = QAction(table_icon, "Table", self)
        table_act.setShortcut(Qt.CTRL + Qt.Key_T)
        table_act.triggered.connect(self.insertTable)
        table_act.setToolTip("Insert a table")

        about_act = QAction("&About", self)
        about_act.triggered.connect(self.about)
        about_act.setStatusTip("Show the application's About box")

        file_menu = self.menuBar().addMenu("&File")
        file_menu.addAction(new_act)
        file_menu.addAction(open_act)
        file_menu.addAction(book_act)
        file_menu.addAction(pdf_act)
        file_menu.addSeparator()
        file_menu.addAction(settings_act)
        file_menu.addSeparator()
        file_menu.addAction(exit_act)

        edit_menu = self.menuBar().addMenu("&Edit")
        edit_menu.addAction(self.undo_act)
        edit_menu.addAction(self.redo_act)
        edit_menu.addSeparator()
        edit_menu.addAction(self.cut_act)
        edit_menu.addAction(self.copy_act)
        edit_menu.addAction(self.paste_act)

        format_menu = self.menuBar().addMenu("&Format")
        format_menu.addAction(bold_act)
        format_menu.addAction(italic_act)

        insert_menu = self.menuBar().addMenu("&Insert")
        insert_menu.addAction(image_act)
        insert_menu.addAction(table_act)

        help_menu = self.menuBar().addMenu("&Help")
        help_menu.addAction(about_act)

        file_tool_bar = self.addToolBar("File")
        file_tool_bar.addAction(new_act)
        file_tool_bar.addAction(open_act)
        file_tool_bar.addAction(book_act)

        format_tool_bar = self.addToolBar("Format")
        format_tool_bar.addAction(bold_act)
        format_tool_bar.addAction(italic_act)

        insert_toolbar = self.addToolBar("Insert")
        insert_toolbar.addAction(image_act)
        insert_toolbar.addAction(table_act)

    def doUndo(self):
        self.text_edit.undo()

    def doRedo(self):
        self.text_edit.redo()

    def doCut(self):
        self.text_edit.cut()

    def doCopy(self):
        self.text_edit.copy()

    def doPaste(self):
        self.text_edit.paste()

    def insertImage(self):
        if not self.book:
            QMessageBox.warning(self, QCoreApplication.applicationName(),
                                "You have to load or create a book first!")
            return
        if not self.filename:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select part from the book content first!")
            return
        if self.image_list.count() == 0:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to add an image to the image list first!")
            return
        if not self.image_list.currentItem():
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select an image from the image list first!")
            return

        item = self.image_list.currentItem()
        filename = item.text()
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        base = filename.split(".")[0].replace("_", "-")
        cursor.insertText("![" + base + "](../images/" + filename + " \"" +
                          base + "\")")
        cursor.setPosition(pos)
        self.text_edit.setTextCursor(cursor)

    def insertTable(self):
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        cursor.insertText(
            "| alignLeft | alignCenter | unAligned | alignRight |\n"
            "|  :---     |   :---:     |   ---     |   ---:     |\n"
            "|  cell a   |   cell b    |   cell c  |   cell d   |\n"
            "|  cell e   |   cell f    |   cell g  |   cell h   |\n")
        cursor.setPosition(pos)
        self.text_edit.setTextCursor(cursor)

    def createStatusBar(self):
        self.statusBar().showMessage("Ready")

    def about(self):
        QMessageBox.about(
            self, "About " + QCoreApplication.applicationName(),
            "EbookCreator\nVersion: " + QCoreApplication.applicationVersion() +
            "\n(C) Copyright 2019 Olaf Japp. All rights reserved.\n\nThis program is provided AS IS with NO\nWARRANTY OF ANY KIND, INCLUDING THE\nWARRANTY OF DESIGN, MERCHANTABILITY AND\nFITNESS FOR A PATICULAR PURPOSE."
        )

    def newFile(self):
        dlg = ProjectWizard(self.install_directory, parent=self)
        dlg.loadBook.connect(self.loadBook)
        dlg.show()

    def open(self):
        fileName = ""
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setNameFilter("EbookCreator (book.qml);;All (*)")
        dialog.setWindowTitle("Load Ebook")
        dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setDirectory(os.path.join(self.install_directory, "sources"))
        if dialog.exec_():
            fileName = dialog.selectedFiles()[0]
        del dialog
        if not fileName:
            return
        self.loadBook(fileName)

    def writeSettings(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        settings.setValue("geometry", self.saveGeometry())
        settings.setValue("lastBook", self.last_book)

    def readSettings(self):
        settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                             QCoreApplication.organizationName(),
                             QCoreApplication.applicationName())
        geometry = settings.value("geometry", QByteArray())
        self.last_book = settings.value("lastBook")
        if not geometry:
            availableGeometry = QApplication.desktop().availableGeometry(self)
            self.resize(availableGeometry.width() / 3,
                        availableGeometry.height() / 2)
            self.move((availableGeometry.width() - self.width()) / 2,
                      (availableGeometry.height() - self.height()) / 2)
        else:
            self.restoreGeometry(geometry)

    def bold(self):
        if not self.filename:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select part from the book content first!")
            return
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        if not cursor.hasSelection():
            cursor.select(QTextCursor.WordUnderCursor)
        cursor.insertText("**" + cursor.selectedText() + "**")
        cursor.setPosition(pos + 2)
        self.text_edit.setTextCursor(cursor)

    def italic(self):
        if not self.filename:
            QMessageBox.warning(
                self, QCoreApplication.applicationName(),
                "You have to select part from the book content first!")
            return
        cursor = self.text_edit.textCursor()
        pos = cursor.position()
        if not cursor.hasSelection():
            cursor.select(QTextCursor.WordUnderCursor)
        cursor.insertText("*" + cursor.selectedText() + "*")
        cursor.setPosition(pos + 1)
        self.text_edit.setTextCursor(cursor)

    def create(self):
        filename = ""
        dialog = QFileDialog()
        dialog.setFileMode(QFileDialog.AnyFile)
        dialog.setNameFilter("ePub3 (*.epub);;All (*)")
        dialog.setWindowTitle("Create Ebook")
        dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        dialog.setAcceptMode(QFileDialog.AcceptSave)
        dialog.setDirectory(self.install_directory)
        dialog.setDefaultSuffix("epub")
        if dialog.exec_():
            filename = dialog.selectedFiles()[0]
        del dialog
        if not filename:
            return
        QApplication.setOverrideCursor(Qt.WaitCursor)
        createEpub(filename, self.book, self)
        QApplication.restoreOverrideCursor()

    def loadStatusChanged(self, status):
        if status == 1:
            self.book = self.component.create()
            if self.book is not None:
                self.book.setFilename(self.last_book)
                self.book.setWindow(self)
            else:
                for error in self.component.errors():
                    print(error.toString())
                return

            self.content_list.clear()
            for part in self.book.parts:
                item = QListWidgetItem()
                item.setText(part.name)
                item.setData(1, part)
                self.content_list.addItem(item)

            self.loadImages()
            self.setWindowTitle(QCoreApplication.applicationName() + " - " +
                                self.book.name)

            self.content.setExpanded(True)
            self.content_list.setCurrentRow(0)
        elif status == 3:
            for error in self.component.errors():
                print(error.toString())
            return

    def loadBook(self, filename):
        self.last_book = filename
        self.filename = ""
        engine = QQmlEngine()
        self.component = QQmlComponent(engine)
        self.component.statusChanged.connect(self.loadStatusChanged)
        self.component.loadUrl(QUrl.fromLocalFile(filename))

    def settingsDialog(self):
        dlg = SettingsDialog(self.theme,
                             self.palette().highlight().color().name(),
                             parent=self)
        dlg.exec()
        if dlg.theme != self.theme or dlg.hilite_color != self.palette(
        ).highlight().color().name():
            settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
                                 QCoreApplication.organizationName(),
                                 QCoreApplication.applicationName())
            settings.setValue("theme", dlg.theme)
            settings.setValue("hiliteColor", dlg.hilite_color)

            msgBox = QMessageBox()
            msgBox.setText("Please restart the app to change the theme!")
            msgBox.exec()

    def textChanged(self):
        if self.filename:
            with open(self.filename, "w") as f:
                f.write(self.text_edit.toPlainText())

        self.lock = Lock()
        with self.lock:
            if not self.tread_running:
                self.tread_running = True
                self.htmlReady.connect(self.previewReady)
                thread = Thread(target=self.createHtml,
                                args=(self.text_edit.toPlainText(), ))
                thread.daemon = True
                thread.start()

    def previewReady(self, html):
        self.preview.setHtml(
            html,
            baseUrl=QUrl(
                Path(os.path.join(self.book.source_path, "parts",
                                  "index.html")).as_uri()))
        self.htmlReady.disconnect()
        with self.lock:
            self.tread_running = False

    def createHtml(self, text):
        html = "<html>\n<head>\n"
        html += "<link href=\"../css/pastie.css\" rel=\"stylesheet\" type=\"text/css\"/>\n"
        html += "<link href=\"../css/stylesheet.css\" rel=\"stylesheet\" type=\"text/css\"/>\n"
        html += "</head>\n<body>\n"
        html += markdown(text,
                         html4tags=False,
                         extras=[
                             "fenced-code-blocks", "wiki-tables", "tables",
                             "header-ids"
                         ])
        html += "\n</body>\n</html>"
        html = addLineNumbers(html)
        self.htmlReady.emit(html)

    def pdfExport(self):
        p = PdfExport("test.pdf", self.book, self.statusBar())
Пример #6
0
class EventSelectionWindow(QMainWindow):
	def __init__(self, main_window):
		super().__init__()

		self.main_window = main_window

		# Defining some variables of the window
		self.title_window = "Event Selection"

		# Setting the window appropriately
		self.setWindowTitle(self.title_window)
		self.set_position()

		self.palette_main_window = self.palette()
		self.palette_main_window.setColor(QPalette.Window, Qt.black)

		# Initiate the sub-widgets
		self.init_window()

	def init_window(self):

		# Read the available labels
		self.labels = list()
		with open('../config/classes.txt') as file:
			for cnt, line in enumerate(file):
				self.labels.append(line.rstrip())

		# Read the available second labels
		self.second_labels = list()
		with open('../config/second_classes.txt') as file:
			for cnt, line in enumerate(file):
				self.second_labels.append(line.rstrip())

		# Read the available third labels
		self.third_labels = list()
		with open('../config/third_classes.txt') as file:
			for cnt, line in enumerate(file):
				self.third_labels.append(line.rstrip())

		self.list_widget = QListWidget()
		self.list_widget.clicked.connect(self.clicked)

		for item_nbr, element in enumerate(self.labels):
			self.list_widget.insertItem(item_nbr,element)

		self.list_widget_second = QListWidget()
		self.list_widget_second.clicked.connect(self.clicked)

		for item_nbr, element in enumerate(self.second_labels):
			self.list_widget_second.insertItem(item_nbr,element)

		self.list_widget_third = QListWidget()
		self.list_widget_third.clicked.connect(self.clicked)

		for item_nbr, element in enumerate(self.third_labels):
			self.list_widget_third.insertItem(item_nbr,element)

		# Layout the different widgets
		central_display = QWidget(self)
		self.setCentralWidget(central_display)
		final_layout = QHBoxLayout()
		final_layout.addWidget(self.list_widget)
		final_layout.addWidget(self.list_widget_second)
		final_layout.addWidget(self.list_widget_third)
		central_display.setLayout(final_layout)

		self.to_second = False
		self.to_third = False
		self.first_label = None
		self.second_label = None

	def clicked(self, qmodelindex):
		print("clicked")

	def set_position(self):
		self.xpos_window = self.main_window.pos().x()+self.main_window.frameGeometry().width()//4
		self.ypos_window = self.main_window.pos().y()+self.main_window.frameGeometry().height()//4
		self.width_window = self.main_window.frameGeometry().width()//2
		self.height_window = self.main_window.frameGeometry().height()//2
		self.setGeometry(self.xpos_window, self.ypos_window, self.width_window, self.height_window)

	def keyPressEvent(self, event):

		if event.key() == Qt.Key_Return:
			if not self.to_second and not self.to_third:
				self.first_label = self.list_widget.currentItem().text()
				self.list_widget_second.setFocus()
				self.to_second=True
			elif self.to_second:
				self.second_label = self.list_widget_second.currentItem().text()
				self.to_second=False
				self.to_third=True
				self.list_widget_third.setFocus()
			elif self.to_third:
				position = self.main_window.media_player.media_player.position()
				self.main_window.list_manager.add_event(Event(self.first_label,self.main_window.half,ms_to_time(position),self.second_label, position, self.list_widget_third.currentItem().text()))
				self.main_window.list_display.display_list(self.main_window.list_manager.create_text_list())
				self.first_label = None
				self.second_label = None
				self.to_third=False
				# Save
				path_label = self.main_window.media_player.get_last_label_file()
				self.main_window.list_manager.save_file(path_label, self.main_window.half)
				self.hide()
				self.list_widget_second.setCurrentRow(-1)
				self.list_widget_third.setCurrentRow(-1)
				self.main_window.setFocus()



		if event.key() == Qt.Key_Escape:
			self.to_second=False
			self.to_third=False
			self.first_label = None	
			self.second_label = None
			self.list_widget_second.setCurrentRow(-1)
			self.list_widget_third.setCurrentRow(-1)
			self.hide()
			self.main_window.setFocus()
Пример #7
0
class repairshopStack(QWidget):
    def __init__(self):

        super(repairshopStack, self).__init__()
        self.leftlist = QListWidget()
        self.leftlist.setFixedWidth(250)
        self.leftlist.insertItem(0, 'Order Stock')
        self.leftlist.insertItem(2, 'View Shop Stock')
        self.leftlist.insertItem(4, 'Manufacturer Stock')

        self.stack1 = QWidget()
        self.stack3 = QWidget()
        self.stack5 = QWidget()

        self.stack1UI()
        self.stack3UI()
        self.stack5UI()

        self.Stack = QStackedWidget(self)
        self.Stack.addWidget(self.stack1)
        self.Stack.addWidget(self.stack3)
        self.Stack.addWidget(self.stack5)

        hbox = QHBoxLayout(self)
        hbox.addWidget(self.leftlist)
        hbox.addWidget(self.Stack)

        self.setLayout(hbox)
        self.leftlist.currentRowChanged.connect(self.display)
        self.setGeometry(500, 350, 200, 200)
        self.setWindowTitle('Stock Management')
        self.show()

    def stack1UI(self):  # ADD STOCK UI
        layout = QFormLayout()
        self.mes = QLabel()

        self.ok = QPushButton('Order Stock', self)
        clear = QPushButton('Clear', self)

        self.stock_name = QLineEdit()
        layout.addRow("Stock Name", self.stock_name)

        self.stock_count = QLineEdit()
        layout.addRow("Quantity", self.stock_count)

        layout.addWidget(self.ok)
        layout.addWidget(clear)
        layout.addWidget(self.mes)

        self.ok.clicked.connect(self.on_click)

        # clear the data from the screen
        clear.clicked.connect(self.stock_name.clear)
        clear.clicked.connect(self.stock_count.clear)
        self.stack1.setLayout(layout)

    def on_click(self):  # update car stock
        # remove quantity from Manufacturer stock
        stock_name_dec = self.stock_name.text().replace(' ', '_').lower()
        stock_count_dec = -(int(self.stock_count.text()))

        # add quantity to Shop stock
        stock_name_inc = self.stock_name.text().replace(' ', '_').lower()
        stock_count_inc = (int(self.stock_count.text()))

        if (stock_count_dec and stock_count_inc > 0):
            mp.del_shop_stock(stock_name_dec, stock_count_dec)
            message = mp.add_shop_stock(stock_name_inc, stock_count_inc)
            self.mes.setText(message)
        else:
            self.mes.setText('Invalid quantity')

    def stack3UI(self):  # VIEW SHOP STOCK TAB
        layout = QVBoxLayout()
        self.srb = QPushButton()
        self.srb.setText("Get Search Result.")
        self.View = QTableWidget()
        self.lbl3 = QLabel()
        self.lbl_conf_text = QLabel()
        self.lbl_conf_text.setText("Enter the search keyword:")
        self.conf_text = QLineEdit()

        self.View.setColumnCount(3)
        self.View.setColumnWidth(0, 250)
        self.View.setColumnWidth(1, 250)
        self.View.setColumnWidth(2, 200)
        self.View.insertRow(0)
        self.View.setItem(0, 0, QTableWidgetItem('Stock Name'))
        self.View.setItem(0, 1, QTableWidgetItem('Quantity'))
        self.View.setItem(0, 2, QTableWidgetItem('Cost(Per Unit)'))

        layout.addWidget(self.View)
        layout.addWidget(self.lbl_conf_text)
        layout.addWidget(self.conf_text)
        layout.addWidget(self.srb)
        layout.addWidget(self.lbl3)
        self.srb.clicked.connect(self.show_search)
        self.stack3.setLayout(layout)

    def show_search(self):
        # checks database for stock items
        if self.View.rowCount() > 1:
            for i in range(1, self.View.rowCount()):
                self.View.removeRow(1)

        x_act = mp.show_shop_stock()
        x = []
        if self.conf_text.text() != '':
            for i in range(0, len(x_act)):
                a = list(x_act[i])
                if self.conf_text.text().lower() in a[0].lower():
                    x.append(a)
        else:
            x = mp.show_shop_stock()

        if len(x) != 0:
            for i in range(1, len(x) + 1):
                self.View.insertRow(i)
                a = list(x[i - 1])
                self.View.setItem(
                    i, 0, QTableWidgetItem(a[0].replace('_', ' ').upper()))
                self.View.setItem(i, 1, QTableWidgetItem(str(a[1])))
                self.View.setItem(i, 2, QTableWidgetItem(str(a[2])))
                self.View.setRowHeight(i, 50)
            self.lbl3.setText('Viewing Stock Database.')
        else:
            self.lbl3.setText('No valid information in database.')

    def stack5UI(self):  # VIEW MANUFACTURER STOCK TAB
        layout_manu = QVBoxLayout()
        self.srb5 = QPushButton()
        self.srb5.setText("Get Search Result.")
        self.View5 = QTableWidget()
        self.lbl5 = QLabel()
        self.lbl_conf_text5 = QLabel()
        self.lbl_conf_text5.setText("Enter the search keyword:")
        self.conf_text5 = QLineEdit()

        self.View5.setColumnCount(3)
        self.View5.setColumnWidth(0, 250)
        self.View5.setColumnWidth(1, 250)
        self.View5.setColumnWidth(2, 200)
        self.View5.insertRow(0)
        self.View5.setItem(0, 0, QTableWidgetItem('Stock Name'))
        self.View5.setItem(0, 1, QTableWidgetItem('Quantity'))
        self.View5.setItem(0, 2, QTableWidgetItem('Cost(Per Unit)'))

        layout_manu.addWidget(self.View5)
        layout_manu.addWidget(self.lbl_conf_text5)
        layout_manu.addWidget(self.conf_text5)
        layout_manu.addWidget(self.srb5)
        layout_manu.addWidget(self.lbl5)
        self.srb5.clicked.connect(self.show_manu_search)
        self.stack5.setLayout(layout_manu)

    def show_manu_search(self):
        # checks database for stock items
        if self.View5.rowCount() > 1:
            for i in range(1, self.View5.rowCount()):
                self.View5.removeRow(1)

        x_act = mp.show_manu_order_stock()
        x = []
        if self.conf_text5.text() != '':
            for i in range(0, len(x_act)):
                a = list(x_act[i])
                if self.conf_text5.text().lower() in a[0].lower():
                    x.append(a)
        else:
            x = mp.show_manu_order_stock()

        if len(x) != 0:
            for i in range(1, len(x) + 1):
                self.View5.insertRow(i)
                a = list(x[i - 1])
                self.View5.setItem(
                    i, 0, QTableWidgetItem(a[0].replace('_', ' ').upper()))
                self.View5.setItem(i, 1, QTableWidgetItem(str(a[1])))
                self.View5.setItem(i, 2, QTableWidgetItem(str(a[2])))
                self.View5.setRowHeight(i, 50)
            self.lbl5.setText('Viewing Manufacturer Stock Database.')
        else:
            self.lbl5.setText('No valid information in database.')

    def display(self, i):
        self.Stack.setCurrentIndex(i)
Пример #8
0
class Gui(QMainWindow):
    mainText = None
    mast = None
    tenants = None
    inc = None
    rowStore = None
    Gen = None
    gen = None
    mastInput = None
    keyNum = 1

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        app_icon = QIcon()
        app_icon.addFile("key.png", QSize(256, 256))
        self.setWindowIcon(app_icon)
        # open
        openFile = QAction('Open', self)
        openFile.setShortcut('Ctrl+O')
        openFile.setStatusTip('Open new File')
        openFile.triggered.connect(self.fileOpen)
        # save
        saveFile = QAction('Save', self)
        saveFile.setShortcut('Ctrl+S')
        saveFile.setStatusTip('Save new File')
        saveFile.triggered.connect(self.fileSave)
        printAction = QAction("Print", self)
        printAction.triggered.connect(self.printSetup)
        # exit
        exitAction = QAction('Exit', self)
        exitAction.triggered.connect(self.closeEvent)
        # menu object
        menubar = self.menuBar()
        # file drop down
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(openFile)
        fileMenu.addAction(saveFile)
        fileMenu.addAction(printAction)
        fileMenu.addAction(exitAction)
        # widgets
        grid = QGridLayout()
        horiz = QVBoxLayout()
        bigHoriz = QHBoxLayout()
        horizLayout = QHBoxLayout()
        window = QWidget()
        window.setLayout(bigHoriz)
        leftPane = QFormLayout()
        bigHoriz.addLayout(leftPane)
        bigHoriz.addLayout(horiz)
        self.setCentralWidget(window)
        btn = QPushButton('Generate', self)
        btn.clicked.connect(lambda: self.runGen())
        clearBtn = QPushButton("Clear", self)
        clearBtn.clicked.connect(self.clearList)
        self.mainText = QListWidget(self)
        self.mainText.itemSelectionChanged.connect(self.listItemClicked)
        self.mainText.setFont(
            QFontDatabase.systemFont(QFontDatabase.FixedFont))
        self.mastInput = []
        i = 0
        while i < 6:
            t = QLineEdit()
            t.setMaxLength(1)
            t.setAlignment(Qt.AlignHCenter)
            t.textChanged.connect(self.textInputed)
            self.mastInput.append(t)
            i = i + 1
        for e in self.mastInput:
            horizLayout.addWidget(e)
        self.mast = QLineEdit()
        self.tenants = QLineEdit()
        self.inc = QLineEdit()
        self.title = QLineEdit()
        self.title.setMinimumWidth(200)
        self.desc = QLineEdit()
        self.address = QLineEdit()
        self.contact = QLineEdit()
        self.phone = QLineEdit()
        self.email = QLineEdit()
        self.notes = QTextEdit()
        self.keyway = QLineEdit()
        label = QLabel("Master Cuts")
        incLabel = QLabel("Increment")
        tenantLabel = QLabel("Tenants")
        # add widgets to layouts
        leftPane.addRow(QLabel("Title"), self.title)
        leftPane.addRow(QLabel("Description"), self.desc)
        leftPane.addRow(QLabel("Keyway"), self.keyway)
        leftPane.addRow(QLabel("Address"), self.address)
        leftPane.addRow(QLabel("contact"), self.contact)
        leftPane.addRow(QLabel("Phone"), self.phone)
        leftPane.addRow(QLabel("Email"), self.email)
        leftPane.addRow(QLabel("Notes"), self.notes)
        grid.addWidget(incLabel, 3, 0)
        grid.addWidget(tenantLabel, 2, 0)
        grid.addWidget(label, 1, 0)
        grid.addWidget(btn, 0, 0)
        horiz.addWidget(self.mainText)
        horiz.addLayout(grid)
        # horiz.addLayout(horizLayout)
        grid.addWidget(clearBtn, 0, 1)
        grid.addWidget(self.tenants, 2, 1)
        grid.addWidget(self.inc, 3, 1)
        grid.addLayout(horizLayout, 1, 1)
        # window properties
        self.setGeometry(300, 300, 500, 425)
        self.setWindowTitle('PySchlageGen')
        self.show()

    def textInputed(self, string):
        if len(string) == 1:
            self.focusNextChild()

    def getGen(self):
        return self.gen

    def runGen(self):
        self.mainText.clear()
        self.keyNum = 1
        text = self.mast.text()
        mastCuts = []
        try:
            for e in self.mastInput:
                if e.text():
                    mastCuts.append(int(e.text()))
            tenants = int(self.tenants.text())
            inc = int(self.inc.text())
            mastCuts = list(map(int, mastCuts))
            self.gen = schlageGen()
            self.gen.addMasterKey(mastCuts)
            output = self.gen.genSystem(tenants, inc)
            self.displayKeys(output)
        except:
            pass

    def displayKeys(self, output):
        i = 0
        for o in output:
            if self.keyNum < 10:
                f = str(self.keyNum) + ":     "
            elif self.keyNum < 100:
                f = str(self.keyNum) + ":   "
            elif self.keyNum < 1000:
                f = str(self.keyNum) + ": "
            else:
                f = str(self.keyNum) + ":"
            for e in o:
                f = f + str(e) + " "
            item = QListWidgetItem(f)
            self.mainText.insertItem(i, item)
            i = i + 1
            self.keyNum = self.keyNum + 1

    def formatText(self, flist, space=True, inj=" "):
        out = ""
        for e in flist[:-1]:
            out = out + str(e)
            if space:
                out = out + inj
        out = out + str(flist[-1])
        return out

    def printSetup(self):
        if self.gen != None:
            printSetup = PrintSetup(self)
            printSetup.exec()
        else:
            QMessageBox.about(self, "Error","Please generate a system before printing.")

    def clearList(self):
        self.title.clear()
        self.desc.clear()
        self.address.clear()
        self.keyway.clear()
        self.contact.clear()
        self.phone.clear()
        self.email.clear()
        self.keyNum = 1
        self.notes.clear()
        self.mainText.clear()
        self.tenants.clear()
        self.inc.clear()
        for e in self.mastInput:
            e.clear()

    def listItemClicked(self):
        item = self.mainText.currentItem()
        flags = item.flags()
        if flags & Qt.ItemIsEnabled:
            if self.rowStore != None:
                self.mainText.takeItem(self.rowStore + 1)
                self.mainText.takeItem(self.rowStore + 1)
            tenCuts = self.gen.getSystem()[int(item.text().split(":")[0]) - 1]
            tenCuts = list(map(int, tenCuts))
            output = self.gen.bittingCalc(tenCuts)
            row = self.mainText.currentRow()
            self.rowStore = row
            flags = item.flags()
            flags ^= Qt.ItemIsEnabled
            item = QListWidgetItem("        " + self.formatText(output[0]))
            item.setFlags(flags)
            item2 = QListWidgetItem("        " + self.formatText(output[1]))
            item2.setFlags(flags)
            self.mainText.insertItem(row + 1, item)
            self.mainText.insertItem(row + 2, item2)

    def fileOpen(self):
        self.clearList()
        home = expanduser("~")
        fname = QFileDialog.getOpenFileName(self, 'Open file', home, "*.mks")
        data = None
        if fname[0] != '':
            with open(fname[0], 'r') as infile:
                data = infile.read()
            sys = data.split("`")
            self.gen = schlageGen()
            master = list(map(int, sys[0]))
            self.gen.addMasterKey(master)
            del sys[0]
            self.inc.setText(str(sys[0]))
            del sys[0]
            self.title.setText(str(sys[0]))
            del sys[0]
            self.desc.setText(str(sys[0]))
            del sys[0]
            self.keyway.setText(str(sys[0]))
            del sys[0]
            self.address.setText(str(sys[0]))
            del sys[0]
            self.contact.setText(str(sys[0]))
            del sys[0]
            self.phone.setText(str(sys[0]))
            del sys[0]
            self.email.setText(str(sys[0]))
            del sys[0]
            self.notes.setPlainText(str(sys[0]))
            del sys[0]
            self.gen.setTenants(sys)
            self.displayKeys(sys)
            i = 0
            while i < len(master):
                self.mastInput[i].setText(str(master[i]))
                i = i + 1
            self.tenants.setText(str(len(sys)))

    def fileSave(self):
        if self.gen != None:
            home = expanduser("~")
            fname = QFileDialog.getSaveFileName(self, 'Open file', home, "*.mks")
            if fname[0]:
                with open(fname[0], "w") as thefile:
                    thefile.write("%s`" % self.formatText(
                        self.gen.getMasterKey(), False))
                    thefile.write("%s`" % self.inc.text())
                    thefile.write("%s`" % self.title.text())
                    thefile.write("%s`" % self.desc.text())
                    thefile.write("%s`" % self.keyway.text())
                    thefile.write("%s`" % self.address.text())
                    thefile.write("%s`" % self.contact.text())
                    thefile.write("%s`" % self.phone.text())
                    thefile.write("%s`" % self.email.text())
                    thefile.write("%s`" % self.notes.toPlainText())
                    for e in self.gen.getSystem()[:-1]:
                        thefile.write("%s`" % self.formatText(e, False))
                    thefile.write("%s" % self.formatText(
                        self.gen.getSystem()[-1], False))
        else:
            QMessageBox.about(self, "Error","Please generate a system before saving.")

    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Message',
                                     "Are you sure to quit?", QMessageBox.Yes |
                                     QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            sys.exit()
        else:
            if event:
                event.ignore()
Пример #9
0
class App(QMainWindow):
    game_filter_positions = {
        "nhl": ['C', 'LW', 'RW', 'D'],
        "nfl": ['QB', 'RB', 'WR', 'TE', 'K', 'DEF']
    }
    game_projection_columns = {
        "nhl": {
            'name': 'Name',
            'posn_display': 'POS',
            'team': 'Team',
            'csh_rank': 'CSH',
            'preseason_rank': 'Preseason',
            'current_rank': 'Current',
            'GP': 'GP',
            'fantasy_score': 'Score'
        },
        "nfl": {
            'name': 'Name',
            'posn_display': 'POS',
            'team': 'Team',
            'Bye': 'Bye',
            'fan_points': 'fan_points',
            'overall_rank': 'Rank',
            'fp_rank': 'FP_rank',
            'position_rank': 'FP_Pos'
        }
    }

    # ['name', 'position', 'player_id', 'GP', 'Bye', 'fan_points',
    #    'overall_rank', 'percent_rostered', 'pass_yds', 'pass_td', 'pass_int',
    #    'pass_sack', 'rush_attempts', 'rush_yards', 'rush_tds',
    #    'receiving_targets', 'receiving_receptions', 'receiving_yards',
    #    'receiving_tds', 'team']
    def __init__(self):
        super().__init__()
        self.title = "Yahoo Draft Board"
        self.left = 10
        self.top = 10
        self.width = 3200
        self.height = 1000
        self.main_widget = QWidget(self)
        self.oauth = OAuth2(None, None, from_file='oauth2.json')
        league_id = "403.l.41177"
        self.game_type = "nhl"
        self.game_year = 2020
        self.league = None
        self.setup_menubar()
        self.my_draft_picks = None
        self.label_num_picks_before_pick = QLabel(
            "Number picks until your turn: 4")
        self.positional_filter_checkboxes = None
        # runnable to grab draft picks from yahoo
        self.draft_monitor = None
        self.draft_complete = False
        self.draft_results = []
        self.position_filtering_layout = QHBoxLayout()
        self.draft_list_widget = QListWidget()
        self.projection_table = QTableView()
        self.projection_table.setSortingEnabled(True)

        self.pause_draft_button = QPushButton("Pause")
        self.pause_draft_button.clicked.connect(self.pause_pressed)

        self.team_combo_box = QComboBox()
        self.draft_status_label = QLabel("Status: Running")

        self.roster_table = QTableView()
        self.roster_table_model = None

        # self.league_changed("403.l.41177", "nhl", 2020)
        self.league_changed("406.l.246660", "nfl", 2021)
        self.initUI()

    def setup_menubar(self):
        menuBar = QMenuBar(self)
        menuBar.setNativeMenuBar(False)
        self.setMenuBar(menuBar)
        leagueMenu = menuBar.addMenu("&League")
        years = [2021, 2020, 2019, 2018]
        fantasy_games = ['nhl', 'nfl']

        for year in years:
            year_menu = leagueMenu.addMenu(str(year))
            for game in fantasy_games:
                game_menu = year_menu.addMenu(game)
                gm = yfa.Game(self.oauth, game)
                ids = gm.league_ids(year)
                for id in ids:
                    lg = gm.to_league(id)
                    lg_action = QAction(lg.settings()['name'], self)
                    lg_action.league_id = id
                    lg_action.game_type = game
                    lg_action.year = year
                    game_menu.addAction(lg_action)
                    game_menu.triggered[QAction].connect(self.league_selected)

    def league_selected(self, q):
        print("league selected")
        if not (q.league_id == self.league_id and q.year == self.game_year):
            self.league_changed(q.league_id, q.game_type, q.year)

    def get_scraped_draft_results(self):
        scraped_draft_results = None
        draft_scrape_filename = f".cache/gui_draft/draft-scrape-{self.league_id}-{self.game_type}-{self.game_year}.pkl"
        if os.path.exists(draft_scrape_filename):
            with open(draft_scrape_filename, "rb") as f:
                scraped_draft_results = pickle.load(f)
        else:
            scraped_draft_results = retrieve_draft_order(self.league)
            with open(draft_scrape_filename, "wb") as f:
                pickle.dump(scraped_draft_results, f)
        return scraped_draft_results

    def league_changed(self, league_id, game_type, year):
        print(
            f"League changed, id: {league_id} - type: {game_type} - year:{year}"
        )
        if self.draft_monitor is not None and self.league_id != league_id:
            self.draft_monitor.stop_flag = True
            print("Draft thread cancelled")
        self.league_id = league_id
        self.game_type = game_type
        self.game_year = year
        self.league = yfa.league.League(self.oauth, self.league_id)
        self.my_draft_picks = self._get_draft_picks(self.league.team_key())

        self.projections_df = self.retrieve_player_projections()

        # figure out if we have keepers
        scraped_draft_results = None
        if "nfl" == self.game_type:
            # for keeper leagues, would be defined in a screen scrape.  lets do that and simulate them
            scraped_draft_results = self.get_scraped_draft_results()

            # assign keepers to teams
            for team, keepers in scraped_draft_results['keepers'].items():
                for keeper in keepers:
                    if 'team' in keeper.keys():
                        self.projections_df.loc[
                            self.projections_df.name.str.
                            contains(keeper['name']) &
                            (self.projections_df.team ==
                             keeper['team'].upper()),
                            ['draft_fantasy_key', 'is_keeper']] = team, True
                    else:
                        self.projections_df.loc[
                            self.projections_df.name.str.
                            contains(keeper['name']),
                            ['draft_fantasy_key', 'is_keeper']] = team, True

        base_columns = App.game_projection_columns[self.game_type].copy()
        # add league specifc scoring cats for hockey
        if self.game_type == "nhl":
            for stat in self.league.stat_categories():
                if stat['position_type'] == 'P':
                    base_columns[stat['display_name']] = stat['display_name']
        self.projections_model = PandasModel(
            self.projections_df,
            column_headers=base_columns,
            valid_positions=App.game_filter_positions[self.game_type],
            highlight_personal_ranking_differences=self.game_type == "nhl")

        self.team_name_by_id = {
            team['team_key']: team['name']
            for team in self.league.teams()
        }
        self.team_key_by_name = {
            team['name']: team['team_key']
            for team in self.league.teams()
        }

        self.build_filter_panel()

        self.projections_model.update_filters(self._position_filter_list())

        self.draft_complete = False
        self.draft_results = []

        self.projection_table.setModel(self.projections_model)
        self.pause_draft_button = QPushButton("Pause")
        self.pause_draft_button.clicked.connect(self.pause_pressed)

        self.team_combo_box.clear()
        for team in self.league.teams():
            self.team_combo_box.addItem(team['name'], team['team_key'])
        self.team_combo_box.setCurrentIndex(
            self.team_combo_box.findData(self.league.team_key()))

        self.roster_table_model = DraftedRosterModel(
            self.draft_results,
            self.league.team_key(),
            self.projections_df,
            keepers=scraped_draft_results['keepers']
            if scraped_draft_results else None)
        self.roster_table.setModel(self.roster_table_model)

        self.draft_list_widget.clear()
        self.update_picks_until_next_player_pick(0)
        the_keepers = scraped_draft_results.get(
            'keepers', None) if scraped_draft_results else None
        self.draft_monitor = DraftMonitor(self.league, keepers=the_keepers)
        self.draft_monitor.register_draft_listener(self)
        QThreadPool.globalInstance().start(self.draft_monitor)

    def build_filter_panel(self):
        '''
        builds the position checkbox filters
        depends on game_type
        '''
        # clear any checkboxes
        for i in reversed(range(self.position_filtering_layout.count())):
            self.position_filtering_layout.itemAt(i).widget().close()
            self.position_filtering_layout.takeAt(i)
        self.positional_filter_checkboxes = []
        for position in self.game_filter_positions[self.game_type]:
            box = QCheckBox(position)
            box.setChecked(True)
            box.clicked.connect(self.filter_checked)
            self.positional_filter_checkboxes.append(box)
            self.position_filtering_layout.addWidget(box)

        all_button = QPushButton('All')
        all_button.pressed.connect(self.filter_all_selected)
        self.position_filtering_layout.addWidget(all_button)
        none_button = QPushButton('None')
        none_button.pressed.connect(self.filter_none_selected)
        self.position_filtering_layout.addWidget(none_button)

    def retrieve_player_projections(self):
        projections = None
        if "nhl" == self.game_type:
            projections = retrieve_yahoo_rest_of_season_projections(
                self.league.league_id)
            scoring_stats = [
                stat['display_name'] for stat in self.league.stat_categories()
                if stat['position_type'] == 'P'
            ]
            produce_csh_ranking(projections,
                                scoring_stats,
                                projections.index,
                                ranking_column_name='fantasy_score')
            projections['fantasy_score'] = round(projections['fantasy_score'],
                                                 3)
            projections.reset_index(inplace=True)
            projections.sort_values("fantasy_score",
                                    ascending=False,
                                    inplace=True,
                                    ignore_index=True)
            projections['csh_rank'] = projections.index + 1

            projections['rank_diff'] = projections['csh_rank'] - projections[
                'current_rank']
        else:
            projections = pd.read_csv(
                f"{self.game_year}-{self.league_id}-predictions-merged.csv",
                converters={
                    "position":
                    lambda x: x.strip("[]").replace('"', "").replace("'", "").
                    replace(" ", "").split(",")
                })
            projections.sort_values('overall_rank', inplace=True)

        projections['draft_fantasy_key'] = -1
        projections['is_keeper'] = False
        # use this for rendering eligible positions
        projections['posn_display'] = projections['position'].apply(
            lambda x: ", ".join(x))

        return projections

    def draft_status_changed(self, is_paused):
        self.draft_status_label.setText(
            "Status: Paused" if is_paused else "Status: Running")

    def _get_draft_picks(self, team_key):
        scraped = self.get_scraped_draft_results()
        if 'predraft' == scraped['status']:
            return scraped['draft_picks'].get('team_key', [])
        else:
            return [
                int(key['number']) for key in scraped['draft_picks'][team_key]
            ]

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setCentralWidget(self.main_widget)
        self.layout_screen()
        self.show()

    def pause_pressed(self):
        print("Pause pressed")
        if self.draft_monitor:
            self.draft_monitor.toggle_paused()
        if "Pause" == self.pause_draft_button.text():
            self.pause_draft_button.setText("Resume")
        else:
            self.pause_draft_button.setText("Pause")

    def handle_team_roster_changed(self, index):
        print(f"Do something with the selected item: {index.data()}")
        self.roster_table_model.specify_team_key(
            self.team_key_by_name[index.data()])
        # self.roster_table.setModel(DraftedRosterModel(self.draft_results,self.team_key_by_name[index.data()]))

    def _set_projection_table_widths(self, table):
        table.setColumnWidth(0, 140)
        table.setColumnWidth(1, 60)
        table.setColumnWidth(2, 60)
        table.setColumnWidth(3, 50)
        table.setColumnWidth(4, 50)
        table.setColumnWidth(5, 50)
        table.setColumnWidth(6, 50)
        table.setColumnWidth(7, 60)
        table.setColumnWidth(8, 50)
        table.setColumnWidth(9, 50)
        table.setColumnWidth(10, 50)
        table.setColumnWidth(11, 50)
        table.setColumnWidth(12, 50)
        table.setColumnWidth(13, 50)
        table.setColumnWidth(14, 50)

    def hide_drafted_click(self):
        cbutton = self.sender()
        self.projections_model.set_hide_drafted(cbutton.isChecked())

    def _position_filter_list(self):
        return {
            checkbox.text()
            for checkbox in self.positional_filter_checkboxes
            if checkbox.isChecked()
        }

    def filter_all_selected(self):
        print("All button pressed")
        for checkbox in self.positional_filter_checkboxes:
            checkbox.setChecked(True)
        self.projections_model.update_filters(self._position_filter_list())

    def filter_none_selected(self):
        print("None pressed")
        for checkbox in self.positional_filter_checkboxes:
            checkbox.setChecked(False)
        self.projections_model.update_filters(self._position_filter_list())

    def filter_checked(self, state):
        print(f"filter was checked: {self.sender().text()}")
        self.projections_model.update_filters(self._position_filter_list())

    def layout_screen(self):

        layout = QHBoxLayout()
        left_layout = QVBoxLayout()

        second_filter_layout = QHBoxLayout()
        hide_drafted = QCheckBox('Hide drafted')
        hide_drafted.toggled.connect(self.hide_drafted_click)
        second_filter_layout.addWidget(hide_drafted)

        name_filter_layout = QFormLayout()
        name_filter_text = QLineEdit()
        name_filter_text.setMaximumWidth(400)
        name_filter_layout.addRow(QLabel("Name filter: "), name_filter_text)

        second_filter_layout.addLayout(name_filter_layout)
        filtering_layout = QVBoxLayout()

        filtering_layout.addLayout(self.position_filtering_layout)
        filtering_layout.addLayout(second_filter_layout)
        second_filter_layout.addStretch(1)

        # this displays list of eligible players, and their projections
        self._set_projection_table_widths(self.projection_table)
        projection_layout = QVBoxLayout()

        projection_layout.addWidget(self.projection_table)
        # projection_layout.addWidget(QTableView())

        roster_layout = QVBoxLayout()
        roster_layout.addWidget(self.draft_status_label)
        roster_team_selection = QHBoxLayout()

        # set up draft pause button
        roster_team_selection.addWidget(self.pause_draft_button)

        roster_team_selection.addWidget(QLabel("Team: "))

        self.team_combo_box.view().pressed.connect(
            self.handle_team_roster_changed)
        roster_team_selection.addWidget(self.team_combo_box)

        roster_layout.addLayout(roster_team_selection)

        game_selection_layout = QHBoxLayout()
        game_selection_layout.addWidget(self.label_num_picks_before_pick)
        game_selection_layout.addStretch(1)

        roster_layout.addWidget(self.roster_table)
        roster_layout.addWidget(self.draft_list_widget)

        left_layout.addLayout(game_selection_layout)

        left_layout.addLayout(filtering_layout)
        left_layout.addLayout(projection_layout)
        layout.addLayout(left_layout, stretch=2)
        layout.addLayout(roster_layout)
        self.main_widget.setLayout(layout)

    def player_drafted(self, draft_entry):
        self.draft_results.append(draft_entry)
        print(f"de: {draft_entry}")
        player_id = int(draft_entry['player_key'].split('.')[-1])
        draft_position = int(draft_entry['pick'])
        player_name = None
        draft_value = 'n/a'
        try:
            player_name = self.projections_df[self.projections_df.player_id ==
                                              player_id]['name'].values[0]
            # figure out draft position relative to csh_rank ranking
            try:
                csh_rank = self.projections_df[self.projections_df.player_id ==
                                               player_id]['csh_rank'].values[0]
                draft_value = draft_position - csh_rank
            except KeyError:
                pass
        except IndexError:
            player_name = f"Unknown({player_id})"

        team_id = int(draft_entry['team_key'].split('.')[-1])
        self.projections_model.player_drafted(player_id, team_id)
        self.roster_table_model.player_drafted(draft_entry)
        try:
            next_draft = next(x for x in self.my_draft_picks
                              if x > draft_position)
            self.label_num_picks_before_pick.setText(
                f"Number picks until your turn: {next_draft-draft_position}")
        except StopIteration:
            pass
        self.draft_list_widget.insertItem(
            0,
            f"{draft_position}. {player_name} - {self.team_name_by_id[draft_entry['team_key']]} - ({draft_value})"
        )

    def update_picks_until_next_player_pick(self, current_draft_position):
        try:
            next_draft = next(x for x in self.my_draft_picks
                              if x > current_draft_position)
            self.label_num_picks_before_pick.setText(
                f"Number picks until your turn: {next_draft-current_draft_position}"
            )
        except StopIteration:
            pass
Пример #10
0
class App(QDialog):
    def __init__(self):
        super().__init__()
        self.title = "CSH Draft Board"
        self.left = 10
        self.top = 10
        self.width = 3200
        self.height = 1000
        self.projection_columns = {
            'name': 'Name',
            'posn_display': 'POS',
            'team': 'Team',
            'csh_rank': 'CSH',
            'preseason_rank': 'Preseason',
            'current_rank': 'Current',
            'GP': 'GP',
            'fantasy_score': 'Score'
        }

        # lg_id = "403.l.18782"
        lg_id = "403.l.41177"

        self.manager = ManagerBot(league_id=lg_id)
        my_team_key = self.manager.lg.team_key()

        for cat in self.manager.stat_categories:
            self.projection_columns[cat] = cat

        self.my_draft_picks = self._get_draft_picks(my_team_key)
        self.label_num_picks_before_pick = QLabel(
            "Number picks until your turn: 4")
        self.projections_df = self.retrieve_player_projections()
        # use this for rendering eligible positions
        self.projections_df['posn_display'] = self.projections_df[
            'position'].apply(lambda x: ", ".join(x))
        self.projections_model = PandasModel(
            self.projections_df, column_headers=self.projection_columns)

        self.team_name_by_id = {
            team['team_key']: team['name']
            for team in self.manager.lg.teams()
        }
        self.team_key_by_name = {
            team['name']: team['team_key']
            for team in self.manager.lg.teams()
        }
        self.positional_filter_checkboxes = {
            pos: QCheckBox(pos)
            for pos in ['C', 'LW', 'RW', 'D']
        }
        for checkbox in self.positional_filter_checkboxes.values():
            checkbox.setChecked(True)

        self.last_draft_count = 0
        self.draft_supplier = None
        self.draft_complete = False
        self.draft_results = []
        self.draft_list_widget = QListWidget()
        self.pause_draft_button = QPushButton("Pause")
        self.pause_draft_button.clicked.connect(self.pause_pressed)

        self.team_combo_box = QComboBox()
        self.draft_status_label = QLabel("Status: Running")
        for team in self.manager.lg.teams():
            self.team_combo_box.addItem(team['name'], team['team_key'])
        self.team_combo_box.setCurrentIndex(
            self.team_combo_box.findData(my_team_key))

        self.roster_table = QTableView()
        self.roster_table_model = DraftedRosterModel(self.draft_results,
                                                     my_team_key,
                                                     self.projections_df)
        self.roster_table.setModel(self.roster_table_model)

        self.initUI()

    def retrieve_player_projections(self):
        projections = retrieve_yahoo_rest_of_season_projections(
            self.manager.lg.league_id)
        produce_csh_ranking(projections,
                            self.manager.stat_categories,
                            projections.index,
                            ranking_column_name='fantasy_score')
        projections['fantasy_score'] = round(projections['fantasy_score'], 3)
        projections.reset_index(inplace=True)
        projections.sort_values("fantasy_score",
                                ascending=False,
                                inplace=True,
                                ignore_index=True)
        projections['csh_rank'] = projections.index + 1
        projections['draft_fantasy_key'] = -1
        return projections

    def draft_status_changed(self, status):
        if status:
            self.draft_status_label.setText("Status: Paused")
        else:
            self.draft_status_label.setText("Status: Running")

    def _get_draft_picks(self, team_key):
        draft_results = self.manager.lg.draft_results()
        # find first pick which matches team_key
        draft_position = None
        for draft_info in draft_results:
            if draft_info['team_key'] == team_key:
                draft_position = int(draft_info['pick'])
                assert draft_info[
                    'round'] == 1, "Didnt find team key in first round of draft"
                break
        # num teams in league
        n_teams = len(self.manager.lg.teams())

        #num rounds in draft
        n_rounds = int(len(draft_results) / n_teams)

        return generate_snake_draft_picks(n_teams=n_teams,
                                          n_rounds=n_rounds,
                                          draft_position=draft_position)

    def initUI(self):
        self.setWindowTitle(self.title)
        self.layout_screen()
        self.show()

    def pause_pressed(self):
        print("Pause pressed")
        if self.draft_supplier:
            self.draft_supplier.toggle_paused()
        if "Pause" == self.pause_draft_button.text():
            self.pause_draft_button.setText("Resume")
        else:
            self.pause_draft_button.setText("Pause")

    def handle_team_roster_changed(self, index):
        print(f"Do something with the selected item: {index.data()}")
        self.roster_table_model.specify_team_key(
            self.team_key_by_name[index.data()])
        # self.roster_table.setModel(DraftedRosterModel(self.draft_results,self.team_key_by_name[index.data()]))

    def _set_projection_table_widths(self, table):
        table.setColumnWidth(0, 140)
        table.setColumnWidth(1, 60)
        table.setColumnWidth(2, 60)
        table.setColumnWidth(3, 50)
        table.setColumnWidth(4, 50)
        table.setColumnWidth(5, 50)
        table.setColumnWidth(6, 50)
        table.setColumnWidth(7, 60)
        table.setColumnWidth(8, 50)
        table.setColumnWidth(9, 50)
        table.setColumnWidth(10, 50)
        table.setColumnWidth(11, 50)
        table.setColumnWidth(12, 50)
        table.setColumnWidth(13, 50)
        table.setColumnWidth(14, 50)

    def hide_drafted_click(self):
        cbutton = self.sender()
        self.projections_model.set_hide_drafted(cbutton.isChecked())
        # self.projections_model.show_drafted = not cbutton.isChecked()
        # self.projections_model.modelReset.emit()

    def _position_filter_list(self):
        return {
            posn
            for posn, checkbox in self.positional_filter_checkboxes.items()
            if checkbox.isChecked()
        }

    def filter_all_selected(self):
        print("All button pressed")
        for checkbox in self.positional_filter_checkboxes.values():
            checkbox.setChecked(True)
        self.projections_model.update_filters(self._position_filter_list())

    def filter_none_selected(self):
        print("None pressed")
        for checkbox in self.positional_filter_checkboxes.values():
            checkbox.setChecked(False)
        self.projections_model.update_filters(self._position_filter_list())

    def filter_checked(self, state):
        print(f"filter was checked: {self.sender().text()}")
        self.projections_model.update_filters(self._position_filter_list())

    def layout_screen(self):
        layout = QHBoxLayout()
        left_layout = QVBoxLayout()
        # filtering
        position_filtering_layout = QHBoxLayout()
        for posn, checkbox in self.positional_filter_checkboxes.items():
            checkbox.clicked.connect(self.filter_checked)
            position_filtering_layout.addWidget(checkbox)

        # position_filtering_layout.addWidget(QCheckBox('G'))
        all_button = QPushButton('All')
        all_button.pressed.connect(self.filter_all_selected)
        position_filtering_layout.addWidget(all_button)
        none_button = QPushButton('None')
        none_button.pressed.connect(self.filter_none_selected)
        position_filtering_layout.addWidget(none_button)

        second_filter_layout = QHBoxLayout()
        hide_drafted = QCheckBox('Hide drafted')
        hide_drafted.toggled.connect(self.hide_drafted_click)
        second_filter_layout.addWidget(hide_drafted)

        name_filter_layout = QFormLayout()
        name_filter_text = QLineEdit()
        name_filter_text.setMaximumWidth(400)
        name_filter_layout.addRow(QLabel("Name filter: "), name_filter_text)

        second_filter_layout.addLayout(name_filter_layout)
        filtering_layout = QVBoxLayout()
        filtering_layout.addLayout(position_filtering_layout)
        filtering_layout.addLayout(second_filter_layout)
        second_filter_layout.addStretch(1)

        # this displays list of eligible players, and their projections
        projection_table = QTableView()
        projection_table.setModel(self.projections_model)
        self._set_projection_table_widths(projection_table)
        projection_layout = QVBoxLayout()

        projection_layout.addWidget(projection_table)
        projection_layout.addWidget(QTableView())

        roster_layout = QVBoxLayout()
        roster_layout.addWidget(self.draft_status_label)
        roster_team_selection = QHBoxLayout()

        # set up draft pause button
        roster_team_selection.addWidget(self.pause_draft_button)

        roster_team_selection.addWidget(QLabel("Team: "))

        self.team_combo_box.view().pressed.connect(
            self.handle_team_roster_changed)
        roster_team_selection.addWidget(self.team_combo_box)

        roster_layout.addLayout(roster_team_selection)

        # this sets row headers of roster to num spots for each position
        # roster_makeup_index = 0
        # for posn, num_spots in self.manager.lg.roster_makeup().items():
        #     if posn != 'IR':
        #         for _ in range(num_spots):
        #             self.roster_table.setVerticalHeaderItem(roster_makeup_index, QTableWidgetItem(posn))
        #             roster_makeup_index += 1

        roster_layout.addWidget(self.roster_table)
        roster_layout.addWidget(self.draft_list_widget)

        left_layout.addWidget(self.label_num_picks_before_pick)
        left_layout.addLayout(filtering_layout)
        left_layout.addLayout(projection_layout)
        layout.addLayout(left_layout, stretch=2)
        layout.addLayout(roster_layout)
        self.setLayout(layout)

    def register_draft_supplier(self, draft_supplier):
        self.draft_supplier = draft_supplier

    def player_drafted(self, draft_entry):
        self.draft_results.append(draft_entry)

        player_id = int(draft_entry['player_key'].split('.')[-1])
        draft_position = int(draft_entry['pick'])
        player_name = None
        draft_value = 'n/a'
        try:
            player_name = self.projections_df[self.projections_df.player_id ==
                                              player_id]['name'].values[0]
            # figure out draft position relative to csh_rank ranking
            csh_rank = self.projections_df[self.projections_df.player_id ==
                                           player_id]['csh_rank'].values[0]
            draft_value = draft_position - csh_rank
        except IndexError:
            player_name = f"Unknown({player_id})"
        team_id = int(draft_entry['team_key'].split('.')[-1])
        print(f"Player1 drafted was: {player_id}")
        self.projections_model.player_drafted(player_id, team_id)
        self.roster_table_model.player_drafted(draft_entry)
        next_draft = next(x for x in self.my_draft_picks if x > draft_position)

        self.label_num_picks_before_pick.setText(
            f"Number picks until your turn: {next_draft-draft_position}")
        # self.my_draft_picks
        # "Number picks until your turn: 4"
        # self.label_num_picks_before_pick
        # 6743 mcdavid

        self.draft_list_widget.insertItem(
            0,
            f"{draft_position}. {player_name} - {self.team_name_by_id[draft_entry['team_key']]} - ({draft_value})"
        )
Пример #11
0
class SelectInitCoordinate(QDockWidget):
    def __init__(self, vp_eng, *__args):
        super().__init__(*__args)
        self.vp_eng = None
        self.point_selected = None

        self.list_widget = None
        self.main_layout = None
        self.main_widget = None

        self.reset(vp_eng)

        # set UI

        # self.xy_button = QPushButton("Use XY")
        # self.xy_button.clicked.connect(lambda: self.extract_side("XY", self.vp_eng.coordinates[self.point_selected[0]], self.vp_eng.coordinates[self.point_selected[1]]))
        # self.xz_button = QPushButton("Use XZ")
        # self.xz_button.clicked.connect(lambda: self.extract_side("XZ", self.vp_eng.coordinates[self.point_selected[0]], self.vp_eng.coordinates[self.point_selected[1]]))
        # self.yz_button = QPushButton("Use YZ")
        # self.yz_button.clicked.connect(lambda: self.extract_side("YZ", self.vp_eng.coordinates[self.point_selected[0]], self.vp_eng.coordinates[self.point_selected[1]]))
        # self.hBox = QHBoxLayout()
        # self.hBox.addWidget(self.xy_button)
        # self.hBox.addWidget(self.xz_button)
        # self.hBox.addWidget(self.yz_button)

        # self.main_layout.addLayout(self.hBox)

    def reset(self, vp_eng):
        self.vp_eng = vp_eng
        self.point_selected = []

        # init UI

        self.list_widget = QListWidget()
        self.list_widget.itemClicked.connect(self.item_click)

        self.setWidget(self.list_widget)

        self.add_layer()
        self.add_layer()
        self.add_layer()

        # self.main_layout = QVBoxLayout()
        # self.main_layout.addWidget(self.list_widget)
        #
        # self.main_widget = QWidget()
        # self.main_widget.setLayout(self.main_layout)
        #
        # self.setWidget(self.main_widget)

    def add_layer(self):
        index = self.list_widget.count()
        widget = LayerWidget(index, self.point_selected)
        item = QListWidgetItem()
        item.setData(Qt.UserRole, index)
        self.list_widget.insertItem(index, item)
        self.list_widget.setItemWidget(item, widget)
        self.vp_eng.coordinates.append([0, 0])
        item.setSizeHint(widget.sizeHint())

    def on_point_selected(self, coordinate):
        widget = self.list_widget.itemWidget(self.list_widget.currentItem())
        widget.set_coordinate(coordinate)

    def extract_side(self, axis, point0, point1):
        xvpoint = self.vp_eng.vpoints[0]
        yvpoint = self.vp_eng.vpoints[1]
        zvpoint = self.vp_eng.vpoints[2]

        basename = self.window().input_file.name

        if axis == "XY":
            vpoint1 = xvpoint
            vpoint2 = yvpoint
            img_out = "output/" + basename + "/" + basename + "(top).png"
        elif axis == "XZ":
            vpoint1 = xvpoint
            vpoint2 = zvpoint
            img_out = "output/" + basename + "/" + basename + "(right).png"
        elif axis == "YZ":
            vpoint1 = yvpoint
            vpoint2 = zvpoint
            img_out = "output/" + basename + "/" + basename + "(left).png"

        L1 = line(point0, vpoint1)
        L2 = line(point1, vpoint2)
        R1 = [round(i) for i in intersection(L1, L2)]
        if R1:
            print("Intersection 1 detected:", R1)
        else:
            print("No single intersection point detected")

        L1 = line(point0, vpoint2)
        L2 = line(point1, vpoint1)
        R2 = [round(i) for i in intersection(L1, L2)]
        if R1:
            print("Intersection 2 detected:", R2)
        else:
            print("No single intersection point detected")

        all_points = [point0, point1, R1, R2]
        ordered_points = rearrange_point(all_points)

        engine = FixPerspective(self.window().input_file.base, img_out,
                                ordered_points, 400, 400)
        engine.show()

    @pyqtSlot()
    def item_click(self):
        self.vp_eng.set_current_wizard(Wizard.ADD_POINT)
        index = self.list_widget.currentItem().data(Qt.UserRole)
        self.window().centralWidget().graphics_view.set_coordinate_index(
            index, self.on_point_selected)
Пример #12
0
class ManagerDialog(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        # remember the parent for future use
        self.parent = parent
        self.dict = None

        # main_window settings
        self.setWindowRole("QDialog")
        self.setWindowModality(Qt.ApplicationModal)
        self.setWindowFlags(self.windowFlags() & QtCore.Qt.CustomizeWindowHint)
        self.setWindowFlags(self.windowFlags() | Qt.Window
                            | Qt.WindowMaximizeButtonHint
                            | Qt.WindowCloseButtonHint)
        self.setWindowFlags(self.windowFlags()
                            & ~QtCore.Qt.WindowMinimizeButtonHint)
        self.resize(800, 600)

        # layouts
        self._layout = QtWidgets.QVBoxLayout(self)
        self._buttonlayout = QtWidgets.QHBoxLayout()
        self._layout.addLayout(self._buttonlayout)

        # item list widget
        self._itemscroll = QListWidget()

    def moveUp(self, subDictName, id):
        """ move the item one position up """
        if id:
            i = self.dict[subDictName].index(id)
            row = self._getIndexinList(id)
            if i > 0 and row > 0:
                j = 1
                item = self._itemscroll.item(row - j)
                # skip hidden items
                while i - j > 0 and item.isHidden():
                    j += 1
                    item = self._itemscroll.item(row - j)

                if not item or item.isHidden():
                    return

                # update dict
                tmp = self.dict[subDictName][i]
                for k in range(0, j):
                    self.dict[subDictName][i -
                                           k] = self.dict[subDictName][i - k -
                                                                       1]
                self.dict[subDictName][i - j] = tmp

                widget = self.createWidget(id)

                #move item widgets
                scroll = self._itemscroll.cursor()
                item = self._itemscroll.takeItem(row)
                item.setSizeHint(widget.sizeHint())
                self._itemscroll.insertItem(row - j, item)
                self._itemscroll.setItemWidget(item, widget)
                self._itemscroll.setCursor(scroll)

                self.updateAfterMovement()

    def moveDown(self, subDictName, id):
        """ move the item one position down """
        if id:
            i = self.dict[subDictName].index(id)
            row = self._getIndexinList(id)
            dictLength = len(self.dict[subDictName])
            if i < dictLength - 1 and row < dictLength - 1:
                j = 1
                item = self._itemscroll.item(row + j)
                # skip hidden items
                while i + j < dictLength and item.isHidden():
                    j += 1
                    item = self._itemscroll.item(row + j)

                if not item or item.isHidden():
                    return

                # update dict
                tmp = self.dict[subDictName][i]
                for k in range(0, j):
                    self.dict[subDictName][i +
                                           k] = self.dict[subDictName][i + k +
                                                                       1]
                self.dict[subDictName][i + j] = tmp

                widget = self.createWidget(id)

                #move item widgets
                scroll = self._itemscroll.cursor()
                item = self._itemscroll.takeItem(row)
                item.setSizeHint(widget.sizeHint())
                self._itemscroll.insertItem(row + j, item)
                self._itemscroll.setItemWidget(item, widget)
                self._itemscroll.setCursor(scroll)

                self.updateAfterMovement()

    def createWidget(self, id):
        """ abstract method returning a widget for one entry in the list """
        raise NotImplementedError("Please Implement this method")

    def updateAfterMovement(self):
        """ abstract method """
        raise NotImplementedError("Please Implement this method")
Пример #13
0
class stackedExample(QWidget):
    def __init__(self):

        super(stackedExample, self).__init__()
        self.leftlist = QListWidget()
        self.leftlist.setFixedWidth(250)
        self.leftlist.insertItem(0, 'Add Stock')
        self.leftlist.insertItem(1, 'Manage Stock')
        self.leftlist.insertItem(2, 'View Stock')
        self.leftlist.insertItem(3, 'View Transaction History')

        self.stack1 = QWidget()
        self.stack2 = QWidget()
        self.stack3 = QWidget()
        self.stack4 = QWidget()

        self.stack1UI()
        self.stack2UI()
        self.stack3UI()
        self.stack4UI()

        self.Stack = QStackedWidget(self)
        self.Stack.addWidget(self.stack1)
        self.Stack.addWidget(self.stack2)
        self.Stack.addWidget(self.stack3)
        self.Stack.addWidget(self.stack4)

        hbox = QHBoxLayout(self)
        hbox.addWidget(self.leftlist)
        hbox.addWidget(self.Stack)

        self.setLayout(hbox)
        self.leftlist.currentRowChanged.connect(self.display)
        # self.setGeometry(500, 350, 200, 200)
        self.setGeometry(500, 350, 200, 200)
        self.setWindowTitle('Quant')
        self.show()

    def stack1UI(self):
        layout = QFormLayout()

        self.ok = QPushButton('Add Stock', self)
        cancel = QPushButton('Cancel', self)

        self.stock_name = QLineEdit()
        layout.addRow("Stock Name", self.stock_name)

        self.stock_count = QLineEdit()
        layout.addRow("Quantity", self.stock_count)

        self.stock_cost = QLineEdit()
        layout.addRow("Cost of Stock (per item)", self.stock_cost)

        layout.addWidget(self.ok)
        layout.addWidget(cancel)

        self.ok.clicked.connect(self.on_click)

        cancel.clicked.connect(self.stock_name.clear)
        cancel.clicked.connect(self.stock_cost.clear)
        cancel.clicked.connect(self.stock_count.clear)
        self.stack1.setLayout(layout)

    def on_click(self):
        now = datetime.datetime.now()
        stock_name_inp = self.stock_name.text().replace(' ', '_').lower()
        stock_count_inp = int(self.stock_count.text())
        stock_cost_inp = int(self.stock_cost.text())
        # print(stock_name_inp,stock_count_inp,stock_cost_inp)
        stock_add_date_time = now.strftime("%Y-%m-%d %H:%M")
        d = mp.insert_prod(stock_name_inp, stock_count_inp, stock_cost_inp,
                           stock_add_date_time)
        print(d)
        # Need to add the above details to table

    def stack2UI(self):

        layout = QHBoxLayout()
        layout.setGeometry(QRect(0, 300, 1150, 500))
        tabs = QTabWidget()
        self.tab1 = QWidget()
        self.tab2 = QWidget()
        self.tab3 = QWidget()

        tabs.addTab(self.tab1, 'Add Quantity')
        tabs.addTab(self.tab2, 'Reduce Quantity')
        tabs.addTab(self.tab3, 'Delete Stock')

        self.tab1UI()
        self.tab2UI()
        self.tab3UI()

        layout.addWidget(tabs)
        self.stack2.setLayout(layout)

    def tab1UI(self):
        layout = QFormLayout()
        self.ok_add = QPushButton('Add Stock', self)
        cancel = QPushButton('Cancel', self)

        self.stock_name_add = QLineEdit()
        layout.addRow("Stock Name", self.stock_name_add)

        self.stock_count_add = QLineEdit()
        layout.addRow("Quantity to add", self.stock_count_add)

        layout.addWidget(self.ok_add)
        layout.addWidget(cancel)
        self.tab1.setLayout(layout)

        self.ok_add.clicked.connect(
            self.call_add)  # need to write function to add quantity
        cancel.clicked.connect(self.stock_name_add.clear)
        cancel.clicked.connect(self.stock_count_add.clear)

    def tab2UI(self):
        layout = QFormLayout()
        self.ok_red = QPushButton('Reduce Stock', self)
        cancel = QPushButton('Cancel', self)

        self.stock_name_red = QLineEdit()
        layout.addRow("Stock Name", self.stock_name_red)

        self.stock_count_red = QLineEdit()
        layout.addRow("Quantity to reduce", self.stock_count_red)

        layout.addWidget(self.ok_red)
        layout.addWidget(cancel)
        self.tab2.setLayout(layout)

        self.ok_red.clicked.connect(
            self.call_red)  # need to write function to reduce quantity
        cancel.clicked.connect(self.stock_name_red.clear)
        cancel.clicked.connect(self.stock_count_red.clear)

    def tab3UI(self):
        layout = QFormLayout()
        self.ok_del = QPushButton('Delete Stock', self)
        cancel = QPushButton('Cancel', self)

        self.stock_name_del = QLineEdit()
        layout.addRow("Stock Name", self.stock_name_del)
        layout.addWidget(self.ok_del)
        layout.addWidget(cancel)
        self.tab3.setLayout(layout)

        self.ok_del.clicked.connect(
            self.call_del)  # need to write function to delete stock
        cancel.clicked.connect(self.stock_name_del.clear)

    def call_del(self):
        now = datetime.datetime.now()
        stock_del_date_time = now.strftime("%Y-%m-%d %H:%M")
        stock_name = self.stock_name_del.text().replace(' ', '_').lower()
        mp.remove_stock(stock_name, stock_del_date_time)

    def call_red(self):
        now = datetime.datetime.now()
        stock_red_date_time = now.strftime("%Y-%m-%d %H:%M")
        stock_name = self.stock_name_red.text().replace(' ', '_').lower()
        try:
            stock_val = -(int(self.stock_count_red.text()))
            print(stock_val)
            print(type(stock_val))
            mp.update_quantity(stock_name, stock_val, stock_red_date_time)
        except Exception:
            print('Exception')

    def call_add(self):
        now = datetime.datetime.now()
        stock_call_add_date_time = now.strftime("%Y-%m-%d %H:%M")
        stock_name = self.stock_name_add.text().replace(' ', '_').lower()
        stock_val = int(self.stock_count_add.text())
        mp.update_quantity(stock_name, stock_val, stock_call_add_date_time)

    def stack3UI(self):

        table = mp.show_stock()
        print('show')
        print(table)
        layout = QVBoxLayout()
        self.srb = QPushButton()
        self.srb.setText("Get Search Result.")
        self.View = QTableWidget()
        self.lbl3 = QLabel()
        self.lbl_conf_text = QLabel()
        self.lbl_conf_text.setText("Enter the search keyword:")
        self.conf_text = QLineEdit()

        self.View.setColumnCount(3)
        self.View.setColumnWidth(0, 250)
        self.View.setColumnWidth(1, 250)
        self.View.setColumnWidth(2, 200)
        self.View.insertRow(0)
        self.View.setItem(0, 0, QTableWidgetItem('Stock Name'))
        self.View.setItem(0, 1, QTableWidgetItem('Quantity'))
        self.View.setItem(0, 2, QTableWidgetItem('Cost(Per Unit)'))

        layout.addWidget(self.View)
        layout.addWidget(self.lbl_conf_text)
        layout.addWidget(self.conf_text)
        layout.addWidget(self.srb)
        layout.addWidget(self.lbl3)
        self.srb.clicked.connect(self.show_search)
        self.stack3.setLayout(layout)

    def show_search(self):
        if self.View.rowCount() > 1:
            for i in range(1, self.View.rowCount()):
                self.View.removeRow(1)

        x_act = mp.show_stock()
        x = []
        if self.conf_text.text() != '':
            for i in range(0, len(x_act)):
                a = list(x_act[i])
                if self.conf_text.text().lower() in a[0].lower():
                    x.append(a)
        else:
            x = mp.show_stock()

        if len(x) != 0:
            for i in range(1, len(x) + 1):
                self.View.insertRow(i)
                a = list(x[i - 1])
                self.View.setItem(
                    i, 0, QTableWidgetItem(a[0].replace('_', ' ').upper()))
                self.View.setItem(i, 1, QTableWidgetItem(str(a[1])))
                self.View.setItem(i, 2, QTableWidgetItem(str(a[2])))
                self.View.setRowHeight(i, 50)
            self.lbl3.setText('Viewing Stock Database.')
        else:
            self.lbl3.setText('No valid information in database.')

    def stack4UI(self):
        layout = QVBoxLayout()
        self.srt = QPushButton()
        self.srt.setText("Get Transaction History.")
        self.Trans = QTableWidget()
        self.lbl4 = QLabel()
        self.lbl_trans_text = QLabel()
        self.lbl_trans_text.setText("Enter the search keyword:")
        self.trans_text = QLineEdit()

        self.Trans.setColumnCount(6)
        self.Trans.setColumnWidth(0, 150)
        self.Trans.setColumnWidth(1, 150)
        self.Trans.setColumnWidth(2, 150)
        self.Trans.setColumnWidth(3, 100)
        self.Trans.setColumnWidth(4, 100)
        self.Trans.setColumnWidth(5, 500)
        self.Trans.insertRow(0)
        self.Trans.setItem(0, 0, QTableWidgetItem('Transaction ID'))
        self.Trans.setItem(0, 1, QTableWidgetItem('Stock Name'))
        self.Trans.setItem(0, 2, QTableWidgetItem('Transaction Type'))
        self.Trans.setItem(0, 3, QTableWidgetItem('Date'))
        self.Trans.setItem(0, 4, QTableWidgetItem('Time'))
        self.Trans.setItem(0, 5, QTableWidgetItem('Transaction Specific'))
        self.Trans.setRowHeight(0, 50)

        layout.addWidget(self.Trans)
        layout.addWidget(self.lbl_trans_text)
        layout.addWidget(self.trans_text)
        layout.addWidget(self.srt)
        layout.addWidget(self.lbl4)
        self.srt.clicked.connect(self.show_trans_history)
        self.stack4.setLayout(layout)

    def show_trans_history(self):
        if self.Trans.rowCount() > 1:
            for i in range(1, self.Trans.rowCount()):
                self.Trans.removeRow(1)

        path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                            'transaction.txt')
        if os.path.exists(path):
            tsearch = open(path, 'r')
            x_c = tsearch.readlines()
            tsearch.close()
            x = []
            if self.trans_text.text() != '':
                key = self.trans_text.text()
                for i in range(0, len(x_c)):
                    a = x_c[i].split(" ")
                    name = a[0]
                    action = a[-2]
                    if (key.lower() in name.lower()) or (key.lower()
                                                         in action.lower()):
                        x.append(a)
            else:
                x = x_c.copy()

            for i in range(0, len(x)):
                x.sort(key=lambda a: a[4])
            # print(x)
            tid = 1900001
            for i in range(1, len(x) + 1):
                self.Trans.insertRow(i)

                a = x[i - 1].split(" ")
                if a[-2] == 'UPDATE':
                    p = 'Quantity of Stock Changed from ' + a[1] + ' to ' + a[2]
                elif a[-2] == 'INSERT':
                    p = 'Stock added with Quantity : ' + a[
                        1] + ' and Cost(Per Unit in Rs.) : ' + a[2]
                elif a[-2] == 'REMOVE':
                    p = 'Stock information deleted.'
                else:
                    p = 'None'

                self.Trans.setItem(i, 0, QTableWidgetItem(str(tid)))
                self.Trans.setItem(i, 1,
                                   QTableWidgetItem(a[0].replace('_', ' ')))
                self.Trans.setItem(i, 2, QTableWidgetItem(a[-2]))
                self.Trans.setItem(i, 3, QTableWidgetItem(a[3]))
                self.Trans.setItem(i, 4, QTableWidgetItem(a[4]))
                self.Trans.setItem(i, 5, QTableWidgetItem(p))
                self.Trans.setRowHeight(i, 50)
                tid += 1

            self.lbl4.setText('Transaction History.')
        else:
            self.lbl4.setText('No valid information found.')

    def display(self, i):
        self.Stack.setCurrentIndex(i)
Пример #14
0
class ProgrammingDialog(QDialog):
    def __init__(self, name, proList=None):
        super(ProgrammingDialog, self).__init__()

        self.name = name

        self.list = QListWidget()

        if proList is not None:
            self.list.addItems(proList)
            self.list.setCurrentRow(0)

        vbox = QVBoxLayout()

        for text, slot in (("Add", self.add), ("Edit", self.edit),
                           ("Remove", self.remove), ("Sort", self.sort),
                           ("Close", self.close)):

            buttons = QPushButton(text)
            buttons.clicked.connect(slot)

            vbox.addWidget(buttons)

        hbox = QHBoxLayout()
        hbox.addWidget(self.list)
        hbox.addLayout(vbox)
        self.setLayout(hbox)

        self.setWindowTitle("PyQt5 Simple List Project")

    def add(self):
        row = self.list.currentRow()
        title = "Add {0}".format(self.name)
        string, ok = QInputDialog.getText(self, title, title)

        if ok and string is not None:
            self.list.insertItem(row, string)

    def edit(self):
        row = self.list.currentRow()
        item = self.list.item(row)

        if item is not None:
            title = "Edit {0}".format(self.name)

            string, ok = QInputDialog.getText(self, title, title,
                                              QLineEdit.Normal, item.text())

            if ok and string is not None:
                item.setText(string)

    def remove(self):
        row = self.list.currentRow()
        item = self.list.item(row)

        if item is None:
            return

        reply = QMessageBox.question(
            self, "Remove {0}".format(self.name),
            "Remove {0} '{1}'?".format(self.name, str(item.text())),
            QMessageBox.Yes | QMessageBox.No)

        if reply == QMessageBox.Yes:
            item = self.list.takeItem(row)

            del item

    def sort(self):
        self.list.sortItems()

    def close(self):
        self.accept()
Пример #15
0
class SimulationGui(QMainWindow):
    """
    class for the graphical user interface
    """
    # TODO enable closing plot docks by right-clicking their name

    runSimulation = pyqtSignal()
    stopSimulation = pyqtSignal()
    playbackTimeChanged = pyqtSignal()
    regimeFinished = pyqtSignal()
    finishedRegimeBatch = pyqtSignal(bool)

    def __init__(self):
        # constructor of the base class
        QMainWindow.__init__(self)

        QCoreApplication.setOrganizationName("RST")
        QCoreApplication.setOrganizationDomain("https://tu-dresden.de/rst")
        QCoreApplication.setApplicationVersion(
            pkg_resources.require("PyMoskito")[0].version)
        QCoreApplication.setApplicationName(globals()["__package__"])

        # load settings
        self._settings = QSettings()
        self._read_settings()

        # initialize logger
        self._logger = logging.getLogger(self.__class__.__name__)

        # Create Simulation Backend
        self.guiProgress = None
        self.cmdProgress = None
        self.sim = SimulatorInteractor(self)
        self.runSimulation.connect(self.sim.run_simulation)
        self.stopSimulation.connect(self.sim.stop_simulation)
        self.sim.simulation_finalized.connect(self.new_simulation_data)
        self.currentDataset = None
        self.interpolator = None

        # sim setup viewer
        self.targetView = SimulatorView(self)
        self.targetView.setModel(self.sim.target_model)
        self.targetView.expanded.connect(self.target_view_changed)
        self.targetView.collapsed.connect(self.target_view_changed)

        # sim results viewer
        self.result_view = QTreeView()

        # the docking area allows to rearrange the user interface at runtime
        self.area = pg.dockarea.DockArea()

        # Window properties
        icon_size = QSize(25, 25)
        self.setCentralWidget(self.area)
        self.resize(1000, 700)
        self.setWindowTitle("PyMoskito")
        res_path = get_resource("mosquito.png")
        icon = QIcon(res_path)
        self.setWindowIcon(icon)

        # create docks
        self.propertyDock = pg.dockarea.Dock("Properties")
        self.animationDock = pg.dockarea.Dock("Animation")
        self.regimeDock = pg.dockarea.Dock("Regimes")
        self.dataDock = pg.dockarea.Dock("Data")
        self.logDock = pg.dockarea.Dock("Log")
        self.plotDockPlaceholder = pg.dockarea.Dock("Placeholder")

        # arrange docks
        self.area.addDock(self.animationDock, "right")
        self.area.addDock(self.regimeDock, "left", self.animationDock)
        self.area.addDock(self.propertyDock, "bottom", self.regimeDock)
        self.area.addDock(self.dataDock, "bottom", self.propertyDock)
        self.area.addDock(self.plotDockPlaceholder, "bottom", self.animationDock)
        self.area.addDock(self.logDock, "bottom", self.dataDock)
        self.non_plotting_docks = list(self.area.findAll()[1].keys())

        # add widgets to the docks
        self.propertyDock.addWidget(self.targetView)

        if not vtk_available:
            self._logger.error("loading vtk failed with:{}".format(vtk_error_msg))

        # check if there is a registered visualizer
        available_vis = get_registered_visualizers()
        self._logger.info("found visualizers: {}".format(
            [name for cls, name in available_vis]))
        if available_vis:
            # instantiate the first visualizer
            self._logger.info("loading visualizer '{}'".format(available_vis[0][1]))
            self.animationLayout = QVBoxLayout()

            if issubclass(available_vis[0][0], MplVisualizer):
                self.animationWidget = QWidget()
                self.visualizer = available_vis[0][0](self.animationWidget,
                                                      self.animationLayout)
                self.animationDock.addWidget(self.animationWidget)
            elif issubclass(available_vis[0][0], VtkVisualizer):
                if vtk_available:
                    # vtk window
                    self.animationFrame = QFrame()
                    self.vtkWidget = QVTKRenderWindowInteractor(
                        self.animationFrame)
                    self.animationLayout.addWidget(self.vtkWidget)
                    self.animationFrame.setLayout(self.animationLayout)
                    self.animationDock.addWidget(self.animationFrame)
                    self.vtk_renderer = vtkRenderer()
                    self.vtkWidget.GetRenderWindow().AddRenderer(
                        self.vtk_renderer)
                    self.visualizer = available_vis[0][0](self.vtk_renderer)
                    self.vtkWidget.Initialize()
                else:
                    self._logger.warning("visualizer depends on vtk which is "
                                         "not available on this system!")
            elif available_vis:
                raise NotImplementedError
        else:
            self.visualizer = None

        # regime window
        self.regime_list = QListWidget(self)
        self.regime_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.regimeDock.addWidget(self.regime_list)
        self.regime_list.itemDoubleClicked.connect(self.regime_dclicked)
        self._regimes = []
        self.regime_file_name = ""

        self.actDeleteRegimes = QAction(self.regime_list)
        self.actDeleteRegimes.setText("&Delete Selected Regimes")
        # TODO shortcut works always, not only with focus on the regime list
        # self.actDeleteRegimes.setShortcutContext(Qt.WindowShortcut)
        self.actDeleteRegimes.setShortcut(QKeySequence(Qt.Key_Delete))
        self.actDeleteRegimes.triggered.connect(self.remove_regime_items)

        self.actSave = QAction(self)
        self.actSave.setText('Save Results As')
        self.actSave.setIcon(QIcon(get_resource("save.png")))
        self.actSave.setDisabled(True)
        self.actSave.setShortcut(QKeySequence.Save)
        self.actSave.triggered.connect(self.export_simulation_data)

        self.actLoadRegimes = QAction(self)
        self.actLoadRegimes.setText("Load Regimes from File")
        self.actLoadRegimes.setIcon(QIcon(get_resource("load.png")))
        self.actLoadRegimes.setDisabled(False)
        self.actLoadRegimes.setShortcut(QKeySequence.Open)
        self.actLoadRegimes.triggered.connect(self.load_regime_dialog)

        self.actExitOnBatchCompletion = QAction(self)
        self.actExitOnBatchCompletion.setText("&Exit On Batch Completion")
        self.actExitOnBatchCompletion.setCheckable(True)
        self.actExitOnBatchCompletion.setChecked(
            self._settings.value("control/exit_on_batch_completion") == "True"
        )
        self.actExitOnBatchCompletion.changed.connect(
            self.update_exit_on_batch_completion_setting)

        # regime management
        self.runningBatch = False
        self._current_regime_index = None
        self._current_regime_name = None
        self._regimes = []

        self.regimeFinished.connect(self.run_next_regime)
        self.finishedRegimeBatch.connect(self.regime_batch_finished)

        # data window
        self.dataList = QListWidget(self)
        self.dataDock.addWidget(self.dataList)
        self.dataList.itemDoubleClicked.connect(self.create_plot)

        # actions for simulation control
        self.actSimulateCurrent = QAction(self)
        self.actSimulateCurrent.setText("&Simulate Current Regime")
        self.actSimulateCurrent.setIcon(QIcon(get_resource("simulate.png")))
        self.actSimulateCurrent.setShortcut(QKeySequence("F5"))
        self.actSimulateCurrent.triggered.connect(self.start_simulation)

        self.actSimulateAll = QAction(self)
        self.actSimulateAll.setText("Simulate &All Regimes")
        self.actSimulateAll.setIcon(QIcon(get_resource("execute_regimes.png")))
        self.actSimulateAll.setShortcut(QKeySequence("F6"))
        self.actSimulateAll.setDisabled(True)
        self.actSimulateAll.triggered.connect(self.start_regime_execution)

        # actions for animation control
        self.actAutoPlay = QAction(self)
        self.actAutoPlay.setText("&Autoplay Simulation")
        self.actAutoPlay.setCheckable(True)
        self.actAutoPlay.setChecked(
            self._settings.value("control/autoplay_animation") == "True"
        )
        self.actAutoPlay.changed.connect(self.update_autoplay_setting)

        self.actPlayPause = QAction(self)
        self.actPlayPause.setText("Play Animation")
        self.actPlayPause.setIcon(QIcon(get_resource("play.png")))
        self.actPlayPause.setDisabled(True)
        self.actPlayPause.setShortcut(QKeySequence(Qt.Key_Space))
        self.actPlayPause.triggered.connect(self.play_animation)

        self.actStop = QAction(self)
        self.actStop.setText("Stop")
        self.actStop.setIcon(QIcon(get_resource("stop.png")))
        self.actStop.setDisabled(True)
        self.actStop.triggered.connect(self.stop_animation)

        self.actSlow = QAction(self)
        self.actSlow.setText("Slowest")
        self.actSlow.setIcon(QIcon(get_resource("slow.png")))
        self.actSlow.setDisabled(False)
        self.actSlow.triggered.connect(self.set_slowest_playback_speed)

        self.actFast = QAction(self)
        self.actFast.setText("Fastest")
        self.actFast.setIcon(QIcon(get_resource("fast.png")))
        self.actFast.setDisabled(False)
        self.actFast.triggered.connect(self.set_fastest_playback_speed)

        self.speedControl = QSlider(Qt.Horizontal, self)
        self.speedControl.setMaximumSize(200, 25)
        self.speedControl.setTickPosition(QSlider.TicksBothSides)
        self.speedControl.setDisabled(False)
        self.speedControl.setMinimum(0)
        self.speedControl.setMaximum(12)
        self.speedControl.setValue(6)
        self.speedControl.setTickInterval(6)
        self.speedControl.setSingleStep(2)
        self.speedControl.setPageStep(3)
        self.speedControl.valueChanged.connect(self.update_playback_speed)

        self.timeSlider = QSlider(Qt.Horizontal, self)
        self.timeSlider.setMinimum(0)
        self.timeSliderRange = 1000
        self.timeSlider.setMaximum(self.timeSliderRange)
        self.timeSlider.setTickInterval(1)
        self.timeSlider.setTracking(True)
        self.timeSlider.setDisabled(True)
        self.timeSlider.valueChanged.connect(self.update_playback_time)

        self.playbackTime = .0
        self.playbackGain = 1
        self.currentStepSize = .0
        self.currentEndTime = .0
        self.playbackTimer = QTimer()
        self.playbackTimer.timeout.connect(self.increment_playback_time)
        self.playbackTimeChanged.connect(self.update_gui)
        self.playbackTimeout = 33  # in [ms] -> 30 fps

        self.actResetCamera = QAction(self)
        self.actResetCamera.setText("Reset Camera")
        self.actResetCamera.setIcon(QIcon(get_resource("reset_camera.png")))
        self.actResetCamera.setDisabled(True)
        if available_vis:
            self.actResetCamera.setEnabled(self.visualizer.can_reset_view)
        self.actResetCamera.triggered.connect(self.reset_camera_clicked)

        # postprocessing
        self.actPostprocessing = QAction(self)
        self.actPostprocessing.setText("Launch Postprocessor")
        self.actPostprocessing.setIcon(QIcon(get_resource("processing.png")))
        self.actPostprocessing.setDisabled(False)
        self.actPostprocessing.triggered.connect(self.postprocessing_clicked)
        self.actPostprocessing.setShortcut(QKeySequence("F7"))

        self.postprocessor = None

        # toolbar
        self.toolbarSim = QToolBar("Simulation")
        self.toolbarSim.setContextMenuPolicy(Qt.PreventContextMenu)
        self.toolbarSim.setMovable(False)
        self.toolbarSim.setIconSize(icon_size)
        self.addToolBar(self.toolbarSim)
        self.toolbarSim.addAction(self.actLoadRegimes)
        self.toolbarSim.addAction(self.actSave)
        self.toolbarSim.addSeparator()
        self.toolbarSim.addAction(self.actSimulateCurrent)
        self.toolbarSim.addAction(self.actSimulateAll)
        self.toolbarSim.addSeparator()
        self.toolbarSim.addAction(self.actPlayPause)
        self.toolbarSim.addAction(self.actStop)
        self.toolbarSim.addWidget(self.timeSlider)
        self.toolbarSim.addSeparator()
        self.toolbarSim.addAction(self.actSlow)
        self.toolbarSim.addWidget(self.speedControl)
        self.toolbarSim.addAction(self.actFast)
        self.toolbarSim.addSeparator()
        self.toolbarSim.addAction(self.actPostprocessing)
        self.toolbarSim.addAction(self.actResetCamera)
        self.postprocessor = None

        # log dock
        self.logBox = QPlainTextEdit(self)
        self.logBox.setReadOnly(True)
        self.logDock.addWidget(self.logBox)

        # init logger for logging box
        self.textLogger = PlainTextLogger(logging.INFO)
        self.textLogger.set_target_cb(self.logBox.appendPlainText)
        logging.getLogger().addHandler(self.textLogger)

        # menu bar
        fileMenu = self.menuBar().addMenu("&File")
        fileMenu.addAction(self.actLoadRegimes)
        fileMenu.addAction(self.actSave)
        fileMenu.addAction("&Quit", self.close)

        editMenu = self.menuBar().addMenu("&Edit")
        editMenu.addAction(self.actDeleteRegimes)

        simMenu = self.menuBar().addMenu("&Simulation")
        simMenu.addAction(self.actSimulateCurrent)
        simMenu.addAction(self.actSimulateAll)
        simMenu.addAction(self.actExitOnBatchCompletion)
        simMenu.addAction(self.actPostprocessing)

        animMenu = self.menuBar().addMenu("&Animation")
        animMenu.addAction(self.actPlayPause)
        animMenu.addAction("&Increase Playback Speed",
                           self.increment_playback_speed,
                           QKeySequence(Qt.CTRL + Qt.Key_Plus))
        animMenu.addAction("&Decrease Playback Speed",
                           self.decrement_playback_speed,
                           QKeySequence(Qt.CTRL + Qt.Key_Minus))
        animMenu.addAction("&Reset Playback Speed",
                           self.reset_playback_speed,
                           QKeySequence(Qt.CTRL + Qt.Key_0))
        animMenu.addAction(self.actAutoPlay)
        animMenu.addAction(self.actResetCamera)

        helpMenu = self.menuBar().addMenu("&Help")
        helpMenu.addAction("&Online Documentation", self.show_online_docs)
        helpMenu.addAction("&About", self.show_info)

        # status bar
        self.status = QStatusBar(self)
        self.setStatusBar(self.status)
        self.statusLabel = QLabel("Ready.")
        self.statusBar().addPermanentWidget(self.statusLabel)
        self.timeLabel = QLabel("current time: 0.0")
        self.statusBar().addPermanentWidget(self.timeLabel)

        self._logger.info("Simulation GUI is up and running.")

    def _read_settings(self):

        # add default settings if none are present
        if not self._settings.contains("path/simulation_results"):
            self._settings.setValue("path/simulation_results",
                                    os.path.join(os.path.curdir,
                                                 "results",
                                                 "simulation"))
        if not self._settings.contains("path/postprocessing_results"):
            self._settings.setValue("path/postprocessing_results",
                                    os.path.join(os.path.curdir,
                                                 "results",
                                                 "postprocessing"))
        if not self._settings.contains("path/metaprocessing_results"):
            self._settings.setValue("path/metaprocessing_results",
                                    os.path.join(os.path.curdir,
                                                 "results",
                                                 "metaprocessing"))

        if not self._settings.contains("control/autoplay_animation"):
            self._settings.setValue("control/autoplay_animation", "False")

        if not self._settings.contains("control/exit_on_batch_completion"):
            self._settings.setValue("control/exit_on_batch_completion", "False")

    def _write_settings(self):
        """ Store the application state. """
        pass

    @pyqtSlot()
    def update_autoplay_setting(self):
        self._settings.setValue("control/autoplay_animation",
                                str(self.actAutoPlay.isChecked()))

    @pyqtSlot()
    def update_exit_on_batch_completion_setting(self, state=None):
        if state is None:
            state = self.actExitOnBatchCompletion.isChecked()
        self._settings.setValue("control/exit_on_batch_completion", str(state))

    def set_visualizer(self, vis):
        self.visualizer = vis
        self.vtkWidget.Initialize()

    @pyqtSlot()
    def play_animation(self):
        """
        play the animation
        """
        self._logger.debug("Starting Playback")

        # if we are at the end, start from the beginning
        if self.playbackTime == self.currentEndTime:
            self.timeSlider.setValue(0)

        self.actPlayPause.setText("Pause Animation")
        self.actPlayPause.setIcon(QIcon(get_resource("pause.png")))
        self.actPlayPause.triggered.disconnect(self.play_animation)
        self.actPlayPause.triggered.connect(self.pause_animation)
        self.playbackTimer.start(self.playbackTimeout)

    @pyqtSlot()
    def pause_animation(self):
        """
        pause the animation
        """
        self._logger.debug("Pausing Playback")
        self.playbackTimer.stop()
        self.actPlayPause.setText("Play Animation")
        self.actPlayPause.setIcon(QIcon(get_resource("play.png")))
        self.actPlayPause.triggered.disconnect(self.pause_animation)
        self.actPlayPause.triggered.connect(self.play_animation)

    def stop_animation(self):
        """
        Stop the animation if it is running and reset the playback time.
        """
        self._logger.debug("Stopping Playback")
        if self.actPlayPause.text() == "Pause Animation":
            # animation is playing -> stop it
            self.playbackTimer.stop()
            self.actPlayPause.setText("Play Animation")
            self.actPlayPause.setIcon(QIcon(get_resource("play.png")))
            self.actPlayPause.triggered.disconnect(self.pause_animation)
            self.actPlayPause.triggered.connect(self.play_animation)

        self.timeSlider.setValue(0)

    @pyqtSlot()
    def start_simulation(self):
        """
        start the simulation and disable start button
        """
        if self._current_regime_index is None:
            regime_name = ""
        else:
            regime_name = str(self.regime_list.item(
                self._current_regime_index).text())

        self.statusLabel.setText("simulating {}".format(regime_name))
        self._logger.info("Simulating: {}".format(regime_name))

        self.actSimulateCurrent.setIcon(QIcon(
            get_resource("stop_simulation.png")))
        self.actSimulateCurrent.setText("Abort &Simulation")
        self.actSimulateCurrent.triggered.disconnect(self.start_simulation)
        self.actSimulateCurrent.triggered.connect(self.stop_simulation)

        if not self.runningBatch:
            self.actSimulateAll.setDisabled(True)

        self.guiProgress = QProgressBar(self)
        self.sim.simulationProgressChanged.connect(self.guiProgress.setValue)
        self.statusBar().addWidget(self.guiProgress)
        self.runSimulation.emit()

    @pyqtSlot()
    def stop_simulation(self):
        self.stopSimulation.emit()

    def export_simulation_data(self, ok):
        """
        Query the user for a custom name and export the current simulation
        results.

        :param ok: unused parameter from QAction.triggered() Signal
        """
        self._save_data()

    def _save_data(self, file_path=None):
        """
        Save the current simulation results.

        If *fie_name* is given, the result will be saved to the specified
        location, making automated exporting easier.

        Args:
            file_path(str): Absolute path of the target file. If `None` the
                use will be asked for a storage location.
        """
        regime_name = self._regimes[self._current_regime_index]["Name"]

        if file_path is None:
            # get default path
            path = self._settings.value("path/simulation_results")

            # create canonic file name
            suggestion = self._simfile_name(regime_name)
        else:
            path = os.path.dirname(file_path)
            suggestion = os.path.basename(file_path)

        # check if path exists otherwise create it
        if not os.path.isdir(path):
            box = QMessageBox()
            box.setText("Export Folder does not exist yet.")
            box.setInformativeText("Do you want to create it? \n"
                                   "{}".format(os.path.abspath(path)))
            box.setStandardButtons(QMessageBox.Ok | QMessageBox.No)
            box.setDefaultButton(QMessageBox.Ok)
            ret = box.exec_()
            if ret == QMessageBox.Ok:
                os.makedirs(path)
            else:
                path = os.path.abspath(os.path.curdir)
                file_path = None

        # If no path was given, present the default and let the user choose
        if file_path is None:
            dialog = QFileDialog(self)
            dialog.setAcceptMode(QFileDialog.AcceptSave)
            dialog.setFileMode(QFileDialog.AnyFile)
            dialog.setDirectory(path)
            dialog.setNameFilter("PyMoskito Results (*.pmr)")
            dialog.selectFile(suggestion)

            if dialog.exec_():
                file_path = dialog.selectedFiles()[0]
            else:
                self._logger.warning("Export Aborted")
                return -1

        # ask whether this should act as new default
        path = os.path.abspath(os.path.dirname(file_path))
        if path != self._settings.value("path/simulation_results"):
            box = QMessageBox()
            box.setText("Use this path as new default?")
            box.setInformativeText("{}".format(path))
            box.setStandardButtons(QMessageBox.Yes | QMessageBox.No)
            box.setDefaultButton(QMessageBox.Yes)
            ret = box.exec_()
            if ret == QMessageBox.Yes:
                self._settings.setValue("path/simulation_results", path)

        self.currentDataset.update({"regime name": regime_name})
        with open(file_path, "wb") as f:
            pickle.dump(self.currentDataset, f, protocol=4)

        self.statusLabel.setText("results saved to {}".format(file_path))
        self._logger.info("results saved to {}".format(file_path))

    def _simfile_name(self, regime_name):
        """ Create a canonical name for a simulation result file
        """
        suggestion = (time.strftime("%Y%m%d-%H%M%S")
                      + "_" + regime_name + ".pmr")
        return suggestion

    def load_regime_dialog(self):
        regime_path = os.path.join(os.curdir)

        dialog = QFileDialog(self)
        dialog.setFileMode(QFileDialog.ExistingFile)
        dialog.setDirectory(regime_path)
        dialog.setNameFilter("Simulation Regime files (*.sreg)")

        if dialog.exec_():
            file = dialog.selectedFiles()[0]
            self.load_regimes_from_file(file)

    def load_regimes_from_file(self, file_name):
        """
        load simulation regime from file
        :param file_name:
        """
        self.regime_file_name = os.path.split(file_name)[-1][:-5]
        self._logger.info("loading regime file: {0}".format(self.regime_file_name))
        with open(file_name.encode(), "r") as f:
            self._regimes += yaml.load(f)

        self._update_regime_list()

        if self._regimes:
            self.actSimulateAll.setDisabled(False)

        self._logger.info("loaded {} regimes".format(len(self._regimes)))
        self.statusBar().showMessage("loaded {} regimes.".format(len(self._regimes)), 1000)
        return

    def _update_regime_list(self):
        self.regime_list.clear()
        for reg in self._regimes:
            self._logger.debug("adding '{}' to regime list".format(reg["Name"]))
            self.regime_list.addItem(reg["Name"])

    def remove_regime_items(self):
        if self.regime_list.currentRow() >= 0:
            # flag all selected files as invalid
            items = self.regime_list.selectedItems()
            for item in items:
                del self._regimes[self.regime_list.row(item)]
                self.regime_list.takeItem(self.regime_list.row(item))

    @pyqtSlot(QListWidgetItem)
    def regime_dclicked(self, item):
        """
        Apply the selected regime to the current target.
        """
        self.apply_regime_by_name(str(item.text()))

    def apply_regime_by_name(self, regime_name):
        """
        Apply the regime given by `regime_name` und update the regime index.

        Returns:
            bool: `True` if successful, `False` if errors occurred.
        """
        # get regime idx
        try:
            idx = list(map(itemgetter("Name"), self._regimes)).index(regime_name)
        except ValueError as e:
            self._logger.error("apply_regime_by_name(): Error no regime called "
                               "'{0}'".format(regime_name))
            return False

        # apply
        return self._apply_regime_by_idx(idx)

    def _apply_regime_by_idx(self, index=0):
        """
        Apply the given regime.

        Args:
            index(int): Index of the regime in the `RegimeList` .

        Returns:
            bool: `True` if successful, `False` if errors occurred.
        """
        if index >= len(self._regimes):
            self._logger.error("applyRegime: index error! ({})".format(index))
            return False

        reg_name = self._regimes[index]["Name"]
        self.statusBar().showMessage("regime {} applied.".format(reg_name),
                                     1000)
        self._logger.info("applying regime '{}'".format(reg_name))

        self._current_regime_index = index
        self._current_regime_name = reg_name

        return self.sim.set_regime(self._regimes[index])

    @pyqtSlot()
    def start_regime_execution(self):
        """
        Simulate all regimes in the regime list.
        """
        self.actSimulateAll.setText("Stop Simulating &All Regimes")
        self.actSimulateAll.setIcon(QIcon(get_resource("stop_batch.png")))
        self.actSimulateAll.triggered.disconnect(self.start_regime_execution)
        self.actSimulateAll.triggered.connect(self.stop_regime_excecution)

        self.runningBatch = True
        self._current_regime_index = -1
        self.regimeFinished.emit()

    def run_next_regime(self):
        """
        Execute the next regime in the regime batch.
        """
        # are we finished?
        if self._current_regime_index == len(self._regimes) - 1:
            self.finishedRegimeBatch.emit(True)
            return

        suc = self._apply_regime_by_idx(self._current_regime_index + 1)
        if not suc:
            self.finishedRegimeBatch.emit(False)
            return

        self.start_simulation()

    @pyqtSlot()
    def stop_regime_excecution(self):
        """ Stop the batch process.
        """
        self.stopSimulation.emit()
        self.finishedRegimeBatch.emit(False)

    def regime_batch_finished(self, status):
        self.runningBatch = False
        self.actSimulateAll.setDisabled(False)
        self.actSave.setDisabled(True)

        self.actSimulateAll.setText("Simulate &All Regimes")
        self.actSimulateAll.setIcon(QIcon(get_resource("execute_regimes.png")))
        self.actSimulateAll.triggered.disconnect(self.stop_regime_excecution)
        self.actSimulateAll.triggered.connect(self.start_regime_execution)

        if status:
            self.statusLabel.setText("All regimes have been simulated")
            self._logger.info("All Regimes have been simulated")
        else:
            self._logger.error("Batch simulation has been aborted")

        if self._settings.value("control/exit_on_batch_completion") == "True":
            self._logger.info("Shutting down SimulationGUI")
            self.close()

    @pyqtSlot(str, dict, name="new_simulation_data")
    def new_simulation_data(self, status, data):
        """
        Slot to be called when the simulation interface has completed the
        current job and new data is available.

        Args:
            status (str): Status of the simulation, either
                - `finished` : Simulation has been finished successfully or
                - `failed` : Simulation has failed.
            data (dict): Dictionary, holding the simulation data.
        """
        self._logger.info("Simulation {}".format(status))
        self.statusLabel.setText("Simulation {}".format(status))

        self.actSimulateCurrent.setText("&Simulate Current Regime")
        self.actSimulateCurrent.setIcon(QIcon(get_resource("simulate.png")))
        self.actSimulateCurrent.triggered.disconnect(self.stop_simulation)
        self.actSimulateCurrent.triggered.connect(self.start_simulation)

        self.actPlayPause.setDisabled(False)
        self.actStop.setDisabled(False)
        self.actSave.setDisabled(False)
        self.speedControl.setDisabled(False)
        self.timeSlider.setDisabled(False)

        self.sim.simulationProgressChanged.disconnect(self.guiProgress.setValue)
        self.statusBar().removeWidget(self.guiProgress)

        self.stop_animation()

        self.currentDataset = data
        if data:
            self._read_results()
            self._update_data_list()
            self._update_plots()

        if self._settings.value("control/autoplay_animation") == "True":
            self.actPlayPause.trigger()

        if self.runningBatch:
            regime_name = self._regimes[self._current_regime_index]["Name"]
            file_name = self._simfile_name(regime_name)
            self._save_data(os.path.join(
                self._settings.value("path/simulation_results"),
                file_name))
            self.regimeFinished.emit()
        else:
            self.actSimulateAll.setDisabled(False)

    def _read_results(self):
        state = self.currentDataset["results"]["Solver"]
        self.interpolator = interp1d(self.currentDataset["results"]["time"],
                                     state,
                                     axis=0,
                                     bounds_error=False,
                                     fill_value=(state[0], state[-1]))
        self.currentStepSize = 1.0/self.currentDataset["simulation"][
            "measure rate"]
        self.currentEndTime = self.currentDataset["simulation"]["end time"]
        self.validData = True

    def increment_playback_speed(self):
        self.speedControl.setValue(self.speedControl.value()
                                   + self.speedControl.singleStep())

    def decrement_playback_speed(self):
        self.speedControl.setValue(self.speedControl.value()
                                   - self.speedControl.singleStep())

    def reset_playback_speed(self):
        self.speedControl.setValue((self.speedControl.maximum()
                                    - self.speedControl.minimum())/2)

    def set_slowest_playback_speed(self):
        self.speedControl.setValue(self.speedControl.minimum())

    def set_fastest_playback_speed(self):
        self.speedControl.setValue(self.speedControl.maximum())

    def update_playback_speed(self, val):
        """
        adjust playback time to slider value

        :param val:
        """
        maximum = self.speedControl.maximum()
        self.playbackGain = 10**(3.0 * (val - maximum / 2) / maximum)

    @pyqtSlot()
    def increment_playback_time(self):
        """
        go one time step forward in playback
        """
        if self.playbackTime == self.currentEndTime:
            self.pause_animation()
            return

        increment = self.playbackGain * self.playbackTimeout / 1000
        self.playbackTime = min(self.currentEndTime,
                                self.playbackTime + increment)
        pos = int(self.playbackTime / self.currentEndTime
                  * self.timeSliderRange)
        self.timeSlider.blockSignals(True)
        self.timeSlider.setValue(pos)
        self.timeSlider.blockSignals(False)
        self.playbackTimeChanged.emit()

    def update_playback_time(self):
        """
        adjust playback time to slider value
        """
        self.playbackTime = self.timeSlider.value()/self.timeSliderRange*self.currentEndTime
        self.playbackTimeChanged.emit()
        return

    def update_gui(self):
        """
        updates the graphical user interface, including:
            - timestamp
            - visualisation
            - time cursor in diagrams
        """
        if not self.validData:
            return

        self.timeLabel.setText("current time: %4f" % self.playbackTime)

        # update time cursor in plots
        self._update_time_cursors()

        # update state of rendering
        if self.visualizer:
            state = self.interpolator(self.playbackTime)
            self.visualizer.update_scene(state)
            if isinstance(self.visualizer, MplVisualizer):
                pass
            elif isinstance(self.visualizer, VtkVisualizer):
                self.vtkWidget.GetRenderWindow().Render()

    def _update_data_list(self):
        self.dataList.clear()
        for module_name, results in self.currentDataset["results"].items():
            if not isinstance(results, np.ndarray):
                continue
            if len(results.shape) == 1:
                self.dataList.insertItem(0, module_name)
            elif len(results.shape) == 2:
                for col in range(results.shape[1]):
                    self.dataList.insertItem(
                        0,
                        self._build_entry_name(module_name, (col, ))
                    )
            elif len(results.shape) == 3:
                for col in range(results.shape[1]):
                    for der in range(results.shape[2]):
                        self.dataList.insertItem(
                            0,
                            self._build_entry_name(module_name, (col, der))
                        )

    def _build_entry_name(self, module_name, idx):
        """
        Construct an identifier for a given entry of a module.
        Args:
            module_name (str): name of the module the entry belongs to.
            idx (tuple): Index of the entry.

        Returns:
            str: Identifier to use for display.
        """
        # save the user from defining 1d entries via tuples
        if len(idx) == 1:
            m_idx = idx[0]
        else:
            m_idx = idx

        mod_settings = self.currentDataset["modules"]
        info = mod_settings.get(module_name, {}).get("output_info", None)
        if info:
            if m_idx in info:
                return ".".join([module_name, info[m_idx]["Name"]])

        return ".".join([module_name] + [str(i) for i in idx])

    def _get_index_from_suffix(self, module_name, suffix):
        info = self.currentDataset["modules"].get(module_name, {}).get(
            "output_info", None)
        idx = next((i for i in info if info[i]["Name"] == suffix), None)
        return idx

    def _get_units(self, entry):
        """
        Return the unit that corresponds to a given entry.

        If no information is available, None is returned.

        Args:
            entry (str): Name of the entry. This can either be "Model.a.b" where
                a and b are numbers or if information is available "Model.Signal"
                where signal is the name of that part.

        Returns:

        """
        args = entry.split(".")
        module_name = args.pop(0)
        info = self.currentDataset["modules"].get(module_name, {}).get(
            "output_info", None)
        if info is None:
            return None

        if len(args) == 1:
            try:
                idx = int(args[0])
            except ValueError:
                idx = next((i for i in info if info[i]["Name"] == args[0]),
                           None)
        else:
            idx = (int(a) for a in args)

        return info[idx]["Unit"]

    def create_plot(self, item):
        """
        Creates a plot widget based on the given item.

        If a plot for this item is already open no new plot is created but the
        existing one is raised up again.

        Args:
            item(Qt.ListItem): Item to plot.
        """
        title = str(item.text())
        if title in self.non_plotting_docks:
            self._logger.error("Title '{}' not allowed for a plot window since"
                               "it would shadow on of the reserved "
                               "names".format(title))

        # check if plot has already been opened
        if title in self.area.findAll()[1]:
            self.area.docks[title].raiseDock()
            return

        # collect data
        data = self._get_data_by_name(title)
        t = self.currentDataset["results"]["time"]
        unit = self._get_units(title)
        if "." in title:
            name = title.split(".")[1]
        else:
            name = title

        # create plot widget
        widget = pg.PlotWidget(title=title)
        widget.showGrid(True, True)
        widget.plot(x=t, y=data)
        widget.getPlotItem().getAxis("bottom").setLabel(text="Time", units="s")
        widget.getPlotItem().getAxis("left").setLabel(text=name, units=unit)

        # add a time line
        time_line = pg.InfiniteLine(self.playbackTime,
                                    angle=90,
                                    movable=False,
                                    pen=pg.mkPen("#FF0000", width=2.0))
        widget.getPlotItem().addItem(time_line)

        # create dock container and add it to dock area
        dock = pg.dockarea.Dock(title, closable=True)
        dock.addWidget(widget)
        self.area.addDock(dock, "above", self.plotDockPlaceholder)

    def _get_data_by_name(self, name):
        tmp = name.split(".")
        module_name = tmp[0]
        if len(tmp) == 1:
            data = np.array(self.currentDataset["results"][module_name])
        elif len(tmp) == 2:
            try:
                idx = int(tmp[1])
            except ValueError:
                idx = self._get_index_from_suffix(module_name, tmp[1])
            finally:
                data = self.currentDataset["results"][module_name][..., idx]
        elif len(tmp) == 3:
            idx = int(tmp[1])
            der = int(tmp[2])
            data = self.currentDataset["results"][module_name][..., idx, der]
        else:
            raise ValueError("Format not supported")

        return data

    def _update_time_cursors(self):
        """
        Update the time lines of all plot windows
        """
        for title, dock in self.area.findAll()[1].items():
            if title in self.non_plotting_docks:
                continue
            for widget in dock.widgets:
                for item in widget.getPlotItem().items:
                    if isinstance(item, pg.InfiniteLine):
                        item.setValue(self.playbackTime)

    def _update_plots(self):
        """
        Update the data in all plot windows
        """
        for title, dock in self.area.findAll()[1].items():
            if title in self.non_plotting_docks:
                continue

            if not self.dataList.findItems(dock.name(), Qt.MatchExactly):
                # no data for this plot -> remove it
                dock.close()
                continue

            for widget in dock.widgets:
                for item in widget.getPlotItem().items:
                    if isinstance(item, pg.PlotDataItem):
                        x_data = self.currentDataset["results"]["time"]
                        y_data = self._get_data_by_name(dock.name())
                        item.setData(x=x_data, y=y_data)

    @pyqtSlot(QModelIndex)
    def target_view_changed(self, index):
        self.targetView.resizeColumnToContents(0)

    def postprocessing_clicked(self):
        """
        starts the post- and metaprocessing application
        """
        self._logger.info("launching postprocessor")
        self.statusBar().showMessage("launching postprocessor", 1000)
        if self.postprocessor is None:
            self.postprocessor = PostProcessor()

        self.postprocessor.show()

    def reset_camera_clicked(self):
        """
        reset camera in vtk window
        """
        self.visualizer.reset_camera()
        self.vtkWidget.GetRenderWindow().Render()

    def show_info(self):
        icon_lic = open(get_resource("license.txt"), "r").read()
        text = "This application was build using PyMoskito ver. {} .<br />" \
               "PyMoskito is free software distributed under GPLv3. <br />" \
               "It is developed by members of the " \
               "<a href=\'https://tu-dresden.de/ing/elektrotechnik/rst'>" \
               "Institute of Control Theory</a>" \
               " at the <a href=\'https://tu-dresden.de'>" \
               "Dresden University of Technology</a>. <br />" \
               "".format(pkg_resources.require("PyMoskito")[0].version) \
               + "<br />" + icon_lic
        box = QMessageBox.about(self, "PyMoskito", text)

    def show_online_docs(self):
        webbrowser.open("https://pymoskito.readthedocs.org")

    def closeEvent(self, QCloseEvent):
        self._logger.info("Close Event received, shutting down.")
        logging.getLogger().removeHandler(self.textLogger)
        super().closeEvent(QCloseEvent)
Пример #16
0
class IRSGUI(QWidget):
    """Image Retrieval System GUI"""
    def __init__(self, args):
        super(IRSGUI, self).__init__()
        self.args = args
        self.state = _STATE(self.args)
        self._setup()
        self._layout()
        self._connect()
        self._init_dataset()
        self.setStyleSheet(self.args.style)

    def _init_dataset(self):
        self.dataset = Dataset(self.args.dataset)
        self._images()

    def _connect(self):
        self.select.clicked.connect(self._slot_search)
        self.edit.textChanged.connect(self._slot_edit)
        self.rarea.itemDoubleClicked.connect(self._slot_rarea_dc)
        self.rarea.itemClicked.connect(self._slot_rarea)

    def _setup(self):
        self.select = QPushButton()
        self.select.setIcon(QIcon(QPixmap(self.args.search)))
        self.select.setStyleSheet(self.args.style)
        self.edit = DndEdit()
        self.edit.setDragEnabled(True)
        self.edit.setStyleSheet(self.args.style)
        self.edit.setMaximumWidth(self.args.lineEdit[1])
        self.edit.setMinimumWidth(self.args.lineEdit[0])
        self.rarea = QListWidget()
        self.rarea.setIconSize(
            QSize(self.args.image_size[0], self.args.image_size[1]))
        self.rarea.setResizeMode(QListView.Adjust)
        self.rarea.setFixedWidth(self.args.fix)
        self.rarea.verticalScrollBar().setStyleSheet(self.args.style)
        self.rarea.setViewMode(QListView.IconMode)
        self.rarea.setMovement(QListView.Static)
        self.rarea.setSpacing(self.args.space)
        self.rarea.setStyleSheet(self.args.style)

    def _layout(self):
        hbox = QHBoxLayout()
        hbox.setContentsMargins(self.args.margins[0], self.args.margins[1],
                                self.args.margins[2], self.args.margins[3])
        hbox.addStretch(1)
        hbox.addWidget(self.edit)
        hbox.addWidget((self.select))
        hbox.addStretch(1)

        self.vbox = QVBoxLayout(self)
        self.vbox.addLayout(hbox)
        self.vbox.addWidget(self.hline())
        self.hbox = QHBoxLayout()
        self.hbox.addStretch(1)
        self.hbox.addWidget(self.rarea)
        self.hbox.addStretch(1)
        # self.vbox.addWidget(self.rarea)
        self.vbox.addLayout(self.hbox)

    def hline(self):
        hline = QFrame()
        hline.setFrameShape(QFrame.HLine)
        hline.setFrameShadow(QFrame.Sunken)
        return hline

    def _create_image(self, image):
        im = QLabel()
        im.setFixedSize(self.args.image_size[0], self.args.image_size[1])
        pix = QPixmap(image)
        im.setPixmap(pix)
        im.setScaledContents(True)
        return im

    def _create_icon(self, image):
        pix = QPixmap(image)
        item = ImageItem(
            QIcon(
                pix.scaled(
                    QSize(self.args.image_size[0], self.args.image_size[1]))),
            image)
        item.setSizeHint(
            QSize(self.args.image_size[0], self.args.image_size[1]))
        return item

    def _slot_edit(self):
        text = self.edit.text()
        if self.edit.legal(text):
            if os.path.isfile(text):
                self.IRetrieval = text
                self.rarea.clear()
                self.state.reset()
                rank_images = self.state.retrieval.metric(self.IRetrieval)
                if rank_images is None:
                    return
                self.state.rank_images = rank_images
                self.rarea.addItem(self._create_icon(self.IRetrieval))
                self._rank_images(rank_images)

    def _slot_search(self):
        image = QFileDialog.getOpenFileName(
            directory='.',
            filter='Images (*.png *.jpeg *.bmp *.jpg)',
            parent=self,
            caption='select a picture to search')
        if image[0] != '':
            self.edit.setText(image[0])

    def _slot_rarea(self, imItem):
        self.IRetrieval = imItem.image
        dialog = ImageDetails(self, imItem.image, self.args)
        dialog.exec_()

    def _slot_rarea_dc(self, imItem):
        pass

    def slot_detail_search(self):
        if hasattr(self, 'IRetrieval'):
            rank_images = self.state.retrieval.metric(self.IRetrieval)
            if rank_images is None:
                return
            self.rarea.clear()
            self.state.reset()
            self.state.rank_images = rank_images
            self._rank_images(rank_images)

    def _rank_images(self, rank_images):
        for idx in range(self.args.top):
            if idx >= len(rank_images):
                break
            self.rarea.addItem(
                self._create_icon(self.dataset.absolute(rank_images[idx])))
            self.state.rank_index += 1

    def _images(self):
        for idx in range(self.args.start_number):
            if idx >= len(self.dataset):
                break
            self.rarea.insertItem(
                idx,
                self._create_icon(self.dataset.absolute(self.dataset[idx])))
            self.state.index += 1

    def resizeEvent(self, QResizeEvent):
        pass

    def wheelEvent(self, QWheelEvent):
        para = QWheelEvent.angleDelta().y()
        if para < 0:
            if self.state.is_retrieval:
                index = self.state.rank_index
                dataset = self.state.rank_images
            else:
                index = self.state.index
                dataset = self.dataset
            incre = self.args.incre
            if (index + self.args.incre) > len(dataset):
                incre = len(dataset) - index - 1
            if incre <= 0:
                return
            for incre_idx in range(incre):
                self.rarea.addItem(
                    self._create_icon(
                        self.dataset.absolute(dataset[index + incre_idx])))
                if self.state.is_retrieval:
                    self.state.rank_index += 1
                else:
                    self.state.index += 1
Пример #17
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.title = 'To The Beat'
        self.can_start = {'vid_chooser_list': False, 'music_file_textbox': False, 'output_file_textbox': False, 'isRendering': False}
        self.vids = []
        self.was_canceled = False
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)

        self.central_widget = QWidget()
        self.layout = QVBoxLayout()

        self.tabs = QTabWidget()
        self.inputTab = QWidget()
        self.inputLayout = QVBoxLayout()
        self.inputTab.setLayout(self.inputLayout)
        self.optionsTab = QWidget()
        self.optionsGrid = QGridLayout()
        self.optionsLayout = QVBoxLayout()
        self.optionsTab.setLayout(self.optionsLayout)

        self.tabs.addTab(self.inputTab, 'Input')
        self.tabs.addTab(self.optionsTab, 'Options')
        
        # Video chooser
        self.vid_chooser_list = QListWidget()
        self.vid_chooser_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.vid_chooser_list.setIconSize(QSize(320/3, 240/3))
        self.vid_chooser_list.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.vid_chooser_model = self.vid_chooser_list.model()
        self.vid_chooser_model.rowsInserted.connect(self.changeVidChooserBtnState)
        self.vid_chooser_model.rowsRemoved.connect(self.changeVidChooserBtnState)

        self.vid_add_btn = QPushButton('Add')
        self.vid_add_btn.clicked.connect(self.addVideos)
        self.vid_rm_btn = QPushButton('Remove')
        self.vid_rm_btn.clicked.connect(self.removeVideos)
        self.vid_up_btn = QPushButton('Up')
        self.vid_up_btn.clicked.connect(self.moveVideosUp)
        self.vid_down_btn = QPushButton('Down')
        self.vid_down_btn.clicked.connect(self.moveVideosDown)

        self.vid_chooser_btn_layout = QVBoxLayout()
        self.vid_chooser_btn_layout.setContentsMargins(0, 0, 0, 0)
        self.vid_chooser_btn_layout.setSpacing(0)
        self.vid_chooser_btn_layout.addWidget(self.vid_add_btn)
        self.vid_chooser_btn_layout.addWidget(self.vid_rm_btn)
        self.vid_chooser_btn_layout.addWidget(self.vid_up_btn)
        self.vid_chooser_btn_layout.addWidget(self.vid_down_btn)
        self.vid_chooser_btn_layout.addStretch(0)

        self.vid_chooser_layout = QHBoxLayout()
        self.vid_chooser_layout.addWidget(self.vid_chooser_list)
        self.vid_chooser_layout.addLayout(self.vid_chooser_btn_layout)

        self.vid_chooser_group_box = QGroupBox('Video files')
        self.vid_chooser_group_box.setLayout(self.vid_chooser_layout)

        # Music chooser
        self.music_file_textbox = QLineEdit()
        self.music_file_textbox.textChanged.connect(self.musicFileTextboxChanged)
        self.music_file_browse_btn = QPushButton('Browse')
        self.music_file_browse_btn.clicked.connect(self.browseMusicFile)

        self.music_chooser_layout = QHBoxLayout()
        self.music_chooser_layout.addWidget(self.music_file_textbox)
        self.music_chooser_layout.addWidget(self.music_file_browse_btn)

        self.music_chooser_group_box = QGroupBox('Music')
        self.music_chooser_group_box.setLayout(self.music_chooser_layout)

        # Output vid chooser
        self.output_file_textbox = QLineEdit()
        self.output_file_textbox.textChanged.connect(self.outputFileTextboxChanged)
        self.output_file_browse_btn = QPushButton('Browse')
        self.output_file_browse_btn.clicked.connect(self.browseOutputFile)

        self.output_chooser_layout = QHBoxLayout()
        self.output_chooser_layout.addWidget(self.output_file_textbox)
        self.output_chooser_layout.addWidget(self.output_file_browse_btn)

        self.output_chooser_group_box = QGroupBox('Output')
        self.output_chooser_group_box.setLayout(self.output_chooser_layout)

        # OPTIONS
        split_beat_tooltip = 'Change this option to change when in the music the video cuts to another clip. Multiples of 3 and 4 work best for most music.'
        self.split_beat_spinbox = QSpinBox()
        self.split_beat_spinbox.setMinimum(1)
        self.split_beat_spinbox.setValue(4)
        self.split_beat_spinbox.setPrefix('Cut every ')
        self.split_beat_spinbox.setSuffix(' beats')
        self.split_beat_spinbox.setToolTip(split_beat_tooltip)

        sep_tooltip = 'Clips from the same video must be at least this many seconds apart.'
        self.sep_spinbox = QSpinBox()
        self.sep_spinbox.setMinimum(1)
        self.sep_spinbox.setValue(5)
        self.sep_spinbox.setSuffix(' seconds')
        self.sep_spinbox.setToolTip(sep_tooltip)

        # TODO: Add a button in this combobox that says 'Custom resolution', and it pops up with a dialog box allowing you to input custom resolution
        resolution_tooltip = 'Sets the output resolution of the video. Select "Custom resolution" to set your own. Higher resolutions will take longer to render.'
        self.resolution_combobox = QComboBox()
        self.resolution_combobox.addItems([
            '1280 x 720 (720p)',
            '1920 x 1080 (1080p)',
            '3840 x 2160 (4K)',
            'Custom resolution'
        ])
        self.resolution_combobox.insertSeparator(3)
        self.resolution_combobox.setToolTip(resolution_tooltip)

        fps_tooltip = 'Sets the output frames per second of the video. The default value of 30fps should work well for most videos.'
        self.fps_spinbox = QSpinBox()
        self.fps_spinbox.setMinimum(1)
        self.fps_spinbox.setValue(30)
        self.fps_spinbox.setSuffix(' fps')
        self.fps_spinbox.setToolTip(fps_tooltip)

        preset_tooltip = 'Sets the FFmpeg render preset. Faster presets will result in faster render times but bigger file sizes.'
        self.preset_combobox = QComboBox()
        self.preset_combobox.addItems([
            'ultrafast', 
            'superfast',
            'veryfast',
            'faster',
            'fast',
            'medium',
            'slow',
            'slower',
            'veryslow'
        ])
        self.preset_combobox.setCurrentIndex(0) #ultrafast
        self.preset_combobox.setToolTip(preset_tooltip)

        self.options = [
            [QLabel('Beat to cut at'), self.split_beat_spinbox],
            [QLabel('Minimum separation time'), self.sep_spinbox],
            [QLabel('Frames per second'), self.fps_spinbox],
            [QLabel('Resolution'), self.resolution_combobox],
            [QLabel('FFmpeg render preset'), self.preset_combobox]
        ]

        for r, row in enumerate(self.options):
            for c, widget in enumerate(row):
                self.optionsGrid.addWidget(widget, r, c)
        
        self.optionsLayout.addWidget(QLabel('Hover over an option to learn more about it'))
        self.optionsLayout.addLayout(self.optionsGrid)
        self.optionsLayout.addStretch()

        # Start button (create video?)
        # Maybe make button bigger vertically so it's more obvious?
        self.start_btn = QPushButton('Start')
        self.start_btn.clicked.connect(self.start)
        self.changeVidChooserBtnState()

        self.stop_btn = QPushButton('Cancel')
        self.stop_btn.clicked.connect(self.stop)
        self.stop_btn.hide()
        
        self.progress_bar = QProgressBar()
        self.progress_bar.setMaximum(100)
        self.progress_bar.setValue(0)
        self.progress_bar.hide()

        # Add everything to the main layout
        self.inputLayout.addWidget(self.vid_chooser_group_box)
        self.inputLayout.addWidget(self.music_chooser_group_box)

        self.layout.addWidget(self.tabs)
        self.layout.addWidget(self.output_chooser_group_box)
        self.layout.addWidget(self.start_btn)
        self.layout.addWidget(self.stop_btn)
        self.layout.addWidget(self.progress_bar)

        self.central_widget.setLayout(self.layout)
        self.setCentralWidget(self.central_widget)

        self.show()

    def checkCanStart(self):
        if self.can_start['vid_chooser_list'] and self.can_start['music_file_textbox'] and self.can_start['output_file_textbox'] and not self.can_start['isRendering']:
            self.start_btn.setEnabled(True)
        else:
            self.start_btn.setEnabled(False)
    
    def changeVidChooserBtnState(self):
        if len(self.vid_chooser_list) > 0:
            self.vid_rm_btn.setEnabled(True)
            self.vid_up_btn.setEnabled(True)
            self.vid_down_btn.setEnabled(True)

            self.can_start['vid_chooser_list'] = True
        else:
            self.vid_rm_btn.setEnabled(False)
            self.vid_up_btn.setEnabled(False)
            self.vid_down_btn.setEnabled(False)

            self.can_start['vid_chooser_list'] = False
        
        self.checkCanStart()

    def musicFileTextboxChanged(self):
        if len(self.music_file_textbox.text()) > 0:
            self.can_start['music_file_textbox'] = True
        else:
            self.can_start['music_file_textbox'] = False
        
        self.checkCanStart()

    def outputFileTextboxChanged(self):
        if len(self.output_file_textbox.text()) > 0:
            self.can_start['output_file_textbox'] = True
        else:
            self.can_start['output_file_textbox'] = False
        
        self.checkCanStart()

    def addVideos(self):
        file_names = QFileDialog.getOpenFileNames(self, 'Select video files', '', (
            'Video and Image files (*.mp4 *.avi *.mov *.flv *.wmv *.png *.jpg *.bpm *.tiff *.gif *.webp)'
        ))[0]

        QApplication.setOverrideCursor(Qt.WaitCursor)
        with tempfile.TemporaryDirectory() as dir:
            for i, name in enumerate(file_names):
                thumbnail_name = f'{dir}/{str(uuid.uuid4())}.jpg'
                tothebeat.createThumbnail(name, thumbnail_name)

                short_name = name.split('/')[-1]
                self.vid_chooser_list.addItem(QListWidgetItem(QIcon(thumbnail_name), short_name))
                self.vids.append(name)
        QApplication.restoreOverrideCursor()

    def removeVideos(self):
        for selected_widget in self.vid_chooser_list.selectedItems():
            index = self.vid_chooser_list.row(selected_widget)
            self.vid_chooser_list.takeItem(index)
            self.vids.pop(index)

    def moveVideosUp(self):
        selected_rows = [self.vid_chooser_list.row(selected_widget) for selected_widget in self.vid_chooser_list.selectedItems()]
        selected_rows.sort()

        if 0 not in selected_rows:
            for row in selected_rows:
                widget = self.vid_chooser_list.takeItem(row)
                self.vid_chooser_list.insertItem(row-1, widget)
                widget.setSelected(True)
                
                self.vids.insert(row-1, self.vids.pop(row))

    def moveVideosDown(self):
        selected_rows = [self.vid_chooser_list.row(selected_widget) for selected_widget in self.vid_chooser_list.selectedItems()]
        selected_rows.sort(reverse=True)
        
        if len(self.vid_chooser_list)-1 not in selected_rows:
            for row in selected_rows:
                widget = self.vid_chooser_list.takeItem(row)
                self.vid_chooser_list.insertItem(row+1, widget)
                widget.setSelected(True)

                self.vids.insert(row+1, self.vids.pop(row))

    def browseMusicFile(self):
        file_name = QFileDialog.getOpenFileName(self, 'Select a music file', '', 'Audio files (*.3gp *.aa *.aac *.aax *.act *.aiff *.amr *.ape *.au *.awb *.dct *.dss *.dvf *.flac *.gsm *.iklax *.ivs *.m4a *.m4b *.m4p *.mmf *.mp3 *.mpc *.msv *.nmf *.nsf *.ogg *.oga *.mogg *.opus *.ra *.rm *.raw *.sln *.tt *.vox *.wav *.webm *.wma *.wv)')[0]
        self.music_file_textbox.setText(file_name)

    def browseOutputFile(self):
        file_name = QFileDialog.getSaveFileName(self, 'Save output video as...', '', 'Video files (*.mp4 *.avi *.mov *.flv *.wmv)')[0]
        self.output_file_textbox.setText(file_name)

    def start(self):
        self.output_file_name = self.output_file_textbox.text()
        resolution = self.resolution_combobox.currentText().split('(')[0].strip().split('x')
        resolution_w = int(resolution[0].strip())
        resolution_h = int(resolution[1].strip())
        sep = self.sep_spinbox.value()
        fps = self.fps_spinbox.value()
        split_every_n_beat = self.split_beat_spinbox.value()
        preset = self.preset_combobox.currentText()

        self.progress_bar.show()
        self.progress_bar.setValue(0)

        self.render_thread = RenderVideoThread(
            self.music_file_textbox.text(),
            self.output_file_name,
            resolution_w,
            resolution_h,
            sep=sep,
            fps=fps,
            split_every_n_beat=split_every_n_beat,
            preset=preset,
            vids=self.vids
        )
        self.render_thread.setProgress.connect(self.setProgress)
        self.render_thread.showErrorMessage.connect(self.showErrorMessage)
        self.render_thread.canceled.connect(self.canceled)
        self.render_thread.finished.connect(self.done)
        self.render_thread.start()

        #self.stop_btn.clicked.connect(self.render_thread.terminate)
        self.stop_btn.show()

        self.can_start['isRendering'] = True
        self.checkCanStart()

    def stop(self):
        ans = QMessageBox.warning(None, 'Cancel render', 'Are you sure you want to cancel the rendering of this video?', QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
        if ans == QMessageBox.Yes:
            self.render_thread.stop(canceled=True)
            self.render_thread.wait()

    def setProgress(self, progress):
        self.progress_bar.setValue(progress)

    def showErrorMessage(self, error_log_path):
        QMessageBox.critical(self, 'Something went wrong!', f'The video could not be rendered for some reason. A log of the error can be found at: {error_log_path}')
        self.render_thread.stop()
        self.render_thread.wait()

    def canceled(self):
        self.was_canceled = True
        QMessageBox.information(self, 'Canceled', 'The rendering of the video has been successfully canceled.')

    def done(self):
        if os.path.isfile(self.output_file_name) and not self.was_canceled:
            self.progress_bar.setValue(100)
            QMessageBox.information(self, 'Render complete!', f'Video has been successfully rendered to {self.output_file_name}!')
        self.was_canceled = False
        self.progress_bar.hide()
        self.progress_bar.setValue(0)
        self.stop_btn.hide()
        self.can_start['isRendering'] = False
        self.checkCanStart()
Пример #18
0
class manufacturerStack(QWidget):
    def __init__(self):

        super(manufacturerStack, self).__init__()
        self.leftlist = QListWidget()
        self.leftlist.setFixedWidth(250)
        self.leftlist.insertItem(0, 'Add Stock')
        self.leftlist.insertItem(1, 'Manage Stock')
        self.leftlist.insertItem(2, 'View Stock')

        self.stack1 = QWidget()
        self.stack2 = QWidget()
        self.stack3 = QWidget()

        self.stack1UI()
        self.stack2UI()
        self.stack3UI()

        self.Stack = QStackedWidget(self)
        self.Stack.addWidget(self.stack1)
        self.Stack.addWidget(self.stack2)
        self.Stack.addWidget(self.stack3)

        hbox = QHBoxLayout(self)
        hbox.addWidget(self.leftlist)
        hbox.addWidget(self.Stack)

        self.setLayout(hbox)
        self.leftlist.currentRowChanged.connect(self.display)
        self.setGeometry(500, 350, 200, 200)
        self.setWindowTitle('Stock Management')
        self.show()

    def stack1UI(self):  # ADD STOCK UI
        layout = QFormLayout()
        self.add_mes = QLabel()

        self.ok = QPushButton('Add Stock', self)
        clear = QPushButton('Clear', self)

        self.stock_name = QLineEdit()
        layout.addRow("Stock Name", self.stock_name)

        self.stock_count = QLineEdit()
        layout.addRow("Quantity", self.stock_count)

        self.stock_cost = QLineEdit()
        layout.addRow("Cost of Stock (per item)", self.stock_cost)

        layout.addWidget(self.ok)
        layout.addWidget(clear)
        layout.addWidget(self.add_mes)

        self.ok.clicked.connect(self.on_click)

        # clear the data from the screen
        clear.clicked.connect(self.stock_name.clear)
        clear.clicked.connect(self.stock_cost.clear)
        clear.clicked.connect(self.stock_count.clear)
        self.stack1.setLayout(layout)

    def on_click(
        self
    ):  # Add user input data to the database when ADD STOCK button is pressed
        stock_name_inp = self.stock_name.text().replace(' ', '_').lower()
        stock_count_inp = int(self.stock_count.text())
        stock_cost_inp = int(self.stock_cost.text())

        if (stock_count_inp and stock_cost_inp > 0):
            message = mp.insert_prod(stock_name_inp, stock_count_inp,
                                     stock_cost_inp)
            self.add_mes.setText(message)
        else:
            self.add_mes.setText('Invalid input')

    def stack2UI(self):  # MANAGE STOCK UI with 3 tab options

        layout = QHBoxLayout()
        layout.setGeometry(QRect(0, 300, 1150, 500))
        tabs = QTabWidget()
        self.tab1 = QWidget()
        self.tab2 = QWidget()
        self.tab3 = QWidget()

        tabs.addTab(self.tab1, 'Add Quantity')
        tabs.addTab(self.tab2, 'Reduce Quantity')
        tabs.addTab(self.tab3, 'Delete Stock')

        self.tab1UI()
        self.tab2UI()
        self.tab3UI()

        layout.addWidget(tabs)
        self.stack2.setLayout(layout)

    def tab1UI(self):  #ADD QUANTITY TAB
        layout = QFormLayout()
        self.mes1 = QLabel()

        self.ok_add = QPushButton('Add Stock', self)
        clear = QPushButton('Clear', self)

        self.stock_name_add = QLineEdit()
        layout.addRow("Stock Name", self.stock_name_add)

        self.stock_count_add = QLineEdit()
        layout.addRow("Quantity to add", self.stock_count_add)

        layout.addWidget(self.ok_add)
        layout.addWidget(clear)
        layout.addWidget(self.mes1)
        self.tab1.setLayout(layout)

        self.ok_add.clicked.connect(self.call_add)
        clear.clicked.connect(self.stock_name_add.clear)
        clear.clicked.connect(self.stock_count_add.clear)

    def tab2UI(self):  # REDUCE QUANTITY TAB
        layout = QFormLayout()
        self.mes2 = QLabel()

        self.ok_red = QPushButton('Reduce Stock', self)
        clear = QPushButton('Clear', self)

        self.stock_name_red = QLineEdit()
        layout.addRow("Stock Name", self.stock_name_red)

        self.stock_count_red = QLineEdit()
        layout.addRow("Quantity to reduce", self.stock_count_red)

        layout.addWidget(self.ok_red)
        layout.addWidget(clear)
        layout.addWidget(self.mes2)
        self.tab2.setLayout(layout)

        self.ok_red.clicked.connect(self.call_red)
        clear.clicked.connect(self.stock_name_red.clear)
        clear.clicked.connect(self.stock_count_red.clear)

    def tab3UI(self):  # DELETE STOCK TAB
        layout = QFormLayout()
        self.mes3 = QLabel()

        self.ok_del = QPushButton('Delete Stock', self)
        clear = QPushButton('Clear', self)

        self.stock_name_del = QLineEdit()
        layout.addRow("Stock Name", self.stock_name_del)
        layout.addWidget(self.ok_del)
        layout.addWidget(clear)
        layout.addWidget(self.mes3)
        self.tab3.setLayout(layout)

        self.ok_del.clicked.connect(self.call_del)
        clear.clicked.connect(self.stock_name_del.clear)

    def call_del(self):
        # deletes the stock item that is passed
        # needs a check test to see if item is in database
        # needs user notification if item was deleted successfully or item not found
        stock_name = self.stock_name_del.text().replace(' ', '_').lower()
        message = mp.remove_stock(stock_name)
        self.mes3.setText(message)

    def call_red(self):
        # reduces the stock item quantity it is passed
        # needs a check test to see if item is in database
        # needs user notification if item quantity was reduced successfully or item not found
        stock_name = self.stock_name_red.text().replace(' ', '_').lower()
        stock_val = int(self.stock_count_red.text())

        if (stock_val > 0):
            message = mp.dec_manu_quantity(stock_name, stock_val)
            self.mes2.setText(message)
        else:
            self.mes2.setText('Invalid quantity')

    def call_add(self):
        # adds the stock item quantity that it is passed
        # needs a check test to see if item is in database
        # needs user notification if item quantity was increased successfully or item not found
        stock_name = self.stock_name_add.text().replace(' ', '_').lower()
        stock_val = int(self.stock_count_add.text())

        if (stock_val > 0):
            message = mp.inc_manu_quantity(stock_name, stock_val)
            self.mes1.setText(message)
        else:
            self.mes1.setText('Invalid quantity')

    def stack3UI(self):  # VIEW STOCK TAB
        layout = QVBoxLayout()
        self.srb = QPushButton()
        self.srb.setText("Get Search Result.")
        self.View = QTableWidget()
        self.lbl3 = QLabel()
        self.lbl_conf_text = QLabel()
        self.lbl_conf_text.setText("Enter the search keyword:")
        self.conf_text = QLineEdit()

        self.View.setColumnCount(3)
        self.View.setColumnWidth(0, 250)
        self.View.setColumnWidth(1, 250)
        self.View.setColumnWidth(2, 200)
        self.View.insertRow(0)
        self.View.setItem(0, 0, QTableWidgetItem('Stock Name'))
        self.View.setItem(0, 1, QTableWidgetItem('Quantity'))
        self.View.setItem(0, 2, QTableWidgetItem('Cost(Per Unit)'))

        layout.addWidget(self.View)
        layout.addWidget(self.lbl_conf_text)
        layout.addWidget(self.conf_text)
        layout.addWidget(self.srb)
        layout.addWidget(self.lbl3)
        self.srb.clicked.connect(self.show_search)
        self.stack3.setLayout(layout)

    def show_search(self):
        # checks database for stock items
        if self.View.rowCount() > 1:
            for i in range(1, self.View.rowCount()):
                self.View.removeRow(1)

        x_act = mp.show_stock()
        x = []
        if self.conf_text.text() != '':
            for i in range(0, len(x_act)):
                a = list(x_act[i])
                if self.conf_text.text().lower() in a[0].lower():
                    x.append(a)
        else:
            x = mp.show_stock()

        if len(x) != 0:
            for i in range(1, len(x) + 1):
                self.View.insertRow(i)
                a = list(x[i - 1])
                self.View.setItem(
                    i, 0, QTableWidgetItem(a[0].replace('_', ' ').upper()))
                self.View.setItem(i, 1, QTableWidgetItem(str(a[1])))
                self.View.setItem(i, 2, QTableWidgetItem(str(a[2])))
                self.View.setRowHeight(i, 50)
            self.lbl3.setText('Viewing Stock Database.')
        else:
            self.lbl3.setText('No valid information in database.')

    def display(self, i):
        self.Stack.setCurrentIndex(i)
Пример #19
0
class BlackScholesUI(QDialog):
    def __init__(self, parent=None):
        super(BlackScholesUI, self).__init__(parent)

        self.originalPalette = QApplication.palette()

        self.outputs = ['price', 'delta', 'vega', 'theta', 'rho', 'omega',\
                        'gamma', 'vanna', 'charm', 'vomma', 'veta', 'speed', \
                            'zomma', 'color', 'ultima', 'dualDelta', 'dualGamma']

        self.optionsList = []

        self.addOptionSelector()
        self.addOptionInputs()
        self.greeksView()
        self.sweepInput()
        self.sweepOutput()
        self.optionsDisplay()
        self.plotWindow()

        leftLayout = QVBoxLayout()
        leftLayout.addWidget(self.optionsSelection)
        leftLayout.addWidget(self.optionsInput)
        leftLayout.addWidget(self.greeksBox)

        rightLayout = QGridLayout()
        rightLayout.addLayout(self.inputBox, 0, 0, 1, 4)
        rightLayout.addWidget(self.outputSelectList, 1, 0, 5, 4)
        MATLABButton = QPushButton("Export to MATLAB")
        rightLayout.addWidget(MATLABButton, 6, 0, 1, 2)
        plotButton = QPushButton("Plot Sweep Outputs")
        rightLayout.addWidget(plotButton, 6, 2, 1, 2)
        plotButton.clicked.connect(self.onPlotSweepButtonClicked)

        bottomLayout = QGridLayout()
        bottomLayout.addWidget(self.optionsBox, 0, 0, 2, 4)

        mainLayout = QGridLayout()
        mainLayout.addLayout(leftLayout, 0, 0, 3, 4)
        mainLayout.addLayout(rightLayout, 0, 9, 3, -1)
        mainLayout.addLayout(bottomLayout, 3, 0, -1, 4)
        mainLayout.addWidget(self.plotGroupBox, 0, 4, 3, 5)

        mainLayout.setColumnStretch(0, 1)
        mainLayout.setColumnStretch(1, 1)
        mainLayout.setColumnStretch(2, 1)
        mainLayout.setColumnStretch(3, 2)
        mainLayout.setColumnStretch(4, 2)
        mainLayout.setColumnStretch(5, 2)
        mainLayout.setColumnStretch(6, 1)
        mainLayout.setColumnStretch(7, 1)
        mainLayout.setColumnStretch(8, 1)
        self.setLayout(mainLayout)

        self.setFixedSize(1440, 900)

        self.setWindowTitle("Black-Scholes Calculations")
        QApplication.setStyle(QStyleFactory.create('Fusion'))

    def addOptionSelector(self):
        self.optionsSelection = QGroupBox()
        addOptionButton = QPushButton("Add Option")
        addOptionButton.clicked.connect(self.onOptionsAddClicked)
        self.optionsTypeBox = QComboBox()
        self.optionsTypeBox.addItems(
            ['Long Call', 'Long Put', 'Short Call', 'Short Put'])

        layout = QHBoxLayout()
        layout.addWidget(addOptionButton)
        layout.addWidget(self.optionsTypeBox)
        layout.addStretch(1)
        self.optionsSelection.setLayout(layout)

    def onOptionsAddClicked(self):
        marketPrice = None
        vol = None
        K = None
        expDay = None
        S0 = None
        q = 0
        r = None
        try:
            K = float(self.kEdit.text())
        except ValueError:
            msgBox = QMessageBox()
            msgBox.setIcon(QMessageBox.Information)
            msgBox.setWindowTitle("Error")
            msgBox.setText("Please Enter a Strike Price")
            msgBox.exec_()
        try:
            expDay = str(self.TEdit.text())
        except ValueError:
            msgBox = QMessageBox()
            msgBox.setIcon(QMessageBox.Information)
            msgBox.setWindowTitle("Error")
            msgBox.setText("Please Enter an Expiration")
            msgBox.exec_()
        try:
            S0 = float(self.S0Edit.text())
        except ValueError:
            msgBox = QMessageBox()
            msgBox.setIcon(QMessageBox.Information)
            msgBox.setWindowTitle("Error")
            msgBox.setText("Please Enter a Stock Price")
            msgBox.exec_()
        try:
            q = float(self.qEdit.text())
        except ValueError:
            msgBox = QMessageBox()
            msgBox.setIcon(QMessageBox.Information)
            msgBox.setWindowTitle("Error")
            msgBox.setText("Please Enter a Dividend Yield")
            msgBox.exec_()
        try:
            r = float(self.rEdit.text())
        except ValueError:
            msgBox = QMessageBox()
            msgBox.setIcon(QMessageBox.Information)
            msgBox.setWindowTitle("Error")
            msgBox.setText("Please Enter a Risk Free Rate")
            msgBox.exec_()
        try:
            vol = float(self.volEdit.text())
        except ValueError:
            try:
                marketPrice = float(self.mpEdit.text())
            except ValueError:
                msgBox = QMessageBox()
                msgBox.setIcon(QMessageBox.Information)
                msgBox.setWindowTitle("Error")
                msgBox.setText("Please Enter a Market Price or Volatility")
                msgBox.exec_()

        if 'Long' in self.optionsTypeBox.currentText():
            ls = 'Long'
        elif 'Short' in self.optionsTypeBox.currentText():
            ls = 'Short'
        if 'Call' in self.optionsTypeBox.currentText():
            otype = 'Call'
        elif 'Put' in self.optionsTypeBox.currentText():
            otype = 'Put'

        if K and expDay and S0 and (q is not None) and r and (vol
                                                              or marketPrice):
            if marketPrice is None:
                opt = option(otype=otype,
                             K=K,
                             expDay=expDay,
                             S0=S0,
                             vol=vol,
                             q=q,
                             r=r,
                             ls=ls)
            elif vol is None:
                opt = option(otype=otype,
                             K=K,
                             expDay=expDay,
                             S0=S0,
                             marketPrice=marketPrice,
                             q=q,
                             r=r,
                             ls=ls)
            self.optionsList.append(opt)
            self.updateOptionsDisplay()

    def updateOptionsDisplay(self):
        for i, opt in enumerate(self.optionsList):
            self.optionsTable.setItem(
                i + 1, 0, QTableWidgetItem(opt.ls + ' ' + opt.otype))
            self.optionsTable.setItem(i + 1, 1, QTableWidgetItem(str(opt.K)))
            self.optionsTable.setItem(i + 1, 2,
                                      QTableWidgetItem(opt.expDayStr))
            self.optionsTable.setItem(i + 1, 3, QTableWidgetItem(str(opt.S0)))

    def addOptionInputs(self):
        self.optionsInput = QGroupBox('Option Inputs')

        kLabel = QLabel("&Strike:")
        self.kEdit = QLineEdit()
        kLabel.setBuddy(self.kEdit)

        TLabel = QLabel("&Expiration Date (YYYY-MM-DD):")
        self.TEdit = QLineEdit()
        TLabel.setBuddy(self.TEdit)

        S0Label = QLabel("&Underlying Price:")
        self.S0Edit = QLineEdit()
        S0Label.setBuddy(self.S0Edit)

        volLabel = QLabel("&Volatility:")
        self.volEdit = QLineEdit()
        volLabel.setBuddy(self.volEdit)

        mpLabel = QLabel("&Option Market Price:")
        self.mpEdit = QLineEdit()
        mpLabel.setBuddy(self.mpEdit)

        qLabel = QLabel("&Dividend Yield:")
        self.qEdit = QLineEdit()
        qLabel.setBuddy(self.qEdit)

        rLabel = QLabel("&Risk Free Rate:")
        self.rEdit = QLineEdit()
        rLabel.setBuddy(self.rEdit)

        layout = QFormLayout()
        layout.addRow(kLabel, self.kEdit)
        layout.addRow(TLabel, self.TEdit)
        layout.addRow(S0Label, self.S0Edit)
        layout.addRow(volLabel, self.volEdit)
        layout.addRow(mpLabel, self.mpEdit)
        layout.addRow(qLabel, self.qEdit)
        layout.addRow(rLabel, self.rEdit)

        self.optionsInput.setLayout(layout)

    def greeksView(self):
        self.greeksBox = QGroupBox("Option Info")
        self.greeksTable = QTableWidget(11, 4)
        self.greeksTable.setItem(0, 0, QTableWidgetItem('Market Price'))
        self.greeksTable.setItem(1, 0, QTableWidgetItem('Volatility'))
        self.greeksTable.setItem(2, 0, QTableWidgetItem('Years To Expiration'))
        self.greeksTable.setItem(3, 0, QTableWidgetItem('Dividend Yield'))
        self.greeksTable.setItem(4, 0, QTableWidgetItem('Risk Free Rate'))
        self.greeksTable.setItem(5, 0, QTableWidgetItem('Delta'))
        self.greeksTable.setItem(6, 0, QTableWidgetItem('Vega'))
        self.greeksTable.setItem(7, 0, QTableWidgetItem('Theta'))
        self.greeksTable.setItem(8, 0, QTableWidgetItem('Rho'))
        self.greeksTable.setItem(9, 0, QTableWidgetItem('Omega'))
        self.greeksTable.setItem(10, 0, QTableWidgetItem('Gamma'))
        self.greeksTable.setItem(0, 2, QTableWidgetItem('Vanna'))
        self.greeksTable.setItem(1, 2, QTableWidgetItem('Charm'))
        self.greeksTable.setItem(2, 2, QTableWidgetItem('Vomma'))
        self.greeksTable.setItem(3, 2, QTableWidgetItem('Veta'))
        self.greeksTable.setItem(4, 2, QTableWidgetItem('Speed'))
        self.greeksTable.setItem(5, 2, QTableWidgetItem('Zomma'))
        self.greeksTable.setItem(6, 2, QTableWidgetItem('Color'))
        self.greeksTable.setItem(7, 2, QTableWidgetItem('Ultima'))
        self.greeksTable.setItem(8, 2, QTableWidgetItem('Dual Delta'))
        self.greeksTable.setItem(9, 2, QTableWidgetItem('Dual Gamma'))

        layout = QHBoxLayout()
        layout.setContentsMargins(5, 5, 5, 5)
        layout.addWidget(self.greeksTable)
        self.greeksBox.setLayout(layout)

    def plotWindow(self):
        self.plotGroupBox = QTabWidget()
        self.plotGroupBox.setSizePolicy(QSizePolicy.Preferred,
                                        QSizePolicy.Ignored)

        self.tab1 = FigureCanvas(Figure(figsize=(4, 8)))
        self.plot1ax = self.tab1.figure.add_subplot(111)

        self.tab2 = FigureCanvas(Figure(figsize=(4, 8)))
        self.plot2ax = self.tab2.figure.add_subplot(111)

        self.plotGroupBox.addTab(self.tab1, "&Time Evolution of Value")
        self.plotGroupBox.addTab(self.tab2, "&Sweep Results")
        #self.plotGroupBox.addTab(tab3, "&Profit Calculator")
        #self.plotGroupBox.addTab(tab4, "&Delta Hedging")

    def optionsDisplay(self):
        self.optionsBox = QGroupBox("Options")
        self.optionsTable = QTableWidget(10, 4)
        self.optionsTable.setItem(0, 0, QTableWidgetItem('Option Type'))
        self.optionsTable.setItem(0, 1, QTableWidgetItem('Strike'))
        self.optionsTable.setItem(0, 2, QTableWidgetItem('Expiration'))
        self.optionsTable.setItem(0, 3, QTableWidgetItem('Underlying Price'))
        self.optionsTable.setSelectionMode(2)
        self.optionsTable.cellClicked.connect(self.onOptionTableClicked)

        layout = QHBoxLayout()
        layout.setContentsMargins(1, 1, 1, 1)
        layout.addWidget(self.optionsTable)
        self.optionsBox.setLayout(layout)

    def onOptionTableClicked(self, row, column):
        self.selected = self.optionsTable.selectedItems()
        fulltime = []
        halftime = []
        expiry = []
        usedRows = []
        for item in self.selected:
            if item.row() != 0 and item.row() <= len(
                    self.optionsList) and item.row() not in usedRows:
                usedRows.append(item.row())
                opt = self.optionsList[item.row() - 1]
                self.greeksTable.setItem(
                    0, 1, QTableWidgetItem(str(opt.marketPrice)))
                self.greeksTable.setItem(1, 1, QTableWidgetItem(str(opt.vol)))
                self.greeksTable.setItem(2, 1, QTableWidgetItem(str(opt.T)))
                self.greeksTable.setItem(3, 1, QTableWidgetItem(str(opt.q)))
                self.greeksTable.setItem(4, 1, QTableWidgetItem(str(opt.r)))
                self.greeksTable.setItem(
                    5, 1,
                    QTableWidgetItem(
                        str(
                            opt.delta(S0=opt.S0,
                                      K=opt.K,
                                      vol=opt.vol,
                                      r=opt.r,
                                      T=opt.T,
                                      q=opt.q))))
                self.greeksTable.setItem(
                    6, 1,
                    QTableWidgetItem(
                        str(
                            opt.vega(S0=opt.S0,
                                     K=opt.K,
                                     vol=opt.vol,
                                     r=opt.r,
                                     T=opt.T,
                                     q=opt.q))))
                self.greeksTable.setItem(
                    7, 1,
                    QTableWidgetItem(
                        str(
                            opt.theta(S0=opt.S0,
                                      K=opt.K,
                                      vol=opt.vol,
                                      r=opt.r,
                                      T=opt.T,
                                      q=opt.q))))
                self.greeksTable.setItem(
                    8, 1,
                    QTableWidgetItem(
                        str(
                            opt.rho(S0=opt.S0,
                                    K=opt.K,
                                    vol=opt.vol,
                                    r=opt.r,
                                    T=opt.T,
                                    q=opt.q))))
                self.greeksTable.setItem(
                    9, 1,
                    QTableWidgetItem(
                        str(
                            opt.omega(S0=opt.S0,
                                      K=opt.K,
                                      vol=opt.vol,
                                      r=opt.r,
                                      T=opt.T,
                                      q=opt.q))))
                self.greeksTable.setItem(
                    10, 1,
                    QTableWidgetItem(
                        str(
                            opt.gamma(S0=opt.S0,
                                      K=opt.K,
                                      vol=opt.vol,
                                      r=opt.r,
                                      T=opt.T,
                                      q=opt.q))))
                self.greeksTable.setItem(
                    0, 3,
                    QTableWidgetItem(
                        str(
                            opt.vanna(S0=opt.S0,
                                      K=opt.K,
                                      vol=opt.vol,
                                      r=opt.r,
                                      T=opt.T,
                                      q=opt.q))))
                self.greeksTable.setItem(
                    1, 3,
                    QTableWidgetItem(
                        str(
                            opt.charm(S0=opt.S0,
                                      K=opt.K,
                                      vol=opt.vol,
                                      r=opt.r,
                                      T=opt.T,
                                      q=opt.q))))
                self.greeksTable.setItem(
                    2, 3,
                    QTableWidgetItem(
                        str(
                            opt.vomma(S0=opt.S0,
                                      K=opt.K,
                                      vol=opt.vol,
                                      r=opt.r,
                                      T=opt.T,
                                      q=opt.q))))
                self.greeksTable.setItem(
                    3, 3,
                    QTableWidgetItem(
                        str(
                            opt.veta(S0=opt.S0,
                                     K=opt.K,
                                     vol=opt.vol,
                                     r=opt.r,
                                     T=opt.T,
                                     q=opt.q))))
                self.greeksTable.setItem(
                    4, 3,
                    QTableWidgetItem(
                        str(
                            opt.speed(S0=opt.S0,
                                      K=opt.K,
                                      vol=opt.vol,
                                      r=opt.r,
                                      T=opt.T,
                                      q=opt.q))))
                self.greeksTable.setItem(
                    5, 3,
                    QTableWidgetItem(
                        str(
                            opt.zomma(S0=opt.S0,
                                      K=opt.K,
                                      vol=opt.vol,
                                      r=opt.r,
                                      T=opt.T,
                                      q=opt.q))))
                self.greeksTable.setItem(
                    6, 3,
                    QTableWidgetItem(
                        str(
                            opt.color(S0=opt.S0,
                                      K=opt.K,
                                      vol=opt.vol,
                                      r=opt.r,
                                      T=opt.T,
                                      q=opt.q))))
                self.greeksTable.setItem(
                    7, 3,
                    QTableWidgetItem(
                        str(
                            opt.ultima(S0=opt.S0,
                                       K=opt.K,
                                       vol=opt.vol,
                                       r=opt.r,
                                       T=opt.T,
                                       q=opt.q))))
                self.greeksTable.setItem(
                    8, 3,
                    QTableWidgetItem(
                        str(
                            opt.dualDelta(S0=opt.S0,
                                          K=opt.K,
                                          vol=opt.vol,
                                          r=opt.r,
                                          T=opt.T,
                                          q=opt.q))))
                self.greeksTable.setItem(
                    9, 3,
                    QTableWidgetItem(
                        str(
                            opt.dualGamma(S0=opt.S0,
                                          K=opt.K,
                                          vol=opt.vol,
                                          r=opt.r,
                                          T=opt.T,
                                          q=opt.q))))

                self.plot1ax.clear()
                toSweep = {'S0': (opt.S0 * 0.8, opt.S0 * 1.2, 50)}
                toGrab = ('price')
                fulltime.append(opt.sweep(toSweep, toGrab))
                self.plot1ax.plot(fulltime[0]['S0'],
                                  self.sumprice(fulltime),
                                  label='Now')
                saveT = opt.T
                opt.T /= 2
                halftime.append(opt.sweep(toSweep, toGrab))
                self.plot1ax.plot(halftime[0]['S0'],
                                  self.sumprice(halftime),
                                  label='Half Time')
                opt.T = 1e-6
                expiry.append(opt.sweep(toSweep, toGrab))
                opt.T = saveT
                self.plot1ax.plot(expiry[0]['S0'],
                                  self.sumprice(expiry),
                                  label='Expiration')
                self.plot1ax.set_xlabel('Stock Price')
                self.plot1ax.set_ylabel('Option Price')
                self.plot1ax.legend()
                self.tab1.draw()

    def sumprice(self, outs):
        for i in range(len(outs)):
            outs[i]['price'] = np.array(outs[i]['price'])
            if i == 0:
                if outs[0]['ls'] == 'Long':
                    price = outs[0]['price']
                elif outs[0]['ls'] == 'Short':
                    price = -outs[0]['price']
            else:
                if outs[i]['ls'] == 'Long':
                    price += outs[i]['price']
                elif outs[i]['ls'] == 'Short':
                    price -= outs[i]['price']
        return price

    def sweepInput(self):
        self.sweepBox = QGroupBox("Sweep Variables")

        toSweepLabel = QLabel("Inputs to Sweep")
        minLabel = QLabel("Min")
        maxLabel = QLabel("Max")
        stepsLabel = QLabel("Steps")
        inputs = [
            'None', 'Stock Price', 'Years to Expiration', 'Volatility',
            'Dividend Yield', 'Risk Free Rate'
        ]
        self.inputSelect1 = QComboBox()
        self.inputSelect1.addItems(inputs)
        self.inputSelect2 = QComboBox()
        self.inputSelect2.addItems(inputs)
        self.min1 = QLineEdit()
        self.min2 = QLineEdit()
        self.max1 = QLineEdit()
        self.max2 = QLineEdit()
        self.steps1 = QLineEdit()
        self.steps2 = QLineEdit()

        self.inputBox = QGridLayout()
        self.inputBox.addWidget(toSweepLabel, 0, 0, 1, 1)
        self.inputBox.addWidget(minLabel, 0, 1, 1, 2)
        self.inputBox.addWidget(maxLabel, 0, 2, 1, 3)
        self.inputBox.addWidget(stepsLabel, 0, 3, 1, 4)
        self.inputBox.addWidget(self.inputSelect1, 1, 0, 2, 1)
        self.inputBox.addWidget(self.inputSelect2, 2, 0, 3, 1)
        self.inputBox.addWidget(self.min1, 1, 1, 2, 2)
        self.inputBox.addWidget(self.min2, 2, 1, 3, 2)
        self.inputBox.addWidget(self.max1, 1, 2, 2, 3)
        self.inputBox.addWidget(self.max2, 2, 2, 3, 3)
        self.inputBox.addWidget(self.steps1, 1, 3, 2, 4)
        self.inputBox.addWidget(self.steps2, 2, 3, 3, 4)

    def sweepOutput(self):
        self.outputSelectList = QListWidget()

        for i, out in enumerate(self.outputs):
            self.outputSelectList.insertItem(i, out)

        self.outputSelectList.setSelectionMode(1)

    def onPlotSweepButtonClicked(self):
        toSweep = {}
        if len(self.outputSelectList.selectedItems()) < 1:
            msgBox = QMessageBox()
            msgBox.setIcon(QMessageBox.Information)
            msgBox.setWindowTitle("Error")
            msgBox.setText("Select At Least One Output")
            msgBox.exec_()
            return
        toGrab = self.outputSelectList.selectedItems()
        toGrab = [str(g.text()) for g in toGrab]
        if str(self.inputSelect1.currentText()) == 'Stock Price': is1 = 'S0'
        if str(self.inputSelect1.currentText()) == 'Years to Expiration':
            is1 = 'T'
        if str(self.inputSelect1.currentText()) == 'Volatility': is1 = 'vol'
        if str(self.inputSelect1.currentText()) == 'Dividend Yield': is1 = 'q'
        if str(self.inputSelect1.currentText()) == 'Risk Free Rate': is1 = 'r'
        if str(self.inputSelect2.currentText()) == 'Stock Price': is2 = 'S0'
        if str(self.inputSelect2.currentText()) == 'Years to Expiration':
            is2 = 'T'
        if str(self.inputSelect2.currentText()) == 'Volatility': is2 = 'vol'
        if str(self.inputSelect2.currentText()) == 'Dividend Yield': is2 = 'q'
        if str(self.inputSelect2.currentText()) == 'Risk Free Rate': is2 = 'r'
        if str(self.inputSelect1.currentText()) != 'None' and bool(
                self.min1.text()) and bool(self.max1.text()) and bool(
                    self.steps1.text()):
            min1 = float(self.min1.text())
            max1 = float(self.max1.text())
            steps1 = int(self.steps1.text())
            toSweep[is1] = (min1, max1, steps1)
        if str(self.inputSelect2.currentText()) != 'None' and bool(
                self.min2.text()) and bool(self.max2.text()) and bool(
                    self.steps2.text()):
            min2 = float(self.min2.text())
            max2 = float(self.max2.text())
            steps2 = int(self.steps2.text())
            toSweep[is2] = (min2, max2, steps2)
        if len(toSweep) == 0:
            msgBox = QMessageBox()
            msgBox.setIcon(QMessageBox.Information)
            msgBox.setWindowTitle("Error")
            msgBox.setText("Select At Least One Input")
            msgBox.exec_()
            return
        if len(self.selected) > 1 and toGrab[0] != 'price' or len(
                self.selected) > 1 and len(toGrab) > 1:
            msgBox = QMessageBox()
            msgBox.setIcon(QMessageBox.Information)
            msgBox.setWindowTitle("Error")
            msgBox.setText(
                "Output Must be Only Price if More than One Option Selected")
            msgBox.exec_()
            return

        if len(toSweep) == 1:
            out = []
            usedRows = []
            self.tab2.figure.clf()
            self.plot2ax = self.tab2.figure.add_subplot(111)
            if len(self.selected) > 1:
                for item in self.selected:
                    if item.row() != 0 and item.row() <= len(
                            self.optionsList) and item.row() not in usedRows:
                        opt = self.optionsList[item.row() - 1]
                        usedRows.append(item.row())
                        out.append(opt.sweep(toSweep, toGrab))
                        self.plot2ax.clear()
                        self.plot2ax.plot(out[0][is1], self.sumprice(out))
                        self.plot2ax.set_xlabel(
                            str(self.inputSelect1.currentText()))
                        self.plot2ax.set_ylabel(str(toGrab[0]))
                        self.tab2.draw()
            else:
                for item in self.selected:
                    if item.row() != 0 and item.row() <= len(self.optionsList):
                        opt = self.optionsList[item.row() - 1]
                        out = opt.sweep(toSweep, toGrab)
                        self.plot2ax.clear()
                        self.plot2ax.plot(out[is1], out[toGrab[0]])
                        self.plot2ax.set_xlabel(
                            str(self.inputSelect1.currentText()))
                        self.plot2ax.set_ylabel(str(toGrab[0]))
                        self.tab2.draw()
        elif len(toSweep) == 2:
            parula_map = LinearSegmentedColormap.from_list('parula', parula())
            out = []
            usedRows = []
            self.tab2.figure.clf()
            self.plot2ax = self.tab2.figure.add_subplot(111, projection='3d')
            if len(self.selected) > 1:
                for item in self.selected:
                    if item.row() != 0 and item.row() <= len(
                            self.optionsList) and item.row() not in usedRows:
                        opt = self.optionsList[item.row() - 1]
                        usedRows.append(item.row())
                        out.append(opt.sweep(toSweep, toGrab))
                        self.plot2ax.clear()
                        self.plot2ax.plot_surface(out[0][is1],
                                                  out[0][is2],
                                                  self.sumprice(out),
                                                  cmap=parula_map)
                        self.plot2ax.set_xlabel(
                            str(self.inputSelect1.currentText()))
                        self.plot2ax.set_ylabel(
                            str(self.inputSelect2.currentText()))
                        self.plot2ax.set_zlabel(str(toGrab[0]))
                self.tab2.draw()
            else:
                for item in self.selected:
                    if item.row() != 0 and item.row() <= len(self.optionsList):
                        opt = self.optionsList[item.row() - 1]
                        out = opt.sweep(toSweep, toGrab)
                        self.plot2ax.clear()
                        self.plot2ax.plot_surface(out[is1],
                                                  out[is2],
                                                  out[toGrab[0]],
                                                  cmap=parula_map)
                        self.plot2ax.set_xlabel(
                            str(self.inputSelect1.currentText()))
                        self.plot2ax.set_ylabel(
                            str(self.inputSelect2.currentText()))
                        self.plot2ax.set_zlabel(str(toGrab[0]))
                        self.tab2.draw()
Пример #20
0
class StringListDlg(QDialog):
    acceptedList = pyqtSignal('QStringList')

    def __init__(self, name, stringlist=None, parent=None):
        super(StringListDlg, self).__init__(parent)

        self.name = name

        self.listWidget = QListWidget()
        if stringlist is not None:
            self.listWidget.addItems(stringlist)
            self.listWidget.setCurrentRow(0)

        buttonLayout = QVBoxLayout()
        for text, slot in (("&Add...", self.add), ("&Edit...", self.edit),
                           ("&Remove...", self.remove), ("&Up", self.up),
                           ("&Down", self.down), ("&Sort",
                                                  self.listWidget.sortItems),
                           ("Close", self.accept)):
            button = QPushButton(text)
            if not MAC:
                button.setFocusPolicy(Qt.NoFocus)
            if text == "Close":
                buttonLayout.addStretch()
            buttonLayout.addWidget(button)
            button.clicked.connect(slot)
        layout = QHBoxLayout()
        layout.addWidget(self.listWidget)
        layout.addLayout(buttonLayout)
        self.setLayout(layout)
        self.setWindowTitle("Edit {} List".format(self.name))

    def add(self):
        row = self.listWidget.currentRow()
        title = "Add {}".format(self.name)

        string, ok = QInputDialog.getText(self, title, title)
        if ok and string:
            self.listWidget.insertItem(row, string)

    def edit(self):
        row = self.listWidget.currentRow()
        item = self.listWidget.item(row)
        if item is not None:
            title = "Edit {}".format(self.name)
            string, ok = QInputDialog.getText(self, title, title,
                                              QLineEdit.Normal, item.text())
            if ok and string:
                item.setText(string)

    def remove(self):
        row = self.listWidget.currentRow()
        item = self.listWidget.item(row)
        if item is None:
            return
        reply = QMessageBox.question(
            self, "Remove {}".format(self.name),
            "Remove {} `{}'?".format(self.name, item.text()),
            QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            item = self.listWidget.takeItem(row)
            del item

    def up(self):
        row = self.listWidget.currentRow()
        if row >= 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(row - 1, item)
            self.listWidget.setCurrentItem(item)

    def down(self):
        row = self.listWidget.currentRow()
        if row < self.listWidget.count() - 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(row + 1, item)
            self.listWidget.setCurrentItem(item)

    def reject(self):
        self.accept()

    def accept(self):
        self.stringlist = []
        for row in range(self.listWidget.count()):
            self.stringlist.append(self.listWidget.item(row).text())
        self.acceptedList['QStringList'].emit(self.stringlist)
        # self.emit(SIGNAL("acceptedList(QStringList)"), self.stringlist)
        QDialog.accept(self)
Пример #21
0
class Window(QWidget):
    def __init__(self):
        super().__init__()

        self.load_image('res\\niceimage.jpg')
        self.root_layout = QHBoxLayout()

        self.control_view = self.build_control_view()
        self.view_layout = self.build_view_layout()

        self.root_layout.addLayout(self.view_layout, stretch=65)
        self.root_layout.addLayout(self.control_view, stretch=35)

        self.cmap = None

        self.setWindowTitle('ImgProc')
        self.setLayout(self.root_layout)
        self.show()

    @staticmethod
    def build_labeled_slider(text, min, max, init_value, c_slider=None):
        h_layout = QHBoxLayout()

        if c_slider is not None:
            slider = c_slider
        else:
            slider = QSlider(orientation=Qt.Horizontal)

        slider.setRange(min, max)
        slider.setValue(init_value)
        label = QLabel(text)
        value_label = QLabel(str(init_value))

        h_layout.addWidget(label, stretch=10)
        h_layout.addWidget(slider, stretch=80)
        h_layout.addWidget(value_label, stretch=10)

        return h_layout, value_label, slider

    def build_control_view(self):

        control_view = QVBoxLayout()

        h_layout = QHBoxLayout()
        v_layout = QVBoxLayout()
        v_layout.setAlignment(Qt.AlignTop)

        s1, self.hue_slider_label, self.hue_slider = \
                Window.build_labeled_slider('H: ', 0, 360, 0)

        s2, self.saturation_slider_label, self.saturation_slider = \
                Window.build_labeled_slider('S: ', 0, 100, 50)

        s3, self.value_slider_label, self.value_slider = \
                Window.build_labeled_slider('V: ', 0, 100, 50)

        s4, self.sigma_slider_label, self.sigma_slider = Window.build_labeled_slider(
            'SIGMA: ', 0, 20, 0)

        self.hue_slider.valueChanged[int].connect(self.on_image_hsv_change)
        self.saturation_slider.valueChanged[int].connect(
            self.on_image_hsv_change)
        self.value_slider.valueChanged[int].connect(self.on_image_hsv_change)
        self.sigma_slider.valueChanged[int].connect(self.on_gaus_sigma_change)

        colors_info_layout = QVBoxLayout()
        self.rgb_label = QLabel(ColorsFormats.RGB.format(0, 0, 0))
        self.hsv_label = QLabel(ColorsFormats.HSV.format(0, 0, 0))
        self.lab_label = QLabel(ColorsFormats.LAB.format(0, 0, 0))
        self.cells_count_label = QLabel('Cells found: 0')

        self.l_hist_button = QPushButton('Show hist')
        self.l_hist_button.clicked.connect(self.show_hist)

        colors_info_layout.addWidget(self.rgb_label)
        colors_info_layout.addWidget(self.hsv_label)
        colors_info_layout.addWidget(self.lab_label)
        colors_info_layout.addWidget(self.cells_count_label)

        v_layout.addLayout(s1)
        v_layout.addLayout(s2)
        v_layout.addLayout(s3)
        v_layout.addLayout(s4)
        v_layout.addLayout(colors_info_layout)
        v_layout.addWidget(self.l_hist_button)

        self.operations_list_widget = QListWidget()
        self.operations_list_widget.itemClicked.connect(
            self.pipeline_item_clicked)
        self.operations_list_widget.setDragEnabled(True)

        l1 = QListWidgetItem('Sobel')
        l1.setCheckState(Qt.Checked)

        l2 = QListWidgetItem('Otsu')
        l2.setCheckState(Qt.Checked)

        l3 = QListWidgetItem('Gabor')
        l3.setData(Qt.UserRole, {'theta': 0})
        l3.setCheckState(Qt.Checked)

        l4 = QListWidgetItem('Canny')
        # l4.setData(Qt.UserRole, {'min_treshold': 80}, {'max_treshold': 120})
        l4.setCheckState(Qt.Checked)

        l5 = QListWidgetItem('CompCount')
        l5.setData(Qt.UserRole, {'ksize': 0})
        l5.setCheckState(Qt.Checked)

        l6 = QListWidgetItem('Harris')
        # l4.setData(Qt.UserRole, {'min_treshold': 80}, {'max_treshold': 120})
        l6.setCheckState(Qt.Checked)

        l7 = QListWidgetItem('Fertness')
        # l4.setData(Qt.UserRole, {'min_treshold': 80}, {'max_treshold': 120})
        l7.setCheckState(Qt.Checked)

        self.operations_list_widget.insertItem(1, l1)
        self.operations_list_widget.insertItem(2, l2)
        self.operations_list_widget.insertItem(3, l3)
        self.operations_list_widget.insertItem(4, l4)
        self.operations_list_widget.insertItem(5, l5)
        self.operations_list_widget.insertItem(6, l6)
        self.operations_list_widget.insertItem(7, l7)

        h_layout.addLayout(v_layout, stretch=50)
        h_layout.addWidget(self.operations_list_widget, stretch=50)

        h_pipeline = QHBoxLayout()
        buttons_layout = QVBoxLayout()
        buttons_layout.setAlignment(Qt.AlignTop)

        self.run_button = QPushButton('run')
        self.run_button.clicked.connect(self.run_pipeline)
        self.open_image_button = QPushButton('open')
        self.open_image_button.clicked.connect(self.open_image)
        self.clear_pipeline_button = QPushButton('clear')
        self.reset_image_button = QPushButton('reset')
        self.reset_image_button.clicked.connect(self.reset_image)

        self.clear_pipeline_button.clicked.connect(self.clear_pipeline)

        buttons_layout.addWidget(self.run_button, stretch=5)
        buttons_layout.addWidget(self.clear_pipeline_button, stretch=5)
        buttons_layout.addWidget(self.reset_image_button, stretch=5)
        buttons_layout.addWidget(self.open_image_button, stretch=5)

        self.pipeline_operations_widget = QListWidget()
        self.pipeline_operations_widget.setAcceptDrops(True)
        self.pipeline_operations_widget.setDragEnabled(True)

        h_pipeline.addWidget(self.pipeline_operations_widget)
        h_pipeline.addLayout(buttons_layout)

        control_view.addLayout(h_layout, stretch=30)
        control_view.addLayout(h_pipeline, stretch=70)

        return control_view

    def reset_image(self):
        self.hsv_adjust_image = self.image
        self.show_image(self.image)

    def clear_pipeline(self):
        self.pipeline_operations_widget.clear()

    def run_pipeline(self):
        self.cmap = None

        for index in range(self.pipeline_operations_widget.count()):
            item = self.pipeline_operations_widget.item(index)
            if item.checkState() == Qt.Checked:
                if item.text() == 'Sobel':
                    self.show_image(T.sobel_filter(self.shown_image).numpy())
                elif item.text() == 'Otsu':
                    self.show_image(
                        T.otsu_binarization(self.shown_image).numpy())
                elif item.text() == 'Gabor':
                    self.show_image(
                        T.gabor_filter(self.shown_image,
                                       item.data(
                                           Qt.UserRole)['theta']).numpy())
                elif item.text() == 'Canny':
                    self.show_image(
                        T.canny_edge_detection(self.shown_image).numpy())
                elif item.text() == 'CompCount':
                    self.cmap = 'YlGnBu'
                    count, img = T.components_count(self.shown_image,
                                                    dilate_ksize=3,
                                                    erode_ksize=7)
                    self.cells_count_label.setText(f'Cells found: {count}')
                    self.show_image(img.numpy())
                elif item.text() == 'Fertness':
                    self.show_image(
                        T.local_features_detection(self.shown_image,
                                                   fertness=True))
                elif item.text() == 'Harris':
                    self.show_image(
                        T.local_features_detection(self.shown_image,
                                                   fertness=False))

    def pipeline_item_clicked(self, item):

        if item.text() == 'Gabor':
            gaborDialog = GaborDialog(item.data(Qt.UserRole)['theta'])
            gaborDialog.exec_()
            item.setData(Qt.UserRole, {'theta': gaborDialog.theta})

    def build_view_layout(self):
        self.image_figure = Figure()
        self.image_canvas = FigureCanvas(self.image_figure)
        self.image_canvas.mpl_connect('motion_notify_event',
                                      self.mouse_moved_on_image)
        self.hist_figure = Figure()
        self.hist_canvas = FigureCanvas(self.hist_figure)

        view_layout = QVBoxLayout()

        info_layout = QHBoxLayout()

        info_layout.addWidget(self.hist_canvas, stretch=30)
        info_layout.addWidget(QWidget(), stretch=40)

        view_layout.addWidget(self.image_canvas, stretch=80)
        view_layout.addLayout(info_layout, stretch=20)
        self.show_image(self.image)

        return view_layout

    def open_image(self):
        path, f = QFileDialog.getOpenFileName(self,
                                              'Select image',
                                              filter="Images (*.png *.jpg);")
        print(f, path)
        self.load_image(path)
        self.show_image(self.image)

    # TODO check for image channels (must be 3)
    def load_image(self, path):
        self.image = np.array(Image.open(path))
        self.hsv_adjust_image = self.image[:, :, :3]
        self.image = self.image[:, :, :3]

    def show_hist(self):

        l_comp = T.cielab_L_component(self.shown_image).numpy()

        self.hist_figure.clear()
        axs = self.hist_figure.add_subplot(111)
        axs.hist(l_comp.flatten(), bins=100)
        self.hist_canvas.draw()

    def mouse_moved_on_image(self, mouse_event):
        if not mouse_event.inaxes:
            return

        x, y = mouse_event.xdata, mouse_event.ydata

        r, g, b = map(int, self.shown_image[int(y), int(x)])
        h, s, v = T.rgb_to_hsv((r, g, b))
        L, la, lb = T.rgb_to_cielab((r, g, b))

        self.rgb_label.setText(ColorsFormats.RGB.format(r, g, b))
        self.hsv_label.setText(ColorsFormats.HSV.format(h, s, v))
        self.lab_label.setText(ColorsFormats.LAB.format(L, la, lb))

    def on_gaus_sigma_change(self, value):
        val = self.sigma_slider.value()

        val = (val / self.sigma_slider.maximum()) * 10

        self.sigma_slider_label.setText(str(val))

        if val == 0.0:
            self.show_image(self.hsv_adjust_image)
            return

        self.show_image(
            T.gaussian_filter(self.hsv_adjust_image, val, 5).numpy())

    def on_image_hsv_change(self, value):
        h = self.hue_slider.value()
        s = self.saturation_slider.value()
        v = self.value_slider.value()

        self.hue_slider_label.setText(str(h))
        self.saturation_slider_label.setText(str(s))
        self.value_slider_label.setText(str(v))

        s = s / 100.0 + 0.5
        v = v / 100.0 + 0.5
        self.hsv_adjust_image = T.transform_hsv(self.image, h, s, v).numpy()
        self.show_image(self.hsv_adjust_image)

    def show_image(self, image):
        self.image_figure.clear()
        axs = self.image_figure.add_subplot(111)
        axs.imshow(image, interpolation='none')
        self.shown_image = image
        self.image_canvas.draw()
Пример #22
0
class IngredientsDialogue(QDialog, QWidget):
    """Class representing second window of program which displays ingredients and allows users to
    input ingredients and specify a maximum time for recipes displayed.
    """

    def __init__(self) -> None:
        """Initialize an instance of the ingredients window
        """
        super().__init__()

        # Set up the screen background
        self.recipes_dialogue = None
        self.setStyleSheet("background-color: rgb(240, 225, 204)")
        self.setWindowIcon(QIcon('visuals/L_C_Icon.PNG'))

        # Initialized all widgets needed
        self.lbl_list = QLabel("Your List", self)
        self.lbl_list.setFont(QFont('Georgia', 12, QFont.Bold))
        self.lbl_list.setStyleSheet('color: rgb(211, 104, 80)')
        self.lbl_list.setFixedSize(200, 25)
        self.lbl_list.move(80, 100)

        self.lbl_max_ingredients = QLabel("(10 ingredients max.)", self)
        self.lbl_max_ingredients.setFont(QFont('Georgia', 9))
        self.lbl_max_ingredients.setStyleSheet('color: rgb(35, 87, 77)')
        self.lbl_max_ingredients.move(57, 125)
        self.lbl_max_ingredients.resize(200, 20)

        self.lbl_max_time = QLabel("Maximum cooking time in minutes (optional):", self)
        self.lbl_max_time.setFont(QFont('Georgia', 12, QFont.Bold))
        self.lbl_max_time.setStyleSheet('color: rgb(211, 104, 80)')
        self.lbl_max_time.setFixedSize(250, 80)
        self.lbl_max_time.setWordWrap(True)

        self.lbl_all_ingredients = QLabel("All Ingredients", self)
        self.lbl_all_ingredients.setFont(QFont('Georgia', 12, QFont.Bold))
        self.lbl_all_ingredients.setStyleSheet('color: rgb(211, 104, 80)')
        self.lbl_all_ingredients.setFixedSize(200, 25)
        self.lbl_all_ingredients.move(375, 100)

        self.lbl_select_items = QLabel("Select your ingredients!", self)
        self.lbl_select_items.setFont(QFont('Georgia', 17, QFont.Bold))
        self.lbl_select_items.setStyleSheet('color: rgb(210, 146, 68)')
        self.lbl_select_items.setFixedSize(400, 40)
        self.lbl_select_items.move(180, 40)

        self.time_selected = QSpinBox(self)
        self.time_selected.setStyleSheet('color: rgb(35, 87, 77)')

        self.time_selected.setFont(QFont('Georgia', 10))
        self.time_selected.setRange(0, 50000)

        self.all_ingredients = QListWidget()
        self.all_ingredients.setFont(QFont('Georgia', 10))
        self.all_ingredients.setStyleSheet('color: rgb(35, 87, 77)')

        self.line_edit = None
        self.user_input = None

        self.disabled_color2 = QGraphicsColorizeEffect()
        self.disabled_color2.setColor(QColor.fromRgb(240, 225, 204))

        self.disabled_color3 = QGraphicsColorizeEffect()
        self.disabled_color3.setColor(QColor.fromRgb(240, 225, 204))

        self.disabled_color4 = QGraphicsColorizeEffect()
        self.disabled_color4.setColor(QColor.fromRgb(240, 225, 204))

        self.disabled_color5 = QGraphicsColorizeEffect()
        self.disabled_color5.setColor(QColor.fromRgb(240, 225, 204))

        self.disabled_color6 = QGraphicsColorizeEffect()
        self.disabled_color6.setColor(QColor.fromRgb(240, 225, 204))

        self.disabled_color7 = QGraphicsColorizeEffect()
        self.disabled_color7.setColor(QColor.fromRgb(240, 225, 204))

        self.disabled_color8 = QGraphicsColorizeEffect()
        self.disabled_color8.setColor(QColor.fromRgb(240, 225, 204))

        self.disabled_color9 = QGraphicsColorizeEffect()
        self.disabled_color9.setColor(QColor.fromRgb(240, 225, 204))

        self.disabled_color10 = QGraphicsColorizeEffect()
        self.disabled_color10.setColor(QColor.fromRgb(240, 225, 204))

        # Sets up all the line edits
        self.ingredient1 = QLineEdit(self)
        self.ingredient1.setStyleSheet(
            'background-color: rgb(224, 182, 157); color: rgb(35, 87, 77)')
        self.ingredient1.setFont(QFont('Georgia', 10))
        self.ingredient2 = QLineEdit(self)
        self.ingredient2.setStyleSheet(
            'background-color: rgb(224, 182, 157); color: rgb(35, 87, 77)')
        self.ingredient2.setFont(QFont('Georgia', 10))
        self.ingredient2.setGraphicsEffect(self.disabled_color2)
        self.ingredient3 = QLineEdit(self)
        self.ingredient3.setStyleSheet(
            'background-color: rgb(224, 182, 157); color: rgb(35, 87, 77)')
        self.ingredient3.setFont(QFont('Georgia', 10))
        self.ingredient3.setGraphicsEffect(self.disabled_color3)
        self.ingredient4 = QLineEdit(self)
        self.ingredient4.setStyleSheet(
            'background-color: rgb(224, 182, 157); color: rgb(35, 87, 77)')
        self.ingredient4.setFont(QFont('Georgia', 10))
        self.ingredient4.setGraphicsEffect(self.disabled_color4)
        self.ingredient5 = QLineEdit(self)
        self.ingredient5.setStyleSheet(
            'background-color: rgb(224, 182, 157); color: rgb(35, 87, 77)')
        self.ingredient5.setFont(QFont('Georgia', 10))
        self.ingredient5.setGraphicsEffect(self.disabled_color5)
        self.ingredient6 = QLineEdit(self)
        self.ingredient6.setStyleSheet(
            'background-color: rgb(224, 182, 157); color: rgb(35, 87, 77)')
        self.ingredient6.setFont(QFont('Georgia', 10))
        self.ingredient6.setGraphicsEffect(self.disabled_color6)
        self.ingredient7 = QLineEdit(self)
        self.ingredient7.setStyleSheet(
            'background-color: rgb(224, 182, 157); color: rgb(35, 87, 77)')
        self.ingredient7.setFont(QFont('Georgia', 10))
        self.ingredient7.setGraphicsEffect(self.disabled_color7)
        self.ingredient8 = QLineEdit(self)
        self.ingredient8.setStyleSheet(
            'background-color: rgb(224, 182, 157); color: rgb(35, 87, 77)')
        self.ingredient8.setFont(QFont('Georgia', 10))
        self.ingredient8.setGraphicsEffect(self.disabled_color8)
        self.ingredient9 = QLineEdit(self)
        self.ingredient9.setStyleSheet(
            'background-color: rgb(224, 182, 157); color: rgb(35, 87, 77)')
        self.ingredient9.setFont(QFont('Georgia', 10))
        self.ingredient9.setGraphicsEffect(self.disabled_color9)
        self.ingredient10 = QLineEdit(self)
        self.ingredient10.setStyleSheet(
            'background-color: rgb(224, 182, 157); color: rgb(35, 87, 77)')
        self.ingredient10.setFont(QFont('Georgia', 10))
        self.ingredient10.setGraphicsEffect(self.disabled_color10)

        # Gets all the ingredients from the data
        self.ingredient = [self.ingredient1, self.ingredient2, self.ingredient3, self.ingredient4,
                           self.ingredient5, self.ingredient6, self.ingredient7,
                           self.ingredient8, self.ingredient9, self.ingredient10]

        self.disabled_color = [self.disabled_color2, self.disabled_color3, self.disabled_color4,
                               self.disabled_color5, self.disabled_color6, self.disabled_color7,
                               self.disabled_color8, self.disabled_color9, self.disabled_color10]
        data = data_reading.read_recipes(data_reading.RECIPES_FILE)
        data_reading.clean_ingredients(data)
        self.clean = sorted(list(data_reading.get_ingredients(data)))
        for i in range(len(self.clean)):
            self.all_ingredients.insertItem(i, self.clean[i])

        # Sets up the screen with all the needed elements
        self.title = "Look and Cook"
        self.left = 500
        self.top = 200
        self.width = 700
        self.height = 700
        self.init_window()
        self.center()
        self.setFixedSize(700, 700)

    def init_window(self) -> None:
        """Open the second window on the user's screen with the provided dimensions.
        """
        # Sets up screen
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.setWindowTitle(self.title)

        # Moves the labels to the right position
        self.lbl_max_time.move(250, self.height - 230)
        self.time_selected.move(550, self.height - 200)

        # Creates an autocomplete system to use when typing the ingredients
        completer = QCompleter(sorted(self.clean))
        completer.setFilterMode(Qt.MatchContains)
        completer.setCaseSensitivity(Qt.CaseInsensitive)

        # Places all the line edits on the window
        self.ingredient1.setCompleter(completer)
        self.ingredient1.move(50, 160)
        self.ingredient1.setFixedSize(160, 30)

        height = 200
        for x in self.ingredient[1:]:
            x.setCompleter(completer)
            x.move(50, height)
            x.setFixedSize(160, 30)
            x.setDisabled(True)
            height += 40

        # Places list in the middle on the window
        vbox = QVBoxLayout()
        vbox.setContentsMargins(250, 0, 120, 120)
        self.all_ingredients.setFixedSize(400, 300)
        vbox.addWidget(self.all_ingredients)
        self.all_ingredients.itemDoubleClicked.connect(self.add_ingredient)
        self.setLayout(vbox)

        # Creates an add_item item button
        add_item = QPushButton("Add", self)
        add_item.setGeometry((self.width // 2) - 50, self.height // 2 + 200, 70, 70)
        add_item.move(50, self.height - 120)
        add_item.setFont(QFont('Georgia', 8, QFont.Bold))
        add_item.setStyleSheet('border-radius: 35; background-color: rgb(211, 104, 80); '
                               'color: rgb(240, 225, 204)')
        add_item.clicked.connect(self.add_item)

        # Creates an remove_item item button
        remove_item = QPushButton("Remove", self)
        remove_item.setGeometry((self.width // 2) - 50, self.height // 2 + 200, 70, 70)
        remove_item.move(140, self.height - 120)
        remove_item.setFont(QFont('Georgia', 8, QFont.Bold))
        remove_item.setStyleSheet('border-radius: 35; background-color: rgb(211, 104, 80); '
                                  'color: rgb(240, 225, 204)')
        remove_item.clicked.connect(self.remove_item)

        # Creates an clear list item button
        clear_list = QPushButton("Clear List", self)
        clear_list.setGeometry((self.width // 2) - 50, self.height // 2 + 200, 190, 70)
        clear_list.move(250, self.height - 120)
        clear_list.setFont(QFont('Georgia', 12, weight=QtGui.QFont.Bold))
        clear_list.setStyleSheet('border-radius: 35; background-color: rgb(211, 104, 80); '
                                 'color: rgb(240, 225, 204)')
        clear_list.clicked.connect(self.clear_list)

        # Creates a submit button
        submit = QPushButton("Find Recipes", self)
        submit.setGeometry((self.width // 2) - 50, self.height // 2 + 200, 190, 70)
        submit.move(460, self.height - 120)
        submit.setFont(QFont('Georgia', 12, weight=QtGui.QFont.Bold))
        submit.setStyleSheet('border-radius: 35; background-color: rgb(210, 146, 68); '
                             'color: rgb(240, 225, 204)')
        submit.clicked.connect(self.submit)

        # Displays everything on the window
        self.show()

    def center(self) -> None:
        """Function to center second window on the provided desktop screen.
        """
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

        # frameGm = self.frameGeometry()
        # screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos())
        # centerPoint = QApplication.desktop().screenGeometry(screen).center()
        # frameGm.moveCenter(centerPoint)
        # self.move(frameGm.topLeft())

        resolution = QDesktopWidget().screenGeometry()
        self.move((resolution.width() / 2) - (self.frameSize().width() / 2),
                  (resolution.height() / 2) - (self.frameSize().height() / 2))

    def add_item(self) -> None:
        """Enables search box for user to input a new ingredient."""
        for x in range(len(self.ingredient) - 1, 0, -1):
            if self.ingredient[x - 1].isEnabled():
                self.ingredient[x - 1].setCursorPosition(0)
                self.ingredient[x].setDisabled(False)
                self.disabled_color[x - 1].setEnabled(False)

    def remove_item(self) -> None:
        """Removes the last ingredient of the list."""
        for x in range(len(self.ingredient))[::-1][:-1]:
            if self.ingredient[x].isEnabled():
                self.ingredient[x].setDisabled(True)
                self.ingredient[x].clear()
                self.disabled_color[x - 1].setEnabled(True)
                return

    def clear_list(self) -> None:
        """Clears all ingredients in user's list."""
        for x in self.ingredient:
            x.clear()
            if x != self.ingredient1:
                x.setDisabled(True)
        self.time_selected.setValue(0)

    def add_ingredient(self, item: QListWidgetItem) -> None:
        """Add the double clicked ingredient to the ingredients list."""
        for x in self.ingredient:
            if x.isEnabled() and x.text() == '':
                x.setText(item.text())
                return

    def submit(self) -> None:
        """Create button to submit user input and proceed to the third page, which displays the
       recipes.

       If there is an ingredient listed twice in the input, raise an error pop up that says
       "Ingredient [duplicated ingredient] appears more than once" or "Ingredients [duplicated
       ingredients] appear more than once" if there are multiple duplicated ingredients.

       If there are remaining unfilled ingredient boxes, raise an error pop up that says
       "Did not fill all the needed information".

       If the user has inputted an invalid ingredient that does not appear in the list of
       ingredients at the center, raise an error pop up that says "The ingredient [invalid
       ingredient] is invalid" or "The ingredients [invalid ingredients] are invalid" if there
       are more than 1 invalid ingredients.
       """
        ingredients_set = set()
        duplicates = ''
        count = 0
        for x in self.ingredient:
            if x.isEnabled() and x.text() in ingredients_set:
                duplicates += x.text()
                count += 1
            else:
                ingredients_set.add(x.text())

        if len(duplicates) != 0:  # This occurs when the user inputs the same ingredient twice
            contains_duplicates = QMessageBox()
            contains_duplicates.setWindowTitle("Error! - Duplicates")
            contains_duplicates.setWindowIcon(QIcon('visuals/L&C Icon.PNG'))
            if count == 1:  # Only one ingredient appears more than once
                contains_duplicates.setText(
                    f'Sorry, the ingredient {duplicates} appears more than once.')
            else:  # Muliple ingredients
                contains_duplicates.setText(
                    f'Sorry, the ingredients {duplicates} appear more than once.')
            contains_duplicates.setIcon(QMessageBox.Critical)
            x = contains_duplicates.exec_()

        elif any([y.isEnabled() and y.text() == '' for y in
                  self.ingredient]):  # Checks if there are any empty textboxes
            warning = QMessageBox()
            warning.setWindowTitle("Error!")
            warning.setWindowIcon(QIcon('visuals/L&C Icon.PNG'))
            warning.setText('Sorry, you did not fill all the necessary information. Please check '
                            'that your ingredients list is correct and there are no empty spots.')
            warning.setIcon(QMessageBox.Critical)
            x = warning.exec_()

        elif not all([z.text() in self.clean for z in self.ingredient if
                      z.isEnabled()]):  # Checks if there are any  items that are not valid
            invalid_ingredient = ''
            count = 0
            for x in self.ingredient:
                if x.text() not in self.clean and x.isEnabled():
                    invalid_ingredient += x.text() + ', '

                    count += 1
            invalid_ingredient = invalid_ingredient.strip(', ')

            invalid = QMessageBox()
            invalid.setWindowTitle("Error! - Invalid Ingredient")
            invalid.setWindowIcon(QIcon('visuals/L&C Icon.PNG'))

            if count == 1:  # One ingredient
                invalid.setText(f"Sorry, the ingredient '{invalid_ingredient}' is invalid.")
            else:  # More than one
                invalid.setText(f"Sorry, the ingredients '{invalid_ingredient}' are invalid.")
            invalid.setIcon(QMessageBox.Critical)
            x = invalid.exec_()

        else:  # If everything is correct
            self.hide()
            user_input = [u.text() for u in self.ingredient if u.isEnabled()]

            # Goes to the next dialogue
            self.recipes_dialogue = \
                RecipesDialogue(user_input, int(self.time_selected.text()), self)
            self.recipes_dialogue.show()
Пример #23
0
class TradeShares(QDialog):
    def __init__(self):
        super().__init__()

        self.title = "Trade shares"
        self.top = 200
        self.left = 200
        self.width = 400
        self.height = 300

        # Set the window title and geometry.
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        # Setting the layout
        self.main_layout = QVBoxLayout()
        self.setLayout(self.main_layout)

        self.UI_trading_layout()

    def UI_trading_layout(self):

        # Layout contaning the below buttons layout and shares list.
        self.horizontal_layout = QHBoxLayout()

        # Layout containing line edit and buttons.
        self.vertical_layout_buttons = QVBoxLayout()

        # Create the list of securities.
        self.stocks_list = QListWidget()

        for i, stock in enumerate(securities_objects):
            self.stocks_list.insertItem(i, stock.name)

        # Create the line edit
        self.line_edit_volume = QLineEdit()
        self.line_edit_volume.setPlaceholderText("Amount")
        self.line_edit_volume.setValidator(QIntValidator(1, 100_000_000))

        # Buttons
        self.buy_button = QPushButton(f"Buy")
        self.buy_button.clicked.connect(self.buy_shares)

        self.sell_button = QPushButton(f"Sell")
        self.sell_button.clicked.connect(self.sell_shares)

        self.close_button = QPushButton(f"Close")
        self.close_button.clicked.connect(self.close)

        # Status line
        self.status_line = QLabel(f"")

        # Populate the vertical layout with buttons.
        self.vertical_layout_buttons.addWidget(self.line_edit_volume)
        self.vertical_layout_buttons.addWidget(self.buy_button)
        self.vertical_layout_buttons.addWidget(self.sell_button)
        self.vertical_layout_buttons.addWidget(self.close_button)

        # Populate the horizontal layout.
        self.horizontal_layout.addWidget(self.stocks_list)
        self.horizontal_layout.addLayout(self.vertical_layout_buttons)

        # Populate the veritcal layout.
        self.main_layout.addLayout(self.horizontal_layout)
        self.main_layout.addWidget(self.status_line)

    def UI_change_status_line(self, string):
        def change_status_line(string):
            self.status_line.setText(string)
            time.sleep(2)
            self.status_line.setText(f"")

        status_line_thread = threading.Thread(target=change_status_line,
                                              args=(string, ))
        status_line_thread.start()

    def buy_shares(self):

        selection = self.stocks_list.currentItem().text()
        volume = int(self.line_edit_volume.text())

        # Find the selcted share's object.
        for share in securities_objects:
            if share.name == selection:
                total_price = volume * share.price

        if patrik.check_balance(total_price) == False:
            self.UI_change_status_line(f"Not enough funds.")
        elif selection in patrik.holdings:
            patrik.holdings[selection] += volume
            self.UI_change_status_line(f"Transaction OK.")
        else:
            self.UI_change_status_line(f"Transaction OK.")
            patrik.holdings[selection] = volume

    def sell_shares(self):

        selection = self.stocks_list.currentItem().text()
        volume = int(self.line_edit_volume.text())

        # Find the selcted share's object.
        for share in securities_objects:
            if share.name == selection:
                total_price = volume * share.price

        if selection in patrik.holdings:
            if volume < patrik.holdings[selection]:
                patrik.holdings[selection] -= volume
                self.UI_change_status_line(f"Transaction OK.")
            elif volume == patrik.holdings[selection]:
                del patrik.holdings[selection]
                self.UI_change_status_line(f"Transaction OK.")
            elif volume > patrik.holdings[selection]:
                self.UI_change_status_line(
                    f"You only own {patrik.holdings[selection]} shares, not {volume}."
                )
        else:
            self.UI_change_status_line(f"You don't own these shares")
Пример #24
0
class Window(QWidget):
    def __init__(self, programming=None):
        super(Window, self).__init__()
        self.li = []
        if programming is not None:
            self.li = programming
        self.InitUi()

    def InitUi(self):
        self.listwidget = QListWidget()
        # li=['java','c++', 'c#']
        # self.listwidget.insertItem(0,'C++')
        # self.listwidget.insertItem(1,'PYthon')
        # self.listwidget.insertItem(2,'C#')
        self.listwidget.addItems(self.li)
        self.listwidget.setCurrentRow(0)
        self.vbox = QVBoxLayout()
        self.vbox.addWidget(self.listwidget)
        self.vbox2 = QVBoxLayout()
        for text, slot in (("Add", self.add), ("Edit", self.edit),
                           ("Remove", self.remove), ("Sort", self.sort),
                           ("exit", self.exit)):
            btn = QPushButton(text)
            btn.clicked.connect(slot)
            self.vbox2.addWidget(btn)
        groubox = QGroupBox()
        vbox3 = QVBoxLayout()
        wizardbtn = QPushButton("Launch wizard")
        vbox3.addWidget(wizardbtn)
        groubox.setLayout(vbox3)
        wizardbtn.clicked.connect(self.wizartBtnClicked)
        self.vbox2.addWidget(groubox)

        self.hbox = QHBoxLayout()
        self.hbox.addWidget(self.listwidget)
        self.hbox.addLayout(self.vbox2)
        self.setLayout(self.hbox)

        self.wizardwin = QWizard()

    def wizartBtnClicked(self):
        self.wizardwin.open()

    def sort(self):
        self.listwidget.sortItems()

    def add(self):
        string, ok = QInputDialog.getText(self, 'Add Language',
                                          '추가할 언어를 입력하세요')
        if ok and string is not None:
            row = self.listwidget.currentRow()
            self.listwidget.insertItem(row, string)

    def edit(self):
        row = self.listwidget.currentRow()
        item = self.listwidget.item(row)
        # string, ok=QInputDialog.getText(self,'Edit Language','Enter new Language',QLineEdit.Normal,item.text())
        string, ok = QInputDialog.getText(self, 'Edit Language',
                                          f"{item.text()}(을)를 무엇으로 수정하시겠나요?")

        if ok and string is not None:
            item.setText(string)

    def exit(self):
        self.close()

    def remove(self):
        row = self.listwidget.currentRow()
        item = self.listwidget.takeItem(row)
        del (item)
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.title = "Weather"
        self.setWindowIcon(QtGui.QIcon('weather.ico'))
        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(50, 130, 640, 500)

        self.label = QLabel('Welcome, ' + username, self)
        self.label.setFont(QFont("Verdana", 20, QFont.Bold))
        self.label.setFixedWidth(320)
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.label.move(160, 30)

        self.label2 = QLabel('WEATHER FORECAST', self)
        self.label2.setFont(QFont("Verdana", 18, QFont.Bold))
        self.label2.setFixedWidth(320)
        self.label2.setAlignment(QtCore.Qt.AlignCenter)
        self.label2.move(160, 90)

        self.label3 = QLabel('Enter a city', self)
        self.label3.setFont(QFont("Verdana", 12))
        self.label3.setFixedWidth(160)
        self.label3.setAlignment(QtCore.Qt.AlignCenter)
        self.label3.move(60, 180)

        self.label4 = QLabel('Days of forecast', self)
        self.label4.setFont(QFont("Verdana", 12))
        self.label4.setFixedWidth(160)
        self.label4.setAlignment(QtCore.Qt.AlignCenter)
        self.label4.move(60, 210)

        self.city_name = QLineEdit(self)
        self.city_name.resize(120, 25)
        self.city_name.move(350, 180)

        self.num_days = QSpinBox(self)
        self.num_days.setRange(1, 5)
        self.num_days.setStyleSheet('QComboBox {background-color: white;}')
        self.num_days.resize(120, 25)
        self.num_days.move(350, 210)

        self.button1 = QPushButton('Get Forecast', self)
        self.button1.setFont(QFont("Verdana", 10, QFont.Bold))
        self.button1.setStyleSheet(
            'QPushButton {background-color: red; color: white;}')
        self.button1.resize(120, 30)
        self.button1.move(260, 280)

        def get_forecast():

            url = "https://community-open-weather-map.p.rapidapi.com/forecast/daily"
            self.city = str(self.city_name.text())
            self.days = str(self.num_days.value())
            querystring = {"q": self.city, "cnt": self.days, "units": "metric"}

            headers = {
                'x-rapidapi-host':
                "community-open-weather-map.p.rapidapi.com",
                'x-rapidapi-key':
                "78034bcf5emsh6d33f4776102e77p10adaajsn7041714f6122"
            }

            response = requests.request("GET",
                                        url,
                                        headers=headers,
                                        params=querystring)
            self.data = response.json()
            #print(self.data)
            self.frcst = ''
            if self.data['cod'] == '404':
                self.error = QMessageBox()
                self.error.setWindowTitle('Warning')
                self.error.setIcon(QMessageBox.Warning)
                self.error.setStandardButtons(QMessageBox.Ok)
                self.error.setText(
                    "City Not Found! \n Please Enter A Valid City")
                self.error.setGeometry(300, 300, 100, 100)
                self.error.exec_()
            else:
                self.label5 = QLabel('CITY FOUND', self)
                self.label5.setFont(QFont("Verdana", 14, QFont.Bold))
                self.label5.setFixedWidth(440)
                self.label5.setAlignment(QtCore.Qt.AlignCenter)
                self.label5.move(100, 320)
                self.label5.show()

                for day in self.data['list']:
                    self.date = str(
                        datetime.datetime.fromtimestamp(
                            day['dt']).strftime('%d-%m-%y'))
                    self.weather = str(day['weather'][0]['description'])
                    self.min_temp = float(day['temp']['min'])
                    self.max_temp = float(day['temp']['max'])
                    self.hum = int(day['humidity'])
                    self.text = 'DATE:'
                    self.text2 = 'Weather:'
                    self.text3 = 'Temp min:'
                    self.text4 = 'Temp max:'
                    self.text5 = 'Humidity:'
                    self.d = '{0} {1}'.format(self.text, self.date)
                    self.w = '{0} {1}'.format(self.text2, self.weather)
                    self.mi = '{0} {1}'.format(self.text3, self.min_temp)
                    self.ma = '{0} {1}'.format(self.text4, self.max_temp)
                    self.h = '{0} {1}{2}'.format(self.text5, self.hum, '%')
                    self.frcst += (self.d + "\n" + self.w + '\n' + self.mi +
                                   "\n" + self.ma + "\n" + self.h + '\n\n')

        def open_forecast():
            self.msg = QListWidget()
            self.msg.setWindowTitle("Weather Forecast")
            self.msg.setGeometry(0, 0, 280, 500)
            self.msg.move(690, 100)
            self.msg.insertItem(0, "Forecast for " + self.city.title() + '\n')
            self.msg.insertItem(1, self.frcst)
            self.msg.show()

        self.button1.clicked.connect(get_forecast)

        self.button2 = QPushButton('Show Forecast', self)
        self.button2.setFont(QtGui.QFont("Verdana", 10, QFont.Bold))
        self.button2.setStyleSheet(
            'QPushButton {background-color: blue; color: white;}')
        self.button2.resize(120, 30)
        self.button2.move(260, 360)
        self.button2.clicked.connect(open_forecast)

        self.button3 = QPushButton('Exit', self)
        self.button3.clicked.connect(QCoreApplication.instance().quit)
        self.button3.setFont(QtGui.QFont("Verdana", 10, QFont.Bold))
        self.button3.setStyleSheet(
            'QPushButton {background-color: black; color: white;}')
        self.button3.resize(80, 30)
        self.button3.move(280, 460)
        self.show()
Пример #26
0
class SelectCellDialog(QDialog):
    '''
	Dialog used to select cells or trials for assigning protocols or types.
	'''
    selected = pyqtSignal(tuple)

    def __init__(self, parent=None):
        '''
		Initialize and build the window.

		Parameters
		----------
		parent: QWidget
			Parent window.

		Attributes
		----------
		items: list of QListWidgetItem
			Items to display in QListWidget.
		included: list of int
			Included cell numbers.
		excluded: list of int
			Excluded cell numbers.
		'''
        super().__init__(parent)
        self.incLW = QListWidget(self)
        self.excLW = QListWidget(self)
        self.incLb = QLabel("Included")
        self.excLb = QLabel("Excluded")
        incVB = QVBoxLayout()
        excVB = QVBoxLayout()
        incVB.addWidget(self.incLb)
        incVB.addWidget(self.incLW)
        excVB.addWidget(self.excLb)
        excVB.addWidget(self.excLW)
        excAllBtn = QPushButton(">>", self)
        excBtn = QPushButton('>', self)
        incBtn = QPushButton('<', self)
        incAllBtn = QPushButton("<<", self)
        btnVB = QVBoxLayout()
        btnVB.addWidget(excAllBtn)
        btnVB.addWidget(excBtn)
        btnVB.addWidget(incBtn)
        btnVB.addWidget(incAllBtn)
        selectHB = QHBoxLayout()
        selectHB.addLayout(incVB)
        selectHB.addLayout(btnVB)
        selectHB.addLayout(excVB)
        acceptBtn = QPushButton("OK", self)
        acceptBtn.setDefault(True)
        cancelBtn = QPushButton("Cancel", self)
        btnHB = QHBoxLayout()
        btnHB.addWidget(acceptBtn)
        btnHB.addWidget(cancelBtn)
        topVB = QVBoxLayout(self)
        topVB.addLayout(selectHB)
        topVB.addLayout(btnHB)
        self.items = []
        self.included = []
        self.excluded = []
        # key binding
        incAllBtn.clicked.connect(self.includeAll)
        excAllBtn.clicked.connect(self.excludeAll)
        incBtn.clicked.connect(self.include)
        excBtn.clicked.connect(self.exclude)
        acceptBtn.clicked.connect(self.finish)
        cancelBtn.clicked.connect(self.reject)

    def start(self, inc, exc):
        '''
		Overload dialog open function, initializing items before
		showing the dialog.

		Parameters
		----------
		inc: list of int
			Predefined included cell numbers.
		exc: list of int
			Predefined excluded cell numbers.
		'''
        self.included = sorted(inc)
        self.excluded = sorted(exc)
        self.incLW.clear()
        self.excLW.clear()
        self.items = [None] * (max(self.included + self.excluded))
        for c in self.included:
            self.items[c - 1] = QListWidgetItem(str(c))
            self.incLW.addItem(self.items[c - 1])
        for c in self.excluded:
            self.items[c - 1] = QListWidgetItem(str(c))
            self.excLW.addItem(self.items[c - 1])
        super().open()

    def finish(self):
        '''
		Finish selection, raise selectd signal with (inc, exc) as parameter.

		Signals
		-------
		selected: 
			Signalling selection is finished and return selection results.
		'''
        self.accept()
        self.selected.emit((self.included, self.excluded))

    def include(self):
        '''
		Move the selected items from excluded list to included list.
		'''
        for item in self.excLW.selectedItems():
            c = int(item.text())
            i = bisect.bisect_left(self.excluded, c)
            self.excLW.takeItem(i)
            self.excluded.pop(i)
            j = bisect.bisect_left(self.included, c)
            self.included.insert(j, c)
            self.incLW.insertItem(j, item)
        self.incLW.update()
        self.excLW.update()

    def exclude(self):
        '''
		Move the selected items from included list to excluded list.
		'''
        for item in self.incLW.selectedItems():
            c = int(item.text())
            i = bisect.bisect_left(self.included, c)
            self.incLW.takeItem(i)
            self.included.pop(i)
            j = bisect.bisect_left(self.excluded, c)
            self.excluded.insert(j, c)
            self.excLW.insertItem(j, item)
        self.incLW.update()
        self.excLW.update()

    def includeAll(self):
        '''
		Move all items from excluded list ot included list.
		'''
        while len(self.excluded):
            item = self.excLW.takeItem(0)
            c = self.excluded.pop(0)
            j = bisect.bisect_left(self.included, c)
            self.included.insert(j, c)
            self.incLW.insertItem(j, item)
        self.excLW.update()
        self.incLW.update()

    def excludeAll(self):
        '''
		Move all items from included list ot excluded list.
		'''
        while len(self.included):
            item = self.incLW.takeItem(0)
            c = self.included.pop(0)
            j = bisect.bisect_left(self.excluded, c)
            self.excluded.insert(j, c)
            self.excLW.insertItem(j, item)
        self.incLW.update()
        self.excLW.update()

    def changeTarget(self, target):
        '''
		Change display included or excluded subject.
		'''
        self.incLb.setText("Included " + target)
        self.excLb.setText("Excluded " + target)
class PowerBIThemeGeneratorWindow(QMainWindow):

    _powerBIThemeGenerator = None
    _pbiFilePath = None
    _horizontalLayoutTabVisualsTop = None
    _horizontalLayoutWelcomeScreen = None
    _groupBoxSelectedVisualPropertiesTree = None
    _listWidgetReportPages = None
    _listWidgetReportPageVisuals = None
    _verticalLayoutVisualsPropertiesTab = None
    _verticalLayoutMainWindow = None
    _treeWidgetSelectedVisualProperties = None
    _tabWidgetMainWindow = None
    _tabGeneralProperties = None
    _generalProperties = {}

    def __init__(self):

        super().__init__()

        # Windows Settings
        self.setWindowTitle(AppInfo.Name + ' - ' + AppInfo.Version)
        self.setGeometry(100, 100, 960, 720)

        # Creating central widget element
        self.centralWidget = QWidget(self)
        self.setCentralWidget(self.centralWidget)

        # Creating status bar
        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)

        # Creating menu bar
        self._createMenuBar()

        # Creating main window layout and adding widgets to them
        self._verticalLayoutMainWindow = QVBoxLayout(self.centralWidget)
        self._verticalLayoutMainWindow.addWidget(self._tabWidgetMainWindow)

        # for testing
        # self.__testOpenFileMethod()
        # end for testing

        self._horizontalLayoutWelcomeScreen = QHBoxLayout()
        self._createTabs()

        self.show()

    def _createMenuBar(self):

        # Create menu bar
        menuBar = self.menuBar()

        # Create root menu such as File, Edit, Help etc.
        menuBarFile = menuBar.addMenu('&File')
        menuBarHelp = menuBar.addMenu('&Help')

        # Create actions for Menu
        actionOpenPowerBIFile = QAction('Open &Power BI File', self)
        actionOpenPowerBIFile.setShortcut('Ctrl+O')
        actionOpenPowerBIFile.setStatusTip('Import Power BI file from which you want to export the visual settings to '
                                           'create theme')

        # actionReloadPowerBIFile = QAction('&Reload Power BI File', self)
        # actionReloadPowerBIFile.setShortcut('Ctrl+R')
        # actionReloadPowerBIFile.setStatusTip('Click to reload Power BI file if there are changes made in Power BI
        # file')

        actionGenerateTheme = QAction('&Generate Theme', self)
        actionGenerateTheme.setShortcut('Ctrl+G')
        actionGenerateTheme.setStatusTip('Click to generate theme and save theme file')

        actionQuit = QAction('&Quit', self)
        actionQuit.setShortcut('Ctrl+Q')
        actionQuit.setStatusTip('Click to quit application')

        actionAbout = QAction('&About', self)
        actionAbout.setStatusTip('Click to see detail application information and useful links')

        # Add actions to menu
        menuBarFile.addAction(actionOpenPowerBIFile)
        # menuBarFile.addAction(actionReloadPowerBIFile)
        menuBarFile.addAction(actionGenerateTheme)
        menuBarFile.addSeparator()
        menuBarFile.addAction(actionQuit)

        menuBarHelp.addAction(actionAbout)

        # Add global events i.e. what will happen when option is selected from menu bar
        actionOpenPowerBIFile.triggered.connect(self._openPowerBIFileDialog)
        actionQuit.triggered.connect(self.close)
        actionGenerateTheme.triggered.connect(self.generateTheme)
        actionAbout.triggered.connect(self._showAboutDialog)

    def _openPowerBIFileDialog(self):
        try:

            directory = '/'
            if self._pbiFilePath is not None:
                directory = self._pbiFilePath.split('/')[0:-1]
                directory = "/".join(directory)

            self._pbiFilePath = QFileDialog.getOpenFileName(
                self,
                caption='Select Power BI File',
                directory=directory,
                filter='Power BI Files(*.pbix)'
            )[0]

            if self._pbiFilePath is not '' and not None:
                if self._pbiFilePath.split('/')[-1].split('.')[-1] == 'pbix':
                    self._powerBIThemeGenerator = PowerBIThemeGenerator(self._pbiFilePath)
                else:
                    raise ValueError('Invalid Power BI File')
                self._reportVisualData = self._powerBIThemeGenerator.modifiedDataStructure()
                self._populateTabVisualProperties()
        except Exception as e:
            ShowErrorDialog(LogException(e))

    def __testOpenFileMethod(self):
        self._pbiFilePath = 'G:/Power BI Reports/Theme Template.pbix'
        self._powerBIThemeGenerator = PowerBIThemeGenerator(self._pbiFilePath)
        self._reportVisualData = self._powerBIThemeGenerator.modifiedDataStructure()

    def _createTabs(self):
        # Creating tabs
        self._tabWidgetMainWindow = QTabWidget(self.centralWidget)

        self._tabGeneralProperties = QWidget()
        self._tabVisualProperties = QWidget()

        self._tabWidgetMainWindow.addTab(self._tabGeneralProperties, 'General Properties')
        self._tabWidgetMainWindow.addTab(self._tabVisualProperties, 'Visuals Properties')

        tabBarMainWindow: QTabBar = self._tabWidgetMainWindow.tabBar()
        tabBarMainWindow.setTabToolTip(0, 'Add optional general properties of the theme')
        tabBarMainWindow.setTabToolTip(1, 'All the Power BI File visuals related properties will be visible here')

        self._verticalLayoutVisualsPropertiesTab = QVBoxLayout(self._tabVisualProperties)
        self._verticalLayoutMainWindow.addWidget(self._tabWidgetMainWindow)

        self._populateTabGeneralProperties()
        self._populateTabVisualProperties()

    def _populateTabVisualProperties(self):

        if self._pbiFilePath is None:
            self._showWelcomeScreenTabVisualProperties()
            self._verticalLayoutVisualsPropertiesTab.addLayout(self._horizontalLayoutWelcomeScreen)
        else:
            self._clearTabVisualProperties()
            self._horizontalLayoutTabVisualsTop = QHBoxLayout()
            self._verticalLayoutVisualsPropertiesTab.insertLayout(0, self._horizontalLayoutTabVisualsTop)

            self._createReportPageList()
            # self._create_extra_options()

    def _populateTabGeneralProperties(self):

        try:
            dataColors = []

            def __showMessageBoxInvalidHexColor(hexColor):
                messageBoxInvalidColor = QMessageBox()
                messageBoxInvalidColor.setIcon(QMessageBox.Critical)
                messageBoxInvalidColor.setWindowTitle('Invalid Hex Color Code')
                messageBoxInvalidColor.setText('"' + hexColor + '"' + ' is not valid hex color code')
                messageBoxInvalidColor.exec_()

            def __validateDataColors():
                try:
                    dataColors = [dataColor.strip() for dataColor in lineEditDataColors.text().split(',')]
                    for dataColor in dataColors:
                        if ColorUtil.IsValidHexColor(dataColor) is False and dataColor is not '':
                            dataColors.remove(dataColor)
                            __showMessageBoxInvalidHexColor(dataColor)
                        elif dataColor is '':
                            dataColors.remove(dataColor)
                    lineEditDataColors.setText(','.join(dataColors))
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __showColorPickerDialog():
                try:
                    sender = self.sender().objectName()
                    color: QColor = QColorDialog().getColor()
                    if color.isValid():
                        hexColor = color.name()
                        buttonBackgroundColor = 'background-color: ' + hexColor
                        if sender == 'push_button_data_color':
                            dataColors.append(hexColor)
                            self._generalProperties['dataColors'] = dataColors
                            lineEditDataColors.setText(','.join(dataColors))
                        elif sender == 'push_button_background_color':
                            pushButtonBackgroundColorPicker.setStyleSheet(buttonBackgroundColor)
                            lineEditBackgroundColor.setText(hexColor)
                            self._generalProperties['background'] = hexColor
                        elif sender == 'push_button_foreground_color':
                            pushButtonForegroundColorPicker.setStyleSheet(buttonBackgroundColor)
                            lineEditForegroundColor.setText(hexColor)
                            self._generalProperties['foreground'] = hexColor
                        elif sender == 'push_button_table_accent_color':
                            pushButtonTableAccentColorPicker.setStyleSheet(buttonBackgroundColor)
                            lineEditTableAccent.setText(hexColor)
                            self._generalProperties['tableAccent'] = hexColor
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __lineEditEditingFinished():
                try:
                    sender = self.sender().objectName()
                    if sender == 'line_edit_data_color':
                        __validateDataColors()
                        nonlocal dataColors
                        dataColors = lineEditDataColors.text().split(",")
                        self._generalProperties['dataColors'] = dataColors
                        return
                    elif sender == 'line_edit_background_color':
                        textColor = lineEditBackgroundColor.text()
                    elif sender == 'line_edit_foreground_color':
                        textColor = lineEditForegroundColor.text()
                    elif sender == 'line_edit_table_accent_color':
                        textColor = lineEditTableAccent.text()
                    elif sender == 'line_edit_theme_name':
                        self._generalProperties['name'] = lineEditThemeName.text()
                        return
                    validColor = ColorUtil.IsValidHexColor(textColor)
                    if validColor is False and textColor is not '':
                        __showMessageBoxInvalidHexColor(textColor)
                        if sender == 'line_edit_background_color':
                            lineEditBackgroundColor.setText('')
                        elif sender == 'line_edit_foreground_color':
                            lineEditForegroundColor.setText('')
                        elif sender == 'line_edit_table_accent_color':
                            lineEditTableAccent.setText('')
                    else:
                        buttonBackgroundColor = 'background-color: ' + textColor
                        if sender == 'line_edit_background_color':
                            self._generalProperties['background'] = textColor
                            pushButtonBackgroundColorPicker.setStyleSheet(buttonBackgroundColor)
                        elif sender == 'line_edit_foreground_color':
                            pushButtonForegroundColorPicker.setStyleSheet(buttonBackgroundColor)
                            self._generalProperties['foreground'] = textColor
                        elif sender == 'line_edit_table_accent_color':
                            pushButtonTableAccentColorPicker.setStyleSheet(buttonBackgroundColor)
                            self._generalProperties['tableAccent'] = textColor

                except Exception as e:
                    ShowErrorDialog(LogException(e))

            labelThemeName = QLabel('Theme Name: ')
            lineEditThemeName = QLineEdit()
            lineEditThemeName.setObjectName('line_edit_theme_name')
            lineEditThemeName.editingFinished.connect(__lineEditEditingFinished)

            horizontalLayoutDataColor = QHBoxLayout()
            labelDataColors = QLabel('Data Colors: ')
            labelDataColors.setToolTip('These colors will be visible in color picker and will apply as data colors in '
                                       'charts')
            lineEditDataColors = QLineEdit()
            lineEditDataColors.editingFinished.connect(__lineEditEditingFinished)
            lineEditDataColors.setObjectName('line_edit_data_color')
            pushButtonDataColorPicker = QPushButton()
            pushButtonDataColorPicker.setToolTip('Click to pick colors for Data Colors')
            pushButtonDataColorPicker.setObjectName('push_button_data_color')
            pushButtonDataColorPicker.clicked.connect(__showColorPickerDialog)
            horizontalLayoutDataColor.addWidget(lineEditDataColors)
            horizontalLayoutDataColor.addWidget(pushButtonDataColorPicker)
            # TO DO: Add generate colors button

            horizontalLayoutBackgroundColor = QHBoxLayout()
            labelBackgroundColor = QLabel('Background Color: ')
            labelBackgroundColor.setToolTip('Applies to button fill and combo chart label background. How these colors '
                                            'are used depends on the specific visual style that\'s applied.')
            lineEditBackgroundColor = QLineEdit()
            lineEditBackgroundColor.setObjectName('line_edit_background_color')
            lineEditBackgroundColor.editingFinished.connect(__lineEditEditingFinished)
            pushButtonBackgroundColorPicker = QPushButton()
            pushButtonBackgroundColorPicker.setToolTip('Click to pick color for Background Color')
            pushButtonBackgroundColorPicker.setObjectName('push_button_background_color')
            pushButtonBackgroundColorPicker.clicked.connect(__showColorPickerDialog)
            horizontalLayoutBackgroundColor.addWidget(lineEditBackgroundColor)
            horizontalLayoutBackgroundColor.addWidget(pushButtonBackgroundColorPicker)

            horizontalLayoutForegroundColor = QHBoxLayout()
            labelForegroundColor = QLabel('Foreground Color: ')
            labelForegroundColor.setToolTip('Applies to textbox text, KPI goal text, multi-row card text, card value '
                                            'text, gauge callout text, vertical slicer element text, and table and '
                                            'matrix total and values text.')
            lineEditForegroundColor = QLineEdit()
            lineEditForegroundColor.setObjectName('line_edit_foreground_color')
            lineEditForegroundColor.editingFinished.connect(__lineEditEditingFinished)
            pushButtonForegroundColorPicker = QPushButton()
            pushButtonForegroundColorPicker.setToolTip('Click to pick color for Foreground Color')
            pushButtonForegroundColorPicker.setObjectName('push_button_foreground_color')
            pushButtonForegroundColorPicker.clicked.connect(__showColorPickerDialog)
            horizontalLayoutForegroundColor.addWidget(lineEditForegroundColor)
            horizontalLayoutForegroundColor.addWidget(pushButtonForegroundColorPicker)

            horizontalLayoutTableAccent = QHBoxLayout()
            labelTableAccent = QLabel('Table Accent: ')
            labelTableAccent.setToolTip('Table and matrix visuals apply these styles by default.')
            lineEditTableAccent = QLineEdit()
            lineEditTableAccent.setObjectName('line_edit_table_accent_color')
            lineEditTableAccent.editingFinished.connect(__lineEditEditingFinished)
            pushButtonTableAccentColorPicker = QPushButton()
            pushButtonTableAccentColorPicker.setToolTip('Click to pick color for Table Accent Color')
            pushButtonTableAccentColorPicker.setObjectName('push_button_table_accent_color')
            pushButtonTableAccentColorPicker.clicked.connect(__showColorPickerDialog)
            horizontalLayoutTableAccent.addWidget(lineEditTableAccent)
            horizontalLayoutTableAccent.addWidget(pushButtonTableAccentColorPicker)

            formLayoutGeneralProperties = QFormLayout(self._tabGeneralProperties)
            formLayoutGeneralProperties.addRow(labelThemeName, lineEditThemeName)
            formLayoutGeneralProperties.addRow(labelDataColors, horizontalLayoutDataColor)
            formLayoutGeneralProperties.addRow(labelBackgroundColor, horizontalLayoutBackgroundColor)
            formLayoutGeneralProperties.addRow(labelForegroundColor, horizontalLayoutForegroundColor)
            formLayoutGeneralProperties.addRow(labelTableAccent, horizontalLayoutTableAccent)
        except Exception as e:
            ShowErrorDialog(LogException(e))

    def _showWelcomeScreenTabVisualProperties(self):
        welcomeLabel = QLabel('Go to File menu or press Ctrl+O to select Power BI File')
        self._horizontalLayoutWelcomeScreen.addStretch()
        self._horizontalLayoutWelcomeScreen.addWidget(welcomeLabel)
        self._horizontalLayoutWelcomeScreen.addStretch()

    def _removeWelcomeScreenFromTabVisualProperties(self):
        self._deleteLayout(self._horizontalLayoutWelcomeScreen)

    def _clearTabVisualProperties(self):
        self._removeWelcomeScreenFromTabVisualProperties()
        self._deleteLayout(self._verticalLayoutVisualsPropertiesTab)
        self._listWidgetReportPages = None
        self._listWidgetReportPageVisuals = None
        self._treeWidgetSelectedVisualProperties = None

    def _deleteLayout(self, layout):
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.deleteLater()
                else:
                    self._deleteLayout(item.layout())
            # sip.delete(layout)

    def _createReportPageList(self):
        try:
            def __reportPageListValueSelected(item):
                try:
                    self._createReportPageVisualsList(item.GetMetaData()['reportPageSection'])
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            if self._listWidgetReportPages is not None:
                self._listWidgetReportPages.clear()

            groupBoxReportPageList = QGroupBox(self.centralWidget)
            groupBoxReportPageList.setTitle("Report Pages")
            verticalLayoutReportPageList = QVBoxLayout(groupBoxReportPageList)

            self._listWidgetReportPages = QListWidget()

            i = 0
            for reportSection in self._powerBIThemeGenerator.get_report_sections():
                reportListWidgetItem = CQListWidgetItemReportPages(str(reportSection['displayName']))
                reportListWidgetItem.SetMetaData(reportSection)
                reportListWidgetItem.setToolTip(reportSection['name'])
                self._listWidgetReportPages.insertItem(i, reportListWidgetItem)
                i += 1

            verticalLayoutReportPageList.addWidget(self._listWidgetReportPages)
            self._horizontalLayoutTabVisualsTop.addWidget(groupBoxReportPageList)
            # __reportPageListValueSelected(self._listWidgetReportPages.item(0))

            self._listWidgetReportPages.itemClicked.connect(__reportPageListValueSelected)

        except Exception as e:
            ShowErrorDialog(LogException(e))

    def _createReportPageVisualsList(self, reportPageSection=None):

        try:
            # print(self._reportVisualData[reportPageSection])
            # print('inside report page visual list', reportPageSection)

            def __updateStateInDataStructure(item):
                vizProperties = item.GetVisualProperties()
                if item.checkState() == Qt.Checked:
                    (self._reportVisualData[vizProperties['report_section']]
                        .get('visuals')[vizProperties['visual_index']]['__selected']) = True
                else:
                    (self._reportVisualData[vizProperties['report_section']]
                        .get('visuals')[vizProperties['visual_index']]['__selected']) = False

            def __getVisualProperties(item: CQListWidgetItemReportPageVisuals):
                try:
                    __updateStateInDataStructure(item)
                    self._createSelectedVisualPropertiesTree(item.GetVisualProperties())
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __selectDeselectAll():
                try:
                    if self._listWidgetReportPageVisuals is not None:
                        for i in range(self._listWidgetReportPageVisuals.count()):
                            item = self._listWidgetReportPageVisuals.item(i)
                            if self.sender().objectName() == 'button_select_all':
                                item.setCheckState(Qt.Checked)
                            else:
                                item.setCheckState(Qt.Unchecked)
                            __updateStateInDataStructure(item)
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            groupBoxReportPageVisualsList = QGroupBox(self.centralWidget)
            groupBoxReportPageVisualsList.setTitle("Visuals in Selected Report Page")
            # groupBoxReportPageVisualsList.setToolTip("All visuals present in the selected page will be visible below")
            verticalLayoutReportPageVisualsList = QVBoxLayout(groupBoxReportPageVisualsList)

            horizontalLayoutSelectDeselectButton = QHBoxLayout()
            pushButtonSelectAll = QPushButton('Select All')
            pushButtonSelectAll.setObjectName('button_select_all')
            pushButtonDeselectAll = QPushButton('Deselect All')
            pushButtonDeselectAll.setObjectName('button_deselect_all')
            horizontalLayoutSelectDeselectButton.addWidget(pushButtonSelectAll)
            horizontalLayoutSelectDeselectButton.addWidget(pushButtonDeselectAll)
            verticalLayoutReportPageVisualsList.addLayout(horizontalLayoutSelectDeselectButton)

            if self._listWidgetReportPageVisuals is None:
                self._listWidgetReportPageVisuals = QListWidget()
                verticalLayoutReportPageVisualsList.addWidget(self._listWidgetReportPageVisuals)
                self._horizontalLayoutTabVisualsTop.addWidget(groupBoxReportPageVisualsList)
                self._listWidgetReportPageVisuals.itemClicked.connect(__getVisualProperties, Qt.UniqueConnection)
            else:
                self._listWidgetReportPageVisuals.clear()

            i = 0
            for visualIndex, visual in enumerate(self._reportVisualData[reportPageSection].get('visuals')):
                visualType = visual['visual_type']
                visualTitle = visual.get('objects').get('title')
                # print(visualType, visualTitle)
                if visualTitle is None or visualTitle.get('text') is None:
                    listDisplayText = str(visualType)
                else:
                    listDisplayText = str(visualType) + " - " + visualTitle.get('text')
                pageVisualsList = CQListWidgetItemReportPageVisuals(listDisplayText)
                pageVisualsList.setFlags(pageVisualsList.flags() | Qt.ItemIsUserCheckable)
                if visual['__selected'] is False:
                    pageVisualsList.setCheckState(Qt.Unchecked)
                else:
                    pageVisualsList.setCheckState(Qt.Checked)
                pageVisualsList.SetVisualProperties(visual, reportPageSection, visualIndex)
                # print(pageVisualsList.GetVisualProperties())
                self._listWidgetReportPageVisuals.insertItem(i, pageVisualsList)
                i += 1

            pushButtonSelectAll.clicked.connect(__selectDeselectAll)
            pushButtonDeselectAll.clicked.connect(__selectDeselectAll)

            # self._listWidgetReportPageVisuals.setCurrentRow(0)
            # __getVisualProperties(self._listWidgetReportPageVisuals.item(0))

        except Exception as e:
            ShowErrorDialog(LogException(e))

    def _createSelectedVisualPropertiesTree(self, visualProperties=None):
        try:

            def __getVisualProperty(item: CQTreeWidgetItemVisualProperties):
                try:
                    visualProperties = item.GetVisualProperties()
                    if visualProperties is not None:
                        visualProperty = (self._reportVisualData[visualProperties['report_section']]
                                          .get('visuals')[visualProperties['visual_index']].get('objects')
                                          .get(str(item.data(0, 0))))
                        return visualProperty
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __updateStateInDataStructure(item: CQTreeWidgetItemVisualProperties):
                try:
                    visualProperty = __getVisualProperty(item)
                    if visualProperty is not None:
                        if item.checkState(0) == Qt.Unchecked:
                            visualProperty['__selected'] = False
                        else:
                            visualProperty['__selected'] = True
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __updateWildCardState(state, item=None):
                try:
                    visualProperty = __getVisualProperty(item)
                    if visualProperty is not None:
                        if state == Qt.Checked:
                            visualProperty['__wildcard'] = True
                            # print(visualProperty)
                        elif visualProperty.get('__wildcard') is not None and state == Qt.Unchecked:
                            visualProperty.pop('__wildcard')
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __treeWidgetVisualsPropertiesClicked(item: CQTreeWidgetItemVisualProperties):
                try:
                    __updateStateInDataStructure(item)
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __selectDeselectAll():
                try:
                    if self._treeWidgetSelectedVisualProperties is not None:
                        for i in range(self._treeWidgetSelectedVisualProperties.topLevelItemCount()):
                            item = self._treeWidgetSelectedVisualProperties.topLevelItem(i)
                            if self.sender().objectName() == 'button_select_all':
                                item.setCheckState(0, Qt.Checked)
                            else:
                                item.setCheckState(0, Qt.Unchecked)
                            __updateStateInDataStructure(item)
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            self._groupBoxSelectedVisualPropertiesTree = QGroupBox(self.centralWidget)
            self._groupBoxSelectedVisualPropertiesTree.setTitle("Selected Visual Properties")
            verticalLayoutSelectedVisualPropertiesTree = QVBoxLayout(self._groupBoxSelectedVisualPropertiesTree)

            horizontalLayoutSelectDeselectButton = QHBoxLayout()
            pushButtonSelectAll = QPushButton('Select All')
            pushButtonSelectAll.setObjectName('button_select_all')
            pushButtonDeselectAll = QPushButton('Deselect All')
            pushButtonDeselectAll.setObjectName('button_deselect_all')
            horizontalLayoutSelectDeselectButton.addWidget(pushButtonSelectAll)
            horizontalLayoutSelectDeselectButton.addWidget(pushButtonDeselectAll)
            verticalLayoutSelectedVisualPropertiesTree.addLayout(horizontalLayoutSelectDeselectButton)

            if self._treeWidgetSelectedVisualProperties is None:
                self._treeWidgetSelectedVisualProperties = QTreeWidget()
                verticalLayoutSelectedVisualPropertiesTree.addWidget(self._treeWidgetSelectedVisualProperties)
                self._verticalLayoutVisualsPropertiesTab.insertWidget(1, self._groupBoxSelectedVisualPropertiesTree)
                self._treeWidgetSelectedVisualProperties.itemClicked.connect(__treeWidgetVisualsPropertiesClicked)
            else:
                self._treeWidgetSelectedVisualProperties.clear()

            self._treeWidgetSelectedVisualProperties.setHeaderLabels(['Property', 'Value', 'Wild Card'])
            treeHeader = self._treeWidgetSelectedVisualProperties.header()
            treeHeader.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
            # treeHeader.setStretchLastSection(False)

            visualObjects = visualProperties['visual_properties'].get('objects')
            for object, objectValues in visualObjects.items():
                if len(objectValues.keys()) > 1:  # greater than 1 because one default key is __selected
                    parent = CQTreeWidgetItemVisualProperties(self._treeWidgetSelectedVisualProperties, [str(object)])
                    parent.SetVisualProperties(visualProperties)
                    wildCardCheckBox = QCheckBox()
                    wildCardCheckBox.stateChanged.connect(partial(__updateWildCardState, item=parent))
                    self._treeWidgetSelectedVisualProperties.setItemWidget(parent, 2, wildCardCheckBox)
                    if objectValues['__selected'] is False:
                        parent.setCheckState(0, Qt.Unchecked)
                    else:
                        parent.setCheckState(0, Qt.Checked)
                    for objectKey, objectValue in objectValues.items():
                        if objectKey is not '__selected':
                            mObjectV = None
                            if type(objectValue) is dict and objectValue.get('solid') is not None:
                                mObjectV = objectValue.get('solid').get('color')
                            else:
                                mObjectV = objectValue
                            CQTreeWidgetItemVisualProperties(parent, [str(objectKey), str(mObjectV)])
                else:
                    objectValues['__selected'] = False

            pushButtonSelectAll.clicked.connect(__selectDeselectAll)
            pushButtonDeselectAll.clicked.connect(__selectDeselectAll)

        except Exception as e:
            ShowErrorDialog(LogException(e))

    def generateTheme(self):
        try:
            correctVisualData = True
            correctWildcardData = True
            themeName = self._generalProperties.get('name')
            themeData = {
                'name': themeName
                if themeName is not None and len(themeName.strip()) > 0 else 'My Theme',
            }
            if self._generalProperties.get('dataColors') is not None:
                dataColors = list(filter(None, self._generalProperties.get('dataColors')))

            else:
                dataColors = []
            background = self._generalProperties.get('background')
            foreground = self._generalProperties.get('foreground')
            tableAccent = self._generalProperties.get('tableAccent')

            if dataColors is not None and dataColors is not "":
                themeData['dataColors'] = dataColors
            if background is not None and background is not "":
                themeData['background'] = background
            if foreground is not None and foreground is not "":
                themeData['foreground'] = foreground
            if tableAccent is not None and tableAccent is not "":
                themeData['tableAccent'] = tableAccent

            selectedVisualsList = [[], [], []]  # page name, visual type and visual data or visual objects
            wildCardPropertiesList = [[], [], []]  # page name, property type and property data
            visualObjectIndex = 0
            themeData['visualStyles'] = {}
            if self._pbiFilePath is not None:
                for reportPage in self._reportVisualData:
                    for visual in self._reportVisualData[reportPage].get('visuals'):
                        pageName = self._reportVisualData[reportPage]['reportPageDisplayName']
                        if visual['__selected'] is True:
                            selectedVisualsList[0].append(pageName)
                            selectedVisualsList[1].append(visual['visual_type'])
                            selectedVisualsList[2].append({})
                            visualObjects = visual.get('objects')
                            for object in visualObjects:
                                if visualObjects[object]['__selected'] is True:
                                    selectedVisualsList[2][visualObjectIndex][object] = [visualObjects[object]]
                                    if visualObjects[object].get('__wildcard') is not None:
                                        # wildCardObjects[object] = [visualObjects[object]]
                                        wildCardPropertiesList[0].append(pageName)
                                        wildCardPropertiesList[1].append(object)
                                        wildCardPropertiesList[2].append(visualObjects[object])

                            visualObjectIndex += 1
                if len(selectedVisualsList[1]) > 0:
                    if len(selectedVisualsList[1]) != len(set(selectedVisualsList[1])):
                        message = 'Multiple visual of same type selected from different report pages. See details below.' \
                                  ' Please select one visual type for only once.'
                        detailMessage = ''
                        seen = set()
                        repeatedVisuals = []
                        for selectedVisual in selectedVisualsList[1]:
                            if selectedVisual in seen:
                                repeatedVisuals.append(selectedVisual)
                            else:
                                seen.add(selectedVisual)

                        for i, selectedVisual in enumerate(selectedVisualsList[1]):
                            if selectedVisual in repeatedVisuals:
                                detailMessage += selectedVisual + ' is selected in report page'\
                                                 + selectedVisualsList[0][i] + '\n'
                        correctVisualData = False
                        self._showDialogAfterThemeGeneration(message, detailMessage=detailMessage)

                    else:
                        # adding wild card data
                        if len(wildCardPropertiesList[1]) > 0:
                            if len(wildCardPropertiesList[1]) != len(set(wildCardPropertiesList[1])):
                                message = 'Multiple wild card properties of same types are selected. Please only select '\
                                          'unique properties for wild card from all the visuals. As a result this' \
                                          'properties will not be added as wild card property in them file. ' \
                                          'See details below'
                                detailMessage = ''
                                seen = set()
                                repeatedWildCardProperties = []
                                for wildCardProperty in wildCardPropertiesList[1]:
                                    if wildCardProperty in seen:
                                        repeatedWildCardProperties.append(wildCardProperty)
                                    else:
                                        seen.add(wildCardProperty)

                                for i, wildCardProperty in enumerate(wildCardPropertiesList[1]):
                                    if wildCardProperty in repeatedWildCardProperties:
                                        detailMessage += wildCardProperty + 'is selected in report page' +\
                                                         wildCardPropertiesList[0][i]
                                correctWildcardData = False
                                self._showDialogAfterThemeGeneration(message, detailMessage=detailMessage)
                            else:
                                themeData['visualStyles']['*'] = {
                                    '*': {}
                                }
                                for i in range(len(wildCardPropertiesList[1])):
                                    themeData['visualStyles']['*']['*'][wildCardPropertiesList[1][i]] = [wildCardPropertiesList[2][i]]

                        # adding visual data
                        for i in range(len(selectedVisualsList[1])):
                            themeData['visualStyles'][selectedVisualsList[1][i]] = {
                                "*": selectedVisualsList[2][i]
                            }
            if correctVisualData is True and correctWildcardData is True:
                self._saveThemeFile(themeData, 'C:/Users/bjadav/Desktop/', themeData['name'])

        except Exception as e:
            ShowErrorDialog(LogException(e))

    def _showDialogAfterThemeGeneration(self, message, messageIcon=QMessageBox.Information, detailMessage=None):
        try:
            messageBoxThemeGeneration = QMessageBox()
            messageBoxThemeGeneration.setIcon(messageIcon)
            messageBoxThemeGeneration.setText(message)
            if detailMessage is not None:
                messageBoxThemeGeneration.setInformativeText(detailMessage)
            messageBoxThemeGeneration.setWindowTitle("Theme Generation Information")
            messageBoxThemeGeneration.setStandardButtons(QMessageBox.Ok)

            messageBoxThemeGeneration.exec_()
        except Exception as e:
            ShowErrorDialog(LogException(e))

    def _saveThemeFile(self, themeData, saveFileDirectory, fileName):
        try:
            _themeData = json.loads(json.dumps(themeData))
            # Removing internal keys such as __selected from final output
            for visualType, visualProperties in _themeData['visualStyles'].items():
                for propertyType, propertyValue in visualProperties['*'].items():
                    if propertyValue[0].get('__selected') is not None:
                        propertyValue[0].pop('__selected')
                    if propertyValue[0].get('__wildcard') is not None:
                        propertyValue[0].pop('__wildcard')

            initialSaveFilePath = saveFileDirectory + fileName + '.json'
            saveFile = QFileDialog.getSaveFileName(self, 'Save Theme File', initialSaveFilePath,
                                                   filter='JSON file(*.json)')[0]
            if saveFile is not '':
                with open(saveFile, 'w') as themeFile:
                    json.dump(_themeData, themeFile, indent=4)
                message = 'Successfully generated theme'
                self._showDialogAfterThemeGeneration(message)
        except Exception as e:
            ShowErrorDialog(LogException(e))

    def _showAboutDialog(self):
        try:
            dialogAbout = QDialog()
            dialogAbout.resize(320, 180)
            dialogButtonBoxAbout = QDialogButtonBox(dialogAbout)
            dialogButtonBoxAbout.setLayoutDirection(Qt.LeftToRight)
            dialogButtonBoxAbout.setAutoFillBackground(False)
            dialogButtonBoxAbout.setOrientation(Qt.Horizontal)
            dialogButtonBoxAbout.setStandardButtons(QtWidgets.QDialogButtonBox.Ok)
            dialogButtonBoxAbout.setCenterButtons(True)
            dialogButtonBoxAbout.accepted.connect(dialogAbout.accept)

            verticalLayoutAboutDialog = QVBoxLayout(dialogAbout)

            dialogAbout.setWindowTitle('About ' + AppInfo.Name)

            labelPowerBIThemeGeneratorFont = QFont()
            labelPowerBIThemeGeneratorFont.setPointSize(16)
            labelPowerBIThemeGeneratorFont.setFamily('Calibri')
            labelPowerBIThemeGenerator = QLabel(AppInfo.Name)
            labelPowerBIThemeGenerator.setFont(labelPowerBIThemeGeneratorFont)

            labelVersionFont = QFont()
            labelVersionFont.setPointSize(8)
            labelVersion = QLabel(AppInfo.Version)
            labelVersion.setContentsMargins(0, 0, 0, 0)

            labelCreatedBy = QLabel('Created By ' + AppInfo.Author)
            link = '<a href="' + AppInfo.GitHubRepoIssuesURL + '">Click here to report bugs</a>'
            labelBugs = QLabel(link)
            labelBugs.setOpenExternalLinks(True)

            verticalLayoutAboutDialog.addWidget(labelPowerBIThemeGenerator)
            verticalLayoutAboutDialog.addWidget(labelVersion)
            verticalLayoutAboutDialog.addWidget(labelCreatedBy)
            verticalLayoutAboutDialog.addWidget(labelBugs)
            verticalLayoutAboutDialog.addStretch()
            verticalLayoutAboutDialog.addWidget(dialogButtonBoxAbout)
            dialogAbout.exec_()
        except Exception as e:
            ShowErrorDialog(LogException(e))
Пример #28
0
class CityListDlg(QDialog):
    citieslist_signal = pyqtSignal([list])
    citiesdict_signal = pyqtSignal([dict])

    def __init__(self,
                 citylist,
                 accurate_url,
                 appid,
                 trans_cities_dict,
                 parent=None):
        super(CityListDlg, self).__init__(parent)
        self.settings = QSettings()
        self.citylist = citylist
        self.trans_cities_dict = trans_cities_dict
        self.accurate_url = accurate_url
        self.appid = appid
        self.listWidget = QListWidget()
        self.listWidget.itemDoubleClicked.connect(self.translate)
        cities_list = []
        for i in self.citylist:
            cities_list.append(self.trans_cities_dict.get(i, i))
        self.listWidget.addItems(cities_list)
        buttonLayout = QVBoxLayout()
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonBox.rejected.connect(self.reject)
        self.buttonBox.accepted.connect(self.accept)
        layoutT = QVBoxLayout()
        layout = QHBoxLayout()
        layout.addWidget(self.listWidget)
        layout.addLayout(buttonLayout)
        for text, slot in ((self.tr("&Add..."),
                            self.add), (self.tr("&Remove..."), self.remove),
                           (self.tr("&Up"), self.up),
                           (self.tr("&Down"), self.down), (self.tr("De&fault"),
                                                           self.default),
                           (self.tr("&Sort"), self.listWidget.sortItems)):
            button = QPushButton(text)
            buttonLayout.addWidget(button)
            button.clicked.connect(slot)
        self.translate_button = QPushButton(
            QCoreApplication.translate('Button', '&Translate',
                                       'Edit cities dialogue'))
        buttonLayout.addWidget(self.translate_button)
        self.translate_button.clicked.connect(self.translate)
        buttonLayout.addWidget(self.buttonBox)
        self.status = QLabel()
        layoutT.addLayout(layout)
        layoutT.addWidget(self.status)
        self.setLayout(layoutT)
        self.setWindowTitle(
            QCoreApplication.translate('Window title', 'Cities',
                                       'Cities list dialogue'))
        self.checklength()

    def add(self):
        self.status.setText('')
        lista = []
        newitem = ''
        self.citytoadd = ''
        self.countrytoadd = ''
        self._idtoadd = ''
        dialog = searchcity.SearchCity(self.accurate_url, self.appid, self)
        dialog.id_signal.connect(self.addcity)
        dialog.city_signal.connect(self.addcity)
        dialog.country_signal.connect(self.addcity)
        if dialog.exec_() == 1:
            newitem = (self.citytoadd + '_' + self.countrytoadd + '_' +
                       self._idtoadd)
            for row in range(self.listWidget.count()):
                lista.append(self.listWidget.item(row).text())
            if newitem in lista:
                self.status.setText(
                    QCoreApplication.translate(
                        'Status bar message',
                        'The city already exists in the list',
                        'Cities list dialogue'))
                return
            else:
                self.listWidget.addItem(newitem)
                self.checklength()

    def addcity(self, what):
        self.status.setText('')
        if what[0] == 'ID':
            self._idtoadd = what[1]
        elif what[0] == 'City':
            self.citytoadd = what[1]
        elif what[0] == 'Country':
            self.countrytoadd = what[1]

    def remove(self):
        self.status.setText('')
        if self.listWidget.count() == 1:
            self.status.setText(
                QCoreApplication.translate(
                    'Message when trying to remove the last and unique city in the list',
                    'This is the default city !', 'Cities list dialogue'))
            return
        row = self.listWidget.currentRow()
        item = self.listWidget.item(row)
        if item is None:
            return
        message = self.tr('The city "{0}" has been removed').format(
            self.listWidget.item(row).text())
        item = self.listWidget.takeItem(row)
        del item
        self.status.setText(message)

    def up(self):
        self.status.setText('')
        row = self.listWidget.currentRow()
        if row >= 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(row - 1, item)
            self.listWidget.setCurrentItem(item)

    def down(self):
        self.status.setText('')
        row = self.listWidget.currentRow()
        if row < self.listWidget.count() - 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(row + 1, item)
            self.listWidget.setCurrentItem(item)

    def default(self):
        self.status.setText('')
        row = self.listWidget.currentRow()
        if row >= 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(0, item)
            self.listWidget.setCurrentItem(item)

    def checklength(self):
        if self.listWidget.count() == 1:
            # After adding the first city the entry is not activated
            self.listWidget.setCurrentRow(0)
        if self.listWidget.count() > 0:
            self.translate_button.setEnabled(True)
            self.listWidget.setMinimumWidth(
                self.listWidget.sizeHintForColumn(0))
        else:
            self.translate_button.setEnabled(False)

    def translate(self):
        city = self.listWidget.currentItem().text()
        dialog = citytranslate.CityTranslate(city, self.trans_cities_dict,
                                             self)
        dialog.city_signal.connect(self.current_translation)
        if dialog.exec_() == 1:
            row = self.listWidget.currentRow()
            item = self.listWidget.takeItem(row)
            del item
            self.listWidget.insertItem(row, self.current_translated_city)
            self.listWidget.setCurrentRow(row)

    def current_translation(self, translated_city):
        for city, translated in translated_city.items():
            if translated == '':
                translated = city
            self.trans_cities_dict[city] = translated
            self.current_translated_city = translated

    def accept(self):
        listtosend = []
        for row in range(self.listWidget.count()):
            city = self.find_city_key(self.listWidget.item(row).text())
            listtosend.append(city)
        if self.listWidget.count() == 0:
            return
        self.citieslist_signal[list].emit(listtosend)
        self.citiesdict_signal[dict].emit(self.trans_cities_dict)
        QDialog.accept(self)

    def find_city_key(self, city):
        for key, value in self.trans_cities_dict.items():
            if value == city:
                return key
        return city
Пример #29
0
class Ui(QWidget):
    def setupUi(self, Main):

        Main.setObjectName("Main")
        Main.setFixedSize(900, 500)

        self.width = 900
        self.height = 500

        self.setFixedSize(self.width, self.height)
        '''MENU ON THE MAIN WINDOW'''
        self.menu = QStackedLayout()

        self.mainMenu = QWidget()
        self.howToMenu = QWidget()

        self.mainMenuUi()
        self.howToMenuUi()

        self.menu.addWidget(self.mainMenu)
        self.menu.addWidget(self.howToMenu)
        '''MENU ON THE HOWTO WINDOW'''
        #self.howToMenuMenu = QStackedLayout()

        #self.howToOverView    = QWidget()
        #self.howToLevel       = QWidget()
        #self.howToTapeMeasure = QWidget()
        #self.howToTheodolite  = QWidget()

        #self.   overViewUi()
        #self.      levelUi()
        #self.tapeMeasureUi()
        #self. theodoliteUi()

        #self.howToMenuMenu.addWidget(self.howToOverView   )
        #self.howToMenuMenu.addWidget(self.howToLevel      )
        #self.howToMenuMenu.addWidget(self.howToTapeMeasure)
        #self.howToMenuMenu.addWidget(self.howToTheodolite )

    def mainMenuUi(self):

        self.mainMenu.setFixedSize(self.width, self.height)

        self.mainMenuText = QLabel(self.mainMenu)
        self.mainMenuText.setGeometry(QRect(30, 120, 480, 200))
        self.mainMenuText.setStyleSheet("font: 14pt Century Gothic")
        self.mainMenuText.setAlignment(Qt.AlignLeading | Qt.AlignLeft
                                       | Qt.AlignTop)
        self.mainMenuText.setText(
            "Welcome to the Surveying Traverse Calculator!")

        self.howToButton = QPushButton("HOW TO DO A TRAVERSE", self.mainMenu)

        self.howToButton.setGeometry(140, 180, 200, 30)

    def howToMenuUi(self):

        self.howToMenu_layout = QGridLayout()

        self.howToMenu.setFixedSize(self.width, self.height)

        self.menuButton1 = QPushButton("Back to main menu")
        self.menuButton1.setGeometry(QRect(10, 10, 200, 30))

        self.howToTitle = QLabel()
        self.howToTitle.setGeometry(QRect(10, 50, self.width, 40))
        self.howToTitle.setStyleSheet("font: 14pt Century Gothic")
        self.howToTitle.setAlignment(Qt.AlignLeading | Qt.AlignLeft
                                     | Qt.AlignVCenter)
        self.howToTitle.setText("How to Do a Traverse")

        self.howToSteps = QListWidget()
        self.howToSteps.setGeometry(QRect(10, 100, 200, 80))
        self.howToSteps.insertItem(0, "OVERVIEW")
        self.howToSteps.insertItem(1, "LEVEL")
        self.howToSteps.insertItem(2, "TAPE MEASURE")
        self.howToSteps.insertItem(3, "THEODOLITE")
        self.howToSteps.currentRowChanged.connect(self.display_traverse)

        self.overview_container = QWidget()
        self.level_container = QWidget()
        self.tape_measure_container = QWidget()
        self.theodolite_container = QWidget()

        self.overViewUi()
        self.levelUi()
        self.tapeMeasureUi()
        self.theodoliteUi()

        self.traverse_action = QStackedWidget()
        self.traverse_action.addWidget(self.overview_container)
        self.traverse_action.addWidget(self.level_container)
        self.traverse_action.addWidget(self.tape_measure_container)
        self.traverse_action.addWidget(self.theodolite_container)
        self.traverse_action.setCurrentIndex(0)

        self.howToMenu_left_layout = QVBoxLayout()
        self.howToMenu_left_layout.addWidget(self.menuButton1)
        self.howToMenu_left_layout.addWidget(self.howToTitle)
        self.howToMenu_left_layout.addWidget(self.howToSteps)

        self.howToMenu_layout.addLayout(self.howToMenu_left_layout, 0, 0, 1, 1)
        self.howToMenu_layout.addWidget(self.traverse_action, 0, 1, 1, 1)
        self.howToMenu.setLayout(self.howToMenu_layout)

    def overViewUi(self):
        self.overview_layout = QVBoxLayout()
        self.overview_button = QPushButton('Overview')
        self.overview_layout.addWidget(self.overview_button)
        self.overview_container.setLayout(self.overview_layout)

    def levelUi(self):
        self.level_layout = QVBoxLayout()
        self.level_button = QPushButton('Level')
        self.level_layout.addWidget(self.level_button)
        self.level_container.setLayout(self.level_layout)

    def tapeMeasureUi(self):
        self.tape_measure_layout = QVBoxLayout()
        self.tape_measure_button = QPushButton('Tape measure')
        self.tape_measure_layout.addWidget(self.tape_measure_button)
        self.tape_measure_container.setLayout(self.tape_measure_layout)

    def theodoliteUi(self):
        self.theodolite_layout = QVBoxLayout()
        self.theodolite_button = QPushButton('Theodolite')
        self.theodolite_layout.addWidget(self.theodolite_button)
        self.theodolite_container.setLayout(self.theodolite_layout)

    def display_traverse(self, index):
        self.traverse_action.setCurrentIndex(index)
Пример #30
0
class TabMain_gui(QWidget):
    def __init__(self, caller, *args, **kwargs):
        QWidget.__init__(self)
        self.caller = caller
        ###-- Initialize
        self.loadIcons()
        self.initGlobalButtons()
        self.initBody()
        ###-- Compose layout
        mainVertical = QVBoxLayout()
        mainVertical.setSpacing(10)
        mainVertical.addLayout(self.globalButtons)
        mainVertical.addWidget(self.body)
        ###-- Set Layout
        self.setLayout(mainVertical)

    def initGlobalButtons(self):
        ###-- Global Buttons
        globalButtons = QHBoxLayout()
        self.button_startAll = QPushButton("Start All Masternodes")
        globalButtons.addWidget(self.button_startAll)
        self.button_getAllStatus = QPushButton("Get Status of All Masternodes")
        globalButtons.addWidget(self.button_getAllStatus)
        self.button_sweepAllRewards = QPushButton("Sweep All Rewards")
        globalButtons.addWidget(self.button_sweepAllRewards)
        self.globalButtons = globalButtons

    def initBody(self):
        ###-- CENTRAL PART
        self.body = QGroupBox()
        self.body.setTitle("My Masternodes")
        # masternode list
        self.myList = QListWidget()
        self.myList.setUpdatesEnabled(True)
        self.myList.setDragDropMode(QAbstractItemView.InternalMove)
        self.myList.setDefaultDropAction(Qt.MoveAction)
        self.current_mn = {}
        self.mnLed = {}
        self.mnLabel = {}
        self.mnBalance = {}
        self.btn_details = {}
        self.mnStatusLabel = {}
        self.mnStatusProgress = {}
        self.btn_remove = {}
        self.btn_edit = {}
        self.btn_start = {}
        self.btn_rewards = {}

        for masternode in self.caller.masternode_list:
            name = masternode['name']
            self.insert_mn_list(name,
                                masternode['ip'],
                                masternode['port'],
                                isHardware=masternode['isHardware'])

        vBox = QVBoxLayout()
        vBox.addWidget(self.myList)
        self.button_addMasternode = QPushButton("New Masternode")
        vBox.addWidget(self.button_addMasternode)
        vBox.stretch(1)
        self.body.setLayout(vBox)

    def insert_mn_list(self, name, ip, port, row=None, isHardware=True):
        mnRow = QWidget()
        mnRow.alias = name
        if isHardware:
            mnRow.setToolTip("Drag rows to re-order.")
        else:
            mnRow.setToolTip("EXTERNAL MASTERNODE - Drag rows to re-order.")
        mnRowLayout = QHBoxLayout()
        ##--- Led
        self.mnLed[name] = QLabel()
        self.mnLed[name].setPixmap(self.caller.ledGrayV_icon)
        mnRowLayout.addWidget(self.mnLed[name])
        ##--- Label & Balance
        self.mnLabel[name] = QLabel()
        if isHardware:
            self.mnLabel[name].setText("%s [<i>%s</i>]" % (name, ip))
        else:
            self.mnLabel[name].setText(
                "<span style='color: orange'>%s</span> [<i>%s</i>]" %
                (name, ip))
        mnRowLayout.addWidget(self.mnLabel[name])
        self.mnBalance[name] = QLabel()
        mnRowLayout.addWidget(self.mnBalance[name])
        self.mnBalance[name].hide()
        mnRowLayout.addStretch(1)
        ##--- Status Label
        self.mnStatusLabel[name] = QLabel()
        mnRowLayout.addWidget(self.mnStatusLabel[name])
        self.mnStatusLabel[name].hide()
        ##--- Rank bar
        self.mnStatusProgress[name] = QProgressBar()
        self.mnStatusProgress[name].setMaximumHeight(15)
        self.mnStatusProgress[name].setMaximumWidth(40)
        self.mnStatusProgress[name].setTextVisible(False)
        mnRowLayout.addWidget(self.mnStatusProgress[name])
        self.mnStatusProgress[name].hide()
        ##--- Details button
        self.btn_details[name] = QToolButton()
        self.btn_details[name].setIcon(self.details_icon)
        self.btn_details[name].setToolTip(
            'Check status details of masternode "%s"' % name)
        mnRowLayout.addWidget(self.btn_details[name])
        self.btn_details[name].hide()
        ##--- Rewards button
        self.btn_rewards[name] = QPushButton()
        self.btn_rewards[name].setToolTip('Transfer rewards from "%s"' % name)
        self.btn_rewards[name].setIcon(self.rewards_icon)
        self.btn_rewards[name].alias = name
        if not isHardware:
            self.btn_rewards[name].setDisabled(True)
            self.btn_rewards[name].setToolTip(
                "EXTERNAL MN: unable to move rewards with SPMT")
        mnRowLayout.addWidget(self.btn_rewards[name])
        ##--- Start button
        self.btn_start[name] = QPushButton()
        self.btn_start[name].setToolTip('Start masternode "%s"' % name)
        self.btn_start[name].setIcon(self.startMN_icon)
        self.btn_start[name].alias = name
        if not isHardware:
            self.btn_start[name].setDisabled(True)
            self.btn_start[name].setToolTip(
                "EXTERNAL MN: unable to start with SPMT")
        mnRowLayout.addWidget(self.btn_start[name])
        ##--- Edit button
        self.btn_edit[name] = QPushButton()
        self.btn_edit[name].setToolTip('Edit masternode "%s"' % name)
        self.btn_edit[name].setIcon(self.editMN_icon)
        self.btn_edit[name].alias = name
        if not isHardware:
            self.btn_edit[name].setDisabled(True)
            self.btn_edit[name].setToolTip(
                "EXTERNAL MN: to edit, delete entry and load new 'masternode.conf'"
            )
        mnRowLayout.addWidget(self.btn_edit[name])
        ##--- Remove button
        self.btn_remove[name] = QPushButton()
        self.btn_remove[name].setToolTip('Delete masternode "%s"' % name)
        self.btn_remove[name].setIcon(self.removeMN_icon)
        self.btn_remove[name].alias = name
        mnRowLayout.addWidget(self.btn_remove[name])
        ##--- Three Dots
        threeDots = QLabel()
        threeDots.setPixmap(
            self.threeDots_icon.scaledToHeight(20, Qt.SmoothTransformation))
        mnRowLayout.addWidget(threeDots)
        ##--- Set Row Layout
        mnRow.setLayout(mnRowLayout)
        ##--- Append Row
        self.current_mn[name] = QListWidgetItem()
        #self.current_mn[name].setFlags(Qt.ItemIsSelectable)
        self.current_mn[name].setSizeHint(mnRow.sizeHint())
        if row is not None:
            self.myList.insertItem(row, self.current_mn[name])
        else:
            self.myList.addItem(self.current_mn[name])
        self.myList.setItemWidget(self.current_mn[name], mnRow)

    def loadIcons(self):
        self.removeMN_icon = QIcon(
            os.path.join(self.caller.imgDir, 'icon_delete.png'))
        self.editMN_icon = QIcon(
            os.path.join(self.caller.imgDir, 'icon_edit.png'))
        self.startMN_icon = QIcon(
            os.path.join(self.caller.imgDir, 'icon_rocket.png'))
        self.rewards_icon = QIcon(
            os.path.join(self.caller.imgDir, 'icon_money.png'))
        self.details_icon = QIcon(
            os.path.join(self.caller.imgDir, 'icon_search.png'))
        self.ledgerImg = QPixmap(os.path.join(self.caller.imgDir,
                                              'ledger.png'))
        self.threeDots_icon = QPixmap(
            os.path.join(self.caller.imgDir, 'icon_3dots.png'))
Пример #31
0
class StartWindow(QWidget):
    def __init__(self, model=None):
        super().__init__()  # zwraca klase rodzica i wywoluje jego konstruktor
        self.model = model
        self.interface()

    def interface(self):

        #1-liniowe pola edycyjne
        self.featuresEdt = QLineEdit()
        self.featuresEdt.setText("1")
        self.sizeSetEdt = QLineEdit()
        self.sizeSetEdt.setText("10")
        self.paramsEdt = QLineEdit()
        self.paramsEdt.setText("1")

        # przyciski
        self.addFeaturesBtn = QPushButton("&AddFeatures", self)
        self.createSetBtn = QPushButton("&Create", self)
        self.addParamsBtn = QPushButton("Add&Params", self)
        self.findParams = QPushButton("&FindParams", self)
        self.resetBtn = QPushButton("&Reset", self)

        self.addFeaturesBtn.clicked.connect(self.addFeaturesClick)
        self.createSetBtn.clicked.connect(self.createSetClick)
        self.addParamsBtn.clicked.connect(self.addParamsClick)
        self.findParams.clicked.connect(self.findParamsClick)
        self.resetBtn.clicked.connect(self.resetClick)

        # etykiety
        self.featuresLabel = QLabel("Features: ", self)
        self.setLabel = QLabel("Set: ", self)
        self.paramsLabel = QLabel("Params: ", self)
        self.matchingLabel = QLabel("Maching: ", self)

        # ListWidget
        self.featuresListWidget = QListWidget()
        self.setWidget = QListWidget()
        self.paramsListWidget = QListWidget()
        self.findParamsListWidget = QListWidget()

        # uklad tabelaryczny:
        self.tab_layout = QGridLayout()

        self.tab_layout.addWidget(self.featuresEdt, 0, 0)
        self.tab_layout.addWidget(self.sizeSetEdt, 0, 1)
        self.tab_layout.addWidget(self.paramsEdt, 0, 2)
        self.tab_layout.addWidget(self.resetBtn, 0, 3)

        self.tab_layout.addWidget(self.addFeaturesBtn, 1, 0)
        self.tab_layout.addWidget(self.createSetBtn, 1, 1)
        self.tab_layout.addWidget(self.addParamsBtn, 1, 2)
        self.tab_layout.addWidget(self.findParams, 1, 3)

        self.tab_layout.addWidget(self.featuresLabel, 2, 0)
        self.tab_layout.addWidget(self.setLabel, 2, 1)
        self.tab_layout.addWidget(self.paramsLabel, 2, 2)
        self.tab_layout.addWidget(self.matchingLabel, 2, 3)

        self.tab_layout.addWidget(self.featuresListWidget, 3, 0)
        self.tab_layout.addWidget(self.setWidget, 3, 1)
        self.tab_layout.addWidget(self.paramsListWidget, 3, 2)
        self.tab_layout.addWidget(self.findParamsListWidget, 3, 3)

        # przypisanie utworzonego ukladu do okna

        self.setLayout(self.tab_layout)

        self.showMaximized()
        self.setWindowTitle("Projekt - dopasowanie zbiorow")
        self.show()

    def addFeaturesClick(self):
        self.model.listoffeatures.addToList(self.featuresEdt.text())
        #print(self.model.listoffeatures.list)
        l = len(self.model.listoffeatures.list) - 1
        self.featuresListWidget.insertItem(l,
                                           self.model.listoffeatures.list[-1])

    def createSetClick(self):
        self.setWidget.clear()
        self.model.set.createSet(int(self.sizeSetEdt.text()),
                                 model.listoffeatures.list)
        print(model.set.set)
        for a in model.set.set:
            self.setWidget.addItem(str(a))

    def addParamsClick(self):

        self.model.listOfParams.addToList(self.paramsEdt.text())
        # print(self.model.listoffeatures.list)
        l = len(self.model.listOfParams.list) - 1
        self.paramsListWidget.insertItem(l, self.model.listOfParams.list[-1])
        print(self.model.listOfParams.list)

    def findParamsClick(self):
        self.model.set.findParams(self.model.listOfParams.list)
        for i, a in enumerate(self.model.set.listofResults):
            self.findParamsListWidget.insertItem(i, str(a))

    def resetClick(self):
        self.model.resetmodel()
        self.clearLayout(self.tab_layout)

    def clearLayout(self, layout):
        self.featuresListWidget.clear()
        self.setWidget.clear()
        self.paramsListWidget.clear()
        self.findParamsListWidget.clear()
Пример #32
0
class composite_gui(QMainWindow):
    def __init__(self):
        super(composite_gui, self).__init__()
        self.title = 'Shadow Compositing'
        self.left, self.top = 400, 400
        self.width, self.height = 1720, 1080
        self.cutout_count = 0
        self.cur_ao_name = 'user_ao.png'

        self.init_ui()

    def init_ui(self):
        self.setWindowTitle(self.title)
        # self.setGeometry(self.left,self.top, self.width, self.height)
        # self.setFixedSize(self.width, self.height)
        self.setAcceptDrops(True)
        self.set_menu()

        # cutout layer
        self.cutout_layer = []

        # shadow layer
        self.shadow_layer = []

        # center widget
        wid = QWidget(self)
        self.setCentralWidget(wid)

        # canvas
        self.canvas = QLabel(self)
        self.canvas_img = np.ones((720, 680, 3))
        self.set_img(self.to_qt_img(self.canvas_img), self.canvas)
        # self.read_img('imgs/x.jpg', self.canvas, (1024, 1024))

        self.ibl = ibl_widget(self)
        self.light_list = QListWidget(self)
        self.light_list.itemClicked.connect(self.light_item_clicked)

        self.touch_widget = painter_widget(256, 256, self)

        # sliders
        self.shadow_intensity_label = QLabel('intensity', self)
        self.shadow_intensity_slider = QSlider(Qt.Horizontal)
        self.shadow_intensity_slider.valueChanged.connect(
            self.shadow_intensity_change)
        self.shadow_intensity_slider.setValue(99)

        self.size_label = QLabel('size', self)
        self.size_slider = QSlider(Qt.Horizontal)
        self.size_slider.valueChanged.connect(self.shadow_size_change)

        self.scale_label = QLabel('scale', self)
        self.scale_slider = QSlider(Qt.Horizontal)
        self.scale_slider.valueChanged.connect(self.shadow_scale_change)

        # buttons
        self.save_btn = QPushButton("save", self)
        self.save_btn.move(1300, self.ibl.pos().y() + self.ibl.height() + 10)
        self.save_btn.clicked.connect(self.save_result)

        # layouts
        self.canvas_group = QGroupBox("canvas", self)
        canvas_layout = QtWidgets.QHBoxLayout()
        canvas_layout.addWidget(self.canvas)
        self.canvas_group.setLayout(canvas_layout)

        control_group = QGroupBox('control', self)
        light_control_layout = QtWidgets.QVBoxLayout()
        widget_layout = QtWidgets.QHBoxLayout()
        widget_layout.addWidget(self.ibl)
        widget_layout.addWidget(self.touch_widget)
        light_control_layout.addLayout(widget_layout)
        light_control_layout.addWidget(self.light_list)
        light_control_layout.addWidget(self.shadow_intensity_label)
        light_control_layout.addWidget(self.shadow_intensity_slider)
        light_control_layout.addWidget(self.size_label)
        light_control_layout.addWidget(self.size_slider)
        light_control_layout.addWidget(self.scale_label)
        light_control_layout.addWidget(self.scale_slider)
        light_control_layout.addWidget(self.save_btn)
        control_group.setLayout(light_control_layout)

        grid = QGridLayout()
        grid.addWidget(self.canvas_group, 0, 0)
        grid.addWidget(control_group, 0, 1)
        wid.setLayout(grid)

        self.setFocusPolicy(Qt.StrongFocus)

        # init smooth mask
        h, w = 256, 256
        mask, padding = np.zeros((h, w, 1)), 5
        mask[padding:h - padding, padding:w - padding] = 1.0
        self.soft_mask = cv2.GaussianBlur(mask,
                                          (padding * 4 + 1, padding * 4 + 1),
                                          0)
        self.soft_mask = self.soft_mask[:, :, np.newaxis]

        self.init_state()
        self.show()

    def init_state(self):
        # self.add_light()
        self.show_shadow = True
        self.update_ao = True

    def set_menu(self):
        main_menu = self.menuBar()
        file_menu = main_menu.addMenu('File')

        load_canvas_button = QAction(QIcon(":/images/open.png"), 'load canvas',
                                     self)
        load_canvas_button.triggered.connect(self.load_canvas)

        load_cutout_button = QAction(QIcon(":/images/open.png"), 'load cutout',
                                     self)
        load_cutout_button.triggered.connect(self.load_cutout)

        file_menu.addAction(load_canvas_button)
        file_menu.addAction(load_cutout_button)

    def dragEnterEvent(self, e):
        e.accept()

    def dropEvent(self, e):
        e.setDropAction(Qt.MoveAction)
        e.accept()

    def dragMoveEvent(self, e):
        e.accept()
        self.cur_cutout.move(e.pos() - self.cur_cutout_offset)
        self.render_layers()

    """ Utilities
    """

    def to_qt_img(self, np_img):
        if np_img.dtype != np.uint8:
            np_img = np.clip(np_img, 0.0, 1.0)
            np_img = np_img * 255.0
            np_img = np_img.astype(np.uint8)

        h, w, c = np_img.shape
        # bytesPerLine = 3 * w
        return QImage(np_img.data, w, h, QImage.Format_RGB888)

    def read_img(self, file, label, size=None):
        if not os.path.exists(file):
            print('cannot find file', file)
            return

        img = plt.imread(file)
        if len(img.shape) == 2:
            img = np.repeat(img[:, :, np.newaxis], 3, axis=2)
        h, w, _ = img.shape

        self.canvas_img = img[:, :, :3]
        if size is not None:
            self.canvas_img = cv2.resize(img, (size[0], size[1]))
            if self.canvas_img.dtype == np.uint8:
                self.canvas_img = self.canvas_img / 255.0

        # print('self canvas: {}, {}'.format(np.min(self.canvas_img), np.max(self.canvas_img)))
        self.set_img(self.to_qt_img(self.canvas_img.copy()), label)

    def set_img(self, img, label):
        pixmap = QPixmap(img)
        label.setPixmap(pixmap)
        w, h = img.width(), img.height()
        label.adjustSize()

    def load_file(self):
        dir_path = os.path.dirname(os.path.realpath(__file__))
        # test_folder = '/home/ysheng/Documents/paper_project/adobe/failed_case/geenral_net'
        test_folder = '/home/ysheng/Documents/paper_project/adobe/soft_shadow/paper_demo/supplementary/videos/mask'
        fname = QFileDialog.getOpenFileName(self, 'Open file',
                                            os.path.join(test_folder))
        self.cur_ao_name = os.path.basename(fname[0])
        return fname[0]

    def add_cutout(self, filename):
        cutout_label = drag_img(self)
        cutout_label.set_id(self.cutout_count)
        self.cutout_count += 1

        # self.read_img(filename, cutout_label)
        cutout_label.read_img(filename)
        cutout_label.show()

        self.cutout_layer.append(cutout_label)

    def get_cutout_label(self, id):
        for label in self.cutout_layer:
            if label.get_id() == id:
                return label

        print('cannot find the label')
        return None

    def set_cur_label(self, id, offset_pos):
        self.cur_cutout = self.get_cutout_label(id)
        self.cur_cutout_offset = offset_pos

    def composite_region(self, canvas_xy, canvas_wh, xy, wh):
        canvas_xxyy = [
            canvas_xy[0] + canvas_wh[0], canvas_xy[1] + canvas_wh[1]
        ]
        xxyy = [xy[0] + wh[0], xy[1] + wh[1]]

        # com_xy, com_xxyy = canvas_xy, canvas_xxyy
        com_xy, com_xxyy = [canvas_xy[0],
                            canvas_xy[1]], [canvas_xy[0], canvas_xy[1]]
        com_xy[0] = max(canvas_xy[0], xy[0])
        com_xy[1] = max(canvas_xy[1], xy[1])
        com_xxyy[0] = min(canvas_xxyy[0], xxyy[0])
        com_xxyy[1] = min(canvas_xxyy[1], xxyy[1])

        # print('canvas xy: {}, xy: {}'.format(canvas_xy, xy))
        # print('canvas xxyy: {}, xxyy: {}'.format(canvas_xxyy, xxyy))
        # print('com xy: {}, com xxyy: {}'.format(com_xy, com_xxyy))

        canvas_region = (com_xy[1] - canvas_xy[1], com_xxyy[1] - canvas_xy[1],
                         com_xy[0] - canvas_xy[0], com_xxyy[0] - canvas_xy[0])
        widget_region = (com_xy[1] - xy[1], com_xxyy[1] - xy[1],
                         com_xy[0] - xy[0], com_xxyy[0] - xy[0])
        return canvas_region, widget_region

    def composite_layer_result(self,
                               cur_canvas,
                               xy,
                               wh,
                               composite_img,
                               composite_operator='lerp'):
        """
            input:   canvas image, composite image top-left corner xy, width and height, ...
            outout:  alpha blending compsite result
        """
        tmp = cur_canvas
        cutout_img = composite_img
        canvas_region, widget_region = self.composite_region(
            [self.canvas.pos().x(),
             self.canvas.pos().y()],
            [self.canvas.width(), self.canvas.height()], xy, wh)
        # print('canvas region: {}, h: {}, w: {}, widget region: {}, h: {}, w: {}'.format(canvas_region,
        #                                                                                 canvas_region[1],
        #                                                                                 cur_canvas.shape[1],
        #                                                                                 widget_region,
        #                                                                                 wh[1],
        #                                                                                 wh[0]))
        if composite_operator == 'lerp':
            mask = cutout_img[widget_region[0]:widget_region[1],
                              widget_region[2]:widget_region[3], 3:]
            mask = np.repeat(mask, 3, axis=2)

            tmp[canvas_region[0]:canvas_region[1], canvas_region[2]:canvas_region[3], :] = \
                (1.0 - mask) * tmp[canvas_region[0]:canvas_region[1], canvas_region[2]:canvas_region[3], :] + \
                mask * cutout_img[widget_region[0]:widget_region[1], widget_region[2]:widget_region[3], :3]
        else:
            tmp[canvas_region[0]:canvas_region[1], canvas_region[2]:canvas_region[3], :] = \
                tmp[canvas_region[0]:canvas_region[1], canvas_region[2]:canvas_region[3],:] * composite_img[widget_region[0]:widget_region[1], widget_region[2]:widget_region[3],:]

        return tmp

    def render_cutout(self, cur_canvas):
        tmp = cur_canvas
        canvas_h, canvas_w, _ = tmp.shape
        # composite result with cutout
        for cutout in self.cutout_layer:
            xy = (cutout.pos().x(), cutout.pos().y())
            wh = (cutout.width(), cutout.height())
            tmp = self.composite_layer_result(tmp, xy, wh, cutout.get_img())

        return tmp

    def render_shadow(self, cur_canvas):
        """
            Render shadow to canvas
        """
        if len(self.cutout_layer
               ) == 0 or not self.show_shadow or self.ibl.get_light_num() == 0:
            return cur_canvas

        # h x w
        ibl_np = self.ibl.get_ibl_numpy()
        ibl_np = ibl_np[:128, :]
        ibl_np = cv2.resize(ibl_np, (32, 16))
        ibl_np = cv2.flip(ibl_np, 0)

        ibl_np = np.transpose(
            np.expand_dims(cv2.resize(ibl_np, (32, 16), cv2.INTER_LINEAR),
                           axis=2), (2, 0, 1))
        if np.sum(ibl_np) > 1e-3:
            ibl_np = ibl_np * 30.0 / np.sum(ibl_np)
        ibl_np = np.repeat(ibl_np[np.newaxis, :, :, :],
                           len(self.cutout_layer),
                           axis=0)

        # convert to predict format
        if self.update_ao:
            mask_input = []
            for cutout in self.cutout_layer:
                cur_curout = cutout.get_img()  # h x w x 4
                cur_curout = cv2.resize(cur_curout, (256, 256))
                cur_curout = cur_curout[:, :, -1:]

                cur_curout = np.transpose(cur_curout, (2, 0, 1))
                mask_input.append(cur_curout)

            ao_pred = evaluation.net_pred_touch(np.array(mask_input), ibl_np)
            ao_pred = ao_pred[0]
            ao_pred = np.transpose(ao_pred, (1, 2, 0))
            save_pred = ao_pred.copy()
            cv2.normalize(save_pred, save_pred, 0.0, 1.0, cv2.NORM_MINMAX)
            save_pred = np.repeat(save_pred, 3, axis=2)
            plt.imsave('AO_pred.png', save_pred)

            self.touch_widget.update_pred(save_pred)
            self.update_ao = False

        mask_input = []
        for cutout in self.cutout_layer:
            cur_curout = cutout.get_img()  # h x w x 4
            cur_curout = cv2.resize(cur_curout, (256, 256))
            cur_curout = cur_curout[:, :, -1]
            cur_touch = self.touch_widget.get_img() * 1.3

            save_user_ao = self.touch_widget.get_img()
            plt.imsave(
                self.cur_ao_name,
                np.clip(np.repeat(save_user_ao[:, :, np.newaxis], 3, axis=2),
                        0.0, 1.0))

            print('cur cutout: {}, cur touch: {} {} {}'.format(
                cur_curout.shape, cur_touch.shape, cur_touch.min(),
                cur_touch.max()))
            inputs = np.concatenate(
                (cur_curout[:, :, np.newaxis], cur_touch[:, :, np.newaxis]),
                axis=2)
            cur_curout = np.transpose(inputs, (2, 0, 1))
            mask_input.append(cur_curout)

        # b x c x h x w
        mask_input = np.array(mask_input)

        shadow_pred = evaluation.net_render_np(mask_input, ibl_np)
        tmp = cur_canvas
        for i, shadow in enumerate(shadow_pred):
            shadow = np.transpose(shadow, (1, 2, 0))
            # print('shadow shape: ', shadow.shape)
            cv2.normalize(shadow[:, :, 0], shadow[:, :, 0], 0.0, 1.0,
                          cv2.NORM_MINMAX)

            plt.imsave("net_shadow.png", np.repeat(shadow, 3, axis=2))
            h, w = shadow.shape[0], shadow.shape[1]
            shadow = self.soft_shadow_boundary(
                shadow) * self.cur_shadow_itensity_fract
            shadow_out = np.zeros((h, w, 3))
            shadow_out[:, :,
                       0] = shadow_out[:, :,
                                       1] = shadow_out[:, :,
                                                       2] = 1.0 - shadow[:, :,
                                                                         0]
            shadow_out = cv2.resize(
                shadow_out,
                (self.cutout_layer[i].width(), self.cutout_layer[i].height()))

            # composite shadow with canvas
            xy, wh = (self.cutout_layer[i].pos().x(),
                      self.cutout_layer[i].pos().y()), (
                          self.cutout_layer[i].width(),
                          self.cutout_layer[i].height())

            tmp = self.composite_layer_result(tmp, xy, wh, shadow_out, 'prod')

        return tmp

    def soft_shadow_boundary(self, shadow_img):
        return np.clip(np.multiply(self.soft_mask, shadow_img), 0.0, 1.0)

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_A:
            print('Pressed A')
            self.add_light()
        if event.key() == Qt.Key_Space:
            self.show_shadow = self.show_shadow ^ True
            print('press space, toggle show shadow ', self.show_shadow)
            self.render_layers()
        if event.key() == Qt.Key_T:
            print("Pressed T")
            self.update_ao = True
        if event.key() == Qt.Key_C:
            print("Clear layers")
            self.cutout_count = 0
            self.cutout_layer.clear()

    #################### Actions ##############################
    @pyqtSlot()
    def load_canvas(self):
        canvas_file = self.load_file()
        print('load file', canvas_file)
        self.read_img(canvas_file, self.canvas, (1024, 1024))

    @pyqtSlot()
    def load_cutout(self):
        cutout_file = self.load_file()
        if not os.path.exists(cutout_file):
            return
        print('load file', cutout_file)
        self.add_cutout(cutout_file)
        self.render_layers()

    @pyqtSlot()
    def render_layers(self):
        if len(self.cutout_layer) == 0:
            return self.canvas_img.copy()

        # print('canvas shape: ', self.canvas_img.shape)

        shadow_canvas = self.render_shadow(
            self.canvas_img.copy())  # render to cutout layers
        shadow_canvas = self.render_cutout(
            shadow_canvas)  # composite cutout with canvas
        self.set_img(self.to_qt_img(shadow_canvas), self.canvas)
        return shadow_canvas

    @pyqtSlot()
    def save_result(self):
        # get save file name
        dir_path = os.path.dirname(os.path.realpath(__file__))
        save_fname = QFileDialog.getSaveFileName(
            self, 'Open file', os.path.join(dir_path, 'output'))
        print(save_fname)

        # layer results
        out_img = self.render_layers()
        if plt.imsave(save_fname[0], out_img):
            print('file {} saved succeed'.format(save_fname[0]))
        else:
            print('file {} save fail'.format(save_fname[0]))

        # shadow layers
        white_back = np.ones(self.canvas_img.shape)
        shadow_layer = self.render_shadow(white_back)

        shadow_out_fanme = 'shadow_' + os.path.basename(save_fname[0])

        if plt.imsave(
                os.path.join(os.path.dirname(save_fname[0]), shadow_out_fanme),
                shadow_layer):
            print('file {} saved succeed'.format(save_fname[0]))
        else:
            print('file {} save fail'.format(save_fname[0]))

    def light_item_clicked(self, item):
        # self.ibl.set_cur_ibl()
        cur_ibl = self.light_list.currentRow()
        self.update_list(cur_ibl)

    @pyqtSlot()
    def add_light(self):
        self.ibl.add_light()
        self.update_list(self.ibl.get_light_num() - 1)

    @pyqtSlot()
    def update_list(self, cur_ibl):
        self.light_list.clear()
        light_num = self.ibl.get_light_num()
        for i in range(light_num):
            self.light_list.insertItem(i, 'light {}'.format(i))

        self.light_list.setCurrentRow(cur_ibl)
        self.ibl.set_cur_light(cur_ibl)

        if cur_ibl >= 0:
            radius, scale = self.ibl.get_cur_light_state()
            self.set_slider_state(radius, scale)
        else:
            self.set_slider_state(0.008, 0)

    def set_slider_state(self, radius, scale):
        size_value = (radius - SIZE_MIN) / (1 - SIZE_MIN) * 99.0
        self.size_slider.setValue(int(size_value))

        scale_value = scale * 99.0
        self.scale_slider.setValue(scale_value)

    @pyqtSlot()
    def shadow_intensity_change(self):
        self.cur_shadow_itensity_fract = self.shadow_intensity_slider.value(
        ) / 99.0
        self.render_layers()

    @pyqtSlot()
    def shadow_scale_change(self):
        fract = self.scale_slider.value() / 99.0
        self.ibl.set_cur_scale(fract)

    @pyqtSlot()
    def shadow_size_change(self):
        fract = self.size_slider.value() / 99.0
        radius = (1.0 - fract) * SIZE_MIN + fract * SIZE_MAX
        self.ibl.set_cur_size(radius)
Пример #33
0
class StringListDlg(QDialog):

    def __init__(self, name, stringlist=None, parent=None):
        super(StringListDlg, self).__init__(parent)

        self.name = name

        self.listWidget = QListWidget()
        if stringlist is not None:
            self.listWidget.addItems(stringlist)
            self.listWidget.setCurrentRow(0)
        buttonLayout = QVBoxLayout()
        for text, slot in (("&Add...", self.add),
                           ("&Edit...", self.edit),
                           ("&Remove...", self.remove),
                           ("&Up", self.up),
                           ("&Down", self.down),
                           ("&Sort", self.listWidget.sortItems),
                           ("Close", self.accept)):
            button = QPushButton(text)
            if not MAC:
                button.setFocusPolicy(Qt.NoFocus)
            if text == "Close":
                buttonLayout.addStretch()
            buttonLayout.addWidget(button)
            button.clicked.connect(slot)
#            self.connect(button, SIGNAL("clicked()"), slot)
        layout = QHBoxLayout()
        layout.addWidget(self.listWidget)
        layout.addLayout(buttonLayout)
        self.setLayout(layout)
        self.setWindowTitle("Edit {0} List".format(self.name))


    def add(self):
        row = self.listWidget.currentRow()
        title = "Add {0}".format(self.name)
        string, ok = QInputDialog.getText(self, title, title)
        if ok and string is not None:
            self.listWidget.insertItem(row, string)


    def edit(self):
        row = self.listWidget.currentRow()
        item = self.listWidget.item(row)
        if item is not None:
            title = "Edit {0}".format(self.name)
            string, ok = QInputDialog.getText(self, title, title,
                    QLineEdit.Normal, item.text())
            if ok and string is not None:
                item.setText(string)


    def remove(self):
        row = self.listWidget.currentRow()
        item = self.listWidget.item(row)
        if item is None:
            return
        reply = QMessageBox.question(self, "Remove {0}".format(
                self.name), "Remove {0} `{1}'?".format(
                self.name, unicode(item.text())),
                QMessageBox.Yes|QMessageBox.No)
        if reply == QMessageBox.Yes:
            item = self.listWidget.takeItem(row)
            del item


    def up(self):
        row = self.listWidget.currentRow()
        if row >= 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(row - 1, item)
            self.listWidget.setCurrentItem(item)


    def down(self):
        row = self.listWidget.currentRow()
        if row < self.listWidget.count() - 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(row + 1, item)
            self.listWidget.setCurrentItem(item)


    def reject(self):
        self.accept()


    def accept(self):
        self.stringlist = QStringListModel().stringList()
        for row in range(self.listWidget.count()):
            self.stringlist.append(self.listWidget.item(row).text())
        #self.stringlist.acceptedList.emit(self.stringlist)
        QDialog.accept(self)
Пример #34
0
class CityListDlg(QDialog):
    citieslist_signal = pyqtSignal([list])

    def __init__(self, citylist, accurate_url, appid, parent=None):
        super(CityListDlg, self).__init__(parent)
        self.citylist = citylist
        self.accurate_url = accurate_url
        self.appid = appid
        self.listWidget = QListWidget()
        self.listWidget.addItems(self.citylist)
        buttonLayout = QVBoxLayout()
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.buttonBox.rejected.connect(self.reject)
        self.buttonBox.accepted.connect(self.accept)
        layoutT = QVBoxLayout()
        layout = QHBoxLayout()
        layout.addWidget(self.listWidget)
        layout.addLayout(buttonLayout)
        for text, slot in ((self.tr("&Add..."), self.add),
                           (self.tr("&Remove..."), self.remove),
                           (self.tr("&Up"), self.up),
                           (self.tr("&Down"), self.down),
                           (self.tr("De&fault"), self.default),
                           (self.tr("&Sort"), self.listWidget.sortItems)):
            button = QPushButton(text)
            buttonLayout.addWidget(button)
            button.clicked.connect(slot)
        buttonLayout.addWidget(self.buttonBox)
        self.status = QLabel()
        layoutT.addLayout(layout)
        layoutT.addWidget(self.status)
        self.setLayout(layoutT)
        self.checklength()

    def add(self):
        self.status.setText('')
        lista = []
        newitem = ''
        self.citytoadd = ''
        self.countrytoadd = ''
        self._idtoadd = ''
        dialog = searchcity.SearchCity(self.accurate_url, self.appid, self)
        dialog.id_signal.connect(self.addcity)
        dialog.city_signal.connect(self.addcity)
        dialog.country_signal.connect(self.addcity)
        if dialog.exec_() == 1:
            newitem = (self.citytoadd + '_' + self.countrytoadd + '_' +
                       self._idtoadd)
            for row in range(self.listWidget.count()):
                lista.append(self.listWidget.item(row).text())
            if newitem in lista:
                self.status.setText(QCoreApplication.translate('Status bar message',
                                    'The city already exists in the list', 'Cities list dialogue'))
                return
            else:
                self.listWidget.addItem(newitem)
                self.checklength()

    def addcity(self, what):
        self.status.setText('')
        if what[0] == 'ID':
            self._idtoadd = what[1]
        elif what[0] == 'City':
            self.citytoadd = what[1]
        elif what[0] == 'Country':
            self.countrytoadd = what[1]

    def remove(self):
        self.status.setText('')
        if self.listWidget.count() == 0:
            self.status.setText(self.tr('The list is empty'))
            return
        row = self.listWidget.currentRow()
        item = self.listWidget.item(row)
        if item is None:
            return
        message = self.tr('The city "{0}" has been removed').format(
            self.listWidget.item(row).text())
        item = self.listWidget.takeItem(row)
        del item
        self.status.setText(message)

    def up(self):
        self.status.setText('')
        row = self.listWidget.currentRow()
        if row >= 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(row - 1, item)
            self.listWidget.setCurrentItem(item)

    def down(self):
        self.status.setText('')
        row = self.listWidget.currentRow()
        if row < self.listWidget.count() - 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(row + 1, item)
            self.listWidget.setCurrentItem(item)

    def default(self):
        self.status.setText('')
        row = self.listWidget.currentRow()
        if row >= 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(0, item)
            self.listWidget.setCurrentItem(item)

    def checklength(self):
        listtosend = []
        for row in range(self.listWidget.count()):
            listtosend.append(self.listWidget.item(row).text())
        if len(listtosend) == 0:
            return
        self.listWidget.setMinimumWidth(self.listWidget.sizeHintForColumn(0))

    def accept(self):
        listtosend = []
        for row in range(self.listWidget.count()):
            listtosend.append(self.listWidget.item(row).text())
        self.citieslist_signal[list].emit(listtosend)
        QDialog.accept(self)
Пример #35
0
class CityListDlg(QDialog):
    citieslist_signal = pyqtSignal([list])
    citiesdict_signal = pyqtSignal([dict])

    def __init__(
        self, citylist, accurate_url, appid, trans_cities_dict, parent=None
    ):
        super(CityListDlg, self).__init__(parent)
        self.settings = QSettings()
        self.citylist = citylist
        self.trans_cities_dict = trans_cities_dict
        self.accurate_url = accurate_url
        self.appid = appid
        self.listWidget = QListWidget()
        self.listWidget.itemDoubleClicked.connect(self.translate)
        cities_list = []
        for i in self.citylist:
            cities_list.append(self.trans_cities_dict.get(i, i))
        self.listWidget.addItems(cities_list)
        buttonLayout = QVBoxLayout()
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel
        )
        self.buttonBox.rejected.connect(self.reject)
        self.buttonBox.accepted.connect(self.accept)
        layoutT = QVBoxLayout()
        layout = QHBoxLayout()
        layout.addWidget(self.listWidget)
        layout.addLayout(buttonLayout)
        for text, slot in ((self.tr("&Add..."), self.add),
                           (self.tr("&Remove..."), self.remove),
                           (self.tr("&Up"), self.up),
                           (self.tr("&Down"), self.down),
                           (self.tr("De&fault"), self.default),
                           (self.tr("&Sort"), self.listWidget.sortItems)):
            button = QPushButton(text)
            buttonLayout.addWidget(button)
            button.clicked.connect(slot)
        self.translate_button = QPushButton(
            QCoreApplication.translate(
                'Button',
                '&Translate',
                'Edit cities name'
            )
        )
        buttonLayout.addWidget(self.translate_button)
        self.translate_button.clicked.connect(self.translate)
        buttonLayout.addWidget(self.buttonBox)
        self.status = QLabel()
        layoutT.addLayout(layout)
        layoutT.addWidget(self.status)
        self.setLayout(layoutT)
        self.setWindowTitle(
            QCoreApplication.translate(
                'Window title',
                'Cities',
                'Cities list dialogue'
            )
        )
        self.checklength()

    def add(self):
        self.status.setText('')
        lista = []
        newitem = ''
        self.citytoadd = ''
        self.countrytoadd = ''
        self._idtoadd = ''
        dialog = searchcity.SearchCity(self.accurate_url, self.appid, self)
        dialog.id_signal.connect(self.addcity)
        dialog.city_signal.connect(self.addcity)
        dialog.country_signal.connect(self.addcity)
        if dialog.exec_() == 1:
            newitem = (
                self.citytoadd + '_' + self.countrytoadd
                + '_' + self._idtoadd
            )
            for row in range(self.listWidget.count()):
                lista.append(self.listWidget.item(row).text())
            if newitem in lista:
                self.status.setText(
                    QCoreApplication.translate(
                        'Status bar message',
                        'The city already exists in the list',
                        'Cities list dialogue'
                    )
                )
                return
            else:
                self.listWidget.addItem(newitem)
                self.checklength()
                self.status.setText(
                    'ℹ ' + QCoreApplication.translate(
                        'Status bar message',
                        'Toggle cities with mouse scroll on the weather window',
                        'Cities list dialogue'
                    )
                )

    def addcity(self, what):
        self.status.setText('')
        if what[0] == 'ID':
            self._idtoadd = what[1]
        elif what[0] == 'City':
            self.citytoadd = what[1]
        elif what[0] == 'Country':
            self.countrytoadd = what[1]

    def remove(self):
        self.status.setText('')
        if self.listWidget.count() == 1:
            self.status.setText(
                QCoreApplication.translate(
                    'Message when trying to remove the'
                    'last and unique city in the list',
                    'This is the default city !',
                    'Cities list dialogue'
                )
            )
            return
        row = self.listWidget.currentRow()
        item = self.listWidget.item(row)
        if item is None:
            return
        message = self.tr('The city "{0}" has been removed').format(
            self.listWidget.item(row).text())
        item = self.listWidget.takeItem(row)
        del item
        self.status.setText(message)

    def up(self):
        self.status.setText('')
        row = self.listWidget.currentRow()
        if row >= 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(row - 1, item)
            self.listWidget.setCurrentItem(item)

    def down(self):
        self.status.setText('')
        row = self.listWidget.currentRow()
        if row < self.listWidget.count() - 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(row + 1, item)
            self.listWidget.setCurrentItem(item)

    def default(self):
        self.status.setText('')
        row = self.listWidget.currentRow()
        if row >= 1:
            item = self.listWidget.takeItem(row)
            self.listWidget.insertItem(0, item)
            self.listWidget.setCurrentItem(item)

    def checklength(self):
        if self.listWidget.count() == 1:
            # After adding the first city the entry is not activated
            self.listWidget.setCurrentRow(0)
        if self.listWidget.count() > 0:
            self.translate_button.setEnabled(True)
            self.listWidget.setMinimumWidth(
                self.listWidget.sizeHintForColumn(0)
            )
        else:
            self.translate_button.setEnabled(False)

    def translate(self):
        city = self.listWidget.currentItem().text()
        dialog = citytranslate.CityTranslate(
            city, self.trans_cities_dict, self
        )
        dialog.city_signal.connect(self.current_translation)
        if dialog.exec_() == 1:
            row = self.listWidget.currentRow()
            item = self.listWidget.takeItem(row)
            del item
            self.listWidget.insertItem(row, self.current_translated_city)
            self.listWidget.setCurrentRow(row)

    def current_translation(self, translated_city):
        for city, translated in translated_city.items():
            if translated == '':
                translated = city
            self.trans_cities_dict[city] = translated
            self.current_translated_city = translated

    def accept(self):
        listtosend = []
        for row in range(self.listWidget.count()):
            city = self.find_city_key(self.listWidget.item(row).text())
            listtosend.append(city)
        if self.listWidget.count() == 0:
            return
        self.citieslist_signal[list].emit(listtosend)
        self.citiesdict_signal[dict].emit(self.trans_cities_dict)
        QDialog.accept(self)

    def find_city_key(self, city):
        for key, value in self.trans_cities_dict.items():
            if value == city:
                return key
        return city