示例#1
0
class DocumentViewManager(QMainWindow):
    """
    MDI area for displaying supporting documents within a given context e.g.
    supporting documents for a specific household based on the lifetime of the
    'SourceDocumentManager' instance.
    """
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setWindowFlags(Qt.Window)

        self._mdi_area = QMdiArea()
        self._mdi_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self._mdi_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self._mdi_area)
        # set the size of mid_area and DocumentViewManager based on the
        # screen size.
        screen = QDesktopWidget().availableGeometry()
        self._mdi_area.resize(screen.width() - 30, screen.height() - 80)
        self.resize(self._mdi_area.size())
        self._mdi_area.subWindowActivated.connect(self.update_actions)
        self._viewer_mapper = QSignalMapper(self)
        self._viewer_mapper.mapped[QWidget].connect(self.set_active_sub_window)

        win_title = QApplication.translate(
            "DocumentViewManager",
            "Document Viewer"
        )
        self.setWindowTitle(win_title)
        self.setUnifiedTitleAndToolBarOnMac(True)
        self.statusBar().showMessage(
            QApplication.translate(
                "DocumentViewManager",
                "Ready"
            )
        )
        self._doc_viewers = {}

        self._create_menu_actions()
        self.update_actions()

    def center(self):
        """
        Move the Document viewer to the center of the screen.
        """
        # Get the current screens' dimensions...
        screen = QDesktopWidget().availableGeometry()
        # ... and get this windows' dimensions
        mdi_area_size = self.frameGeometry()
        # The horizontal position
        hpos = (screen.width() - mdi_area_size.width()) / 2
        # vertical position
        vpos = (screen.height() - mdi_area_size.height()) / 2
        # repositions the window
        self.move(hpos, vpos)

    def _create_menu_actions(self):
        self._window_menu = self.menuBar().addMenu(
            QApplication.translate(
                "DocumentViewManager","&Windows"))

        self._close_act = QAction(
            QApplication.translate("DocumentViewManager",
                                                         "Cl&ose"), self)
        self._close_act.setStatusTip(
            QApplication.translate("DocumentViewManager",
                                   "Close the active document viewer"))
        self._close_act.triggered.connect(self._mdi_area.closeActiveSubWindow)

        self._close_all_act = QAction(QApplication.translate(
            "DocumentViewManager",
            "Close &All"), self
        )
        self._close_all_act.setStatusTip(
            QApplication.translate("DocumentViewManager",
                                   "Close all the document viewers")
        )
        self._close_all_act.triggered.connect(
            self._mdi_area.closeAllSubWindows
        )

        self._tile_act = QAction(QApplication.translate(
            "DocumentViewManager",
            "&Tile"), self
        )
        self._tile_act.setStatusTip(
            QApplication.translate("DocumentViewManager",
                                   "Tile the document viewers"))
        self._tile_act.triggered.connect(self.tile_windows)

        self._cascade_act = QAction(QApplication.translate(
            "DocumentViewManager",
            "&Cascade"), self)
        self._cascade_act.setStatusTip(QApplication.translate(
            "DocumentViewManager",
            "Cascade the document viewers"))
        self._cascade_act.triggered.connect(self.cascade_windows)

        self._next_act = QAction(QApplication.translate(
            "DocumentViewManager",
            "Ne&xt"), self)
        self._next_act.setStatusTip(
            QApplication.translate(
                "DocumentViewManager",
                "Move the focus to the next document viewer"
            )
        )
        self._next_act.triggered.connect(self._mdi_area.activateNextSubWindow)

        self._previous_act = QAction(QApplication.translate(
            "DocumentViewManager",
            "Pre&vious"), self)
        self._previous_act.setStatusTip(
            QApplication.translate(
                "DocumentViewManager",
                "Move the focus to the previous document viewer"
            )
        )
        self._previous_act.triggered.connect(
            self._mdi_area.activatePreviousSubWindow
        )

        self._separator_act = QAction(self)
        self._separator_act.setSeparator(True)

        self.update_window_menu()
        self._window_menu.aboutToShow.connect(self.update_window_menu)

    def cascade_windows(self):
        #Cascade document windows
        self._mdi_area.cascadeSubWindows()

    def tile_windows(self):
        #Arrange document windows to occupy the available space in mdi area
        self._mdi_area.tileSubWindows()

    def update_actions(self):
        if self._mdi_area.activeSubWindow():
            has_mdi_child = True

        else:
            has_mdi_child = False

        self._close_act.setEnabled(has_mdi_child)
        self._close_all_act.setEnabled(has_mdi_child)
        self._tile_act.setEnabled(has_mdi_child)
        self._cascade_act.setEnabled(has_mdi_child)
        self._previous_act.setEnabled(has_mdi_child)
        self._next_act.setEnabled(has_mdi_child)
        self._separator_act.setVisible(has_mdi_child)

    def update_window_menu(self):
        self._window_menu.clear()
        self._window_menu.addAction(self._close_act)
        self._window_menu.addAction(self._close_all_act)
        self._window_menu.addSeparator()
        self._window_menu.addAction(self._tile_act)
        self._window_menu.addAction(self._cascade_act)
        self._window_menu.addSeparator()
        self._window_menu.addAction(self._next_act)
        self._window_menu.addAction(self._previous_act)
        self._window_menu.addAction(self._separator_act)

        windows = self._mdi_area.subWindowList()
        self._separator_act.setVisible(len(windows) != 0)

        for i, window in enumerate(windows):
            text = "%d. %s" % (i + 1, window.windowTitle())

            win_action = self._window_menu.addAction(text)
            win_action.setCheckable(True)
            win_action.setChecked(window is self._mdi_area.activeSubWindow())
            win_action.triggered.connect(self._viewer_mapper.map)
            self._viewer_mapper.setMapping(win_action, window)

    def load_viewer(self, document_widget, visible=True):
        """
        Open a new instance of the viewer or activate an existing one if the
        document had been previously loaded.
        :param document_widget: Contains all the necessary information required
        to load the specific document.
        :type document_widget: DocumentWidget
        :param visible: True to show the view manager after the viewer has
        been loaded, otherwise it will be the responsibility of the caller to
        enable visibility.
        :type visible: bool
        :returns: True if the document was successfully loaded, else False.
        :rtype: bool
        """
        doc_identifier = document_widget.file_identifier()

        if doc_identifier in self._doc_viewers:

            doc_sw = self._doc_viewers[doc_identifier]

            self._mdi_area.setActiveSubWindow(doc_sw)
            doc_sw.showNormal()

        else:
            doc_viewer = self._create_viewer(document_widget)

            abs_doc_path = self.absolute_document_path(document_widget)

            if not QFile.exists(abs_doc_path):
                msg = QApplication.translate(
                    "DocumentViewManager",
                    "The selected document does not exist."
                    "\nPlease check the supporting documents' "
                    "repository setting."
                )
                QMessageBox.critical(
                    self,
                    QApplication.translate(
                        "DocumentViewManager","Invalid Document"
                    ),
                    msg
                )

                return False

            doc_viewer.load_document(abs_doc_path)

            self._doc_viewers[doc_identifier] = doc_viewer

            self._mdi_area.addSubWindow(doc_viewer)

            doc_viewer.show()

        if not self.isVisible() and visible:
            self.setVisible(True)

        if self.isMinimized():
            self.showNormal()

        self.center()

        return True

    def set_active_sub_window(self, viewer):
        if viewer:
            self._mdi_area.setActiveSubWindow(viewer)

    def absolute_document_path(self, document_widget):
        """
        Build the absolute document path using info from the document widget.
        :param document_widget: Instance of document widget.
        :return: Absolute path of the supporting document.
        :rtype: str
        """
        abs_path = ''

        file_manager = document_widget.fileManager
        if not file_manager is None:
            network_repository = file_manager.networkPath
            file_id = document_widget.file_identifier()
            source_entity = document_widget.doc_source_entity()
            profile_name = current_profile().name
            doc_type = document_widget.doc_type_value().lower().replace(
                ' ', '_'
            )
            file_name, file_extension = guess_extension(
                document_widget.displayName()
            )

            abs_path = network_repository + "/" +profile_name + '/' +\
                       unicode(source_entity) + "/" + unicode(doc_type) + "/" +\
                       unicode(file_id) + unicode(file_extension)

        return abs_path

    def reset(self):
        """
        Removes all document viewers in the view area.
        The QCloseEvent sent to each sub-window will decrement the register.
        """
        self._mdi_area.closeAllSubWindows()

    def _create_viewer(self, document_widget):
        """
        Creates a new instance of a document viewer.
        :param document_widget: Contains all
        the necessary information required
        to load the specific document.
        :return: Document viewer object
        :rtype: DocumentViewer
        """
        doc_viewer = DocumentViewer(
            self._mdi_area, document_widget.file_identifier()
        )
        doc_viewer.setAttribute(Qt.WA_DeleteOnClose)
        doc_viewer.setWindowTitle(
            document_widget.displayName()
        )

        # TODO: Incorporate logic for determining
        # TODO: viewer based on document type
        ph_viewer = PhotoViewer()

        # v_layout = QVBoxLayout()
        # v_layout.addWidget(ph_viewer)
        # doc_viewer.setLayout(v_layout)

        doc_viewer.set_view_widget(ph_viewer)

        doc_viewer.closed.connect(self._on_viewer_closed)

        return doc_viewer

    def remove_viewer(self, viewer_id):
        """
        Close and remove the viewer with the specified viewer ID.
        """
        if viewer_id in self._doc_viewers:
            viewer = self._doc_viewers[viewer_id]
            self._mdi_area.setActiveSubWindow(viewer)
            self._mdi_area.closeActiveSubWindow()

        self._on_viewer_closed(viewer_id)

    def _on_viewer_closed(self,file_id):
        """
        Slot raised when a document viewer is closed.
        """
        if file_id in self._doc_viewers:
            del self._doc_viewers[file_id]
示例#2
0
class Environment(QWidget):
	def __init__(self, port, parent=None):
		QWidget.__init__(self, parent=parent)
		self.port = port

		self.sharedMemory = {}
		memFilePath = '{}.mem'.format(port)
		if os.path.isfile(memFilePath):
			try:
				with open(memFilePath) as f:
					self.sharedMemory = pickle.load(f)
					sys.stdout.write(u"[INFO] Wczytano zapisaną pamięć.\n", name=port)
			except:
				sys.stdout.write(u"[BŁĄD] Błąd odczytywania pamięci. Resetuję!\n", name=port)

		#self.sharedMemory = SharedDict(self.sharedMemory)

		try:
			self.client = Client(port)
		except:
			#print "Brak połączenia z serwerem!"
			#self.client = None
			raise NoServerConnection()

		self.workerThread = None
		self.uiUpdateEvent = threading.Event()

		self.snippetQueue = []

		self.context = {}
		self.context['mem'] = self.sharedMemory
		self.context['active'] = None
		self.context['client'] = self.client # TODO: polaczenie z klientem

		self.timer = QTimer()
		self.timer.setInterval(0)
		self.timer.timeout.connect(self.tick)
		self.timer.start()

		self.actions = []
		self.setupUI()

		# Autoload modules
		#for modulePath in filter(lambda x: x[-3:]=='.py', os.listdir('..')):
		for modulePath in [ x for x in os.listdir('..') if x[-3:] == '.py' ]:
			self.strategies.load(os.path.join("..", modulePath))

	def setupUI(self):
		self.setWindowTitle("%d" % self.port)
		self.mdi = QMdiArea()
		self.mdi.setHorizontalScrollBarPolicy( Qt.ScrollBarAsNeeded )
		self.mdi.setVerticalScrollBarPolicy( Qt.ScrollBarAsNeeded )

		self.inter = Interpreter(self.context)
		self.mdi.addSubWindow(self.inter,
							Qt.WindowTitleHint |
							Qt.WindowMinimizeButtonHint |
							Qt.WindowMaximizeButtonHint |
							Qt.WindowMaximized)

		#self.mdi.addSubWindow(FileBrowser())

		# Dock windows

		self.strategies = Strategies()

		#stratDock = QDockWidget("Strategies", self)
		#stratDock.setWidget(self.strategies)
		#self.addDockWidget(Qt.RightDockWidgetArea, stratDock)

		# Actions
		newDocIcon = QIcon(QPixmap("img/newdoc.png"))
		playIcon = QIcon(QPixmap("img/Play.png"))

		newSnippetAction = QAction(newDocIcon, "Nowy skrawek", self)
		newSnippetAction.setShortcut('F1')
		self.actions.append(newSnippetAction)
		runSnippetAction = QAction(playIcon, "Uruchom skrawek", self)
		runSnippetAction.setShortcut('F9')
		self.actions.append(runSnippetAction)

		layout = QHBoxLayout()
		layout.addWidget(self.mdi)
		layout.addWidget(self.strategies)

		self.setLayout(layout)

		# Connecting
		QWidget.connect(self.strategies, SIGNAL('strategyChanged'), self.strategyChanged)
		QWidget.connect(newSnippetAction, SIGNAL('triggered()'), self.newSnippet)
		QWidget.connect(runSnippetAction, SIGNAL('triggered()'), self.runSnippet)

	def strategyChanged(self, old, new):
		if old != None:
			with output(self.port, True): old.remove()
			self.workerThread.work = False
			self.workerThread.join()  # wait for QThread
			self.workerThread = None
			if hasattr(old, '__widget__'):
				self.mdi.removeSubWindow(old.__widget__.parent())
			self.tick()

		self.context['active'] = new

		if new:
			with output(self.port): print "Starting new worker..."
			widget = QWidget()
			widget.setWindowTitle(new.name())
			self.mdi.addSubWindow(widget,
							Qt.WindowTitleHint |
							Qt.WindowMinimizeButtonHint |
							Qt.WindowMaximizeButtonHint |
							Qt.WindowMaximized)
			new.__widget__ = widget
			new.mem = self.sharedMemory
			new.widget = widget
			new.client = self.client

			try:
				with output(self.port): new.install()
			except:
				traceback.print_exc()

			widget.parent().adjustSize()

			self.workerThread = WorkerThread(self.client, new, self.uiUpdateEvent)
			self.workerThread.daemon = True
			self.workerThread.start()

	# czyta stdout dla danego interpretera i robi update GUI
	def tick(self):
		if self.context['active'] and self.uiUpdateEvent.isSet():
			self.uiUpdateEvent.clear()
			with output(self.port, True): self.context['active'].updateUI()


		data = sys.stdout.getOutput(self.port)
		if data:
			count = len( self.inter.out.toPlainText().split('\n') ) - 100
			if count > 0:
				cursor = self.inter.out.textCursor()
				cursor.movePosition( QTextCursor.Start )
				cursor.movePosition( QTextCursor.Down, QTextCursor.KeepAnchor, count)
				cursor.removeSelectedText()

			self.inter.write(data)

	def newSnippet(self):
		w = SnippetEditor()
		QWidget.connect(w, SIGNAL('codeOutput'), self.inter.write)
		self.mdi.addSubWindow(w)
		w.show()

	def runSnippet(self):
		w = self.mdi.activeSubWindow().widget()
		if hasattr(w, 'runCode') and callable(w.runCode):
			w.runCode(self.context)

	def queueSnippet(self):
		w = self.mdi.activeSubWindow().widget()
		if hasattr(w, 'runCode') and callable(w.runCode):
			self.workerThread.snippetQueue.append( (w, self.context) )

	def renameSnippet(self, title):
		#print self.mdi.activeSubWindow().widget()
		if self.mdi.activeSubWindow():
			self.mdi.activeSubWindow().setWindowTitle(title)
		#if hasattr(w, 'runCode') and callable(w.runCode):

	def cleanup(self):
		self.client.close()
		if self.workerThread is not None:
			self.workerThread.work = False