Пример #1
0
    def setupTabs(self):
        """ Setup the various tabs in the AddressWidget. """
        groups = ["ABC", "DEF", "GHI", "JKL", "MNO", "PQR", "STU", "VW", "XYZ"]

        for group in groups:
            proxyModel = QSortFilterProxyModel(self)
            proxyModel.setSourceModel(self.tableModel)
            proxyModel.setDynamicSortFilter(True)

            tableView = QTableView()
            tableView.setModel(proxyModel)
            tableView.setSortingEnabled(True)
            tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
            tableView.horizontalHeader().setStretchLastSection(True)
            tableView.verticalHeader().hide()
            tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)
            tableView.setSelectionMode(QAbstractItemView.SingleSelection)

            # This here be the magic: we use the group name (e.g. "ABC") to
            # build the regex for the QSortFilterProxyModel for the group's
            # tab. The regex will end up looking like "^[ABC].*", only
            # allowing this tab to display items where the name starts with
            # "A", "B", or "C". Notice that we set it to be case-insensitive.
            re = QRegularExpression("^[{}].*".format(group))
            assert re.isValid()
            re.setPatternOptions(QRegularExpression.CaseInsensitiveOption)
            proxyModel.setFilterRegularExpression(re)
            proxyModel.setFilterKeyColumn(0) # Filter on the "name" column
            proxyModel.sort(0, Qt.AscendingOrder)

            # This prevents an application crash (see: http://www.qtcentre.org/threads/58874-QListView-SelectionModel-selectionChanged-Crash)
            viewselectionmodel = tableView.selectionModel()
            tableView.selectionModel().selectionChanged.connect(self.selectionChanged)

            self.addTab(tableView, group)
Пример #2
0
    def parseMCodes(cls, command: str) -> List[int]:
        re = QRegularExpression("[Mm]0*(\\d+)")

        codes = []
        pos = 0
        match = re.match(command, pos)

        while match.hasMatch():
            codes.append(int(match.captured(1)))
            pos += match.capturedLength()
            match = re.match(command, pos)

        return codes
Пример #3
0
    def __init__(self, document):
        super().__init__(document)

        self.rules = []

        # keywords
        f = QTextCharFormat()
        f.setFontWeight(QFont.Bold)
        f.setForeground(Qt.darkBlue)
        for kw in keyword.kwlist:
            self.rules.append((QRegularExpression(rf"\b{kw}\b"), f))

        # numerals
        f = QTextCharFormat()
        f.setForeground(Qt.blue)
        self.rules.append((QRegularExpression("[0-9]+"), f))

        # strings
        f = QTextCharFormat()
        f.setForeground(Qt.darkCyan)
        self.rules.append((QRegularExpression('"[^"]*"'), f))
        self.rules.append((QRegularExpression("'[^']*'"), f))
Пример #4
0
    def __init__(self, parent):
        super().__init__(parent)
        keywordFormat = QTextCharFormat()
        commentFormat = QTextCharFormat()
        stringFormat = QTextCharFormat()
        singleQuotedStringFormat = QTextCharFormat()

        self.highlightingRules = []

        # keyword
        brush = QBrush(Qt.blue, Qt.SolidPattern)
        keywordFormat.setForeground(brush)
        keywordFormat.setFontWeight(QFont.Bold)
        keywords = keyword.kwlist

        for word in keywords:
            pattern = QRegularExpression("\\b" + word + "\\b")
            rule = HighlightingRule(pattern, keywordFormat)
            self.highlightingRules.append(rule)

        # comment
        brush = QBrush(Qt.green, Qt.SolidPattern)
        pattern = QRegularExpression("#[^\n]*")
        commentFormat.setForeground(brush)
        rule = HighlightingRule(pattern, commentFormat)
        self.highlightingRules.append(rule)

        # string
        brush = QBrush(Qt.red, Qt.SolidPattern)
        pattern = QRegularExpression("\".*\"")
        stringFormat.setForeground(brush)
        rule = HighlightingRule(pattern, stringFormat)
        self.highlightingRules.append(rule)

        # singleQuotedString
        pattern = QRegularExpression("\'.*\'")
        singleQuotedStringFormat.setForeground(brush)
        rule = HighlightingRule(pattern, singleQuotedStringFormat)
        self.highlightingRules.append(rule)
    def filterRegExpChanged(self):
        syntax_nr = self.filterSyntaxComboBox.currentData()
        pattern = self.filterPatternLineEdit.text()
        if syntax_nr == WILDCARD:
            pattern = QRegularExpression.wildcardToRegularExpression(pattern)
        elif syntax_nr == FIXED_STRING:
            pattern = QRegularExpression.escape(pattern)

        regExp = QRegularExpression(pattern)
        if not self.filterCaseSensitivityCheckBox.isChecked():
            options = regExp.patternOptions()
            options |= QRegularExpression.CaseInsensitiveOption
            regExp.setPatternOptions(options)
        self.proxyModel.setFilterRegularExpression(regExp)
Пример #6
0
class GcodePreprocessorUtils:
    '''
    '''
    re_speed = QRegularExpression("[Ff]([0-9.]+)")

    rx1_comment_parenthesis = QRegularExpression("\\(+[^\\(]*\\)+")
    #[rx2_comment_commapoint = QRegularExpression(";.*")

    re_comment = QRegularExpression("(\\([^\\(\\)]*\\)|[^].*)")

    re_truncate_decimals = QRegularExpression("(\\d*\\.\\d*)")

    M_PI = math.acos(-1)

    @classmethod
    def overrideSpeed(cls,
                      command: str,
                      speed: float,
                      original: float = None) -> str:
        '''
        Searches the command string for an 'f' and replaces the speed value
        between the 'f' and the next space with a percentage of that speed.
        In that way all speed values become a ratio of the provided speed
        and don't get overridden with just a fixed speed.
        '''
        match = cls.re_speed.match(command)
        if match.hasMatch():
            command = "F%d" % float(match.captured(1)) / 100 * speed

            # BUG: original does not comes back
            if original:
                original = float(match.captured(1))

        return command
        # return command, original

    @classmethod
    def removeComment(cls, command: str) -> str:
        '''
        Removes any comments within parentheses or beginning with a semi-colon.
        '''
        res = command

        #Remove any comments within ( parentheses ) using regex "\([^\(]*\)"
        match = cls.rx1_comment_parenthesis.match(command)
        if match.hasMatch():
            #comment = match.captured(0)
            idx = match.capturedStart()
            len = match.capturedLength()
            res = res[:idx] + res[idx + len:]

        # Remove any comment beginning with ';' using regex ";.*"
        if ';' in res:
            idx = res.index(";")
            res = res[:idx]

        return res.strip()

    @classmethod
    def parseComment(cls, command: str) -> str:
        '''
        Searches for a comment in the input string and returns the first match.
        '''
        match = cls.re_comment.match(command)
        if match.hasMatch():
            return match.captured(1)

        return ""

    @classmethod
    def truncateDecimals(cls, length: int, command: str) -> str:
        res = command
        pos = 0
        match = cls.re_truncate_decimals.match(res, pos)

        while match.hasMatch():
            pos = match.capturedStart()
            len = match.capturedLength()

            newNum = "%.*f" % (length, float(match.captured(1)))
            res = res[:pos] + newNum + res[pos + len:]
            pos += len(newNum) + 1
            match = cls.re_truncate_decimals.match(res, pos)

        return res

    @classmethod
    def removeAllWhitespace(cls, command: str) -> str:
        #rx = QRegularExpression("\\s")
        #return command.remove(rx)

        return command.replace(" ", "")

    @classmethod
    def parseCodes(cls, args: List[str], code: str) -> List[float]:
        l = []

        for s in args:
            if len(s) > 0 and s[0].upper() == code:
                l.append(float(s[1:]))

        return l

    @classmethod
    def parseGCodes(cls, command: str) -> List[int]:
        re = QRegularExpression("[Gg]0*(\\d+)")

        codes = []
        pos = 0
        match = re.match(command, pos)

        while match.hasMatch():
            codes.append(int(match.captured(1)))
            pos += match.capturedLength()
            match = re.match(command, pos)

        return codes

    @classmethod
    def parseMCodes(cls, command: str) -> List[int]:
        re = QRegularExpression("[Mm]0*(\\d+)")

        codes = []
        pos = 0
        match = re.match(command, pos)

        while match.hasMatch():
            codes.append(int(match.captured(1)))
            pos += match.capturedLength()
            match = re.match(command, pos)

        return codes

    @classmethod
    def updatePointWithCommand(cls, command: str, initial: QVector3D,
                               absoluteMode: bool) -> QVector3D:
        '''
        Update a point given the arguments of a command.
        '''
        if command.__class__.__name__ == 'str':
            l = cls.splitCommand(command)
            return cls.updatePointWithCommand(l, initial, absoluteMode)
        else:
            return cls.updatePointWithCommand_FromStringList(
                command, initial, absoluteMode)

    @classmethod
    def updatePointWithCommand_FromStringList(cls, commandArgs: List[str],
                                              initial: QVector3D,
                                              absoluteMode: bool) -> QVector3D:
        '''
        Update a point given the arguments of a command, using a pre-parsed list.
        '''
        x = qQNaN()
        y = qQNaN()
        z = qQNaN()
        c = ""

        for command in commandArgs:
            if len(command) > 0:
                #c = command.upper().toLatin1()
                c = command[0].upper()
                if c == 'X':
                    x = float(command[1:])
                elif c == 'Y':
                    y = float(command[1:])
                elif c == 'Z':
                    z = float(command[1:])

        return cls.updatePointWithCommand_FromVector3D(initial, x, y, z,
                                                       absoluteMode)

    @classmethod
    def updatePointWithCommand_FromVector3D(cls, initial: QVector3D, x: float,
                                            y: float, z: float,
                                            absoluteMode: bool) -> QVector3D:
        '''
        Update a point given the new coordinates.
        '''
        newPoint = QVector3D(initial.x(), initial.y(), initial.z())

        if absoluteMode:
            if not qIsNaN(x): newPoint.setX(x)
            if not qIsNaN(y): newPoint.setY(y)
            if not qIsNaN(z): newPoint.setZ(z)
        else:
            if not qIsNaN(x): newPoint.setX(newPoint.x() + x)
            if not qIsNaN(y): newPoint.setY(newPoint.y() + y)
            if not qIsNaN(z): newPoint.setZ(newPoint.z() + z)

        return newPoint

    @classmethod
    def updateCenterWithCommand(cls, commandArgs: List[str],
                                initial: QVector3D, nextPoint: QVector3D,
                                absoluteIJKMode: bool,
                                clockwise: bool) -> QVector3D:
        i = qQNaN()
        j = qQNaN()
        k = qQNaN()
        r = qQNaN()
        c = ""

        for t in commandArgs:
            if len(t) > 0:
                # c = t[0].upper().toLatin1()
                c = t[0].upper()
                if c == 'I':
                    i = float(t[1:])
                elif c == 'J':
                    j = float(t[1:])
                elif c == 'K':
                    k = float(t[1:])
                elif c == 'R':
                    r = float(t[1:])

        if qIsNaN(i) and qIsNaN(j) and qIsNaN(k):
            return cls.convertRToCenter(initial, nextPoint, r, absoluteIJKMode,
                                        clockwise)

        return cls.updatePointWithCommand_FromVector3D(initial, i, j, k,
                                                       absoluteIJKMode)

    @classmethod
    def generateG1FromPoints(cls, start: QVector3D, end: QVector3D,
                             absoluteMode: bool, precision: int) -> str:
        sb = "G1"

        if absoluteMode:
            if not qIsNaN(end.x()):
                sb.append("X" + "%.*f" % (precision, end.x()))
            if not qIsNaN(end.y()):
                sb.append("Y" + "%.*f" % (precision, end.y()))
            if not qIsNaN(end.z()):
                sb.append("Z" + "%.*f" % (precision, end.z()))
        else:
            if not qIsNaN(end.x()):
                sb.append("X" + "%.*f" % (precision, end.x() - start.x()))
            if not qIsNaN(end.y()):
                sb.append("Y" + "%.*f" % (precision, end.y() - start.y()))
            if not qIsNaN(end.z()):
                sb.append("Z" + "%.*f" % (precision, end.z() - start.z()))

        return sb

    @classmethod
    def splitCommand(cls, command: str) -> List[str]:
        '''
        Splits a gcode command by each word/argument, doesn't care about spaces.
        This command is about the same speed as the string.split(" ") command,
        but might be a little faster using precompiled regex.
        '''
        l = []
        readNumeric = False
        sb = ""

        # NO UNICODE STUFF
        #ba = command.encode(encoding="latin_1")
        #cmd = ba.decode() # Direct access to string data

        for c in command:
            if readNumeric and not c.isdigit() and c != '.':
                readNumeric = False
                l.append(sb)
                sb = ""
                if c.isalpha():
                    sb += c
            elif c.isdigit() or c == '.' or c == '-':
                sb += c
                readNumeric = True
            elif c.isalpha():
                sb += c

        if len(sb) > 0:
            l.append(sb)

        return l

    @classmethod
    def parseCoord(cls, argList: List[str], c: str) -> float:
        '''
        TODO: Replace everything that uses this with a loop that loops through
        the string and creates a hash with all the values.
        '''
        for t in argList:
            if len(t) > 0 and t[0].upper() == c:
                return float(t[1:])

        return qQNaN()

    @classmethod
    def convertRToCenter(cls, start: QVector3D, end: QVector3D, radius: float,
                         absoluteIJK: bool, clockwise: bool) -> QVector3D:
        R = radius
        center = QVector3D()

        x = end.x() - start.x()
        y = end.y() - start.y()

        h_x2_div_d = 4 * R * R - x * x - y * y
        if h_x2_div_d < 0:
            print("Error computing arc radius.")

        h_x2_div_d = (-math.sqrt(h_x2_div_d)) / math.hypot(x, y)

        if not clockwise:
            h_x2_div_d = -h_x2_div_d

        # Special message from gcoder to software for which radius
        # should be used.
        if R < 0:
            h_x2_div_d = -h_x2_div_d
            # TODO: Places that use this need to run ABS on radius.
            radius = -radius

        offsetX = 0.5 * (x - (y * h_x2_div_d))
        offsetY = 0.5 * (y + (x * h_x2_div_d))

        if not absoluteIJK:
            center.setX(start.x() + offsetX)
            center.setY(start.y() + offsetY)
        else:
            center.setX(offsetX)
            center.setY(offsetY)

        return center

    @classmethod
    def getAngle(cls, start: QVector3D, end: QVector3D) -> float:
        '''
        Return the angle in radians when going from start to end.
        '''
        deltaX = end.x() - start.x()
        deltaY = end.y() - start.y()

        angle = 0.0

        if deltaX != 0:  # prevent div by 0
            # it helps to know what quadrant you are in
            if deltaX > 0 and deltaY >= 0:  # 0 - 90
                angle = math.atan(deltaY / deltaX)
            elif deltaX < 0 and deltaY >= 0:  # 90 to 180
                angle = cls.M_PI - math.fabs(math.atan(deltaY / deltaX))
            elif deltaX < 0 and deltaY < 0:  # 180 - 270
                angle = cls.M_PI + math.fabs(math.atan(deltaY / deltaX))
            elif deltaX > 0 and deltaY < 0:  # 270 - 360
                angle = cls.M_PI * 2 - math.fabs(math.atan(deltaY / deltaX))
        else:
            # 90 deg
            if deltaY > 0:
                angle = cls.M_PI / 2.0
            #270 deg
            else:
                angle = cls.M_PI * 3.0 / 2.0

        return angle

    @classmethod
    def calculateSweep(cls, startAngle: float, endAngle: float,
                       isCw: bool) -> float:
        sweep = 0.0

        # Full circle
        if startAngle == endAngle:
            sweep = cls.M_PI * 2
        #Arcs
        else:
            # Account for full circles and end angles of 0/360
            if endAngle == 0:
                endAngle = cls.M_PI * 2

            # Calculate distance along arc.
            if (not isCw) and endAngle < startAngle:
                sweep = (cls.M_PI * 2 - startAngle) + endAngle
            elif isCw and endAngle > startAngle:
                sweep = (cls.M_PI * 2 - endAngle) + startAngle
            else:
                sweep = math.fabs(endAngle - startAngle)

        return sweep

    @classmethod
    def generatePointsAlongArcBDring(cls, plane: PointSegment.Plane,
                                     start: QVector3D, end: QVector3D,
                                     center: QVector3D, clockwise: bool,
                                     R: float, minArcLength: float,
                                     arcPrecision: float,
                                     LAST_ARG: Any) -> List[QVector3D]:
        '''
        DUMMY DISPATCH
        '''
        if isinstance(LAST_ARG, bool):
            return cls.generatePointsAlongArcBDring_Arc(
                plane, start, end, center, clockwise, R, minArcLength,
                arcPrecision, LAST_ARG)
        else:
            return cls.generatePointsAlongArcBDring_Num(
                plane, start, end, center, clockwise, R, minArcLength,
                arcPrecision, LAST_ARG)

    @classmethod
    def generatePointsAlongArcBDring_Arc(
            cls, plane: PointSegment.Plane, start: QVector3D, end: QVector3D,
            center: QVector3D, clockwise: bool, R: float, minArcLength: float,
            arcPrecision: float, arcDegreeMode: bool) -> List[QVector3D]:
        '''
        Generates the points along an arc including the start and end points.
        '''
        radius = R

        # Rotate vectors according to plane
        m = QMatrix4x4()
        m.setToIdentity()
        if plane == PointSegment.Plane.XY:
            pass
        elif plane == PointSegment.Plane.ZX:
            m.rotate(90, 1.0, 0.0, 0.0)
        elif plane == PointSegment.Plane.YZ:
            m.rotate(-90, 0.0, 1.0, 0.0)

        start = m * start
        end = m * end
        center = m * center

        # Check center
        if qIsNaN(center.length()):
            return []

        # Calculate radius if necessary.
        if radius == 0:
            radius = math.sqrt(
                math.pow((start.x() - center.x(), 2.0) +
                         math.pow(end.y() - center.y(), 2.0)))

        startAngle = cls.getAngle(center, start)
        endAngle = cls.getAngle(center, end)
        sweep = cls.calculateSweep(startAngle, endAngle, clockwise)

        # Convert units.
        arcLength = sweep * radius

        numPoints = 0

        if arcDegreeMode and arcPrecision > 0:
            numPoints = max(1.0, sweep / (cls.M_PI * arcPrecision / 180))
        else:
            if arcPrecision <= 0 and minArcLength > 0:
                arcPrecision = minArcLength

            numPoints = math.ceil(arcLength / arcPrecision)

        return cls.generatePointsAlongArcBDring_Num(plane, start, end, center,
                                                    clockwise, radius,
                                                    startAngle, sweep,
                                                    numPoints)

    @classmethod
    def generatePointsAlongArcBDring_Num(cls, plane: PointSegment.Plane,
                                         p1: QVector3D, p2: QVector3D,
                                         center: QVector3D, isCw: bool,
                                         radius: float, startAngle: float,
                                         sweep: float,
                                         numPoints: int) -> List[QVector3D]:
        '''
        Generates the points along an arc including the start and end points.
        '''
        # Prepare rotation matrix to restore plane
        m = QMatrix4x4()
        m.setToIdentity()

        if plane == PointSegment.plane.XY:
            pass
        elif plane == PointSegment.plane.ZX:
            m.rotate(-90, 1.0, 0.0, 0.0)
        elif plane == PointSegment.plane.YZ:
            m.rotate(90, 0.0, 1.0, 0.0)

        lineEnd = QVector3D(p2.x(), p2.y(), p1.z())
        segments = []
        angle = 0.0

        # Calculate radius if necessary.
        if radius == 0:
            radius = math.sqrt(
                math.pow((p1.x() - center.x()), 2.0) +
                math.pow((p1.y() - center.y()), 2.0))

        zIncrement = (p2.z() - p1.z()) / numPoints

        for i in range(numPoints):
            if isCw:
                angle = (startAngle - i * sweep / numPoints)
            else:
                angle = (startAngle + i * sweep / numPoints)

            if angle >= cls.M_PI * 2:
                angle = angle - cls.M_PI * 2

            lineEnd.setX(math.cos(angle) * radius + center.x())
            lineEnd.setY(math.sin(angle) * radius + center.y())
            lineEnd.setZ(lineEnd.z() + zIncrement)

            segments.append(m * lineEnd)

        segments.append(m * p2)

        return segments
Пример #7
0
 def setFilter(self, search: str) -> None:
     self.filtermodel.setFilterRegularExpression(
         QRegularExpression(search,
                            QRegularExpression.CaseInsensitiveOption))
Пример #8
0
    def init_layout(self):
        """
        Initialize the layout for the DICOM View tab.
        Add the view widget and the slider in the layout.
        Add the whole container 'tab2_view' as a tab in the main page.
        """

        # Initialise a DrawROIWindow
        if platform.system() == 'Darwin':
            self.stylesheet_path = "res/stylesheet.qss"
        else:
            self.stylesheet_path = "res/stylesheet-win-linux.qss"
        stylesheet = open(resource_path(self.stylesheet_path)).read()
        window_icon = QIcon()
        window_icon.addPixmap(QPixmap(resource_path("res/images/icon.ico")),
                              QIcon.Normal, QIcon.Off)
        self.draw_roi_window_instance.setObjectName("DrawRoiWindowInstance")
        self.draw_roi_window_instance.setWindowIcon(window_icon)

        # Creating a form box to hold all buttons and input fields
        self.draw_roi_window_input_container_box = QFormLayout()
        self.draw_roi_window_input_container_box. \
            setObjectName("DrawRoiWindowInputContainerBox")
        self.draw_roi_window_input_container_box. \
            setLabelAlignment(Qt.AlignLeft)

        # Create a label for denoting the ROI name
        self.roi_name_label = QLabel()
        self.roi_name_label.setObjectName("ROINameLabel")
        self.roi_name_line_edit = QLineEdit()
        # Create an input box for ROI name
        self.roi_name_line_edit.setObjectName("ROINameLineEdit")
        self.roi_name_line_edit.setSizePolicy(QSizePolicy.Minimum,
                                              QSizePolicy.Minimum)
        self.roi_name_line_edit.resize(
            self.roi_name_line_edit.sizeHint().width(),
            self.roi_name_line_edit.sizeHint().height())
        self.roi_name_line_edit.setEnabled(False)
        self.draw_roi_window_input_container_box. \
            addRow(self.roi_name_label, self.roi_name_line_edit)

        # Create horizontal box to store image slice number and backward,
        # forward buttons
        self.image_slice_number_box = QHBoxLayout()
        self.image_slice_number_box.setObjectName("ImageSliceNumberBox")

        # Create a label for denoting the Image Slice Number
        self.image_slice_number_label = QLabel()
        self.image_slice_number_label.setObjectName("ImageSliceNumberLabel")
        self.image_slice_number_box.addWidget(self.image_slice_number_label)
        # Create a line edit for containing the image slice number
        self.image_slice_number_line_edit = QLineEdit()
        self.image_slice_number_line_edit. \
            setObjectName("ImageSliceNumberLineEdit")
        self.image_slice_number_line_edit. \
            setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.image_slice_number_line_edit.resize(
            self.image_slice_number_line_edit.sizeHint().width(),
            self.image_slice_number_line_edit.sizeHint().height())

        self.image_slice_number_line_edit.setCursorPosition(0)
        self.image_slice_number_line_edit.setEnabled(False)
        self.image_slice_number_box. \
            addWidget(self.image_slice_number_line_edit)
        # Create a button to move backward to the previous image
        self.image_slice_number_move_backward_button = QPushButton()
        self.image_slice_number_move_backward_button. \
            setObjectName("ImageSliceNumberMoveBackwardButton")
        self.image_slice_number_move_backward_button.setSizePolicy(
            QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self.image_slice_number_move_backward_button.resize(QSize(24, 24))
        self.image_slice_number_move_backward_button.clicked. \
            connect(self.onBackwardClicked)
        icon_move_backward = QtGui.QIcon()
        icon_move_backward.addPixmap(
            QtGui.QPixmap(
                resource_path('res/images/btn-icons/backward_slide_icon.png')))
        self.image_slice_number_move_backward_button.setIcon(
            icon_move_backward)
        self.image_slice_number_box. \
            addWidget(self.image_slice_number_move_backward_button)
        # Create a button to move forward to the next image
        self.image_slice_number_move_forward_button = QPushButton()
        self.image_slice_number_move_forward_button. \
            setObjectName("ImageSliceNumberMoveForwardButton")
        self.image_slice_number_move_forward_button.setSizePolicy(
            QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self.image_slice_number_move_forward_button.resize(QSize(24, 24))
        self.image_slice_number_move_forward_button.clicked. \
            connect(self.onForwardClicked)
        icon_move_forward = QtGui.QIcon()
        icon_move_forward.addPixmap(
            QtGui.QPixmap(
                resource_path('res/images/btn-icons/forward_slide_icon.png')))
        self.image_slice_number_move_forward_button.setIcon(icon_move_forward)
        self.image_slice_number_box. \
            addWidget(self.image_slice_number_move_forward_button)

        self.draw_roi_window_input_container_box. \
            addRow(self.image_slice_number_box)

        # Create a horizontal box for containing the zoom function
        self.draw_roi_window_viewport_zoom_box = QHBoxLayout()
        self.draw_roi_window_viewport_zoom_box.setObjectName(
            "DrawRoiWindowViewportZoomBox")
        # Create a label for zooming
        self.draw_roi_window_viewport_zoom_label = QLabel()
        self.draw_roi_window_viewport_zoom_label. \
            setObjectName("DrawRoiWindowViewportZoomLabel")
        # Create an input box for zoom factor
        self.draw_roi_window_viewport_zoom_input = QLineEdit()
        self.draw_roi_window_viewport_zoom_input. \
            setObjectName("DrawRoiWindowViewportZoomInput")
        self.draw_roi_window_viewport_zoom_input. \
            setText("{:.2f}".format(self.zoom * 100) + "%")
        self.draw_roi_window_viewport_zoom_input.setCursorPosition(0)
        self.draw_roi_window_viewport_zoom_input.setEnabled(False)
        self.draw_roi_window_viewport_zoom_input. \
            setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.draw_roi_window_viewport_zoom_input.resize(
            self.draw_roi_window_viewport_zoom_input.sizeHint().width(),
            self.draw_roi_window_viewport_zoom_input.sizeHint().height())
        # Create 2 buttons for zooming in and out
        # Zoom In Button
        self.draw_roi_window_viewport_zoom_in_button = QPushButton()
        self.draw_roi_window_viewport_zoom_in_button. \
            setObjectName("DrawRoiWindowViewportZoomInButton")
        self.draw_roi_window_viewport_zoom_in_button.setSizePolicy(
            QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self.draw_roi_window_viewport_zoom_in_button.resize(QSize(24, 24))
        self.draw_roi_window_viewport_zoom_in_button. \
            setProperty("QPushButtonClass", "zoom-button")
        icon_zoom_in = QtGui.QIcon()
        icon_zoom_in.addPixmap(
            QtGui.QPixmap(
                resource_path('res/images/btn-icons/zoom_in_icon.png')))
        self.draw_roi_window_viewport_zoom_in_button.setIcon(icon_zoom_in)
        self.draw_roi_window_viewport_zoom_in_button.clicked. \
            connect(self.onZoomInClicked)
        # Zoom Out Button
        self.draw_roi_window_viewport_zoom_out_button = QPushButton()
        self.draw_roi_window_viewport_zoom_out_button. \
            setObjectName("DrawRoiWindowViewportZoomOutButton")
        self.draw_roi_window_viewport_zoom_out_button.setSizePolicy(
            QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
        self.draw_roi_window_viewport_zoom_out_button.resize(QSize(24, 24))
        self.draw_roi_window_viewport_zoom_out_button. \
            setProperty("QPushButtonClass", "zoom-button")
        icon_zoom_out = QtGui.QIcon()
        icon_zoom_out.addPixmap(
            QtGui.QPixmap(
                resource_path('res/images/btn-icons/zoom_out_icon.png')))
        self.draw_roi_window_viewport_zoom_out_button.setIcon(icon_zoom_out)
        self.draw_roi_window_viewport_zoom_out_button.clicked. \
            connect(self.onZoomOutClicked)
        self.draw_roi_window_viewport_zoom_box. \
            addWidget(self.draw_roi_window_viewport_zoom_label)
        self.draw_roi_window_viewport_zoom_box. \
            addWidget(self.draw_roi_window_viewport_zoom_input)
        self.draw_roi_window_viewport_zoom_box. \
            addWidget(self.draw_roi_window_viewport_zoom_out_button)
        self.draw_roi_window_viewport_zoom_box. \
            addWidget(self.draw_roi_window_viewport_zoom_in_button)
        self.draw_roi_window_input_container_box. \
            addRow(self.draw_roi_window_viewport_zoom_box)

        self.init_cursor_radius_change_box()
        # Create field to toggle two options: Keep empty pixel or fill empty
        # pixel when using draw cursor
        self.toggle_keep_empty_pixel_box = QHBoxLayout()
        self.toggle_keep_empty_pixel_label = QLabel()
        self.toggle_keep_empty_pixel_label. \
            setObjectName("ToggleKeepEmptyPixelLabel")
        # Create input for min pixel size
        self.toggle_keep_empty_pixel_combo_box = QComboBox()
        self.toggle_keep_empty_pixel_combo_box.addItems(["Off", "On"])
        self.toggle_keep_empty_pixel_combo_box.setCurrentIndex(0)
        self.toggle_keep_empty_pixel_combo_box.setEnabled(False)
        self.toggle_keep_empty_pixel_combo_box. \
            setObjectName("ToggleKeepEmptyPixelComboBox")
        self.toggle_keep_empty_pixel_combo_box. \
            setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.toggle_keep_empty_pixel_combo_box.resize(
            self.toggle_keep_empty_pixel_combo_box.sizeHint().width(),
            self.toggle_keep_empty_pixel_combo_box.sizeHint().height())
        self.toggle_keep_empty_pixel_combo_box.currentIndexChanged.connect(
            self.toggle_keep_empty_pixel_box_index_changed)
        self.toggle_keep_empty_pixel_box. \
            addWidget(self.toggle_keep_empty_pixel_label)
        self.toggle_keep_empty_pixel_box. \
            addWidget(self.toggle_keep_empty_pixel_combo_box)
        self.draw_roi_window_input_container_box. \
            addRow(self.toggle_keep_empty_pixel_box)

        # Create a horizontal box for transect and draw button
        self.draw_roi_window_transect_draw_box = QHBoxLayout()
        self.draw_roi_window_transect_draw_box. \
            setObjectName("DrawRoiWindowTransectDrawBox")
        # Create a transect button
        self.image_slice_number_transect_button = QPushButton()
        self.image_slice_number_transect_button. \
            setObjectName("ImageSliceNumberTransectButton")
        self.image_slice_number_transect_button.setSizePolicy(
            QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum))
        self.image_slice_number_transect_button.resize(
            self.image_slice_number_transect_button.sizeHint().width(),
            self.image_slice_number_transect_button.sizeHint().height())
        self.image_slice_number_transect_button.clicked. \
            connect(self.transect_handler)
        icon_transect = QtGui.QIcon()
        icon_transect.addPixmap(
            QtGui.QPixmap(
                resource_path('res/images/btn-icons/transect_icon.png')))
        self.image_slice_number_transect_button.setIcon(icon_transect)
        self.draw_roi_window_transect_draw_box. \
            addWidget(self.image_slice_number_transect_button)
        # Create a bounding box button
        self.image_slice_number_box_draw_button = QPushButton()
        self.image_slice_number_box_draw_button. \
            setObjectName("ImageSliceNumberBoxDrawButton")
        self.image_slice_number_box_draw_button.setSizePolicy(
            QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        self.image_slice_number_box_draw_button.resize(
            self.image_slice_number_box_draw_button.sizeHint().width(),
            self.image_slice_number_box_draw_button.sizeHint().height())
        self.image_slice_number_box_draw_button.clicked. \
            connect(self.onBoxDrawClicked)
        icon_box_draw = QtGui.QIcon()
        icon_box_draw.addPixmap(
            QtGui.QPixmap(
                resource_path('res/images/btn-icons/draw_bound_icon.png')))
        self.image_slice_number_box_draw_button.setIcon(icon_box_draw)
        self.draw_roi_window_transect_draw_box. \
            addWidget(self.image_slice_number_box_draw_button)
        # Create a draw button
        self.image_slice_number_draw_button = QPushButton()
        self.image_slice_number_draw_button. \
            setObjectName("ImageSliceNumberDrawButton")
        self.image_slice_number_draw_button.setSizePolicy(
            QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum))
        self.image_slice_number_draw_button.resize(
            self.image_slice_number_draw_button.sizeHint().width(),
            self.image_slice_number_draw_button.sizeHint().height())
        self.image_slice_number_draw_button.clicked.connect(self.onDrawClicked)
        icon_draw = QtGui.QIcon()
        icon_draw.addPixmap(
            QtGui.QPixmap(resource_path('res/images/btn-icons/draw_icon.png')))
        self.image_slice_number_draw_button.setIcon(icon_draw)
        self.draw_roi_window_transect_draw_box. \
            addWidget(self.image_slice_number_draw_button)
        self.draw_roi_window_input_container_box. \
            addRow(self.draw_roi_window_transect_draw_box)

        # Create a contour preview button
        self.row_preview_layout = QtWidgets.QHBoxLayout()
        self.button_contour_preview = QtWidgets.QPushButton("Preview contour")
        self.button_contour_preview.clicked.connect(self.onPreviewClicked)
        self.row_preview_layout.addWidget(self.button_contour_preview)
        self.draw_roi_window_input_container_box. \
            addRow(self.row_preview_layout)
        icon_preview = QtGui.QIcon()
        icon_preview.addPixmap(
            QtGui.QPixmap(
                resource_path('res/images/btn-icons/preview_icon.png')))
        self.button_contour_preview.setIcon(icon_preview)

        # Create input line edit for alpha value
        self.label_alpha_value = QtWidgets.QLabel("Alpha value:")
        self.input_alpha_value = QtWidgets.QLineEdit("0.2")
        self.input_alpha_value. \
            setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        self.input_alpha_value.resize(
            self.input_alpha_value.sizeHint().width(),
            self.input_alpha_value.sizeHint().height())
        self.input_alpha_value.setValidator(
            QRegularExpressionValidator(
                QRegularExpression("^[0-9]*[.]?[0-9]*$")))
        self.draw_roi_window_input_container_box. \
            addRow(self.label_alpha_value, self.input_alpha_value)

        # Create a label for denoting the max internal hole size
        self.internal_hole_max_label = QLabel()
        self.internal_hole_max_label.setObjectName("InternalHoleLabel")

        # Create input for max internal hole size
        self.internal_hole_max_line_edit = QLineEdit()
        self.internal_hole_max_line_edit.setObjectName("InternalHoleInput")
        self.internal_hole_max_line_edit. \
            setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        self.internal_hole_max_line_edit.resize(
            self.internal_hole_max_line_edit.sizeHint().width(),
            self.internal_hole_max_line_edit.sizeHint().height())
        self.internal_hole_max_line_edit.setValidator(
            QRegularExpressionValidator(
                QRegularExpression("^[0-9]*[.]?[0-9]*$")))
        self.draw_roi_window_input_container_box.addRow(
            self.internal_hole_max_label, self.internal_hole_max_line_edit)

        # Create a label for denoting the isthmus width size
        self.isthmus_width_max_label = QLabel()
        self.isthmus_width_max_label.setObjectName("IsthmusWidthLabel")
        # Create input for max isthmus width size
        self.isthmus_width_max_line_edit = QLineEdit()
        self.isthmus_width_max_line_edit.setObjectName("IsthmusWidthInput")
        self.isthmus_width_max_line_edit.setSizePolicy(
            QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        self.isthmus_width_max_line_edit.resize(
            self.isthmus_width_max_line_edit.sizeHint().width(),
            self.isthmus_width_max_line_edit.sizeHint().height())
        self.isthmus_width_max_line_edit.setValidator(
            QRegularExpressionValidator(
                QRegularExpression("^[0-9]*[.]?[0-9]*$")))
        self.draw_roi_window_input_container_box.addRow(
            self.isthmus_width_max_label, self.isthmus_width_max_line_edit)

        # Create a label for denoting the minimum pixel density
        self.min_pixel_density_label = QLabel()
        self.min_pixel_density_label.setObjectName("MinPixelDensityLabel")
        # Create input for min pixel size
        self.min_pixel_density_line_edit = QLineEdit()
        self.min_pixel_density_line_edit.setObjectName("MinPixelDensityInput")
        self.min_pixel_density_line_edit.setSizePolicy(
            QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        self.min_pixel_density_line_edit.resize(
            self.min_pixel_density_line_edit.sizeHint().width(),
            self.min_pixel_density_line_edit.sizeHint().height())
        self.min_pixel_density_line_edit.setValidator(
            QRegularExpressionValidator(
                QRegularExpression("^[0-9]*[.]?[0-9]*$")))
        self.draw_roi_window_input_container_box.addRow(
            self.min_pixel_density_label, self.min_pixel_density_line_edit)

        # Create a label for denoting the minimum pixel density
        self.max_pixel_density_label = QLabel()
        self.max_pixel_density_label.setObjectName("MaxPixelDensityLabel")
        # Create input for min pixel size
        self.max_pixel_density_line_edit = QLineEdit()
        self.max_pixel_density_line_edit.setObjectName("MaxPixelDensityInput")
        self.max_pixel_density_line_edit. \
            setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum)
        self.max_pixel_density_line_edit.resize(
            self.max_pixel_density_line_edit.sizeHint().width(),
            self.max_pixel_density_line_edit.sizeHint().height())
        self.max_pixel_density_line_edit.setValidator(
            QRegularExpressionValidator(
                QRegularExpression("^[0-9]*[.]?[0-9]*$")))
        self.draw_roi_window_input_container_box.addRow(
            self.max_pixel_density_label, self.max_pixel_density_line_edit)

        # Create a button to clear the draw
        self.draw_roi_window_instance_action_reset_button = QPushButton()
        self.draw_roi_window_instance_action_reset_button. \
            setObjectName("DrawRoiWindowInstanceActionClearButton")
        self.draw_roi_window_instance_action_reset_button.setSizePolicy(
            QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum))

        reset_button = self.draw_roi_window_instance_action_reset_button
        self.draw_roi_window_instance_action_reset_button.resize(
            reset_button.sizeHint().width(),
            reset_button.sizeHint().height())
        self.draw_roi_window_instance_action_reset_button.clicked. \
            connect(self.onResetClicked)
        self.draw_roi_window_instance_action_reset_button. \
            setProperty("QPushButtonClass", "fail-button")
        icon_clear_roi_draw = QtGui.QIcon()
        icon_clear_roi_draw.addPixmap(
            QtGui.QPixmap(
                resource_path('res/images/btn-icons/reset_roi_draw_icon.png')))
        self.draw_roi_window_instance_action_reset_button. \
            setIcon(icon_clear_roi_draw)
        self.draw_roi_window_input_container_box. \
            addRow(self.draw_roi_window_instance_action_reset_button)

        # Create a horizontal box for saving and cancel the drawing
        self.draw_roi_window_cancel_save_box = QHBoxLayout()
        self.draw_roi_window_cancel_save_box. \
            setObjectName("DrawRoiWindowCancelSaveBox")
        # Create an exit button to cancel the drawing
        # Add a button to go back/exit from the application
        self.draw_roi_window_instance_cancel_button = QPushButton()
        self.draw_roi_window_instance_cancel_button. \
            setObjectName("DrawRoiWindowInstanceCancelButton")
        self.draw_roi_window_instance_cancel_button.setSizePolicy(
            QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum))
        self.draw_roi_window_instance_cancel_button.resize(
            self.draw_roi_window_instance_cancel_button.sizeHint().width(),
            self.draw_roi_window_instance_cancel_button.sizeHint().height())
        self.draw_roi_window_instance_cancel_button. \
            setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.draw_roi_window_instance_cancel_button.clicked. \
            connect(self.onCancelButtonClicked)
        self.draw_roi_window_instance_cancel_button. \
            setProperty("QPushButtonClass", "fail-button")
        icon_cancel = QtGui.QIcon()
        icon_cancel.addPixmap(
            QtGui.QPixmap(
                resource_path('res/images/btn-icons/cancel_icon.png')))
        self.draw_roi_window_instance_cancel_button.setIcon(icon_cancel)
        self.draw_roi_window_cancel_save_box. \
            addWidget(self.draw_roi_window_instance_cancel_button)
        # Create a save button to save all the changes
        self.draw_roi_window_instance_save_button = QPushButton()
        self.draw_roi_window_instance_save_button. \
            setObjectName("DrawRoiWindowInstanceSaveButton")
        self.draw_roi_window_instance_save_button.setSizePolicy(
            QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum))
        self.draw_roi_window_instance_save_button.resize(
            self.draw_roi_window_instance_save_button.sizeHint().width(),
            self.draw_roi_window_instance_save_button.sizeHint().height())
        self.draw_roi_window_instance_save_button. \
            setProperty("QPushButtonClass", "success-button")
        icon_save = QtGui.QIcon()
        icon_save.addPixmap(
            QtGui.QPixmap(resource_path('res/images/btn-icons/save_icon.png')))
        self.draw_roi_window_instance_save_button.setIcon(icon_save)
        self.draw_roi_window_instance_save_button.clicked. \
            connect(self.onSaveClicked)
        self.draw_roi_window_cancel_save_box. \
            addWidget(self.draw_roi_window_instance_save_button)

        self.draw_roi_window_input_container_box. \
            addRow(self.draw_roi_window_cancel_save_box)

        # Creating a horizontal box to hold the ROI view and slider
        self.draw_roi_window_instance_view_box = QHBoxLayout()
        self.draw_roi_window_instance_view_box. \
            setObjectName("DrawRoiWindowInstanceViewBox")
        # Add View and Slider into horizontal box
        self.draw_roi_window_instance_view_box.addWidget(self.dicom_view)
        # Create a widget to hold the image slice box
        self.draw_roi_window_instance_view_widget = QWidget()
        self.draw_roi_window_instance_view_widget.setObjectName(
            "DrawRoiWindowInstanceActionWidget")
        self.draw_roi_window_instance_view_widget.setLayout(
            self.draw_roi_window_instance_view_box)

        # Create a horizontal box for containing the input fields and the
        # viewport
        self.draw_roi_window_main_box = QHBoxLayout()
        self.draw_roi_window_main_box.setObjectName("DrawRoiWindowMainBox")
        self.draw_roi_window_main_box. \
            addLayout(self.draw_roi_window_input_container_box, 1)
        self.draw_roi_window_main_box. \
            addWidget(self.draw_roi_window_instance_view_widget, 11)

        # Create a new central widget to hold the vertical box layout
        self.draw_roi_window_instance_central_widget = QWidget()
        self.draw_roi_window_instance_central_widget. \
            setObjectName("DrawRoiWindowInstanceCentralWidget")
        self.draw_roi_window_instance_central_widget.setLayout(
            self.draw_roi_window_main_box)

        self.retranslate_ui(self.draw_roi_window_instance)
        self.draw_roi_window_instance.setStyleSheet(stylesheet)
        self.draw_roi_window_instance. \
            setCentralWidget(self.draw_roi_window_instance_central_widget)
        QtCore.QMetaObject.connectSlotsByName(self.draw_roi_window_instance)
Пример #9
0
    def __init__(self, parent=None):
        self.bool_exp = QRegularExpression('^(true)|(false)$')
        assert self.bool_exp.isValid()
        self.bool_exp.setPatternOptions(QRegularExpression.CaseInsensitiveOption)

        self.byteArray_exp = QRegularExpression(r'^[\x00-\xff]*$')
        assert self.byteArray_exp.isValid()

        self.char_exp = QRegularExpression('^.$')
        assert self.char_exp.isValid()

        pattern = r'^[+-]?\d+$'
        self.int_exp = QRegularExpression(pattern)
        assert self.int_exp.isValid()

        pattern = r'^\(([0-9]*),([0-9]*),([0-9]*),([0-9]*)\)$'
        self.color_exp = QRegularExpression(pattern)
        assert self.color_exp.isValid()

        pattern = r'^\((-?[0-9]*),(-?[0-9]*)\)$'
        self.point_exp = QRegularExpression(pattern)
        assert self.point_exp.isValid()

        pattern = r'^\((-?[0-9]*),(-?[0-9]*),(-?[0-9]*),(-?[0-9]*)\)$'
        self.rect_exp = QRegularExpression(pattern)
        assert self.rect_exp.isValid()

        self.size_exp = QRegularExpression(self.point_exp)

        date_pattern = '([0-9]{,4})-([0-9]{,2})-([0-9]{,2})'
        self.date_exp = QRegularExpression('^{}$'.format(date_pattern))
        assert self.date_exp.isValid()

        time_pattern = '([0-9]{,2}):([0-9]{,2}):([0-9]{,2})'
        self.time_exp = QRegularExpression('^{}$'.format(time_pattern))
        assert self.time_exp.isValid()

        pattern = '^{}T{}$'.format(date_pattern, time_pattern)
        self.dateTime_exp = QRegularExpression(pattern)
        assert self.dateTime_exp.isValid()
Пример #10
0
class TypeChecker:
    def __init__(self, parent=None):
        self.bool_exp = QRegularExpression('^(true)|(false)$')
        assert self.bool_exp.isValid()
        self.bool_exp.setPatternOptions(QRegularExpression.CaseInsensitiveOption)

        self.byteArray_exp = QRegularExpression(r'^[\x00-\xff]*$')
        assert self.byteArray_exp.isValid()

        self.char_exp = QRegularExpression('^.$')
        assert self.char_exp.isValid()

        pattern = r'^[+-]?\d+$'
        self.int_exp = QRegularExpression(pattern)
        assert self.int_exp.isValid()

        pattern = r'^\(([0-9]*),([0-9]*),([0-9]*),([0-9]*)\)$'
        self.color_exp = QRegularExpression(pattern)
        assert self.color_exp.isValid()

        pattern = r'^\((-?[0-9]*),(-?[0-9]*)\)$'
        self.point_exp = QRegularExpression(pattern)
        assert self.point_exp.isValid()

        pattern = r'^\((-?[0-9]*),(-?[0-9]*),(-?[0-9]*),(-?[0-9]*)\)$'
        self.rect_exp = QRegularExpression(pattern)
        assert self.rect_exp.isValid()

        self.size_exp = QRegularExpression(self.point_exp)

        date_pattern = '([0-9]{,4})-([0-9]{,2})-([0-9]{,2})'
        self.date_exp = QRegularExpression('^{}$'.format(date_pattern))
        assert self.date_exp.isValid()

        time_pattern = '([0-9]{,2}):([0-9]{,2}):([0-9]{,2})'
        self.time_exp = QRegularExpression('^{}$'.format(time_pattern))
        assert self.time_exp.isValid()

        pattern = '^{}T{}$'.format(date_pattern, time_pattern)
        self.dateTime_exp = QRegularExpression(pattern)
        assert self.dateTime_exp.isValid()

    def type_from_text(self, text):
        if self.bool_exp.match(text).hasMatch():
            return bool
        if self.int_exp.match(text).hasMatch():
            return int
        return None

    def create_validator(self, value, parent):
        if isinstance(value, bool):
            return QRegularExpressionValidator(self.bool_exp, parent)
        if isinstance(value, float):
            return QDoubleValidator(parent)
        if isinstance(value, int):
            return QIntValidator(parent)
        if isinstance(value, QByteArray):
            return QRegularExpressionValidator(self.byteArray_exp, parent)
        if isinstance(value, QColor):
            return QRegularExpressionValidator(self.color_exp, parent)
        if isinstance(value, QDate):
            return QRegularExpressionValidator(self.date_exp, parent)
        if isinstance(value, QDateTime):
            return QRegularExpressionValidator(self.dateTime_exp, parent)
        if isinstance(value, QTime):
            return QRegularExpressionValidator(self.time_exp, parent)
        if isinstance(value, QPoint):
            return QRegularExpressionValidator(self.point_exp, parent)
        if isinstance(value, QRect):
            return QRegularExpressionValidator(self.rect_exp, parent)
        if isinstance(value, QSize):
            return QRegularExpressionValidator(self.size_exp, parent)
        return None

    def from_string(self, text, original_value):
        if isinstance(original_value, QColor):
            match = self.color_exp.match(text)
            return QColor(min(int(match.captured(1)), 255),
                          min(int(match.captured(2)), 255),
                          min(int(match.captured(3)), 255),
                          min(int(match.captured(4)), 255))
        if isinstance(original_value, QDate):
            value = QDate.fromString(text, Qt.ISODate)
            return value if value.isValid() else None
        if isinstance(original_value, QDateTime):
            value = QDateTime.fromString(text, Qt.ISODate)
            return value if value.isValid() else None
        if isinstance(original_value, QTime):
            value = QTime.fromString(text, Qt.ISODate)
            return value if value.isValid() else None
        if isinstance(original_value, QPoint):
            match = self.point_exp.match(text)
            return QPoint(int(match.captured(1)),
                          int(match.captured(2)))
        if isinstance(original_value, QRect):
            match = self.rect_exp.match(text)
            return QRect(int(match.captured(1)),
                         int(match.captured(2)),
                         int(match.captured(3)),
                         int(match.captured(4)))
        if isinstance(original_value, QSize):
            match = self.size_exp.match(text)
            return QSize(int(match.captured(1)),
                         int(match.captured(2)))
        if isinstance(original_value, list):
            return text.split(',')
        return type(original_value)(text)
Пример #11
0
class GCodeSyntaxHighlightDelegate(QtWidgets.QStyledItemDelegate):
    '''
    Html of QTextDocument can be painted

    Note: QPlainTextEdit document FAILS to be painted...
    '''
    HTML_STYLES = {
        'comment': "color:darkGreen;font-style:italic",
        'keyword': "color:blue;font-weight:bold",
        'numbers': "color:brown",
        'numbersZ': "color:magenta",
    }

    # The rules
    rules = [

        # From ';' until a newline
        (r';[^\n]*', 0, HTML_STYLES['comment']),

        # Positions Numeric literals
        (r'\b[XY][+-]?[0-9]+(?:\.[0-9]+)?\b', 0, HTML_STYLES['numbers']),
        (r'\b[Z][+-]?[0-9]+(?:\.[0-9]+)?\b', 0, HTML_STYLES['numbersZ']),

        # Others Numeric literals
        (r'\b[GSMF][0-9]+?\b', 0, HTML_STYLES['keyword'])
    ]

    # Build a QRegularExpression for each pattern
    RULES = [(QRegularExpression(pat), index, style)
             for (pat, index, style) in rules]

    def __init__(self, parent):
        '''
        '''
        super().__init__(parent)

    def paint(self, painter: QtGui.QPainter,
              option: QtWidgets.QStyleOptionViewItem,
              index: QtCore.QModelIndex):

        painter.save()

        options = QtWidgets.QStyleOptionViewItem(option)
        self.initStyleOption(options, index)

        painter.translate(options.rect.left(), options.rect.top())

        doc = QtGui.QTextDocument()
        doc.setHtml(self.makeHtml(index.data()))
        doc.drawContents(painter)

        painter.restore()

    def makeHtml(self, text: str):
        '''
        '''
        html_parts = {}

        for expression, nth, style in self.RULES:
            nth = 0
            match = expression.match(text, offset=0)
            index = match.capturedStart()

            while index >= 0:
                # We actually want the index of the nth match
                index = match.capturedStart(nth)
                length = match.capturedLength(nth)

                ####self.setFormat(index, length, format)
                html_parts[index] = '<span style="%s">%s</span>' % (
                    style, text[index:index + length])

                # check the rest of the string

                match = expression.match(text, offset=index + length)
                index = match.capturedStart()

        # sorted by index
        keys = list(html_parts.keys())
        keys.sort()

        htmls = []
        for key in keys:
            htmls.append(html_parts[key])

        html = "<p>" + "&nbsp;".join(htmls) + "</p>"
        #print("------------------------------------------")
        #print("TEXT -> ", text)
        #print("HTML -> ", html)
        return html
Пример #12
0
    def init_layout(self):
        """
        Initialize the layout for the DICOM View tab.
        Add the view widget and the slider in the layout.
        Add the whole container 'tab2_view' as a tab in the main page.
        """

        # Initialise a ManipulateROIWindow
        if platform.system() == 'Darwin':
            self.stylesheet_path = "res/stylesheet.qss"
        else:
            self.stylesheet_path = "res/stylesheet-win-linux.qss"
        stylesheet = open(resource_path(self.stylesheet_path)).read()
        window_icon = QIcon()
        window_icon.addPixmap(QPixmap(resource_path("res/images/icon.ico")),
                              QIcon.Normal, QIcon.Off)
        self.manipulate_roi_window_instance.setObjectName(
            "ManipulateRoiWindowInstance")
        self.manipulate_roi_window_instance.setWindowIcon(window_icon)

        # Creating a form box to hold all buttons and input fields
        self.manipulate_roi_window_input_container_box = QFormLayout()
        self.manipulate_roi_window_input_container_box.setObjectName(
            "ManipulateRoiWindowInputContainerBox")
        self.manipulate_roi_window_input_container_box.setLabelAlignment(
            Qt.AlignLeft)

        # Create a label for denoting the first ROI name
        self.first_roi_name_label = QLabel()
        self.first_roi_name_label.setObjectName("FirstROINameLabel")
        self.first_roi_name_dropdown_list = QComboBox()
        # Create an dropdown list for ROI name
        self.first_roi_name_dropdown_list.setObjectName(
            "FirstROINameDropdownList")
        self.first_roi_name_dropdown_list.setSizePolicy(
            QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.first_roi_name_dropdown_list.resize(
            self.first_roi_name_dropdown_list.sizeHint().width(),
            self.first_roi_name_dropdown_list.sizeHint().height())
        self.first_roi_name_dropdown_list.activated.connect(
            self.update_selected_rois)
        self.manipulate_roi_window_input_container_box.addRow(
            self.first_roi_name_label, self.first_roi_name_dropdown_list)

        # Create a label for denoting the operation
        self.operation_name_label = QLabel()
        self.operation_name_label.setObjectName("OperationNameLabel")
        self.operation_name_dropdown_list = QComboBox()
        # Create an dropdown list for operation name
        self.operation_name_dropdown_list.setObjectName(
            "OperationNameDropdownList")
        self.operation_name_dropdown_list.setSizePolicy(
            QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.operation_name_dropdown_list.resize(
            self.operation_name_dropdown_list.sizeHint().width(),
            self.operation_name_dropdown_list.sizeHint().height())
        self.operation_name_dropdown_list.activated.connect(
            self.operation_changed)
        self.manipulate_roi_window_input_container_box.addRow(
            self.operation_name_label, self.operation_name_dropdown_list)

        # Create a label for denoting the second ROI name
        self.second_roi_name_label = QLabel()
        self.second_roi_name_label.setObjectName("SecondROINameLabel")
        self.second_roi_name_label.setVisible(False)
        self.second_roi_name_dropdown_list = QComboBox()
        # Create an dropdown list for ROI name
        self.second_roi_name_dropdown_list.setObjectName(
            "SecondROINameDropdownList")
        self.second_roi_name_dropdown_list.setSizePolicy(
            QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.second_roi_name_dropdown_list.resize(
            self.second_roi_name_dropdown_list.sizeHint().width(),
            self.second_roi_name_dropdown_list.sizeHint().height())
        self.second_roi_name_dropdown_list.setVisible(False)
        self.second_roi_name_dropdown_list.activated.connect(
            self.update_selected_rois)
        self.manipulate_roi_window_input_container_box.addRow(
            self.second_roi_name_label, self.second_roi_name_dropdown_list)

        # Create a label for denoting the margin
        self.margin_label = QLabel()
        self.margin_label.setObjectName("MarginLabel")
        self.margin_label.setVisible(False)
        # Create input for the new ROI name
        self.margin_line_edit = QLineEdit()
        self.margin_line_edit.setObjectName("MarginInput")
        self.margin_line_edit.setSizePolicy(QSizePolicy.MinimumExpanding,
                                            QSizePolicy.Minimum)
        self.margin_line_edit.resize(self.margin_line_edit.sizeHint().width(),
                                     self.margin_line_edit.sizeHint().height())
        self.margin_line_edit.setVisible(False)
        self.margin_line_edit.setValidator(
            QRegularExpressionValidator(
                QRegularExpression("^[0-9]*[.]?[0-9]*$")))
        self.manipulate_roi_window_input_container_box.addRow(
            self.margin_label, self.margin_line_edit)

        # Create a label for denoting the new ROI name
        self.new_roi_name_label = QLabel()
        self.new_roi_name_label.setObjectName("NewROINameLabel")
        # Create input for the new ROI name
        self.new_roi_name_line_edit = QLineEdit()
        self.new_roi_name_line_edit.setObjectName("NewROINameInput")
        self.new_roi_name_line_edit.setSizePolicy(QSizePolicy.MinimumExpanding,
                                                  QSizePolicy.Minimum)
        self.new_roi_name_line_edit.resize(
            self.new_roi_name_line_edit.sizeHint().width(),
            self.new_roi_name_line_edit.sizeHint().height())
        self.manipulate_roi_window_input_container_box.addRow(
            self.new_roi_name_label, self.new_roi_name_line_edit)

        # Create a spacer between inputs and buttons
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        spacer.setFocusPolicy(Qt.NoFocus)
        self.manipulate_roi_window_input_container_box.addRow(spacer)

        # Create a warning message when missing inputs
        self.warning_message = QWidget()
        self.warning_message.setContentsMargins(8, 5, 8, 5)
        warning_message_layout = QHBoxLayout()
        warning_message_layout.setAlignment(QtCore.Qt.AlignLeft
                                            | QtCore.Qt.AlignLeft)

        warning_message_icon = QLabel()
        warning_message_icon.setPixmap(
            QtGui.QPixmap(
                resource_path("res/images/btn-icons/alert_icon.png")))
        warning_message_layout.addWidget(warning_message_icon)

        self.warning_message_text = QLabel()
        self.warning_message_text.setStyleSheet("color: red")
        warning_message_layout.addWidget(self.warning_message_text)
        self.warning_message.setLayout(warning_message_layout)
        self.warning_message.setVisible(False)
        self.manipulate_roi_window_input_container_box.addRow(
            self.warning_message)

        # Create a draw button
        self.manipulate_roi_window_instance_draw_button = QPushButton()
        self.manipulate_roi_window_instance_draw_button.setObjectName(
            "ManipulateRoiWindowInstanceDrawButton")
        self.manipulate_roi_window_instance_draw_button.setSizePolicy(
            QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum))
        self.manipulate_roi_window_instance_draw_button.resize(
            self.manipulate_roi_window_instance_draw_button.sizeHint().width(),
            self.manipulate_roi_window_instance_draw_button.sizeHint().height(
            ))
        self.manipulate_roi_window_instance_draw_button.setCursor(
            QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.manipulate_roi_window_instance_draw_button.clicked.connect(
            self.onDrawButtonClicked)
        self.manipulate_roi_window_input_container_box.addRow(
            self.manipulate_roi_window_instance_draw_button)

        # Create a horizontal box for saving and cancel the drawing
        self.manipulate_roi_window_cancel_save_box = QHBoxLayout()
        self.manipulate_roi_window_cancel_save_box.setObjectName(
            "ManipulateRoiWindowCancelSaveBox")
        # Create an exit button to cancel the drawing
        # Add a button to go back/exit from the application
        self.manipulate_roi_window_instance_cancel_button = QPushButton()
        self.manipulate_roi_window_instance_cancel_button.setObjectName(
            "ManipulateRoiWindowInstanceCancelButton")
        self.manipulate_roi_window_instance_cancel_button.setSizePolicy(
            QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum))
        self.manipulate_roi_window_instance_cancel_button.resize(
            self.manipulate_roi_window_instance_cancel_button.sizeHint().width(
            ),
            self.manipulate_roi_window_instance_cancel_button.sizeHint().
            height())
        self.manipulate_roi_window_instance_cancel_button.setCursor(
            QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.manipulate_roi_window_instance_cancel_button.clicked.connect(
            self.onCancelButtonClicked)
        self.manipulate_roi_window_instance_cancel_button.setProperty(
            "QPushButtonClass", "fail-button")
        icon_cancel = QtGui.QIcon()
        icon_cancel.addPixmap(
            QtGui.QPixmap(
                resource_path('res/images/btn-icons/cancel_icon.png')))
        self.manipulate_roi_window_instance_cancel_button.setIcon(icon_cancel)
        self.manipulate_roi_window_cancel_save_box.addWidget(
            self.manipulate_roi_window_instance_cancel_button)
        # Create a save button to save all the changes
        self.manipulate_roi_window_instance_save_button = QPushButton()
        self.manipulate_roi_window_instance_save_button.setObjectName(
            "ManipulateRoiWindowInstanceSaveButton")
        self.manipulate_roi_window_instance_save_button.setSizePolicy(
            QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum))
        self.manipulate_roi_window_instance_save_button.resize(
            self.manipulate_roi_window_instance_save_button.sizeHint().width(),
            self.manipulate_roi_window_instance_save_button.sizeHint().height(
            ))
        self.manipulate_roi_window_instance_save_button.setProperty(
            "QPushButtonClass", "success-button")
        icon_save = QtGui.QIcon()
        icon_save.addPixmap(
            QtGui.QPixmap(resource_path('res/images/btn-icons/save_icon.png')))
        self.manipulate_roi_window_instance_save_button.setIcon(icon_save)
        self.manipulate_roi_window_instance_save_button.clicked.connect(
            self.onSaveClicked)
        self.manipulate_roi_window_cancel_save_box.addWidget(
            self.manipulate_roi_window_instance_save_button)
        self.manipulate_roi_window_input_container_box.addRow(
            self.manipulate_roi_window_cancel_save_box)

        # Creating a horizontal box to hold the ROI view and the preview
        self.manipulate_roi_window_instance_view_box = QHBoxLayout()
        self.manipulate_roi_window_instance_view_box.setObjectName(
            "ManipulateRoiWindowInstanceViewBoxes")
        # Font for the ROI view and preview's labels
        font = QFont()
        font.setBold(True)
        font.setPixelSize(20)
        # Creating the ROI view
        self.ROI_view_box_layout = QVBoxLayout()
        self.ROI_view_box_label = QLabel()
        self.ROI_view_box_label.setFont(font)
        self.ROI_view_box_label.setAlignment(Qt.AlignHCenter)
        self.ROI_view_box_layout.addWidget(self.ROI_view_box_label)
        self.ROI_view_box_layout.addWidget(self.dicom_view)
        self.ROI_view_box_widget = QWidget()
        self.ROI_view_box_widget.setLayout(self.ROI_view_box_layout)
        # Creating the preview
        self.preview_box_layout = QVBoxLayout()
        self.preview_box_label = QLabel()
        self.preview_box_label.setFont(font)
        self.preview_box_label.setAlignment(Qt.AlignHCenter)
        self.preview_box_layout.addWidget(self.preview_box_label)
        self.preview_box_layout.addWidget(self.dicom_preview)
        self.preview_box_widget = QWidget()
        self.preview_box_widget.setLayout(self.preview_box_layout)

        # Add View and Slider into horizontal box
        self.manipulate_roi_window_instance_view_box.addWidget(
            self.ROI_view_box_widget)
        self.manipulate_roi_window_instance_view_box.addWidget(
            self.preview_box_widget)
        # Create a widget to hold the image slice box
        self.manipulate_roi_window_instance_view_widget = QWidget()
        self.manipulate_roi_window_instance_view_widget.setObjectName(
            "ManipulateRoiWindowInstanceActionWidget")
        self.manipulate_roi_window_instance_view_widget.setLayout(
            self.manipulate_roi_window_instance_view_box)

        # Create a horizontal box for containing the input fields and the
        # viewports
        self.manipulate_roi_window_main_box = QHBoxLayout()
        self.manipulate_roi_window_main_box.setObjectName(
            "ManipulateRoiWindowMainBox")
        self.manipulate_roi_window_main_box.addLayout(
            self.manipulate_roi_window_input_container_box, 1)
        self.manipulate_roi_window_main_box.addWidget(
            self.manipulate_roi_window_instance_view_widget, 11)

        # Create a new central widget to hold the horizontal box layout
        self.manipulate_roi_window_instance_central_widget = QWidget()
        self.manipulate_roi_window_instance_central_widget.setObjectName(
            "ManipulateRoiWindowInstanceCentralWidget")
        self.manipulate_roi_window_instance_central_widget.setLayout(
            self.manipulate_roi_window_main_box)

        self.retranslate_ui(self.manipulate_roi_window_instance)
        self.manipulate_roi_window_instance.setStyleSheet(stylesheet)
        self.manipulate_roi_window_instance.setCentralWidget(
            self.manipulate_roi_window_instance_central_widget)
        QtCore.QMetaObject.connectSlotsByName(
            self.manipulate_roi_window_instance)
Пример #13
0
    def setupUi(self):
        """
        Constructs the GUI and sets the limit of each input field.
        """
        # Create a vertical Widget to hold Vertical Layout
        self.vertical_layout_widget = QWidget()
        self.vertical_layout = QtWidgets.QVBoxLayout()

        # Create a Widget and set layout to a GridLayout
        self.gridLayoutWidget = QWidget()
        self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setSizeConstraint(QLayout.SetDefaultConstraint)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setVerticalSpacing(0)

        # Create horizontal spacer in the middle of the grid
        hspacer = QtWidgets.QSpacerItem(QtWidgets.QSizePolicy.Expanding,
                                        QtWidgets.QSizePolicy.Minimum)
        self.gridLayout.addItem(hspacer, 0, 5, 16, 1)

        # Labels
        self.fixed_image_label = QLabel("Fixed Image: ")
        fixed_image_sizePolicy = QSizePolicy(QSizePolicy.Maximum,
                                             QSizePolicy.Preferred)
        fixed_image_sizePolicy.setHorizontalStretch(0)
        fixed_image_sizePolicy.setVerticalStretch(0)
        fixed_image_sizePolicy.setHeightForWidth(
            self.fixed_image_label.sizePolicy().hasHeightForWidth())

        self.fixed_image_label.setAlignment(Qt.AlignRight | Qt.AlignTrailing
                                            | Qt.AlignVCenter)

        self.fixed_image_placeholder \
            = QLabel("This is a placeholder for fixed image")
        self.fixed_image_placeholder.setWordWrap(False)
        self.fixed_image_placeholder.setText(str(self.fixed_image))
        self.fixed_image_placeholder.setMaximumSize(200, 50)

        self.moving_image_label = QLabel("Moving Image: ")
        moving_image_label_sizePolicy = QSizePolicy(QSizePolicy.Maximum,
                                                    QSizePolicy.Maximum)
        moving_image_label_sizePolicy.setHorizontalStretch(0)
        moving_image_label_sizePolicy.setVerticalStretch(0)
        moving_image_label_sizePolicy.setHeightForWidth(
            self.moving_image_label.sizePolicy().hasHeightForWidth())
        self.moving_image_label.setSizePolicy(moving_image_label_sizePolicy)

        self.moving_image_placeholder = QLabel("This is a placeholder")
        self.moving_image_placeholder.setWordWrap(False)
        self.moving_image_placeholder.setText(str(self.moving_image))
        self.moving_image_placeholder.setMaximumSize(200, 50)

        self.gridLayout.addWidget(self.fixed_image_label, 0, 0)
        self.gridLayout.addWidget(self.fixed_image_placeholder, 0, 1)
        self.gridLayout.addWidget(self.moving_image_label, 0, 2)
        self.gridLayout.addWidget(self.moving_image_placeholder, 0, 3)

        # Default Numbers
        self.default_numbers_label = QLabel("Default Numbers")
        self.default_numbers_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                                | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.default_numbers_label, 1, 0)

        self.default_number_spinBox = QSpinBox(self.gridLayoutWidget)
        self.default_number_spinBox.setRange(-2147483648, 2147483647)
        self.default_number_spinBox.setSizePolicy(QSizePolicy.Minimum,
                                                  QSizePolicy.Fixed)
        self.default_number_spinBox.setToolTip(
            "Default voxel value. Defaults to -1000.")
        self.gridLayout.addWidget(self.default_number_spinBox, 1, 1)

        # Final Interp
        self.interp_order_label = QLabel("Final Interp")
        self.interp_order_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                             | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.interp_order_label, 2, 0)

        self.interp_order_spinbox = QSpinBox(self.gridLayoutWidget)
        self.interp_order_spinbox.setSizePolicy(QSizePolicy.Minimum,
                                                QSizePolicy.Fixed)
        self.interp_order_spinbox.setToolTip("The final interpolation order.")
        self.gridLayout.addWidget(self.interp_order_spinbox, 2, 1)

        # Metric
        self.metric_label = QLabel("Metric")
        self.metric_label.setAlignment(QtCore.Qt.AlignLeft | Qt.AlignTrailing
                                       | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.metric_label, 3, 0)

        self.metric_comboBox = QComboBox()
        self.metric_comboBox.addItem("correlation")
        self.metric_comboBox.addItem("mean_squares")
        self.metric_comboBox.addItem("mattes_mi")
        self.metric_comboBox.addItem("joint_hist_mi")
        self.metric_comboBox.setToolTip(
            "The metric to be optimised during image registration.")
        self.gridLayout.addWidget(self.metric_comboBox, 3, 1)

        # Number of Iterations
        self.no_of_iterations_label = QLabel("Number of Iterations")
        self.no_of_iterations_label.setAlignment(Qt.AlignLeft
                                                 | Qt.AlignTrailing
                                                 | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.no_of_iterations_label, 4, 0)

        self.no_of_iterations_spinBox = QSpinBox(self.gridLayoutWidget)
        self.no_of_iterations_spinBox.setSizePolicy(QSizePolicy.Minimum,
                                                    QSizePolicy.Fixed)
        self.no_of_iterations_spinBox.setRange(0, 100)
        self.no_of_iterations_spinBox.setToolTip(
            "Number of iterations in each multi-resolution step.")
        self.gridLayout.addWidget(self.no_of_iterations_spinBox, 4, 1)

        # Shrink Factor
        self.shrink_factor_label = QLabel("Shrink Factor")
        self.shrink_factor_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                              | Qt.AlignVCenter)

        self.gridLayout.addWidget(self.shrink_factor_label, 5, 0)

        self.shrink_factor_qLineEdit = QLineEdit()
        self.shrink_factor_qLineEdit.resize(
            self.shrink_factor_qLineEdit.sizeHint().width(),
            self.shrink_factor_qLineEdit.sizeHint().height())

        self.shrink_factor_qLineEdit.setValidator(
            QRegularExpressionValidator(
                QRegularExpression("^[0-9]*[,]?[0-9]*[,]?[0-9]")))

        self.shrink_factor_qLineEdit.setToolTip(
            "The multi-resolution downsampling factors. Can be up to three "
            "integer elements in an array. Example [8, 2, 1]")
        self.gridLayout.addWidget(self.shrink_factor_qLineEdit, 5, 1)

        # Optimiser
        self.optimiser_label = QLabel("Optimiser")
        self.optimiser_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                          | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.optimiser_label, 1, 2)

        self.optimiser_comboBox = QComboBox(self.gridLayoutWidget)
        self.optimiser_comboBox.addItem("lbfgsb")
        self.optimiser_comboBox.addItem("gradient_descent")
        self.optimiser_comboBox.addItem("gradient_descent_line_search")
        self.optimiser_comboBox.setToolTip(
            "The optimiser algorithm used for image registration.")
        self.gridLayout.addWidget(self.optimiser_comboBox, 1, 3)

        # Reg Method
        self.reg_method_label = QLabel("Reg Method")
        self.reg_method_label.setAlignment(QtCore.Qt.AlignLeft
                                           | Qt.AlignTrailing
                                           | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.reg_method_label, 2, 2)

        self.reg_method_comboBox = QComboBox()
        self.reg_method_comboBox.addItem("translation")
        self.reg_method_comboBox.addItem("rigid")
        self.reg_method_comboBox.addItem("similarity")
        self.reg_method_comboBox.addItem("affine")
        self.reg_method_comboBox.addItem("scaleversor")
        self.reg_method_comboBox.addItem("scaleskewversor")
        self.reg_method_comboBox.setToolTip(
            "The linear transformation model to be used for image "
            "registration.")
        self.gridLayout.addWidget(self.reg_method_comboBox, 2, 3)

        # Sampling Rate
        self.sampling_rate_label = QLabel("Sampling Rate")
        self.sampling_rate_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                              | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.sampling_rate_label, 3, 2)

        self.sampling_rate_spinBox = QDoubleSpinBox(self.gridLayoutWidget)
        self.sampling_rate_spinBox.setMinimum(0)
        self.sampling_rate_spinBox.setMaximum(1)
        self.sampling_rate_spinBox.setSingleStep(0.01)
        self.sampling_rate_spinBox.setSizePolicy(QSizePolicy.Minimum,
                                                 QSizePolicy.Fixed)
        self.sampling_rate_spinBox.setToolTip("The fraction of voxels sampled "
                                              "during each iteration.")
        self.gridLayout.addWidget(self.sampling_rate_spinBox, 3, 3)

        # Smooth Sigmas
        self.smooth_sigma_label = QLabel("Smooth Sigma")
        self.smooth_sigma_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                             | Qt.AlignVCenter)
        self.gridLayout.addWidget(self.smooth_sigma_label, 4, 2)

        self.smooth_sigmas_qLineEdit = QLineEdit()
        self.smooth_sigmas_qLineEdit.resize(
            self.smooth_sigmas_qLineEdit.sizeHint().width(),
            self.smooth_sigmas_qLineEdit.sizeHint().height())
        self.smooth_sigmas_qLineEdit.setValidator(
            QRegularExpressionValidator(
                QRegularExpression("^[0-9]*[,]?[0-9]*[,]?[0-9]")))
        self.smooth_sigmas_qLineEdit.setToolTip(
            "The multi-resolution smoothing kernal scale (Gaussian). Can be "
            "up to three integer elements in an array. Example [4, 2, 1]")
        self.gridLayout.addWidget(self.smooth_sigmas_qLineEdit, 4, 3)

        # Label to hold warning labels.
        self.warning_label = QLabel()

        # Button for fast mode
        self.fast_mode_button = QtWidgets.QPushButton("Fast Mode")
        self.fast_mode_button.setCursor(
            QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.fast_mode_button.clicked.connect(self.set_fast_mode)

        # Add Widgets to the vertical layout
        self.vertical_layout.addWidget(self.fast_mode_button)
        self.vertical_layout.addWidget(self.gridLayoutWidget)
        self.vertical_layout.addWidget(self.warning_label)

        # Set layout of frame to the gridlayout widget
        self.auto_image_fusion_frame.setLayout(self.vertical_layout)