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]
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