def testArrowContact(self, indices, x, y): if type(indices) != list: indices = [indices] for index in indices: if index >= len(self.attributes) or index < 0: continue int_x = self.transform(xBottom, index) bottom = self.transform( yLeft, self.selection_conditions.get(self.attributes[index], [0, 1])[0]) bottom_rect = QRect(int_x - self.bottom_pixmap.width() / 2, bottom, self.bottom_pixmap.width(), self.bottom_pixmap.height()) if bottom_rect.contains(QPoint(x, y)): return 1, (index, 0) top = self.transform( yLeft, self.selection_conditions.get(self.attributes[index], [0, 1])[1]) top_rect = QRect(int_x - self.top_pixmap.width() / 2, top - self.top_pixmap.height(), self.top_pixmap.width(), self.top_pixmap.height()) if top_rect.contains(QPoint(x, y)): return 1, (index, 1) return 0, (0, 0)
def mouseMoveEvent(self, event): '''Overrides QWidget's mouseMoveEvent. Handles resizing and dragging operations on selection''' # pylint: disable=C0103 sel_rect = self._selection_rect if self._resize_start: resize_end = event.pos() / self._zoom sel_rect.setBottomRight(sel_rect.bottomRight() + (resize_end - self._resize_start)) self._resize_start = resize_end self.make_selection_square() self.update() elif self._drag_start is not None: drag_end = event.pos() / self._zoom sel_rect.translate(drag_end - self._drag_start) self._drag_start = drag_end self.update() # cursor shape: mouse_pos = event.pos() / self._zoom if (not sel_rect.isNull()) and sel_rect.contains(mouse_pos, True): handle_rect = QRect(sel_rect.bottomRight(), self._handle_size) if handle_rect.contains(mouse_pos): self.setCursor(Qt.SizeFDiagCursor) else: self.setCursor(Qt.OpenHandCursor) else: self.setCursor(Qt.CrossCursor)
def __autoScrollAdvance(self): """Advance the auto scroll """ pos = QCursor.pos() pos = self.mapFromGlobal(pos) margin = self.__autoScrollMargin vvalue = self.verticalScrollBar().value() hvalue = self.horizontalScrollBar().value() vrect = QRect(0, 0, self.width(), self.height()) # What should be the speed advance = 10 # We only do auto scroll if the mouse is inside the view. if vrect.contains(pos): if pos.x() < vrect.left() + margin: self.horizontalScrollBar().setValue(hvalue - advance) if pos.y() < vrect.top() + margin: self.verticalScrollBar().setValue(vvalue - advance) if pos.x() > vrect.right() - margin: self.horizontalScrollBar().setValue(hvalue + advance) if pos.y() > vrect.bottom() - margin: self.verticalScrollBar().setValue(vvalue + advance) if self.verticalScrollBar().value() == vvalue and \ self.horizontalScrollBar().value() == hvalue: self.__stopAutoScroll() else: self.__stopAutoScroll() log.debug("Auto scroll advance")
def mouseReleaseEvent(self, event): """ Обрабатываем нажатие на иконку 'Интересно/Скучно' как нажатие на обычный чекбокс Решение достаточно грубое, но в данной ситуации вполне себе работает. Перехватывать нужно отпускание мыши, потому что в QAbstractItemView редактирование запускается именно по отпусканию. """ if event.pos().x() < settings.entryIconWidth(): item = self.itemAt(event.pos()) item.setSelected(True) rect = self.visualItemRect(item) iconRect = QRect(rect.left(), rect.top(), settings.entryIconWidth(), settings.entryIconHeight()) if iconRect.contains(event.pos()): if item.checkState() == Qt.Checked: item.setCheckState(Qt.Unchecked) else: item.setCheckState(Qt.Checked) else: QListWidget.mousePressEvent(self, event)
def mouseMoveEvent (self, event): '''Overrides QWidget's mouseMoveEvent. Handles resizing and dragging operations on selection''' # pylint: disable=C0103 sel_rect = self._selection_rect if self._resize_start: resize_end = event.pos() / self._zoom sel_rect.setBottomRight(sel_rect.bottomRight() + (resize_end - self._resize_start)) self._resize_start = resize_end self.make_selection_square() self.update() elif self._drag_start is not None: drag_end = event.pos() / self._zoom sel_rect.translate(drag_end - self._drag_start) self._drag_start = drag_end self.update() # cursor shape: mouse_pos = event.pos() / self._zoom if (not sel_rect.isNull()) and sel_rect.contains(mouse_pos, True): handle_rect = QRect(sel_rect.bottomRight(), self._handle_size) if handle_rect.contains(mouse_pos): self.setCursor(Qt.SizeFDiagCursor) else: self.setCursor(Qt.OpenHandCursor) else: self.setCursor(Qt.CrossCursor)
def _dropEvent(self, partition, pos): for block in self._accepted_blocks: bpos = self.parentWidget().mapToGlobal(block.pos()) bpos = QRect(bpos, block.size()) if bpos.contains(pos): print 'Partition "%s" from "%s" dropped on the block "%s"' % \ (partition.text(), partition.parentWidget()._name, block._name) for _partition in block._partitions: bpos = _partition.parentWidget().mapToGlobal(_partition.pos()) rect = QRect(bpos, _partition.size()) if rect.contains(pos, proper = True): print 'Partition "%s" dropped on the partition "%s (%s-%s)"' % \ (partition.text(), _partition.text(), _partition._fs_type, _partition._size) if _partition._fs_type == FREE and _partition._size >= partition._size: print 'It is ok to create a new partition !' block.updatePartition(_partition, partition) self.deletePartition(partition, fillFree = True) break
def testArrowContact(self, indices, x, y): if type(indices) != list: indices = [indices] for index in indices: if index >= len(self.attributes) or index < 0: continue int_x = self.transform(xBottom, index) bottom = self.transform(yLeft, self.selection_conditions.get(self.attributes[index], [0, 1])[0]) bottom_rect = QRect(int_x - self.bottom_pixmap.width() / 2, bottom, self.bottom_pixmap.width(), self.bottom_pixmap.height()) if bottom_rect.contains(QPoint(x, y)): return 1, (index, 0) top = self.transform(yLeft, self.selection_conditions.get(self.attributes[index], [0, 1])[1]) top_rect = QRect(int_x - self.top_pixmap.width() / 2, top - self.top_pixmap.height(), self.top_pixmap.width(), self.top_pixmap.height()) if top_rect.contains(QPoint(x, y)): return 1, (index, 1) return 0, (0, 0)
def mousePressEvent(self, event): if event.button() != Qt.LeftButton: return size = self.height() / 2.0 rect = QRect(self.width() - size, size * 0.5, size, size) if rect.contains(event.pos()): self.clear() self.valid = True event.accept()
def mouseMoveEvent(self, event): if self._interaction.moving: mouse_position = event.globalPos() offset = mouse_position - self._interaction.mouse_last_position if self.parent() is not None: parent_rect = self.parent().rect() old_geometry = self.geometry() new_geometry = old_geometry.translated(offset) if new_geometry.left() < 0: new_geometry.moveLeft(0) if new_geometry.top() < 0: new_geometry.moveTop(0) if new_geometry.right() > parent_rect.right(): new_geometry.moveRight(parent_rect.right()) if new_geometry.bottom() > parent_rect.bottom(): new_geometry.moveBottom(parent_rect.bottom()) offset = new_geometry.topLeft() - old_geometry.topLeft() self.move(self.pos() + offset) self._interaction.mouse_last_position += offset elif self._interaction.resizing: mouse_position = event.globalPos() delta_y = mouse_position.y() - self._interaction.mouse_last_position.y() geometry = self.geometry() if self._interaction.resize_corner is self.TopLeftCorner: delta_x = -(self.width_for_height(geometry.height() - delta_y) - geometry.width()) geometry.setTopLeft(geometry.topLeft() + QPoint(delta_x, delta_y)) elif self._interaction.resize_corner is self.TopRightCorner: delta_x = (self.width_for_height(geometry.height() - delta_y) - geometry.width()) geometry.setTopRight(geometry.topRight() + QPoint(delta_x, delta_y)) elif self._interaction.resize_corner is self.BottomLeftCorner: delta_x = -(self.width_for_height(geometry.height() + delta_y) - geometry.width()) geometry.setBottomLeft(geometry.bottomLeft() + QPoint(delta_x, delta_y)) else: delta_x = (self.width_for_height(geometry.height() + delta_y) - geometry.width()) geometry.setBottomRight(geometry.bottomRight() + QPoint(delta_x, delta_y)) if self.minimumHeight() <= geometry.height() <= self.maximumHeight() and (self.parent() is None or self.parent().rect().contains(geometry)): self.setGeometry(geometry) self._interaction.mouse_last_position = mouse_position elif self.interactive: mouse_position = event.pos() topbar_rect = QRect(0, 0, self.width(), 10) if self.rect().adjusted(0, 10, 0, -10).contains(mouse_position): self.setCursor(Qt.ArrowCursor) elif topbar_rect.contains(mouse_position): self.setCursor(self.cursors.resize_top) else: self.setCursor(self.cursors.resize_bottom)
def replace(self): log.trace("Icon is %r", self._icon) self._icon_geometry = rect = self._icon.geometry() log.trace("IconRect is : %s,%s | %s,%s", rect.x(), rect.y(), rect.width(), rect.height()) from PyQt4.QtGui import QApplication, QCursor from PyQt4.QtCore import QRect desktop = QApplication.desktop() log.trace("Screen id is %d", desktop.screenNumber(rect.topLeft())) desk = desktop.screenGeometry(desktop.screenNumber(rect.topLeft())) log.trace("ScreenRect is : %s,%s | %s,%s", desk.x(), desk.y(), desk.width(), desk.height()) pos = QCursor.pos() log.trace("Cursor is : %s,%s", pos.x(), pos.y()) # Make our calculation on a offset screen to 0/0 rect = QRect(rect.x() - desk.x(), rect.y() - desk.y(), rect.width(), rect.height()) pos.setX(pos.x() - desk.x()) pos.setY(pos.y() - desk.y()) if not rect.contains(pos) or (rect.x() == 0 and rect.y() == 0): # Avoid any modulo 0 if rect.width() == 0 or rect.height() == 0: rect = QRect(pos.x(), pos.y(), rect.width(), rect.height()) else: rect = QRect(pos.x() - pos.x() % rect.width(), pos.y() - pos.y() % rect.height(), rect.width(), rect.height()) log.trace("Adjusting X/Y to %d/%d", rect.x(), rect.y()) pos = rect self._icon_geometry = QRect(rect.x() + desk.x(), rect.y() + desk.y(), rect.width(), rect.height()) log.trace("New rect is : %s,%s | %s,%s", pos.x(), pos.y(), pos.width(), pos.height()) x = rect.x() + rect.width() - self.width() y = rect.y() - self.height() # Prevent the systray to be hidden if y < 0: y = rect.y() + rect.height() if x < 0: x = rect.x() # Use the offset again x += desk.x() y += desk.y() log.trace("Move systray menu to %d/%d", x, y) self.move(x, y)
def mousePressEvent (self, event): '''Overrides QWidget's mousePressEvent. Handles starting a new selection, starting a drag operation''' # pylint: disable=C0103 mouse_pos = event.pos() / self._zoom sel_rect = self._selection_rect if not event.button() == Qt.LeftButton: return if (not sel_rect.isNull()) and sel_rect.contains(mouse_pos, True): handle_rect = QRect(sel_rect.bottomRight(), self._handle_size) if handle_rect.contains(mouse_pos): self._resize_start = mouse_pos else: self._drag_start = mouse_pos else: self._resize_start = mouse_pos sel_rect.setTopLeft (mouse_pos) self._selection_rect.setSize(QSize(0, 0))
def mousePressEvent(self, event): '''Overrides QWidget's mousePressEvent. Handles starting a new selection, starting a drag operation''' # pylint: disable=C0103 mouse_pos = event.pos() / self._zoom sel_rect = self._selection_rect if not event.button() == Qt.LeftButton: return if (not sel_rect.isNull()) and sel_rect.contains(mouse_pos, True): handle_rect = QRect(sel_rect.bottomRight(), self._handle_size) if handle_rect.contains(mouse_pos): self._resize_start = mouse_pos else: self._drag_start = mouse_pos else: self._resize_start = mouse_pos sel_rect.setTopLeft(mouse_pos) self._selection_rect.setSize(QSize(0, 0))
def replace(self): log.trace("Icon is %r", self._icon) self._icon_geometry = rect = self._icon.geometry() log.trace("IconRect is : %s,%s | %s,%s",rect.x(), rect.y(), rect.width(), rect.height()) from PyQt4.QtGui import QApplication, QCursor from PyQt4.QtCore import QRect desktop = QApplication.desktop() log.trace("Screen id is %d", desktop.screenNumber(rect.topLeft())) desk = desktop.screenGeometry(desktop.screenNumber(rect.topLeft())) log.trace("ScreenRect is : %s,%s | %s,%s",desk.x(), desk.y(), desk.width(), desk.height()) pos = QCursor.pos() log.trace("Cursor is : %s,%s",pos.x(), pos.y()) # Make our calculation on a offset screen to 0/0 rect = QRect(rect.x()-desk.x(), rect.y()-desk.y(), rect.width(), rect.height()) pos.setX(pos.x()-desk.x()) pos.setY(pos.y()-desk.y()) if not rect.contains(pos) or (rect.x() == 0 and rect.y() == 0): # Avoid any modulo 0 if rect.width() == 0 or rect.height() == 0: rect = QRect(pos.x(), pos.y(), rect.width(), rect.height()) else: rect = QRect(pos.x()-pos.x()%rect.width(), pos.y()-pos.y()%rect.height(), rect.width(), rect.height()) log.trace("Adjusting X/Y to %d/%d", rect.x(), rect.y()) pos = rect self._icon_geometry = QRect(rect.x()+desk.x(), rect.y()+desk.y(), rect.width(), rect.height()) log.trace("New rect is : %s,%s | %s,%s",pos.x(), pos.y(), pos.width(), pos.height()) x = rect.x() + rect.width() - self.width() y = rect.y() - self.height() # Prevent the systray to be hidden if y < 0: y = rect.y() + rect.height() if x < 0: x = rect.x() # Use the offset again x += desk.x() y += desk.y() log.trace("Move systray menu to %d/%d", x, y) self.move(x, y)
def mouseReleaseEvent(self, event): """ Обрабатываем нажатие на иконку 'Интересно/Скучно' как нажатие на обычный чекбокс Решение достаточно грубое, но в данной ситуации вполне себе работает. Перехватывать нужно отпускание мыши, потому что в QAbstractItemView редактирование запускается именно по отпусканию. """ item = self.itemAt(event.pos()) if self._itemIsCategory(item) and event.pos().x() < 20: item.setExpanded(not item.isExpanded()) elif item is not None and event.pos().x() < settings.entryIconWidth(): item.setSelected(True) rect = self.visualItemRect(item) iconRect = QRect(rect.left(), rect.top() + (rect.height() - settings.entryIconHeight()) / 2, settings.entryIconWidth(), settings.entryIconHeight()) if iconRect.contains(event.pos()): self._invertItemCheckState(item) else: QTreeWidget.mouseReleaseEvent(self, event)
class LegendWidget(legend_widget, QWidget): showmap = pyqtSignal() def __init__(self, parent=None): super(LegendWidget, self).__init__(parent) self.setupUi(self) self.pixmap = QPixmap() self.items = {} self.framerect = QRect() self._lastextent = None self.legendareabrush = QBrush(QColor(255,255,255,200)) self.legendareapen = QPen(QColor(255,255,255,20)) self.legendareapen.setWidth(0.5) def paintEvent(self, event): def itemlist(items): for layer, items in self.items.iteritems(): if len(items) == 1: yield layer, items[0][1] else: for text, icon in items: if not text: continue yield text, icon def _drawitem(pixmap, text, itempostion): painter.drawPixmap(itempostion, pixmap) textrect = QRectF(pixmap.width() + currentx + 10, itempostion.y(), event.rect().width() - pixmap.width() - OFFSET_X, pixmap.height()) painter.drawText(textrect, text, QTextOption(Qt.AlignVCenter)) def calcitems(): font = painter.font() metrices = QFontMetrics(font) maxwidth = 0 maxheight = 0 for item, _ in itemlist(self.items): maxwidth = max(metrices.boundingRect(item).width(), maxwidth) maxheight = max(metrices.boundingRect(item).height(), maxheight) return maxwidth, maxheight if not self.pixmap: return painter = QPainter(self) painter.setRenderHints(QPainter.Antialiasing) painter.drawPixmap(event.rect(), self.pixmap) itemwidths, itemmaxheight = calcitems() OFFSET_X = 30 OFFSET_Y = itemmaxheight + 10 rect = event.rect() neededheight = (len(self.items) * OFFSET_Y) runs = 1 if neededheight > rect.height(): import math runs = math.ceil(neededheight / float(rect.height())) print runs framerect = QRect(rect) framewidth = (itemwidths + OFFSET_X + ICON_SIZE.width() + 100) * runs framerect.setWidth(framewidth) painter.setBrush(self.legendareabrush) painter.setPen(self.legendareapen) painter.drawRect(framerect) self.framerect = framerect painter.setPen(Qt.black) currenty = OFFSET_Y currentx = OFFSET_X position = rect.topLeft() + QPoint(OFFSET_X, currenty) for text, icon in itemlist(self.items): itempostion = QPoint(position) if currenty > rect.height(): currentx = itemwidths + OFFSET_X + 100 currenty = itemmaxheight + 10 itempostion.setX(currentx) itempostion.setY(currenty) _drawitem(icon, text, itempostion) currenty += OFFSET_Y position.setY(currenty + OFFSET_Y) def mousePressEvent(self, event): if self.framerect.contains(event.pos()): return self.showmap.emit() def updateitems(self, layers): self.items = {} for layer in layers: if not layer.type() == QgsMapLayer.VectorLayer: continue try: items = layer.rendererV2().legendSymbologyItems(ICON_SIZE) except AttributeError: continue self.items[layer.name()] = items self.update() def updatecanvas(self, canvas): """ Update the canvas object for the legend background. """ if canvas.isDrawing() or self._lastextent == canvas.extent(): return self._lastextent = canvas.extent() pixmap = QPixmap(self.size()) pixmap.fill(canvas.canvasColor()) painter = QPainter(pixmap) painter.setRenderHints(QPainter.Antialiasing) renderer = canvas.mapRenderer() renderer.render(painter) del painter self.pixmap = pixmap self.update()
class VispaWidgetOwner(object): """ Interface for classes containing VispaWidgets Only makes sense if implementing class also inherits QWidget or class inheriting QWidget. """ def enableMultiSelect(self, multiSelect=True): self._multiSelectEnabledFlag = multiSelect def multiSelectEnabled(self): return hasattr( self, "_multiSelectEnabledFlag") and self._multiSelectEnabledFlag def selectedWidgets(self): """ Returns a list of all selected widgets. """ if hasattr(self, "_selectedWidgets"): return self._selectedWidgets return [ child for child in self.children() if hasattr(child, "isSelected") and child.isSelected() ] def widgetSelected(self, widget, multiSelect=False): """ Forward selection information to super class if it is a VispaWidgetOwner. """ logging.debug(self.__class__.__name__ + ": widgetSelected()") if isinstance(self, QObject): if not hasattr(self, "_selectedWidgets"): self._selectedWidgets = [] if not multiSelect or not self.multiSelectEnabled(): self.deselectAllWidgets(widget) self._selectedWidgets = [] if widget.parent() == self and not widget in self._selectedWidgets: self._selectedWidgets.append(widget) for widget in [ child for child in self._selectedWidgets if hasattr(child, "isSelected") and not child.isSelected() ]: self._selectedWidgets.remove(widget) if isinstance(self.parent(), VispaWidgetOwner): self.parent().widgetSelected(widget) def widgetDoubleClicked(self, widget): """ Forward selection information to super class if it is a VispaWidgetOwner. """ #logging.debug(self.__class__.__name__ +": widgetDoubleClicked()") if isinstance(self, QObject): if isinstance(self.parent(), VispaWidgetOwner): self.parent().widgetDoubleClicked(widget) def initWidgetMovement(self, widget): self._lastMovedWidgets = [] if self.multiSelectEnabled(): pos = widget.pos() for child in self.children(): if child != widget and hasattr( child, "isSelected") and child.isSelected(): child.setDragReferencePoint(pos - child.pos()) def widgetDragged(self, widget): """ Tell parent widget has moved. Only informs parent if it is a VispaWidgetOwner, too. """ if isinstance(self.parent(), VispaWidgetOwner): self.parent().widgetDragged(widget) if hasattr(self, "_lastMovedWidgets"): self._lastMovedWidgets.append(widget) if self.multiSelectEnabled(): for child in self.children(): if hasattr( child, "dragReferencePoint") and child != widget and hasattr( child, "isSelected") and child.isSelected(): if hasattr(child, "setPreviousDragPosition"): child.setPreviousDragPosition(child.pos()) child.move(widget.pos() - child.dragReferencePoint()) self._lastMovedWidgets.append(child) # apparently unused feature (2010-07-02), remove if really unnecessary # also see self._lastMovedWidget definition above def lastMovedWidgets(self): if hasattr(self, "_lastMovedWidgets"): return self._lastMovedWidgets return None def widgetAboutToDelete(self, widget): """ This function is called from the delete() function of VispaWidget. """ pass def keyPressEvent(self, event): """ Calls delete() method of selected child widgets if multi-select is activated. """ if self.multiSelectEnabled() and (event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete): selection = self.selectedWidgets()[:] for widget in selection: widget.delete() def deselectAllWidgets(self, exception=None): """ Deselects all widgets except the widget given as exception. """ #logging.debug(self.__class__.__name__ +": deselectAllWidgets()") self._selectedWidgets = [] for child in self.children(): if child != exception: if hasattr(child, 'select'): child.select(False) else: self._selectedWidgets.append(child) if isinstance(child, VispaWidgetOwner): child.deselectAllWidgets(exception) self.update() def mousePressEvent(self, event): """ Calls deselectAllWidgets. """ multiSelectEnabled = self.multiSelectEnabled() if event.modifiers() != Qt.ControlModifier: self.deselectAllWidgets() if multiSelectEnabled: self._selectionRectStartPos = QPoint(event.pos()) self._selectionRect = None def mouseMoveEvent(self, event): if self.multiSelectEnabled() and self._selectionRectStartPos and ( event.pos() - self._selectionRectStartPos ).manhattanLength() >= QApplication.startDragDistance(): eventX = event.pos().x() eventY = event.pos().y() startX = self._selectionRectStartPos.x() startY = self._selectionRectStartPos.y() oldRect = self._selectionRect self._selectionRect = QRect(min(startX, eventX), min(startY, eventY), abs(eventX - startX), abs(eventY - startY)) if oldRect: self.update( self._selectionRect.united(oldRect).adjusted(-5, -5, 5, 5)) else: self.update(self._selectionRect) # dynamically update selection statur # currently bad performance (2010-07-07) # TODO: improve selection mechanism # for child in self.children(): # if hasattr(child, "select") and hasattr(child, "isSelected"): # child.select(self._selectionRect.contains(child.geometry()), True) # select, mulitSelect def mouseReleaseEvent(self, event): if hasattr(self, "_selectionRect" ) and self._selectionRect and self.multiSelectEnabled(): for child in self.children(): if hasattr(child, "select") and hasattr( child, "isSelected") and self._selectionRect.contains( child.geometry()) and not child.isSelected(): child.select(True, True) # select, mulitSelect self.update(self._selectionRect.adjusted(-5, -5, 5, 5)) self._selectionRect = None self._selectionRectStartPos = None
class LegendWidget(Ui_legendsWidget, QWidget): showmap = pyqtSignal() def __init__(self, parent=None): super(LegendWidget, self).__init__(parent) self.setupUi(self) self.canvasimage = QImage() self.items = {} self.framerect = QRect() self._lastextent = None self.legendareabrush = QBrush(QColor(255, 255, 255, 200)) self.legendareapen = QPen(QColor(255, 255, 255, 20)) self.legendareapen.setWidth(0.5) def paintEvent(self, event): def itemlist(): for layer, items in self.items.iteritems(): if len(items) == 1 and not layer.startswith("~"): yield layer, items[0][1] else: for text, icon in items: if not text or text.startswith("~"): continue yield text, icon def _drawitem(pixmap, text, itempostion): painter.drawPixmap(itempostion, pixmap) textrect = QRectF(pixmap.width() + currentx + 10, itempostion.y(), event.rect().width() - pixmap.width() - OFFSET_X, pixmap.height()) painter.drawText(textrect, text, QTextOption(Qt.AlignVCenter)) def calcitems(): font = painter.font() metrices = QFontMetrics(font) maxwidth = 0 maxheight = 0 for item, _ in itemlist(): maxwidth = max(metrices.boundingRect(item).width(), maxwidth) maxheight = max( metrices.boundingRect(item).height(), maxheight) return maxwidth, maxheight if not self.canvasimage: return painter = QPainter(self) painter.setRenderHints(QPainter.Antialiasing) painter.drawImage(event.rect(), self.canvasimage) itemwidths, itemmaxheight = calcitems() OFFSET_X = 30 OFFSET_Y = itemmaxheight + 10 rect = event.rect() neededheight = (len(self.items) * OFFSET_Y) columns = 1 if neededheight > rect.height(): columns = math.ceil(neededheight / float(rect.height())) framerect = QRect(rect) framewidth = (itemwidths + OFFSET_X + ICON_SIZE.width() + 100) * columns framerect.setWidth(framewidth) painter.setBrush(self.legendareabrush) painter.setPen(self.legendareapen) painter.drawRect(framerect) self.framerect = framerect painter.setPen(Qt.black) currenty = OFFSET_Y currentx = OFFSET_X position = rect.topLeft() + QPoint(OFFSET_X, currenty) for text, icon in itemlist(): itempostion = QPoint(position) if currenty > rect.height(): currentx = itemwidths + OFFSET_X + 100 currenty = itemmaxheight + 10 itempostion.setX(currentx) itempostion.setY(currenty) _drawitem(icon, text, itempostion) currenty += OFFSET_Y position.setY(currenty + OFFSET_Y) def mousePressEvent(self, event): if self.framerect.contains(event.pos()): return self.showmap.emit() def updateitems(self, layers): self.items = {} for layer in layers: if not layer.type() == QgsMapLayer.VectorLayer: continue try: items = layer.rendererV2().legendSymbologyItems(ICON_SIZE) except AttributeError: continue self.items[layer.name()] = items self.update() def _renderimage(self): image = self.renderjob.renderedImage() self.canvasimage = image self.update() def updatecanvas(self, canvas): """ Update the canvas object for the legend background. """ if self._lastextent == canvas.extent(): return self._lastextent = canvas.extent() if QGis.QGIS_VERSION_INT > 20200: from qgis.core import QgsMapRendererParallelJob, QgsMapSettings settings = canvas.mapSettings() extent = settings.extent() settings.setOutputSize(self.size()) settings.setExtent(extent) #settings.setFlags(QgsMapSettings.Antialiasing | QgsMapSettings.DrawLabeling ) self.renderjob = QgsMapRendererParallelJob(settings) self.renderjob.finished.connect(self._renderimage) self.renderjob.start() else: if canvas.isDrawing(): return pixmap = QPixmap(self.size()) pixmap.fill(canvas.canvasColor()) painter = QPainter(pixmap) painter.setRenderHints(QPainter.Antialiasing) renderer = canvas.mapRenderer() renderer.render(painter) del painter self.canvasimage = pixmap.toImage() self.update()
class WebSystrayView(WebDialog): DEFAULT_WIDTH = 300 DEFAULT_HEIGHT = 370 ''' classdocs ''' def __init__(self, application, icon): ''' Constructor ''' super(WebSystrayView, self).__init__(application, "systray.html", api=WebSystrayApi(application, self)) self._icon = icon self._icon_geometry = None self._view.setFocusProxy(self) self.resize(WebSystrayView.DEFAULT_WIDTH, WebSystrayView.DEFAULT_HEIGHT) self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.Popup | QtCore.Qt.Dialog) def replace(self): log.trace("Icon is %r", self._icon) self._icon_geometry = rect = self._icon.geometry() log.trace("IconRect is : %s,%s | %s,%s", rect.x(), rect.y(), rect.width(), rect.height()) from PyQt4.QtGui import QApplication, QCursor from PyQt4.QtCore import QRect desktop = QApplication.desktop() log.trace("Screen id is %d", desktop.screenNumber(rect.topLeft())) desk = desktop.screenGeometry(desktop.screenNumber(rect.topLeft())) log.trace("ScreenRect is : %s,%s | %s,%s", desk.x(), desk.y(), desk.width(), desk.height()) pos = QCursor.pos() log.trace("Cursor is : %s,%s", pos.x(), pos.y()) # Make our calculation on a offset screen to 0/0 rect = QRect(rect.x() - desk.x(), rect.y() - desk.y(), rect.width(), rect.height()) pos.setX(pos.x() - desk.x()) pos.setY(pos.y() - desk.y()) if not rect.contains(pos) or (rect.x() == 0 and rect.y() == 0): # Avoid any modulo 0 if rect.width() == 0 or rect.height() == 0: rect = QRect(pos.x(), pos.y(), rect.width(), rect.height()) else: rect = QRect(pos.x() - pos.x() % rect.width(), pos.y() - pos.y() % rect.height(), rect.width(), rect.height()) log.trace("Adjusting X/Y to %d/%d", rect.x(), rect.y()) pos = rect self._icon_geometry = QRect(rect.x() + desk.x(), rect.y() + desk.y(), rect.width(), rect.height()) log.trace("New rect is : %s,%s | %s,%s", pos.x(), pos.y(), pos.width(), pos.height()) x = rect.x() + rect.width() - self.width() y = rect.y() - self.height() # Prevent the systray to be hidden if y < 0: y = rect.y() + rect.height() if x < 0: x = rect.x() # Use the offset again x += desk.x() y += desk.y() log.trace("Move systray menu to %d/%d", x, y) self.move(x, y) def show(self): self.replace() super(WebSystrayView, self).show() if self.isVisible(): self.raise_() self.activateWindow() self.setFocus(QtCore.Qt.ActiveWindowFocusReason) def underMouse(self): # The original result was different from this simple return self.geometry().contains(QtGui.QCursor.pos()) def shouldHide(self): log.trace("Geometry: %r", self.geometry()) log.trace("Cursor is: %r", QtGui.QCursor.pos()) log.trace("Icon: %r", self._icon) log.trace("Icon geometry: %r", self._icon_geometry) if not (self.underMouse() or (self._icon and self._icon.geometry().contains(QtGui.QCursor.pos())) or (self._icon_geometry and self._icon_geometry.contains(QtGui.QCursor.pos()))): log.trace('will close menu') self.close() def focusOutEvent(self, event): if not (self.underMouse() or (self._icon and self._icon.geometry().contains(QtGui.QCursor.pos())) or (self._icon_geometry and self._icon_geometry.contains(QtGui.QCursor.pos()))): self.close() super(WebSystrayView, self).focusOutEvent(event) def resizeEvent(self, event): super(WebSystrayView, self).resizeEvent(event) self.replace() @QtCore.pyqtSlot() def close(self): self._icon = None try: super(WebSystrayView, self).close() except RuntimeError: # This exception can happen here # wrapped C/C++ object of type WebSystrayView has been deleted pass
class WebSystrayView(WebDialog): DEFAULT_WIDTH = 300 DEFAULT_HEIGHT = 370 ''' classdocs ''' def __init__(self, application, icon): ''' Constructor ''' super(WebSystrayView, self).__init__(application, "systray.html", api=WebSystrayApi(application, self)) self._icon = icon self._icon_geometry = None self._view.setFocusProxy(self) self.resize(WebSystrayView.DEFAULT_WIDTH, WebSystrayView.DEFAULT_HEIGHT) self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.Popup | QtCore.Qt.Dialog); def replace(self): log.trace("Icon is %r", self._icon) self._icon_geometry = rect = self._icon.geometry() log.trace("IconRect is : %s,%s | %s,%s",rect.x(), rect.y(), rect.width(), rect.height()) from PyQt4.QtGui import QApplication, QCursor from PyQt4.QtCore import QRect desktop = QApplication.desktop() log.trace("Screen id is %d", desktop.screenNumber(rect.topLeft())) desk = desktop.screenGeometry(desktop.screenNumber(rect.topLeft())) log.trace("ScreenRect is : %s,%s | %s,%s",desk.x(), desk.y(), desk.width(), desk.height()) pos = QCursor.pos() log.trace("Cursor is : %s,%s",pos.x(), pos.y()) # Make our calculation on a offset screen to 0/0 rect = QRect(rect.x()-desk.x(), rect.y()-desk.y(), rect.width(), rect.height()) pos.setX(pos.x()-desk.x()) pos.setY(pos.y()-desk.y()) if not rect.contains(pos) or (rect.x() == 0 and rect.y() == 0): # Avoid any modulo 0 if rect.width() == 0 or rect.height() == 0: rect = QRect(pos.x(), pos.y(), rect.width(), rect.height()) else: rect = QRect(pos.x()-pos.x()%rect.width(), pos.y()-pos.y()%rect.height(), rect.width(), rect.height()) log.trace("Adjusting X/Y to %d/%d", rect.x(), rect.y()) pos = rect self._icon_geometry = QRect(rect.x()+desk.x(), rect.y()+desk.y(), rect.width(), rect.height()) log.trace("New rect is : %s,%s | %s,%s",pos.x(), pos.y(), pos.width(), pos.height()) x = rect.x() + rect.width() - self.width() y = rect.y() - self.height() # Prevent the systray to be hidden if y < 0: y = rect.y() + rect.height() if x < 0: x = rect.x() # Use the offset again x += desk.x() y += desk.y() log.trace("Move systray menu to %d/%d", x, y) self.move(x, y) def show(self): self.replace() super(WebSystrayView, self).show() if self.isVisible(): self.raise_() self.activateWindow() self.setFocus(QtCore.Qt.ActiveWindowFocusReason) def underMouse(self): # The original result was different from this simple return self.geometry().contains(QtGui.QCursor.pos()) def shouldHide(self): log.trace("Geometry: %r", self.geometry()) log.trace("Cursor is: %r", QtGui.QCursor.pos()) log.trace("Icon: %r", self._icon) log.trace("Icon geometry: %r", self._icon_geometry) if not (self.underMouse() or (self._icon and self._icon.geometry().contains(QtGui.QCursor.pos())) or (self._icon_geometry and self._icon_geometry.contains(QtGui.QCursor.pos()))): log.trace('will close menu') self.close() def focusOutEvent(self, event): if not (self.underMouse() or (self._icon and self._icon.geometry().contains(QtGui.QCursor.pos())) or (self._icon_geometry and self._icon_geometry.contains(QtGui.QCursor.pos()))): self.close() super(WebSystrayView, self).focusOutEvent(event) def resizeEvent(self, event): super(WebSystrayView, self).resizeEvent(event) self.replace() @QtCore.pyqtSlot() def close(self): self._icon = None try: super(WebSystrayView, self).close() except RuntimeError: # This exception can happen here # wrapped C/C++ object of type WebSystrayView has been deleted pass
class LegendWidget(legend_widget, QWidget): showmap = pyqtSignal() def __init__(self, parent=None): super(LegendWidget, self).__init__(parent) self.setupUi(self) self.pixmap = QPixmap() self.items = {} self.framerect = QRect() self._lastextent = None self.legendareabrush = QBrush(QColor(255,255,255,200)) self.legendareapen = QPen(QColor(255,255,255,20)) self.legendareapen.setWidth(0.5) def paintEvent(self, event): def _drawitem(pixmap, text, itempostion): painter.drawPixmap(itempostion, pixmap) textrect = QRectF(pixmap.width() + 40, itempostion.y(), framerect.width() - pixmap.width() - 40, pixmap.height()) painter.drawText(textrect, text, QTextOption(Qt.AlignVCenter)) if not self.pixmap: return painter = QPainter(self) painter.setRenderHints(QPainter.Antialiasing) painter.drawPixmap(event.rect(), self.pixmap) rect = event.rect() framerect = QRect(rect) newwidth = (rect.width() / 100) * 40 framerect.setWidth(newwidth) painter.setBrush(self.legendareabrush) painter.setPen(self.legendareapen) painter.drawRect(framerect) self.framerect = framerect painter.setPen(Qt.black) currenty = 40 position = rect.topLeft() + QPoint(30, currenty) for layer, items in self.items.iteritems(): if len(items) == 1: itempostion = QPoint(position) itempostion.setY(currenty) _drawitem(items[0][1], layer, itempostion) currenty += 40 else: for text, icon in items: if not text: continue itempostion = QPoint(position) itempostion.setY(currenty) _drawitem(icon, text, itempostion) currenty += 40 position.setY(currenty + 40) def mousePressEvent(self, event): if self.framerect.contains(event.pos()): return self.showmap.emit() def updateitems(self, layers): self.items = {} for layer in layers: if not layer.type() == QgsMapLayer.VectorLayer: continue try: items = layer.rendererV2().legendSymbologyItems(QSize(32, 32)) except AttributeError: continue self.items[layer.name()] = items self.update() def updatecanvas(self, canvas): """ Update the canvas object for the legend background. """ if canvas.isDrawing() or self._lastextent == canvas.extent(): return self._lastextent = canvas.extent() pixmap = QPixmap(self.size()) pixmap.fill(canvas.canvasColor()) painter = QPainter(pixmap) painter.setRenderHints(QPainter.Antialiasing) renderer = canvas.mapRenderer() renderer.render(painter) del painter self.pixmap = pixmap self.update()
class ScheduleVisualizer(QWidget): time = 50 proc = 20 scale = 1.5 schedule = None method = None vertices = {} positions = {} procrects = {} colors = { "axis": QColor(255, 255, 255), "task": QColor(255, 255, 0), "delivery": QColor(100, 0, 255), "select": QColor(255, 0, 0) } selectedTask = None addrect = None delrect = None targetPos = None pressed = False def __init__(self, parent=None): QWidget.__init__(self, parent) self.setGeometry(0, 0, (70 + self.time * 10) * self.scale, (40 + self.proc * 20) * self.scale) self.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) try: _fromUtf8 = QtCore.QString.fromUtf8 except AttributeError: _fromUtf8 = lambda s: s self.procicon = QImage(_fromUtf8(":/pics/pics/processor.png")) self.addicon = QImage(_fromUtf8(":/pics/pics/add.png")) self.delicon = QImage(_fromUtf8(":/pics/pics/meenoos.png")) def paintEvent(self, event): if self.schedule: paint = QPainter() paint.begin(self) paint.setPen(self.colors["axis"]) paint.setFont(QtGui.QFont('Decorative', 9 * self.scale)) procX = {} # Draw processor names and axis for i in range(self.proc): paint.drawImage( QRect(15 * self.scale, (10 + i * 20) * self.scale, 24 * self.scale, 24 * self.scale), self.procicon) paint.drawText(40 * self.scale, (25 + i * 20) * self.scale, str(self.schedule.processors[i].reserves)) plus = QRect(5 * self.scale, (10 + i * 20) * self.scale, 10 * self.scale, 10 * self.scale) paint.drawImage(plus, self.addicon) meenoos = QRect(5 * self.scale, (20 + i * 20) * self.scale, 10 * self.scale, 10 * self.scale) paint.drawImage(meenoos, self.delicon) self.procrects[self.schedule.processors[i]] = [plus, meenoos] paint.drawLine(50 * self.scale, (20 + i * 20) * self.scale, (50 + self.time * 10) * self.scale, (20 + i * 20) * self.scale) procX[self.schedule.processors[i].number] = 20 + i * 20 # Draw timeline tdir = self.method.system.tdir paint.drawLine(50 * self.scale, self.height() - 15, (50 + tdir * 10) * self.scale, self.height() - 15) paint.drawLine(50 * self.scale, 10 * self.scale, 50 * self.scale, self.height() - 10) t = 0 paint.setFont(QtGui.QFont('Decorative', 8)) while t < tdir + 10: paint.drawLine((50 + t * 10) * self.scale, self.height() - 20, (50 + t * 10) * self.scale, self.height() - 10) paint.drawText((50 + t * 10 + 1) * self.scale, self.height() - 5, str(t)) t += 10 paint.setPen(self.colors["select"]) paint.drawLine((50 + tdir * 10) * self.scale, 10 * self.scale, (50 + tdir * 10) * self.scale, self.height() - 10) if self.selectedTask: t = self.selectedTask start = self.method.interpreter.executionTimes[t][0] finish = self.method.interpreter.executionTimes[t][1] paint.drawText((50 + start * 10) * self.scale, self.height() - 16, str(start)) paint.drawText((50 + finish * 10) * self.scale, self.height() - 16, str(finish)) # Draw tasks paint.setPen(self.colors["task"]) paint.setFont(QtGui.QFont('Decorative', 9 * self.scale)) self.vertices = {} self.positions = {} for m in self.schedule.vertices.keys(): i = 0 prev = None for t in self.schedule.vertices[m]: start = self.method.interpreter.executionTimes[t][0] finish = self.method.interpreter.executionTimes[t][1] task = QtCore.QRect((50 + start * 10) * self.scale, (procX[t.m.number] - 5) * self.scale, (finish - start) * 10 * self.scale, 10 * self.scale) # TODO: calculate once! self.vertices[t] = task if i == 0: self.positions[(m, i)] = QtCore.QRect( QPoint(50 * self.scale, task.y()), task.bottomLeft()) else: self.positions[(m, i)] = QtCore.QRect( prev.topRight(), task.bottomLeft()) if t != self.selectedTask: paint.fillRect(task, self.colors["task"]) else: paint.fillRect(task, self.colors["select"]) if self.schedule.CanAddVersions(t): self.addrect = QRect(task.topLeft().x(), task.topLeft().y(), 10 * self.scale, 10 * self.scale) paint.drawImage(self.addrect, self.addicon) if self.schedule.CanDeleteVersions(t): self.delrect = QRect( task.topRight().x() - 10 * self.scale, task.topRight().y(), 10 * self.scale, 10 * self.scale) paint.drawImage(self.delrect, self.delicon) paint.setPen(self.colors["axis"]) paint.drawRect(task) paint.setPen(self.colors["task"]) prev = task i += 1 self.positions[(m, i)] = QtCore.QRect( prev.topRight(), QPoint(prev.topRight().x() + 100, prev.bottomRight().y())) if self.targetPos: width = min(self.selectedTask.v.time * 10 * self.scale, self.positions[self.targetPos].width()) rect = QtCore.QRect(self.positions[self.targetPos]) rect.setWidth(width) paint.fillRect(rect, self.colors["select"]) # Draw deliveries paint.setPen(QPen(self.colors["delivery"], 2)) for d in self.method.interpreter.deliveryTimes: self.drawArrow(paint, (50 + d[2] * 10) * self.scale, procX[d[0].number] * self.scale, (50 + d[3] * 10) * self.scale, procX[d[1].number] * self.scale) # Draw captions paint.setPen(self.colors["axis"]) for m in self.schedule.vertices.keys(): for t in self.schedule.vertices[m]: start = self.method.interpreter.executionTimes[t][0] finish = self.method.interpreter.executionTimes[t][1] s = str(t.v.number) if t.k.number > 1: s += " v" + str(t.k.number) paint.drawText((10 + finish + start - int(len(s) / 2)) * 5 * self.scale, (procX[t.m.number] + 5) * self.scale, s) paint.end() def mousePressEvent(self, e): def update(): self.proc = self.schedule.GetProcessorsWithoutDoubles() self.time = self.schedule.Interpret() self.targetPos = None self.pressed = False self.selectedTask = None self.addrect = None self.delrect = None self.emit(SIGNAL("ManualOperation")) self.ResizeCanvas() self.repaint() return if self.selectedTask: if self.addrect: if self.addrect.contains(e.pos()): self.method.ManualStep("AddVersion", v=self.selectedTask.v) update() return if self.delrect: if self.delrect.contains(e.pos()): self.method.ManualStep("DeleteVersion", v=self.selectedTask.v) update() return for p in self.procrects.keys(): if self.procrects[p][0].contains(e.pos()): self.method.ManualStep("AddProcessor", m=p) update() return if self.procrects[p][1].contains(e.pos()): self.method.ManualStep("DeleteProcessor", m=p) update() return for v in self.vertices.keys(): if self.vertices[v].contains(e.pos()): self.selectedTask = v self.repaint() self.pressed = True return self.selectedTask = None self.addrect = None self.delrect = None self.repaint() def mouseMoveEvent(self, e): if self.pressed: for p in self.positions.keys(): if self.positions[p].contains(e.pos()): self.targetPos = p self.repaint() return self.targetPos = None self.repaint() def mouseReleaseEvent(self, e): if self.pressed and self.targetPos: result = self.method.ManualStep( "MoveVertex", v=self.selectedTask, n1=self.schedule.vertices[self.selectedTask.m].index( self.selectedTask), m2=self.schedule.GetProcessor(self.targetPos[0]), n2=self.targetPos[1]) if result == True: self.proc = self.schedule.GetProcessorsWithoutDoubles() self.time = self.method.interpreter.Interpret(self.schedule) self.emit(SIGNAL("ManualOperation")) else: self.emit(SIGNAL("WrongOperation"), result) self.targetPos = None self.pressed = False self.selectedTask = None self.addrect = None self.delrect = None self.ResizeCanvas() self.repaint() return self.pressed = False self.targetPos = None self.repaint() def drawArrow(self, paint, x1, y1, x2, y2): m = paint.worldMatrix() paint.translate(x1, y1) pi = 3.1415926 alpha = math.atan(abs(y2 - y1) / abs(x2 - x1)) * 180 / pi if y2 > y1: if x2 > x1: paint.rotate(alpha) else: paint.rotate(180 - alpha) else: if x2 > x1: paint.rotate(-alpha) else: paint.rotate(alpha - 180) endcoord = math.sqrt((x2 - x1)**2 + (y2 - y1)**2) p1 = QPointF(endcoord, 0) paint.drawLine(0, 0, p1.x(), 0) coord = math.sqrt(12**2 - 6**2) p2 = QPointF(endcoord - coord, 6) p3 = QPointF(endcoord - coord, -6) path = QPainterPath() path.moveTo(p1) path.lineTo(p2) path.lineTo(p3) path.lineTo(p1) paint.fillPath(path, paint.pen().color()) paint.setWorldMatrix(m) def SetScale(self, d): self.scale = d self.ResizeCanvas() self.repaint() def Visualize(self, m): self.schedule = m.system.schedule self.method = m # TODO: get rid of this self.proc = self.schedule.GetProcessorsWithoutDoubles() self.time = self.method.interpreter.Interpret(self.schedule) self.ResizeCanvas() self.repaint() def ResizeCanvas(self): self.setGeometry( 0, 0, max(int((70 + self.time * 10) * self.scale), self.parent().width()), max(int((40 + self.proc * 20) * self.scale), self.parent().height()))
class VispaWidgetOwner(object): """ Interface for classes containing VispaWidgets Only makes sense if implementing class also inherits QWidget or class inheriting QWidget. """ def enableMultiSelect(self, multiSelect=True): self._multiSelectEnabledFlag = multiSelect def multiSelectEnabled(self): return hasattr(self, "_multiSelectEnabledFlag") and self._multiSelectEnabledFlag def selectedWidgets(self): """ Returns a list of all selected widgets. """ if hasattr(self, "_selectedWidgets"): return self._selectedWidgets return [child for child in self.children() if hasattr(child, "isSelected") and child.isSelected()] def widgetSelected(self, widget, multiSelect=False): """ Forward selection information to super class if it is a VispaWidgetOwner. """ logging.debug(self.__class__.__name__ +": widgetSelected()") if isinstance(self, QObject): if not hasattr(self, "_selectedWidgets"): self._selectedWidgets = [] if not multiSelect or not self.multiSelectEnabled(): self.deselectAllWidgets(widget) self._selectedWidgets = [] if widget.parent() == self and not widget in self._selectedWidgets: self._selectedWidgets.append(widget) for widget in [child for child in self._selectedWidgets if hasattr(child, "isSelected") and not child.isSelected()]: self._selectedWidgets.remove(widget) if isinstance(self.parent(), VispaWidgetOwner): self.parent().widgetSelected(widget) def widgetDoubleClicked(self, widget): """ Forward selection information to super class if it is a VispaWidgetOwner. """ #logging.debug(self.__class__.__name__ +": widgetDoubleClicked()") if isinstance(self, QObject): if isinstance(self.parent(), VispaWidgetOwner): self.parent().widgetDoubleClicked(widget) def initWidgetMovement(self, widget): self._lastMovedWidgets = [] if self.multiSelectEnabled(): pos = widget.pos() for child in self.children(): if child != widget and hasattr(child, "isSelected") and child.isSelected(): child.setDragReferencePoint(pos - child.pos()) def widgetDragged(self, widget): """ Tell parent widget has moved. Only informs parent if it is a VispaWidgetOwner, too. """ if isinstance(self.parent(), VispaWidgetOwner): self.parent().widgetDragged(widget) if hasattr(self, "_lastMovedWidgets"): self._lastMovedWidgets.append(widget) if self.multiSelectEnabled(): for child in self.children(): if hasattr(child, "dragReferencePoint") and child != widget and hasattr(child, "isSelected") and child.isSelected(): if hasattr(child, "setPreviousDragPosition"): child.setPreviousDragPosition(child.pos()) child.move(widget.pos() - child.dragReferencePoint()) self._lastMovedWidgets.append(child) # apparently unused feature (2010-07-02), remove if really unnecessary # also see self._lastMovedWidget definition above def lastMovedWidgets(self): if hasattr(self, "_lastMovedWidgets"): return self._lastMovedWidgets return None def widgetAboutToDelete(self, widget): """ This function is called from the delete() function of VispaWidget. """ pass def keyPressEvent(self, event): """ Calls delete() method of selected child widgets if multi-select is activated. """ if self.multiSelectEnabled() and ( event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete ): selection = self.selectedWidgets()[:] for widget in selection: widget.delete() def deselectAllWidgets(self, exception=None): """ Deselects all widgets except the widget given as exception. """ #logging.debug(self.__class__.__name__ +": deselectAllWidgets()") self._selectedWidgets = [] for child in self.children(): if child != exception: if hasattr(child, 'select'): child.select(False) else: self._selectedWidgets.append(child) if isinstance(child, VispaWidgetOwner): child.deselectAllWidgets(exception) self.update() def mousePressEvent(self, event): """ Calls deselectAllWidgets. """ multiSelectEnabled = self.multiSelectEnabled() if event.modifiers() != Qt.ControlModifier: self.deselectAllWidgets() if multiSelectEnabled: self._selectionRectStartPos = QPoint(event.pos()) self._selectionRect = None def mouseMoveEvent(self, event): if self.multiSelectEnabled() and self._selectionRectStartPos and (event.pos() - self._selectionRectStartPos).manhattanLength() >= QApplication.startDragDistance(): eventX = event.pos().x() eventY = event.pos().y() startX = self._selectionRectStartPos.x() startY = self._selectionRectStartPos.y() oldRect = self._selectionRect self._selectionRect = QRect(min(startX, eventX), min(startY, eventY), abs(eventX - startX), abs(eventY - startY)) if oldRect: self.update(self._selectionRect.united(oldRect).adjusted(-5, -5, 5, 5)) else: self.update(self._selectionRect) # dynamically update selection statur # currently bad performance (2010-07-07) # TODO: improve selection mechanism # for child in self.children(): # if hasattr(child, "select") and hasattr(child, "isSelected"): # child.select(self._selectionRect.contains(child.geometry()), True) # select, mulitSelect def mouseReleaseEvent(self, event): if hasattr(self, "_selectionRect") and self._selectionRect and self.multiSelectEnabled(): for child in self.children(): if hasattr(child, "select") and hasattr(child, "isSelected") and self._selectionRect.contains(child.geometry()) and not child.isSelected(): child.select(True, True) # select, mulitSelect self.update(self._selectionRect.adjusted(-5, -5, 5, 5)) self._selectionRect = None self._selectionRectStartPos = None
def mouseMoveEvent(self, event): if self._interaction.moving: mouse_position = event.globalPos() offset = mouse_position - self._interaction.mouse_last_position if self.parent() is not None: parent_rect = self.parent().rect() old_geometry = self.geometry() new_geometry = old_geometry.translated(offset) if new_geometry.left() < 0: new_geometry.moveLeft(0) if new_geometry.top() < 0: new_geometry.moveTop(0) if new_geometry.right() > parent_rect.right(): new_geometry.moveRight(parent_rect.right()) if new_geometry.bottom() > parent_rect.bottom(): new_geometry.moveBottom(parent_rect.bottom()) offset = new_geometry.topLeft() - old_geometry.topLeft() self.move(self.pos() + offset) self._interaction.mouse_last_position += offset elif self._interaction.resizing: mouse_position = event.globalPos() delta_y = mouse_position.y( ) - self._interaction.mouse_last_position.y() geometry = self.geometry() if self._interaction.resize_corner is self.TopLeftCorner: delta_x = -(self.width_for_height(geometry.height() - delta_y) - geometry.width()) geometry.setTopLeft(geometry.topLeft() + QPoint(delta_x, delta_y)) elif self._interaction.resize_corner is self.TopRightCorner: delta_x = (self.width_for_height(geometry.height() - delta_y) - geometry.width()) geometry.setTopRight(geometry.topRight() + QPoint(delta_x, delta_y)) elif self._interaction.resize_corner is self.BottomLeftCorner: delta_x = -(self.width_for_height(geometry.height() + delta_y) - geometry.width()) geometry.setBottomLeft(geometry.bottomLeft() + QPoint(delta_x, delta_y)) else: delta_x = (self.width_for_height(geometry.height() + delta_y) - geometry.width()) geometry.setBottomRight(geometry.bottomRight() + QPoint(delta_x, delta_y)) if self.minimumHeight() <= geometry.height() <= self.maximumHeight( ) and (self.parent() is None or self.parent().rect().contains(geometry)): self.setGeometry(geometry) self._interaction.mouse_last_position = mouse_position elif self.interactive: mouse_position = event.pos() topbar_rect = QRect(0, 0, self.width(), 10) if self.rect().adjusted(0, 10, 0, -10).contains(mouse_position): self.setCursor(Qt.ArrowCursor) elif topbar_rect.contains(mouse_position): self.setCursor(self.cursors.resize_top) else: self.setCursor(self.cursors.resize_bottom)