def __move_to_systray(self): """ update the window position to be centered under the system tray icon """ geo = self.systray.geometry() self.__logger.debug("__move_to_systray: systray_geo: %s" % geo) side = self._guess_toolbar_side() if side != self.__class__: # anchor needs to be updated self._set_window_mask() if side == self.DOCK_TOP: x = geo.x() + (geo.width() - self.rect().width()) / 2.0 pos = QtCore.QPoint(x, geo.y() + geo.height()) elif side == self.DOCK_LEFT: y = geo.y() + (geo.height() - self.rect().height()) / 2.0 pos = QtCore.QPoint(geo.x() + geo.width(), y) elif side == self.DOCK_RIGHT: y = geo.y() + (geo.height() - self.rect().height()) / 2.0 pos = QtCore.QPoint(geo.x() - self.rect().width(), y) elif side == self.DOCK_BOTTOM: x = geo.x() + (geo.width() - self.rect().width()) / 2.0 pos = QtCore.QPoint(x, geo.y() - self.rect().height() - geo.height()) else: raise ValueError("Unknown value for side: %s" % side) self.move(pos)
def paint(self, painter, style_options, model_index): """ Paint method to handle all cells that are not being currently edited. """ if model_index != self.__current_editor_index: # for performance reasons, we are not creating a widget every time # but merely moving the same widget around. # first call out to have the widget set the right values self._on_before_paint(self.__paint_widget, model_index, style_options) # now paint! painter.save() self.__paint_widget.resize(style_options.rect.size()) painter.translate(style_options.rect.topLeft()) # note that we set the render flags NOT to render the background of the widget # this makes it consistent with the way the editor widget is mounted inside # each element upon hover. # WEIRD! It seems pyside and pyqt actually have different signatures for this method if USING_PYQT: # pyqt is using the flags parameter, which seems inconsistent with QT # http://pyqt.sourceforge.net/Docs/PyQt4/qwidget.html#render self.__paint_widget.render(painter, QtCore.QPoint(0,0), QtGui.QRegion(), QtGui.QWidget.DrawChildren) else: # pyside is using the renderFlags parameter which seems correct self.__paint_widget.render(painter, QtCore.QPoint(0,0), renderFlags=QtGui.QWidget.DrawChildren) painter.restore()
def show(self, pos=None): pos = QtGui.QCursor.pos() if pos is None else QtCore.QPoint( pos[0], pos[1]) self._handle.activateWindow() self._handle.raise_() self._handle.exec_(pos)
def position_minicut(self): p = self._tray.tray_mini_label.pos() s = self._mini_button.size() y = s.height() + p.y() + 15 p2 = QtCore.QPoint(p.x() - 100, y) self.move(p2) self.raise_()
def _on_right_arrow_click(self): """ User clicks the right arrow """ start_index = self.ui.stackedWidget.currentIndex() next_index = start_index + 1 if next_index == (self._num_images - 1): # we arrived at the last slide! Hide right arrow self.ui.right_arrow.setVisible(False) self.ui.left_arrow.setVisible(True) else: self.ui.right_arrow.setVisible(True) self.ui.left_arrow.setVisible(True) this_page = self._pages[start_index] next_page = self._pages[next_index] # rest positions next_page.move(next_page.x()+650, next_page.y()) self.ui.stackedWidget.setCurrentIndex(next_index) this_page.show() this_page.raise_() self.anim = QtCore.QPropertyAnimation(this_page, "pos") self.anim.setDuration(600) self.anim.setStartValue(QtCore.QPoint(this_page.x(), this_page.y())) self.anim.setEndValue(QtCore.QPoint(this_page.x()-650, this_page.y())) self.anim.setEasingCurve(QtCore.QEasingCurve.OutCubic) self.anim2 = QtCore.QPropertyAnimation(next_page, "pos") self.anim2.setDuration(600) self.anim2.setStartValue(QtCore.QPoint(next_page.x()+650, next_page.y())) self.anim2.setEndValue(QtCore.QPoint(next_page.x(), next_page.y())) self.anim2.setEasingCurve(QtCore.QEasingCurve.OutCubic) self.grp = QtCore.QParallelAnimationGroup() self.grp.addAnimation(self.anim) self.grp.addAnimation(self.anim2) self.grp.start()
def show(self, pos=None): pos = (QtGui.QCursor.pos() if pos is None else QtCore.QPoint( pos[0], pos[1])) qApp = QtGui.QApplication.instance() self.menu_handle.activateWindow() self.menu_handle.raise_() qApp.processEvents() self.menu_handle.exec_(pos)
def slide_view(self, new_page, from_direction="right"): offsetx = self.ui.stack.frameRect().width() offsety = self.ui.stack.frameRect().height() current_page = self.ui.stack.currentWidget() new_page.setGeometry(0, 0, offsetx, offsety) if from_direction == "left": offsetx = -offsetx curr_pos = new_page.pos() new_page.move(curr_pos.x() + offsetx, curr_pos.y()) new_page.show() new_page.raise_() anim_old = QtCore.QPropertyAnimation(current_page, "pos", self) anim_old.setDuration(500) anim_old.setStartValue(QtCore.QPoint(curr_pos.x(), curr_pos.y())) anim_old.setEndValue( QtCore.QPoint(curr_pos.x() - offsetx, curr_pos.y())) anim_old.setEasingCurve(QtCore.QEasingCurve.OutBack) anim_new = QtCore.QPropertyAnimation(new_page, "pos", self) anim_new.setDuration(500) anim_new.setStartValue( QtCore.QPoint(curr_pos.x() + offsetx, curr_pos.y())) anim_new.setEndValue(QtCore.QPoint(curr_pos.x(), curr_pos.y())) anim_new.setEasingCurve(QtCore.QEasingCurve.OutBack) anim_group = QtCore.QParallelAnimationGroup(self) anim_group.addAnimation(anim_old) anim_group.addAnimation(anim_new) def slide_finished(): self.ui.stack.setCurrentWidget(new_page) anim_group.finished.connect(slide_finished) anim_group.start()
def _load_settings(self): # last window position pos = self._settings_manager.retrieve( "pos", QtCore.QPoint(200, 200), self._settings_manager.SCOPE_SITE) self.move(pos) # Force update so the project selection happens if the window is shown by default QtGui.QApplication.processEvents() # load up last project project_id = self._settings_manager.retrieve( "project_id", 0, self._settings_manager.SCOPE_SITE) self.__set_project_from_id(project_id) # settings that apply across any instance (after site specific, so pinned can reset pos) self.set_on_top(self._settings_manager.retrieve("on_top", False)) # always start pinned and hidden self.state = self.STATE_PINNED
def paintEvent(self, event): """ Render the UI. """ if self._mode == self.MODE_OFF: return painter = QtGui.QPainter() painter.begin(self) try: # set up semi transparent backdrop overlay_color = QtGui.QColor("#1B1B1B") painter.setBrush(QtGui.QBrush(overlay_color)) painter.setPen(QtGui.QPen(overlay_color)) painter.drawRect(0, 0, painter.device().width(), painter.device().height()) if self._mode == self.MODE_INFO_TEXT: # show text in the middle pen = QtGui.QPen(QtGui.QColor("#888888")) painter.setPen(pen) text_rect = QtCore.QRect(0, 0, painter.device().width(), painter.device().height()) text_flags = QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter | QtCore.Qt.TextWordWrap painter.drawText(text_rect, text_flags, self._message) elif self._mode == self.MODE_ERROR: # show error text in the center pen = QtGui.QPen(QtGui.QColor("#C8534A")) painter.setPen(pen) text_rect = QtCore.QRect(0, 0, painter.device().width(), painter.device().height()) text_flags = QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter | QtCore.Qt.TextWordWrap painter.drawText(text_rect, text_flags, self._message) elif self._mode == self.MODE_INFO_PIXMAP: # draw image painter.translate((painter.device().width() / 2) - (self._message_pixmap.width() / 2), (painter.device().height() / 2) - (self._message_pixmap.height() / 2)) painter.drawPixmap(QtCore.QPoint(0, 0), self._message_pixmap) finally: painter.end() return super(ShotgunOverlayWidget, self).paintEvent(event)
def _draw_opened_circle(self, painter, start_angle, span_angle): """ Draws an arc around the SG logo. :param painter: Painter object we will draw with. :param start_angle: Angle at which we will start drawing the arc. :param span_angle: Degrees the arc covers. """ # show the spinner painter.translate((painter.device().width() / 2) - 40, (painter.device().height() / 2) - 40) pen = QtGui.QPen(QtGui.QColor("#424141")) pen.setWidth(3) painter.setPen(pen) painter.drawPixmap(QtCore.QPoint(8, 24), self._sg_icon) r = QtCore.QRectF(0.0, 0.0, 80.0, 80.0) # drawArc accepts 1/16th on angles. painter.drawArc(r, start_angle * 16, span_angle * 16)
def __turn_page(self, direction=NEXT_PAGE): """ Turn the page in the direction specified :param direction: The direction to turn the page """ current_index = self.ui.stackedWidget.currentIndex() dst_index = current_index page_offset = 650 # depending on the direction, figure out the destination page # and page offset for animation: if direction == Dialog.NEXT_PAGE: dst_index += 1 page_offset = 650 # update the arrow visibility so that the right arrow is # hidden if we're on the last page: self.ui.right_arrow.setVisible(dst_index < (self._num_images - 1)) self.ui.left_arrow.setVisible(True) else: # going back a page dst_index -= 1 page_offset = -650 # update the arrow visibility so that the left arrow is # hidden if we're on the first page: self.ui.right_arrow.setVisible(True) self.ui.left_arrow.setVisible(dst_index > 0) if not hasattr(QtCore, "QAbstractAnimation"): # this version of Qt (probably PyQt4) doesn't contain # Q*Animation classes so just change the page: self.ui.stackedWidget.setCurrentIndex(dst_index) else: anim_duration = 600 # milliseconds if self.__page_anim_grp and self.__page_anim_grp.state( ) == QtCore.QAbstractAnimation.Running: # the previous animation hasn't finished yet so jump to the end! self.__page_anim_grp.setCurrentTime(anim_duration) # animate the transition from one page to the next: current_page = self._pages[current_index] dst_page = self._pages[dst_index] # reset positions dst_page.move(dst_page.x() + page_offset, dst_page.y()) self.ui.stackedWidget.setCurrentIndex(dst_index) # still need to show the current page whilst it transitions current_page.show() current_page.raise_() # animate the current page away self.__anim = QtCore.QPropertyAnimation(current_page, "pos") self.__anim.setDuration(anim_duration) self.__anim.setStartValue( QtCore.QPoint(current_page.x(), current_page.y())) self.__anim.setEndValue( QtCore.QPoint(current_page.x() - page_offset, current_page.y())) self.__anim.setEasingCurve(QtCore.QEasingCurve.OutCubic) # animate the new page in: self.__anim2 = QtCore.QPropertyAnimation(dst_page, "pos") self.__anim2.setDuration(anim_duration) self.__anim2.setStartValue( QtCore.QPoint(dst_page.x() + page_offset, dst_page.y())) self.__anim2.setEndValue(QtCore.QPoint(dst_page.x(), dst_page.y())) self.__anim2.setEasingCurve(QtCore.QEasingCurve.OutCubic) # create a parallel animation group so that both pages animate at # the same time: self.__page_anim_grp = QtCore.QParallelAnimationGroup() self.__page_anim_grp.addAnimation(self.__anim) self.__page_anim_grp.addAnimation(self.__anim2) # run the animation/transition self.__page_anim_grp.start()
def paintEvent(self, event): """ Render the UI. """ if self._mode == self.MODE_OFF: return painter = QtGui.QPainter() painter.begin(self) try: # set up semi transparent backdrop painter.setRenderHint(QtGui.QPainter.Antialiasing) overlay_color = QtGui.QColor("#1B1B1B") painter.setBrush(QtGui.QBrush(overlay_color)) painter.setPen(QtGui.QPen(overlay_color)) painter.drawRect(0, 0, painter.device().width(), painter.device().height()) # now draw different things depending on mode if self._mode == self.MODE_SPIN: # show the spinner painter.translate((painter.device().width() / 2) - 40, (painter.device().height() / 2) - 40) pen = QtGui.QPen(QtGui.QColor("#424141")) pen.setWidth(3) painter.setPen(pen) painter.drawPixmap(QtCore.QPoint(8, 24), self._sg_icon) r = QtCore.QRectF(0.0, 0.0, 80.0, 80.0) start_angle = (0 + self._spin_angle) * 4 * 16 span_angle = 340 * 16 painter.drawArc(r, start_angle, span_angle) elif self._mode == self.MODE_INFO_TEXT: # show text in the middle pen = QtGui.QPen(QtGui.QColor("#888888")) painter.setPen(pen) text_rect = QtCore.QRect(0, 0, painter.device().width(), painter.device().height()) text_flags = QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter | QtCore.Qt.TextWordWrap painter.drawText(text_rect, text_flags, self._message) elif self._mode == self.MODE_ERROR: # show error text in the center pen = QtGui.QPen(QtGui.QColor("#C8534A")) painter.setPen(pen) text_rect = QtCore.QRect(0, 0, painter.device().width(), painter.device().height()) text_flags = QtCore.Qt.AlignCenter | QtCore.Qt.AlignVCenter | QtCore.Qt.TextWordWrap painter.drawText(text_rect, text_flags, self._message) elif self._mode == self.MODE_INFO_PIXMAP: # draw image painter.translate((painter.device().width() / 2) - (self._message_pixmap.width() / 2), (painter.device().height() / 2) - (self._message_pixmap.height() / 2)) painter.drawPixmap(QtCore.QPoint(0, 0), self._message_pixmap) finally: painter.end()
def _set_window_mask(self): """ set the window mask when pinned to the systray """ if self.state == self.STATE_WINDOWED: self.__content_layout.setContentsMargins(0, 0, 0, 0) self.clearMask() return # temp bitmap to store the mask bmp = QtGui.QBitmap(self.size()) # create and configure the painter self.painter = QtGui.QPainter(bmp) self.painter.setRenderHint(QtGui.QPainter.HighQualityAntialiasing, True) # figure out what side to draw the anchor on side = self._guess_toolbar_side() # mask out from the top margin of the border_layout rect = self.rect() # make sure there is room to draw the anchor anchor_height = self.__bottom_anchor.height() if self.__content_layout is not None: if side == self.DOCK_TOP: mask = rect.adjusted(0, anchor_height, 0, 0) self.__content_layout.setContentsMargins( 0, anchor_height, 0, 0) elif side == self.DOCK_LEFT: mask = rect.adjusted(anchor_height, 0, 0, 0) self.__content_layout.setContentsMargins( anchor_height, 0, 0, 0) elif side == self.DOCK_RIGHT: mask = rect.adjusted(0, 0, -anchor_height, 0) self.__content_layout.setContentsMargins( 0, 0, -anchor_height, 0) elif side == self.DOCK_BOTTOM: mask = rect.adjusted(0, 0, 0, -anchor_height) self.__content_layout.setContentsMargins( 0, 0, 0, anchor_height) else: raise ValueError("Unknown value for side: %s" % side) self.painter.fillRect(rect, QtCore.Qt.white) self.painter.setBrush(QtCore.Qt.black) self.painter.drawRoundedRect(mask, self.__corner_radius, self.__corner_radius) if self.state == self.STATE_PINNED: # add back in the anchor triangle points = [] mask_center = mask.center() if side == self.DOCK_TOP: anchor_pixmap = self.__top_anchor anchor_center = anchor_pixmap.rect().center() points.append(QtCore.QPoint(mask_center.x(), rect.top())) points.append( QtCore.QPoint(mask_center.x() - anchor_height, mask.top())) points.append( QtCore.QPoint(mask_center.x() + anchor_height, mask.top())) elif side == self.DOCK_LEFT: anchor_pixmap = self.__left_anchor anchor_center = anchor_pixmap.rect().center() points.append(QtCore.QPoint(rect.left(), mask_center.y())) points.append( QtCore.QPoint(mask.left(), mask_center.y() - anchor_center.y())) points.append( QtCore.QPoint(mask.left(), mask_center.y() + anchor_center.y())) elif side == self.DOCK_RIGHT: anchor_pixmap = self.__right_anchor anchor_center = anchor_pixmap.rect().center() points.append( QtCore.QPoint(mask.right(), mask_center.y() + anchor_center.y())) points.append( QtCore.QPoint(mask.right(), mask_center.y() - anchor_center.y())) points.append(QtCore.QPoint(rect.right(), mask_center.y())) elif side == self.DOCK_BOTTOM: anchor_pixmap = self.__bottom_anchor anchor_center = anchor_pixmap.rect().center() points.append( QtCore.QPoint(mask_center.x() - anchor_height, mask.bottom())) points.append( QtCore.QPoint(mask_center.x() + anchor_height, mask.bottom())) points.append(QtCore.QPoint(mask_center.x(), rect.bottom())) else: raise ValueError("Unknown value for side: %s" % side) self.painter.drawPolygon(points) # need to end the painter to make sure that its resources get # garbage collected before the bitmap to avoid a crash self.painter.end() # finally set the window mask to the bitmap self.setMask(bmp) self.__anchor_side = side