コード例 #1
0
 def __init__(self, navbar, label, controls, parent=None):
     super().__init__(parent)
     vbox = QVBoxLayout()
     vbox.insertLayout(-1, navbar, stretch=2)
     vbox.addWidget(StateLabel(label), stretch=1)
     vbox.insertLayout(-1, controls, stretch=9)
     self.setLayout(vbox)
コード例 #2
0
ファイル: fighterView.py プロジェクト: Me0w1ng/bot2pix
class FighterView(QWidget):

    def __init__(self, parent):
        super(FighterView, self).__init__(parent)
        self.initButton()
        self.initLayout()
        self.mainWindow = parent

    def initButton(self):
        # next map button
        self.highlight_grid_button = QPushButton("highlight grid")
        self.highlight_grid_button.clicked.connect(self.highlightGrid)

    def initLayout(self):
        self.layout = QVBoxLayout()
        self.setLayout(self.layout)

        self.button_combat_box = QGroupBox()
        self.button_combat_layout = QHBoxLayout()
        self.button_combat_box.setLayout(self.button_combat_layout)

        self.button_combat_layout.addWidget(self.highlight_grid_button)

        self.layout.addWidget(self.button_combat_box)
        self.layout.insertLayout(0, self.button_combat_layout)

    def highlightGrid(self, event):
        self.mainWindow.hide()
        combat_grid = Grid(env.COMBAT_R, env.VCELLS, env.HCELLS)
        combat_grid.parse()
        self.overlay = GridOverlay(combat_grid)
        self.overlay.highlightEnded.connect(self.mainWindow.show)
        self.overlay.highlight(2)
コード例 #3
0
class TwinContainer(QWidget):
    def __init__(self, dock_widget, *args, parent=None, **kwargs):
        super(TwinContainer, self).__init__(parent)
        self.parent = parent
        self.layout = QVBoxLayout(self)
        self.layouts = {}
        self.dock_widget = dock_widget

    def add_to_layout(self, name, widget):
        if name not in self.layouts:
            keys = sorted(list(self.layouts) + [name])
            idx = keys.index(name)
            self.layouts[name] = QHBoxLayout()
            self.layout.insertLayout(idx, self.layouts[name])
        self.layouts[name].addWidget(widget)
        widget.mpl_canvas.sig_twin.connect(self.mouse_twin_event)

    @pyqtSlot(object)
    def mouse_twin_event(self, event):
        if event.button == 1:
            self.parent.select_tab(self.sender())
        elif event.button == 3:
            plot_widget = self.sender().my_parent
            plot_widget.trim_widget.sig_set_state.emit(True)

    def handle_show(self, name, widget, state):
        widget.setVisible(state)
        if state:
            self.layouts[name].addWidget(widget)
        else:
            self.layouts[name].removeWidget(widget)
コード例 #4
0
    def __init__(self, *args):
        QWidget.__init__(self, *args)
        vLayout = QVBoxLayout(self)
        self.setLayout(vLayout)

        hLayout = QHBoxLayout()
        vLayout.insertLayout(0, hLayout)

        tableModel = Model(self)

        self.ViewA = QTableView(self)
        self.ViewA.setModel(tableModel)
        self.ViewA.clicked.connect(self.viewClicked)
        self.ViewA.setSelectionBehavior(QTableView.SelectRows)
        self.ViewA.setSelectionMode(QTableWidget.SingleSelection)

        hLayout.addWidget(self.ViewA)

        insertButton = QPushButton('Insert Row Above Selection')
        insertButton.setObjectName('insertButton')
        insertButton.clicked.connect(self.buttonClicked)
        removeButton = QPushButton('Remove Selected Item')
        removeButton.setObjectName('removeButton')
        removeButton.clicked.connect(self.buttonClicked)

        vLayout.addWidget(insertButton)
        vLayout.addWidget(removeButton)
コード例 #5
0
class MyApp(object):    
    def __init__(self):
        super(MyApp, self).__init__()                
        self.mainWidget = QWidget()
        self.mainLayout = QVBoxLayout()
        self.mainWidget.setLayout(self.mainLayout)

        self.hLayout = QHBoxLayout()
        self.mainLayout.insertLayout(0, self.hLayout)


        self.listA = QTreeWidget()
        self.listA.setColumnCount(3)
        self.listA.setHeaderLabels(['Checkbox','Name','Data'])

        for i in range(3):
            item = QTreeWidgetItem()
            item.setCheckState(0,QtCore.Qt.Checked)
            item.setText(1, 'Item '+str(i))
            item.setData(2, QtCore.Qt.UserRole, id(item) )
            item.setText(2, str(id(item) ) )
            self.listA.addTopLevelItem(item)

        self.hLayout.addWidget(self.listA)

        self.buttonGroupbox = QGroupBox()
        self.buttonlayout = QVBoxLayout()
        self.buttonGroupbox.setLayout(self.buttonlayout)

        okButton = QPushButton('Remove Selected')
        okButton.clicked.connect(self.removeSel)
        self.buttonlayout.addWidget(okButton)

        getDataButton = QPushButton('Get Items Data')
        getDataButton.clicked.connect(self.getItemsData)
        self.buttonlayout.addWidget(getDataButton)

        self.mainLayout.addWidget(self.buttonGroupbox)
        self.mainWidget.show()
        sys.exit(app.exec_())

    def removeSel(self):
        listItems=self.listA.selectedItems()
        if not listItems: return   
        for item in listItems:
            itemIndex=self.listA.indexOfTopLevelItem(item)
            self.listA.takeTopLevelItem(itemIndex)
        print('\n\t Number of items remaining', self.listA.topLevelItemCount())

    def getItemsData(self):
        for i in range(self.listA.topLevelItemCount()):
            item=self.listA.topLevelItem(i)
            itmData=item.data(2, QtCore.Qt.UserRole)
            itemId=itmData.toPyObject()
            print('\n\t Item Id Stored as Item Data:', itemId, 'Item Checkbox State:', item.checkState(0))
コード例 #6
0
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        def inttocheck(value):
            if value:
                return Qt.Checked
            return Qt.Unchecked

        cparser = PuddleConfig()

        self.extpattern = QLineEdit()
        self.extpattern.setText(
            cparser.load('playlist', 'extpattern', '%artist% - %title%'))

        self.extinfo = QCheckBox(
            translate("Playlist Settings", '&Write extended info'), self)
        self.extinfo.stateChanged.connect(self.extpattern.setEnabled)
        self.extinfo.setCheckState(
            inttocheck(cparser.load('playlist', 'extinfo', 1, True)))
        self.extpattern.setEnabled(self.extinfo.checkState())

        self.reldir = QCheckBox(
            translate("Playlist Settings",
                      'Entries &relative to working directory'))
        self.reldir.setCheckState(
            inttocheck(cparser.load('playlist', 'reldir', 0, True)))

        self.windows_separator = QCheckBox(
            translate("Playlist Settings", 'Use windows path separator (\\)'))
        self.windows_separator.setCheckState(
            inttocheck(cparser.load('playlist', 'windows_separator', 0, True)))

        self.filename = QLineEdit()
        self.filename.setText(
            cparser.load('playlist', 'filepattern', 'puddletag.m3u'))
        label = QLabel(translate("Playlist Settings", '&Filename pattern.'))
        label.setBuddy(self.filename)

        hbox = QHBoxLayout()
        hbox.addSpacing(10)
        hbox.addWidget(self.extpattern)

        vbox = QVBoxLayout()
        [
            vbox.addWidget(z)
            for z in (self.extinfo, self.reldir, self.windows_separator, label,
                      self.filename)
        ]
        vbox.insertLayout(1, hbox)
        vbox.addStretch()
        vbox.insertSpacing(3, 5)
        vbox.insertSpacing(5, 5)
        self.setLayout(vbox)
コード例 #7
0
class HtmlDialog(QDialog):
    """Generate a more complex HTML Viewer dialog window, with Prin/Close Buttons"""
    def __init__(self, parent=None):
        """
        Constructor of HtmlDialog

        :param parent: dialog parent
        :return:
        """
        super().__init__(
            parent,
            QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowMinMaxButtonsHint
            | QtCore.Qt.WindowCloseButtonHint)

        self.horzLayout = QHBoxLayout()
        self.vertLayout = QVBoxLayout()
        self.spacer = QSpacerItem(1, 1, QSizePolicy.Expanding,
                                  QSizePolicy.Fixed)

        # print button
        self.btnPrint = QPushButton(self)
        self.btnPrint.setText(translate("ReportDialog", "Print"))
        self.btnPrint.setMaximumWidth(100)
        self.btnClose = QPushButton(self)
        self.btnClose.setText(translate("ReportDialog", "Close"))
        self.btnClose.setMaximumWidth(100)

        # webview for help information
        self.wv = HtmlView(self)

        # build structure
        self.horzLayout.addWidget(self.btnPrint)
        self.horzLayout.addWidget(self.btnClose)
        self.horzLayout.addSpacerItem(self.spacer)
        self.vertLayout.insertLayout(0, self.horzLayout)
        self.vertLayout.addWidget(self.wv)

        self.setLayout(self.vertLayout)

        self.btnPrint.clicked.connect(self.wv.execpreview)
        self.btnClose.clicked.connect(self.close)

    def showHtml(self, html):
        """
        Show rendered value of ``html``

        :param html: raw html data
        """
        print(html)
        self.wv.setHtml_(html)
        self.show()
コード例 #8
0
 def __init__(self, label_text):
     super(GetMapField, self).__init__()
     self.chooseStartMapLyt = QHBoxLayout()
     self.startMapLbl = QLabel(label_text)
     self.xcoords = MapCoordField("x coord")
     self.ycoords = MapCoordField("y coord")
     self.chooseStartMapLyt.addWidget(self.startMapLbl)
     self.chooseStartMapLyt.addWidget(self.xcoords)
     self.chooseStartMapLyt.addWidget(self.ycoords)
     self.set_button = QPushButton("set")
     self.chooseStartMapLyt.addWidget(self.set_button)
     window_layout = QVBoxLayout()
     window_layout.insertLayout(0, self.chooseStartMapLyt)
     self.setLayout(window_layout)
コード例 #9
0
class HtmlDialog(QDialog):
    """Generate a more complex HTML Viewer dialog window, with Prin/Close Buttons"""

    def __init__(self, parent = None):
        """
        Constructor of HtmlDialog

        :param parent: dialog parent
        :return:
        """
        super().__init__(parent, QtCore.Qt.WindowTitleHint | QtCore.Qt.WindowMinMaxButtonsHint | QtCore.Qt.WindowCloseButtonHint)

        self.horzLayout = QHBoxLayout()
        self.vertLayout = QVBoxLayout()
        self.spacer = QSpacerItem(1, 1, QSizePolicy.Expanding, QSizePolicy.Fixed)

        # print button
        self.btnPrint = QPushButton(self)
        self.btnPrint.setText(translate("ReportDialog", "Print"))
        self.btnPrint.setMaximumWidth(100)
        self.btnClose = QPushButton(self)
        self.btnClose.setText(translate("ReportDialog", "Close"))
        self.btnClose.setMaximumWidth(100)

        # webview for help information
        self.wv = HtmlView(self)

        # build structure
        self.horzLayout.addWidget(self.btnPrint)
        self.horzLayout.addWidget(self.btnClose)
        self.horzLayout.addSpacerItem(self.spacer)
        self.vertLayout.insertLayout(0, self.horzLayout)
        self.vertLayout.addWidget(self.wv)

        self.setLayout(self.vertLayout)

        self.btnPrint.clicked.connect(self.wv.execpreview)
        self.btnClose.clicked.connect(self.close)

    def showHtml(self, html):
        """
        Show rendered value of ``html``

        :param html: raw html data
        """
        print(html)
        self.wv.setHtml_(html)
        self.show()
コード例 #10
0
class ViewTab(QWidget):

    LAYERS = ('original', 'model', 'decontaminated residual', 'model residual')

    def __init__(self, inspector, *args):

        super().__init__(*args)

        self.inspector = inspector

        self.current_detector = 1
        self.current_dither = 1
        self.boxes_visible = False

        self.pixmap_item = {}  # {dither: {detector: {layer: pixmap}}

        for dither in (1, 2, 3, 4):
            self.pixmap_item[dither] = {}
            for detector in range(1, 17):
                self.pixmap_item[dither][detector] = {
                    layer: None
                    for layer in self.LAYERS
                }

        self._layout = QVBoxLayout()

        self._layout.setContentsMargins(5, 0, 5, 5)

        self._layout.setSpacing(0)

        self.selection_area = ObjectSelectionArea()

        self._layout.insertLayout(0, self.selection_area)

        # create and add the view area

        self.view = View(self)

        self.scene = QGraphicsScene()

        self._background = QBrush(QColor('#56595e'))

        executable_directory = os.path.dirname(
            os.path.abspath(inspect.stack()[0][1]))

        self._blank_image = QPixmap(
            QImage(executable_directory + '/load-exposure-message.svg'))

        self.scene.setBackgroundBrush(self._background)

        self._blank_pixmap = self.scene.addPixmap(self._blank_image)

        self.view.setScene(self.scene)

        self._layout.addWidget(self.view)

        self.setLayout(self._layout)

        self.current_layer = 'original'

    def init_view(self):
        # display dither 1, detector 1 in single view

        dithers = list(self.inspector.exposures.keys())

        self.current_dither = dithers[0]

        self.update_view()

        self.selection_area.dither_selector.setEnabled(True)
        self.selection_area.detector_selector.setEnabled(True)

        for i, dither in enumerate(dithers):
            self.selection_area.dither_selector.addItem(str(dither), dither)

        self.selection_area.dither_selector.activated[int].connect(
            self.change_dither)

        for detector in range(1, 17):
            self.selection_area.detector_selector.addItem(
                str(detector), detector)

        self.selection_area.detector_selector.activated[int].connect(
            self.change_detector)

        for layer in self.LAYERS:
            self.selection_area.data_selector.addItem(layer)

        self.selection_area.data_selector.activated[str].connect(
            self.change_layer)

        self.boxes_visible = False

    def change_dither(self, dither_index):
        self.current_dither = self.selection_area.dither_selector.itemData(
            dither_index)
        if dither_index != self.selection_area.dither_selector.currentIndex():
            self.selection_area.dither_selector.blockSignals(True)
            self.selection_area.dither_selector.setCurrentIndex(dither_index)
            self.selection_area.dither_selector.blockSignals(False)
        self.update_view()

    def change_detector(self, detector_index):
        self.current_detector = self.selection_area.detector_selector.itemData(
            detector_index)
        if detector_index != self.selection_area.detector_selector.currentIndex(
        ):
            self.selection_area.detector_selector.blockSignals(True)
            self.selection_area.detector_selector.setCurrentIndex(
                detector_index)
            self.selection_area.detector_selector.blockSignals(False)
        self.update_view()

    def update_view(self):
        if self.current_dither is None or self.current_detector is None:
            return

        data = self.inspector.exposures[self.current_dither][
            self.current_detector].data

        pixmap, _ = utils.np_to_pixmap(data, data.max())

        self.scene.clear()
        self.current_layer = 'original'
        original_index = self.selection_area.data_selector.findText(
            self.current_layer)
        self.selection_area.data_selector.setCurrentIndex(original_index)
        self.pixmap_item[self.current_dither][self.current_detector][
            self.current_layer] = self.scene.addPixmap(pixmap)
        self.pixmap_item[self.current_dither][self.current_detector][
            self.current_layer].setZValue(-1.0)

        self.boxes_visible = False

        self.inspector.rename_tab(self)

        self.inspector.detector_info_window.update_detector(
            self.current_dither, self.current_detector)

        if self.inspector.collection is not None:
            collection = self.inspector.collection
            dither = self.current_dither
            detector = self.current_detector
            if dither in collection.get_dithers(
            ) and detector in collection.get_detectors(dither):
                self.selection_area.data_selector.setEnabled(True)
            else:
                self.selection_area.data_selector.setDisabled(True)
        else:
            self.selection_area.data_selector.setDisabled(True)

    def show_bounding_box(self, dither, detector, object_id):
        spec = self.inspector.collection.get_spectrum(dither, detector,
                                                      object_id)
        return self.draw_spec_box(spec)

    def draw_spec_box(self, spec):
        if spec is not None:
            left = spec.x_offset
            height, width = spec.science.shape
            top = spec.y_offset

            rect = SpecBox(left, top, width, height)

            rect.spec = spec

            model = self.inspector.collection.get_model(self.current_dither,
                                                        self.current_detector,
                                                        spec.id,
                                                        order=1)

            if model is not None:
                rect.model = model.pixels

            self.scene.addItem(rect)

            return rect, QPointF(left, top)

    def show_bounding_boxes(self, dither, detector):
        for spec in self.inspector.collection.get_spectra(dither, detector):
            self.draw_spec_box(spec)

    def toggle_bounding_boxes(self):
        if not self.boxes_visible:
            self.show_boxes_in_view()
        else:
            self.remove_boxes_in_view()

    def toggle_decontaminated(self):
        if not self.decontamination_visible:
            self.show_decontaminated_in_view()
        else:
            self.remove_decontaminated_in_view()

    def show_boxes_in_view(self):
        self.show_bounding_boxes(self.current_dither, self.current_detector)
        self.boxes_visible = True

    def remove_boxes_in_view(self):
        for item in self.scene.items():
            if isinstance(item, SpecBox) and not item.pinned:
                self.scene.removeItem(item)
        self.boxes_visible = False

    def active_detector_has_spectral_data(self):
        if self.inspector.exposures is None or self.inspector.collection is None:
            return False

        dith = self.current_dither
        det = self.current_detector

        return dith in self.inspector.collection.get_dithers(
        ) and det in self.inspector.collection.get_detectors(dith)

    def select_spectrum(self):
        object_id = self.selection_area.searchbox.text()

        spec = self.select_spectrum_by_id(object_id)

        if spec is None:
            self.selection_area.searchbox.setText('Not found')

    def select_spectrum_by_id(self, object_id):

        if self.inspector.collection is None or self.inspector.exposures is None:
            return None

        spec = self.inspector.collection.get_spectrum(self.current_dither,
                                                      self.current_detector,
                                                      object_id)

        if spec is not None:
            # make sure that the spec is not already pinned

            for pinned_item in self.get_pinned_spectra():
                if pinned_item.spec.id == object_id:
                    pinned_item.grabKeyboard()
                    return None

            # this point is only reached if the specified spectrum is not already pinned. Pin the spec
            spec_box, pos = self.show_bounding_box(self.current_dither,
                                                   self.current_detector,
                                                   object_id)
            spec_box.pin(pos)
            spec_box.grabKeyboard()

        return spec

    def unselect_spectrum_by_id(self, object_id):
        for item in self.get_pinned_spectra():
            if item.spec.id == object_id:
                self.scene.removeItem(item)

    def get_pinned_spectra(self):
        items = []
        for item in self.scene.items():
            if isinstance(item, SpecBox) and item.pinned:
                items.append(item)
        return items

    def get_model_residual_image(self):
        """removes all model contaminants from the detector and returns the model residual"""
        data = self.inspector.exposures[self.current_dither][
            self.current_detector].data
        return data - self.get_model_image()

    def get_model_image(self):
        data = self.inspector.exposures[self.current_dither][
            self.current_detector].data
        sim = np.zeros_like(data)

        for object_id in self.inspector.collection.get_object_ids(
                self.current_dither, self.current_detector):
            model = self.inspector.collection.get_model(
                self.current_dither, self.current_detector, object_id, 1)
            if model is not None:
                height, width = model.pixels.shape
                region = (slice(model.y_offset, model.y_offset + height),
                          slice(model.x_offset, model.x_offset + width))
                sim[region] += model.pixels
            else:
                # there is no model because this was not contaminated. The spectrum itself is essentially the model.
                model = self.inspector.collection.get_spectrum(
                    self.current_dither, self.current_detector, object_id)
                height, width = model.science.shape
                region = (slice(model.y_offset, model.y_offset + height),
                          slice(model.x_offset, model.x_offset + width))
                sim[region] += model.science

        return sim

    def get_residual_image(self):
        data = self.inspector.exposures[self.current_dither][
            self.current_detector].data
        decon = np.zeros_like(data)

        for object_id in self.inspector.collection.get_object_ids(
                self.current_dither, self.current_detector):
            spec = self.inspector.collection.get_spectrum(
                self.current_dither, self.current_detector, object_id)
            height, width = spec.science.shape
            region = (slice(spec.y_offset, spec.y_offset + height),
                      slice(spec.x_offset, spec.x_offset + width))
            decon[region] += spec.science

        return data - decon

    def get_pixmap(self, image_data):
        data = self.inspector.exposures[self.current_dither][
            self.current_detector].data
        _, pixmap = utils.np_to_pixmap(data, data.max(), data.min(),
                                       image_data)
        return pixmap

    def remove_pinned_boxes(self):
        for item in self.scene.items():
            if isinstance(item, SpecBox) and item.pinned:
                self.scene.removeItem(item)

        if len(self.scene.items()) == 0:
            self.boxes_visible = False

    def n_pinned_boxes(self):
        n = 0
        for item in self.scene.items():
            if isinstance(item, SpecBox) and item.pinned:
                n += 1

        return n

    def change_layer(self, layer):
        if self.current_layer == layer:
            return

        print('switching to', layer)

        if layer not in self.LAYERS:
            return

        self.scene.removeItem(self.pixmap_item[self.current_dither][
            self.current_detector][self.current_layer])

        if self.pixmap_item[self.current_dither][
                self.current_detector][layer] is None:
            if layer == 'original':
                image_data = self.inspector.exposures[self.current_dither][
                    self.current_detector].data
                pixmap = utils.np_to_pixmap(image_data, image_data.max())
            elif layer == 'model residual':
                image_data = self.get_model_residual_image()
                pixmap = self.get_pixmap(image_data)
            elif layer == 'decontaminated residual':
                image_data = self.get_residual_image()
                pixmap = self.get_pixmap(image_data)
            elif layer == 'model':
                print('switching to the model layer')
                image_data = self.get_model_image()
                pixmap = self.get_pixmap(image_data)

            pixmap_item = self.scene.addPixmap(pixmap)
            pixmap_item.setZValue(-1.0)
            self.pixmap_item[self.current_dither][
                self.current_detector][layer] = pixmap_item
        else:
            self.scene.addItem(self.pixmap_item[self.current_dither][
                self.current_detector][layer])

        self.current_layer = layer
コード例 #11
0
ファイル: gui.py プロジェクト: Matvezy/Detector
class TrackWindow(QMainWindow):
    def __init__(self, people):
        super().__init__()
        self.people = people
        self.setWindowTitle("Tracking stats")  
        self.result = []
        self.central = QWidget(self)
        self.vlayout = QVBoxLayout() 
        self.button_names = []       
        for person in self.people:
            self.upadte_column(person)
        self.add_button = QPushButton('Add new people')
        self.add_button.setMinimumSize(int((QDesktopWidget().screenGeometry(-1).width())/4), int((QDesktopWidget().screenGeometry(-1).height())/15))
        self.vlayout.addWidget(self.add_button)
        self.central.setLayout(self.vlayout)
        self.setCentralWidget(self.central)
        self.add_button.clicked.connect(self.add_person)

    def add_person(self):
        self.name_person, okPressed = QInputDialog.getText(self, "Name","Name of a person:",QLineEdit.Normal, "")
        if okPressed and self.name_person != '':
            self.window = QWidget()
            self.window.setWindowTitle('Doubleclick your image')
            okButtons = QHBoxLayout()
            windowLayout = QVBoxLayout()
            '''
            self.ok_button = QPushButton('Ok')
            self.cancel_button = QPushButton('Cancel')
            okButtons.addWidget(self.ok_button)
            okButtons.addWidget(self.cancel_button)
            self.ok_button.setEnabled(False)
            self.ok_button.setCheckable(True)
            '''
            self.model = QFileSystemModel()
            self.model.setRootPath('')
            self.tree = QTreeView()
            self.tree.setModel(self.model)
            self.tree.setIndentation(20)
            self.tree.setSortingEnabled(True)
            self.tree.setWindowTitle("Dir View")
            self.tree.setMinimumSize(int((QDesktopWidget().screenGeometry(-1).width())/2), int((QDesktopWidget().screenGeometry(-1).height())/2))
            windowLayout.addWidget(self.tree)
            windowLayout.addLayout(okButtons)
            self.window.setLayout(windowLayout)
            self.tree.doubleClicked.connect(self.on_treeView_clicked)
            self.window.show()
        else:
            print('Enter something')

    @pyqtSlot(QModelIndex)    
    def on_treeView_clicked(self, index):
        indexItem = self.model.index(index.row(), 0, index.parent())
        values = []
        fileName = self.model.fileName(indexItem)
        filePath = self.model.filePath(indexItem)
        values.append(filePath)
        self.result.append(self.name_person)               
        self.result.append(values)
        
    def update_stats(self):
        for person in self.people:
            ind = str(self.people.index(person))
            for key, value in person.__dict__.items():
                parametr = getattr(self, key+ind)
                if key  != 'name':     
                    time_val = float(value.split(' ')[-2])
                    indx = value.find(str(time_val))
                    parametr.setText(key+' time: '+value[:indx]+str(int(time_val))+value[value.find('sec')-1:]) 
    
    def upadte_column(self, person):
            ind = self.people.index(person)
            setattr(self, 'button'+str(ind), QVBoxLayout())
            self.button_names.append('button'+str(ind))
            if ind%2 == 0:
                setattr(self, 'buttons'+str(ind), QHBoxLayout())
            for key, value in person.__dict__.items():
                setattr(self, key+str(ind), QLabel(self))
                parametr = getattr(self, key+str(ind))
                if key  != 'name':
                    time_val = float(value.split(' ')[-2])
                    indx = value.find(str(time_val))
                    parametr.setText(key+' time: '+value[:indx]+str(int(time_val))+value[value.find('sec')-1:])
                else:
                    parametr.setText(value)
                but_ind = getattr(self, 'button'+str(ind))
                but_ind.addWidget(parametr)
                if ind%2 == 0:
                    box_lay = getattr(self, 'buttons'+str(ind))
                else:
                    box_lay = getattr(self, 'buttons'+str(ind-1))
                box_lay.addLayout(but_ind)
                self.vlayout.insertLayout(-2,box_lay)

    def update_row(self):
        key = list(self.people[-1].__dict__.keys())[-1]
        count = 0 
        for name in self.button_names:
            but_ind = getattr(self, name) 
            setattr(self, key+str(count), QLabel(self))
            parametr = getattr(self, key+str(count))
            parametr.setText(key+' time: 0 hrs 0 min 0.0 sec')
            but_ind.addWidget(parametr)  
            count += 1
コード例 #12
0
class AutoEditor(TableInfoChanger):
    """Ух, шайтан
    класс, в которых запихнули кишки из PathEditor, который основан на ViewShower,
     со всеми вытекающими для совместимости"""
    combo_update = ViewInfoChanger.combo_update

    def __init__(self, header, info, parent):
        super().__init__(header, info, parent)
        self.combo_change_idx = {"Водитель": {}}
        self.slave_drivers_layout = QVBoxLayout()
        push_btn = self.main_layout.takeAt(self.main_layout.count() -
                                           1).widget()

        self.auto_id = info[0]
        add_btn = QPushButton("Добавить")
        add_btn.clicked.connect(lambda e: self.add_cell(-1))
        self.main_layout.addWidget(add_btn)

        way = self.db.execute(
            f"SELECT CONCAT(`Фамилия`,' ', `Имя`,' ',`Отчество`), `назначение автомобиля водителю`.`Табельный номер` FROM `назначение автомобиля водителю` join `водитель` on `водитель`.`Табельный номер` = `назначение автомобиля водителю`.`Табельный номер` where `Номер автомобиля` = '{self.auto_id}'"
        )
        for pos, point in enumerate(way, start=-1):
            auto_info = str(point[0])
            self.combo_change_idx["Водитель"][auto_info] = point[1]
            self.add_cell(pos, auto_info)

        self.main_layout.addLayout(self.slave_drivers_layout)
        self.main_layout.addWidget(push_btn)

    def add_cell(self, pos: int, txt=""):
        """Вставляет ячейку ниже активирующей кнопки для вставки на уровне надо передать ::pos:: = -1"""

        cell = QHBoxLayout()
        edi = QLineEdit()
        edi.setText(txt)

        add_btn = QPushButton("Добавить")
        del_btn = QPushButton("Удалить")

        cmb = QComboBox()
        cmb.addItem(txt)

        edi.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        cmb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        add_btn.clicked.connect(lambda e, c=cell: self.add_cell(c.pos))
        del_btn.clicked.connect(lambda e, c=cell: self.del_cell(c.pos))

        edi.editingFinished.connect(
            lambda c=cmb, t=edi.text: self.combo_update("Водитель", c, t()
                                                        ))  # le-kostyl
        cell.pos = pos
        cell.addWidget(edi)
        cell.addWidget(cmb)
        cell.addWidget(add_btn)
        cell.addWidget(del_btn)
        for i in range(pos + 1, self.slave_drivers_layout.count()):
            cell_to_move = self.slave_drivers_layout.itemAt(i)
            cell_to_move.pos += 1
        cell.pos += 1  # для вставки ниже активированной кнопки

        self.slave_drivers_layout.insertLayout(cell.pos, cell)

    def del_cell(self, pos):
        cell: QVBoxLayout
        cell = self.slave_drivers_layout.takeAt(pos)
        for i in range(cell.count()):
            w = cell.takeAt(0).widget()
            w.deleteLater()
        cell.deleteLater()

        for i in range(pos, self.slave_drivers_layout.count()):
            cell_to_move = self.slave_drivers_layout.itemAt(i)
            cell_to_move.pos -= 1

    def push_point_changes(self):
        params = []
        for i in range(self.slave_drivers_layout.count()):
            cell = self.slave_drivers_layout.itemAt(i)
            w = cell.itemAt(1).widget()
            driver = w.currentText()
            if driver:
                driver_id = self.combo_change_idx["Водитель"][driver]
                params.append((driver_id, self.auto_id))

        query = f" insert into `назначение автомобиля водителю` values(%s, %s)"
        self.db.execute(
            "delete from `назначение автомобиля водителю` where `Номер автомобиля` = %s",
            (self.auto_id, ))
        self.db.executemany(query, params)
        self.db.commit()

    def push_changes(self):
        self.push_point_changes()
        super().push_changes()
コード例 #13
0
class GUI_HyperParameters(QWidget):
    def __init__(self, gui_play, cur_hps=None):
        super().__init__()
        self.gui_play = gui_play
        self.name_inpt_dict = {}
        self.structured_hyperparams = {}
        self.substructered_items = []
        self.reference_hps = hp.AgentsHyperparameters()
        if cur_hps is None:
            self.hp = hp.AgentsHyperparameters()
        else:
            self.hp = cur_hps
        self.initUI()

    def initUI(self):
        self.resize(800, 600)
        self.center()
        self.setWindowTitle('Icon')
        self.setWindowIcon(QIcon('test.png'))

        self.v_main = QVBoxLayout()
        idx = 0
        for attr in dir(self.hp):
            attr_name = str(attr)
            if not callable(getattr(self.hp,
                                    attr)) and not attr.startswith("__"):
                idx += 1
                hbox = QHBoxLayout()
                lab = QLabel(attr_name, self)
                hbox.addWidget(lab)
                the_attrib = getattr(self.hp, attr_name)
                if isinstance(the_attrib, dict):
                    inp = QComboBox()
                    inp.addItems(the_attrib.keys())
                    self.structured_hyperparams[attr_name] = (idx, the_attrib)
                    inp.activated.connect(self.activated_combobox)
                    hbox.addWidget(inp)
                elif isinstance(the_attrib, list):
                    list_key = the_attrib[0]
                    reference = getattr(self.reference_hps, attr_name)
                    if isinstance(reference, dict):
                        if list_key in reference:
                            reference[list_key] = the_attrib[1]
                            inp = QComboBox()
                            inp.addItems(reference.keys())
                            self.structured_hyperparams[attr_name] = (
                                idx, reference)
                            inp.activated.connect(self.activated_combobox)
                            hbox.addWidget(inp)
                        else:
                            inp = None
                    else:
                        inp = None
                else:
                    inp = QLineEdit(str(the_attrib), self)
                    hbox.addWidget(inp)
                if inp is not None:
                    self.name_inpt_dict[attr_name] = inp
                    self.v_main.addLayout(hbox)
        self.add_sub_inputs()

        self.start_btn = QPushButton("start", self)
        self.start_btn.clicked.connect(self.train_click)
        self.v_main.addWidget(self.start_btn)

        self.setLayout(self.v_main)
        self.show()

    def add_sub_inputs(self):
        items_per_row = 3
        for sub_struct in self.substructered_items:
            for i in range(self.v_main.count()):
                layout_item = self.v_main.itemAt(i)
                if isinstance(
                        layout_item,
                        QHBoxLayout) and layout_item.layout() == sub_struct:
                    clear_layout(layout_item)
                    self.v_main.removeItem(layout_item)
        self.substructered_items.clear()
        for struct_hyper_key in self.structured_hyperparams.keys():
            combo_box = self.name_inpt_dict[struct_hyper_key]
            new_items_dict = self.structured_hyperparams[struct_hyper_key][1][
                combo_box.currentText()]
            new_item_keys = list(new_items_dict.keys())
            for i in range(0, len(new_item_keys), items_per_row):
                h_outer = QHBoxLayout()
                for j in range(items_per_row):
                    if i + j < len(new_item_keys):
                        cur_key = new_item_keys[i + j]
                        hbox = QHBoxLayout()
                        hbox.addWidget(QLabel(cur_key, self))
                        inp = QLineEdit(str(new_items_dict[cur_key]), self)
                        hbox.addWidget(inp)
                        self.name_inpt_dict[cur_key] = inp
                        h_outer.addLayout(hbox)
                self.substructered_items.append(h_outer)
                self.v_main.insertLayout(
                    self.structured_hyperparams[struct_hyper_key][0], h_outer)

    def activated_combobox(self):
        print("connected")
        self.add_sub_inputs()

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

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

    @pyqtSlot()
    def train_click(self):
        for attr in dir(self.hp):
            if not callable(getattr(self.hp,
                                    attr)) and not attr.startswith("__"):
                attr_nam = str(attr)
                if isinstance(self.name_inpt_dict[attr_nam], QComboBox):
                    combo_box = self.name_inpt_dict[attr_nam]
                    selected_item = combo_box.currentText()
                    items_dict = self.structured_hyperparams[attr_nam][1][
                        selected_item]
                    for cur_key in items_dict.keys():
                        value = get_int_or_else_float_from_str(
                            self.name_inpt_dict[cur_key].text())
                        if value is not None:
                            items_dict[cur_key] = value
                    print(items_dict)
                    setattr(self.hp, attr_nam, (selected_item, items_dict))
                    print(getattr(self.hp, attr_nam))
                else:
                    value = get_int_or_else_float_from_str(
                        self.name_inpt_dict[attr_nam].text())
                    if value is not None:
                        setattr(self.hp, attr_nam, value)
        self.gui_play.new_handler_and_start(self.hp)
        self.hide()
コード例 #14
0
class GUI(QWidget):
    def __init__(self):
        super().__init__()

        try:
            urlopen('http://maia.usno.navy.mil/ser7/finals2000A.all')
        except HTTPError as e:
            print("Main IERS link not working, using mirror")
            iers.conf.iers_auto_url = 'http://toshi.nofs.navy.mil/ser7/finals2000A.all'
        except URLError as e:
            print("Main IERS link not working, using mirror")
            iers.conf.iers_auto_url = 'http://toshi.nofs.navy.mil/ser7/finals2000A.all'

        #download_IERS_A()

        plt.style.use(astropy_mpl_style)

        irbeneLocation = EarthLocation(lat=57.5535171694 * u.deg, lon=21.8545525000 * u.deg, height=87.30 * u.m)
        self.irbene = Observer(location=irbeneLocation, name="Irbene", timezone="Europe/Riga")

        observe_time = Time(['2019-02-05 15:30:00'])

        self.targets = []
        self.targetsDict = {}
        with open("config/config.csv", "r") as csvfile:
            next(csvfile)
            reader = csv.reader(csvfile, delimiter=",", quotechar="|")
            for row in reader:
                sourceName = row[0]

                raText = row[1]
                raText = insert(raText, 'h', 2)     #Nolasa targets no faila un ievieto targetsDict un targets
                raText = insert(raText, 'm', 5)
                raText = insert(raText, 's', len(raText))

                decText = row[2]
                if (decText[0] != "-"):
                    decText = insert(decText, 'd', 2)
                    decText = insert(decText, 'm', 5)
                    decText = insert(decText, 's', len(decText))
                else:
                    decText = insert(decText, 'd', 3)
                    decText = insert(decText, 'm', 6)
                    decText = insert(decText, 's', len(decText))

                ra = Angle(raText)
                dec = Angle(decText)

                targetCoord = SkyCoord(frame='icrs', ra=ra, dec=dec, obstime="J2000")
                target = FixedTarget(coord=targetCoord, name=sourceName)
                plannedObs = PlannedObs(target, int(row[4]), int(row[3]), int(row[5]))
                self.targets.append(plannedObs)  # target / obs per_week / priority / scans per obs
                coords = {"ra": ra, "dec": dec}
                self.targetsDict[sourceName] = coords

        self.targets = sorted(self.targets, key=lambda x: x.priority)  # sort targets by priority
        self.calibrators = []
        self.calibratorsDict = {}
        with open("config/calibrators.csv", "r") as csvfile:
            next(csvfile)
            reader = csv.reader(csvfile, delimiter=";", quotechar="|")
            for row in reader:
                sourceName = row[0]

                raText = str(row[1]).replace(" ", "")
                raText = insert(raText, 'h', 2)
                raText = insert(raText, 'm', 5)
                raText = insert(raText, 's', len(raText))

                decText = str(row[2]).replace(" ", "")
                if (decText[0] != "-"):
                    decText = insert(decText, 'd', 3)
                    decText = insert(decText, 'm', 6)
                    decText = insert(decText, 's', len(decText))
                else:
                    decText = insert(decText, 'd', 3)
                    decText = insert(decText, 'm', 6)
                    decText = insert(decText, 's', len(decText))            #Nolasa no faila calibratorus un ievieto calibratorsDict un calibrators

                ra = Angle(raText)
                dec = Angle(decText)

                coords = {"ra": ra, "dec": dec}
                self.calibratorsDict[sourceName] = coords
                calibratorCoord = SkyCoord(frame='icrs', ra=ra, dec=dec, obstime="J2000")
                calibrator = FixedTarget(coord=calibratorCoord, name=sourceName)
                self.calibrators.append(calibrator)

        startArray, endArray, summaryArray = get_all_events()       #No google calendar sanem noverosanas datumus un laikus
        self.dateList = QListWidget()

        tempCheck = True
        for i in range(len(startArray)):
            dayStart = parse(startArray[i])
            dayEnd = parse(endArray[i])
            daySummary = summaryArray[i]
            daySummary = daySummary + " " + str(dayStart.date()) + " " + str(dayStart.time()) + "-" + str(dayEnd.time())
            item = QListWidgetItem(daySummary, self.dateList)
            item.setData(Qt.UserRole, [dayStart, dayEnd])               #Izveido listwidget item no datuma un laika un to ievieto listwidget
            item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
            item.setCheckState(Qt.Unchecked)
            if tempCheck and "maser" in daySummary:
                item.setCheckState(Qt.Checked)
                tempCheck = False
            self.dateList.addItem(item)

        config = configparser.ConfigParser()
        config.read('config/config.ini')
        self.config = config._sections['Default']
        self.config['calibration'] = config['Default'].getboolean('calibration')  #Nolasa config failu


        self.layout = QGridLayout()
        self.layout.setSpacing(0)
        self.layout.setContentsMargins(0,0,0,0)
        self.setLayout(self.layout)
        self.resize(1000, 600)



        self.dateBoxList = []
        self.targetTimesCount = 0
        self.load_ui()

    def load_ui(self):   #Funkcija kas ielade galveno skatu
        self.observationList = QListWidget()
        self.plannedTargets = []
        for target in self.targets[:10]:
            item = QListWidgetItem(str(target), self.observationList)    #Aizpilda planotaju ar 10 targets kurus ieprieks nolasija no faila
            item.setData(Qt.UserRole, target)
            self.observationList.addItem(item)
            self.plannedTargets.append(target.name)

        self.layout.addWidget(self.observationList, 0, 0, 10, 2)

        self.observationList.itemSelectionChanged.connect(self.obsChanged) #Connect savieno kada UI elementa action (piemeram click) ar funkciju koda
                                                                           #Seit mainot izveleto elemntu listwidget izsauksies funkcija obsChanged
        for index in range(self.observationList.count()):
            item = self.observationList.item(index)

        self.targetLayout = QVBoxLayout()
        targetBox = QGroupBox()
        targetBox.setMaximumSize(350, 250)

        line = QHBoxLayout()
        nameLabel = QLabel("Target:")
        self.nameBox = QLineEdit()
        self.nameBox.setEnabled(False)
        nameLabel.setParent(targetBox)
        self.nameBox.setParent(targetBox)
        line.addWidget(nameLabel)
        line.addWidget(self.nameBox)
        self.targetLayout.addLayout(line)

        line = QHBoxLayout()
        priorityLabel = QLabel("Priority:")
        self.priorityBox = QLineEdit()
        priorityLabel.setParent(targetBox)
        self.priorityBox.setParent(targetBox)
        line.addWidget(priorityLabel)
        line.addWidget(self.priorityBox)
        self.targetLayout.addLayout(line)

        line = QHBoxLayout()
        obsLabel = QLabel("Obs per week:")
        self.obsBox = QLineEdit()
        obsLabel.setParent(targetBox)
        self.obsBox.setParent(targetBox)
        line.addWidget(obsLabel)
        line.addWidget(self.obsBox)
        self.targetLayout.addLayout(line)

        line = QHBoxLayout()
        scanLabel = QLabel("Scans per obs:")
        self.scanBox = QLineEdit()
        scanLabel.setParent(targetBox)
        self.scanBox.setParent(targetBox)
        line.addWidget(scanLabel)
        line.addWidget(self.scanBox)
        self.targetLayout.addLayout(line)

        line = QHBoxLayout()
        globalLabel = QLabel("Global time:")
        self.globalTimeBox = QLineEdit()
        line.addWidget(globalLabel)
        line.addWidget(self.globalTimeBox)
        self.targetLayout.addLayout(line)

        line = QHBoxLayout()
        specificLabel = QLabel("Specific times:")
        addTime = QPushButton("Add specific time")
        addTime.clicked.connect(self.add_time)
        line.addWidget(specificLabel)
        line.addWidget(addTime)
        self.targetLayout.addLayout(line)

        saveButton = QPushButton("Save changes")
        saveButton.clicked.connect(self.save_obs_changes)
        self.targetLayout.addWidget(saveButton)

        removeButton = QPushButton("Remove target")
        removeButton.clicked.connect(self.remove_obs)
        self.targetLayout.addWidget(removeButton)

        targetBox.setLayout(self.targetLayout)
        self.layout.addWidget(targetBox, 0, 2, 2, 1)

        self.targetComboBox = QComboBox()
        for key in self.targetsDict:
            if key not in self.plannedTargets:
                self.targetComboBox.addItem(key)
        self.layout.addWidget(self.targetComboBox, 2, 2)

        addButton = QPushButton("Add observation")
        addButton.clicked.connect(self.add_obs)
        self.layout.addWidget(addButton, 3, 2)

        nextButton = QPushButton("Schedule")
        nextButton.clicked.connect(self.prepare_schedule)
        self.layout.addWidget(nextButton, 0, 3)
        datesButton = QPushButton("Dates")
        datesButton.clicked.connect(self.edit_dates)
        self.layout.addWidget(datesButton, 1, 3)
        targetsButton = QPushButton("Targets")
        targetsButton.clicked.connect(self.edit_targets)
        self.layout.addWidget(targetsButton, 2, 3)
        calibratorsButton = QPushButton("Calibrators")
        calibratorsButton.clicked.connect(self.edit_calibrators)
        self.layout.addWidget(calibratorsButton, 3, 3)
        settingsButton = QPushButton("Settings")
        settingsButton.clicked.connect(self.load_settings)
        self.layout.addWidget(settingsButton, 4, 3)
        saveObsButton = QPushButton("Save observation")
        saveObsButton.clicked.connect(self.save_obs)
        self.layout.addWidget(saveObsButton, 5, 3)
        loadObsButton = QPushButton("Load observation")
        loadObsButton.clicked.connect(self.load_obs_new)
        self.layout.addWidget(loadObsButton, 6, 3)

    def add_time(self):    #Pievieno combobox ar izveletajiem datumiem
        datesChecked = 0
        for index in range(self.dateList.count()):
            if self.dateList.item(index).checkState() == Qt.Checked:
                datesChecked = datesChecked + 1
        if datesChecked > self.targetTimesCount:
            line = QHBoxLayout()
            dateBox = QComboBox()
            for index in range(self.dateList.count()):
                if self.dateList.item(index).checkState() == Qt.Checked:
                    dateBox.addItem(self.dateList.item(index).text(), self.dateList.item(index).data(Qt.UserRole))
            dateBox.addItem("Remove")
            dateBox.currentTextChanged.connect(self.timeChanged)
            self.targetTimesCount+= 1
            dateBox.sizePolicy().setHorizontalStretch(1)
            timeBox = QLineEdit()
            timeBox.sizePolicy().setHorizontalStretch(3)
            line.addWidget(dateBox)
            line.addWidget(timeBox)
            self.dateBoxList.append(line)
            self.targetLayout.insertLayout(self.targetLayout.count()-2, line)
        else:
            self.show_error("Date error", "Can't select more times than selected dates")

    def timeChanged(self, item): #Ja pie specifiskajiem laikiem izvelas remove tad iznem to
        if item == "Remove":
            for line in self.dateBoxList:
                if line is not None:
                    item = line.itemAt(0)
                    widget = item.widget()
                    if type(widget) == type(QComboBox()):
                        if widget.currentText() == "Remove":
                            break
            self.targetTimesCount -= 1
            widget.disconnect()
            self.deleteItemsOfLayout(line)
            self.targetLayout.removeItem(line)
            self.dateBoxList.remove(line)


    def obsChanged(self):  #Nomainot observation nomaina visus texta laukus
        if len(self.observationList.selectedItems()) > 0:
            item = self.observationList.currentItem()
            plannedObs = item.data(Qt.UserRole)
            self.nameBox.setText(plannedObs.name)
            self.priorityBox.setText(str(plannedObs.priority))
            self.obsBox.setText(str(plannedObs.obs_per_week))
            self.scanBox.setText(str(plannedObs.scans_per_obs))
            i = 0
            maxi = self.targetLayout.count()
            while(i < maxi):
                layout_item = self.targetLayout.itemAt(i)
                if layout_item in self.dateBoxList:
                    self.deleteItemsOfLayout(layout_item.layout())
                    self.targetLayout.removeItem(layout_item)
                    self.dateBoxList.remove(layout_item)
                    maxi = self.targetLayout.count()
                    i = i -1
                i=i+1
            self.dateBoxList.clear()
            self.targetTimesCount = 0
            if plannedObs.times:
                checkedDates = []
                for index in range(self.dateList.count()):
                    if self.dateList.item(index).checkState() == Qt.Checked:
                        checkedDates.append(self.dateList.item(index).text())
                print(checkedDates)
                for time in list(plannedObs.times):
                    print(time)
                    if time not in checkedDates:    #Ja observation pievienots specifisks laiks datumam kurs vairs netiks izmantots to pazino lietotajam
                        self.show_error("Date mismatch", "Date "+time+" is not checked, removing it")
                        plannedObs.times.remove(time)
                for time in list(plannedObs.times):
                    line = QHBoxLayout()
                    dateBox = QComboBox()
                    for index in range(self.dateList.count()):
                        if self.dateList.item(index).checkState() == Qt.Checked: #Specific laikiem pievieno tikai datumus kas izveleti pie dates
                            dateBox.addItem(self.dateList.item(index).text(), self.dateList.item(index).data(Qt.UserRole))
                    dateBox.addItem("Remove")
                    dateBox.currentTextChanged.connect(self.timeChanged)
                    self.targetTimesCount += 1
                    dateBox.sizePolicy().setHorizontalStretch(1)
                    timeBox = QLineEdit(plannedObs.times[time])
                    timeBox.sizePolicy().setHorizontalStretch(3)
                    line.addWidget(dateBox)
                    line.addWidget(timeBox)
                    self.dateBoxList.append(line)
                    self.targetLayout.insertLayout(self.targetLayout.count() - 2, line)
                    dateBox.setCurrentIndex(dateBox.findText(time))

        else:
            self.nameBox.setText("")
            self.priorityBox.setText("")
            self.obsBox.setText("")
            self.scanBox.setText("")
            self.targetTimesCount = 0

    def remove_obs(self):
        if len(self.observationList.selectedItems()) > 0:
            self.plannedTargets.remove(self.observationList.currentItem().data(Qt.UserRole).name)
            self.targetComboBox.addItem(self.observationList.currentItem().data(Qt.UserRole).name)
            self.observationList.takeItem(self.observationList.currentRow())
        else:
            self.show_error("Observation error","Select an observation to remove it")


    def save_obs_changes(self): #Ja visi teksta lauki atbilst parbaudem tad saglaba datus, ja ne tad pazino lietotajam
        if not self.priorityBox.text().isdigit():
            self.show_error("Priority error", "Priority must be from 1 to 4")
        elif int(self.priorityBox.text()) > 4 or int(self.priorityBox.text()) < 0:
            self.show_error("Priority error", "Priority must be from 1 to 4")
        elif not self.obsBox.text().isdigit():
            self.show_error("Obs error", "Obs must be from 1 to 7")
        elif int(self.obsBox.text()) > 7 or int(self.obsBox.text()) < 0:
            self.show_error("Obs error", "Obs must be from 1 to 7")
        elif not self.scanBox.text().isdigit():
            self.show_error("Scan error", "Scan must be from 1 to 120")
        elif int(self.scanBox.text()) > 120 or int(self.scanBox.text()) < 0:
            self.show_error("Scan error", "Scan must be from 1 to 120")
        elif len(self.dateBoxList) != len(set(self.dateBoxList)):
            self.show_error("Date error", "Make sure specified times don't use same dates")
        else:
            times = {}
            timeCheck = True
            for line in self.dateBoxList:
                if line.count() > 0:
                    item = line.itemAt(0)
                    widget = item.widget()
                    date = widget.currentText()
                    time = date[-17:]
                    time = time.split('-')
                    timeStart = time[0]
                    timeStart = timeStart[:-3]
                    timeEnd = time[1]
                    timeEnd = timeEnd[:-3]
                    time = line.itemAt(1).widget().text()
                    timeCheck = self.time_check(time, timeStart, timeEnd)

                    if timeCheck == False:
                        break
                    else:
                        times[date] = line.itemAt(1).widget().text()

            if timeCheck: #Ja visas parbaudes izietas tad saglaba datus
                self.observationList.currentItem().data(Qt.UserRole).times = times
                self.observationList.currentItem().data(Qt.UserRole).priority = int(self.priorityBox.text())
                self.observationList.currentItem().data(Qt.UserRole).obs_per_week = int(self.obsBox.text())
                self.observationList.currentItem().data(Qt.UserRole).scans_per_obs = int(self.scanBox.text())
                self.observationList.currentItem().data(Qt.UserRole).global_time = self.globalTimeBox.text()
                self.observationList.currentItem().setText(str(self.observationList.currentItem().data(Qt.UserRole)))
            else:
                self.show_error("Specific time error", "Make sure the specific times fit the dates selected")

    def add_obs(self): #Izveido jaunu observation
        if self.targetComboBox.count() > 0:
            targetName = self.targetComboBox.currentText()
            ra = self.targetsDict[targetName]["ra"]
            dec = self.targetsDict[targetName]["dec"]
            coord = SkyCoord(frame='icrs', ra=ra, dec=dec, obstime="J2000")
            target = FixedTarget(coord=coord, name=targetName)
            data = PlannedObs(target, 1, 1, 1)
            item = QListWidgetItem(str(data), self.observationList)
            item.setData(Qt.UserRole, data)
            self.observationList.addItem(item)
            self.plannedTargets.append(data.name)
            self.targetComboBox.removeItem(self.targetComboBox.currentIndex())

    def edit_dates(self): #Atver dates skatu
        self.clear_window()
        self.layout.addWidget(self.dateList, 0, 0, 5, 2)
        backButton = QPushButton("Back to planner")
        self.layout.addWidget(backButton, 1, 2)
        backButton.clicked.connect(self.to_start)

    def edit_targets(self): #Atver targets skatu
        self.clear_window()

        self.targetList = QListWidget()
        for key in self.targetsDict:
            self.targetList.addItem(key)
        self.targetList.itemClicked.connect(self.targetChanged)
        self.layout.addWidget(self.targetList, 0, 0, 3, 1)

        targetLayout = QGridLayout()
        targetLayout.addWidget(QLabel("Ra:"), 0, 0)
        self.raBox = QLineEdit()
        targetLayout.addWidget(self.raBox, 0, 1)
        targetLayout.addWidget(QLabel("Dec:"), 1, 0)
        self.decBox = QLineEdit()
        targetLayout.addWidget(self.decBox, 1, 1)
        self.saveButton = QPushButton("Save changes")
        self.saveButton.clicked.connect(self.save_target_changes)
        targetLayout.addWidget(self.saveButton, 2, 0, 1, 2)
        targetBox = QGroupBox()
        targetBox.setLayout(targetLayout)
        self.layout.addWidget(targetBox, 0, 1)
        self.saveButton.setEnabled(False)

        addTargetLayout = QGridLayout()
        addTargetLayout.addWidget(QLabel("Name:"), 0, 0)
        self.addNameBox = QLineEdit()
        addTargetLayout.addWidget(self.addNameBox, 0, 1)

        addTargetLayout.addWidget(QLabel("Ra:"), 1, 0)
        self.addRaBox = QLineEdit()
        addTargetLayout.addWidget(self.addRaBox, 1, 1)

        addTargetLayout.addWidget(QLabel("Dec:"), 2, 0)
        self.addDecBox = QLineEdit()
        addTargetLayout.addWidget(self.addDecBox, 2, 1)

        self.addSaveButton = QPushButton("Save changes")
        self.addSaveButton.clicked.connect(self.add_target)
        addTargetLayout.addWidget(self.addSaveButton, 3, 0, 1, 2)

        addTargetBox = QGroupBox()
        addTargetBox.setLayout(addTargetLayout)
        self.layout.addWidget(addTargetBox, 1, 1)

        backButton = QPushButton("Back to planner")
        self.layout.addWidget(backButton, 0, 3)
        backButton.clicked.connect(self.to_start)

    def targetChanged(self, item):
        if not self.saveButton.isEnabled():
            self.saveButton.setEnabled(True)
        targetName = item.text()
        target = self.targetsDict[targetName]
        self.raBox.setText(target["ra"].to_string())
        self.decBox.setText(target["dec"].to_string(unit=u.degree))

    def save_target_changes(self):
        if len(self.targetList.selectedItems()) != 1:
            self.show_error("Target error", "Make sure you have selected only 1 target")
        else:
            targetName = self.targetList.selectedItems()[0].text()
            raPattern = re.compile("[0-9]{1,2}h[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,3})?s")
            decPattern = re.compile("-?[0-9]{1,2}d[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,3})?s")
            ra = self.raBox.text()
            dec = self.decBox.text()
            if not raPattern.match(ra):
                self.show_error("Ra error", "Ra coordinates don't match pattern 00h00m00.00s")
            elif not decPattern.match(dec):
                self.show_error("Dec error", "Dec coordinates don't match pattern 00d00m00.00s")
            else:
                self.targetsDict[targetName]["ra"] = Angle(ra)
                self.targetsDict[targetName]["dec"] = Angle(dec)

    def add_target(self): #Pievieno jaunu target
        raPattern = re.compile("[0-9]{1,2}h[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,3})?s")
        decPattern = re.compile("-?[0-9]{1,2}d[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,3})?s")
        ra = self.addRaBox.text()
        dec = self.addDecBox.text()
        name = self.addNameBox.text()
        print(self.targetsDict.keys())
        if ra == "" or dec == "" or name == "":
            self.show_error("Empty box", "Please fill all boxes")
        elif name in self.targetsDict.keys():
            self.show_error("Existing target", "Target already exists, please edit it")
        elif not raPattern.match(ra):
            self.show_error("Ra error", "Ra coordinates don't match pattern 00h00m00.00s")
        elif not decPattern.match(dec):
            self.show_error("Dec error", "Dec coordinates don't match pattern 00d00m00.00s")
        else:
            self.targetsDict[name] = {}
            self.targetsDict[name]["ra"] = Angle(ra)
            self.targetsDict[name]["dec"] = Angle(dec)
            self.edit_targets()

    def edit_calibrators(self): #Atver calibrators skatu
        self.clear_window()

        self.calibratorList = QListWidget()
        for key in self.calibratorsDict:
            self.calibratorList.addItem(key)
        self.calibratorList.itemClicked.connect(self.calibratorChanged)
        self.layout.addWidget(self.calibratorList, 0, 0, 3, 1)

        calibratorLayout = QGridLayout()
        calibratorLayout.addWidget(QLabel("Ra:"), 0, 0)
        self.raBox = QLineEdit()
        calibratorLayout.addWidget(self.raBox, 0, 1)
        calibratorLayout.addWidget(QLabel("Dec:"), 1, 0)
        self.decBox = QLineEdit()
        calibratorLayout.addWidget(self.decBox, 1, 1)
        self.saveButton = QPushButton("Save changes")
        self.saveButton.clicked.connect(self.save_calibrator_changes)
        calibratorLayout.addWidget(self.saveButton, 2, 0, 1, 2)
        calibratorBox = QGroupBox()
        calibratorBox.setLayout(calibratorLayout)
        self.layout.addWidget(calibratorBox, 0, 1)
        self.saveButton.setEnabled(False)

        addcalibratorLayout = QGridLayout()
        addcalibratorLayout.addWidget(QLabel("Name:"), 0, 0)
        self.addNameBox = QLineEdit()
        addcalibratorLayout.addWidget(self.addNameBox, 0, 1)

        addcalibratorLayout.addWidget(QLabel("Ra:"), 1, 0)
        self.addRaBox = QLineEdit()
        addcalibratorLayout.addWidget(self.addRaBox, 1, 1)

        addcalibratorLayout.addWidget(QLabel("Dec:"), 2, 0)
        self.addDecBox = QLineEdit()
        addcalibratorLayout.addWidget(self.addDecBox, 2, 1)

        self.addSaveButton = QPushButton("Save changes")
        self.addSaveButton.clicked.connect(self.add_calibrator)
        addcalibratorLayout.addWidget(self.addSaveButton, 3, 0, 1, 2)

        addcalibratorBox = QGroupBox()
        addcalibratorBox.setLayout(addcalibratorLayout)
        self.layout.addWidget(addcalibratorBox, 1, 1)

        backButton = QPushButton("Back to planner")
        self.layout.addWidget(backButton, 0, 3)
        backButton.clicked.connect(self.to_start)

    def calibratorChanged(self, item):
        if not self.saveButton.isEnabled():
            self.saveButton.setEnabled(True)
        calibratorName = item.text()
        calibrator = self.calibratorsDict[calibratorName]
        self.raBox.setText(calibrator["ra"].to_string())
        self.decBox.setText(calibrator["dec"].to_string(unit=u.degree))

    def save_calibrator_changes(self):
        if len(self.calibratorList.selectedItems()) != 1:
            self.show_error("calibrator error", "Make sure you have selected only 1 calibrator")
        else:
            calibratorName = self.calibratorList.selectedItems()[0].text()
            raPattern = re.compile("[0-9]{1,2}h[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,5})?s")
            decPattern = re.compile("-?[0-9]{1,2}d[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,5})?s")
            ra = self.raBox.text()
            dec = self.decBox.text()
            if not raPattern.match(ra):
                self.show_error("Ra error", "Ra coordinates don't match pattern 00h00m00.00s")
            elif not decPattern.match(dec):
                self.show_error("Dec error", "Dec coordinates don't match pattern 00d00m00.00s")
            else:
                self.calibratorsDict[calibratorName]["ra"] = Angle(ra)
                self.calibratorsDict[calibratorName]["dec"] = Angle(dec)

    def add_calibrator(self):
        raPattern = re.compile("[0-9]{1,2}h[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,5})?s")
        decPattern = re.compile("-?[0-9]{1,2}d[0-9]{1,2}m[0-9]{1,2}(\.[0-9]{1,5})?s")
        ra = self.addRaBox.text()
        dec = self.addDecBox.text()
        name = self.addNameBox.text()
        print(self.calibratorsDict.keys())
        if ra == "" or dec == "" or name == "":
            self.show_error("Empty box", "Please fill all boxes")
        elif name in self.calibratorsDict.keys():
            self.show_error("Existing calibrator", "calibrator already exists, please edit it")
        elif not raPattern.match(ra):
            self.show_error("Ra error", "Ra coordinates don't match pattern 00h00m00.00s")
        elif not decPattern.match(dec):
            self.show_error("Dec error", "Dec coordinates don't match pattern 00d00m00.00s")
        else:
            self.calibratorsDict[name] = {}
            self.calibratorsDict[name]["ra"] = Angle(ra)
            self.calibratorsDict[name]["dec"] = Angle(dec)
            self.edit_calibrators()


    def load_settings(self): #Atver settings skatu
        self.clear_window()
        targetLayout = QFormLayout()
        targetBox = QGroupBox()
        targetBox.setMaximumSize(350, 250)

        calibLabel = QLabel("Calib every X min:")
        self.calibBox = QLineEdit()
        calibLabel.setParent(targetBox)
        self.calibBox.setParent(targetBox)
        self.calibBox.setText(self.config['maxtimewithoutcalibration'])
        targetLayout.addRow(calibLabel, self.calibBox)

        calibDurLabel = QLabel("Calib duration:")
        self.calibDurBox = QLineEdit()
        calibDurLabel.setParent(targetBox)
        self.calibDurBox.setParent(targetBox)
        self.calibDurBox.setText(self.config['calibrationlength'])
        targetLayout.addRow(calibDurLabel, self.calibDurBox)

        minAltLabel = QLabel("Min alt:")
        self.minAltBox = QLineEdit()
        minAltLabel.setParent(targetBox)
        self.minAltBox.setParent(targetBox)
        self.minAltBox.setText(self.config['minaltitude'])
        targetLayout.addRow(minAltLabel, self.minAltBox)

        maxAltLabel = QLabel("Max alt:")
        self.maxAltBox = QLineEdit()
        maxAltLabel.setParent(targetBox)
        self.maxAltBox.setParent(targetBox)
        self.maxAltBox.setText(self.config['maxaltitude'])
        targetLayout.addRow(maxAltLabel, self.maxAltBox)

        calibToggleLabel = QLabel("Calibration on/off")
        self.calibCheckBox = QCheckBox()
        calibToggleLabel.setParent(targetBox)
        self.calibCheckBox.setParent(targetBox)
        if (self.config['calibration']):
            self.calibCheckBox.setChecked(True)
        else:
            self.calibCheckBox.setChecked(False)
        targetLayout.addRow(calibToggleLabel, self.calibCheckBox)

        saveButton = QPushButton("Save settings")
        saveButton.clicked.connect(self.save_settings)
        targetLayout.addRow(saveButton)

        targetBox.setLayout(targetLayout)
        self.layout.addWidget(targetBox, 0, 2, 2, 1)

    def save_settings(self):
        if not (self.calibBox.text().isdigit() and int(self.calibBox.text()) > 0):
            self.show_error("Input error","Max time without calib must be positive number")
        elif not (self.calibDurBox.text().isdigit() and int(self.calibDurBox.text()) > 0):
            self.show_error("Input error","Calib duration must be positive number")
        elif not (self.minAltBox.text().isdigit() and int(self.minAltBox.text()) > 0):
            self.show_error("Input error","Min alt must be positive number")
        elif not (self.maxAltBox.text().isdigit() and int(self.maxAltBox.text()) > 0):
            self.show_error("Input error","Max alt must be positive number")
        else:
            self.config['maxtimewithoutcalibration'] = self.calibBox.text()
            self.config['calibrationlength'] = self.calibDurBox.text()
            self.config['minaltitude'] = self.minAltBox.text()
            self.config['maxaltitude'] = self.maxAltBox.text()
            self.config['calibration'] = self.calibCheckBox.isChecked()
            self.to_start()

    def prepare_schedule(self): #Pirms uzsak planosanu, parbauda vai ir izvelets kads datums
        hasDate = False
        for index in range(self.dateList.count()):
            if self.dateList.item(index).checkState() == Qt.Checked:
                hasDate = True
                break
        if not hasDate:
            self.show_error("Date error", "No dates selected for schedule")
        else:
            self.start_schedule()

    def start_schedule(self): #Sak planosanu
        items = (self.layout.itemAt(i).widget() for i in range(self.layout.count()))
        self.targets = []

        for index in range(self.observationList.count()):
            item = self.observationList.item(index)
            target = item.data(Qt.UserRole)
            self.targets.append(target)  #Visus obs ievieto masiva targets

        targ_to_color = {}
        color_idx = np.linspace(0, 1, len(self.targets))

        for target, ci in zip(set(self.targets), color_idx): #Katram target un calibrator pieskir savu krasu
            if "split" not in target.name:
                if target.name not in targ_to_color:
                    targ_to_color[target.name] = plt.cm.jet(ci)

        calib_to_color = {}
        color_idx = np.linspace(0, 1, len(self.calibrators))

        for calibrator, ci in zip(set(self.calibrators), color_idx):
            if "split" not in calibrator.name:
                if calibrator.name not in calib_to_color:
                    calib_to_color[calibrator.name] = plt.cm.brg(ci)

        self.plots_idx = 0
        self.plots = []

        week = {}

        for index in range(self.dateList.count()):
            if self.dateList.item(index).checkState() == Qt.Checked: #Dates ievieto dict week
                week[self.dateList.item(index).text()]=[self.dateList.item(index).data(Qt.UserRole)[0], self.dateList.item(index).data(Qt.UserRole)[1]]


        for daySummary, day in week.items():

            dayStart = Time(day[0])  # convert from datetime to astropy.time
            dayEnd = Time(day[1])

            timeDict = {}

            for target in self.targets:
                if daySummary in target.times:
                    timeDict[target.name] = target.times[daySummary] #Pievieno specifiskos laikus dict timeDict
                elif target.global_time != "":
                    timeDict[target.name] = target.global_time

            minalt = self.config['minaltitude']
            maxalt = self.config['maxaltitude']

            constraints = [AltitudeConstraint(minalt * u.deg, maxalt * u.deg)]

            read_out = 1 * u.second
            target_exp = 60 * u.second
            blocks = []

            for target in self.targets:
                n = target.scans_per_obs
                priority = target.priority
                if (target.obs_per_week != 0): #Ja observation vel ir janovero tad izveido ObservingBlock
                    b = ObservingBlock.from_exposures(target.target, priority, target_exp, n, read_out)
                    blocks.append(b)


            slew_rate = 2 * u.deg / u.second
            transitioner = Transitioner(slew_rate, {'filter': {'default': 5 * u.second}})

            if (self.config['calibration']): #Padod mainigos planotajam
                prior_scheduler = SequentialScheduler(constraints=constraints, observer=self.irbene, transitioner=transitioner,
                                                      calibrators=self.calibrators, config=self.config, timeDict=timeDict)

                priority_schedule = Schedule(dayStart, dayEnd, targColor=targ_to_color, calibColor=calib_to_color, minalt=minalt, maxalt=maxalt)
            else:
                prior_scheduler = SequentialScheduler(constraints=constraints, observer=self.irbene,
                                                      transitioner=transitioner,
                                                      config=self.config, timeDict=timeDict)

                priority_schedule = Schedule(dayStart, dayEnd, targColor=targ_to_color, minalt=minalt, maxalt=maxalt)

            prior_scheduler(blocks, priority_schedule)

            observations = []
            for block in priority_schedule.scheduled_blocks:
                if hasattr(block, 'target'):
                    observation = Observation(block.target.name, block.start_time.datetime,
                                              (block.start_time + block.duration).datetime)
                    observations.append(observation)

            dict_array = []
            for observation in observations: #Saplanotos block nolasa un ieraksta faila
                for target in self.targets:
                    if target.name == observation.name:
                        print(target.name, " has been observed once")
                        target.obs_per_week -= 1
                dict_array.append({
                    "obs_name": observation.name,
                    "start_time": observation.start_time.strftime("%Y-%m-%d %H:%M:%S"),
                    "end_time": observation.end_time.strftime("%Y-%m-%d %H:%M:%S"),
                })

            json_dict = dict()
            json_dict["observations"] = dict_array
            if not os.path.isdir("observations"):
                os.mkdir("observations")
            if not os.path.isdir("observations/"):
                os.mkdir("observations")
            with open("observations/" + day[0].strftime("%Y-%m-%d-%H-%M") + ".json", 'w') as outfile:
                json.dump(json_dict, outfile, indent=4)


            sky = Plot() #Izveido grafikus
            skyCheck = sky.plot_sky_schedule(priority_schedule)
            alt = Plot(width=6)
            alt.plot_altitude_schedule(priority_schedule)

            if skyCheck is not False:
                self.plots.append([sky, alt])
            else:
                self.show_error("Empty schedule", "Schedule "+daySummary+"removing it")

        timeLeft = 0
        for target in self.targets:
            timeLeft += target.obs_per_week * target.scans_per_obs
            print(target.name, ' observations left ', target.obs_per_week, ' scan size ', target.scans_per_obs, ' priority ', target.priority)
        print('Total time left to observe ', timeLeft)

        self.showSky = False
        self.showAlt = False
        self.showBoth = True

        self.show_schedule()

    def show_schedule(self): #Atver grafiku skatu
        self.clear_window()

        sky, alt = self.plots[self.plots_idx]

        if self.showSky:
            self.layout.addWidget(sky, 0, 0, 2, 6)

        elif self.showAlt:
            self.layout.addWidget(alt, 0, 0, 2, 6)

        elif self.showBoth:
            self.layout.addWidget(sky, 0, 0, 1, 6)
            self.layout.addWidget(alt, 1, 0, 1, 6)

        self.toolbar = NavigationToolbar(alt, alt.parent)
        self.layout.addWidget(self.toolbar, 2, 0, 1, 3)

        self.radioSky = QRadioButton("Show skychart")
        self.radioAlt = QRadioButton("Show altitude")
        self.radioBoth = QRadioButton("Show both")

        self.radioSky.clicked.connect(self.changeScheduleView)
        self.radioAlt.clicked.connect(self.changeScheduleView)
        self.radioBoth.clicked.connect(self.changeScheduleView)


        self.layout.addWidget(self.radioSky, 2, 3)
        self.layout.addWidget(self.radioAlt, 2, 4)
        self.layout.addWidget(self.radioBoth, 2, 5)

        nextButton = QPushButton("Next")
        nextButton.clicked.connect(self.next_schedule)
        backButton = QPushButton("Back")
        backButton.clicked.connect(self.back_schedule)
        self.layout.addWidget(backButton, 3, 0, 1, 3)
        self.layout.addWidget(nextButton, 3, 3, 1, 3)

        startButton = QPushButton("To start")
        startButton.clicked.connect(self.to_start)
        self.layout.addWidget(startButton, 4, 0, 1, 3)

        if self.plots_idx == 0:
            backButton.hide()
        if self.plots_idx == (len(self.plots) - 1):
            nextButton.hide()

    def next_schedule(self):
        self.plots_idx += 1
        self.show_schedule()

    def changeScheduleView(self):
        radioText = self.sender().text()
        if "sky" in radioText:
            self.showSky = True
            self.showAlt = False
            self.showBoth = False
            self.show_schedule()
            self.radioSky.setChecked(True)
        elif "alt" in radioText:
            self.showSky = False
            self.showAlt = True
            self.showBoth = False
            self.show_schedule()
            self.radioAlt.setChecked(True)
        elif "both" in radioText:
            self.showSky = False
            self.showAlt = False
            self.showBoth = True
            self.show_schedule()
            self.radioBoth.setChecked(True)

    def back_schedule(self):
        self.plots_idx -= 1
        self.show_schedule()

    def save_obs(self):
        filename = self.saveFileDialog()
        if filename != "Fail":
            obsList = [self.observationList.item(i).data(Qt.UserRole) for i in range(self.observationList.count())]
            json_dict = dict()
            for obs in obsList:
                json_dict[obs.target.name]={
                    "priority": obs.priority,
                    "obs_per_week": obs.obs_per_week,
                    "scans_per_obs": obs.scans_per_obs,
                    "global_time": obs.global_time,
                    "times": obs.times,
                }
            print(json_dict)
            with open(filename, 'w') as outfile:
                json.dump(json_dict, outfile, indent=4)


    def saveFileDialog(self):
        save = QFileDialog()
        save.setDefaultSuffix(".json")
        save.setNameFilter("JSON files (*.json)")
        save.setAcceptMode(QFileDialog.AcceptSave)
        save.setOption(QFileDialog.DontUseNativeDialog)
        if save.exec_() == QFileDialog.Accepted:
            return save.selectedFiles()[0]
        else:
            return "Fail"

    def load_obs(self):
        load = QFileDialog()
        load.setDefaultSuffix(".json")
        load.setNameFilter("JSON files (*.json)")
        load.setAcceptMode(QFileDialog.AcceptOpen)
        load.setOption(QFileDialog.DontUseNativeDialog)
        if load.exec_() == QFileDialog.Accepted:
            filename = load.selectedFiles()[0]
            with open(filename) as json_file:
                obs_dict = json.load(json_file)
                self.observationList.clear()
                for key in obs_dict:
                    if key in self.targetsDict:
                        targetName = key
                        ra = self.targetsDict[targetName]["ra"]
                        dec = self.targetsDict[targetName]["dec"]
                        coord = SkyCoord(frame='icrs', ra=ra, dec=dec, obstime="J2000")
                        target = FixedTarget(coord=coord, name=targetName)
                        for date in obs_dict[key]['times']:
                            print(date)

                            # TODO Te pielikt date parbaudes, vai atkekset ja ir vai iznemt ja nav

                        data = PlannedObs(target, int(obs_dict[key]['priority']), int(obs_dict[key]['obs_per_week']),
                                          int(obs_dict[key]['scans_per_obs']), obs_dict[key]['times'],
                                          obs_dict[key]['global_time'])
                        item = QListWidgetItem(str(data), self.observationList)
                        item.setData(Qt.UserRole, data)
                        self.observationList.addItem(item)
                        self.plannedTargets.append(target.name)
                    else:
                        self.show_error("Target error", key + " not in targets, skipping it")
        else:
            print("Something went wrong")

    def load_obs_new(self):
        load = QFileDialog()
        load.setDefaultSuffix(".conf")
        load.setNameFilter("CONF files (*.conf)")
        load.setAcceptMode(QFileDialog.AcceptOpen)
        load.setOption(QFileDialog.DontUseNativeDialog)
        if load.exec_() == QFileDialog.Accepted:
            self.observationList.clear()
            filename = load.selectedFiles()[0]
            configObs = configparser.ConfigParser()
            configObs.read(filename)
            sections = configObs.sections()
            for section in sections:
                target = section.split('_')[0]
                ra = configObs[section]["RA"]
                dec = configObs[section]["DEC"]

                if target not in self.targetsDict.keys():
                    coords = {"ra": Angle(ra), "dec": Angle(dec)}
                    self.targetsDict[target] = coords
                else:
                    if Angle(ra) != Angle(self.targetsDict[target]["ra"]) or Angle(dec) != Angle(self.targetsDict[target]["dec"]):
                        qm = QMessageBox
                        ret = qm.question(self,'', target+" has different coords in the load file, would you like to overwrite the current ones?\n"+
                                                            "new coords:"+str(ra)+";   "+str(dec)+"\ncurrent coords:"+str(self.targetsDict[target]["ra"])+";   "+str(self.targetsDict[target]["dec"]), qm.Yes | qm.No)
                        if ret == qm.Yes:
                            self.targetsDict[target]["ra"] = Angle(ra)
                            self.targetsDict[target]["dec"] = Angle(dec)

                targetName = target
                ra = self.targetsDict[targetName]["ra"]
                dec = self.targetsDict[targetName]["dec"]
                coord = SkyCoord(frame='icrs', ra=ra, dec=dec, obstime="J2000")
                target = FixedTarget(coord=coord, name=targetName)

                data = PlannedObs(target, 1, 1, int(configObs[section]["n_scans"]), None, None)
                item = QListWidgetItem(str(data), self.observationList)
                item.setData(Qt.UserRole, data)
                self.observationList.addItem(item)
                self.plannedTargets.append(target.name)

        else:
            print("Something went wrong")


    def show_error(self, title, error_message):
        error_dialog = QMessageBox.critical(self, title, error_message)

    def to_start(self):
        self.clear_window()
        self.load_ui()

    def clear_window(self):
        for i in reversed(range(self.layout.count())):
            self.layout.itemAt(i).widget().setParent(None)

    def is_time_format(self, string):
        p = re.compile('^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$')
        print(string)
        res = bool(p.match(string))
        return res

    def time_check(self, time, timeStart, timeEnd):
        if not self.is_time_format(time):
            return False
        else:
            time = time.split(':')
            timeStart = timeStart.split(':')
            timeEnd = timeEnd.split(':')
            if int(time[0]) < int(timeStart[0]) or int(time[0]) > int(timeEnd[0]):
                return False
            elif int(time[0]) > int(timeStart[0]) and int(time[0]) < int(timeEnd[0]):
                return True
            elif (int(time[0]) == int(timeStart[0]) and int(time[1]) < int(timeStart[1])) or (int(time[0]) == int(timeEnd[0]) and int(time[1]) > int(timeEnd[1])):
                return False
            elif (int(time[0]) == int(timeStart[0]) and int(time[1]) >= int(timeStart[1])) or (int(time[0]) == int(timeEnd[0]) and int(time[1]) < int(timeEnd[1])):
                return True

    def deleteItemsOfLayout(self, layout):
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.setParent(None)
                else:
                    self.deleteItemsOfLayout(item.layout())
コード例 #15
0
class E5TextEditSearchWidget(QWidget):
    """
    Class implementing a horizontal search widget for QTextEdit.
    """
    def __init__(self, parent=None, widthForHeight=True):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        @param widthForHeight flag indicating to prefer width for height.
            If this parameter is False, some widgets are shown in a third
            line.
        @type bool
        """
        super(E5TextEditSearchWidget, self).__init__(parent)
        self.__setupUi(widthForHeight)
        
        self.__textedit = None
        self.__texteditType = ""
        self.__findBackwards = True
        
        self.__defaultBaseColor = (
            self.findtextCombo.lineEdit().palette().color(QPalette.Base)
        )
        self.__defaultTextColor = (
            self.findtextCombo.lineEdit().palette().color(QPalette.Text)
        )
        
        self.findHistory = []
        
        self.findtextCombo.setCompleter(None)
        self.findtextCombo.lineEdit().returnPressed.connect(
            self.__findByReturnPressed)
        
        self.__setSearchButtons(False)
        self.infoLabel.hide()
        
        self.setFocusProxy(self.findtextCombo)
    
    def __setupUi(self, widthForHeight):
        """
        Private method to generate the UI.
        
        @param widthForHeight flag indicating to prefer width for height
        @type bool
        """
        self.setObjectName("E5TextEditSearchWidget")
        
        self.verticalLayout = QVBoxLayout(self)
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        
        # row 1 of widgets
        self.horizontalLayout1 = QHBoxLayout()
        self.horizontalLayout1.setObjectName("horizontalLayout1")
        
        self.label = QLabel(self)
        self.label.setObjectName("label")
        self.label.setText(self.tr("Find:"))
        self.horizontalLayout1.addWidget(self.label)
        
        self.findtextCombo = E5ClearableComboBox(self)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.findtextCombo.sizePolicy().hasHeightForWidth())
        self.findtextCombo.setSizePolicy(sizePolicy)
        self.findtextCombo.setMinimumSize(QSize(100, 0))
        self.findtextCombo.setEditable(True)
        self.findtextCombo.setInsertPolicy(QComboBox.InsertAtTop)
        self.findtextCombo.setDuplicatesEnabled(False)
        self.findtextCombo.setObjectName("findtextCombo")
        self.horizontalLayout1.addWidget(self.findtextCombo)
        
        # row 2 (maybe) of widgets
        self.horizontalLayout2 = QHBoxLayout()
        self.horizontalLayout2.setObjectName("horizontalLayout2")
        
        self.caseCheckBox = QCheckBox(self)
        self.caseCheckBox.setObjectName("caseCheckBox")
        self.caseCheckBox.setText(self.tr("Match case"))
        self.horizontalLayout2.addWidget(self.caseCheckBox)
        
        self.wordCheckBox = QCheckBox(self)
        self.wordCheckBox.setObjectName("wordCheckBox")
        self.wordCheckBox.setText(self.tr("Whole word"))
        self.horizontalLayout2.addWidget(self.wordCheckBox)
        
        # layout for the navigation buttons
        self.horizontalLayout3 = QHBoxLayout()
        self.horizontalLayout3.setSpacing(0)
        self.horizontalLayout3.setObjectName("horizontalLayout3")
        
        self.findPrevButton = QToolButton(self)
        self.findPrevButton.setObjectName("findPrevButton")
        self.findPrevButton.setToolTip(self.tr(
            "Press to find the previous occurrence"))
        self.findPrevButton.setIcon(UI.PixmapCache.getIcon("1leftarrow.png"))
        self.horizontalLayout3.addWidget(self.findPrevButton)
        
        self.findNextButton = QToolButton(self)
        self.findNextButton.setObjectName("findNextButton")
        self.findNextButton.setToolTip(self.tr(
            "Press to find the next occurrence"))
        self.findNextButton.setIcon(UI.PixmapCache.getIcon("1rightarrow.png"))
        self.horizontalLayout3.addWidget(self.findNextButton)
        
        self.horizontalLayout2.addLayout(self.horizontalLayout3)
        
        # info label (in row 2 or 3)
        self.infoLabel = QLabel(self)
        self.infoLabel.setText("")
        self.infoLabel.setObjectName("infoLabel")
        
        # place everything together
        self.verticalLayout.addLayout(self.horizontalLayout1)
        self.__addWidthForHeightLayout(widthForHeight)
        self.verticalLayout.addWidget(self.infoLabel)
        
        QMetaObject.connectSlotsByName(self)
        
        self.setTabOrder(self.findtextCombo, self.caseCheckBox)
        self.setTabOrder(self.caseCheckBox, self.wordCheckBox)
        self.setTabOrder(self.wordCheckBox, self.findPrevButton)
        self.setTabOrder(self.findPrevButton, self.findNextButton)
    
    def setWidthForHeight(self, widthForHeight):
        """
        Public method to set the 'width for height'.
        
        @param widthForHeight flag indicating to prefer width
        @type bool
        """
        if self.__widthForHeight:
            self.horizontalLayout1.takeAt(self.__widthForHeightLayoutIndex)
        else:
            self.verticalLayout.takeAt(self.__widthForHeightLayoutIndex)
        self.__addWidthForHeightLayout(widthForHeight)
    
    def __addWidthForHeightLayout(self, widthForHeight):
        """
        Private method to set the middle part of the layout.
        
        @param widthForHeight flag indicating to prefer width
        @type bool
        """
        if widthForHeight:
            self.horizontalLayout1.addLayout(self.horizontalLayout2)
            self.__widthForHeightLayoutIndex = 2
        else:
            self.verticalLayout.insertLayout(1, self.horizontalLayout2)
            self.__widthForHeightLayoutIndex = 1
        
        self.__widthForHeight = widthForHeight
    
    def attachTextEdit(self, textedit, editType="QTextEdit"):
        """
        Public method to attach a QTextEdit widget.
        
        @param textedit reference to the edit widget to be attached
        @type QTextEdit, QWebEngineView or QWebView
        @param editType type of the attached edit widget
        @type str (one of "QTextEdit", "QWebEngineView" or "QWebView")
        """
        assert editType in ["QTextEdit", "QWebEngineView", "QWebView"]
        
        self.__textedit = textedit
        self.__texteditType = editType
        
        self.wordCheckBox.setVisible(editType == "QTextEdit")
    
    def keyPressEvent(self, event):
        """
        Protected slot to handle key press events.
        
        @param event reference to the key press event (QKeyEvent)
        """
        if self.__textedit and event.key() == Qt.Key_Escape:
            self.__textedit.setFocus(Qt.ActiveWindowFocusReason)
            event.accept()
    
    @pyqtSlot(str)
    def on_findtextCombo_editTextChanged(self, txt):
        """
        Private slot to enable/disable the find buttons.
        
        @param txt text of the combobox (string)
        """
        self.__setSearchButtons(txt != "")
        
        self.infoLabel.hide()
        self.__setFindtextComboBackground(False)
    
    def __setSearchButtons(self, enabled):
        """
        Private slot to set the state of the search buttons.
        
        @param enabled flag indicating the state (boolean)
        """
        self.findPrevButton.setEnabled(enabled)
        self.findNextButton.setEnabled(enabled)
    
    def __findByReturnPressed(self):
        """
        Private slot to handle the returnPressed signal of the findtext
        combobox.
        """
        self.__find(self.__findBackwards)
    
    @pyqtSlot()
    def on_findPrevButton_clicked(self):
        """
        Private slot to find the previous occurrence.
        """
        self.__find(True)
    
    @pyqtSlot()
    def on_findNextButton_clicked(self):
        """
        Private slot to find the next occurrence.
        """
        self.__find(False)
    
    def __find(self, backwards):
        """
        Private method to search the associated text edit.
        
        @param backwards flag indicating a backwards search (boolean)
        """
        if not self.__textedit:
            return
        
        self.infoLabel.clear()
        self.infoLabel.hide()
        self.__setFindtextComboBackground(False)
        
        txt = self.findtextCombo.currentText()
        if not txt:
            return
        self.__findBackwards = backwards
        
        # This moves any previous occurrence of this statement to the head
        # of the list and updates the combobox
        if txt in self.findHistory:
            self.findHistory.remove(txt)
        self.findHistory.insert(0, txt)
        self.findtextCombo.clear()
        self.findtextCombo.addItems(self.findHistory)
        
        if self.__texteditType == "QTextEdit":
            ok = self.__findPrevNextQTextEdit(backwards)
            self.__findNextPrevCallback(ok)
        elif self.__texteditType == "QWebEngineView":
            self.__findPrevNextQWebEngineView(backwards)
    
    def __findPrevNextQTextEdit(self, backwards):
        """
        Private method to to search the associated edit widget of
        type QTextEdit.
        
        @param backwards flag indicating a backwards search
        @type bool
        @return flag indicating the search result
        @rtype bool
        """
        if backwards:
            flags = QTextDocument.FindFlags(QTextDocument.FindBackward)
        else:
            flags = QTextDocument.FindFlags()
        if self.caseCheckBox.isChecked():
            flags |= QTextDocument.FindCaseSensitively
        if self.wordCheckBox.isChecked():
            flags |= QTextDocument.FindWholeWords
        
        ok = self.__textedit.find(self.findtextCombo.currentText(), flags)
        if not ok:
            # wrap around once
            cursor = self.__textedit.textCursor()
            if backwards:
                moveOp = QTextCursor.End        # move to end of document
            else:
                moveOp = QTextCursor.Start      # move to start of document
            cursor.movePosition(moveOp)
            self.__textedit.setTextCursor(cursor)
            ok = self.__textedit.find(self.findtextCombo.currentText(), flags)
        
        return ok
    
    def __findPrevNextQWebEngineView(self, backwards):
        """
        Private method to to search the associated edit widget of
        type QWebEngineView.
        
        @param backwards flag indicating a backwards search
        @type bool
        """
        from PyQt5.QtWebEngineWidgets import QWebEnginePage
        
        findFlags = QWebEnginePage.FindFlags()
        if self.caseCheckBox.isChecked():
            findFlags |= QWebEnginePage.FindCaseSensitively
        if backwards:
            findFlags |= QWebEnginePage.FindBackward
        self.__textedit.findText(self.findtextCombo.currentText(),
                                 findFlags, self.__findNextPrevCallback)
    
    def __findNextPrevCallback(self, found):
        """
        Private method to process the result of the last search.
        
        @param found flag indicating if the last search succeeded
        @type bool
        """
        if not found:
            txt = self.findtextCombo.currentText()
            self.infoLabel.setText(
                self.tr("'{0}' was not found.").format(txt))
            self.infoLabel.show()
            self.__setFindtextComboBackground(True)
    
    def __setFindtextComboBackground(self, error):
        """
        Private slot to change the findtext combo background to indicate
        errors.
        
        @param error flag indicating an error condition (boolean)
        """
        le = self.findtextCombo.lineEdit()
        p = le.palette()
        if error:
            p.setBrush(QPalette.Base, QBrush(QColor("#FF6666")))
            p.setBrush(QPalette.Text, QBrush(QColor("#000000")))
        else:
            p.setBrush(QPalette.Base, self.__defaultBaseColor)
            p.setBrush(QPalette.Text, self.__defaultTextColor)
        le.setPalette(p)
        le.update()
コード例 #16
0
ファイル: lines.py プロジェクト: GrammarGuru/Sentence
class Lines(Window):
    def __init__(self, reset_func=None):
        super().__init__()
        self.size = 0
        self.reset_func = reset_func
        self.layout = QVBoxLayout()
        self.lines = []

        for i in range(10):
            self.add_line()

        layout = self.get_layout()

        add_btn = create_control_btn('Add', self.add_line)
        clear_btn = create_control_btn('Reset', self.reset)
        fill_layout(layout, add_btn, clear_btn)

    def get_layout(self):
        container = QWidget()
        container.setLayout(self.layout)
        scroll = create_scroll_area(container)

        layout = QVBoxLayout(self)
        self.setLayout(layout)
        layout.addWidget(scroll)
        return layout

    def add_line(self):
        hbox = QHBoxLayout()

        box = create_text_box()
        self.lines.append(box)
        btn = create_remove_btn(lambda: self.remove_line(hbox, box, btn))

        index = self.size
        fill_layout(hbox, box, btn)
        self.layout.insertLayout(index, hbox)
        self.size += 1

    def reset(self):
        for line in self.lines:
            line.setText('')
        if self.reset_func is not None:
            self.reset_func()

    def fill(self, lines):
        index = 0
        for line in self.lines:
            if index == len(lines):
                return
            if not line.toPlainText():
                line.setText(lines[index])
                index += 1

    def remove_line(self, line, box, btn):
        box.deleteLater()
        btn.deleteLater()
        line.deleteLater()
        del self.lines[self.lines.index(box)]
        self.size -= 1

    def get_data(self):
        result = []
        for line in self.lines:
            text = line.toPlainText()
            if text:
                result.append(text)
        return result
コード例 #17
0
class MainWindow(QWidget):
    
	def __init__(self, inList):
		super().__init__()
		self.inList = inList
		self.nameFrom = 'Folder'
		self.codec = 'utvideo'
		self.alpha = False
		self.frameRate = 24
		self.defaulStyle = ''
		
		self.okIcon = QIcon(self.style().standardIcon(QStyle.SP_CustomBase))
		self.okPix = QPixmap(self.okIcon.pixmap(QSize(13, 13)))
		self.goodIcon = QIcon(self.style().standardIcon(QStyle.SP_DialogApplyButton))
		self.goodPix = QPixmap(self.goodIcon.pixmap(QSize(13, 13)))
		self.badIcon = QIcon(self.style().standardIcon(QStyle.SP_MessageBoxCritical))
		self.badPix = QPixmap(self.badIcon.pixmap(QSize(13, 13)))
		self.processingIcon = QIcon(self.style().standardIcon(QStyle.SP_ArrowRight))
		self.processingPix = QPixmap(self.processingIcon.pixmap(QSize(13, 13)))
		self.removeIcon = QIcon(self.style().standardIcon(QStyle.SP_DockWidgetCloseButton))
		self.removePix = QPixmap(self.removeIcon.pixmap(QSize(19, 19)))
		self.folderIcon = QIcon(self.style().standardIcon(QStyle.SP_FileDialogNewFolder))
		self.folderPix = QPixmap(self.folderIcon.pixmap(QSize(19, 19)))
		
		self.pbList = []
		self.chList = []
		self.lblList = []
		self.rmbList = []
		#self.newFolders = []
		self.initUI()

	def initUI(self):
		self.resize(720, 300)
		self.setWindowTitle('FFMpeg Python Compressor')
		self.verticalLayout = QVBoxLayout(self)
		self.verticalLayout.setContentsMargins(11, 11, 11, 11)
		self.verticalLayout.setSpacing(11)
		
		#COMBOBOX LABELS
		self.gridLayoutControlls = QGridLayout()
		self.codecLabel = QLabel('Codec', self)
		self.codecLabel.setMinimumHeight(13)
		self.alphaLabel = QLabel('Alpha' , self)
		self.alphaLabel.setMinimumHeight(13)
		self.frameRateLabel = QLabel('Frame Rate' , self)
		self.frameRateLabel.setMinimumHeight(13)
		self.gridLayoutControlls.addWidget(self.codecLabel, 0, 0, 1, 1)
		self.gridLayoutControlls.addWidget(self.alphaLabel, 0, 1, 1, 1)
		self.gridLayoutControlls.addWidget(self.frameRateLabel, 0, 2, 1, 1)
		
		#COMBOBOXES AND COMPRESS BUTTON
		self.codecComboBox = QComboBox(self)
		self.codecComboBox.setMinimumSize(80,23)
		self.codecComboBox.addItem("UT Video")
		self.codecComboBox.activated[str].connect(self.chooseCodec)
		
		self.alphaComboBox = QComboBox(self)
		self.alphaComboBox.setMinimumSize(80,23)
		self.alphaComboBox.addItem("No Alpha")
		self.alphaComboBox.addItem("with Alpha")
		self.alphaComboBox.activated[str].connect(self.chooseAlpha)
		
		self.frameRateComboBox = QComboBox(self)
		self.frameRateComboBox.setMinimumSize(80,23)
		self.frameRateComboBox.addItem("23.976")
		self.frameRateComboBox.addItem("24.00")
		self.frameRateComboBox.addItem("29.97")
		self.frameRateComboBox.addItem("30.00")
		self.frameRateComboBox.setCurrentIndex(1)
		self.frameRateComboBox.activated[str].connect(self.chooseFrameRate)
		
		self.compressButton = QPushButton('Compress', self)
		self.compressButton.setMinimumSize(80,23)
		self.compressButton.clicked[bool].connect(self.compressPress)
			
		self.gridLayoutControlls.addWidget(self.codecComboBox, 1, 0, 1, 1)
		self.gridLayoutControlls.addWidget(self.alphaComboBox, 1, 1, 1, 1)
		self.gridLayoutControlls.addWidget(self.frameRateComboBox, 1, 2, 1, 1)
		self.gridLayoutControlls.addWidget(self.compressButton, 1, 3, 1, 1)
			
		#RADIO BUTTON GROUP
		self.groupBox = QButtonGroup(self)
		self.radio1 = QRadioButton('Output file name from Folder name', self)
		self.radio1.setMinimumSize(80,25)
		self.radio2 = QRadioButton('Output file name from File name', self)
		self.radio2.setMinimumSize(80,25)
		self.radio1.setChecked(True)
		self.groupBox.addButton(self.radio1,1)
		self.groupBox.addButton(self.radio2,2)
		self.groupBox.buttonClicked[int].connect(self.radioBtnState)
		
		self.gridLayoutControlls.addWidget(self.radio1, 2, 0, 1, 2)
		self.gridLayoutControlls.addWidget(self.radio2, 2, 2, 1, 2)
		
		#LINE
		self.line = QFrame(self)
		self.line.setLineWidth(2)
		self.line.setMinimumHeight(3)
		self.line.setFrameShape(QFrame.HLine)
		self.line.setFrameShadow(QFrame.Sunken)
		
		self.gridLayoutControlls.addWidget(self.line, 3, 0, 1, 4)
		
		#PROGRESS BAR 
		self.gridLayoutProgress = QGridLayout()
		self.gridLayoutProgress.setVerticalSpacing(11)
		self.gridLayoutProgress.setHorizontalSpacing(6)
		self.gridLayoutProgress.setSizeConstraint(QLayout.SetNoConstraint)
		
		self.removeGroupBox = QButtonGroup(self)
		self.addProgressBarUI(self.inList)			
		self.removeGroupBox.buttonClicked[int].connect(self.removeButtonClicked)

		#ADD MORE AREA
		self.gridLayoutAddMore = QGridLayout()
		self.gridLayoutAddMore.setContentsMargins(0, 0, 0, 0)
		
		self.dragAndDropLabel_1 = QLabel("Drag and Drop folders here", self)
		self.dragAndDropLabel_1.setMinimumSize(QSize(120, 40))
		self.dragAndDropLabel_1.setAlignment(Qt.AlignCenter)
		
		self.dragAndDropLabel_2 = QLabel("", self)
		self.dragAndDropLabel_2.setFixedSize(QSize(20, 40))
		self.dragAndDropLabel_2.setAlignment(Qt.AlignCenter)
		self.dragAndDropLabel_2.setPixmap(self.folderPix)
		
		sI = QSpacerItem(40, 40,QSizePolicy.Expanding, QSizePolicy.Minimum)
		sI2 = QSpacerItem(40, 40,QSizePolicy.Expanding, QSizePolicy.Minimum)
		
		self.gridLayoutAddMore.addItem(sI, 1, 0, 1, 1)
		self.gridLayoutAddMore.addWidget(self.dragAndDropLabel_2, 1, 1, 1, 1)
		self.gridLayoutAddMore.addWidget(self.dragAndDropLabel_1, 1, 2, 1, 1)
		self.gridLayoutAddMore.addItem(sI2, 1, 3, 1, 1)
		
		#DEBUG AREA
		self.gridLayoutDebug = QGridLayout()
		self.line_2 = QFrame(self)
		self.line_2.setLineWidth(2)
		self.line_2.setFrameShape(QFrame.HLine)
		self.line_2.setFrameShadow(QFrame.Sunken)
		
		self.exploreOutputBtn = QPushButton('Explore Output',self)
		self.exploreOutputBtn.clicked[bool].connect(self.exploreOutput)

		self.hideShowLog = QPushButton('Show Log',self)
		self.hideShowLog.setCheckable(True)
		self.hideShowLog.clicked[bool].connect(self.showDebugLog)
		#self.hideShowLog.setMinimumSize(QSize(0, 20))
		
		self.logText = QPlainTextEdit('',self)
		self.logText.setReadOnly(True)
		self.logText.hide()
		
		self.spacerItem = QSpacerItem(20, 0, QSizePolicy.Minimum, QSizePolicy.Expanding)
		
		self.gridLayoutDebug.addWidget(self.line_2, 0, 0, 1, 1)
		self.gridLayoutDebug.addWidget(self.exploreOutputBtn, 1, 0, 1, 1)
		self.gridLayoutDebug.addWidget(self.hideShowLog, 2, 0, 1, 1)
		self.gridLayoutDebug.addWidget(self.logText, 3, 0, 1, 1)
		self.gridLayoutDebug.addItem(self.spacerItem, 4, 0, 1, 1)
		
		self.verticalLayout.addLayout(self.gridLayoutControlls)
		self.verticalLayout.addLayout(self.gridLayoutProgress)
		self.verticalLayout.addLayout(self.gridLayoutAddMore)
		self.verticalLayout.addLayout(self.gridLayoutDebug)
		
		# Enable dragging and dropping onto the GUI
		self.setAcceptDrops(True)
		
		#QtCore.QMetaObject.connectSlotsByName(self)
		self.show()
		self.setMinimumSize(self.size())
		
		self.threadpool = QThreadPool()
		self.threadpool.setMaxThreadCount(1)
		print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())
    
	
	
	'''
	Progress bar populate function
	'''
	def addProgressBarUI(self, arr):
		pbCount = len(self.pbList)
		for i in range(len(arr)):
			tempCheckBox = QCheckBox(self)
			tempCheckBox.setChecked(True)
			tempCheckBox.setMinimumSize(14,21)
			
			tempRemoveButton = QPushButton(self)
			tempRemoveButton.setIcon(self.removeIcon)
			tempRemoveButton.setFlat(True)
			tempRemoveButton.setIconSize(QSize(19,19))
			tempRemoveButton.setFixedSize(QSize(19,21))
			
			
			tempPB = QProgressBar(self)
			tempPB.setMinimumSize(50,21)
			tempPB.setMinimum(0)
			tempPB.setMaximum(100)
			tempPB.setTextVisible(True)
			tempPB.setFormat(str(arr[i])+" %p%")
			tempPB.setAlignment(Qt.AlignCenter)
			tempPB.setValue(0)
			if i==0:
				self.defaulStyle = tempPB.styleSheet()
			
			tempStatusLabel = QLabel(self)			
			tempStatusLabel.setPixmap(self.okPix)
			tempStatusLabel.setMinimumSize(13,21)
			
			self.gridLayoutProgress.addWidget(tempCheckBox, pbCount+i, 0, 1, 1)
			self.gridLayoutProgress.addWidget(tempPB, pbCount+i, 1, 1, 1)
			self.gridLayoutProgress.addWidget(tempStatusLabel, pbCount+i, 2, 1, 1)
			self.gridLayoutProgress.addWidget(tempRemoveButton, pbCount+i, 3, 1, 1)
			self.removeGroupBox.addButton(tempRemoveButton, pbCount+i)
			
			self.pbList.append(tempPB)
			self.chList.append(tempCheckBox)
			self.lblList.append(tempStatusLabel)
			self.rmbList.append(tempRemoveButton)
	
		
	'''
	Drag+Drop Functions
	'''
	# The following three methods set up dragging and dropping for the app
	def dragEnterEvent(self, e):
		if e.mimeData().hasUrls:
			e.accept()
		else:
			e.ignore()

	def dragMoveEvent(self, e):
		if e.mimeData().hasUrls:
			e.accept()
		else:
			e.ignore()

	def dropEvent(self, e):
		"""
		Drop files directly onto the widget
		File locations are stored in fname
		:param e:
		:return:
		"""
		newFolders = []
		if e.mimeData().hasUrls:
			e.setDropAction(Qt.CopyAction)
			e.accept()
			# Workaround for OSx dragging and dropping
			for url in e.mimeData().urls():
				if op_sys == 'Darwin':
					#check for dir here as well
					fname = str(NSURL.URLWithString_(str(url.toString())).filePathURL().path())
				else:
					fname = str(url.toLocalFile())
					if os.path.isdir(fname) == True:
						newFolders.append(fname)
					#print(fname)

			#self.fname = fname
			#print(self.fname)
			#self.load_image()
			self.addNewFolders(newFolders)
			self.inList = self.inList + newFolders
		else:
			e.ignore()
	

	def addNewFolders(self, newFolders):
		self.addProgressBarUI(newFolders)
		self.setMinimumHeight(self.height()+len(newFolders)*32)
		#self.resize(self.width(),self.height()+200)
		self.update()
		self.adjustSize()
		self.setMinimumSize(self.size())
	'''
	Button Functions
	'''
	def chooseAlpha(self, text):
		switcher={
			"No Alpha":False,
			"with Alpha":True
		}
		self.alpha = switcher.get(text,"Invalid day of week")
		#print (self.alpha)

	def chooseCodec(self, text):
		switcher={
			"UT Video":"utvideo"
		}
		self.codec =  switcher.get(text,"Invalid day of week")
		#print (self.codec)
		
	def chooseFrameRate(self, text):
		self.frameRate =  float(text)
		#print (self.frameRate)
	
	
	def currentData(self, widget):
		return widget.currentText() 

	def radioBtnState(self, text):
		switcher={
			1:'Folder',
			2:'File'
		}
		self.nameFrom = switcher.get(text,"Invalid day of week")
		#print(self.nameFrom)
	
	def removeButtonClicked(self, i):
		#print('remove trigger on id '+str(i))
		
		#self.pbList.pop(i)
		'''
		self.pbList[i].hide()
		self.chList[i].setChecked(False)
		self.chList[i].hide()
		self.lblList[i].hide()
		self.rmbList[i].hide()
		'''
		print(self.gridLayoutProgress.rowCount())
		self.pbList[i].setParent(None)
		self.chList[i].setChecked(False)
		self.chList[i].setParent(None)
		self.lblList[i].setParent(None)
		self.rmbList[i].setParent(None)
		
		self.removeGroupBox.removeButton(self.rmbList[i])

		self.gridLayoutProgress.removeWidget(self.pbList[i])
		self.gridLayoutProgress.removeWidget(self.chList[i])
		self.gridLayoutProgress.removeWidget(self.lblList[i])
		self.gridLayoutProgress.removeWidget(self.rmbList[i])
		self.gridLayoutProgress.invalidate()
		self.gridLayoutProgress = QGridLayout()
		self.gridLayoutProgress.setVerticalSpacing(11)
		self.gridLayoutProgress.setHorizontalSpacing(6)
		self.gridLayoutProgress.setSizeConstraint(QLayout.SetDefaultConstraint)
		self.verticalLayout.insertLayout(1,self.gridLayoutProgress)
		
		print(self.gridLayoutProgress.rowCount())
		'''
		print(self.pbList)
		print(self.chList)
		print(self.lblList)
		print(self.rmbList)
		'''
		
		self.pbList.pop(i)
		self.chList.pop(i)
		self.lblList.pop(i)
		self.rmbList.pop(i)
		self.inList.pop(i)		
		

		#clear the gridLayout
		for j in reversed(range(len(self.pbList))):
			self.pbList[j].setParent(None)
			self.chList[j].setParent(None)
			self.lblList[j].setParent(None)
			self.rmbList[j].setParent(None)
		
		
		#reorder the gridLayout
		for j in range(len(self.pbList)):
			self.gridLayoutProgress.addWidget(self.chList[j], j, 0, 1, 1)
			self.gridLayoutProgress.addWidget(self.pbList[j], j, 1, 1, 1)
			self.gridLayoutProgress.addWidget(self.lblList[j], j, 2, 1, 1)
			self.gridLayoutProgress.addWidget(self.rmbList[j], j, 3, 1, 1)
			self.removeGroupBox.setId(self.rmbList[j],j)

		
		
		self.setMinimumHeight(self.height()-30)
		#self.setMinimumHeight(100)
		self.adjustSize()
		self.setMinimumSize(self.size())
		print(self.gridLayoutProgress.rowCount())
		#self.correctSize()
		'''
		for j in range(len(self.removeGroupBox.buttons())):
			button = self.removeGroupBox.buttons()[j]
			#print(button)
			#print('original id '+str(self.removeGroupBox.id(button)))
			#print('new id '+str(j))
			self.removeGroupBox.setId(button,j)
		'''
	
	def correctSize(self):
			self.logText.show()
			self.gridLayoutDebug.removeItem(self.spacerItem)
			self.adjustSize()
			self.setMinimumSize(self.size())
			self.repaint()
			self.gridLayoutDebug.addItem(self.spacerItem)
			self.logText.hide()
			self.setMinimumHeight(100)
			self.adjustSize()
			self.setMinimumSize(self.size())
	
	def showDebugLog(self, bol):
		if bol:
			self.logText.show()
			self.hideShowLog.setText('Hide Log')
			self.gridLayoutDebug.removeItem(self.spacerItem)
			self.adjustSize()
			#self.resize(self.width(), self.height()+80)
			self.setMinimumSize(self.size())
		else:
			self.gridLayoutDebug.addItem(self.spacerItem)
			self.logText.hide()
			self.hideShowLog.setText('Show Log')
			self.setMinimumHeight(100)
			self.adjustSize()
			self.setMinimumSize(self.size())
			#self.resize(self.width(), 100)
			#self.setGeometry(0,0,self.width(),100)
	
	'''
	Execution Functions
	'''
	def execute_this_fn(self, path, codec, alpha, frameRate, nameFrom, i, progress_callback, errorFFMPEG_callback):
		#print(path)
		pyCompression = pyFFMEGCompress(path, codec, alpha, frameRate, nameFrom)
		ffProcess = pyCompression.ffmpegCompress()
		self.lblList[i].setPixmap(self.processingPix)
		
		#with kwargs
		kwargs = {'progress_callback':progress_callback, 'errorFFMPEG_callback':errorFFMPEG_callback}
		pyCompression.printProcess(ffProcess, **kwargs)

		return (pyCompression.debugString,pyCompression.error,i)
 
	def printOutput(self, s):
		print("Printing output "+ str(s))
		
	def threadComplete(self, r):
		#print("THREAD COMPLETE! WITH ERROR " + str(r[2]) )
		if r[1] == False:
			self.lblList[r[2]].setPixmap(self.goodPix)
			self.pbList[r[2]].setStyleSheet("QProgressBar::chunk {background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #44dd14,stop: 0.4999 #39c10f,stop: 0.5 #39c10f,stop: 1 #39c10f );border-radius: 3px; border: 1px solid #29880b;}QProgressBar{color:white}")
			self.pbList[r[2]].setValue(100)

	def errorPB(self, err):
		for i in range(len(self.pbList)):
			if self.pbList[i].format() == err:
				self.pbList[i].setValue(100)
				self.pbList[i].setStyleSheet("QProgressBar::chunk {background: QLinearGradient( x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #FF0350,stop: 0.4999 #FF0020,stop: 0.5 #FF0019,stop: 1 #FF0000 );border-radius: 3px; border: 1px solid #a60233;}QProgressBar{color:white}")
				self.pbList[i].setFormat(self.pbList[i].format()+" - Error")
				self.chList[i].setChecked(False)
				self.lblList[i].setPixmap(self.badPix)
				
	def resetProgressBar(self, pb, text, lbl):
		pb.setValue(0)
		pb.setFormat(text + ' %p%')
		pb.setStyleSheet(self.defaulStyle)
		lbl.setPixmap(self.okPix)
	

	def compressPress(self):
		for i in range(len(self.pbList)):				
			if self.chList[i].isChecked():
				self.resetProgressBar(self.pbList[i],self.inList[i],self.lblList[i])
				
				worker = Worker(self.execute_this_fn, self.inList[i], self.codec, self.alpha, self.frameRate, self.nameFrom, i) # Any other args, kwargs are passed to the run function
				#worker.signals.result.connect(self.printOutput)
				worker.signals.result.connect(self.logText.appendPlainText)
				worker.signals.progress.connect(self.pbList[i].setValue)
				worker.signals.errorFFMPEG.connect(self.errorPB)
				worker.signals.error.connect(self.errorPB)
				worker.signals.finished.connect(self.threadComplete)
				#worker.signals.finished.connect(self.logText.appendPlainText)
				
				# Execute
				self.threadpool.start(worker)

	def exploreOutput(self):
		FILEBROWSER_PATH = os.path.join(os.getenv('WINDIR'), 'explorer.exe')
		explorePath = os.path.normpath('C:\\ExportedMOVs')
		subprocess.run([FILEBROWSER_PATH, explorePath])
コード例 #18
0
ファイル: main.py プロジェクト: amosborne/puyo-trainer
class MainView(QMainWindow):
    select_module = pyqtSignal(str)
    new_module = pyqtSignal()
    test_module = pyqtSignal(str, int, int)
    new_puzzle = pyqtSignal(str)
    review_puzzle = pyqtSignal(str, str)
    self_compat = pyqtSignal()
    closed = pyqtSignal()

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("PuyoTrainer v1.0.0")

        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        self.layout = QVBoxLayout(main_widget)

        self._createStatusBar()
        self._createPuzzleSelector()
        self._hlineSeparator()
        self._createModuleControls()
        self._hlineSeparator()
        self._createSettingSelector()

    def closeEvent(self, event):
        self.closed.emit()
        super().closeEvent(event)

    def show(self):
        self.select_module.emit(self.module())
        return super().show()

    def setModuleMetadata(self, module):
        new_module_layout = ViewModuleFormLayout(module)

        def transfer_widget(row, col):
            widget = self.module_layout.itemAtPosition(row, col).widget()
            new_module_layout.addWidget(widget)

        transfer_widget(1, 0)
        transfer_widget(1, 1)
        transfer_widget(2, 0)
        transfer_widget(2, 1)

        deleteItemOfLayout(self.layout, 2)
        self.layout.insertLayout(2, new_module_layout)
        self.module_layout = new_module_layout

        if module is None:
            self._updatePuzzleSelector(empty=True)

    def addModuleSelector(self, modulename):
        self.module_selector.addItem(modulename, userData=modulename)

    def _createStatusBar(self):
        status_bar = QStatusBar()

        def addLink(link, text):
            label = QLabel('<a href="' + link + '">' + text + "</a>")
            label.setOpenExternalLinks(True)
            status_bar.addWidget(label)

        addLink(link="https://twitter.com/terramyst1", text="by terramyst, ")
        addLink(link="https://github.com/amosborne/puyo-trainer",
                text="github.")

        status_bar.addWidget(
            QLabel("(keyboard usage: arrow keys, x, z, spacebar)"))

        self.setStatusBar(status_bar)

    def _hlineSeparator(self):
        hline = QFrame()
        hline.setFrameShape(QFrame.HLine)
        self.layout.addWidget(hline)

    def _createSettingSelector(self):
        sublayout = QHBoxLayout()

        skins = [f for f in os.listdir(SKIN_DIRECTORY) if f.endswith(".png")]

        label = QLabel("Puyo Skin:")
        label.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        label.setStyleSheet("font-weight: bold")

        combo_box = QComboBox()
        combo_box.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        for skin in skins:
            root, _ = os.path.splitext(skin)
            combo_box.addItem(root, userData=skin)

        sublayout.addWidget(label)
        sublayout.addWidget(combo_box)
        self.skin = combo_box.currentData

        label = QLabel("Test Moves:")
        label.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        label.setStyleSheet("font-weight: bold")

        combo_box = QComboBox()
        combo_box.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        for val in range(1, 11):
            combo_box.addItem(str(val), userData=val)

        sublayout.addWidget(label)
        sublayout.addWidget(combo_box)
        self.movelen = combo_box.currentData

        label = QLabel("Test Period:")
        label.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        label.setStyleSheet("font-weight: bold")

        combo_box = QComboBox()
        combo_box.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        for val in range(1, 11):
            combo_box.addItem(str(val), userData=val)

        sublayout.addWidget(label)
        sublayout.addWidget(combo_box)
        self.fbdelay = combo_box.currentData

        self.layout.addLayout(sublayout)

    def _createPuzzleSelector(self):

        modlabel = QLabel("Module:")
        modlabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        modlabel.setStyleSheet("font-weight: bold")

        modcombo = QComboBox()
        modcombo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        modules = [
            d for d in os.listdir(MODULE_DIRECTORY)
            if os.path.isdir(os.path.join(MODULE_DIRECTORY, d))
        ]
        for module in modules:
            modcombo.addItem(module, userData=module)

        self.module = modcombo.currentData

        def module_select():
            self._updatePuzzleSelector()
            self.select_module.emit(self.module())

        modcombo.currentIndexChanged.connect(module_select)
        self.module_selector = modcombo

        puzlabel = QLabel("Puzzle:")
        puzlabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        puzlabel.setStyleSheet("font-weight: bold")

        puzcombo = QComboBox()
        puzcombo.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        self.puzzle = puzcombo.currentData
        self.puzzle_selector = puzcombo

        self._updatePuzzleSelector()

        self.selfcompat_button = QPushButton("Self-Compat")
        self.selfcompat_button.clicked.connect(self.self_compat)

        puzzle_select_layout = QHBoxLayout()
        puzzle_select_layout.addWidget(modlabel)
        puzzle_select_layout.addWidget(modcombo)
        puzzle_select_layout.addWidget(puzlabel)
        puzzle_select_layout.addWidget(puzcombo)
        puzzle_select_layout.addWidget(self.selfcompat_button)
        self.layout.addLayout(puzzle_select_layout)

    def setCompatStatus(self, isactive):
        if isactive:
            self.selfcompat_button.setStyleSheet("font: bold; color: red")
        else:
            self.selfcompat_button.setStyleSheet("font: bold; color: blue")

    def _updatePuzzleSelector(self, empty=False):
        self.puzzle_selector.clear()
        if empty or self.module() is None:
            return

        _, _, filenames = next(os.walk(MODULE_DIRECTORY + self.module()))
        puzzle_files = [
            filename for filename in filenames
            if filename.startswith(PUZZLE_FILE_ROOT)
            and filename.endswith(PUZZLE_FILE_EXT)
        ]
        for filename in sorted(puzzle_files):
            root, _ = os.path.splitext(filename)
            self.puzzle_selector.addItem(root, userData=root)

    def _createModuleControls(self):
        new_module_button = QPushButton("New Module")
        new_module_button.clicked.connect(lambda: self.new_module.emit())
        new_module_button.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Expanding)

        test_module_button = QPushButton("Test Module")
        test_module_button.clicked.connect(lambda: self.test_module.emit(
            self.skin(), self.movelen(), self.fbdelay()))
        test_module_button.setSizePolicy(QSizePolicy.Expanding,
                                         QSizePolicy.Expanding)

        new_puzzle_button = QPushButton("New Puzzle")
        new_puzzle_button.clicked.connect(
            lambda: self.new_puzzle.emit(self.skin()))
        new_puzzle_button.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Expanding)

        review_puzzle_button = QPushButton("Review Puzzle")
        review_puzzle_button.clicked.connect(
            lambda: self.review_puzzle.emit(self.skin(), self.puzzle()))
        review_puzzle_button.setSizePolicy(QSizePolicy.Expanding,
                                           QSizePolicy.Expanding)

        module_control_layout = ViewModuleFormLayout()
        module_control_layout.addWidget(new_module_button, 1, 0)
        module_control_layout.addWidget(test_module_button, 1, 1)
        module_control_layout.addWidget(new_puzzle_button, 2, 0)
        module_control_layout.addWidget(review_puzzle_button, 2, 1)
        self.layout.addLayout(module_control_layout)

        self.module_layout = module_control_layout
コード例 #19
0
class MemoryGui(QWidget):
    def __init__(self, parent=None):
        super(MemoryGui, self).__init__(parent)
        self.title = "Memory Game"
        self.left = 200
        self.top = 100
        self.width = 500
        self.height = 300
        self.initialize_match_settings()
        self.initUI()

    def initUI(self):
        #create widgets
        self.current_playing_player = QLabel("Current playing player: "+str(get_game_setting("player_one_name")))
        self.player_one_score = QLabel("Player: "+str(get_game_setting("player_one_name"))+", score: "+str(self.memory_match.get_player_one_score()))
        self.player_two_score = QLabel("Player: "+str(get_game_setting("player_two_name"))+", score: "+str(self.memory_match.get_player_two_score()))
        self.next_turn_button = QPushButton("Next turn")
        self.next_turn_button.setEnabled(False)
        self.next_turn_button.clicked.connect(self.next_turn)
        self.go_back_to_setup_button = QPushButton("Go to Setup")

        self.finished_game_message = QMessageBox()
        self.finished_game_message.setWindowTitle("The memory game is finished")
        self.finished_game_message.setText("")
        self.finished_game_message.setStandardButtons(QMessageBox.Ok)

        horizontal_go_back_to_setup_box = QHBoxLayout()
        horizontal_go_back_to_setup_box.addWidget(self.go_back_to_setup_button)
        horizontal_go_back_to_setup_box.addStretch()

        self.grid = self.create_playfield()
        horizontal_playing_player_box = QHBoxLayout()
        horizontal_playing_player_box.addWidget(self.current_playing_player)
        horizontal_playing_player_box.addStretch()
        horizontal_playing_player_box.addWidget(self.next_turn_button)

        horizontal_player_scores_box = QHBoxLayout()
        horizontal_player_scores_box.addWidget(self.player_one_score)
        horizontal_player_scores_box.addStretch()
        horizontal_player_scores_box.addWidget(self.player_two_score)

        self.vertical_box = QVBoxLayout()
        self.vertical_box.insertLayout(1, horizontal_go_back_to_setup_box)
        self.vertical_box.insertLayout(2, self.grid)
        self.vertical_box.insertLayout(3, horizontal_playing_player_box)
        self.vertical_box.insertLayout(4, horizontal_player_scores_box)

        self.setWindowTitle(self.title)
        self.setLayout(self.vertical_box)
        self.setGeometry(self.left, self.top, self.width, self.height)

    def create_playfield(self):
        #create a matrix of buttons which will be the playing field.
        self.grid = QGridLayout()
        columns, rows = get_row_and_colum(int(get_game_setting("playfield_size")))
        positions = [(column, row) for column in range(int(columns)) for row in range(int(rows))]

        self.add_buttons_to_grid(positions)
        return self.grid
    def initialize_match_settings(self):
        #set the memory_match object with the default beginning values and initialize the playfield names
        column_count, row_count = get_row_and_colum(int(get_game_setting("playfield_size")))
        self.memory_match = MemoryMatch("player_one")
        self.registered_buttons = RegisterButtons(column_count, row_count)
        self.registered_buttons.initialize_button_dict()
        #accumulate +1 for started games.
        update_game_statistics("started_games")

    def button_pressed(self, button):
        #display the "hidden" text of the button and disable it.
        #when a button is pressed,(1) check which button it was (2) do some logic rules
        coordinates = button.text()
        hidden_name = self.registered_buttons.get_playfield_name(coordinates)
        button.setText(hidden_name)
        button.setEnabled(False)
        print("Button: "+coordinates+" was pressed")
        #accumulate the turn and save the guess of the player.
        self.memory_match.accumulate_turn()
        self.memory_match.save_clicked_button(coordinates, hidden_name)
        #check if the current player has chosen two cards
        if is_turn_over(self.memory_match.get_turn()) == False:
            #the turn is not over
            return
        else:
            #the turn is over. Disable all buttons and check if the player has guessed correctly.
            self.disable_all_buttons()
            self.process_turn()
            self.has_game_ended()


    def process_turn(self):
        #did the player guess two cards correctly or did he not?
        first_clicked_button = self.memory_match.get_clicked_buttons()[0]
        second_clicked_button = self.memory_match.get_clicked_buttons()[1]
        if first_clicked_button["card_name"] == second_clicked_button["card_name"]:
            #the guess was correct :-)
            print("The current player guessed two cards correctly. ")
            #add a point to the current player
            self.accumulate_point_to_current_player()
            #Make the correctly guessed buttons no longer clickable.
            self.registered_buttons.set_button_status(first_clicked_button["position"], False)
            self.registered_buttons.set_button_status(second_clicked_button["position"], False)
            self.outcome = True
        else:
            #The guess was not correct :-(
            print("The current player did not guess two cards correctly. ")
            self.outcome = False
        self.next_turn_button.setEnabled(True)

    def set_original_button_text(self):
        for index in range(0, 2):
            button_index = self.memory_match.get_clicked_buttons()[index]["position"]
            self.registered_buttons.get_button_instance(button_index)["button_instance"].setText(button_index)

    def accumulate_point_to_current_player(self):
        if self.memory_match.get_current_player() == "player_one":
            self.memory_match.accumulate_player_one_score()
            self.player_one_score.setText("Player: " + str(get_game_setting("player_one_name")) + ", score: " + str(
                self.memory_match.get_player_one_score()))
        else:
            self.memory_match.accumulate_player_two_score()
            self.player_two_score.setText("Player: " + str(get_game_setting("player_two_name")) + ", score: " + str(
                self.memory_match.get_player_two_score()))

    def next_turn(self):
        #keep the correctly guessed buttons disabled and make everything ready for a new turn
        #disable the next_turn_button
        self.next_turn_button.setEnabled(False)
        #set the turn back to zero
        self.memory_match.set_turn_to_zero()
        #set the current player
        self.set_current_player(self.memory_match.get_current_player())
        #If the previous player did not guess correctly, the buttons are reset to there original message.
        if self.outcome == False: self.set_original_button_text()
        #remove the clicked buttons from the previous turn
        self.memory_match.remove_clicked_buttons()
        #enable the buttons for the next turn.
        self.enabled_buttons()

    def enabled_buttons(self):
        #enable the buttons which need to be enabled.
        for button in self.registered_buttons.get_button_dict().values():
            button["button_instance"].setEnabled(button["status"])
    def disable_all_buttons(self):
        for button in self.registered_buttons.get_button_dict().values():
            button["button_instance"].setEnabled(False)

    def set_current_player(self, current_player):
        if current_player == "player_one":
            #time to set the new current player to player_two
            self.memory_match.set_current_player("player_two")
            self.current_playing_player.setText("Current playing player: " + str(get_game_setting("player_two_name")))
        elif current_player == "player_two":
            #time to set the new current player to player_one
            self.memory_match.set_current_player("player_one")
            self.current_playing_player.setText("Current playing player: " + str(get_game_setting("player_one_name")))
    def has_game_ended(self):
        #check if the game has ended.
        status_list = [button["status"] for button in self.registered_buttons.get_button_dict().values()]
        if True in status_list:
            #the game has not ended yet
            return
        else:
            #the game has ended. Show a message with the game outcome.
            game_outcome = analyze_game_outcome(str(get_game_setting("player_one_name")), str(get_game_setting("player_two_name")),
                                                str(self.memory_match.get_player_one_score()),str(self.memory_match.get_player_two_score()))
            self.finished_game_message.setText(game_outcome)
            self.finished_game_message.show()

            # disable the next_turn_button
            self.next_turn_button.setEnabled(False)
            # set the turn back to zero
            self.memory_match.set_turn_to_zero()
            # remove the clicked buttons from the previous turn
            self.memory_match.remove_clicked_buttons()
            #set the scores 0 for both player_one and player_two and update the labels to this new score.
            self.memory_match.set_player_one_score_to_zero()
            self.memory_match.set_player_two_score_to_zero()
            self.player_one_score.setText("Player: "+str(get_game_setting("player_one_name"))+", score: "+str(self.memory_match.get_player_one_score()))
            self.player_two_score.setText("Player: "+str(get_game_setting("player_two_name"))+", score: "+str(self.memory_match.get_player_two_score()))
            #make player_one the first player for coming game
            self.memory_match.set_current_player("player_one")
            #Add plus one to the finished games statistic
            update_game_statistics("finished_games")
            #Refresh the contents of the buttons
            self.update_content_buttons()

    def update_content_buttons(self):
        # All buttons need to be clickable again, have a new hidden_name and have a viewable message.
        names = self.registered_buttons.get_X_different_names(self.grid.columnCount(), self.grid.rowCount())
        index = 0
        for position, button in self.registered_buttons.get_button_dict().items():
            button["status"] = True
            button["hidden_name"] = names[index]
            button["button_instance"].setText(position)
            button["button_instance"].setEnabled(True)
            index += 1

    def update_grid(self):
        current_column_count, current_row_count = get_row_and_colum(int(get_game_setting("playfield_size")))
        current_positions = [(column, row) for column in range(int(current_column_count)) for row in range(int(current_row_count))]

        self.registered_buttons.initialize_button_dict()
        self.remove_grid_buttons()
        self.add_buttons_to_grid(current_positions)

    def remove_grid_buttons(self):
        for i in reversed(range(self.grid.count())):
            widgetToRemove = self.grid.itemAt(i).widget()
            # remove it from the layout list
            self.grid.removeWidget(widgetToRemove)
            # remove it from the gui
            widgetToRemove.setParent(None)

    def add_buttons_to_grid(self, positions):
        for position in positions:
            coordinates = str(position[0])+"_"+str(position[1])
            button = QPushButton(coordinates)
            button.setFixedHeight(50)
            self.registered_buttons.set_button_instance(coordinates, button)
            self.registered_buttons.get_button_instance(coordinates)["button_instance"].clicked.connect(lambda state, button=button: self.button_pressed(button))
            self.grid.addWidget(self.registered_buttons.get_button_instance(coordinates)["button_instance"], position[0], position[1])
        print("There are "+str(self.grid.count())+" buttons/cards in the grid")
コード例 #20
0
class DangerConfEditor(ViewInfoChanger):
    def __init__(self, header, info, parent: ViewShower):
        super().__init__(header, info, parent)
        self.way_layout = QVBoxLayout()
        push_btn = self.main_layout.takeAt(self.main_layout.count() -
                                           1).widget()

        self.worker_id = info[0]
        self.slave_combo_config = {
            "название_параметра":
            ("параметры", "*", "название_параметра", "код_параметра")
        }
        self.combo_change_idx["название_параметра"] = {}
        add_btn = QPushButton("Добавить")
        add_btn.clicked.connect(lambda e: self.add_cell(-1))
        self.main_layout.addWidget(add_btn)

        way = self.db.execute(
            f"SELECT код_параметра, название_параметра, нижний_допустимый_порог, верхний_допустимый_порог FROM `подчинённые_допустимые_значения_параметров_view` where `код_категории_вредности` = {self.worker_id}"
        )
        for pos, point in enumerate(way, start=-1):
            param_name = str(point[1])
            self.combo_change_idx["название_параметра"][param_name] = point[0]
            self.add_cell(pos, param_name, point[2], point[3])

        self.main_layout.addLayout(self.way_layout)
        self.main_layout.addWidget(push_btn)

    def add_cell(self, pos: int, txt="", dnw_val="", up_val=""):
        """Вставляет ячейку ниже активирующей кнопки для вставки на уровне надо передать ::pos:: = -1"""

        cell = QHBoxLayout()
        edi = QLineEdit()
        edi.setText(txt)

        dwn_val_edt = QLineEdit()
        dwn_val_edt.setText(str(dnw_val))
        up_val_edt = QLineEdit(str(up_val))

        add_btn = QPushButton("Добавить")
        del_btn = QPushButton("Удалить")

        cmb = QComboBox()
        cmb.addItem(txt)

        edi.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        cmb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        dwn_val_edt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        up_val_edt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        add_btn.clicked.connect(lambda e, c=cell: self.add_cell(c.pos))
        del_btn.clicked.connect(lambda e, c=cell: self.del_cell(c.pos))

        edi.editingFinished.connect(
            lambda c=cmb, t=edi.text: self.slave_combo_update(
                "название_параметра", c, t()))  # le-kostyl
        cell.pos = pos
        cell.addWidget(edi)
        cell.addWidget(cmb)
        cell.addWidget(dwn_val_edt)
        cell.addWidget(up_val_edt)
        cell.addWidget(add_btn)
        cell.addWidget(del_btn)
        for i in range(pos + 1, self.way_layout.count()):
            cell_to_move = self.way_layout.itemAt(i)
            cell_to_move.pos += 1
        cell.pos += 1  # для вставки ниже активированной кнопки

        self.way_layout.insertLayout(cell.pos, cell)

    def slave_combo_update(self, c_name: str, c: QComboBox,
                           text: str):  # grand le-kostyl
        tmp = self.combo_config
        self.combo_config = self.slave_combo_config
        self.combo_update(c_name, c, text)
        self.combo_config = tmp

    def del_cell(self, pos):
        cell: QVBoxLayout
        cell = self.way_layout.takeAt(pos)
        for i in range(cell.count()):
            w = cell.takeAt(0).widget()
            w.deleteLater()
        cell.deleteLater()

        for i in range(pos, self.way_layout.count()):
            cell_to_move = self.way_layout.itemAt(i)
            cell_to_move.pos -= 1

    def push_slave_changes(self):
        params = []
        kakoito_set = set()
        try:
            for i in range(self.way_layout.count()):
                cell = self.way_layout.itemAt(i)
                w = cell.itemAt(1).widget()
                param = w.currentText()
                if param:
                    if param in kakoito_set:
                        raise KeyError
                    kakoito_set.add(param)
                    param_id = self.combo_change_idx["название_параметра"][
                        param]
                    dwn_w = cell.itemAt(2).widget()
                    up_w = cell.itemAt(3).widget()
                    dwn_val = dwn_w.text()
                    up_val = up_w.text()
                    if not dwn_val:
                        dwn_val = 0
                    if not up_val:
                        up_val = 0
                    params.append((self.worker_id, param_id, dwn_val, up_val))

            query = f" insert into `допустимые_значения_параметров` values(%s, %s, %s, %s)"
            self.db.execute(
                "delete from `допустимые_значения_параметров` where код_категории_вредности = %s",
                (self.worker_id, ))
            self.db.executemany(query, params)
            self.db.commit()
        except KeyError as er:
            from PyQt5.QtWidgets import QErrorMessage
            error_widget = QErrorMessage()
            error_widget.showMessage(f"Дубликат параметра")
            error_widget.exec()

    def push_changes(self):
        self.push_slave_changes()
        super().push_changes()
class PowerBIThemeGeneratorWindow(QMainWindow):

    _powerBIThemeGenerator = None
    _pbiFilePath = None
    _horizontalLayoutTabVisualsTop = None
    _horizontalLayoutWelcomeScreen = None
    _groupBoxSelectedVisualPropertiesTree = None
    _listWidgetReportPages = None
    _listWidgetReportPageVisuals = None
    _verticalLayoutVisualsPropertiesTab = None
    _verticalLayoutMainWindow = None
    _treeWidgetSelectedVisualProperties = None
    _tabWidgetMainWindow = None
    _tabGeneralProperties = None
    _generalProperties = {}

    def __init__(self):

        super().__init__()

        # Windows Settings
        self.setWindowTitle(AppInfo.Name + ' - ' + AppInfo.Version)
        self.setGeometry(100, 100, 960, 720)

        # Creating central widget element
        self.centralWidget = QWidget(self)
        self.setCentralWidget(self.centralWidget)

        # Creating status bar
        self.statusBar = QStatusBar(self)
        self.setStatusBar(self.statusBar)

        # Creating menu bar
        self._createMenuBar()

        # Creating main window layout and adding widgets to them
        self._verticalLayoutMainWindow = QVBoxLayout(self.centralWidget)
        self._verticalLayoutMainWindow.addWidget(self._tabWidgetMainWindow)

        # for testing
        # self.__testOpenFileMethod()
        # end for testing

        self._horizontalLayoutWelcomeScreen = QHBoxLayout()
        self._createTabs()

        self.show()

    def _createMenuBar(self):

        # Create menu bar
        menuBar = self.menuBar()

        # Create root menu such as File, Edit, Help etc.
        menuBarFile = menuBar.addMenu('&File')
        menuBarHelp = menuBar.addMenu('&Help')

        # Create actions for Menu
        actionOpenPowerBIFile = QAction('Open &Power BI File', self)
        actionOpenPowerBIFile.setShortcut('Ctrl+O')
        actionOpenPowerBIFile.setStatusTip('Import Power BI file from which you want to export the visual settings to '
                                           'create theme')

        # actionReloadPowerBIFile = QAction('&Reload Power BI File', self)
        # actionReloadPowerBIFile.setShortcut('Ctrl+R')
        # actionReloadPowerBIFile.setStatusTip('Click to reload Power BI file if there are changes made in Power BI
        # file')

        actionGenerateTheme = QAction('&Generate Theme', self)
        actionGenerateTheme.setShortcut('Ctrl+G')
        actionGenerateTheme.setStatusTip('Click to generate theme and save theme file')

        actionQuit = QAction('&Quit', self)
        actionQuit.setShortcut('Ctrl+Q')
        actionQuit.setStatusTip('Click to quit application')

        actionAbout = QAction('&About', self)
        actionAbout.setStatusTip('Click to see detail application information and useful links')

        # Add actions to menu
        menuBarFile.addAction(actionOpenPowerBIFile)
        # menuBarFile.addAction(actionReloadPowerBIFile)
        menuBarFile.addAction(actionGenerateTheme)
        menuBarFile.addSeparator()
        menuBarFile.addAction(actionQuit)

        menuBarHelp.addAction(actionAbout)

        # Add global events i.e. what will happen when option is selected from menu bar
        actionOpenPowerBIFile.triggered.connect(self._openPowerBIFileDialog)
        actionQuit.triggered.connect(self.close)
        actionGenerateTheme.triggered.connect(self.generateTheme)
        actionAbout.triggered.connect(self._showAboutDialog)

    def _openPowerBIFileDialog(self):
        try:

            directory = '/'
            if self._pbiFilePath is not None:
                directory = self._pbiFilePath.split('/')[0:-1]
                directory = "/".join(directory)

            self._pbiFilePath = QFileDialog.getOpenFileName(
                self,
                caption='Select Power BI File',
                directory=directory,
                filter='Power BI Files(*.pbix)'
            )[0]

            if self._pbiFilePath is not '' and not None:
                if self._pbiFilePath.split('/')[-1].split('.')[-1] == 'pbix':
                    self._powerBIThemeGenerator = PowerBIThemeGenerator(self._pbiFilePath)
                else:
                    raise ValueError('Invalid Power BI File')
                self._reportVisualData = self._powerBIThemeGenerator.modifiedDataStructure()
                self._populateTabVisualProperties()
        except Exception as e:
            ShowErrorDialog(LogException(e))

    def __testOpenFileMethod(self):
        self._pbiFilePath = 'G:/Power BI Reports/Theme Template.pbix'
        self._powerBIThemeGenerator = PowerBIThemeGenerator(self._pbiFilePath)
        self._reportVisualData = self._powerBIThemeGenerator.modifiedDataStructure()

    def _createTabs(self):
        # Creating tabs
        self._tabWidgetMainWindow = QTabWidget(self.centralWidget)

        self._tabGeneralProperties = QWidget()
        self._tabVisualProperties = QWidget()

        self._tabWidgetMainWindow.addTab(self._tabGeneralProperties, 'General Properties')
        self._tabWidgetMainWindow.addTab(self._tabVisualProperties, 'Visuals Properties')

        tabBarMainWindow: QTabBar = self._tabWidgetMainWindow.tabBar()
        tabBarMainWindow.setTabToolTip(0, 'Add optional general properties of the theme')
        tabBarMainWindow.setTabToolTip(1, 'All the Power BI File visuals related properties will be visible here')

        self._verticalLayoutVisualsPropertiesTab = QVBoxLayout(self._tabVisualProperties)
        self._verticalLayoutMainWindow.addWidget(self._tabWidgetMainWindow)

        self._populateTabGeneralProperties()
        self._populateTabVisualProperties()

    def _populateTabVisualProperties(self):

        if self._pbiFilePath is None:
            self._showWelcomeScreenTabVisualProperties()
            self._verticalLayoutVisualsPropertiesTab.addLayout(self._horizontalLayoutWelcomeScreen)
        else:
            self._clearTabVisualProperties()
            self._horizontalLayoutTabVisualsTop = QHBoxLayout()
            self._verticalLayoutVisualsPropertiesTab.insertLayout(0, self._horizontalLayoutTabVisualsTop)

            self._createReportPageList()
            # self._create_extra_options()

    def _populateTabGeneralProperties(self):

        try:
            dataColors = []

            def __showMessageBoxInvalidHexColor(hexColor):
                messageBoxInvalidColor = QMessageBox()
                messageBoxInvalidColor.setIcon(QMessageBox.Critical)
                messageBoxInvalidColor.setWindowTitle('Invalid Hex Color Code')
                messageBoxInvalidColor.setText('"' + hexColor + '"' + ' is not valid hex color code')
                messageBoxInvalidColor.exec_()

            def __validateDataColors():
                try:
                    dataColors = [dataColor.strip() for dataColor in lineEditDataColors.text().split(',')]
                    for dataColor in dataColors:
                        if ColorUtil.IsValidHexColor(dataColor) is False and dataColor is not '':
                            dataColors.remove(dataColor)
                            __showMessageBoxInvalidHexColor(dataColor)
                        elif dataColor is '':
                            dataColors.remove(dataColor)
                    lineEditDataColors.setText(','.join(dataColors))
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __showColorPickerDialog():
                try:
                    sender = self.sender().objectName()
                    color: QColor = QColorDialog().getColor()
                    if color.isValid():
                        hexColor = color.name()
                        buttonBackgroundColor = 'background-color: ' + hexColor
                        if sender == 'push_button_data_color':
                            dataColors.append(hexColor)
                            self._generalProperties['dataColors'] = dataColors
                            lineEditDataColors.setText(','.join(dataColors))
                        elif sender == 'push_button_background_color':
                            pushButtonBackgroundColorPicker.setStyleSheet(buttonBackgroundColor)
                            lineEditBackgroundColor.setText(hexColor)
                            self._generalProperties['background'] = hexColor
                        elif sender == 'push_button_foreground_color':
                            pushButtonForegroundColorPicker.setStyleSheet(buttonBackgroundColor)
                            lineEditForegroundColor.setText(hexColor)
                            self._generalProperties['foreground'] = hexColor
                        elif sender == 'push_button_table_accent_color':
                            pushButtonTableAccentColorPicker.setStyleSheet(buttonBackgroundColor)
                            lineEditTableAccent.setText(hexColor)
                            self._generalProperties['tableAccent'] = hexColor
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __lineEditEditingFinished():
                try:
                    sender = self.sender().objectName()
                    if sender == 'line_edit_data_color':
                        __validateDataColors()
                        nonlocal dataColors
                        dataColors = lineEditDataColors.text().split(",")
                        self._generalProperties['dataColors'] = dataColors
                        return
                    elif sender == 'line_edit_background_color':
                        textColor = lineEditBackgroundColor.text()
                    elif sender == 'line_edit_foreground_color':
                        textColor = lineEditForegroundColor.text()
                    elif sender == 'line_edit_table_accent_color':
                        textColor = lineEditTableAccent.text()
                    elif sender == 'line_edit_theme_name':
                        self._generalProperties['name'] = lineEditThemeName.text()
                        return
                    validColor = ColorUtil.IsValidHexColor(textColor)
                    if validColor is False and textColor is not '':
                        __showMessageBoxInvalidHexColor(textColor)
                        if sender == 'line_edit_background_color':
                            lineEditBackgroundColor.setText('')
                        elif sender == 'line_edit_foreground_color':
                            lineEditForegroundColor.setText('')
                        elif sender == 'line_edit_table_accent_color':
                            lineEditTableAccent.setText('')
                    else:
                        buttonBackgroundColor = 'background-color: ' + textColor
                        if sender == 'line_edit_background_color':
                            self._generalProperties['background'] = textColor
                            pushButtonBackgroundColorPicker.setStyleSheet(buttonBackgroundColor)
                        elif sender == 'line_edit_foreground_color':
                            pushButtonForegroundColorPicker.setStyleSheet(buttonBackgroundColor)
                            self._generalProperties['foreground'] = textColor
                        elif sender == 'line_edit_table_accent_color':
                            pushButtonTableAccentColorPicker.setStyleSheet(buttonBackgroundColor)
                            self._generalProperties['tableAccent'] = textColor

                except Exception as e:
                    ShowErrorDialog(LogException(e))

            labelThemeName = QLabel('Theme Name: ')
            lineEditThemeName = QLineEdit()
            lineEditThemeName.setObjectName('line_edit_theme_name')
            lineEditThemeName.editingFinished.connect(__lineEditEditingFinished)

            horizontalLayoutDataColor = QHBoxLayout()
            labelDataColors = QLabel('Data Colors: ')
            labelDataColors.setToolTip('These colors will be visible in color picker and will apply as data colors in '
                                       'charts')
            lineEditDataColors = QLineEdit()
            lineEditDataColors.editingFinished.connect(__lineEditEditingFinished)
            lineEditDataColors.setObjectName('line_edit_data_color')
            pushButtonDataColorPicker = QPushButton()
            pushButtonDataColorPicker.setToolTip('Click to pick colors for Data Colors')
            pushButtonDataColorPicker.setObjectName('push_button_data_color')
            pushButtonDataColorPicker.clicked.connect(__showColorPickerDialog)
            horizontalLayoutDataColor.addWidget(lineEditDataColors)
            horizontalLayoutDataColor.addWidget(pushButtonDataColorPicker)
            # TO DO: Add generate colors button

            horizontalLayoutBackgroundColor = QHBoxLayout()
            labelBackgroundColor = QLabel('Background Color: ')
            labelBackgroundColor.setToolTip('Applies to button fill and combo chart label background. How these colors '
                                            'are used depends on the specific visual style that\'s applied.')
            lineEditBackgroundColor = QLineEdit()
            lineEditBackgroundColor.setObjectName('line_edit_background_color')
            lineEditBackgroundColor.editingFinished.connect(__lineEditEditingFinished)
            pushButtonBackgroundColorPicker = QPushButton()
            pushButtonBackgroundColorPicker.setToolTip('Click to pick color for Background Color')
            pushButtonBackgroundColorPicker.setObjectName('push_button_background_color')
            pushButtonBackgroundColorPicker.clicked.connect(__showColorPickerDialog)
            horizontalLayoutBackgroundColor.addWidget(lineEditBackgroundColor)
            horizontalLayoutBackgroundColor.addWidget(pushButtonBackgroundColorPicker)

            horizontalLayoutForegroundColor = QHBoxLayout()
            labelForegroundColor = QLabel('Foreground Color: ')
            labelForegroundColor.setToolTip('Applies to textbox text, KPI goal text, multi-row card text, card value '
                                            'text, gauge callout text, vertical slicer element text, and table and '
                                            'matrix total and values text.')
            lineEditForegroundColor = QLineEdit()
            lineEditForegroundColor.setObjectName('line_edit_foreground_color')
            lineEditForegroundColor.editingFinished.connect(__lineEditEditingFinished)
            pushButtonForegroundColorPicker = QPushButton()
            pushButtonForegroundColorPicker.setToolTip('Click to pick color for Foreground Color')
            pushButtonForegroundColorPicker.setObjectName('push_button_foreground_color')
            pushButtonForegroundColorPicker.clicked.connect(__showColorPickerDialog)
            horizontalLayoutForegroundColor.addWidget(lineEditForegroundColor)
            horizontalLayoutForegroundColor.addWidget(pushButtonForegroundColorPicker)

            horizontalLayoutTableAccent = QHBoxLayout()
            labelTableAccent = QLabel('Table Accent: ')
            labelTableAccent.setToolTip('Table and matrix visuals apply these styles by default.')
            lineEditTableAccent = QLineEdit()
            lineEditTableAccent.setObjectName('line_edit_table_accent_color')
            lineEditTableAccent.editingFinished.connect(__lineEditEditingFinished)
            pushButtonTableAccentColorPicker = QPushButton()
            pushButtonTableAccentColorPicker.setToolTip('Click to pick color for Table Accent Color')
            pushButtonTableAccentColorPicker.setObjectName('push_button_table_accent_color')
            pushButtonTableAccentColorPicker.clicked.connect(__showColorPickerDialog)
            horizontalLayoutTableAccent.addWidget(lineEditTableAccent)
            horizontalLayoutTableAccent.addWidget(pushButtonTableAccentColorPicker)

            formLayoutGeneralProperties = QFormLayout(self._tabGeneralProperties)
            formLayoutGeneralProperties.addRow(labelThemeName, lineEditThemeName)
            formLayoutGeneralProperties.addRow(labelDataColors, horizontalLayoutDataColor)
            formLayoutGeneralProperties.addRow(labelBackgroundColor, horizontalLayoutBackgroundColor)
            formLayoutGeneralProperties.addRow(labelForegroundColor, horizontalLayoutForegroundColor)
            formLayoutGeneralProperties.addRow(labelTableAccent, horizontalLayoutTableAccent)
        except Exception as e:
            ShowErrorDialog(LogException(e))

    def _showWelcomeScreenTabVisualProperties(self):
        welcomeLabel = QLabel('Go to File menu or press Ctrl+O to select Power BI File')
        self._horizontalLayoutWelcomeScreen.addStretch()
        self._horizontalLayoutWelcomeScreen.addWidget(welcomeLabel)
        self._horizontalLayoutWelcomeScreen.addStretch()

    def _removeWelcomeScreenFromTabVisualProperties(self):
        self._deleteLayout(self._horizontalLayoutWelcomeScreen)

    def _clearTabVisualProperties(self):
        self._removeWelcomeScreenFromTabVisualProperties()
        self._deleteLayout(self._verticalLayoutVisualsPropertiesTab)
        self._listWidgetReportPages = None
        self._listWidgetReportPageVisuals = None
        self._treeWidgetSelectedVisualProperties = None

    def _deleteLayout(self, layout):
        if layout is not None:
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.deleteLater()
                else:
                    self._deleteLayout(item.layout())
            # sip.delete(layout)

    def _createReportPageList(self):
        try:
            def __reportPageListValueSelected(item):
                try:
                    self._createReportPageVisualsList(item.GetMetaData()['reportPageSection'])
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            if self._listWidgetReportPages is not None:
                self._listWidgetReportPages.clear()

            groupBoxReportPageList = QGroupBox(self.centralWidget)
            groupBoxReportPageList.setTitle("Report Pages")
            verticalLayoutReportPageList = QVBoxLayout(groupBoxReportPageList)

            self._listWidgetReportPages = QListWidget()

            i = 0
            for reportSection in self._powerBIThemeGenerator.get_report_sections():
                reportListWidgetItem = CQListWidgetItemReportPages(str(reportSection['displayName']))
                reportListWidgetItem.SetMetaData(reportSection)
                reportListWidgetItem.setToolTip(reportSection['name'])
                self._listWidgetReportPages.insertItem(i, reportListWidgetItem)
                i += 1

            verticalLayoutReportPageList.addWidget(self._listWidgetReportPages)
            self._horizontalLayoutTabVisualsTop.addWidget(groupBoxReportPageList)
            # __reportPageListValueSelected(self._listWidgetReportPages.item(0))

            self._listWidgetReportPages.itemClicked.connect(__reportPageListValueSelected)

        except Exception as e:
            ShowErrorDialog(LogException(e))

    def _createReportPageVisualsList(self, reportPageSection=None):

        try:
            # print(self._reportVisualData[reportPageSection])
            # print('inside report page visual list', reportPageSection)

            def __updateStateInDataStructure(item):
                vizProperties = item.GetVisualProperties()
                if item.checkState() == Qt.Checked:
                    (self._reportVisualData[vizProperties['report_section']]
                        .get('visuals')[vizProperties['visual_index']]['__selected']) = True
                else:
                    (self._reportVisualData[vizProperties['report_section']]
                        .get('visuals')[vizProperties['visual_index']]['__selected']) = False

            def __getVisualProperties(item: CQListWidgetItemReportPageVisuals):
                try:
                    __updateStateInDataStructure(item)
                    self._createSelectedVisualPropertiesTree(item.GetVisualProperties())
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __selectDeselectAll():
                try:
                    if self._listWidgetReportPageVisuals is not None:
                        for i in range(self._listWidgetReportPageVisuals.count()):
                            item = self._listWidgetReportPageVisuals.item(i)
                            if self.sender().objectName() == 'button_select_all':
                                item.setCheckState(Qt.Checked)
                            else:
                                item.setCheckState(Qt.Unchecked)
                            __updateStateInDataStructure(item)
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            groupBoxReportPageVisualsList = QGroupBox(self.centralWidget)
            groupBoxReportPageVisualsList.setTitle("Visuals in Selected Report Page")
            # groupBoxReportPageVisualsList.setToolTip("All visuals present in the selected page will be visible below")
            verticalLayoutReportPageVisualsList = QVBoxLayout(groupBoxReportPageVisualsList)

            horizontalLayoutSelectDeselectButton = QHBoxLayout()
            pushButtonSelectAll = QPushButton('Select All')
            pushButtonSelectAll.setObjectName('button_select_all')
            pushButtonDeselectAll = QPushButton('Deselect All')
            pushButtonDeselectAll.setObjectName('button_deselect_all')
            horizontalLayoutSelectDeselectButton.addWidget(pushButtonSelectAll)
            horizontalLayoutSelectDeselectButton.addWidget(pushButtonDeselectAll)
            verticalLayoutReportPageVisualsList.addLayout(horizontalLayoutSelectDeselectButton)

            if self._listWidgetReportPageVisuals is None:
                self._listWidgetReportPageVisuals = QListWidget()
                verticalLayoutReportPageVisualsList.addWidget(self._listWidgetReportPageVisuals)
                self._horizontalLayoutTabVisualsTop.addWidget(groupBoxReportPageVisualsList)
                self._listWidgetReportPageVisuals.itemClicked.connect(__getVisualProperties, Qt.UniqueConnection)
            else:
                self._listWidgetReportPageVisuals.clear()

            i = 0
            for visualIndex, visual in enumerate(self._reportVisualData[reportPageSection].get('visuals')):
                visualType = visual['visual_type']
                visualTitle = visual.get('objects').get('title')
                # print(visualType, visualTitle)
                if visualTitle is None or visualTitle.get('text') is None:
                    listDisplayText = str(visualType)
                else:
                    listDisplayText = str(visualType) + " - " + visualTitle.get('text')
                pageVisualsList = CQListWidgetItemReportPageVisuals(listDisplayText)
                pageVisualsList.setFlags(pageVisualsList.flags() | Qt.ItemIsUserCheckable)
                if visual['__selected'] is False:
                    pageVisualsList.setCheckState(Qt.Unchecked)
                else:
                    pageVisualsList.setCheckState(Qt.Checked)
                pageVisualsList.SetVisualProperties(visual, reportPageSection, visualIndex)
                # print(pageVisualsList.GetVisualProperties())
                self._listWidgetReportPageVisuals.insertItem(i, pageVisualsList)
                i += 1

            pushButtonSelectAll.clicked.connect(__selectDeselectAll)
            pushButtonDeselectAll.clicked.connect(__selectDeselectAll)

            # self._listWidgetReportPageVisuals.setCurrentRow(0)
            # __getVisualProperties(self._listWidgetReportPageVisuals.item(0))

        except Exception as e:
            ShowErrorDialog(LogException(e))

    def _createSelectedVisualPropertiesTree(self, visualProperties=None):
        try:

            def __getVisualProperty(item: CQTreeWidgetItemVisualProperties):
                try:
                    visualProperties = item.GetVisualProperties()
                    if visualProperties is not None:
                        visualProperty = (self._reportVisualData[visualProperties['report_section']]
                                          .get('visuals')[visualProperties['visual_index']].get('objects')
                                          .get(str(item.data(0, 0))))
                        return visualProperty
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __updateStateInDataStructure(item: CQTreeWidgetItemVisualProperties):
                try:
                    visualProperty = __getVisualProperty(item)
                    if visualProperty is not None:
                        if item.checkState(0) == Qt.Unchecked:
                            visualProperty['__selected'] = False
                        else:
                            visualProperty['__selected'] = True
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __updateWildCardState(state, item=None):
                try:
                    visualProperty = __getVisualProperty(item)
                    if visualProperty is not None:
                        if state == Qt.Checked:
                            visualProperty['__wildcard'] = True
                            # print(visualProperty)
                        elif visualProperty.get('__wildcard') is not None and state == Qt.Unchecked:
                            visualProperty.pop('__wildcard')
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __treeWidgetVisualsPropertiesClicked(item: CQTreeWidgetItemVisualProperties):
                try:
                    __updateStateInDataStructure(item)
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            def __selectDeselectAll():
                try:
                    if self._treeWidgetSelectedVisualProperties is not None:
                        for i in range(self._treeWidgetSelectedVisualProperties.topLevelItemCount()):
                            item = self._treeWidgetSelectedVisualProperties.topLevelItem(i)
                            if self.sender().objectName() == 'button_select_all':
                                item.setCheckState(0, Qt.Checked)
                            else:
                                item.setCheckState(0, Qt.Unchecked)
                            __updateStateInDataStructure(item)
                except Exception as e:
                    ShowErrorDialog(LogException(e))

            self._groupBoxSelectedVisualPropertiesTree = QGroupBox(self.centralWidget)
            self._groupBoxSelectedVisualPropertiesTree.setTitle("Selected Visual Properties")
            verticalLayoutSelectedVisualPropertiesTree = QVBoxLayout(self._groupBoxSelectedVisualPropertiesTree)

            horizontalLayoutSelectDeselectButton = QHBoxLayout()
            pushButtonSelectAll = QPushButton('Select All')
            pushButtonSelectAll.setObjectName('button_select_all')
            pushButtonDeselectAll = QPushButton('Deselect All')
            pushButtonDeselectAll.setObjectName('button_deselect_all')
            horizontalLayoutSelectDeselectButton.addWidget(pushButtonSelectAll)
            horizontalLayoutSelectDeselectButton.addWidget(pushButtonDeselectAll)
            verticalLayoutSelectedVisualPropertiesTree.addLayout(horizontalLayoutSelectDeselectButton)

            if self._treeWidgetSelectedVisualProperties is None:
                self._treeWidgetSelectedVisualProperties = QTreeWidget()
                verticalLayoutSelectedVisualPropertiesTree.addWidget(self._treeWidgetSelectedVisualProperties)
                self._verticalLayoutVisualsPropertiesTab.insertWidget(1, self._groupBoxSelectedVisualPropertiesTree)
                self._treeWidgetSelectedVisualProperties.itemClicked.connect(__treeWidgetVisualsPropertiesClicked)
            else:
                self._treeWidgetSelectedVisualProperties.clear()

            self._treeWidgetSelectedVisualProperties.setHeaderLabels(['Property', 'Value', 'Wild Card'])
            treeHeader = self._treeWidgetSelectedVisualProperties.header()
            treeHeader.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
            # treeHeader.setStretchLastSection(False)

            visualObjects = visualProperties['visual_properties'].get('objects')
            for object, objectValues in visualObjects.items():
                if len(objectValues.keys()) > 1:  # greater than 1 because one default key is __selected
                    parent = CQTreeWidgetItemVisualProperties(self._treeWidgetSelectedVisualProperties, [str(object)])
                    parent.SetVisualProperties(visualProperties)
                    wildCardCheckBox = QCheckBox()
                    wildCardCheckBox.stateChanged.connect(partial(__updateWildCardState, item=parent))
                    self._treeWidgetSelectedVisualProperties.setItemWidget(parent, 2, wildCardCheckBox)
                    if objectValues['__selected'] is False:
                        parent.setCheckState(0, Qt.Unchecked)
                    else:
                        parent.setCheckState(0, Qt.Checked)
                    for objectKey, objectValue in objectValues.items():
                        if objectKey is not '__selected':
                            mObjectV = None
                            if type(objectValue) is dict and objectValue.get('solid') is not None:
                                mObjectV = objectValue.get('solid').get('color')
                            else:
                                mObjectV = objectValue
                            CQTreeWidgetItemVisualProperties(parent, [str(objectKey), str(mObjectV)])
                else:
                    objectValues['__selected'] = False

            pushButtonSelectAll.clicked.connect(__selectDeselectAll)
            pushButtonDeselectAll.clicked.connect(__selectDeselectAll)

        except Exception as e:
            ShowErrorDialog(LogException(e))

    def generateTheme(self):
        try:
            correctVisualData = True
            correctWildcardData = True
            themeName = self._generalProperties.get('name')
            themeData = {
                'name': themeName
                if themeName is not None and len(themeName.strip()) > 0 else 'My Theme',
            }
            if self._generalProperties.get('dataColors') is not None:
                dataColors = list(filter(None, self._generalProperties.get('dataColors')))

            else:
                dataColors = []
            background = self._generalProperties.get('background')
            foreground = self._generalProperties.get('foreground')
            tableAccent = self._generalProperties.get('tableAccent')

            if dataColors is not None and dataColors is not "":
                themeData['dataColors'] = dataColors
            if background is not None and background is not "":
                themeData['background'] = background
            if foreground is not None and foreground is not "":
                themeData['foreground'] = foreground
            if tableAccent is not None and tableAccent is not "":
                themeData['tableAccent'] = tableAccent

            selectedVisualsList = [[], [], []]  # page name, visual type and visual data or visual objects
            wildCardPropertiesList = [[], [], []]  # page name, property type and property data
            visualObjectIndex = 0
            themeData['visualStyles'] = {}
            if self._pbiFilePath is not None:
                for reportPage in self._reportVisualData:
                    for visual in self._reportVisualData[reportPage].get('visuals'):
                        pageName = self._reportVisualData[reportPage]['reportPageDisplayName']
                        if visual['__selected'] is True:
                            selectedVisualsList[0].append(pageName)
                            selectedVisualsList[1].append(visual['visual_type'])
                            selectedVisualsList[2].append({})
                            visualObjects = visual.get('objects')
                            for object in visualObjects:
                                if visualObjects[object]['__selected'] is True:
                                    selectedVisualsList[2][visualObjectIndex][object] = [visualObjects[object]]
                                    if visualObjects[object].get('__wildcard') is not None:
                                        # wildCardObjects[object] = [visualObjects[object]]
                                        wildCardPropertiesList[0].append(pageName)
                                        wildCardPropertiesList[1].append(object)
                                        wildCardPropertiesList[2].append(visualObjects[object])

                            visualObjectIndex += 1
                if len(selectedVisualsList[1]) > 0:
                    if len(selectedVisualsList[1]) != len(set(selectedVisualsList[1])):
                        message = 'Multiple visual of same type selected from different report pages. See details below.' \
                                  ' Please select one visual type for only once.'
                        detailMessage = ''
                        seen = set()
                        repeatedVisuals = []
                        for selectedVisual in selectedVisualsList[1]:
                            if selectedVisual in seen:
                                repeatedVisuals.append(selectedVisual)
                            else:
                                seen.add(selectedVisual)

                        for i, selectedVisual in enumerate(selectedVisualsList[1]):
                            if selectedVisual in repeatedVisuals:
                                detailMessage += selectedVisual + ' is selected in report page'\
                                                 + selectedVisualsList[0][i] + '\n'
                        correctVisualData = False
                        self._showDialogAfterThemeGeneration(message, detailMessage=detailMessage)

                    else:
                        # adding wild card data
                        if len(wildCardPropertiesList[1]) > 0:
                            if len(wildCardPropertiesList[1]) != len(set(wildCardPropertiesList[1])):
                                message = 'Multiple wild card properties of same types are selected. Please only select '\
                                          'unique properties for wild card from all the visuals. As a result this' \
                                          'properties will not be added as wild card property in them file. ' \
                                          'See details below'
                                detailMessage = ''
                                seen = set()
                                repeatedWildCardProperties = []
                                for wildCardProperty in wildCardPropertiesList[1]:
                                    if wildCardProperty in seen:
                                        repeatedWildCardProperties.append(wildCardProperty)
                                    else:
                                        seen.add(wildCardProperty)

                                for i, wildCardProperty in enumerate(wildCardPropertiesList[1]):
                                    if wildCardProperty in repeatedWildCardProperties:
                                        detailMessage += wildCardProperty + 'is selected in report page' +\
                                                         wildCardPropertiesList[0][i]
                                correctWildcardData = False
                                self._showDialogAfterThemeGeneration(message, detailMessage=detailMessage)
                            else:
                                themeData['visualStyles']['*'] = {
                                    '*': {}
                                }
                                for i in range(len(wildCardPropertiesList[1])):
                                    themeData['visualStyles']['*']['*'][wildCardPropertiesList[1][i]] = [wildCardPropertiesList[2][i]]

                        # adding visual data
                        for i in range(len(selectedVisualsList[1])):
                            themeData['visualStyles'][selectedVisualsList[1][i]] = {
                                "*": selectedVisualsList[2][i]
                            }
            if correctVisualData is True and correctWildcardData is True:
                self._saveThemeFile(themeData, 'C:/Users/bjadav/Desktop/', themeData['name'])

        except Exception as e:
            ShowErrorDialog(LogException(e))

    def _showDialogAfterThemeGeneration(self, message, messageIcon=QMessageBox.Information, detailMessage=None):
        try:
            messageBoxThemeGeneration = QMessageBox()
            messageBoxThemeGeneration.setIcon(messageIcon)
            messageBoxThemeGeneration.setText(message)
            if detailMessage is not None:
                messageBoxThemeGeneration.setInformativeText(detailMessage)
            messageBoxThemeGeneration.setWindowTitle("Theme Generation Information")
            messageBoxThemeGeneration.setStandardButtons(QMessageBox.Ok)

            messageBoxThemeGeneration.exec_()
        except Exception as e:
            ShowErrorDialog(LogException(e))

    def _saveThemeFile(self, themeData, saveFileDirectory, fileName):
        try:
            _themeData = json.loads(json.dumps(themeData))
            # Removing internal keys such as __selected from final output
            for visualType, visualProperties in _themeData['visualStyles'].items():
                for propertyType, propertyValue in visualProperties['*'].items():
                    if propertyValue[0].get('__selected') is not None:
                        propertyValue[0].pop('__selected')
                    if propertyValue[0].get('__wildcard') is not None:
                        propertyValue[0].pop('__wildcard')

            initialSaveFilePath = saveFileDirectory + fileName + '.json'
            saveFile = QFileDialog.getSaveFileName(self, 'Save Theme File', initialSaveFilePath,
                                                   filter='JSON file(*.json)')[0]
            if saveFile is not '':
                with open(saveFile, 'w') as themeFile:
                    json.dump(_themeData, themeFile, indent=4)
                message = 'Successfully generated theme'
                self._showDialogAfterThemeGeneration(message)
        except Exception as e:
            ShowErrorDialog(LogException(e))

    def _showAboutDialog(self):
        try:
            dialogAbout = QDialog()
            dialogAbout.resize(320, 180)
            dialogButtonBoxAbout = QDialogButtonBox(dialogAbout)
            dialogButtonBoxAbout.setLayoutDirection(Qt.LeftToRight)
            dialogButtonBoxAbout.setAutoFillBackground(False)
            dialogButtonBoxAbout.setOrientation(Qt.Horizontal)
            dialogButtonBoxAbout.setStandardButtons(QtWidgets.QDialogButtonBox.Ok)
            dialogButtonBoxAbout.setCenterButtons(True)
            dialogButtonBoxAbout.accepted.connect(dialogAbout.accept)

            verticalLayoutAboutDialog = QVBoxLayout(dialogAbout)

            dialogAbout.setWindowTitle('About ' + AppInfo.Name)

            labelPowerBIThemeGeneratorFont = QFont()
            labelPowerBIThemeGeneratorFont.setPointSize(16)
            labelPowerBIThemeGeneratorFont.setFamily('Calibri')
            labelPowerBIThemeGenerator = QLabel(AppInfo.Name)
            labelPowerBIThemeGenerator.setFont(labelPowerBIThemeGeneratorFont)

            labelVersionFont = QFont()
            labelVersionFont.setPointSize(8)
            labelVersion = QLabel(AppInfo.Version)
            labelVersion.setContentsMargins(0, 0, 0, 0)

            labelCreatedBy = QLabel('Created By ' + AppInfo.Author)
            link = '<a href="' + AppInfo.GitHubRepoIssuesURL + '">Click here to report bugs</a>'
            labelBugs = QLabel(link)
            labelBugs.setOpenExternalLinks(True)

            verticalLayoutAboutDialog.addWidget(labelPowerBIThemeGenerator)
            verticalLayoutAboutDialog.addWidget(labelVersion)
            verticalLayoutAboutDialog.addWidget(labelCreatedBy)
            verticalLayoutAboutDialog.addWidget(labelBugs)
            verticalLayoutAboutDialog.addStretch()
            verticalLayoutAboutDialog.addWidget(dialogButtonBoxAbout)
            dialogAbout.exec_()
        except Exception as e:
            ShowErrorDialog(LogException(e))
コード例 #22
0
class PathEditor(ViewInfoChanger):
    def __init__(self, header, info, parent: ViewShower):
        super().__init__(header, info, parent)
        self.way_layout = QVBoxLayout()
        push_btn = self.main_layout.takeAt(self.main_layout.count() -
                                           1).widget()

        self.path_id = info[0]

        add_btn = QPushButton("Добавить")
        add_btn.clicked.connect(lambda e: self.add_cell(-1))
        self.main_layout.addWidget(add_btn)

        way = self.db.execute(
            f"SELECT Станция, `Код станции` FROM `состав_маршрута_view` where `Номер маршрута` = {self.path_id}"
        )
        for pos, point in enumerate(way, start=-1):
            station_info = str(point[0])
            self.combo_change_idx["Станция отправления"][station_info] = point[
                1]
            self.add_cell(pos, station_info)

        self.main_layout.addLayout(self.way_layout)
        self.main_layout.addWidget(push_btn)

    def add_cell(self, pos: int, txt=""):
        """Вставляет ячейку ниже активирующей кнопки для вставки на уровне надо передать ::pos:: = -1"""

        cell = QHBoxLayout()
        edi = QLineEdit()
        edi.setText(txt)

        add_btn = QPushButton("Добавить")
        down_btn = QPushButton("Вниз")
        up_btn = QPushButton("Вверх")
        del_btn = QPushButton("Удалить")

        cmb = QComboBox()
        cmb.addItem(txt)

        edi.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        cmb.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)

        up_btn.clicked.connect(lambda e, p=pos, c=cell: self.move_cell_up(c))
        down_btn.clicked.connect(
            lambda e, p=pos, c=cell: self.move_cell_down(c))

        add_btn.clicked.connect(lambda e, c=cell: self.add_cell(c.pos))
        del_btn.clicked.connect(lambda e, c=cell: self.del_cell(c.pos))

        edi.editingFinished.connect(
            lambda c=cmb, t=edi.text: self.combo_update(
                "Станция отправления", c, t()))  # le-kostyl
        cell.pos = pos
        cell.addWidget(edi)
        cell.addWidget(cmb)
        cell.addWidget(add_btn)
        cell.addWidget(down_btn)
        cell.addWidget(up_btn)
        cell.addWidget(del_btn)
        for i in range(pos + 1, self.way_layout.count()):
            cell_to_move = self.way_layout.itemAt(i)
            cell_to_move.pos += 1
        cell.pos += 1  # для вставки ниже активированной кнопки

        self.way_layout.insertLayout(cell.pos, cell)

    def del_cell(self, pos):
        cell: QVBoxLayout
        cell = self.way_layout.takeAt(pos)
        for i in range(cell.count()):
            w = cell.takeAt(0).widget()
            w.deleteLater()
        cell.deleteLater()

        for i in range(pos, self.way_layout.count()):
            cell_to_move = self.way_layout.itemAt(i)
            cell_to_move.pos -= 1

    def move_cell_up(self, cell):
        if cell.pos > 0:
            old_cell = self.way_layout.itemAt(cell.pos - 1)
            self.way_layout.takeAt(cell.pos)
            self.way_layout.insertLayout(cell.pos - 1, cell)
            old_cell.pos += 1
            cell.pos -= 1

    def move_cell_down(self, cell):
        if cell.pos < self.way_layout.count() - 1:
            old_cell = self.way_layout.itemAt(cell.pos + 1)
            self.way_layout.takeAt(cell.pos)
            self.way_layout.insertLayout(cell.pos + 1, cell)
            old_cell.pos -= 1
            cell.pos += 1

    def push_point_changes(self):
        params = []
        station_ord_numb_in_path = 0
        for i in range(self.way_layout.count()):
            cell = self.way_layout.itemAt(i)
            w = cell.itemAt(1).widget()
            station = w.currentText()
            if station:
                station_id = self.combo_change_idx["Станция отправления"][
                    station]
                params.append(
                    (self.path_id, station_ord_numb_in_path, station_id))
                station_ord_numb_in_path += 1

        query = f" insert into `состав маршрута` values(%s, %s, %s)"
        self.db.execute(
            "delete from `состав маршрута` where `Номер маршрута` = %s",
            (self.path_id, ))
        self.db.executemany(query, params)
        self.db.commit()

    def push_changes(self):
        self.push_point_changes()
        super().push_changes()
コード例 #23
0
class DropSiteWindow(QWidget):
    def __init__(self, pageNumber, driver):
        super().__init__()
        """
            QUICK START IN OPTIONS
            HANDLE EXCEPTIONS WERES ARE BLOCKED OR NETWORK DOESNT WORK ETC -> WHEN GOING BACK ONLINE LOAD IMAGE

            REOPNING TAB DOESNT SAVE PAGE STATE
            REOPNING TAB OPENS IN DIFFERENT BROWSER
            BETTER WAY TO CHECK WHETHER ITS A STANDLONE EXEC OR LOCALLY RUN
            HAVE A LOOK AT QSETTINGS TO REMEMBER WINDOW SIZES AND SESSION STATE ETC..

            FUTURE FEATURES:
             - MORE FREEDOM WITH REARRANGING TABS
             - SUPPORT OTHER DATA TYPES E.G. PDF FILE ETC..
             - FAVOURITE TABS -> MOVES THEM HIGHER
             - ANIMATE CLOSE BUTTON FADE IN/OUT
             - IMPLEMENT THEMES (ONLY DARK MODE RIGHT NOW)
        """

        # SETUP THUMBNAIL FOLDER
        if not (os.path.isdir(tabsettings.absImageFolderPath())):
            os.mkdir(tabsettings.absImageFolderPath())

        self.clearingTabs = False
        self.acceptDrops = True
        self.options = tabsettings.TabSettings()
        self.pageNumber = pageNumber
        self.pageName = 'Page ' + str(self.pageNumber)
        self.driver = driver

        self.setPageName()

        # SETUP LAYOUTS
        self.mainLayout = QVBoxLayout()
        self.scroll = QScrollArea()
        self.scrollWidget = QWidget()
        self.scrollWidgetLayout = QVBoxLayout()

        self.scroll.setWidgetResizable(True)
        self.scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.scroll.setFrameStyle(QFrame.NoFrame)

        self.scrollWidgetLayout.setAlignment(Qt.AlignTop | Qt.AlignLeft)
        self.scrollWidgetLayout.setContentsMargins(3, 3, 3, 3)
        self.scrollWidgetLayout.setSpacing(3)

        self.mainLayout.setContentsMargins(0, 0, 0, 0)

        self.scrollWidget.setLayout(self.scrollWidgetLayout)
        self.scroll.setWidget(self.scrollWidget)
        self.mainLayout.addWidget(self.scroll)
        self.setLayout(self.mainLayout)

        # IF TAB FILE EXISTS REMAKE TABS
        self.tabFilePath = os.path.join(os.getcwd(),
                                        tabsettings.tabFileName(self))
        self.tabFileName = tabsettings.tabFileName(self)
        self.archiveTabFileName = tabsettings.archiveTabFileName(self)
        exists = os.path.isfile(self.tabFilePath)
        size = 0
        if exists: size = os.path.getsize(self.tabFilePath)
        if size > 0 and exists:
            self.loadTabs(self.tabFilePath)
        else:
            self.newTab()

        self.updatePageNames()
        self.checkArchiveTabFileSize()

    # LOAD TABS FROM CURRENT PAGE TAB FILE -> CREATE NEW TAB -> LOAD TAB WITH CONTENT OF TAB FILE ENTRY
    def loadTabs(self, path):
        with open(path, 'r') as f:
            data = f.readlines()
            for index, line in enumerate(data):
                l = line.split('\n')[0]
                currentItems = l.split(' ')
                url = currentItems[0]
                imagePath = currentItems[1]
                tabNumber = currentItems[2]

                tab = self.newTab()
                self.loadTabData(tab, url, imagePath)
                # IF ITS LAST TAB ADD EMPTY TAB AFTER
                if index == len(data) - 1:
                    self.newTab()

    # CREATE NEW TAB -> IF TABCOUNT > ALLOWED -> CREATE NEW ROW THEN ADD TAB
    def newTab(self):
        if (self.options.tabCount % self.options.tabsPerRow) == 0:
            self.currentRow = QHBoxLayout()
            self.currentRow.setAlignment(Qt.AlignTop | Qt.AlignLeft)
            self.currentRow.setSpacing(3)
            self.currentRow.setSizeConstraint(QLayout.SetMinimumSize)
            self.scrollWidgetLayout.insertLayout(
                self.scrollWidgetLayout.layout().count(), self.currentRow)
            self.options.tabRows.append(self.currentRow)

        self.options.tabCount += 1
        drp = DropArea(self.options, self.options.tabCount, self.driver,
                       tabsettings.MIN_TAB_WIDTH, tabsettings.MIN_TAB_HEIGHT,
                       tabsettings.ASPECT_RATIO,
                       tabsettings.absImageFolderPath(), self.tabFileName,
                       self.archiveTabFileName)
        drp.imageLoaded.connect(self.newTab)
        drp.tabDeleted.connect(lambda: self.deleteTab(drp))
        drp.tabAdded.connect(self.addTabToList)
        drp.tabReordered.connect(self.reorderTab)
        drp.destroyed.connect(self.reorganizeTabFile)
        self.options.emptyTab = drp
        self.currentRow.addWidget(drp)
        return drp

    # SHORTCUT METHOD TO LOAD TAB
    def loadTabData(self, tab, url, imagePath):
        tab.load(url, imagePath)

    # DELETE TAB -> SET PARENT NONE -> REMOVE FROM TAB LIST -> DELETE ENTRY IN TAB FILE -> ARCHIVE IF NOT DUPLICATE
    def deleteTab(self, tab):
        if tab.taken:
            self.options.tabCount -= 1
            self.options.loadedTabCount -= 1
            self.options.tabList.remove(tab)
            tab.setParent(None)
            tab.deleteLater()

            # REMOVE ENTRY FROM SAVED TABS FILE
            fileData = open(self.tabFileName, 'r').readlines()
            with open(self.tabFileName, 'w') as out:
                # FILE LAYOUT EACH LINE -> (URL IMAGE_PATH TAB_NUMBER)
                for line in fileData:
                    currentItems = line.split(' ')
                    tabNum = int(currentItems[2])
                    # IF CURRENT LINE IS NOT TAB TO BE DELETED WRITE LINE
                    if not (tabNum == tab.tabNumber): out.write(line)

            # CHECK IF THERE IS DUPLICATE TAB IF SO DON'T ARCHIVE
            dontArchiveImage = tab.checkDuplicateTab(tab.url, self.tabFileName)
            if not dontArchiveImage: self.archiveTab(tab.url, tab.imagePath)

    # ARCHIVE TAB IN ARCHIVE TAB FILE NAME OF CURRENT PAGE -> RENAME IMAGE TO .IMAGE IF ITS AVAILABLE
    def archiveTab(self, url, imagePath):
        try:
            os.rename(
                os.path.normpath(
                    os.path.join(tabsettings.IMAGE_FOLDER_PATH, imagePath)),
                os.path.normpath(
                    os.path.join(tabsettings.IMAGE_FOLDER_PATH,
                                 '.' + imagePath)))
        except FileNotFoundError:
            pass

        with open(self.archiveTabFileName, 'a+') as f:
            f.seek(0)
            lines = f.readlines()
            duplicate = False
            for line in lines:
                if line.split(' ')[0] == url:
                    duplicate = True
            if not duplicate: f.write(url + ' ' + '.' + imagePath + '\n')

    # ADD TAB TO TABLIST -> IF NUMBER GREATER THEN LIST SIZE -> APPEND -> ELSE REPLACE TAB IN LIST
    def addTabToList(self, tab, tabNum):
        if len(self.options.tabList) <= tabNum:
            self.options.tabList.append(tab)
        else:
            self.options.tabList[tabNum] = tab

    # REORDER TAB IN TABLIST AND MOVE WIDGET -> REORGANIZE TAB FILE TO SHOW CHANGES MADE
    def reorderTab(self, tab, swapValue):
        # GET INDEX OF TAB IN TAB LIST
        index = self.options.tabList.index(tab)
        # SWAP VALUE = SHIFT IN TABS E.G. -1 FOR ONE LEFT
        newIndex = index + swapValue
        self.options.tabList.remove(tab)
        self.options.tabList.insert(newIndex, tab)
        self.reorganizeTabFile()

    # REORGANIZE TAB FILE -> FROM DELETED TAB (TAB NUMBERS WRONG) -> OR FROM REORGANIZING TAB
    def reorganizeTabFile(self):
        if os.path.isfile(
                self.tabFilePath) and os.path.getsize(self.tabFilePath) > 0:
            if not self.clearingTabs:
                for index, tab in enumerate(self.options.tabList):
                    tab.tabNumber = index + 1
                self.options.emptyTab.tabNumber = len(self.options.tabList) + 1

                # REORDER TABS IN THE SAVED TABS FILE SO THEY HAVE CORRECT TAB NUMBER
                with open(self.tabFileName, 'r+') as f:
                    lines = f.readlines()
                    currentTab = 1
                    finalStringData = ''
                    for line in lines:
                        currentItems = line.split('\n')[0].split(' ')
                        # REORGANIZING AFTER DELETING A TAB
                        if (currentTab != int(currentItems[2])):
                            finalStringData += currentItems[
                                0] + ' ' + self.options.tabList[
                                    currentTab -
                                    1].imagePath + ' ' + str(currentTab) + '\n'
                            # REORGANIZING AFTER REORDERING A TAB
                        elif (currentItems[0] !=
                              self.options.tabList[currentTab - 1].url):
                            current = self.options.tabList[currentTab - 1]
                            finalStringData += current.url + ' ' + current.imagePath + ' ' + str(
                                current.tabNumber) + '\n'
                        else:
                            finalStringData += line
                        currentTab += 1

                    # SEEK BEGINNING -> CLEAR FILE -> WRITE DATA (TRUNCATE SETS FILE SIZE TO MAX (0))
                    f.seek(0)
                    f.truncate(0)
                    f.write(finalStringData)
        self.checkLayouts()

    # CHECK IF ANY LAYOUTS HAVE < 3 CHILDREN APART FROM LAST -> MOVE WIDGETS TO PREVIOUS LAYOUT/ROW ::: IF CURRENT ROW EMPTY -> SET TO PREVIOUS ROW
    def checkLayouts(self):
        # IF ANY LAYOUTS HAVE < 3 CHILDREN REORGANIZE THE WIDGETS
        complete = False
        while not complete:
            for i in range(0, len(self.options.tabRows) - 1):
                if self.options.tabRows[i].count() < 3:
                    child = self.options.tabRows[i + 1].itemAt(0)
                    self.options.tabRows[i + 1].removeItem(child)
                    self.options.tabRows[i].addItem(child)
            complete = True

        # IF CURRENT ROW HAS NO CHILDREN REMOVE IT AND SET IT TO PREVIOUS ROW
        if self.currentRow.count() == 0:
            self.options.tabRows.remove(self.currentRow)
            self.currentRow.deleteLater()
            self.currentRow = self.options.tabRows[len(self.options.tabRows) -
                                                   1]

    # CLEAR ALL TABS IN CURRENT PAGE -> EMPTY TABLIST AND TABROWS -> ARCHIVE ALL DELETED TABS
    def clear(self):
        self.clearingTabs = True

        # REMOVE ENTRY FROM SAVED TABS FILE
        fileData = []
        with open(self.tabFileName, 'r') as inp:
            fileData += inp.readlines()

        for line in fileData:
            currentItems = line.split(' ')
            self.archiveTab(currentItems[0], currentItems[1])

        for i in range(len(self.options.tabList) - 1, -1, -1):
            self.options.tabList[i].setParent(None)
            self.options.tabList[i].deleteLater()
            self.options.tabList.remove(self.options.tabList[i])
        os.remove(self.tabFilePath)
        self.options.tabCount = 0

        # REMOVE ALL ROWS FROM LIST EXCEPT FIRST AND CLEAR TABS
        for x in range(len(self.options.tabRows) - 1, -1, -1):
            if self.options.tabRows[x].count() > 0:
                self.options.tabRows[x].itemAt(0).widget().deleteLater()
            if x == 0: self.options.tabRows[x].destroyed.connect(self.newTab)
            self.options.tabRows[x].deleteLater()
            self.options.tabRows.remove(self.options.tabRows[x])
        self.clearingTabs = False

    # CLEARS ALL TABS BUT DOES NOT REMOVE THEM OR ARCHIVE THEM AND RESETS VARIABLES
    def cleanClear(self):
        for i in reversed(range(len(self.options.tabRows))):
            for j in reversed(range(self.options.tabRows[i].count())):
                self.options.tabRows[i].itemAt(j).widget().setParent(None)

        self.options.tabRows.clear()
        self.options.tabList.clear()
        self.options.emptyTab = None
        self.options.tabCount = 0
        self.options.loadedTabCount = 0

    # RUN AFTER CLEAN CLEAR JUST RELOADS ALL TABS INTO WINDOW
    def cleanLoad(self):
        with open(self.tabFileName, 'r') as f:
            for line in f:
                current = line.split('\n')[0].split(' ')
                url = current[0]
                imagePath = current[1]
                tabNumber = current[2]
                drp = self.newTab()
                drp.load(url, imagePath)
        self.newTab()

    # CHANGE TABS PER ROW IN CURRENT PAGE OPTIONS -> CHANGE MIN WIDTH/HEIGHT -> RELOAD ALL TABS
    def changeTabsPerRow(self, number):
        self.clearingTabs = True
        tabsettings.MIN_TAB_WIDTH *= (self.options.tabsPerRow / number)
        tabsettings.MIN_TAB_HEIGHT *= (self.options.tabsPerRow / number)
        self.options.tabsPerRow = number
        self.cleanClear()
        self.cleanLoad()
        self.clearingTabs = False

    # SET PAGE NAME FROM ENTRY IN PAGENAMES.TXT BY PAGENUMBER
    def setPageName(self):
        if os.path.exists(os.path.join(os.getcwd(), 'pagenames.txt')):
            with open('pagenames.txt', 'r+') as f:
                for index, line in enumerate(f.readlines()):
                    if index + 1 == self.pageNumber:
                        self.pageName = line.split('\n')[0]

    # UPDATE PAGENAMES.TXT -> IF DOESN'T EXIST -> WRITE PAGENAME -> ELSE REWRITE ENTRY TO PAGENAME -> OR IF NEW PAGE WRITE NEW LINE
    def updatePageNames(self):
        if not os.path.exists(os.path.join(os.getcwd(), 'pagenames.txt')):
            with open('pagenames.txt', 'a+') as f:
                f.write(self.pageName + '\n')
        else:
            data = open('pagenames.txt', 'r').readlines()
            # IF NUMBER OF LINES >= NUMBER THEN NAME WILL BE IN FILE
            if len(data) >= self.pageNumber:
                with open('pagenames.txt', 'w') as f:
                    for index, line in enumerate(data):
                        if index + 1 == self.pageNumber:
                            f.write(self.pageName + '\n')
                        else:
                            f.write(line)
            # NAME IS NOT IN FILE SO MUST APPEND IT TO FILE
            else:
                with open('pagenames.txt', 'a') as f:
                    f.write(self.pageName + '\n')

    # SET PAGENAME AND UPDATE PAGENAMES.TXT WITH NEW NAME
    def rename(self, string):
        self.pageName = string
        self.updatePageNames()

    # CHECK IF ARCHIVE TAB FILE SIZE IS GREATER THEN VALUE -> REWRITE OUT FIRST LINES UNTIL ITS DESIRED SIZE
    def checkArchiveTabFileSize(self):
        if os.path.isfile(os.path.join(os.getcwd(), self.archiveTabFileName)):
            data = open(self.archiveTabFileName, 'r').readlines()
            if len(data) > tabsettings.ARCHIVE_TAB_FILE_MAX_SIZE:
                with open(self.archiveTabFileName, 'w') as f:
                    for index, line in enumerate(data):
                        if index != 0 and index <= tabsettings.ARCHIVE_TAB_FILE_MAX_SIZE:
                            f.write(line)

    def close(self):
        self.driver.close()
        self.driver.quit()
        print('Exited')
        sys.exit(0)
コード例 #24
0
class DualEntry(QDialog):
    """ Just a simple Dialog for retrieving 2 values """
    def __init__(self,
                 entry1,
                 entry2,
                 input_type,
                 text,
                 min,
                 max,
                 parent=None):
        """
        Note: Use the static method
        """
        super().__init__(parent=parent)
        self.initUI(entry1, entry2, input_type, text, min, max)

    def initUI(self, entry1, entry2, input_type, text, min, max):
        self.setObjectName('Dialog')
        self.setStyleSheet("font: 10pt \"Arial\";")
        self.setWindowTitle('Input dialog')

        # Setting the parent makes it the default layout
        self.vlayout = QVBoxLayout(self)
        self.vlayout.setObjectName('vlayout')

        self.main_text = QLabel(self)
        self.main_text.setText(text)
        self.vlayout.insertWidget(0, self.main_text)
        self.hlayout = QHBoxLayout()
        self.hlayout.setObjectName('hlayout')
        self.vlayout.insertLayout(1, self.hlayout)

        if input_type is float:
            self.entry1 = QDoubleSpinBox(self)
            self.entry2 = QDoubleSpinBox(self)
        elif input_type is int:
            self.entry1 = QSpinBox(self)
            self.entry2 = QSpinBox(self)
        self.entry1.setMaximum(max)
        self.entry1.setMinimum(min)
        self.entry2.setMaximum(max)
        self.entry2.setMinimum(min)
        self.entry1.setValue(entry1)
        self.entry2.setValue(entry2)

        self.hlayout.insertWidget(0, self.entry1)
        self.hlayout.insertWidget(1, self.entry2)

        self.bb = QDialogButtonBox(self)
        self.bb.setStandardButtons(QDialogButtonBox.Cancel
                                   | QDialogButtonBox.Ok)
        self.bb.accepted.connect(self.accept)
        self.bb.rejected.connect(self.reject)
        self.vlayout.insertWidget(-1, self.bb)
        self.show()

    @staticmethod
    def getDualEntries(entry1,
                       entry2,
                       input_type=float,
                       text='Enter Values:',
                       min=-10000000000,
                       max=10000000000,
                       parent=None):
        """
        Pops up a dialog box that retrieves 2 values, either float or int

        Parameters
        ----------
        entry1: int or float
            Default value in the left box

        entry2: int or float
            Default value in the right box

        input_type : type
            Either float or int are currently supported

        text : str
            Text describing the values to set

        min : int or float
            Minimum value for entries

        max : int or float
            Maximum value for entries

        parent : object or None
            Parent of the Dialog (QDialog) box.

        Returns
        -------
        (numeric, numeric), int
            Returns (left value, right value), Ok pressed. If Ok was pressed, value == 1, else 0.    

        """
        dialog = DualEntry(entry1, entry2, input_type, text, min, max, parent)
        result = dialog.exec_()
        if result:
            return (dialog.entry1.value(), dialog.entry2.value()), result
        else:
            return (), result
コード例 #25
0
class DeviceWidget(QWidget):

    def __init__(self, device):
        super().__init__()

        self._device = device

        self._layout = QVBoxLayout()
        self.setLayout(self._layout)

        self._gb = QGroupBox(self._device.label)

        self._layout.addWidget(self._gb)

        # label to display this device's polling rate
        self._polling_rate_label = QLabel('Polling rate: --')
        self._layout.addWidget(self._polling_rate_label)
        self._layout.addStretch()

        self._gblayout = QVBoxLayout()
        self._gb.setLayout(self._gblayout)

        self._hasMessage = False
        self._retry_time = self._device._retry_time

        self._retry_thread = None

    def show_error_message(self, message=''):
        if not self._hasMessage:

            self._messageframe = QFrame()
            vbox = QVBoxLayout()
            vbox.setContentsMargins(0, 0, 0, 0)
            self._messageframe.setLayout(vbox)

            self._txtmessage = QLabel()
            self._txtmessage.setWordWrap(True)
            vbox.addWidget(self._txtmessage)

            self._txtretry = QLabel('Retrying ...') #in {} seconds...'.format(self._retry_time))
            vbox.addWidget(self._txtretry)

            self._gb.setEnabled(False)
            self._layout.insertWidget(0, self._messageframe)

            self._hbox = QHBoxLayout()
            self._btnRetry = QPushButton('Force Retry')
            self._polling_rate_label.setText('Polling rate: --')
            self._btnRetry.clicked.connect(self.force_retry_connect)
            self._hbox.addStretch()
            self._hbox.addWidget(self._btnRetry)
            self._hbox.addStretch()
            self._layout.insertLayout(3, self._hbox)

            self._hasMessage = True

        self._txtmessage.setText('<font color="red">{}</font>'.format(message))

        if self._retry_thread is not None:
            # probably ok since the thread isn't doing anything critical
            del self._retry_thread

        #self._retry_thread = threading.Thread(target=self.test_update_retry_label, args=())
        #self._retry_thread.start()

    def force_retry_connect(self):
        self._device.unlock()

    '''
    def test_update_retry_label(self):
        for i in range(self._retry_time):
            self._txtretry.setText('Retrying in {} seconds...'.format(self._retry_time - i))
            time.sleep(1)
        self._device.unlock()
        self._txtretry.setText('Retrying')
    '''

    def set_retry_label(self, time):
        self._txtretry.setText('Retrying in {} seconds...'.format(str(time)))

    def hide_error_message(self):
        if self._hasMessage:
            wdg = self._layout.itemAt(0).widget()
            wdg.deleteLater()
            self._gb.setEnabled(True)
            self._hasMessage = False

            self._btnRetry.deleteLater()
            self._hbox.setParent(None)

    @property
    def gblayout(self):
        return self._gblayout
コード例 #26
0
ファイル: tomoebi.py プロジェクト: chao7150/tomoebi
class MyWindow(QWidget):
    """main window"""
    def __init__(self):
        super().__init__()
        self.auths = {}
        self.activeaccounts = []
        self.streams = []
        self.tweets = []
        self.tagarray = []
        self.tweettags = []
        self.receivetags = []
        self.following = []
        self.searchstream = None

        self.init_main()
        self.init_accounts()
        self.init_tweets()
        self.init_widgets()

        self.show()
        sys.exit(app.exec_())

    def init_main(self):
        """options of main window"""
        self.setGeometry(300, 100, 1000, 600)
        self.setWindowTitle("tomoebi")
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_timeline)
        self.timer.start(500)

    def init_tweets(self):
        """create initial tweet"""
        self.tweets = ["start"]

    #initialize widgets
    def init_widgets(self):
        """initialize widgets"""
        #upper half of main window consists of accounts, composer and buttons
        self.compose_vbox = QVBoxLayout()
        self.accounts_hbox = QHBoxLayout()
        self.accbuttons = []
        for a in self.auths:
            accbutton = QPushButton(self)
            accbutton.setWhatsThis(a)
            accbutton.setCheckable(True)
            accbutton.toggled.connect(self.choose_account)
            accbutton.setChecked(True)
            accbutton.setIcon(PyQt5.QtGui.QIcon('images/' + a + '.jpg'))
            accbutton.setIconSize(QSize(48, 48))
            self.accounts_hbox.addWidget(accbutton)
        self.addaccbutton = QPushButton("+", self)
        self.addaccbutton.clicked.connect(self.add_account)
        self.accounts_hbox.addWidget(self.addaccbutton)
        self.composer = ComposeTextEdit(self)
        #self.composer.setPlaceholderText("いまなにしてる?")
        self.composer.setMaximumHeight(60)

        self.compose_hbox = QHBoxLayout()
        self.imagebutton = QPushButton("image", self)
        self.submitbutton = QPushButton("tweet", self)
        self.submitbutton.clicked.connect(self.submit)

        self.hashtag_hbox = QHBoxLayout()
        self.hashtagedit = QLineEdit(self)
        self.hashtagedit.setPlaceholderText("hashtags")
        self.hashtagbutton = QPushButton("set")
        self.hashtagbutton.setCheckable(True)
        self.hashtagbutton.toggled.connect(self.sethashtag)
        self.hashtag_hbox.addWidget(self.hashtagedit)
        self.hashtag_hbox.addWidget(self.hashtagbutton)

        self.compose_hbox.addWidget(self.imagebutton)
        self.compose_hbox.addWidget(self.submitbutton)
        self.compose_vbox.addLayout(self.accounts_hbox)
        self.compose_vbox.addWidget(self.composer)
        self.compose_vbox.addLayout(self.compose_hbox)
        self.compose_vbox.addLayout(self.hashtag_hbox)

        #lower half of main window consists of timeline
        l = QTextEdit()
        l.setPlainText(self.tweets[0])
        l.setReadOnly(True)
        l.setFixedHeight(350)
        self.inner = QWidget()
        self.timeline_vbox = QVBoxLayout(self.inner)
        self.timeline_vbox.addWidget(l)
        self.tweets = []
        self.timeline_vbox.addStretch()
        self.scroll = QScrollArea()
        self.scroll.setWidgetResizable(True)
        self.scroll.setWidget(self.inner)

        #integrate upper and lower part of main window
        self.whole_vbox = QVBoxLayout()
        self.whole_vbox.addLayout(self.compose_vbox)
        self.whole_vbox.addWidget(self.scroll)

        #right half of the main window
        self.image_collumn = QVBoxLayout()
        self.imageinner = QWidget()
        self.imagetimeline = QVBoxLayout(self.imageinner)
        self.imagescroll = QScrollArea()
        self.imagescroll.setWidgetResizable(True)
        self.imagescroll.setWidget(self.imageinner)
        self.imagetext = QTextEdit()
        self.imagetext.setMaximumHeight(60)
        self.imagetext.setReadOnly(True)
        self.image_collumn.addWidget(self.imagetext)
        self.image_collumn.addWidget(self.imagescroll)

        self.whole_hbox = QHBoxLayout()
        self.whole_hbox.addLayout(self.whole_vbox)
        self.whole_hbox.addLayout(self.image_collumn)
        self.setLayout(self.whole_hbox)

    #initialize registered accounts
    def init_accounts(self):
        """load account AT and AS from local and create api object and stream"""
        if not os.path.exists("images"):
            os.mkdir("images")
        if os.path.isfile("auth.json"):
            with open('auth.json', 'r') as f:
                authdic = json.load(f)
            for name, keys in authdic["Twitter"].items():
                api = twitter.connect(keys["ACCESS_TOKEN"],
                                      keys["ACCESS_SECRET"])
                self.auths[name] = api
                #self.following = self.following + api.friends_ids(k)
                self.streams.append(
                    twitter.open_userstream(api, self.receive_tweet, name))
                if not os.path.isfile("images/" + name + ".jpg"):
                    twitter.getmyicon(api, name)
            #twitter.open_filterstream(self.auths["XXXX"], self.receive_tweet,
            #  "XXXX", [str(x) for x in self.following])
        else:
            default = {"Twitter": {}, "Mastodon": {}}
            with open('auth.json', 'w') as f:
                json.dump(default, f, indent=2)
            self.authdic = {}

    def add_account(self):
        """add account and register it to local file"""
        api, screen_name = twitter.authentication()
        self.auths[screen_name] = api
        self.streams.append(
            twitter.open_userstream(api, self.receive_tweet, screen_name))
        twitter.getmyicon(api, screen_name)
        accbutton = QPushButton(self)
        accbutton.setWhatsThis(screen_name)
        accbutton.setCheckable(True)
        accbutton.toggled.connect(self.choose_account)
        accbutton.setIcon(PyQt5.QtGui.QIcon('images/' + screen_name + '.jpg'))
        accbutton.setIconSize(QSize(48, 48))
        self.accounts_hbox.insertWidget(self.accounts_hbox.count() - 1,
                                        accbutton)

    def choose_account(self):
        """
        called when accbutton are toggled.
        add or remove active accounts
        """
        acc = self.sender()
        if acc.isChecked():
            self.activeaccounts.append(acc.whatsThis())
        else:
            self.activeaccounts.remove(acc.whatsThis())

    def receive_tweet(self, status, name, icon):
        """called when stream receive a tweet"""
        self.tweets.append((status, name, icon))

    def update_timeline(self):
        """called every 500ms and update gui timeline according to self.tweets"""
        for t in self.tweets:
            if hasattr(t[0], "in_reply_to_status_id"):
                self.addTweet(*t)
            elif hasattr(t[0], "event"):
                self.addEvent(*t)
        self.tweets = []

    def addTweet(self, t, name, icon):
        rtby = None
        if hasattr(t, "retweeted_status"):
            rtby = [t.user.profile_image_url_https, t.user.screen_name]
            t = t.retweeted_status
        tweet = self.create_tweet(t)
        tweet_hbox = QHBoxLayout()
        if icon:
            if not glob.glob("images/" + t.user.screen_name + ".*"):
                twitter.geticon(t.user.profile_image_url_https,
                                t.user.screen_name)
            icon = PyQt5.QtGui.QPixmap(
                glob.glob("images/" + t.user.screen_name + ".*")[0])
            scaled_icon = icon.scaled(QSize(48, 48), 1, 1)
            iconviewer = IconLabel(t.id, name, self.retweet, self.reply)
            iconviewer.setPixmap(scaled_icon)
            icon_vbox = QVBoxLayout()
            icon_vbox.addWidget(iconviewer, alignment=Qt.AlignTop)
            if rtby:
                if not glob.glob("images/" + rtby[1] + ".*"):
                    twitter.geticon(*rtby)
                icon = PyQt5.QtGui.QPixmap(
                    glob.glob("images/" + rtby[1] + ".*")[0])
                scaled_icon = icon.scaled(QSize(24, 24), 1, 1)
                rticonviewer = QLabel()
                rticonviewer.setPixmap(scaled_icon)
                rticon_hbox = QHBoxLayout()
                #rticon_hbox.addStretch()
                rticon_hbox.addWidget(rticonviewer,
                                      alignment=(Qt.AlignRight | Qt.AlignTop))
                icon_vbox.addLayout(rticon_hbox)
                icon_vbox.addStretch()
            tweet_hbox.addLayout(icon_vbox)
        tweet_hbox.addWidget(tweet)
        favbutton = QPushButton("fav")
        favbutton.setSizePolicy(QSizePolicy.MinimumExpanding,
                                QSizePolicy.MinimumExpanding)
        favbutton.setCheckable(True)
        favbutton.toggled.connect(lambda: self.fav(t.id, name))
        tweet_hbox.addWidget(favbutton)
        self.timeline_vbox.insertLayout(0, tweet_hbox)
        if "media" in t.entities:
            images = twitter.get_allimages(self.auths[name], t.id)
            self.imagetext.setPlainText("@" + t.user.screen_name + "\n" +
                                        t.text)
            for n, _ in enumerate(images):
                pixmap = PyQt5.QtGui.QPixmap()
                pixmap.loadFromData(QByteArray(images[n]))
                scaled = pixmap.scaled(QSize(320, 180), 1, 1)
                imageviewer = QLabel()
                imageviewer.setPixmap(scaled)
                self.imagetimeline.insertWidget(0, imageviewer)

    def addEvent(self, t, name, icon):
        if t.event == "favorite" and not (t.source["screen_name"]
                                          in self.auths.keys()):
            text = t.source["screen_name"] + " favored " + t.target_object[
                "text"]
            favLabel = QLabel(text)
            self.timeline_vbox.insertWidget(0, favLabel)

    def create_tweet(self, t):
        """create tweet widget"""
        text = "@" + t.user.screen_name + "\n" + t.text
        tweetdocument = PyQt5.QtGui.QTextDocument()
        tweetdocument.setTextWidth(
            300)  #this line is not working so it needs to be fixed someday
        tweetdocument.setPlainText(text)
        tweettext = QTextEdit()
        tweettext.setDocument(tweetdocument)
        tweettext.setReadOnly(True)
        tweettext.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        tweettext.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        tweettext.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
        tweettext.setAttribute(103)
        tweettext.show()
        tweettext.setFixedHeight(tweettext.document().size().height() +
                                 tweettext.contentsMargins().top() * 2)
        return tweettext

    def submit(self):
        """called when tweet button is pressed and submit tweet"""
        if not self.activeaccounts:
            return
        submittext = self.composer.toPlainText()
        for t in self.tweettags:
            submittext = submittext + " " + t
        if not submittext:
            return
        for a in self.activeaccounts:
            self.auths[a].update_status(submittext)
        self.composer.setPlainText("")

    def fav(self, tweetid, name):
        '''favor or unfavor a tweet from an account from which the tweet was obtained'''
        switch = self.sender()
        if switch.isChecked():
            try:
                self.auths[name].create_favorite(tweetid)
            except:
                print("already favored")
        else:
            try:
                self.auths[name].destroy_favorite(tweetid)
            except:
                print("not favored")

    def retweet(self, id, account):
        self.auths[account].retweet(id)

    def reply(self, id, account):
        if not self.activeaccounts:
            return
        submittext = self.composer.toPlainText()
        if not submittext:
            return
        self.auths[account].update_status(submittext,
                                          in_reply_to_status_id=id,
                                          auto_populate_reply_metadata=True)
        self.composer.setPlainText("")

    def sethashtag(self):
        """set hashtab for receive and tweet"""
        switch = self.sender()
        if switch.isChecked():
            htinput = self.hashtagedit.text()
            htlist = htinput.strip().split()
            for t in htlist:
                if not t[0] == "*":
                    self.receivetags.append(t)
                    self.tweettags.append(t)
                else:
                    self.receivetags.append(t[1:])
            repl_screen_name = list(self.auths.keys())[0]
            self.searchstream = twitter.open_filterstream(
                self.auths[repl_screen_name], self.receive_tweet,
                repl_screen_name, self.receivetags)
        else:
            self.receivetags = []
            self.tweettags = []
            self.searchstream.disconnect()

    def closeEvent(self, event):
        """called when gui window is closed and terminate all streams and thread"""
        for s in self.streams:
            s.disconnect()
        os._exit(1)
コード例 #27
0
    def initUI(self):
        self.card_amount_label = QLabel("With how many cards will you play: ")
        self.player_one_label = QLabel("What's the first players name: ")
        self.player_two_label = QLabel("What's the second players name: ")
        self.statistics_label = QLabel("Some game statistics:")
        self.games_started_label = QLabel(
            "The amount of games started: " +
            str(get_game_statistic("started_games")))
        self.games_finished_label = QLabel(
            "The amount of games finished: " +
            str(get_game_statistic("finished_games")))

        self.go_back_to_setup_button = QPushButton("Go to Setup")

        self.card_amount_options = QComboBox()
        self.card_amount_options.addItems(["4", "8", "10", "16", "36"])
        self.card_amount_options.setCurrentText(
            get_game_setting("playfield_size"))
        self.card_amount_options.currentIndexChanged.connect(
            self.card_selection_change)

        self.player_one_name_line_edit = QLineEdit()
        self.player_one_name_line_edit.setText(
            get_game_setting("player_one_name"))
        self.player_one_name_line_edit.setMaxLength(30)
        self.player_one_name_line_edit.setAlignment(Qt.AlignLeft)
        self.player_one_name_line_edit.textChanged.connect(
            self.player_one_name_changed)

        self.player_two_name_line_edit = QLineEdit()
        self.player_two_name_line_edit.setText(
            get_game_setting("player_two_name"))
        self.player_two_name_line_edit.setMaxLength(30)
        self.player_two_name_line_edit.setAlignment(Qt.AlignLeft)
        self.player_two_name_line_edit.textChanged.connect(
            self.player_two_name_changed)

        horizontal_go_back_to_setup_gui_box = QHBoxLayout()
        horizontal_go_back_to_setup_gui_box.addWidget(
            self.go_back_to_setup_button)
        horizontal_go_back_to_setup_gui_box.addStretch()

        horizontal_player_one_name_box = QHBoxLayout()
        horizontal_player_one_name_box.addWidget(self.player_one_label)
        horizontal_player_one_name_box.addWidget(
            self.player_one_name_line_edit)

        horizontal_player_two_name_box = QHBoxLayout()
        horizontal_player_two_name_box.addWidget(self.player_two_label)
        horizontal_player_two_name_box.addWidget(
            self.player_two_name_line_edit)

        horizontal_card_amount_box = QHBoxLayout()
        horizontal_card_amount_box.addWidget(self.card_amount_label)
        horizontal_card_amount_box.addWidget(self.card_amount_options)
        horizontal_card_amount_box.addStretch()

        horizontal_game_statistics_box = QHBoxLayout()
        horizontal_game_statistics_box.addWidget(self.statistics_label)
        horizontal_game_statistics_box.addStretch()

        horizontal_games_started_box = QHBoxLayout()
        horizontal_games_started_box.addWidget(self.games_started_label)
        horizontal_games_started_box.addStretch()

        horizontal_games_finished_box = QHBoxLayout()
        horizontal_games_finished_box.addWidget(self.games_finished_label)
        horizontal_games_finished_box.addStretch()

        vertical_box = QVBoxLayout()
        vertical_box.insertLayout(1, horizontal_go_back_to_setup_gui_box)
        vertical_box.insertLayout(2, horizontal_card_amount_box)
        vertical_box.insertLayout(3, horizontal_player_one_name_box)
        vertical_box.insertLayout(4, horizontal_player_two_name_box)
        vertical_box.addSpacing(20)
        vertical_box.insertLayout(5, horizontal_game_statistics_box)
        vertical_box.insertLayout(6, horizontal_games_started_box)
        vertical_box.insertLayout(7, horizontal_games_finished_box)
        vertical_box.addStretch()

        self.setLayout(vertical_box)
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)