예제 #1
0
    def init_ui(self):
        self.setWindowTitle("About")
        self.setFixedSize(550, 190)
        layout = QVBoxLayout()
        about_text = QLabel(
            "Here it is. In your hands you have music generator using neural network."
            "\nWith enough midi files you can create basically any kind of song."
            "\nFor more details and instruction visit our github by clicking this link: ",
            self)
        about_text.move(10, 20)

        link = QLabel()
        link.setText(
            '''<a href='https://github.com/Bananasis/PytonMusic-Inc.'>PytonMusic-Inc</a>'''
        )
        link.setOpenExternalLinks(True)
        link.setAlignment(Qt.AlignCenter)

        authors_text = QLabel(
            "by: Dominika Szydło, Patryk Majewski, Ivan Feofilaktov and Gabriel Wechta."
        )

        layout.addWidget(about_text)
        layout.addWidget(link)
        layout.addWidget(authors_text)

        main_widget = QWidget()
        main_widget.setLayout(layout)
        main_widget.adjustSize()
        # self.about_text.adjustSize()

        self.setCentralWidget(main_widget)
        self.center()
예제 #2
0
    def adjust(self, width, height, scrollValue):
        QWidget.adjustSize(self)
        self.mwindow.adjustSize()
        self.mwindow.resize(width, height)

        if scrollValue:
            self.sequenceTable.verticalScrollBar().setScrollValue(value=scrollValue)
예제 #3
0
def restoreGeom(
    widget: QWidget, key: str, offset: Optional[int] = None, adjustSize: bool = False
) -> None:
    key += "Geom"
    if aqt.mw.pm.profile.get(key):
        widget.restoreGeometry(aqt.mw.pm.profile[key])
        if isMac and offset:
            if qtminor > 6:
                # bug in osx toolkit
                s = widget.size()
                widget.resize(s.width(), s.height() + offset * 2)
        ensureWidgetInScreenBoundaries(widget)
    else:
        if adjustSize:
            widget.adjustSize()
예제 #4
0
def exceptionRaised():
    ater = "N/C"
    from traceback import print_exc
    tps = int(time.time())
    print_exc(file=open(f"./log/log_{tps}.txt", "w"))

    app_error = QApplication(sys.argv)
    win_error = QWidget()
    win_error.setGeometry(80, 80, 50, 50)
    win_error.setWindowTitle("Error Script")
    win_error.show()

    label_error = QLabel(win_error)
    label_error.setText(
        f"Une exception a été levée : {str(ater)}\n\n\n\n {open(f'./log/log_{tps}.txt').read()}"
    )
    label_error.setStyleSheet("font-weight: bold;")
    label_error.setFont(QFont('Mangal', 10))
    label_error.move(20, 20)
    label_error.adjustSize()
    label_error.show()

    temp = Online()
    del temp

    if Donnees.online_final:
        bouton_send_error = QPushButton(win_error)
        bouton_send_error.setText("Envoyer rapport d'erreur")
        bouton_send_error.clicked.connect(
            lambda: uploadftp(f"log_{tps}.txt", "./log/"))
        bouton_send_error.move(20, 60)
        bouton_send_error.show()

    win_error.adjustSize()

    sys.exit(app_error.exec_())
예제 #5
0
class GridWindow(QWidget):
    def __init__(self, dashboard):
        super(GridWindow, self).__init__(None)
        with open('dashboard/gui/stylesheet.txt', "r") as file:
            self.setStyleSheet(file.read())
        self.setWindowTitle('Timing grid')
        self.setObjectName('timingGrid')
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.dashboard = dashboard
        self.picklable = False
        # self.dashboard.test_signal.connect(lambda: self.insert_step('test', 0))
        # self.dashboard.test_signal.connect(lambda: self.swap_timesteps('load', 'probe'))

        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        self.selector_layout = QHBoxLayout()
        self.sequence_selector = QComboBox()
        for item in self.dashboard.get('artiq/sequences'):
            self.sequence_selector.addItem(item)
        self.sequence_selector.currentTextChanged.connect(self.activate)
        self.selector_layout.addWidget(self.sequence_selector)
        self.store_button = IconButton(
            'dashboard/gui/media/Material/content-save.svg', self.store)
        self.selector_layout.addWidget(self.store_button)
        self.delete_button = IconButton(
            'dashboard/gui/media/Material/trash.svg', self.delete)
        self.selector_layout.addWidget(self.delete_button)
        self.selector_layout.addWidget(
            IconButton('dashboard/gui/media/Material/content-add.svg',
                       self.insert_step))

        self.selector_layout.addWidget(
            IconButton('dashboard/gui/media/Material/outline-play-arrow.svg',
                       self.play))
        self.layout.addLayout(self.selector_layout)

        self.widget = QWidget()
        self.grid_layout = QGridLayout()
        self.widget.setLayout(self.grid_layout)
        self.layout.addWidget(self.widget)

        # self.add_table()
        self.add_labels()
        timesteps = self.dashboard.get('artiq/sequence')
        self.draw(timesteps)

        # self.dashboard.timestep_signal.connect(self.bold_active_step)
        self.dashboard.sequence_update_signal.connect(self.refresh)

    def activate(self, sequence):
        self.dashboard.post('artiq/activate', {'sequence': sequence})

    def delete(self):
        name = self.sequence_selector.currentText()
        if name == 'default':
            return
        self.dashboard.post('artiq/delete', {'name': name})
        self.sequence_selector.removeItem(
            self.sequence_selector.currentIndex())

    def store(self):
        name, ok = QInputDialog.getText(self, 'New sequence',
                                        'Enter preset name:')
        if not ok:
            return
        self.dashboard.post('artiq/store', {'name': name})
        self.sequence_selector.addItem(name)
        self.sequence_selector.setCurrentIndex(self.sequence_selector.count() -
                                               1)

    def push_sequence(self):
        self.dashboard.post('artiq/sequence', self.get_sequence())

    def add_table(self):
        self.ttls = self.dashboard.get('artiq/ttl')
        self.table = SequencerTable()
        timesteps = self.dashboard.get('artiq/sequence')
        self.table.set_channels(self.ttls)
        for step in timesteps:
            self.table.add_timestep(self.ttls, step)
        self.grid_layout.addWidget(self.table, 0, 0)
        self.table.adjustSize()
        self.widget.adjustSize()
        self.adjustSize()

    def add_labels(self):
        ''' Create TTL labels '''
        self.ttls = self.dashboard.get('artiq/ttl')
        label = BoldLabel('TTL')
        label.setBold(True)
        self.grid_layout.addWidget(label, 2, 0)
        row = 3

        for ttl in self.ttls:
            name = str(ttl)
            if type(self.ttls) is dict:
                name += ': %s' % str(self.ttls[ttl])
            self.grid_layout.addWidget(ttlLabel(name, channel=ttl, grid=self),
                                       row, 0)
            row += 1
        ''' Create ADC labels '''
        self.adcs = self.dashboard.get('artiq/adc')
        label = BoldLabel('ADC')
        label.setBold(True)
        self.grid_layout.addWidget(label, row, 0)
        row += 1
        for adc in self.adcs:
            label = str(adc)
            if type(self.adcs) is dict:
                label += ': %s' % str(self.adcs[adc])
            self.grid_layout.addWidget(QLabel(label), row, 0)
            row += 1
        ''' Create DAC labels '''
        self.dacs = self.dashboard.get('artiq/dac')
        label = BoldLabel('DAC')
        label.setBold(True)
        self.grid_layout.addWidget(label, row, 0)
        row += 1
        for dac in self.dacs:
            self.grid_layout.addWidget(QLabel(str(dac)), row, 0)
            row += 1
        #
        # ''' Create DDS labels '''
        # self.dds = self.dashboard.get('artiq/dds')
        # self.grid_layout.addWidget(QLabel('DDS'), row, 0)
        # row += 1
        # for dds in self.dds:
        #     self.grid_layout.addWidget(QLabel(str(dds)), row, 0)
        #     row += 1
    def refresh(self, sequence=None):
        # if sequence is None:
        sequence = self.dashboard.get('artiq/sequence')
        self.redraw(sequence)

    def draw(self, sequence):
        self.order = []
        self.labels = []
        self.step_edits = []
        self.checkboxes = []
        self.adc_checkboxes = []
        self.dac_edits = []
        col = 1
        row = 0
        for step in sequence:
            row = self.add_step(step, col)
            col += 1
        total_cycle_time = self.get_cycle_time() * 1000
        self.total_time_label = QLabel('%.1f ms' % total_cycle_time)
        self.grid_layout.addWidget(QLabel('Cycle time:'), row, 0)
        self.grid_layout.addWidget(self.total_time_label, row, 1)
        # self.bold_active_step()
        QApplication.processEvents()  # determine new minimumSize
        self.resize(self.minimumSize())

    def redraw(self, sequence):
        for step in range(len(self.labels)):
            self.remove_step_widgets(step)
        self.grid_layout.removeWidget(self.total_time_label)
        self.total_time_label.deleteLater()
        self.draw(sequence)

    def update_cycle_time(self):
        total_cycle_time = self.get_cycle_time() * 1000
        self.total_time_label.setText('%.1f ms' % total_cycle_time)

    def get_cycle_time(self):
        T = 0
        for edit in self.step_edits:
            T += edit.magnitude
        return T

    def get_sequence(self):
        sequence = []
        for i in range(len(self.labels)):
            name = self.labels[i].name
            new_step = {}
            new_step['duration'] = self.step_edits[i].magnitude
            new_step['name'] = name
            new_step['TTL'] = []
            new_step['ADC'] = []
            new_step['DAC'] = {}
            for ttl in self.ttls:
                if self.checkboxes[i][ttl].isChecked():
                    new_step['TTL'].append(ttl)
            for adc in self.adcs:
                if self.adc_checkboxes[i][adc].isChecked():
                    new_step['ADC'].append(adc)
            for dac in self.dacs:
                new_step['DAC'][int(dac)] = float(
                    self.dac_edits[i][dac].text())
            sequence.append(new_step)
        return sequence

    def add_step(self, step, col):
        name = step['name']
        ''' Add label and edit '''
        self.order.append(name)
        self.labels.append(StepLabel(name, self, col - 1))
        self.grid_layout.addWidget(self.labels[-1], 0, col)
        self.step_edits.append(
            StepEdit(name, str(step['duration']), self.dashboard, self))
        self.grid_layout.addWidget(self.step_edits[-1], 1, col)
        ''' Add TTL checkboxes '''
        row = 3
        self.checkboxes.append({})
        for switch in self.ttls:
            state = 0
            if int(switch) in step['TTL'] or str(switch) in step['TTL']:
                state = 1
            box = StateCheckbox(name, step, state, self.dashboard, self)
            self.grid_layout.addWidget(box, row, col)
            self.checkboxes[-1][switch] = box
            row += 1
        ''' Add ADC checkboxes '''
        self.adc_checkboxes.append({})
        row += 1
        for adc in self.adcs:
            state = 0
            if int(adc) in step['ADC'] or str(adc) in step['ADC']:
                state = 1
            box = StateCheckbox(name, step, state, self.dashboard, self)
            self.grid_layout.addWidget(box, row, col)
            self.adc_checkboxes[-1][adc] = box
            row += 1
        ''' Add DAC edits '''
        self.dac_edits.append({})
        row += 1
        for dac in self.dacs:
            if int(dac) in step['DAC']:
                value = float(step['DAC'][int(dac)])
            elif str(dac) in step['DAC']:
                value = float(step['DAC'][str(dac)])
            else:
                value = 0.0
            edit = DACEdit(name, str(value), self.dashboard, self)
            self.grid_layout.addWidget(edit, row, col)
            self.dac_edits[-1][dac] = edit
            row += 1
        return row

    def remove_step(self, i):
        ''' Removes the step labeled by i '''
        self.remove_step_widgets(i)
        self.step_edits.pop(i)
        self.labels.pop(i)
        self.checkboxes.pop(i)
        self.adc_checkboxes.pop(i)
        self.dac_edits.pop(i)
        for j in range(i, len(self.labels)):
            self.labels[j].index -= 1
        self.redraw(self.get_sequence())

        self.push_sequence()

    def remove_step_widgets(self, step):
        remove = [
            self.labels[step], self.step_edits[step],
            *self.checkboxes[step].values(),
            *self.adc_checkboxes[step].values(),
            *self.dac_edits[step].values()
        ]
        # for ttl in self.ttls:
        #     remove.append(self.checkboxes[step][ttl])
        # for adc in self.adcs:
        #     remove.append(self.adc_checkboxes[step][adc])
        # for dac in self.dacs:
        #     remove.append(self.dac_edits[step][dac])
        for widget in remove:
            self.grid_layout.removeWidget(widget)
            widget.deleteLater()

    #
    # def bold_active_step(self, current_step=None):
    #     steps = self.dashboard.get('artiq/sequence')
    #     if current_step is None:
    #         current_step = self.dashboard.get('artiq/current_step')
    #     else:
    #         current_step = current_step['name']
    #     for step in steps:
    #         if step['name'] == current_step:
    #             self.labels[step['name']].setBold(True)
    #         else:
    #             self.labels[step['name']].setBold(False)

    def insert_step(self, name=''):
        step = {
            'name': '',
            'duration': 0,
            'TTL': [],
            'ADC': [],
            'DAC': {},
            'DDS': {}
        }
        steps = self.get_sequence()
        steps.append(step)
        self.redraw(steps)

        self.dashboard.post('artiq/sequence', steps)

    def move(self, step, n):
        ''' Moves the passed step (integer or string) n places to the left (negative n)
            or right (positive n). '''
        steps = self.get_sequence()
        i = 0
        for s in self.order:
            if s == step:
                break
            i += 1
        if (i + n) < 0 or (i + n) > len(steps) - 1:
            return

        i_n = i
        for n0 in range(np.abs(n)):
            d_i = np.sign(n)
            adjacent_step = self.order[i_n + d_i]
            self.swap_timesteps(step, adjacent_step)
            steps.insert(i_n + d_i, steps.pop(i_n))
            self.order.insert(i_n + d_i, self.order.pop(i_n))
            i_n += d_i

        self.dashboard.post('artiq/sequence', steps)

    # def swap(self, row1, col1, row2, col2):
    #     ''' Swaps two widgets '''
    #     widget1 = self.grid_layout.itemAtPosition(row1, col1).widget()
    #     widget2 = self.grid_layout.itemAtPosition(row2, col2).widget()
    #     self.grid_layout.removeWidget(widget1)
    #     self.grid_layout.removeWidget(widget2)
    #     self.grid_layout.addWidget(widget1, row2, col2)
    #     self.grid_layout.addWidget(widget2, row1, col1)
    #
    # def swap_columns(self, col1, col2):
    #     header_rows = [0, 1]        # headers
    #     ttl_rows = list(range(header_rows[-1]+2, header_rows[-1]+2+len(self.ttls)))
    #     header_rows.extend(ttl_rows)
    #     adc_rows = list(range(ttl_rows[-1]+2, ttl_rows[-1]+2+len(self.adcs)))
    #     header_rows.extend(adc_rows)
    #     dac_rows = list(range(adc_rows[-1]+2, adc_rows[-1]+2+len(self.dacs)))
    #     header_rows.extend(dac_rows)
    #
    #     for row in header_rows:
    #         self.swap(row, col1, row, col2)
    #         time.sleep(1e-6)            # need a short pause here or Qt will crash

    # def swap_timesteps(self, name1, name2):
    #     widget1 = self.labels[name1]
    #     index1 = self.grid_layout.indexOf(widget1)
    #     row1, col1, rowspan, colspan = self.grid_layout.getItemPosition(index1)
    #     widget2 = self.labels[name2]
    #     index2 = self.grid_layout.indexOf(widget2)
    #     row2, col2, rowspan, colspan = self.grid_layout.getItemPosition(index2)
    #
    #     self.swap_columns(col1, col2)

    def play(self):
        print(self.get_sequence())

        import os
        os.system(
            'start "" cmd /k "cd /emergent/emergent/artiq/ & call activate artiq-4 & artiq_run sequencer_loop.py"'
        )
예제 #6
0
class MainWindow(QMainWindow):
    def __init__(self, config: Config, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setWindowTitle("FolderPlay by Hurlenko")
        self.setWindowIcon(main_icon())
        self.config = config
        self.central_widget = None
        self.set_style()

        self.basic_view_widget = BasicViewWidget(self)
        self.basic_view_widget.btn_advanced.clicked.connect(
            self.toggle_advanced_view
        )

        self.settings_widget = SettingsWidget(self)
        self.settings_widget.hide()

        # Media list
        self.lst_media = QListWidget(self)
        self.setup_files_list()

        # Left Pane
        self.left_pane = QWidget(self)
        self.left_pane.setLayout(self.left_pane_layout())
        self.left_pane.layout().setContentsMargins(0, 0, 0, 0)
        self.left_pane.layout().setSpacing(0)

        # Right pane
        self.right_pane = QWidget(self)
        self.right_pane.setLayout(self.right_pane_layout())
        self.right_pane.layout().setContentsMargins(0, 0, 0, 0)
        self.right_pane.layout().setSpacing(0)
        self.right_pane.hide()

        average_char_width = self.fontMetrics().averageCharWidth()
        self.left_pane_width = average_char_width * (MAX_MOVIE_TITLE_LENGTH + 5)
        self.right_pane_width = self.left_pane_width * 2

        self.left_pane.setFixedWidth(self.left_pane_width)
        self.right_pane.setFixedWidth(self.right_pane_width)
        self.central_widget.setLayout(self.advanced_view_layout())

    def set_style(self):
        icons = IconSet[self.config.iconset]
        IconSet.set_current(icons)

        style = Style[self.config.style]

        if style in (Style.dark, Style.light):
            self.central_widget = ModernWindow(self)
        else:
            self.central_widget = QWidget(self)
        style.apply(QApplication.instance())
        self.setCentralWidget(self.central_widget)

    def left_pane_layout(self):
        layout = QVBoxLayout()
        layout.addWidget(self.basic_view_widget)
        layout.addWidget(self.settings_widget)
        return layout

    def right_pane_layout(self):
        layout = QVBoxLayout()
        layout.addWidget(self.lst_media)
        return layout

    def advanced_view_layout(self):
        layout = QHBoxLayout()
        layout.addWidget(self.left_pane)
        layout.addWidget(self.right_pane)

        return layout

    def center(self):
        frame_gm = self.frameGeometry()
        screen = QApplication.desktop().screenNumber(
            QApplication.desktop().cursor().pos()
        )
        center_point = QApplication.desktop().screenGeometry(screen).center()
        frame_gm.moveCenter(center_point)
        self.move(frame_gm.topLeft())

    def toggle_advanced_view(self):
        # QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)
        # self.adjustSize()
        if not self.basic_view_widget.btn_advanced.isChecked():
            self.settings_widget.hide()
            self.right_pane.hide()
        else:
            self.settings_widget.show()
            self.right_pane.show()

        self.reset()

    def reset(self):
        QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)
        self.adjustSize()
        # https://stackoverflow.com/a/30472749/8014793
        # self.setFixedSize(self.layout().sizeHint())
        # self.central_widget.adjustSize()
        QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)

        self.central_widget.adjustSize()
        QApplication.processEvents(QEventLoop.ExcludeUserInputEvents)
        self.setFixedSize(self.layout().sizeHint())

        # self.setFixedSize(self.central_widget.sizeHint())
        self.center()

    def setup_play_button(self):
        self.btn_play.setIcon(IconSet.current.play)
        self.btn_play.setIconSize(QSize(100, 100))

    def setup_files_list(self):
        size_policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.lst_media.setSizePolicy(size_policy)
        self.lst_media.setSelectionMode(QAbstractItemView.ExtendedSelection)
        # self.lst_media.setSortingEnabled(True)
        self.lst_media.setContextMenuPolicy(Qt.CustomContextMenu)
class PyRegExpWizardCharactersDialog(
        QDialog, Ui_PyRegExpWizardCharactersDialog):
    """
    Class implementing a dialog for entering character classes.
    """
    specialChars = {
        4: "\\a",
        5: "\\f",
        6: "\\n",
        7: "\\r",
        8: "\\t",
        9: "\\v"
    }
    
    predefinedClasses = ["\\s", "\\S", "\\w", "\\W", "\\d", "\\D"]
    
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent parent widget (QWidget)
        """
        super(PyRegExpWizardCharactersDialog, self).__init__(parent)
        self.setupUi(self)
        
        self.comboItems = []
        self.singleComboItems = []      # these are in addition to the above
        self.comboItems.append(self.tr("Normal character"))
        self.comboItems.append(
            self.tr("Unicode character in hexadecimal notation"))
        self.comboItems.append(
            self.tr("Unicode character in octal notation"))
        self.singleComboItems.append(self.tr("---"))
        self.singleComboItems.append(self.tr("Bell character (\\a)"))
        self.singleComboItems.append(self.tr("Page break (\\f)"))
        self.singleComboItems.append(self.tr("Line feed (\\n)"))
        self.singleComboItems.append(self.tr("Carriage return (\\r)"))
        self.singleComboItems.append(self.tr("Horizontal tabulator (\\t)"))
        self.singleComboItems.append(self.tr("Vertical tabulator (\\v)"))
        
        self.charValidator = QRegExpValidator(QRegExp(".{0,1}"), self)
        self.hexValidator = QRegExpValidator(QRegExp("[0-9a-fA-F]{0,4}"), self)
        self.octValidator = QRegExpValidator(QRegExp("[0-3]?[0-7]{0,2}"), self)
        
        # generate dialog part for single characters
        self.singlesBoxLayout = QVBoxLayout(self.singlesBox)
        self.singlesBoxLayout.setObjectName("singlesBoxLayout")
        self.singlesBoxLayout.setSpacing(6)
        self.singlesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesBox.setLayout(self.singlesBoxLayout)
        self.singlesView = QScrollArea(self.singlesBox)
        self.singlesView.setObjectName("singlesView")
        self.singlesBoxLayout.addWidget(self.singlesView)
        
        self.singlesItemsBox = QWidget(self)
        self.singlesView.setWidget(self.singlesItemsBox)
        self.singlesItemsBox.setObjectName("singlesItemsBox")
        self.singlesItemsBoxLayout = QVBoxLayout(self.singlesItemsBox)
        self.singlesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesItemsBoxLayout.setSpacing(6)
        self.singlesItemsBox.setLayout(self.singlesItemsBoxLayout)
        self.singlesEntries = []
        self.__addSinglesLine()
        
        hlayout0 = QHBoxLayout()
        hlayout0.setContentsMargins(0, 0, 0, 0)
        hlayout0.setSpacing(6)
        hlayout0.setObjectName("hlayout0")
        self.moreSinglesButton = QPushButton(
            self.tr("Additional Entries"), self.singlesBox)
        self.moreSinglesButton.setObjectName("moreSinglesButton")
        hlayout0.addWidget(self.moreSinglesButton)
        hspacer0 = QSpacerItem(
            30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        hlayout0.addItem(hspacer0)
        self.singlesBoxLayout.addLayout(hlayout0)
        self.moreSinglesButton.clicked.connect(self.__addSinglesLine)
        
        # generate dialog part for character ranges
        self.rangesBoxLayout = QVBoxLayout(self.rangesBox)
        self.rangesBoxLayout.setObjectName("rangesBoxLayout")
        self.rangesBoxLayout.setSpacing(6)
        self.rangesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesBox.setLayout(self.rangesBoxLayout)
        self.rangesView = QScrollArea(self.rangesBox)
        self.rangesView.setObjectName("rangesView")
        self.rangesBoxLayout.addWidget(self.rangesView)
        
        self.rangesItemsBox = QWidget(self)
        self.rangesView.setWidget(self.rangesItemsBox)
        self.rangesItemsBox.setObjectName("rangesItemsBox")
        self.rangesItemsBoxLayout = QVBoxLayout(self.rangesItemsBox)
        self.rangesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesItemsBoxLayout.setSpacing(6)
        self.rangesItemsBox.setLayout(self.rangesItemsBoxLayout)
        self.rangesEntries = []
        self.__addRangesLine()
        
        hlayout1 = QHBoxLayout()
        hlayout1.setContentsMargins(0, 0, 0, 0)
        hlayout1.setSpacing(6)
        hlayout1.setObjectName("hlayout1")
        self.moreRangesButton = QPushButton(
            self.tr("Additional Entries"), self.rangesBox)
        self.moreSinglesButton.setObjectName("moreRangesButton")
        hlayout1.addWidget(self.moreRangesButton)
        hspacer1 = QSpacerItem(
            30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        hlayout1.addItem(hspacer1)
        self.rangesBoxLayout.addLayout(hlayout1)
        self.moreRangesButton.clicked.connect(self.__addRangesLine)
        
    def __addSinglesLine(self):
        """
        Private slot to add a line of entry widgets for single characters.
        """
        hbox = QWidget(self.singlesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        cb1.addItems(self.comboItems)
        cb1.addItems(self.singleComboItems)
        hboxLayout.addWidget(cb1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        cb2 = QComboBox(hbox)
        cb2.setEditable(False)
        cb2.addItems(self.comboItems)
        cb2.addItems(self.singleComboItems)
        hboxLayout.addWidget(cb2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        self.singlesItemsBoxLayout.addWidget(hbox)
        
        cb1.activated[int].connect(self.__singlesCharTypeSelected)
        cb2.activated[int].connect(self.__singlesCharTypeSelected)
        hbox.show()
        
        self.singlesItemsBox.adjustSize()
        
        self.singlesEntries.append([cb1, le1])
        self.singlesEntries.append([cb2, le2])
        
    def __addRangesLine(self):
        """
        Private slot to add a line of entry widgets for character ranges.
        """
        hbox = QWidget(self.rangesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        cb1.addItems(self.comboItems)
        hboxLayout.addWidget(cb1)
        l1 = QLabel(self.tr("Between:"), hbox)
        hboxLayout.addWidget(l1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        l2 = QLabel(self.tr("And:"), hbox)
        hboxLayout.addWidget(l2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        self.rangesItemsBoxLayout.addWidget(hbox)
        
        cb1.activated[int].connect(self.__rangesCharTypeSelected)
        
        hbox.show()
        
        self.rangesItemsBox.adjustSize()
        
        self.rangesEntries.append([cb1, le1, le2])
        
    def __performSelectedAction(self, index, lineedit):
        """
        Private method performing some actions depending on the input.
        
        @param index selected list index (integer)
        @param lineedit line edit widget to act on (QLineEdit)
        """
        if index < 3:
            lineedit.setEnabled(True)
            if index == 0:
                lineedit.setValidator(self.charValidator)
            elif index == 1:
                lineedit.setValidator(self.hexValidator)
            elif index == 2:
                lineedit.setValidator(self.octValidator)
        elif index > 3:
            lineedit.setEnabled(False)
        lineedit.clear()
        
    def __singlesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the single chars
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.singlesEntries:
            if combo == entriesList[0]:
                self.__performSelectedAction(index, entriesList[1])
                break
        
    def __rangesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the char ranges
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.rangesEntries:
            if combo == entriesList[0]:
                self.__performSelectedAction(index, entriesList[1])
                self.__performSelectedAction(index, entriesList[2])
                break
        
    def __formatCharacter(self, index, char):
        """
        Private method to format the characters entered into the dialog.
        
        @param index selected list index (integer)
        @param char character string enetered into the dialog (string)
        @return formated character string (string)
        """
        if index == 0:
            return char
        elif index == 1:
            return "\\x{0}".format(char.lower())
        elif index == 2:
            return "\\0{0}".format(char)
        else:
            try:
                return self.specialChars[index]
            except KeyError:
                return ""
        
    def getCharacters(self):
        """
        Public method to return the character string assembled via the dialog.
        
        @return formatted string for character classes (string)
        """
        regexp = ""
        
        # negative character range
        if self.negativeCheckBox.isChecked():
            regexp += "^"
            
        # predefined character ranges
        if self.wordCharCheckBox.isChecked():
            regexp += "\\w"
        if self.nonWordCharCheckBox.isChecked():
            regexp += "\\W"
        if self.digitsCheckBox.isChecked():
            regexp += "\\d"
        if self.nonDigitsCheckBox.isChecked():
            regexp += "\\D"
        if self.whitespaceCheckBox.isChecked():
            regexp += "\\s"
        if self.nonWhitespaceCheckBox.isChecked():
            regexp += "\\S"
            
        # single characters
        for entrieslist in self.singlesEntries:
            index = entrieslist[0].currentIndex()
            char = entrieslist[1].text()
            regexp += self.__formatCharacter(index, char)
        
        # character ranges
        for entrieslist in self.rangesEntries:
            if entrieslist[1].text() == "" or \
               entrieslist[2].text() == "":
                continue
            index = entrieslist[0].currentIndex()
            char1 = entrieslist[1].text()
            char2 = entrieslist[2].text()
            regexp += "{0}-{1}".format(
                self.__formatCharacter(index, char1),
                self.__formatCharacter(index, char2))
        
        if regexp:
            if (len(regexp) == 2 and
                (regexp in self.predefinedClasses or
                 regexp in self.specialChars)) or \
               len(regexp) == 1:
                return regexp
            else:
                return "[{0}]".format(regexp)
        else:
            return ""
class Ui_SmainWindow(object):
   
    def setupUi(self, SmainWindow): 
        width = QDesktopWidget().screenGeometry().width()
        height = QDesktopWidget().screenGeometry().height()
        '''screen_resolution = app.desktop().screenGeometry()
                                width, height = screen_resolution.width(), screen_resolution.height()'''
        SmainWindow.setObjectName("SmainWindow")
        SmainWindow.resize((3400/3840)*width,(1700/2160)*height)
        SmainWindow.setMaximumSize(QtCore.QSize((3400/3840)*width,(1700/2160)*height))
        SmainWindow.setMinimumSize(QtCore.QSize((3400/3840)*width,(1700/2160)*height))
        self.centralwidget = QtWidgets.QWidget(SmainWindow)
        self.centralwidget.setObjectName("centralwidget")

        self.line = QtWidgets.QFrame(self.centralwidget)
        self.line.setGeometry(QtCore.QRect((20/3840)*width, (1070/2160)*height ,(3300/3840)*width, (30/2160)*height))
        self.line.setFrameShape(QtWidgets.QFrame.HLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setLineWidth(5)
        self.line.setObjectName("line")

        self.line2 = QtWidgets.QFrame(self.centralwidget)
        self.line2.setGeometry(QtCore.QRect((1440/3840)*width, (290/2160)*height ,(30/3840)*width, (700/2160)*height))
        self.line2.setFrameShape(QtWidgets.QFrame.VLine)
        self.line2.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line2.setLineWidth(5)
        self.line2.setObjectName("line2")

        self.line3 = QtWidgets.QFrame(self.centralwidget)
        self.line3.setGeometry(QtCore.QRect((2290/3840)*width, (290/2160)*height ,(30/3840)*width, (700/2160)*height))
        self.line3.setFrameShape(QtWidgets.QFrame.VLine)
        self.line3.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line3.setLineWidth(5)
        self.line3.setObjectName("line3")
       

        self.layout = QVBoxLayout(self.centralwidget)
        self.fig = Figure(figsize=((8/3840)*width, (6.5/2160)*height ))
        self.canvas = FigureCanvas(self.fig)
        self.layout.addWidget(self.canvas)

        self.widget = QWidget(self.centralwidget)
        #self.toolbar = NavigationToolbar(self.canvas, self.widget)
        self.layout.setMenuBar(NavigationToolbar(self.canvas,self.widget))
        self.widget.setLayout(self.layout)
        self.widget.setGeometry((1480/3840)*width,(290/2160)*height,(800/3840)*width,(600/2160)*height)
        
        
        
        
        
        #layout.addWidget(self.canvas)
        '''
        self.graphicsView = PlotWidget(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(700, 150, 700, 700))
        self.graphicsView.setObjectName("graphicsView")
        '''
        self.chartView = QChartView(self.centralwidget)
        self.chartView.setGeometry(QtCore.QRect((200/3840)*width, (1090/2160)*height, (1700/3840)*width, (500/2160)*height))
        self.chartView.setObjectName("graphicsView")


        self.browseFile = QtWidgets.QPushButton(self.centralwidget)
        self.browseFile.setGeometry(QtCore.QRect((200/3840)*width, (50/2160)*height, (350/3840)*width, (50/2160)*height))
        self.browseFile.setObjectName("browseFile")


        self.filenameLabel = QtWidgets.QLabel(self.centralwidget)
        self.filenameLabel.setGeometry(QtCore.QRect((700/3840)*width, (55/2160)*height, (350/3840)*width, (70/2160)*height))
        self.filenameLabel.setObjectName("filenameLabel")

        self.datasize = QtWidgets.QLabel(self.centralwidget)
        self.datasize.setGeometry(QtCore.QRect((20/3840)*width, (105/2160)*height, (350/3840)*width, (70/2160)*height))
        self.datasize.setObjectName("datasize")
        self.datasize.setText("Data Shape :")
        self.datasize.setStyleSheet(
        """QLabel {
                           font: bold;
                           font-size: 10pt;
                           font-family: Typograf;}""")

        self.datashape = QtWidgets.QLabel(self.centralwidget)
        self.datashape.setGeometry(QtCore.QRect((250/3840)*width, (105/2160)*height, (350/3840)*width, (70/2160)*height))
        self.datashape.setObjectName("datashape")
        self.datashape.setStyleSheet(
        """QLabel {
                           font: bold;
                           font-size: 12pt;
                           font-family: Typograf;}""")

        self.atributelabe = QtWidgets.QLabel(self.centralwidget)
        self.atributelabe.setGeometry(QtCore.QRect((295/3840)*width, (200/2160)*height, (350/3840)*width, (70/2160)*height))
        self.atributelabe.setObjectName("atributelabe")
        self.atributelabe.setText("Variables")
        self.atributelabe.setStyleSheet(
        """QLabel {
                           font: bold;
                           font-size: 10pt;
                           font-family: Typograf;}""")

        self.statisticlabel = QtWidgets.QLabel(self.centralwidget)
        self.statisticlabel.setGeometry(QtCore.QRect((1020/3840)*width, (200/2160)*height, (350/3840)*width, (70/2160)*height))
        self.statisticlabel.setObjectName("statisticlabel")
        self.statisticlabel.setText("Statistics")
        self.statisticlabel.setStyleSheet(
        """QLabel {
                           font: bold;
                           font-size: 10pt;
                           font-family: Typograf;}""")
        
        self.textBrowser = QtWidgets.QTextBrowser(self.centralwidget)
        self.textBrowser.setGeometry(QtCore.QRect((740/3840)*width, (290/2160)*height, (700/3840)*width, (700/2160)*height))
        self.textBrowser.setObjectName("textBrowser")
        self.textBrowser.setStyleSheet(
        """QTextBrowser {
                           font: bold;
                           font-size: 12pt;
                           font-family: Courier;}""")

        self.missingvalulabel = QtWidgets.QLabel(self.centralwidget)
        self.missingvalulabel.setGeometry(QtCore.QRect((2330/3840)*width, (500/2160)*height, (250/3840)*width, (100/2160)*height))
        self.missingvalulabel.setObjectName("missingvalulabel")
        self.missingvalulabel.setText("Show Missing \nValues")
        self.missingvalulabel.setStyleSheet(
        """QLabel {
                           font: bold;
                           font-size: 10pt;
                           font-family: Courier;}""")
        
        self.resetbtn = QtWidgets.QPushButton(self.centralwidget)
        self.resetbtn.setGeometry(QtCore.QRect((2330/3840)*width, (300/2160)*height, (250/3840)*width, (50/2160)*height))
        self.resetbtn.setObjectName("resetbtn")
        self.resetbtn.setText("Reset")
        self.resetbtn.setEnabled(False)

        self.perclm = QtWidgets.QPushButton(self.centralwidget)
        self.perclm.setGeometry(QtCore.QRect((2330/3840)*width, (600/2160)*height, (250/3840)*width, (50/2160)*height))
        self.perclm.setObjectName("perclm")
        self.perclm.setText("PerColumn")
        self.perclm.setEnabled(False)

        self.perrow = QtWidgets.QPushButton(self.centralwidget)
        self.perrow.setGeometry(QtCore.QRect((2330/3840)*width, (670/2160)*height, (250/3840)*width, (50/2160)*height))
        self.perrow.setObjectName("perrow")
        self.perrow.setText("PerRow")
        self.perrow.setEnabled(False)

        self.datainfo = QtWidgets.QLabel(self.centralwidget)
        self.datainfo.setGeometry(QtCore.QRect((2850/3840)*width, (200/2160)*height, (350/3840)*width, (70/2160)*height))
        self.datainfo.setObjectName("statisticlabel")
        self.datainfo.setText("Data Info")
        self.datainfo.setStyleSheet(
        """QLabel {
                           font: bold;
                           font-size: 10pt;
                           font-family: Typograf;}""")
        
        self.infor = QtWidgets.QTextBrowser(self.centralwidget)
        self.infor.setGeometry(QtCore.QRect((2600/3840)*width, (290/2160)*height, (700/3840)*width, (700/2160)*height))
        self.infor.setObjectName("infor")
        self.infor.setStyleSheet(
        """QTextBrowser {
                           font: bold;
                           font-family: Courier;}""")

       
       
        self.calstatistics = QtWidgets.QPushButton(self.centralwidget)
        self.calstatistics.setGeometry(QtCore.QRect((200/3840)*width, (1020/2160)*height, (350/3840)*width, (50/2160)*height))
        self.calstatistics.setObjectName("calstatistics")
        

        self.listWidget = QtWidgets.QListWidget(self.centralwidget)
        self.listWidget.setGeometry(QtCore.QRect((20/3840)*width, (290/2160)*height, (700/3840)*width, (700/2160)*height))
        self.listWidget.setObjectName("listWidget")
        self.listWidget.setAlternatingRowColors(True)
       


        self.comboBox = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox.setGeometry(QtCore.QRect((1480/3840)*width,(120/2160)*height,(800/3840)*width,(50/2160)*height))
        self.comboBox.setObjectName("comboBox")

        self.comboBox2 = QtWidgets.QComboBox(self.centralwidget)
        self.comboBox2.setGeometry(QtCore.QRect((1480/3840)*width,(200/2160)*height,(800/3840)*width,(50/2160)*height))
        self.comboBox2.setObjectName("comboBox2")

        self.report = QtWidgets.QPushButton(self.centralwidget)
        self.report.setGeometry(QtCore.QRect((1700/3840)*width, (1020/2160)*height, (300/3840)*width, (50/2160)*height))
        self.report.setObjectName("report")
        self.report.setText("Generate Report")



        self.back = QtWidgets.QPushButton(self.centralwidget)
        self.back.setGeometry(QtCore.QRect((5/3840)*width, (1600/2160)*height, (300/3840)*width, (50/2160)*height))
        self.back.setObjectName("back")
        self.back.setText("Back")
        self.back.setStyleSheet(
        """QPushButton {
                           
                             
border-radius:0;
border:0;

text-align:left;
padding-left:70px;
qproperty-icon:url('back.png');
qproperty-iconSize: 40px 40px;}""")






        SmainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(SmainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, (469/3840)*width, (22/2160)*height))
        self.menubar.setObjectName("menubar")
        SmainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(SmainWindow)
        self.statusbar.setObjectName("statusbar")
        SmainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(SmainWindow)
        QtCore.QMetaObject.connectSlotsByName(SmainWindow)

        




    def retranslateUi(self, SmainWindow):
        _translate = QtCore.QCoreApplication.translate
        SmainWindow.setWindowTitle(_translate("SmainWindow", "Data Statistical Analysis"))
        self.browseFile.setText(_translate("SmainWindow", "Open File"))
        self.browseFile.clicked.connect(self.pushButton_handler)
        self.filenameLabel.setText(_translate("SmainWindow", ""))
        self.calstatistics.setText(_translate("SmainWindow", "Calculate Statistics"))
        self.calstatistics.clicked.connect(self.cal)
        self.listWidget.clicked.connect(self.listview_clicked)

        self.resetbtn.clicked.connect(self.information)
        self.perclm.clicked.connect(self.num_missing)
        self.perrow.clicked.connect(self.row_missing)
        self.report.clicked.connect(self.generatereport)


            
        
        

    def pushButton_handler(self):
        self.open_dialog_box()

    def open_dialog_box(self):
        filename = QFileDialog.getOpenFileName(None, 'Open File', r"~/Desktop", '*.csv')
        path = filename[0]

        with open(path, "r") as fpath:
            self.infor.clear()
            self.comboBox.clear()
            self.comboBox2.clear()
            self.datasetheaders=[]
            self.filenameLabel.setText(str(path))
            self.filenameLabel.adjustSize()
            pandas.set_option('display.max_rows', None)
            self.dataset=pandas.read_csv(fpath)
            buf = io.StringIO()
            self.dataset.info(verbose=True, null_counts=True,buf=buf)
            s = buf.getvalue()
            self.perclm.setDisabled(False)
            self.perrow.setDisabled(False)

            self.infor.append(s)
            SIZE=self.dataset.shape
            self.datashape.setText(str(SIZE))
            self.create_piechart()
            #headers=self.dataset.columns
            self.datasetheaders=self.dataset.columns.to_numpy()
            self.listWidget.clear()
          
            for i in range(len(self.datasetheaders)-1):
                self.listWidget.insertItem(i,self.datasetheaders[i])

            for i in range(len(self.datasetheaders)-1):
                self.comboBox.addItem(self.datasetheaders[i])

            for i in range(len(self.datasetheaders)-1):
                self.comboBox2.addItem(self.datasetheaders[i])    
                
           

            self.setup()

            self.comboBox.currentIndexChanged.connect(self.setup)
            self.comboBox2.currentIndexChanged.connect(self.setup)

            #print(unique_headers)

            '''print ("Missing values per column:")
                                                print(self.dataset.apply(lambda x: sum(x.isnull()))) 
                                    '''


    def generatereport(self):
        try:
            profile = ProfileReport(self.dataset)
            profile.to_file(output_file="AnalysisReport.html")
            print("yes")
        except Exception as e:
            print(repr(e))

        
    def information(self):
        self.infor.clear()
        self.resetbtn.setEnabled(False)
        self.perrow.setDisabled(False)
        self.perclm.setDisabled(False)
        buf = io.StringIO()
        self.dataset.info(verbose=True, null_counts=True,buf=buf)
        s = buf.getvalue()

        self.infor.append(s)

      
            

            
        



    def row_missing(self):
        self.perrow.setEnabled(False)
        self.perclm.setDisabled(False)
        self.resetbtn.setDisabled(False)
        self.infor.clear()
       
        #self.infor.append(str(self.dataset.apply(lambda x: sum(x.isnull()))))
        self.infor.append(str(self.dataset.apply(self.missing, axis=1)))

        
    def num_missing(self):
        self.perclm.setEnabled(False)
        self.perrow.setDisabled(False)
        self.resetbtn.setDisabled(False)
        self.infor.clear()
        #self.infor.append(str(self.dataset.apply(lambda x: sum(x.isnull()))))
        self.infor.append(str(self.dataset.apply(self.missing, axis=0)))
         
    def missing(self,x):
        return sum(x.isnull())




         
 
    def setup(self):
        try:
            print("fig")
            iris=self.dataset 
        
       


            x_index = 0
            y_index = 1
            w=iris.iloc[:,self.comboBox.currentIndex()]
            z=iris.iloc[:,self.comboBox2.currentIndex()]

            y=iris.iloc[:,-1].values

            # this formatter will label the colorbar with the correct target names
            #formatter = plt.FuncFormatter(y)

            #plt.figure(figsize=(5, 4))
        
            ax = self.fig.add_subplot(111)
            ax.clear()
            scatter=ax.scatter(w, z, c=y)
        
            #self.figure.colorbar(ticks=y)

            #ax.xlabel("iris.feature_names[x_index]")
            #ax.ylabel("iris.feature_names[y_index]")
            ax.set_xlabel(self.comboBox.currentText(),  fontsize=25) 
            ax.set_ylabel(self.comboBox2.currentText(), fontsize=25)
            ax.set_title('Scatter Plot',fontsize=25)

            legend1 = ax.legend(*scatter.legend_elements(),
                    loc="lower left", title="Classes")
            ax.add_artist(legend1)

            self.widget.adjustSize()
        

            print("fig123456789")

        except Exception as e:
            print(repr(e)) 
               

        
        

        


    def cal(self):
        #self.graphicsView.clear()
        z=self.dataset
        w=z.iloc[:,self.a]
     
        self.textBrowser.setText("Mean:\n"+str(np.mean(w))+"\nMedian:\n"+str(np.median(w))+"\nMode:\n"+str(stats.mode(w))+"\nvariance:\n"+str(np.var(w))+"\nStdev:\n"+str(np.std(w)))
        #self.textBrowser.adjustSize()
        '''
        pen = pg.mkPen(color=(255, 0, 0),width=8)
        self.graphicsView.setBackground('w')
        self.graphicsView.plot(w,symbol='+',symbolSize=30, pen=pen)
        '''
       


    def listview_clicked(self):
        item=self.listWidget.currentRow()
        self.a=item

    def create_piechart(self):
       
        z=self.dataset
        w=z.iloc[:,-1]
        r=w.value_counts()
        p=r.to_numpy()
        y=w.nunique()
       
      
        df_val_counts = pandas.DataFrame(r)
        df_val_counts = df_val_counts.reset_index()
        df_val_counts.columns = ['unique_values', 'counts']
        
        w=df_val_counts.iloc[:,0].to_numpy()
        k=df_val_counts.iloc[:,1].to_numpy()
        res = w.astype(str)
       
        series = QPieSeries()
        for i in range(y):
            series.append(res[i], k[i])
        

        
        
        chart = self.chartView.chart()
        chart.removeAllSeries()
        chart.legend().hide()
        chart.addSeries(series)
        chart.createDefaultAxes()
        
        chart.setAnimationOptions(QChart.AllAnimations)
        chart.setTitle("Pie Chart")
        
        
        chart.legend().setVisible(True)
        chart.legend().setAlignment(Qt.AlignBottom)
      
        #self.chartView = QChartView(chart)
        self.chartView.setRenderHint(QPainter.Antialiasing)
예제 #9
0
    class PythonTogether:
        
        def __init__(self,
                    win: QMainWindow,
                    winParent: QWidget,
                    open: QWidget) -> None:
            """
            Tous les utilitaires pour PTProject
            """

            self.win = win
            self.winParent = winParent
            self.open = open

            self.online = Online()

            self.winParent.setVisible(False)
            self.win.setWindowTitle("Python Together")

            self.a, self.b = 1280, 720
            self.x, self.y = center(self.a, self.b)
            self.win.setGeometry(self.x, self.y, self.a, self.b)
            self.win.show()

            self.label = QLabel(self.win)
            self.label.setText("Python Together 0.1")
            self.label.setFont(QFont('Mangal', 50))
            self.label.adjustSize()
            self.label.show()
            self.label.move(20,10)

            self.bouton1 = QPushButton(self.win)
            self.bouton1.setText("Revenir en arrière")
            self.bouton1.move(20, 100)
            self.bouton1.adjustSize()
            self.bouton1.clicked.connect(
                lambda: (self.winParent.setVisible(True), self.win.close()))
            self.bouton1.show()

            self.winEdit = QWidget(self.win)
            self.winEdit.setGeometry(0, 120, 1260, 600)
            self.winEdit.adjustSize()
            self.winEdit.show()
            self.layout = QVBoxLayout(self.winEdit)

            self.textEdit = QTextEdit()
            # self.text.move(20, 120)
            self.textEdit.setFont(QFont('Mangal', 15))
            self.textEdit.show()

            self.layout.addWidget(self.textEdit)
            self.winEdit.setLayout(self.layout)

            self.menuBar = QMenuBar(self.win)
            self.win.setMenuBar(self.menuBar)

            # Menu Bar
            self.fileMenu = QMenu("&Fichier", self.win)

            self.openAction = QAction("&Ouvrir", self.win)
            self.openAction.triggered.connect(self.openproject)
            self.openAction.setShortcut("Ctrl+O")

            self.saveAction = QAction("&Sauvegarder", self.win)
            self.saveAction.triggered.connect(self.saveFile)
            self.saveAction.setShortcut("Ctrl+S")

            self.saveOnlineAction = QAction("&Sauver en ligne", self.win)
            self.saveOnlineAction.triggered.connect(self.saveOnline)
            self.saveOnlineAction.setShortcut("Ctrl+Shift+S")

            self.loadOnlineAction = QAction("&Charger en ligne (Soon)", self.win)
            self.loadOnlineAction.triggered.connect(self.loadOnline)
            self.loadOnlineAction.setShortcut("Ctrl+Shift+O")

            self.fileMenu.addAction(self.openAction)
            self.fileMenu.addAction(self.saveAction)
            
            if Donnees.online:
                self.fileMenu.addAction(self.saveOnlineAction)
                self.fileMenu.addAction(self.loadOnlineAction)

            self.menuBar.addMenu(self.fileMenu)

        def openproject(self):

            self.open.setGeometry(50,50,200,200)
            self.open.setWindowTitle("Ouvrir")
            self.open.show()

            self.label11 = QLabel(self.open)
            self.label11.setText("Ouvrir fichier local\n(dans dossier ptprojects)")
            self.label11.move(20, 20)
            self.label11.show()

            self.champ = QLineEdit(self.open)
            self.champ.move(20, 60)
            self.champ.resize(160, 20)
            self.champ.show()

            self.bouton = QPushButton(self.open)
            self.bouton.setText("Ouvrir")
            self.bouton.move(20,90)
            self.bouton.clicked.connect(self.openFile)
            self.bouton.show()

        def openFile(self):
            try:
                with open("./module/ptprojects/"+self.champ.text(), "r") as f:
                    Donnees.ptfile = f.read()
                    Donnees.nameFileProject = self.champ.text()
                    self.label.setText(self.champ.text())
                    self.label.adjustSize()
                    self.textEdit.setText(Donnees.ptfile)
                    self.open.close()
            except:
                from traceback import print_exc
                print_exc()
                self.label11.setText("Impossible d'ouvrir")
        
        def saveFile(self):

            try:
                with open("./module/ptprojects/"+Donnees.nameFileProject, "w") as f:
                    f.write(self.textEdit.toPlainText())

            except:
                if Donnees.online:
                    a = f"{Donnees.current_user['user']}_python_{int(time.time())}.py"
                    with open(f"./module/ptprojects/{a}", "w") as f:
                        f.write(self.textEdit.toPlainText())
                        Donnees.nameFileProject = a
                        self.label.setText(a)
                        self.label.adjustSize()
                
                elif not Donnees.online:
                    a = f'python_{int(time.time())}.py'
                    with open(f"./module/ptprojects/{a}", "w") as f:
                        f.write(self.textEdit.toPlainText())
                        Donnees.nameFileProject = a
                        self.label.setText(a)
                        self.label.adjustSize()
        
        def saveOnline(self):
            self.online.uploadftp(Donnees.nameFileProject, "./module/ptprojects/")
            self.saveFile()
        
        def loadOnline(self):
            pass
class TemplateMultipleVariablesDialog(QDialog):
    """
    Class implementing a dialog for entering multiple template variables.
    """

    def __init__(self, variables, parent=None):
        """
        Constructor
        
        @param variables list of template variable names (list of strings)
        @param parent parent widget of this dialog (QWidget)
        """
        super(TemplateMultipleVariablesDialog, self).__init__(parent)

        self.TemplateMultipleVariablesDialogLayout = QVBoxLayout(self)
        self.TemplateMultipleVariablesDialogLayout.setContentsMargins(6, 6, 6, 6)
        self.TemplateMultipleVariablesDialogLayout.setSpacing(6)
        self.TemplateMultipleVariablesDialogLayout.setObjectName("TemplateMultipleVariablesDialogLayout")
        self.setLayout(self.TemplateMultipleVariablesDialogLayout)

        # generate the scrollarea
        self.variablesView = QScrollArea(self)
        self.variablesView.setObjectName("variablesView")
        self.TemplateMultipleVariablesDialogLayout.addWidget(self.variablesView)

        self.variablesView.setWidgetResizable(True)
        self.variablesView.setFrameStyle(QFrame.NoFrame)

        self.top = QWidget(self)
        self.variablesView.setWidget(self.top)
        self.grid = QGridLayout(self.top)
        self.grid.setContentsMargins(0, 0, 0, 0)
        self.grid.setSpacing(6)
        self.top.setLayout(self.grid)

        # populate the scrollarea with labels and text edits
        self.variablesEntries = {}
        row = 0
        for var in variables:
            label = QLabel("{0}:".format(var), self.top)
            self.grid.addWidget(label, row, 0, Qt.Alignment(Qt.AlignTop))
            if var.find(":") >= 0:
                formatStr = var[1:-1].split(":")[1]
                if formatStr in ["ml", "rl"]:
                    t = QTextEdit(self.top)
                    t.setTabChangesFocus(True)
                else:
                    t = QLineEdit(self.top)
            else:
                t = QLineEdit(self.top)
            self.grid.addWidget(t, row, 1)
            self.variablesEntries[var] = t
            row += 1
        # add a spacer to make the entries aligned at the top
        spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.grid.addItem(spacer, row, 1)
        self.variablesEntries[variables[0]].setFocus()
        self.top.adjustSize()

        # generate the buttons
        layout1 = QHBoxLayout()
        layout1.setContentsMargins(0, 0, 0, 0)
        layout1.setSpacing(6)
        layout1.setObjectName("layout1")

        spacer1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        layout1.addItem(spacer1)

        self.okButton = QPushButton(self)
        self.okButton.setObjectName("okButton")
        self.okButton.setDefault(True)
        layout1.addWidget(self.okButton)

        self.cancelButton = QPushButton(self)
        self.cancelButton.setObjectName("cancelButton")
        layout1.addWidget(self.cancelButton)

        spacer2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        layout1.addItem(spacer2)

        self.TemplateMultipleVariablesDialogLayout.addLayout(layout1)

        # set the texts of the standard widgets
        self.setWindowTitle(self.tr("Enter Template Variables"))
        self.okButton.setText(self.tr("&OK"))
        self.cancelButton.setText(self.tr("&Cancel"))

        # polish up the dialog
        self.resize(QSize(400, 480).expandedTo(self.minimumSizeHint()))

        self.okButton.clicked.connect(self.accept)
        self.cancelButton.clicked.connect(self.reject)

    def getVariables(self):
        """
        Public method to get the values for all variables.
        
        @return dictionary with the variable as a key and its value (string)
        """
        values = {}
        for var, textEdit in list(self.variablesEntries.items()):
            try:
                values[var] = textEdit.text()
            except AttributeError:
                values[var] = textEdit.toPlainText()
        return values
예제 #11
0
class Popup(QDialog):
    def __init__(self, schedule: Schedule, parent=None, edit_data=None):
        super(Popup, self).__init__(parent)
        self.schedule = schedule
        self.event_name, self.data = edit_data if edit_data is not None else (
            None, None)
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.setWindowTitle("Add New Scheduled Notes" if edit_data is None else
                            "Edit {} Details".format(self.event_name))

        self.layout = QVBoxLayout()
        self.layout.setSpacing(0)
        self.form_layout = QFormLayout()
        self.form_layout.setContentsMargins(0, 0, 0,
                                            self.form_layout.verticalSpacing())
        self.form_layout_widget = QWidget()
        self.form_layout_widget.setLayout(self.form_layout)

        #The amount of fields in the form that come before the block section (name, #blocks, start, end date, color)
        self.rows_before_blocks = 3

        self.event_type = QPushButton()
        event_type_menu = QMenu()
        event_type_menu.addAction("Class")
        event_type_menu.addSection("Event")
        event_type_menu.addAction("One Time Event")
        event_type_menu.addAction("Recurring Event")
        event_type_menu.addAction("One Time Class Event")
        for action in event_type_menu.actions():
            if not action.isSeparator():
                action.triggered.connect(
                    lambda state, x=action.text(): self.set_type(x))
        self.event_type.setMenu(event_type_menu)
        self.form_layout.addRow("Type:", self.event_type)

        #Class Title
        self.name_edit = QLineEdit()
        self.form_layout.addRow("Name:", self.name_edit)
        #Color
        self.color_picker = QColorDialog()
        self.color_button = QPushButton("Pick Color")
        self.color_button.clicked.connect(self.color_picker.open)
        self.color_picker.currentColorChanged.connect(self.update_color)
        self.form_layout.addRow("Color Code:", self.color_button)

        # Initialize widgets to be added later
        self.start_date_model = DateTimePickerSeriesModel(self)
        self.class_start_date = DateTimePickerSeries(self.start_date_model,
                                                     "MMM d yyyy")
        self.event_start_date = DateTimePickerSeries(self.start_date_model,
                                                     "MMM d yyyy")

        self.end_date_model = DateTimePickerSeriesModel(self)
        self.class_end_date = DateTimePickerSeries(self.end_date_model,
                                                   "MMM d yyyy")
        self.event_end_date = DateTimePickerSeries(self.end_date_model,
                                                   "MMM d yyyy")

        self.event_date_model = DateTimePickerSeriesModel(self)
        self.class_event_date = DateTimePickerSeries(self.event_date_model,
                                                     "MMM d yyyy hh:mm:AP")
        self.event_date = DateTimePickerSeries(self.event_date_model,
                                               "MMM d yyyy hh:mm:AP")

        # Blocks
        self.blocks = 1
        self.spin_box = QSpinBox()
        self.spin_box.setValue(1)
        self.spin_box.setMinimum(1)
        self.spin_box.setMaximum(7)
        self.spin_box.valueChanged.connect(self.update_blocks)

        self.class_picker = QPushButton()
        class_picker_menu = QMenu()
        for class_name in self.schedule.schedule.keys():
            if self.schedule.schedule[class_name]["type"] != "class":
                continue
            class_action = QAction(class_name, parent=class_picker_menu)
            class_action.triggered.connect(lambda state, x=class_action.text():
                                           self.class_picker.setText(x))
            class_picker_menu.addAction(class_action)
        class_picker_menu.aboutToShow.connect(
            lambda: class_picker_menu.setMinimumWidth(self.class_picker.width(
            )))
        self.class_picker.setMenu(class_picker_menu)

        self.stack = QStackedWidget()
        self.stack.setContentsMargins(0, 0, 0, 0)

        class_layout = QFormLayout()
        class_layout.setContentsMargins(0, 0, 0,
                                        class_layout.verticalSpacing())
        class_layout.addRow("Start Date:", self.class_start_date)
        class_layout.addRow("End Date:", self.class_end_date)
        class_layout.addRow("Weekly Blocks:", self.spin_box)
        class_layout.addRow("Block Time:", ClassTimePicker())
        self.class_options = QWidget()
        self.class_options.setSizePolicy(QSizePolicy.Ignored,
                                         QSizePolicy.Ignored)
        self.class_options.setLayout(class_layout)

        recurring_event_layout = QFormLayout()
        recurring_event_layout.setContentsMargins(
            0, 0, 0, recurring_event_layout.verticalSpacing())
        recurring_event_layout.addRow("Start Date:", self.event_start_date)
        recurring_event_layout.addRow("End Date:", self.event_end_date)
        self.recurring_event_time_picker = ClassTimePicker()
        recurring_event_layout.addRow("Event Time:",
                                      self.recurring_event_time_picker)
        self.recurring_event_options = QWidget()
        self.recurring_event_options.setSizePolicy(QSizePolicy.Ignored,
                                                   QSizePolicy.Ignored)
        self.recurring_event_options.setLayout(recurring_event_layout)

        one_time_event_layout = QFormLayout()
        one_time_event_layout.setContentsMargins(
            0, 0, 0, one_time_event_layout.verticalSpacing())
        one_time_event_layout.addRow("Event Date:", self.event_date)
        self.one_time_event_options = QWidget()
        self.one_time_event_options.setSizePolicy(QSizePolicy.Ignored,
                                                  QSizePolicy.Ignored)
        self.one_time_event_options.setLayout(one_time_event_layout)

        class_event_layout = QFormLayout()
        class_event_layout.setContentsMargins(
            0, 0, 0, class_event_layout.verticalSpacing())
        class_event_layout.addRow("Class:", self.class_picker)
        class_event_layout.addRow("Event Date:", self.class_event_date)
        self.class_event_options = QWidget()
        self.class_event_options.setSizePolicy(QSizePolicy.Ignored,
                                               QSizePolicy.Ignored)
        self.class_event_options.setLayout(class_event_layout)

        self.stack.addWidget(self.class_event_options)
        self.stack.addWidget(self.one_time_event_options)
        self.stack.addWidget(self.recurring_event_options)
        self.stack.addWidget(self.class_options)

        if self.data is None:
            self.set_type("Class")

        self.layout.addWidget(self.form_layout_widget)
        self.layout.addWidget(self.stack)
        self.setLayout(self.layout)
        self.show_buttons()

        #Update Values if self.data is defined
        if self.data is not None:
            event_type = self.data["type"]
            self.set_type(camel_case(event_type))
            # noinspection PyTypeChecker
            class_layout: QFormLayout = self.stack.currentWidget().layout()
            self.name_edit.setText(self.event_name)
            self.name_edit.setDisabled(True)
            self.color_picker.setCurrentColor(to_qcolor(self.data["color"]))
            if event_type in ["class", "recurring event"]:
                self.start_date_model.content = QDateTime(
                    to_qdate(self.data["start"]))
                self.end_date_model.content = QDateTime(
                    to_qdate(self.data["end"]))
            if event_type == "class":
                blocks = self.data["blocks"]
                self.update_blocks(len(blocks))
                for i, row in enumerate(
                        range(self.rows_before_blocks,
                              class_layout.rowCount())):
                    block = blocks[i]
                    # noinspection PyTypeChecker
                    block_widget: ClassTimePicker = class_layout.itemAt(
                        row, QFormLayout.FieldRole).widget()
                    block_widget.set_time(to_qtime(block["time"]))
                    block_widget.set_day(block["day"])
            if event_type == "recurring event":
                self.recurring_event_time_picker.set_day(self.data["day"])
                self.recurring_event_time_picker.set_time(
                    to_qtime(self.data["time"]))
            if event_type in ["one time event", "one time class event"]:
                date_time = QDateTime()
                date_time.setDate(to_qdate(self.data["date"]))
                date_time.setTime(to_qtime(self.data["time"]))
                self.event_date_model.content = date_time
            if event_type == "one time class event":
                self.class_picker.setText(self.data["class_name"])

    def show_buttons(self):
        save_button = QDialogButtonBox.Save if self.data is None else QDialogButtonBox.Apply
        cancel_button = QDialogButtonBox.Cancel
        buttonBox = QDialogButtonBox(Qt.Horizontal)
        buttonBox.addButton(save_button).clicked.connect(self.accept)
        buttonBox.addButton(cancel_button).clicked.connect(self.reject)
        if self.data is not None:
            delete_button = buttonBox.addButton(QDialogButtonBox.Discard)
            delete_button.setText("Delete")
            delete_button.clicked.connect(self.delete_event)
        self.layout.addWidget(buttonBox)

    def set_type(self, event_type: str):
        if self.event_type.text() == event_type:
            return
        self.event_type.setText(event_type)
        self.stack.currentWidget().setSizePolicy(QSizePolicy.Ignored,
                                                 QSizePolicy.Ignored)
        if event_type == "Class":
            self.class_options.setSizePolicy(QSizePolicy.Expanding,
                                             QSizePolicy.Expanding)
            self.class_options.adjustSize()
            self.stack.setCurrentWidget(self.class_options)
        elif event_type == "Recurring Event":
            self.recurring_event_options.setSizePolicy(QSizePolicy.Expanding,
                                                       QSizePolicy.Expanding)
            self.recurring_event_options.adjustSize()
            self.stack.setCurrentWidget(self.recurring_event_options)
        elif event_type == "One Time Event":
            self.one_time_event_options.setSizePolicy(QSizePolicy.Expanding,
                                                      QSizePolicy.Expanding)
            self.one_time_event_options.adjustSize()
            self.stack.setCurrentWidget(self.one_time_event_options)
        elif event_type == "One Time Class Event":
            self.class_event_options.setSizePolicy(QSizePolicy.Expanding,
                                                   QSizePolicy.Expanding)
            self.class_event_options.adjustSize()
            self.stack.setCurrentWidget(self.class_event_options)
        self.stack.adjustSize()
        max_width = 0
        for i in range(self.form_layout.rowCount()):
            widget = self.form_layout.itemAt(i, QFormLayout.LabelRole).widget()
            widget.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
            widget.adjustSize()
            max_width = max(widget.size().width(), max_width)
        # noinspection PyTypeChecker
        current_widget_layout: QFormLayout = self.stack.currentWidget().layout(
        )
        for i in range(current_widget_layout.rowCount()):
            widget = current_widget_layout.itemAt(
                i, QFormLayout.LabelRole).widget()
            widget.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
            widget.adjustSize()
            max_width = max(widget.size().width(), max_width)
        for i in range(self.form_layout.rowCount()):
            self.form_layout.itemAt(
                i, QFormLayout.LabelRole).widget().setMinimumWidth(max_width)
        for i in range(current_widget_layout.rowCount()):
            current_widget_layout.itemAt(
                i, QFormLayout.LabelRole).widget().setMinimumWidth(max_width)
        self.adjustSize()

    def update_color(self):
        self.color_button.setStyleSheet(
            "background-color: rgb({},{},{})".format(
                self.color_picker.currentColor().red(),
                self.color_picker.currentColor().green(),
                self.color_picker.currentColor().blue()))

    def update_blocks(self, value):
        if self.spin_box.value() != value:
            self.spin_box.setValue(value)
            return
        if self.blocks == value:
            return
        old_blocks = self.blocks
        self.blocks = value
        class_options_layout: QFormLayout = self.class_options.layout()
        if self.blocks > old_blocks:
            #Change label of block 1
            if old_blocks == 1:
                class_options_layout.itemAt(
                    self.rows_before_blocks,
                    QFormLayout.LabelRole).widget().setText("Block 1 Time:")
            for i in range(1, self.blocks - old_blocks + 1):
                offset = self.rows_before_blocks + old_blocks + i - 1
                widget = class_options_layout.itemAt(offset,
                                                     QFormLayout.FieldRole)
                label = class_options_layout.itemAt(offset,
                                                    QFormLayout.LabelRole)
                if widget is not None and label is not None:
                    widget = widget.widget()
                    label = label.widget()
                    widget.setSizePolicy(QSizePolicy.Expanding,
                                         QSizePolicy.Expanding)
                    label.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Expanding)
                    widget.adjustSize()
                    label.adjustSize()
                    widget.show()
                    label.show()
                else:
                    picker = ClassTimePicker()
                    picker.sizePolicy().setRetainSizeWhenHidden(False)
                    class_options_layout.addRow(
                        "Block {} Time:".format(old_blocks + i), picker)
        elif self.blocks < old_blocks:
            if self.blocks == 1:
                class_options_layout.itemAt(
                    self.rows_before_blocks,
                    QFormLayout.LabelRole).widget().setText("Block Time:")
            for i in range(old_blocks - self.blocks):
                offset = self.rows_before_blocks + old_blocks + i - 1
                widget = class_options_layout.itemAt(
                    offset, QFormLayout.FieldRole).widget()
                label = class_options_layout.itemAt(
                    offset, QFormLayout.LabelRole).widget()
                widget.hide()
                label.hide()
                widget.adjustSize()
                label.adjustSize()
                self.class_options.adjustSize()
                self.stack.adjustSize()
                self.adjustSize()

        # self.class_options.adjustSize()
        # self.stack.adjustSize()
        # self.adjustSize()

    def get_name(self):
        return self.name_edit.text()

    def get_data(self):
        event_type = self.event_type.text()
        data = {
            "type": event_type.lower(),
            "name": self.get_name(),
            "color": {
                "r": self.color_picker.currentColor().red(),
                "g": self.color_picker.currentColor().green(),
                "b": self.color_picker.currentColor().blue(),
            }
        }
        if event_type == "Class":
            block_data = []
            # noinspection PyTypeChecker
            class_layout: QFormLayout = self.stack.currentWidget().layout()
            for row in range(self.rows_before_blocks, class_layout.rowCount()):
                # noinspection PyTypeChecker
                block_widget: ClassTimePicker = class_layout.itemAt(
                    row, QFormLayout.FieldRole).widget()
                if block_widget.isHidden():
                    continue
                time = block_widget.get_time()
                block_data.append({
                    "day": block_widget.day_picker.get_day(),
                    "time": {
                        "hour": time.hour(),
                        "minute": time.minute()
                    }
                })
            data["blocks"] = block_data
        if event_type in ["Class", "Recurring Event"]:
            start_date = self.start_date_model.content.date()
            data["start"] = {
                "day": start_date.day(),
                "month": start_date.month(),
                "year": start_date.year()
            }
            end_date = self.end_date_model.content.date()
            data["end"] = {
                "day": end_date.day(),
                "month": end_date.month(),
                "year": end_date.year()
            }
        if event_type == "Recurring Event":
            data["day"] = self.recurring_event_time_picker.day_picker.get_day()
            time = self.recurring_event_time_picker.get_time()
            data["time"] = {"hour": time.hour(), "minute": time.minute()}
        if event_type == "One Time Class Event":
            data["class_name"] = self.class_picker.text()
        if event_type in ["One Time Event", "One Time Class Event"]:
            date_time = self.event_date_model.content
            date = date_time.date()
            time = date_time.time()
            data["date"] = {
                "day": date.day(),
                "month": date.month(),
                "year": date.year(),
            }
            data["time"] = {"hour": time.hour(), "minute": time.minute()}
        return data

    def delete_event(self):
        error = QMessageBox()
        error.setText("Are you sure you would like to delete this event?")
        error.setStandardButtons(QMessageBox.Yes | QMessageBox.Cancel)
        result = error.exec_()
        if result == QMessageBox.Yes:
            self.schedule.delete_event(self.event_name)
            self.reject()

    def accept(self):
        event_type = self.event_type.text()
        if event_type == "":
            error = QMessageBox()
            error.setText("Please select a type for the event.")
            error.exec_()
            self.event_type.setFocus()
            return
        # Check Name
        if len(self.get_name()) == 0:
            error = QMessageBox()
            error.setText("Please enter a name for the event.")
            error.exec_()
            self.name_edit.setFocus()
            return
        if event_type in ["Class", "Recurring Event"]:
            # Check Start/End Date
            start_date = self.start_date_model.content.date()
            end_date = self.end_date_model.content.date()
            if start_date >= end_date:
                error = QMessageBox()
                error.setText("End date cannot {} start date.".format(
                    "be equal to" if start_date ==
                    end_date else "come before"))
                error.exec_()
                if event_type == "Class":
                    self.class_end_date.setFocus()
                else:
                    self.event_end_date.setFocus()
                return
            if event_type == "Class":
                # Check Blocks
                # noinspection PyTypeChecker
                class_layout: QFormLayout = self.stack.currentWidget().layout()
                for row in range(self.rows_before_blocks,
                                 class_layout.rowCount()):
                    block_widget = class_layout.itemAt(
                        row, QFormLayout.FieldRole).widget()
                    if block_widget.isHidden():
                        continue
                    # Make sure a day is selected for each block
                    if not block_widget.is_valid():
                        block_name = "the class block" if self.blocks == 1 else str.lower(
                            class_layout.itemAt(row, QFormLayout.LabelRole).
                            widget().text()).replace(" time:", "")
                        error = QMessageBox()
                        error.setText(
                            "Please select a valid day for {}.".format(
                                block_name))
                        error.exec_()
                        return
                    # Check for duplicate blocks
                    for other in range(self.rows_before_blocks,
                                       class_layout.rowCount() - 1):
                        if row == other:
                            continue
                        other_block_widget = class_layout.itemAt(
                            other, QFormLayout.FieldRole).widget()
                        same_time = block_widget.get_time(
                        ) == other_block_widget.get_time()
                        same_day = block_widget.day_picker.get_day(
                        ) == other_block_widget.day_picker.get_day()
                        if same_time and same_day:
                            error = QMessageBox()
                            error.setText(
                                "Block {} and {} cannot have the same day and time."
                                .format(row - self.rows_before_blocks + 1,
                                        other - self.rows_before_blocks + 1))
                            error.exec_()
                            return
            if event_type == "Recurring Event":
                # Make sure a day is selected
                if not self.recurring_event_time_picker.is_valid():
                    error = QMessageBox()
                    error.setText("Please select a valid day for this event.")
                    error.exec_()
                    self.recurring_event_time_picker.setFocus()
                    return
        if event_type == "One Time Class Event":
            # Check Class
            if len(self.class_picker.text()) == 0:
                error = QMessageBox()
                error.setText("Please select a class for this event.")
                error.exec_()
                self.class_picker.setFocus()
                return
        # Valid name
        if self.get_name() in self.schedule.schedule.keys():
            if self.data is None:
                error = QMessageBox()
                error.setText(
                    "An event with this name already exists, would you like to overwrite it?"
                )
                error.setStandardButtons(error.Apply | error.Cancel)
                result = error.exec_()
                if result == error.Apply:
                    to_overwrite = self.schedule.schedule[self.get_name()]
                    if to_overwrite["type"] == "class":
                        if self.event_type.text() == "One Time Class Event":
                            if self.class_picker.text() == self.get_name():
                                error = QMessageBox()
                                error.setText(
                                    "Cannot overwrite a class with a one time class event for that class.\n"
                                    "Please select a different class.")
                                error.setStandardButtons(QMessageBox.Close)
                                error.exec_()
                                return
                    self.schedule.edit_event(self.get_data())
                    self.reject()
                elif result == error.Cancel:
                    self.name_edit.setFocus()
                    return
            self.schedule.edit_event(self.get_data())
            self.reject()
        super(Popup, self).accept()

    def reject(self):
        super(Popup, self).reject()
예제 #12
0
class ControlElement:
    def __init__(self, option_name: str, config_object: ConfigObject,
                 outer_layout: QLayout, dialog: QDialog, update_callback):
        self.option_name = option_name
        self.state = config_object.value
        self.outer_layout = outer_layout
        self.dialog = dialog
        self.update_callback = update_callback
        self.edit_control = None
        self.add_btn = QPushButton("Add item")
        self.add_btn.setAutoDefault(False)
        self.add_btn.clicked.connect(lambda: self.add_btn_click())
        self.outer_layout.addWidget(self.add_btn)

        self.list_layout = QVBoxLayout()
        self.list_widget = QWidget()
        self.list_widget.setContentsMargins(50, 0, 50, 0)
        self.list_widget.setLayout(self.list_layout)
        self.outer_layout.addWidget(self.list_widget)
        self.is_editing = False
        self.update_view()

    def init_edit_control(self):
        pass

    def set_state(self, new_value):
        # update state
        self.state = new_value
        self.update_view()
        self.update_callback(new_value)

    def delete_entry(self, item, h_layout):
        h_layout.deleteLater()
        self.set_state([x for x in self.state if x != item])

    def render_edit_control(self, h_layout):
        h_layout.addWidget(self.edit_control)

    def render_entries(self):
        from .. import asset_dir
        for item in self.state:
            h_layout = QHBoxLayout()
            if len(item) == 0:  # is editing
                self.render_edit_control(h_layout)
            else:
                label = QLabel("'" + item + "'")
                label.setStyleSheet(
                    "font-family: monospace; text-align: right; font-size: 16px"
                )
                h_layout.addWidget(label)

            btn = QPushButton("")
            btn.setIcon(
                QIcon(
                    os.path.join(
                        asset_dir, "checkmark-1.png"
                        if len(item) == 0 else "trashcan.png")))
            btn.setFixedWidth(30)
            btn.setStyleSheet(
                "background-color: #FFFFFF; border: 1px solid gray; border-radius: 2px; cursor: pointer"
            )
            btn.setFixedHeight(30)
            btn.setIconSize(QSize(20, 20))
            h_layout.addWidget(btn)
            btn.pressed.connect(
                partial(self.submit_draft) if len(item) ==
                0 else partial(self.delete_entry, item, h_layout))
            self.list_layout.addLayout(h_layout)

    def update_view(self):
        delete_layout_contents(self.list_layout)
        self.init_edit_control()
        self.list_widget.adjustSize()
        self.dialog.adjustSize()

        self.render_entries()
        self.list_widget.adjustSize()
        self.dialog.adjustSize()

    def submit_draft(self):
        pass

    def add_btn_click(self):
        pass
예제 #13
0
class App(QMainWindow):
    def __init__(self):
        super(App, self).__init__()

        self.central_widget = QWidget()
        self.vbox = QVBoxLayout()
        self.lbl_img = QLabel()
        self.file_name = 'assets/lenna.png'

        self.init_ui()

    def init_ui(self):
        self.setWindowTitle('Computer Vision Playground')
        self.setWindowIcon(QIcon('assets/app-icon.png'))

        self.init_menubar()

        self.init_central_widget()

        self.statusBar().showMessage('Ready')
        self.center()
        self.show()

    def center(self):
        # Adjust the window size
        self.central_widget.adjustSize()
        self.adjustSize()

        # Center the app
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def init_central_widget(self):
        # Show the sample image
        self.lbl_img.setPixmap(QPixmap(self.file_name))
        self.vbox.addWidget(self.lbl_img)

        self.central_widget.setLayout(self.vbox)
        self.setCentralWidget(self.central_widget)

    def init_menubar(self):
        menubar = self.menuBar()
        menubar.setNativeMenuBar(False)

        # File menus
        menu_file = menubar.addMenu('&File')
        # Open menu
        action_open = QAction('Open', self)
        action_open.setShortcut('Ctrl+O')
        action_open.setStatusTip('Open an image file')
        action_open.triggered.connect(self.open_file)
        menu_file.addAction(action_open)
        # Exit menu
        menu_file.addSeparator()
        action_exit = QAction('Exit', self)
        action_exit.setShortcut('Ctrl+Q')
        action_exit.setStatusTip('Quit application')
        action_exit.triggered.connect(qApp.quit)
        menu_file.addAction(action_exit)

    def open_file(self):
        self.file_name = \
            QFileDialog.getOpenFileName(self, 'Open an image file', '/home', 'Images (*.png *.jpg *.jpeg)')[0]

        if self.file_name:
            self.update_pixmap(self.file_name)

    def update_pixmap(self, file_name):
        pixmap = QPixmap(file_name)

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

        # Update the center widget with the pixmap
        self.lbl_img.setPixmap(pixmap)
        self.center()
예제 #14
0
class TemplateMultipleVariablesDialog(QDialog):
    """
    Class implementing a dialog for entering multiple template variables.
    """
    def __init__(self, variables, parent=None):
        """
        Constructor
        
        @param variables list of template variable names (list of strings)
        @param parent parent widget of this dialog (QWidget)
        """
        super(TemplateMultipleVariablesDialog, self).__init__(parent)

        self.TemplateMultipleVariablesDialogLayout = QVBoxLayout(self)
        self.TemplateMultipleVariablesDialogLayout.setContentsMargins(
            6, 6, 6, 6)
        self.TemplateMultipleVariablesDialogLayout.setSpacing(6)
        self.TemplateMultipleVariablesDialogLayout.setObjectName(
            "TemplateMultipleVariablesDialogLayout")
        self.setLayout(self.TemplateMultipleVariablesDialogLayout)

        # generate the scrollarea
        self.variablesView = QScrollArea(self)
        self.variablesView.setObjectName("variablesView")
        self.TemplateMultipleVariablesDialogLayout.addWidget(
            self.variablesView)

        self.variablesView.setWidgetResizable(True)
        self.variablesView.setFrameStyle(QFrame.NoFrame)

        self.top = QWidget(self)
        self.variablesView.setWidget(self.top)
        self.grid = QGridLayout(self.top)
        self.grid.setContentsMargins(0, 0, 0, 0)
        self.grid.setSpacing(6)
        self.top.setLayout(self.grid)

        # populate the scrollarea with labels and text edits
        self.variablesEntries = {}
        row = 0
        for var in variables:
            label = QLabel("{0}:".format(var), self.top)
            self.grid.addWidget(label, row, 0, Qt.Alignment(Qt.AlignTop))
            if var.find(":") >= 0:
                formatStr = var[1:-1].split(":")[1]
                if formatStr in ["ml", "rl"]:
                    t = QTextEdit(self.top)
                    t.setTabChangesFocus(True)
                else:
                    t = QLineEdit(self.top)
            else:
                t = QLineEdit(self.top)
            self.grid.addWidget(t, row, 1)
            self.variablesEntries[var] = t
            row += 1
        # add a spacer to make the entries aligned at the top
        spacer = QSpacerItem(20, 40, QSizePolicy.Minimum,
                             QSizePolicy.Expanding)
        self.grid.addItem(spacer, row, 1)
        self.variablesEntries[variables[0]].setFocus()
        self.top.adjustSize()

        # generate the buttons
        layout1 = QHBoxLayout()
        layout1.setContentsMargins(0, 0, 0, 0)
        layout1.setSpacing(6)
        layout1.setObjectName("layout1")

        spacer1 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                              QSizePolicy.Minimum)
        layout1.addItem(spacer1)

        self.okButton = QPushButton(self)
        self.okButton.setObjectName("okButton")
        self.okButton.setDefault(True)
        layout1.addWidget(self.okButton)

        self.cancelButton = QPushButton(self)
        self.cancelButton.setObjectName("cancelButton")
        layout1.addWidget(self.cancelButton)

        spacer2 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                              QSizePolicy.Minimum)
        layout1.addItem(spacer2)

        self.TemplateMultipleVariablesDialogLayout.addLayout(layout1)

        # set the texts of the standard widgets
        self.setWindowTitle(self.tr("Enter Template Variables"))
        self.okButton.setText(self.tr("&OK"))
        self.cancelButton.setText(self.tr("&Cancel"))

        # polish up the dialog
        self.resize(QSize(400, 480).expandedTo(self.minimumSizeHint()))

        self.okButton.clicked.connect(self.accept)
        self.cancelButton.clicked.connect(self.reject)

    def getVariables(self):
        """
        Public method to get the values for all variables.
        
        @return dictionary with the variable as a key and its value (string)
        """
        values = {}
        for var, textEdit in list(self.variablesEntries.items()):
            try:
                values[var] = textEdit.text()
            except AttributeError:
                values[var] = textEdit.toPlainText()
        return values
예제 #15
0
class PyRegExpWizardCharactersDialog(QDialog,
                                     Ui_PyRegExpWizardCharactersDialog):
    """
    Class implementing a dialog for entering character classes.
    """
    specialChars = {4: "\\a", 5: "\\f", 6: "\\n", 7: "\\r", 8: "\\t", 9: "\\v"}

    predefinedClasses = ["\\s", "\\S", "\\w", "\\W", "\\d", "\\D"]

    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent parent widget (QWidget)
        """
        super(PyRegExpWizardCharactersDialog, self).__init__(parent)
        self.setupUi(self)

        self.comboItems = []
        self.singleComboItems = []  # these are in addition to the above
        self.comboItems.append(self.tr("Normal character"))
        self.comboItems.append(
            self.tr("Unicode character in hexadecimal notation"))
        self.comboItems.append(self.tr("Unicode character in octal notation"))
        self.singleComboItems.append(self.tr("---"))
        self.singleComboItems.append(self.tr("Bell character (\\a)"))
        self.singleComboItems.append(self.tr("Page break (\\f)"))
        self.singleComboItems.append(self.tr("Line feed (\\n)"))
        self.singleComboItems.append(self.tr("Carriage return (\\r)"))
        self.singleComboItems.append(self.tr("Horizontal tabulator (\\t)"))
        self.singleComboItems.append(self.tr("Vertical tabulator (\\v)"))

        self.charValidator = QRegExpValidator(QRegExp(".{0,1}"), self)
        self.hexValidator = QRegExpValidator(QRegExp("[0-9a-fA-F]{0,4}"), self)
        self.octValidator = QRegExpValidator(QRegExp("[0-3]?[0-7]{0,2}"), self)

        # generate dialog part for single characters
        self.singlesBoxLayout = QVBoxLayout(self.singlesBox)
        self.singlesBoxLayout.setObjectName("singlesBoxLayout")
        self.singlesBoxLayout.setSpacing(6)
        self.singlesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesBox.setLayout(self.singlesBoxLayout)
        self.singlesView = QScrollArea(self.singlesBox)
        self.singlesView.setObjectName("singlesView")
        self.singlesBoxLayout.addWidget(self.singlesView)

        self.singlesItemsBox = QWidget(self)
        self.singlesView.setWidget(self.singlesItemsBox)
        self.singlesItemsBox.setObjectName("singlesItemsBox")
        self.singlesItemsBoxLayout = QVBoxLayout(self.singlesItemsBox)
        self.singlesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesItemsBoxLayout.setSpacing(6)
        self.singlesItemsBox.setLayout(self.singlesItemsBoxLayout)
        self.singlesEntries = []
        self.__addSinglesLine()

        hlayout0 = QHBoxLayout()
        hlayout0.setContentsMargins(0, 0, 0, 0)
        hlayout0.setSpacing(6)
        hlayout0.setObjectName("hlayout0")
        self.moreSinglesButton = QPushButton(self.tr("Additional Entries"),
                                             self.singlesBox)
        self.moreSinglesButton.setObjectName("moreSinglesButton")
        hlayout0.addWidget(self.moreSinglesButton)
        hspacer0 = QSpacerItem(30, 20, QSizePolicy.Expanding,
                               QSizePolicy.Minimum)
        hlayout0.addItem(hspacer0)
        self.singlesBoxLayout.addLayout(hlayout0)
        self.moreSinglesButton.clicked.connect(self.__addSinglesLine)

        # generate dialog part for character ranges
        self.rangesBoxLayout = QVBoxLayout(self.rangesBox)
        self.rangesBoxLayout.setObjectName("rangesBoxLayout")
        self.rangesBoxLayout.setSpacing(6)
        self.rangesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesBox.setLayout(self.rangesBoxLayout)
        self.rangesView = QScrollArea(self.rangesBox)
        self.rangesView.setObjectName("rangesView")
        self.rangesBoxLayout.addWidget(self.rangesView)

        self.rangesItemsBox = QWidget(self)
        self.rangesView.setWidget(self.rangesItemsBox)
        self.rangesItemsBox.setObjectName("rangesItemsBox")
        self.rangesItemsBoxLayout = QVBoxLayout(self.rangesItemsBox)
        self.rangesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesItemsBoxLayout.setSpacing(6)
        self.rangesItemsBox.setLayout(self.rangesItemsBoxLayout)
        self.rangesEntries = []
        self.__addRangesLine()

        hlayout1 = QHBoxLayout()
        hlayout1.setContentsMargins(0, 0, 0, 0)
        hlayout1.setSpacing(6)
        hlayout1.setObjectName("hlayout1")
        self.moreRangesButton = QPushButton(self.tr("Additional Entries"),
                                            self.rangesBox)
        self.moreSinglesButton.setObjectName("moreRangesButton")
        hlayout1.addWidget(self.moreRangesButton)
        hspacer1 = QSpacerItem(30, 20, QSizePolicy.Expanding,
                               QSizePolicy.Minimum)
        hlayout1.addItem(hspacer1)
        self.rangesBoxLayout.addLayout(hlayout1)
        self.moreRangesButton.clicked.connect(self.__addRangesLine)

    def __addSinglesLine(self):
        """
        Private slot to add a line of entry widgets for single characters.
        """
        hbox = QWidget(self.singlesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        cb1.addItems(self.comboItems)
        cb1.addItems(self.singleComboItems)
        hboxLayout.addWidget(cb1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        cb2 = QComboBox(hbox)
        cb2.setEditable(False)
        cb2.addItems(self.comboItems)
        cb2.addItems(self.singleComboItems)
        hboxLayout.addWidget(cb2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        self.singlesItemsBoxLayout.addWidget(hbox)

        cb1.activated[int].connect(self.__singlesCharTypeSelected)
        cb2.activated[int].connect(self.__singlesCharTypeSelected)
        hbox.show()

        self.singlesItemsBox.adjustSize()

        self.singlesEntries.append([cb1, le1])
        self.singlesEntries.append([cb2, le2])

    def __addRangesLine(self):
        """
        Private slot to add a line of entry widgets for character ranges.
        """
        hbox = QWidget(self.rangesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        cb1.addItems(self.comboItems)
        hboxLayout.addWidget(cb1)
        l1 = QLabel(self.tr("Between:"), hbox)
        hboxLayout.addWidget(l1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        l2 = QLabel(self.tr("And:"), hbox)
        hboxLayout.addWidget(l2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        self.rangesItemsBoxLayout.addWidget(hbox)

        cb1.activated[int].connect(self.__rangesCharTypeSelected)

        hbox.show()

        self.rangesItemsBox.adjustSize()

        self.rangesEntries.append([cb1, le1, le2])

    def __performSelectedAction(self, index, lineedit):
        """
        Private method performing some actions depending on the input.
        
        @param index selected list index (integer)
        @param lineedit line edit widget to act on (QLineEdit)
        """
        if index < 3:
            lineedit.setEnabled(True)
            if index == 0:
                lineedit.setValidator(self.charValidator)
            elif index == 1:
                lineedit.setValidator(self.hexValidator)
            elif index == 2:
                lineedit.setValidator(self.octValidator)
        elif index > 3:
            lineedit.setEnabled(False)
        lineedit.clear()

    def __singlesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the single chars
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.singlesEntries:
            if combo == entriesList[0]:
                self.__performSelectedAction(index, entriesList[1])
                break

    def __rangesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the char ranges
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.rangesEntries:
            if combo == entriesList[0]:
                self.__performSelectedAction(index, entriesList[1])
                self.__performSelectedAction(index, entriesList[2])
                break

    def __formatCharacter(self, index, char):
        """
        Private method to format the characters entered into the dialog.
        
        @param index selected list index (integer)
        @param char character string enetered into the dialog (string)
        @return formated character string (string)
        """
        if index == 0:
            return char
        elif index == 1:
            return "\\x{0}".format(char.lower())
        elif index == 2:
            return "\\0{0}".format(char)
        else:
            try:
                return self.specialChars[index]
            except KeyError:
                return ""

    def getCharacters(self):
        """
        Public method to return the character string assembled via the dialog.
        
        @return formatted string for character classes (string)
        """
        regexp = ""

        # negative character range
        if self.negativeCheckBox.isChecked():
            regexp += "^"

        # predefined character ranges
        if self.wordCharCheckBox.isChecked():
            regexp += "\\w"
        if self.nonWordCharCheckBox.isChecked():
            regexp += "\\W"
        if self.digitsCheckBox.isChecked():
            regexp += "\\d"
        if self.nonDigitsCheckBox.isChecked():
            regexp += "\\D"
        if self.whitespaceCheckBox.isChecked():
            regexp += "\\s"
        if self.nonWhitespaceCheckBox.isChecked():
            regexp += "\\S"

        # single characters
        for entrieslist in self.singlesEntries:
            index = entrieslist[0].currentIndex()
            char = entrieslist[1].text()
            regexp += self.__formatCharacter(index, char)

        # character ranges
        for entrieslist in self.rangesEntries:
            if entrieslist[1].text() == "" or \
               entrieslist[2].text() == "":
                continue
            index = entrieslist[0].currentIndex()
            char1 = entrieslist[1].text()
            char2 = entrieslist[2].text()
            regexp += "{0}-{1}".format(self.__formatCharacter(index, char1),
                                       self.__formatCharacter(index, char2))

        if regexp:
            if (len(regexp) == 2 and
                (regexp in self.predefinedClasses or
                 regexp in self.specialChars)) or \
               len(regexp) == 1:
                return regexp
            else:
                return "[{0}]".format(regexp)
        else:
            return ""
예제 #16
0
class GraphTableUI(PageWindow):
    def __init__(self, controller, fontSize):
        logging.debug("GraphTableUI initialization")
        super().__init__()

        self.controller = controller
        self.shortestPathUI = ShortestPathUI(self.controller,
                                             350,
                                             120,
                                             fontSize=fontSize)
        self.allPathsUI = AllPathsUI(self.controller,
                                     400,
                                     250,
                                     fontSize=fontSize)

        self.__generalLayout = QGridLayout()
        self.__tableLayout = QGridLayout()
        self.__generalLayout.addLayout(self.__tableLayout, 1, 0)

        self.fontSize = fontSize
        layoutFont = QFont("Arial", self.fontSize, QFont.Bold)
        self.__centralWidget = QWidget()
        self.__centralWidget.setFont(layoutFont)
        self.__centralWidget.setLayout(self.__generalLayout)
        self.setCentralWidget(self.__centralWidget)

        self.createView(buttonsWidth=50)
        self.createTable(lineEditWidth=40)
        self.__generalLayout.setSizeConstraint(self.__tableLayout.SetFixedSize)
        self.__centralWidget.adjustSize()
        self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)

    def createView(self, buttonsWidth):
        """
        Creates widgets of GraphTableUI.
        """
        logging.debug("GraphTableUI.createView function started")
        self.backButton = QPushButton("Back")
        self.backButton.setFixedWidth(buttonsWidth)
        self.backButton.clicked.connect(self.gotoVerticesInputMenu)
        self.__generalLayout.addWidget(self.backButton, 0, 0)

        bottomLayout = QHBoxLayout()
        self.OkButton = QPushButton("Ok")
        self.OkButton.setFixedWidth(buttonsWidth)
        self.OkButton.clicked.connect(self.generateGraphEdges)
        bottomLayout.addWidget(self.OkButton)

        self.clearButton = QPushButton("Clear")
        self.clearButton.setFixedWidth(buttonsWidth)
        self.clearButton.clicked.connect(self.clearTable)
        bottomLayout.addWidget(self.clearButton)

        self.drawButton = QPushButton("Draw")
        self.drawButton.setFixedWidth(buttonsWidth)
        self.drawButton.clicked.connect(self.controller.drawGraph)
        bottomLayout.addWidget(self.drawButton)
        self.__generalLayout.addLayout(bottomLayout,
                                       2,
                                       0,
                                       alignment=Qt.AlignLeft)

        functionsLayout = QVBoxLayout()
        functionsLayout.addWidget(QLabel(""))
        self.shortestPathButton = QPushButton("Find the\nshortest path")
        self.shortestPathButton.clicked.connect(self.shortestPathUI.show)
        functionsLayout.addWidget(self.shortestPathButton)

        self.allPathsButton = QPushButton("Find all paths")
        self.allPathsButton.clicked.connect(self.allPathsUI.show)
        functionsLayout.addWidget(self.allPathsButton)
        self.__generalLayout.addLayout(functionsLayout,
                                       1,
                                       1,
                                       alignment=Qt.AlignTop)
        logging.debug("GraphTableUI.createView function ended\n")

    def createTable(self, lineEditWidth):
        """
        Generates Table depending on numbers of vertices.
        """
        logging.debug("GraphTableUI.createTable function started")
        self.vertices = self.controller.getVertices()
        self.cellsDict = dict()
        verticesNum = len(self.vertices)
        for rowNum in range(1, verticesNum + 1):
            for colNum in range(1, verticesNum + 1):
                if colNum == 1:
                    vertexRowLabel = QLabel(self.vertices[rowNum - 1])
                    vertexColLabel = QLabel(self.vertices[rowNum - 1])
                    vertexRowLabel.setAlignment(Qt.AlignHCenter)
                    vertexColLabel.setAlignment(Qt.AlignHCenter)
                    self.__tableLayout.addWidget(vertexColLabel, 0, rowNum)
                    self.__tableLayout.addWidget(vertexRowLabel, rowNum, 0)
                    self.cellsDict[(0, rowNum)] = vertexColLabel
                    self.cellsDict[(rowNum, 0)] = vertexRowLabel
                lineEdit = QLineEdit()
                lineEdit.setFixedWidth(lineEditWidth)
                lineEdit.textChanged.connect(
                    partial(self.__clearErrorInfo, lineEdit, (rowNum, colNum)))
                lineEdit.setStyleSheet("""font: bold;
                                          font-size: {self.fontSize}pt;
                                          font-family: Arial""")
                if rowNum == colNum:
                    lineEdit.setReadOnly(True)
                    lineEdit.setStyleSheet("background: gray")
                self.__tableLayout.addWidget(lineEdit, rowNum, colNum)
                self.cellsDict[(rowNum, colNum)] = lineEdit

        logging.debug("GraphTableUI.createTable function ended\n")

    def removeTable(self):
        """
        Removes Table from generalLayout.
        """
        logging.debug("GraphTableUI.removeTable function started")
        for widget in self.cellsDict.values():
            self.__tableLayout.removeWidget(widget)
            widget.setParent(None)
        self.cellsDict = dict()
        self.__generalLayout.setSizeConstraint(self.__tableLayout.SetFixedSize)
        self.__centralWidget.adjustSize()
        logging.debug("GraphTableUI.removeTable function ended\n")

    def clearTable(self):
        """
        Clears a Table.
        """
        logging.debug("GraphTableUI.clearTable function started")
        for widget in self.cellsDict.values():
            if isinstance(widget, QLineEdit):
                widget.setText("")
        logging.debug("GraphTableUI.clearTable function ended\n")

    def createDisplay(self):
        """
        Creates a Table after going to Graph Table page.
        """
        logging.debug("GraphTableUI.createDisplay function started")
        self.createTable(lineEditWidth=40)
        logging.debug("GraphTableUI.createDisplay function ended\n")

    def getEdgesList(self):
        """
        Creates list of Edges based on a Table.
        """
        logging.debug("GraphTableUI.getEdgesList function started")
        edgesList = []
        error = False
        for gridPlace, widget in self.cellsDict.items():
            self.__clearErrorInfo(widget, gridPlace)
            if 0 in gridPlace or not widget.text():
                continue
            rowNum, colNum = gridPlace
            fromVertex = self.cellsDict[(rowNum, 0)].text()
            toVertex = self.cellsDict[(0, colNum)].text()
            try:
                weight = int(widget.text())
            except:
                self.__drawErrorInfo(widget)
                error = True
                continue
            edgesList.append((fromVertex, toVertex, weight))
        logging.debug("GraphTableUI.getEdgesList function ended\n")
        if not error:
            return edgesList

    def generateGraphEdges(self):
        """
        Makes Controller add edges to Graph.
        """
        logging.debug("GraphTableUI.generateGraphEdges function started")
        edgesList = self.getEdgesList()
        if edgesList:
            self.controller.addEdgesToGraph(edgesList)
        logging.debug("GraphTableUI.generateGraphEdges function ended\n")

    def gotoVerticesInputMenu(self):
        """
        Go to VerticesInputMenu page.
        """
        logging.debug("GraphTableUI.gotoVerticesInputMenu function started")
        self.getEdgesList()
        self.removeTable()
        self.controller.deleteVertices()
        self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
        self.goto("VerticesInput")
        logging.debug("GraphTableUI.gotoVerticesInputMenu function ended\n")

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Return:
            self.generateGraphEdges()

    def __drawErrorInfo(self, widget):
        widget.setStyleSheet(f"""border: 1px solid red;
                                 font-size: {self.fontSize}pt;
                                 font-family: Arial""")

    def __clearErrorInfo(self, widget, gridPlace):
        if gridPlace[0] != gridPlace[1]:
            widget.setStyleSheet(f"""font: bold;
                                     font-size: {self.fontSize}pt;
                                     font-family: Arial""")
예제 #17
0
class PreferencesWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.setLayout(QVBoxLayout())

        # backup directory
        self.backup_directory_widget = QWidget()
        self.backup_directory_widget.setLayout(QHBoxLayout())
        self.backup_directory_line_edit = PreferencesLineEdit()
        self.backup_directory_line_edit.textChanged.connect(
            self.backup_directory_changed)
        self.select_backup_directory_button = QPushButton(
            "Select Backup Directory")
        self.select_backup_directory_button.clicked.connect(
            self.select_backup_directory)
        self.backup_directory_widget.layout().addWidget(
            QLabel("Backup Directory:"))
        self.backup_directory_widget.layout().addWidget(
            self.backup_directory_line_edit)
        self.backup_directory_widget.layout().addWidget(
            self.select_backup_directory_button)
        self.backup_directory_widget.layout().addStretch()
        self.backup_directory_widget.adjustSize(
        )  # all done adding - figure out what the height should be
        self.backup_directory_widget.setMaximumHeight(
            self.backup_directory_widget.minimumHeight())
        self.layout().addWidget(self.backup_directory_widget)
        self.layout().addWidget(QLabel())  # space
        self.layout().addWidget(QLabel())  # space

        # AWS Credentials
        # profile
        self.aws_profile_widget = QWidget()
        self.aws_profile_widget.setLayout(QHBoxLayout())
        self.aws_profile_widget.layout().addWidget(QLabel("AWS Profile:"))
        self.aws_profile_line_edit = PreferencesLineEdit()
        self.aws_profile_line_edit.textChanged.connect(
            self.aws_profile_changed)
        self.aws_profile_widget.layout().addWidget(self.aws_profile_line_edit)
        self.aws_profile_widget.layout().addStretch()
        self.layout().addWidget(self.aws_profile_widget)
        or_label = QLabel("or")  # italicize "or"
        or_font = or_label.font()
        or_font.setItalic(True)
        or_label.setFont(or_font)
        self.layout().addWidget(or_label)
        # access key ID and secret access key
        self.aws_key_widget = QWidget()
        self.aws_key_widget.setLayout(QHBoxLayout())
        self.aws_key_widget.layout().addWidget(QLabel("AWS Access Key ID:"))
        self.aws_access_key_id_line_edit = PreferencesLineEdit()
        self.aws_access_key_id_line_edit.textChanged.connect(
            self.aws_access_key_id_changed)
        self.aws_key_widget.layout().addWidget(
            self.aws_access_key_id_line_edit)
        self.aws_key_widget.layout().addWidget(
            QLabel("AWS Secret Access Key:"))
        self.aws_secret_access_key_line_edit = PreferencesLineEdit()
        self.aws_secret_access_key_line_edit.textChanged.connect(
            self.aws_secret_access_key_changed)
        self.aws_secret_access_key_line_edit.setEchoMode(
            PreferencesLineEdit.Password)
        self.aws_key_widget.layout().addWidget(
            self.aws_secret_access_key_line_edit)
        self.aws_show_button = QPushButton("Show")
        self.aws_show_button.clicked.connect(
            self.aws_secret_access_key_visible_clicked)
        self.aws_key_widget.layout().addWidget(self.aws_show_button)
        self.aws_key_widget.layout().addStretch()
        self.layout().addWidget(self.aws_key_widget)
        self.layout().addWidget(QLabel())  # space
        # region
        self.aws_region_widget = QWidget()
        self.aws_region_widget.setLayout(QHBoxLayout())
        self.aws_region_widget.layout().addWidget(QLabel("AWS Region:"))
        self.aws_region_line_edit = PreferencesLineEdit()
        self.aws_region_line_edit.textChanged.connect(self.aws_region_changed)
        self.aws_region_widget.layout().addWidget(self.aws_region_line_edit)
        self.aws_region_widget.layout().addStretch()
        self.layout().addWidget(self.aws_region_widget)
        self.layout().addWidget(QLabel())  # space
        self.layout().addWidget(QLabel())  # space

        # github
        self.github_widget = QWidget()
        self.github_widget.setLayout(QHBoxLayout())
        self.github_widget.layout().addWidget(QLabel("github token:"))
        self.github_token_line_edit = PreferencesLineEdit()
        self.github_token_line_edit.setEchoMode(PreferencesLineEdit.Password)
        self.github_token_line_edit.textChanged.connect(
            self.github_token_changed)
        self.github_widget.layout().addWidget(self.github_token_line_edit)
        self.github_show_button = QPushButton("Show")
        self.github_show_button.clicked.connect(self.github_visible_clicked)
        self.github_widget.layout().addWidget(self.github_show_button)
        self.github_widget.layout().addStretch()
        self.layout().addWidget(self.github_widget)
        self.layout().addWidget(QLabel())  # space
        self.layout().addWidget(QLabel())  # space

        # automatic backup
        self.automatic_backup_widget = QWidget()
        self.automatic_backup_widget.setLayout(QHBoxLayout())
        self.automatic_backup_period = QSpinBox()
        self.automatic_backup_period.textChanged.connect(
            self.automatic_backup_changed)
        self.automatic_backup_widget.layout().addWidget(
            QLabel("Backup every (hours):"))
        self.automatic_backup_widget.layout().addWidget(
            self.automatic_backup_period)
        self.automatic_backup_enable_check_box = QCheckBox("enable")
        self.automatic_backup_enable_check_box.clicked.connect(
            self.automatic_backup_changed)
        self.automatic_backup_widget.layout().addWidget(
            self.automatic_backup_enable_check_box)
        self.automatic_backup_widget.layout().addStretch()
        self.layout().addWidget(self.automatic_backup_widget)
        self.layout().addWidget(QLabel())  # space
        self.layout().addWidget(QLabel())  # space

        # dry run
        self.dry_run_check_box = QCheckBox("Dry run")
        self.dry_run_check_box.clicked.connect(self.dry_run_clicked)
        self.layout().addWidget(self.dry_run_check_box)

        # verbose
        self.verbose_check_box = QCheckBox("Verbose")
        self.verbose_check_box.clicked.connect(self.verbose_clicked)
        self.layout().addWidget(self.verbose_check_box)

        self.layout().addStretch()  # bottom padding

        self.load_preferences()

    def load_preferences(self):
        preferences = get_gui_preferences()
        self.backup_directory_line_edit.setText(preferences.backup_directory)
        self.aws_profile_line_edit.setText(preferences.aws_profile)
        self.aws_access_key_id_line_edit.setText(preferences.aws_access_key_id)
        self.aws_secret_access_key_line_edit.setText(
            preferences.aws_secret_access_key)
        self.aws_region_line_edit.setText(preferences.aws_region)
        self.github_token_line_edit.setText(preferences.github_token)
        self.verbose_check_box.setChecked(bool(
            preferences.verbose))  # None translates to False
        self.automatic_backup_enable_check_box.setChecked(
            bool(preferences.automatic_backup))
        if preferences.backup_period is not None:
            self.automatic_backup_period.setValue(preferences.backup_period)

    def select_backup_directory(self):
        new_backup_directory = QFileDialog.getExistingDirectory(
            self, "Select Backup Directory")
        if new_backup_directory is not None and len(new_backup_directory) > 0:
            self.backup_directory_line_edit.setText(new_backup_directory)

    def backup_directory_changed(self):
        get_gui_preferences(
        ).backup_directory = self.backup_directory_line_edit.text()

    def aws_profile_changed(self):
        get_gui_preferences().aws_profile = self.aws_profile_line_edit.text()

    def aws_access_key_id_changed(self):
        get_gui_preferences(
        ).aws_access_key_id = self.aws_access_key_id_line_edit.text()

    def aws_secret_access_key_changed(self):
        get_gui_preferences(
        ).aws_secret_access_key = self.aws_secret_access_key_line_edit.text()

    def aws_secret_access_key_visible_clicked(self):
        if self.aws_secret_access_key_line_edit.echoMode(
        ) == PreferencesLineEdit.Password:
            self.aws_show_button.setText("Hide")
            self.aws_secret_access_key_line_edit.setEchoMode(
                PreferencesLineEdit.Normal)
        else:
            self.aws_show_button.setText("Show")
            self.aws_secret_access_key_line_edit.setEchoMode(
                PreferencesLineEdit.Password)

    def aws_region_changed(self):
        get_gui_preferences().aws_region = self.aws_region_line_edit.text()

    def github_token_changed(self):
        get_gui_preferences().github_token = self.github_token_line_edit.text()

    def github_visible_clicked(self):
        if self.github_token_line_edit.echoMode(
        ) == PreferencesLineEdit.Password:
            self.github_show_button.setText("Hide")
            self.github_token_line_edit.setEchoMode(PreferencesLineEdit.Normal)
        else:
            self.github_show_button.setText("Show")
            self.github_token_line_edit.setEchoMode(
                PreferencesLineEdit.Password)

    def verbose_clicked(self):
        get_gui_preferences().verbose = self.verbose_check_box.isChecked()

    def dry_run_clicked(self):
        get_gui_preferences().dry_run = self.dry_run_check_box.isChecked()

    def automatic_backup_changed(self):
        preferences = get_gui_preferences()
        preferences.automatic_backup = self.automatic_backup_enable_check_box.isChecked(
        )
        if len(backup_period :=
               self.automatic_backup_period.text().strip()) > 0:
            preferences.backup_period = int(round(float(backup_period)))
예제 #18
0
    def init_ui(self):
        self.setWindowTitle("About")
        self.setFixedSize(550, 700)
        layout = QVBoxLayout()
        about_text = QLabel(
            "<b>DESCRIPTION</b> <br>"
            "In a time of great conflict, new kingdoms are born in minds of ambitious rules and willing hearts of dedicated serfs. "
            "Every great kingdom needs a powerful army, vivid homeland culture and thoughtful diplomacy. "
            "Be ready to conquer civilizations and win extensive battles, in which the key to defeating your enemy will be both hands and minds. "
            "Will you win by being a despotic tyrant or maybe by creating a web of secret pacts? Will your kingdom story be written by romantic tales or fearful half lies? "
            "Nevertheless, keep your kingdom in order and do not find your domain in the age of divisiveness.",
            self)
        about_text.setWordWrap(True)
        about_text.setAlignment(Qt.AlignCenter)
        about_text.move(10, 20)

        link_button = QPushButton()
        link_button.setMaximumHeight(150)
        link_button.setIconSize(QSize(300, 400))
        link_button.setIcon(QIcon("resources/images/aod_logo.png"))
        link_button.setFlat(True)
        link_button.clicked.connect(self.show_github)

        authors_text = QLabel(
            "<b>AUTHORS </b> <br> Patryk Majewski, Krzysztof Szymaniak, Gabriel Wechta, Błażej Wróbel"
        )
        authors_text.setAlignment(Qt.AlignCenter)
        attributions_fonts = QLabel()
        attributions_fonts.setText(
            "<b>ATTRIBUTIONS</b> <br> <a href='https://www.1001fonts.com/november-font.html'>November</a> - in game font<br> <a href='https://fontenddev.com/fonts/alkhemikal/ '>Alkhemikal</a> - logo font"
        )
        attributions_fonts.setOpenExternalLinks(True)
        attributions_fonts.setAlignment(Qt.AlignCenter)

        attributions_images = QLabel()
        attributions_images.setText(
            "Image authors: <br> "
            "Aneta Pawska [<a href='https://commons.wikimedia.org/wiki/File:Ko%C5%9Bci%C3%B3%C5%82_Wang,_Karpacz.jpg#/media/File:Ko%C5%9Bci%C3%B3%C5%82_Wang,_Karpacz.jpg'>1</a>] <br>"
            "Paul Berzinn [<a href='https://commons.wikimedia.org/wiki/Category:Longhouse_at_Lofotr_Vikingmuseum#/media/File:Viking_museum_at_Borge_-_panoramio.jpg'>1</a>] <br>"
            "Jarek Tarnogórski [<a href='https://commons.wikimedia.org/wiki/Category:Archeopark_in_Chot%C4%9Bbuz#/media/File:Cieszynisko_017.JPG'>1</a>] <br>"
            "Boryslav Javir [<a href='https://commons.wikimedia.org/wiki/Category:Perun#/media/File:Perun7516_1_21.jpg'>1</a>] <br>"
            "Maunus [<a href='https://commons.wikimedia.org/wiki/File:StaCeciliaAcatitlanNorte.jpg'>1</a>] <br>"
            "Arian Zwegers [<a href='https://commons.wikimedia.org/wiki/File:El_Tajin,_Pyramid_of_the_Niches_(20686703945).jpg'>1</a>] "
            "[<a href='https://commons.wikimedia.org/wiki/File:Mitla,_Group_of_the_Columns,_Palace_of_Columns_(20064199284).jpg'>2</a>] <br>"
            "Martin Falbisoner [<a href='https://commons.wikimedia.org/wiki/File:Himeji_Castle,_November_2016_-02.jpg'>1</a>] <br>"
            "Basile Morin [<a href='https://commons.wikimedia.org/w/index.php?search=japan+&title=Special%3ASearch&go=Go&ns0=1&ns6=1&ns12=1&ns14=1&ns100=1&ns106=1#/media/File:Yasaka-dori_early_morning_with_street_lanterns_and_the_Tower_of_Yasaka_(Hokan-ji_Temple),_Kyoto,_Japan.jpg'>1</a>] <br>"
            "Nobrinskii [<a href='https://commons.wikimedia.org/wiki/File:Eigen-ji_(Rinzai_temple)_-_front_area.jpg'>1</a>] <br>"
        )
        attributions_images.setOpenExternalLinks(True)
        attributions_images.setAlignment(Qt.AlignCenter)

        # for future development - "Aneta Pawska [<a href=''>1</a>] <br>"

        thanks_label = QLabel("Big thanks to all sources!")
        thanks_label.setAlignment(Qt.AlignCenter)

        layout.addWidget(link_button)
        layout.addWidget(about_text)
        layout.addWidget(authors_text)
        layout.addWidget(attributions_fonts)
        layout.addWidget(attributions_images)
        layout.addWidget(thanks_label)

        main_widget = QWidget()
        main_widget.setLayout(layout)
        main_widget.adjustSize()

        self.setCentralWidget(main_widget)
        self.center()
class QRegularExpressionWizardCharactersDialog(
        QDialog, Ui_QRegularExpressionWizardCharactersDialog):
    """
    Class implementing a dialog for entering character classes.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget (QWidget)
        """
        super(QRegularExpressionWizardCharactersDialog, self).__init__(parent)
        self.setupUi(self)
        
        self.__initCharacterSelectors()
        
        self.comboItems = []
        self.singleComboItems = []      # these are in addition to the above
        self.comboItems.append((self.tr("Normal character"), "-c"))
        self.comboItems.append((self.tr(
            "Unicode character in hexadecimal notation"), "-h"))
        self.comboItems.append((self.tr(
            "ASCII/Latin1 character in octal notation"), "-o"))
        self.singleComboItems.extend([
            ("---", "-i"),
            (self.tr("Bell character (\\a)"), "\\a"),
            (self.tr("Escape character (\\e)"), "\\e"),
            (self.tr("Page break (\\f)"), "\\f"),
            (self.tr("Line feed (\\n)"), "\\n"),
            (self.tr("Carriage return (\\r)"), "\\r"),
            (self.tr("Horizontal tabulator (\\t)"), "\\t"),
            ("---", "-i"),
            (self.tr("Character Category"), "-ccp"),
            (self.tr("Special Character Category"), "-csp"),
            (self.tr("Character Block"), "-cbp"),
            (self.tr("POSIX Named Set"), "-psp"),
            (self.tr("Not Character Category"), "-ccn"),
            (self.tr("Not Character Block"), "-cbn"),
            (self.tr("Not Special Character Category"), "-csn"),
            (self.tr("Not POSIX Named Set"), "-psn"),
        ])
        
        self.charValidator = QRegExpValidator(QRegExp(".{0,1}"), self)
        self.hexValidator = QRegExpValidator(QRegExp("[0-9a-fA-F]{0,4}"), self)
        self.octValidator = QRegExpValidator(QRegExp("[0-3]?[0-7]{0,2}"), self)
        
        # generate dialog part for single characters
        self.singlesBoxLayout = QVBoxLayout(self.singlesBox)
        self.singlesBoxLayout.setObjectName("singlesBoxLayout")
        self.singlesBoxLayout.setSpacing(6)
        self.singlesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesBox.setLayout(self.singlesBoxLayout)
        self.singlesView = QScrollArea(self.singlesBox)
        self.singlesView.setObjectName("singlesView")
        self.singlesBoxLayout.addWidget(self.singlesView)
        
        self.singlesItemsBox = QWidget(self)
        self.singlesView.setWidget(self.singlesItemsBox)
        self.singlesItemsBox.setObjectName("singlesItemsBox")
        self.singlesItemsBox.setMinimumWidth(1000)
        self.singlesItemsBoxLayout = QVBoxLayout(self.singlesItemsBox)
        self.singlesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesItemsBoxLayout.setSpacing(6)
        self.singlesItemsBox.setLayout(self.singlesItemsBoxLayout)
        self.singlesEntries = []
        self.__addSinglesLine()
        
        hlayout0 = QHBoxLayout()
        hlayout0.setContentsMargins(0, 0, 0, 0)
        hlayout0.setSpacing(6)
        hlayout0.setObjectName("hlayout0")
        self.moreSinglesButton = QPushButton(
            self.tr("Additional Entries"), self.singlesBox)
        self.moreSinglesButton.setObjectName("moreSinglesButton")
        hlayout0.addWidget(self.moreSinglesButton)
        hspacer0 = QSpacerItem(
            30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        hlayout0.addItem(hspacer0)
        self.singlesBoxLayout.addLayout(hlayout0)
        self.moreSinglesButton.clicked.connect(self.__addSinglesLine)
        
        # generate dialog part for character ranges
        self.rangesBoxLayout = QVBoxLayout(self.rangesBox)
        self.rangesBoxLayout.setObjectName("rangesBoxLayout")
        self.rangesBoxLayout.setSpacing(6)
        self.rangesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesBox.setLayout(self.rangesBoxLayout)
        self.rangesView = QScrollArea(self.rangesBox)
        self.rangesView.setObjectName("rangesView")
        self.rangesBoxLayout.addWidget(self.rangesView)
        
        self.rangesItemsBox = QWidget(self)
        self.rangesView.setWidget(self.rangesItemsBox)
        self.rangesItemsBox.setObjectName("rangesItemsBox")
        self.rangesItemsBox.setMinimumWidth(1000)
        self.rangesItemsBoxLayout = QVBoxLayout(self.rangesItemsBox)
        self.rangesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesItemsBoxLayout.setSpacing(6)
        self.rangesItemsBox.setLayout(self.rangesItemsBoxLayout)
        self.rangesEntries = []
        self.__addRangesLine()
        
        hlayout1 = QHBoxLayout()
        hlayout1.setContentsMargins(0, 0, 0, 0)
        hlayout1.setSpacing(6)
        hlayout1.setObjectName("hlayout1")
        self.moreRangesButton = QPushButton(
            self.tr("Additional Entries"), self.rangesBox)
        self.moreSinglesButton.setObjectName("moreRangesButton")
        hlayout1.addWidget(self.moreRangesButton)
        hspacer1 = QSpacerItem(
            30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        hlayout1.addItem(hspacer1)
        self.rangesBoxLayout.addLayout(hlayout1)
        self.moreRangesButton.clicked.connect(self.__addRangesLine)
    
    def __initCharacterSelectors(self):
        """
        Private method to initialize the W3C character selector entries.
        """
        self.__characterCategories = (
            # display name                                  code
            (self.tr("Letter, Any"), "L"),
            (self.tr("Letter, Lower case"), "Ll"),
            (self.tr("Letter, Modifier"), "Lm"),
            (self.tr("Letter, Other"), "Lo"),
            (self.tr("Letter, Title case"), "Lt"),
            (self.tr("Letter, Upper case"), "Lu"),
            (self.tr("Letter, Lower, Upper or Title"), "L&"),
            (self.tr("Mark, Any"), "M"),
            (self.tr("Mark, Spacing"), "Mc"),
            (self.tr("Mark, Enclosing"), "Me"),
            (self.tr("Mark, Non-spacing"), "Mn"),
            (self.tr("Number, Any"), "N"),
            (self.tr("Number, Decimal"), "Nd"),
            (self.tr("Number, Letter"), "Nl"),
            (self.tr("Number, Other"), "No"),
            (self.tr("Punctuation, Any"), "P"),
            (self.tr("Punctuation, Connector"), "Pc"),
            (self.tr("Punctuation, Dash"), "Pd"),
            (self.tr("Punctuation, Close"), "Pe"),
            (self.tr("Punctuation, Final"), "Pf"),
            (self.tr("Punctuation, Initial"), "Pi"),
            (self.tr("Punctuation, Other"), "Po"),
            (self.tr("Punctuation, Open"), "Ps"),
            (self.tr("Symbol, Any"), "S"),
            (self.tr("Symbol, Currency"), "Sc"),
            (self.tr("Symbol, Modifier"), "Sk"),
            (self.tr("Symbol, Mathematical"), "Sm"),
            (self.tr("Symbol, Other"), "So"),
            (self.tr("Separator, Any"), "Z"),
            (self.tr("Separator, Line"), "Zl"),
            (self.tr("Separator, Paragraph"), "Zp"),
            (self.tr("Separator, Space"), "Zs"),
            (self.tr("Other, Any"), "C"),
            (self.tr("Other, Control"), "Cc"),
            (self.tr("Other, Format"), "Cf"),
            (self.tr("Other, Unassigned"), "Cn"),
            (self.tr("Other, Private Use"), "Co"),
            (self.tr("Other, Surrogat"), "Cn"),
        )
        
        self.__specialCharacterCategories = (
            # display name                           code
            (self.tr("Alphanumeric"), "Xan"),
            (self.tr("POSIX Space"), "Xps"),
            (self.tr("Perl Space"), "Xsp"),
            (self.tr("Universal Character"), "Xuc"),
            (self.tr("Perl Word"), "Xan"),
        )
        
        self.__characterBlocks = (
            # display name                           code
            (self.tr("Arabic"), "Arabic"),
            (self.tr("Armenian"), "Armenian"),
            (self.tr("Avestan"), "Avestan"),
            (self.tr("Balinese"), "Balinese"),
            (self.tr("Bamum"), "Bamum"),
            (self.tr("Batak"), "Batak"),
            (self.tr("Bengali"), "Bengali"),
            (self.tr("Bopomofo"), "Bopomofo"),
            (self.tr("Brahmi"), "Brahmi"),
            (self.tr("Braille"), "Braille"),
            (self.tr("Buginese"), "Buginese"),
            (self.tr("Buhid"), "Buhid"),
            (self.tr("Canadian Aboriginal"), "Canadian_Aboriginal"),
            (self.tr("Carian"), "Carian"),
            (self.tr("Chakma"), "Chakma"),
            (self.tr("Cham"), "Cham"),
            (self.tr("Cherokee"), "Cherokee"),
            (self.tr("Common"), "Common"),
            (self.tr("Coptic"), "Coptic"),
            (self.tr("Cuneiform"), "Cuneiform"),
            (self.tr("Cypriot"), "Cypriot"),
            (self.tr("Cyrillic"), "Cyrillic"),
            (self.tr("Deseret"), "Deseret,"),
            (self.tr("Devanagari"), "Devanagari"),
            (self.tr("Egyptian Hieroglyphs"), "Egyptian_Hieroglyphs"),
            (self.tr("Ethiopic"), "Ethiopic"),
            (self.tr("Georgian"), "Georgian"),
            (self.tr("Glagolitic"), "Glagolitic"),
            (self.tr("Gothic"), "Gothic"),
            (self.tr("Greek"), "Greek"),
            (self.tr("Gujarati"), "Gujarati"),
            (self.tr("Gurmukhi"), "Gurmukhi"),
            (self.tr("Han"), "Han"),
            (self.tr("Hangul"), "Hangul"),
            (self.tr("Hanunoo"), "Hanunoo"),
            (self.tr("Hebrew"), "Hebrew"),
            (self.tr("Hiragana"), "Hiragana"),
            (self.tr("Imperial Aramaic"), "Imperial_Aramaic"),
            (self.tr("Inherited"), "Inherited"),
            (self.tr("Inscriptional Pahlavi"), "Inscriptional_Pahlavi"),
            (self.tr("Inscriptional Parthian"), "Inscriptional_Parthian"),
            (self.tr("Javanese"), "Javanese"),
            (self.tr("Kaithi"), "Kaithi"),
            (self.tr("Kannada"), "Kannada"),
            (self.tr("Katakana"), "Katakana"),
            (self.tr("Kayah Li"), "Kayah_Li"),
            (self.tr("Kharoshthi"), "Kharoshthi"),
            (self.tr("Khmer"), "Khmer"),
            (self.tr("Lao"), "Lao"),
            (self.tr("Latin"), "Latin"),
            (self.tr("Lepcha"), "Lepcha"),
            (self.tr("Limbu"), "Limbu"),
            (self.tr("Linear B"), "Linear_B"),
            (self.tr("Lisu"), "Lisu"),
            (self.tr("Lycian"), "Lycian"),
            (self.tr("Lydian"), "Lydian"),
            (self.tr("Malayalam"), "Malayalam"),
            (self.tr("Mandaic"), "Mandaic"),
            (self.tr("Meetei Mayek"), "Meetei_Mayek"),
            (self.tr("Meroitic Cursive"), "Meroitic_Cursive"),
            (self.tr("Meroitic Hieroglyphs"), "Meroitic_Hieroglyphs"),
            (self.tr("Miao"), "Miao"),
            (self.tr("Mongolian"), "Mongolian"),
            (self.tr("Myanmar"), "Myanmar"),
            (self.tr("New Tai Lue"), "New_Tai_Lue"),
            (self.tr("N'Ko"), "Nko"),
            (self.tr("Ogham"), "Ogham"),
            (self.tr("Old Italic"), "Old_Italic"),
            (self.tr("Old Persian"), "Old_Persian"),
            (self.tr("Old South Arabian"), "Old_South_Arabian"),
            (self.tr("Old Turkic"), "Old_Turkic,"),
            (self.tr("Ol Chiki"), "Ol_Chiki"),
            (self.tr("Oriya"), "Oriya"),
            (self.tr("Osmanya"), "Osmanya"),
            (self.tr("Phags-pa"), "Phags_Pa"),
            (self.tr("Phoenician"), "Phoenician"),
            (self.tr("Rejang"), "Rejang"),
            (self.tr("Runic"), "Runic"),
            (self.tr("Samaritan"), "Samaritan"),
            (self.tr("Saurashtra"), "Saurashtra"),
            (self.tr("Sharada"), "Sharada"),
            (self.tr("Shavian"), "Shavian"),
            (self.tr("Sinhala"), "Sinhala"),
            (self.tr("Sora Sompeng"), "Sora_Sompeng"),
            (self.tr("Sundanese"), "Sundanese"),
            (self.tr("Syloti Nagri"), "Syloti_Nagri"),
            (self.tr("Syriac"), "Syriac"),
            (self.tr("Tagalog"), "Tagalog"),
            (self.tr("Tagbanwa"), "Tagbanwa"),
            (self.tr("Tai Le"), "Tai_Le"),
            (self.tr("Tai Tham"), "Tai_Tham"),
            (self.tr("Tai Viet"), "Tai_Viet"),
            (self.tr("Takri"), "Takri"),
            (self.tr("Tamil"), "Tamil"),
            (self.tr("Telugu"), "Telugu"),
            (self.tr("Thaana"), "Thaana"),
            (self.tr("Thai"), "Thai"),
            (self.tr("Tibetan"), "Tibetan"),
            (self.tr("Tifinagh"), "Tifinagh"),
            (self.tr("Ugaritic"), "Ugaritic"),
            (self.tr("Vai"), "Vai"),
            (self.tr("Yi"), "Yi"),
        )
        
        self.__posixNamedSets = (
            # display name                                  code
            (self.tr("Alphanumeric"), "alnum"),
            (self.tr("Alphabetic"), "alpha"),
            (self.tr("ASCII"), "ascii"),
            (self.tr("Word Letter"), "word"),
            (self.tr("Lower Case Letter"), "lower"),
            (self.tr("Upper Case Letter"), "upper"),
            (self.tr("Decimal Digit"), "digit"),
            (self.tr("Hexadecimal Digit"), "xdigit"),
            (self.tr("Space or Tab"), "blank"),
            (self.tr("White Space"), "space"),
            (self.tr("Printing (excl. space)"), "graph"),
            (self.tr("Printing (incl. space)"), "print"),
            (self.tr("Printing (excl. alphanumeric)"), "punct"),
            (self.tr("Control Character"), "cntrl"),
        )
    
    def __populateCharTypeCombo(self, combo, isSingle):
        """
        Private method to populate a given character type selection combo box.
        
        @param combo reference to the combo box to be populated (QComboBox)
        @param isSingle flag indicating a singles combo (boolean)
        """
        for txt, value in self.comboItems:
            combo.addItem(txt, value)
        if isSingle:
            for txt, value in self.singleComboItems:
                combo.addItem(txt, value)

    def __addSinglesLine(self):
        """
        Private slot to add a line of entry widgets for single characters.
        """
        hbox = QWidget(self.singlesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        self.__populateCharTypeCombo(cb1, True)
        hboxLayout.addWidget(cb1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        cb1a = QComboBox(hbox)
        cb1a.setEditable(False)
        cb1a.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        hboxLayout.addWidget(cb1a)
        cb1a.hide()
        cb2 = QComboBox(hbox)
        cb2.setEditable(False)
        self.__populateCharTypeCombo(cb2, True)
        hboxLayout.addWidget(cb2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        cb2a = QComboBox(hbox)
        cb2a.setEditable(False)
        cb2a.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        hboxLayout.addWidget(cb2a)
        cb2a.hide()
        self.singlesItemsBoxLayout.addWidget(hbox)
        
        cb1.activated[int].connect(self.__singlesCharTypeSelected)
        cb2.activated[int].connect(self.__singlesCharTypeSelected)
        hbox.show()
        
        self.singlesItemsBox.adjustSize()
        
        self.singlesEntries.append([cb1, le1, cb1a])
        self.singlesEntries.append([cb2, le2, cb2a])
    
    def __addRangesLine(self):
        """
        Private slot to add a line of entry widgets for character ranges.
        """
        hbox = QWidget(self.rangesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        self.__populateCharTypeCombo(cb1, False)
        hboxLayout.addWidget(cb1)
        l1 = QLabel(self.tr("Between:"), hbox)
        hboxLayout.addWidget(l1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        l2 = QLabel(self.tr("And:"), hbox)
        hboxLayout.addWidget(l2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        self.rangesItemsBoxLayout.addWidget(hbox)
        
        cb1.activated[int].connect(self.__rangesCharTypeSelected)
        hbox.show()
        
        self.rangesItemsBox.adjustSize()
        
        self.rangesEntries.append([cb1, le1, le2])
    
    def __populateCharacterCombo(self, combo, format):
        """
        Private method to populate a character selection combo.
        
        @param combo combo box to be populated (QComboBox)
        @param format format identifier (one of "-ccp", "-ccn",
            "-cbp", "-cbn", "-csp", "-csn", "-psp", "-psn")
        """
        combo.clear()
        
        if format in ["-ccp", "-ccn"]:
            items = self.__characterCategories
        elif format in ["-csp", "-csn"]:
            items = self.__specialCharacterCategories
        elif format in ["-cbp", "-cbn"]:
            items = self.__characterBlocks
        elif format in ["-psp", "-psn"]:
            items = self.__posixNamedSets
        
        comboLen = 0
        for txt, code in items:
            combo.addItem(txt, code)
            comboLen = max(comboLen, len(txt))
        combo.setMinimumContentsLength(comboLen)
    
    def __performSelectedAction(self, format, lineedit, combo):
        """
        Private method performing some actions depending on the input.
        
        @param format format of the selected entry (string)
        @param lineedit line edit widget to act on (QLineEdit)
        @param combo combo box widget to act on (QComboBox)
        """
        if format == "-i":
            return
        
        if format in ["-c", "-h", "-o"]:
            lineedit.show()
            lineedit.setEnabled(True)
            if combo is not None:
                combo.hide()
            if format == "-c":
                lineedit.setValidator(self.charValidator)
            elif format == "-h":
                lineedit.setValidator(self.hexValidator)
            elif format == "-o":
                lineedit.setValidator(self.octValidator)
        elif format in ["-ccp", "-ccn", "-cbp", "-cbn", "-csp", "-csn",
                        "-psp", "-psn"]:
            lineedit.setEnabled(False)
            lineedit.hide()
            if combo is not None:
                combo.show()
            self.__populateCharacterCombo(combo, format)
        else:
            lineedit.setEnabled(False)
            lineedit.hide()
            if combo is not None:
                combo.hide()
        lineedit.clear()
    
    def __singlesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the single chars
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.singlesEntries:
            if combo == entriesList[0]:
                format = combo.itemData(index)
                self.__performSelectedAction(
                    format, entriesList[1], entriesList[2])
                break
    
    def __rangesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the char ranges
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.rangesEntries:
            if combo == entriesList[0]:
                format = combo.itemData(index)
                self.__performSelectedAction(format, entriesList[1], None)
                self.__performSelectedAction(format, entriesList[2], None)
                break
    
    def __formatCharacter(self, char, format):
        """
        Private method to format the characters entered into the dialog.
        
        @param char character string entered into the dialog (string)
        @param format string giving a special format (-c, -h, -i or -o) or
            the already formatted character (string)
        @return formatted character string (string)
        """
        if format == "-c":
            return char
        elif format == "-i":
            return ""
        
        if format == "-h":
            while len(char) < 2:
                char = "0" + char
            if len(char) > 2:
                return "\\x{{{0}}}".format(char.lower())
            else:
                return "\\x{0}".format(char.lower())
        elif format == "-o":
            while len(char) < 3:
                char = "0" + char
            if len(char) > 3:
                char = char[:3]
            return "\\{0}".format(char)
        elif format in ["-ccp", "-cbp", "-csp"]:
            return "\\p{{{0}}}".format(char)
        elif format in ["-ccn", "-cbn", "-csn"]:
            return "\\P{{{0}}}".format(char)
        elif format == "-psp":
            return "[:{0}:]".format(char)
        elif format == "-psn":
            return "[:^{0}:]".format(char)
        else:
            return format
    
    def getCharacters(self):
        """
        Public method to return the character string assembled via the dialog.
        
        @return formatted string for character classes (string)
        """
        regexp = ""
        
        # negative character range
        if self.negativeCheckBox.isChecked():
            regexp += "^"
            
        # predefined character ranges
        if self.wordCharCheckBox.isChecked():
            regexp += "\\w"
        if self.nonWordCharCheckBox.isChecked():
            regexp += "\\W"
        if self.digitsCheckBox.isChecked():
            regexp += "\\d"
        if self.nonDigitsCheckBox.isChecked():
            regexp += "\\D"
        if self.newlineCheckBox.isChecked():
            regexp += "\\R"
        if self.nonNewlineCheckBox.isChecked():
            regexp += "\\N"
        if self.whitespaceCheckBox.isChecked():
            regexp += "\\s"
        if self.nonWhitespaceCheckBox.isChecked():
            regexp += "\\S"
        if self.horizontalWhitespaceCheckBox.isChecked():
            regexp += "\\h"
        if self.nonHorizontalWhitespaceCheckBox.isChecked():
            regexp += "\\H"
        if self.verticalWhitespaceCheckBox.isChecked():
            regexp += "\\v"
        if self.nonVerticalWhitespaceCheckBox.isChecked():
            regexp += "\\V"
        
        # single characters
        for entrieslist in self.singlesEntries:
            format = entrieslist[0].itemData(entrieslist[0].currentIndex())
            if format in ["-ccp", "-ccn", "-cbp", "-cbn", "-csp", "-csn",
                          "-psp", "-psn"]:
                char = entrieslist[2].itemData(entrieslist[2].currentIndex())
            else:
                char = entrieslist[1].text()
            regexp += self.__formatCharacter(char, format)
        
        # character ranges
        for entrieslist in self.rangesEntries:
            if not entrieslist[1].text() or \
               not entrieslist[2].text():
                continue
            format = entrieslist[0].itemData(entrieslist[0].currentIndex())
            char1 = entrieslist[1].text()
            char2 = entrieslist[2].text()
            regexp += "{0}-{1}".format(
                self.__formatCharacter(char1, format),
                self.__formatCharacter(char2, format))
        
        if regexp:
            if (regexp.startswith("\\") and
                regexp.count("\\") == 1 and
                "-" not in regexp) or \
               len(regexp) == 1:
                return regexp
            else:
                return "[{0}]".format(regexp)
        else:
            return ""
예제 #20
0
class QRegExpWizardCharactersDialog(QDialog, Ui_QRegExpWizardCharactersDialog):
    """
    Class implementing a dialog for entering character classes.
    """
    RegExpMode = 0
    WildcardMode = 1
    W3CMode = 2

    def __init__(self, mode=RegExpMode, parent=None):
        """
        Constructor
        
        @param mode mode of the dialog (one of RegExpMode, WildcardMode,
            W3CMode)
        @param parent parent widget (QWidget)
        """
        super(QRegExpWizardCharactersDialog, self).__init__(parent)
        self.setupUi(self)

        self.__mode = mode

        if mode == QRegExpWizardCharactersDialog.WildcardMode:
            self.predefinedBox.setEnabled(False)
            self.predefinedBox.hide()
        elif mode == QRegExpWizardCharactersDialog.RegExpMode:
            self.w3cInitialIdentifierCheckBox.hide()
            self.w3cNonInitialIdentifierCheckBox.hide()
            self.w3cNmtokenCheckBox.hide()
            self.w3cNonNmtokenCheckBox.hide()
        elif mode == QRegExpWizardCharactersDialog.W3CMode:
            self.__initCharacterSelectors()

        self.comboItems = []
        self.singleComboItems = []  # these are in addition to the above
        self.comboItems.append((self.tr("Normal character"), "-c"))
        if mode == QRegExpWizardCharactersDialog.RegExpMode:
            self.comboItems.append(
                (self.tr("Unicode character in hexadecimal notation"), "-h"))
            self.comboItems.append(
                (self.tr("ASCII/Latin1 character in octal notation"), "-o"))
            self.singleComboItems.append(("---", "-i"))
            self.singleComboItems.append(
                (self.tr("Bell character (\\a)"), "\\a"))
            self.singleComboItems.append((self.tr("Page break (\\f)"), "\\f"))
            self.singleComboItems.append((self.tr("Line feed (\\n)"), "\\n"))
            self.singleComboItems.append(
                (self.tr("Carriage return (\\r)"), "\\r"))
            self.singleComboItems.append(
                (self.tr("Horizontal tabulator (\\t)"), "\\t"))
            self.singleComboItems.append(
                (self.tr("Vertical tabulator (\\v)"), "\\v"))
        elif mode == QRegExpWizardCharactersDialog.W3CMode:
            self.comboItems.append(
                (self.tr("Unicode character in hexadecimal notation"), "-h"))
            self.comboItems.append(
                (self.tr("ASCII/Latin1 character in octal notation"), "-o"))
            self.singleComboItems.append(("---", "-i"))
            self.singleComboItems.append((self.tr("Line feed (\\n)"), "\\n"))
            self.singleComboItems.append(
                (self.tr("Carriage return (\\r)"), "\\r"))
            self.singleComboItems.append(
                (self.tr("Horizontal tabulator (\\t)"), "\\t"))
            self.singleComboItems.append(("---", "-i"))
            self.singleComboItems.append(
                (self.tr("Character Category"), "-ccp"))
            self.singleComboItems.append((self.tr("Character Block"), "-cbp"))
            self.singleComboItems.append(
                (self.tr("Not Character Category"), "-ccn"))
            self.singleComboItems.append(
                (self.tr("Not Character Block"), "-cbn"))

        self.charValidator = QRegExpValidator(QRegExp(".{0,1}"), self)
        self.hexValidator = QRegExpValidator(QRegExp("[0-9a-fA-F]{0,4}"), self)
        self.octValidator = QRegExpValidator(QRegExp("[0-3]?[0-7]{0,2}"), self)

        # generate dialog part for single characters
        self.singlesBoxLayout = QVBoxLayout(self.singlesBox)
        self.singlesBoxLayout.setObjectName("singlesBoxLayout")
        self.singlesBoxLayout.setSpacing(6)
        self.singlesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesBox.setLayout(self.singlesBoxLayout)
        self.singlesView = QScrollArea(self.singlesBox)
        self.singlesView.setObjectName("singlesView")
        self.singlesBoxLayout.addWidget(self.singlesView)

        self.singlesItemsBox = QWidget(self)
        self.singlesView.setWidget(self.singlesItemsBox)
        self.singlesItemsBox.setObjectName("singlesItemsBox")
        self.singlesItemsBox.setMinimumWidth(1000)
        self.singlesItemsBoxLayout = QVBoxLayout(self.singlesItemsBox)
        self.singlesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesItemsBoxLayout.setSpacing(6)
        self.singlesItemsBox.setLayout(self.singlesItemsBoxLayout)
        self.singlesEntries = []
        self.__addSinglesLine()

        hlayout0 = QHBoxLayout()
        hlayout0.setContentsMargins(0, 0, 0, 0)
        hlayout0.setSpacing(6)
        hlayout0.setObjectName("hlayout0")
        self.moreSinglesButton = QPushButton(self.tr("Additional Entries"),
                                             self.singlesBox)
        self.moreSinglesButton.setObjectName("moreSinglesButton")
        hlayout0.addWidget(self.moreSinglesButton)
        hspacer0 = QSpacerItem(30, 20, QSizePolicy.Expanding,
                               QSizePolicy.Minimum)
        hlayout0.addItem(hspacer0)
        self.singlesBoxLayout.addLayout(hlayout0)
        self.moreSinglesButton.clicked.connect(self.__addSinglesLine)

        # generate dialog part for character ranges
        self.rangesBoxLayout = QVBoxLayout(self.rangesBox)
        self.rangesBoxLayout.setObjectName("rangesBoxLayout")
        self.rangesBoxLayout.setSpacing(6)
        self.rangesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesBox.setLayout(self.rangesBoxLayout)
        self.rangesView = QScrollArea(self.rangesBox)
        self.rangesView.setObjectName("rangesView")
        self.rangesBoxLayout.addWidget(self.rangesView)

        self.rangesItemsBox = QWidget(self)
        self.rangesView.setWidget(self.rangesItemsBox)
        self.rangesItemsBox.setObjectName("rangesItemsBox")
        self.rangesItemsBox.setMinimumWidth(1000)
        self.rangesItemsBoxLayout = QVBoxLayout(self.rangesItemsBox)
        self.rangesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesItemsBoxLayout.setSpacing(6)
        self.rangesItemsBox.setLayout(self.rangesItemsBoxLayout)
        self.rangesEntries = []
        self.__addRangesLine()

        hlayout1 = QHBoxLayout()
        hlayout1.setContentsMargins(0, 0, 0, 0)
        hlayout1.setSpacing(6)
        hlayout1.setObjectName("hlayout1")
        self.moreRangesButton = QPushButton(self.tr("Additional Entries"),
                                            self.rangesBox)
        self.moreSinglesButton.setObjectName("moreRangesButton")
        hlayout1.addWidget(self.moreRangesButton)
        hspacer1 = QSpacerItem(30, 20, QSizePolicy.Expanding,
                               QSizePolicy.Minimum)
        hlayout1.addItem(hspacer1)
        self.rangesBoxLayout.addLayout(hlayout1)
        self.moreRangesButton.clicked.connect(self.__addRangesLine)

    def __initCharacterSelectors(self):
        """
        Private method to initialize the W3C character selector entries.
        """
        self.__characterCategories = (
            # display name                              code
            (self.tr("Letter, Any"), "L"),
            (self.tr("Letter, Uppercase"), "Lu"),
            (self.tr("Letter, Lowercase"), "Ll"),
            (self.tr("Letter, Titlecase"), "Lt"),
            (self.tr("Letter, Modifier"), "Lm"),
            (self.tr("Letter, Other"), "Lo"),
            (self.tr("Mark, Any"), "M"),
            (self.tr("Mark, Nonspacing"), "Mn"),
            (self.tr("Mark, Spacing Combining"), "Mc"),
            (self.tr("Mark, Enclosing"), "Me"),
            (self.tr("Number, Any"), "N"),
            (self.tr("Number, Decimal Digit"), "Nd"),
            (self.tr("Number, Letter"), "Nl"),
            (self.tr("Number, Other"), "No"),
            (self.tr("Punctuation, Any"), "P"),
            (self.tr("Punctuation, Connector"), "Pc"),
            (self.tr("Punctuation, Dash"), "Pd"),
            (self.tr("Punctuation, Open"), "Ps"),
            (self.tr("Punctuation, Close"), "Pe"),
            (self.tr("Punctuation, Initial Quote"), "Pi"),
            (self.tr("Punctuation, Final Quote"), "Pf"),
            (self.tr("Punctuation, Other"), "Po"),
            (self.tr("Symbol, Any"), "S"),
            (self.tr("Symbol, Math"), "Sm"),
            (self.tr("Symbol, Currency"), "Sc"),
            (self.tr("Symbol, Modifier"), "Sk"),
            (self.tr("Symbol, Other"), "So"),
            (self.tr("Separator, Any"), "Z"),
            (self.tr("Separator, Space"), "Zs"),
            (self.tr("Separator, Line"), "Zl"),
            (self.tr("Separator, Paragraph"), "Zp"),
            (self.tr("Other, Any"), "C"),
            (self.tr("Other, Control"), "Cc"),
            (self.tr("Other, Format"), "Cf"),
            (self.tr("Other, Private Use"), "Co"),
            (self.tr("Other, Not Assigned"), "Cn"),
        )

        self.__characterBlocks = (
            (self.tr("Basic Latin"), "IsBasicLatin"),
            (self.tr("Latin-1 Supplement"), "IsLatin-1Supplement"),
            (self.tr("Latin Extended-A"), "IsLatinExtended-A"),
            (self.tr("Latin Extended-B"), "IsLatinExtended-B"),
            (self.tr("IPA Extensions"), "IsIPAExtensions"),
            (self.tr("Spacing Modifier Letters"), "IsSpacingModifierLetters"),
            (self.tr("Combining Diacritical Marks"),
             "IsCombiningDiacriticalMarks"),
            (self.tr("Greek"), "IsGreek"),
            (self.tr("Cyrillic"), "IsCyrillic"),
            (self.tr("Armenian"), "IsArmenian"),
            (self.tr("Hebrew"), "IsHebrew"),
            (self.tr("Arabic"), "IsArabic"),
            (self.tr("Syriac"), "IsSyriac"),
            (self.tr("Thaana"), "IsThaana"),
            (self.tr("Devanagari"), "IsDevanagari"),
            (self.tr("Bengali"), "IsBengali"),
            (self.tr("Gurmukhi"), "IsBengali"),
            (self.tr("Gujarati"), "IsGujarati"),
            (self.tr("Oriya"), "IsOriya"),
            (self.tr("Tamil"), "IsTamil"),
            (self.tr("Telugu"), "IsTelugu"),
            (self.tr("Kannada"), "IsKannada"),
            (self.tr("Malayalam"), "IsMalayalam"),
            (self.tr("Sinhala"), "IsSinhala"),
            (self.tr("Thai"), "IsThai"),
            (self.tr("Lao"), "IsLao"),
            (self.tr("Tibetan"), "IsTibetan"),
            (self.tr("Myanmar"), "IsMyanmar"),
            (self.tr("Georgian"), "IsGeorgian"),
            (self.tr("Hangul Jamo"), "IsHangulJamo"),
            (self.tr("Ethiopic"), "IsEthiopic"),
            (self.tr("Cherokee"), "IsCherokee"),
            (self.tr("Unified Canadian Aboriginal Syllabics"),
             "IsUnifiedCanadianAboriginalSyllabics"),
            (self.tr("Ogham"), "IsOgham"),
            (self.tr("Runic"), "IsRunic"),
            (self.tr("Khmer"), "IsKhmer"),
            (self.tr("Mongolian"), "IsMongolian"),
            (self.tr("Latin Extended Additional"),
             "IsLatinExtendedAdditional"),
            (self.tr("Greek Extended"), "IsGreekExtended"),
            (self.tr("General Punctuation"), "IsGeneralPunctuation"),
            (self.tr("Superscripts and Subscripts"),
             "IsSuperscriptsandSubscripts"),
            (self.tr("Currency Symbols"), "IsCurrencySymbols"),
            (self.tr("Combining Marks for Symbols"),
             "IsCombiningMarksforSymbols"),
            (self.tr("Letterlike Symbols"), "IsLetterlikeSymbols"),
            (self.tr("Number Forms"), "IsNumberForms"),
            (self.tr("Arrows"), "IsArrows"),
            (self.tr("Mathematical Operators"), "IsMathematicalOperators"),
            (self.tr("Miscellaneous Technical"), "IsMiscellaneousTechnical"),
            (self.tr("Control Pictures"), "IsControlPictures"),
            (self.tr("Optical Character Recognition"),
             "IsOpticalCharacterRecognition"),
            (self.tr("Enclosed Alphanumerics"), "IsEnclosedAlphanumerics"),
            (self.tr("Box Drawing"), "IsBoxDrawing"),
            (self.tr("Block Elements"), "IsBlockElements"),
            (self.tr("Geometric Shapes"), "IsGeometricShapes"),
            (self.tr("Miscellaneous Symbols"), "IsMiscellaneousSymbols"),
            (self.tr("Dingbats"), "IsDingbats"),
            (self.tr("Braille Patterns"), "IsBraillePatterns"),
            (self.tr("CJK Radicals Supplement"), "IsCJKRadicalsSupplement"),
            (self.tr("KangXi Radicals"), "IsKangXiRadicals"),
            (self.tr("Ideographic Description Chars"),
             "IsIdeographicDescriptionChars"),
            (self.tr("CJK Symbols and Punctuation"),
             "IsCJKSymbolsandPunctuation"),
            (self.tr("Hiragana"), "IsHiragana"),
            (self.tr("Katakana"), "IsKatakana"),
            (self.tr("Bopomofo"), "IsBopomofo"),
            (self.tr("Hangul Compatibility Jamo"),
             "IsHangulCompatibilityJamo"),
            (self.tr("Kanbun"), "IsKanbun"),
            (self.tr("Bopomofo Extended"), "IsBopomofoExtended"),
            (self.tr("Enclosed CJK Letters and Months"),
             "IsEnclosedCJKLettersandMonths"),
            (self.tr("CJK Compatibility"), "IsCJKCompatibility"),
            (self.tr("CJK Unified Ideographs Extension A"),
             "IsCJKUnifiedIdeographsExtensionA"),
            (self.tr("CJK Unified Ideographs"), "IsCJKUnifiedIdeographs"),
            (self.tr("Yi Syllables"), "IsYiSyllables"),
            (self.tr("Yi Radicals"), "IsYiRadicals"),
            (self.tr("Hangul Syllables"), "IsHangulSyllables"),
            (self.tr("Private Use"), "IsPrivateUse"),
            (self.tr("CJK Compatibility Ideographs"),
             "IsCJKCompatibilityIdeographs"),
            (self.tr("Alphabetic Presentation Forms"),
             "IsAlphabeticPresentationForms"),
            (self.tr("Arabic Presentation Forms-A"),
             "IsArabicPresentationForms-A"),
            (self.tr("Combining Half Marks"), "IsCombiningHalfMarks"),
            (self.tr("CJK Compatibility Forms"), "IsCJKCompatibilityForms"),
            (self.tr("Small Form Variants"), "IsSmallFormVariants"),
            (self.tr("Arabic Presentation Forms-B"),
             "IsArabicPresentationForms-B"),
            (self.tr("Halfwidth and Fullwidth Forms"),
             "IsHalfwidthandFullwidthForms"),
            (self.tr("Specials"), "IsSpecials"),
            (self.tr("Old Italic"), "IsOldItalic"),
            (self.tr("Gothic"), "IsGothic"),
            (self.tr("Deseret"), "IsDeseret"),
            (self.tr("Byzantine Musical Symbols"),
             "IsByzantineMusicalSymbols"),
            (self.tr("Musical Symbols"), "IsMusicalSymbols"),
            (self.tr("Mathematical Alphanumeric Symbols"),
             "IsMathematicalAlphanumericSymbols"),
            (self.tr("CJK Unified Ideographic Extension B"),
             "IsCJKUnifiedIdeographicExtensionB"),
            (self.tr("CJK Compatapility Ideographic Supplement"),
             "IsCJKCompatapilityIdeographicSupplement"),
            (self.tr("Tags"), "IsTags"),
        )

    def __populateCharTypeCombo(self, combo, isSingle):
        """
        Private method to populate a given character type selection combo box.
        
        @param combo reference to the combo box to be populated (QComboBox)
        @param isSingle flag indicating a singles combo (boolean)
        """
        for txt, value in self.comboItems:
            combo.addItem(txt, value)
        if isSingle:
            for txt, value in self.singleComboItems:
                combo.addItem(txt, value)

    def __addSinglesLine(self):
        """
        Private slot to add a line of entry widgets for single characters.
        """
        hbox = QWidget(self.singlesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        self.__populateCharTypeCombo(cb1, True)
        hboxLayout.addWidget(cb1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        cb1a = QComboBox(hbox)
        cb1a.setEditable(False)
        cb1a.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        hboxLayout.addWidget(cb1a)
        cb1a.hide()
        cb2 = QComboBox(hbox)
        cb2.setEditable(False)
        self.__populateCharTypeCombo(cb2, True)
        hboxLayout.addWidget(cb2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        cb2a = QComboBox(hbox)
        cb2a.setEditable(False)
        cb2a.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        hboxLayout.addWidget(cb2a)
        cb2a.hide()
        self.singlesItemsBoxLayout.addWidget(hbox)

        cb1.activated[int].connect(self.__singlesCharTypeSelected)
        cb2.activated[int].connect(self.__singlesCharTypeSelected)
        hbox.show()

        self.singlesItemsBox.adjustSize()

        self.singlesEntries.append([cb1, le1, cb1a])
        self.singlesEntries.append([cb2, le2, cb2a])

    def __addRangesLine(self):
        """
        Private slot to add a line of entry widgets for character ranges.
        """
        hbox = QWidget(self.rangesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        self.__populateCharTypeCombo(cb1, False)
        hboxLayout.addWidget(cb1)
        l1 = QLabel(self.tr("Between:"), hbox)
        hboxLayout.addWidget(l1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        l2 = QLabel(self.tr("And:"), hbox)
        hboxLayout.addWidget(l2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        self.rangesItemsBoxLayout.addWidget(hbox)

        cb1.activated[int].connect(self.__rangesCharTypeSelected)
        hbox.show()

        self.rangesItemsBox.adjustSize()

        self.rangesEntries.append([cb1, le1, le2])

    def __populateW3cCharacterCombo(self, combo, format):
        """
        Private method to populate a W3C character selection combo.
        
        @param combo combo box to be populated (QComboBox)
        @param format format identifier (one of "-ccp", "-ccn", "-cbp", "-cbn")
        """
        combo.clear()

        if format in ["-ccp", "-ccn"]:
            comboLen = 0
            for txt, code in self.__characterCategories:
                combo.addItem(txt, code)
                comboLen = max(comboLen, len(txt))
            combo.setMinimumContentsLength(comboLen)
        elif format in ["-cbp", "-cbn"]:
            comboLen = 0
            for txt, code in self.__characterBlocks:
                combo.addItem(txt, code)
                comboLen = max(comboLen, len(txt))
            combo.setMinimumContentsLength(comboLen)

    def __performSelectedAction(self, format, lineedit, combo):
        """
        Private method performing some actions depending on the input.
        
        @param format format of the selected entry (string)
        @param lineedit line edit widget to act on (QLineEdit)
        @param combo combo box widget to act on (QComboBox)
        """
        if format == "-i":
            return

        if format in ["-c", "-h", "-o"]:
            lineedit.show()
            lineedit.setEnabled(True)
            if combo is not None:
                combo.hide()
            if format == "-c":
                lineedit.setValidator(self.charValidator)
            elif format == "-h":
                lineedit.setValidator(self.hexValidator)
            elif format == "-o":
                lineedit.setValidator(self.octValidator)
        elif format in ["-ccp", "-ccn", "-cbp", "-cbn"]:
            lineedit.setEnabled(False)
            lineedit.hide()
            if combo is not None:
                combo.show()
            self.__populateW3cCharacterCombo(combo, format)
        else:
            lineedit.setEnabled(False)
            lineedit.hide()
            if combo is not None:
                combo.hide()
        lineedit.clear()

    def __singlesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the single chars
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.singlesEntries:
            if combo == entriesList[0]:
                format = combo.itemData(index)
                self.__performSelectedAction(format, entriesList[1],
                                             entriesList[2])
                break

    def __rangesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the char ranges
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.rangesEntries:
            if combo == entriesList[0]:
                format = combo.itemData(index)
                self.__performSelectedAction(format, entriesList[1], None)
                self.__performSelectedAction(format, entriesList[2], None)
                break

    def __formatCharacter(self, char, format):
        """
        Private method to format the characters entered into the dialog.
        
        @param char character string entered into the dialog (string)
        @param format string giving a special format (-c, -h, -i or -o) or
            the already formatted character (string)
        @return formatted character string (string)
        """
        if format == "-c":
            return char
        elif format == "-i":
            return ""

        if self.__mode in [
                QRegExpWizardCharactersDialog.RegExpMode,
                QRegExpWizardCharactersDialog.W3CMode
        ]:
            if format == "-h":
                return "\\x{0}".format(char.lower())
            elif format == "-o":
                return "\\0{0}".format(char)
            elif format in ["-ccp", "-cbp"]:
                return "\\p{{{0}}}".format(char)
            elif format in ["-ccn", "-cbn"]:
                return "\\P{{{0}}}".format(char)
            else:
                return format

    def getCharacters(self):
        """
        Public method to return the character string assembled via the dialog.
        
        @return formatted string for character classes (string)
        """
        regexp = ""

        # negative character range
        if self.negativeCheckBox.isChecked():
            regexp += "^"

        # predefined character ranges
        if self.wordCharCheckBox.isChecked():
            regexp += "\\w"
        if self.nonWordCharCheckBox.isChecked():
            regexp += "\\W"
        if self.digitsCheckBox.isChecked():
            regexp += "\\d"
        if self.nonDigitsCheckBox.isChecked():
            regexp += "\\D"
        if self.whitespaceCheckBox.isChecked():
            regexp += "\\s"
        if self.nonWhitespaceCheckBox.isChecked():
            regexp += "\\S"
        if self.w3cInitialIdentifierCheckBox.isChecked():
            regexp += "\\i"
        if self.w3cNonInitialIdentifierCheckBox.isChecked():
            regexp += "\\I"
        if self.w3cNmtokenCheckBox.isChecked():
            regexp += "\\c"
        if self.w3cNonNmtokenCheckBox.isChecked():
            regexp += "\\C"

        # single characters
        for entrieslist in self.singlesEntries:
            format = entrieslist[0].itemData(entrieslist[0].currentIndex())
            if format in ["-ccp", "-ccn", "-cbp", "-cbn"]:
                char = entrieslist[2].itemData(entrieslist[2].currentIndex())
            else:
                char = entrieslist[1].text()
            regexp += self.__formatCharacter(char, format)

        # character ranges
        for entrieslist in self.rangesEntries:
            if not entrieslist[1].text() or \
               not entrieslist[2].text():
                continue
            format = entrieslist[0].itemData(entrieslist[0].currentIndex())
            char1 = entrieslist[1].text()
            char2 = entrieslist[2].text()
            regexp += "{0}-{1}".format(self.__formatCharacter(char1, format),
                                       self.__formatCharacter(char2, format))

        if regexp:
            if (regexp.startswith("\\") and
                regexp.count("\\") == 1 and
                "-" not in regexp) or \
               len(regexp) == 1:
                return regexp
            else:
                return "[{0}]".format(regexp)
        else:
            return ""
class QRegularExpressionWizardCharactersDialog(
        QDialog, Ui_QRegularExpressionWizardCharactersDialog):
    """
    Class implementing a dialog for entering character classes.
    """
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget (QWidget)
        """
        super(QRegularExpressionWizardCharactersDialog, self).__init__(parent)
        self.setupUi(self)

        self.__initCharacterSelectors()

        self.comboItems = []
        self.singleComboItems = []  # these are in addition to the above
        self.comboItems.append((self.tr("Normal character"), "-c"))
        self.comboItems.append(
            (self.tr("Unicode character in hexadecimal notation"), "-h"))
        self.comboItems.append(
            (self.tr("ASCII/Latin1 character in octal notation"), "-o"))
        self.singleComboItems.extend([
            ("---", "-i"),
            (self.tr("Bell character (\\a)"), "\\a"),
            (self.tr("Escape character (\\e)"), "\\e"),
            (self.tr("Page break (\\f)"), "\\f"),
            (self.tr("Line feed (\\n)"), "\\n"),
            (self.tr("Carriage return (\\r)"), "\\r"),
            (self.tr("Horizontal tabulator (\\t)"), "\\t"),
            ("---", "-i"),
            (self.tr("Character Category"), "-ccp"),
            (self.tr("Special Character Category"), "-csp"),
            (self.tr("Character Block"), "-cbp"),
            (self.tr("POSIX Named Set"), "-psp"),
            (self.tr("Not Character Category"), "-ccn"),
            (self.tr("Not Character Block"), "-cbn"),
            (self.tr("Not Special Character Category"), "-csn"),
            (self.tr("Not POSIX Named Set"), "-psn"),
        ])

        self.charValidator = QRegExpValidator(QRegExp(".{0,1}"), self)
        self.hexValidator = QRegExpValidator(QRegExp("[0-9a-fA-F]{0,4}"), self)
        self.octValidator = QRegExpValidator(QRegExp("[0-3]?[0-7]{0,2}"), self)

        # generate dialog part for single characters
        self.singlesBoxLayout = QVBoxLayout(self.singlesBox)
        self.singlesBoxLayout.setObjectName("singlesBoxLayout")
        self.singlesBoxLayout.setSpacing(6)
        self.singlesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesBox.setLayout(self.singlesBoxLayout)
        self.singlesView = QScrollArea(self.singlesBox)
        self.singlesView.setObjectName("singlesView")
        self.singlesBoxLayout.addWidget(self.singlesView)

        self.singlesItemsBox = QWidget(self)
        self.singlesView.setWidget(self.singlesItemsBox)
        self.singlesItemsBox.setObjectName("singlesItemsBox")
        self.singlesItemsBox.setMinimumWidth(1000)
        self.singlesItemsBoxLayout = QVBoxLayout(self.singlesItemsBox)
        self.singlesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesItemsBoxLayout.setSpacing(6)
        self.singlesItemsBox.setLayout(self.singlesItemsBoxLayout)
        self.singlesEntries = []
        self.__addSinglesLine()

        hlayout0 = QHBoxLayout()
        hlayout0.setContentsMargins(0, 0, 0, 0)
        hlayout0.setSpacing(6)
        hlayout0.setObjectName("hlayout0")
        self.moreSinglesButton = QPushButton(self.tr("Additional Entries"),
                                             self.singlesBox)
        self.moreSinglesButton.setObjectName("moreSinglesButton")
        hlayout0.addWidget(self.moreSinglesButton)
        hspacer0 = QSpacerItem(30, 20, QSizePolicy.Expanding,
                               QSizePolicy.Minimum)
        hlayout0.addItem(hspacer0)
        self.singlesBoxLayout.addLayout(hlayout0)
        self.moreSinglesButton.clicked.connect(self.__addSinglesLine)

        # generate dialog part for character ranges
        self.rangesBoxLayout = QVBoxLayout(self.rangesBox)
        self.rangesBoxLayout.setObjectName("rangesBoxLayout")
        self.rangesBoxLayout.setSpacing(6)
        self.rangesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesBox.setLayout(self.rangesBoxLayout)
        self.rangesView = QScrollArea(self.rangesBox)
        self.rangesView.setObjectName("rangesView")
        self.rangesBoxLayout.addWidget(self.rangesView)

        self.rangesItemsBox = QWidget(self)
        self.rangesView.setWidget(self.rangesItemsBox)
        self.rangesItemsBox.setObjectName("rangesItemsBox")
        self.rangesItemsBox.setMinimumWidth(1000)
        self.rangesItemsBoxLayout = QVBoxLayout(self.rangesItemsBox)
        self.rangesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesItemsBoxLayout.setSpacing(6)
        self.rangesItemsBox.setLayout(self.rangesItemsBoxLayout)
        self.rangesEntries = []
        self.__addRangesLine()

        hlayout1 = QHBoxLayout()
        hlayout1.setContentsMargins(0, 0, 0, 0)
        hlayout1.setSpacing(6)
        hlayout1.setObjectName("hlayout1")
        self.moreRangesButton = QPushButton(self.tr("Additional Entries"),
                                            self.rangesBox)
        self.moreSinglesButton.setObjectName("moreRangesButton")
        hlayout1.addWidget(self.moreRangesButton)
        hspacer1 = QSpacerItem(30, 20, QSizePolicy.Expanding,
                               QSizePolicy.Minimum)
        hlayout1.addItem(hspacer1)
        self.rangesBoxLayout.addLayout(hlayout1)
        self.moreRangesButton.clicked.connect(self.__addRangesLine)

    def __initCharacterSelectors(self):
        """
        Private method to initialize the W3C character selector entries.
        """
        self.__characterCategories = (
            # display name                                  code
            (self.tr("Letter, Any"), "L"),
            (self.tr("Letter, Lower case"), "Ll"),
            (self.tr("Letter, Modifier"), "Lm"),
            (self.tr("Letter, Other"), "Lo"),
            (self.tr("Letter, Title case"), "Lt"),
            (self.tr("Letter, Upper case"), "Lu"),
            (self.tr("Letter, Lower, Upper or Title"), "L&"),
            (self.tr("Mark, Any"), "M"),
            (self.tr("Mark, Spacing"), "Mc"),
            (self.tr("Mark, Enclosing"), "Me"),
            (self.tr("Mark, Non-spacing"), "Mn"),
            (self.tr("Number, Any"), "N"),
            (self.tr("Number, Decimal"), "Nd"),
            (self.tr("Number, Letter"), "Nl"),
            (self.tr("Number, Other"), "No"),
            (self.tr("Punctuation, Any"), "P"),
            (self.tr("Punctuation, Connector"), "Pc"),
            (self.tr("Punctuation, Dash"), "Pd"),
            (self.tr("Punctuation, Close"), "Pe"),
            (self.tr("Punctuation, Final"), "Pf"),
            (self.tr("Punctuation, Initial"), "Pi"),
            (self.tr("Punctuation, Other"), "Po"),
            (self.tr("Punctuation, Open"), "Ps"),
            (self.tr("Symbol, Any"), "S"),
            (self.tr("Symbol, Currency"), "Sc"),
            (self.tr("Symbol, Modifier"), "Sk"),
            (self.tr("Symbol, Mathematical"), "Sm"),
            (self.tr("Symbol, Other"), "So"),
            (self.tr("Separator, Any"), "Z"),
            (self.tr("Separator, Line"), "Zl"),
            (self.tr("Separator, Paragraph"), "Zp"),
            (self.tr("Separator, Space"), "Zs"),
            (self.tr("Other, Any"), "C"),
            (self.tr("Other, Control"), "Cc"),
            (self.tr("Other, Format"), "Cf"),
            (self.tr("Other, Unassigned"), "Cn"),
            (self.tr("Other, Private Use"), "Co"),
            (self.tr("Other, Surrogat"), "Cn"),
        )

        self.__specialCharacterCategories = (
            # display name                           code
            (self.tr("Alphanumeric"), "Xan"),
            (self.tr("POSIX Space"), "Xps"),
            (self.tr("Perl Space"), "Xsp"),
            (self.tr("Universal Character"), "Xuc"),
            (self.tr("Perl Word"), "Xan"),
        )

        self.__characterBlocks = (
            # display name                           code
            (self.tr("Arabic"), "Arabic"),
            (self.tr("Armenian"), "Armenian"),
            (self.tr("Avestan"), "Avestan"),
            (self.tr("Balinese"), "Balinese"),
            (self.tr("Bamum"), "Bamum"),
            (self.tr("Batak"), "Batak"),
            (self.tr("Bengali"), "Bengali"),
            (self.tr("Bopomofo"), "Bopomofo"),
            (self.tr("Brahmi"), "Brahmi"),
            (self.tr("Braille"), "Braille"),
            (self.tr("Buginese"), "Buginese"),
            (self.tr("Buhid"), "Buhid"),
            (self.tr("Canadian Aboriginal"), "Canadian_Aboriginal"),
            (self.tr("Carian"), "Carian"),
            (self.tr("Chakma"), "Chakma"),
            (self.tr("Cham"), "Cham"),
            (self.tr("Cherokee"), "Cherokee"),
            (self.tr("Common"), "Common"),
            (self.tr("Coptic"), "Coptic"),
            (self.tr("Cuneiform"), "Cuneiform"),
            (self.tr("Cypriot"), "Cypriot"),
            (self.tr("Cyrillic"), "Cyrillic"),
            (self.tr("Deseret"), "Deseret,"),
            (self.tr("Devanagari"), "Devanagari"),
            (self.tr("Egyptian Hieroglyphs"), "Egyptian_Hieroglyphs"),
            (self.tr("Ethiopic"), "Ethiopic"),
            (self.tr("Georgian"), "Georgian"),
            (self.tr("Glagolitic"), "Glagolitic"),
            (self.tr("Gothic"), "Gothic"),
            (self.tr("Greek"), "Greek"),
            (self.tr("Gujarati"), "Gujarati"),
            (self.tr("Gurmukhi"), "Gurmukhi"),
            (self.tr("Han"), "Han"),
            (self.tr("Hangul"), "Hangul"),
            (self.tr("Hanunoo"), "Hanunoo"),
            (self.tr("Hebrew"), "Hebrew"),
            (self.tr("Hiragana"), "Hiragana"),
            (self.tr("Imperial Aramaic"), "Imperial_Aramaic"),
            (self.tr("Inherited"), "Inherited"),
            (self.tr("Inscriptional Pahlavi"), "Inscriptional_Pahlavi"),
            (self.tr("Inscriptional Parthian"), "Inscriptional_Parthian"),
            (self.tr("Javanese"), "Javanese"),
            (self.tr("Kaithi"), "Kaithi"),
            (self.tr("Kannada"), "Kannada"),
            (self.tr("Katakana"), "Katakana"),
            (self.tr("Kayah Li"), "Kayah_Li"),
            (self.tr("Kharoshthi"), "Kharoshthi"),
            (self.tr("Khmer"), "Khmer"),
            (self.tr("Lao"), "Lao"),
            (self.tr("Latin"), "Latin"),
            (self.tr("Lepcha"), "Lepcha"),
            (self.tr("Limbu"), "Limbu"),
            (self.tr("Linear B"), "Linear_B"),
            (self.tr("Lisu"), "Lisu"),
            (self.tr("Lycian"), "Lycian"),
            (self.tr("Lydian"), "Lydian"),
            (self.tr("Malayalam"), "Malayalam"),
            (self.tr("Mandaic"), "Mandaic"),
            (self.tr("Meetei Mayek"), "Meetei_Mayek"),
            (self.tr("Meroitic Cursive"), "Meroitic_Cursive"),
            (self.tr("Meroitic Hieroglyphs"), "Meroitic_Hieroglyphs"),
            (self.tr("Miao"), "Miao"),
            (self.tr("Mongolian"), "Mongolian"),
            (self.tr("Myanmar"), "Myanmar"),
            (self.tr("New Tai Lue"), "New_Tai_Lue"),
            (self.tr("N'Ko"), "Nko"),
            (self.tr("Ogham"), "Ogham"),
            (self.tr("Old Italic"), "Old_Italic"),
            (self.tr("Old Persian"), "Old_Persian"),
            (self.tr("Old South Arabian"), "Old_South_Arabian"),
            (self.tr("Old Turkic"), "Old_Turkic,"),
            (self.tr("Ol Chiki"), "Ol_Chiki"),
            (self.tr("Oriya"), "Oriya"),
            (self.tr("Osmanya"), "Osmanya"),
            (self.tr("Phags-pa"), "Phags_Pa"),
            (self.tr("Phoenician"), "Phoenician"),
            (self.tr("Rejang"), "Rejang"),
            (self.tr("Runic"), "Runic"),
            (self.tr("Samaritan"), "Samaritan"),
            (self.tr("Saurashtra"), "Saurashtra"),
            (self.tr("Sharada"), "Sharada"),
            (self.tr("Shavian"), "Shavian"),
            (self.tr("Sinhala"), "Sinhala"),
            (self.tr("Sora Sompeng"), "Sora_Sompeng"),
            (self.tr("Sundanese"), "Sundanese"),
            (self.tr("Syloti Nagri"), "Syloti_Nagri"),
            (self.tr("Syriac"), "Syriac"),
            (self.tr("Tagalog"), "Tagalog"),
            (self.tr("Tagbanwa"), "Tagbanwa"),
            (self.tr("Tai Le"), "Tai_Le"),
            (self.tr("Tai Tham"), "Tai_Tham"),
            (self.tr("Tai Viet"), "Tai_Viet"),
            (self.tr("Takri"), "Takri"),
            (self.tr("Tamil"), "Tamil"),
            (self.tr("Telugu"), "Telugu"),
            (self.tr("Thaana"), "Thaana"),
            (self.tr("Thai"), "Thai"),
            (self.tr("Tibetan"), "Tibetan"),
            (self.tr("Tifinagh"), "Tifinagh"),
            (self.tr("Ugaritic"), "Ugaritic"),
            (self.tr("Vai"), "Vai"),
            (self.tr("Yi"), "Yi"),
        )

        self.__posixNamedSets = (
            # display name                                  code
            (self.tr("Alphanumeric"), "alnum"),
            (self.tr("Alphabetic"), "alpha"),
            (self.tr("ASCII"), "ascii"),
            (self.tr("Word Letter"), "word"),
            (self.tr("Lower Case Letter"), "lower"),
            (self.tr("Upper Case Letter"), "upper"),
            (self.tr("Decimal Digit"), "digit"),
            (self.tr("Hexadecimal Digit"), "xdigit"),
            (self.tr("Space or Tab"), "blank"),
            (self.tr("White Space"), "space"),
            (self.tr("Printing (excl. space)"), "graph"),
            (self.tr("Printing (incl. space)"), "print"),
            (self.tr("Printing (excl. alphanumeric)"), "punct"),
            (self.tr("Control Character"), "cntrl"),
        )

    def __populateCharTypeCombo(self, combo, isSingle):
        """
        Private method to populate a given character type selection combo box.
        
        @param combo reference to the combo box to be populated (QComboBox)
        @param isSingle flag indicating a singles combo (boolean)
        """
        for txt, value in self.comboItems:
            combo.addItem(txt, value)
        if isSingle:
            for txt, value in self.singleComboItems:
                combo.addItem(txt, value)

    def __addSinglesLine(self):
        """
        Private slot to add a line of entry widgets for single characters.
        """
        hbox = QWidget(self.singlesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        self.__populateCharTypeCombo(cb1, True)
        hboxLayout.addWidget(cb1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        cb1a = QComboBox(hbox)
        cb1a.setEditable(False)
        cb1a.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        hboxLayout.addWidget(cb1a)
        cb1a.hide()
        cb2 = QComboBox(hbox)
        cb2.setEditable(False)
        self.__populateCharTypeCombo(cb2, True)
        hboxLayout.addWidget(cb2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        cb2a = QComboBox(hbox)
        cb2a.setEditable(False)
        cb2a.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        hboxLayout.addWidget(cb2a)
        cb2a.hide()
        self.singlesItemsBoxLayout.addWidget(hbox)

        cb1.activated[int].connect(self.__singlesCharTypeSelected)
        cb2.activated[int].connect(self.__singlesCharTypeSelected)
        hbox.show()

        self.singlesItemsBox.adjustSize()

        self.singlesEntries.append([cb1, le1, cb1a])
        self.singlesEntries.append([cb2, le2, cb2a])

    def __addRangesLine(self):
        """
        Private slot to add a line of entry widgets for character ranges.
        """
        hbox = QWidget(self.rangesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        self.__populateCharTypeCombo(cb1, False)
        hboxLayout.addWidget(cb1)
        l1 = QLabel(self.tr("Between:"), hbox)
        hboxLayout.addWidget(l1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        l2 = QLabel(self.tr("And:"), hbox)
        hboxLayout.addWidget(l2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        self.rangesItemsBoxLayout.addWidget(hbox)

        cb1.activated[int].connect(self.__rangesCharTypeSelected)
        hbox.show()

        self.rangesItemsBox.adjustSize()

        self.rangesEntries.append([cb1, le1, le2])

    def __populateCharacterCombo(self, combo, format):
        """
        Private method to populate a character selection combo.
        
        @param combo combo box to be populated (QComboBox)
        @param format format identifier (one of "-ccp", "-ccn",
            "-cbp", "-cbn", "-csp", "-csn", "-psp", "-psn")
        """
        combo.clear()

        if format in ["-ccp", "-ccn"]:
            items = self.__characterCategories
        elif format in ["-csp", "-csn"]:
            items = self.__specialCharacterCategories
        elif format in ["-cbp", "-cbn"]:
            items = self.__characterBlocks
        elif format in ["-psp", "-psn"]:
            items = self.__posixNamedSets

        comboLen = 0
        for txt, code in items:
            combo.addItem(txt, code)
            comboLen = max(comboLen, len(txt))
        combo.setMinimumContentsLength(comboLen)

    def __performSelectedAction(self, format, lineedit, combo):
        """
        Private method performing some actions depending on the input.
        
        @param format format of the selected entry (string)
        @param lineedit line edit widget to act on (QLineEdit)
        @param combo combo box widget to act on (QComboBox)
        """
        if format == "-i":
            return

        if format in ["-c", "-h", "-o"]:
            lineedit.show()
            lineedit.setEnabled(True)
            if combo is not None:
                combo.hide()
            if format == "-c":
                lineedit.setValidator(self.charValidator)
            elif format == "-h":
                lineedit.setValidator(self.hexValidator)
            elif format == "-o":
                lineedit.setValidator(self.octValidator)
        elif format in [
                "-ccp", "-ccn", "-cbp", "-cbn", "-csp", "-csn", "-psp", "-psn"
        ]:
            lineedit.setEnabled(False)
            lineedit.hide()
            if combo is not None:
                combo.show()
            self.__populateCharacterCombo(combo, format)
        else:
            lineedit.setEnabled(False)
            lineedit.hide()
            if combo is not None:
                combo.hide()
        lineedit.clear()

    def __singlesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the single chars
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.singlesEntries:
            if combo == entriesList[0]:
                format = combo.itemData(index)
                self.__performSelectedAction(format, entriesList[1],
                                             entriesList[2])
                break

    def __rangesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the char ranges
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.rangesEntries:
            if combo == entriesList[0]:
                format = combo.itemData(index)
                self.__performSelectedAction(format, entriesList[1], None)
                self.__performSelectedAction(format, entriesList[2], None)
                break

    def __formatCharacter(self, char, format):
        """
        Private method to format the characters entered into the dialog.
        
        @param char character string entered into the dialog (string)
        @param format string giving a special format (-c, -h, -i or -o) or
            the already formatted character (string)
        @return formatted character string (string)
        """
        if format == "-c":
            return char
        elif format == "-i":
            return ""

        if format == "-h":
            while len(char) < 2:
                char = "0" + char
            if len(char) > 2:
                return "\\x{{{0}}}".format(char.lower())
            else:
                return "\\x{0}".format(char.lower())
        elif format == "-o":
            while len(char) < 3:
                char = "0" + char
            if len(char) > 3:
                char = char[:3]
            return "\\{0}".format(char)
        elif format in ["-ccp", "-cbp", "-csp"]:
            return "\\p{{{0}}}".format(char)
        elif format in ["-ccn", "-cbn", "-csn"]:
            return "\\P{{{0}}}".format(char)
        elif format == "-psp":
            return "[:{0}:]".format(char)
        elif format == "-psn":
            return "[:^{0}:]".format(char)
        else:
            return format

    def getCharacters(self):
        """
        Public method to return the character string assembled via the dialog.
        
        @return formatted string for character classes (string)
        """
        regexp = ""

        # negative character range
        if self.negativeCheckBox.isChecked():
            regexp += "^"

        # predefined character ranges
        if self.wordCharCheckBox.isChecked():
            regexp += "\\w"
        if self.nonWordCharCheckBox.isChecked():
            regexp += "\\W"
        if self.digitsCheckBox.isChecked():
            regexp += "\\d"
        if self.nonDigitsCheckBox.isChecked():
            regexp += "\\D"
        if self.newlineCheckBox.isChecked():
            regexp += "\\R"
        if self.nonNewlineCheckBox.isChecked():
            regexp += "\\N"
        if self.whitespaceCheckBox.isChecked():
            regexp += "\\s"
        if self.nonWhitespaceCheckBox.isChecked():
            regexp += "\\S"
        if self.horizontalWhitespaceCheckBox.isChecked():
            regexp += "\\h"
        if self.nonHorizontalWhitespaceCheckBox.isChecked():
            regexp += "\\H"
        if self.verticalWhitespaceCheckBox.isChecked():
            regexp += "\\v"
        if self.nonVerticalWhitespaceCheckBox.isChecked():
            regexp += "\\V"

        # single characters
        for entrieslist in self.singlesEntries:
            format = entrieslist[0].itemData(entrieslist[0].currentIndex())
            if format in [
                    "-ccp", "-ccn", "-cbp", "-cbn", "-csp", "-csn", "-psp",
                    "-psn"
            ]:
                char = entrieslist[2].itemData(entrieslist[2].currentIndex())
            else:
                char = entrieslist[1].text()
            regexp += self.__formatCharacter(char, format)

        # character ranges
        for entrieslist in self.rangesEntries:
            if not entrieslist[1].text() or \
               not entrieslist[2].text():
                continue
            format = entrieslist[0].itemData(entrieslist[0].currentIndex())
            char1 = entrieslist[1].text()
            char2 = entrieslist[2].text()
            regexp += "{0}-{1}".format(self.__formatCharacter(char1, format),
                                       self.__formatCharacter(char2, format))

        if regexp:
            if (regexp.startswith("\\") and
                regexp.count("\\") == 1 and
                "-" not in regexp) or \
               len(regexp) == 1:
                return regexp
            else:
                return "[{0}]".format(regexp)
        else:
            return ""
    def init_ui(self):

        mainLayout = QVBoxLayout()
        self.setGeometry(600, 200, 1000, 800)
        self.flag = False

        self.done_red = 'font-size: 18px; color: rgb(200,50,50)'
        self.done_blue = 'font-size: 18px; color: rgb(50,50,200)'
        self.done_green = 'font-size: 20px; color: rgb(50,200,100)'

        #H box for vertical panes
        paneLayout = QHBoxLayout()
        paneWidget = QWidget()
        paneWidget.setLayout(paneLayout)

        doneLayout = QHBoxLayout()
        doneWidget = QWidget()
        doneWidget.setLayout(doneLayout)

        #First vertical pane: Input layout
        self.inputLayout = QVBoxLayout()
        self.inputLayout.setAlignment(Qt.AlignTop)
        inputWidget = QWidget()
        inputWidget.setFixedWidth(250)
        inputWidget.setLayout(self.inputLayout)

        #Drop down menu for phantom plans
        lbl = QLabel("Select Phantom Plan")
        lbl.setFixedHeight(20)
        dropdown = QComboBox(self)
        dropdown.setFixedHeight(20)
        self.phantom_path = './MGH_Phantoms/'
        phantoms = gen1.get_phantom_list(self.phantom_path)
        dropdown.addItem('Select Phantom')
        for name in phantoms:
            dropdown.addItem(name)

        dropdown.activated[str].connect(self.onActivated)
        self.inputLayout.addWidget(lbl)
        self.inputLayout.addWidget(dropdown)

        #Text box for patient name
        name_lbl1 = QLabel("Enter Patient First Name (required)")
        name_lbl2 = QLabel("Enter Patient Last Name (required)")
        name_lbl1.setFixedHeight(20)
        name_lbl2.setFixedHeight(20)
        self.patientfirstname = QLineEdit()
        self.patientlastname = QLineEdit()

        self.inputLayout.addWidget(name_lbl1)
        self.inputLayout.addWidget(self.patientfirstname)
        self.inputLayout.addWidget(name_lbl2)
        self.inputLayout.addWidget(self.patientlastname)

        #Current Isocenter values
        self.currentiso_lbl = QLabel()
        self.currentiso_lbl.setFixedHeight(30)

        #Hbox for isocenter
        isoLayout = QHBoxLayout()
        isoWidget = QWidget()
        isoWidget.setFixedWidth(250)
        isoWidget.setLayout(isoLayout)

        #Isocenter parameters
        lbl_iso = QLabel("Enter new isocenter values below")
        lbl_iso.setFixedHeight(20)
        lbl_x = QLabel("X (mm)")
        lbl_y = QLabel("Y (mm)")
        lbl_z = QLabel("Z (mm)")
        self.le_x = QLineEdit()
        self.le_y = QLineEdit()
        self.le_z = QLineEdit()

        self.inputLayout.addWidget(self.currentiso_lbl)
        self.inputLayout.addWidget(lbl_iso)

        isoLayout.addWidget(lbl_x)
        isoLayout.addWidget(self.le_x)
        isoLayout.addWidget(lbl_y)
        isoLayout.addWidget(self.le_y)
        isoLayout.addWidget(lbl_z)
        isoLayout.addWidget(self.le_z)
        self.inputLayout.addWidget(isoWidget)

        #Gantry Angle
        gantry_lbl = QLabel("Gantry Angle")
        gantry_lbl.setFixedHeight(20)
        self.gantry = QLineEdit()
        self.inputLayout.addWidget(gantry_lbl)
        self.inputLayout.addWidget(self.gantry)

        #Generate new set and upload to WB
        new_lbl = QLabel("Click below to generate new phantom set")
        new_lbl.setFixedHeight(30)
        new_btn = QPushButton("Generate")
        new_btn.setFixedHeight(30)
        new_btn.setStyleSheet('font-size: 18px')
        new_btn.clicked.connect(self.generate_dicom)
        self.upload_btn = QPushButton("Upload to WB")
        self.upload_btn.setFixedHeight(30)
        self.upload_btn.setStyleSheet(self.done_red)
        self.upload_btn.clicked.connect(self.upload_to_WB)

        self.inputLayout.addWidget(new_lbl)
        self.inputLayout.addWidget(new_btn)
        self.inputLayout.addWidget(self.upload_btn)

        #Second vertical pane
        self.rtipLayout = QVBoxLayout()
        self.rtipLayout.setAlignment(Qt.AlignTop)
        rtipWidget = QWidget()
        rtipWidget.adjustSize()
        rtipWidget.setLayout(self.rtipLayout)

        #Current spot map
        self.spot_lbl = QLabel("Spot map specs")
        self.spot_lbl.setStyleSheet("font-size : 12px")
        self.spot_lbl.setFixedHeight(20)
        self.spot_stats = QLabel()
        self.spot_stats.setWordWrap(True)
        self.spot_stats.adjustSize()

        # Button to load new spot map
        spot_lbl2 = QLabel("Click below to browse for new spot map")
        spot_lbl2.setStyleSheet("font-size : 12px")
        spot_lbl2.setFixedHeight(30)
        dataLoadBtn = QPushButton("Browse")
        dataLoadBtn.setFixedHeight(30)
        dataLoadBtn.clicked.connect(self.load_spot_map)
        self.chkbox = QCheckBox("Check box to use loaded csv file")
        self.chkbox2 = QCheckBox(
            "Check box if the first beam is the setup beam")

        self.rtipLayout.addWidget(self.spot_lbl)
        self.rtipLayout.addWidget(self.spot_stats)
        self.rtipLayout.addWidget(spot_lbl2)
        self.rtipLayout.addWidget(dataLoadBtn)
        self.rtipLayout.addWidget(self.chkbox)
        self.rtipLayout.addWidget(self.chkbox2)

        # Add space for spot map statistics
        self.loadstatus = QLabel()
        self.loadstatus.setFixedHeight(40)

        self.csv_stats = QLabel()
        self.csv_stats.setAlignment(Qt.AlignTop)
        self.csv_stats.setWordWrap(True)

        self.rtipLayout.addWidget(self.loadstatus)
        self.rtipLayout.addWidget(self.csv_stats)

        #Third pane
        plotWidget = QWidget()
        plotLayout = QVBoxLayout()

        #Make figures and navi toolbar
        self.fig = Figure()
        self.canvas = FigureCanvas(self.fig)
        self.axes11 = self.fig.add_subplot(2, 1, 1)
        self.axes12 = self.fig.add_subplot(2, 1, 2)
        self.fig.tight_layout()

        navi_toolbar = NavigationToolbar(self.canvas, plotWidget)
        plotLayout.addWidget(navi_toolbar)
        plotLayout.addWidget(self.canvas, Qt.AlignHCenter)

        #Done status
        self.done_lbl = QLabel()
        self.done_lbl.setStyleSheet(self.done_green)
        self.done_lbl.setAlignment(Qt.AlignHCenter)
        doneLayout.addWidget(self.done_lbl)

        #Add widgets to main window
        paneLayout.addWidget(inputWidget)
        paneLayout.addWidget(rtipWidget)
        paneLayout.addLayout(plotLayout)

        mainLayout.addWidget(paneWidget)
        mainLayout.addWidget(doneWidget)
        self.setLayout(mainLayout)

        self.show()
class QRegExpWizardCharactersDialog(QDialog, Ui_QRegExpWizardCharactersDialog):
    """
    Class implementing a dialog for entering character classes.
    """
    RegExpMode = 0
    WildcardMode = 1
    W3CMode = 2
    
    def __init__(self, mode=RegExpMode, parent=None):
        """
        Constructor
        
        @param mode mode of the dialog (one of RegExpMode, WildcardMode,
            W3CMode)
        @param parent parent widget (QWidget)
        """
        super(QRegExpWizardCharactersDialog, self).__init__(parent)
        self.setupUi(self)
        
        self.__mode = mode
        
        if mode == QRegExpWizardCharactersDialog.WildcardMode:
            self.predefinedBox.setEnabled(False)
            self.predefinedBox.hide()
        elif mode == QRegExpWizardCharactersDialog.RegExpMode:
            self.w3cInitialIdentifierCheckBox.hide()
            self.w3cNonInitialIdentifierCheckBox.hide()
            self.w3cNmtokenCheckBox.hide()
            self.w3cNonNmtokenCheckBox.hide()
        elif mode == QRegExpWizardCharactersDialog.W3CMode:
            self.__initCharacterSelectors()
        
        self.comboItems = []
        self.singleComboItems = []      # these are in addition to the above
        self.comboItems.append((self.tr("Normal character"), "-c"))
        if mode == QRegExpWizardCharactersDialog.RegExpMode:
            self.comboItems.append((self.tr(
                "Unicode character in hexadecimal notation"), "-h"))
            self.comboItems.append((self.tr(
                "ASCII/Latin1 character in octal notation"), "-o"))
            self.singleComboItems.append(("---", "-i"))
            self.singleComboItems.append(
                (self.tr("Bell character (\\a)"), "\\a"))
            self.singleComboItems.append(
                (self.tr("Page break (\\f)"), "\\f"))
            self.singleComboItems.append(
                (self.tr("Line feed (\\n)"), "\\n"))
            self.singleComboItems.append(
                (self.tr("Carriage return (\\r)"), "\\r"))
            self.singleComboItems.append(
                (self.tr("Horizontal tabulator (\\t)"), "\\t"))
            self.singleComboItems.append(
                (self.tr("Vertical tabulator (\\v)"), "\\v"))
        elif mode == QRegExpWizardCharactersDialog.W3CMode:
            self.comboItems.append((self.tr(
                "Unicode character in hexadecimal notation"), "-h"))
            self.comboItems.append((self.tr(
                "ASCII/Latin1 character in octal notation"), "-o"))
            self.singleComboItems.append(("---", "-i"))
            self.singleComboItems.append(
                (self.tr("Line feed (\\n)"), "\\n"))
            self.singleComboItems.append(
                (self.tr("Carriage return (\\r)"), "\\r"))
            self.singleComboItems.append(
                (self.tr("Horizontal tabulator (\\t)"), "\\t"))
            self.singleComboItems.append(("---", "-i"))
            self.singleComboItems.append(
                (self.tr("Character Category"), "-ccp"))
            self.singleComboItems.append(
                (self.tr("Character Block"), "-cbp"))
            self.singleComboItems.append(
                (self.tr("Not Character Category"), "-ccn"))
            self.singleComboItems.append(
                (self.tr("Not Character Block"), "-cbn"))
        
        self.charValidator = QRegExpValidator(QRegExp(".{0,1}"), self)
        self.hexValidator = QRegExpValidator(QRegExp("[0-9a-fA-F]{0,4}"), self)
        self.octValidator = QRegExpValidator(QRegExp("[0-3]?[0-7]{0,2}"), self)
        
        # generate dialog part for single characters
        self.singlesBoxLayout = QVBoxLayout(self.singlesBox)
        self.singlesBoxLayout.setObjectName("singlesBoxLayout")
        self.singlesBoxLayout.setSpacing(6)
        self.singlesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesBox.setLayout(self.singlesBoxLayout)
        self.singlesView = QScrollArea(self.singlesBox)
        self.singlesView.setObjectName("singlesView")
        self.singlesBoxLayout.addWidget(self.singlesView)
        
        self.singlesItemsBox = QWidget(self)
        self.singlesView.setWidget(self.singlesItemsBox)
        self.singlesItemsBox.setObjectName("singlesItemsBox")
        self.singlesItemsBox.setMinimumWidth(1000)
        self.singlesItemsBoxLayout = QVBoxLayout(self.singlesItemsBox)
        self.singlesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.singlesItemsBoxLayout.setSpacing(6)
        self.singlesItemsBox.setLayout(self.singlesItemsBoxLayout)
        self.singlesEntries = []
        self.__addSinglesLine()
        
        hlayout0 = QHBoxLayout()
        hlayout0.setContentsMargins(0, 0, 0, 0)
        hlayout0.setSpacing(6)
        hlayout0.setObjectName("hlayout0")
        self.moreSinglesButton = QPushButton(
            self.tr("Additional Entries"), self.singlesBox)
        self.moreSinglesButton.setObjectName("moreSinglesButton")
        hlayout0.addWidget(self.moreSinglesButton)
        hspacer0 = QSpacerItem(
            30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        hlayout0.addItem(hspacer0)
        self.singlesBoxLayout.addLayout(hlayout0)
        self.moreSinglesButton.clicked.connect(self.__addSinglesLine)
        
        # generate dialog part for character ranges
        self.rangesBoxLayout = QVBoxLayout(self.rangesBox)
        self.rangesBoxLayout.setObjectName("rangesBoxLayout")
        self.rangesBoxLayout.setSpacing(6)
        self.rangesBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesBox.setLayout(self.rangesBoxLayout)
        self.rangesView = QScrollArea(self.rangesBox)
        self.rangesView.setObjectName("rangesView")
        self.rangesBoxLayout.addWidget(self.rangesView)
        
        self.rangesItemsBox = QWidget(self)
        self.rangesView.setWidget(self.rangesItemsBox)
        self.rangesItemsBox.setObjectName("rangesItemsBox")
        self.rangesItemsBox.setMinimumWidth(1000)
        self.rangesItemsBoxLayout = QVBoxLayout(self.rangesItemsBox)
        self.rangesItemsBoxLayout.setContentsMargins(6, 6, 6, 6)
        self.rangesItemsBoxLayout.setSpacing(6)
        self.rangesItemsBox.setLayout(self.rangesItemsBoxLayout)
        self.rangesEntries = []
        self.__addRangesLine()
        
        hlayout1 = QHBoxLayout()
        hlayout1.setContentsMargins(0, 0, 0, 0)
        hlayout1.setSpacing(6)
        hlayout1.setObjectName("hlayout1")
        self.moreRangesButton = QPushButton(
            self.tr("Additional Entries"), self.rangesBox)
        self.moreSinglesButton.setObjectName("moreRangesButton")
        hlayout1.addWidget(self.moreRangesButton)
        hspacer1 = QSpacerItem(
            30, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
        hlayout1.addItem(hspacer1)
        self.rangesBoxLayout.addLayout(hlayout1)
        self.moreRangesButton.clicked.connect(self.__addRangesLine)
        
    def __initCharacterSelectors(self):
        """
        Private method to initialize the W3C character selector entries.
        """
        self.__characterCategories = (
            # display name                              code
            (self.tr("Letter, Any"), "L"),
            (self.tr("Letter, Uppercase"), "Lu"),
            (self.tr("Letter, Lowercase"), "Ll"),
            (self.tr("Letter, Titlecase"), "Lt"),
            (self.tr("Letter, Modifier"), "Lm"),
            (self.tr("Letter, Other"), "Lo"),
            (self.tr("Mark, Any"), "M"),
            (self.tr("Mark, Nonspacing"), "Mn"),
            (self.tr("Mark, Spacing Combining"), "Mc"),
            (self.tr("Mark, Enclosing"), "Me"),
            (self.tr("Number, Any"), "N"),
            (self.tr("Number, Decimal Digit"), "Nd"),
            (self.tr("Number, Letter"), "Nl"),
            (self.tr("Number, Other"), "No"),
            (self.tr("Punctuation, Any"), "P"),
            (self.tr("Punctuation, Connector"), "Pc"),
            (self.tr("Punctuation, Dash"), "Pd"),
            (self.tr("Punctuation, Open"), "Ps"),
            (self.tr("Punctuation, Close"), "Pe"),
            (self.tr("Punctuation, Initial Quote"), "Pi"),
            (self.tr("Punctuation, Final Quote"), "Pf"),
            (self.tr("Punctuation, Other"), "Po"),
            (self.tr("Symbol, Any"), "S"),
            (self.tr("Symbol, Math"), "Sm"),
            (self.tr("Symbol, Currency"), "Sc"),
            (self.tr("Symbol, Modifier"), "Sk"),
            (self.tr("Symbol, Other"), "So"),
            (self.tr("Separator, Any"), "Z"),
            (self.tr("Separator, Space"), "Zs"),
            (self.tr("Separator, Line"), "Zl"),
            (self.tr("Separator, Paragraph"), "Zp"),
            (self.tr("Other, Any"), "C"),
            (self.tr("Other, Control"), "Cc"),
            (self.tr("Other, Format"), "Cf"),
            (self.tr("Other, Private Use"), "Co"),
            (self.tr("Other, Not Assigned"), "Cn"),
        )
        
        self.__characterBlocks = (
            (self.tr("Basic Latin"),
             "IsBasicLatin"),
            (self.tr("Latin-1 Supplement"),
             "IsLatin-1Supplement"),
            (self.tr("Latin Extended-A"),
             "IsLatinExtended-A"),
            (self.tr("Latin Extended-B"),
             "IsLatinExtended-B"),
            (self.tr("IPA Extensions"),
             "IsIPAExtensions"),
            (self.tr("Spacing Modifier Letters"),
             "IsSpacingModifierLetters"),
            (self.tr("Combining Diacritical Marks"),
             "IsCombiningDiacriticalMarks"),
            (self.tr("Greek"),
             "IsGreek"),
            (self.tr("Cyrillic"),
             "IsCyrillic"),
            (self.tr("Armenian"),
             "IsArmenian"),
            (self.tr("Hebrew"),
             "IsHebrew"),
            (self.tr("Arabic"),
             "IsArabic"),
            (self.tr("Syriac"),
             "IsSyriac"),
            (self.tr("Thaana"),
             "IsThaana"),
            (self.tr("Devanagari"),
             "IsDevanagari"),
            (self.tr("Bengali"),
             "IsBengali"),
            (self.tr("Gurmukhi"),
             "IsBengali"),
            (self.tr("Gujarati"),
             "IsGujarati"),
            (self.tr("Oriya"),
             "IsOriya"),
            (self.tr("Tamil"),
             "IsTamil"),
            (self.tr("Telugu"),
             "IsTelugu"),
            (self.tr("Kannada"),
             "IsKannada"),
            (self.tr("Malayalam"),
             "IsMalayalam"),
            (self.tr("Sinhala"),
             "IsSinhala"),
            (self.tr("Thai"),
             "IsThai"),
            (self.tr("Lao"),
             "IsLao"),
            (self.tr("Tibetan"),
             "IsTibetan"),
            (self.tr("Myanmar"),
             "IsMyanmar"),
            (self.tr("Georgian"),
             "IsGeorgian"),
            (self.tr("Hangul Jamo"),
             "IsHangulJamo"),
            (self.tr("Ethiopic"),
             "IsEthiopic"),
            (self.tr("Cherokee"),
             "IsCherokee"),
            (self.tr("Unified Canadian Aboriginal Syllabics"),
             "IsUnifiedCanadianAboriginalSyllabics"),
            (self.tr("Ogham"),
             "IsOgham"),
            (self.tr("Runic"),
             "IsRunic"),
            (self.tr("Khmer"),
             "IsKhmer"),
            (self.tr("Mongolian"),
             "IsMongolian"),
            (self.tr("Latin Extended Additional"),
             "IsLatinExtendedAdditional"),
            (self.tr("Greek Extended"),
             "IsGreekExtended"),
            (self.tr("General Punctuation"),
             "IsGeneralPunctuation"),
            (self.tr("Superscripts and Subscripts"),
             "IsSuperscriptsandSubscripts"),
            (self.tr("Currency Symbols"),
             "IsCurrencySymbols"),
            (self.tr("Combining Marks for Symbols"),
             "IsCombiningMarksforSymbols"),
            (self.tr("Letterlike Symbols"),
             "IsLetterlikeSymbols"),
            (self.tr("Number Forms"),
             "IsNumberForms"),
            (self.tr("Arrows"),
             "IsArrows"),
            (self.tr("Mathematical Operators"),
             "IsMathematicalOperators"),
            (self.tr("Miscellaneous Technical"),
             "IsMiscellaneousTechnical"),
            (self.tr("Control Pictures"),
             "IsControlPictures"),
            (self.tr("Optical Character Recognition"),
             "IsOpticalCharacterRecognition"),
            (self.tr("Enclosed Alphanumerics"),
             "IsEnclosedAlphanumerics"),
            (self.tr("Box Drawing"),
             "IsBoxDrawing"),
            (self.tr("Block Elements"),
             "IsBlockElements"),
            (self.tr("Geometric Shapes"),
             "IsGeometricShapes"),
            (self.tr("Miscellaneous Symbols"),
             "IsMiscellaneousSymbols"),
            (self.tr("Dingbats"),
             "IsDingbats"),
            (self.tr("Braille Patterns"),
             "IsBraillePatterns"),
            (self.tr("CJK Radicals Supplement"),
             "IsCJKRadicalsSupplement"),
            (self.tr("KangXi Radicals"),
             "IsKangXiRadicals"),
            (self.tr("Ideographic Description Chars"),
             "IsIdeographicDescriptionChars"),
            (self.tr("CJK Symbols and Punctuation"),
             "IsCJKSymbolsandPunctuation"),
            (self.tr("Hiragana"),
             "IsHiragana"),
            (self.tr("Katakana"),
             "IsKatakana"),
            (self.tr("Bopomofo"),
             "IsBopomofo"),
            (self.tr("Hangul Compatibility Jamo"),
             "IsHangulCompatibilityJamo"),
            (self.tr("Kanbun"),
             "IsKanbun"),
            (self.tr("Bopomofo Extended"),
             "IsBopomofoExtended"),
            (self.tr("Enclosed CJK Letters and Months"),
             "IsEnclosedCJKLettersandMonths"),
            (self.tr("CJK Compatibility"),
             "IsCJKCompatibility"),
            (self.tr("CJK Unified Ideographs Extension A"),
             "IsCJKUnifiedIdeographsExtensionA"),
            (self.tr("CJK Unified Ideographs"),
             "IsCJKUnifiedIdeographs"),
            (self.tr("Yi Syllables"),
             "IsYiSyllables"),
            (self.tr("Yi Radicals"),
             "IsYiRadicals"),
            (self.tr("Hangul Syllables"),
             "IsHangulSyllables"),
            (self.tr("Private Use"),
             "IsPrivateUse"),
            (self.tr("CJK Compatibility Ideographs"),
             "IsCJKCompatibilityIdeographs"),
            (self.tr("Alphabetic Presentation Forms"),
             "IsAlphabeticPresentationForms"),
            (self.tr("Arabic Presentation Forms-A"),
             "IsArabicPresentationForms-A"),
            (self.tr("Combining Half Marks"),
             "IsCombiningHalfMarks"),
            (self.tr("CJK Compatibility Forms"),
             "IsCJKCompatibilityForms"),
            (self.tr("Small Form Variants"),
             "IsSmallFormVariants"),
            (self.tr("Arabic Presentation Forms-B"),
             "IsArabicPresentationForms-B"),
            (self.tr("Halfwidth and Fullwidth Forms"),
             "IsHalfwidthandFullwidthForms"),
            (self.tr("Specials"),
             "IsSpecials"),
            (self.tr("Old Italic"),
             "IsOldItalic"),
            (self.tr("Gothic"),
             "IsGothic"),
            (self.tr("Deseret"),
             "IsDeseret"),
            (self.tr("Byzantine Musical Symbols"),
             "IsByzantineMusicalSymbols"),
            (self.tr("Musical Symbols"),
             "IsMusicalSymbols"),
            (self.tr("Mathematical Alphanumeric Symbols"),
             "IsMathematicalAlphanumericSymbols"),
            (self.tr("CJK Unified Ideographic Extension B"),
             "IsCJKUnifiedIdeographicExtensionB"),
            (self.tr("CJK Compatapility Ideographic Supplement"),
             "IsCJKCompatapilityIdeographicSupplement"),
            (self.tr("Tags"),
             "IsTags"),
        )
        
    def __populateCharTypeCombo(self, combo, isSingle):
        """
        Private method to populate a given character type selection combo box.
        
        @param combo reference to the combo box to be populated (QComboBox)
        @param isSingle flag indicating a singles combo (boolean)
        """
        for txt, value in self.comboItems:
            combo.addItem(txt, value)
        if isSingle:
            for txt, value in self.singleComboItems:
                combo.addItem(txt, value)
        
    def __addSinglesLine(self):
        """
        Private slot to add a line of entry widgets for single characters.
        """
        hbox = QWidget(self.singlesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        self.__populateCharTypeCombo(cb1, True)
        hboxLayout.addWidget(cb1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        cb1a = QComboBox(hbox)
        cb1a.setEditable(False)
        cb1a.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        hboxLayout.addWidget(cb1a)
        cb1a.hide()
        cb2 = QComboBox(hbox)
        cb2.setEditable(False)
        self.__populateCharTypeCombo(cb2, True)
        hboxLayout.addWidget(cb2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        cb2a = QComboBox(hbox)
        cb2a.setEditable(False)
        cb2a.setSizeAdjustPolicy(QComboBox.AdjustToContents)
        hboxLayout.addWidget(cb2a)
        cb2a.hide()
        self.singlesItemsBoxLayout.addWidget(hbox)
        
        cb1.activated[int].connect(self.__singlesCharTypeSelected)
        cb2.activated[int].connect(self.__singlesCharTypeSelected)
        hbox.show()
        
        self.singlesItemsBox.adjustSize()
        
        self.singlesEntries.append([cb1, le1, cb1a])
        self.singlesEntries.append([cb2, le2, cb2a])
        
    def __addRangesLine(self):
        """
        Private slot to add a line of entry widgets for character ranges.
        """
        hbox = QWidget(self.rangesItemsBox)
        hboxLayout = QHBoxLayout(hbox)
        hboxLayout.setContentsMargins(0, 0, 0, 0)
        hboxLayout.setSpacing(6)
        hbox.setLayout(hboxLayout)
        cb1 = QComboBox(hbox)
        cb1.setEditable(False)
        self.__populateCharTypeCombo(cb1, False)
        hboxLayout.addWidget(cb1)
        l1 = QLabel(self.tr("Between:"), hbox)
        hboxLayout.addWidget(l1)
        le1 = QLineEdit(hbox)
        le1.setValidator(self.charValidator)
        hboxLayout.addWidget(le1)
        l2 = QLabel(self.tr("And:"), hbox)
        hboxLayout.addWidget(l2)
        le2 = QLineEdit(hbox)
        le2.setValidator(self.charValidator)
        hboxLayout.addWidget(le2)
        self.rangesItemsBoxLayout.addWidget(hbox)
        
        cb1.activated[int].connect(self.__rangesCharTypeSelected)
        hbox.show()
        
        self.rangesItemsBox.adjustSize()
        
        self.rangesEntries.append([cb1, le1, le2])
        
    def __populateW3cCharacterCombo(self, combo, format):
        """
        Private method to populate a W3C character selection combo.
        
        @param combo combo box to be populated (QComboBox)
        @param format format identifier (one of "-ccp", "-ccn", "-cbp", "-cbn")
        """
        combo.clear()
        
        if format in ["-ccp", "-ccn"]:
            comboLen = 0
            for txt, code in self.__characterCategories:
                combo.addItem(txt, code)
                comboLen = max(comboLen, len(txt))
            combo.setMinimumContentsLength(comboLen)
        elif format in ["-cbp", "-cbn"]:
            comboLen = 0
            for txt, code in self.__characterBlocks:
                combo.addItem(txt, code)
                comboLen = max(comboLen, len(txt))
            combo.setMinimumContentsLength(comboLen)
        
    def __performSelectedAction(self, format, lineedit, combo):
        """
        Private method performing some actions depending on the input.
        
        @param format format of the selected entry (string)
        @param lineedit line edit widget to act on (QLineEdit)
        @param combo combo box widget to act on (QComboBox)
        """
        if format == "-i":
            return
        
        if format in ["-c", "-h", "-o"]:
            lineedit.show()
            lineedit.setEnabled(True)
            if combo is not None:
                combo.hide()
            if format == "-c":
                lineedit.setValidator(self.charValidator)
            elif format == "-h":
                lineedit.setValidator(self.hexValidator)
            elif format == "-o":
                lineedit.setValidator(self.octValidator)
        elif format in ["-ccp", "-ccn", "-cbp", "-cbn"]:
            lineedit.setEnabled(False)
            lineedit.hide()
            if combo is not None:
                combo.show()
            self.__populateW3cCharacterCombo(combo, format)
        else:
            lineedit.setEnabled(False)
            lineedit.hide()
            if combo is not None:
                combo.hide()
        lineedit.clear()
        
    def __singlesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the single chars
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.singlesEntries:
            if combo == entriesList[0]:
                format = combo.itemData(index)
                self.__performSelectedAction(
                    format, entriesList[1], entriesList[2])
                break
        
    def __rangesCharTypeSelected(self, index):
        """
        Private slot to handle the activated(int) signal of the char ranges
        combo boxes.
        
        @param index selected list index (integer)
        """
        combo = self.sender()
        for entriesList in self.rangesEntries:
            if combo == entriesList[0]:
                format = combo.itemData(index)
                self.__performSelectedAction(format, entriesList[1], None)
                self.__performSelectedAction(format, entriesList[2], None)
                break
        
    def __formatCharacter(self, char, format):
        """
        Private method to format the characters entered into the dialog.
        
        @param char character string entered into the dialog (string)
        @param format string giving a special format (-c, -h, -i or -o) or
            the already formatted character (string)
        @return formatted character string (string)
        """
        if format == "-c":
            return char
        elif format == "-i":
            return ""
        
        if self.__mode in [QRegExpWizardCharactersDialog.RegExpMode,
                           QRegExpWizardCharactersDialog.W3CMode]:
            if format == "-h":
                return "\\x{0}".format(char.lower())
            elif format == "-o":
                return "\\0{0}".format(char)
            elif format in ["-ccp", "-cbp"]:
                return "\\p{{{0}}}".format(char)
            elif format in ["-ccn", "-cbn"]:
                return "\\P{{{0}}}".format(char)
            else:
                return format
        
    def getCharacters(self):
        """
        Public method to return the character string assembled via the dialog.
        
        @return formatted string for character classes (string)
        """
        regexp = ""
        
        # negative character range
        if self.negativeCheckBox.isChecked():
            regexp += "^"
            
        # predefined character ranges
        if self.wordCharCheckBox.isChecked():
            regexp += "\\w"
        if self.nonWordCharCheckBox.isChecked():
            regexp += "\\W"
        if self.digitsCheckBox.isChecked():
            regexp += "\\d"
        if self.nonDigitsCheckBox.isChecked():
            regexp += "\\D"
        if self.whitespaceCheckBox.isChecked():
            regexp += "\\s"
        if self.nonWhitespaceCheckBox.isChecked():
            regexp += "\\S"
        if self.w3cInitialIdentifierCheckBox.isChecked():
            regexp += "\\i"
        if self.w3cNonInitialIdentifierCheckBox.isChecked():
            regexp += "\\I"
        if self.w3cNmtokenCheckBox.isChecked():
            regexp += "\\c"
        if self.w3cNonNmtokenCheckBox.isChecked():
            regexp += "\\C"
            
        # single characters
        for entrieslist in self.singlesEntries:
            format = entrieslist[0].itemData(entrieslist[0].currentIndex())
            if format in ["-ccp", "-ccn", "-cbp", "-cbn"]:
                char = entrieslist[2].itemData(entrieslist[2].currentIndex())
            else:
                char = entrieslist[1].text()
            regexp += self.__formatCharacter(char, format)
        
        # character ranges
        for entrieslist in self.rangesEntries:
            if not entrieslist[1].text() or \
               not entrieslist[2].text():
                continue
            format = entrieslist[0].itemData(entrieslist[0].currentIndex())
            char1 = entrieslist[1].text()
            char2 = entrieslist[2].text()
            regexp += "{0}-{1}".format(
                self.__formatCharacter(char1, format),
                self.__formatCharacter(char2, format))
        
        if regexp:
            if (regexp.startswith("\\") and
                regexp.count("\\") == 1 and
                "-" not in regexp) or \
               len(regexp) == 1:
                return regexp
            else:
                return "[{0}]".format(regexp)
        else:
            return ""