def popup_menu(self, position): selected_row = self.view.rowAt(position.y()) if selected_row >= 0 and self._used_categories and len( self._used_categories) > 1: category_menu = QMenu(_("Categories")) selected_doc = self.model.object_at(selected_row) category_actions = [] for category in self._used_categories: a = QAction(category.full_name, category_menu) a.setData(category) a.setEnabled(selected_doc.document_category_id != category.document_category_id) category_menu.addAction(a) category_actions.append(a) action = category_menu.exec_(QCursor.pos()) if action: new_category = action.data() if selected_doc.document_category_id != new_category.document_category_id: selected_doc.document_category_id = new_category.document_category_id self.model.signal_object_change(selected_doc)
def on_show_supported_type(self): node_types = sorted( [n_type for (n_type, nice, attr) in MTTSettings.SUPPORTED_TYPE] + MTTSettings.UNSUPPORTED_TYPE) support_info = self.sender() support_info.clear() for node_type in node_types: current = QAction(node_type, self) current.setEnabled(False) current.setCheckable(True) current.setChecked(node_type not in MTTSettings.UNSUPPORTED_TYPE) support_info.addAction(current)
def on_show_supported_type(self): node_types = sorted( [n_type for (n_type, nice, attr) in MTTSettings.SUPPORTED_TYPE] + MTTSettings.UNSUPPORTED_TYPE) support_info = self.sender() support_info.clear() for node_type in node_types: current = QAction(node_type, self) current.setEnabled(False) current.setCheckable(True) current.setChecked(node_type not in MTTSettings.UNSUPPORTED_TYPE) support_info.addAction(current)
class ChatWindow(QMainWindow): """ The chat application window. """ def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.chat_widget = ChatWidget(self) self.setCentralWidget(self.chat_widget) # set up all actions self.chat_widget.message.connect(self.statusBar().showMessage) app_menu = self.menuBar().addMenu('&Application') self.connect_action = QAction('&Connect', self) self.connect_action.triggered.connect(self._connect) self.connect_action.setShortcut('Ctrl+C') app_menu.addAction(self.connect_action) app_menu.addSeparator() self.quit_server_action = QAction('Quit &server', self) self.quit_server_action.triggered.connect(self._quit_server) self.quit_server_action.setEnabled(False) self.quit_server_action.setShortcut('Ctrl+D') app_menu.addAction(self.quit_server_action) quit_action = QAction( self.style().standardIcon(QStyle.SP_DialogCloseButton), '&Quit', self) quit_action.triggered.connect(QApplication.instance().quit) quit_action.setShortcut('Ctrl+Q') app_menu.addAction(quit_action) # attempt to connect self._connect() def _quit_server(self): if self.chat_widget.connected: self.chat_widget.send_text('quit') def _connect(self): # connect to a server if not self.chat_widget.connected: self.chat_widget.connection = QTcpSocket() # upon connection, disable the connect action, and enable the # quit server action self.chat_widget.connection.connected.connect( partial(self.quit_server_action.setEnabled, True)) self.chat_widget.connection.connected.connect( partial(self.connect_action.setDisabled, True)) # to the reverse thing upon disconnection self.chat_widget.connection.disconnected.connect( partial(self.connect_action.setEnabled, True)) self.chat_widget.connection.disconnected.connect( partial(self.quit_server_action.setDisabled, True)) # connect to the chat server self.chat_widget.connection.connectToHost(HOST_ADDRESS, PORT)
class ChatWindow(QMainWindow): """ The chat application window. """ def __init__(self, parent=None): QMainWindow.__init__(self, parent) self.chat_widget = ChatWidget(self) self.setCentralWidget(self.chat_widget) # set up all actions self.chat_widget.message.connect(self.statusBar().showMessage) app_menu = self.menuBar().addMenu('&Application') self.connect_action = QAction('&Connect', self) self.connect_action.triggered.connect(self._connect) self.connect_action.setShortcut('Ctrl+C') app_menu.addAction(self.connect_action) app_menu.addSeparator() self.quit_server_action = QAction('Quit &server', self) self.quit_server_action.triggered.connect(self._quit_server) self.quit_server_action.setEnabled(False) self.quit_server_action.setShortcut('Ctrl+D') app_menu.addAction(self.quit_server_action) quit_action = QAction(self.style().standardIcon( QStyle.SP_DialogCloseButton), '&Quit', self) quit_action.triggered.connect(QApplication.instance().quit) quit_action.setShortcut('Ctrl+Q') app_menu.addAction(quit_action) # attempt to connect self._connect() def _quit_server(self): if self.chat_widget.connected: self.chat_widget.send_text('quit') def _connect(self): # connect to a server if not self.chat_widget.connected: self.chat_widget.connection = QTcpSocket() # upon connection, disable the connect action, and enable the # quit server action self.chat_widget.connection.connected.connect( partial(self.quit_server_action.setEnabled, True)) self.chat_widget.connection.connected.connect( partial(self.connect_action.setDisabled, True)) # to the reverse thing upon disconnection self.chat_widget.connection.disconnected.connect( partial(self.connect_action.setEnabled, True)) self.chat_widget.connection.disconnected.connect( partial(self.quit_server_action.setDisabled, True)) # connect to the chat server self.chat_widget.connection.connectToHost(HOST_ADDRESS, PORT)
def populate_menu( menu, action_target, list_actions, context=Qt.WindowShortcut): """ action_target is a QWidget where the menu's action can be added so that they are callable from there """ global configuration global user_session for t in list_actions: # t = (Text, Slot to call, KeySequence shortcut, roles which can use the action) # t = (QAction, roles which can use the action) # if QAction then slot, KeySequence will be ignored roles = a = None if isinstance( t[0], QAction): a = t[0] roles = t[1] if a.parent() is None: action_target.addAction(a) elif isinstance( t[0], QMenu): a = t[0] roles = t[1] else: a = QAction(t[0],action_target) # text, parent if t[1]: a.triggered.connect(t[1]) if t[2]: a.setShortcut(t[2]) a.setShortcutContext(context) roles = t[3] action_target.addAction(a) if roles is not None: a.setEnabled(user_session.has_any_roles(roles)) if isinstance( a, QMenu): menu.addMenu(a) else: menu.addAction(a)
def createAction(self, icon, toolTip, statusTip, scripted=False): """ TOWRITE :param `icon`: TOWRITE :type `icon`: QString :param `toolTip`: TOWRITE :type `toolTip`: QString :param `statusTip`: TOWRITE :type `statusTip`: QString :param `scripted`: TOWRITE :type `scripted`: bool :rtype: `QAction`_ .. TODO:: send the global Icon, Image, Commands Dirs in to be used. """ connect = self.connect # NOT local optimization, but for ease of the code looking similar to the C++ whash mdiArea = self.mdiArea # ditto ACTION = QAction( QIcon(self.gIconDir + os.sep + self.getSettingsGeneralIconTheme() + "/" + icon + ".png"), toolTip, self ) # QAction * # TODO: Qt4.7 wont load icons without an extension... ACTION.setStatusTip(statusTip) ACTION.setObjectName(icon) # TODO: Set What's This Context Help to statusTip for now so there is some infos there. # Make custom whats this context help popup with more descriptive help than just # the status bar/tip one liner(short but not real long) with a hyperlink in the custom popup # at the bottom to open full help file description. Ex: like wxPython AGW's SuperToolTip. ACTION.setWhatsThis(statusTip) # TODO: Finish All Commands ... <.< if icon == "donothing": connect(ACTION, SIGNAL("triggered()"), self, SLOT("doNothing()")) elif icon == "new": ACTION.setShortcut(QKeySequence.New) connect(ACTION, SIGNAL("triggered()"), self, SLOT("newFile()")) elif icon == "open": ACTION.setShortcut(QKeySequence.Open) connect(ACTION, SIGNAL("triggered()"), self, SLOT("openFile()")) elif icon == "save": ACTION.setShortcut(QKeySequence.Save) connect(ACTION, SIGNAL("triggered()"), self, SLOT("savefile()")) elif icon == "saveas": ACTION.setShortcut(QKeySequence.SaveAs) connect(ACTION, SIGNAL("triggered()"), self, SLOT("saveasfile()")) elif icon == "print": ACTION.setShortcut(QKeySequence.Print) connect(ACTION, SIGNAL("triggered()"), self, SLOT("print_()")) elif icon == "designdetails": ACTION.setShortcut(QKeySequence("Ctrl+D")) connect(ACTION, SIGNAL("triggered()"), self, SLOT("designDetails()")) elif icon == "exit": ACTION.setShortcut(QKeySequence("Ctrl+Q")) connect(ACTION, SIGNAL("triggered()"), self, SLOT("exit()")) elif icon == "cut": ACTION.setShortcut(QKeySequence.Cut) connect(ACTION, SIGNAL("triggered()"), self, SLOT("cut()")) elif icon == "copy": ACTION.setShortcut(QKeySequence.Copy) connect(ACTION, SIGNAL("triggered()"), self, SLOT("copy()")) elif icon == "paste": ACTION.setShortcut(QKeySequence.Paste) connect(ACTION, SIGNAL("triggered()"), self, SLOT("paste()")) elif icon == "windowcascade": connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("cascade()")) elif icon == "windowtile": connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("tile()")) elif icon == "windowclose": ACTION.setShortcut(QKeySequence.Close) connect(ACTION, SIGNAL("triggered()"), self, SLOT("onCloseWindow()")) elif icon == "windowcloseall": connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("closeAllSubWindows()")) elif icon == "windownext": ACTION.setShortcut(QKeySequence.NextChild) connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("activateNextSubWindow()")) elif icon == "windowprevious": ACTION.setShortcut(QKeySequence.PreviousChild) connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("activatePreviousSubWindow()")) elif icon == "help": connect(ACTION, SIGNAL("triggered()"), self, SLOT("help()")) elif icon == "changelog": connect(ACTION, SIGNAL("triggered()"), self, SLOT("changelog()")) elif icon == "tipoftheday": connect(ACTION, SIGNAL("triggered()"), self, SLOT("tipOfTheDay()")) elif icon == "about": connect(ACTION, SIGNAL("triggered()"), self, SLOT("about()")) elif icon == "whatsthis": connect(ACTION, SIGNAL("triggered()"), self, SLOT("whatsThisContextHelp()")) elif icon == "icon16": connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon16()")) elif icon == "icon24": connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon24()")) elif icon == "icon32": connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon32()")) elif icon == "icon48": connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon48()")) elif icon == "icon64": connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon64()")) elif icon == "icon128": connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon128()")) elif icon == "settingsdialog": connect(ACTION, SIGNAL("triggered()"), self, SLOT("settingsDialog()")) elif icon == "undo": connect(ACTION, SIGNAL("triggered()"), self, SLOT("undo()")) elif icon == "redo": connect(ACTION, SIGNAL("triggered()"), self, SLOT("redo()")) elif icon == "makelayercurrent": connect(ACTION, SIGNAL("triggered()"), self, SLOT("makeLayerActive()")) elif icon == "layers": connect(ACTION, SIGNAL("triggered()"), self, SLOT("layerManager()")) elif icon == "layerprevious": connect(ACTION, SIGNAL("triggered()"), self, SLOT("layerPrevious()")) elif icon == "textbold": ACTION.setCheckable(True) connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextBold(bool)")) elif icon == "textitalic": ACTION.setCheckable(True) connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextItalic(bool)")) elif icon == "textunderline": ACTION.setCheckable(True) connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextUnderline(bool)")) elif icon == "textstrikeout": ACTION.setCheckable(True) connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextStrikeOut(bool)")) elif icon == "textoverline": ACTION.setCheckable(True) connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextOverline(bool)")) elif icon == "zoomrealtime": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomRealtime()")) elif icon == "zoomprevious": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomPrevious()")) elif icon == "zoomwindow": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomWindow()")) elif icon == "zoomdynamic": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomDynamic()")) elif icon == "zoomscale": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomScale()")) elif icon == "zoomcenter": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomCenter()")) elif icon == "zoomin": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomIn()")) elif icon == "zoomout": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomOut()")) elif icon == "zoomselected": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomSelected()")) elif icon == "zoomall": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomAll()")) elif icon == "zoomextents": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomExtents()")) elif icon == "panrealtime": connect(ACTION, SIGNAL("triggered()"), self, SLOT("panrealtime()")) elif icon == "panpoint": connect(ACTION, SIGNAL("triggered()"), self, SLOT("panpoint()")) elif icon == "panleft": connect(ACTION, SIGNAL("triggered()"), self, SLOT("panLeft()")) elif icon == "panright": connect(ACTION, SIGNAL("triggered()"), self, SLOT("panRight()")) elif icon == "panup": connect(ACTION, SIGNAL("triggered()"), self, SLOT("panUp()")) elif icon == "pandown": connect(ACTION, SIGNAL("triggered()"), self, SLOT("panDown()")) elif icon == "day": connect(ACTION, SIGNAL("triggered()"), self, SLOT("dayVision()")) elif icon == "night": connect(ACTION, SIGNAL("triggered()"), self, SLOT("nightVision()")) elif scripted: ACTION.setIcon( QIcon(self.gAppDir + os.sep + "commands/" + icon + "/" + icon + ".png")) connect(ACTION, SIGNAL("triggered()"), self, SLOT("runCommand()")) else: ACTION.setEnabled(False) connect(ACTION, SIGNAL("triggered()"), self, SLOT("stub_implement()")) return ACTION
def contextMenuEvent(self, event): """ Handles the ``contextMenuEvent`` event for :class:`StatusBarButton`. :param `event`: A `QContextMenuEvent`_ to be processed. """ QApplication.setOverrideCursor(Qt.ArrowCursor) menu = QMenu(self) objName = self.objectName() themeDir = gIconDir + os.sep + '..' + os.sep + self.mainWin.getSettingsGeneralIconTheme( ) + os.sep s = "&Settings..." if objName == "StatusBarButtonSNAP": settingsSnapAction = QAction( QIcon(themeDir + "gridsnapsettings.png"), s, menu) settingsSnapAction.triggered.connect(self.settingsSnap) menu.addAction(settingsSnapAction) elif objName == "StatusBarButtonGRID": settingsGridAction = QAction(QIcon(themeDir + "gridsettings.png"), s, menu) settingsGridAction.triggered.connect(self.settingsGrid) menu.addAction(settingsGridAction) elif objName == "StatusBarButtonRULER": settingsRulerAction = QAction( QIcon(themeDir + "rulersettings.png"), s, menu) settingsRulerAction.triggered.connect(self.settingsRuler) menu.addAction(settingsRulerAction) elif objName == "StatusBarButtonORTHO": settingsOrthoAction = QAction( QIcon(themeDir + "orthosettings.png"), s, menu) settingsOrthoAction.triggered.connect(self.settingsOrtho) menu.addAction(settingsOrthoAction) elif objName == "StatusBarButtonPOLAR": settingsPolarAction = QAction( QIcon(themeDir + "polarsettings.png"), s, menu) settingsPolarAction.triggered.connect(self.settingsPolar) menu.addAction(settingsPolarAction) elif objName == "StatusBarButtonQSNAP": settingsQSnapAction = QAction( QIcon(themeDir + "qsnapsettings.png"), s, menu) settingsQSnapAction.triggered.connect(self.settingsQSnap) menu.addAction(settingsQSnapAction) elif objName == "StatusBarButtonQTRACK": settingsQTrackAction = QAction( QIcon(themeDir + "qtracksettings.png"), s, menu) settingsQTrackAction.triggered.connect(self.settingsQTrack) menu.addAction(settingsQTrackAction) elif objName == "StatusBarButtonLWT": gview = self.mainWin.activeView() if gview: enableRealAction = QAction(QIcon(themeDir + "realrender.png"), "&RealRender On", menu) enableRealAction.setEnabled(not gview.isRealEnabled()) enableRealAction.triggered.connect(self.enableReal) menu.addAction(enableRealAction) disableRealAction = QAction(QIcon(themeDir + "realrender.png"), "&RealRender Off", menu) disableRealAction.setEnabled(gview.isRealEnabled()) disableRealAction.triggered.connect(self.disableReal) menu.addAction(disableRealAction) settingsLwtAction = QAction( QIcon(themeDir + "lineweightsettings" + ".png"), s, menu) settingsLwtAction.triggered.connect(self.settingsLwt) menu.addAction(settingsLwtAction) menu.exec_(event.globalPos()) QApplication.restoreOverrideCursor() self.statusbar.clearMessage()
class MainWindow(QMainWindow): start_acq = Signal(str) start_rec = Signal(str) collect_frame = Signal(object) collect_threshed = Signal(object) def __init__(self, parent=None): ''' sets up the whole main window ''' #standard init super(MainWindow, self).__init__(parent) #set the window title self.setWindowTitle('Open Ephys Control GUI') self.window_height = 700 self.window_width = 1100 self.screen2 = QDesktopWidget().screenGeometry(0) self.move( self.screen2.left() + (self.screen2.width() - self.window_width) / 2., self.screen2.top() + (self.screen2.height() - self.window_height) / 2.) self.get_info() self.noinfo = True while self.noinfo: loop = QEventLoop() QTimer.singleShot(500., loop.quit) loop.exec_() subprocess.Popen('start %s' % open_ephys_path, shell=True) self.collect_frame.connect(self.update_frame) self.collect_threshed.connect(self.update_threshed) self.acquiring = False self.recording = False self.video_height = self.window_height * .52 self.video_width = self.window_width * .48 self.resize(self.window_width, self.window_height) #create QTextEdit window 'terminal' for receiving stdout and stderr self.terminal = QTextEdit(self) #set the geometry self.terminal.setGeometry( QRect(self.window_width * .02, self.window_height * .15 + self.video_height, self.video_width * .96, 150)) #make widgets self.setup_video_frames() self.setup_thresh_buttons() self.overlay = True #create thread and worker for video processing self.videoThread = QThread(self) self.videoThread.start() self.videoproc_worker = VideoWorker(self) self.videoproc_worker.moveToThread(self.videoThread) self.vt_file = None """""" """""" """""" """""" """""" """""" """""" """ set up menus """ """""" """""" """""" """""" """""" """""" """""" #create a QMenuBar and set geometry self.menubar = QMenuBar(self) self.menubar.setGeometry( QRect(0, 0, self.window_width * .5, self.window_height * .03)) #set the QMenuBar as menu bar for main window self.setMenuBar(self.menubar) #create a QStatusBar statusbar = QStatusBar(self) #set it as status bar for main window self.setStatusBar(statusbar) #create icon toolbar with default image iconToolBar = self.addToolBar("iconBar.png") #create a QAction for the acquire button self.action_Acq = QAction(self) #make it checkable self.action_Acq.setCheckable(True) #grab an icon for the button acq_icon = self.style().standardIcon(QStyle.SP_MediaPlay) #set the icon for the action self.action_Acq.setIcon(acq_icon) #when the button is pressed, call the Acquire function self.action_Acq.triggered.connect(self.Acquire) #create a QAction for the record button self.action_Record = QAction(self) #make it checkable self.action_Record.setCheckable(True) #grab an icon for the button record_icon = self.style().standardIcon(QStyle.SP_DialogYesButton) #set the icon for the action self.action_Record.setIcon(record_icon) #when the button is pressed, call advanced_settings function self.action_Record.triggered.connect(self.Record) #create QAction for stop button action_Stop = QAction(self) #grab close icon stop_icon = self.style().standardIcon(QStyle.SP_MediaStop) #set icon for action action_Stop.setIcon(stop_icon) #when button pressed, close window action_Stop.triggered.connect(self.Stop) #show tips for each action in the status bar self.action_Acq.setStatusTip("Start acquiring") self.action_Record.setStatusTip("Start recording") action_Stop.setStatusTip("Stop acquiring/recording") #add actions to icon toolbar iconToolBar.addAction(self.action_Acq) iconToolBar.addAction(self.action_Record) iconToolBar.addAction(action_Stop) # self.sort_button = QPushButton('Sort Now',self) # self.sort_button.setGeometry(QRect(self.window_width*.85,0,self.window_width*.15,self.window_height*.05)) # self.sort_button.clicked.connect(self.sort_now) #show the window if minimized by windows self.showMinimized() self.showNormal() """""" """""" """""" """""" """""" """""" """""" """""" """""" """""" "" """""" """""" """""" """""" """""" """""" """""" """""" """""" """""" "" #this function acts as a slot to accept 'message' signal @Slot(str) def print_message(self, message): ''' print stdout and stderr to terminal window ''' #move terminal cursor to end self.terminal.moveCursor(QTextCursor.End) #write message to terminal self.terminal.insertPlainText(message) def setup_thresh_buttons(self): ''' set up buttons for overlay/clearing thresh view ''' self.button_frame = QFrame(self) self.button_frame.setGeometry( QRect(self.window_width * .52, self.window_height * .13 + self.video_height, self.video_width * .98, 50)) button_layout = QHBoxLayout() self.button_frame.setLayout(button_layout) self.clear_button = QPushButton('Clear') self.overlay_button = QPushButton('Overlay') button_layout.addWidget(self.clear_button) button_layout.addWidget(self.overlay_button) self.clear_button.setEnabled(False) self.clear_button.clicked.connect(self.clear_threshed) self.overlay_button.setEnabled(False) self.overlay_button.clicked.connect(self.overlay_threshed) def setup_video_frames(self): ''' set up spots for playing video frames ''' filler_frame = np.zeros((360, 540, 3)) filler_frame = qimage2ndarray.array2qimage(filler_frame) self.raw_frame = QFrame(self) self.raw_label = QLabel() self.raw_label.setText('raw') self.raw_frame.setGeometry( QRect(self.window_width * .01, self.window_height * .15, self.video_width, self.video_height)) self.raw_frame raw_layout = QVBoxLayout() self.raw_frame.setLayout(raw_layout) raw_layout.addWidget(self.raw_label) self.threshed_frame = QFrame(self) self.threshed_label = QLabel() self.threshed_label.setText('Threshed') self.threshed_frame.setGeometry( QRect(self.window_width * .51, self.window_height * .15, self.video_width, self.video_height)) threshed_layout = QVBoxLayout() self.threshed_frame.setLayout(threshed_layout) threshed_layout.addWidget(self.threshed_label) self.label_frame = QFrame(self) self.label_frame.setGeometry( QRect(self.window_width * .01, self.window_height * .11, self.video_width * 2, 50)) self.label_rawlabel = QLabel() self.label_rawlabel.setText('Raw Video') self.label_threshedlabel = QLabel() self.label_threshedlabel.setText('Threshold View') label_layout = QHBoxLayout() self.label_frame.setLayout(label_layout) label_layout.addWidget(self.label_rawlabel) label_layout.addWidget(self.label_threshedlabel) self.raw_label.setPixmap(QPixmap.fromImage(filler_frame)) self.threshed_label.setPixmap(QPixmap.fromImage(filler_frame)) def Acquire(self): if self.action_Acq.isChecked(): self.vidbuffer = [] if self.recording: while 1: try: self.sock.send('StopRecord') self.sock.recv() except: continue break self.recording = False else: #create and start a thread to transport a worker to later self.workerThread = QThread(self) self.workerThread.start() #create a worker object based on Worker class and move it to our #worker thread self.worker = Worker(self) self.worker.moveToThread(self.workerThread) try: self.start_acq.disconnect() except: pass while 1: try: self.sock.send('StartAcquisition') self.sock.recv() except: continue break self.acquiring = True self.start_acq.connect(self.worker.acquire) self.start_acq.emit('start!') self.action_Acq.setEnabled(False) self.action_Record.setChecked(False) self.action_Record.setEnabled(True) record_icon = self.style().standardIcon(QStyle.SP_DialogYesButton) #set the icon for the action self.action_Record.setIcon(record_icon) def Record(self): if self.action_Record.isChecked(): if not self.acquiring: self.workerThread = QThread(self) self.workerThread.start() self.worker = Worker(self) self.worker.moveToThread(self.workerThread) try: self.start_rec.disconnect() except: pass while 1: try: self.sock.send('StartAcquisition') self.sock.recv() except: continue break while 1: try: self.sock.send('StartRecord') self.sock.recv() except: continue break self.vidbuffer = [] self.start_rec.connect(self.worker.acquire) self.recording = True self.start_rec.emit('start!') else: while 1: try: self.sock.send('StartRecord') self.sock.recv() except: continue break self.vidbuffer = [] self.recording = True record_icon = self.style().standardIcon(QStyle.SP_DialogNoButton) #set the icon for the action self.action_Record.setIcon(record_icon) self.action_Record.setEnabled(False) self.action_Acq.setChecked(False) self.action_Acq.setEnabled(True) def Stop(self): self.acquiring = False self.recording = False while 1: try: self.sock.send('isRecording') rec = self.sock.recv() except: continue break if rec == '1': while 1: try: self.sock.send('StopRecord') self.sock.recv() except: continue break self.action_Record.setEnabled(True) self.action_Record.setChecked(False) while 1: try: self.sock.send('isAcquiring') acq = self.sock.recv_string() except: continue break if acq == '1': while 1: try: self.sock.send('StopAcquisition') self.sock.recv() except: continue break self.action_Acq.setEnabled(True) self.action_Acq.setChecked(False) try: #open a csv file for saving tracking data with open(self.vt_file, 'a') as csvfile: #create a writer vidwriter = csv.writer(csvfile, dialect='excel-tab') #check if it's an empty file for row in self.vidbuffer: vidwriter.writerow(row) except: pass record_icon = self.style().standardIcon(QStyle.SP_DialogYesButton) #set the icon for the action self.action_Record.setIcon(record_icon) def update_frame(self, image): self.raw_label.setPixmap(QPixmap.fromImage(image)) def update_threshed(self, threshed_image): self.threshed_label.setPixmap(QPixmap.fromImage(threshed_image)) def clear_threshed(self): self.green_frame = np.zeros_like(self.green_frame) self.red_frame = np.zeros_like(self.red_frame) def overlay_threshed(self): if self.overlay: self.overlay = False elif not self.overlay: self.overlay = True # def sort_now(self): # # if self.recdir is not None: # os.chdir('./kilosort_control') # #create and show the main window # self.sort_frame = kilosort_control.sort_gui.MainWindow() # self.sort_frame.show() # # #set up stream for stdout and stderr based on outputStream class # self.outputStream = kilosort_control.sort_gui.outputStream() # #when outputStream sends messages, connect to appropriate function for # #writing to terminal window # self.outputStream.message.connect(self.sort_frame.print_message) # # #connect stdout and stderr to outputStream # sys.stdout = self.outputStream # sys.stderr = self.outputStream # # self.sort_frame.run_now(self.recdir) # # self.close() def get_info(self): self.info_window = QWidget() self.info_window.resize(400, 350) #set title self.info_window.setWindowTitle('Session Info') #give layout info_layout = QVBoxLayout(self.info_window) with open('info_fields.pickle', 'rb') as f: default_fields = pickle.load(f) f.close() #set label for pic_resolution setting experimenter_label = QLabel('Experimenter:') #make a QLineEdit box for displaying/editing settings experimenter = QComboBox(self.info_window) experimenter.setEditable(True) experimenter.addItems(default_fields['experimenter']) #add label and box to current window info_layout.addWidget(experimenter_label) info_layout.addWidget(experimenter) #set label for pic_resolution setting whose_animal_label = QLabel('Whose animal?') #make a QLineEdit box for displaying/editing settings whose_animal = QComboBox(self.info_window) whose_animal.setEditable(True) whose_animal.addItems(default_fields['whose_animal']) #add label and box to current window info_layout.addWidget(whose_animal_label) info_layout.addWidget(whose_animal) animal_number_label = QLabel('Animal number:') animal_number = QComboBox(self.info_window) animal_number.setEditable(True) animal_number.addItems(default_fields['animal_number']) info_layout.addWidget(animal_number_label) info_layout.addWidget(animal_number) session_number_label = QLabel('Session number:') session_number = QTextEdit(self.info_window) session_number.setText('1') info_layout.addWidget(session_number_label) info_layout.addWidget(session_number) session_type_label = QLabel('Session type:') session_type = QComboBox(self.info_window) session_type.setEditable(True) session_type.addItems(default_fields['session_type']) info_layout.addWidget(session_type_label) info_layout.addWidget(session_type) def save_info(self): info_fields = {} info_fields['experimenter'] = [ experimenter.itemText(i) for i in range(experimenter.count()) ] info_fields['whose_animal'] = [ whose_animal.itemText(i) for i in range(whose_animal.count()) ] info_fields['animal_number'] = [ animal_number.itemText(i) for i in range(animal_number.count()) ] info_fields['session_type'] = [ session_type.itemText(i) for i in range(session_type.count()) ] with open('info_fields.pickle', 'wb') as f: pickle.dump(info_fields, f, protocol=2) f.close() current_experimenter = str(experimenter.currentText()) current_whose_animal = str(whose_animal.currentText()) current_animal_number = str(animal_number.currentText()) current_session_number = str(session_number.toPlainText()) current_session_type = str(session_type.currentText()) recdir = data_save_dir + current_whose_animal + '/' + current_animal_number if not os.path.exists(recdir): os.makedirs(recdir) self.experiment_info = '###### Experiment Info ######\r\n' self.experiment_info += 'Experimenter: %s\r\n' % current_experimenter self.experiment_info += 'Whose animal? %s\r\n' % current_whose_animal self.experiment_info += 'Animal number: %s\r\n' % current_animal_number self.experiment_info += 'Session number: %s\r\n' % current_session_number self.experiment_info += 'Session type: %s\r\n' % current_session_type self.experiment_info = self.experiment_info.encode() config_file = config_path + '/' + current_animal_number + '.xml' if not os.path.exists(config_file): shutil.copy(default_config, config_file) tree = et.parse(config_file) root = tree.getroot() for child in root: if child.tag == 'CONTROLPANEL': child.attrib['recordPath'] = recdir.replace('/', '\\') tree.write(config_file) tree.write(default_config) self.info_window.close() self.noinfo = False ready_button = QPushButton('Ready!') ready_button.clicked.connect(lambda: save_info(self)) info_layout.addWidget(ready_button) self.info_window.show()
class STMainWindow(QMainWindow): def __init__(self): super(STMainWindow, self).__init__() self.createActions() self.createMenus() layout = QVBoxLayout() self.tabs = QTabWidget() self.tabs.setTabPosition(QTabWidget.West) self.tabs.currentChanged[int].connect(self.tabChanged) self.sessiontab = sweattrails.qt.sessiontab.SessionTab(self) self.tabs.addTab(self.sessiontab, "Sessions") self.tabs.addTab(sweattrails.qt.fitnesstab.FitnessTab(self), "Fitness") self.tabs.addTab(sweattrails.qt.profiletab.ProfileTab(self), "Profile") self.usertab = sweattrails.qt.usertab.UserTab(self) self.tabs.addTab(self.usertab, "Users") self.usertab.hide() layout.addWidget(self.tabs) w = QWidget(self) w.setLayout(layout) self.setCentralWidget(w) self.statusmessage = QLabel() self.statusmessage.setMinimumWidth(200) self.statusBar().addPermanentWidget(self.statusmessage) self.progressbar = QProgressBar() self.progressbar.setMinimumWidth(100) self.progressbar.setMinimum(0) self.progressbar.setMaximum(100) self.statusBar().addPermanentWidget(self.progressbar) self.setWindowTitle("SweatTrails") self.setWindowIconText("SweatTrails") icon = QPixmap("image/sweatdrops.png") self.setWindowIcon(QIcon(icon)) QCoreApplication.instance().refresh.connect(self.userSet) def createActions(self): self.switchUserAct = QAction("&Switch User", self, shortcut = "Ctrl+U", statusTip = "Switch User", triggered = self.switch_user) self.importFileAct = QAction("&Import", self, shortcut = "Ctrl+I", statusTip = "Import Session", triggered = self.file_import) self.downloadAct = QAction("&Download", self, shortcut = "Ctrl+D", statusTip = "Download activities from device", triggered = QCoreApplication.instance().download) self.downloadAct = QAction("&Withings", self, statusTip = "Download Withings data", triggered = QCoreApplication.instance().withings) self.exitAct = QAction("E&xit", self, shortcut = "Ctrl+Q", statusTip = "Exit SweatTrails", triggered = self.close) self.aboutAct = QAction("&About", self, triggered = self.about) self.aboutQtAct = QAction("About &Qt", self, triggered = QApplication.aboutQt) def createMenus(self): self.fileMenu = self.menuBar().addMenu(self.tr("&File")) self.fileMenu.addAction(self.switchUserAct) self.fileMenu.addSeparator() self.fileMenu.addAction(self.importFileAct) self.fileMenu.addAction(self.downloadAct) self.fileMenu.addSeparator() self.fileMenu.addAction(self.exitAct) self.menuBar().addSeparator() self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutQtAct) def show(self): super(QMainWindow, self).show() if self.select_user(): t = sweattrails.qt.imports.BackgroundThread.get_thread() t.jobStarted.connect(self.status_message) t.jobFinished.connect(self.status_message) t.jobError.connect(self.status_message) else: self.close() def switch_user(self): pass def select_user(self): ret = False if QCoreApplication.instance().user: return True elif QCoreApplication.instance().has_users(): dialog = SelectUser(self) dialog.select() ret = QCoreApplication.instance().is_authenticated() if ret: self.refresh() else: dialog = CreateUser(self) dialog.exec_() ret = QCoreApplication.instance().is_authenticated() if ret: self.refresh() return ret # # FILE IMPORT # def file_import(self): (fileNames, _) = QFileDialog.getOpenFileNames(self, "Open Activity File", "", "Activity Files (*.tcx *.fit *.csv)") if fileNames: QCoreApplication.instance().import_files(*fileNames) def file_import_started(self, filename): self.switchUserAct.setEnabled(False) def file_imported(self, filename): self.switchUserAct.setEnabled(True) self.refresh() def file_import_error(self, filename, msg): self.switchUserAct.setEnabled(True) self.refresh() # # END FILE IMPORT # # ===================================================================== # S I G N A L H A N D L E R S # ===================================================================== def refresh(self): QCoreApplication.instance().refresh.emit() self.status_message("") def tabChanged(self, tabix): w = self.tabs.currentWidget() if hasattr(w, "activate"): w.activate(0) if hasattr(w, "setValues"): w.setValues() def setSession(self, session): self.tabs.setCurrentIndex(0) self.sessiontab.setSession(session) def setTab(self, tab): t = self.tabs.currentWidget() if t and hasattr(t, "setTab"): t.setTab(tab) def userSet(self): user = QCoreApplication.instance().user if user.is_admin(): self.usertab.show() def status_message(self, msg, *args): self.statusmessage.setText(msg.format(*args)) def progress_init(self, msg, *args): self.progressbar.setValue(0) self.status_message(msg, *args) def progress(self, percentage): self.progressbar.setValue(percentage) def progress_done(self): self.progressbar.reset() def about(self): QMessageBox.about(self, "About SweatTrails", "SweatTrails is a training log application")
class MainWindow(QtGui.QMainWindow): """The application's main window """ FILE_FILTER = "inselect files (*{0})".format(InselectDocument.EXTENSION) def __init__(self, app, filename=None): super(MainWindow, self).__init__() self.app = app # Boxes view self.view_graphics_item = GraphicsItemView() # self.boxes_view is a QGraphicsView, not a QAbstractItemView self.boxes_view = BoxesView(self.view_graphics_item.scene) # Metadata view self.view_specimen = SpecimenView() self.view_metadata = MetadataView() self.specimens = QtGui.QSplitter() self.specimens.addWidget(self.view_specimen) self.specimens.addWidget(self.view_metadata.widget) self.specimens.setSizes([600, 300]) # Views in tabs self.tabs = QtGui.QTabWidget(self) self.tabs.addTab(self.boxes_view, 'Boxes') self.tabs.addTab(self.specimens, 'Specimens') self.tabs.setCurrentIndex(0) # Summary view self.view_summary = SummaryView() # Main window layout layout = QtGui.QVBoxLayout() layout.addWidget(self.view_summary.widget) layout.addWidget(self.tabs) box = QtGui.QWidget() box.setLayout(layout) self.setCentralWidget(box) # Document self.document = None self.document_path = None # Model self.model = Model() self.view_graphics_item.setModel(self.model) self.view_specimen.setModel(self.model) self.view_metadata.setModel(self.model) self.view_summary.setModel(self.model) # A consistent selection across all views sm = self.view_specimen.selectionModel() self.view_graphics_item.setSelectionModel(sm) self.view_metadata.setSelectionModel(sm) self.view_summary.setSelectionModel(sm) # Plugins self.plugins = [SegmentPlugin, SubsegmentPlugin, BarcodePlugin] self.plugin_actions = len(self.plugins) * [None] # QActions self.plugin_image = None self.plugin_image_visible = False # Long-running operations are run in their own thread. self.running_operation = None self.create_actions() self.create_menus() # Conect signals self.tabs.currentChanged.connect(self.current_tab_changed) sm.selectionChanged.connect(self.selection_changed) # Filter events self.tabs.installEventFilter(self) self.boxes_view.installEventFilter(self) self.view_specimen.installEventFilter(self) self.view_metadata.installEventFilter(self) self.empty_document() self.setAcceptDrops(True) if filename: self.open_file(filename) def eventFilter(self, obj, event): if event.type() in (QEvent.DragEnter, QEvent.Drop): return True else: return super(MainWindow, self).eventFilter(obj, event) @report_to_user def open_file(self, path=None): """Opens path, which can be None, the path to an inselect document or the path to an image file. If None, the user is prompted to select a file. * If a .inselect file, the file is opened * If an image file for which a .inselect document already exists, the .inselect file is opened * If a _thumbnail.jpg file corresponding to an existing .inselect file, the .inselect file is opened * If an image file, a new .inselect file is created and opened """ debug_print(u'MainWindow.open_file [{0}]'.format(path)) if not path: folder = QSettings().value( 'working_directory', QDesktopServices.storageLocation( QDesktopServices.DocumentsLocation)) filter = u'Inselect documents (*{0});;Images ({1})' filter = filter.format(InselectDocument.EXTENSION, u' '.join(IMAGE_PATTERNS)) path, selectedFilter = QtGui.QFileDialog.getOpenFileName( self, "Open", folder, filter) if path: # Will be None if user cancelled getOpenFileName if not self.close_document(): # User does not want to close the existing document pass else: path = Path(path) if path.suffix in IMAGE_SUFFIXES: # Compute the path to the inselect document (which may or # may not already exist) of the image file doc_of_image = path.name.replace( InselectDocument.THUMBNAIL_SUFFIX, u'') doc_of_image = path.parent / doc_of_image doc_of_image = doc_of_image.with_suffix( InselectDocument.EXTENSION) else: doc_of_image = None if InselectDocument.EXTENSION == path.suffix: # Open the .inselect document debug_print('Opening inselect document [{0}]'.format(path)) self.open_document(path) elif doc_of_image and doc_of_image.is_file(): # An image file corresponding to an existing .inselect file msg = u'Opening inselect document [{0}] of thumbnail [{1}]' debug_print(msg.format(doc_of_image, path)) self.open_document(doc_of_image) elif path.suffix in IMAGE_SUFFIXES: msg = u'Creating new inselect document for image [{0}]' debug_print(msg.format(path)) self.new_document(path) else: raise InselectError('Unknown file type [{0}]'.format(path)) def new_document(self, path): """Creates and opens a new inselect document for the scanned image given in path """ debug_print('MainWindow.new_document [{0}]'.format(path)) path = Path(path) if not path.is_file(): raise InselectError( u'Image file [{0}] does not exist'.format(path)) else: # Callable for worker thread class NewDoc(object): def __init__(self, image): self.image = image def __call__(self, progress): progress('Creating thumbnail of scanned image') doc = ingest_image(self.image, self.image.parent) self.document_path = doc.document_path self.run_in_worker(NewDoc(path), 'New document', self.new_document_finished) def new_document_finished(self, operation): """Called when new_document worker has finished """ debug_print('MainWindow.new_document_finished') document_path = operation.document_path QSettings().setValue('working_directory', str(document_path.parent)) self.open_file(document_path) msg = u'New Inselect document [{0}] created in [{1}]' msg = msg.format(document_path.stem, document_path.parent) QMessageBox.information(self, "Document created", msg) def open_document(self, path): """Opens the inselect document given by path """ debug_print('MainWindow.open_document [{0}]'.format(path)) path = Path(path) document = InselectDocument.load(path) QSettings().setValue("working_directory", str(path.parent)) self.document = document self.document_path = path self.model.from_document(self.document) # TODO LH Prefer setWindowFilePath to setWindowTitle? self.setWindowTitle(u"Inselect [{0}]".format(self.document_path.stem)) self.sync_ui() @report_to_user def save_document(self): """Saves the document """ debug_print('MainWindow.save_document') items = [] self.model.to_document(self.document) self.document.save() self.model.clear_modified() @report_to_user def save_crops(self): """Saves cropped specimen images """ debug_print('MainWindow.save_crops') res = QMessageBox.Yes existing_crops = self.document.crops_dir.is_dir() if existing_crops: msg = 'Overwrite the existing cropped specimen images?' res = QMessageBox.question(self, 'Write cropped specimen images?', msg, QMessageBox.No, QMessageBox.Yes) if QMessageBox.Yes == res: def save_crops(progress): progress('Loading full-resolution scanned image') self.document.scanned.array progress('Saving crops') self.document.save_crops(progress) def completed(operation): QMessageBox.information(self, "Crops saved", msg) self.model.to_document(self.document) msg = "{0} crops saved in {1}" msg = msg.format(self.document.n_items, self.document.crops_dir) self.run_in_worker(save_crops, 'Save crops', completed) @report_to_user def export_csv(self): debug_print('MainWindow.export_csv') path = self.document.document_path.with_suffix('.csv') res = QMessageBox.Yes existing_csv = path.is_file() if existing_csv: msg = 'Overwrite the existing CSV file?' res = QMessageBox.question(self, 'Export CSV file?', msg, QMessageBox.No, QMessageBox.Yes) if QMessageBox.Yes == res: self.model.to_document(self.document) self.document.export_csv(path) msg = "Data for {0} boxes written to {1}" msg = msg.format(self.document.n_items, path) QMessageBox.information(self, "CSV saved", msg) @report_to_user def close_document(self): """Closes the document and returns True if not modified or if modified and user does not cancel. Does not close the document and returns False if modified and users cancels. """ debug_print('MainWindow.close_document') if self.model.modified: # Ask the user if they work like to save before closing res = QMessageBox.question( self, 'Save document?', 'Save the document before closing?', (QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel), QMessageBox.Yes) if QMessageBox.Yes == res: self.save_document() # Answering Yes or No means the document will be closed close = QMessageBox.Cancel != res else: # The document is not modified so it is OK to close it close = True if close: self.empty_document() return close @report_to_user def empty_document(self): """Creates an empty document """ debug_print('MainWindow.empty_document') self.document = None self.plugin_image = None self.plugin_image_visible = False self.model.clear() # TODO LH Prefer setWindowFilePath to setWindowTitle? self.setWindowTitle("Inselect") self.sync_ui() def closeEvent(self, event): """QWidget virtual """ debug_print('MainWindow.closeEvent') if self.close_document(): # User wants to close self.write_geometry_settings() event.accept() else: # User does not want to close event.ignore() @report_to_user def zoom_in(self): self.boxes_view.zoom_in() @report_to_user def zoom_out(self): self.boxes_view.zoom_out() @report_to_user def toggle_zoom(self): self.boxes_view.toggle_zoom() @report_to_user def zoom_home(self): self.boxes_view.zoom_home() @report_to_user def show_grid(self): self.view_specimen.show_grid() @report_to_user def show_expanded(self): self.view_specimen.show_expanded() @report_to_user def about(self): text = u"""<h1>Inselect {version}</h1> <h2>Contributors</h2> <p> <strong>Stefan van der Walt</strong>: Application development and segmentation algorithm </p> <p> <strong>Pieter Holtzhausen</strong>: Application development and segmentation algorithm </p> <p> <strong>Alice Heaton</strong>: Application development </p> <p> <strong>Lawrence Hudson</strong>: Application development </p> """.format(version=inselect.__version__) QMessageBox.about(self, 'Inselect', text) @report_to_user def help(self): """Open the help dialog""" d = HelpDialog(self) d.exec_() def run_in_worker(self, operation, name, complete_fn=None): """Runs the callable operation in a worker thread. The callable complete_fn is called when the operation has finished. """ debug_print("MainWindow.run_in_worker") if self.running_operation: debug_print('Operation already running') else: worker = WorkerThread(operation, name, self) worker.completed.connect(self.worker_finished) self.running_operation = (operation, name, complete_fn, worker) worker.start() @report_to_user def worker_finished(self, user_cancelled, error_message): debug_print("MainWindow.worker_finished", user_cancelled, error_message) operation, name, complete_fn, worker = self.running_operation self.running_operation = None if user_cancelled: QMessageBox.information(self, 'Cancelled', "'{0} cancelled'".format(name)) elif error_message: QMessageBox.information( self, "An error occurred running '{0}'".format(name), error_message + '\n\nExisting data has not been altered') else: if complete_fn: complete_fn(operation) self.sync_ui() @report_to_user def run_plugin(self, plugin_number): """Passes each cropped specimen image through plugin """ debug_print("MainWindow.run_plugin") if plugin_number < 0 or plugin_number > len(self.plugins): raise ValueError('Unexpected plugin [{0}]'.format(plugin_number)) else: plugin = self.plugins[plugin_number] self.model.to_document(self.document) # Create the plugin operation = plugin(self.document, self) if operation.proceed(): self.run_in_worker(operation, operation.name(), self.plugin_finished) else: pass def plugin_finished(self, operation): """Called when a plugin has finished running in a worker thread """ debug_print("MainWindow.plugin_finished") if hasattr(operation, 'items'): self.model.set_new_boxes(operation.items) if hasattr(operation, 'display'): # An image that can be displayed instead of the main image display = operation.display self.plugin_image = QtGui.QPixmap.fromImage(qimage_of_bgr(display)) self.update_boxes_display_pixmap() @report_to_user def select_all(self): """Selects all boxes in the model """ sm = self.view_specimen.selectionModel() m = self.model sm.select( QtGui.QItemSelection(m.index(0, 0), m.index(m.rowCount() - 1, 0)), QtGui.QItemSelectionModel.Select) @report_to_user def select_none(self): sm = self.view_specimen.selectionModel() sm.select(QtGui.QItemSelection(), QtGui.QItemSelectionModel.Clear) @report_to_user def delete_selected(self): """Deletes the selected boxes """ # Delete contiguous blocks of rows selected = self.view_specimen.selectionModel().selectedIndexes() selected = sorted([i.row() for i in selected]) # Remove blocks in reverse order so that row indices are not invalidated # TODO LH We shouldn't need to remove blocks in reverse order - stems # from crummy GraphicsItemView for row, count in reversed(list(contiguous(selected))): self.model.removeRows(row, count) @report_to_user def select_next_prev(self, next): """Selects the next box in the mode if next is True, the previous box in the model if next if False. """ sm = self.view_specimen.selectionModel() current = sm.currentIndex() current = current.row() if current else -1 select = current + (1 if next else -1) if select == self.model.rowCount(): select = 0 elif -1 == select: select = self.model.rowCount() - 1 debug_print('Will move selection [{0}] from [{1}]'.format( current, select)) select = self.model.index(select, 0) sm.select(QtGui.QItemSelection(select, select), QtGui.QItemSelectionModel.ClearAndSelect) sm.setCurrentIndex(select, QtGui.QItemSelectionModel.Current) @report_to_user def rotate90(self, clockwise): """Rotates the selected boxes 90 either clockwise or counter-clockwise. """ debug_print('MainWindow.rotate') value = 90 if clockwise else -90 selected = self.view_specimen.selectionModel().selectedIndexes() for index in selected: current = index.data(RotationRole) self.model.setData(index, current + value, RotationRole) def update_boxes_display_pixmap(self): """Sets the pixmap in the boxes view """ pixmap = self.plugin_image if self.plugin_image_visible else None self.view_graphics_item.show_alternative_pixmap(pixmap) @report_to_user def toggle_plugin_image(self): """Action method to switch between display of the last plugin's information image (if any) and the actual image. """ self.plugin_image_visible = not self.plugin_image_visible self.update_boxes_display_pixmap() def create_actions(self): # File menu self.open_action = QAction("&Open...", self, shortcut=QtGui.QKeySequence.Open, triggered=self.open_file, icon=self.style().standardIcon( QtGui.QStyle.SP_DialogOpenButton)) self.save_action = QAction("&Save", self, shortcut=QtGui.QKeySequence.Save, triggered=self.save_document, icon=self.style().standardIcon( QtGui.QStyle.SP_DialogSaveButton)) self.save_crops_action = QAction("&Save crops", self, triggered=self.save_crops) self.export_csv_action = QAction("&Export CSV", self, triggered=self.export_csv) self.close_action = QAction("&Close", self, shortcut=QtGui.QKeySequence.Close, triggered=self.close_document) self.exit_action = QAction("E&xit", self, shortcut=QtGui.QKeySequence.Quit, triggered=self.close) # Edit menu self.select_all_action = QAction("Select &All", self, shortcut=QtGui.QKeySequence.SelectAll, triggered=self.select_all) # QT does not provide a 'select none' key sequence self.select_none_action = QAction("Select &None", self, shortcut="ctrl+D", triggered=self.select_none) self.next_box_action = QAction("Next box", self, shortcut="N", triggered=partial(self.select_next_prev, next=True)) self.previous_box_action = QAction("Previous box", self, shortcut="P", triggered=partial( self.select_next_prev, next=False)) # TODO LH Does CMD + Backspace work on a mac? self.delete_action = QAction("&Delete selected", self, shortcut=QtGui.QKeySequence.Delete, triggered=self.delete_selected) self.rotate_clockwise_action = QAction("Rotate clockwise", self, shortcut="R", triggered=partial( self.rotate90, clockwise=True)) self.rotate_counter_clockwise_action = QAction( "Rotate counter-clockwise", self, shortcut="L", triggered=partial(self.rotate90, clockwise=False)) # Plugins # Plugin shortcuts start at F5 shortcut_offset = 5 for index, plugin in enumerate(self.plugins): action = QAction(plugin.name(), self, triggered=partial(self.run_plugin, index)) shortcut_fkey = index + shortcut_offset if shortcut_fkey < 13: # Keyboards typically have 12 function keys action.setShortcut('f{0}'.format(shortcut_fkey)) icon = plugin.icon() if icon: action.setIcon(icon) self.plugin_actions[index] = action # View menu # The obvious approach is to set the trigger to # partial(self.tabs.setCurrentIndex, 0) but this causes a segfault when # the application exits on linux. self.boxes_view_action = QAction("&Boxes", self, checkable=True, triggered=partial(self.show_tab, 0)) self.metadata_view_action = QAction("&Specimens", self, checkable=True, triggered=partial( self.show_tab, 1)) # FullScreen added in Qt 5.something # https://qt.gitorious.org/qt/qtbase-miniak/commit/1ef8a6d if not hasattr(QtGui.QKeySequence, 'FullScreen'): if 'darwin' == sys.platform: KeySequenceFullScreen = 'shift+ctrl+f' else: KeySequenceFullScreen = 'f11' else: KeySequenceFullScreen = QtGui.QKeySequence.FullScreen self.full_screen_action = QAction("&Full screen", self, shortcut=KeySequenceFullScreen, triggered=self.toggle_full_screen) self.zoom_in_action = QAction("Zoom &In", self, shortcut=QtGui.QKeySequence.ZoomIn, triggered=self.zoom_in, icon=self.style().standardIcon( QtGui.QStyle.SP_ArrowUp)) self.zoom_out_action = QAction("Zoom &Out", self, shortcut=QtGui.QKeySequence.ZoomOut, triggered=self.zoom_out, icon=self.style().standardIcon( QtGui.QStyle.SP_ArrowDown)) self.toogle_zoom_action = QAction("&Toogle Zoom", self, shortcut='Z', triggered=self.toggle_zoom) self.zoom_home_action = QAction( "Fit To Window", self, shortcut=QtGui.QKeySequence.MoveToStartOfDocument, triggered=self.zoom_home) # TODO LH Is F3 (normally meaning 'find next') really the right # shortcut for the 'toggle plugin image' action? self.toggle_plugin_image_action = QAction( "&Display plugin image", self, shortcut="f3", triggered=self.toggle_plugin_image, statusTip="Display plugin image", checkable=True) self.show_specimen_grid_action = QAction('Show grid', self, shortcut='g', triggered=self.show_grid) self.show_specimen_expanded_action = QAction( 'Show expanded', self, shortcut='e', triggered=self.show_expanded) # Help menu self.about_action = QAction("&About", self, triggered=self.about) self.help_action = QAction("&Help", self, shortcut=QtGui.QKeySequence.HelpContents, triggered=self.help) def create_menus(self): self.toolbar = self.addToolBar("Edit") self.toolbar.addAction(self.open_action) self.toolbar.addAction(self.save_action) for action in [a for a in self.plugin_actions if a.icon()]: self.toolbar.addAction(action) self.toolbar.addAction(self.zoom_in_action) self.toolbar.addAction(self.zoom_out_action) self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.fileMenu = QMenu("&File", self) self.fileMenu.addAction(self.open_action) self.fileMenu.addAction(self.save_action) self.fileMenu.addAction(self.save_crops_action) self.fileMenu.addAction(self.export_csv_action) self.fileMenu.addAction(self.close_action) self.fileMenu.addSeparator() self.fileMenu.addAction(self.exit_action) self.editMenu = QMenu("&Edit", self) self.editMenu.addAction(self.select_all_action) self.editMenu.addAction(self.select_none_action) self.editMenu.addAction(self.delete_action) self.editMenu.addSeparator() self.editMenu.addAction(self.next_box_action) self.editMenu.addAction(self.previous_box_action) self.editMenu.addSeparator() self.editMenu.addAction(self.rotate_clockwise_action) self.editMenu.addAction(self.rotate_counter_clockwise_action) self.editMenu.addSeparator() for action in self.plugin_actions: self.editMenu.addAction(action) self.viewMenu = QMenu("&View", self) self.viewMenu.addAction(self.boxes_view_action) self.viewMenu.addAction(self.metadata_view_action) self.viewMenu.addSeparator() self.viewMenu.addAction(self.full_screen_action) self.viewMenu.addSeparator() self.viewMenu.addAction(self.zoom_in_action) self.viewMenu.addAction(self.zoom_out_action) self.viewMenu.addAction(self.toogle_zoom_action) self.viewMenu.addAction(self.zoom_home_action) self.viewMenu.addAction(self.toggle_plugin_image_action) self.viewMenu.addSeparator() self.viewMenu.addAction(self.show_specimen_grid_action) self.viewMenu.addAction(self.show_specimen_expanded_action) self.helpMenu = QMenu("&Help", self) self.helpMenu.addAction(self.help_action) self.helpMenu.addAction(self.about_action) self.menuBar().addMenu(self.fileMenu) self.menuBar().addMenu(self.editMenu) self.menuBar().addMenu(self.viewMenu) self.menuBar().addMenu(self.helpMenu) def show_tab(self, index): self.tabs.setCurrentIndex(index) def current_tab_changed(self, index): """Slot for self.tabs.currentChanged() signal """ self.sync_ui() def selection_changed(self, selected, deselected): """Slot for self.grid_view.selectionModel().selectionChanged() signal """ self.sync_ui() @report_to_user def toggle_full_screen(self): """Toggles between full screen and normal """ if self.isFullScreen(): self.showNormal() else: self.showFullScreen() def _accept_drag_drop(self, event): """If event refers to a single file that can opened, returns the path. Returns None otherwise. """ urls = event.mimeData().urls() if event.mimeData() else None path = Path(urls[0].toLocalFile()) if urls and 1 == len(urls) else None if (path and path.suffix in chain([InselectDocument.EXTENSION], IMAGE_SUFFIXES)): return urls[0].toLocalFile() else: return None def dragEnterEvent(self, event): """QWidget virtual """ debug_print('MainWindow.dragEnterEvent') if self._accept_drag_drop(event): event.acceptProposedAction() else: super(MainWindow, self).dragEnterEvent(event) def dropEvent(self, event): """QWidget virtual """ debug_print('MainWindow.dropEvent') res = self._accept_drag_drop(event) if res: event.acceptProposedAction() self.open_file(res) else: super(MainWindow, self).dropEvent(event) def write_geometry_settings(self): "Writes geometry to settings" debug_print('MainWindow.write_geometry_settings') # Taken from http://stackoverflow.com/a/8736705 # TODO LH Test on multiple display system s = QSettings() s.setValue("mainwindow/geometry", self.saveGeometry()) s.setValue("mainwindow/pos", self.pos()) s.setValue("mainwindow/size", self.size()) def show_from_geometry_settings(self): debug_print('MainWindow.show_from_geometry_settings') # TODO LH What if screen resolution, desktop config change or roaming # profile means that restored state is outside desktop? s = QSettings() self.restoreGeometry( s.value("mainwindow/geometry", self.saveGeometry())) if not (self.isMaximized() or self.isFullScreen()): self.move(s.value("mainwindow/pos", self.pos())) self.resize(s.value("mainwindow/size", self.size())) self.show() # if read_bool("mainwindow/maximized", self.isMaximized()): # debug_print('Will show maximized') # self.showMaximized() # elif read_bool("mainwindow/full_screen", self.isMaximized()): # debug_print('Will show full screen') # self.showFullScreen() # else: # debug_print('Will show normally') # self.show() def sync_ui(self): """Synchronise the user interface with the application state """ document = self.document is not None has_rows = self.model.rowCount() > 0 if self.model else False boxes_view_visible = self.boxes_view == self.tabs.currentWidget() specimens_view_visible = self.specimens == self.tabs.currentWidget() has_selection = len(self.view_specimen.selectedIndexes()) > 0 # File self.save_action.setEnabled(document) self.save_crops_action.setEnabled(has_rows) self.export_csv_action.setEnabled(has_rows) self.close_action.setEnabled(document) # Edit self.select_all_action.setEnabled(has_rows) self.select_none_action.setEnabled(document) self.delete_action.setEnabled(has_selection) self.next_box_action.setEnabled(has_rows) self.previous_box_action.setEnabled(has_rows) self.rotate_clockwise_action.setEnabled(has_selection) self.rotate_counter_clockwise_action.setEnabled(has_selection) for action in self.plugin_actions: action.setEnabled(document) # View self.boxes_view_action.setChecked(boxes_view_visible) self.metadata_view_action.setChecked(not boxes_view_visible) self.zoom_in_action.setEnabled(document and boxes_view_visible) self.zoom_out_action.setEnabled(document and boxes_view_visible) self.toogle_zoom_action.setEnabled(document and boxes_view_visible) self.zoom_home_action.setEnabled(document and boxes_view_visible) self.toggle_plugin_image_action.setEnabled(document and boxes_view_visible) self.show_specimen_grid_action.setEnabled(specimens_view_visible) self.show_specimen_expanded_action.setEnabled(specimens_view_visible)
def __init__(self): QMainWindow.__init__(self) # the user interface, consisting of a progress bar above a plain # text edit, which logs all actions. container = QWidget(self) container.setLayout(QVBoxLayout(container)) self.setCentralWidget(container) progressbar = QProgressBar(container) container.layout().addWidget(progressbar) log = QPlainTextEdit(container) container.layout().addWidget(log) # the actual worker thread counter = Counter(100, self) # an action to quit the windows exit = QAction(QIcon.fromTheme('application-exit'), 'exit', self) # add two actions to start and stop the worker to the toolbar of the # main window start_counting = QAction(QIcon.fromTheme('media-playback-start'), 'Start counting', self) stop_counting = QAction(QIcon.fromTheme('media-playback-stop'), 'Stop counting', self) # initially no counter runs, so we can disable the stop action stop_counting.setEnabled(False) # add all actions to a toolbar actions = self.addToolBar('Actions') actions.addAction(exit) actions.addSeparator() actions.addAction(start_counting) actions.addAction(stop_counting) # quit the application, if the quit action is triggered exit.triggered.connect(QApplication.instance().quit) # start and stop the counter, if the corresponding actions are # triggered. start_counting.triggered.connect(counter.start) stop_counting.triggered.connect(counter.stop) # adjust the minimum and the maximum of the progress bar, if # necessary. Not really required in this snippet, but added for the # purpose of demonstrating it counter.minimumChanged.connect(progressbar.setMinimum) counter.maximumChanged.connect(progressbar.setMaximum) # switch the enabled states of the actions according to whether the # worker is running or not counter.started.connect(partial(start_counting.setEnabled, False)) counter.started.connect(partial(stop_counting.setEnabled, True)) counter.finished.connect(partial(start_counting.setEnabled, True)) counter.finished.connect(partial(stop_counting.setEnabled, False)) # update the progess bar continuously counter.progress.connect(progressbar.setValue) # log all actions in our logging widget counter.started.connect( partial(self.statusBar().showMessage, 'Counting')) counter.finished.connect(partial(self.statusBar().showMessage, 'Done')) # log a forced stop stop_counting.triggered.connect(partial(log.appendPlainText, 'Stopped')) # log all counted values counter.progress.connect(lambda v: log.appendPlainText(str(v))) # and finally show the current state in the status bar. counter.started.connect(partial(log.appendPlainText, 'Counting')) counter.finished.connect(partial(log.appendPlainText, 'Done'))
def _get_menu_header(self, title): header = QAction(title, self) header.setEnabled(False) return header
def __init__(self): QMainWindow.__init__(self) # the user interface, consisting of a progress bar above a plain # text edit, which logs all actions. container = QWidget(self) container.setLayout(QVBoxLayout(container)) self.setCentralWidget(container) progressbar = QProgressBar(container) container.layout().addWidget(progressbar) log = QPlainTextEdit(container) container.layout().addWidget(log) # the actual worker thread counter = Counter(100, self) # an action to quit the windows exit = QAction(QIcon.fromTheme('application-exit'), 'exit', self) # add two actions to start and stop the worker to the toolbar of the # main window start_counting = QAction(QIcon.fromTheme('media-playback-start'), 'Start counting', self) stop_counting = QAction(QIcon.fromTheme('media-playback-stop'), 'Stop counting', self) # initially no counter runs, so we can disable the stop action stop_counting.setEnabled(False) # add all actions to a toolbar actions = self.addToolBar('Actions') actions.addAction(exit) actions.addSeparator() actions.addAction(start_counting) actions.addAction(stop_counting) # quit the application, if the quit action is triggered exit.triggered.connect(QApplication.instance().quit) # start and stop the counter, if the corresponding actions are # triggered. start_counting.triggered.connect(counter.start) stop_counting.triggered.connect(counter.stop) # adjust the minimum and the maximum of the progress bar, if # necessary. Not really required in this snippet, but added for the # purpose of demonstrating it counter.minimumChanged.connect(progressbar.setMinimum) counter.maximumChanged.connect(progressbar.setMaximum) # switch the enabled states of the actions according to whether the # worker is running or not counter.started.connect(partial(start_counting.setEnabled, False)) counter.started.connect(partial(stop_counting.setEnabled, True)) counter.finished.connect(partial(start_counting.setEnabled, True)) counter.finished.connect(partial(stop_counting.setEnabled, False)) # update the progess bar continuously counter.progress.connect(progressbar.setValue) # log all actions in our logging widget counter.started.connect( partial(self.statusBar().showMessage, 'Counting')) counter.finished.connect( partial(self.statusBar().showMessage, 'Done')) # log a forced stop stop_counting.triggered.connect( partial(log.appendPlainText, 'Stopped')) # log all counted values counter.progress.connect(lambda v: log.appendPlainText(str(v))) # and finally show the current state in the status bar. counter.started.connect(partial(log.appendPlainText, 'Counting')) counter.finished.connect(partial(log.appendPlainText, 'Done'))
class CookieCutterWidget(QWidget): "CookieCutter UI" FILE_FILTER = u'Inselect cookie cutter (*{0})'.format( CookieCutter.EXTENSION ) def __init__(self, parent=None): super(CookieCutterWidget, self).__init__(parent) # Configure the UI self._create_actions() self.button = QPushButton("Cookie cutter") self.button.setMaximumWidth(250) self.button.setStyleSheet("text-align: left") self.popup = QMenu() self.inject_actions(self.popup) self.button.setMenu(self.popup) layout = QHBoxLayout() layout.addWidget(self.button) self.setLayout(layout) def _create_actions(self): self.save_to_new_action = QAction( "Save boxes to new cookie cutter...", self ) self.choose_action = QAction( "Choose...", self, triggered=self.choose ) self.clear_action = QAction( "Do not use a cookie cutter", self, triggered=self.clear ) self.apply_current_action = QAction("Apply", self) def inject_actions(self, menu): "Adds cookie cutter actions to menu" menu.addAction(self.choose_action) menu.addAction(self.apply_current_action) menu.addSeparator() menu.addAction(self.clear_action) menu.addSeparator() menu.addAction(self.save_to_new_action) @report_to_user def clear(self): "Clears the choice of cookie cutter" cookie_cutter_choice().clear() @report_to_user def choose(self): "Shows a 'choose cookie cutter' file dialog" debug_print('CookieCutterWidget.choose_cookie_cutter') path, selectedFilter = QFileDialog.getOpenFileName( self, "Choose cookie cutter", unicode(cookie_cutter_choice().last_directory()), self.FILE_FILTER ) if path: # Save the user's choice cookie_cutter_choice().load(path) def sync_actions(self, has_document, has_rows): "Sync state of actions" debug_print('CookieCutterWidget.sync_ui') current = cookie_cutter_choice().current has_current = cookie_cutter_choice().current is not None name = current.name if current else 'Cookie cutter' # Truncate text to fit button metrics = QFontMetrics(self.button.font()) elided = metrics.elidedText( name, Qt.ElideRight, self.button.width() - 25 ) self.button.setText(elided) self.save_to_new_action.setEnabled(has_rows) self.clear_action.setEnabled(has_current) self.apply_current_action.setEnabled(has_document and has_current)
class UserTemplatePopupButton(QPushButton): "User template popup button" FILE_FILTER = u'Inselect user templates (*{0})'.format( UserTemplate.EXTENSION ) def __init__(self, parent=None): super(UserTemplatePopupButton, self).__init__(parent) # Configure the UI self._create_actions() self.popup = QMenu() self.inject_actions(self.popup) self.setMenu(self.popup) user_template_choice().template_changed.connect(self.changed) # User template might already have been loaded so load the initial if user_template_choice().current: self.changed() def __del__(self): # Doing this prevents segfault on exit. Unsatisfactory. del self.popup def _create_actions(self): self._choose_action = QAction( "Choose...", self, triggered=self.choose ) self._refresh_action = QAction( "Reload", self, triggered=self.refresh ) self._default_action = QAction( u"Default ({0})".format(user_template_choice().DEFAULT.name), self, triggered=self.default ) def inject_actions(self, menu): "Adds user template actions to menu" menu.addAction(self._choose_action) menu.addAction(self._refresh_action) menu.addSeparator() menu.addAction(self._default_action) @report_to_user def default(self): "Sets the default template" user_template_choice().select_default() @report_to_user def choose(self): "Shows a 'choose template' file dialog" debug_print('UserTemplateWidget.choose') path, selectedFilter = QFileDialog.getOpenFileName( self, "Choose user template", unicode(user_template_choice().last_directory()), self.FILE_FILTER ) if path: # Save the user's choice user_template_choice().load(path) @report_to_user def refresh(self): debug_print('UserTemplateWidget.refresh') user_template_choice().refresh() def changed(self): "Slot for UserTemplateChoice.template_changed" debug_print('UserTemplateWidget.changed') choice = user_template_choice() self.setText(choice.current.name) self._refresh_action.setEnabled(not choice.current_is_default)
class Gui(): """main gui class""" def __init__(self): self.mainwindow = QMainWindow() settings.get_settings() self.access = tuple(settings.access.items()) self.progress = QProgressDialog("Setting up modules...", "cancel", 0, 7, self.mainwindow) self.progress.setWindowTitle( QApplication.translate("MainWindow", str(settings.company), None, QApplication.UnicodeUTF8)) def setup(self): """initializes the uio of the erp client""" self.progress.setFixedWidth(1000) self.progress.setCancelButton(None) # self.progress.setWindowModality(Qt.WindowModal) self.progress.setValue(1) self.mainwindow.setObjectName("MainWindow") self.mainwindow.resize(832, 668) self.mainwindow.setStyleSheet( "QToolBar{\n" "background: qlineargradient(x1:0, y1:0, x2:1, y2:1,\n" "stop:0 rgba(0,0,0),stop:1 rgb(162, 162, 162, 162));\n" "border: 0px;\n" "}\n" "QToolBar > QWidget{\n" "color:white;\n" "}\n" "QToolBar > QWidget:hover {\n" "background:transparent;\n" " }\n" "QToolBar > QWidget:checked {\n" "background:transparent;\n" " }\n" "#MainWindow{\n" "background: qlineargradient(x1:0, y1:0, x2:1, y2:1,\n" "stop:0 rgba(0,0,0),stop:1 rgb(162, 162, 162, 162));\n" "border: 0px;\n" "}\n" "") self.centralWidget = QWidget(self.mainwindow) self.centralWidget.setObjectName("centralWidget") self.gridLayout_2 = QGridLayout(self.centralWidget) self.gridLayout_2.setObjectName("gridLayout_2") self.stackedWidget = QStackedWidget(self.centralWidget) self.stackedWidget.setStyleSheet("") self.stackedWidget.setObjectName("stackedWidget") self.shortcut = NewShortcut() scroll = QScrollArea() scroll.setWidget(self.shortcut.shortcut_setting) self.stackedWidget.addWidget(self.shortcut.shortcut_setting) self.home_page = QWidget() self.home_page.setObjectName("home_page") self.gridLayout = QGridLayout(self.home_page) self.gridLayout.setObjectName("gridLayout") self.billing_frame_2 = QFrame(self.home_page) self.billing_frame_2.setStyleSheet( "background-image:url(:/images/billing_frame.png);\n" "background-repeat: no-repeat;\n" "background-position: center;\n" "background-color:#6CBED2;") self.billing_frame_2.setFrameShape(QFrame.StyledPanel) self.billing_frame_2.setFrameShadow(QFrame.Raised) self.billing_frame_2.setObjectName("billing_frame_2") self.verticalLayout_4 = QVBoxLayout(self.billing_frame_2) self.verticalLayout_4.setObjectName("verticalLayout_4") spacerItem = QSpacerItem(20, 217, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout_4.addItem(spacerItem) self.label_10 = QLabel(self.billing_frame_2) self.label_10.setStyleSheet("background:transparent;") self.label_10.setObjectName("label_10") self.verticalLayout_4.addWidget(self.label_10) self.gridLayout.addWidget(self.billing_frame_2, 0, 1, 1, 1) self.employee_frame_3 = QFrame(self.home_page) self.employee_frame_3.setStyleSheet( "background-image:url(:/images/employee_frame.png);\n" "background-repeat: no-repeat;\n" "background-position: center;\n" "background-color:#0099CC;") self.employee_frame_3.setFrameShape(QFrame.StyledPanel) self.employee_frame_3.setFrameShadow(QFrame.Raised) self.employee_frame_3.setObjectName("employee_frame_3") self.verticalLayout_5 = QVBoxLayout(self.employee_frame_3) self.verticalLayout_5.setObjectName("verticalLayout_5") spacerItem1 = QSpacerItem(20, 217, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout_5.addItem(spacerItem1) self.label_11 = QLabel(self.employee_frame_3) self.label_11.setStyleSheet("background:transparent;") self.label_11.setObjectName("label_11") self.verticalLayout_5.addWidget(self.label_11) self.gridLayout.addWidget(self.employee_frame_3, 0, 2, 1, 1) self.menu_frame_4 = QFrame(self.home_page) self.menu_frame_4.setStyleSheet( "background-image:url(:/images/menu_frame.png);\n" "background-repeat: no-repeat;\n" "background-position: center;\n" "background-color:#297ACC;") self.menu_frame_4.setFrameShape(QFrame.StyledPanel) self.menu_frame_4.setFrameShadow(QFrame.Raised) self.menu_frame_4.setObjectName("menu_frame_4") self.verticalLayout_3 = QVBoxLayout(self.menu_frame_4) self.verticalLayout_3.setObjectName("verticalLayout_3") spacerItem2 = QSpacerItem(20, 216, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout_3.addItem(spacerItem2) self.label_12 = QLabel(self.menu_frame_4) self.label_12.setStyleSheet("background:transparent;") self.label_12.setObjectName("label_12") self.verticalLayout_3.addWidget(self.label_12) self.gridLayout.addWidget(self.menu_frame_4, 1, 0, 1, 1) self.report_frame_5 = QFrame(self.home_page) self.report_frame_5.setStyleSheet( "background-image:url(:/images/report_frame.png);\n" "background-repeat: no-repeat;\n" "background-position: center;\n" "background-color:#006BB2;") self.report_frame_5.setFrameShape(QFrame.StyledPanel) self.report_frame_5.setFrameShadow(QFrame.Raised) self.report_frame_5.setObjectName("report_frame_5") self.verticalLayout_6 = QVBoxLayout(self.report_frame_5) self.verticalLayout_6.setObjectName("verticalLayout_6") spacerItem3 = QSpacerItem(20, 216, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout_6.addItem(spacerItem3) self.label_13 = QLabel(self.report_frame_5) self.label_13.setStyleSheet("background:transparent;") self.label_13.setObjectName("label_13") self.verticalLayout_6.addWidget(self.label_13) self.gridLayout.addWidget(self.report_frame_5, 1, 1, 1, 1) self.waste_frame_6 = QFrame(self.home_page) self.waste_frame_6.setStyleSheet( "background-image:url(:/images/waste_frame.png);\n" "background-repeat: no-repeat;\n" "background-position: center;\n" "background-color:#003D7A;") self.waste_frame_6.setFrameShape(QFrame.StyledPanel) self.waste_frame_6.setFrameShadow(QFrame.Raised) self.waste_frame_6.setObjectName("waste_frame_6") self.verticalLayout_7 = QVBoxLayout(self.waste_frame_6) self.verticalLayout_7.setObjectName("verticalLayout_7") spacerItem4 = QSpacerItem(20, 216, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout_7.addItem(spacerItem4) self.label_14 = QLabel(self.waste_frame_6) self.label_14.setStyleSheet("background:transparent;") self.label_14.setObjectName("label_14") self.verticalLayout_7.addWidget(self.label_14) self.gridLayout.addWidget(self.waste_frame_6, 1, 2, 1, 1) self.inventory_frame_1 = QFrame(self.home_page) self.inventory_frame_1.setStyleSheet( "background-image:url(:/images/inventory_frame.png);\n" "background-repeat: no-repeat;\n" "background-position: center;\n" "background-color:#ADEBFF;") self.inventory_frame_1.setFrameShape(QFrame.StyledPanel) self.inventory_frame_1.setFrameShadow(QFrame.Raised) self.inventory_frame_1.setObjectName("inventory_frame_1") self.verticalLayout_2 = QVBoxLayout(self.inventory_frame_1) self.verticalLayout_2.setObjectName("verticalLayout_2") spacerItem5 = QSpacerItem(20, 217, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout_2.addItem(spacerItem5) self.label_9 = QLabel(self.inventory_frame_1) self.label_9.setStyleSheet("background:transparent;") self.label_9.setObjectName("label_9") self.verticalLayout_2.addWidget(self.label_9) self.gridLayout.addWidget(self.inventory_frame_1, 0, 0, 1, 1) self.stackedWidget.addWidget(self.home_page) self.detail_page = QWidget() self.detail_page.setObjectName("detail_page") self.horizontalLayout_2 = QHBoxLayout(self.detail_page) self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.main_tabWidget = QTabWidget(self.detail_page) self.main_tabWidget.setAutoFillBackground(False) self.main_tabWidget.setStyleSheet("") self.main_tabWidget.setTabPosition(QTabWidget.West) self.main_tabWidget.setIconSize(QSize(60, 60)) self.main_tabWidget.setElideMode(Qt.ElideNone) self.main_tabWidget.setObjectName("main_tabWidget") ##initializes the tabs self.add_tabs() self.main_tabWidget.setFocusPolicy(Qt.StrongFocus) self.main_tabWidget.focusInEvent = self.change_focus self.main_tabWidget.currentChanged.connect(self.change_focus) self.stackedWidget.currentChanged.connect(self.change_focus) ###### self.horizontalLayout_2.addWidget(self.main_tabWidget) self.stackedWidget.addWidget(self.detail_page) if ('Admin', True) in self.access: self.stackedWidget.addWidget(Admin(self.mainwindow)) notification = NotificationTab() tab = notification.notificationTab_tab_4 tab.custom_class_object = notification # class_object is used to access the api through the self.stackedWidget.addWidget(tab) self.gridLayout_2.addWidget(self.stackedWidget, 0, 0, 1, 1) self.mainwindow.setCentralWidget(self.centralWidget) self.menuBar = QMenuBar(self.mainwindow) self.menuBar.setGeometry(QRect(0, 0, 832, 29)) self.menuBar.setObjectName("menuBar") self.mainwindow.setMenuBar(self.menuBar) self.mainToolBar = QToolBar(self.mainwindow) self.mainToolBar.setLayoutDirection(Qt.RightToLeft) self.mainToolBar.setStyleSheet("") self.mainToolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.mainToolBar.setObjectName("mainToolBar") self.mainwindow.addToolBar(Qt.TopToolBarArea, self.mainToolBar) self.statusBar = QStatusBar(self.mainwindow) self.statusBar.setObjectName("statusBar") self.mainwindow.setStatusBar(self.statusBar) self.toolBar = QToolBar(self.mainwindow) self.toolBar.setLayoutDirection(Qt.RightToLeft) self.toolBar.setStyleSheet("") self.toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.toolBar.setObjectName("toolBar") self.mainwindow.addToolBar(Qt.TopToolBarArea, self.toolBar) self.actionNotification = QAction(self.mainwindow) self.actionNotification.setCheckable(True) self.actionNotification.setChecked(False) self.actionNotification.setEnabled(True) icon6 = QIcon() icon6.addPixmap(QPixmap(":/images/notification.png"), QIcon.Normal, QIcon.Off) self.actionNotification.setIcon(icon6) self.actionNotification.setAutoRepeat(True) self.actionNotification.setVisible(True) self.actionNotification.setIconVisibleInMenu(False) self.actionNotification.setObjectName("actionNotification") self.actionNotification self.actionAdmin = QAction(self.mainwindow) # self.actionAdmin.setCheckable(True) icon7 = QIcon() icon7.addPixmap(QPixmap(":/images/admin.png"), QIcon.Normal, QIcon.Off) self.actionAdmin.setIcon(icon7) self.actionAdmin.setObjectName("actionAdmin") self.actionRefresh = QAction(self.mainwindow) icon8 = QIcon() icon8.addPixmap(QPixmap(":/images/refresh.png"), QIcon.Normal, QIcon.Off) self.actionRefresh.setIcon(icon8) self.actionRefresh.setObjectName("actionRefresh") self.actionHome = QAction(self.mainwindow) # self.actionHome.setCheckable(True) icon9 = QIcon() icon9.addPixmap(QPixmap(":/images/home.png"), QIcon.Normal, QIcon.Off) self.actionHome.setIcon(icon9) self.actionHome.setObjectName("actionHome") self.actionSettings = QAction(self.mainwindow) icon10 = QIcon() icon10.addPixmap(QPixmap(":/images/settings.png"), QIcon.Normal, QIcon.Off) self.actionSettings.setIcon(icon10) self.actionSettings.setObjectName("actionRefresh") self.toolBar.addAction(self.actionNotification) self.toolBar.addSeparator() self.toolBar.addAction(self.actionAdmin) if ('Admin', True) in self.access: self.toolBar.addSeparator() else: self.actionAdmin.setVisible(False) self.toolBar.addAction(self.actionHome) self.toolBar.addSeparator() self.toolBar.addAction(self.actionRefresh) self.toolBar.addSeparator() self.toolBar.addAction(self.actionSettings) ##retranslates self.mainwindow.setWindowTitle( QApplication.translate("MainWindow", settings.company, None, QApplication.UnicodeUTF8)) self.label_10.setText( QApplication.translate( "MainWindow", "<html><head/><body><p align=\"center\">BILLING</p></body></html>", None, QApplication.UnicodeUTF8)) self.label_11.setText( QApplication.translate( "MainWindow", "<html><head/><body><p align=\"center\">EMPLOYEE</p></body></html>", None, QApplication.UnicodeUTF8)) self.label_12.setText( QApplication.translate( "MainWindow", "<html><head/><body><p align=\"center\">MENU</p></body></html>", None, QApplication.UnicodeUTF8)) self.label_13.setText( QApplication.translate( "MainWindow", "<html><head/><body><p align=\"center\">REPORT</p></body></html>", None, QApplication.UnicodeUTF8)) self.label_14.setText( QApplication.translate( "MainWindow", "<html><head/><body><p align=\"center\">WASTE</p></body></html>", None, QApplication.UnicodeUTF8)) self.label_9.setText( QApplication.translate( "MainWindow", "<html><head/><body><p align=\"center\">INVENTORY</p></body></html>", None, QApplication.UnicodeUTF8)) self.inventory_frame_1.setToolTip( QApplication.translate("MainWindow", "Go to the Inventory Tab", None, QApplication.UnicodeUTF8)) self.billing_frame_2.setToolTip( QApplication.translate("MainWindow", "Go to the Billing Tab", None, QApplication.UnicodeUTF8)) self.employee_frame_3.setToolTip( QApplication.translate("MainWindow", "Go to the Employee Tab", None, QApplication.UnicodeUTF8)) self.menu_frame_4.setToolTip( QApplication.translate("MainWindow", "Go to the Menu Tab", None, QApplication.UnicodeUTF8)) self.report_frame_5.setToolTip( QApplication.translate("MainWindow", "Go to the Report Tab", None, QApplication.UnicodeUTF8)) self.waste_frame_6.setToolTip( QApplication.translate("MainWindow", "Go to the Waste Tab", None, QApplication.UnicodeUTF8)) self.toolBar.setWindowTitle( QApplication.translate("MainWindow", "toolBar", None, QApplication.UnicodeUTF8)) self.actionNotification.setText("&&Notification") # QApplication.translate("MainWindow", "&Notification", None, QApplication.UnicodeUTF8)) self.actionNotification.setToolTip( QApplication.translate("MainWindow", "Click to see new notifications", None, QApplication.UnicodeUTF8)) # self.actionNotification.setShortcut( # QApplication.translate("MainWindow", "Ctrl+Shift+N", None, QApplication.UnicodeUTF8)) self.actionAdmin.setText('&&Admin') # QApplication.translate("MainWindow", "Admin", None, QApplication.UnicodeUTF8)) self.actionAdmin.setToolTip( QApplication.translate("MainWindow", "Click to go to admin interface", None, QApplication.UnicodeUTF8)) # self.actionAdmin.setShortcut( # QApplication.translate("MainWindow", "Ctrl+Shift+A", None, QApplication.UnicodeUTF8)) self.actionRefresh.setText("&&Refresh") # QApplication.translate("MainWindow", "Refresh", None, QApplication.UnicodeUTF8)) self.actionRefresh.setToolTip( QApplication.translate("MainWindow", "refreshes the data from the server", None, QApplication.UnicodeUTF8)) # self.actionRefresh.setShortcut( # QApplication.translate("MainWindow", "Ctrl+Shift+R", None, QApplication.UnicodeUTF8)) self.actionHome.setText('&&Home') # QApplication.translate("MainWindow", "Home", None, QApplication.UnicodeUTF8)) self.actionHome.setToolTip( QApplication.translate("MainWindow", "Go back to the home screen", None, QApplication.UnicodeUTF8)) self.actionSettings.setText('&&Settings') # QApplication.translate("MainWindow", "Settings", None, QApplication.UnicodeUTF8)) self.actionSettings.setToolTip( QApplication.translate("MainWindow", "Go to the settings panel", None, QApplication.UnicodeUTF8)) # self.actionHome.setShortcut( # QApplication.translate("MainWindow", "Ctrl+Shift+H", None, QApplication.UnicodeUTF8)) self.stackedWidget.setCurrentIndex(1) self.main_tabWidget.setCurrentIndex(0) self.ob = self.main_tabWidget.tabBar() # self.add_tool_tip(self.ob) todo avoided due to segmentation fault error, left for future fixes self.tb = EventHandlerForTabBar() self.ob.installEventFilter(self.tb) QMetaObject.connectSlotsByName(self.mainwindow) def add_tabs(self): """ adds new tabs """ global logger if ('Inventory', True) in self.access: logger.info('initiating Inventory') icon = QIcon() icon.addPixmap(QPixmap(":/images/inventory.png"), QIcon.Normal, QIcon.Off) from inventory.inventory import Inventory inventory = Inventory() # inventory.inventory_tab_1.setToolTip("Inventory Section") self.main_tabWidget.addTab(inventory.inventory_tab_1, icon, "") inventory.inventory_detail_tabWidget.setCurrentIndex(0) else: self.inventory_frame_1.setVisible(False) self.progress.setLabelText('Inventory Done....') self.progress.setValue(2) if ('Billing', True) in self.access: logger.info('initiating Billing') icon1 = QIcon() icon1.addPixmap(QPixmap(":/images/billing.png"), QIcon.Normal, QIcon.Off) from billing.billing import Billing bill = Billing() # bill.billing_tab_2.setToolTip("Billing Section") self.main_tabWidget.addTab(bill.billing_tab_2, icon1, "") bill.billing_detail_tabWidget.setCurrentIndex(0) else: self.billing_frame_2.setVisible(False) self.progress.setLabelText('Billing Done...') self.progress.setValue(3) if ('Employee', True) in self.access: logger.info('initiating Employee') icon2 = QIcon() icon2.addPixmap(QPixmap(":/images/employee.png"), QIcon.Normal, QIcon.Off) from employee.employee import Employee employee = Employee() # employee.employee_tab_3.setToolTip("Employee Section") self.main_tabWidget.addTab(employee.employee_tab_3, icon2, "") employee.employee_detail_tabWidget.setCurrentIndex(0) else: self.employee_frame_3.setVisible(False) self.progress.setLabelText('Employee Done...') self.progress.setValue(4) if ('Menu', True) in self.access: logger.info('initiating Menu') icon3 = QIcon() icon3.addPixmap(QPixmap(":/images/menu.png"), QIcon.Normal, QIcon.Off) from menu.menu import Menu menu = Menu() # menu.menu_tab_4.setToolTip("Menu Section") self.main_tabWidget.addTab(menu.menu_tab_4, icon3, "") menu.menu_detail_tabWidget.setCurrentIndex(0) else: self.menu_frame_4.setVisible(False) self.progress.setLabelText('Menu Done....') self.progress.setValue(5) if ('Report', True) in self.access: logger.info('initiating Report') icon4 = QIcon() icon4.addPixmap(QPixmap(":/images/report.png"), QIcon.Normal, QIcon.Off) from report.report import Report report = Report() # report.report_tab_5.setToolTip("Report Section") self.main_tabWidget.addTab(report.report_tab_5, icon4, "") report.report_detail_tabWidget.setCurrentIndex(0) else: self.report_frame_5.setVisible(False) self.progress.setLabelText('Report Done....') self.progress.setValue(6) if ('Waste', True) in self.access: logger.info('initiating Waste') icon5 = QIcon() icon5.addPixmap(QPixmap(":/images/waste.png"), QIcon.Normal, QIcon.Off) from waste.waste import Waste waste = Waste() # waste.waste_tab_6.setToolTip("Waste Section") self.main_tabWidget.addTab(waste.waste_tab_6, icon5, "") waste.waste_detail_tabWidget.setCurrentIndex(0) else: self.waste_frame_6.setVisible(False) self.progress.setLabelText('Waste Done....') self.progress.setValue(7) def change_focus(self, event=None): """ focus method to set focus to a tab to initialize the corresponding events of the tab """ wid = self.main_tabWidget.currentWidget() if wid: if wid.isVisible(): # print wid.objectName() # print '1y' wid.setFocus() def add_tool_tip( self, ob ): # todo not working causing segmentation fault, avoided calling this function """ method to add tool tip to the tabs :param ob: Tab bar """ obj = ob count = obj.count() hardcode = { 0: 'Inventory Section', 1: "Billing Section", 2: "Employee Section", 3: "Menu Section", 4: "Report Section", 5: "Waste Section" } for i in range(count): obj.setTabToolTip(i, hardcode[i])
class DeliverySlipPanel(HorsePanel): delivery_slip_changed = Signal() def close_panel(self): self.filter_widget.remember_current_selection( configuration) def _selected_slip(self): cur_ndx = self.search_results_view.currentIndex() if cur_ndx.row() >= 0: return cur_ndx.model().object_at(cur_ndx.row()) return None def reprint(self): cur_ndx = self.search_results_view.currentIndex() slip_id = cur_ndx.model().index(cur_ndx.row(),0).data() if dao.delivery_slip_part_dao.id_exists(slip_id): print_delivery_slip(dao,slip_id) else: makeErrorBox(_("The delivery slip {} doesn't exist").format(slip_id)).exec_() def desactivate(self): slip_id = self._selected_slip().delivery_slip_id mainlog.debug("Desactivate slip {}".format(slip_id)) dao.delivery_slip_part_dao.deactivate(slip_id) self.refresh(slip_id) self.delivery_slip_changed.emit() def activate(self): slip_id = self._selected_slip().delivery_slip_id dao.delivery_slip_part_dao.activate(slip_id) self.refresh(slip_id) self.delivery_slip_changed.emit() def delete(self): slip_id = self._selected_slip().delivery_slip_id dao.delivery_slip_part_dao.delete_last(slip_id) self.refresh(slip_id) self.delivery_slip_changed.emit() @Slot() def show_actions(self): button = self.action_menu.parent() p = button.mapToGlobal(QPoint(0,button.height())) self.action_menu.exec_(p) @Slot() def _toggle_edit_filters(self): self.filter_widget.setVisible( not self.filter_widget.isVisible()) def __init__(self,parent): super(DeliverySlipPanel,self).__init__(parent) title = _("Delivery slips") self.slip_data = None self.set_panel_title(_("Delivery slip overview")) self.reprint_delivery_slip = QAction(_("Reprint delivery slip"),self) # , parent self.reprint_delivery_slip.triggered.connect( self.reprint) # self.reprint_delivery_slip.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_V)) self.reprint_delivery_slip.setShortcutContext(Qt.WidgetWithChildrenShortcut) # self.controller_operation.view.addAction(self.reprint_delivery_slip) self.desactivate_delivery_slip = QAction(_("Desactivate delivery slip"),self) # , parent self.desactivate_delivery_slip.triggered.connect( self.desactivate) self.desactivate_delivery_slip.setShortcutContext(Qt.WidgetWithChildrenShortcut) self.activate_delivery_slip = QAction(_("Activate delivery slip"),self) # , parent self.activate_delivery_slip.triggered.connect( self.activate) self.activate_delivery_slip.setShortcutContext(Qt.WidgetWithChildrenShortcut) self.delete_delivery_slip = QAction(_("Delete delivery slip"),self) # , parent self.delete_delivery_slip.triggered.connect( self.delete) self.delete_delivery_slip.setShortcutContext(Qt.WidgetWithChildrenShortcut) filter_family = FilterQuery.DELIVERY_SLIPS_FAMILY self.filter_widget = PersistentFilter( filter_family, suggestion_finder) self.filter_widget.apply_filter.connect(self.apply_filter_slot) self.filter_widget.hide() navigation = NavBar( self, [ (self.filter_widget.get_filters_combo(), None), (_("Edit filter"),self._toggle_edit_filters), (_("Action"),self.show_actions) ] ) self.title_widget = TitleWidget(title, self, navigation) # navigation) self.action_menu = QMenu(navigation.buttons[0]) list_actions = [ (self.reprint_delivery_slip,None), (self.activate_delivery_slip,None), (self.desactivate_delivery_slip,None), # (self.delete_delivery_slip,None) ] populate_menu(self.action_menu, self, list_actions, context=Qt.WidgetWithChildrenShortcut) # self.setWindowTitle(title) top_layout = QVBoxLayout(self) # self.filter_line_edit = QLineEdit() # self.filter_line_edit = QueryLineEdit(suggestion_finder) initialize_customer_cache() # FIXME Not the place to do that # filter_family = 'delivery_slips' # self.filter_name = FiltersCombo(self, filter_family) # filter_widget = PersistentFilter(filter_family, self.filter_name) # filter_widget.apply_filter.connect(self.apply_filter_slot) self.proto = [] self.proto.append( IntegerNumberPrototype('delivery_slip_id',_("Slip Nr"), editable=False)) self.proto.append( DatePrototype('creation',_('Date'), editable=False)) self.proto.append( TextLinePrototype('fullname',_('Customer'), editable=False)) self.proto.append( TextLinePrototype('user_label',_('Order'), editable=False)) self.search_results_model = DeliverySlipPanelModel(self.proto, self) self.search_results_view = PrototypedQuickView(self.proto, self) self.search_results_view.setModel(self.search_results_model) self.search_results_view.verticalHeader().hide() self.search_results_view.horizontalHeader().setResizeMode(1, QHeaderView.ResizeToContents) self.search_results_view.horizontalHeader().setResizeMode(2, QHeaderView.Stretch) self.search_results_view.horizontalHeader().setSortIndicatorShown(True) self.search_results_view.horizontalHeader().setSortIndicator(0,Qt.AscendingOrder) self.search_results_view.horizontalHeader().sectionClicked.connect(self._section_clicked) self.search_results_view.setSelectionBehavior(QAbstractItemView.SelectRows) self.search_results_view.setSelectionMode(QAbstractItemView.SingleSelection) self.search_results_view.selectionModel().currentRowChanged.connect(self.row_selected) self.slip_part_view = DeliverySlipViewWidget(self) hlayout_results = QHBoxLayout() # w = SubFrame(_("Delivery slips"),self.search_results_view,None) hlayout_results.addWidget(self.search_results_view) w = SubFrame(_("Detail"),self.slip_part_view,None) hlayout_results.addWidget(w) top_layout.addWidget(self.title_widget) top_layout.addWidget(self.filter_widget) top_layout.addLayout(hlayout_results) top_layout.setStretch(2,100) self.setLayout(top_layout) self.filter_widget.load_last_filter( configuration) def refresh(self,slip_id): filter_string = self.filter_line_edit.text() self.apply_filter_slot(filter_string) if slip_id: ndx = self.search_results_model.find_index( lambda s:s.delivery_slip_id == slip_id) r = 0 m = self.search_results_model if ndx: r = ndx.row() s = QItemSelection(m.index(r,0), m.index(r, m.columnCount()-1)) self.search_results_view.selectionModel().select(s, QItemSelectionModel.Select) @Slot(int) def _section_clicked(self,logical_ndx): self.refresh_action() @Slot(str) def apply_filter_slot(self, filter_string): if filter_string: try: self.slip_data = dao.delivery_slip_part_dao.load_slip_parts_on_filter(filter_string) except DataException as de: if de.code == DataException.CRITERIA_IS_EMPTY: showErrorBox(_("Error in the filter !"),_("The filter can't be empty"),object_name="filter_is_empty") elif de.code == DataException.CRITERIA_IS_TOO_SHORT: showErrorBox(_("Error in the filter !"),_("The filter is too short"),object_name="filter_is_too_short") elif de.code == DataException.CRITERIA_IS_TOO_LONG: showErrorBox(_("Error in the filter !"),_("The filter is too long"),object_name="filter_is_too_long") return else: self.slip_data = dao.delivery_slip_part_dao.find_recent2(1000) self.refresh_action() def refresh_action(self): if self.slip_data == None: self.slip_data = dao.delivery_slip_part_dao.find_recent2(1000) data = self.slip_data headers = self.search_results_view.horizontalHeader() section_sorted = headers.sortIndicatorSection() sort_criteria = self._get_sort_criteria( section_sorted) sort_order = None if sort_criteria: sort_order = headers.sortIndicatorOrder() data = sorted(data, key=cmp_to_key(sort_criteria), reverse = sort_order == Qt.DescendingOrder) self.search_results_model.buildModelFromObjects(data) if sort_criteria: # Changing the model removes the sort order (which makes sense because # changing the model may alter the order of rows) headers.setSortIndicator(section_sorted,sort_order) self.search_results_view.setFocus(Qt.OtherFocusReason) @Slot(QModelIndex,QModelIndex) def row_selected(self,cur_ndx,prev_ndx): if cur_ndx.model(): slip = cur_ndx.model().object_at( cur_ndx.row()) if slip: slip_id = slip.delivery_slip_id self.slip_part_view.set_delivery_slip_parts(dao.delivery_slip_part_dao.load_slip_parts_frozen(slip_id)) self.activate_delivery_slip.setEnabled( not slip.active) self.desactivate_delivery_slip.setEnabled( slip.active) self.delete_delivery_slip.setEnabled( cur_ndx.row() == 0) return self.slip_part_view.set_delivery_slip_parts(None) SECTION_SLIP_ID = 0 SECTION_CREATION_DATE = 1 SECTION_CUSTOMER = 2 SECTION_ORDER_LABEL = 3 def _get_sort_criteria(self,section_sorted): sort_criteria = None # True if the parts of the order stay grouped # together in the table order_stay_together = True if section_sorted == self.SECTION_CUSTOMER: # Customer sort_criteria = lambda a,b: cmp(a.fullname, b.fullname) or \ cmp(a.delivery_slip_id,b.delivery_slip_id) elif section_sorted == self.SECTION_CREATION_DATE: sort_criteria = lambda a,b: cmp(a.creation or date(2100,1,1), b.creation or date(2100,1,1)) elif section_sorted == self.SECTION_SLIP_ID: sort_criteria = lambda a,b: cmp(a.delivery_slip_id, b.delivery_slip_id) elif section_sorted == self.SECTION_ORDER_LABEL: sort_criteria = lambda a,b: cmp(a.user_label, b.user_label) else: sort_criteria = None if sort_criteria is not None: self.current_sort_criteria = sort_criteria else: sort_criteria = self.current_sort_criteria return sort_criteria
def contextMenuEvent(self, event): """ Handles the ``contextMenuEvent`` event for :class:`StatusBarButton`. :param `event`: a `QContextMenuEvent` event to be processed. """ QApplication.setOverrideCursor(Qt.ArrowCursor) menu = QMenu(self) objName = self.objectName() themeDir = gIconDir + os.sep + '..' + os.sep + self.mainWin.getSettingsGeneralIconTheme() + os.sep s = "&Settings..." if objName == "StatusBarButtonSNAP": settingsSnapAction = QAction(QIcon(themeDir + "gridsnapsettings.png"), s, menu) settingsSnapAction.triggered.connect(self.settingsSnap) menu.addAction(settingsSnapAction) elif objName == "StatusBarButtonGRID": settingsGridAction = QAction(QIcon(themeDir + "gridsettings.png"), s, menu) settingsGridAction.triggered.connect(self.settingsGrid) menu.addAction(settingsGridAction) elif objName == "StatusBarButtonRULER": settingsRulerAction = QAction(QIcon(themeDir + "rulersettings.png"), s, menu) settingsRulerAction.triggered.connect(self.settingsRuler) menu.addAction(settingsRulerAction) elif objName == "StatusBarButtonORTHO": settingsOrthoAction = QAction(QIcon(themeDir + "orthosettings.png"), s, menu) settingsOrthoAction.triggered.connect(self.settingsOrtho) menu.addAction(settingsOrthoAction) elif objName == "StatusBarButtonPOLAR": settingsPolarAction = QAction(QIcon(themeDir + "polarsettings.png"), s, menu) settingsPolarAction.triggered.connect(self.settingsPolar) menu.addAction(settingsPolarAction) elif objName == "StatusBarButtonQSNAP": settingsQSnapAction = QAction(QIcon(themeDir + "qsnapsettings.png"), s, menu) settingsQSnapAction.triggered.connect(self.settingsQSnap) menu.addAction(settingsQSnapAction) elif objName == "StatusBarButtonQTRACK": settingsQTrackAction = QAction(QIcon(themeDir + "qtracksettings.png"), s, menu) settingsQTrackAction.triggered.connect(self.settingsQTrack) menu.addAction(settingsQTrackAction) elif objName == "StatusBarButtonLWT": gview = self.mainWin.activeView() if gview: enableRealAction = QAction(QIcon(themeDir + "realrender.png"), "&RealRender On", menu) enableRealAction.setEnabled(not gview.isRealEnabled()) enableRealAction.triggered.connect(self.enableReal) menu.addAction(enableRealAction) disableRealAction = QAction(QIcon(themeDir + "realrender.png"), "&RealRender Off", menu) disableRealAction.setEnabled(gview.isRealEnabled()) disableRealAction.triggered.connect(self.disableReal) menu.addAction(disableRealAction) settingsLwtAction = QAction(QIcon(themeDir + "lineweightsettings" + ".png"), s, menu) settingsLwtAction.triggered.connect(self.settingsLwt) menu.addAction(settingsLwtAction) menu.exec_(event.globalPos()) QApplication.restoreOverrideCursor() self.statusbar.clearMessage()
def handleEvents(self, event, signals): att = self.axisOrder[self.findAxisIndex(event.x)] # context menu if event.contextRequested: contextMenu = QMenu(self) contextMenu.addAction(u'Select all') contextMenu.addAction(u'Select none') contextMenu.addSeparator() act = QAction(u'Hide Axis', self) contextMenu.addAction(act) if len(self.axisOrder) <= 1: act.setEnabled(False) axesMenu = QMenu(u'Show/Hide Axes', self) axesActions = QActionGroup(self) for a in self.axisOrder: act = QAction(a,self,checkable=True) if self.axes[a].visible: act.toggle() if len(self.axisOrder) <= 1: act.setEnabled(False) axesActions.addAction(act) for act in axesActions.actions(): axesMenu.addAction(act) contextMenu.addMenu(axesMenu) contextMenu.addSeparator() contextMenu.addAction(u'Use as X axis') contextMenu.addAction(u'Use as Y axis') resultAction = contextMenu.exec_(QCursor.pos()) if resultAction != None and resultAction != 0: # Select all if resultAction.text() == u'Select all': self.app.intMan.newOperation(operation.ALL,att=att.dataAxis) # Select none if resultAction.text() == u'Select none': self.app.intMan.newOperation(operation.NONE,att=att.dataAxis) # Hide axis if resultAction.text() == u'Hide Axis': self.toggleVisible(att) # Toggle axis if resultAction.actionGroup() == axesActions: self.toggleVisible(resultAction.text()) # X axis if resultAction.text() == u'Use as X axis': if self.app.currentYattribute != self.app.currentXattribute: self.axes[self.app.currentXattribute].visAxis.handle.background.setAttribute('fill',self.normalHandleColor) self.axes[self.app.currentXattribute].visAxis.handle.originalBackgroundColor = self.normalHandleColor self.axes[att].visAxis.handle.background.setAttribute('fill',self.activeHandleColor) self.axes[att].visAxis.handle.originalBackgroundColor = self.activeHandleColor self.app.notifyAxisChange(att,xAxis=True) # Y axis if resultAction.text() == u'Use as Y axis': if self.app.currentXattribute != self.app.currentYattribute: self.axes[self.app.currentYattribute].visAxis.handle.background.setAttribute('fill',self.normalHandleColor) self.axes[self.app.currentYattribute].visAxis.handle.originalBackgroundColor = self.normalHandleColor self.axes[att].visAxis.handle.background.setAttribute('fill',self.activeHandleColor) self.axes[att].visAxis.handle.originalBackgroundColor = self.activeHandleColor self.app.notifyAxisChange(att,xAxis=False) #if linesMoved: # self.highlightedLayer.refreshLines(self.app.highlightedRsNumbers) return signals
def _get_menu_header(self, title): header = QAction(title, self) header.setEnabled(False) return header
class AppWindow(QMainWindow): # ===================== # The Main Window Class # ===================== def __init__(self): # ==================== # Constructor Function # ==================== QMainWindow.__init__(self) self.setWindowTitle("Virtua Text Editor") self.setGeometry(300, 300, 1024, 768) QToolTip.setFont(QFont("Ubuntu", 10, QFont.Normal)) self.setToolTip('Application Window') # ================================ # Function to setup menus, etc etc # ================================ self.textEdit = QTextEdit() self.textEdit.setFont(QFont("Ubuntu", 12, QFont.Normal)) self.setCentralWidget(self.textEdit) self.create_menus() self.create_actions() self.fileMenu.addAction(self.newAction) self.fileMenu.addAction(self.openAction) self.fileMenu.addAction(self.saveAction) self.fileMenu.addAction(self.saveasAction) self.fileMenu.addSeparator() self.fileMenu.addAction(self.printAction) self.fileMenu.addSeparator() self.fileMenu.addAction(self.exitAction) self.editMenu.addAction(self.undoAction) self.editMenu.addAction(self.redoAction) self.editMenu.addAction(self.cutAction) self.editMenu.addAction(self.copyAction) self.editMenu.addAction(self.pasteAction) self.editMenu.addSeparator() self.editMenu.addAction(self.selectallAction) self.editMenu.addAction(self.deselectallAction) self.editMenu.addSeparator() self.editMenu.addAction(self.findAction) self.editMenu.addAction(self.findReplaceAction) self.helpMenu.addAction(self.aboutAction) self.app_status_bar = QStatusBar() self.app_status_bar.showMessage('Ready, v0.2', 10000) self.setStatusBar(self.app_status_bar) self.create_toolbar() self.toolbar.addAction(self.newAction) self.toolbar.addSeparator() self.toolbar.addAction(self.cutAction) self.toolbar.addAction(self.copyAction) self.toolbar.addAction(self.pasteAction) self.toolbar.addSeparator() self.toolbar.addAction(self.printAction) self.toolbar.addSeparator() self.toolbar.addAction(self.undoAction) self.toolbar.addAction(self.redoAction) self.toolbar.addSeparator() self.toolbar.addAction(self.findAction) self.toolbar.addAction(self.findReplaceAction) def create_toolbar(self): # =============================== # Function to create the toolbar. # =============================== self.toolbar = self.addToolBar('Main') self.toolbar.setToolButtonStyle(PySide.QtCore.Qt.ToolButtonTextUnderIcon) def newfile(self): self.textEdit.setText('') # TODO: Create the file/open method def openfile(self): print "Open File Menu Selected" # TODO: Create the file/save method def savefile(self): print "Save File Menu Selected" # TODO: Create the file/saveas method def saveasfile(self): print "Save As File Menu Selected" # TODO: Create the print method def print_page(self): print "Print Page Selected" # TODO: Create the find method def find_text(self): print "Find text option selected" # TODO: Create the replace method def find_replace_text(self): print "Replace text selected" def create_actions(self): # ========================================= # Function to create actions for menu items # ========================================= self.newAction = QAction(QIcon('digital_assets/document-new.svg'), 'New', self) self.newAction.setShortcut(QKeySequence.New) self.newAction.setStatusTip("Create a New File") self.newAction.setIconText("New") self.newAction.triggered.connect(self.newfile) self.openAction = QAction(QIcon('digital_assets/document-open.svg'), 'Open', self) self.openAction.setShortcut(QKeySequence.Open) self.openAction.setStatusTip("Open a file") self.openAction.triggered.connect(self.openfile) self.saveAction = QAction(QIcon('digital_assets/document-save.svg'), 'Save', self) self.saveAction.setShortcut(QKeySequence.Save) self.saveAction.setStatusTip("Save a file") self.saveAction.triggered.connect(self.savefile) self.saveasAction = QAction(QIcon('digital_assets/document-save-as.svg'), 'Save As', self) self.saveasAction.setShortcut(QKeySequence.SaveAs) self.saveasAction.setStatusTip("Save a File As....") self.saveasAction.triggered.connect(self.saveasfile) self.printAction = QAction(QIcon('digital_assets/document-print.svg'), 'Print', self) self.printAction.setShortcut(QKeySequence.Print) self.printAction.setStatusTip("Print") self.printAction.triggered.connect(self.print_page) self.exitAction = QAction(QIcon('digital_assets/application-exit.svg'), 'Exit', self) self.exitAction.setShortcut(QKeySequence.Quit) self.exitAction.setStatusTip("Exit the Application") self.exitAction.triggered.connect(self.quit_application) self.undoAction = QAction(QIcon('digital_assets/undo.svg'), 'Undo', self) self.undoAction.setShortcut(QKeySequence.Undo) self.undoAction.setStatusTip("Undo") self.undoAction.triggered.connect(self.textEdit.undo) self.redoAction = QAction(QIcon('digital_assets/redo.svg'), 'Redo', self) self.redoAction.setShortcut(QKeySequence.Redo) self.redoAction.setStatusTip("Redo") self.redoAction.triggered.connect(self.textEdit.redo) self.cutAction = QAction(QIcon('digital_assets/edit-cut.svg'), 'Cut', self) self.cutAction.setShortcut(QKeySequence.Cut) self.cutAction.setStatusTip("Cut") self.cutAction.setEnabled(False) self.cutAction.triggered.connect(self.textEdit.cut) self.copyAction = QAction(QIcon('digital_assets/edit-copy.svg'), 'Copy', self) self.copyAction.setShortcut(QKeySequence.Copy) self.copyAction.setStatusTip("Copy") self.copyAction.setEnabled(False) self.copyAction.triggered.connect(self.textEdit.copy) self.pasteAction = QAction(QIcon('digital_assets/edit-paste.svg'), 'Paste', self) self.pasteAction.setShortcut(QKeySequence.Paste) self.pasteAction.setStatusTip("Paste") self.pasteAction.setEnabled(False) self.pasteAction.triggered.connect(self.textEdit.paste) self.selectallAction = QAction(QIcon('digital_assets/edit-select-all.svg'), 'Select All', self) self.selectallAction.setShortcut(QKeySequence.SelectAll) self.selectallAction.setStatusTip("Select All") self.selectallAction.triggered.connect(self.textEdit.selectAll) self.deselectallAction = QAction(QIcon('digital_assets/edit-select-all.svg'), 'Deselect All', self) self.deselectallAction.setShortcut("Shift+Ctrl+A") self.deselectallAction.setStatusTip("Deselect All") self.deselectallAction.triggered.connect(self.deselect_all_text) self.findAction = QAction(QIcon('digital_assets/edit-find.svg'), 'Find', self) self.findAction.setShortcut(QKeySequence.Find) self.findAction.setStatusTip("Find") self.findAction.triggered.connect(self.find_text) self.findReplaceAction = QAction(QIcon('digital_assets/edit-find-replace.svg'), 'Replace', self) self.findReplaceAction.setShortcut(QKeySequence.Replace) self.findReplaceAction.setShortcut("Replace") self.findReplaceAction.triggered.connect(self.find_replace_text) self.aboutAction = QAction(QIcon('digital_assets/AppIcon.png'), 'About', self) self.aboutAction.setStatusTip("Displays info about the application") self.aboutAction.triggered.connect(self.show_about) def deselect_all_text(self): text_cursor = self.textEdit.textCursor() text_cursor.clearSelection() self.textEdit.setTextCursor(text_cursor) def create_menus(self): # ================================ # Function to create the menu bar. # ================================ self.fileMenu = self.menuBar().addMenu("File") self.fileMenu.setFont(QFont("Ubuntu", 10, QFont.Normal)) self.editMenu = self.menuBar().addMenu("Edit") self.editMenu.setFont(QFont("Ubuntu", 10, QFont.Normal)) self.helpMenu = self.menuBar().addMenu("Help") self.helpMenu.setFont(QFont("Ubuntu", 10, QFont.Normal)) def set_icon(self): # =============================== # Function to set the Window Icon # =============================== appicon = QIcon('digital_assets/AppIcon.png') self.setWindowIcon(appicon) def quit_application(self): # ================================ # Function to quit the application # ================================ userinfo = QMessageBox.question(self, "Confirmation", "This will quit, Do you want to continue?", QMessageBox.Yes | QMessageBox.No) if userinfo == QMessageBox.Yes: templateApp.quit() if userinfo == QMessageBox.No: pass def show_about(self): QMessageBox.about(self, "About Virtua Text Editor", "<b><h3>Virtua Text Editor</h3></b>" "<p><h4>Virtua Text Editor has been written to serve as a template" " that can be used as a basis for creating a working application." " All of the components that make up the core functions of an" " application, the main window, a status bar, menus and dialogs" " are provided here as a basis for writing something new and interesting</h4></p>") def center_application(self): # ============================================ # Function to center the Application on screen # ============================================ qrect = self.frameGeometry() centerpoint = QDesktopWidget().availableGeometry().center() qrect.moveCenter(centerpoint) self.move(qrect.topLeft())
def createAction(self, icon, toolTip, statusTip, scripted=False): """ TOWRITE :param `icon`: TOWRITE :type `icon`: QString :param `toolTip`: TOWRITE :type `toolTip`: QString :param `statusTip`: TOWRITE :type `statusTip`: QString :param `scripted`: TOWRITE :type `scripted`: bool :rtype: `QAction`_ .. TODO:: send the global Icon, Image, Commands Dirs in to be used. """ connect = self.connect # NOT local optimization, but for ease of the code looking similar to the C++ whash mdiArea = self.mdiArea # ditto ACTION = QAction( QIcon(self.gIconDir + os.sep + self.getSettingsGeneralIconTheme() + "/" + icon + ".png"), toolTip, self ) # QAction * # TODO: Qt4.7 wont load icons without an extension... ACTION.setStatusTip(statusTip) ACTION.setObjectName(icon) # TODO: Set What's This Context Help to statusTip for now so there is some infos there. # Make custom whats this context help popup with more descriptive help than just # the status bar/tip one liner(short but not real long) with a hyperlink in the custom popup # at the bottom to open full help file description. Ex: like wxPython AGW's SuperToolTip. ACTION.setWhatsThis(statusTip) # TODO: Finish All Commands ... <.< if icon == "donothing": connect(ACTION, SIGNAL("triggered()"), self, SLOT("doNothing()")) elif icon == "new": ACTION.setShortcut(QKeySequence.New) connect(ACTION, SIGNAL("triggered()"), self, SLOT("newFile()")) elif icon == "open": ACTION.setShortcut(QKeySequence.Open) connect(ACTION, SIGNAL("triggered()"), self, SLOT("openFile()")) elif icon == "save": ACTION.setShortcut(QKeySequence.Save) connect(ACTION, SIGNAL("triggered()"), self, SLOT("savefile()")) elif icon == "saveas": ACTION.setShortcut(QKeySequence.SaveAs) connect(ACTION, SIGNAL("triggered()"), self, SLOT("saveasfile()")) elif icon == "print": ACTION.setShortcut(QKeySequence.Print) connect(ACTION, SIGNAL("triggered()"), self, SLOT("print_()")) elif icon == "designdetails": ACTION.setShortcut(QKeySequence("Ctrl+D")) connect(ACTION, SIGNAL("triggered()"), self, SLOT("designDetails()")) elif icon == "exit": ACTION.setShortcut(QKeySequence("Ctrl+Q")) connect(ACTION, SIGNAL("triggered()"), self, SLOT("exit()")) elif icon == "cut": ACTION.setShortcut(QKeySequence.Cut) connect(ACTION, SIGNAL("triggered()"), self, SLOT("cut()")) elif icon == "copy": ACTION.setShortcut(QKeySequence.Copy) connect(ACTION, SIGNAL("triggered()"), self, SLOT("copy()")) elif icon == "paste": ACTION.setShortcut(QKeySequence.Paste) connect(ACTION, SIGNAL("triggered()"), self, SLOT("paste()")) elif icon == "windowcascade": connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("cascade()")) elif icon == "windowtile": connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("tile()")) elif icon == "windowclose": ACTION.setShortcut(QKeySequence.Close) connect(ACTION, SIGNAL("triggered()"), self, SLOT("onCloseWindow()")) elif icon == "windowcloseall": connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("closeAllSubWindows()")) elif icon == "windownext": ACTION.setShortcut(QKeySequence.NextChild) connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("activateNextSubWindow()")) elif icon == "windowprevious": ACTION.setShortcut(QKeySequence.PreviousChild) connect(ACTION, SIGNAL("triggered()"), mdiArea, SLOT("activatePreviousSubWindow()")) elif icon == "help": connect(ACTION, SIGNAL("triggered()"), self, SLOT("help()")) elif icon == "changelog": connect(ACTION, SIGNAL("triggered()"), self, SLOT("changelog()")) elif icon == "tipoftheday": connect(ACTION, SIGNAL("triggered()"), self, SLOT("tipOfTheDay()")) elif icon == "about": connect(ACTION, SIGNAL("triggered()"), self, SLOT("about()")) elif icon == "whatsthis": connect(ACTION, SIGNAL("triggered()"), self, SLOT("whatsThisContextHelp()")) elif icon == "icon16": connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon16()")) elif icon == "icon24": connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon24()")) elif icon == "icon32": connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon32()")) elif icon == "icon48": connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon48()")) elif icon == "icon64": connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon64()")) elif icon == "icon128": connect(ACTION, SIGNAL("triggered()"), self, SLOT("icon128()")) elif icon == "settingsdialog": connect(ACTION, SIGNAL("triggered()"), self, SLOT("settingsDialog()")) elif icon == "undo": connect(ACTION, SIGNAL("triggered()"), self, SLOT("undo()")) elif icon == "redo": connect(ACTION, SIGNAL("triggered()"), self, SLOT("redo()")) elif icon == "makelayercurrent": connect(ACTION, SIGNAL("triggered()"), self, SLOT("makeLayerActive()")) elif icon == "layers": connect(ACTION, SIGNAL("triggered()"), self, SLOT("layerManager()")) elif icon == "layerprevious": connect(ACTION, SIGNAL("triggered()"), self, SLOT("layerPrevious()")) elif icon == "textbold": ACTION.setCheckable(True) connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextBold(bool)")) elif icon == "textitalic": ACTION.setCheckable(True) connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextItalic(bool)")) elif icon == "textunderline": ACTION.setCheckable(True) connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextUnderline(bool)")) elif icon == "textstrikeout": ACTION.setCheckable(True) connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextStrikeOut(bool)")) elif icon == "textoverline": ACTION.setCheckable(True) connect(ACTION, SIGNAL("toggled(bool)"), self, SLOT("setTextOverline(bool)")) elif icon == "zoomrealtime": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomRealtime()")) elif icon == "zoomprevious": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomPrevious()")) elif icon == "zoomwindow": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomWindow()")) elif icon == "zoomdynamic": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomDynamic()")) elif icon == "zoomscale": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomScale()")) elif icon == "zoomcenter": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomCenter()")) elif icon == "zoomin": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomIn()")) elif icon == "zoomout": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomOut()")) elif icon == "zoomselected": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomSelected()")) elif icon == "zoomall": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomAll()")) elif icon == "zoomextents": connect(ACTION, SIGNAL("triggered()"), self, SLOT("zoomExtents()")) elif icon == "panrealtime": connect(ACTION, SIGNAL("triggered()"), self, SLOT("panrealtime()")) elif icon == "panpoint": connect(ACTION, SIGNAL("triggered()"), self, SLOT("panpoint()")) elif icon == "panleft": connect(ACTION, SIGNAL("triggered()"), self, SLOT("panLeft()")) elif icon == "panright": connect(ACTION, SIGNAL("triggered()"), self, SLOT("panRight()")) elif icon == "panup": connect(ACTION, SIGNAL("triggered()"), self, SLOT("panUp()")) elif icon == "pandown": connect(ACTION, SIGNAL("triggered()"), self, SLOT("panDown()")) elif icon == "day": connect(ACTION, SIGNAL("triggered()"), self, SLOT("dayVision()")) elif icon == "night": connect(ACTION, SIGNAL("triggered()"), self, SLOT("nightVision()")) elif scripted: ACTION.setIcon(QIcon(self.gAppDir + os.sep + "commands/" + icon + "/" + icon + ".png")) connect(ACTION, SIGNAL("triggered()"), self, SLOT("runCommand()")) else: ACTION.setEnabled(False) connect(ACTION, SIGNAL("triggered()"), self, SLOT("stub_implement()")) return ACTION