Exemple #1
0
 def store_file(self, id, file):
     id = id.replace('/', '_')
     directory = ApplicationData.get('images')
     filename = os.path.join(directory, id + '.png')
     if filename == os.path.normpath(file):
         return self.iconmap.get(id, None)
     makedirs(directory)
     pixmap = QPixmap()
     if file is not None and pixmap.load(file):
         if pixmap.size().width() > self.max_size or pixmap.size().height(
         ) > self.max_size:
             pixmap = pixmap.scaled(self.max_size, self.max_size,
                                    Qt.KeepAspectRatio,
                                    Qt.SmoothTransformation)
         buffer = QBuffer()
         pixmap.save(buffer, 'png')
         data = str(buffer.data())
         with open(filename, 'wb') as f:
             f.write(data.encode())
         icon = QIcon(pixmap)
         icon.filename = filename
         icon.content = data
         icon.content_type = 'image/png'
     else:
         unlink(filename)
         icon = None
     self.iconmap[id] = icon
     return icon
Exemple #2
0
def show_splash(version=''):
    splash_fname = utils.get_resource_path('icons/splash.jpg')
    splash_pix = QPixmap(splash_fname)

    size = splash_pix.size()*.35
    splash_pix = splash_pix.scaled(size, Qt.KeepAspectRatio,
                                   transformMode=Qt.SmoothTransformation)
    numbers = {}
    for number in list(range(10)) + ['point']:
        fname = utils.get_resource_path('icons/{}.png'.format(number))
        pix = QPixmap(fname)
        size = pix.size() * .65
        numbers[str(number)] = pix.scaled(size, Qt.KeepAspectRatio,
                                transformMode=Qt.SmoothTransformation)
    numbers['.'] = numbers['point']

    painter = QPainter(splash_pix)
    painter.begin(splash_pix)

    x, y = 470, 70
    for digit in version:
        painter.drawPixmap(x, y, numbers[digit])
        x += numbers[digit].rect().width()/3

    painter.end()

    splash = QSplashScreen(splash_pix, Qt.WindowStaysOnBottomHint)
    splash.show()
    return splash
Exemple #3
0
    def init(self, ddir):
        """加载lolita.dat配置"""
        if not ddir or not isinstance(ddir, str): return
        try:
            if PY3: conf = json.loads(open(ddir + "/lolita.dat", "rb").read().decode())
            else: conf = json.loads(open(ddir + "/lolita.dat", "rb").read(), "utf-8")
            normal = conf.get("normal", "").format(DATA_DIR = ddir)
            move = conf.get("move", "").format(DATA_DIR = ddir)
            hover = conf.get("hover", "").format(DATA_DIR = ddir)
            press = conf.get("press", "").format(DATA_DIR = ddir)

            image = QPixmap(normal)
            self.resize(image.size())    # 设置窗口的大小
            self.setMinimumSize(image.size())
            self.setMaximumSize((image.size()))

            self.movies = {
                "normal": image,    # 普通
                "move": QPixmap(move),    # 移动
                "hover": QMovie(hover),    # 悬停(会动)
                "press": QPixmap(press),    # 按下
            }

            self._currentImage = image    # 当前的图形
            self.update()

            # 声音播放列表
            playList = conf.get("playList", [])
            self.player = LolitaPlayer(playList, ddir)
            self.player.setCurrentIndex(0)
        except Exception as e:
            self.close()
            traceback.print_exc(e)
Exemple #4
0
 def store_data(self, id, data):
     id = id.replace('/', '_')
     directory = ApplicationData.get('images')
     filename = os.path.join(directory, id + '.png')
     makedirs(directory)
     pixmap = QPixmap()
     if data is not None and pixmap.loadFromData(data):
         image_size = pixmap.size()
         if image_size.width() > self.max_size or image_size.height() > self.max_size:
             pixmap = pixmap.scaled(self.max_size, self.max_size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
         if imghdr.what(None, data) != 'png' or pixmap.size() != image_size:
             buffer = QBuffer()
             pixmap.save(buffer, 'png')
             data = str(buffer.data())
         with open(filename, 'wb') as f:
             f.write(data)
         icon = QIcon(pixmap)
         icon.filename = filename
         icon.content = data
         icon.content_type = 'image/png'
     else:
         unlink(filename)
         icon = None
     self.iconmap[id] = icon
     return icon
Exemple #5
0
 def store_file(self, id, file):
     id = id.replace('/', '_')
     directory = ApplicationData.get('images')
     filename = os.path.join(directory, id + '.png')
     if filename == os.path.normpath(file):
         return self.iconmap.get(id, None)
     makedirs(directory)
     pixmap = QPixmap()
     if file is not None and pixmap.load(file):
         if pixmap.size().width() > self.max_size or pixmap.size().height() > self.max_size:
             pixmap = pixmap.scaled(self.max_size, self.max_size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
         buffer = QBuffer()
         pixmap.save(buffer, 'png')
         data = str(buffer.data())
         with open(filename, 'wb') as f:
             f.write(data)
         icon = QIcon(pixmap)
         icon.filename = filename
         icon.content = data
         icon.content_type = 'image/png'
     else:
         unlink(filename)
         icon = None
     self.iconmap[id] = icon
     return icon
Exemple #6
0
 def store_data(self, id, data):
     id = id.replace('/', '_')
     directory = ApplicationData.get('images')
     filename = os.path.join(directory, id + '.png')
     makedirs(directory)
     pixmap = QPixmap()
     if data is not None and pixmap.loadFromData(data):
         image_size = pixmap.size()
         if image_size.width() > self.max_size or image_size.height(
         ) > self.max_size:
             pixmap = pixmap.scaled(self.max_size, self.max_size,
                                    Qt.KeepAspectRatio,
                                    Qt.SmoothTransformation)
         if imghdr.what(None, data) != 'png' or pixmap.size() != image_size:
             buffer = QBuffer()
             pixmap.save(buffer, 'png')
             data = str(buffer.data())
         with open(filename, 'wb') as f:
             f.write(data.encode())
         icon = QIcon(pixmap)
         icon.filename = filename
         icon.content = data
         icon.content_type = 'image/png'
     else:
         unlink(filename)
         icon = None
     self.iconmap[id] = icon
     return icon
    def initUI(self, gameboard):

        self.setFixedSize((gameboard.width - 1) * blockSize, 40)

        moneypix = QPixmap(os.path.join('./Pictures/', "money.png"))
        moneyLabel = QLabel(self)
        moneyLabel.setPixmap(moneypix)
        moneyLabel.setFixedSize(moneypix.size())
        moneyLabel.move(5, 10)
        moneyLabel.show()

        wavepix = QPixmap(os.path.join('./Pictures/', "waves.png"))
        waveLabel = QLabel(self)
        waveLabel.setPixmap(wavepix)
        waveLabel.setFixedSize(wavepix.size())
        waveLabel.move((gameboard.width - 1) * blockSize / 2 - 82, 8)
        waveLabel.show()

        self.hearts = []
        heart = QPixmap(os.path.join('./Pictures/', 'heart.png'))
        self.heart_lost = QPixmap(os.path.join('./Pictures/',
                                               'heart_lost.png'))
        i = 1

        while i <= self.parent.gameboard.startingLives:
            heartLabel = QLabel(self)
            heartLabel.setPixmap(heart)
            self.hearts.append([True, heartLabel])
            heartLabel.move((gameboard.width - 1) * blockSize - (2 + i * 12),
                            18)
            heartLabel.show()
            i += 1

        self.show()
Exemple #8
0
class ButtonPixmap(QGraphicsObject):
    clicked = pyqtSignal(str,str)
    def __init__(self, pix,name=None):
        super(ButtonPixmap, self).__init__()
        self.p = QPixmap(pix)
        self.name = name

    def paint(self, painter, option, widget):
        painter.drawPixmap(QPointF(), self.p)

    def boundingRect(self):
        return QRectF(QPointF(0, 0), QSizeF(self.p.size()))

    def mousePressEvent(self, event):
        #print("鼠标按下:::",self.name)
        self.clicked.emit(self.name,"press")
        event.accept()
    def mouseReleaseEvent(self, event):
        #print("鼠标释放:::",self.name)
        self.clicked.emit(self.name,"release")
        event.accept()

    def setGeometry(self, rect):
        super(ButtonPixmap, self).setGeometry(rect)
        if rect.size().width() > self.p.size().width():
            self.p = self.p.scaled(rect.size().toSize())
        else:
            self.p = QPixmap(self.p)
    def initUI(self, gameboard): 

        self.setFixedSize((gameboard.width - 1)*blockSize, 40)
        
        moneypix = QPixmap(os.path.join('./Pictures/', "money.png"))
        moneyLabel = QLabel(self)
        moneyLabel.setPixmap(moneypix)
        moneyLabel.setFixedSize(moneypix.size())
        moneyLabel.move(5, 10)
        moneyLabel.show()
        
        
        wavepix = QPixmap(os.path.join('./Pictures/', "waves.png"))
        waveLabel = QLabel(self)
        waveLabel.setPixmap(wavepix)
        waveLabel.setFixedSize(wavepix.size())
        waveLabel.move((gameboard.width - 1)*blockSize / 2 - 82, 8)
        waveLabel.show()
        
        self.hearts = []
        heart = QPixmap(os.path.join('./Pictures/', 'heart.png'))
        self.heart_lost = QPixmap(os.path.join('./Pictures/', 'heart_lost.png'))
        i = 1
        
        while i <= self.parent.gameboard.startingLives:
            heartLabel = QLabel(self)
            heartLabel.setPixmap(heart)
            self.hearts.append([True, heartLabel])
            heartLabel.move((gameboard.width - 1)*blockSize - (2 + i * 12), 18)
            heartLabel.show()
            i += 1
        
        self.show()
Exemple #10
0
    def _download_img(self, idx: int, url: str):
        self.logger.info('Downloading image [{}] from {}'.format(idx, url))
        res = self.http_client.get(url)

        if res:
            if not res.content:
                self.logger.warning('Image [{}] from {} has no content'.format(
                    idx, url))
                self.loaded_imgs.append(
                    self.i18n['screenshots.download.no_content'])
                self._load_img()
            else:
                self.logger.info(
                    'Image [{}] successfully downloaded'.format(idx))
                pixmap = QPixmap()
                pixmap.loadFromData(res.content)

                if pixmap.size().height() > self.MAX_HEIGHT or pixmap.size(
                ).width() > self.MAX_WIDTH:
                    pixmap = pixmap.scaled(self.MAX_WIDTH, self.MAX_HEIGHT,
                                           Qt.KeepAspectRatio,
                                           Qt.SmoothTransformation)

                self.loaded_imgs.append(pixmap)

                if self.img_idx == idx:
                    self._load_img()
        else:
            self.logger.info("Could not retrieve image [{}] from {}".format(
                idx, url))
            self.loaded_imgs.append(
                self.i18n['screenshots.download.no_response'])
            self._load_img()
Exemple #11
0
    def __init__(self, theme):
        QWidget.__init__(self)
        self.theme = theme
        self.themename = theme.name
        self.setMaximumWidth(400)
        picurl = ":/images/theme.png"
        self.url = theme.sample_url
        if theme.sample_pic:
            picurl = theme.sample_pic
        pic = FlatButton(picurl, picurl)
        map = QPixmap(400, 200)
        p = QPainter(map)
        p.setRenderHint(QPainter.Antialiasing)
        p.setRenderHint(QPainter.TextAntialiasing)
        p.drawImage(QRect(0, 0, 400, 200), QImage(picurl))
        p.fillRect(0, 0,
                   map.size().width(),
                   map.size().height(), QColor(69, 187, 230, 125))
        if self.url:
            w = 100
            h = 30

            p.fillRect(QRect((400 - w) / 2, (200 - h) / 2, w, h),
                       QColor(69, 187, 230, 255))
            p.drawRoundedRect(QRect((400 - w) / 2, (200 - h) / 2, w, h), 5, 5)
            font = QFont()
            font.setFamily("Arial")
            font.setBold(True)
            font.setPixelSize(20)
            p.setFont(font)
            p.setPen(QPen(Qt.black))
            p.drawText(QRectF(0, 0, 400, 200), "PREVIEW",
                       QTextOption(Qt.AlignHCenter | Qt.AlignVCenter))

            pic.clicked.connect(self.clicked)
        else:
            pic.setCursor(Qt.ArrowCursor)
        del p

        pic.setHoverPixmap(map)
        pic.setMaximumSize(400, 200)
        pic.setScaledContents(True)
        if theme.aktiv:
            name = QLabel(theme.name.upper() + " (Aktiv)")
        else:
            name = QLabel(theme.name.upper())
        fnt = name.font()
        fnt.setPointSize(13)
        fnt.setBold(True)
        name.setFont(fnt)
        layout = QGridLayout()
        layout.addWidget(pic, 0, 0, 1, 2)
        layout.addWidget(name, 1, 0)
        if not theme.aktiv:
            activate = QPushButton("Activate")
            layout.addWidget(activate, 1, 1, 1, 1, Qt.AlignRight)
            activate.clicked.connect(self.activate)

        self.setLayout(layout)
Exemple #12
0
 def _pixmap(self, dataBytes, h=200, w=150):
     pixmap = QPixmap()
     pixmap.loadFromData(dataBytes)
     if h is None or w is None:
         return pixmap
     height = pixmap.size().height()
     width = pixmap.size().width()
     if width == 0 or height == 0:
         return pixmap
     return pixmap.scaled(w, h, Qt.IgnoreAspectRatio,
                          Qt.SmoothTransformation)
Exemple #13
0
 def set_image(self, img: QPixmap = None):
     if img is None:
         self.view_img.clear()
         return
     w = img.size().width()
     h = img.size().height()
     if w > h:
         pix = img.scaledToWidth(60)
     else:
         pix = img.scaledToHeight(60)
     self.view_img.setPixmap(pix)
Exemple #14
0
    def set_Icon(self, img):
        if img != "":
            pixmap = QPixmap()
            ret = pixmap.load(img)
            if not ret:
                qDebug(f"{img}加载图片失败")

            self.setFixedSize(pixmap.size())
            self.setStyleSheet("QPushButton{border:0px;}")
            self.setIcon(QIcon(pixmap))
            self.setIconSize(pixmap.size())
 def update_background(self, image_path):
     #Update Background Picture
     self.scene.clear()
     pixMap = QPixmap(image_path)
     self.scene.addPixmap(pixMap)
     h = pixMap.size().height()
     w = pixMap.size().width()
     self.ui.graphic_background.setScene(self.scene)
     self.ui.graphic_background.fitInView(QRectF(0, 0, w, h),
                                          #Qt.KeepAspectRatio
                                          )
     self.scene.update()
    def init_gui(self):
        game_over_png = QPixmap('../pommerman/resources/game_over.png')
        self.mainframe.setPixmap(game_over_png)
        self.setGeometry(200, 200, game_over_png.size().width(), game_over_png.size().height())
        self.setWindowTitle('Game Over')
        continue_png = QPixmap('../pommerman/resources/continue.png')
        save_png = QPixmap('../pommerman/resources/save.png')

        create_button(self.continue_button, continue_png, 172, 355)
        create_button(self.save_button, save_png, 173, 393)

        self.continue_button.clicked.connect(self.continue_action)
        self.save_button.clicked.connect(self.save)
    def update_pixmap(self, file_name):
        pixmap = QPixmap(file_name)

        # Scale the pixmap if it's too large
        screen_avail = QDesktopWidget().availableGeometry()
        max_width = int(screen_avail.width() * 0.8)
        max_height = int(screen_avail.height() * 0.8)
        if pixmap.size().width() > max_width:
            pixmap = pixmap.scaledToWidth(max_width)
        if pixmap.size().height() > max_height:
            pixmap = pixmap.scaledToHeight(max_height)

        # Update the center widget with the pixmap
        self.lbl_img.setPixmap(pixmap)
        self.center()
Exemple #18
0
class AnimeWaiting(QLabel):
    def __init__(self, parent) -> None:
        super().__init__(parent)

        self.setScaledContents(True)

        self.bgpix = QPixmap('等待.svg')
        self.setPixmap(self.bgpix)

        timer = QTimer(self)
        timer.timeout.connect(self.update_func)
        timer.start(10)

        self.rotate_angle = 0

    def update_func(self):
        self.rotate_angle += 1
        if self.rotate_angle == 360:
            self.rotate_angle = 0
        self.update()

    def paintEvent(self, event: QPaintEvent) -> None:
        painter = QPainter(self)
        sz = self.bgpix.size()
        w, h = sz.width(), sz.height()
        painter.translate(w / 2, h / 2)
        painter.rotate(self.rotate_angle)
        painter.translate(-w / 2, -h / 2)
        painter.drawPixmap(0, 0, w, h, self.bgpix)
 def initUI(self):
     
     self.setFixedSize(400, 260)
     
     self.setWindowTitle('Fomoire!')
     fomoire = QPixmap(os.path.join('./Pictures/', "fomoire.png"))
     logo = QLabel(self)
     logo.setPixmap(fomoire)
     logo.setFixedSize(fomoire.size())
     logo.move(400 / 2 - fomoire.width() / 2, 15)
     
     towerDefence = QLabel('A Tower Defence Game', self)
     towerDefence.move(130, 66)
     
     selectMap = QLabel('Select map:', self)
     selectMap.move(50, 105)
     
     mapList = QComboBox(self)
     mapList.addItem('No map selected')
     
     for mapFile in os.listdir('./Maps/'):
         mapList.addItem(mapFile)
     
     mapList.move(135, 102)
     mapList.activated[str].connect(self.selectMap)
     
     setSpeed = QLabel('Set game speed:', self)
     setSpeed.move(50, 140)
     
     slow = QLabel('Slow', self)
     slow.move(170, 140)
     
     slider = QSlider(Qt.Horizontal, self)
     slider.setFocusPolicy(Qt.NoFocus)
     slider.setSliderPosition(100 - self.gameSpeed)
     slider.setGeometry(210, 140, 100, 20)
     slider.valueChanged[int].connect(self.changeGameSpeed)
     
     fast = QLabel('Fast', self)
     fast.move(325, 140)
     
     start = QPushButton('Start game!', self)
     start.move(145, 175)
     start.clicked[bool].connect(self.startGame)
     
     quitButton = QPushButton('Quit', self)
     quitButton.move(168, 210)
     quitButton.clicked[bool].connect(qApp.quit)
     
     barbarian = QLabel(self)
     brbr = QPixmap(os.path.join('./Pictures/', "barbarian.png"))
     barbarian.setPixmap(brbr)
     barbarian.move(70, 185)
     
     berserker = QLabel(self)
     berber = QPixmap(os.path.join('./Pictures/', "berserker_left.png"))
     berserker.setPixmap(berber)
     berserker.move(290, 185)
     
     self.show()
Exemple #20
0
class Gui(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.layout = QVBoxLayout()

        self.img_label = QLabel()
        self.image = QPixmap(":/ww_banner.png")
        size = self.image.size()
        width = math.floor(size.width() * 0.33)
        height = math.floor(size.height() * 0.33)
        self.image = self.image.scaled(width, height, QtCore.Qt.KeepAspectRatio)
        self.img_label.setPixmap(self.image)

        self.text_label = QLabel(
            "Talvisota - Winter War launcher. This launcher is ran minimized "
            "to track Steam play time. You may close this window or leave it open.\r\n\r\n"
            "Please note that the standard Rising Storm 2: Vietnam main menu and "
            "server browser are used for Talvisota - Winter War."
        )
        self.text_label.setWordWrap(True)
        self.text_label.setTextInteractionFlags(QtCore.Qt.TextBrowserInteraction)

        self.layout.addWidget(self.img_label)
        self.layout.addWidget(self.text_label)

        self.setLayout(self.layout)
        self.setWindowFlags(QtCore.Qt.MSWindowsFixedSizeDialogHint)
        self.setWindowTitle("Talvisota - Winter War")
        self.setWindowIcon(QIcon(":/ww_icon.ico"))
        self.setWindowState(QtCore.Qt.WindowMinimized)

    def warn(self, title: str, msg: str):
        QMessageBox.warning(self, title, msg)
 def loadDataFromFile(self, filePath, which, point, tmpPoint = None, newPoint = None):
     pixmap = QPixmap(filePath)
     self.size = pixmap.size()
     painter = QPainter(pixmap)
     painter.drawPixmap(pixmap.rect(), pixmap)
     if point is not None:
         pen = QPen(QtCore.Qt.red, 5)
         painter.setPen(pen)
         painter.setBrush(QtCore.Qt.red)
         for n in point:
             painter.drawEllipse(QPointF(n[0], n[1]), 10, 10)
     if tmpPoint != None:
         painter.setPen(QPen(QtCore.Qt.green, 5))
         painter.setBrush(QtCore.Qt.green)
         painter.drawEllipse(QPointF(tmpPoint[0], tmpPoint[1]), 10, 10)
         if point == self.leftPoint:
             self.tmpLDotPic = pixmap
         else:
             self.tmpRDotPic = pixmap
     if newPoint != None:
         painter.setPen(QPen(QtCore.Qt.blue, 5))
         painter.setBrush(QtCore.Qt.blue)
         for n in newPoint:
             painter.drawEllipse(QPointF(n[0], n[1]), 10, 10)
         if point == self.leftPoint:
             self.leftDot = pixmap
         if point == self.rightPoint:
             self.rightDot = pixmap
     del painter
     which.setPixmap(pixmap)
     which.setScaledContents(True)
     if self.Left & self.Right:
         self.loadedState()
Exemple #22
0
    def mousePressEvent(self, e: QtGui.QMouseEvent) -> None:
        item = self.itemAt(e.pos())
        if item is None:  # if not clicking on item, do nothing
            return

        if e.button() == Qt.RightButton:
            self.takeItem(self.row(item))
            self.parentWidget().parent().listWidget.addItem(item)
            pass

        else:
            rect = self.visualItemRect(item)
            itemPos = self.mapToParent(QPoint(rect.x(), rect.y()))

            filename = item.filename
            label = MovableLabel(self.window, filename)
            pixmap = QPixmap('Players/' + filename).scaledToHeight(
                100, QtCore.Qt.SmoothTransformation)
            label.setPixmap(pixmap)
            label.setFixedSize(pixmap.size())
            label.move(itemPos)
            label.grabMouse()
            label.oldPos = itemPos
            label.clicked = False
            label.show()
            label.ogIndex = self.row(item)

            self.takeItem(self.row(item))
Exemple #23
0
 def __init__(self, painting_model: PaintingModel, painting_controller: PaintingController):
     super().__init__()
     self.model = painting_model
     self.controller = painting_controller
     trump_painting = QPixmap(
         resource_filename('design.ui',
                           'resources/donald-trump.png')
     )
     self.scene_img = None
     pixmap_size = trump_painting.size()
     self.setMinimumSize(pixmap_size)
     self._height_for_width_factor = 1.0 * pixmap_size.height() / pixmap_size.width()
     self.grid_layout = QtWidgets.QGridLayout(self)
     self.grid_layout.setContentsMargins(0, 0, 0, 0)
     self.painting_view = QtWidgets.QGraphicsView(self)
     self.painting_view.setResizeAnchor(0)
     self.painting_view.setAlignment(Qt.AlignLeft | Qt.AlignTop)
     self.painting_scene = QtWidgets.QGraphicsScene()
     self.painting_view.setScene(self.painting_scene)
     self.grid_layout.addWidget(self.painting_view, 0, 0)
     self.painting_view.setRenderHint(QtGui.QPainter.Antialiasing)
     self.painting_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
     self.painting_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
     self.radius = 5
     self.painting_scene.addPixmap(trump_painting)
     self._painting_graphics = QGraphicsView()
     self.model.subscribe_update_function(self.update_world_image)
Exemple #24
0
def launch_main(xml_fname=None, introspect_fname=None):
    app = QApplication(sys.argv)

    import time
    start = time.time()
    splash_fname = utils.get_resource_path('icons/splash.jpg')
    splash_pix = QPixmap(splash_fname)

    size = splash_pix.size()*.35
    splash_pix = splash_pix.scaled(size, Qt.KeepAspectRatio,
                                transformMode=Qt.SmoothTransformation)

    # # below makes the pixmap half transparent
    painter = QPainter(splash_pix)
    painter.setCompositionMode(painter.CompositionMode_DestinationAtop)
    painter.end()

    splash = QSplashScreen(splash_pix, Qt.WindowStaysOnTopHint)
    splash.show()
    app.processEvents()
    time.sleep(2)

    app.processEvents()
    mdwiz = PyMdWizardMainForm()
    mdwiz.show()
    splash.finish(mdwiz)

    if xml_fname is not None and os.path.exists(xml_fname):
        mdwiz.open_file(xml_fname)

    if introspect_fname is not None and os.path.exists(introspect_fname):
        mdwiz.metadata_root.eainfo.detaileds[0].populate_from_fname(introspect_fname)
        mdwiz.metadata_root.eainfo.ui.fgdc_eainfo.setCurrentIndex(1)
    app.exec_()
class ShapeWidget(QWidget):
    def __init__(self, parent=None):
        super(ShapeWidget, self).__init__(parent)
        self.i = 1
        self.mypix()
        self.timer = QTimer()
        self.timer.setInterval(500)  # 500毫秒
        self.timer.timeout.connect(self.timeChange)
        self.timer.start()

# 顯示不規則 pic

    def mypix(self):
        self.update()
        if self.i == 5:
            self.i = 1
        self.mypic = {
            1: './images/left.png',
            2: "./images/up.png",
            3: './images/right.png',
            4: './images/down.png'
        }
        self.pix = QPixmap(
            self.mypic[self.i], "0",
            Qt.AvoidDither | Qt.ThresholdDither | Qt.ThresholdAlphaDither)
        self.resize(self.pix.size())
        self.setMask(self.pix.mask())
        self.dragPosition = None

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.m_drag = True
            self.m_DragPosition = event.globalPos() - self.pos()
            event.accept()
            self.setCursor(QCursor(Qt.OpenHandCursor))

    def mouseMoveEvent(self, QMouseEvent):
        if Qt.LeftButton and self.m_drag:
            self.move(QMouseEvent.globalPos() - self.m_DragPosition)
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        self.m_drag = False
        self.setCursor(QCursor(Qt.ArrowCursor))

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawPixmap(0, 0, self.pix.width(), self.pix.height(), self.pix)

    # 按兩下滑鼠事件
    def mouseDoubleClickEvent(self, event):
        if event.button() == 1:
            self.i += 1
            self.mypix()

# 每500毫秒修改paint

    def timeChange(self):
        self.i += 1
        self.mypix()
Exemple #26
0
    def __init__(self, vertices_model: VerticesModel,
                 vertices_controller: VerticesController):
        super().__init__()
        self.model = vertices_model
        self.controller = vertices_controller
        trump_painting = QPixmap(
            resource_filename('design.ui', 'resources/donald-trump.png'))
        self.scene_img = None
        pixmap_size = trump_painting.size()
        self.setMinimumSize(pixmap_size)
        self._height_for_width_factor = 1.0 * pixmap_size.height(
        ) / pixmap_size.width()
        self.path_lines_pen = QtGui.QPen(QColor('#f44280'), 5, Qt.SolidLine,
                                         Qt.RoundCap, Qt.RoundJoin)
        self.path_points_pen = QtGui.QPen(QColor('#95ff95'), 10)
        self.grid_layout = QtWidgets.QGridLayout(self)
        self.grid_layout.setContentsMargins(0, 0, 0, 0)
        self.vertices_view = QtWidgets.QGraphicsView(self)
        self.vertices_view.setResizeAnchor(0)
        self.vertices_view.setAlignment(Qt.AlignLeft | Qt.AlignTop)
        self.vertices_scene = QtWidgets.QGraphicsScene()
        self.vertices_view.setScene(self.vertices_scene)
        self.grid_layout.addWidget(self.vertices_view, 0, 0)
        self.vertices_view.setRenderHint(QtGui.QPainter.Antialiasing)
        self.vertices_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.vertices_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.radius = 5

        self.vertices_scene.addPixmap(trump_painting)

        self._painting_graphics = QGraphicsView()

        self.model.subscribe_update_function(self.draw_path)
Exemple #27
0
 def __init__(self, pixmap, overlay=None, grayout=False):
     super(CompositePixmap, self).__init__()
     base_pixmap = QPixmap(pixmap)
     if grayout:
         painter = QPainter(base_pixmap)
         painter.setCompositionMode(painter.CompositionMode_SourceIn)
         painter.fillRect(base_pixmap.rect(), QColor(128, 128, 128, 128))
         painter.end()
     if overlay:
         width = int(base_pixmap.size().width() / 2)
         height = int(base_pixmap.size().height() / 2)
         overlay_pixmap = QPixmap(overlay).scaled(width, height)
         painter = QPainter(base_pixmap)
         painter.drawPixmap(width, height, overlay_pixmap)
         painter.end()
     self.swap(base_pixmap)
Exemple #28
0
class Chessman(QLabel):
    """
    棋子类
    """

    def __init__(self, color: str, parent=None):
        assert color == 'w' or color == 'b'
        super().__init__(parent=parent)
        self.color = color
        self.pic = None
        if color == 'w':
            self.pic = QPixmap("./sources/white.png")
        else:
            self.pic = QPixmap("./sources/black.png")
        self.setFixedSize(self.pic.size())
        self.setPixmap(self.pic)

    def move_chessman(self, board, coord: QtCore.QPoint):
        x, y = coord.x(), coord.y()
        x0 = (x - PIVOT[0]) // (BORDER_SIZE + GRID_SIZE)
        y0 = (y - PIVOT[1]) // (BORDER_SIZE + GRID_SIZE)
        if x0 < 8 and y0 < 8:
            pic_x = PIVOT[0] + x0 * (BORDER_SIZE + GRID_SIZE) + BORDER_SIZE
            pic_y = PIVOT[1] + y0 * (BORDER_SIZE + GRID_SIZE) + BORDER_SIZE
            super().move(pic_x, pic_y)
            board.board[y0][x0] = self

    def reverse(self):
        self.color = 'w' if self.color == 'b' else 'b'
        if self.color == 'w':
            self.pic = QPixmap("./sources/white.png")
        else:
            self.pic = QPixmap("./sources/black.png")
        self.setPixmap(self.pic)
Exemple #29
0
 def _printLabel(self):
     # self.label.setText(self.__args[5]) if self.label.setObjectName=='Item_Name'else self.label.setText('')
     dialog = QPrintDialog(self.__printer, self)  #choose printer
     if not dialog.exec_():
         return
     for o in self.__oL:  #set value to label
         # print(o.objectName())
         if o.objectName() == 'ItemCode':
             o.setText(self.__args[1])
         if o.objectName() == 'Barcode':
             o.setBarcode(self.__args[2])
         if o.objectName() == 'ItemBarcode':
             o.setText(self.__args[2])
         if o.objectName() == 'PLU':
             o.setText(self.__args[3])
         if o.objectName() == 'ItemName':
             o.setText(self.__args[4])
     # for s in self.__args:
     #     print(s)
     painter = QPainter(self.__printer)
     image = QPixmap()
     image = self.grab(
         QRect(QPoint(0, 0), QSize(self.size().width(),
                                   self.size().height())))  # /* 绘制窗口至画布 */
     rect = painter.viewport()
     size = image.size()
     size.scale(rect.size(), Qt.KeepAspectRatio)
     painter.setViewport(rect.x(), rect.y(), size.width(), size.height())
     painter.setWindow(image.rect())
     painter.drawPixmap(0, 0, image)
Exemple #30
0
 def initColour(self,
                colourKey,
                button,
                prefMethod,
                byName=False,
                hasAlpha=False):
     """
     Public method to initialize a colour selection button.
     
     @param colourKey key of the colour resource (string)
     @param button reference to a button to show the colour on (QPushButton)
     @param prefMethod preferences method to get the colour
     @keyparam byName flag indicating to retrieve/save by colour name
         (boolean)
     @keyparam hasAlpha flag indicating to allow alpha channel (boolean)
     """
     colour = QColor(prefMethod(colourKey))
     size = button.size()
     pm = QPixmap(size.width() / 2, size.height() / 2)
     pm.fill(colour)
     button.setIconSize(pm.size())
     button.setIcon(QIcon(pm))
     button.setProperty("colorKey", colourKey)
     button.setProperty("hasAlpha", hasAlpha)
     button.clicked.connect(self.__selectColourSlot)
     self.__coloursDict[colourKey] = [colour, byName]
Exemple #31
0
class PuyoView(QAbstractButton):
    rightclick = pyqtSignal()
    leftclick = pyqtSignal()

    def __init__(self, image, opacity, parent=None):
        super().__init__(parent)
        self.setFocusPolicy(Qt.NoFocus)
        self.setGraphic(image, opacity)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.leftclick.emit()
        if event.button() == Qt.RightButton:
            self.rightclick.emit()

    def setGraphic(self, image, opacity):
        height, width, channel = image.shape
        qimg = QImage(
            image.tobytes(),
            width,
            height,
            channel * width,
            QImage.Format_RGBA8888,
        )
        self.image = QPixmap(qimg)
        self.opacity = opacity
        self.update()

    def paintEvent(self, _):
        painter = QPainter(self)
        painter.setOpacity(self.opacity)
        painter.drawPixmap(self.rect(), self.image)

    def sizeHint(self):
        return self.image.size()
Exemple #32
0
    def __init__(self, pixmap, text, size=0.5, corner=BottomRight):
        super().__init__()

        base_pixmap = QPixmap(pixmap)
        base_size = base_pixmap.size()
        base_max = min(base_size.height(), base_size.width())
        if not base_max:
            # Because gridsync.gui.systray.animation.currentPixmap() returns
            # a blank pixmap when unpausing the animation for the first time.
            # Returning early to prevents QPainter from spewing warnings.
            self.swap(base_pixmap)
            return

        badge_max = base_max * size
        pen_width = badge_max * 0.05
        rect = QRect(base_max * max(corner[0] - size, 0) + pen_width,
                     base_max * max(corner[1] - size, 0) + pen_width,
                     badge_max - pen_width, badge_max - pen_width)

        painter = QPainter(base_pixmap)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setPen(QPen(Qt.red, pen_width))
        painter.setBrush(QBrush(Qt.red))
        painter.drawEllipse(rect)

        if text:
            font = painter.font()
            font.setPixelSize(badge_max - pen_width)
            painter.setFont(font)
            painter.setPen(Qt.white)
            painter.drawText(rect, Qt.AlignCenter, str(text))

        painter.end()
        self.swap(base_pixmap)
Exemple #33
0
class Chessman(QLabel):
    '''
    棋子类
    '''
    def __init__(self, color, parent=None):
        super().__init__(parent=parent)
        self.pic = None
        self.color = color
        if color == 'w':  # 白棋
            self.pic = QPixmap("source/白子.png")
        elif color == 'b':  # 黑棋
            self.pic = QPixmap("source/黑子.png")
        else:
            raise InvailidArguementsException("构造棋子时的参数错误,请传入'b'(黑棋)或者'w'(白棋)")
        self.setFixedSize(self.pic.size())
        self.setPixmap(self.pic)

    def move(self, a0: QtCore.QPoint):
        # 通过点击点的位置,定位到棋盘的相交点上
        x = a0.x()
        y = a0.y()
        if (x - 50) % 30 <= 15:  # 对三十求余小于等于15,落子在左半边的交线上
            x = (x - 50) // 30 * 30  # 整除三十再乘以三十,目的是过滤掉除以三十的余数,使其正好落在标线上
        else:
            x = (x - 50) // 30 * 30 + 30  # 对三十求余大于15,落子在右半边的交线上
        if (y - 50) % 30 <= 15:  # 对三十求余小于等于15,落子在上半边的交线上
            y = (y - 50) // 30 * 30  # 整除三十再乘以三十,目的是过滤掉除以三十的余数,使其正好落在标线上
        else:
            y = (y - 50) // 30 * 30 + 30  # 对三十求余大于15,落子在下半边的交线上

        #最后横纵坐标各减去图片的一般,并且各加上50恢复原来的坐标
        x = x - self.pic.width() / 2 + 50
        y = y - self.pic.height() / 2 + 50
        super().move(x, y)
class MonoidAboutWindow(QDialog):
    """
    Applications About window. At the moment this window just displays the Monoid logo, without any additional
    informtion.
    """
    def __init__(self, app, *args, **kwargs):
        super(MonoidAboutWindow, self).__init__(*args, **kwargs)

        # Load required data for about window.
        self.logo = QPixmap("images/logo.png")
        self.app = app

        # Configure window.
        self.setWindowTitle("About {0}".format(app.applicationName()))

        # Add logo and app name labels.
        self.logo_view = QLabel(self)
        self.logo_view.setPixmap(self.logo)
        self.logo_view.setToolTip("I love you!")

    def show(self, *args):
        """
        Set the size to a fixed one after showing the window to disable the minimize and maximize button.
        """
        super(MonoidAboutWindow, self).show(*args)
        self.setFixedSize(self.logo.size())
    def initUI(self):

        self.setFixedSize(400, 260)

        self.setWindowTitle('Fomoire!')
        fomoire = QPixmap(os.path.join('./Pictures/', "fomoire.png"))
        logo = QLabel(self)
        logo.setPixmap(fomoire)
        logo.setFixedSize(fomoire.size())
        logo.move(400 / 2 - fomoire.width() / 2, 15)

        towerDefence = QLabel('A Tower Defence Game', self)
        towerDefence.move(130, 66)

        selectMap = QLabel('Select map:', self)
        selectMap.move(50, 105)

        mapList = QComboBox(self)
        mapList.addItem('No map selected')

        for mapFile in os.listdir('./Maps/'):
            mapList.addItem(mapFile)

        mapList.move(135, 102)
        mapList.activated[str].connect(self.selectMap)

        setSpeed = QLabel('Set game speed:', self)
        setSpeed.move(50, 140)

        slow = QLabel('Slow', self)
        slow.move(170, 140)

        slider = QSlider(Qt.Horizontal, self)
        slider.setFocusPolicy(Qt.NoFocus)
        slider.setSliderPosition(100 - self.gameSpeed)
        slider.setGeometry(210, 140, 100, 20)
        slider.valueChanged[int].connect(self.changeGameSpeed)

        fast = QLabel('Fast', self)
        fast.move(325, 140)

        start = QPushButton('Start game!', self)
        start.move(145, 175)
        start.clicked[bool].connect(self.startGame)

        quitButton = QPushButton('Quit', self)
        quitButton.move(168, 210)
        quitButton.clicked[bool].connect(qApp.quit)

        barbarian = QLabel(self)
        brbr = QPixmap(os.path.join('./Pictures/', "barbarian.png"))
        barbarian.setPixmap(brbr)
        barbarian.move(70, 185)

        berserker = QLabel(self)
        berber = QPixmap(os.path.join('./Pictures/', "berserker_left.png"))
        berserker.setPixmap(berber)
        berserker.move(290, 185)

        self.show()
Exemple #36
0
 def init_big_button(button, image_name):
     pix = QPixmap('/usr/share/ubiquity/qt/images/' + image_name)
     icon = QIcon(pix)
     button.setIcon(icon)
     button.setIconSize(pix.size())
     # Set a fixed height to ensure the button text is not cropped
     # when the window is resized
     button.setFixedHeight(button.sizeHint().height())
Exemple #37
0
 def __init__(self, parent, **kwargs):
     super().__init__(parent, **kwargs)
     pixmap = QPixmap(':/search_clear_13')
     self.setIcon(QIcon(pixmap))
     self.setIconSize(pixmap.size())
     self.setCursor(Qt.ArrowCursor)
     self.setPopupMode(QToolButton.InstantPopup)
     stylesheet = "QToolButton { border: none; padding: 0px; }"
     self.setStyleSheet(stylesheet)
Exemple #38
0
 def create_scene(self):
     pixmap = QPixmap(self.image_filename)
     size = pixmap.size()
     self.imageSizeChanged.emit(size)
     self._item = QGraphicsPixmapItem(pixmap)
     self._item.setCacheMode(QGraphicsPixmapItem.NoCache)
     self._item.setZValue(0)
     self.scene().addItem(self._item)
     self.__emit_scale_factor()
class ImageWidget(QWidget):
    def __init__(self, imagePath, parent):
        super(ImageWidget, self).__init__(parent)
        self.picture = QPixmap(imagePath)
        size = self.picture.size()
        self.picture = self.picture.scaled(size.width() / 2, size.height() / 2, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.drawPixmap(0, 0, self.picture)
Exemple #40
0
class Pixmap(QGraphicsObject):
    def __init__(self, pix):
        super(Pixmap, self).__init__()

        self.p = QPixmap(pix)

    def paint(self, painter, option, widget):
        painter.drawPixmap(QPointF(), self.p)

    def boundingRect(self):
        return QRectF(QPointF(0, 0), QSizeF(self.p.size()))
Exemple #41
0
    def loadImage(self):
        """Open a file dialog.
        """
        path, filters = QFileDialog.getOpenFileName(self, self.tr('Open file'), '.',
                                                    self.tr('Image (*.jpg *.png *.jpeg *.bmp)'))
        if path:
            self.sourcePathField.setText(path)

            pixmap = QPixmap(path)
            pixmap = self.fitImageToScreen(pixmap)
            self.imageLabel.setPixmap(pixmap)
            self.imageLabel.setFixedSize(pixmap.size())
Exemple #42
0
def _load_icon(filename, backgroundColor, width, height):
    foreground = QPixmap()
    foreground.load(filename)
    pixmap = QPixmap(foreground.size())
    pixmap.fill(backgroundColor)

    painter = QPainter()
    painter.begin(pixmap)
    painter.drawPixmap(QPointF(0, 0), foreground)
    painter.end()

    pixmap = pixmap.scaled(QSize(width, height), Qt.KeepAspectRatio, Qt.SmoothTransformation)
    return pixmap
Exemple #43
0
class ShapeWidget(QWidget):  
	def __init__(self,parent=None):  
		super(ShapeWidget,self).__init__(parent)
		self.i = 1
		self.mypix()
		self.timer = QTimer()
		self.timer.setInterval(500)  # 500毫秒
		self.timer.timeout.connect(self.timeChange)   
		self.timer.start()

    # 显示不规则 pic
	def mypix(self):
		self.update()
		if self.i == 5:
			self.i = 1
		self.mypic = {1: './images/left.png', 2: "./images/up.png", 3: './images/right.png', 4: './images/down.png'}
		self.pix = QPixmap(self.mypic[self.i], "0", Qt.AvoidDither | Qt.ThresholdDither | Qt.ThresholdAlphaDither)   
		self.resize(self.pix.size())
		self.setMask(self.pix.mask())  
		self.dragPosition = None

	def mousePressEvent(self, event):
		if event.button() == Qt.LeftButton:
			self.m_drag=True
			self.m_DragPosition=event.globalPos()-self.pos()
			event.accept()
			self.setCursor(QCursor(Qt.OpenHandCursor))

	def mouseMoveEvent(self, QMouseEvent):
		if Qt.LeftButton and self.m_drag:
			self.move(QMouseEvent.globalPos()- self.m_DragPosition )
			QMouseEvent.accept()
	
	def mouseReleaseEvent(self, QMouseEvent):
		self.m_drag=False
		self.setCursor(QCursor(Qt.ArrowCursor))
        
	def paintEvent(self, event):
		painter = QPainter(self)
		painter.drawPixmap(0, 0, self.pix.width(),self.pix.height(),self.pix)
    
	# 鼠标双击事件
	def mouseDoubleClickEvent(self, event):
		if event.button() == 1:
			self.i += 1
			self.mypix()

    # 每500毫秒修改paint
	def timeChange(self):
		self.i += 1
		self.mypix()
    def requestPixmap(self, id, size):
        row = int(id)

        if row < 0 or row >= self.model.rowCount():
            return QPixmap(), QSize()

        data = self.model.imageData(row)
        if data == None:
            return QPixmap(), QSize()

        pixmap = QPixmap()
        if not pixmap.loadFromData(data):
            return QPixmap(), QSize()

        return pixmap, pixmap.size()
Exemple #45
0
class Pixmap(QGraphicsWidget):
    clicked = pyqtSignal()

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

        self.orig = QPixmap(pix)
        self.p = QPixmap(pix)

    def paint(self, painter, option, widget):
        painter.drawPixmap(QPointF(), self.p)

    def mousePressEvent(self, ev):
        self.clicked.emit()

    def setGeometry(self, rect):
        super(Pixmap, self).setGeometry(rect)

        if rect.size().width() > self.orig.size().width():
            self.p = self.orig.scaled(rect.size().toSize())
        else:
            self.p = QPixmap(self.orig)
 def initColour(self, colourKey, button, prefMethod, byName=False,
                hasAlpha=False):
     """
     Public method to initialize a colour selection button.
     
     @param colourKey key of the colour resource (string)
     @param button reference to a button to show the colour on (QPushButton)
     @param prefMethod preferences method to get the colour
     @keyparam byName flag indicating to retrieve/save by colour name
         (boolean)
     @keyparam hasAlpha flag indicating to allow alpha channel (boolean)
     """
     colour = QColor(prefMethod(colourKey))
     size = button.size()
     pm = QPixmap(size.width() / 2, size.height() / 2)
     pm.fill(colour)
     button.setIconSize(pm.size())
     button.setIcon(QIcon(pm))
     button.setProperty("colorKey", colourKey)
     button.setProperty("hasAlpha", hasAlpha)
     button.clicked.connect(self.__selectColourSlot)
     self.__coloursDict[colourKey] = [colour, byName]
Exemple #47
0
class ImageViewerCenter(QScrollArea):
	topZoneEntered = Signal()
	topZoneLeft = Signal()
	leftZoneEntered = Signal()
	leftZoneLeft = Signal()

	def __init__(self):
		QScrollArea.__init__(self)
		self.zoomMode = ZOOM_FACTOR
		self.zoomFactor = 1
		self.moving = None

		imgWidget = QLabel()
		imgWidget.setMouseTracking(True)
		imgWidget.setAlignment(Qt.AlignCenter)
		self.setWidget(imgWidget)

		self.setAlignment(Qt.AlignCenter)
		self.setMouseTracking(True)
		self.setFrameShape(self.NoFrame)
		self.setWidgetResizable(True)

		pal = QPalette()
		pal.setColor(QPalette.Window, Qt.black)
		self.setPalette(pal)

		self.leftZone = False
		self.topZone = False

	### events
	def mousePressEvent(self, ev):
		self.moving = (ev.pos().x(), ev.pos().y())
		self.movingScrolls = (self.horizontalScrollBar().value(), self.verticalScrollBar().value())

	def mouseReleaseEvent(self, ev):
		self.moving = False

	def mouseMoveEvent(self, ev):
		if self.moving:
			p = ev.pos()
			self.horizontalScrollBar().setValue(self.movingScrolls[0] - (p.x() - self.moving[0]))
			self.verticalScrollBar().setValue(self.movingScrolls[1] - (p.y() - self.moving[1]))
		else:
			newLeft = (ev.x() < 30)
			if newLeft and not self.leftZone:
				self.leftZoneEntered.emit()
			elif self.leftZone and not newLeft:
				self.leftZoneLeft.emit()
			self.leftZone = newLeft

			newTop = (ev.y() < 30)
			if newTop and not self.topZone:
				self.topZoneEntered.emit()
			elif self.topZone and not newTop:
				self.topZoneLeft.emit()
			self.topZone = newTop

	def resizeEvent(self, ev):
		super(ImageViewerCenter, self).resizeEvent(ev)
		if self.zoomMode != ZOOM_FACTOR:
			self._rebuildZoom()

	def keyPressEvent_(self, ev):
		if ev.key() not in (Qt.Key_PageUp, Qt.Key_PageDown):
			QScrollArea.keyPressEvent(self, ev)

	def keyReleaseEvent_(self, ev):
		if ev.key() == Qt.Key_PageUp:
			self.imageviewer.prevImage_s()
		elif ev.key() == Qt.Key_PageDown:
			self.imageviewer.nextImage_s()
		else:
			QScrollArea.keyReleaseEvent(self, ev)

	### public
	def setZoomMode(self, mode):
		self.zoomMode = mode
		self._rebuildZoom()

	def setZoomFactor(self, factor):
		self.zoomFactor = factor
		self.setZoomMode(ZOOM_FACTOR)

	def multiplyZoomFactor(self, factor):
		self.setZoomFactor(self.zoomFactor * factor)

	def setFile(self, file):
		self.file = file
		self.originalPixmap = QPixmap(file)
		#~ self.widget().setPixmap()
		self._rebuildZoom()

	###
	def _rebuildZoom(self):
		if self.zoomMode == ZOOM_FACTOR:
			if self.zoomFactor == 1:
				self._setPixmap(self.originalPixmap)
			else:
				self._setPixmap(self._getScaledPixmap(self.originalPixmap.size() * self.zoomFactor))
		elif self.zoomMode == ZOOM_FITALL:
			newpix = self._getScaledPixmap(self.viewport().size())
			self._setPixmap(newpix)
			self.zoomFactor = newpix.size().width() / float(self.originalPixmap.size().width())
		elif self.zoomMode == ZOOM_FITCUT:
			newpix = self._getScaledPixmap(self.viewport().size(), Qt.KeepAspectRatioByExpanding)
			self._setPixmap(newpix)
			self.zoomFactor = newpix.size().width() / float(self.originalPixmap.size().width())

	def _getScaledPixmap(self, size, mode=Qt.KeepAspectRatio):
		return self.originalPixmap.scaled(size, mode, Qt.SmoothTransformation)

	def _setPixmap(self, pixmap):
		self.widget().setPixmap(pixmap)
Exemple #48
0
class Ground(QLabel):
    def __init__(self, parent):
        QLabel.__init__(self, parent)
        self.symbol = QPixmap()
        self.symbol.load('gnd.png')
        self.symbol = self.symbol.scaledToWidth(30)
        self.resize(self.symbol.size())
        self.setPixmap(self.symbol)
        self.move(300, 300)
        self.show()

        self.Node = node(parent)
        self.Node.move(self.x() + 10, self.y())
        self.Node.id = 'N0'
        self.Node.show()
        self.parent().node_dict['N0'].add(self)

        # When right click on element a menu pops on
        self.PropMenu = QMenu(parent)
        # self.PropMenu.addAction('Rotate')
        self.PropMenu.addAction('Delete')
        # Setting Geometry of menu
        self.PropMenu.move(parent.frameGeometry().left() + self.x() + 30,
                           parent.frameGeometry().top() + self.y() + 30)

    def mousePressEvent(self, event):
        self.__mousePressPos = None
        self.__mouseMovePos = None
        if event.button() == QtCore.Qt.LeftButton:
            self.__mousePressPos = event.globalPos()
            self.__mouseMovePos = event.globalPos()

        if event.button() == QtCore.Qt.RightButton:
            action = self.PropMenu.exec()

            if action is not None:
                if action.text() == 'Delete':
                    print('Delete clicked')
                    self.deleteMe()

                # elif action.text() == 'Rotate':
                #     print('Rotate clicked')
                #     # self.Rotate()

        super(Ground, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() == QtCore.Qt.LeftButton:
            # adjust offset from clicked point to origin of widget
            currPos = self.mapToGlobal(self.pos())
            globalPos = event.globalPos()
            diff = globalPos - self.__mouseMovePos
            newPos = self.mapFromGlobal(currPos + diff)

            # Moving element to new position
            self.move(newPos)

            self.Node.move(newPos.x() + 10, newPos.y() )
            self.PropMenu.move(self.parent().frameGeometry().left() + newPos.x() + 30,
                               self.parent().frameGeometry().top() + newPos.y() + 30)

            self.__mouseMovePos = globalPos
        super(Ground, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if self.__mousePressPos is not None:
            moved = event.globalPos() - self.__mousePressPos
            if moved.manhattanLength() > 3:
                event.ignore()
                return

        super(Ground, self).mouseReleaseEvent(event)

    def deleteMe(self):
        self.hide()
        self.Node.hide()
Exemple #49
0
class Inductor(element):
    def __init__(self, name, parent, value = 0.01):
        element.__init__(self, name, parent, value)
        self.Impedance = 1j *2 * np.pi * Current_src.freq * self.value

        # adding image to resistor(that is a QLabel object itself) as its symbol
        self.symbol = QPixmap()
        self.symbol.load('ind.png')
        self.symbol = self.symbol.scaledToWidth(100)
        self.resize(self.symbol.size())
        self.setPixmap(self.symbol)
        self.move(200, 100)

        self.valueText = QLineEdit(parent)
        self.valueText.move(self.x() + 30, self.y() + 40)
        self.valueText.resize(50, 15)
        self.valueText.setText(str(self.value) + '  H')

        self.idLabel = QLabel(parent)
        self.idLabel.move(self.x() + 45, self.y())
        self.idLabel.resize(20, 15)
        self.idLabel.setText(str(self.name))
        self.idLabel.show()

        self.nodeP = node(parent)
        self.nodeS = node(parent)
        self.nodeP.move(self.x(), self.y() + 22)
        self.nodeS.move(self.x() + 90, self.y() + 22)
        self.nodeP.show()
        self.nodeS.show()
        # first element tahr is connected to a ned is It's element.
        self.nodeP.connected_elements.add(self.name)
        self.nodeS.connected_elements.add(self.name)

        # When right click on element a menu pops on
        self.PropMenu = QMenu(parent)
        self.PropMenu.addAction('Change Value')
        self.PropMenu.addAction('Rotate')
        self.PropMenu.addAction('Delete')
        # Setting Geometry of menu
        self.PropMenu.move(parent.frameGeometry().left() + self.x() + 20,
                           parent.frameGeometry().top() + self.y() + 100)

        self.isHorizontal = True

        self.direction_label = QLabel(parent)
        self.direction = QPixmap()

        self.valueText.show()
        self.show()

    def mousePressEvent(self, event):
        self.__mousePressPos = None
        self.__mouseMovePos = None
        if event.button() == QtCore.Qt.LeftButton:
            self.__mousePressPos = event.globalPos()
            self.__mouseMovePos = event.globalPos()

        if event.button() == QtCore.Qt.RightButton:
            action = self.PropMenu.exec()

            if action is not None:
                if action.text() == 'Change Value':
                    print('Change Value clicked')
                    self.value = float(re.match('\d*(?:.\d*e?-?\d*)?', self.valueText.text()).group())
                    self.Impedance = 1j *2 * np.pi * Current_src.freq * self.value

                elif action.text() == 'Rotate':
                    print('Rotate clicked')
                    self.Rotate()

                elif action.text() == 'Delete':
                    print('Delete clicked')
                    self.deleteMe()
                    self.parent().elements.remove(self)

        super(Inductor, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        if event.buttons() == QtCore.Qt.LeftButton:
            # adjust offset from clicked point to origin of widget
            currPos = self.mapToGlobal(self.pos())
            globalPos = event.globalPos()
            diff = globalPos - self.__mouseMovePos
            newPos = self.mapFromGlobal(currPos + diff)

            # Moving element to new position
            self.move(newPos)
            if self.isHorizontal:
                self.nodeP.move(newPos.x(), newPos.y() + 22)
                self.nodeS.move(newPos.x() + 90, newPos.y() + 22)
                self.valueText.move(newPos.x() + 30, newPos.y() + 40)
                self.idLabel.move(newPos.x() + 45, newPos.y())
                self.PropMenu.move(self.parent().frameGeometry().left() + newPos.x() + 20,
                                   self.parent().frameGeometry().top() + newPos.y() + 100)
            else:
                self.nodeP.move(newPos.x() + 18, newPos.y())
                self.nodeS.move(newPos.x() + 18, newPos.y() + 90)
                self.valueText.move(newPos.x() + 40, newPos.y() + 45)
                self.idLabel.move(newPos.x() + 40, newPos.y() + 25)
                self.PropMenu.move(self.parent().frameGeometry().left() + newPos.x() + 100,
                                   self.parent().frameGeometry().top() + newPos.y() + 20)

            self.__mouseMovePos = globalPos
        super(Inductor, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        if self.__mousePressPos is not None:
            moved = event.globalPos() - self.__mousePressPos
            if moved.manhattanLength() > 3:
                event.ignore()
                return

        super(Inductor, self).mouseReleaseEvent(event)

    def Rotate(self):
        if(self.isHorizontal):
            self.symbol = QPixmap()
            self.symbol.load('ind2.png')
            self.symbol = self.symbol.scaledToHeight(100)
            self.resize(self.symbol.size())
            self.setPixmap(self.symbol)

            self.valueText.move(self.x() + 40, self.y() + 45)
            self.idLabel.move(self.x() + 40, self.y() + 25)
            self.valueText.setText(str(self.value) + ' H')

            self.nodeP.move(self.x() + 18, self.y())
            self.nodeS.move(self.x() + 18, self.y() + 90)

            self.isHorizontal = False

        else:
            self.symbol = QPixmap()
            self.symbol.load('ind.png')
            self.symbol = self.symbol.scaledToWidth(100)
            self.resize(self.symbol.size())
            self.setPixmap(self.symbol)

            self.valueText.move(self.x() + 30, self.y() + 40)
            self.idLabel.move(self.x() + 45, self.y())
            self.valueText.setText(str(self.value) + ' H')

            self.nodeP.move(self.x(), self.y() + 22)
            self.nodeS.move(self.x() + 90, self.y() + 22)

            self.isHorizontal = True

    def deleteMe(self):
        self.hide()
        self.nodeP.hide()
        self.nodeS.hide()
        self.idLabel.hide()
        self.valueText.hide()

    def show_detail(self):
        self.setStyleSheet("background-color: yellow")
        if self.isHorizontal:
            self.direction.load('arrow_right.png')
            self.direction = self.direction.scaledToWidth(100)
            self.direction_label.resize(self.direction.size())
            self.direction_label.setPixmap(self.direction)
            self.direction_label.move(self.x(), self.y())
            self.direction_label.show()
        else:
            self.direction.load('arrow_down.png')
            self.direction = self.direction.scaledToHeight(100)
            self.direction_label.resize(self.direction.size())
            self.direction_label.setPixmap(self.direction)
            self.direction_label.move(self.x(), self.y())
            self.direction_label.show()

    def hide_detail(self):
        self.setStyleSheet("background-color: none")
        self.direction_label.hide()
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.current_dir = os.getcwd()
        self.descriptors = {}
        self.image_names = []
        self.current_index = 0
        self.pixmap = None
        self.scaledPixmap = None

        self.initUI()
        self.reloadDirectory()

    def initUI(self):
        centralWidget = QWidget()
        self.setCentralWidget(centralWidget)

        self.statusBar()

        # menu
        openIcon = qApp.style().standardIcon(QStyle.SP_DirOpenIcon)
        openFolder = QAction(openIcon, 'Open folder..', self)
        openFolder.setShortcut('Ctrl+O')
        openFolder.setStatusTip('Open a new folder with images')
        openFolder.triggered.connect(self.showDialog)

        exitIcon = qApp.style().standardIcon(QStyle.SP_DialogCloseButton)
        exitAction = QAction(exitIcon, '&Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(qApp.quit)

        menubar = self.menuBar()
        menubar.setNativeMenuBar(False)
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(openFolder)
        fileMenu.addAction(exitAction)

        aboutMenu = menubar.addMenu('&About')
        aboutAction = QAction('&About', self)
        aboutAction.setShortcut('F1')
        aboutAction.setStatusTip('About the author')
        aboutAction.triggered.connect(self.about)
        aboutMenu.addAction(aboutAction)

        # window contents
        self.label = CustomQLabel(self)
        self.label.setMinimumSize(1, 1)
        self.label.setAlignment(Qt.AlignCenter)
        self.label.mousePressEvent = self.handleImageClick
        self.label.installEventFilter(self)

        self.commentEdit = QLineEdit()
        self.commentEdit.setPlaceholderText("Enter comment here...")
        self.commentEdit.setDragEnabled(True)  # Allows drag-n-drop in the text field
        self.commentEdit.textChanged.connect(self.saveComment)

        prevIcon = qApp.style().standardIcon(QStyle.SP_ArrowBack)
        prevButton = QPushButton("Previous image")
        prevButton.setIcon(prevIcon)
        prevButton.setToolTip("PageUp")

        nextIcon = qApp.style().standardIcon(QStyle.SP_ArrowForward)
        nextButton = QPushButton("Next image")
        nextButton.setIcon(nextIcon)
        nextButton.setToolTip("PageDown")

        prevButton.clicked.connect(self.moveBackward)
        nextButton.clicked.connect(self.moveForward)

        hbox = QHBoxLayout()
        hbox.addWidget(self.commentEdit)
        hbox.addWidget(prevButton)
        hbox.addWidget(nextButton)

        vbox = QVBoxLayout()
        vbox.addWidget(self.label)
        vbox.addLayout(hbox)

        centralWidget.setLayout(vbox)

        # window itself
        self.setGeometry(300, 300, 800, 480)
        self.center()
        self.setWindowTitle('Tickster')
        self.show()

    def about(self):
        QMessageBox.about(self, "About",
                """<b> Tickster version %s </b>
                <p>Copyright &copy; by Dmitry Nikulin. October 2015.
                <ul>
                  <li>Python %s</li>
                  <li>PyQt %s</li>
                  <li>Qt %s</li>
                </ul>
                <p>Esc to exit, Ctrl+O to open a folder, PageUp/PageDown to navigate.</p>
                <p>Data is saved automatically in <b>%s</b> when switching between images,
                directories, and on exit.</p>""" %
                          (__version__, platform.python_version(), PYQT_VERSION_STR,
                           QT_VERSION_STR, csv_filename))

    def eventFilter(self, source, event):
        if source is self.label and event.type() == QEvent.Resize:
            # re-scaling the pixmap when the label resizes
            self.setPixmap()
        return super(MainWindow, self).eventFilter(source, event)

    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            self.close()
        elif event.key() == Qt.Key_PageDown:
            self.moveForward()
        elif event.key() == Qt.Key_PageUp:
            self.moveBackward()

    def closeEvent(self, event):
        if self.image_names:
            self.saveDescriptors()
        event.accept()

    def moveBackward(self):
        if self.image_names:
            self.saveDescriptors()

            if self.current_index == 0:
                self.current_index = len(self.image_names) - 1
            else:
                self.current_index -= 1
            self.reloadImage()
        else:
            self.statusBar().showMessage('No images loaded')

    def moveForward(self):
        if self.image_names:
            self.saveDescriptors()

            if self.current_index == len(self.image_names) - 1:
                self.current_index = 0
            else:
                self.current_index += 1
            self.reloadImage()
        else:
            self.statusBar().showMessage('No images loaded')

    def saveComment(self, text):
        if self.image_names:
            self.descriptors[self.image_names[self.current_index]].comment = text

    def showDialog(self):
        new_dir = QFileDialog.getExistingDirectory(self, 'Open image folder', self.current_dir)

        if new_dir:
            if self.image_names:
                self.saveDescriptors()

            self.current_dir = new_dir
            self.reloadDirectory()
        else:
            self.statusBar().showMessage('Nothing was selected')

    def reloadDirectory(self):
        self.image_names = []
        self.descriptors = {}
        self.current_index = 0

        self.label.clear()

        contents = os.listdir(self.current_dir)
        if csv_filename in contents:
            with open(os.path.join(self.current_dir, csv_filename)) as f:
                reader = csv.reader(f)
                for row in reader:
                    desc = row_to_desc(row)
                    self.descriptors[desc.filename] = desc

        self.image_names = [fname for fname in contents if is_image_filename(fname)]

        if self.image_names:
            self.image_names.sort()
            self.reloadImage()
        else:
            self.statusBar().showMessage('No images found in %s' % self.current_dir)
            self.label.setText("No images found")

    def reloadImage(self):
        image_name = self.image_names[self.current_index]

        if image_name not in self.descriptors:
            self.descriptors[image_name] = ImageDescriptor(image_name, [], '')

        self.commentEdit.setText(self.descriptors[image_name].comment)
        # ticks are drawn elsewhere

        self.pixmap = QPixmap(os.path.join(self.current_dir, image_name))
        self.setPixmap()

        self.updateStatusBar()

    def setPixmap(self):
        if self.image_names:
            self.scaledPixmap = self.pixmap.scaled(
                self.label.size(), Qt.KeepAspectRatio,
                Qt.SmoothTransformation
            )
            self.label.setPixmap(self.scaledPixmap)

    def handleImageClick(self, event):
        if self.image_names:
            ticks = self.descriptors[self.image_names[self.current_index]].ticks
            pt = event.pos()
            x, y = pt.x(), pt.y()

            pixmap_x = (x * 2 + self.scaledPixmap.size().width() - self.label.size().width()) / 2
            pixmap_y = (y * 2 + self.scaledPixmap.size().height() - self.label.size().height()) / 2

            # adding +1 so that the indexes are 1-based instead of 0-based
            image_x = round(pixmap_x * self.pixmap.size().width() / self.scaledPixmap.size().width()) + 1
            image_y = round(pixmap_y * self.pixmap.size().height() / self.scaledPixmap.size().height()) + 1

            if 1 <= image_x <= self.pixmap.size().width() and 1 <= image_y <= self.pixmap.size().height():
                if len(ticks) >= 4:
                    del ticks[0]
                ticks.append((image_x, image_y))

            self.updateStatusBar()

        event.accept()
        self.label.repaint()

    def updateStatusBar(self):
        if self.image_names:
            desc = self.descriptors[self.image_names[self.current_index]]
            self.statusBar().showMessage('[%d / %d (%d)] %s | %r' % (
                self.current_index + 1, len(self.image_names),
                len(self.descriptors), desc.filename, desc.ticks
            ))

    def drawTicks(self, qp):
        if self.image_names:
            ticks = self.descriptors[self.image_names[self.current_index]].ticks
            for i, (image_x, image_y) in enumerate(ticks):
                pen = QPen(cross_colors[i], 2, Qt.SolidLine)
                qp.setPen(pen)

                # subtracting 1 because the coordinates are stored as 1-based
                # no need to care whether they fit in the image
                pixmap_x = (image_x - 1) * self.scaledPixmap.size().width() / self.pixmap.size().width()
                pixmap_y = (image_y - 1) * self.scaledPixmap.size().height() / self.pixmap.size().height()

                x = round((pixmap_x * 2 + self.label.size().width() - self.scaledPixmap.size().width()) / 2)
                y = round((pixmap_y * 2 + self.label.size().height() - self.scaledPixmap.size().height()) / 2)

                cross_t = y - (cross_size // 2)
                cross_b = y + (cross_size // 2)
                cross_l = x - (cross_size // 2)
                cross_r = x + (cross_size // 2)

                qp.drawLine(x, cross_t, x, cross_b)
                qp.drawLine(cross_l, y, cross_r, y)

    def saveDescriptors(self):
        # skipping empty descriptors
        rows = [desc_to_row(desc) for desc in self.descriptors.values() if (desc.ticks or desc.comment)]

        if rows:
            rows.sort(key=lambda row: row[0])
            with open(os.path.join(self.current_dir, csv_filename), 'w') as f:
                writer = csv.writer(f)
                writer.writerows(rows)
class SnapshotRegionGrabber(QWidget):
    """
    Class implementing a grabber widget for a rectangular snapshot region.
    
    @signal grabbed(QPixmap) emitted after the region was grabbed
    """
    grabbed = pyqtSignal(QPixmap)
    
    StrokeMask = 0
    FillMask = 1
    
    Rectangle = 0
    Ellipse = 1
    
    def __init__(self, mode=Rectangle):
        """
        Constructor
        
        @param mode region grabber mode (SnapshotRegionGrabber.Rectangle or
            SnapshotRegionGrabber.Ellipse)
        """
        super(SnapshotRegionGrabber, self).__init__(
            None,
            Qt.X11BypassWindowManagerHint | Qt.WindowStaysOnTopHint |
            Qt.FramelessWindowHint | Qt.Tool)
        
        assert mode in [SnapshotRegionGrabber.Rectangle,
                        SnapshotRegionGrabber.Ellipse]
        self.__mode = mode
        
        self.__selection = QRect()
        self.__mouseDown = False
        self.__newSelection = False
        self.__handleSize = 10
        self.__mouseOverHandle = None
        self.__showHelp = True
        self.__grabbing = False
        self.__dragStartPoint = QPoint()
        self.__selectionBeforeDrag = QRect()
        
        # naming conventions for handles
        # T top, B bottom, R Right, L left
        # 2 letters: a corner
        # 1 letter: the handle on the middle of the corresponding side
        self.__TLHandle = QRect(0, 0, self.__handleSize, self.__handleSize)
        self.__TRHandle = QRect(0, 0, self.__handleSize, self.__handleSize)
        self.__BLHandle = QRect(0, 0, self.__handleSize, self.__handleSize)
        self.__BRHandle = QRect(0, 0, self.__handleSize, self.__handleSize)
        self.__LHandle = QRect(0, 0, self.__handleSize, self.__handleSize)
        self.__THandle = QRect(0, 0, self.__handleSize, self.__handleSize)
        self.__RHandle = QRect(0, 0, self.__handleSize, self.__handleSize)
        self.__BHandle = QRect(0, 0, self.__handleSize, self.__handleSize)
        self.__handles = [self.__TLHandle, self.__TRHandle, self.__BLHandle,
                          self.__BRHandle, self.__LHandle, self.__THandle,
                          self.__RHandle, self.__BHandle]
        self.__helpTextRect = QRect()
        self.__helpText = self.tr(
            "Select a region using the mouse. To take the snapshot, press"
            " the Enter key or double click. Press Esc to quit.")
        
        self.__pixmap = QPixmap()
        
        self.setMouseTracking(True)
        
        QTimer.singleShot(200, self.__initialize)
    
    def __initialize(self):
        """
        Private slot to initialize the rest of the widget.
        """
        self.__desktop = QApplication.desktop()
        x = self.__desktop.x()
        y = self.__desktop.y()
        if qVersion() >= "5.0.0":
            self.__pixmap = QApplication.screens()[0].grabWindow(
                self.__desktop.winId(), x, y,
                self.__desktop.width(), self.__desktop.height())
        else:
            self.__pixmap = QPixmap.grabWindow(
                self.__desktop.winId(), x, y,
                self.__desktop.width(), self.__desktop.height())
        self.resize(self.__pixmap.size())
        self.move(x, y)
        self.setCursor(Qt.CrossCursor)
        self.show()

        self.grabMouse()
        self.grabKeyboard()
    
    def paintEvent(self, evt):
        """
        Protected method handling paint events.
        
        @param evt paint event (QPaintEvent)
        """
        if self.__grabbing:     # grabWindow() should just get the background
            return
        
        painter = QPainter(self)
        pal = QPalette(QToolTip.palette())
        font = QToolTip.font()
        
        handleColor = pal.color(QPalette.Active, QPalette.Highlight)
        handleColor.setAlpha(160)
        overlayColor = QColor(0, 0, 0, 160)
        textColor = pal.color(QPalette.Active, QPalette.Text)
        textBackgroundColor = pal.color(QPalette.Active, QPalette.Base)
        painter.drawPixmap(0, 0, self.__pixmap)
        painter.setFont(font)
        
        r = QRect(self.__selection)
        if not self.__selection.isNull():
            grey = QRegion(self.rect())
            if self.__mode == SnapshotRegionGrabber.Ellipse:
                reg = QRegion(r, QRegion.Ellipse)
            else:
                reg = QRegion(r)
            grey = grey.subtracted(reg)
            painter.setClipRegion(grey)
            painter.setPen(Qt.NoPen)
            painter.setBrush(overlayColor)
            painter.drawRect(self.rect())
            painter.setClipRect(self.rect())
            drawRect(painter, r, handleColor)
        
        if self.__showHelp:
            painter.setPen(textColor)
            painter.setBrush(textBackgroundColor)
            self.__helpTextRect = painter.boundingRect(
                self.rect().adjusted(2, 2, -2, -2),
                Qt.TextWordWrap, self.__helpText).translated(
                -self.__desktop.x(), -self.__desktop.y())
            self.__helpTextRect.adjust(-2, -2, 4, 2)
            drawRect(painter, self.__helpTextRect, textColor,
                     textBackgroundColor)
            painter.drawText(
                self.__helpTextRect.adjusted(3, 3, -3, -3),
                Qt.TextWordWrap, self.__helpText)
        
        if self.__selection.isNull():
            return
        
        # The grabbed region is everything which is covered by the drawn
        # rectangles (border included). This means that there is no 0px
        # selection, since a 0px wide rectangle will always be drawn as a line.
        txt = "{0:n}, {1:n} ({2:n} x {3:n})".format(
            self.__selection.x(), self.__selection.y(),
            self.__selection.width(), self.__selection.height())
        textRect = painter.boundingRect(self.rect(), Qt.AlignLeft, txt)
        boundingRect = textRect.adjusted(-4, 0, 0, 0)
        
        if textRect.width() < r.width() - 2 * self.__handleSize and \
           textRect.height() < r.height() - 2 * self.__handleSize and \
           r.width() > 100 and \
           r.height() > 100:
            # center, unsuitable for small selections
            boundingRect.moveCenter(r.center())
            textRect.moveCenter(r.center())
        elif r.y() - 3 > textRect.height() and \
                r.x() + textRect.width() < self.rect().width():
            # on top, left aligned
            boundingRect.moveBottomLeft(QPoint(r.x(), r.y() - 3))
            textRect.moveBottomLeft(QPoint(r.x() + 2, r.y() - 3))
        elif r.x() - 3 > textRect.width():
            # left, top aligned
            boundingRect.moveTopRight(QPoint(r.x() - 3, r.y()))
            textRect.moveTopRight(QPoint(r.x() - 5, r.y()))
        elif r.bottom() + 3 + textRect.height() < self.rect().bottom() and \
                r.right() > textRect.width():
            # at bottom, right aligned
            boundingRect.moveTopRight(QPoint(r.right(), r.bottom() + 3))
            textRect.moveTopRight(QPoint(r.right() - 2, r.bottom() + 3))
        elif r.right() + textRect.width() + 3 < self.rect().width():
            # right, bottom aligned
            boundingRect.moveBottomLeft(QPoint(r.right() + 3, r.bottom()))
            textRect.moveBottomLeft(QPoint(r.right() + 5, r.bottom()))
        
        # If the above didn't catch it, you are running on a very
        # tiny screen...
        drawRect(painter, boundingRect, textColor, textBackgroundColor)
        painter.drawText(textRect, Qt.AlignHCenter, txt)
        
        if (r.height() > self.__handleSize * 2 and
            r.width() > self.__handleSize * 2) or \
           not self.__mouseDown:
            self.__updateHandles()
            painter.setPen(Qt.NoPen)
            painter.setBrush(handleColor)
            painter.setClipRegion(
                self.__handleMask(SnapshotRegionGrabber.StrokeMask))
            painter.drawRect(self.rect())
            handleColor.setAlpha(60)
            painter.setBrush(handleColor)
            painter.setClipRegion(
                self.__handleMask(SnapshotRegionGrabber.FillMask))
            painter.drawRect(self.rect())
    
    def resizeEvent(self, evt):
        """
        Protected method to handle resize events.
        
        @param evt resize event (QResizeEvent)
        """
        if self.__selection.isNull():
            return
        
        r = QRect(self.__selection)
        r.setTopLeft(self.__limitPointToRect(r.topLeft(), self.rect()))
        r.setBottomRight(self.__limitPointToRect(r.bottomRight(), self.rect()))
        if r.width() <= 1 or r.height() <= 1:
            # This just results in ugly drawing...
            self.__selection = QRect()
        else:
            self.__selection = self.__normalizeSelection(r)
    
    def mousePressEvent(self, evt):
        """
        Protected method to handle mouse button presses.
        
        @param evt mouse press event (QMouseEvent)
        """
        self.__showHelp = not self.__helpTextRect.contains(evt.pos())
        if evt.button() == Qt.LeftButton:
            self.__mouseDown = True
            self.__dragStartPoint = evt.pos()
            self.__selectionBeforeDrag = QRect(self.__selection)
            if not self.__selection.contains(evt.pos()):
                self.__newSelection = True
                self.__selection = QRect()
            else:
                self.setCursor(Qt.ClosedHandCursor)
        elif evt.button() == Qt.RightButton:
            self.__newSelection = False
            self.__selection = QRect()
            self.setCursor(Qt.CrossCursor)
        self.update()
    
    def mouseMoveEvent(self, evt):
        """
        Protected method to handle mouse movements.
        
        @param evt mouse move event (QMouseEvent)
        """
        shouldShowHelp = not self.__helpTextRect.contains(evt.pos())
        if shouldShowHelp != self.__showHelp:
            self.__showHelp = shouldShowHelp
            self.update()
        
        if self.__mouseDown:
            if self.__newSelection:
                p = evt.pos()
                r = self.rect()
                self.__selection = self.__normalizeSelection(
                    QRect(self.__dragStartPoint,
                          self.__limitPointToRect(p, r)))
            elif self.__mouseOverHandle is None:
                # moving the whole selection
                r = self.rect().normalized()
                s = self.__selectionBeforeDrag.normalized()
                p = s.topLeft() + evt.pos() - self.__dragStartPoint
                r.setBottomRight(
                    r.bottomRight() - QPoint(s.width(), s.height()) +
                    QPoint(1, 1))
                if not r.isNull() and r.isValid():
                    self.__selection.moveTo(self.__limitPointToRect(p, r))
            else:
                # dragging a handle
                r = QRect(self.__selectionBeforeDrag)
                offset = evt.pos() - self.__dragStartPoint
                
                if self.__mouseOverHandle in \
                   [self.__TLHandle, self.__THandle, self.__TRHandle]:
                    r.setTop(r.top() + offset.y())
                
                if self.__mouseOverHandle in \
                   [self.__TLHandle, self.__LHandle, self.__BLHandle]:
                    r.setLeft(r.left() + offset.x())
                
                if self.__mouseOverHandle in \
                   [self.__BLHandle, self.__BHandle, self.__BRHandle]:
                    r.setBottom(r.bottom() + offset.y())
                
                if self.__mouseOverHandle in \
                   [self.__TRHandle, self.__RHandle, self.__BRHandle]:
                    r.setRight(r.right() + offset.x())
                
                r.setTopLeft(self.__limitPointToRect(r.topLeft(), self.rect()))
                r.setBottomRight(
                    self.__limitPointToRect(r.bottomRight(), self.rect()))
                self.__selection = self.__normalizeSelection(r)
            
            self.update()
        else:
            if self.__selection.isNull():
                return
            
            found = False
            for r in self.__handles:
                if r.contains(evt.pos()):
                    self.__mouseOverHandle = r
                    found = True
                    break
            
            if not found:
                self.__mouseOverHandle = None
                if self.__selection.contains(evt.pos()):
                    self.setCursor(Qt.OpenHandCursor)
                else:
                    self.setCursor(Qt.CrossCursor)
            else:
                if self.__mouseOverHandle in [self.__TLHandle,
                                              self.__BRHandle]:
                    self.setCursor(Qt.SizeFDiagCursor)
                elif self.__mouseOverHandle in [self.__TRHandle,
                                                self.__BLHandle]:
                    self.setCursor(Qt.SizeBDiagCursor)
                elif self.__mouseOverHandle in [self.__LHandle,
                                                self.__RHandle]:
                    self.setCursor(Qt.SizeHorCursor)
                elif self.__mouseOverHandle in [self.__THandle,
                                                self.__BHandle]:
                    self.setCursor(Qt.SizeVerCursor)
    
    def mouseReleaseEvent(self, evt):
        """
        Protected method to handle mouse button releases.
        
        @param evt mouse release event (QMouseEvent)
        """
        self.__mouseDown = False
        self.__newSelection = False
        if self.__mouseOverHandle is None and \
           self.__selection.contains(evt.pos()):
            self.setCursor(Qt.OpenHandCursor)
        self.update()
    
    def mouseDoubleClickEvent(self, evt):
        """
        Protected method to handle mouse double clicks.
        
        @param evt mouse double click event (QMouseEvent)
        """
        self.__grabRect()
    
    def keyPressEvent(self, evt):
        """
        Protected method to handle key presses.
        
        @param evt key press event (QKeyEvent)
        """
        if evt.key() == Qt.Key_Escape:
            self.grabbed.emit(QPixmap())
        elif evt.key() in [Qt.Key_Enter, Qt.Key_Return]:
            self.__grabRect()
        else:
            evt.ignore()
    
    def __updateHandles(self):
        """
        Private method to update the handles.
        """
        r = QRect(self.__selection)
        s2 = self.__handleSize // 2
        
        self.__TLHandle.moveTopLeft(r.topLeft())
        self.__TRHandle.moveTopRight(r.topRight())
        self.__BLHandle.moveBottomLeft(r.bottomLeft())
        self.__BRHandle.moveBottomRight(r.bottomRight())
        
        self.__LHandle.moveTopLeft(QPoint(r.x(), r.y() + r.height() // 2 - s2))
        self.__THandle.moveTopLeft(QPoint(r.x() + r.width() // 2 - s2, r.y()))
        self.__RHandle.moveTopRight(
            QPoint(r.right(), r.y() + r.height() // 2 - s2))
        self.__BHandle.moveBottomLeft(
            QPoint(r.x() + r.width() // 2 - s2, r.bottom()))
    
    def __handleMask(self, maskType):
        """
        Private method to calculate the handle mask.
        
        @param maskType type of the mask to be used
            (SnapshotRegionGrabber.FillMask or
            SnapshotRegionGrabber.StrokeMask)
        @return calculated mask (QRegion)
        """
        mask = QRegion()
        for rect in self.__handles:
            if maskType == SnapshotRegionGrabber.StrokeMask:
                r = QRegion(rect)
                mask += r.subtracted(QRegion(rect.adjusted(1, 1, -1, -1)))
            else:
                mask += QRegion(rect.adjusted(1, 1, -1, -1))
        return mask
    
    def __limitPointToRect(self, point, rect):
        """
        Private method to limit the given point to the given rectangle.
        
        @param point point to be limited (QPoint)
        @param rect rectangle the point shall be limited to (QRect)
        @return limited point (QPoint)
        """
        q = QPoint()
        if point.x() < rect.x():
            q.setX(rect.x())
        elif point.x() < rect.right():
            q.setX(point.x())
        else:
            q.setX(rect.right())
        if point.y() < rect.y():
            q.setY(rect.y())
        elif point.y() < rect.bottom():
            q.setY(point.y())
        else:
            q.setY(rect.bottom())
        return q
    
    def __normalizeSelection(self, sel):
        """
        Private method to normalize the given selection.
        
        @param sel selection to be normalized (QRect)
        @return normalized selection (QRect)
        """
        rect = QRect(sel)
        if rect.width() <= 0:
            left = rect.left()
            width = rect.width()
            rect.setLeft(left + width - 1)
            rect.setRight(left)
        if rect.height() <= 0:
            top = rect.top()
            height = rect.height()
            rect.setTop(top + height - 1)
            rect.setBottom(top)
        return rect
    
    def __grabRect(self):
        """
        Private method to grab the selected rectangle (i.e. do the snapshot).
        """
        if self.__mode == SnapshotRegionGrabber.Ellipse:
            ell = QRegion(self.__selection, QRegion.Ellipse)
            if not ell.isEmpty():
                self.__grabbing = True
                
                xOffset = self.__pixmap.rect().x() - ell.boundingRect().x()
                yOffset = self.__pixmap.rect().y() - ell.boundingRect().y()
                translatedEll = ell.translated(xOffset, yOffset)
                
                pixmap2 = QPixmap(ell.boundingRect().size())
                pixmap2.fill(Qt.transparent)
                
                pt = QPainter()
                pt.begin(pixmap2)
                if pt.paintEngine().hasFeature(QPaintEngine.PorterDuff):
                    pt.setRenderHints(
                        QPainter.Antialiasing |
                        QPainter.HighQualityAntialiasing |
                        QPainter.SmoothPixmapTransform,
                        True)
                    pt.setBrush(Qt.black)
                    pt.setPen(QPen(QBrush(Qt.black), 0.5))
                    pt.drawEllipse(translatedEll.boundingRect())
                    pt.setCompositionMode(QPainter.CompositionMode_SourceIn)
                else:
                    pt.setClipRegion(translatedEll)
                    pt.setCompositionMode(QPainter.CompositionMode_Source)
                
                pt.drawPixmap(pixmap2.rect(), self.__pixmap,
                              ell.boundingRect())
                pt.end()
                
                self.grabbed.emit(pixmap2)
        else:
            r = QRect(self.__selection)
            if not r.isNull() and r.isValid():
                self.__grabbing = True
                self.grabbed.emit(self.__pixmap.copy(r))
Exemple #52
0
    def __init__(self):
        super().__init__()
        self._scale = round(QFontMetrics(QCoreApplication.instance().font()).ascent() / 12)

        splash_image = QPixmap(Resources.getPath(Resources.Images, "cura.png"))
        self.setPixmap(splash_image.scaled(splash_image.size() * self._scale))
Exemple #53
0
class ImageDisplay(QWidget):
    def __init__(self, my_book, parent=None):
        super().__init__(parent)
        self.my_book = my_book
        # register metadata readers and writers
        md = my_book.get_meta_manager()
        md.register(C.MD_IZ,self._zoom_read,self._zoom_write)
        md.register(C.MD_IX,self._link_read,self._link_write)
        # Create our widgets including cursor_to_image and
        # image_to_cursor pushbuttons.
        self._uic()
        # set defaults in case no metadata
        self.cursor_to_image.setChecked(True)
        self.image_to_cursor.setChecked(False)
        self.zoom_factor = 0.25
        self.png_path = None
        # disable all widgetry until we get some metadata
        self._disable()
        # end of __init__()

    # Disable our widgets because we have no image to show.
    def _disable(self):
        self.no_image = True
        self.last_index = None # compares unequal to any
        self.pix_map = QPixmap()
        self.image = QImage()
        self.cursor_to_image.setEnabled(False)
        self.image_to_cursor.setEnabled(False)
        self.zoom_pct.setEnabled(False)
        self.zoom_to_width.setEnabled(False)
        self.zoom_to_height.setEnabled(False)
        self.image_display.setPixmap(self.gray_image)
        self.image_display.setToolTip(
            _TR('Image view tooltip',
                'Display of one scanned page (no images available)')
            )

    # Enable our widgets, we have images to show. At this time the Book
    # has definitely created an edit view and a page model.
    def _enable(self):
        self.edit_view = self.my_book.get_edit_view()
        self.editor = self.edit_view.Editor # access to actual QTextEdit
        self.page_data = self.my_book.get_page_model()
        self.cursor_to_image.setEnabled(True)
        self.image_to_cursor.setEnabled(True)
        self.zoom_to_width.setEnabled(True)
        self.zoom_to_height.setEnabled(True)
        self.image_display.setToolTip(
            _TR('Image view tooltip',
                'Display of one scanned page from the book')
            )
        self.no_image = False
        self.zoom_pct.setEnabled(True)
        # the following triggers entry to _new_zoom_pct() below
        self.zoom_pct.setValue(int(100*self.zoom_factor))

    # Metadata: read or write the {{IMAGEZOOM f}} section.
    # Parameter f should be a decimal number between 0.15 and 2.0
    # but we do not depend on text the user could edit.
    def _zoom_read(self, qts, section, vers, parm):
        try:
            z = float(parm) # throws exception on a bad literal
            if math.isnan(z) or (z < 0.15) or (z > 2.0) :
                raise ValueError
            self.zoom_factor = z
        except:
            imageview_logger.error('Invalid IMAGEZOOM "{0}" ignored'.format(parm))

    def _zoom_write(self, qts, section):
        qts << metadata.open_line(section, str(self.zoom_factor))

    # Metadata: read or write the {{IMAGELINK b}} section. The parameter should
    # be an int 0/1/2/3. Bit 0 represents the state of cursor_to_image
    # (usually 1); bit 1 represents the state of image_to_cursor (usually 0).
    def _link_read(self, qts, section, vers, parm):
        try:
            b = int(parm) # exception on a bad literal
            if (b < 0) or (b > 3) : raise ValueError
            self.cursor_to_image.setChecked( True if b & 1 else False )
            self.image_to_cursor.setChecked( True if b & 2 else False )
        except :
            imageview_logger.error('Invalid IMAGELINKING "{0}" ignored'.format(parm))

    def _link_write(self, qts, section):
        b = 0
        if self.cursor_to_image.isChecked() : b |= 1
        if self.image_to_cursor.isChecked() : b |= 2
        qts << metadata.open_line(section, str(b))

    # The Book calls here after it has loaded a book with defined page data,
    # passing the path to the folder containing the book. If we can find a
    # folder named 'pngs' in it we record that path and enable our widgets,
    # and fake a cursorMoved signal to display the current edit page.
    def set_path(self,book_folder_path):
        book_dir = QDir(book_folder_path)
        if book_dir.exists('pngs') :
            self.png_dir = QDir(book_dir.absoluteFilePath('pngs'))
            self._enable()
            self.cursor_move()

    # Come here to display or re-display an image. The last-displayed
    # page image index (if any) is in self.last_index. The desired page
    # index is passed as the argument, which may be:
    # * the same as last_index, for example on a change of zoom%. Just
    #   redisplay the current page.
    # * negative or None if the cursor is "above" the first available page or on
    #   a Page-Up keystroke. Display the gray image.
    # * greater than page_data.page_count() on a Page-Down keystroke,
    #   display the last available page.
    # If different from last_index, try to load the .png file for that
    # page. If that fails, use the gray image. Otherwise display that
    # page and save it as last_index.

    def _show_page(self, page_index):
        if page_index != self.last_index :
            self.last_index = page_index
            # change of page, see if we have a filename for it
            self.pix_map = self.gray_image # assume failure...
            im_name = self.page_data.filename(page_index)
            if im_name :
                # pagedata has a filename; of course there is no guarantee
                # such a file exists now or ever did.
                im_name += '.png'
                if self.png_dir.exists(im_name) :
                    self.image = QImage(self.png_dir.absoluteFilePath(im_name))
                    if not self.image.isNull():
                        # we loaded it ok, make a full-scale pixmap for display
                        self.pix_map = QPixmap.fromImage(self.image,Qt.ColorOnly)
        # Whether new page or not, rescale to current zoom. The .resize method
        # takes a QSize; pix_map.size() returns one, and it supports * by a real.
        self.image_display.setPixmap(self.pix_map)
        self.image_display.resize( self.zoom_factor * self.pix_map.size() )

    # Slot to receive the cursorMoved signal from the editview widget. If we
    # are in no_image state, do nothing. If the cursor_to_image switch is
    # not checked, do nothing. Else get the character position of
    # the high-end of the current edit selection, and use that to get the
    # current page index from pagedata, and pass that to _show_page.
    def cursor_move(self):
        if self.no_image : return
        if self.cursor_to_image.isChecked() :
            pos = self.editor.textCursor().selectionEnd()
            self._show_page( self.page_data.page_index(pos) )

    # Slots to receive the signals from our zoom percent and zoom-to buttons.
    # The controls are disabled while we are in no_image state, so if a signal
    # arrives, we are not in that state.
    #
    # These are strictly internal hence _names.

    # Any change in the value of the zoom % spin-box including setValue().
    def _new_zoom_pct(self,new_value):
        self.zoom_factor = self.zoom_pct.value() / 100
        self._show_page(self.last_index)

    # Set a new zoom factor (a real) and update the zoom pct spinbox.
    # Setting zoom_pct triggers a signal to _new_zoom_pct above, and
    # thence to _show_page which repaints the page at the new scale value.
    def _set_zoom_real(self,new_value):
        zoom = max(new_value, ZOOM_FACTOR_MIN)
        zoom = min(zoom, ZOOM_FACTOR_MAX)
        self.zoom_factor = zoom
        self.zoom_pct.setValue(int(100*zoom))

    # Re-implement keyPressEvent in order to provide zoom and page up/down.
    #   ctrl-plus increases the image size by 1.25
    #   ctrl-minus decreases the image size by 0.8
    #   page-up displays the next-higher page
    #   page-down displays the next-lower page

    def keyPressEvent(self, event):
        # assume we will not handle this key and clear its accepted flag
        event.ignore()
        if self.no_image or (self.last_index is None) :
            return # ignore keys until we are showing some image
        # We have images to show, check the key value.
        modkey = int( int(event.key() | (int(event.modifiers()) & C.KEYPAD_MOD_CLEAR)) )
        if modkey in C.KEYS_ZOOM :
            event.accept()
            fac = (0.8) if (modkey == C.CTL_MINUS) else (1.25)
            self._set_zoom_real( fac * self.zoom_factor)
        elif (event.key() == Qt.Key_PageUp) or (event.key() == Qt.Key_PageDown) :
            event.accept()
            pgix = self.last_index + (1 if (event.key() == Qt.Key_PageDown) else -1)
            # If not paging off either end, show that page
            if pgix >= 0 and pgix < self.page_data.page_count() :
                self._show_page(pgix)
                if self.image_to_cursor.isChecked():
                    self.edit_view.show_position(self.page_data.position(pgix))

    # Zoom to width and zoom to height are basically the same thing:
    # 1. Using the QImage of the current page in self.image,
    #    scan its pixels to find the width (height) of the nonwhite area.
    # 2. Get the ratio of that to our image label's viewport width (height).
    # 3. Set that ratio as the zoom factor and redraw the image.
    # 5. Set the scroll position(s) of our scroll area to left-justify the text.
    #
    # We get access to the pixel data using QImage.bits() which gives us a
    # "sip.voidptr" object that we can index to get byte values.
    def _zoom_to_width(self):

        # Generic loop to scan inward from the left or right edge of one
        # column inward until a dark pixel is seen, returning that margin.
        def inner_loop(row_range, col_start, margin, col_step):
            pa, pb = 255, 255 # virtual white outside column
            for row in row_range:
                for col in range(col_start, margin, col_step):
                    pc = color_table[ bytes_ptr[row+col] ]
                    if (pa + pb + pc) < 24 : # black or dark gray trio
                        margin = col # new, narrower, margin
                        break # no need to look further on this row
                    pa, pb = pb, pc # else shift 3-pixel window
            return margin - (2*col_step) # allow for 3-px window

        if self.no_image or self.image.isNull() :
            return # nothing to do
        scale_factor = 4
        orig_rows = self.image.height() # number of pixels high
        orig_cols = self.image.width() # number of logical pixels across
        # Scale the image to 1/4 size (1/16 the pixel count) and then force
        # it to indexed-8 format, one byte per pixel.
        work_image = self.image.scaled(
            QSize(int(orig_cols/scale_factor),int(orig_rows/scale_factor)),
            Qt.KeepAspectRatio, Qt.FastTransformation)
        work_image = work_image.convertToFormat(QImage.Format_Indexed8,Qt.ColorOnly)
        # Get a reduced version of the color table by extracting just the GG
        # values of each entry, as a dict keyed by the pixel byte value. For
        # PNG-2, this gives [0,255] but it could have 8, 16, even 256 elements.
        color_table = { bytes([c]): int((work_image.color(c) >> 8) & 255)
                         for c in range(work_image.colorCount()) }
        # Establish limits for the inner loop
        rows = work_image.height() # number of pixels high
        cols = work_image.width() # number of logical pixels across
        stride = (cols + 3) & (-4) # scan-line width in bytes
        bytes_ptr = work_image.bits() # uchar * a_bunch_o_pixels
        bytes_ptr.setsize(stride * rows) # make the pointer indexable

        # Scan in from left and from right to find the outermost dark spots.
        # Pages tend to start with many lines of white pixels so in hopes of
        # establishing a narrow margin quickly, scan from the middle to the
        # end, then do the top half.
        left_margin = inner_loop(
                        range(int(rows/2)*stride, (rows-1)*stride, stride*2),
                        0, int(cols/2), 1
        )
        left_margin = inner_loop(
                        range(0, int(rows/2)*stride, stride*2),
                        0, left_margin, 1
                        )
        # Now do exactly the same but for the right margin.
        right_margin = inner_loop(
                        range(int(rows/2)*stride, (rows-1)*stride, stride*2),
                        cols-1, int(cols/2), -1
                        )
        right_margin = inner_loop(
                        range(0, int(rows/2)*stride, stride*2),
                        cols-1, right_margin, -1
                        )
        # Adjust the margins by the scale factor to fit the full size image.
        #left_margin = max(0,left_margin*scale_factor-scale_factor)
        #right_margin = min(orig_cols,right_margin*scale_factor+scale_factor)
        left_margin = left_margin*scale_factor
        right_margin = right_margin*scale_factor
        text_size = right_margin - left_margin + 2
        port_width = self.scroll_area.viewport().width()
        # Set the new zoom factor, after limiting by min/max values
        self._set_zoom_real(port_width/text_size)
        # Set the scrollbar to show the page from its left margin.
        self.scroll_area.horizontalScrollBar().setValue(
                             int( left_margin * self.zoom_factor)
                         )
        # and that completes zoom-to-width

    def _zoom_to_height(self):
        def dark_row(row_start, cols):
            '''
            Scan one row of pixels and return True if it contains
            at least one 3-pixel blob of darkness, or False if not.
            '''
            pa, pb = 255, 255
            for c in range(row_start,row_start+cols):
                pc = color_table[ bytes_ptr[c] ]
                if (pa + pb + pc) < 24 : # black or dark gray trio
                    return True
                pa, pb = pb, pc
            return False # row was all-white-ish

        if self.no_image or self.image.isNull() :
            return # nothing to do
        scale_factor = 4
        orig_rows = self.image.height() # number of pixels high
        orig_cols = self.image.width() # number of logical pixels across
        # Scale the image to 1/4 size (1/16 the pixel count) and then force
        # it to indexed-8 format, one byte per pixel.
        work_image = self.image.scaled(
            QSize(int(orig_cols/scale_factor),int(orig_rows/scale_factor)),
            Qt.KeepAspectRatio, Qt.FastTransformation)
        work_image = work_image.convertToFormat(QImage.Format_Indexed8,Qt.ColorOnly)
        # Get a reduced version of the color table by extracting just the GG
        # values of each entry, as a dict keyed by the pixel byte value. For
        # PNG-2, this gives [0,255] but it could have 8, 16, even 256 elements.
        color_table = { bytes([c]): int((work_image.color(c) >> 8) & 255)
                         for c in range(work_image.colorCount()) }
        rows = work_image.height() # number of pixels high
        cols = work_image.width() # number of logical pixels across
        stride = (cols + 3) & (-4) # scan-line width in bytes
        bytes_ptr = work_image.bits() # uchar * a_bunch_o_pixels
        bytes_ptr.setsize(stride * rows) # make the pointer indexable
        # Scan the image rows from the top down looking for one with darkness
        for top_row in range(rows):
            if dark_row(top_row*stride, cols): break
        if top_row > (rows/2) : # too much white, skip it
            return
        for bottom_row in range(rows-1, top_row, -1):
            if dark_row(bottom_row*stride, cols) : break
        # bottom_row has to be >= top_row. if they are too close together
        # set_zoom_real will limit the zoom to 200%.
        top_row = top_row*scale_factor
        bottom_row = bottom_row*scale_factor
        text_height = bottom_row - top_row + 1
        port_height = self.scroll_area.viewport().height()
        self._set_zoom_real(port_height/text_height)
        self.scroll_area.verticalScrollBar().setValue(
                         int( top_row * self.zoom_factor ) )
        # and that completes zoom-to-height

    # Build the widgetary contents. The widget consists mostly of a vertical
    # layout with two items: A scrollArea containing a QLabel used to display
    # an image, and a horizontal layout containing the zoom controls.
    # TODO: figure out design and location of two cursor-link tool buttons.
    def _uic(self):

        # Function to return the actual width of the label text
        # of a widget. Get the fontMetrics and ask it for the width.
        def _label_width(widget):
            fm = widget.fontMetrics()
            return fm.width(widget.text())

        # Create a gray field to use when no image is available
        self.gray_image = QPixmap(700,900)
        self.gray_image.fill(QColor("gray"))

        # Build the QLabel that displays the image pixmap. It gets all
        # available space and scales its contents to fit that space.
        self.image_display = QLabel()
        self.image_display.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.image_display.setScaledContents(True)

        # Create a scroll area within which to display the image. It will
        # create a horizontal and/or vertical scroll bar when
        # the image_display size exceeds the size of the scroll area.
        self.scroll_area = QScrollArea()
        self.scroll_area.setBackgroundRole(QPalette.Dark)
        self.scroll_area.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
        self.scroll_area.setWidget(self.image_display)
        # Make sure the scroll area does not swallow user keystrokes
        self.setFocusPolicy(Qt.ClickFocus) # focus into whole widget
        self.scroll_area.setFocusProxy(self) # you, pass it on.

        # Create the image-linking toolbuttons.
        # Cursor-to-image uses left-hands.
        c2i_on = QPixmap(':/hand-left-closed.png')
        c2i_off = QPixmap(':/hand-left-open.png')
        c2i_con = QIcon()
        c2i_con.addPixmap(c2i_on,QIcon.Normal,QIcon.On)
        c2i_con.addPixmap(c2i_off,QIcon.Normal,QIcon.Off)
        self.cursor_to_image = QToolButton()
        self.cursor_to_image.setCheckable(True)
        self.cursor_to_image.setContentsMargins(0,0,0,0)
        self.cursor_to_image.setIconSize(QSize(30,24))
        self.cursor_to_image.setMaximumSize(QSize(32,26))
        self.cursor_to_image.setIcon(c2i_con)
        # Image-to-cursor uses right-hands.
        i2c_on = QPixmap(':/hand-right-closed.png')
        i2c_off = QPixmap(':/hand-right-open.png')
        i2c_con = QIcon()
        i2c_con.addPixmap(i2c_on,QIcon.Normal,QIcon.On)
        i2c_con.addPixmap(i2c_off,QIcon.Normal,QIcon.Off)
        self.image_to_cursor = QToolButton()
        self.image_to_cursor.setCheckable(True)
        self.image_to_cursor.setContentsMargins(0,0,0,0)
        self.image_to_cursor.setIconSize(QSize(30,24))
        self.image_to_cursor.setMaximumSize(QSize(32,26))
        self.image_to_cursor.setIcon(i2c_con)

        # Create a spinbox to set the zoom from 15 to 200 and connect its
        # signal to our slot.
        self.zoom_pct = QSpinBox()
        self.zoom_pct.setRange(
            int(100*ZOOM_FACTOR_MIN),int(100*ZOOM_FACTOR_MAX))
        self.zoom_pct.setToolTip(
            _TR('Imageview zoom control tooltip',
                'Set the magnification of the page image')
            )
        # Connect the valueChanged(int) signal as opposed to the
        # valueChanged(str) signal.
        self.zoom_pct.valueChanged['int'].connect(self._new_zoom_pct)
        # Create a label for the zoom spinbox. (the label is not saved as a
        # class member, its layout will keep it in focus) Not translating
        # the word "Zoom".
        pct_label = QLabel(
            '&Zoom {0}-{1}%'.format(
                str(self.zoom_pct.minimum() ),
                str(self.zoom_pct.maximum() )
                )
            )
        pct_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        pct_label.setBuddy(self.zoom_pct)

        # Create the to-width and to-height zoom buttons. Make
        # sure their widths are equal after translation.
        self.zoom_to_width = QPushButton(
            _TR('Imageview zoom control button name','to Width')
            )
        self.zoom_to_width.setToolTip(
            _TR('Imageview zoom control tooltip',
                'Adjust the image to fill the window side to side.')
            )
        self.zoom_to_width.clicked.connect(self._zoom_to_width)
        self.zoom_to_height = QPushButton(
            _TR('Imageview zoom control button name','to Height')
            )
        self.zoom_to_height.setToolTip(
            _TR('Imageview zoom control tooltip',
                'Adjust the image to fill the window top to bottom.')
            )
        self.zoom_to_height.clicked.connect(self._zoom_to_height)

        w = 20 + max(_label_width(self.zoom_to_height),_label_width(self.zoom_to_width))
        self.zoom_to_height.setMinimumWidth(w)
        self.zoom_to_width.setMinimumWidth(w)

        # Create an HBox for the top of the panel which contains only
        # the cursor-to-image link button.
        tophbox = QHBoxLayout()
        tophbox.setContentsMargins(0,0,0,0)
        tophbox.addWidget(self.cursor_to_image,0)
        tophbox.addStretch() # left-align the button
        # Create an HBox layout to contain the above controls, using
        # spacers left and right to center them and a spacers between
        # to control the spacing.

        zhbox = QHBoxLayout()
        zhbox.setContentsMargins(0,0,0,0)
        zhbox.addWidget(self.image_to_cursor,0)
        zhbox.addStretch(2) # left and right spacers have stretch 2
        zhbox.addWidget(pct_label,0)
        zhbox.addWidget(self.zoom_pct,0)
        zhbox.addStretch(1) # spacers between widgets are stretch 1
        zhbox.addWidget(self.zoom_to_height,0)
        zhbox.addSpacing(10) # juuuust a little space between buttons
        zhbox.addWidget(self.zoom_to_width,0)
        zhbox.addStretch(2) # right side spacer

        # With all the pieces in hand, create our layout with a stack of
        # image over row of controls.
        vbox = QVBoxLayout()
        vbox.setContentsMargins(0,0,0,0)
        vbox.addLayout(tophbox,0)
        # The image gets a high stretch and default alignment.
        vbox.addWidget(self.scroll_area,2)
        vbox.addLayout(zhbox,0)
        self.setLayout(vbox)
        # And that completes the UI setup.
Exemple #54
0
class LightMaps(QWidget):
    def __init__(self, parent = None):
        super(LightMaps, self).__init__(parent)

        self.pressed = False
        self.snapped = False
        self.zoomed = False
        self.invert = False
        self._normalMap = SlippyMap(self)
        self._largeMap = SlippyMap(self)
        self.pressPos = QPoint()
        self.dragPos = QPoint()
        self.tapTimer = QBasicTimer()
        self.zoomPixmap = QPixmap()
        self.maskPixmap = QPixmap()
        self._normalMap.updated.connect(self.updateMap)
        self._largeMap.updated.connect(self.update)
 
    def setCenter(self, lat, lng):
        self._normalMap.latitude = lat
        self._normalMap.longitude = lng
        self._normalMap.invalidate()
        self._largeMap.invalidate()

    # slots
    def toggleNightMode(self):
        self.invert = not self.invert
        self.update()
 
    def updateMap(self, r):
        self.update(r)

    def activateZoom(self):
        self.zoomed = True
        self.tapTimer.stop()
        self._largeMap.zoom = self._normalMap.zoom + 1
        self._largeMap.width = self._normalMap.width * 2
        self._largeMap.height = self._normalMap.height * 2
        self._largeMap.latitude = self._normalMap.latitude
        self._largeMap.longitude = self._normalMap.longitude
        self._largeMap.invalidate()
        self.update()
 
    def resizeEvent(self, event):
        self._normalMap.width = self.width()
        self._normalMap.height = self.height()
        self._normalMap.invalidate()
        self._largeMap.width = self._normalMap.width * 2
        self._largeMap.height = self._normalMap.height * 2
        self._largeMap.invalidate()

    def paintEvent(self, event):
        p = QPainter()
        p.begin(self)
        self._normalMap.render(p, event.rect())
        p.setPen(Qt.black)
        p.drawText(self.rect(), Qt.AlignBottom | Qt.TextWordWrap,
                   "Map data CCBYSA 2009 OpenStreetMap.org contributors")
        p.end()

        if self.zoomed:
            dim = min(self.width(), self.height())
            magnifierSize = min(MAX_MAGNIFIER, dim * 2 / 3)
            radius = magnifierSize / 2
            ring = radius - 15
            box = QSize(magnifierSize, magnifierSize)

            # reupdate our mask
            if self.maskPixmap.size() != box:
                self.maskPixmap = QPixmap(box)
                self.maskPixmap.fill(Qt.transparent)
                g = QRadialGradient()
                g.setCenter(radius, radius)
                g.setFocalPoint(radius, radius)
                g.setRadius(radius)
                g.setColorAt(1.0, QColor(255, 255, 255, 0))
                g.setColorAt(0.5, QColor(128, 128, 128, 255))
                mask = QPainter(self.maskPixmap)
                mask.setRenderHint(QPainter.Antialiasing)
                mask.setCompositionMode(QPainter.CompositionMode_Source)
                mask.setBrush(g)
                mask.setPen(Qt.NoPen)
                mask.drawRect(self.maskPixmap.rect())
                mask.setBrush(QColor(Qt.transparent))
                mask.drawEllipse(g.center(), ring, ring)
                mask.end()

            center = self.dragPos - QPoint(0, radius)
            center += QPoint(0, radius / 2)
            corner = center - QPoint(radius, radius)
            xy = center * 2 - QPoint(radius, radius)
            # only set the dimension to the magnified portion
            if self.zoomPixmap.size() != box:
                self.zoomPixmap = QPixmap(box)
                self.zoomPixmap.fill(Qt.lightGray)
    
            if True:
                p = QPainter(self.zoomPixmap)
                p.translate(-xy)
                self._largeMap.render(p, QRect(xy, box))
                p.end()

            clipPath = QPainterPath()
            clipPath.addEllipse(QPointF(center), ring, ring)
            p = QPainter(self)
            p.setRenderHint(QPainter.Antialiasing)
            p.setClipPath(clipPath)
            p.drawPixmap(corner, self.zoomPixmap)
            p.setClipping(False)
            p.drawPixmap(corner, self.maskPixmap)
            p.setPen(Qt.gray)
            p.drawPath(clipPath)

        if self.invert:
            p = QPainter(self)
            p.setCompositionMode(QPainter.CompositionMode_Difference)
            p.fillRect(event.rect(), Qt.white)
            p.end()

    def timerEvent(self, event):
        if not self.zoomed:
            self.activateZoom()

        self.update()
 
    def mousePressEvent(self, event):
        if event.buttons() != Qt.LeftButton:
            return

        self.pressed = self.snapped = True
        self.pressPos = self.dragPos = event.pos()
        self.tapTimer.stop()
        self.tapTimer.start(HOLD_TIME, self)

    def mouseMoveEvent(self, event):
        if not event.buttons():
            return

        if not self.zoomed:
            if not self.pressed or not self.snapped:
                delta = event.pos() - self.pressPos
                self.pressPos = event.pos()
                self._normalMap.pan(delta)
                return
            else:
                threshold = 10
                delta = event.pos() - self.pressPos
                if self.snapped:
                    self.snapped &= delta.x() < threshold
                    self.snapped &= delta.y() < threshold
                    self.snapped &= delta.x() > -threshold
                    self.snapped &= delta.y() > -threshold

                if not self.snapped:
                    self.tapTimer.stop()

        else:
            self.dragPos = event.pos()
            self.update()

    def mouseReleaseEvent(self, event):
        self.zoomed = False
        self.update()
 
    def keyPressEvent(self, event):
        if not self.zoomed:
            if event.key() == Qt.Key_Left:
                self._normalMap.pan(QPoint(20, 0))
            if event.key() == Qt.Key_Right:
                self._normalMap.pan(QPoint(-20, 0))
            if event.key() == Qt.Key_Up:
                self._normalMap.pan(QPoint(0, 20))
            if event.key() == Qt.Key_Down:
                self._normalMap.pan(QPoint(0, -20))
            if event.key() == Qt.Key_Z or event.key() == Qt.Key_Select:
                self.dragPos = QPoint(self.width() / 2, self.height() / 2)
                self.activateZoom()
        else:
            if event.key() == Qt.Key_Z or event.key() == Qt.Key_Select:
                self.zoomed = False
                self.update()

            delta = QPoint(0, 0)
            if event.key() == Qt.Key_Left:
                delta = QPoint(-15, 0)
            if event.key() == Qt.Key_Right:
                delta = QPoint(15, 0)
            if event.key() == Qt.Key_Up:
                delta = QPoint(0, -15)
            if event.key() == Qt.Key_Down:
                delta = QPoint(0, 15)
            if delta != QPoint(0, 0):
                self.dragPos += delta
                self.update()
Exemple #55
0
class Shufti(ShuftiWindow):
    
    def __init__(self):
        super(Shufti,self).__init__()
        try:
            self.key = sys.argv[1]
        except IndexError:
            print('\nshufti 2.2\n\nTo use shufti from the terminal, you must specify the full path to an image as a parameter.\n')
            sys.exit(1)
        self.dbSanitise()
        self.formats = ('.png', '.jpg', '.jpeg', '.gif', '.bmp', '.pbm', '.pgm', '.ppm',
         '.xbm', '.xpm', '.dds', '.icns', '.jp2', '.mng', '.tga', '.tiff', '.wbmp', '.webp')
        try:
            open(self.key, 'r')
        except IOError:
            print('There was an error opening the file')
            sys.exit(1)
        
        if self.key.lower().endswith(self.formats):
            # If inshuft = 0, the image is not in shufti's image database
            self.inshuft = 0
            self.rotval = 0
            self.rotvals = (0,-90,-180,-270)
            self.dbfile = expanduser("~/.config/shufti/shufti.db")
            self.dbdir = os.path.dirname(self.dbfile)
            if not os.path.isfile(self.dbfile):
                self.createDB()
            self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
            self.db.setDatabaseName(self.dbfile)
            self.db.open()
            self.query = QtSql.QSqlQuery()
            self.dbSearch(self.dbkey)
            # Set common window attributes
            self.path, self.title = os.path.split(self.key)
            self.setWindowTitle(str(self.title))
            self.img = QPixmap(self.key)
            self.scene = QGraphicsScene()
            self.scene.addPixmap(self.img)
            self.view = ShuftiView(self.scene, self)
            self.view.setDragMode(QGraphicsView.ScrollHandDrag)
            self.view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
            self.view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
            # Create array of images in current image dir
            self.imgfiles = []
            for filename in glob.glob(str(self.path) + '/*'):
                base, ext = os.path.splitext(filename)
                if ext.lower() in self.formats:
                    self.imgfiles.append(filename)
            # Find location of current image in imgfiles array
            self.dirpos = 0
            while self.dirpos < len(self.imgfiles) and self.imgfiles[self.dirpos] != self.key:
                self.dirpos += 1
            # If we have no inshuftery, we use the defaults
            if self.inshuft == 0:
                self.newImage()
            else:
                self.oldImage()
        else:
            print("Unsupported file format")
            sys.exit(1)
        
    def newImage(self):               
        
        self.zoom = 1
        self.rotate = 0
        self.resize(self.img.size())
        self.view.resize(self.img.width() + 2, self.img.height() + 2)
        self.show()
        self.view.verticalScrollBar().setValue(0)
        self.view.horizontalScrollBar().setValue(0)
        
    def oldImage(self):
        
        if self.rotate == -90:
            self.rotval = 1
        elif self.rotate == -180:
            self.rotval = 2
        elif self.rotate == -270:
            self.rotval = 3
        self.resize(self.img.size())
        self.updateView()
        self.show()
        self.setGeometry(self.winposx, self.winposy, self.winsizex, self.winsizey)
        self.view.verticalScrollBar().setValue(self.vscroll)
        self.view.horizontalScrollBar().setValue(self.hscroll)
        
    def toggleFullscreen(self):
        
        if self.isFullScreen():
            self.showNormal()
        else:
            self.showFullScreen()
            
    def keyPressEvent(self, event):
        
        if event.key() == QtCore.Qt.Key_F11:
            self.toggleFullscreen()
        elif event.key() == QtCore.Qt.Key_Equal or event.key() == QtCore.Qt.Key_E:
            self.zoomIn()
        elif event.key() == QtCore.Qt.Key_Minus or event.key() == QtCore.Qt.Key_D:
            self.zoomOut()
        elif event.key() == QtCore.Qt.Key_1:
            self.zoomReset()
        elif event.key() == QtCore.Qt.Key_S:
            self.rotateImg(-1)
        elif event.key() == QtCore.Qt.Key_R:
            self.rotateImg(1)
        elif event.key() == QtCore.Qt.Key_F:
            self.fitView()
        elif event.key() == QtCore.Qt.Key_Space:
            self.dirBrowse(1)
        elif event.key() == QtCore.Qt.Key_Backspace:
            self.dirBrowse(-1)
        elif event.key() == QtCore.Qt.Key_V:
            self.vertMax()
        elif event.key() == QtCore.Qt.Key_Z:
            self.horizMax()
        elif event.key() == QtCore.Qt.Key_Q:
            self.close()
            
    def mouseDoubleClickEvent(self, event):
        
        self.toggleFullscreen()
            
    def createDB(self):
        
        if not os.path.exists(self.dbdir):
            os.makedirs(self.dbdir)
        self.db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
        self.db.setDatabaseName(self.dbfile)
        self.query = QtSql.QSqlQuery()
        self.db.open()
        self.query.exec_("create table shuftery(filename text primary key, "
        "zoom real, winposx int, winposy int, winsizex int, winsizey int, "
        "hscroll int, vscroll int, rotate int)")
        return True
        
    def zoomIn(self):
        
        self.zoom *= 1.05
        self.updateView()
        
    def zoomOut(self):
        
        self.zoom /= 1.05
        self.updateView()
        
    def zoomReset(self):
        
        self.zoom = 1
        self.updateView()
        
    def rotateImg(self, clock):
        
        self.rotval += clock
        if self.rotval == 4:
            self.rotval = 0
        elif self.rotval < 0:
            self.rotval = 3
        self.rotate = self.rotvals[self.rotval]
        self.updateView()
        
    def fitView(self):
        
        self.view.fitInView(self.scene.sceneRect(), QtCore.Qt.KeepAspectRatio)
        if self.rotate == 0:
            self.zoom = self.view.transform().m11()
        elif self.rotate == -90:
            self.zoom = (self.view.transform().m12()) * -1
        elif self.rotate == -180:
            self.zoom = (self.view.transform().m11()) * -1
        else:
            self.zoom = self.view.transform().m12()
        
    def updateView(self):
        
        self.view.setTransform(QTransform().scale(self.zoom, self.zoom).rotate(self.rotate))
        
    def winState(self):
        
        self.winsizex = self.geometry().width()
        self.winsizey = self.geometry().height()
        self.vscroll = self.view.verticalScrollBar().value()
        self.hscroll = self.view.horizontalScrollBar().value()
        self.winposx = self.pos().x()
        self.winposy = self.pos().y()
        
    def dbInsert(self):
        
        self.query.exec_("insert into shuftery values('%s" % self.dbkey + 
        "', " + str(self.zoom) + ", " + str(self.winposx) + ", " + str(self.winposy) + 
        ", " + str(self.winsizex) + ", " + str(self.winsizey) + ", " + str(self.hscroll) + 
        ", " + str(self.vscroll) + ", " + str(self.rotate) + ")")
        
    def dbUpdate(self):
        
        self.query.exec_("update shuftery set zoom=" + str(self.zoom) + 
        ", winposx=" + str(self.winposx) + ", winposy=" + str(self.winposy) + 
        ", winsizex=" + str(self.winsizex) + ", winsizey=" + str(self.winsizey) + 
        ", hscroll=" + str(self.hscroll) + ", vscroll=" + str(self.vscroll) + 
        ", rotate=" + str(self.rotate) + " where filename='%s'" % self.dbkey)
        
    def dbSearch(self, field):
        
        self.query.exec_("SELECT * FROM shuftery WHERE filename='%s'" % field)
        # If the image is found in shufti.db, load the previous view settings
        while self.query.next() and self.inshuft == 0:
            self.zoom = self.query.value(1)
            self.winposx = self.query.value(2)
            self.winposy = self.query.value(3)
            self.winsizex = self.query.value(4)
            self.winsizey = self.query.value(5)
            self.hscroll = self.query.value(6)
            self.vscroll = self.query.value(7)
            self.rotate = self.query.value(8)
            self.inshuft = 1
    
    def dbSanitise(self):
        
        self.dbkey = self.key.replace("\"", "\"\"")
        self.dbkey = self.dbkey.replace("\'", "\'\'")
        self.dbkey = self.dbkey.replace("\\", "\\\\")
        
    def dirBrowse(self, direc):
        
        if len(self.imgfiles) > 1:
            self.dirpos += direc
            if self.dirpos > (len(self.imgfiles) - 1):
                self.dirpos = 0
            elif self.dirpos < 0:
                self.dirpos = (len(self.imgfiles) - 1)
            shufti.winState()
            if self.inshuft == 0:
                shufti.dbInsert()
            else:
                shufti.dbUpdate()
            self.key = self.imgfiles[self.dirpos]
            self.dbSanitise()
            self.path, self.title = os.path.split(self.key)
            self.setWindowTitle(str(self.title) + " - shufti")
            self.inshuft = 0
            self.dbSearch(self.dbkey)
            self.scene.clear()
            self.view.resetTransform()
            self.img = QPixmap(self.key)
            self.scene.addPixmap(self.img)
            if self.inshuft == 0:
                self.newImage()
            else:
                self.oldImage()
                
    def vertMax(self):
        
        self.screen_res = app.desktop().availableGeometry(shufti)
        self.screenh = self.screen_res.height()
        self.winsizex = self.geometry().width()
        self.winposx = self.pos().x()
        self.setGeometry(self.winposx, 0, self.winsizex, self.screenh)
        
    def horizMax(self):
        
        self.screen_res = app.desktop().availableGeometry(shufti)
        self.screenw = self.screen_res.width()
        self.winsizey = self.geometry().height()
        self.winposy = self.pos().y()
        self.setGeometry(0, self.winposy, self.screenw, self.winsizey)
        
    def about(self):
        
        self.pop = AboutShufti()
        self.pop.resize(450, 200)
        self.pop.setWindowTitle("About shufti")
        self.pop.show()
class SnapshotFreehandGrabber(QWidget):
    """
    Class implementing a grabber widget for a freehand snapshot region.
    
    @signal grabbed(QPixmap) emitted after the region was grabbed
    """
    grabbed = pyqtSignal(QPixmap)
    
    def __init__(self):
        """
        Constructor
        """
        super(SnapshotFreehandGrabber, self).__init__(
            None,
            Qt.X11BypassWindowManagerHint | Qt.WindowStaysOnTopHint |
            Qt.FramelessWindowHint | Qt.Tool)
        
        self.__selection = QPolygon()
        self.__mouseDown = False
        self.__newSelection = False
        self.__handleSize = 10
        self.__showHelp = True
        self.__grabbing = False
        self.__dragStartPoint = QPoint()
        self.__selectionBeforeDrag = QPolygon()
        self.__locale = QLocale()
        
        self.__helpTextRect = QRect()
        self.__helpText = self.tr(
            "Select a region using the mouse. To take the snapshot,"
            " press the Enter key or double click. Press Esc to quit.")
        
        self.__pixmap = QPixmap()
        self.__pBefore = QPoint()
        
        self.setMouseTracking(True)
        
        QTimer.singleShot(200, self.__initialize)
    
    def __initialize(self):
        """
        Private slot to initialize the rest of the widget.
        """
        self.__desktop = QApplication.desktop()
        x = self.__desktop.x()
        y = self.__desktop.y()
        if qVersion() >= "5.0.0":
            self.__pixmap = QApplication.screens()[0].grabWindow(
                self.__desktop.winId(), x, y,
                self.__desktop.width(), self.__desktop.height())
        else:
            self.__pixmap = QPixmap.grabWindow(
                self.__desktop.winId(), x, y,
                self.__desktop.width(), self.__desktop.height())
        self.resize(self.__pixmap.size())
        self.move(x, y)
        self.setCursor(Qt.CrossCursor)
        self.show()

        self.grabMouse()
        self.grabKeyboard()
        self.activateWindow()
    
    def paintEvent(self, evt):
        """
        Protected method handling paint events.
        
        @param evt paint event (QPaintEvent)
        """
        if self.__grabbing:     # grabWindow() should just get the background
            return
        
        painter = QPainter(self)
        pal = QPalette(QToolTip.palette())
        font = QToolTip.font()
        
        handleColor = pal.color(QPalette.Active, QPalette.Highlight)
        handleColor.setAlpha(160)
        overlayColor = QColor(0, 0, 0, 160)
        textColor = pal.color(QPalette.Active, QPalette.Text)
        textBackgroundColor = pal.color(QPalette.Active, QPalette.Base)
        painter.drawPixmap(0, 0, self.__pixmap)
        painter.setFont(font)
        
        pol = QPolygon(self.__selection)
        if not self.__selection.boundingRect().isNull():
            # Draw outline around selection.
            # Important: the 1px-wide outline is *also* part of the
            # captured free-region
            pen = QPen(handleColor, 1, Qt.SolidLine, Qt.SquareCap,
                       Qt.BevelJoin)
            painter.setPen(pen)
            painter.drawPolygon(pol)
            
            # Draw the grey area around the selection.
            grey = QRegion(self.rect())
            grey = grey - QRegion(pol)
            painter.setClipRegion(grey)
            painter.setPen(Qt.NoPen)
            painter.setBrush(overlayColor)
            painter.drawRect(self.rect())
            painter.setClipRect(self.rect())
            drawPolygon(painter, pol, handleColor)
        
        if self.__showHelp:
            painter.setPen(textColor)
            painter.setBrush(textBackgroundColor)
            self.__helpTextRect = painter.boundingRect(
                self.rect().adjusted(2, 2, -2, -2),
                Qt.TextWordWrap, self.__helpText).translated(
                -self.__desktop.x(), -self.__desktop.y())
            self.__helpTextRect.adjust(-2, -2, 4, 2)
            drawPolygon(painter, self.__helpTextRect, textColor,
                        textBackgroundColor)
            painter.drawText(
                self.__helpTextRect.adjusted(3, 3, -3, -3),
                Qt.TextWordWrap, self.__helpText)
        
        if self.__selection.isEmpty():
            return
        
        # The grabbed region is everything which is covered by the drawn
        # rectangles (border included). This means that there is no 0px
        # selection, since a 0px wide rectangle will always be drawn as a line.
        boundingRect = self.__selection.boundingRect()
        txt = "{0}, {1} ({2} x {3})".format(
            self.__locale.toString(boundingRect.x()),
            self.__locale.toString(boundingRect.y()),
            self.__locale.toString(boundingRect.width()),
            self.__locale.toString(boundingRect.height())
        )
        textRect = painter.boundingRect(self.rect(), Qt.AlignLeft, txt)
        boundingRect = textRect.adjusted(-4, 0, 0, 0)
        
        polBoundingRect = pol.boundingRect()
        if (textRect.width() <
            polBoundingRect.width() - 2 * self.__handleSize) and \
           (textRect.height() <
            polBoundingRect.height() - 2 * self.__handleSize) and \
           polBoundingRect.width() > 100 and \
           polBoundingRect.height() > 100:
            # center, unsuitable for small selections
            boundingRect.moveCenter(polBoundingRect.center())
            textRect.moveCenter(polBoundingRect.center())
        elif polBoundingRect.y() - 3 > textRect.height() and \
                polBoundingRect.x() + textRect.width() < self.rect().width():
            # on top, left aligned
            boundingRect.moveBottomLeft(
                QPoint(polBoundingRect.x(), polBoundingRect.y() - 3))
            textRect.moveBottomLeft(
                QPoint(polBoundingRect.x() + 2, polBoundingRect.y() - 3))
        elif polBoundingRect.x() - 3 > textRect.width():
            # left, top aligned
            boundingRect.moveTopRight(
                QPoint(polBoundingRect.x() - 3, polBoundingRect.y()))
            textRect.moveTopRight(
                QPoint(polBoundingRect.x() - 5, polBoundingRect.y()))
        elif (polBoundingRect.bottom() + 3 + textRect.height() <
              self.rect().bottom()) and \
                polBoundingRect.right() > textRect.width():
            # at bottom, right aligned
            boundingRect.moveTopRight(
                QPoint(polBoundingRect.right(), polBoundingRect.bottom() + 3))
            textRect.moveTopRight(
                QPoint(polBoundingRect.right() - 2,
                       polBoundingRect.bottom() + 3))
        elif polBoundingRect.right() + textRect.width() + 3 < \
                self.rect().width():
            # right, bottom aligned
            boundingRect.moveBottomLeft(
                QPoint(polBoundingRect.right() + 3, polBoundingRect.bottom()))
            textRect.moveBottomLeft(
                QPoint(polBoundingRect.right() + 5, polBoundingRect.bottom()))
        
        # If the above didn't catch it, you are running on a very
        # tiny screen...
        drawPolygon(painter, boundingRect, textColor, textBackgroundColor)
        painter.drawText(textRect, Qt.AlignHCenter, txt)
        
        if (polBoundingRect.height() > self.__handleSize * 2 and
            polBoundingRect.width() > self.__handleSize * 2) or \
           not self.__mouseDown:
            painter.setBrush(Qt.transparent)
            painter.setClipRegion(QRegion(pol))
            painter.drawPolygon(QPolygon(self.rect()))
    
    def mousePressEvent(self, evt):
        """
        Protected method to handle mouse button presses.
        
        @param evt mouse press event (QMouseEvent)
        """
        self.__pBefore = evt.pos()
        
        self.__showHelp = not self.__helpTextRect.contains(evt.pos())
        if evt.button() == Qt.LeftButton:
            self.__mouseDown = True
            self.__dragStartPoint = evt.pos()
            self.__selectionBeforeDrag = QPolygon(self.__selection)
            if not self.__selection.containsPoint(evt.pos(), Qt.WindingFill):
                self.__newSelection = True
                self.__selection = QPolygon()
            else:
                self.setCursor(Qt.ClosedHandCursor)
        elif evt.button() == Qt.RightButton:
            self.__newSelection = False
            self.__selection = QPolygon()
            self.setCursor(Qt.CrossCursor)
        self.update()
    
    def mouseMoveEvent(self, evt):
        """
        Protected method to handle mouse movements.
        
        @param evt mouse move event (QMouseEvent)
        """
        shouldShowHelp = not self.__helpTextRect.contains(evt.pos())
        if shouldShowHelp != self.__showHelp:
            self.__showHelp = shouldShowHelp
            self.update()
        
        if self.__mouseDown:
            if self.__newSelection:
                p = evt.pos()
                self.__selection.append(p)
            else:
                # moving the whole selection
                p = evt.pos() - self.__pBefore  # Offset
                self.__pBefore = evt.pos()  # save position for next iteration
                self.__selection.translate(p)
            
            self.update()
        else:
            if self.__selection.boundingRect().isEmpty():
                return
            
            if self.__selection.containsPoint(evt.pos(), Qt.WindingFill):
                self.setCursor(Qt.OpenHandCursor)
            else:
                self.setCursor(Qt.CrossCursor)
    
    def mouseReleaseEvent(self, evt):
        """
        Protected method to handle mouse button releases.
        
        @param evt mouse release event (QMouseEvent)
        """
        self.__mouseDown = False
        self.__newSelection = False
        if self.__selection.containsPoint(evt.pos(), Qt.WindingFill):
            self.setCursor(Qt.OpenHandCursor)
        self.update()
    
    def mouseDoubleClickEvent(self, evt):
        """
        Protected method to handle mouse double clicks.
        
        @param evt mouse double click event (QMouseEvent)
        """
        self.__grabRegion()
    
    def keyPressEvent(self, evt):
        """
        Protected method to handle key presses.
        
        @param evt key press event (QKeyEvent)
        """
        if evt.key() == Qt.Key_Escape:
            self.grabbed.emit(QPixmap())
        elif evt.key() in [Qt.Key_Enter, Qt.Key_Return]:
            self.__grabRegion()
        else:
            evt.ignore()
    
    def __grabRegion(self):
        """
        Private method to grab the selected region (i.e. do the snapshot).
        """
        pol = QPolygon(self.__selection)
        if not pol.isEmpty():
            self.__grabbing = True
            
            xOffset = self.__pixmap.rect().x() - pol.boundingRect().x()
            yOffset = self.__pixmap.rect().y() - pol.boundingRect().y()
            translatedPol = pol.translated(xOffset, yOffset)
            
            pixmap2 = QPixmap(pol.boundingRect().size())
            pixmap2.fill(Qt.transparent)
            
            pt = QPainter()
            pt.begin(pixmap2)
            if pt.paintEngine().hasFeature(QPaintEngine.PorterDuff):
                pt.setRenderHints(
                    QPainter.Antialiasing |
                    QPainter.HighQualityAntialiasing |
                    QPainter.SmoothPixmapTransform,
                    True)
                pt.setBrush(Qt.black)
                pt.setPen(QPen(QBrush(Qt.black), 0.5))
                pt.drawPolygon(translatedPol)
                pt.setCompositionMode(QPainter.CompositionMode_SourceIn)
            else:
                pt.setClipRegion(QRegion(translatedPol))
                pt.setCompositionMode(QPainter.CompositionMode_Source)
            
            pt.drawPixmap(pixmap2.rect(), self.__pixmap, pol.boundingRect())
            pt.end()
            
            self.grabbed.emit(pixmap2)
Exemple #57
0
class KEyesWidget(QWidget):

  update_interval = 50 # ms

  faces = {
    "Aaron":     ("keyes-aaron.png",     (49, 63, 12, 8), (79, 63, 12, 8)),
    "Adrian":    ("keyes-adrian.png",    (46, 67, 11, 6), (74, 68, 11, 6)),
    "Cornelius": ("keyes-cornelius.png", (49, 68, 11, 6), (79, 68, 11, 6)),
    "Eva":       ("keyes-eva.png",       (51, 63, 12, 6), (83, 63, 12, 6)),
    "Sebastian": ("keyes-sebastian.png", (50, 58, 14, 7), (83, 58, 14, 7)),
  }


  def __init__(self):

    QLabel.__init__(self)

    self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)
    self.setAttribute(Qt.WA_NoSystemBackground)
    self.setMouseTracking(True)

    self.dragPosition  = QPoint(0, 0)
    self.mousePosition = QCursor.pos()

    self.actionFaces = QActionGroup(self)
    allFaceActions   = []

    for name in sorted(self.faces):

      action = QAction(name, self.actionFaces)
      action.setCheckable(True)
      allFaceActions.append(action)

    self.actionFaces.triggered.connect(self.actionUpdateFace)

    startAction = random.choice(allFaceActions)
    startAction.setChecked(True)
    self.actionUpdateFace(startAction)

    self.actionQuit = QAction("Quit", self)
    self.actionQuit.triggered.connect(QApplication.instance().quit)

    self.timer = QTimer()
    self.timer.timeout.connect(self.updateFromMousePosition)

    self.timer.start(self.update_interval)

    self.painter = None


  def actionUpdateFace(self, action):

    self.setFace(action.text())


  def setFace(self, name):

    self.setWindowTitle(name)
    self.pixmap = QPixmap(normalize_path(self.faces[name][0]))

    self.setWindowIcon(QIcon(self.pixmap))

    self.eyes = [Eye(*self.faces[name][1]), Eye(*self.faces[name][2])]

    self.setMask(self.pixmap.createHeuristicMask())

    if self.isVisible():
      self.update()


  def updateFromMousePosition(self):

    newPosition = QCursor.pos()

    if newPosition == self.mousePosition:
      return

    self.mousePosition = newPosition

    if self.isVisible():
      self.update()


  def mousePressEvent(self, event):

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

      self.dragPosition = event.globalPos() - self.frameGeometry().topLeft()
      event.accept()


  def mouseMoveEvent(self, event):

    if event.buttons() == Qt.LeftButton:

      self.move(event.globalPos() - self.dragPosition)
      event.accept()


  def contextMenuEvent(self, event):

    menu = QMenu(self)

    menu.addActions(self.actionFaces.actions())
    menu.addSeparator()
    menu.addAction(self.actionQuit)

    menu.exec_(event.globalPos())


  def paintEvent(self, event):

    painter      = QPainter(self)
    self.painter = painter

    painter.drawPixmap(QPoint(0, 0), self.pixmap)

    for eye in self.eyes:
      eye.render(self)

    self.painter = None


  def sizeHint(self):

    return self.pixmap.size()