Example #1
0
class Label(QLabel):
    selection_changed = pyqtSignal(QRect, name="selectionChanged")

    def __init__(self):
        QLabel.__init__(self)
        self.rb = QRubberBand(QRubberBand.Rectangle, self)
        self.setMouseTracking(True)

    def mousePressEvent(self, event: QMouseEvent):
        self.origin = event.pos()
        self.rb.setGeometry(QRect(self.origin, QSize()))
        self.rb.show()
        QLabel.mousePressEvent(self, event)

    def mouseMoveEvent(self, event: QMouseEvent):
        if self.rb.isVisible():
            self.rb.setGeometry(
                QRect(self.origin, event.pos()).normalized())
        QWidget.mouseMoveEvent(self, event)

    def mouseReleaseEvent(self, event):
        if self.rb.isVisible():
            self.rb.hide()
        self.selection_changed.emit(self.rb.geometry())
        QLabel.mouseReleaseEvent(self, event)
Example #2
0
class MiniMapGraphicsView(QGraphicsView):
    def __init__(self, parent):
        super().__init__(parent)

        self._drag_start_pos = None

        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.setFixedSize(200, 200)
        self.viewport().setFixedSize(self.contentsRect().size())
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setInteractive(False)
        self.setFocusProxy(parent)

        self.band = QRubberBand(QRubberBand.Rectangle, self)
        self.band.hide()

    def centerOn(self, pos):
        if self.band.isVisible():
            self.parent().centerOn(self.mapToScene(pos))
            rect = self.band.geometry()
            rect.moveCenter(pos)
            self.band.setGeometry(rect)

    def mousePressEvent(self, event):
        if self.band.isVisible() and event.button() == Qt.LeftButton:
            rect = self.band.geometry()
            if event.pos() in rect:
                self._drag_start_pos = event.pos()
            else:
                self.centerOn(event.pos())

    def mouseMoveEvent(self, event):
        if self.band.isVisible() and event.buttons() == Qt.MouseButtons(
                Qt.LeftButton) and self._drag_start_pos is not None:
            self.centerOn(event.pos())

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton and self.band.isVisible():
            self.viewport().unsetCursor()
            self._drag_start_pos = None

    def adjustRubberband(self):
        scene = self.scene()
        if scene is None:
            return

        rect = self.parent().mapToScene(self.parent().rect()).boundingRect()
        if not rect.contains(scene.sceneRect()):
            rect = self.mapFromScene(rect).boundingRect()
            self.band.setGeometry(rect)
            self.band.show()
        else:
            self.band.hide()

    def zoomToFit(self):
        self.fitInView(self.scene().sceneRect().adjusted(-20, -20, 20, 20),
                       Qt.KeepAspectRatio)
Example #3
0
class SelectWidget(QWidget, Ui_Form2):

    select = [0,0,0,0]

    def __init__(self, parent=None):
        super(SelectWidget, self).__init__(parent)
        self.setWindowOpacity(0.5)
        self.setupUi(self)
        desktop = QtWidgets.QDesktopWidget()
        self.resize(desktop.availableGeometry().width(), desktop.availableGeometry().height())
        self.rubberband = QRubberBand(
            QRubberBand.Rectangle, self)
        self.setMouseTracking(True)

    def mousePressEvent(self, event):
        self.select[0] = event.screenPos().x()
        self.select[1] = event.screenPos().y()
        self.origin = event.pos()
        self.rubberband.setGeometry(
            QtCore.QRect(self.origin, QtCore.QSize()))
        self.rubberband.show()
        QWidget.mousePressEvent(self, event)

    def mouseMoveEvent(self, event):
        if self.rubberband.isVisible():
            self.rubberband.setGeometry(
                QtCore.QRect(self.origin, event.pos()).normalized())
        QWidget.mouseMoveEvent(self, event)

    def mouseReleaseEvent(self, event):
        self.select[2] = event.screenPos().x()
        self.select[3] = event.screenPos().y()
        if self.rubberband.isVisible():
            self.rubberband.hide()
            rect = self.rubberband.geometry()

        # ポインタ座標を左上→右下に揃える
        if self.select[0] > self.select[2]:
            tmp = self.select[0]
            self.select[0] = self.select[2]
            self.select[2] = tmp
        if self.select[1] > self.select[3]:
            tmp = self.select[1]
            self.select[1] = self.select[3]
            self.select[3] = tmp
        # 選択した面積がゼロの場合は何もしないで関数を終わる
        if self.select[0]==self.select[2] or self.select[1]==self.select[3]:
            QWidget.mouseReleaseEvent(self, event)
            self.close()
            return
        # ポインタ座標をメインウインドウに設定する
        area = ''
        for point in self.select:
            area = area + str(int(point)) + ','
        main_window.lineEdit.setText(area[0:-1])
        self.close()
        QWidget.mouseReleaseEvent(self, event)
Example #4
0
class VideoArea(QLabel):
    def __init__(self, parent=None, main=None):
        QLabel.__init__(self, parent)
        self.selection = QRubberBand(QRubberBand.Rectangle, self)
        self.main = main

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:

            position = QPoint(event.pos())
            if self.selection.isVisible():
                if (self.upper_left - position).manhattanLength() < 20:
                    self.mode = "UL"
                elif (self.lower_right - position).manhattanLength() < 20:
                    self.mode = "LR"
                else:
                    self.selection.hide()
            else:
                self.upper_left = position
                self.lower_right = position
                self.mode = "LR"
                self.selection.show()

    def mouseMoveEvent(self, event):
        if self.selection.isVisible():
            if self.mode == "LR":
                self.lower_right = QPoint(event.pos())
            elif self.mode == "UL":
                self.upper_left = QPoint(event.pos())
            self.selection.setGeometry(
                QRect(self.upper_left, self.lower_right).normalized())

    def mouseReleaseEvent(self, event):
        self.main.controller.set_coordinates(
            *self.selection.geometry().getCoords())
        self.selection.hide()
Example #5
0
class DragWidget(QWidget):
    spacerX = 16
    spacerY = 16
    clipicon = None
    new_window_signal = pyqtSignal(str)
    query = pyqtSignal()
    src_dragwidget = None
    src_selected = []

    def __init__(self, path, parent=None):
        super(DragWidget, self).__init__(parent)
        self.setMinimumSize(400, 200)
        self.setAcceptDrops(True)
        self.parent = parent
        # self.parent.menu.connect(self.delete_icon)
        self.modifier = False
        self.rubberband = QRubberBand(QRubberBand.Rectangle, self)
        self.path = path
        self.icons = []
        self.icon_offsetx = 0
        self.icon_offsety = 0
        # self.clipicon = None
        # self.moving_icons = []
        self.read_drawer()
        self.clean_up()
        # print(type(IconWidget.icon))
        # print(self.findChildren(ClickableIcon))

    def read_drawer(self):
        # self.icons.clear()
        for item in os.scandir(self.path):
            if item.is_dir():
                icon_widget = IconWidget(parent=self, name=item.name, path=self.path, dir=True)
            else:
                icon_widget = IconWidget(parent=self, name=item.name, path=self.path, dir=False)
            icon_widget.new_window.connect(self.new_window_signal.emit)
            icon_widget.clipboard.connect(self.on_clipboard)
            self.icons.append(icon_widget)
            self.icons[-1].setAttribute(Qt.WA_DeleteOnClose)
        # self.update()

    def updateScrollArea(self):
        """ set the dimension of the widget """
        iconx = []
        icony = []
        if len(self.icons) > 0:
            for item in self.icons:
                iconx.append(item.x())
                icony.append(item.y())
            self.setMinimumWidth(max(iconx)+75)
            self.setMinimumHeight(max(icony)+75)
        
    def dragEnterEvent(self, event):
        event.accept()

    def dragMoveEvent(self, event):
        event.accept()

    def get_dnd_list(self, event):
        icon_list = []
        icon_offsetx = None
        icon_offsety = None
        if len(DragWidget.src_selected) > 0:
            for item in DragWidget.src_selected:
                icon_list.append(item)
        else:
            icon_list.append(event.source())
        return icon_list

    def create_icon(self, name, drawer):
        if drawer:
            icon_widget = IconWidget(self, name=name, path=self.path, dir=True)
        else: 
            icon_widget = IconWidget(self, name=name, path=self.path, dir=False)
        icon_widget.new_window.connect(self.new_window_signal.emit)
        self.icons.append(icon_widget)

    def place_icon(self, x, y):
        self.icons[-1].move(x, y)
        self.icons[-1].show()

    def dropEvent(self, event):
        event.accept()
        icon_list = self.get_dnd_list(event)
        icon_offsetx = event.pos().x()
        icon_offsety = event.pos().y()
        for item in icon_list:
            name = item.name
            drawer = item.drawer
            src_path = item.path + "/" + name
            dst_path = self.path + "/"
            if event.mimeData().hasFormat("application/x-icon"):
                self.create_icon(name, drawer)
                self.move_data(src_path, dst_path)
                self.place_icon(icon_offsetx, icon_offsety)
                icon_offsetx += 100 
                if icon_offsetx > self.window().width():
                    icon_offsetx = event.pos().x()
                    icon_offsety += 75

        icon_offsetx = None
        icon_offsety = None
        self.updateScrollArea()

    def clear_dnd(self):
        DragWidget.src_dragwidget = None
        DragWidget.src_selected.clear()

    def get_modifier(self):
        return self.parent.modifier

    def mousePressEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            for item in self.icons:
                item.icon.deselect_icon()
            self.clear_dnd() 

            self.origin = event.pos()
            self.rubberband.setGeometry(QRect(self.origin, QSize()))
            self.rubberband.show()

    def mouseMoveEvent(self, event):
        if self.rubberband.isVisible():
            self.rubberband.setGeometry(
                QRect(self.origin, event.pos()).normalized())
        # QWidget.mouseMoveEvent(self, event)

    def mouseReleaseEvent(self, event):
        self.clear_dnd()
        if self.rubberband.isVisible():
            self.rubberband.hide()
            rect = self.rubberband.geometry()
            for child in self.findChildren(IconWidget):
                if rect.intersects(child.geometry()):
                    child.icon.select_icon()
                    DragWidget.src_selected.append(child)
                    if DragWidget.src_dragwidget is not self:
                        DragWidget.src_dragwidget = self

    def mouseDoubleClickEvent(self, event):
        print(BLU, "Double Click", END) 
        self.query.emit()

    def create_file(self):
        new_file = self.path + "/" + "newfile.txt"
        open(new_file, 'w').close()
        icon_widget = IconWidget(self, name="newfile.txt", path=self.path, dir=False)
        icon_widget.new_window.connect(self.new_window_signal.emit)
        icon_widget.show()
        self.icons.append(icon_widget)

    def create_drawer(self):
        print("creating new drawer")
        new_drawer = self.path + "/" + "NewDrawer"
        os.makedirs(new_drawer)
        icon_widget = IconWidget(self, name="NewDrawer", path=self.path, dir=True)
        icon_widget.new_window.connect(self.new_window_signal.emit)
        icon_widget.show()
        self.icons.append(icon_widget)

    def rename_file(self):
        print("renaming file")

    def clean_up(self):
        for item in self.icons:
            item.move(DragWidget.spacerX, DragWidget.spacerY)
            # initial icon placement
            DragWidget.spacerX += 100
            if DragWidget.spacerX + 100 > self.window().width():
                DragWidget.spacerY += 75
                DragWidget.spacerX = 16
        # reset placement values
        DragWidget.spacerX = 16
        DragWidget.spacerY = 16
        self.updateScrollArea()

    def move_data(self, source, dest):
        srce_path = source.rsplit('/', 1)[0]
        dest_path = dest.rsplit('/', 1)[0]
        if srce_path != dest_path:
            try:
                shutil.move(source, dest)
            except Exception as err:
                print(err)

    def copy_icon(self, source, dest):
        pass

    def delete_icon(self):
        dest = os.path.expanduser("~") + "/.Trash/"
        error_string = ""
        for item in self.icons:
            if item.icon.selected:
                source = item.path + "/" + item.name
                if source is not "":
                    try:
                        shutil.move(source, dest)
                    except Exception as err:
                        error_string += str(err) + "\n" + "\n"
                    else:
                        self.icons.remove(item)
                        item.deleteLater()
        if error_string is not "":
            QMessageBox.information(self, 'Info', error_string, QMessageBox.Ok)

    def paste_icon(self):
        print("---")
        print("srce=", self.clipicon.path + "/" + self.clipicon.name)
        # print("res=", self.clipicon.path + "/" + self.clipicon.name)
        print("dest=", self.path + "/")

        # if os.path.isdir(os.path.join(self.clipicon.path, self.clipicon.name)):
        SRCE = self.clipicon.path + "/" + self.clipicon.name
        DEST = self.path+"/" + self.clipicon.name
        shutil.copytree(SRCE, DEST)

    def on_clipboard(self, icon):
        print("realpath", self.path)
        print("clip_icon_name=", icon.name)
        DragWidget.clipicon = icon
Example #6
0
class ImageViewer(QLabel):
    def __init__(self):
        super(ImageViewer, self).__init__()
        self.crop = Signal()
        #pixmap = QPixmap(640, 640)
        pixmap = QPixmap()
        self.setPixmap(pixmap)

        self.first_x, self.first_y = None, None
        self.last_x, self.last_y = None, None
        self.pen_color = QColor('#000000')
        self.scaleFactor = 0.0
        self.setBackgroundRole(QPalette.Base)
        #self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        #self.setScaledContents(True)

        #self.setGeometry(QRect(110, 550, 640, 640))
        self.setText("Feature")
        self.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        #self.setAlignment(Qt.AlignCenter)
        self.setWordWrap(False)
        #self.setFixedSize(640,640)
        self.createActions()
        self.show()
        #self.showMaximized()

    def setImage(self, q_img):
        self.setPixmap(q_img)
        self.scaleFactor = 1.0
        #self.fitToWindowAct.setEnabled(True)
        self.updateActions()

        if not self.fitToWindowAct.isChecked():
            self.adjustSize()

    def open(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open File",
                                                  QDir.currentPath())
        if fileName:
            image = QImage(fileName)
            if image.isNull():
                QMessageBox.information(self, "Image Viewer",
                                        "Cannot load %s." % fileName)
                return

            self.setPixmap(QPixmap.fromImage(image))
            self.scaleFactor = 1.0

            self.fitToWindowAct.setEnabled(True)
            self.updateActions()

            if not self.fitToWindowAct.isChecked():
                self.adjustSize()

    def zoomIn(self):
        self.scaleImage(1.25)

    def zoomOut(self):
        self.scaleImage(0.8)

    def normalSize(self):
        self.adjustSize()
        self.scaleFactor = 1.0

    def fitToWindow(self):
        fitToWindow = self.fitToWindowAct.isChecked()
        self.scrollArea.setWidgetResizable(fitToWindow)
        if not fitToWindow:
            self.normalSize()

        self.updateActions()

    def createActions(self):
        self.openAct = QAction("&Open...",
                               self,
                               shortcut="Ctrl+O",
                               triggered=self.open)

        self.zoomInAct = QAction("Zoom &In (25%)",
                                 self,
                                 shortcut="Ctrl++",
                                 enabled=False,
                                 triggered=self.zoomIn)

        self.zoomOutAct = QAction("Zoom &Out (25%)",
                                  self,
                                  shortcut="Ctrl+-",
                                  enabled=False,
                                  triggered=self.zoomOut)

        self.normalSizeAct = QAction("&Normal Size",
                                     self,
                                     shortcut="Ctrl+S",
                                     enabled=False,
                                     triggered=self.normalSize)

        self.fitToWindowAct = QAction("&Fit to Window",
                                      self,
                                      enabled=False,
                                      checkable=True,
                                      shortcut="Ctrl+F",
                                      triggered=self.fitToWindow)

    def updateActions(self):
        self.zoomInAct.setEnabled(not self.fitToWindowAct.isChecked())
        self.zoomOutAct.setEnabled(not self.fitToWindowAct.isChecked())
        self.normalSizeAct.setEnabled(not self.fitToWindowAct.isChecked())

    def scaleImage(self, factor):
        self.scaleFactor *= factor
        self.resize(self.scaleFactor * self.pixmap().size())
        self.zoomInAct.setEnabled(self.scaleFactor < 3.0)
        self.zoomOutAct.setEnabled(self.scaleFactor > 0.333)

    def mousePressEvent(self, eventQMouseEvent):
        self.originQPoint = self.mapFrom(self, eventQMouseEvent.pos())
        self.first_x = int(eventQMouseEvent.x())
        self.first_y = int(eventQMouseEvent.y())
        self.currentQRubberBand = QRubberBand(QRubberBand.Rectangle, self)
        self.currentQRubberBand.setGeometry(QRect(self.originQPoint, QSize()))
        self.currentQRubberBand.show()

    def mouseMoveEvent(self, eventQMouseEvent):
        self.x = int(eventQMouseEvent.x())
        self.y = int(eventQMouseEvent.y())
        text1 = str(self.x)
        text2 = str(self.y)
        p = self.mapToGlobal(eventQMouseEvent.pos())
        #QToolTip.showText(eventQMouseEvent.pos() , "X: "+text1+" "+"Y: "+text2,self)
        QToolTip.showText(p, "X: " + text1 + " " + "Y: " + text2, self)
        # print ('mouse QToolTip 1') 전체장에서의 위젯 시작점의 좌표가 오리진 포인트가 되어야 함.
        '''
        if self.currentQRubberBand.isVisible():
            self.currentQRubberBand.setGeometry(QRect(self.originQPoint, eventQMouseEvent.pos()).normalized() & self.pixmap().rect())
        '''
        pos = self.mapFromGlobal(self.mapToGlobal(eventQMouseEvent.pos()))
        #QToolTip.showText(eventQMouseEvent.pos(), "X: {} Y: {}".format(p.x(), p.y()), self)
        if self.currentQRubberBand.isVisible() and self.pixmap() is not None:
            self.currentQRubberBand.setGeometry(
                QRect(self.originQPoint, pos).normalized() & self.rect())

    def mouseReleaseEvent(self, eventQMouseEvent):
        self.last_x = int(eventQMouseEvent.x())
        self.last_y = int(eventQMouseEvent.y())
        '''
        self.currentQRubberBand.hide()
        currentQRect = self.currentQRubberBand.geometry()
        self.currentQRubberBand.deleteLater()
        if self.pixmap() is not None:
            tr = QTransform()
            if self.fitToWindowAct.isChecked():
                tr.scale(self.pixmap().width() / self.scrollArea.width(),
                         self.pixmap().height() / self.scrollArea.height())
            else:
                tr.scale(1 / self.scaleFactor, 1 / self.scaleFactor)
            r = tr.mapRect(currentQRect)
            cropQPixmap = self.pixmap().copy(r)
            cropQPixmap.save('output.png')
        '''

        self.currentQRubberBand.hide()
        currentQRect = self.currentQRubberBand.geometry()
        self.currentQRubberBand.deleteLater()
        cropQPixmap = self.pixmap().copy(currentQRect)
        #size = cropQPixmap.size()
        # 직접변환 해서 저장하는 코드... 나중에
        #s = cropQPixmap.bits().asstring(size.width() * size.height() * image.depth() // 8)  # format 0xffRRGGBB
        #arr = np.fromstring(s, dtype=np.uint8).reshape((size.height(), size.width(), cropQPixmap.depth() // 8))
        #new_image = Image.fromarray(array)
        cropQPixmap.save('output.png')
        img = cv2.imread("output.png", cv2.IMREAD_COLOR)
        h, w = self.cut_imgSize()
        self.crop.cut_signal.emit(img, h, w)

    def cut_imgSize(self):
        h = abs(self.last_y - self.first_y)
        w = abs(self.last_x - self.first_x)
        return h, w
class FsApp(QMainWindow):

    def __init__(self, app):
        super(FsApp, self).__init__()
        self.app       = app
        self.selRect   = None
        self.screenPix = None

        # Set up the user interface from Designer.
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        #self.setWindowOpacity(0.5)
        #self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
        self.captureScreen()
        self.showMaximized()
        self.showFullScreen()


        #capture screen and display
        rec = QApplication.desktop().screenGeometry()
        height = rec.height()
        width = rec.width()
        self.ui.labPix.resize(width, height)
        self.ui.labPix.setScaledContents(True)
        self.ui.labPix.setPixmap(self.screenPix)

        #start rubberband
        self.rubberband = QRubberBand(QRubberBand.Rectangle, self)
        bla = QtGui.QPalette()
        bla.setBrush(QtGui.QPalette.Highlight, QtGui.QBrush(QtCore.Qt.red))
        self.rubberband.setPalette(bla)
        self.rubberband.setWindowOpacity(1.0)

    def captureScreen(self):
        screens = self.app.screens()
        self.screenPix = screens[0].grabWindow(0)

    def mousePressEvent(self, event):
        self.origin = event.pos()
        self.rubberband.setGeometry(QtCore.QRect(self.origin, QtCore.QSize()))
        self.rubberband.show()
        QWidget.mousePressEvent(self, event)

    def mouseMoveEvent(self, event):
        if self.rubberband.isVisible():
            self.rubberband.setGeometry(QtCore.QRect(self.origin, event.pos()).normalized())
        QWidget.mouseMoveEvent(self, event)

    def mouseReleaseEvent(self, event):
        if self.rubberband.isVisible():
            self.selRect = self.rubberband.geometry()
            self.rubberband.hide()
            codePix = self.screenPix.copy(    self.selRect.x(),
                            self.selRect.y(), 
                            self.selRect.width(),
                            self.selRect.height())
            QApplication.clipboard().setPixmap(codePix)
            self.exit()
        QWidget.mouseReleaseEvent(self, event)

    def exit(self):
        sys.exit(0)
Example #8
0
class DragWidget(QWidget):
    spacerX = 16
    spacerY = 16
    clipicon = None
    new_window_signal = pyqtSignal(str)
    query = pyqtSignal()
    src_dragwidget = None
    src_selected = []

    def __init__(self, path, parent=None):
        super(DragWidget, self).__init__(parent)
        self.setMinimumSize(400, 200)
        self.setAcceptDrops(True)
        self.parent = parent
        # self.parent.menu.connect(self.delete_icon)
        self.modifier = False
        self.rubberband = QRubberBand(QRubberBand.Rectangle, self)
        self.path = path
        self.icons = []
        self.icon_offsetx = 0
        self.icon_offsety = 0
        # self.clipicon = None
        # self.moving_icons = []
        self.read_drawer()
        self.clean_up()
        # print(type(IconWidget.icon))
        # print(self.findChildren(ClickableIcon))

    def read_drawer(self):
        # self.icons.clear()
        for item in os.scandir(self.path):
            if item.is_dir():
                icon_widget = IconWidget(parent=self,
                                         name=item.name,
                                         path=self.path,
                                         dir=True)
            else:
                icon_widget = IconWidget(parent=self,
                                         name=item.name,
                                         path=self.path,
                                         dir=False)
            icon_widget.new_window.connect(self.new_window_signal.emit)
            icon_widget.clipboard.connect(self.on_clipboard)
            self.icons.append(icon_widget)
            self.icons[-1].setAttribute(Qt.WA_DeleteOnClose)
        # self.update()

    def updateScrollArea(self):
        """ set the dimension of the widget """
        iconx = []
        icony = []
        if len(self.icons) > 0:
            for item in self.icons:
                iconx.append(item.x())
                icony.append(item.y())
            self.setMinimumWidth(max(iconx) + 75)
            self.setMinimumHeight(max(icony) + 75)

    def dragEnterEvent(self, event):
        event.accept()

    def dragMoveEvent(self, event):
        event.accept()

    def get_dnd_list(self, event):
        icon_list = []
        icon_offsetx = None
        icon_offsety = None
        if len(DragWidget.src_selected) > 0:
            for item in DragWidget.src_selected:
                icon_list.append(item)
        else:
            icon_list.append(event.source())
        return icon_list

    def create_icon(self, name, drawer):
        if drawer:
            icon_widget = IconWidget(self, name=name, path=self.path, dir=True)
        else:
            icon_widget = IconWidget(self,
                                     name=name,
                                     path=self.path,
                                     dir=False)
        icon_widget.new_window.connect(self.new_window_signal.emit)
        self.icons.append(icon_widget)

    def place_icon(self, x, y):
        self.icons[-1].move(x, y)
        self.icons[-1].show()

    def dropEvent(self, event):
        event.accept()
        icon_list = self.get_dnd_list(event)
        icon_offsetx = event.pos().x()
        icon_offsety = event.pos().y()
        for item in icon_list:
            name = item.name
            drawer = item.drawer
            src_path = item.path + "/" + name
            dst_path = self.path + "/"
            if event.mimeData().hasFormat("application/x-icon"):
                self.create_icon(name, drawer)
                self.move_data(src_path, dst_path)
                self.place_icon(icon_offsetx, icon_offsety)
                icon_offsetx += 100
                if icon_offsetx > self.window().width():
                    icon_offsetx = event.pos().x()
                    icon_offsety += 75

        icon_offsetx = None
        icon_offsety = None
        self.updateScrollArea()

    def clear_dnd(self):
        DragWidget.src_dragwidget = None
        DragWidget.src_selected.clear()

    def get_modifier(self):
        return self.parent.modifier

    def mousePressEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            for item in self.icons:
                item.icon.deselect_icon()
            self.clear_dnd()

            self.origin = event.pos()
            self.rubberband.setGeometry(QRect(self.origin, QSize()))
            self.rubberband.show()

    def mouseMoveEvent(self, event):
        if self.rubberband.isVisible():
            self.rubberband.setGeometry(
                QRect(self.origin, event.pos()).normalized())
        # QWidget.mouseMoveEvent(self, event)

    def mouseReleaseEvent(self, event):
        self.clear_dnd()
        if self.rubberband.isVisible():
            self.rubberband.hide()
            rect = self.rubberband.geometry()
            for child in self.findChildren(IconWidget):
                if rect.intersects(child.geometry()):
                    child.icon.select_icon()
                    DragWidget.src_selected.append(child)
                    if DragWidget.src_dragwidget is not self:
                        DragWidget.src_dragwidget = self

    def mouseDoubleClickEvent(self, event):
        print(BLU, "Double Click", END)
        self.query.emit()

    def create_file(self):
        new_file = self.path + "/" + "newfile.txt"
        open(new_file, 'w').close()
        icon_widget = IconWidget(self,
                                 name="newfile.txt",
                                 path=self.path,
                                 dir=False)
        icon_widget.new_window.connect(self.new_window_signal.emit)
        icon_widget.show()
        self.icons.append(icon_widget)

    def create_drawer(self):
        print("creating new drawer")
        new_drawer = self.path + "/" + "NewDrawer"
        os.makedirs(new_drawer)
        icon_widget = IconWidget(self,
                                 name="NewDrawer",
                                 path=self.path,
                                 dir=True)
        icon_widget.new_window.connect(self.new_window_signal.emit)
        icon_widget.show()
        self.icons.append(icon_widget)

    def rename_file(self):
        print("renaming file")

    def clean_up(self):
        for item in self.icons:
            item.move(DragWidget.spacerX, DragWidget.spacerY)
            # initial icon placement
            DragWidget.spacerX += 100
            if DragWidget.spacerX + 100 > self.window().width():
                DragWidget.spacerY += 75
                DragWidget.spacerX = 16
        # reset placement values
        DragWidget.spacerX = 16
        DragWidget.spacerY = 16
        self.updateScrollArea()

    def move_data(self, source, dest):
        srce_path = source.rsplit('/', 1)[0]
        dest_path = dest.rsplit('/', 1)[0]
        if srce_path != dest_path:
            try:
                shutil.move(source, dest)
            except Exception as err:
                print(err)

    def copy_icon(self, source, dest):
        pass

    def delete_icon(self):
        dest = os.path.expanduser("~") + "/.Trash/"
        error_string = ""
        for item in self.icons:
            if item.icon.selected:
                source = item.path + "/" + item.name
                if source is not "":
                    try:
                        shutil.move(source, dest)
                    except Exception as err:
                        error_string += str(err) + "\n" + "\n"
                    else:
                        self.icons.remove(item)
                        item.deleteLater()
        if error_string is not "":
            QMessageBox.information(self, 'Info', error_string, QMessageBox.Ok)

    def paste_icon(self):
        print("---")
        print("srce=", self.clipicon.path + "/" + self.clipicon.name)
        # print("res=", self.clipicon.path + "/" + self.clipicon.name)
        print("dest=", self.path + "/")

        # if os.path.isdir(os.path.join(self.clipicon.path, self.clipicon.name)):
        SRCE = self.clipicon.path + "/" + self.clipicon.name
        DEST = self.path + "/" + self.clipicon.name
        shutil.copytree(SRCE, DEST)

    def on_clipboard(self, icon):
        print("realpath", self.path)
        print("clip_icon_name=", icon.name)
        DragWidget.clipicon = icon
Example #9
0
class QTrappingPattern(pg.ScatterPlotItem):
    """Interface between QJansenScreen GUI and CGH pipeline.
    Implements logic for manipulating traps.
    """

    trapAdded = pyqtSignal(QTrap)
    sigCompute = pyqtSignal(object)

    def __init__(self, parent=None, *args, **kwargs):
        super(QTrappingPattern, self).__init__(*args, **kwargs)
        self.setParent(parent)  # this is not set by ScatterPlotItem
        self.setPxMode(False)  # scale plot symbols with window
        # Rubberband selection
        self.selection = QRubberBand(QRubberBand.Rectangle, self.parent())
        self.origin = QPoint()
        # traps, selected trap and active group
        self.traps = QTrapGroup(self)
        self.trap = None
        self.group = None
        self._prev = None
        self.selected = []
        self._appearanceOutdated = False
        self._hologramOutdated = False

    @property
    def prev(self):
        return self._prev

    @prev.setter
    def prev(self, prev):
        if self._prev is not None: self._prev.state = states.normal
        self._prev = prev
        if self.prev is not None: prev.state = states.special

    @pyqtSlot()
    def toggleAppearance(self):
        logger.debug('toggleAppearance')
        self._appearanceOutdated = True

    @pyqtSlot()
    def toggleHologram(self):
        logger.debug('toggleHologram')
        self._hologramOutdated = True

    @pyqtSlot(object)
    def refresh(self, frame):
        self.refreshAppearance()
        self.refreshHologram()

    @pyqtSlot()
    def refreshAppearance(self):
        """Provide a list of spots to screen for plotting.

        This will be called by children when their properties change.
        Changes can be triggered by mouse events, by interaction with
        property widgets, or by direct programmatic control of traps
        or groups.
        """
        if self._appearanceOutdated:
            traps = self.traps.flatten()
            spots = [trap.spot for trap in traps]
            self.setData(spots=spots)
            self._appearanceOutdated = False
            logger.debug('refreshAppearance')

    @pyqtSlot()
    def refreshHologram(self):
        if self._hologramOutdated:
            traps = self.traps.flatten()
            self.sigCompute.emit(traps)
            self._hologramOutdated = False
            logger.debug('refreshHologram')

    def selectedPoint(self, position):
        points = self.pointsAt(position)
        index = self.points().tolist().index(points[0]) if points else None
        return index

    # Selecting traps and groups of traps
    def clickedTrap(self, pos):
        """Return the trap at the specified position
        """
        coords = self.mapFromScene(pos)
        index = self.selectedPoint(coords)
        found = index is not None
        return self.traps.flatten()[index] if found else None

    def groupOf(self, obj):
        """Return the highest-level group containing the specified object.
        """
        if obj is None:
            return None
        while obj.parent() is not self.traps:
            obj = obj.parent()
        return obj

    def clickedGroup(self, pos):
        """Return the highest-level group containing the trap at
        the specified position.
        """
        self.trap = self.clickedTrap(pos)
        return self.groupOf(self.trap)

    def selectedTraps(self, region):
        """Return a list of traps whose groups fall
        entirely within the selection region.
        """
        self.selected = []
        rect = self.mapFromScene(QRectF(region)).boundingRect()
        for child in self.traps.children():
            if child.isWithin(rect):
                self.selected.append(child)
                child.state = states.grouping
            else:
                child.state = states.normal
        self.refreshAppearance()

    # Creating and deleting traps
    def addTrap(self, trap):
        trap.setParent(self)
        self.traps.add(trap)
        trap.appearanceChanged.connect(self.toggleAppearance)
        trap.hologramChanged.connect(self.toggleHologram)
        trap.destroyed.connect(self.toggleAppearance)
        trap.destroyed.connect(self.toggleHologram)
        trap.cgh = self.parent().cgh.device
        self.trapAdded.emit(trap)

    def createTrap(self, r, state=None):
        trap = QTrap(r=r, state=state)
        self.addTrap(trap)
        return trap

    def createTraps(self, coordinates, state=None):
        coords = list(coordinates)
        if not coords:
            return
        group = QTrapGroup()
        self.traps.add(group)
        for r in coords:
            trap = self.createTrap(r, state=state)
            group.add(trap)
        return group

    def clearTrap(self, trap):
        """Remove specified trap from trapping pattern"""
        self.traps.remove(trap, delete=True)

    def clearTraps(self, traps=None):
        """Remove all traps from trapping pattern.
        """
        traps = traps or self.traps.flatten()
        for trap in traps:
            self.clearTrap(trap)

    # Creating, breaking and moving groups of traps
    def createGroup(self):
        """Combine selected objects into new group"""
        group = QTrapGroup()
        for trap in self.selected:
            if trap.parent() is not self:
                trap.parent().remove(trap)
            group.add(trap)
        self.traps.add(group)
        self.selected = []
        return group

    def breakGroup(self):
        """Break group into children and
        place children in the top level.
        """
        if isinstance(self.group, QTrapGroup):
            for child in self.group.children():
                child.state = states.grouping
                self.group.remove(child)
                self.traps.add(child)
            self.group = None

    def moveGroup(self, pos):
        """Move the selected group so that the selected
        trap is at the specified position.
        """
        coords = self.mapFromScene(pos)
        dr = QVector3D(coords - self.trap.coords())
        self.group.moveBy(dr)

    # Dispatch low-level events to actions
    def leftPress(self, pos, modifiers):
        """Selection and grouping.
        """
        self.group = self.clickedGroup(pos)
        # update selection rectangle
        if self.group is None:
            self.origin = QPoint(pos)
            rect = QRect(self.origin, QSize())
            self.selection.setGeometry(rect)
            self.selection.show()
        # break selected group
        elif modifiers == Qt.ControlModifier:
            self.breakGroup()
        # select group
        else:
            self.group.state = states.selected
        self.refreshAppearance()

    def rightPress(self, pos, modifiers):
        """Creation and destruction.
        """
        # Shift-Right Click: Add trap
        if modifiers == Qt.ShiftModifier:
            r = self.mapFromScene(pos)
            self.createTrap(r, state=states.selected)
        # Ctrl-Right Click: Delete trap
        elif modifiers == Qt.ControlModifier:
            self.traps.remove(self.clickedGroup(pos), delete=True)

    # Handlers for signals emitted by QJansenScreen
    @pyqtSlot(QMouseEvent)
    def mousePress(self, event):
        """Event handler for mousePress events.
        """
        button = event.button()
        pos = event.pos()
        modifiers = event.modifiers()
        self.prev = None
        if button == Qt.LeftButton:
            self.leftPress(pos, modifiers)
        elif button == Qt.RightButton:
            self.rightPress(pos, modifiers)

    @pyqtSlot(QMouseEvent)
    def mouseMove(self, event):
        """Event handler for mouseMove events.
        """
        pos = event.pos()
        # Move traps
        if self.group is not None:
            self.moveGroup(pos)
        # Update selection box
        elif self.selection.isVisible():
            region = QRect(self.origin, QPoint(pos)).normalized()
            self.selection.setGeometry(region)
            self.selectedTraps(region)

    @pyqtSlot(QMouseEvent)
    def mouseRelease(self, event):
        """Event handler for mouseRelease events.
        """
        if self.selected:
            self.createGroup()
        for child in self.traps.children():
            child.state = states.normal
        self.prev = self.group
        self.group = None
        self.selection.hide()
        self.refreshAppearance()

    @pyqtSlot(QWheelEvent)
    def mouseWheel(self, event):
        """Event handler for mouse wheel events.
        """
        pos = event.pos()
        group = self.clickedGroup(pos)
        if group is not None:
            group.state = states.selected
            dz = event.angleDelta().y() / 120.
            group.moveBy(QVector3D(0, 0, dz))
            # group.state = states.normal
        self.group = None
Example #10
0
class ViewerWidget(QAbstractScrollArea):
    """
    The main ViewerWidget class. Should be embeddable in
    other applications. See the open() function for loading
    images.
    """
    # signals
    geolinkMove = pyqtSignal(GeolinkInfo, name='geolinkMove')
    geolinkQueryPoint = pyqtSignal(GeolinkInfo, name='geolinkQueryPoint')
    # can't use ViewerWidget - use base class instead
    layerAdded = pyqtSignal(QAbstractScrollArea, name='layerAdded')
    showStatusMessage = pyqtSignal('QString', name='showStatusMessage')
    activeToolChanged = pyqtSignal(ActiveToolChangedInfo,
                                   name='activeToolChanged')
    polygonCollected = pyqtSignal(PolygonToolInfo, name='polygonCollected')
    polylineCollected = pyqtSignal(PolylineToolInfo, name='polylineCollected')
    vectorLocationSelected = pyqtSignal(list,
                                        viewerlayers.ViewerVectorLayer,
                                        name='vectorLocationSelected')
    locationSelected = pyqtSignal(QueryInfo, name='locationSelected')

    def __init__(self, parent):
        QAbstractScrollArea.__init__(self, parent)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn)

        # tracking works awfully badly under X
        # turn off until we work out a workaround
        self.verticalScrollBar().setTracking(False)
        self.horizontalScrollBar().setTracking(False)

        self.layers = viewerlayers.LayerManager()

        self.paintPoint = QPoint()  # normally 0,0 unless we are panning

        # when moving the scroll bars
        # events get fired that we wish to ignore
        self.suppressscrollevent = False

        # set the background color to black so window
        # is black when nothing loaded and when panning
        # new areas are initially black.
        self.setBackgroundColor(Qt.black)

        # to do with tools
        self.rubberBand = None
        self.panCursor = None
        self.panGrabCursor = None
        self.zoomInCursor = None
        self.zoomOutCursor = None
        self.queryCursor = None
        self.vectorQueryCursor = None
        self.polygonCursor = None
        self.activeTool = VIEWER_TOOL_NONE
        self.panOrigin = None
        self.toolPoints = None  # for line and polygon tools - list of points
        self.toolPointsFinished = True  # True if we finished collecting
        # with line and poly tools
        self.toolPen = QPen()  # for drawing the toolPoints
        self.toolPen.setWidth(1)
        self.toolPen.setColor(Qt.yellow)
        self.toolPen.setDashPattern([5, 5, 5, 5])

        # Define the scroll wheel behaviour
        self.mouseWheelZoom = True
        # do we follow extent when geolinking?
        self.geolinkFollowExtent = True
        # to we query all layers or only displayed?
        self.queryOnlyDisplayed = False

    def updateScrollBars(self):
        """
        Update the scroll bars to accurately show where
        we are relative to the full extent
        """
        fullextent = self.layers.getFullExtent()
        setbars = False
        self.suppressscrollevent = True
        if fullextent is not None:
            (fullleft, fulltop, fullright, fullbottom) = fullextent
            layer = self.layers.getTopLayer()
            if layer is not None:
                (left, top, right, bottom) = layer.coordmgr.getWorldExtent()
                (wldX, wldY) = layer.coordmgr.getWorldCenter()
                verticalBar = self.verticalScrollBar()
                horizontalBar = self.horizontalScrollBar()
                # always set range to 0 - 1000 and calculate
                # everything as fraction of that
                verticalBar.setRange(0, 1000)
                horizontalBar.setRange(0, 1000)

                # to pagestep which is also the slider size
                fullxsize = float(fullright - fullleft)
                if fullxsize == 0:
                    fullxsize = 100
                hpagestep = (float(right - left) / fullxsize) * 1000
                horizontalBar.setPageStep(int(hpagestep))
                fullysize = float(fulltop - fullbottom)
                if fullysize == 0:
                    fullysize = 100
                vpagestep = (float(top - bottom) / fullysize) * 1000
                verticalBar.setPageStep(int(vpagestep))

                # position of the slider relative to the center of the image
                hpos = (float(wldX - fullleft) / fullxsize) * 1000
                horizontalBar.setSliderPosition(int(hpos))
                vpos = (float(fulltop - wldY) / fullysize) * 1000
                verticalBar.setSliderPosition(int(vpos))
                setbars = True
        if not setbars:
            # something went wrong - disable
            self.horizontalScrollBar().setRange(0, 0)
            self.verticalScrollBar().setRange(0, 0)
        self.suppressscrollevent = False

    def addRasterLayer(self,
                       gdalDataset,
                       stretch,
                       lut=None,
                       ignoreProjectionMismatch=False,
                       quiet=False):
        """
        Add the given dataset to the stack of images being displayed
        as a raster layer
        """
        size = self.viewport().size()
        self.layers.addRasterLayer(gdalDataset, size.width(), size.height(),
                                   stretch, lut, ignoreProjectionMismatch,
                                   quiet)
        # get rid off tool points
        self.toolPoints = None
        self.toolPointsFinished = True

        self.viewport().update()
        self.updateScrollBars()

        self.layerAdded.emit(self)

    def addVectorLayer(self,
                       ogrDataSource,
                       ogrLayer,
                       color=None,
                       resultSet=False,
                       origSQL=None,
                       quiet=False):
        """
        Add the vector given by the ogrDataSource and its dependent 
        ogrLayer to the stack of images.
        """
        size = self.viewport().size()
        if color is None:
            color = viewerlayers.DEFAULT_VECTOR_COLOR

        self.layers.addVectorLayer(ogrDataSource, ogrLayer, size.width(),
                                   size.height(), color, resultSet, origSQL,
                                   quiet)
        self.viewport().update()
        self.updateScrollBars()

        self.layerAdded.emit(self)

    def addVectorFeatureLayer(self,
                              ogrDataSource,
                              ogrLayer,
                              ogrFeature,
                              color=None,
                              quiet=None):
        """
        Just a single feature vector
        """
        size = self.viewport().size()
        if color is None:
            color = viewerlayers.DEFAULT_VECTOR_COLOR

        self.layers.addVectorFeatureLayer(ogrDataSource, ogrLayer, ogrFeature,
                                          size.width(), size.height(), color,
                                          quiet)
        self.viewport().update()
        self.updateScrollBars()

        self.layerAdded.emit(self)

    def addLayersFromJSONFile(self, fileobj, nlayers):
        """
        Get the layer manager to read all the layer descriptions from fileobj
        and load these layers into this widget.
        """
        size = self.viewport().size()
        self.layers.fromFile(fileobj, nlayers, size.width(), size.height())

        self.viewport().update()
        self.updateScrollBars()

        self.layerAdded.emit(self)

    def removeLayer(self):
        """
        Removes the top later
        """
        self.layers.removeTopLayer()
        # get rid off tool points
        self.toolPoints = None
        self.toolPointsFinished = True
        self.viewport().update()
        self.updateScrollBars()

    # query point functions
    def setQueryPoint(self,
                      senderid,
                      easting,
                      northing,
                      color,
                      size=None,
                      cursor=None):
        """
        Sets/Updates query point keyed on the id() of the sender
        """
        self.layers.queryPointLayer.setQueryPoint(senderid, easting, northing,
                                                  color, size, cursor)
        self.layers.queryPointLayer.getImage()
        self.viewport().update()

    def removeQueryPoint(self, senderid):
        """
        Removes a query point. keyed on the id() of the sender
        """
        self.layers.queryPointLayer.removeQueryPoint(senderid)
        self.layers.queryPointLayer.getImage()
        self.viewport().update()

    def highlightValues(self, color, selectionArray=None):
        """
        Applies a QColor to the LUT where selectionArray == True
        to the top layer and redraws. Pass None to reset
        """
        layer = self.layers.getTopRasterLayer()
        if layer is not None:
            if len(layer.stretch.bands) != 1:
                msg = 'can only highlight values on single band images'
                raise viewererrors.InvalidDataset(msg)
            layer.highlightRows(color, selectionArray)

            # force repaint
            self.viewport().update()

    def setColorTableLookup(self,
                            lookupArray=None,
                            colName=None,
                            surrogateLUT=None,
                            surrogateName=None):
        """
        Uses the supplied lookupArray to look up image
        data before indexing into color table in the top
        layer and redraws. Pass None to reset.
        """
        layer = self.layers.getTopRasterLayer()
        if layer is not None:
            if len(layer.stretch.bands) != 1:
                msg = 'can only highlight values on single band images'
                raise viewererrors.InvalidDataset(msg)
            layer.setColorTableLookup(lookupArray, colName, surrogateLUT,
                                      surrogateName)

            # force repaint
            self.viewport().update()

    def zoomNativeResolution(self):
        """
        Sets the zoom to native resolution wherever
        the current viewport is centered
        """
        self.layers.zoomNativeResolution()
        # force repaint
        self.viewport().update()
        self.updateScrollBars()
        # geolink
        self.emitGeolinkMoved()

    def zoomFullExtent(self):
        """
        Resets the zoom to full extent - should be
        the same as when file was opened.
        """
        self.layers.zoomFullExtent()
        # force repaint
        self.viewport().update()
        self.updateScrollBars()
        # geolink
        self.emitGeolinkMoved()

    def setActiveTool(self, tool, senderid):
        """
        Set active tool (one of VIEWER_TOOL_*).
        pass VIEWER_TOOL_NONE to disable
        pass the id() of the calling object. This is passed around
        in the activeToolChanged signal so GUI elements can recognise
        who asked for the change
        """
        # if the tool was line or polygon
        # now is the time to remove the outline from the widget
        if (self.activeTool == VIEWER_TOOL_POLYGON
                or self.activeTool == VIEWER_TOOL_POLYLINE):
            self.toolPoints = None
            self.toolPointsFinished = True
            # force repaint
            self.viewport().update()

        self.activeTool = tool
        if tool == VIEWER_TOOL_ZOOMIN:
            if self.zoomInCursor is None:
                # create if needed.
                self.zoomInCursor = QCursor(
                    QPixmap([
                        "16 16 3 1", ". c None", "a c #000000", "# c #ffffff",
                        ".....#####......", "...##aaaaa##....",
                        "..#.a.....a.#...", ".#.a...a...a.#..",
                        ".#a....a....a#..", "#a.....a.....a#.",
                        "#a.....a.....a#.", "#a.aaaa#aaaa.a#.",
                        "#a.....a.....a#.", "#a.....a.....a#.",
                        ".#a....a....a#..", ".#.a...a...aaa#.",
                        "..#.a.....a#aaa#", "...##aaaaa###aa#",
                        ".....#####...###", "..............#."
                    ]))
            self.viewport().setCursor(self.zoomInCursor)

        elif tool == VIEWER_TOOL_ZOOMOUT:
            if self.zoomOutCursor is None:
                # create if needed
                self.zoomOutCursor = QCursor(
                    QPixmap([
                        "16 16 4 1", "b c None", ". c None", "a c #000000",
                        "# c #ffffff", ".....#####......", "...##aaaaa##....",
                        "..#.a.....a.#...", ".#.a.......a.#..",
                        ".#a.........a#..", "#a...........a#.",
                        "#a...........a#.", "#a.aaaa#aaaa.a#.",
                        "#a...........a#.", "#a...........a#.",
                        ".#a.........a#..", ".#.a.......aaa#.",
                        "..#.a.....a#aaa#", "...##aaaaa###aa#",
                        ".....#####...###", "..............#."
                    ]))
            self.viewport().setCursor(self.zoomOutCursor)

        elif tool == VIEWER_TOOL_PAN:
            if self.panCursor is None:
                # both these used for pan operations
                self.panCursor = QCursor(Qt.OpenHandCursor)
                self.panGrabCursor = QCursor(Qt.ClosedHandCursor)
            self.viewport().setCursor(self.panCursor)

        elif tool == VIEWER_TOOL_QUERY:
            if self.queryCursor is None:
                self.queryCursor = QCursor(Qt.CrossCursor)
            self.viewport().setCursor(self.queryCursor)

        elif tool == VIEWER_TOOL_VECTORQUERY:
            if self.vectorQueryCursor is None:
                self.vectorQueryCursor = QCursor(
                    QPixmap([
                        "16 16 3 1", "# c None", "a c #000000", ". c #ffffff",
                        "######aaaa######", "######a..a######",
                        "######a..a######", "######a..a######",
                        "######a..a######", "######aaaa######",
                        "aaaaa######aaaaa", "a...a######a...a",
                        "a...a######a...a", "aaaaa######aaaaa",
                        "######aaaa######", "######a..a###a.a",
                        "######a..a###aaa", "######a..a###a.a",
                        "######a..a###a.a", "######aaaa###aaa"
                    ]))
            self.viewport().setCursor(self.vectorQueryCursor)

        elif tool == VIEWER_TOOL_POLYGON or tool == VIEWER_TOOL_POLYLINE:
            if self.polygonCursor is None:
                self.polygonCursor = QCursor(
                    QPixmap([
                        "16 16 3 1", "      c None", ".     c #000000",
                        "+     c #FFFFFF", "                ",
                        "       +.+      ", "      ++.++     ",
                        "     +.....+    ", "    +.     .+   ",
                        "   +.   .   .+  ", "  +.    .    .+ ",
                        " ++.    .    .++", " ... ...+... ...",
                        " ++.    .    .++", "  +.    .    .+ ",
                        "   +.   .   .+  ", "   ++.     .+   ",
                        "    ++.....+    ", "      ++.++     ",
                        "       +.+      "
                    ]))
            self.viewport().setCursor(self.polygonCursor)
            msg = ('Left click adds a point, middle to remove last,' +
                   ' right click to end')
            self.showStatusMessage.emit(msg)

        elif tool == VIEWER_TOOL_NONE:
            # change back
            self.viewport().setCursor(Qt.ArrowCursor)

        obj = ActiveToolChangedInfo(self.activeTool, senderid)
        self.activeToolChanged.emit(obj)

    def setNewStretch(self, newstretch, layer, local=False):
        """
        Change the stretch being applied to the current data
        """
        layer.setNewStretch(newstretch, local)
        self.viewport().update()

    def timeseriesBackward(self):
        """
        Assume images are a stacked timeseries oldest
        to newest. Turn on the previous one to the current
        topmost displayed
        """
        self.layers.timeseriesBackward()
        self.viewport().update()

    def timeseriesForward(self):
        """
        Assume images are a stacked timeseries oldest
        to newest. Turn off the current topmost displayed
        """
        self.layers.timeseriesForward()
        self.viewport().update()

    def setMouseScrollWheelAction(self, scrollZoom):
        "Set the action for a mouse wheen event (scroll/zoom)"
        self.mouseWheelZoom = scrollZoom

    def setBackgroundColor(self, color):
        "Sets the background color for the widget"
        widget = self.viewport()
        palette = widget.palette()
        palette.setColor(widget.backgroundRole(), color)
        widget.setPalette(palette)

    def setGeolinkFollowExtentAction(self, followExtent):
        "Set whether we are following geolink extent of just center"
        self.geolinkFollowExtent = followExtent

    def setQueryOnlyDisplayed(self, queryOnlyDisplayed):
        """
        set whether we are only querying displayed layers (True)
        or all (False)
        """
        self.queryOnlyDisplayed = queryOnlyDisplayed

    def flicker(self):
        """
        Call to change the flicker state (ie draw the top raster image
        or not). 
        """
        state = False
        layer = self.layers.getTopLayer()
        if layer is not None:
            state = not layer.displayed
            self.layers.setDisplayedState(layer, state)
            self.viewport().update()
        return state

    def scrollContentsBy(self, dx, dy):
        """
        Handle the user moving the scroll bars
        """
        if not self.suppressscrollevent:
            layer = self.layers.getTopLayer()
            if layer is not None:
                (left, top, right, bottom) = layer.coordmgr.getWorldExtent()
                hpagestep = float(self.horizontalScrollBar().pageStep())
                xamount = -(float(dx) / hpagestep) * (right - left)
                vpagestep = float(self.verticalScrollBar().pageStep())
                yamount = (float(dy) / vpagestep) * (top - bottom)
                wldX, wldY = layer.coordmgr.getWorldCenter()
                layer.coordmgr.setWorldCenter(wldX + xamount, wldY + yamount)
                # not sure why we need this but get black strips
                # around otherwise
                layer.coordmgr.recalcBottomRight()
                self.layers.makeLayersConsistent(layer)
                self.layers.updateImages()
                self.viewport().update()
                self.updateScrollBars()

                # geolink
                self.emitGeolinkMoved()

    def wheelEvent(self, event):
        """
        User has used mouse wheel to zoom in/out or pan depending on defined preference
        """
        layer = self.layers.getTopRasterLayer()
        if layer is not None:
            delta = event.angleDelta().y()

            # Shift scrolling will move you forward and backwards through the time series
            if QApplication.keyboardModifiers() == Qt.ShiftModifier:
                if delta > 0:
                    self.timeseriesBackward()
                elif delta < 0:
                    self.timeseriesForward()

            elif self.mouseWheelZoom:
                (wldX, wldY) = layer.coordmgr.getWorldCenter()

                impixperwinpix = layer.coordmgr.imgPixPerWinPix
                if delta > 0:
                    impixperwinpix *= 1.0 - VIEWER_ZOOM_WHEEL_FRACTION
                elif delta < 0:
                    impixperwinpix *= 1.0 + VIEWER_ZOOM_WHEEL_FRACTION
                layer.coordmgr.setZoomFactor(impixperwinpix)
                layer.coordmgr.setWorldCenter(wldX, wldY)
                # not sure why we need this but get black strips
                # around otherwise
                layer.coordmgr.recalcBottomRight()
                self.layers.makeLayersConsistent(layer)
                self.layers.updateImages()
                self.updateScrollBars()
                self.viewport().update()
            else:
                dx = event.angleDelta().x()
                dy = delta
                self.scrollContentsBy(dx, dy)

            # geolink
            self.emitGeolinkMoved()

    def resizeEvent(self, event):
        """
        Window has been resized - get new data
        """
        size = event.size()
        self.layers.setDisplaySize(size.width(), size.height())
        self.updateScrollBars()

    def paintEvent(self, event):
        """
        Viewport needs to be redrawn. Assume that
        each layer's image is current (as created by getImage())
        we can just draw it with QPainter
        """
        paint = QPainter(self.viewport())

        for layer in self.layers.layers:
            if layer.displayed:
                paint.drawImage(self.paintPoint, layer.image)

        # draw any query points on top of image
        paint.drawImage(self.paintPoint, self.layers.queryPointLayer.image)

        # now any tool points
        if self.toolPoints is not None:
            path = QPainterPath()
            firstpt = self.toolPoints[0]
            path.moveTo(firstpt.x(), firstpt.y())
            for pt in self.toolPoints[1:]:
                path.lineTo(pt.x(), pt.y())
            paint.setPen(self.toolPen)
            paint.drawPath(path)

        paint.end()

    def mousePressEvent(self, event):
        """
        Mouse has been clicked down if we are in zoom/pan
        mode we need to start doing stuff here
        """
        QAbstractScrollArea.mousePressEvent(self, event)
        pos = event.pos()

        if (self.activeTool == VIEWER_TOOL_ZOOMIN
                or self.activeTool == VIEWER_TOOL_ZOOMOUT):
            if self.rubberBand is None:
                self.rubberBand = QRubberBand(QRubberBand.Rectangle, self)
            self.rubberBand.setGeometry(QRect(pos, QSize()))
            self.rubberBand.show()
            self.rubberBand.origin = pos

        elif self.activeTool == VIEWER_TOOL_PAN:
            # remember pos
            self.panOrigin = pos
            # change cursor
            self.viewport().setCursor(self.panGrabCursor)

        elif self.activeTool == VIEWER_TOOL_QUERY:

            modifiers = event.modifiers()
            (dspX, dspY) = (pos.x(), pos.y())
            self.newQueryPoint(dspX=dspX, dspY=dspY, modifiers=modifiers)

        elif self.activeTool == VIEWER_TOOL_VECTORQUERY:

            modifiers = event.modifiers()
            (dspX, dspY) = (pos.x(), pos.y())
            self.newVectorQueryPoint(dspX, dspY, modifiers=modifiers)

        elif self.activeTool == VIEWER_TOOL_POLYGON:
            button = event.button()
            if button == Qt.LeftButton:
                # adding points
                if self.toolPoints is None or self.toolPointsFinished:
                    # first point - starts and ends at same pos
                    self.toolPoints = [pos, pos]
                    self.toolPointsFinished = False
                else:
                    # last point same as first - insert before last
                    self.toolPoints.insert(-1, pos)

            elif button == Qt.MiddleButton and self.toolPoints is not None:
                # delete last point
                if len(self.toolPoints) > 2:
                    del self.toolPoints[-2]

            elif button == Qt.RightButton and self.toolPoints is not None:
                # finished
                # create object for signal
                layer = self.layers.getTopRasterLayer()
                modifiers = event.modifiers()
                obj = PolygonToolInfo(self.toolPoints, layer, modifiers)
                self.polygonCollected.emit(obj)

                self.toolPointsFinished = True  # done, but still display

            # redraw so paint() gets called
            self.viewport().update()

        elif self.activeTool == VIEWER_TOOL_POLYLINE:
            button = event.button()
            if button == Qt.LeftButton:
                # adding points
                if self.toolPoints is None or self.toolPointsFinished:
                    # first point
                    self.toolPoints = [pos]
                    self.toolPointsFinished = False
                else:
                    # add to list
                    self.toolPoints.append(pos)

            elif button == Qt.MiddleButton and self.toolPoints is not None:
                # delete last point
                if len(self.toolPoints) > 1:
                    self.toolPoints.pop()

            elif button == Qt.RightButton and self.toolPoints is not None:
                # finished
                # create object for signal
                if self.queryOnlyDisplayed:
                    layer = self.layers.getTopDisplayedRasterLayer()
                else:
                    layer = self.layers.getTopRasterLayer()
                modifiers = event.modifiers()
                obj = PolylineToolInfo(self.toolPoints, layer, modifiers)
                self.polylineCollected.emit(obj)

                self.toolPointsFinished = True  # done, but still display

            # redraw so paint() gets called
            self.viewport().update()

    def mouseReleaseEvent(self, event):
        """
        Mouse has been released, if we are in zoom/pan
        mode we do stuff here.
        """
        QAbstractScrollArea.mouseReleaseEvent(self, event)
        if self.rubberBand is not None and self.rubberBand.isVisible():
            # get the information about the rect they have drawn
            # note this is on self, rather than viewport()
            selection = self.rubberBand.geometry()
            geom = self.viewport().geometry()

            selectionsize = float(selection.width() * selection.height())

            geomsize = float(geom.width() * geom.height())

            self.rubberBand.hide()

            layer = self.layers.getTopRasterLayer()
            if layer is not None:
                if selectionsize < MIN_SELECTION_SIZE_PX:
                    # this is practically a '0' size selection on a 4K screen and
                    # an improbably small selection on an HD screen so assume user
                    # has just clicked the image and set fraction to 0.5
                    fraction = 0.5
                else:
                    fraction = numpy.sqrt(selectionsize / geomsize)

                if self.activeTool == VIEWER_TOOL_ZOOMIN:
                    if selectionsize < MIN_SELECTION_SIZE_PX:
                        # user 'just clicked' (see if statement above).
                        # NOTE: this fixes issues with 0 or negative dimensions
                        #  inside else: below that used ot hard-crash tuiview

                        wldX, wldY = layer.coordmgr.display2world(
                            selection.left(), selection.top())
                        layer.coordmgr.setZoomFactor(
                            layer.coordmgr.imgPixPerWinPix * fraction)
                        layer.coordmgr.setWorldCenter(wldX, wldY)
                        # not sure why we need this but get black strips
                        # around otherwise
                        layer.coordmgr.recalcBottomRight()
                    else:
                        # I don't think anything needs to be added here
                        dspTop = selection.top()
                        dspLeft = selection.left()
                        dspBottom = selection.bottom()
                        dspRight = selection.right()
                        (rastLeft, rastTop) = layer.coordmgr.display2pixel(
                            dspLeft, dspTop)
                        (rastRight, rastBottom) = layer.coordmgr.display2pixel(
                            dspRight, dspBottom)
                        #print layer.coordmgr
                        layer.coordmgr.setTopLeftPixel(rastLeft, rastTop)
                        layer.coordmgr.calcZoomFactor(rastRight, rastBottom)
                        # not sure why we need this but get black strips
                        # around otherwise
                        layer.coordmgr.recalcBottomRight()
                        #print layer.coordmgr

                elif self.activeTool == VIEWER_TOOL_ZOOMOUT:
                    # the smaller the area the larger the zoom
                    center = selection.center()
                    wldX, wldY = layer.coordmgr.display2world(
                        center.x(), center.y())
                    layer.coordmgr.setZoomFactor(
                        layer.coordmgr.imgPixPerWinPix / fraction)
                    layer.coordmgr.setWorldCenter(wldX, wldY)
                    # not sure why we need this but get black strips
                    # around otherwise
                    layer.coordmgr.recalcBottomRight()

                # redraw
                self.layers.makeLayersConsistent(layer)
                self.layers.updateImages()
                self.viewport().update()
                self.updateScrollBars()

                # geolink
                self.emitGeolinkMoved()

        elif self.activeTool == VIEWER_TOOL_PAN:
            # change cursor back
            self.viewport().setCursor(self.panCursor)
            layer = self.layers.getTopRasterLayer()
            if layer is not None:
                # stop panning and move viewport
                dspXmove = -self.paintPoint.x()
                dspYmove = -self.paintPoint.y()
                (pixNewX,
                 pixNewY) = layer.coordmgr.display2pixel(dspXmove, dspYmove)
                #print 'panning'
                #print layer.coordmgr
                layer.coordmgr.setTopLeftPixel(pixNewX, pixNewY)
                layer.coordmgr.recalcBottomRight()
                #print layer.coordmgr
                # reset
                self.paintPoint.setX(0)
                self.paintPoint.setY(0)
                # redraw
                self.layers.makeLayersConsistent(layer)
                self.layers.updateImages()
                self.viewport().update()
                self.updateScrollBars()
                # geolink
                self.emitGeolinkMoved()

    def mouseMoveEvent(self, event):
        """
        Mouse has been moved while dragging. If in zoom/pan
        mode we need to do something here.
        """
        QAbstractScrollArea.mouseMoveEvent(self, event)
        if self.rubberBand is not None and self.rubberBand.isVisible():
            # must be doing zoom in/out. extend rect
            rect = QRect(self.rubberBand.origin, event.pos()).normalized()
            self.rubberBand.setGeometry(rect)

        elif self.activeTool == VIEWER_TOOL_PAN:
            # panning. Work out the offset from where we
            # starting panning and draw the current image
            # at an offset
            pos = event.pos()
            xamount = pos.x() - self.panOrigin.x()
            yamount = pos.y() - self.panOrigin.y()
            self.paintPoint.setX(xamount)
            self.paintPoint.setY(yamount)
            # force repaint - self.paintPoint used by paintEvent()
            self.viewport().update()
            self.updateScrollBars()

    # query point routines
    def newQueryPoint(self,
                      easting=None,
                      northing=None,
                      dspY=None,
                      dspX=None,
                      column=None,
                      row=None,
                      modifiers=None):
        """
        This viewer has recorded a new query point. Or
        user has entered new coords in querywindow.

        Calls updateQueryPoint and emits the geolinkQueryPoint signal

        pass either [easting and northing] or [dspX,dspY] or [column, row]
        """
        if self.queryOnlyDisplayed:
            layer = self.layers.getTopDisplayedRasterLayer()
        else:
            layer = self.layers.getTopRasterLayer()
        if layer is None:
            return

        if ((easting is None or northing is None)
                and (dspX is None or dspY is None)
                and (column is None or row is None)):
            msg = ("must provide one of [easting,northing] or [dspX,dspY] " +
                   "or [column, row]")
            raise ValueError(msg)

        if dspX is not None and dspY is not None:
            (column, row) = layer.coordmgr.display2pixel(dspX, dspY)
            (easting, northing) = layer.coordmgr.pixel2world(column, row)
        elif easting is not None and northing is not None:
            (column, row) = layer.coordmgr.world2pixel(easting, northing)
        elif column is not None and row is not None:
            (easting, northing) = layer.coordmgr.pixel2world(column, row)

        # update the point
        self.updateQueryPoint(easting, northing, column, row, modifiers)

        # emit the geolinked query point signal
        obj = GeolinkInfo(id(self), easting, northing)
        self.geolinkQueryPoint.emit(obj)

    def newVectorQueryPoint(self, dspX, dspY, modifiers=None):
        """
        New vector query point. Does the spatial query
        and emits the vectorLocationSelected signal with
        the results
        """
        if self.queryOnlyDisplayed:
            layer = self.layers.getTopDisplayedVectorLayer()
        else:
            layer = self.layers.getTopVectorLayer()
        if layer is None:
            return

        (easting, northing) = layer.coordmgr.display2world(dspX, dspY)
        tolerance = layer.coordmgr.metersperpix * 3  # maybe should be a pref?

        # show hourglass while query running
        oldCursor = self.cursor()
        self.setCursor(Qt.WaitCursor)

        results = layer.getAttributesAtPoint(easting, northing, tolerance)

        self.setCursor(oldCursor)

        self.vectorLocationSelected.emit(results, layer)

    def updateQueryPoint(self, easting, northing, column, row, modifiers):
        """
        Map has been clicked, get the value and emit
        a locationSelected signal.
        Called by newQueryPoint or when a geolinkQueryPoint signal
        has been received.
        """
        # read the data out of the dataset
        if self.queryOnlyDisplayed:
            layer = self.layers.getTopDisplayedRasterLayer()
        else:
            layer = self.layers.getTopRasterLayer()
        if (layer is not None and column >= 0
                and column < layer.gdalDataset.RasterXSize and row >= 0
                and row < layer.gdalDataset.RasterYSize):
            data = layer.gdalDataset.ReadAsArray(int(column), int(row), 1, 1)
            if data is not None:
                # we just want the single 'drill down' of data as a 1d array
                data = data[..., 0, 0]
                # if single band GDAL gives us a single value -
                # convert back to array
                # to make life easier
                if data.size == 1:
                    data = numpy.array([data])

                qi = QueryInfo(easting, northing, column, row, data, layer,
                               modifiers)
                # emit the signal - handled by the QueryDockWidget
                self.locationSelected.emit(qi)

    def doGeolinkQueryPoint(self, easting, northing):
        """
        Call this when the widget query point has been moved
        in another viewer and should be updated in this
        one if the query tool is active.
        """
        if self.activeTool == VIEWER_TOOL_QUERY:
            if self.queryOnlyDisplayed:
                layer = self.layers.getTopDisplayedRasterLayer()
            else:
                layer = self.layers.getTopRasterLayer()
            if layer is not None:
                (col, row) = layer.coordmgr.world2pixel(easting, northing)
                self.updateQueryPoint(easting, northing, col, row, None)

    # geolinking routines
    def doGeolinkMove(self, easting, northing, metresperwinpix):
        """
        Call this when widget needs to be moved because
        of geolinking event.
        """
        layer = self.layers.getTopRasterLayer()
        if layer is not None:
            if self.geolinkFollowExtent and metresperwinpix != 0:
                imgpixperwinpix = metresperwinpix / layer.coordmgr.geotransform[
                    1]
                layer.coordmgr.setZoomFactor(imgpixperwinpix)

            layer.coordmgr.setWorldCenter(easting, northing)
            self.layers.makeLayersConsistent(layer)
            self.layers.updateImages()
            self.updateScrollBars()
            self.viewport().update()

    def getGeolinkInfo(self):
        """
        Called by emitGeolinkMoved and anything else that needs the
        current GeolinkInfo
        """
        info = None
        # get the coords of the current centre
        layer = self.layers.getTopRasterLayer()
        if layer is not None:
            easting, northing = layer.coordmgr.getWorldCenter()
            metresperwinpix = (layer.coordmgr.imgPixPerWinPix *
                               layer.coordmgr.geotransform[1])
            info = GeolinkInfo(id(self), easting, northing, metresperwinpix)
        return info

    def emitGeolinkMoved(self):
        """
        Call this on each zoom/pan to emit the appropriate signal.
        """
        info = self.getGeolinkInfo()
        if info is not None:
            # emit the signal
            self.geolinkMove.emit(info)
Example #11
0
        class RubberbandEnhancedLabel(QLabel):

            def __init__(self, parent=None):
                self._parent_class = _parent_class
                QLabel.__init__(self, parent)
                self.selection = QRubberBand(QRubberBand.Rectangle, self)

            def mousePressEvent(self, event):
                '''
                    Mouse is pressed. If selection is visible either set dragging mode (if close to border) or hide selection.
                    If selection is not visible make it visible and start at this point.
                '''
                #
                if event.button() == Qt.LeftButton:

                    position = QPoint(event.pos())
                    if self.selection.isVisible():
                        # visible selection
                        if (self.upper_left - position).manhattanLength() < 20:
                            # close to upper left corner, drag it
                            self.mode = "drag_upper_left"
                        elif (self.lower_right - position).manhattanLength() < 20:
                            # close to lower right corner, drag it
                            self.mode = "drag_lower_right"
                        else:
                            # clicked somewhere else, hide selection
                            self.selection.hide()
                    else:
                        # no visible selection, start new selection
                        self.upper_left = position
                        self.lower_right = position
                        self.mode = "drag_lower_right"
                        self.selection.show()


            def mouseMoveEvent(self, event):
                '''
                    Mouse moved. If selection is visible, drag it according to drag mode.
                '''
                if self.selection.isVisible():
                    # visible selection
                    if self.mode == "drag_lower_right":
                        self.lower_right = QPoint(event.pos())
                    elif self.mode == "drag_upper_left":
                        self.upper_left = QPoint(event.pos())
                    # update geometry
                    self.selection.setGeometry(QRect(self.upper_left, self.lower_right).normalized())

            def mouseReleaseEvent(self, event):

                if self.selection.isVisible():
                    currentQRect = self.selection.geometry()
                    cropQPixmap = self.pixmap().copy(currentQRect)
                    cropQPixmap.save('output.png')

                    image = QImage("output.png")
                    if image.isNull():
                        QMessageBox.information(self.centralwidget, "Image Viewer", "Cannot load %s." % self.fileName)
                        return

                    pm = QPixmap.fromImage(image)
                    h = pm.height()
                    w = pm.width()

                    if (h > w):
                        self._parent_class.originalImageLabel.setPixmap(pm.scaledToHeight(400))

                    else:
                        self._parent_class.originalImageLabel.setPixmap(pm.scaledToWidth(400))



                    self.selection.hide()
Example #12
0
class GUI(QMainWindow):
    '''
        Main GUI class
    '''
    def __init__(self):

        '''
            Initializes most basic object and sets default values for parameters
        '''
        super().__init__()
        self.initUI()

        #path to pdf
        self.path = None
        #masks for flat elimination algorithm
        self.conditionLower = np.array([255, 255, 255])
        self.conditionUpper = np.array([100, 100, 100])
        #batch size
        self.batchSize = 5
        #pages to work on -> unfinished so set to always work on full file
        self.pages = [0]
        #color to use when replacing pixels
        self.color = np.array([255, 255, 255])
        #default output name
        self.outName = "temporary"
        #not existing bounding box
        self.boundingBox = [0]

        self.DEBUG = True
        
    def initUI(self):               
        '''
            UI initialization
        '''
        #set size and center
        self.setFixedSize(370, 350)
        self.center()
        
        #create all butons for menu and assign them functions
        self.btn1 = QPushButton('Load PDF', self)
        self.btn1.clicked.connect(self.getFilePath)
        self.btn1.setToolTip('Choose pdf file to work with')
        self.btn1.resize(100, 50)
        self.btn1.move(25, 25) 

        self.btn2 = QPushButton('Set Config', self)
        self.btn2.clicked.connect(self.initConfigForm)
        self.btn2.setToolTip('Configure settings')
        self.btn2.resize(100, 50)
        self.btn2.move(25, 80) 
        
        self.btn3 = QPushButton('Create\nBounding Box', self)
        self.btn3.clicked.connect(self.createBoundingBox)
        self.btn3.setToolTip('Create box limiting area of change')
        self.btn3.resize(100, 50)
        self.btn3.move(135, 25) 

        self.btn4 = QPushButton('Generate Average', self)
        self.btn4.clicked.connect(self.getAverageEstimateWrapper)
        self.btn4.setToolTip('Estimate watermark by averaging over pages')
        self.btn4.resize(100, 50)
        self.btn4.move(135, 80) 

        self.btn5 = QPushButton('Flat Elimination', self)
        self.btn5.clicked.connect(self.convertFlatWrapper)
        self.btn5.setToolTip('Replace all RGB values between set values and replace them with color')
        self.btn5.resize(100, 50)
        self.btn5.move(245, 25) 

        self.btn6 = QPushButton('Average\nElimination', self)
        self.btn6.clicked.connect(self.convertAverageWrapper)
        self.btn6.setToolTip('Replace all RGB values that are similar enough to averaged sample')
        self.btn6.resize(100, 50)
        self.btn6.move(245, 80) 

        #hide certain buttons untill a pdf is choosen
        self.btn3.hide()
        self.btn4.hide()
        self.btn5.hide()
        self.btn6.hide()

        #set name, logo, etc. for progress bar
        self.bar = QWidget()
        self.bar.setWindowIcon(QIcon('graphics//logo.png'))
        self.bar.setWindowTitle('Progress bar')
        self.progress = QProgressBar(self.bar)
        self.bar.move(QDesktopWidget().availableGeometry().center() - QPoint(150, 15))
        self.progress.setGeometry(0, 0, 300, 30)

        #slector for bounding box
        self.selector = QWidget()
        self.pic = QLabel(self.selector)
        
        #assign events to the correct window
        self.selector.mousePressEvent = lambda event : self.MPE(event)
        self.selector.mouseMoveEvent  = lambda event : self.MME(event)
        self.selector.mouseReleaseEvent = lambda event : self.MRE(event)
        
        #set title and logo
        self.selector.setWindowTitle('Select Bounding Box')
        self.selector.setWindowIcon(QIcon('graphics//logo.png'))

        #create rubber band for selector
        self.selection = QRubberBand(QRubberBand.Rectangle, self.pic)
        
        #set project logo in the menu
        logo = QLabel(self)
        logo.resize(200, 200)
        logo.setPixmap(QPixmap("graphics//logo.png"))
        logo.move(85, 130)

        #set title and logo for main windows and finish initialization
        self.setWindowIcon(QIcon('graphics//logo.png'))
        self.setWindowTitle('PDF Purifico')    
        self.show()

        return
        

    def pageForm(self):
        '''
            Unfinished form for retrieving arbitrary start and finish pages
        '''
        #setup widget
        self.pageForm = QWidget()
        self.pageForm.resize(600, 100)

        #set label
        label = QLabel(self.pageForm)
        label.setText("Set first and last page")
        label.move(15, 15)

        #set input fields
        self.firstP = QLineEdit(self.pageForm)
        self.firstP.move(180, 15)

        self.lastP = QLineEdit(self.pageForm)
        self.lastP.move(330, 15)

        #create send button
        self.formPageButton = QPushButton('Set pages', self.pageForm)
        self.formPageButton.clicked.connect(self.setPages)
        self.formPageButton.move(480, 15)

        self.pageForm.show()
        return


    def setPages(self):
        '''
            validate input and save it
        '''
        
        firstP = int(self.firstP.text())
        lastP = int(self.lastP.text())

        #validate
        if (firstP > 0) and (lastP > 0) and (lastP >= firstP):
            self.pages = [firstP, lastP]

        self.waitForPages = False

        #hide form once done
        self.pageForm.hide()

        return



    def initConfigForm(self):
        '''
            Create form forconfiguration changes
        '''

        #create base widget
        self.form = QWidget()
        self.form.resize(500, 350)

        #Creates labels and input fields for all the data
        label = QLabel(self.form)
        label.setText("R value from RGB (min - max)")
        label.move(15, 15)

        label = QLabel(self.form)
        label.setText("G value from RGB (min - max)")
        label.move(15, 45)

        label = QLabel(self.form)
        label.setText("B value from RGB (min - max)")
        label.move(15, 75)


        self.minR = QLineEdit(self.form)
        self.minR.move(180, 15)
        self.maxR = QLineEdit(self.form)
        self.maxR.move(330, 15)

        self.minG = QLineEdit(self.form)
        self.minG.move(180, 45)
        self.maxG = QLineEdit(self.form)
        self.maxG.move(330, 45)

        self.minB = QLineEdit(self.form)
        self.minB.move(180, 75)
        self.maxB = QLineEdit(self.form)
        self.maxB.move(330, 75)


        label = QLabel(self.form)
        label.setText("R value from RGB to set")
        label.move(15, 105)

        label = QLabel(self.form)
        label.setText("G value from RGB to set")
        label.move(15, 135)

        label = QLabel(self.form)
        label.setText("B value from RGB to set")
        label.move(15, 165)

        self.colorR = QLineEdit(self.form)
        self.colorR.move(180, 105)

        self.colorG = QLineEdit(self.form)
        self.colorG.move(180, 135)

        self.colorB = QLineEdit(self.form)
        self.colorB.move(180, 165)

        label = QLabel(self.form)
        label.setText("Size of batches to read to RAM")
        label.move(15, 195)

        self.batchS = QLineEdit(self.form)
        self.batchS.move(180, 195)

        label = QLabel(self.form)
        label.setText("Name for new file")
        label.move(15, 225)

        self.name = QLineEdit(self.form)
        self.name.move(180, 225)

        #button to send
        self.formButton = QPushButton('Save Config', self.form)
        self.formButton.clicked.connect(self.setConfig)
        self.formButton.move(330, 135)
        self.formButton.resize(135, 50)

        #set name and logo
        self.form.setWindowTitle("Config")
        self.form.setWindowIcon(QIcon('graphics//logo.png'))
        self.form.show()
        return


    def setConfig(self):
        '''
            validate and set data from config form
        '''
        try:
            #retrieve all the data and cast to correct type
            minR = int(self.minR.text())
            minG = int(self.minG.text())
            minB = int(self.minB.text())

            maxR = int(self.maxR.text())
            maxG = int(self.maxG.text())
            maxB = int(self.maxB.text())

            colorR = int(self.colorR.text())
            colorG = int(self.colorG.text())
            colorB = int(self.colorB.text())

            batchS = int(self.batchS.text())

            self.outName = self.name.text()

            #validate and save
            if (0 <= minR <= 255) and (0 <= minG <= 255) and (0 <= minB <= 255):
                self.conditionUpper = np.array([minR, minG, minB])

            if (0 <= maxR <= 255) and (0 <= maxG <= 255) and (0 <= maxB <= 255):
                self.conditionUpper = np.array([maxR, maxG, maxB])

            if (0 <= colorR <= 255) and (0 <= colorG <= 255) and (0 <= colorB <= 255):
                self.conditionUpper = np.array([colorR, colorG, colorB])

            if (batchS > 0):
                self.batchSize = batchS

            self.form.hide()

        except:
            #in case of error
            QMessageBox.question(self, 'Error', "Something broke", QMessageBox.Yes)
            self.form.hide()


        return

    def onCountChanged(self, value):
        '''
            For updating progress bar
        '''
        self.progress.setValue(value)
        return



    def getFilePath(self):
        '''
            Get path to pdf file
        '''
        w = QWidget()
        filename = QFileDialog.getOpenFileName(w, 'Select PDF file')
        self.path = filename[0]

        #since we got a pdf now we can enable the other buttons
        self.btn3.show()
        self.btn4.show()
        self.btn5.show()
        self.btn6.show()
        return

    def convertFlatWrapper(self):
        '''
            Wrapper for convertFlat function
        '''

        #set pages correctly
        if (len(self.pages) == 2):
            pagesToClean = self.pages[1] - self.pages[0] + 1
            pageOffset = self.pages[0] - 1
        elif (len(self.pages) == 1):
            pagesToClean = self.pages[0]
            pageOffset = 0
        else:
            QMessageBox.about(self,"Error", "Pages set incorrectly")
            return

        #prepare update bar send data to thread and start it
        self.bar.show()
        self.calc = External()
        self.calc.setFunction(convertFlat, (self.path, self.conditionLower, self.conditionUpper, self.batchSize, self.outName, pagesToClean, pageOffset, self.color, self.boundingBox))

        self.calc.countChanged.connect(self.onCountChanged)
        self.calc.start()

        return

    def getAverageEstimateWrapper(self):
        '''
            Wrapper for getAverageEstimate
        '''

        #set pages correctly
        if (len(self.pages) == 2):
            pagesToClean = self.pages[1] - self.pages[0] + 1
            pageOffset = self.pages[0] - 1
        elif (len(self.pages) == 1):
            pagesToClean = self.pages[0]
            pageOffset = 0
        else:
            QMessageBox.about(self,"Error", "Pages set incorrectly")
            return

        #prepare update bar send data to thread and start it
        self.bar.show()
        self.calc = External()
        self.calc.setFunction(getAverageEstimate, (self.path, self.batchSize, self.outName, pagesToClean, pageOffset))

        self.calc.countChanged.connect(self.onCountChanged)

        self.calc.start()

        return

    def convertAverageWrapper(self):
        '''
            Wrapper for converAverage
        '''
        if (len(self.pages) == 2):
            pagesToClean = self.pages[1] - self.pages[0] + 1
            pageOffset = self.pages[0] - 1
        elif (len(self.pages) == 1):
            pagesToClean = self.pages[0]
            pageOffset = 0
        else:
            QMessageBox.about(self,"Error", "Pages set incorrectly")


        #slect averaged file touse as filter for pdf
        w = QWidget()
        filename = QFileDialog.getOpenFileName(w, 'Select averaged file to filter pdf')

        #prepare update bar send data to thread and start it
        self.bar.show()
        self.calc = External()
        self.calc.setFunction(convertAverage, (self.path, filename[0], self.batchSize, self.outName, pagesToClean, pageOffset, self.color, self.boundingBox))
        self.calc.countChanged.connect(self.onCountChanged)

        self.calc.start()

        return

    def center(self):
        '''
            method for centering
        '''
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())
        return
        
        
    def closeEvent(self, event):
        '''
            Confirmation when closing software
        '''
        reply = QMessageBox.question(self, 'Message', "Are you sure?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

        return
        
    
        
    def MPE(self, event):
        '''
            Mouse is pressed. If selection is visible either set dragging mode (if close to border) or hide selection.
            If selection is not visible make it visible and start at this point.
        '''

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

            position = QPoint(event.pos())

            if (self.DEBUG):
                print("Start coords:", position.x(), position.y())

            #set coords for later
            self.start_x = position.x()
            self.start_y = position.y()
            
            if self.selection.isVisible():
                # visible selection
                if (self.upper_left - position).manhattanLength() < 20:
                    # close to upper left corner, drag it
                    self.mode = "drag_upper_left"
                elif (self.lower_right - position).manhattanLength() < 20:
                    # close to lower right corner, drag it
                    self.mode = "drag_lower_right"
                else:
                    # clicked somewhere else, hide selection
                    self.selection.hide()
            else:
                # no visible selection, start new selection
                self.upper_left = position
                self.lower_right = position
                self.mode = "drag_lower_right"
                self.selection.show()

        return

    def MME(self, event):
        '''
            Mouse moved. If selection is visible, drag it according to drag mode.
        '''

        if self.selection.isVisible():
            # visible selection
            if self.mode is "drag_lower_right":
                self.lower_right = QPoint(event.pos())
            elif self.mode is "drag_upper_left":
                self.upper_left = QPoint(event.pos())
            # update geometry
            self.selection.setGeometry(QRect(self.upper_left, self.lower_right).normalized())

        return
        
    def MRE(self, event):
        '''
            Mouse is released. Hide selector, selection and save propertly transformed coords 
        '''
        if event.button() == Qt.LeftButton:

            position = QPoint(event.pos())

            if (self.DEBUG):
                print("Stop coords:", position.x(), position.y())
            
            #save final position
            self.stop_x = position.x()
            self.stop_y = position.y()
            
            if self.selection.isVisible():
                self.selection.hide()
                self.selector.hide()
        
            im = convert_from_path(self.path, fmt='jpeg', first_page=1, last_page=1)[0]
            width, height = im.size

            if (self.DEBUG):
                orig = np.array(im)
                color = np.array([100, 100, 200])
                

            pts = np.zeros((2,2))

            #set coordinates for bounding box
            pts[0][0] = int(self.start_x / self.scaled_im_width * width)
            pts[0][1] = int(self.start_y / self.scaled_im_height * height)
            pts[1][0] = int(self.stop_x / self.scaled_im_width * width)
            pts[1][1] = int(self.stop_y / self.scaled_im_height * height)

            self.boundingBox = pts

            if(self.DEBUG):

                drawLines(orig, pts.astype(int), color, 3)
                im = Image.fromarray(orig)
                im.save('temp\\sample.jpeg')
                im.show()

        return     
        
    def createBoundingBox(self):
        '''
            Creates bounding box to be used in one of the enxt algorithms
        '''
        im = convert_from_path(self.path, fmt='jpeg', first_page=1, last_page=1)[0]

        im.save("temp\\temp.jpg")

        #get original sizes
        width, height = im.size
        
        im.close()
        
        
        geo = QDesktopWidget().availableGeometry()
        
        #transform for convinience
        if (geo.height() < height):
            width *=  (geo.height()/height) * 0.9
            height = geo.height() * 0.9

        #save for reversing later
        self.scaled_im_width = int(width)
        self.scaled_im_height = int(height)
            
        
        self.pic.setGeometry(0 , 0, width, height)
        self.selector.setFixedSize(width, height)

        #load picture
        self.pic.setPixmap(QPixmap("temp\\temp.jpg").scaledToHeight(height))

        qr = self.selector.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.selector.move(qr.topLeft())
        
        self.selector.show()

        return