def handleMouseMove(event): if self.drawingStuff: mouse_in_map_coords = ( self.ui.graphicsView.mapToScene( self.ui.graphicsView.mapFromGlobal(QCursor.pos()))) coords = list( map(lambda p: int(p), [mouse_in_map_coords.x(), mouse_in_map_coords.y()])) coords[1] -= 1 # fix misalignment if self.lastMousePosOnMap is None: self.lastMousePosOnMap = coords self.drawOnMap(self.world, self.lastMousePosOnMap[0], self.lastMousePosOnMap[1], coords[0], coords[1], self.ui.painterRadius.value(), self.ui.painterIntensity.value() * 0.01 *\ anthill.WorldGenerator.default_pheromone_params.scale) self.lastMousePosOnMap = coords if self.draggingCamera: if self.lastMousePosGlobal is None: self.lastMousePosGlobal = QCursor.pos() delta = QCursor.pos() - self.lastMousePosGlobal self.ui.graphicsView.setTransformationAnchor( self.ui.graphicsView.NoAnchor) self.ui.graphicsView.translate(delta.x(), delta.y()) self.lastMousePosGlobal = QCursor.pos()
def mousePressEvent(self, event): """ Handler for mouse press events. Keyword arguments: event -- mouse event """ print("Click") super(ChainScene, self).mousePressEvent(event) if event.button() == Qt.LeftButton: if self.mode == ChainScene.InsertItem: item = MetaElement(self.toInsert.leftConnectorType, self.toInsert.rightConnectorType, self.toInsert.elementName, self.toInsert.color) item.addProperties(self.toInsert.properties) self.addItem(item) item.setPos(event.scenePos()) self.itemInserted.emit(item) self.update() self.clearSelection() elif self.mode == ChainScene.InsertLine: self.line = QGraphicsLineItem(QLineF(event.scenePos(), event.scenePos())) self.addItem(self.line) elif self.mode == ChainScene.MoveItem: if self.focusItem() is None: self.clearSelection() self.clearFocus() elif event.button() == Qt.RightButton: if len(self.selectedItems()) > 0: if isinstance(self.selectedItems()[0], MetaElement): self.contextMenu1.exec(QCursor.pos()) elif isinstance(self.selectedItems()[0], Connection): self.contextMenu2.exec(QCursor.pos())
def mousePressEvent(self, e): if not self.menu.is_active and not self.game_over: if e.buttons() == Qt.LeftButton and QCursor.pos().x() - self.geometry().x() < 560: square = int((QCursor.pos().x() - self.geometry().x()) / self.board.side_of_square), \ int((QCursor.pos().y() - self.geometry().y()) / self.board.side_of_square) if not self.board.button_pressed: if self.board.field.coords[square[1]][square[0]] is not None and self.board.field.coords[square[1]][square[0]].color == self.board.info.color: self.board.button_pressed = True self.board.pressed_piece = square[1], square[0] self.board.painted_squares = right_moves(square[1], square[0], self.board.field) self.board.painted_squares.append((square[1], square[0])) else: doing_move((self.board.pressed_piece[0], self.board.pressed_piece[1]), (square[1], square[0]), self.board.field, self.board.info) self.board.button_pressed = False self.board.painted_squares = [] self.board.pressed_piece = None pawn = pawn_can_transform(self.board.field) if pawn is not None: self.pawn = pawn self.__transform_pawn__() self.repaint() if not self.board.vs_player and self.board.computer.color == self.board.info.color and self.pawn == None: self.board.computer.move() self.repaint() self.check_game_state()
def __customContextMenuRequested(self, pos): """ Private slot to handle the context menu request for the bookmarks tree. @param pos position the context menu was requested (QPoint) """ itm = self.feedsTree.currentItem() if itm is None: return if self.feedsTree.indexOfTopLevelItem(itm) != -1: return urlString = itm.data(0, FeedsManager.UrlStringRole) if urlString: menu = QMenu() menu.addAction( self.tr("&Open"), self.__openMessageInCurrentTab) menu.addAction( self.tr("Open in New &Tab"), self.__openMessageInNewTab) menu.addSeparator() menu.addAction(self.tr("&Copy URL to Clipboard"), self.__copyUrlToClipboard) menu.exec_(QCursor.pos()) else: errorString = itm.data(0, FeedsManager.ErrorDataRole) if errorString: menu = QMenu() menu.addAction( self.tr("&Show error data"), self.__showError) menu.exec_(QCursor.pos())
def showDetails(self): """ This method is invoked when the text on the SVG schedule is selected. Firstly the name of the schedule is read from the database, secondly a label is displayed with the text name and thirdly the schedule in the main GUI is updated to the chosen one from the displayed SVG file and the associated jobs displayed. :return: None """ sched = self.webView.selectedText() try: name = self._sched.getSchedName(sched, self._sqlite_db) except KeyError: return #Display label with description label = QLabel('<font style="color: grey; background-color: yellow"><p>' + name + '</p></font>') label.move(QCursor.pos().x()+30,QCursor.pos().y()+20) label.setWindowFlags(QtCore.Qt.SplashScreen) label.show() QTimer.singleShot(10000,label.destroy) #set schedule selected in main parent dialog to be that selected in the graph display try: if sched != '': self._parent_dialog.comboBoxSched.setCurrentText(sched) #Change display of combo box i = self._parent_dialog.findIndex(sched) # Where in selection combo list self._parent_dialog.comboBoxSched.setCurrentIndex(i) self._parent_dialog.comboBoxSched.currentIndexChanged(i) self._parent_dialog.tablePopulate(i) #Populate main display except TypeError : pass
def show_menu(self): self.menu = Menu(right_click_menu) hasVideo = movie_info.movie_file != "" self.menu.getItemById("_fullscreen_quit").isActive = hasVideo self.menu.getItemById("_mini_mode").isActive = hasVideo self.menu.getItemById("_play_operation_forward").isActive = hasVideo self.menu.getItemById("_play_operation_backward").isActive = hasVideo self.menu.getItemById("_frame").isActive = \ hasVideo and self._window.getState() != Qt.WindowFullScreen self.menu.getItemById("_subtitle_hide").isActive = \ hasVideo and bool(movie_info.subtitle_file) self.menu.getItemById("_subtitle_manual").isActive = hasVideo self.menu.getItemById("_subtitle_choose").isActive = \ bool(movie_info.subtitle_file) self.menu.getItemById("_information").isActive = hasVideo \ and movie_info.movie_duration != 0 self.menu.getItemById("_on_top").checked = self._window.staysOnTop self.menu.getItemById("proportion:radio:_p_default").checked = \ self._proportion == "proportion:radio:_p_default" self.menu.getItemById("proportion:radio:_p_4_3").checked = \ self._proportion == "proportion:radio:_p_4_3" self.menu.getItemById("proportion:radio:_p_16_9").checked = \ self._proportion == "proportion:radio:_p_16_9" self.menu.getItemById("proportion:radio:_p_16_10").checked = \ self._proportion == "proportion:radio:_p_16_10" self.menu.getItemById("proportion:radio:_p_1_85_1").checked = \ self._proportion == "proportion:radio:_p_1_85_1" self.menu.getItemById("proportion:radio:_p_2_35_1").checked = \ self._proportion == "proportion:radio:_p_2_35_1" self.menu.getItemById("scale:radio:_s_0_5").checked = \ self._scale == "scale:radio:_s_0_5" self.menu.getItemById("scale:radio:_s_1").checked = \ self._scale == "scale:radio:_s_1" self.menu.getItemById("scale:radio:_s_1_5").checked = \ self._scale == "scale:radio:_s_1_5" self.menu.getItemById("scale:radio:_s_2").checked = \ self._scale == "scale:radio:_s_2" self.menu.getItemById("_sound_muted").checked = config.playerMuted self.menu.getItemById("_subtitle_hide").checked = \ not self._window.subtitleVisible subtitles = movie_info.movie_file) subtitles = _subtitle_menu_items_from_files(subtitles) self.menu.getItemById("_subtitle_choose").setSubMenu(Menu(subtitles)) self.menu.getItemById("_fullscreen_quit").text = _("Fullscreen") if \ self._window.getState() != Qt.WindowFullScreen else _("Exit fullscreen") self.menu.getItemById("_mini_mode").text = _("Exit mini mode") if \ self._window.miniModeState() else _("Mini mode") self.menu.itemClicked.connect(self._menu_item_invoked) self.menu.showRectMenu(QCursor.pos().x(), QCursor.pos().y())
def onPress(self, e): self.isPress = True self.__lastX = self.widget.mapFromGlobal(QCursor.pos()).x() self.__lastY = self.widget.mapFromGlobal(QCursor.pos()).y() # print(self.widget.mapFromGlobal(QCursor.pos()).x(), QCursor.pos().x(), e.pos().x()) if self.exPressFunc: e.dragObject = self self.exPressFunc(e) pass
def setupPuzzle(self): size = min(self.puzzleImage.width(), self.puzzleImage.height()) self.puzzleImage = self.puzzleImage.copy((self.puzzleImage.width()-size)/2, (self.puzzleImage.height() - size)/2, size, size).scaled(400, 400, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) random.seed(QCursor.pos().x() ^ QCursor.pos().y()) self.model.addPieces(self.puzzleImage) self.puzzleWidget.clear()
def __scaleTL(self): if (self.parent().width()==800 and QCursor.pos().x()>self.parent().x() and self.parent().height()==600 and QCursor.pos().y()>self.parent().y()): return else: if (self.parent().width()==800 and QCursor.pos().x()>self.parent().x()): self.__scaleTop() elif (self.parent().height()==600 and QCursor.pos().y()>self.parent().y()): self.__scaleLeft() else: self.parent().setGeometry(QCursor.pos().x(), QCursor.pos().y(), self.__lastGeo.x()-QCursor.pos().x()+self.__lastGeo.width(), self.__lastGeo.height()-QCursor.pos().y()+self.__lastGeo.y()) self.resized.emit()
def showDetails(self): try: key = self.webView.selectedText() if key != '': name = self._db.get_node_text(key) else: name = '' except KeyError: return label = QLabel('<font style="color: grey; background-color: yellow"><p>' + repr(name) + '</p></font>') label.move(QCursor.pos().x()+30,QCursor.pos().y()+20) label.setWindowFlags(QtCore.Qt.SplashScreen) label.show() QTimer.singleShot(10000,label.destroy)
def __scaleBR(self): if (self.parent().width()==800 and QCursor.pos().x()<self.parent().x() and self.parent().height()==600 and QCursor.pos().y()<self.parent().y()): return else: if (self.parent().width()==800 and QCursor.pos().x()<self.parent().x()): self.__scaleBottom() elif (self.parent().height()==600 and QCursor.pos().y()<self.parent().y()): self.__scaleRight() else: self.parent().setGeometry(self.__lastGeo.x(), self.__lastGeo.y(), QCursor.pos().x()- self.__lastGeo.x(), QCursor.pos().y()- self.__lastGeo.y()) self.resized.emit()
def showContextMenu(self): """Called when the user right-clicks or presses the context menu key.""" pos = self.view.mapToGlobal(QPoint(0, 0)) link, cursor = None, None # mouse inside view? if self.view.mapFromGlobal(QCursor.pos()) in self.view.viewport().rect(): pos = QCursor.pos() pos_in_surface = self.view.surface().mapFromGlobal(pos) page, link = self.view.surface().pageLayout().linkAt(pos_in_surface) if link: cursor = self._links.cursor(link, True) self._contextMenu.show(pos, link, cursor)
def show_mode_menu(self): self.menu = Menu(play_sequence_sub_menu) self.menu.itemClicked.connect(self._menu_item_invoked) self.menu.getItemById("mode_group:radio:in_order").checked = \ config.playerPlayOrderType == ORDER_TYPE_IN_ORDER self.menu.getItemById("mode_group:radio:random").checked = \ config.playerPlayOrderType == ORDER_TYPE_RANDOM self.menu.getItemById("mode_group:radio:single").checked = \ config.playerPlayOrderType == ORDER_TYPE_SINGLE self.menu.getItemById("mode_group:radio:single_cycle").checked = \ config.playerPlayOrderType == ORDER_TYPE_SINGLE_CYCLE self.menu.getItemById("mode_group:radio:playlist_cycle").checked = \ config.playerPlayOrderType == ORDER_TYPE_PLAYLIST_CYCLE self.menu.showRectMenu(QCursor.pos().x(), QCursor.pos().y())
def __init__(self): QLabel.__init__(self) self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint) self.setAttribute(Qt.WA_NoSystemBackground) self.setMouseTracking(True) self.dragPosition = QPoint(0, 0) self.mousePosition = QCursor.pos() self.actionFaces = QActionGroup(self) allFaceActions = [] for name in sorted(self.faces): action = QAction(name, self.actionFaces) action.setCheckable(True) allFaceActions.append(action) self.actionFaces.triggered.connect(self.actionUpdateFace) startAction = random.choice(allFaceActions) startAction.setChecked(True) self.actionUpdateFace(startAction) self.actionQuit = QAction("Quit", self) self.actionQuit.triggered.connect(QApplication.instance().quit) self.timer = QTimer() self.timer.timeout.connect(self.updateFromMousePosition) self.timer.start(self.update_interval) self.painter = None
def on_tab_add_clicked(self): pos = QCursor.pos() planets = self.world.get_planets() # logger.debug('tab bar add clicked, cursor pos = ({0}, {1})'.format(pos.x(), pos.y())) menu = QMenu(self) # galaxy view galaxy_action = QAction(menu) galaxy_action.setText(self.tr('Add galaxy view')) galaxy_action.setData(QVariant('galaxy')) menu.addAction(galaxy_action) # planets menu.addSection(self.tr('-- Planet tabs: --')) for planet in planets: action = QAction(menu) action.setText('{0} {1}'.format(planet.name, planet.coords.coords_str())) action.setData(QVariant(planet.planet_id)) menu.addAction(action) action_ret = menu.exec(pos) if action_ret is not None: # logger.debug('selected action data = {0}'.format(str(action_ret.data()))) if action_ret == galaxy_action: logger.debug('action_ret == galaxy_action') self.add_tab_for_galaxy() return # else consider this is planet widget planet_id = int(action_ret.data()) self.on_request_open_planet_tab(planet_id)
def icon_activated_slot(self, reason): """Кликнули по иконке в панеле управления""" print('icon_activated_slot') if reason == QSystemTrayIcon.Unknown: #неизвестно print('QSystemTrayIcon.Unknown') pass elif reason == QSystemTrayIcon.Context: #запрос контекстного меню print('QSystemTrayIcon.Context') pass elif reason == QSystemTrayIcon.DoubleClick: print('QSystemTrayIcon.DoubleClick') #двойной клие pass elif reason == QSystemTrayIcon.Trigger: print('QSystemTrayIcon.Trigger') # Клик по системному терю pass elif reason == QSystemTrayIcon.MiddleClick: # Нажата средняя кнопка мыши print('QSystemTrayIcon.MiddleClick') # Получим актуальную позицию мышки # Сдвинем на 50 пикселей по Х и У осям экрана вверх current_mouse_cursor = QCursor.pos() - QPoint(50, 50) # Запросим актуальное меню # Хотя могли бы и self._menu использовать menu = self.contextMenu() menu.popup(current_mouse_cursor)
def contextMenuEvent(self,event): # print(dir(event)) rightMenu = QMenu(self) # rightMenu.setWindowOpacity(0.9); # pos = QGraphicsColorizeEffect(rightMenu) # pos.setColor(QColor("red")) # pos.setStrength() # rightMenu.setGraphicsEffect(pos) # print(dir(rightMenu)) rightMenu.setStyleSheet(qss_rightmenu) loveAction = QAction(u"添加收藏", self, triggered=self.noexc) delAction = QAction(u"删除文件", self, triggered=self.deleteSongItem) rateAction = QAction(u"我要打分", self, triggered=self.noexc) cmAction = QAction(u"评论", self, triggered=self.noexc) moreAction = QAction(u"歌曲详情", self, triggered=self.noexc) moneyAction = QAction(u"打赏", self, triggered=self.noexc) rightMenu.addAction(loveAction) rightMenu.addAction(delAction) rightMenu.addAction(rateAction) rightMenu.addAction(cmAction) rightMenu.addAction(moreAction) rightMenu.addAction(moneyAction) rightMenu.exec_(QCursor.pos())
def make_toolbar(self, list_of_actions=None): """Make or Update the main Tool Bar.""" self.toolbar = QToolBar(self) self.left_spacer, self.right_spacer = QWidget(self), QWidget(self) self.left_spacer.setSizePolicy(1 | 2, 1 | 2) # Expanding, Expanding self.right_spacer.setSizePolicy(1 | 2, 1 | 2) # Expanding, Expanding self.toolbar.addAction("Menu", lambda: self.menubar.exec_(QCursor.pos())) self.toolbar.addWidget(self.left_spacer) self.toolbar.addSeparator() self.toolbar.addAction(QIcon.fromTheme("help-contents"), "Help and Docs", lambda: open_new_tab(__url__)) self.toolbar.addAction(QIcon.fromTheme("help-about"), "About Qt 5", lambda: QMessageBox.aboutQt(self)) self.toolbar.addAction(QIcon.fromTheme("help-about"), "About Python 3", lambda: open_new_tab('http://python.org/about')) self.toolbar.addAction(QIcon.fromTheme("application-exit"), "Quit", self.close) self.toolbar.addSeparator() if list_of_actions and len(list_of_actions): for action in list_of_actions: # if list_of_actions, add actions. self.toolbar.addAction(action) self.toolbar.addSeparator() self.toolbar.addWidget(self.right_spacer) self.addToolBar(self.toolbar) if sys.platform.startswith("win"): self.toolbar.hide() # windows dont have QIcon.fromTheme,so hide. return self.toolbar
def show_context_menu(self, event): index = self.renters_QTableView.indexAt(event) if index.isValid(): menu = QMenu(self) menu.addAction('Edit Renter', lambda: self.edit_renter(index)) menu.addAction('Remove Renter', lambda: self.remove_renter(index)) menu.popup(QCursor.pos())
def pasteClipboard(self): """ """ if self.clip_board is None: return doc = self.manager.document part_item = self.part_item part = part_item.part() sgv = self.slice_graphics_view # 1. get mouse point at the paste qc = QCursor() global_pos = qc.pos() view_pt = sgv.mapFromGlobal(global_pos) s_pt = sgv.mapToScene(view_pt) to_pt = part_item.mapFromScene(s_pt) # print("To Grid Point", to_pt.x(), to_pt.y()) # self.vhi_hint_item.setParentItem(part_item) # self.setHintPos(to_pt) # self.vhi_hint_item.show() # 2. Calculate a delta from the CORNER of the selection box sf = part_item.scaleFactor() delta = to_pt - self.copy_pt distance_offset = delta.x()/sf, -delta.y()/sf part_instance = self.part_item.partInstance() new_vh_set = v3decode.importToPart( part_instance, self.clip_board, offset=distance_offset) self.modelClearSelected()
def timerEvent(self, event): """Handle events sent by the kinetic timer to decrease progressively the scrolling speed, eventually halting it. """ count = 0 if self._kineticData._state == KineticData.ManualScroll: count += 1 cursorPos = QCursor.pos() self._kineticData._speed = cursorPos - self._kineticData._dragPos self._kineticData._dragPos = cursorPos elif self._kineticData._state == KineticData.AutoScroll: count += 1 p = self.scrollOffset() if self._kineticData._speed == QPoint(0, 0) or not self.setScrollOffset(p - self._kineticData._speed): self._kineticData._state = KineticData.Steady # reset speed to 0, as wheel scrolling accumulates speed instead of setting it to a fixed value. self._kineticData._speed = QPoint(0,0) # reset count to 0 to stop iterating. count = 0 self._kineticData._speed = deaccelerate(self._kineticData._speed, 1, self._kineticData._maxSpeed) if count == 0: self._kineticData._ticker.stop() self.kineticScrollingActive.emit(False) super(KineticScrollArea, self).timerEvent(event)
def node_context_menu(self, point): index = self.table_network.indexAt(point) model = self.table_network.model() if index.isValid() and index.row() < model.rowCount(QModelIndex()): source_index = model.mapToSource(index) is_root_col = model.sourceModel().columns_types.index('is_root') is_root_index = model.sourceModel().index(source_index.row(), is_root_col) is_root = model.sourceModel().data(is_root_index, Qt.DisplayRole) menu = QMenu() if is_root: unset_root = QAction(self.tr("Unset root node"), self) unset_root.triggered.connect(self.unset_root_node) unset_root.setData(self.community.network.root_node_index(source_index.row())) if len(self.community.network.root_nodes) > 1: menu.addAction(unset_root) else: set_root = QAction(self.tr("Set as root node"), self) set_root.triggered.connect(self.set_root_node) set_root.setData(self.community.network.nodes[source_index.row()]) menu.addAction(set_root) if self.app.preferences['expert_mode']: open_in_browser = QAction(self.tr("Open in browser"), self) open_in_browser.triggered.connect(self.open_node_in_browser) open_in_browser.setData(self.community.network.nodes[source_index.row()]) menu.addAction(open_in_browser) # Show the context menu. menu.exec_(QCursor.pos())
def right_click(self, type, champ): "Retourne une fonction qui sera executée lors d'un clic droit sur le champ 'champ'." champ.setFocus() plusieurs = isinstance(type, list) if plusieurs: type = type[0] liste_objets = self.onglet_actuel.feuille_actuelle.objets.lister(False, type = type) liste_objets.sort(key = attrgetter('nom')) # ordre alphabétique if not liste_objets: return menu = QMenu() for obj in liste_objets: action = menu.addAction(obj.nom_complet) action.nom = obj.nom action = menu.exec_(QCursor.pos()) if action: if plusieurs: # le champ doit contenir non pas un objet, mais une liste d'objets val = champ.text().strip() if val: if not val.endswith(","): val += "," val += " " champ.setText(val + action.nom) else: # le champ contient un seul objet champ.setText(action.nom)
def show(widget, pos=None, timeout=10000): """Show the widget at position.""" if pos is None: pos = QCursor.pos() global _widget if _widget: if _widget is not widget: _widget.hide() else: global _handler if _handler is None: _handler = EventHandler() QApplication.instance().installEventFilter(_handler) # where to display the tooltip screen = QApplication.desktop().availableGeometry(pos) x = pos.x() + 2 y = pos.y() + 20 if x + widget.width() > screen.x() + screen.width(): x -= 4 + widget.width() if y + widget.height() > screen.y() + screen.height(): y -= 24 + widget.height() if y < screen.y(): y = screen.y() if x < screen.x(): x = screen.x() widget.move(x, y) if widget.windowFlags() & Qt.ToolTip != Qt.ToolTip: widget.setWindowFlags(Qt.ToolTip) widget.ensurePolished() widget.show() _widget = widget _timer.start(timeout)
def __showContextMenu(self): """ Private slot to show the context menu. """ menu = QMenu() act = menu.addAction(self.tr("Object blocked by ClickToFlash")) font = act.font() font.setBold(True) act.setFont(font) menu.addAction( self.tr("Show information about object"), self.__showInfo) menu.addSeparator() menu.addAction(self.tr("Load"), self.__load) menu.addAction(self.tr("Delete object"), self.__hideAdBlocked) menu.addSeparator() host = self.__url.host() add = menu.addAction( self.tr("Add '{0}' to Whitelist").format(host), self.__addToWhitelist) remove = menu.addAction( self.tr("Remove '{0}' from Whitelist").format(host), self.__removeFromWhitelist) onWhitelist = self.__plugin.onWhitelist(host) add.setEnabled(not onWhitelist) remove.setEnabled(onWhitelist) menu.addSeparator() menu.addAction(self.tr("Configure Whitelist"), self.__configure) menu.actions()[0].setEnabled(False) menu.exec_(QCursor.pos())
def __customContextMenuRequested(self, pos): """ Private slot to handle the context menu request for the bookmarks tree. @param pos position the context menu was requested (QPoint) """ from .BookmarkNode import BookmarkNode menu = QMenu() idx = self.bookmarksTree.indexAt(pos) idx = idx.sibling(idx.row(), 0) sourceIndex = self.__proxyModel.mapToSource(idx) node = self.__bookmarksModel.node(sourceIndex) if idx.isValid() and node.type() != BookmarkNode.Folder: menu.addAction( self.tr("&Open"), self.__openBookmarkInCurrentTab) menu.addAction( self.tr("Open in New &Tab"), self.__openBookmarkInNewTab) menu.addSeparator() act = menu.addAction(self.tr("Edit &Name"), self.__editName) act.setEnabled(idx.flags() & Qt.ItemIsEditable) if idx.isValid() and node.type() != BookmarkNode.Folder: menu.addAction(self.tr("Edit &Address"), self.__editAddress) menu.addSeparator() act = menu.addAction( self.tr("&Delete"), self.bookmarksTree.removeSelected) act.setEnabled(idx.flags() & Qt.ItemIsDragEnabled) menu.addSeparator() act = menu.addAction(self.tr("&Properties..."), self.__edit) act.setEnabled(idx.flags() & Qt.ItemIsEditable) menu.exec_(QCursor.pos())
def zoom(self, factor, zoom_to_mouse_cursor=True, cursor_pos=None): if factor > 1 and self.view_rect().width() / factor < 300: factor = self.view_rect().width() / 300 if zoom_to_mouse_cursor: pos = self.mapFromGlobal(QCursor.pos()) if cursor_pos is None else cursor_pos else: pos = None old_pos = self.mapToScene(pos) if pos is not None else None show_full = False if self.view_rect().width() / factor > self.sceneRect().width(): self.show_full_scene() factor = 1 show_full = True self.scale(factor, 1) if show_full: self.zoomed.emit(-1) else: self.zoomed.emit(factor) if pos is not None: move = self.mapToScene(pos) - old_pos self.translate(move.x(), 0)
def updateCurrentColor(self): cursorPos = QCursor.pos() # Catch the pixel pointed by the mouse on a pixmap pixmap = QGuiApplication.screens()[self._desktop.screenNumber()].grabWindow(self._desktop.winId(), cursorPos.x(), cursorPos.y(), 1, 1) qImage = pixmap.toImage() qColor = QColor(qImage.pixel(0, 0)) self.setCurrentColor(qColor)
def verifier_feuille(self, eq1, eq2): print(eq1, eq2) for nom, eq in (('d1', eq1), ('d2', eq2)): if nom in self.feuille_actuelle.objets.noms: d = self.feuille_actuelle.objets[nom] d.label(mode='nom') champ = self.feuille_actuelle.objets['champ_cache_' + nom] M, N = d M = (int(M.x), int(M.y)) N = (int(N.x), int(N.y)) if self.eq_reduite(M, N) == eq: d.style(couleur='g') champ.texte = 'ok' msg = 'La droite %s est correcte.' % nom if nom == 'd1': msg += ' Construisez maintenant d2.' else: print(self.eq_reduite(*d), eq) d.style(couleur='r') # On peut mettre n'importe quoi différent de ok dans # champ, l'idée étant que si la droite est fausse mais # n'a pas changé, on ne perde pas de point, et par # contre on perde des points en cas de changement si # c'est toujours faux. champ.texte = str(d.equation) msg = "Attention, la droite %s est fausse." % nom QToolTip.showText(QCursor.pos(), msg) self.canvas.message(msg, temporaire=False)
def nextFrame(self): mouse_pos = self.mapFromGlobal(QCursor.pos()) mouse_x = mouse_pos.x() mouse_y = mouse_pos.y() self.x1 = mouse_x self.y1 = mouse_y self.radius1 = self.radius1 + math.sin(self.frame_count / 8) * 4 delay = 20 self.x2 += (mouse_x - self.x2) / delay self.y2 += (mouse_y - self.y2) / delay self.frame_count += 1 if self.paint_image.width() != self.width() or self.paint_image.height() != self.height(): self.paint_image = QPixmap(self.width(), self.height()) self.paint_image.fill(self.background_color) p = QPainter() p.begin(self.paint_image) # auf das paint_image malen p.setBackground(self.background_color) # color when stuff is erased # Hintergrund löschen, wenn Rechteck bei der Maus angekommen ist # print("{0}, {1}".format(self.x2, mouse_x)) if round(self.x2) == mouse_x and round(self.y2) == mouse_y: p.eraseRect(0, 0, self.paint_image.width(), self.paint_image.height()) self.drawFrame(p) p.end() self.repaint()
def _menu_context_tree(self, point): index = self.indexAt(point) if not index.isValid(): return handler = None menu = QMenu(self) if self.model().isDir(index): self._add_context_menu_for_folders(menu) else: filename = self.model().fileName(index) lang = file_manager.get_file_extension(filename) self._add_context_menu_for_files(menu, lang) menu.addMenu(self._folding_menu) # menu for the Project Type(if present) if handler: for m in handler.get_context_menus(): if isinstance(m, QMenu): menu.addSeparator() menu.addMenu(m) # show the menu! menu.exec_(QCursor.pos())
def makePopupMenu(self): menu = outlineBasics.makePopupMenu(self) first = menu.actions()[3] # Open item in new tab #sel = self.selectedIndexes() pos = self.viewport().mapFromGlobal(QCursor.pos()) mouseIndex = self.indexAt(pos) # Expand /collapse item if mouseIndex.isValid(): # index = self.currentIndex() item = mouseIndex.internalPointer() if item.isFolder(): self.actExpand = QAction(self.tr("Expand {}").format(item.title()), menu) self.actExpand.triggered.connect(self.expandCurrentIndex) menu.insertAction(first, self.actExpand) self.actCollapse = QAction(self.tr("Collapse {}").format(item.title()), menu) self.actCollapse.triggered.connect(self.collapseCurrentIndex) menu.insertAction(first, self.actCollapse) menu.insertSeparator(first) # Expand /collapse all self.actExpandAll = QAction(self.tr("Expand All"), menu) self.actExpandAll.triggered.connect(self.expandAll) menu.insertAction(first, self.actExpandAll) self.actCollapseAll = QAction(self.tr("Collapse All"), menu) self.actCollapseAll.triggered.connect(self.collapseAll) menu.insertAction(first, self.actCollapseAll) menu.insertSeparator(first) return menu
def onClickBtnSeteo(self): menu = QMenu(self.view) emisionConfig = menu.addAction(u"Configuracion de inicio") paramAction = menu.addAction(u"Parametros de sistema") firmaEmailAction = menu.addAction(u"Firma de correo electronico") generaAction = menu.addAction(u"Genera certificados digitales") menu.addAction(emisionConfig) menu.addAction(paramAction) menu.addAction(firmaEmailAction) menu.addAction(generaAction) menu.addAction(u"Volver") action = menu.exec_(QCursor.pos()) if action == emisionConfig: config = ConfiguracionController() config.view.exec_() elif action == paramAction: _ventana = ABMParamSistController() _ventana.exec_() elif action == generaAction: _ventana_genera = GeneraCertificadosController() _ventana_genera.exec_() elif action == firmaEmailAction: _ventana_firma_email = FirmaCorreoElectronicoController() _ventana_firma_email.exec_()
def onRightClick(self): self.play_list_menu.clear() act1 = self.create_widget_action("./resource/image/nav-播放.png", "播放(Enter)") act2 = QAction("收藏到歌单(Ctrl+S)", self) act3 = self.create_widget_action("./resource/image/打开文件.png", "打开文件所在目录") act4 = self.create_widget_action("./resource/image/删除.png", "从列表中删除(Delete)") self.play_list_menu.addAction(act1) self.play_list_menu.addAction(act2) # 获取被选中的行, 包括列 items = self.tableWidget.selectedItems() # 被选中的行号 rows = set() for item in items: rows.add(item.row()) musics = [] for row in rows: music = self.playlist.get(row) musics.append(music) # 只选中了一行 if len(rows) == 1: self.play_list_menu.addAction(act3) # 设置子菜单归属于act2 self.create_collect_menu(musics) act2.setMenu(self.collect_menu) self.play_list_menu.addMenu(self.collect_menu) self.play_list_menu.addSeparator() self.play_list_menu.addAction(act4) act1.triggered.connect(lambda: self.parent().on_act_play(musics)) act3.triggered.connect(lambda: self.parent().on_act_open_file(musics)) act4.triggered.connect(lambda: self.onActDel(musics)) self.play_list_menu.exec(QCursor.pos())
def on_pressed(self): """Button pressed event handler Shows color dialog and sets the chosen color. """ dlg = QColorDialog(self.parent()) dlg.setCurrentColor(self.color) dlg.setWindowTitle(self.title) dlg.setWindowFlags(Qt.Tool | Qt.FramelessWindowHint) dlg.setWindowModality(Qt.ApplicationModal) dlg.setOptions(QColorDialog.DontUseNativeDialog) p = self.mapFromGlobal(QCursor.pos()) p.setX(p.x() + (self.rect().width() / 2)) p.setY(p.y() + (self.rect().height() / 2)) dlg.move(self.mapToGlobal(p)) if dlg.exec_(): self.color = dlg.currentColor() self.colorChanged.emit()
def __contextMenuRequested(self, pos): """ Private slot to handle the context menu request. @param pos position the context menu shall be shown (QPoint) """ act = self.actionAt(pos) if act is not None and \ act.menu() is None and \ self.index(act).isValid(): menu = QMenu() v = act.data() menuAction = menu.addAction(self.tr("&Open"), self.__openBookmark) menuAction.setData(v) menuAction = menu.addAction(self.tr("Open in New &Tab\tCtrl+LMB"), self.__openBookmarkInNewTab) menuAction.setData(v) menu.addSeparator() menuAction = menu.addAction(self.tr("&Remove"), self.__removeBookmark) menuAction.setData(v) menu.addSeparator() menuAction = menu.addAction(self.tr("&Properties..."), self.__edit) menuAction.setData(v) execAct = menu.exec_(QCursor.pos()) if execAct is not None: self.close() parent = self.parent() while parent is not None and isinstance(parent, QMenu): parent.close() parent = parent.parent()
def show_context_menu(self, text_edit): """ Creates a context menu for the dialog with options to switch the ui between the single line input and the list input, as well as options for importing a list of reddit objects. :param text_edit: True if the context menu is being requested from a line edit. If True, standard copy and paste methods will be included in the context menu. """ menu = QtWidgets.QMenu() if text_edit: copy = menu.addAction('Copy') paste = menu.addAction('Paste') menu.addSeparator() copy.triggered.connect(lambda: QtWidgets.QApplication.clipboard(). setText(self.object_name_line_edit.text())) paste.triggered.connect(lambda: self.object_name_line_edit.setText( QtWidgets.QApplication.clipboard().text())) toggle_text = 'Switch To List' if self.layout_style == 'SINGLE' else 'Switch To Single Line' toggle_layout = menu.addAction(toggle_text) import_text_file = menu.addAction('Import From Text File') import_json_file = menu.addAction('Import From Json File') import_xml_file = menu.addAction('Import From Xml File') import_from_directory = menu.addAction('Import From Directory') if self.layout_style == 'MULTIPLE': menu.addSeparator() clear_non_valid = menu.addAction('Clear All Non Valid') clear_non_valid.triggered.connect( self.object_name_list_model.clear_non_valid) toggle_layout.triggered.connect(self.toggle_layout) import_text_file.triggered.connect(self.import_from_text_file) import_json_file.triggered.connect(self.import_from_json_file) import_xml_file.triggered.connect(self.import_from_xml_file) import_from_directory.triggered.connect(self.import_from_directory) menu.exec(QCursor.pos())
def __performGrab(self): """ Private method to perform a screen grab other than a selected region. """ self.__grabberWidget.releaseMouse() self.__grabberWidget.hide() self.__grabTimer.stop() if self.__mode == SnapWidget.ModeFullscreen: desktop = QApplication.desktop() if qVersion() >= "5.0.0": self.__snapshot = QApplication.screens()[0].grabWindow( desktop.winId(), desktop.x(), desktop.y(), desktop.width(), desktop.height()) else: self.__snapshot = QPixmap.grabWindow( desktop.winId(), desktop.x(), desktop.y(), desktop.width(), desktop.height()) elif self.__mode == SnapWidget.ModeScreen: desktop = QApplication.desktop() screenId = desktop.screenNumber(QCursor.pos()) geom = desktop.screenGeometry(screenId) x = geom.x() y = geom.y() if qVersion() >= "5.0.0": self.__snapshot = QApplication.screens()[0].grabWindow( desktop.winId(), x, y, geom.width(), geom.height()) else: self.__snapshot = QPixmap.grabWindow( desktop.winId(), x, y, geom.width(), geom.height()) else: self.__snapshot = QPixmap() self.__redisplay() self.__modified = True self.__updateCaption()
def _rect_context(self, roi: Roi): menu = QMenu() delete_menu = menu.addMenu('Delete') delete_menu.addAction('Delete on this image', lambda *x, r=roi: self._delete_rois(roi, DeleteRegime.current)) delete_menu.addAction('Delete on all the following images', lambda *x, r=roi: self._delete_rois(roi, DeleteRegime.following)) delete_menu.addAction('Delete everywhere', lambda *x, r=roi: self._delete_rois(roi, DeleteRegime.all)) if roi.movable: menu.addAction('Fix', lambda *x, r=roi: self._fix(roi)) menu.addAction('Fit', lambda *x, r=roi: self._fit(roi)) else: menu.addAction('Unfix', lambda *x, r=roi: self._unfix(roi)) if not roi.type == RoiTypes.segment: menu.addAction(f'Change to segment type', lambda *x, r=roi: self._change_roi_type(roi, RoiTypes.segment)) if not roi.type == RoiTypes.ring: menu.addAction(f'Change to ring type', lambda *x, r=roi: self._change_roi_type(roi, RoiTypes.ring)) if not roi.type == RoiTypes.background: menu.addAction(f'Change to background type', lambda *x, r=roi: self._change_roi_type(roi, RoiTypes.background)) menu.exec_(QCursor.pos())
def rclick_tbl_unpass(self): popMenu = QMenu() submenu_caseto = QMenu('CaseTo') submenu_caseto.setIcon(QIcon('icons/user.ico')) for part in user_info.get_value('PARTS')[:-1]: submenu_caseto.addAction(QAction(part, self)) action_del = QAction('Delete', self) action_del.setIcon(QIcon('icons/delete_file_32px.ico')) action_part_preview = QAction('Start Department Review', self) action_part_preview.setIcon(QIcon('icons/parameterreview_32px.ico')) action_flush = QAction('刷新', self) action_flush.setIcon(QIcon('icons/dir.png')) action_typeidea = QAction('输入处理意见', self) action_typeidea.setIcon(QIcon('icons/input_tablet_32px.ico')) if user_info.get_value('PART') != '质量部': for ctl in [action_del, action_part_preview, submenu_caseto]: ctl.setEnabled(False) popMenu.addMenu(submenu_caseto) popMenu.addAction(action_del) popMenu.addAction(action_part_preview) popMenu.addAction(action_flush) popMenu.addAction(action_typeidea) popMenu.triggered.connect(self.processtrigger_tbl_unpass) popMenu.exec_(QCursor.pos())
def __contextMenuRequested(self, pos): """ Private slot to handle the context menu request. @param pos position the context menu shall be shown (QPoint) """ act = self.actionAt(pos) menu = QMenu() if act is not None: v = act.data() if act.menu() is None: menuAction = menu.addAction( self.tr("&Open"), self.__openBookmark) menuAction.setData(v) menuAction = menu.addAction( self.tr("Open in New &Tab\tCtrl+LMB"), self.__openBookmarkInNewTab) menuAction.setData(v) menu.addSeparator() menuAction = menu.addAction( self.tr("&Remove"), self.__removeBookmark) menuAction.setData(v) menu.addSeparator() menuAction = menu.addAction( self.tr("&Properties..."), self.__edit) menuAction.setData(v) menu.addSeparator() menu.addAction(self.tr("Add &Bookmark..."), self.__newBookmark) menu.addAction(self.tr("Add &Folder..."), self.__newFolder) menu.exec_(QCursor.pos())
def scrollContentsBy(self, dx, dy): """Reimplemented to move the rubberband and adjust the mouse cursor.""" if self._rubberband: self._rubberband.scrollBy(QPoint(dx, dy)) if not self.isScrolling() and not self.isDragging(): # don't adjust the cursor during a kinetic scroll pos = self.viewport().mapFromGlobal(QCursor.pos()) if pos in self.viewport().rect() and not self.viewport().childAt(pos): self.adjustCursor(pos) self.viewport().update() # keep track of current page. If the scroll wasn't initiated by the # setCurrentPage() call, check # whether the current page number needs # to be updated if self.pagingOnScrollEnabled and not self._scrollingToPage and self.pageCount() > 0: # do nothing if current page is still fully in view if self.currentPage().geometry() not in self.visibleRect(): # find the page in the center of the view layout = self._pageLayout pos = self.visibleRect().center() p = layout.pageAt(pos) or layout.nearestPageAt(pos) if p: num = layout.index(p) + 1 self.updateCurrentPageNumber(num)
def initStripsMenu(data): from src.ui.generators.create_menu_context import CreateMenuContext from PyQt5.QtGui import QCursor ContextMenuGen = CreateMenuContext(parent=__globals__.parent) # Create menu __globals__.popup_view = ContextMenuGen.makeMenu() popup_view = ContextMenuGen.makeMenu() # Add entries try: for i in range(data): # Set highlighted entry if i == __globals__.current_strip: ContextMenuGen.addOption(popup_view, f'LED Strip {i}', (None, ('selectStrip', i)), highlighted=True) # Set non-highlighted entry else: ContextMenuGen.addOption(popup_view, f'LED Strip {i}', (None, ('selectStrip', i))) except: pass # Show menu popup_view.exec(QCursor.pos())
def on_add_dictionaries(self): self.menu_AddDictionaries.exec_(QCursor.pos())
def showItemRightMenu(self): self.itemRightMenu.exec(QCursor.pos())
def mouseMoveEvent(self, a0: QtGui.QMouseEvent) -> None: if self.is_press: rx = QCursor.pos().x() - self.ox ry = QCursor.pos().y() - self.oy self.s.emit(rx, ry)
def custom_context_menu_requested(self): """Context menu for mouse right click""" if self.menu is not None: self.menu.popup(QCursor.pos())
def mouseReleaseEvent(self, evnet): if QCursor.pos() != self.mousePos: return else: self.getDetailInfo()
def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None: self.is_press = True self.ox = QCursor.pos().x() self.oy = QCursor.pos().y() self.e.emit()
def contextMenuEvent(self, event): self.category_tree_menu.popup(QCursor.pos())
def contextMenuEvent(self, event): self.menu = QMenu(self) if self.tableView.selectionModel().hasSelection(): # copy copyAction = QAction(QIcon.fromTheme("edit-copy"), 'Copy Cell', self) copyAction.triggered.connect(lambda: self.copyByContext()) # paste pasteAction = QAction(QIcon.fromTheme("edit-paste"), 'Paste Cell', self) pasteAction.triggered.connect(lambda: self.pasteByContext()) # cut cutAction = QAction(QIcon.fromTheme("edit-cut"), 'Cut Cell', self) cutAction.triggered.connect(lambda: self.cutByContext()) # delete selected Row removeAction = QAction(QIcon.fromTheme("edit-delete"), 'delete Row', self) removeAction.triggered.connect( lambda: self.deleteRowByContext(event)) # add Row after addAction = QAction(QIcon.fromTheme("add"), 'insert new Row after', self) addAction.triggered.connect(lambda: self.addRowByContext(event)) # add Row before addAction2 = QAction(QIcon.fromTheme("add"), 'insert new Row before', self) addAction2.triggered.connect(lambda: self.addRowByContext2(event)) # add Column before addColumnBeforeAction = QAction(QIcon.fromTheme("add"), 'insert new Column before', self) addColumnBeforeAction.triggered.connect( lambda: self.addColumnBeforeByContext(event)) # add Column after addColumnAfterAction = QAction(QIcon.fromTheme("add"), 'insert new Column after', self) addColumnAfterAction.triggered.connect( lambda: self.addColumnAfterByContext(event)) # delete Column deleteColumnAction = QAction(QIcon.fromTheme("edit-delete"), 'delete Column', self) deleteColumnAction.triggered.connect( lambda: self.deleteColumnByContext(event)) # replace all row = self.selectedRow() col = self.selectedColumn() myitem = self.tableView.item(row, col) if myitem is not None: self.mytext = myitem.text() replaceThisAction = QAction( QIcon.fromTheme("edit-find-and-replace"), "replace all occurrences of '" + self.mytext + "'", self) replaceThisAction.triggered.connect(lambda: self.replaceThis()) # find all findThisAction = QAction( QIcon.fromTheme("edit-find"), "find all rows contains '" + self.mytext + "'", self) findThisAction.triggered.connect(lambda: self.findThis()) ### self.menu.addAction(copyAction) self.menu.addAction(pasteAction) self.menu.addAction(cutAction) self.menu.addSeparator() self.menu.addAction(QIcon.fromTheme("edit-delete"), "delete", self.deleteCell, QKeySequence.Delete) self.menu.addSeparator() self.menu.addAction(QIcon.fromTheme("edit-copy"), "copy Row", self.copyRow) self.menu.addAction(QIcon.fromTheme("edit-paste"), "paste Row", self.pasteRow) self.menu.addSeparator() self.menu.addAction(QIcon.fromTheme("edit-copy"), "copy Column", self.copyColumn) self.menu.addAction(QIcon.fromTheme("edit-paste"), "paste Column", self.pasteColumn) self.menu.addSeparator() self.menu.addAction(addAction) self.menu.addAction(addAction2) self.menu.addSeparator() self.menu.addAction(addColumnBeforeAction) self.menu.addAction(addColumnAfterAction) self.menu.addSeparator() self.menu.addAction(removeAction) self.menu.addAction(deleteColumnAction) self.menu.addSeparator() self.menu.addAction(replaceThisAction) self.menu.addAction(findThisAction) self.menu.addSeparator() self.menu.addAction(self.whiteAction) self.menu.popup(QCursor.pos())
def right(self): popMenu = QMenu() popMenu.addAction(QAction(u'clear', self)) popMenu.triggered[QAction].connect(self.processtrigger) popMenu.exec_(QCursor.pos())
def contextMenuEvent(self, event): self.tablewidget_menu.popup(QCursor.pos())
def _on_click_copy_tx_id(self) -> None: app_state.app.clipboard().setText(self._tx_hash) QToolTip.showText(QCursor.pos(), _("Transaction ID copied to clipboard"), self)
def tree_context_menu(self, point): mapped = self.view.splitter.mapFromParent(point) index = self.view.tree_view.indexAt(mapped) raw_data = self.view.tree_view.model().data( index, GenericTreeModel.ROLE_RAW_DATA) if raw_data: menu = QMenu(self.view) if raw_data['misc']['connection'].uid: action_view_in_wot = QAction(self.tr("View in Web of Trust"), menu) menu.addAction(action_view_in_wot) action_view_in_wot.triggered.connect( lambda c: self.model.view_in_wot(raw_data['misc'][ 'connection'])) action_gen_revokation = QAction( self.tr("Save revokation document"), menu) menu.addAction(action_gen_revokation) action_gen_revokation.triggered.connect( lambda c: self.action_save_revokation(raw_data['misc'][ 'connection'])) action_publish_uid = QAction(self.tr("Publish UID"), menu) menu.addAction(action_publish_uid) action_publish_uid.triggered.connect( lambda c: self.publish_uid(raw_data['misc']['connection'])) identity_published = self.model.identity_published( raw_data['misc']['connection']) action_publish_uid.setEnabled(not identity_published) action_export_identity = QAction( self.tr("Export identity document"), menu) menu.addAction(action_export_identity) action_export_identity.triggered.connect( lambda c: self.export_identity_document(raw_data['misc'][ 'connection'])) action_leave = QAction(self.tr("Leave the currency"), menu) menu.addAction(action_leave) action_leave.triggered.connect( lambda c: self.send_leave(raw_data['misc']['connection'])) action_leave.setEnabled( self.model.identity_is_member( raw_data['misc']['connection'])) copy_pubkey = QAction(menu.tr("Copy pubkey to clipboard"), menu.parent()) copy_pubkey.triggered.connect(lambda checked, c=raw_data['misc']['connection']: \ NavigationModel.copy_pubkey_to_clipboard(c)) menu.addAction(copy_pubkey) copy_pubkey_crc = QAction( menu.tr("Copy pubkey to clipboard (with CRC)"), menu.parent()) copy_pubkey_crc.triggered.connect(lambda checked, c=raw_data['misc']['connection']: \ NavigationModel.copy_pubkey_to_clipboard_with_crc(c)) menu.addAction(copy_pubkey_crc) action_remove = QAction(self.tr("Remove the connection"), menu) menu.addAction(action_remove) action_remove.triggered.connect(lambda c: self.remove_connection( raw_data['misc']['connection'])) # Show the context menu. menu.popup(QCursor.pos())
def show_right_menu(self, pos): # 重载弹出式菜单事件 pos = QCursor.pos() pos.setX(pos.x() + 2) pos.setY(pos.y() + 2) self.rightMenu.exec_(pos)
class Canvas(QWidget): def __init__(self, images: list, nStimuli: int, imageWidth: int, nrow: int, ncol: int, conditions: list, conditionOrder: list, nTrials: int, useCustomTimer: bool = False, trialTimeOut: int = 10000, addNoise=True, customCalibration: bool = False, customCalibrationSize: int = 20, fixationCrossSize=20, fixationCrossMs=3000, driftToleranceDeg=2.0, inTrainingMode=False, left: int = 50, top: int = 50, width: int = 2560, height: int = 1440): super().__init__() # Set window params self.title = 'Copying task' self.left = left self.top = top self.width = width self.height = height self.sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.sizePolicy.setHeightForWidth(True) self.setSizePolicy(self.sizePolicy) self.styleStr = "background-color:transparent" # Set stimuli params self.nStimuli = nStimuli self.allImages = images self.images = None self.shuffledImages = None self.imageWidth = imageWidth self.nrow = nrow self.ncol = ncol # Set experiment params self.nTrials = nTrials self.conditions = conditions self.nConditions = len(conditions) self.conditionOrder = conditionOrder self.currentTrial = 1 self.conditionOrderIndex = 0 self.currentConditionIndex = self.conditionOrder[ self.conditionOrderIndex] self.useCustomTimer = useCustomTimer self.visibleTime = 0 self.occludedTime = 0 self.backCrossing = False self.backCrossStart = 0 self.possibleBlinkStart = None self.addNoise = addNoise self.trialTimeOut = trialTimeOut self.customCalibration = customCalibration self.customCalibrationSize = customCalibrationSize self.fixationCrossSize = fixationCrossSize self.fixationCrossMs = fixationCrossMs self.driftToleranceDeg = driftToleranceDeg self.spacePushed = False # Set tracking vars self.timer = QTimer(self) self.fixTimer = QTimer() self.fixTimer2 = QTimer() self.mouse = QCursor() self.dragStartTime = None self.dragStartPosition = None self.lastNow = 0 self.mean_error, self.sd_error = 0, 0 self.inTrainingMode = inTrainingMode # Track correct placements self.correctPlacements = pd.DataFrame(columns=[ 'x', 'y', 'Name', 'shouldBe', 'Correct', 'Time', 'dragDuration', 'dragDistance', 'Trial', 'Condition', 'visibleTime', 'cameFromX', 'cameFromY' ]) self.mouseTrackerDict = { key: [] for key in ['x', 'y', 'Time', 'TrackerTime', 'Trial', 'Condition'] } self.eventTracker = pd.DataFrame(columns=[ 'Time', 'TrackerTime', 'TimeDiff', 'Event', 'Condition', 'Trial' ]) self.projectFolder = Path(__file__).parent self.ppNumber = None self.setParticipantNumber() self.disp = None self.tracker = None self.recordingSession = 0 self.inOpeningScreen = True self.inFixationScreen = False self.initUI() # ============================================================================= # TRACKING FUNCTIONS # ============================================================================= def setParticipantNumber(self): # Get input number = input('Enter participant number or name:\n') # If input is none, try again (recursively) if len(number) < 1 or number is None: print('Invalid input, try again') self.setParticipantNumber() # Read already used numbers with open(self.projectFolder / 'results/usedNumbers.txt', 'r') as f: usedNumbers = json.load(f) # If not in use, save and return if number not in usedNumbers: self.ppNumber = number usedNumbers.append(number) with open(self.projectFolder / 'results/usedNumbers.txt', 'w') as f: json.dump(usedNumbers, f) # Make dedicated folder for this person if not str(self.ppNumber) in os.listdir( self.projectFolder / 'results'): os.mkdir(self.projectFolder / f'results/{self.ppNumber}') return # If already in use, recursively run again else: print(f'{number} is already in use! Use another number or name') self.setParticipantNumber() def writeCursorPosition(self, now): e = self.mouse.pos() self.mouseTrackerDict['x'].append(e.x()) self.mouseTrackerDict['y'].append(e.y()) self.mouseTrackerDict['Time'].append(now) self.mouseTrackerDict['TrackerTime'].append(self.getTrackerClock()) self.mouseTrackerDict['Trial'].append(self.currentTrial) self.mouseTrackerDict['Condition'].append(self.currentConditionIndex) def defaultTimer(self, now): # Use default. None means no update, otherwise flip if self.exampleGridBox.isVisible(): if now - self.start >= self.visibleTime: self.start = now return 'hide', 'show' else: if now - self.start >= self.occludedTime: self.start = now return 'show', 'hide' return None, None def updateTimer(self): if self.inOpeningScreen: return now = round(time.time() * 1000) # Only write cursor every 2 ms if ((now % 2) == 0) and (now != self.lastNow): self.writeCursorPosition(now) self.lastNow = now # Check for timeout if now - self.globalTrialStart >= self.trialTimeOut: self.checkIfFinished(timeOut=True) return # Check if update necessary with custom timer if self.useCustomTimer: gridInstruction, hourglassInstruction = customTimer(self, now) else: gridInstruction, hourglassInstruction = self.defaultTimer(now) self.showHideExampleGrid(gridInstruction) self.showHideHourGlass(hourglassInstruction) # Check if result needs checking, every 200ms to avoid too much processing if now - self.checkIfFinishedStart >= 500: self.checkIfFinished() self.checkIfFinishedStart = now def runTimer(self): self.timer.setInterval(1) # 1 ms self.timer.timeout.connect(self.updateTimer) # Unfortunately we need three tracking vars to keep updates not too time-consuming self.start = round(time.time() * 1000) self.globalTrialStart = self.start self.checkIfFinishedStart = self.start self.crossingStart = None self.timer.start() def disconnectTimer(self): try: self.timer.stop() except AttributeError: pass # Happens if the timer has never been started yet def getTrackerClock(self): try: trackerClock = self.tracker.get_eyelink_clock() except Exception: trackerClock = 0 return trackerClock def writeEvent(self, msg): trackerClock = self.getTrackerClock() localTime = round(time.time() * 1000) timeDiff = localTime - trackerClock event = pd.DataFrame( { 'Time': localTime, 'TrackerTime': trackerClock, 'TimeDiff': timeDiff, 'Event': msg, 'Condition': self.currentConditionIndex, 'Trial': self.currentTrial }, index=[0]) self.eventTracker = self.eventTracker.append(event, ignore_index=True) def writeFiles(self): self.correctPlacements.to_csv( self.projectFolder / f'results/{self.ppNumber}/{self.ppNumber}-correctPlacements.csv') self.eventTracker.to_csv( self.projectFolder / f'results/{self.ppNumber}/{self.ppNumber}-eventTracking.csv') def writeMouseTracker(self): mouseTrackerDF = pd.DataFrame(self.mouseTrackerDict) mouseTrackerDF.to_csv( self.projectFolder / f'results/{self.ppNumber}/{self.ppNumber}-mouseTracking-condition{self.currentConditionIndex}-trackingSession-{self.recordingSession}.csv' ) self.mouseTrackerDict = { key: [] for key in ['x', 'y', 'Time', 'TrackerTime', 'Trial', 'Condition'] } def checkIfFinished(self, timeOut=False): copiedTemp = self.correctPlacements.loc[self.correctPlacements['Trial'] == self.currentTrial] copiedTemp = copiedTemp.loc[copiedTemp['Condition'] == self.currentConditionIndex] allCorrect = np.all(copiedTemp['Correct'].values) if (len(copiedTemp) > 0 and allCorrect) or timeOut: self.writeEvent('Finished trial') self.clearScreen() self.writeFiles() self.currentTrial += 1 self.initOpeningScreen(timeOut) def showHideHourGlass(self, specific=None): text = None if specific is None: return elif specific == 'show': if not self.hourGlass.isVisible(): self.hourGlass.setVisible(True) text = 'Showing' elif specific == 'hide': if self.hourGlass.isVisible(): self.hourGlass.setVisible(False) text = 'Hiding' elif specific == 'flip': if self.hourGlass.isVisible(): self.hourGlass.setVisible(False) text = 'Hiding' else: self.hourGlass.setVisible(True) text = 'Showing' else: raise ValueError( f"{specific} is not an accepted keyword for 'showHideHourGlass'." + "Choose from: None, 'show', 'hide', 'flip'.") if text is not None: self.writeEvent(f'{text} hourglass') def showHideExampleGrid(self, specific=None): text = None if specific is None: return elif specific == 'show': if not self.exampleGridBox.isVisible(): self.exampleGridBox.setVisible(True) text = 'Showing' elif specific == 'hide': if self.exampleGridBox.isVisible(): self.exampleGridBox.setVisible(False) text = 'Hiding' elif specific == 'flip': if self.exampleGridBox.isVisible(): self.exampleGridBox.setVisible(False) text = 'Hiding' else: self.exampleGridBox.setVisible(True) text = 'Showing' else: raise ValueError( f"{specific} is not an accepted keyword for 'showHideExamplegrid'." + "Choose from: None, 'show', 'hide', 'flip'.") if text is not None: self.writeEvent(f'{text} grid') def moveAndRenameTrackerFile(self): fromLocation = self.projectFolder / 'default.edf' toLocation = self.projectFolder / f'results/{self.ppNumber}/{self.ppNumber}-trackingSession-{self.recordingSession}.edf' os.rename(Path(fromLocation), Path(toLocation)) self.writeMouseTracker() self.writeEvent(f'Writing eyetracker session {self.recordingSession}') print(f'Saved session {self.recordingSession} to {toLocation}') def custom_calibration(self, x, y): self.screen = libscreen.Screen() self.screen.draw_circle(colour='black', pos=(x, y), r=self.customCalibrationSize, fill=True) self.disp.fill(self.screen) self.disp.show() def eventFilter(self, widget, e): if e.type() == QtCore.QEvent.KeyPress: key = e.key() # Retry the fixation cross with key 'r' if key == QtCore.Qt.Key_R and self.inFixationScreen: self.clearScreen() self.initTask() if key == QtCore.Qt.Key_Space and not self.spacePushed: # Set spacePushed to true and remove all widgets self.spacePushed = True self.clearScreen() # Start the task if self.inOpeningScreen: self.initTask() elif self.inFixationScreen: self.continueInitTask() return True elif key == QtCore.Qt.Key_Backspace: print('Backspace pressed') self.clearScreen() # Try to close the eyetracker try: self.tracker.stop_recording() self.tracker.close(full_close=False) self.moveAndRenameTrackerFile() self.disp = None self.tracker = None except Exception as e: # There is no recording to stop print(e) # Go into calibration if self.disp is None: # Program crashes if both pygaze and this want to use fullscreen, so maximize instead of FS self.showMaximized() self.disp = libscreen.Display() self.tracker = EyeTracker(self.disp) if self.customCalibration: self.tracker.set_draw_calibration_target_func( self.custom_calibration) self.tracker.calibrate() self.disp.close() self.showFullScreen() # When done, start recording and init task self.recordingSession += 1 self.tracker.start_recording() # Get the async between tracker and os async_val = self.tracker._get_eyelink_clock_async() self.writeEvent(f'Async {async_val}') time.sleep(1) self.initOpeningScreen() return True # Trigger early exit elif key == QtCore.Qt.Key_Tab: try: self.tracker.stop_recording() self.tracker.close(full_close=True) self.moveAndRenameTrackerFile() except Exception as e: print(e) self.writeEvent('Early exit') self.writeFiles() self.close() print('\nEarly exit') raise SystemExit(0) return QWidget.eventFilter(self, widget, e) def setConditionTiming(self): # Try to retrieve condition timing. If index out of range (IndexError), conditions are exhausted. # visibleTime and occludedTime are pulled from conditions, and assigned to class after mutation has been done try: visibleTime, occludedTime = self.getConditionTiming() except IndexError as e: try: self.tracker.stop_recording() self.tracker.close(full_close=True) self.moveAndRenameTrackerFile() except AttributeError as ae: print(ae) self.writeEvent('Finished') self.writeFiles() self.close() print('\nNo more conditions, the experiment is finished!') raise SystemExit(0) if self.addNoise and occludedTime != 0: sumDuration = visibleTime + occludedTime # Generating a noise and its invert keeps the sum duration the same as without permutation noise = gauss(mu=1.0, sigma=0.1) self.occludedTime = int(occludedTime * noise) self.visibleTime = sumDuration - occludedTime else: self.visibleTime = visibleTime self.occludedTime = occludedTime self.backCrossStart = 0 self.backCrossing = False # print(f'Moving to condition {self.currentConditionIndex}: ({self.visibleTime}, {self.occludedTime})') def getConditionTiming(self): # conditionOrderIndex to retrieve a condition number from conditionOrder self.currentConditionIndex = self.conditionOrder[ self.conditionOrderIndex] # Use the condition number retrieved from conditionOrder to retrieve the actual condition to use visibleTime = self.conditions[self.currentConditionIndex][0] occludedTime = self.conditions[self.currentConditionIndex][1] return visibleTime, occludedTime # ============================================================================= # INITIALIZATION OF SCREENS # ============================================================================= def clearScreen(self): for i in reversed(range(self.layout.count())): self.layout.itemAt(i).widget().setParent(None) def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.setStyleSheet("background-color:rgb(128, 128, 128)") self.layout = QVBoxLayout() self.writeEvent('UI init') self.loadThumbsUp() self.loadFixationCross() self.initOpeningScreen() def loadThumbsUp(self): path = Path(__file__).parent / 'pictograms' / 'thumbs.png' with open(path, 'rb') as f: im = f.read() image = QImage() image.loadFromData(im) image = image.scaledToWidth(100) pixmap = QPixmap.fromImage(image) self.thumbsUp = QLabel() self.thumbsUp.setPixmap(pixmap) self.thumbsUp.setAlignment(QtCore.Qt.AlignCenter) self.thumbsUp.setSizePolicy(self.sizePolicy) def loadFixationCross(self): path = Path(__file__).parent / 'pictograms' / 'fixation_cross.png' with open(path, 'rb') as f: im = f.read() image = QImage() image.loadFromData(im) image = image.scaledToWidth(self.fixationCrossSize) pixmap = QPixmap.fromImage(image) self.fixationCross = QLabel() self.fixationCross.setPixmap(pixmap) self.fixationCross.setAlignment(QtCore.Qt.AlignCenter) self.fixationCross.setSizePolicy(self.sizePolicy) def initOpeningScreen(self, timeOut=False): self.disconnectTimer() self.inOpeningScreen = True # If all trials are done, increment condition counter and # reset trial counter to 1. if self.currentTrial > self.nTrials: self.conditionOrderIndex += 1 self.currentTrial = 1 print( f'Trial {self.currentTrial}, Block {self.conditionOrderIndex}, Condition {self.currentConditionIndex}' ) self.spacePushed = False self.writeEvent('In starting screen') if self.currentTrial == 1: if self.conditionOrderIndex == 0: self.label = QLabel( "Welcome to the experiment.\n" + "Throughout this experiment, you will be asked to copy the layout on the left side of the screen to the right side of the screen,\n" + "by dragging the images in the lower right part of the screen to their correct positions. You are asked to do this as quickly" + "and as accurately as possible.\n" + "If you make a mistake, the location will briefly turn red. \n" + "Throughout the experiment, the example layout may disappear for brief periods of time. You are asked to keep\n" + "performing the task as quickly and as accurately as possible.\n" + "If you performed a trial correctly, you will see a thumbs up at the bottom of the screen, as shown below \n \n" + "If you have any questions now or anytime during the experiment, please ask them straightaway.\n" + "If you need to take a break, please tell the experimenter so.\n \n" + "When you are ready to start the experiment, please tell the experimenter and we will start calibrating.\n" + "Good luck!") elif self.conditionOrderIndex > 0: self.label = QLabel( f"End of block {self.conditionOrderIndex}. You may now take a break if you wish to do so.\n" + "If you wish to carry on immediately, let the experimenter know.\n" + "If you have taken a break, please wait for the experimenter to start the calibration procedure." ) self.label.setStyleSheet("color:rgba(0, 0, 255, 200)") elif self.currentTrial > 1: nextTrial = f'Press space to continue to the next trial ({self.currentTrial} of {self.nTrials}).' # addText = f'\nFixation error last trial was {self.mean_error} ({self.sd_error}) degrees.' if timeOut: self.label = QLabel( f"You timed out. {nextTrial}") # {addText}") else: self.label = QLabel( f"End of trial. {nextTrial}") # {addText}") self.label.setFont(QFont("Times", 18)) self.label.setAlignment(Qt.AlignCenter | Qt.AlignHCenter) self.layout.addWidget(QLabel()) self.layout.addWidget(self.label) # Add an empty widget if trial was incorrect, otherwise show a thumbs up if timeOut: self.layout.addWidget(QLabel()) else: self.layout.addWidget(self.thumbsUp) self.installEventFilter(self) self.setLayout(self.layout) self.show() def initTask(self): self.inOpeningScreen = False self.images = pick_stimuli(self.allImages, self.nStimuli) self.grid = example_grid.generate_grid(self.images, self.nrow, self.ncol) self.shuffledImages = sample(self.images, len(self.images)) self.setConditionTiming( ) # Set slightly different timing for each trial self.fixationCrossSamples = [] self.fixationScreen() def continueInitTask(self): self.inFixationScreen = False # Create the actual task layout self.createMasterGrid() self.layout.addWidget(self.masterGrid) self.setLayout(self.layout) self.removeEventFilter(self) self.writeEvent('Task init') self.show() self.hourGlass.setVisible(False) self.runTimer() # ============================================================================= # GENERATE FIXATION CROSS. NOTE THAT THIS IS PURELY USED AS AN INDICATION FOR THE EXPERIMENTER # ============================================================================= def stopFixationScreen(self): self.fixTimer2.stop() self.mean_error, self.sd_error = calculateMeanError( self.fixationCrossSamples) self.writeEvent(f'Fixation cross error mean: {self.mean_error}') self.writeEvent(f'Fixation cross error sd: {self.sd_error}') print(f'Mean error = {self.mean_error}, SD error = {self.sd_error}') try: self.tracker.status_msg( f'Mean error = {self.mean_error}, SD error = {self.sd_error}') except: pass self.clearScreen() if self.mean_error < self.driftToleranceDeg: self.continueInitTask() else: self.driftWarningScreen() def updateFixationScreen(self): try: samp = self.tracker.sample() # Remove outliers that are very far from the center, as they're more likely a different issue than drift if (constants.DISPSIZE[0] * .2) < samp[0] < (constants.DISPSIZE[0] * .8): if (constants.DISPSIZE[1] * .2) < samp[1] < (constants.DISPSIZE[1] * .8): self.fixationCrossSamples.append(samp) except Exception as e: if self.inTrainingMode: # If in traning mode, pretend there is no tracker error samp = constants.SCREEN_CENTER else: # Otherwise, return np.nan to indicate an issue samp = np.nan # samp = (random.gauss(1280, 10), random.gauss(720, 10)) # Used for testing self.fixationCrossSamples.append(samp) def fixationScreen(self): self.inFixationScreen = True self.spacePushed = False self.layout.addWidget(self.fixationCross) self.setLayout(self.layout) self.show() self.fixTimer2.setInterval(2) self.fixTimer2.timeout.connect(self.updateFixationScreen) self.fixTimer2.start() self.fixTimer.singleShot(self.fixationCrossMs, self.stopFixationScreen) def driftWarningScreen(self): self.writeEvent('Showing drift warning') self.label = QLabel( "Warning: fixation error was greater than threshold.\n") # + # "Press 'backspace' to calibrate, 'r' to retry, or 'spacebar' to continue.") self.label.setFont(QFont("Times", 18)) self.label.setStyleSheet("color:rgba(255, 0, 0, 200)") self.label.setAlignment(Qt.AlignCenter | Qt.AlignHCenter) self.layout.addWidget(self.label) self.installEventFilter(self) self.setLayout(self.layout) self.show() # ============================================================================= # GENERATE GRIDS # ============================================================================= def createMasterGrid(self): self.masterGrid = QGroupBox("Grid", self) layout = QGridLayout() masterGridRows = 3 masterGridCols = 6 gridLocs = [(1, 1), (1, 4), (2, 4)] self.emptyGridLayout() for row in range(masterGridRows): for col in range(masterGridCols): if (row, col) not in gridLocs: layout.addWidget(self.emptyGridBox, row, col) self.exampleGridLayout() layout.addWidget(self.exampleGridBox, gridLocs[0][0], gridLocs[0][1]) self.copyGridLayout() layout.addWidget(self.copyGridBox, gridLocs[1][0], gridLocs[1][1]) self.resourceGridLayout() layout.addWidget(self.resourceGridBox, gridLocs[2][0], gridLocs[2][1]) self.emptyOutlineLayout() layout.addWidget(self.emptyOutline, gridLocs[0][0], gridLocs[0][1]) self.hourGlassLayout() layout.addWidget(self.hourGlass, gridLocs[0][0], gridLocs[0][1]) self.masterGrid.setLayout(layout) self.masterGrid.setTitle('') self.masterGrid.setStyleSheet(self.styleStr) def hourGlassLayout(self): path = Path(__file__).parent / 'pictograms' / 'hourglass.png' with open(path, 'rb') as f: im = f.read() image = QImage() image.loadFromData(im) image = image.scaledToWidth(75) self.hourGlass = QLabel() pixmap = QPixmap.fromImage(image) self.hourGlass.setPixmap(pixmap) self.hourGlass.setAlignment(QtCore.Qt.AlignCenter) self.hourGlass.setSizePolicy(self.sizePolicy) def emptyOutlineLayout(self): self.emptyOutline = QGroupBox("Grid", self) layout = QGridLayout() self.emptyOutline.setLayout(layout) self.emptyOutline.setTitle('') self.emptyOutline.setStyleSheet(self.styleStr) def emptyGridLayout(self): self.emptyGridBox = QGroupBox("Grid", self) layout = QGridLayout() self.emptyGridBox.setLayout(layout) self.emptyGridBox.setTitle('') self.emptyGridBox.setStyleSheet(self.styleStr + "; border:0px") def exampleGridLayout(self): self.exampleGridBox = QGroupBox("Grid", self) layout = QGridLayout() i = 0 for x in range(self.ncol): for y in range(self.nrow): label = QLabel(self) label.setFrameStyle(QFrame.Panel) if self.grid[x, y]: image = self.images[i] pixmap = QPixmap.fromImage(image.qimage) label.setPixmap(pixmap) label.setAlignment(QtCore.Qt.AlignCenter) label.setSizePolicy(self.sizePolicy) exampleDict = pd.DataFrame( { 'x': x, 'y': y, 'Name': '', 'shouldBe': image.name, 'Correct': False, 'Time': None, 'dragDuration': None, 'dragDistance': None, 'Trial': self.currentTrial, 'Condition': self.currentConditionIndex, 'visibleTime': self.visibleTime, 'cameFromX': None, 'cameFromY': None }, index=[0]) self.correctPlacements = self.correctPlacements.append( exampleDict, ignore_index=True) i += 1 layout.addWidget(label, y, x) # addWidget asks for (row, column) self.exampleGridBox.setLayout(layout) self.exampleGridBox.setTitle('') self.exampleGridBox.setSizePolicy(self.sizePolicy) self.exampleGridBox.setStyleSheet(self.styleStr) def copyGridLayout(self): self.copyGridBox = QGroupBox("Grid", self) layout = QGridLayout() i = 0 for x in range(self.ncol): for y in range(self.nrow): # Pass along the name of the intended images for this location if self.grid[x, y]: shouldBe = self.images[i].name i += 1 else: shouldBe = '' label = CustomLabel('', self, x, y, self.currentTrial, self.currentConditionIndex, shouldBe) label.setFrameStyle(QFrame.Panel) label.resize(self.imageWidth, self.imageWidth) label.setAlignment(QtCore.Qt.AlignCenter) label.setSizePolicy(self.sizePolicy) layout.addWidget(label, y, x) # addWidget asks for (row, column) self.copyGridBox.setLayout(layout) self.copyGridBox.setTitle('') self.copyGridBox.setStyleSheet(self.styleStr) def resourceGridLayout(self): self.resourceGridBox = QGroupBox("Grid", self) layout = QGridLayout() i = 0 row = 0 col = 0 for x in range(self.ncol): for y in range(self.nrow): if self.grid[x, y]: image = self.shuffledImages[i] label = DraggableLabel(self, image) # label.setFrameStyle(QFrame.Panel) # temp label.setAlignment(QtCore.Qt.AlignCenter) label.setSizePolicy(self.sizePolicy) if i % self.ncol == 0: row += 1 col = 0 layout.addWidget(label, row, col) # addWidget asks for (row, column) i += 1 col += 1 self.resourceGridBox.setLayout(layout) self.resourceGridBox.setTitle('') self.resourceGridBox.setSizePolicy(self.sizePolicy) self.resourceGridBox.setStyleSheet(self.styleStr)
def mousePressEvent(self, event): self.mousePos = QCursor.pos()
def on_copy(self): self.app.clipboard().setText(self.text()) QToolTip.showText(QCursor.pos(), _("Text copied to clipboard"), self)
def bookmark_table_context_menu_event(self): """Context menu for bookmark table right click""" self.bookmark_menu.popup(QCursor.pos())