예제 #1
0
    def maxSize(self):
        size = QSize()
        for variation in self.d.variations:
            size.setWidth(max(size.width(), variation.map.width()))
            size.setHeight(max(size.height(), variation.map.height()))

        return size
예제 #2
0
 def maxSize(self):
     size = QSize()
     for variation in self.d.variations:
         size.setWidth(max(size.width(), variation.map.width()))
         size.setHeight(max(size.height(), variation.map.height()))
     
     return size
예제 #3
0
    def sizeHint(self):
        metrics = QFontMetricsF(self.editor.font())
        size_hint = QSize(metrics.height(), metrics.height())

        if size_hint.width() > 16:
            size_hint.setWidth(16)

        return size_hint
 def sizeHint(self):
     s = QSize()
     if self._minimum_rows:
         s.setHeight(self.count() * self.sizeHintForRow(0) + self.frameWidth() * 2)
     else:
         s.setHeight(super().sizeHint().height())
     s.setWidth(max(self.sizeHintForColumn(0) + self.frameWidth() * 2, self._minimum_width))
     return s
예제 #5
0
 def height_for_width(self, icon: QIcon, height: int) -> QSize:
     size = QSize()
     size.setWidth(height)
     size.setHeight(height)
     actual = icon.actualSize(size)
     if actual.height() != height:
         ratio = actual.width() / actual.height()
         width = int(ratio * height)
         size.setWidth(width)
         size.setHeight(height)
     return size
 def overread(self,msize):
     moutdata = ""
     img = Snapshot.snapshot(width = msize.width(), height = msize.height()).scaled(msize.width(),msize.height(),Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
     moutdata = moutdata + ";"+(hex(msize.width())[2:]).rjust(4,'0')+(hex(msize.height())[2:]).rjust(4,'0')+"\r\n"
     pos = QSize(0,0)
     for ypos in range(0,img.height()):
         qrgb = ";"
         for xpos in range(0,img.width()):
             data = img.pixel(xpos,ypos)
             pos.setWidth(pos.width()+1)
             qrgb = qrgb + (hex(((data & 0x00F80000) >> 8 ) | ((data & 0x0000FC00) >> 5 ) | ((data & 0x000000F8) >> 3 ))[2:]).rjust(4,'0')
         pos.setWidth(0)
         pos.setHeight(pos.height()+1)
         moutdata = moutdata + qrgb + "\r\n"
     return moutdata
예제 #7
0
 def mapSize(self):
     p = RenderParams(self.map())
     # The map size is the same regardless of which indexes are shifted.
     if (p.staggerX):
         size = QSize(self.map().width() * p.columnWidth + p.sideOffsetX,
                    self.map().height() * (p.tileHeight + p.sideLengthY))
         if (self.map().width() > 1):
             size.setHeight(size.height() + p.rowHeight)
         return size
     else:
         size = QSize(self.map().width() * (p.tileWidth + p.sideLengthX),
                    self.map().height() * p.rowHeight + p.sideOffsetY)
         if (self.map().height() > 1):
             size.setWidth(size.width() + p.columnWidth)
         return size
예제 #8
0
 def mapSize(self):
     p = RenderParams(self.map())
     # The map size is the same regardless of which indexes are shifted.
     if (p.staggerX):
         size = QSize(self.map().width() * p.columnWidth + p.sideOffsetX,
                      self.map().height() * (p.tileHeight + p.sideLengthY))
         if (self.map().width() > 1):
             size.setHeight(size.height() + p.rowHeight)
         return size
     else:
         size = QSize(self.map().width() * (p.tileWidth + p.sideLengthX),
                      self.map().height() * p.rowHeight + p.sideOffsetY)
         if (self.map().height() > 1):
             size.setWidth(size.width() + p.columnWidth)
         return size
예제 #9
0
파일: video.py 프로젝트: xlongfeng/bigeye
 def requestImage(self, id, requestedSize):
     if self._recorder.width == 1024:
         size = QSize(self._recorder.width * 7 / 8,
                      self._recorder.height * 7 / 8)
     elif self._recorder.width == 1280:
         size = QSize(self._recorder.width * 3 / 4,
                      self._recorder.height * 3 / 4)
     else:
         size = QSize(self._recorder.width, self._recorder.height)
     if requestedSize.width() > 0:
         size.setWidth(requestedSize.width())
     if requestedSize.height() > 0:
         size.setHeight(requestedSize.height())
     image = VideoRecorder.instance().frame.scaled(size, Qt.KeepAspectRatio,
                                                   Qt.SmoothTransformation)
     return image, size
예제 #10
0
 def requestImage(self, id, requestedSize):
     image = self._snapshot.image
     if self._snapshot.width == 1024:
         size = QSize(self._snapshot.width * 7 / 8,
                      self._snapshot.height * 7 / 8)
     elif self._snapshot.width == 1280:
         size = QSize(self._snapshot.width * 3 / 4,
                      self._snapshot.height * 3 / 4)
     else:
         size = QSize(self._snapshot.width, self._snapshot.height)
     if requestedSize.width() > 0:
         size.setWidth(requestedSize.width())
     if requestedSize.height() > 0:
         size.setHeight(requestedSize.height())
     image = image.scaled(size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
     return image, size
예제 #11
0
    def _update_icon(self):
        icon_size = QSize(self.iconSize())
        icon_size.setWidth(icon_size.width() - 2)
        icon_size.setHeight(icon_size.height() - 2)

        pix_map = QPixmap(icon_size)
        pix_map.fill(self._color)

        painter = QPainter()
        painter.begin(pix_map)
        border_color = QColor(Qt.black)
        border_color.setAlpha(128)
        painter.setPen(border_color)
        painter.drawRect(0, 0, pix_map.width() - 1, pix_map.height() - 1)
        painter.end()

        self.setIcon(QIcon(pix_map))
예제 #12
0
 def sectionSizeFromContents(self, logicalIndex: int) -> QSize:
     if self._pd.headerModel:
         curLeafIndex = QModelIndex(self._pd.leafIndex(logicalIndex))
         if curLeafIndex.isValid():
             styleOption = QStyleOptionHeader(
                 self.styleOptionForCell(logicalIndex))
             s = QSize(self._pd.cellSize(curLeafIndex, self, styleOption))
             curLeafIndex = curLeafIndex.parent()
             while curLeafIndex.isValid():
                 if self.orientation() == Qt.Horizontal:
                     s.setHeight(s.height() + self._pd.cellSize(
                         curLeafIndex, self, styleOption).height())
                 else:
                     s.setWidth(s.width() + self._pd.cellSize(
                         curLeafIndex, self, styleOption).width())
                 curLeafIndex = curLeafIndex.parent()
             return s
     return super().sectionSizeFromContents(logicalIndex)
예제 #13
0
 def setColor(self, color):
     if type(color) != QColor:
         color = QColor(color)
     if (self.mColor == color or not color.isValid()):
         return
     self.mColor = color
     size = QSize(self.iconSize())
     size.setWidth(size.width() - 2)
     size.setHeight(size.height() - 2)
     pixmap = QPixmap(size)
     pixmap.fill(self.mColor)
     painter = QPainter(pixmap)
     border = QColor(Qt.black)
     border.setAlpha(128)
     painter.setPen(border)
     painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1)
     painter.end()
     self.setIcon(QIcon(pixmap))
     self.colorChanged.emit(color)
예제 #14
0
    def construct_array(self):
        rec1 = QRect(
            self.start_x, self.start_y, self.actuator[0].w,
            self.row * self.actuator[0].h + (self.row - 1) * self.gap_h)
        self.rec.append(rec1)

        size = QSize()
        size.setHeight(self.actuator[1].h)
        size.setWidth(self.actuator[1].w)

        for i in range(0, self.row):
            for j in range(0, self.col):
                index = i * self.col + j + 1
                x = self.start_x + \
                    self.actuator[index].w+self.gap_w + \
                    self.actuator[index].w*j+self.gap_w*j
                y = self.start_y + self.actuator[index].h * i + self.gap_h * i
                temp = QPoint(x, y)
                self.rec.append(QRect(temp, size))
예제 #15
0
    def calculateSize(self, sizeType):
        totalSize = QSize()

        for wrapper in self.list:
            position = wrapper.position
            itemSize = QSize()

            if sizeType == self.MinimumSize:
                itemSize = wrapper.item.minimumSize()
            else: # sizeType == self.SizeHint
                itemSize = wrapper.item.sizeHint()

            if position in (self.North, self.South, self.Center):
                totalSize.setHeight(totalSize.height() + itemSize.height())

            if position in (self.West, self.East, self.Center):
                totalSize.setWidth(totalSize.width() + itemSize.width())

        return totalSize
예제 #16
0
    def calculateSize(self, sizeType):
        totalSize = QSize()

        for wrapper in self.list:
            position = wrapper.position
            itemSize = QSize()

            if sizeType == self.MinimumSize:
                itemSize = wrapper.item.minimumSize()
            else: # sizeType == self.SizeHint
                itemSize = wrapper.item.sizeHint()

            if position in (self.North, self.South, self.Center):
                totalSize.setHeight(totalSize.height() + itemSize.height())

            if position in (self.West, self.East, self.Center):
                totalSize.setWidth(totalSize.width() + itemSize.width())

        return totalSize
예제 #17
0
 def setColor(self, color):
     if type(color)!=QColor:
         color = QColor(color)
     if (self.mColor == color or not color.isValid()):
         return
     self.mColor = color
     size = QSize(self.iconSize())
     size.setWidth(size.width()-2)
     size.setHeight(size.height()-2)
     pixmap = QPixmap(size)
     pixmap.fill(self.mColor)
     painter = QPainter(pixmap)
     border = QColor(Qt.black)
     border.setAlpha(128)
     painter.setPen(border)
     painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1)
     painter.end()
     self.setIcon(QIcon(pixmap))
     self.colorChanged.emit(color)
예제 #18
0
파일: Plotter.py 프로젝트: wiratmoko11/CNN
    def plot_testing(self, x_batch, predict, list_widget):
        list_widget.clear()
        """

        :param x_batch:
        :param predict:
        :return:
        """
        for i in range(len(x_batch)):
            top_3_predict = numpy.argsort(predict[i])[::-1][:3]
            #print(predict)
            result_widget = ResultWidget()
            result_widget.label_number.setText(str(i + 1))
            category_1 = self.CIFAR10_LABELS_LIST.__getitem__(top_3_predict[0])
            value_1 = predict[i][top_3_predict[0]]
            category_2 = self.CIFAR10_LABELS_LIST.__getitem__(top_3_predict[1])
            value_2 = predict[i][top_3_predict[1]]
            category_3 = self.CIFAR10_LABELS_LIST.__getitem__(top_3_predict[2])
            value_3 = predict[i][top_3_predict[2]]
            result_widget.label_prediksi_1.setText(category_1 + " - " +
                                                   str(value_1) + "")
            result_widget.label_prediksi_2.setText(category_2 + " - " +
                                                   str(value_2) + "")
            result_widget.label_prediksi_3.setText(category_3 + " - " +
                                                   str(value_3) + "")

            # result_widget.canvas_image.
            ax = result_widget.figure_image.add_subplot(111)
            ax.imshow(
                self.dataset.to_channel_last(x_batch[i], shape=(32, 32, 3)))
            ax.set_position([0.1, 0.2, 0.8, 0.8])
            ax.set_axis_off()
            result_widget.canvas_image.draw()
            list_item_widget = QListWidgetItem(list_widget)
            # print(result_widget.sizeHint())
            list_size = QSize()
            list_size.setHeight(100)
            list_size.setWidth(502)
            list_item_widget.setSizeHint(list_size)

            list_widget.addItem(list_item_widget)
            list_widget.setItemWidget(list_item_widget, result_widget)
예제 #19
0
 def gif(self):
     if self.movie:
         # Movie is already created
         self.movie.start()
         return
     print("Creating movie for", str(self.iv_image.path))
     self.movie = QMovie(str(self.iv_image.path))
     image = QImage(str(self.iv_image.path))
     if image.height() > imageviewer.settings.IMAGE_HEIGHT or image.width() > imageviewer.settings.IMAGE_WIDTH:
         # scale the movie if it doesn't fit in the frame
         # the frame is big enough we don't need the gif at full size to see what is going on
         image2 = image.scaled(imageviewer.settings.IMAGE_WIDTH,
                               imageviewer.settings.IMAGE_HEIGHT,
                               Qt.KeepAspectRatio)
         size = QSize()
         size.setHeight(image2.height())
         size.setWidth(image2.width())
         self.movie.setScaledSize(size)
         print("Scaled movie size")
     self.setMovie(self.movie)
     self.movie.start()
예제 #20
0
    def paintEvent(self, event):
        self.drawLabel1.clear()
        self.drawLabel2.clear()
        size = self.widget_4.size()
        size1 = QSize()
        size2 = QSize()
        size2.setHeight(size.height() * 0.45)
        size2.setWidth(size.width())
        size1.setHeight(size.height() * 0.45)
        size1.setHeight(size.height() * 0.45)
        size1.setWidth(size.width())
        self.drawLabel1.resize(size1)
        self.drawLabel2.resize(size2)
        if not self.image1 is None:

            size1 = self.drawLabel1.size()
            qimage1 = QImage(self.image1.tobytes(), self.image1.shape[1],
                             self.image1.shape[0], QImage.Format_RGB888)
            pixmap1 = QPixmap(qimage1)
            pixmap1 = pixmap1.scaled(size1.width(), size1.height(),
                                     Qt.KeepAspectRatio,
                                     Qt.SmoothTransformation)
            self.drawLabel1.setPixmap(pixmap1)
            self.drawLabel1.setAlignment(Qt.AlignCenter)
        if not self.image2 is None:
            self.drawLabel2.clear()
            size2 = self.drawLabel2.size()
            qimage2 = QImage(self.image2.tobytes(), self.image2.shape[1],
                             self.image2.shape[0], QImage.Format_RGB888)
            pixmap2 = QPixmap(qimage2)
            pixmap2 = pixmap2.scaled(size2.width(), size2.height(),
                                     Qt.KeepAspectRatio,
                                     Qt.SmoothTransformation)
            self.drawLabel2.setPixmap(pixmap2)
            self.drawLabel2.setAlignment(Qt.AlignCenter)
        QMainWindow.paintEvent(self, event)
예제 #21
0
	def getMinimumSizeForOrientation ( self, orientation ) -> QSize:
		isDefaultOrientation = orientation == self.editor.GetDefaultOrientation ()
		contentMinSize = self.content.layout ().minimumSize ()

		topArea = self.toolBarAreaManager.getWidget ( CToolBarAreaManagerArea.Top )
		bottomArea = self.toolBarAreaManager.getWidget ( CToolBarAreaManagerArea.Bottom )
		leftArea = self.toolBarAreaManager.getWidget ( CToolBarAreaManagerArea.Left )
		rightArea = self.toolBarAreaManager.getWidget ( CToolBarAreaManagerArea.Right )

		result = QSize ( 0, 0 )
		if isDefaultOrientation:
			# Take width from left and right areas if we're switching to the editor's default orientation
			result.setWidth ( result.width () + leftArea.getLargestItemMinimumSize ().width () )
			result.setWidth ( result.width () + rightArea.getLargestItemMinimumSize ().width () )

			# Use top and bottom area to calculate min height
			result.setHeight ( result.height () + leftArea.getLargestItemMinimumSize ().height () )
			result.setHeight ( result.height () + rightArea.getLargestItemMinimumSize ().height () )

			# Add content min size
			result += contentMinSize

			# Take the area layout size hints into account. Expand the current result with the toolbar area layout's size hint.
			# We use size hint rather than minimum size since toolbar area item's size policy is set to preferred.
			result = result.expandedTo ( QSize ( topArea.layout ().sizeHint ().height (), leftArea.layout ().sizeHint ().width () ) )
			result = result.expandedTo ( QSize ( bottomArea.layout ().sizeHint ().height (), rightArea.layout ().sizeHint ().width () ) )
		else:
			# If we're not switching to the default orientation, then we need to use the top and bottom toolbar areas' width
			# since these areas will be placed at the left and right of the editor content in this case of adaptive layouts
			result.setWidth ( result.width () + topArea.getLargestItemMinimumSize ().width () )
			result.setWidth ( result.width () + bottomArea.getLargestItemMinimumSize ().width () )

			# We must also flip where we get toolbar area min height from
			result.setHeight ( result.height () + leftArea.getLargestItemMinimumSize ().height () )
			result.setHeight ( result.height () + rightArea.getLargestItemMinimumSize ().height () )

			# Add flipped content min size
			result += QSize ( contentMinSize.height (), contentMinSize.width () )

			result = result.expandedTo ( QSize ( leftArea.layout ().sizeHint ().height (), topArea.layout ().sizeHint ().width () ) )
			result = result.expandedTo ( QSize ( rightArea.layout ().sizeHint ().height (), bottomArea.layout ().sizeHint ().width () ) )

		return result
예제 #22
0
class Widget(QWidget):
    """
    Encapsulates a QWindow into a widget

    QWindow is preferred for rendering over a QWidget because there is more control over OpenGL. A QOpenGLWidget
    limitations impose undesirable effects onto WindowProxy. To use QOpenGLWidget, WindowProxy would need to draw to
    a QOffscreenSurface and blit the result onto the QOpenGLWidget at appropriate times.

    Attributes
    ----------
    _size_hint : QSize
        The hint that this widget provides to Qt for sizing

    """
    def __init__(self, window_type=Window):
        """
        Instantiates a widget that creates a new object of window_type and encapsulates it

        Attributes
        ----------
        window_type : class, optional
            The class type to encapsulated by this widget, default class is Window.

        """
        super().__init__()

        self._size_hint = QSize(DEFAULT_WIDTH, DEFAULT_HEIGHT)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        window = window_type()
        container = QWidget.createWindowContainer(window, self)
        self.setLayout(QGridLayout())
        self.layout().addWidget(container)

    def sizeHint(self):
        """
        Overrides QWidget.sizeHint() to provide the user set size hint

        Returns
        -------
        QSize
            Size hint to Qt

        """
        return self._size_hint

    def set_size_hint(self, width, height):
        """
        Set the preferred size for this widget

        The default size policy is QSizePolicy.Expanding. Therefore, Qt tries to make this widget as large as possible.
        Under this policy, Qt is allowed to shrink the widget below this size if necessary.

        Parameters
        ----------
        width : int
            The desired width
        height : int
            The desired height

        References
        ----------
        [1] https://doc.qt.io/qt-5/qsizepolicy.html#Policy-enum

        """
        self._size_hint.setWidth(width)
        self._size_hint.setHeight(height)
예제 #23
0
class MainWindow(QMainWindow, Ui_MainWindow):
    resized = QtCore.pyqtSignal()

    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.pushButton_bubble.clicked.connect(self.on_click)
        self.pushButton_dbsetting.clicked.connect(self.on_click)
        self.pushButton_shortcuts.clicked.connect(self.on_click)
        self.pushButton_calibrate.clicked.connect(self.on_click)
        self.pushButton_start.clicked.connect(self.on_click)
        self.pushButton_ok.clicked.connect(self.on_click)
        self.pushButton_cancel.clicked.connect(self.on_click)
        self.pushButton_apply.clicked.connect(self.on_click)
        self.edit_ratioValue.returnPressed.connect(self.on_enter)
        self.edit_id.returnPressed.connect(self.on_enter)
        self.check_id.stateChanged.connect(self.on_check)
        self.frame_board.installEventFilter(self)
        self.image = QImage()
        self.image_size = QSize()
        self.stack.setCurrentWidget(self.page_main)
        self.url = ""
        self.customConnected = False

    def on_calibration_click(self, name):
        if eq(name, "close"):
            self.calibration_window.destroy()
        if eq(name, "cancel"):
            self.calibration_window.destroy()
        if eq(name, "calibrate"):
            if eq(self.calibration_window.url, ""): return
            self.url = self.calibration_window.url
            self.setImageSize(self.calibration_window.image_size)
            self.calibration_window.destroy()
            self.setBoardBackground()

    def on_check(self):
        if self.check_id.isChecked():
            if self.isExistingID():
                self.warning("Duplicated ID!")
                self.check_id.setChecked(False)

    def on_enter(self):
        sending_edit = self.sender()
        if eq(sending_edit.objectName(), "edit_ratioValue"):
            if self.isFloat(self.edit_ratioValue.displayText()) is not True:
                return
            if eq(self.url, "") is True:
                self.edit_ratioValue.setText("")
                return
            width = (float(self.edit_ratioValue.displayText()) *
                     self.image.size().width()) / 100
            if width <= 0:
                self.setImageSize(self.image_size)
                return
            self.image_size.setWidth(width)
            self.image_size.setHeight(self.getScaledHeight(width))
            self.setImageSize(self.image_size)
        if eq(sending_edit.objectName(), "edit_id"):
            if self.isExistingID():
                self.warning("Duplicated ID!")
            elif self.isValidID() is not True:
                self.edit_id.setText("")
            else:
                self.check_id.setChecked(True)

    def warning(self, warning):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Critical)
        msg.setText(warning)
        msg.setWindowTitle("Error")
        msg.show()
        msg.exec_()

    def isValidID(self):
        if eq(self.edit_id.displayText(), "") is True: return False
        if len(self.edit_id.displayText()) > 255: return False
        return True

    def isExistingID(self):
        if self.customConnected is True:
            dbconn = MYSQL(dbhost=self.table.item(0, 0).text(),
                           dbuser=self.table.item(1, 0).text(),
                           dbpwd=self.table.item(2, 0).text(),
                           dbname=self.table.item(3, 0).text(),
                           dbcharset=self.table.item(4, 0).text())
        else:
            dbconn = MYSQL(dbhost=dbconstant.HOST,
                           dbuser=dbconstant.USER,
                           dbpwd=dbconstant.PASSWORD,
                           dbname=dbconstant.DB_NAME,
                           dbcharset=dbconstant.CHARSET)

        condition = {'id': self.edit_id.displayText()}
        count = dbconn.count(table=dbconstant.TABLE, condition=condition)
        dbconn.close()

        return True if count > 0 else False

    def isFloat(self, str):
        try:
            float(str)
            return True
        except:
            return False

    @pyqtSlot()
    def on_click(self):
        sending_button = self.sender()
        if eq(sending_button.objectName(), "pushButton_bubble"):
            self.toggleName(sending_button)
        if eq(sending_button.objectName(), "pushButton_dbsetting"):
            self.stack.setCurrentWidget(self.page_database)
        if eq(sending_button.objectName(), "pushButton_shortcuts"):
            self.stack.setCurrentWidget(self.page_shortcuts)
        if eq(sending_button.objectName(), "pushButton_calibrate"):
            if self.image_size.width() > pyautogui.size(
            ).width or self.image_size.height() > pyautogui.size().height:
                self.warning("Image size is too big")
                return
            self.calibration_window = Calibration(self, self.url,
                                                  self.image_size)
            self.calibration_window.show()
        if eq(sending_button.objectName(), "pushButton_start"):
            isPlotting = True if eq(self.pushButton_calibrate.text(),
                                    "ok") else False
            # 2. db 체크
            if self.check_id.isChecked():
                if eq(self.edit_id.text(), ""):
                    self.warning("there is no id")
                    return
                if self.isExistingID():
                    self.warning("Database ID Duplicated!")
                    return
                id = self.edit_id.text()
            else:
                id = ""
            # 3. 이미지 체크
            if eq(self.url, ""):
                self.warning("There is no image!")
                return
            if self.image_size.width() > pyautogui.size(
            ).width or self.image_size.height() > pyautogui.size().height:
                self.warning("Image size is too big")
                return
            self.tracking_window = Tracker(self.url, self.image_size,
                                           isPlotting, id, self.table,
                                           self.customConnected)
            self.tracking_window.showFullScreen()
            self.tracking_window.setFixedSize(self.tracking_window.size())
        if eq(sending_button.objectName(), "pushButton_ok"):
            self.stack.setCurrentWidget(self.page_main)
        if eq(sending_button.objectName(), "pushButton_cancel"):
            filled = self.checkFilled()
            if filled is False:
                self.table.clearContents()
                self.stack.setCurrentWidget(self.page_main)
                return
            if self.checkConnect() is False:
                self.table.clearContents()
                self.stack.setCurrentWidget(self.page_main)
        if eq(sending_button.objectName(), "pushButton_apply"):
            if self.checkFilled() is not True:
                self.warning("Not Filled!")
                return
            if self.checkConnect() is True:
                self.stack.setCurrentWidget(self.page_main)
            else:
                self.warning("Not Valid Information!")

    def checkFilled(self):
        for row in range(5):
            if self.table.item(row, 0) is None:
                self.customConnected = False
                return False
        return True

    def checkConnect(self):
        dbconn = MYSQL(dbhost=self.table.item(0, 0).text(),
                       dbuser=self.table.item(1, 0).text(),
                       dbpwd=self.table.item(2, 0).text(),
                       dbname=self.table.item(3, 0).text(),
                       dbcharset=self.table.item(4, 0).text())

        if dbconn.session() is None:
            dbconn.close()
            self.customConnected = False
            return False
        else:
            dbconn.close()
            self.customConnected = True
            return True

    def eventFilter(self, object, event):
        if object is self.frame_board:
            if event.type() == QtCore.QEvent.Drop:
                if event.mimeData().hasUrls():
                    event.accept()
                    self.url = event.mimeData().urls()[0].toLocalFile()
                    self.setBoardBackground()
                    self.setImageSize(self.image.size())
                else:
                    event.ignore()
        return False

    def setBoardBackground(self):
        self.image = QImage(self.url)
        pixmap = QPixmap(self.url)
        pixmap = pixmap.scaled(self.frame_board.width(),
                               self.getScaledHeight(self.frame_board.width()))
        self.frame_board.setPixmap(pixmap)

    def getScaledHeight(self, width):
        height = math.floor(
            (width * self.image.size().height()) / self.image.size().width())
        return height

    def setImageSize(self, size):
        self.image_size = size
        self.ratio = (100 *
                      self.image_size.width()) / self.image.size().width()
        self.label_widthValue.setText("%d" % self.image_size.width())
        self.label_heightValue.setText("%d" % self.image_size.height())
        self.edit_ratioValue.setText("%0.2f" % self.ratio)
예제 #24
0
 def sizeHint(self):
     """ Set a reasonable size for the list widget. """
     s = QSize()
     s.setHeight(super(ListWidget, self).sizeHint().height())
     s.setWidth(self.sizeHintForColumn(0))
     return s
예제 #25
0
class FaceView(QQuickGLItem):

    requestUpdate = pyqtSignal()
    setFloatParam = pyqtSignal(str, float)

    def __init__(self, parent=None):
        super(FaceView, self).__init__(parent=parent)

        self._params = {}
        self._size = QSize()
        self.detector = FaceDetector()

        lip_faces = np.array([
            [54, 55, 64],
            [55, 65, 64],
            [55, 56, 65],
            [56, 66, 65],
            [56, 57, 66],
            [57, 67, 66],
            [57, 58, 67],
            [58, 59, 67],
            [59, 60, 67],
            [59, 48, 60],
        ],
                             dtype=np.uint8)

        lm_model = ColorModel(name='facelm_model',
                              color=np.array([1.0, 0.3, 0.3],
                                             dtype=np.float32),
                              faces=lip_faces,
                              draw_point=False)
        self.lm_model = lm_model

        self.requestUpdate.connect(self._requestUpdate)
        self.setFloatParam.connect(self._setFloatParam)

        # Fixme: workaround...
        QTimer.singleShot(500, lambda: self.update())

    def geometryChanged(self, newGeometry, oldGeometry):
        if not newGeometry.isEmpty():
            if newGeometry.width() != self._size.width() or \
               newGeometry.height() != self._size.height():
                self._update_size(newGeometry.width(), newGeometry.height())
                self.update()

    def _update_size(self, w=0, h=0):
        if self.provider is None:
            return

        if w <= 0 or h <= 0:
            w, h = self.width(), self.height()

        w, h = geo.scale(1.0, self.provider.aspect_ratio, w, h, True)

        self._size.setWidth(w)
        self._size.setHeight(h)
        self.setWidth(w)
        self.setHeight(h)

    def _update_frame(self, image):
        if image is None:
            return None

        _, shapes = self.detector.detect(image)
        if shapes.shape[0] > 0:
            v_ndc = geo.to_ndc(shapes[0].astype(np.float32),
                               (image.shape[1], image.shape[0]))
            self.lm_model.vertices = v_ndc

        return image

    def _requestUpdate(self):
        self.update()

    def _setFloatParam(self, key, value):
        self._params[key] = value
        self.update()
예제 #26
0
class Button(QAbstractButton):
    clicked = pyqtSignal(int)
    leftClicked = pyqtSignal()
    middleClicked = pyqtSignal()
    rightClicked = pyqtSignal()
    activated = pyqtSignal()

    def __init__(self, label=None):

        super(Button, self).__init__()

        self._bgColor = QColor(51, 51, 51)
        self._activeBgColor = QColor(21, 21, 21)
        self._labelSize = QSize()
        self._size = QSize()
        self._iconSize = QSize()
        self._icon = None
        self._tooltip = None
        self._padding = 8
        self._idlePixmap = None
        self._checkedPixmap = None

        if label is not None:
            self.setText(label)

    def sizeHint(self):

        self._update_size()
        return self._size

    def setIcon(self, icon):

        self._icon = icon

        actual_size = self._icon.actualSize(self.size())

        self._iconSize.setWidth(actual_size.width())
        self._iconSize.setHeight(actual_size.height())

        self._update_icon_pixmaps()

        self.update()

    def setIconSize(self, size):

        self._iconSize.setWidth(size.width())
        self._iconSize.setHeight(size.height())

        self._update_icon_pixmaps()

        # self._updateSize()

        self.update()

    def set_tooltip(self, text):

        self._tooltip = text

    def resizeEvent(self, e):
        pass
        # self._updateSize()

    def mousePressEvent(self, e):

        if not self.isCheckable():

            self.setDown(True)

        else:

            was_checked = self.isChecked()

            self.setChecked(not self.isChecked())

            if not was_checked and self.isChecked():
                self.activated.emit()

    def mouseReleaseEvent(self, e):

        if not self.isCheckable():
            self.setDown(False)

        if e.button() == Qt.LeftButton:

            self.leftClicked.emit()

        elif e.button() == Qt.MiddleButton:

            self.middleClicked.emit()

        elif e.button() == Qt.RightButton:

            self.rightClicked.emit()

        self.clicked.emit(e.button())

    def enterEvent(self, e):

        if self._tooltip is not None and len(self._tooltip) > 0:
            QTimer.singleShot(300,
                              lambda t=self._tooltip: self._show_tooltip(t))

    def paintEvent(self, e):
        p = QPainter(self)

        active = self.isDown() or self.isChecked()

        if active:
            bg_color = self._activeBgColor
            border_color = bg_color.lighter(250)

        else:
            bg_color = self._bgColor
            border_color = bg_color.lighter(150)

        p.setPen(border_color)
        draw_rect = e.rect().adjusted(0, 0, -1, -1)

        p.drawRect(draw_rect)

        p.fillRect(draw_rect.adjusted(1, 1, 0, 0), bg_color)

        icon_margin = 0

        icon_present = self._icon is not None
        text_present = len(self.text()) > 0

        if icon_present:

            if not text_present:
                draw_x = round(draw_rect.width() / 2 -
                               self._iconSize.width() / 2)
                draw_y = round(draw_rect.height() / 2 -
                               self._iconSize.height() / 2)
            else:
                draw_x = self._padding
                draw_y = self._padding
                icon_margin = draw_x + self._iconSize.width()

            if not active and self._idlePixmap is not None:
                p.drawPixmap(draw_x, draw_y, self._idlePixmap)

            elif active and self._checkedPixmap is not None:

                p.drawPixmap(draw_x, draw_y, self._checkedPixmap)

        if text_present:

            p.setPen(Qt.white)

            if not icon_present:
                draw_x = round(draw_rect.width() / 2 -
                               self._labelSize.width() / 2)
                draw_y = round(draw_rect.height() / 2 +
                               self._labelSize.height() / 3)

            else:
                draw_x = icon_margin + 8
                draw_y = round(draw_rect.height() / 2 +
                               self._labelSize.height() / 3)

            p.drawText(draw_x, draw_y, self.text())

    def _update_icon_pixmaps(self):

        if self._icon is None:
            return

        self._idlePixmap = self._icon.pixmap(self._iconSize, QIcon.Normal,
                                             QIcon.Off)
        self._checkedPixmap = self._icon.pixmap(self._iconSize, QIcon.Normal,
                                                QIcon.On)

    def _update_size(self):

        width = 0
        height = 0

        if self._icon is not None:
            width = self._iconSize.width() + (self._padding * 2)
            height = self._iconSize.height() + (self._padding * 2)

        if len(self.text()) > 0:
            font_metrics = QFontMetrics(self.font())

            self._labelSize.setWidth(font_metrics.width(self.text()))
            self._labelSize.setHeight(font_metrics.height())

            width = width + self._labelSize.width() + self._padding

            if height == 0:
                height = self._labelSize.height() + self._padding * 2

        self._size.setWidth(width)
        self._size.setHeight(height)

    def _show_tooltip(self, text):

        QToolTip.showText(self.mapToGlobal(QPoint(0, self.height())), text)
예제 #27
0
 def sizeHint(self):
     s = QSize()
     s.setHeight(200)
     s.setWidth(150)
     return s
예제 #28
0
 def sizeHint(self, option: QStyleOptionViewItem,
              index: QtCore.QModelIndex) -> QtCore.QSize:
     sz = QSize(self.thumbnails.thumbnail_size)
     sz.setHeight(sz.height())
     sz.setWidth(sz.width())
     return sz
예제 #29
0
class ResizeHelper(QWidget):
    offsetChanged = pyqtSignal(QPoint)
    offsetXChanged = pyqtSignal(int)
    offsetYChanged = pyqtSignal(int)
    offsetBoundsChanged = pyqtSignal(QRect)

    def __init__(self, parent = None):
        super().__init__(parent)
        
        self.mMouseAnchorPoint = QPoint()
        self.mOffset = QPoint()
        self.mOldSize = QSize()
        self.mDragging = False
        self.mOffsetBounds = QRect()
        self.mScale = 0.0
        self.mNewSize = QSize()
        self.mOrigOffset = QPoint()
        
        self.setMinimumSize(20, 20)
        self.setOldSize(QSize(1, 1))

    def oldSize(self):
        return self.mOldSize

    def newSize(self):
        return self.mNewSize

    def offset(self):
        return self.mOffset

    def offsetBounds(self):
        return self.mOffsetBounds

    def setOldSize(self, size):
        self.mOldSize = size
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    def setNewSize(self, size):
        self.mNewSize = size
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    def setOffset(self, offset):
        # Clamp the offset within the offset bounds
        newOffset = QPoint(min(self.mOffsetBounds.right(),
                            max(self.mOffsetBounds.left(), offset.x())),
                                min(self.mOffsetBounds.bottom(),
                                    max(self.mOffsetBounds.top(), offset.y())))
        if (self.mOffset != newOffset):
            xChanged = self.mOffset.x() != newOffset.x()
            yChanged = self.mOffset.y() != newOffset.y()
            self.mOffset = newOffset
            if (xChanged):
                self.offsetXChanged.emit(self.mOffset.x())
            if (yChanged):
                self.offsetYChanged.emit(self.mOffset.y())
            self.offsetChanged.emit(self.mOffset)
            self.update()

    ## Method to set only the X offset, provided for convenience. */
    def setOffsetX(self, x):
        self.setOffset(QPoint(x, self.mOffset.y()))

    ## Method to set only the Y offset, provided for convenience. */
    def setOffsetY(self, y):
        self.setOffset(QPoint(self.mOffset.x(), y))

    ## Method to set only new width, provided for convenience. */
    def setNewWidth(self, width):
        self.mNewSize.setWidth(width)
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    ## Method to set only new height, provided for convenience. */
    def setNewHeight(self, height):
        self.mNewSize.setHeight(height)
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    def paintEvent(self, event):
        _size = self.size() - QSize(2, 2)
        if (_size.isEmpty()):
            return
        origX = (_size.width() - self.mNewSize.width() * self.mScale) / 2 + 0.5
        origY = (_size.height() - self.mNewSize.height() * self.mScale) / 2 + 0.5
        oldRect = QRect(self.mOffset, self.mOldSize)
        painter = QPainter(self)
        painter.translate(origX, origY)
        painter.scale(self.mScale, self.mScale)
        pen = QPen(Qt.black)
        pen.setCosmetic(True)
        painter.setPen(pen)
        painter.drawRect(QRect(QPoint(0, 0), self.mNewSize))
        pen.setColor(Qt.white)
        painter.setPen(pen)
        painter.setBrush(Qt.white)
        painter.setOpacity(0.5)
        painter.drawRect(oldRect)
        pen.setColor(Qt.black)
        pen.setStyle(Qt.DashLine)
        painter.setOpacity(1.0)
        painter.setBrush(Qt.NoBrush)
        painter.setPen(pen)
        painter.drawRect(oldRect)
        painter.end()

    def mousePressEvent(self, event):
        self.mMouseAnchorPoint = event.pos()
        self.mOrigOffset = self.mOffset
        self.mDragging = event.button() == Qt.LeftButton

    def mouseMoveEvent(self, event):
        if (not self.mDragging):
            return
        pos = event.pos()
        if (pos != self.mMouseAnchorPoint):
            self.setOffset(self.mOrigOffset + (pos - self.mMouseAnchorPoint) / self.mScale)
            self.offsetChanged.emit(self.mOffset)

    def resizeEvent(self, event):
        self.recalculateScale()

    def recalculateScale(self):
        _size = self.size() - QSize(2, 2)
        if (_size.isEmpty()):
            return
        if self.mOldSize.width() < self.mNewSize.width():
            width = self.mNewSize.width()
        else:
            width = 2 * self.mOldSize.width() - self.mNewSize.width()
        if self.mOldSize.height() < self.mNewSize.height():
            height = self.mNewSize.height()
        else:
            height = 2 * self.mOldSize.height() - self.mNewSize.height()

        # Pick the smallest scale
        scaleW = _size.width() / width
        scaleH = _size.height() / height
        if scaleW < scaleH:
            self.mScale = scaleW
        else:
            self.mScale = scaleH

        self.update()

    def recalculateMinMaxOffset(self):
        offsetBounds = self.mOffsetBounds
        if (self.mOldSize.width() <= self.mNewSize.width()):
            offsetBounds.setLeft(0)
            offsetBounds.setRight(self.mNewSize.width() - self.mOldSize.width())
        else:
            offsetBounds.setLeft(self.mNewSize.width() - self.mOldSize.width())
            offsetBounds.setRight(0)

        if (self.mOldSize.height() <= self.mNewSize.height()):
            offsetBounds.setTop(0)
            offsetBounds.setBottom(self.mNewSize.height() - self.mOldSize.height())
        else:
            offsetBounds.setTop(self.mNewSize.height() - self.mOldSize.height())
            offsetBounds.setBottom(0)

        if (self.mOffsetBounds != offsetBounds):
            self.mOffsetBounds = offsetBounds
            self.offsetBoundsChanged.emit(self.mOffsetBounds)
예제 #30
0
    def updateActionRect(self):
        """
        void QMenuPrivate::updateActionRects(const QRect &screen) const
        https://cep.xray.aps.anl.gov/software/qt4-x11-4.8.6-browser/da/d61/class_q_menu_private.html#acf93cda3ebe88b1234dc519c5f1b0f5d
        """
        self._aRect = {}
        topmargin = 0
        leftmargin = 0
        rightmargin = 0

        # qmenu.cpp Line 259:
        # init
        max_column_width = 0
        dh = self.height()
        y = 0
        style = self.style()
        opt = QStyleOption()
        opt.initFrom(self)
        hmargin = style.pixelMetric(QStyle.PM_MenuHMargin, opt, self)
        vmargin = style.pixelMetric(QStyle.PM_MenuVMargin, opt, self)
        icone = style.pixelMetric(QStyle.PM_SmallIconSize, opt, self)
        fw = style.pixelMetric(QStyle.PM_MenuPanelWidth, opt, self)
        deskFw = style.pixelMetric(QStyle.PM_MenuDesktopFrameWidth, opt, self)
        tearoffHeight = style.pixelMetric(QStyle.PM_MenuTearoffHeight, opt, self) if self.isTearOffEnabled() else 0

        # for compatibility now - will have to refactor this away
        tabWidth = 0
        maxIconWidth = 0
        hasCheckableItems = False
        # ncols = 1
        # sloppyAction = 0

        for i in range(len(self.actions())):
            act = self.actions()[i]
            if act.isSeparator() or act.isVisible() is False:
                continue
            # ..and some members
            hasCheckableItems |= act.isCheckable()
            ic = act.icon()
            if ic.isNull() is False:
                maxIconWidth = max(maxIconWidth, icone + 4)

        # qmenu.cpp Line 291:
        # calculate size
        qfm = self.fontMetrics()
        previousWasSeparator = True  # this is true to allow removing the leading separators
        for i in range(len(self.actions())):
            act = self.actions()[i]

            if act.isVisible() is False \
            or (self.separatorsCollapsible() and previousWasSeparator and act.isSeparator()):
                # we continue, this action will get an empty QRect
                self._aRect[i] = QRect()
                continue

            previousWasSeparator = act.isSeparator()

            # let the style modify the above size..
            opt = QStyleOptionMenuItem()
            self.initStyleOption(opt, act)
            fm = opt.fontMetrics

            sz = QSize()
            # sz = self.sizeHint().expandedTo(self.minimumSize()).expandedTo(self.minimumSizeHint()).boundedTo(self.maximumSize())
            # calc what I think the size is..
            if act.isSeparator():
                sz = QSize(2, 2)
            else:
                s = act.text()
                if '\t' in s:
                    t = s.index('\t')
                    act.setText(s[t + 1:])
                    tabWidth = max(int(tabWidth), qfm.width(s[t + 1:]))
                else:
                    seq = act.shortcut()
                    if seq.isEmpty() is False:
                        tabWidth = max(int(tabWidth), qfm.width(seq.toString()))

                sz.setWidth(fm.boundingRect(QRect(), Qt.TextSingleLine | Qt.TextShowMnemonic, s).width())
                sz.setHeight(fm.height())

                if not act.icon().isNull():
                    is_sz = QSize(icone, icone)
                    if is_sz.height() > sz.height():
                        sz.setHeight(is_sz.height())

            sz = style.sizeFromContents(QStyle.CT_MenuItem, opt, sz, self)

            if sz.isEmpty() is False:
                max_column_width = max(max_column_width, sz.width())
                # wrapping
                if y + sz.height() + vmargin > dh - deskFw * 2:
                    # ncols += 1
                    y = vmargin
                y += sz.height()
                # update the item
                self._aRect[i] = QRect(0, 0, sz.width(), sz.height())
        pass  # exit for

        max_column_width += tabWidth  # finally add in the tab width
        sfcMargin = style.sizeFromContents(QStyle.CT_Menu, opt, QApplication.globalStrut(),
                                           self).width() - QApplication.globalStrut().width()
        min_column_width = self.minimumWidth() - (sfcMargin + leftmargin + rightmargin + 2 * (fw + hmargin))
        max_column_width = max(min_column_width, max_column_width)

        # qmenu.cpp Line 259:
        # calculate position
        base_y = vmargin + fw + topmargin + tearoffHeight
        x = hmargin + fw + leftmargin
        y = base_y

        for i in range(len(self.actions())):
            if self._aRect[i].isNull():
                continue
            if y + self._aRect[i].height() > dh - deskFw * 2:
                x += max_column_width + hmargin
                y = base_y

            self._aRect[i].translate(x, y)  # move
            self._aRect[i].setWidth(max_column_width)  # uniform width
            y += self._aRect[i].height()

        # update menu size
        s = self.sizeHint()
        self.resize(s)
예제 #31
0
 def sizeHint(self):
     s = QSize()
     s.setHeight(super(CustomList, self).sizeHint().height())
     s.setWidth(self.sizeHintForColumn(0) + 25)
     return s
예제 #32
0
class TileLayer(Layer):
    ##
    # Constructor.
    ##
    def __init__(self, name, x, y, width, height):
        super().__init__(Layer.TileLayerType, name, x, y, width, height)
        self.mMaxTileSize = QSize(0, 0)
        self.mGrid = QVector()
        for i in range(width * height):
            self.mGrid.append(Cell())
        self.mOffsetMargins = QMargins()

    def __iter__(self):
        return self.mGrid.__iter__()

    ##
    # Returns the maximum tile size of this layer.
    ##
    def maxTileSize(self):
        return self.mMaxTileSize

    ##
    # Returns the margins that have to be taken into account while drawing
    # this tile layer. The margins depend on the maximum tile size and the
    # offset applied to the tiles.
    ##
    def drawMargins(self):
        return QMargins(
            self.mOffsetMargins.left(),
            self.mOffsetMargins.top() + self.mMaxTileSize.height(),
            self.mOffsetMargins.right() + self.mMaxTileSize.width(),
            self.mOffsetMargins.bottom())

    ##
    # Recomputes the draw margins. Needed after the tile offset of a tileset
    # has changed for example.
    #
    # Generally you want to call Map.recomputeDrawMargins instead.
    ##
    def recomputeDrawMargins(self):
        maxTileSize = QSize(0, 0)
        offsetMargins = QMargins()
        i = 0
        while (i < self.mGrid.size()):
            cell = self.mGrid.at(i)
            tile = cell.tile
            if tile:
                size = tile.size()
                if (cell.flippedAntiDiagonally):
                    size.transpose()
                offset = tile.offset()
                maxTileSize = maxSize(size, maxTileSize)
                offsetMargins = maxMargins(
                    QMargins(-offset.x(), -offset.y(), offset.x(), offset.y()),
                    offsetMargins)
            i += 1

        self.mMaxTileSize = maxTileSize
        self.mOffsetMargins = offsetMargins
        if (self.mMap):
            self.mMap.adjustDrawMargins(self.drawMargins())

    ##
    # Returns whether (x, y) is inside this map layer.
    ##
    def contains(self, *args):
        l = len(args)
        if l == 2:
            x, y = args
            return x >= 0 and y >= 0 and x < self.mWidth and y < self.mHeight
        elif l == 1:
            point = args[0]
            return self.contains(point.x(), point.y())

    ##
    # Calculates the region of cells in this tile layer for which the given
    # \a condition returns True.
    ##
    def region(self, *args):
        l = len(args)
        if l == 1:
            condition = args[0]
            region = QRegion()
            for y in range(self.mHeight):
                for x in range(self.mWidth):
                    if (condition(self.cellAt(x, y))):
                        rangeStart = x
                        x += 1
                        while (x <= self.mWidth):
                            if (x == self.mWidth
                                    or not condition(self.cellAt(x, y))):
                                rangeEnd = x
                                region += QRect(rangeStart + self.mX,
                                                y + self.mY,
                                                rangeEnd - rangeStart, 1)
                                break
                            x += 1

            return region
        elif l == 0:
            ##
            # Calculates the region occupied by the tiles of this layer. Similar to
            # Layer.bounds(), but leaves out the regions without tiles.
            ##
            return self.region(lambda cell: not cell.isEmpty())

    ##
    # Returns a read-only reference to the cell at the given coordinates. The
    # coordinates have to be within this layer.
    ##
    def cellAt(self, *args):
        l = len(args)
        if l == 2:
            x, y = args
            return self.mGrid.at(x + y * self.mWidth)
        elif l == 1:
            point = args[0]
            return self.cellAt(point.x(), point.y())

    ##
    # Sets the cell at the given coordinates.
    ##
    def setCell(self, x, y, cell):
        if (cell.tile):
            size = cell.tile.size()
            if (cell.flippedAntiDiagonally):
                size.transpose()
            offset = cell.tile.offset()
            self.mMaxTileSize = maxSize(size, self.mMaxTileSize)
            self.mOffsetMargins = maxMargins(
                QMargins(-offset.x(), -offset.y(), offset.x(), offset.y()),
                self.mOffsetMargins)
            if (self.mMap):
                self.mMap.adjustDrawMargins(self.drawMargins())

        self.mGrid[x + y * self.mWidth] = cell

    ##
    # Returns a copy of the area specified by the given \a region. The
    # caller is responsible for the returned tile layer.
    ##
    def copy(self, *args):
        l = len(args)
        if l == 1:
            region = args[0]
            if type(region) != QRegion:
                region = QRegion(region)
            area = region.intersected(QRect(0, 0, self.width(), self.height()))
            bounds = region.boundingRect()
            areaBounds = area.boundingRect()
            offsetX = max(0, areaBounds.x() - bounds.x())
            offsetY = max(0, areaBounds.y() - bounds.y())
            copied = TileLayer(QString(), 0, 0, bounds.width(),
                               bounds.height())
            for rect in area.rects():
                for x in range(rect.left(), rect.right() + 1):
                    for y in range(rect.top(), rect.bottom() + 1):
                        copied.setCell(x - areaBounds.x() + offsetX,
                                       y - areaBounds.y() + offsetY,
                                       self.cellAt(x, y))
            return copied
        elif l == 4:
            x, y, width, height = args

            return self.copy(QRegion(x, y, width, height))

    ##
    # Merges the given \a layer onto this layer at position \a pos. Parts that
    # fall outside of this layer will be lost and empty tiles in the given
    # layer will have no effect.
    ##
    def merge(self, pos, layer):
        # Determine the overlapping area
        area = QRect(pos, QSize(layer.width(), layer.height()))
        area &= QRect(0, 0, self.width(), self.height())
        for y in range(area.top(), area.bottom() + 1):
            for x in range(area.left(), area.right() + 1):
                cell = layer.cellAt(x - pos.x(), y - pos.y())
                if (not cell.isEmpty()):
                    self.setCell(x, y, cell)

    ##
    # Removes all cells in the specified region.
    ##
    def erase(self, area):
        emptyCell = Cell()
        for rect in area.rects():
            for x in range(rect.left(), rect.right() + 1):
                for y in range(rect.top(), rect.bottom() + 1):
                    self.setCell(x, y, emptyCell)

    ##
    # Sets the cells starting at the given position to the cells in the given
    # \a tileLayer. Parts that fall outside of this layer will be ignored.
    #
    # When a \a mask is given, only cells that fall within this mask are set.
    # The mask is applied in local coordinates.
    ##
    def setCells(self, x, y, layer, mask=QRegion()):
        # Determine the overlapping area
        area = QRegion(QRect(x, y, layer.width(), layer.height()))
        area &= QRect(0, 0, self.width(), self.height())
        if (not mask.isEmpty()):
            area &= mask
        for rect in area.rects():
            for _x in range(rect.left(), rect.right() + 1):
                for _y in range(rect.top(), rect.bottom() + 1):
                    self.setCell(_x, _y, layer.cellAt(_x - x, _y - y))

    ##
    # Flip this tile layer in the given \a direction. Direction must be
    # horizontal or vertical. This doesn't change the dimensions of the
    # tile layer.
    ##
    def flip(self, direction):
        newGrid = QVector()
        for i in range(self.mWidth * self.mHeight):
            newGrid.append(Cell())
        for y in range(self.mHeight):
            for x in range(self.mWidth):
                dest = newGrid[x + y * self.mWidth]
                if (direction == FlipDirection.FlipHorizontally):
                    source = self.cellAt(self.mWidth - x - 1, y)
                    dest = source
                    dest.flippedHorizontally = not source.flippedHorizontally
                elif (direction == FlipDirection.FlipVertically):
                    source = self.cellAt(x, self.mHeight - y - 1)
                    dest = source
                    dest.flippedVertically = not source.flippedVertically

        self.mGrid = newGrid

    ##
    # Rotate this tile layer by 90 degrees left or right. The tile positions
    # are rotated within the layer, and the tiles themselves are rotated. The
    # dimensions of the tile layer are swapped.
    ##
    def rotate(self, direction):
        rotateRightMask = [5, 4, 1, 0, 7, 6, 3, 2]
        rotateLeftMask = [3, 2, 7, 6, 1, 0, 5, 4]
        if direction == RotateDirection.RotateRight:
            rotateMask = rotateRightMask
        else:
            rotateMask = rotateLeftMask
        newWidth = self.mHeight
        newHeight = self.mWidth
        newGrid = QVector(newWidth * newHeight)
        for y in range(self.mHeight):
            for x in range(self.mWidth):
                source = self.cellAt(x, y)
                dest = source
                mask = (dest.flippedHorizontally << 2) | (
                    dest.flippedVertically << 1) | (
                        dest.flippedAntiDiagonally << 0)
                mask = rotateMask[mask]
                dest.flippedHorizontally = (mask & 4) != 0
                dest.flippedVertically = (mask & 2) != 0
                dest.flippedAntiDiagonally = (mask & 1) != 0
                if (direction == RotateDirection.RotateRight):
                    newGrid[x * newWidth + (self.mHeight - y - 1)] = dest
                else:
                    newGrid[(self.mWidth - x - 1) * newWidth + y] = dest

        t = self.mMaxTileSize.width()
        self.mMaxTileSize.setWidth(self.mMaxTileSize.height())
        self.mMaxTileSize.setHeight(t)
        self.mWidth = newWidth
        self.mHeight = newHeight
        self.mGrid = newGrid

    ##
    # Computes and returns the set of tilesets used by this tile layer.
    ##
    def usedTilesets(self):
        tilesets = QSet()
        i = 0
        while (i < self.mGrid.size()):
            tile = self.mGrid.at(i).tile
            if tile:
                tilesets.insert(tile.tileset())
            i += 1
        return tilesets

    ##
    # Returns whether this tile layer has any cell for which the given
    # \a condition returns True.
    ##
    def hasCell(self, condition):
        i = 0
        for cell in self.mGrid:
            if (condition(cell)):
                return True
            i += 1
        return False

    ##
    # Returns whether this tile layer is referencing the given tileset.
    ##
    def referencesTileset(self, tileset):
        i = 0
        while (i < self.mGrid.size()):
            tile = self.mGrid.at(i).tile
            if (tile and tile.tileset() == tileset):
                return True
            i += 1
        return False

    ##
    # Removes all references to the given tileset. This sets all tiles on this
    # layer that are from the given tileset to null.
    ##
    def removeReferencesToTileset(self, tileset):
        i = 0
        while (i < self.mGrid.size()):
            tile = self.mGrid.at(i).tile
            if (tile and tile.tileset() == tileset):
                self.mGrid.replace(i, Cell())
            i += 1

    ##
    # Replaces all tiles from \a oldTileset with tiles from \a newTileset.
    ##
    def replaceReferencesToTileset(self, oldTileset, newTileset):
        i = 0
        while (i < self.mGrid.size()):
            tile = self.mGrid.at(i).tile
            if (tile and tile.tileset() == oldTileset):
                self.mGrid[i].tile = newTileset.tileAt(tile.id())
            i += 1

    ##
    # Resizes this tile layer to \a size, while shifting all tiles by
    # \a offset.
    ##
    def resize(self, size, offset):
        if (self.size() == size and offset.isNull()):
            return
        newGrid = QVector()
        for i in range(size.width() * size.height()):
            newGrid.append(Cell())
        # Copy over the preserved part
        startX = max(0, -offset.x())
        startY = max(0, -offset.y())
        endX = min(self.mWidth, size.width() - offset.x())
        endY = min(self.mHeight, size.height() - offset.y())
        for y in range(startY, endY):
            for x in range(startX, endX):
                index = x + offset.x() + (y + offset.y()) * size.width()
                newGrid[index] = self.cellAt(x, y)

        self.mGrid = newGrid
        self.setSize(size)

    ##
    # Offsets the tiles in this layer within \a bounds by \a offset,
    # and optionally wraps them.
    #
    # \sa ObjectGroup.offset()
    ##
    def offsetTiles(self, offset, bounds, wrapX, wrapY):
        newGrid = QVector()
        for i in range(self.mWidth * self.mHeight):
            newGrid.append(Cell())
        for y in range(self.mHeight):
            for x in range(self.mWidth):
                # Skip out of bounds tiles
                if (not bounds.contains(x, y)):
                    newGrid[x + y * self.mWidth] = self.cellAt(x, y)
                    continue

                # Get position to pull tile value from
                oldX = x - offset.x()
                oldY = y - offset.y()
                # Wrap x value that will be pulled from
                if (wrapX and bounds.width() > 0):
                    while oldX < bounds.left():
                        oldX += bounds.width()
                    while oldX > bounds.right():
                        oldX -= bounds.width()

                # Wrap y value that will be pulled from
                if (wrapY and bounds.height() > 0):
                    while oldY < bounds.top():
                        oldY += bounds.height()
                    while oldY > bounds.bottom():
                        oldY -= bounds.height()

                # Set the new tile
                if (self.contains(oldX, oldY) and bounds.contains(oldX, oldY)):
                    newGrid[x + y * self.mWidth] = self.cellAt(oldX, oldY)
                else:
                    newGrid[x + y * self.mWidth] = Cell()

        self.mGrid = newGrid

    def canMergeWith(self, other):
        return other.isTileLayer()

    def mergedWith(self, other):
        o = other
        unitedBounds = self.bounds().united(o.bounds())
        offset = self.position() - unitedBounds.topLeft()
        merged = self.clone()
        merged.resize(unitedBounds.size(), offset)
        merged.merge(o.position() - unitedBounds.topLeft(), o)
        return merged

    ##
    # Returns the region where this tile layer and the given tile layer
    # are different. The relative positions of the layers are taken into
    # account. The returned region is relative to this tile layer.
    ##
    def computeDiffRegion(self, other):
        ret = QRegion()
        dx = other.x() - self.mX
        dy = other.y() - self.mY
        r = QRect(0, 0, self.width(), self.height())
        r &= QRect(dx, dy, other.width(), other.height())
        for y in range(r.top(), r.bottom() + 1):
            for x in range(r.left(), r.right() + 1):
                if (self.cellAt(x, y) != other.cellAt(x - dx, y - dy)):
                    rangeStart = x
                    while (x <= r.right() and
                           self.cellAt(x, y) != other.cellAt(x - dx, y - dy)):
                        x += 1

                    rangeEnd = x
                    ret += QRect(rangeStart, y, rangeEnd - rangeStart, 1)

        return ret

    ##
    # Returns True if all tiles in the layer are empty.
    ##
    def isEmpty(self):
        i = 0
        while (i < self.mGrid.size()):
            if (not self.mGrid.at(i).isEmpty()):
                return False
            i += 1
        return True

    ##
    # Returns a duplicate of this TileLayer.
    #
    # \sa Layer.clone()
    ##
    def clone(self):
        return self.initializeClone(
            TileLayer(self.mName, self.mX, self.mY, self.mWidth, self.mHeight))

    def begin(self):
        return self.mGrid.begin()

    def end(self):
        return self.mGrid.end()

    def initializeClone(self, clone):
        super().initializeClone(clone)
        clone.mGrid = self.mGrid
        clone.mMaxTileSize = self.mMaxTileSize
        clone.mOffsetMargins = self.mOffsetMargins
        return clone
예제 #33
0
class ResizeHelper(QWidget):
    offsetChanged = pyqtSignal(QPoint)
    offsetXChanged = pyqtSignal(int)
    offsetYChanged = pyqtSignal(int)
    offsetBoundsChanged = pyqtSignal(QRect)

    def __init__(self, parent=None):
        super().__init__(parent)

        self.mMouseAnchorPoint = QPoint()
        self.mOffset = QPoint()
        self.mOldSize = QSize()
        self.mDragging = False
        self.mOffsetBounds = QRect()
        self.mScale = 0.0
        self.mNewSize = QSize()
        self.mOrigOffset = QPoint()

        self.setMinimumSize(20, 20)
        self.setOldSize(QSize(1, 1))

    def oldSize(self):
        return self.mOldSize

    def newSize(self):
        return self.mNewSize

    def offset(self):
        return self.mOffset

    def offsetBounds(self):
        return self.mOffsetBounds

    def setOldSize(self, size):
        self.mOldSize = size
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    def setNewSize(self, size):
        self.mNewSize = size
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    def setOffset(self, offset):
        # Clamp the offset within the offset bounds
        newOffset = QPoint(
            min(self.mOffsetBounds.right(),
                max(self.mOffsetBounds.left(), offset.x())),
            min(self.mOffsetBounds.bottom(),
                max(self.mOffsetBounds.top(), offset.y())))
        if (self.mOffset != newOffset):
            xChanged = self.mOffset.x() != newOffset.x()
            yChanged = self.mOffset.y() != newOffset.y()
            self.mOffset = newOffset
            if (xChanged):
                self.offsetXChanged.emit(self.mOffset.x())
            if (yChanged):
                self.offsetYChanged.emit(self.mOffset.y())
            self.offsetChanged.emit(self.mOffset)
            self.update()

    ## Method to set only the X offset, provided for convenience. */
    def setOffsetX(self, x):
        self.setOffset(QPoint(x, self.mOffset.y()))

    ## Method to set only the Y offset, provided for convenience. */
    def setOffsetY(self, y):
        self.setOffset(QPoint(self.mOffset.x(), y))

    ## Method to set only new width, provided for convenience. */
    def setNewWidth(self, width):
        self.mNewSize.setWidth(width)
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    ## Method to set only new height, provided for convenience. */
    def setNewHeight(self, height):
        self.mNewSize.setHeight(height)
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    def paintEvent(self, event):
        _size = self.size() - QSize(2, 2)
        if (_size.isEmpty()):
            return
        origX = (_size.width() - self.mNewSize.width() * self.mScale) / 2 + 0.5
        origY = (_size.height() -
                 self.mNewSize.height() * self.mScale) / 2 + 0.5
        oldRect = QRect(self.mOffset, self.mOldSize)
        painter = QPainter(self)
        painter.translate(origX, origY)
        painter.scale(self.mScale, self.mScale)
        pen = QPen(Qt.black)
        pen.setCosmetic(True)
        painter.setPen(pen)
        painter.drawRect(QRect(QPoint(0, 0), self.mNewSize))
        pen.setColor(Qt.white)
        painter.setPen(pen)
        painter.setBrush(Qt.white)
        painter.setOpacity(0.5)
        painter.drawRect(oldRect)
        pen.setColor(Qt.black)
        pen.setStyle(Qt.DashLine)
        painter.setOpacity(1.0)
        painter.setBrush(Qt.NoBrush)
        painter.setPen(pen)
        painter.drawRect(oldRect)
        painter.end()

    def mousePressEvent(self, event):
        self.mMouseAnchorPoint = event.pos()
        self.mOrigOffset = self.mOffset
        self.mDragging = event.button() == Qt.LeftButton

    def mouseMoveEvent(self, event):
        if (not self.mDragging):
            return
        pos = event.pos()
        if (pos != self.mMouseAnchorPoint):
            self.setOffset(self.mOrigOffset +
                           (pos - self.mMouseAnchorPoint) / self.mScale)
            self.offsetChanged.emit(self.mOffset)

    def resizeEvent(self, event):
        self.recalculateScale()

    def recalculateScale(self):
        _size = self.size() - QSize(2, 2)
        if (_size.isEmpty()):
            return
        if self.mOldSize.width() < self.mNewSize.width():
            width = self.mNewSize.width()
        else:
            width = 2 * self.mOldSize.width() - self.mNewSize.width()
        if self.mOldSize.height() < self.mNewSize.height():
            height = self.mNewSize.height()
        else:
            height = 2 * self.mOldSize.height() - self.mNewSize.height()

        # Pick the smallest scale
        scaleW = _size.width() / width
        scaleH = _size.height() / height
        if scaleW < scaleH:
            self.mScale = scaleW
        else:
            self.mScale = scaleH

        self.update()

    def recalculateMinMaxOffset(self):
        offsetBounds = self.mOffsetBounds
        if (self.mOldSize.width() <= self.mNewSize.width()):
            offsetBounds.setLeft(0)
            offsetBounds.setRight(self.mNewSize.width() -
                                  self.mOldSize.width())
        else:
            offsetBounds.setLeft(self.mNewSize.width() - self.mOldSize.width())
            offsetBounds.setRight(0)

        if (self.mOldSize.height() <= self.mNewSize.height()):
            offsetBounds.setTop(0)
            offsetBounds.setBottom(self.mNewSize.height() -
                                   self.mOldSize.height())
        else:
            offsetBounds.setTop(self.mNewSize.height() -
                                self.mOldSize.height())
            offsetBounds.setBottom(0)

        if (self.mOffsetBounds != offsetBounds):
            self.mOffsetBounds = offsetBounds
            self.offsetBoundsChanged.emit(self.mOffsetBounds)
예제 #34
0
class TileLayer(Layer):
    ##
    # Constructor.
    ##
    def __init__(self, name, x, y, width, height):
        super().__init__(Layer.TileLayerType, name, x, y, width, height)
        self.mMaxTileSize = QSize(0, 0)
        self.mGrid = QVector()
        for i in range(width * height):
            self.mGrid.append(Cell())
        self.mOffsetMargins = QMargins()

    def __iter__(self):
        return self.mGrid.__iter__()
        
    ##
    # Returns the maximum tile size of this layer.
    ##
    def maxTileSize(self):
        return self.mMaxTileSize

    ##
    # Returns the margins that have to be taken into account while drawing
    # this tile layer. The margins depend on the maximum tile size and the
    # offset applied to the tiles.
    ##
    def drawMargins(self):
        return QMargins(self.mOffsetMargins.left(),
                        self.mOffsetMargins.top() + self.mMaxTileSize.height(),
                        self.mOffsetMargins.right() + self.mMaxTileSize.width(),
                        self.mOffsetMargins.bottom())

    ##
    # Recomputes the draw margins. Needed after the tile offset of a tileset
    # has changed for example.
    #
    # Generally you want to call Map.recomputeDrawMargins instead.
    ##
    def recomputeDrawMargins(self):
        maxTileSize = QSize(0, 0)
        offsetMargins = QMargins()
        i = 0
        while(i<self.mGrid.size()):
            cell = self.mGrid.at(i)
            tile = cell.tile
            if tile:
                size = tile.size()
                if (cell.flippedAntiDiagonally):
                    size.transpose()
                offset = tile.offset()
                maxTileSize = maxSize(size, maxTileSize)
                offsetMargins = maxMargins(QMargins(-offset.x(),
                                                     -offset.y(),
                                                     offset.x(),
                                                     offset.y()),
                                            offsetMargins)
            i += 1

        self.mMaxTileSize = maxTileSize
        self.mOffsetMargins = offsetMargins
        if (self.mMap):
            self.mMap.adjustDrawMargins(self.drawMargins())

    ##
    # Returns whether (x, y) is inside this map layer.
    ##
    def contains(self, *args):
        l = len(args)
        if l==2:
            x, y = args
            return x >= 0 and y >= 0 and x < self.mWidth and y < self.mHeight
        elif l==1:
            point = args[0]
            return self.contains(point.x(), point.y())

    ##
    # Calculates the region of cells in this tile layer for which the given
    # \a condition returns True.
    ##
    def region(self, *args):
        l = len(args)
        if l==1:
            condition = args[0]
            region = QRegion()
            for y in range(self.mHeight):
                for x in range(self.mWidth):
                    if (condition(self.cellAt(x, y))):
                        rangeStart = x
                        x += 1
                        while(x<=self.mWidth):
                            if (x == self.mWidth or not condition(self.cellAt(x, y))):
                                rangeEnd = x
                                region += QRect(rangeStart + self.mX, y + self.mY,
                                                rangeEnd - rangeStart, 1)
                                break
                            x += 1

            return region
        elif l==0:
            ##
            # Calculates the region occupied by the tiles of this layer. Similar to
            # Layer.bounds(), but leaves out the regions without tiles.
            ##
            return self.region(lambda cell:not cell.isEmpty())

    ##
    # Returns a read-only reference to the cell at the given coordinates. The
    # coordinates have to be within this layer.
    ##
    def cellAt(self, *args):
        l = len(args)
        if l==2:
            x, y = args
            return self.mGrid.at(x + y * self.mWidth)
        elif l==1:
            point = args[0]
            return self.cellAt(point.x(), point.y())

    ##
    # Sets the cell at the given coordinates.
    ##
    def setCell(self, x, y, cell):
        if (cell.tile):
            size = cell.tile.size()
            if (cell.flippedAntiDiagonally):
                size.transpose()
            offset = cell.tile.offset()
            self.mMaxTileSize = maxSize(size, self.mMaxTileSize)
            self.mOffsetMargins = maxMargins(QMargins(-offset.x(),
                                                 -offset.y(),
                                                 offset.x(),
                                                 offset.y()),
                                        self.mOffsetMargins)
            if (self.mMap):
                self.mMap.adjustDrawMargins(self.drawMargins())

        self.mGrid[x + y * self.mWidth] = cell

    ##
    # Returns a copy of the area specified by the given \a region. The
    # caller is responsible for the returned tile layer.
    ##
    def copy(self, *args):
        l = len(args)
        if l==1:
            region = args[0]
            if type(region) != QRegion:
                region = QRegion(region)
            area = region.intersected(QRect(0, 0, self.width(), self.height()))
            bounds = region.boundingRect()
            areaBounds = area.boundingRect()
            offsetX = max(0, areaBounds.x() - bounds.x())
            offsetY = max(0, areaBounds.y() - bounds.y())
            copied = TileLayer(QString(), 0, 0, bounds.width(), bounds.height())
            for rect in area.rects():
                for x in range(rect.left(), rect.right()+1):
                    for y in range(rect.top(), rect.bottom()+1):
                        copied.setCell(x - areaBounds.x() + offsetX,
                                        y - areaBounds.y() + offsetY,
                                        self.cellAt(x, y))
            return copied
        elif l==4:
            x, y, width, height = args

            return self.copy(QRegion(x, y, width, height))

    ##
    # Merges the given \a layer onto this layer at position \a pos. Parts that
    # fall outside of this layer will be lost and empty tiles in the given
    # layer will have no effect.
    ##
    def merge(self, pos, layer):
        # Determine the overlapping area
        area = QRect(pos, QSize(layer.width(), layer.height()))
        area &= QRect(0, 0, self.width(), self.height())
        for y in range(area.top(), area.bottom()+1):
            for x in range(area.left(), area.right()+1):
                cell = layer.cellAt(x - pos.x(), y - pos.y())
                if (not cell.isEmpty()):
                    self.setCell(x, y, cell)

    ##
    # Removes all cells in the specified region.
    ##
    def erase(self, area):
        emptyCell = Cell()
        for rect in area.rects():
            for x in range(rect.left(), rect.right()+1):
                for y in range(rect.top(), rect.bottom()+1):
                    self.setCell(x, y, emptyCell)

    ##
    # Sets the cells starting at the given position to the cells in the given
    # \a tileLayer. Parts that fall outside of this layer will be ignored.
    #
    # When a \a mask is given, only cells that fall within this mask are set.
    # The mask is applied in local coordinates.
    ##
    def setCells(self, x, y, layer, mask = QRegion()):
        # Determine the overlapping area
        area = QRegion(QRect(x, y, layer.width(), layer.height()))
        area &= QRect(0, 0, self.width(), self.height())
        if (not mask.isEmpty()):
            area &= mask
        for rect in area.rects():
            for _x in range(rect.left(), rect.right()+1):
                for _y in range(rect.top(), rect.bottom()+1):
                    self.setCell(_x, _y, layer.cellAt(_x - x, _y - y))

    ##
    # Flip this tile layer in the given \a direction. Direction must be
    # horizontal or vertical. This doesn't change the dimensions of the
    # tile layer.
    ##
    def flip(self, direction):
        newGrid = QVector()
        for i in range(self.mWidth * self.mHeight):
            newGrid.append(Cell())
        for y in range(self.mHeight):
            for x in range(self.mWidth):
                dest = newGrid[x + y * self.mWidth]
                if (direction == FlipDirection.FlipHorizontally):
                    source = self.cellAt(self.mWidth - x - 1, y)
                    dest = source
                    dest.flippedHorizontally = not source.flippedHorizontally
                elif (direction == FlipDirection.FlipVertically):
                    source = self.cellAt(x, self.mHeight - y - 1)
                    dest = source
                    dest.flippedVertically = not source.flippedVertically

        self.mGrid = newGrid

    ##
    # Rotate this tile layer by 90 degrees left or right. The tile positions
    # are rotated within the layer, and the tiles themselves are rotated. The
    # dimensions of the tile layer are swapped.
    ##
    def rotate(self, direction):
        rotateRightMask = [5, 4, 1, 0, 7, 6, 3, 2]
        rotateLeftMask  = [3, 2, 7, 6, 1, 0, 5, 4]
        if direction == RotateDirection.RotateRight:
            rotateMask = rotateRightMask
        else:
            rotateMask = rotateLeftMask
        newWidth = self.mHeight
        newHeight = self.mWidth
        newGrid = QVector(newWidth * newHeight)
        for y in range(self.mHeight):
            for x in range(self.mWidth):
                source = self.cellAt(x, y)
                dest = source
                mask = (dest.flippedHorizontally << 2) | (dest.flippedVertically << 1) | (dest.flippedAntiDiagonally << 0)
                mask = rotateMask[mask]
                dest.flippedHorizontally = (mask & 4) != 0
                dest.flippedVertically = (mask & 2) != 0
                dest.flippedAntiDiagonally = (mask & 1) != 0
                if (direction == RotateDirection.RotateRight):
                    newGrid[x * newWidth + (self.mHeight - y - 1)] = dest
                else:
                    newGrid[(self.mWidth - x - 1) * newWidth + y] = dest

        t = self.mMaxTileSize.width()
        self.mMaxTileSize.setWidth(self.mMaxTileSize.height())
        self.mMaxTileSize.setHeight(t)
        self.mWidth = newWidth
        self.mHeight = newHeight
        self.mGrid = newGrid

    ##
    # Computes and returns the set of tilesets used by this tile layer.
    ##
    def usedTilesets(self):
        tilesets = QSet()
        i = 0
        while(i<self.mGrid.size()):
            tile = self.mGrid.at(i).tile
            if tile:
                tilesets.insert(tile.tileset())
            i += 1
        return tilesets

    ##
    # Returns whether this tile layer has any cell for which the given
    # \a condition returns True.
    ##
    def hasCell(self, condition):
        i = 0
        for cell in self.mGrid:
            if (condition(cell)):
                return True
            i += 1
        return False

    ##
    # Returns whether this tile layer is referencing the given tileset.
    ##
    def referencesTileset(self, tileset):
        i = 0
        while(i<self.mGrid.size()):
            tile = self.mGrid.at(i).tile
            if (tile and tile.tileset() == tileset):
                return True
            i += 1
        return False

    ##
    # Removes all references to the given tileset. This sets all tiles on this
    # layer that are from the given tileset to null.
    ##
    def removeReferencesToTileset(self, tileset):
        i = 0
        while(i<self.mGrid.size()):
            tile = self.mGrid.at(i).tile
            if (tile and tile.tileset() == tileset):
                self.mGrid.replace(i, Cell())
            i += 1

    ##
    # Replaces all tiles from \a oldTileset with tiles from \a newTileset.
    ##
    def replaceReferencesToTileset(self, oldTileset, newTileset):
        i = 0
        while(i<self.mGrid.size()):
            tile = self.mGrid.at(i).tile
            if (tile and tile.tileset() == oldTileset):
                self.mGrid[i].tile = newTileset.tileAt(tile.id())
            i += 1

    ##
    # Resizes this tile layer to \a size, while shifting all tiles by
    # \a offset.
    ##
    def resize(self, size, offset):
        if (self.size() == size and offset.isNull()):
            return
        newGrid = QVector()
        for i in range(size.width() * size.height()):
            newGrid.append(Cell())
        # Copy over the preserved part
        startX = max(0, -offset.x())
        startY = max(0, -offset.y())
        endX = min(self.mWidth, size.width() - offset.x())
        endY = min(self.mHeight, size.height() - offset.y())
        for y in range(startY, endY):
            for x in range(startX, endX):
                index = x + offset.x() + (y + offset.y()) * size.width()
                newGrid[index] = self.cellAt(x, y)

        self.mGrid = newGrid
        self.setSize(size)

    ##
    # Offsets the tiles in this layer within \a bounds by \a offset,
    # and optionally wraps them.
    #
    # \sa ObjectGroup.offset()
    ##
    def offsetTiles(self, offset, bounds, wrapX, wrapY):
        newGrid = QVector()
        for i in range(self.mWidth * self.mHeight):
            newGrid.append(Cell())
        for y in range(self.mHeight):
            for x in range(self.mWidth):
                # Skip out of bounds tiles
                if (not bounds.contains(x, y)):
                    newGrid[x + y * self.mWidth] = self.cellAt(x, y)
                    continue

                # Get position to pull tile value from
                oldX = x - offset.x()
                oldY = y - offset.y()
                # Wrap x value that will be pulled from
                if (wrapX and bounds.width() > 0):
                    while oldX < bounds.left():
                        oldX += bounds.width()
                    while oldX > bounds.right():
                        oldX -= bounds.width()

                # Wrap y value that will be pulled from
                if (wrapY and bounds.height() > 0):
                    while oldY < bounds.top():
                        oldY += bounds.height()
                    while oldY > bounds.bottom():
                        oldY -= bounds.height()

                # Set the new tile
                if (self.contains(oldX, oldY) and bounds.contains(oldX, oldY)):
                    newGrid[x + y * self.mWidth] = self.cellAt(oldX, oldY)
                else:
                    newGrid[x + y * self.mWidth] = Cell()

        self.mGrid = newGrid

    def canMergeWith(self, other):
        return other.isTileLayer()

    def mergedWith(self, other):
        o = other
        unitedBounds = self.bounds().united(o.bounds())
        offset = self.position() - unitedBounds.topLeft()
        merged = self.clone()
        merged.resize(unitedBounds.size(), offset)
        merged.merge(o.position() - unitedBounds.topLeft(), o)
        return merged

    ##
    # Returns the region where this tile layer and the given tile layer
    # are different. The relative positions of the layers are taken into
    # account. The returned region is relative to this tile layer.
    ##
    def computeDiffRegion(self, other):
        ret = QRegion()
        dx = other.x() - self.mX
        dy = other.y() - self.mY
        r = QRect(0, 0, self.width(), self.height())
        r &= QRect(dx, dy, other.width(), other.height())
        for y in range(r.top(), r.bottom()+1):
            for x in range(r.left(), r.right()+1):
                if (self.cellAt(x, y) != other.cellAt(x - dx, y - dy)):
                    rangeStart = x
                    while (x <= r.right() and self.cellAt(x, y) != other.cellAt(x - dx, y - dy)):
                        x += 1

                    rangeEnd = x
                    ret += QRect(rangeStart, y, rangeEnd - rangeStart, 1)

        return ret

    ##
    # Returns True if all tiles in the layer are empty.
    ##
    def isEmpty(self):
        i = 0
        while(i<self.mGrid.size()):
            if (not self.mGrid.at(i).isEmpty()):
                return False
            i += 1
        return True

    ##
    # Returns a duplicate of this TileLayer.
    #
    # \sa Layer.clone()
    ##
    def clone(self):
        return self.initializeClone(TileLayer(self.mName, self.mX, self.mY, self.mWidth, self.mHeight))

    def begin(self):
        return self.mGrid.begin()
    
    def end(self):
        return self.mGrid.end()
        
    def initializeClone(self, clone):
        super().initializeClone(clone)
        clone.mGrid = self.mGrid
        clone.mMaxTileSize = self.mMaxTileSize
        clone.mOffsetMargins = self.mOffsetMargins
        return clone