class NewRelationDialog(QDialog):

    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle(self.tr("Nueva Relación"))
        vbox = QVBoxLayout(self)
        hbox = QHBoxLayout()
        self._line_relation_name = QLineEdit()
        hbox.addWidget(QLabel(self.tr("Nombre:")))
        hbox.addWidget(self._line_relation_name)
        vbox.addLayout(hbox)

        vbox.addWidget(QLabel(
            self.tr("La primera fila corresponde a los campos")))

        hbox = QHBoxLayout()
        btn_add_column = QPushButton(self.tr("Agregar Columna"))
        hbox.addWidget(btn_add_column)
        btn_add_tuple = QPushButton(self.tr("Agregar Tupla"))
        hbox.addWidget(btn_add_tuple)
        btn_remove_column = QPushButton(self.tr("Eliminar Columna"))
        hbox.addWidget(btn_remove_column)
        btn_remove_tuple = QPushButton(self.tr("Eliminar Tupla"))
        hbox.addWidget(btn_remove_tuple)
        vbox.addLayout(hbox)

        self._table = QTableWidget()
        vbox.addWidget(self._table)
        self._table.setRowCount(1)
        self._table.setColumnCount(2)
        self._table.setItem(0, 0, QTableWidgetItem("Campo 1"))
        self._table.setItem(0, 1, QTableWidgetItem("Campo 2"))

        hbox = QHBoxLayout()
        hbox.addItem(QSpacerItem(1, 0, QSizePolicy.Expanding))
        btn_ok = QPushButton(self.tr("Aceptar"))
        hbox.addWidget(btn_ok)
        btn_cancel = QPushButton(self.tr("Cancelar"))
        hbox.addWidget(btn_cancel)
        vbox.addLayout(hbox)

        # Connections
        self.connect(btn_add_column, SIGNAL("clicked()"),
            self.__add_column)
        self.connect(btn_remove_column, SIGNAL("clicked()"),
            self.__remove_column)
        self.connect(btn_add_tuple, SIGNAL("clicked()"),
            self.__add_tuple)
        self.connect(btn_remove_tuple, SIGNAL("clicked()"),
            self.__remove_tuple)
        self.connect(btn_ok, SIGNAL("clicked()"),
            self.__create_table)
        self.connect(btn_cancel, SIGNAL("clicked()"),
            self.close)

    def __add_column(self):
        columns = self._table.columnCount()
        self._table.insertColumn(columns)

    def __remove_column(self):
        current = self._table.currentColumn()
        self._table.removeColumn(current)

    def __add_tuple(self):
        tuples = self._table.rowCount()
        self._table.insertRow(tuples)

    def __remove_tuple(self):
        current = self._table.currentRow()
        self._table.removeRow(current)

    def __create_table(self):
        # Name of relation
        name = self._line_relation_name.text()
        if not name.strip():
            QMessageBox.critical(self, self.tr("Error"),
                                 self.tr("Nombre de relación no especificado"))
            return
        rows = self._table.rowCount()
        columns = self._table.columnCount()

        rel = relation.Relation()
        # Header of relation
        fields = []
        for i in range(columns):
            text = self._table.item(0, i).text()
            if not text.strip():
                QMessageBox.critical(self, self.tr("Error"),
                                     self.tr("Nombre de campo inválido"))
                return
            fields.append(text)

        rel.fields = fields

        # Data
        data = {}
        for row in range(1, rows):
            reg = []
            for column in range(columns):
                item = self._table.item(row, column)
                if item is None or not item.text().strip():
                    QMessageBox.critical(self, self.tr("Campo vacío"),
                                         self.tr("El campo {0}:{1} está "
                                         "vacío").format(row + 1, column + 1))
                    return
                reg.append(self._table.item(row, column).text())
                data[row, column] = self._table.item(row, column).text()
            rel.insert(reg)
        # Add table and relation
        table_widget = Pireal.get_service("container").table_widget
        table_widget.add_table(rows - 1, columns, name, data, fields)
        table_widget.relations[name] = rel

        self.close()
Beispiel #2
0
class ApBbaDlg(QDialog):
    def __init__(self, parent=None, **kwargs):
        super(ApBbaDlg, self).__init__(parent)

        self.bpms = []
        self.quads = []
        self.corrs = []
        self.quad_dkicks = []
        self.cor_dkicks = []

        self.bba = ap.bba.BbaBowtie()

        self.table = QTableWidget(0, 5)
        self.table.setMinimumHeight(120)
        self.table.setMinimumWidth(500)
        self.table.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        hdview = QHeaderView(Qt.Horizontal)
        self.table.setHorizontalHeaderLabels(
            ['QUAD', 'BPM.field', 'BPM center', "Corr", "Kick"])

        fmbox = QFormLayout()
        self.subprogress = QProgressBar()
        self.subprogress.setTextVisible(True)
        self.subprogress.setSizePolicy(QSizePolicy.MinimumExpanding,
                                       QSizePolicy.Fixed)
        self.progress = QProgressBar()
        self.progress.setTextVisible(True)
        self.progress.setSizePolicy(QSizePolicy.MinimumExpanding,
                                    QSizePolicy.Fixed)
        fmbox.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
        fmbox.addRow("Current BPM", self.subprogress)
        fmbox.addRow("All Alignment", self.progress)
        #self.progress.setMaximum(self.repeatbox.value())
        vbox = QVBoxLayout()
        vbox.addWidget(self.table)
        vbox.addLayout(fmbox)

        #hbox.addStretch()
        self.widtab = QTabWidget()

        vbox.addWidget(self.widtab)

        self.setLayout(vbox)

        self.connect(self.widtab, SIGNAL("currentChanged(int)"),
                     self.activateResult)
        self.connect(self.table, SIGNAL("cellClicked(int, int)"),
                     self.activateResult)
        #self.bbathread = ApBbaThread()
        #self.connect(self.bbathread,
        #             SIGNAL("aligned(QString, QString, float, float)"),
        #             self.setResult)
        #self.connect(self.bbathread,
        #             SIGNAL("startAlign(QString, QString, QString)"),
        #             self.appendRecord)

        #self.connect(self.bbathread,
        #             SIGNAL("aligned(QString, QString, float, float)"),
        #             self.bbadlg.appendResult)

    def setInput(self, **kwargs):
        self.bpms = kwargs.get('bpms', [])
        self.quads = kwargs.get('quads', [])
        self.cors = kwargs.get('cors', [])
        self.quad_dkicks = kwargs.get('quad_dkicks', [])
        self.cor_dkicks = kwargs.get('cor_dkicks', [])

    def runAlignment(self, **kwargs):
        self.setInput(**kwargs)
        #self.bbathread.start()
        print "Starting %d measurements" % len(self.bpms)
        self.progress.setMaximum(len(self.bpms))
        self.subprogress.setMaximum(100)
        from cothread.catools import caget, caput
        print __file__, "BBA align", caget('V:2-SR:C30-BI:G2{PH1:11}SA:X')
        self.table.setRowCount(len(self.bpms))
        for i, bpmrec in enumerate(self.bpms):
            print i, bpmrec[0].name, self.quads[i][0].name
            self.bba.setInput(bpmrec, self.quads[i], self.cors[i],
                              self.quad_dkicks[i], self.cor_dkicks[i])
            #self.emit(SIGNAL("startAlign(QString, QString, QString)"),
            #          self.quads[i][0].name, bpmrec[0].name, bpmrec[1])
            self.setNames(i, self.quads[i][0].name, bpmrec[0].name, bpmrec[1],
                          self.cors[i][0].name)
            self.bba.align(verbose=2,
                           guihook=QApplication.processEvents,
                           logger=None,
                           progress=self.subprogress)

            cv1 = BbaMplCanvas()
            cv2 = BbaMplCanvas()
            self.bba.plot(cv1.axes, cv2.axes, factor=(1e6, 1e6))
            cv1.draw()
            cv2.draw()

            wid = QWidget(self)
            hbox = QHBoxLayout()
            hbox.addWidget(cv1)
            hbox.addWidget(cv2)
            wid.setLayout(hbox)
            self.widtab.addTab(wid, "%s.%s" % (bpmrec[0].name, bpmrec[1]))
            self.widtab.setCurrentIndex(i)

            #time.sleep(.1)

            #self.emit(SIGNAL("aligned(QString, QString, float, float)"),
            #          bpmrec[0].name, bpmrec[1], 0.0, 0.0)
            self.setResult(i, bpmrec[0].name, bpmrec[1], self.bba.bpm_fitted,
                           self.bba.cor_fitted)
            self.progress.setValue(i + 1)

    def activateResult(self, i=0, j=0):
        if i < self.widtab.count() and i != self.widtab.currentIndex():
            self.widtab.setCurrentIndex(i)
        if i < self.table.rowCount() and i != self.table.currentRow():
            self.table.setCurrentCell(i, 1)

    def setNames(self, i, quadname, bpmname, fld, corname):
        self.table.setItem(i, 0, QTableWidgetItem(quadname))
        self.table.setItem(i, 1,
                           QTableWidgetItem("{0}.{1}".format(bpmname, fld)))
        self.table.setItem(i, 3, QTableWidgetItem(corname))

    def setResult(self, i, bpmname, fld, bpmval, corval):
        #self.table.setItem(n, 1, QTableWidgetItem(bpmname))
        #self.table.setItem(n, 2, QTableWidgetItem(fld))
        self.table.setItem(i, 2, QTableWidgetItem("%g" % bpmval))
        self.table.setItem(i, 4, QTableWidgetItem("%g" % corval))
        self.table.setCurrentCell(i, 1)
class WellMarkerDialog(QDialog):
    def __init__(self, well):
        super(WellMarkerDialog, self).__init__()
        self.well = well
        self.setupUi()
        self.initUI()
        self.button_box.accepted.connect(self.save_markers)
        self.button_box.rejected.connect(self.close)
        self.add_Button.clicked.connect(self.add_row)
        self.del_Button.clicked.connect(self.del_row)
        self.export_Button.clicked.connect(self.export_markers)
        self.import_Button.clicked.connect(self.import_markers)

    def setupUi(self):
        self.resize(568, 411)
        self.setWindowIcon(QIcon(':/icon/layer_icon'))
        self.setWindowTitle("Edit Markers")
        self.gridLayout = QGridLayout(self)
        # table widget
        self.tableWidget = QTableWidget(self)
        self.tableWidget.setColumnCount(4)
        self.tableWidget.setRowCount(0)
        self.tableWidget.setHorizontalHeaderItem(0, QTableWidgetItem("Name"))
        self.tableWidget.setHorizontalHeaderItem(1,
                                                 QTableWidgetItem("TVD (m)"))
        self.tableWidget.setHorizontalHeaderItem(2,
                                                 QTableWidgetItem("TVDSS (m)"))
        self.tableWidget.setHorizontalHeaderItem(3, QTableWidgetItem("Color"))
        self.gridLayout.addWidget(self.tableWidget, 0, 0, 1, 1)
        # button box
        self.button_box = QDialogButtonBox(self)
        self.export_Button = self.button_box.addButton(
            "Export", QDialogButtonBox.ResetRole)
        self.import_Button = self.button_box.addButton(
            "Import", QDialogButtonBox.ResetRole)
        self.add_Button = self.button_box.addButton("Add",
                                                    QDialogButtonBox.ResetRole)
        self.del_Button = self.button_box.addButton("Del",
                                                    QDialogButtonBox.ResetRole)
        self.button_box.setStandardButtons(QDialogButtonBox.Save
                                           | QDialogButtonBox.Cancel)
        self.gridLayout.addWidget(self.button_box, 1, 0, 1, 1)

    def initUI(self):
        self.populate_marker_table()

    def populate_marker_table(self):
        try:
            markers_dict = self.well.params["horizon"]
            for mark in markers_dict.keys():
                self.tableWidget.insertRow(0)
                self.tableWidget.setItem(0, 0, QTableWidgetItem(mark))
                self.tableWidget.setItem(
                    0, 1, QTableWidgetItem(str(markers_dict[mark])))
                self.tableWidget.setItem(
                    0, 2, QTableWidgetItem(str(markers_dict[mark])))
            self.tableWidget.sortItems(0, Qt.AscendingOrder)
        except KeyError:
            pass

    def add_row(self):
        self.tableWidget.insertRow(self.tableWidget.rowCount())

    def del_row(self):
        self.tableWidget.removeRow(self.tableWidget.currentRow())

    def save_markers(self):
        l_names = [str(self.tableWidget.item(irow, 0).text()) \
            for irow in range(self.tableWidget.rowCount())]
        l_md = [float(self.tableWidget.item(irow, 1).text()) \
            for irow in range(self.tableWidget.rowCount())]
        new_dict = OrderedDict([(a, b) for a, b in zip(l_names, l_md)])
        if self.well.params['horizon'] != new_dict:
            respond = QMessageBox.question(
                self, "Save Markers", "Sure to save changes?",
                QMessageBox.Save | QMessageBox.Cancel)
            if respond == QMessageBox.Save:
                self.well.params['horizon'] = new_dict
                self.well.save_params()
        self.close()

    def export_markers(self):
        file_path = str(QFileDialog.getSaveFileName(self, "Save Markers"))
        l_names = [str(self.tableWidget.item(irow, 0).text()) \
            for irow in range(self.tableWidget.rowCount())]
        l_md = [float(self.tableWidget.item(irow, 1).text()) \
            for irow in range(self.tableWidget.rowCount())]
        df = pd.DataFrame({"name": l_names, "MD(m)": l_md})
        df.to_csv(file_path, sep='\t', columns=["name", "MD(m)"], index=False)
        QMessageBox.information(self, "Export Markers", "Succeed!")

    def import_markers(self):
        read_csv_dialog = ReadCsvDialog()
        read_csv_dialog.setWindowIcon(QIcon(':/icon/layer_icon'))
        read_csv_dialog.setWindowTitle("Open Markers File")
        read_csv_dialog.label.setText("Read Makers from File")
        read_csv_dialog.exec_()
Beispiel #4
0
class KeywordTable(HelpedWidget):
    """Shows a table of key/value pairs. The data structure expected and sent to the getter and setter is a dictionary of values."""
    def __init__(self, model, table_label="", help_link=""):
        HelpedWidget.__init__(self, table_label, help_link)

        self.table = QTableWidget(self)
        self.table.setColumnCount(2)
        self.setColumnHeaders()
        self.table.verticalHeader().setHidden(True)
        self.table.setColumnWidth(0, 150)
        self.table.horizontalHeader().setStretchLastSection(True)

        self.table.setMinimumHeight(110)
        self.table.setSelectionMode(QAbstractItemView.SingleSelection)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)

        self.addWidget(self.table)

        self.addWidget(AddRemoveWidget(self.addItem, self.removeItem))

        self.connect(self.table, SIGNAL('cellChanged(int,int)'), self.tableChanged)

        assert isinstance(model, DictionaryModelMixin)
        self.model = model
        model.observable().attach(DictionaryModelMixin.DICTIONARY_CHANGED_EVENT, self.modelChanged)
        self.modelChanged()


    def setColumnHeaders(self, keyword_name="Keyword", value_name="Value"):
        self.headers = [keyword_name, value_name]
        self.table.setHorizontalHeaderLabels(self.headers)

    def addItem(self):
        """Called by the add button to insert a new keyword"""
        title = "New %s" % self.headers[0]
        description = "Enter new %s:" % self.headers[0]
        (new_keyword, ok) = QInputDialog.getText(self, title, description, QLineEdit.Normal)

        if ok:
            new_keyword = str(new_keyword).strip()
            self.model.addKey(new_keyword)

    def removeItem(self):
        """Called by the remove button to remove a selected keyword"""
        current_row = self.table.currentRow()

        if current_row >= 0:
            do_delete = QMessageBox.question(self, "Delete row?", "Are you sure you want to delete the key/value pair?", QMessageBox.Yes | QMessageBox.No )

            if do_delete:
                key_item = self.table.item(current_row, 0)
                if key_item is not None:
                    key = str(key_item.text()).strip()
                    self.model.removeKey(key)


    def tableChanged(self, row, column):
        """Called whenever the contents of a cell changes."""
        key_item = self.table.item(row, 0)

        if key_item is not None:
            key = str(key_item.text()).strip()
            value_item = self.table.item(row, 1)

            if value_item is not None:
                value = str(value_item.text()).strip()

                self.model.setValueForKey(key, value)


    def modelChanged(self):
        """Retrieves data from the model and inserts it into the table."""
        values = self.model.getDictionary()

        blocked = self.table.blockSignals(True)

        for row in reversed(range(self.table.rowCount())):
            self.table.removeRow(row)

        row = 0
        for key in values:
            key_item = QTableWidgetItem(str(key))
            key_item.setFlags(key_item.flags() ^ Qt.ItemIsEditable)
            value_item = QTableWidgetItem(str(values[key]))
            self.table.insertRow(row)
            self.table.setItem(row, 0, key_item)
            self.table.setItem(row, 1, value_item)
            row += 1

        self.table.blockSignals(blocked)
class NewRelationDialog(QDialog):

    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle(self.tr("Nueva Relación"))
        vbox = QVBoxLayout(self)
        hbox = QHBoxLayout()
        self._line_relation_name = QLineEdit()
        hbox.addWidget(QLabel(self.tr("Nombre:")))
        hbox.addWidget(self._line_relation_name)
        vbox.addLayout(hbox)

        vbox.addWidget(QLabel(
            self.tr("La primera fila corresponde a los campos")))

        hbox = QHBoxLayout()
        btn_add_column = QPushButton(self.tr("Agregar Columna"))
        hbox.addWidget(btn_add_column)
        btn_add_tuple = QPushButton(self.tr("Agregar Tupla"))
        hbox.addWidget(btn_add_tuple)
        btn_remove_column = QPushButton(self.tr("Eliminar Columna"))
        hbox.addWidget(btn_remove_column)
        btn_remove_tuple = QPushButton(self.tr("Eliminar Tupla"))
        hbox.addWidget(btn_remove_tuple)
        vbox.addLayout(hbox)

        self._table = QTableWidget()
        vbox.addWidget(self._table)
        self._table.setRowCount(1)
        self._table.setColumnCount(2)
        self._table.setItem(0, 0, QTableWidgetItem("Campo 1"))
        self._table.setItem(0, 1, QTableWidgetItem("Campo 2"))

        hbox = QHBoxLayout()
        hbox.addItem(QSpacerItem(1, 0, QSizePolicy.Expanding))
        btn_ok = QPushButton(self.tr("Aceptar"))
        hbox.addWidget(btn_ok)
        btn_cancel = QPushButton(self.tr("Cancelar"))
        hbox.addWidget(btn_cancel)
        vbox.addLayout(hbox)

        # Connections
        self.connect(btn_add_column, SIGNAL("clicked()"),
            self.__add_column)
        self.connect(btn_remove_column, SIGNAL("clicked()"),
            self.__remove_column)
        self.connect(btn_add_tuple, SIGNAL("clicked()"),
            self.__add_tuple)
        self.connect(btn_remove_tuple, SIGNAL("clicked()"),
            self.__remove_tuple)
        self.connect(btn_ok, SIGNAL("clicked()"),
            self.__create_table)
        self.connect(btn_cancel, SIGNAL("clicked()"),
            self.close)

    def __add_column(self):
        columns = self._table.columnCount()
        self._table.insertColumn(columns)

    def __remove_column(self):
        current = self._table.currentColumn()
        self._table.removeColumn(current)

    def __add_tuple(self):
        tuples = self._table.rowCount()
        self._table.insertRow(tuples)

    def __remove_tuple(self):
        current = self._table.currentRow()
        self._table.removeRow(current)

    def __create_table(self):
        name = self._line_relation_name.text()
        rows = self._table.rowCount()
        columns = self._table.columnCount()

        rel = relation.Relation()
        fields = [self._table.item(0, i).text() for i in range(columns)]
        rel.fields = fields

        data = {}
        for row in range(1, rows):
            reg = []
            for column in range(columns):
                reg.append(self._table.item(row, column).text())
                data[row, column] = self._table.item(row, column).text()
            rel.insert(reg)
        table_widget = Pireal.get_service("container").table_widget
        table_widget.add_table(rows - 1, columns, name, data)
        #table_widget.relations[name] = rel

        self.close()
class FilesUIManager(QWidget):

    def __init__(self, winged, pref):
        QWidget.__init__(self)
        self.winged = winged
        self.pref = pref
        self._vbox = QVBoxLayout(self)
        self._hbox = QHBoxLayout()
        self._table = QTableWidget(1, 3)
        self._table.setHorizontalHeaderLabels(['Access', 'File Name', 'Size'])
        self._table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self._table.verticalHeader().hide()
        self._table.removeRow(0)
        self._table.setColumnWidth(0, 80)
        self._table.setColumnWidth(1, 480)
        self._hbox.addWidget(self._table)

        self._btnDownload = QPushButton(QIcon(config.images['download']), '')
        self._btnDownload.setToolTip('Download')
        self._btnFacebook = QPushButton(QIcon(config.images['facebook']), '')
        self._btnFacebook.setToolTip('Share on Facebook')
        self._btnTwitter = QPushButton(QIcon(config.images['twitter']), '')
        self._btnTwitter.setToolTip('Share on Twitter')
        self._btnLink = QPushButton(QIcon(config.images['link']), '')
        self._btnLink.setToolTip('Copy Link')
        self.connect(self._btnDownload, SIGNAL("clicked()"), self._save)
        self.connect(self._btnFacebook, SIGNAL("clicked()"), self._facebook)
        self.connect(self._btnTwitter, SIGNAL("clicked()"), self._twitter)
        self.connect(self._btnLink, SIGNAL("clicked()"), self._copy_link)

    def _save(self):
        file_ = self._files[self._table.currentRow()]
        if file_['accesibility'] == '2':
            if self.pref.get('ask', True):
                folderName = str(QFileDialog.getExistingDirectory(self, 'Save File in...'))
            else:
                folderName = self.pref.get('folder', '')
            if folderName != '':
                self.winged.save_file(file_, folderName)
        else:
            QMessageBox.information(self, 'Download Fail', 'You can only download public files\nwith WingedBox-Client.')

    def _facebook(self):
        file_ = self._files[self._table.currentRow()]
        self.winged.thread.api.facebook(file_)

    def _twitter(self):
        file_ = self._files[self._table.currentRow()]
        self.winged.thread.api.twitter(file_)

    def _copy_link(self):
        clipboard = QApplication.clipboard()
        file = self._files[self._table.currentRow()]
        clipboard.setText('http://wingedbox.com/downloads/' + file['id'] + "-" + file['file-name'])

    def find(self, text):
        items = self._table.findItems(text, Qt.MatchContains)
        rows = [i.row() for i in items]
        rowsCount = range(self._table.rowCount())
        rowsCount.reverse()
        for i in rowsCount:
            if i not in rows:
                self._table.removeRow(i)

    def load_table(self, files):
        self._files = files
        r = 0
        for file in files:
            self._table.insertRow(r)
            if len(file['name']) > 0:
                item = QTableWidgetItem(file['name'])
            else:
                item = QTableWidgetItem(file['file-name'])
            item.setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            self._table.setItem(r, 1, item)
            item = QTableWidgetItem(str(file['file-size'] / 1024) + ' kb')
            item.setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            self._table.setItem(r, 2, item)
            imageFile = config.type.get(file['type'], config.typeBlank)
            access = config.access[file['accesibility']]
            item = QTableWidgetItem(QIcon(imageFile), access[3])
            item.setBackgroundColor(QColor(access[0], access[1], access[2]))
            item.setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            self._table.setItem(r, 0, item)
            r += 1
        self._table.resizeRowsToContents()
        self._table.resizeColumnsToContents()
        self._table.horizontalHeader().setStretchLastSection(True)
Beispiel #7
0
class edycja_proby(QDialog):
    def __init__(self, sample, defpol={}, defpol_order=[], parent=None):
        ''' defpol and defpol_order should contains the same values, it will
        not be checked in this class is it valid, pay attention to it'''
        super(edycja_proby, self).__init__(parent)

        # self.dane = globals()["daneW"][0]
        # self.defpol = globals()["daneW"][1]
        # globals()["daneW"] = []
        self.sample = copy.deepcopy(sample)
        self.sample._edytowany = 'E'
        self.org_sample = sample
        self.newName = self.sample.KeyCode()

        self.setWindowTitle("Sample: " + self.sample.KeyCode())
        self.resize(691, 749)
        self.setMinimumSize(QSize(691, 749))
        # self.setMaximumSize(QSize(691, 749))

        # Prepare headers
        self.defpol = defpol
        self.defpol_order = defpol_order
        self.prepareDefPol()
        self.selected = []  # list with index of selected ring in sample

        # ustawienie pol z danymi
        self.p_naglowek = QTableWidget()
        self.p_naglowek.setObjectName("p_naglowek")
        self.p_naglowek.setColumnCount(1)
        self.p_naglowek.setRowCount(len(self.headers))
        self.p_naglowek.setHorizontalHeaderLabels(["Value"])
        self.p_naglowek.setVerticalHeaderLabels(self.headers)
        self.p_naglowek.setAlternatingRowColors(True)
        self.p_naglowek.setSortingEnabled(False)

        self.p_dane = QTableWidget()
        self.p_dane.setObjectName("p_dane")
        self.p_dane.setColumnCount(10)
        self.p_dane.setHorizontalHeaderLabels(
            ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"])

        self.dodaj = QPushButton("Add")
        self.usun = QPushButton("Delete")
        self.przerysuj = QPushButton("Redraw")
        self.podziel = QPushButton("Divide")
        self.polacz = QPushButton("Join")
        self.anuluj = QPushButton("Cancel")
        self.wykonaj = QPushButton("Update")

        self.vbl = QVBoxLayout()
        self.qmc = Qt4MplCanvas(self)
        self.ntb = NavigationToolbar(self.qmc, self)
        self.vbl.addWidget(self.qmc)
        self.vbl.addWidget(self.ntb)

        self.updateHeaderTable()
        self.wpisz_pomiary()
        self.przerysuj_wykres()

        # ustawiamy wyglad okna
        layout = QGridLayout()
        layout.addWidget(self.p_naglowek, 0, 0)

        layout1 = QGridLayout()
        layout1.addWidget(self.p_dane, 0, 0, 1, 5)
        layout1.addWidget(self.dodaj, 1, 0)
        layout1.addWidget(self.usun, 1, 1)
        layout1.addWidget(self.podziel, 1, 2)
        layout1.addWidget(self.polacz, 1, 3)
        layout1.addWidget(self.przerysuj, 1, 4)
        layout1.setRowMinimumHeight(1, 25)
        layout1.setRowStretch(0, 1)

        layout.addLayout(layout1, 0, 1)
        layout.addLayout(self.vbl, 1, 0, 1, 2)
        layout.addWidget(self.anuluj, 2, 0)
        layout.addWidget(self.wykonaj, 2, 1)
        layout.setColumnMinimumWidth(0, 290)
        layout.setColumnStretch(1, 1)
        layout.setRowStretch(0, 1)
        layout.setRowMinimumHeight(0, 350)
        self.setLayout(layout)

        # Sygnaly
        self.connect(self.anuluj, SIGNAL("clicked()"), self.schowaj)
        self.connect(self.wykonaj, SIGNAL("clicked()"), self.wykonaj_odczytanie)
        self.connect(self.dodaj, SIGNAL("clicked()"), self.dodaj_wartosc)
        self.connect(self.przerysuj, SIGNAL("clicked()"), self.przerysuj_wykres)
        self.connect(self.usun, SIGNAL("clicked()"), self.usun_wartosc)
        self.connect(self.podziel, SIGNAL("clicked()"), self.podziel_wartosc)
        self.connect(self.polacz, SIGNAL("clicked()"), self.polacz_wartosc)
        self.p_naglowek.cellChanged.connect(self.edytowana_kom_nagl)
        self.p_dane.itemSelectionChanged.connect(self.przerysuj_wykres)
        self.p_dane.cellChanged.connect(self.przerysuj_wykres)

    def prepareDefPol(self):
        """Prepare Headers for metadata,
        BEAWARE! measurements are delete on the end"""
        self.headers = [
                        'KeyCode',
                        'DateBegin',
                        'DateEnd',
                        'Length',
                        'Gat',
                        'SapWoodRings',
                        'measurements',
                        ]
        add_table = []
        if len(self.defpol_order):
            add_table = self.defpol_order[:]
        elif len(self.defpol.keys()):
            add_table = sorted(list(self.defpol.keys()))
        else:
            add_table = sorted(self.sample.unikalneNaglowki())

        for val in add_table:
            if val not in self.headers:
                self.headers.append(val)
        self.headers.remove('measurements')

    def updateHeaderTable(self):
        # Dodaj wartosci wierszow dla tabeli naglowka proby
        self.p_naglowek.blockSignals(True)
        for i, val in enumerate(self.headers):
            if self.sample.wypiszMetadana(val):
                komorka = QTableWidgetItem(str(self.sample.wypiszMetadana(val)))
            else:
                komorka = QTableWidgetItem('---')

            if val == 'Length':
                komorka.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)

            self.p_naglowek.setItem(i, 0, komorka)
        self.p_naglowek.blockSignals(False)

    def wykonaj_odczytanie(self):
        # spisz cala probe z edytowanych tabel i zapisz ja do zmiennej globalnej
        # daneW
        self.odczytaj_dane(origin='org')
        self.newName = self.org_sample.KeyCode()
        self.hide()

    def przerysuj_wykres(self):
        self.odczytaj_dane()
        self.updateHeaderTable()
        self.chartData = [
                     [],  # X axis - years
                     [],  # Y axis - measurements
                    ]

        self.chartData[1] = self.sample.wypiszPomiary()
        self.chartData[0] = range(1, self.sample.Length() + 1)

        self.qmc.axes.clear()
        # draw sample curve
        self.qmc.axes.plot(self.chartData[0], self.chartData[1])

        # draw selected years
        Xpoints = []
        Ypoints = []
        self.selected = []
        j = 0
        for i in range(self.sample.Length()):
            if i == 11:
                j += 1
            item = self.p_dane.item(j, i-(j*10))
            if item.isSelected():
                Xpoints.append(i+1)
                self.selected.append(i)
                Ypoints.append(int(item.text()))
        self.qmc.axes.plot(Xpoints, Ypoints, 'ro')

        # formatting of support lines
        self.qmc.axes.xaxis.set_major_locator(MultipleLocator(10))
        self.qmc.axes.xaxis.set_minor_locator(MultipleLocator(2))

        # Prepare axis dimensions
        Xmax = 40
        if self.sample.Length() > 40:
            Xmax = self.sample.Length() + 2
        Ymax = max(self.sample.wypiszPomiary()) + 30
        self.qmc.axes.axis([0, Xmax, 0, Ymax])

        self.qmc.axes.xaxis.grid(
            True,
            'minor',
            linewidth=0.4,
            ls='-',
            color='0.20')
        self.qmc.axes.xaxis.grid(
            True,
            'major',
            linewidth=1,
            ls='-',
            color='0.80')
        self.qmc.axes.tick_params(axis='both', which='major', labelsize=10)
        self.qmc.axes.set_axisbelow(True)
        # ustawienie obszaru wykresu
        self.qmc.axes.set_position([0.03, 0.05, 0.96, 0.94])
        self.qmc.draw()

    def odczytaj_dane(self, origin='copy'):
        """update sample - read all metadata and measurements which could be
            altered by user. If origin of sample has to be modified use any
            string in origin
        """
        if origin == 'copy':
            target = self.sample
        else:
            target = self.org_sample

        for i, head in enumerate(self.headers):
            ins = unicode(self.p_naglowek.item(i, 0).text())
            if head not in ['Length'] and ins not in ['---', 0]:
                target.wpiszMetadana(
                    head,
                    ins
                    )

        rowNum = self.p_dane.rowCount()
        colNum = self.p_dane.columnCount()
        measurements = []
        check = 'ok'
        redraw = 0
        for w in range(rowNum):
            for k in range(colNum):
                item = self.p_dane.item(w, k)
                try:
                    if int(item.text()) != 0 and str(item.text()).isdigit:
                        measurements.append(int(item.text()))
                        # if after notOk we find number there is something wrong
                        # and we neef to reread measuremnts to tabel
                        if check == 'notOk':
                            redraw = 1
                except:
                    check = 'notOk'

        target.uaktualnijPom(measurements)
        if redraw == 1:
            self.wpisz_pomiary()

    def dodaj_wartosc(self):
        kk = 0
        self.ile_wierszy = self.p_dane.rowCount()
        self.ile_kol = self.p_dane.columnCount()
        for wiersz in range(self.ile_wierszy):
            for kolumna in range(self.ile_kol):
                item = self.p_dane.item(wiersz, kolumna)
                if self.p_dane.isItemSelected(item) == True and kk == 0:
                    kk = 1
                    text, ok = QInputDialog.getText(
                        self, 'Value', 'inser value: ')
                    if ok:
                        measurements = self.sample.wypiszPomiary()
                        measurements.insert((wiersz*10)+kolumna, int(text))
                        self.sample.uaktualnijPom(measurements)
        self.wpisz_pomiary()
        self.przerysuj_wykres()

    def usun_wartosc(self):
        sel = self.selected[:]
        sel.reverse()
        for s in sel:
            self.sample.usunOstatniPomiar(position=int(s))
        self.wpisz_pomiary()
        self.przerysuj_wykres()

    def wpisz_pomiary(self):
        # przygotowanie labelek poziomych dla tablicy z pomiarami
        self.w = (len(self.sample.wypiszPomiary()))/10
        if (len(self.sample.wypiszPomiary())) % 10 > 0:
            self.w += 1
        i = 0
        self.ww = []
        while i < self.w:
            self.ww.append(str(i*10))
            i += 1
        self.p_dane.blockSignals(True)
        self.p_dane.clear()
        self.p_dane.setRowCount(self.w)
        self.p_dane.setVerticalHeaderLabels(self.ww)
        self.p_dane.setAlternatingRowColors(True)
        self.p_dane.setSortingEnabled(False)

        # Dodajemy wartosci pomiarow
        i = 0
        j = 0
        k = 0
        measurements = self.sample.wypiszPomiary()
        while k < len(measurements):
            if j == 10:
                j = 0
                i += 1
            komorka = QTableWidgetItem(str(measurements[k]))
            self.p_dane.setItem(i, j, komorka)
            j += 1
            k += 1
        # uzupelniamy pozostale pola pustymi wartosciami
        while j % 10 != 0:
            komorka = QTableWidgetItem("")
            self.p_dane.setItem(i, j, komorka)
            j += 1
        self.p_dane.resizeColumnsToContents()
        self.p_dane.blockSignals(False)

    def podziel_wartosc(self):
        if len(self.selected) != 1:
            pass
        else:
            measurements = self.sample.wypiszPomiary()
            val = measurements[self.selected[0]]
            self.divideWindow = okno_podzialu(val)
            self.divideWindow.exec_()
            measurements.pop(self.selected[0])
            self.sample.uaktualnijPom(measurements)
            self.sample.dodajPomiar(self.divideWindow.val1,
                                    position=self.selected[0])
            self.sample.dodajPomiar(self.divideWindow.val0,
                                    position=self.selected[0])

            self.wpisz_pomiary()
            self.przerysuj_wykres()

    def polacz_wartosc(self):
        measurements = self.sample.wypiszPomiary()
        i = len(measurements) - 1
        selectionRange = []
        newMeasurements = []
        while i > -1:
            if i in self.selected:
                selectionRange.append(measurements[i])
            elif i not in self.selected:
                if len(selectionRange) > 0:
                    newMeasurements.append(sum(selectionRange))
                    selectionRange = []
                newMeasurements.append(measurements[i])
            i -= 1
        if len(selectionRange) > 0:
            newMeasurements.append(selectionRange)
        newMeasurements.reverse()
        self.sample.uaktualnijPom(newMeasurements)

        self.wpisz_pomiary()
        self.przerysuj_wykres()

    def schowaj(self):
        self.odczytaj_dane()
        self.hide()

    def edytowana_kom_nagl(self):
        # neccessary to maintain user specific date, otherwise it will be
        # shuflled
        row = self.p_naglowek.currentRow()
        self.p_naglowek.blockSignals(True)
        if self.headers[row] in ['DateBegin', 'DateEnd']:
            head_temp = self.headers[row]
            if head_temp == "DateBegin":
                self.sample.ustawDateBegin(
                    int(self.p_naglowek.item(row, 0).text()))
                it = QTableWidgetItem(str(self.sample.DateEnd()))
                self.p_naglowek.setItem(self.headers.index("DateEnd"), 0, it)
            if head_temp == "DateEnd":
                self.sample.ustawDateEnd(
                    int(self.p_naglowek.item(row, 0).text()))
                it = QTableWidgetItem(str(self.sample.DateBegin()))
                self.p_naglowek.setItem(self.headers.index("DateBegin"), 0, it)
        self.p_naglowek.blockSignals(False)
        self.przerysuj_wykres()
Beispiel #8
0
class daq_window(QMainWindow):
    """Window to control and visualise DAQ measurements.
    Set up the desired channels with a given sampling rate.
    Start an acquisition after a trigger. 
    Display the acquired data on a trace, and accumulated
    data on a graph.
    
    Arguments:
    n       -- run number for synchronisation
    rate    -- max sample rate in samples / second
    dt      -- desired acquisition period in seconds
    config_file -- path to file storing default settings
    port    -- the port number to open for TCP connections
    """
    def __init__(self, n=0, rate=250, dt=500, config_file='monitor\\daqconfig.dat', port=8622):
        super().__init__()
        self.types = OrderedDict([('n', int), ('config_file', str), ('trace_file', str), ('graph_file', str),
            ('save_dir', str), ('Sample Rate (kS/s)',float), 
            ('Duration (ms)', float), ('Trigger Channel', str), ('Trigger Level (V)', float), 
            ('Trigger Edge', str), ('channels',channel_stats)])
        self.stats = OrderedDict([('n', n), ('config_file', config_file), ('trace_file', 'DAQtrace.csv'), 
            ('graph_file', 'DAQgraph.csv'),('save_dir', '.'), ('Sample Rate (kS/s)', rate), 
            ('Duration (ms)', dt), ('Trigger Channel', 'Dev2/ai1'), # /Dev2/PFI0
            ('Trigger Level (V)', 1.0), ('Trigger Edge', 'rising'), 
            ('channels', channel_stats("[['Dev2/ai0', '0', '1.0', '0.0', '5', '1', '1']]"))])
        self.trigger_toggle = True       # whether to trigger acquisition or just take a measurement
        self.slave = worker(rate*1e3, dt/1e3, self.stats['Trigger Channel'], 
                self.stats['Trigger Level (V)'], self.stats['Trigger Edge'], list(self.stats['channels'].keys()), 
                [ch['range'] for ch in self.stats['channels'].values()]) # this controls the DAQ
        self.dc = daqCollection(param=[], channels=list(self.stats['channels'].keys()))
        self.init_UI()
        self.load_config(config_file)    # load default settings          
        self.n_samples = int(self.stats['Duration (ms)'] * self.stats['Sample Rate (kS/s)']) # number of samples per acquisition
        self.last_path = './'

        self.x = [] # run numbers for graphing collections of acquired data
        self.y = [] # average voltages in slice of acquired trace 

        self.slave.acquired.connect(self.update_graph) # take average of slices
        self.slave.acquired.connect(self.update_trace) # plot new data when it arrives
        self.tcp = PyClient(port=port)
        remove_slot(self.tcp.dxnum, self.set_n, True)
        remove_slot(self.tcp.textin, self.respond, True)
        self.tcp.start()

    def init_UI(self):
        """Produce the widgets and buttons."""
        self.centre_widget = QWidget()
        self.tabs = QTabWidget()       # make tabs for each main display 
        self.centre_widget.layout = QVBoxLayout()
        self.centre_widget.layout.addWidget(self.tabs)
        self.centre_widget.setLayout(self.centre_widget.layout)
        self.setCentralWidget(self.centre_widget)
        
        # change font size
        font = QFont()
        font.setPixelSize(18)

        #### menubar at top gives options ####
        menubar = self.menuBar()

        # file menubar allows you to save/load data
        file_menu = menubar.addMenu('File')
        for label, function in [['Load Config', self.load_config],
                ['Save Config', self.save_config],
                ['Load Trace', self.load_trace], 
                ['Save Trace', self.save_trace], 
                ['Save Graph', self.save_graph]]:
            action = QAction(label, self) 
            action.triggered.connect(function)
            file_menu.addAction(action)

        #### tab for settings  ####
        settings_tab = QWidget()
        settings_grid = QGridLayout()
        settings_tab.setLayout(settings_grid)
        self.tabs.addTab(settings_tab, "Settings")

        self.settings = QTableWidget(1, 6)
        self.settings.setHorizontalHeaderLabels(['Duration (ms)', 
            'Sample Rate (kS/s)', 'Trigger Channel', 'Trigger Level (V)', 
            'Trigger Edge', 'Use Trigger?'])
        settings_grid.addWidget(self.settings, 0,0, 1,1)
        defaults = [str(self.stats['Duration (ms)']), str(self.stats['Sample Rate (kS/s)']), 
            self.stats['Trigger Channel'], str(self.stats['Trigger Level (V)']), 
            self.stats['Trigger Edge'], '1']
        validators = [double_validator, double_validator, None, double_validator, None, bool_validator]
        for i in range(6):
            table_item = QLineEdit(defaults[i]) # user can edit text to change the setting
            if defaults[i] == 'Sample Rate (kS/s)': table_item.setEnabled(False)
            table_item.setValidator(validators[i]) # validator limits the values that can be entered
            self.settings.setCellWidget(0,i, table_item)
        self.settings.resizeColumnToContents(1) 
        self.settings.setFixedHeight(70) # make it take up less space
        self.settings.cellWidget(0,0).textChanged.connect(self.check_slice_duration)
                    
        # start/stop: start waiting for a trigger or taking an acquisition
        self.toggle = QPushButton('Start', self)
        self.toggle.setCheckable(True)
        self.toggle.clicked.connect(self.activate)
        settings_grid.addWidget(self.toggle, 1,0, 1,1)

        # channels
        self.channels = QTableWidget(8, 7) # make table
        self.channels.setHorizontalHeaderLabels(['Channel', 'Label', 
            'Scale (X/V)', 'Offset (V)', 'Range', 'Acquire?', 'Plot?'])
        settings_grid.addWidget(self.channels, 2,0, 1,1) 
        validators = [None, double_validator, double_validator, None, bool_validator, bool_validator]
        for i in range(8):
            chan = 'Dev2/ai'+str(i)  # name of virtual channel
            table_item = QLabel(chan)
            self.channels.setCellWidget(i,0, table_item)
            if chan in self.stats['channels']: # load values from previous
                defaults = self.stats['channels'][chan]
            else: # default values when none are loaded
                defaults = channel_stats("[dummy, "+str(i)+", 1.0, 0.0, 5.0, 0, 0]")['dummy']
            for j, key in zip([0,1,2,4,5], ['label', 'scale', 'offset', 'acquire', 'plot']):
                table_item = QLineEdit(str(defaults[key]))
                if 'acquire' in key:
                    table_item.textChanged.connect(self.check_slice_channels)
                elif 'plot' in key:
                    table_item.textChanged.connect(self.set_acquire)
                table_item.setValidator(validators[j])        
                self.channels.setCellWidget(i,j+1, table_item)
            vrange = QComboBox() # only allow certain values for voltage range
            vrange.text = vrange.currentText # overload function so it's same as QLabel
            vrange.addItems(['%.1f'%x for x in self.slave.vrs])
            try: vrange.setCurrentIndex(self.slave.vrs.index(defaults['range']))
            except Exception as e: logger.error('Invalid channel voltage range\n'+str(e))
            self.channels.setCellWidget(i,4, vrange)

        #### Plot for most recently acquired trace ####
        trace_tab = QWidget()
        trace_grid = QGridLayout()
        trace_tab.setLayout(trace_grid)
        self.tabs.addTab(trace_tab, "Trace")
        
        # button activates horizontal line
        self.hline_toggle = QPushButton('Horizontal line', self, checkable=True)
        self.hline_toggle.clicked.connect(self.add_horizontal)
        trace_grid.addWidget(self.hline_toggle, 0,0, 1,1)
        self.hline_label = QLabel()
        trace_grid.addWidget(self.hline_label, 0,1, 1,1)
        fadeline_button = QPushButton('Persist', self)
        fadeline_button.clicked.connect(self.set_fadelines)
        trace_grid.addWidget(fadeline_button, 0,2, 1,1)
        

        # plot the trace
        self.trace_canvas = pg.PlotWidget()
        self.trace_legend = self.trace_canvas.addLegend()
        self.trace_canvas.getAxis('bottom').tickFont = font
        self.trace_canvas.getAxis('left').tickFont = font
        self.trace_canvas.setLabel('bottom', 'Time', 's', **{'font-size':'18pt'})
        self.trace_canvas.setLabel('left', 'Voltage', 'V', **{'font-size':'18pt'})
        self.lines = [] # handles for lines plotting the last measurement
        self.fadelines = [] # handles for previous measurement lines
        for i in range(8):
            chan = self.channels.cellWidget(i,1).text()
            self.lines.append(self.trace_canvas.plot([1], name=chan, 
                    pen=pg.mkPen(pg.intColor(i), width=3)))
            self.lines[i].hide()
            self.fadelines.append(self.trace_canvas.plot([1], 
                    pen=pg.mkPen(pg.intColor(i, alpha=50), width=2)))
            self.fadelines[i].hide()
        self.hline = pg.InfiniteLine(1., angle=0, pen='k', movable=True)
        self.trace_canvas.addItem(self.hline)
        self.hline.sigPositionChanged.connect(self.update_hline)
        self.hline.hide()
        
            
        trace_grid.addWidget(self.trace_canvas, 1,0, 1,3)
        
        #### Settings for slices of the trace accumulating into the graph ####
        slice_tab = QWidget()
        slice_grid = QGridLayout()
        slice_tab.setLayout(slice_grid)
        self.tabs.addTab(slice_tab, "Slice")
        
        # Buttons to add/remove slices and reset graph
        for i, (label, func) in enumerate([['Add slice', self.add_slice],
                ['Remove slice', self.del_slice], ['Reset graph', self.reset_graph]]):
            button = QPushButton(label, self)
            button.clicked.connect(func)
            slice_grid.addWidget(button, 0,i, 1,1)
        
        # parameters for slices
        self.slices = QTableWidget(0, 4) # make table
        self.slices.setHorizontalHeaderLabels(['Slice name', 
            'Start (ms)', 'End (ms)', 'Channels'])
        slice_grid.addWidget(self.slices, 1,0, 1,3) 

        #### Plot for graph of accumulated data ####
        graph_tab = QWidget()
        graph_grid = QGridLayout()
        graph_tab.setLayout(graph_grid)
        self.tabs.addTab(graph_tab, "Graph")

        self.mean_graph = pg.PlotWidget() # for plotting means
        self.stdv_graph = pg.PlotWidget() # for plotting standard deviations
        self.graph_legends = []
        for i, g in enumerate([self.mean_graph, self.stdv_graph]):
            g.getAxis('bottom').tickFont = font
            g.getAxis('bottom').setFont(font)
            g.getAxis('left').tickFont = font
            g.getAxis('left').setFont(font)
            graph_grid.addWidget(g, i,0, 1,1)
        self.reset_lines() # make a line for every slice channel
        self.stdv_graph.setLabel('bottom', 'Shot', '', **{'font-size':'18pt'})
        self.stdv_graph.setLabel('left', 'Standard Deviation', 'V', **{'font-size':'18pt'})
        self.mean_graph.setLabel('left', 'Mean', 'V', **{'font-size':'18pt'})
        
        #### tab for TCP message settings  ####
        tcp_tab = QWidget()
        tcp_grid = QGridLayout()
        tcp_tab.setLayout(tcp_grid)
        self.tabs.addTab(tcp_tab, "Sync")

        label = QLabel('Run number: ')
        tcp_grid.addWidget(label, 0,0, 1,1)
        self.n_edit = QLineEdit(str(self.stats['n']))
        self.n_edit.setValidator(int_validator)
        self.n_edit.textEdited[str].connect(self.set_n)
        tcp_grid.addWidget(self.n_edit, 0,1, 1,1)
        
        label = QLabel('Save directory: ')
        tcp_grid.addWidget(label, 1,0, 1,1)
        self.save_edit = QLineEdit(self.stats['save_dir'])
        self.save_edit.textEdited[str].connect(self.set_save_dir)
        tcp_grid.addWidget(self.save_edit, 1,1, 1,1)
        
        label = QLabel('Trace file name: ')
        tcp_grid.addWidget(label, 2,0, 1,1)
        self.trace_edit = QLineEdit(self.stats['trace_file'])
        self.trace_edit.textEdited[str].connect(self.set_trace_file)
        tcp_grid.addWidget(self.trace_edit, 2,1, 1,1)
        
        label = QLabel('Graph file name: ')
        tcp_grid.addWidget(label, 3,0, 1,1)
        self.graph_edit = QLineEdit(self.stats['graph_file'])
        self.graph_edit.textEdited[str].connect(self.set_graph_file)
        tcp_grid.addWidget(self.graph_edit, 3,1, 1,1)
        
        reset = QPushButton('Reset TCP client', self)
        reset.clicked.connect(self.reset_client)
        tcp_grid.addWidget(reset, 4,0, 1,1)

        #### Title and icon ####
        self.setWindowTitle('- NI DAQ Controller -')
        self.setWindowIcon(QIcon('docs/daqicon.png'))
        self.setGeometry(200, 200, 800, 600)

    #### user input functions ####

    def set_acquire(self):
        """If the user chooses to plot, set the same channel to acquire."""
        for i in range(self.channels.rowCount()):
            if BOOL(self.channels.cellWidget(i,6).text()): # plot
                self.channels.cellWidget(i,5).setText('1') # only plot if acquiring
    
    def check_settings(self):
        """Coerce the settings into allowed values."""
        statstr = "[[" # dictionary of channel names and properties
        for i in range(self.channels.rowCount()):
            self.trace_legend.items[i][1].setText(self.channels.cellWidget(i,1).text()) # label
            if BOOL(self.channels.cellWidget(i,5).text()): # acquire
                statstr += ', '.join([self.channels.cellWidget(i,j).text() 
                    for j in range(self.channels.columnCount())]) + '],['
        self.stats['channels'] = channel_stats(statstr[:-2] + ']')
        self.dc.channels = self.stats['channels'].keys()

        # acquisition settings
        self.stats['Duration (ms)'] = float(self.settings.cellWidget(0,0).text())
        # check that the requested rate is valid
        rate = float(self.settings.cellWidget(0,1).text())
        if len(self.stats['channels']) > 1 and rate > 245 / len(self.stats['channels']):
            rate = 245 / len(self.stats['channels'])
        elif len(self.stats['channels']) < 2 and rate > 250:
            rate = 250
        self.stats['Sample Rate (kS/s)'] = rate
        self.settings.cellWidget(0,1).setText('%.2f'%(rate))
        self.n_samples = int(self.stats['Duration (ms)'] * self.stats['Sample Rate (kS/s)'])
        # check the trigger channel is valid
        trig_chan = self.settings.cellWidget(0,2).text() 
        if 'Dev2/PFI' in trig_chan or 'Dev2/ai' in trig_chan:
            self.stats['Trigger Channel'] = trig_chan
        else: 
            self.stats['Trigger Channel'] = 'Dev2/ai0'
        self.settings.cellWidget(0,2).setText(str(self.stats['Trigger Channel']))
        self.stats['Trigger Level (V)'] = float(self.settings.cellWidget(0,3).text())
        self.stats['Trigger Edge'] = self.settings.cellWidget(0,4).text()
        self.trigger_toggle = BOOL(self.settings.cellWidget(0,5).text())
        
        
    def set_table(self):
        """Display the acquisition and channel settings in the table."""
        x = self.stats.copy() # prevent it getting overwritten
        for i in range(5):
            self.settings.cellWidget(0,i).setText(str(x[
                self.settings.horizontalHeaderItem(i).text()]))
        for i in range(8):
            ch = self.channels.cellWidget(i,0).text()
            if ch in x['channels']:
                for j, key in zip([0,1,2,4,5], 
                        ['label', 'scale', 'offset', 'acquire', 'plot']):
                    self.channels.cellWidget(i,j+1).setText(str(x['channels'][ch][key]))
                self.channels.cellWidget(i,4).setCurrentText('%.1f'%x['channels'][ch]['range'])
            else:
                self.channels.cellWidget(i,5).setText('0') # don't acquire
                self.channels.cellWidget(i,6).setText('0') # don't plot

    #### slice settings functions ####

    def add_slice(self, param=[]):
        """Add a row to the slice table and append it to the
        daqCollection instance for analysis.
        param -- [name, start (ms), end (ms), channels]"""
        try:
            name, start, end, channels = param
        except TypeError:
            name = 'Slice' + str(self.slices.rowCount())
            start = 0
            end = self.stats['Duration (ms)']
            channels = list(self.stats['channels'].keys())
        i = self.slices.rowCount() # index to add row at
        self.slices.insertRow(i) # add row to table
        validator = QDoubleValidator(0.,float(self.stats['Duration (ms)']),3)
        for j, text in enumerate([name, str(start), str(end)]):
            item = QLineEdit(text)
            item.pos = (i, j)
            if j > 0:
                item.setValidator(validator)
            item.textChanged.connect(self.update_slices)
            self.slices.setCellWidget(i, j, item)
        chanbox = QListWidget(self)
        chanbox.setSelectionMode(3) # extended selection, allows multiple selection
        chanbox.itemSelectionChanged.connect(self.update_slices)
        chanbox.pos = (i, 3)
        chanbox.text = chanbox.objectName
        chanlist = list(self.stats['channels'].keys())
        chanbox.addItems(chanlist)
        self.slices.setCellWidget(i, j+1, chanbox)
        self.slices.resizeRowToContents(i) 
        # add to the dc list of slices
        t = np.linspace(0, self.stats['Duration (ms)']/1000, self.n_samples)
        self.dc.add_slice(name, np.argmin(np.abs(t-start)), np.argmin(np.abs(t-end)), 
            OrderedDict([(chan, chanlist.index(chan)) for chan in channels]))
            
        self.reset_lines()
            

    def del_slice(self, toggle=True):
        """Remove the slice at the selected row of the slice table."""
        index = self.slices.currentRow()
        self.slices.removeRow(index)
        if index >= 0:
            self.dc.slices.pop(index)
        
    def check_slice_duration(self, newtxt):
        """If the acquisition duration is changed, make sure the slices can't
        use times beyond this."""
        self.check_settings() # update DAQ acquisition settings first
        for i in range(self.slices.rowCount()):
            for j in [1,2]: # force slice to be within max duration
                validator = QDoubleValidator(0.,float(self.stats['Duration (ms)']),3)
                self.slices.cellWidget(i, j).setValidator(validator)

    def check_slice_channels(self, newtxt):
        """If the channels that can be used for the acquisition are changed, 
        change the list widgets in the slice settings to match."""
        self.check_settings() # update DAQ acquisition settings first
        for i in range(self.slices.rowCount()):
            w = self.slices.cellWidget(i, 3) # widget shorthand
            selected = [w.row(x) for x in w.selectedItems()] # make record of selected channels
            w.clear()
            w.addItems(list(self.stats['channels'].keys()))
            for r in selected:
                try:
                    w.setCurrentRow(r, QItemSelectionModel.SelectCurrent)
                except Exception as e: pass

    def update_slices(self, newtxt=''):
        """Use the current item from the table to update the parameter for the slices."""
        try:
            w = self.sender()
            i, j = w.pos
            t = np.linspace(0, self.stats['Duration (ms)'], self.n_samples)
            x = self.dc.slices[i] # shorthand
            if j == 0: # name
                x.name = w.text()
            elif j == 1: # start (ms)
                x.i0 = np.argmin(np.abs(t-float(w.text())))
            elif j == 2: # end (ms)
                x.i1 = np.argmin(np.abs(t-float(w.text())))
            elif j == 3:
                x.channels = OrderedDict([(x.text(), w.row(x)) for x in w.selectedItems()])
                x.stats = OrderedDict([(chan, OrderedDict([
                    ('mean',[]), ('stdv',[])])) for chan in x.channels.keys()])
                self.reset_lines()
                self.reset_graph()
            x.inds = slice(x.i0, x.i1+1)
            x.size = x.i1 - x.i0
        except IndexError as e: pass # logger.error("Couldn't update slice.\n"+str(e))    

    #### TCP functions ####
    
    def set_n(self, num):
        """Receive the new run number to update to"""
        self.stats['n'] = int(num)
        self.n_edit.setText(str(num))
        
    def set_save_dir(self, directory):
        """Set the directory to save results to"""
        self.stats['save_dir'] = directory
        self.save_edit.setText(directory)
        
    def set_trace_file(self, fname):
        """Set the default name for trace files when they're saved."""
        self.stats['trace_file'] = fname
        self.trace_edit.setText(fname)
    
    def set_graph_file(self, fname):
        """Set the default name for graph files when they're saved."""
        self.stats['graph_file'] = fname
        self.graph_edit.setText(fname)
        
    def reset_client(self, toggle=True):
        """Stop the TCP client thread then restart it."""
        self.tcp.stop = True
        for i in range(100): # wait til it's stopped
            if not self.tcp.isRunning():
                break
            else: time.sleep(0.001)
        self.tcp.start() # restart
        
    def respond(self, msg=''):
        """Interpret a TCP message. For setting properties, the syntax is:
        value=property. E.g. 'Z:\Tweezer=save_dir'."""
        if 'save_dir' in msg: 
            self.set_save_dir(msg.split('=')[0])
        elif 'trace_file' in msg:
            self.set_trace_file(msg.split('=')[0])
        elif 'graph_file' in msg:
            self.set_graph_file(msg.split('=')[0])
        elif 'start' in msg and not self.toggle.isChecked():
            self.toggle.setChecked(True)
            self.activate()
        elif 'stop' in msg and self.toggle.isChecked():
            self.toggle.setChecked(False)
            self.activate()
        elif 'save trace' in msg:
            self.save_trace(os.path.join(self.stats['save_dir'], self.stats['trace_file']))
        elif 'save graph' in msg:
            self.save_graph(os.path.join(self.stats['save_dir'], self.stats['graph_file']))
        elif 'set fadelines' in msg:
            self.set_fadelines()
    
    #### acquisition functions #### 

    def activate(self, toggle=0):
        """Prime the DAQ task for acquisition if it isn't already running.
        Otherwise, stop the task running."""
        if self.toggle.isChecked():
            self.check_settings()
            self.slave = worker(self.stats['Sample Rate (kS/s)']*1e3, self.stats['Duration (ms)']/1e3, self.stats['Trigger Channel'], 
                self.stats['Trigger Level (V)'], self.stats['Trigger Edge'], list(self.stats['channels'].keys()), 
                [ch['range'] for ch in self.stats['channels'].values()])
            remove_slot(self.slave.acquired, self.update_trace, True)
            remove_slot(self.slave.acquired, self.update_graph, True)
            if self.trigger_toggle:
                # remove_slot(self.slave.finished, self.activate, True)
                self.slave.start()
                self.toggle.setText('Stop')
            else: 
                self.toggle.setChecked(False)
                self.slave.analogue_acquisition()
        else:
            # remove_slot(self.slave.finished, self.activate, False)
            self.slave.stop = True
            self.slave.quit()
            self.toggle.setText('Start')

    #### plotting functions ####

    def update_trace(self, data):
        """Plot the supplied data with labels on the trace canvas."""
        t = np.linspace(0, self.stats['Duration (ms)']/1000, self.n_samples)
        i = 0 # index to keep track of which channels have been plotted
        for j in range(8):
            ch = self.channels.cellWidget(j,0).text()
            l = self.lines[j] # shorthand
            if ch in self.stats['channels'] and self.stats['channels'][ch]['plot']:
                try:
                    l.setData(t, data[i])
                except Exception as e:
                    logger.error('DAQ trace could not be plotted.\n'+str(e))
                self.fadelines[j].show()
                l.show()
                self.trace_legend.items[j][0].show()
                self.trace_legend.items[j][1].show()
                i += 1
            else:
                l.hide()
                self.fadelines[j].hide()
                self.trace_legend.items[j][0].hide()
                self.trace_legend.items[j][1].hide()
        self.trace_legend.resize(0,0)
        
    def set_fadelines(self):
        """Take the data from the current lines and sets it to the fadelines."""
        for j in range(8):
            ch = self.channels.cellWidget(j,0).text()
            l = self.lines[j] # shorthand
            if ch in self.stats['channels'] and self.stats['channels'][ch]['plot']:
                try:
                    self.fadelines[j].setData(l.xData, l.yData)
                except Exception as e:
                    logger.error('DAQ trace could not be plotted.\n'+str(e))
                self.fadelines[j].show()
            else:
                self.fadelines[j].hide()
        
    def reset_lines(self):
        """Clear the mean and stdv graphs, reset the legends, then make new 
        lines for each of the slice channels."""
        for legend in self.graph_legends: # reset the legends
            try:
                legend.scene().removeItem(legend)
            except AttributeError: pass
        for g in [self.mean_graph, self.stdv_graph]:
            g.clear()
            g.lines = OrderedDict([])
            self.graph_legends.append(g.addLegend())
            i = 0
            for s in self.dc.slices:
                for chan, val in s.stats.items():
                    g.lines[s.name+'/'+chan] = g.plot([1], name=s.name+'/'+chan, 
                        pen=None, symbol='o', symbolPen=pg.mkPen(pg.intColor(i)),
                        symbolBrush=pg.intColor(i)) 
                    i += 1

    def reset_graph(self):
        """Reset the collection of slice data, then replot the graph."""
        self.dc.reset_arrays()
        self.update_graph()

    def update_graph(self, data=[]):
        """Extract averages from slices of the data.
        Replot the stored data accumulated from averages in slices
        of the measurements."""
        if np.size(data):
            self.dc.process(data, self.stats['n'])
        for s in self.dc.slices:
            for chan, val in s.stats.items():
                self.mean_graph.lines[s.name+'/'+chan].setData(self.dc.runs, val['mean'])
                self.stdv_graph.lines[s.name+'/'+chan].setData(self.dc.runs, val['stdv'])
                
    def add_horizontal(self, toggle=True):
        """Display a horizontal line on the trace"""
        if toggle: self.hline.show()
        else: 
            self.hline.hide()
            self.hline_label.setText('')
        
    def update_hline(self):
        """Display the value of the horizontal line in the label"""
        self.hline_label.setText(str(self.hline.value()))

    #### save/load functions ####

    def try_browse(self, title='Select a File', file_type='all (*)', 
                open_func=QFileDialog.getOpenFileName, default_path=''):
        """Open a file dialog and retrieve a file name from the browser.
        title: String to display at the top of the file browser window
        default_path: directory to open first
        file_type: types of files that can be selected
        open_func: the function to use to open the file browser"""
        default_path = default_path if default_path else os.path.dirname(self.last_path)
        try:
            if 'PyQt4' in sys.modules:
                file_name = open_func(self, title, default_path, file_type)
            elif 'PyQt5' in sys.modules:
                file_name, _ = open_func(self, title, default_path, file_type)
            if type(file_name) == str: self.last_path = file_name 
            return file_name
        except OSError: return '' # probably user cancelled

    def save_config(self, file_name='daqconfig.dat'):
        """Save the current acquisition settings to the config file."""
        self.stats['config_file'] = file_name if file_name else self.try_browse(
                'Save Config File', 'dat (*.dat);;all (*)', QFileDialog.getSaveFileName)
        try:
            with open(self.stats['config_file'], 'w+') as f:
                for key, val in self.stats.items():
                    if key == 'channels':
                        f.write(key+'='+channel_str(val)+'\n')
                    else:
                        f.write(key+'='+str(val)+'\n')
            logger.info('DAQ config saved to '+self.stats['config_file'])
        except Exception as e: 
            logger.error('DAQ settings could not be saved to config file.\n'+str(e))

    def load_config(self, file_name='daqconfig.dat'):
        """Load the acquisition settings from the config file."""
        self.stats['config_file'] = file_name if file_name else self.try_browse(file_type='dat (*.dat);;all (*)')
        try:
            with open(self.stats['config_file'], 'r') as f:
                for line in f:
                    if len(line.split('=')) == 2:
                        key, val = line.replace('\n','').split('=') # there should only be one = per line
                        try:
                            self.stats[key] = self.types[key](val)
                        except KeyError as e:
                            logger.warning('Failed to load DAQ default config line: '+line+'\n'+str(e))
            self.set_table() # make sure the updates are displayed
            self.set_n(self.stats['n'])
            self.set_save_dir(self.stats['save_dir'])
            self.set_trace_file(self.stats['trace_file'])
            self.set_graph_file(self.stats['graph_file'])
            self.dc.channels = list(self.stats['channels'].keys())
            logger.info('DAQ config loaded from '+self.stats['config_file'])
        except FileNotFoundError as e: 
            logger.warning('DAQ settings could not find the config file.\n'+str(e))

    def save_trace(self, file_name=''):
        """Save the data currently displayed on the trace to a csv file."""
        file_name = file_name if file_name else self.try_browse(
                'Save File', 'csv (*.csv);;all (*)', QFileDialog.getSaveFileName)
        if file_name:
            # metadata
            header = ', '.join(list(self.stats.keys())) + '\n'
            header += ', '.join(list(map(str, self.stats.values()))[:-1]
                ) + ', ' + channel_str(self.stats['channels']) + '\n'
            # determine which channels are in the plot
            header += 'Time (s)'
            data = []
            for key, d in self.stats['channels'].items():
                if d['plot']:
                    header += ', ' + key # column headings
                    if len(data) == 0: # time (s)
                        data.append(self.lines[int(key[-1])].xData)
                    data.append(self.lines[int(key[-1])].yData) # voltage
            # data converted to the correct type
            out_arr = np.array(data).T
            try:
                np.savetxt(file_name, out_arr, fmt='%s', delimiter=',', header=header)
                logger.info('DAQ trace saved to '+file_name)
            except (PermissionError, FileNotFoundError) as e:
                logger.error('DAQ controller denied permission to save file: \n'+str(e))

    def load_trace(self, file_name=''):
        """Load data for the current trace from a csv file."""
        file_name = file_name if file_name else self.try_browse(file_type='csv(*.csv);;all (*)')
        if file_name:
            head = [[],[],[]] # get metadata
            with open(file_name, 'r') as f:
                for i in range(3):
                    row = f.readline()
                    if row[:2] == '# ':
                        head[i] = row[2:].replace('\n','').split(', ')
            # apply the acquisition settings from the file
            labels = [self.settings.horizontalHeaderItem(i).text() for 
                i in range(self.settings.columnCount())]
            for i in range(len(head[0])):
                try:
                    j = labels.index(head[0][i])
                    self.settings.cellWidget(0,j).setText(head[1][i])
                except ValueError: pass
            self.stats['channels'] = channel_stats(', '.join(head[1][7:]))
            for i in range(8): # whether to plot or not
                ch = self.channels.cellWidget(i,0).text()
                if ch in head[2]:
                    self.channels.cellWidget(i,6).setText('1')
                    self.channels.cellWidget(i,1).setText(self.stats['channels'][ch]['label'])
                else: self.channels.cellWidget(i,6).setText('0')
            self.check_settings()

            # plot the data
            data = np.genfromtxt(file_name, delimiter=',', dtype=float)
            if np.size(data) < 2:
                return 0 # insufficient data to load
            self.update_trace(data.T[1:])

    def save_graph(self, file_name=''):
        """Save the data accumulated from several runs that's displayed in the
        graph into a csv file."""
        file_name = file_name if file_name else self.try_browse(
                'Save File', 'csv (*.csv);;all (*)', QFileDialog.getSaveFileName)
        if file_name:
            self.dc.save(file_name, list(self.stats.keys()), 
                list(map(str, self.stats.values()))[:-1]
                 + [channel_str(self.stats['channels'])])
            logger.info('DAQ graph saved to '+file_name)
        
    def closeEvent(self, event):
        """Before closing, try to save the config settings to file."""
        statstr = "[[" # dictionary of channel names and properties
        for i in range(self.channels.rowCount()):
            statstr += ', '.join([self.channels.cellWidget(i,j).text() 
                    for j in range(self.channels.columnCount())]) + '],['
        self.stats['channels'] = channel_stats(statstr[:-2] + ']')
        # add all channels to stats
        self.save_config(self.stats['config_file'])
        event.accept()
Beispiel #9
0
class SpreadSheet(QMainWindow):

   dateFormats = ["dd/M/yyyy", "yyyy/M/dd", "dd.MM.yyyy"]

   currentDateFormat = dateFormats[0]

   def __init__(self, rows, cols, parent = None):
      super(SpreadSheet, self).__init__(parent)

      self.toolBar = QToolBar()
      self.addToolBar(self.toolBar)
      self.formulaInput = QLineEdit()
      self.cellLabel = QLabel(self.toolBar)
      self.cellLabel.setMinimumSize(80, 0)
      self.toolBar.addWidget(self.cellLabel)
      self.toolBar.addWidget(self.formulaInput)
      self.table = QTableWidget(rows, cols, self)
      for c in range(cols):
         character = chr(ord('A') + c)
         self.table.setHorizontalHeaderItem(c, QTableWidgetItem(character))

      self.table.setItemPrototype(self.table.item(rows - 1, cols - 1))
      self.table.setItemDelegate(SpreadSheetDelegate(self))
      self.createActions()
      self.updateColor(0)
      self.setupMenuBar()
      self.setupContents()
      self.setupContextMenu()
      self.setCentralWidget(self.table)
      self.statusBar()
      self.table.currentItemChanged.connect(self.updateStatus)
      self.table.currentItemChanged.connect(self.updateColor)
      self.table.currentItemChanged.connect(self.updateLineEdit)
      self.table.itemChanged.connect(self.updateStatus)
      self.formulaInput.returnPressed.connect(self.returnPressed)
      self.table.itemChanged.connect(self.updateLineEdit)
      self.setWindowTitle("Spreadsheet")

   def createActions(self):
      self.cell_sumAction = QAction("Sum", self)
      self.cell_sumAction.triggered.connect(self.actionSum)

      self.cell_addAction = QAction("&Add", self)
      self.cell_addAction.setShortcut(Qt.CTRL | Qt.Key_Plus)
      self.cell_addAction.triggered.connect(self.actionAdd)

      self.cell_subAction = QAction("&Subtract", self)
      self.cell_subAction.setShortcut(Qt.CTRL | Qt.Key_Minus)
      self.cell_subAction.triggered.connect(self.actionSubtract)

      self.cell_mulAction = QAction("&Multiply", self)
      self.cell_mulAction.setShortcut(Qt.CTRL | Qt.Key_multiply)
      self.cell_mulAction.triggered.connect(self.actionMultiply)

      self.cell_divAction = QAction("&Divide", self)
      self.cell_divAction.setShortcut(Qt.CTRL | Qt.Key_division)
      self.cell_divAction.triggered.connect(self.actionDivide)

      self.fontAction = QAction("Font...", self)
      self.fontAction.setShortcut(Qt.CTRL | Qt.Key_F)
      self.fontAction.triggered.connect(self.selectFont)

      self.colorAction = QAction(QIcon(QPixmap(16, 16)), "Background &Color...", self)
      self.colorAction.triggered.connect(self.selectColor)

      self.clearAction = QAction("Clear", self)
      self.clearAction.setShortcut(Qt.Key_Delete)
      self.clearAction.triggered.connect(self.clear)

      self.aboutSpreadSheet = QAction("About Spreadsheet", self)
      self.aboutSpreadSheet.triggered.connect(self.showAbout)

      self.exitAction = QAction("E&xit", self)
      self.exitAction.setShortcut(QKeySequence.Quit)
      self.exitAction.triggered.connect(QApplication.instance().quit)

      self.printAction = QAction("&Print", self)
      self.printAction.setShortcut(QKeySequence.Print)
      self.printAction.triggered.connect(self.print_)

      self.firstSeparator = QAction(self)
      self.firstSeparator.setSeparator(True)

      self.secondSeparator = QAction(self)
      self.secondSeparator.setSeparator(True)

   def setupMenuBar(self):
      self.fileMenu = self.menuBar().addMenu("&File")
      self.dateFormatMenu = self.fileMenu.addMenu("&Date format")
      self.dateFormatGroup = QActionGroup(self)
      for f in self.dateFormats:
         action = QAction(f, self, checkable=True,
                 triggered=self.changeDateFormat)
         self.dateFormatGroup.addAction(action)
         self.dateFormatMenu.addAction(action)
         if f == self.currentDateFormat:
            action.setChecked(True)
              
      self.fileMenu.addAction(self.printAction)
      self.fileMenu.addAction(self.exitAction)
      self.cellMenu = self.menuBar().addMenu("&Cell")
      self.cellMenu.addAction(self.cell_addAction)
      self.cellMenu.addAction(self.cell_subAction)
      self.cellMenu.addAction(self.cell_mulAction)
      self.cellMenu.addAction(self.cell_divAction)
      self.cellMenu.addAction(self.cell_sumAction)
      self.cellMenu.addSeparator()
      self.cellMenu.addAction(self.colorAction)
      self.cellMenu.addAction(self.fontAction)
      self.menuBar().addSeparator()
      self.aboutMenu = self.menuBar().addMenu("&Help")
      self.aboutMenu.addAction(self.aboutSpreadSheet)

   def changeDateFormat(self):
      action = self.sender()
      oldFormat = self.currentDateFormat
      newFormat = self.currentDateFormat = action.text()
      for row in range(self.table.rowCount()):
         item = self.table.item(row, 1)
         date = QDate.fromString(item.text(), oldFormat)
         item.setText(date.toString(newFormat))

   def updateStatus(self, item):
      if item and item == self.table.currentItem():
         self.statusBar().showMessage(item.data(Qt.StatusTipRole).toString(), 1000)
         self.cellLabel.setText("Cell: (%s)" % encode_pos(self.table.row(item),
                                                                    self.table.column(item)))

   def updateColor(self, item):
      pixmap = QPixmap(16, 16)
      color = QColor()
      if item:
         color = item.backgroundColor()
      if not color.isValid():
         color = self.palette().base().color()
      painter = QPainter(pixmap)
      painter.fillRect(0, 0, 16, 16, color)
      lighter = color.lighter()
      painter.setPen(lighter)
      # light frame
      painter.drawPolyline(QPoint(0, 15), QPoint(0, 0), QPoint(15, 0))
      painter.setPen(color.darker())
      # dark frame
      painter.drawPolyline(QPoint(1, 15), QPoint(15, 15), QPoint(15, 1))
      painter.end()
      self.colorAction.setIcon(QIcon(pixmap))

   def updateLineEdit(self, item):
      if item != self.table.currentItem():
         return
      if item:
         self.formulaInput.setText(item.data(Qt.EditRole).toString())
      else:
         self.formulaInput.clear()

   def returnPressed(self):
      text = self.formulaInput.text()
      row = self.table.currentRow()
      col = self.table.currentColumn()
      item = self.table.item(row, col)
      if not item:
         self.table.setItem(row, col, SpreadSheetItem(text))
      else:
         item.setData(Qt.EditRole, text)
      self.table.viewport().update()

   def selectColor(self):
      item = self.table.currentItem()
      color = item and QColor(item.background()) or self.table.palette().base().color()
      color = QColorDialog.getColor(color, self)
      if not color.isValid():
         return
      selected = self.table.selectedItems()
      if not selected:
         return
      for i in selected:
         i and i.setBackground(color)
      self.updateColor(self.table.currentItem())

   def selectFont(self):
      selected = self.table.selectedItems()
      if not selected:
         return
      font, ok = QFontDialog.getFont(self.font(), self)
      if not ok:
         return
      for i in selected:
         i and i.setFont(font)

   def runInputDialog(self, title, c1Text, c2Text, opText,
                      outText, cell1, cell2, outCell):
      rows = []
      cols = []
      for r in range(self.table.rowCount()):
         rows.append(str(r + 1))
      for c in range(self.table.columnCount()):
         cols.append(chr(ord('A') + c))
      addDialog = QDialog(self)
      addDialog.setWindowTitle(title)
      group = QGroupBox(title, addDialog)
      group.setMinimumSize(250, 100)
      cell1Label = QLabel(c1Text, group)
      cell1RowInput = QComboBox(group)
      c1Row, c1Col = decode_pos(cell1)
      cell1RowInput.addItems(rows)
      cell1RowInput.setCurrentIndex(c1Row)
      cell1ColInput = QComboBox(group)
      cell1ColInput.addItems(cols)
      cell1ColInput.setCurrentIndex(c1Col)
      operatorLabel = QLabel(opText, group)
      operatorLabel.setAlignment(Qt.AlignHCenter)
      cell2Label = QLabel(c2Text, group)
      cell2RowInput = QComboBox(group)
      c2Row, c2Col = decode_pos(cell2)
      cell2RowInput.addItems(rows)
      cell2RowInput.setCurrentIndex(c2Row)
      cell2ColInput = QComboBox(group)
      cell2ColInput.addItems(cols)
      cell2ColInput.setCurrentIndex(c2Col)
      equalsLabel = QLabel("=", group)
      equalsLabel.setAlignment(Qt.AlignHCenter)
      outLabel = QLabel(outText, group)
      outRowInput = QComboBox(group)
      outRow, outCol = decode_pos(outCell)
      outRowInput.addItems(rows)
      outRowInput.setCurrentIndex(outRow)
      outColInput = QComboBox(group)
      outColInput.addItems(cols)
      outColInput.setCurrentIndex(outCol)

      cancelButton = QPushButton("Cancel", addDialog)
      cancelButton.clicked.connect(addDialog.reject)
      okButton = QPushButton("OK", addDialog)
      okButton.setDefault(True)
      okButton.clicked.connect(addDialog.accept)
      buttonsLayout = QHBoxLayout()
      buttonsLayout.addStretch(1)
      buttonsLayout.addWidget(okButton)
      buttonsLayout.addSpacing(10)
      buttonsLayout.addWidget(cancelButton)

      dialogLayout = QVBoxLayout(addDialog)
      dialogLayout.addWidget(group)
      dialogLayout.addStretch(1)
      dialogLayout.addItem(buttonsLayout)

      cell1Layout = QHBoxLayout()
      cell1Layout.addWidget(cell1Label)
      cell1Layout.addSpacing(10)
      cell1Layout.addWidget(cell1ColInput)
      cell1Layout.addSpacing(10)
      cell1Layout.addWidget(cell1RowInput)

      cell2Layout = QHBoxLayout()
      cell2Layout.addWidget(cell2Label)
      cell2Layout.addSpacing(10)
      cell2Layout.addWidget(cell2ColInput)
      cell2Layout.addSpacing(10)
      cell2Layout.addWidget(cell2RowInput)
      outLayout = QHBoxLayout()
      outLayout.addWidget(outLabel)
      outLayout.addSpacing(10)
      outLayout.addWidget(outColInput)
      outLayout.addSpacing(10)
      outLayout.addWidget(outRowInput)
      vLayout = QVBoxLayout(group)
      vLayout.addItem(cell1Layout)
      vLayout.addWidget(operatorLabel)
      vLayout.addItem(cell2Layout)
      vLayout.addWidget(equalsLabel)
      vLayout.addStretch(1)
      vLayout.addItem(outLayout)
      if addDialog.exec_():
         cell1 = cell1ColInput.currentText() + cell1RowInput.currentText()
         cell2 = cell2ColInput.currentText() + cell2RowInput.currentText()
         outCell = outColInput.currentText() + outRowInput.currentText()
         return True, cell1, cell2, outCell

      return False, None, None, None

   def actionSum(self):
      row_first = 0
      row_last = 0
      row_cur = 0
      col_first = 0
      col_last = 0
      col_cur = 0
      selected = self.table.selectedItems()
      if selected:
         first = selected[0]
         last = selected[-1]
         row_first = self.table.row(first)
         row_last = self.table.row(last)
         col_first = self.table.column(first)
         col_last = self.table.column(last)

      current = self.table.currentItem()
      if current:
         row_cur = self.table.row(current)
         col_cur = self.table.column(current)

      cell1 = encode_pos(row_first, col_first)
      cell2 = encode_pos(row_last, col_last)
      out = encode_pos(row_cur, col_cur)
      ok, cell1, cell2, out = self.runInputDialog("Sum cells", "First cell:",
              "Last cell:", u"\N{GREEK CAPITAL LETTER SIGMA}", "Output to:",
              cell1, cell2, out)
      if ok:
         row, col = decode_pos(out)
         self.table.item(row, col).setText("sum %s %s" % (cell1, cell2))

   def actionMath_helper(self, title, op):
      cell1 = "C1"
      cell2 = "C2"
      out = "C3"
      current = self.table.currentItem()
      if current:
         out = encode_pos(self.table.currentRow(), self.table.currentColumn())
      ok, cell1, cell2, out = self.runInputDialog(title, "Cell 1", "Cell 2",
              op, "Output to:", cell1, cell2, out)
      if ok:
         row, col = decode_pos(out)
         self.table.item(row, col).setText("%s %s %s" % (op, cell1, cell2))

   def actionAdd(self):
      self.actionMath_helper("Addition", "+")

   def actionSubtract(self):
      self.actionMath_helper("Subtraction", "-")

   def actionMultiply(self):
      self.actionMath_helper("Multiplication", "*")

   def actionDivide(self):
      self.actionMath_helper("Division", "/")

   def clear(self):
      for i in self.table.selectedItems():
         i.setText("")

   def setupContextMenu(self):
      self.addAction(self.cell_addAction)
      self.addAction(self.cell_subAction)
      self.addAction(self.cell_mulAction)
      self.addAction(self.cell_divAction)
      self.addAction(self.cell_sumAction)
      self.addAction(self.firstSeparator)
      self.addAction(self.colorAction)
      self.addAction(self.fontAction)
      self.addAction(self.secondSeparator)
      self.addAction(self.clearAction)
      self.setContextMenuPolicy(Qt.ActionsContextMenu)

   def setupContents(self):
      titleBackground = QColor(Qt.lightGray)
      titleFont = self.table.font()
      titleFont.setBold(True)
      # column 0
      self.table.setItem(0, 0, SpreadSheetItem("Item"))
      self.table.item(0, 0).setBackground(titleBackground)
      self.table.item(0, 0).setToolTip("This column shows the purchased item/service")
      self.table.item(0, 0).setFont(titleFont)
      self.table.setItem(1, 0, SpreadSheetItem("AirportBus"))
      self.table.setItem(2, 0, SpreadSheetItem("Flight (Munich)"))
      self.table.setItem(3, 0, SpreadSheetItem("Lunch"))
      self.table.setItem(4, 0, SpreadSheetItem("Flight (LA)"))
      self.table.setItem(5, 0, SpreadSheetItem("Taxi"))
      self.table.setItem(6, 0, SpreadSheetItem("Dinner"))
      self.table.setItem(7, 0, SpreadSheetItem("Hotel"))
      self.table.setItem(8, 0, SpreadSheetItem("Flight (Oslo)"))
      self.table.setItem(9, 0, SpreadSheetItem("Total:"))
      self.table.item(9, 0).setFont(titleFont)
      self.table.item(9, 0).setBackground(Qt.lightGray)
      # column 1
      self.table.setItem(0, 1, SpreadSheetItem("Date"))
      self.table.item(0, 1).setBackground(titleBackground)
      self.table.item(0, 1).setToolTip("This column shows the purchase date, double click to change")
      self.table.item(0, 1).setFont(titleFont)
      self.table.setItem(1, 1, SpreadSheetItem("15/6/2006"))
      self.table.setItem(2, 1, SpreadSheetItem("15/6/2006"))
      self.table.setItem(3, 1, SpreadSheetItem("15/6/2006"))
      self.table.setItem(4, 1, SpreadSheetItem("21/5/2006"))
      self.table.setItem(5, 1, SpreadSheetItem("16/6/2006"))
      self.table.setItem(6, 1, SpreadSheetItem("16/6/2006"))
      self.table.setItem(7, 1, SpreadSheetItem("16/6/2006"))
      self.table.setItem(8, 1, SpreadSheetItem("18/6/2006"))
      self.table.setItem(9, 1, SpreadSheetItem())
      self.table.item(9, 1).setBackground(Qt.lightGray)
      # column 2
      self.table.setItem(0, 2, SpreadSheetItem("Price"))
      self.table.item(0, 2).setBackground(titleBackground)
      self.table.item(0, 2).setToolTip("This column shows the price of the purchase")
      self.table.item(0, 2).setFont(titleFont)
      self.table.setItem(1, 2, SpreadSheetItem("150"))
      self.table.setItem(2, 2, SpreadSheetItem("2350"))
      self.table.setItem(3, 2, SpreadSheetItem("-14"))
      self.table.setItem(4, 2, SpreadSheetItem("980"))
      self.table.setItem(5, 2, SpreadSheetItem("5"))
      self.table.setItem(6, 2, SpreadSheetItem("120"))
      self.table.setItem(7, 2, SpreadSheetItem("300"))
      self.table.setItem(8, 2, SpreadSheetItem("1240"))
      self.table.setItem(9, 2, SpreadSheetItem())
      self.table.item(9, 2).setBackground(Qt.lightGray)
      # column 3
      self.table.setItem(0, 3, SpreadSheetItem("Currency"))
      self.table.item(0, 3).setBackgroundColor(titleBackground)
      self.table.item(0, 3).setToolTip("This column shows the currency")
      self.table.item(0, 3).setFont(titleFont)
      self.table.setItem(1, 3, SpreadSheetItem("NOK"))
      self.table.setItem(2, 3, SpreadSheetItem("NOK"))
      self.table.setItem(3, 3, SpreadSheetItem("EUR"))
      self.table.setItem(4, 3, SpreadSheetItem("EUR"))
      self.table.setItem(5, 3, SpreadSheetItem("USD"))
      self.table.setItem(6, 3, SpreadSheetItem("USD"))
      self.table.setItem(7, 3, SpreadSheetItem("USD"))
      self.table.setItem(8, 3, SpreadSheetItem("USD"))
      self.table.setItem(9, 3, SpreadSheetItem())
      self.table.item(9,3).setBackground(Qt.lightGray)
      # column 4
      self.table.setItem(0, 4, SpreadSheetItem("Ex. Rate"))
      self.table.item(0, 4).setBackground(titleBackground)
      self.table.item(0, 4).setToolTip("This column shows the exchange rate to NOK")
      self.table.item(0, 4).setFont(titleFont)
      self.table.setItem(1, 4, SpreadSheetItem("1"))
      self.table.setItem(2, 4, SpreadSheetItem("1"))
      self.table.setItem(3, 4, SpreadSheetItem("8"))
      self.table.setItem(4, 4, SpreadSheetItem("8"))
      self.table.setItem(5, 4, SpreadSheetItem("7"))
      self.table.setItem(6, 4, SpreadSheetItem("7"))
      self.table.setItem(7, 4, SpreadSheetItem("7"))
      self.table.setItem(8, 4, SpreadSheetItem("7"))
      self.table.setItem(9, 4, SpreadSheetItem())
      self.table.item(9,4).setBackground(Qt.lightGray)
      # column 5
      self.table.setItem(0, 5, SpreadSheetItem("NOK"))
      self.table.item(0, 5).setBackground(titleBackground)
      self.table.item(0, 5).setToolTip("This column shows the expenses in NOK")
      self.table.item(0, 5).setFont(titleFont)
      self.table.setItem(1, 5, SpreadSheetItem("* C2 E2"))
      self.table.setItem(2, 5, SpreadSheetItem("* C3 E3"))
      self.table.setItem(3, 5, SpreadSheetItem("* C4 E4"))
      self.table.setItem(4, 5, SpreadSheetItem("* C5 E5"))
      self.table.setItem(5, 5, SpreadSheetItem("* C6 E6"))
      self.table.setItem(6, 5, SpreadSheetItem("* C7 E7"))
      self.table.setItem(7, 5, SpreadSheetItem("* C8 E8"))
      self.table.setItem(8, 5, SpreadSheetItem("* C9 E9"))
      self.table.setItem(9, 5, SpreadSheetItem("sum F2 F9"))
      self.table.item(9,5).setBackground(Qt.lightGray)

   def showAbout(self):
      QMessageBox.about(self, "About Spreadsheet", """
          <HTML>
          <p><b>This demo shows use of <c>QTableWidget</c> with custom handling for
           individual cells.</b></p>
          <p>Using a customized table item we make it possible to have dynamic
           output in different cells. The content that is implemented for this
           particular demo is:
          <ul>
          <li>Adding two cells.</li>
          <li>Subtracting one cell from another.</li>
          <li>Multiplying two cells.</li>
          <li>Dividing one cell with another.</li>
          <li>Summing the contents of an arbitrary number of cells.</li>
          </HTML>
      """)

   def print_(self):
      pass
Beispiel #10
0
class WordsWidget(QWidget):

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

        self.page_number = 1
        self.row = 20

        self.create_layout()
        self.create_connections()
        self.load_words()

    def create_layout(self):
        self.words_table = QTableWidget(0, 8)

        self.dictionaries = Dictionary.objects.all()
        self.dict_combo = QComboBox()
        self.dict_combo.addItems([d.name for d in self.dictionaries])

        self.refresh_button = QPushButton("Refresh")
        self.next_button = QPushButton("Next")
        self.previous_button = QPushButton("Previous")

        hbox = QHBoxLayout()
        hbox.addWidget(QLabel('Dictionary'))
        hbox.addWidget(self.dict_combo)
        hbox.addWidget(self.refresh_button)
        hbox.addStretch()
        hbox.addWidget(self.previous_button)
        hbox.addWidget(self.next_button)

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

        self.setLayout(vbox)

    def create_connections(self):
        self.connect(self.dict_combo, SIGNAL("currentIndexChanged(int)"),
                     self.change_dictionary)
        self.connect(self.refresh_button, SIGNAL("clicked()"), self.load_words)
        self.connect(self.next_button, SIGNAL("clicked()"), self.next_words)
        self.connect(self.previous_button, SIGNAL("clicked()"),
                     self.previous_words)
        self.connect(self.words_table,
                     SIGNAL("itemDoubleClicked(QTableWidgetItem*)"),
                     self.edit_word)

    def next_words(self):
        self.page_number += 1
        self.load_words()

    def previous_words(self):
        self.page_number -= 1
        self.load_words()

    def change_dictionary(self):
        self.page_number = 1
        self.load_words()

    def load_words(self):
        dictionary = self.dictionaries[self.dict_combo.currentIndex()]
        words = Word.objects.filter(dictionary=dictionary.abbrev) \
                    .order_by('original')
        paginator = Paginator(words, self.row, allow_empty_first_page=True)
        try:
            page_obj = paginator.page(self.page_number)
        except InvalidPage:
            return

        self.words_table.clear()
        self.words_table.setRowCount(len(page_obj.object_list))

        self.words_table.setHorizontalHeaderLabels(['Original',
                                                    'Translation',
                                                    'Parts of Speech',
                                                    'Phoneme',
                                                    'Synonyms',
                                                    'Antonyms',
                                                    'Added at',
                                                    'Status'
                                                   ])

        for i, word in enumerate(page_obj.object_list):
            for j, cell in enumerate([word.original, word.translation, word.pos,
                                     word.phoneme, word.synonyms, word.antonyms,
                                     word.added_at.strftime("%Y-%m-%d %H:%M"),
                                      "exported" if word.exported else "new"]):
                item = QTableWidgetItem(cell)
                item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
                self.words_table.setItem(i, j, item)

        self.next_button.setEnabled(page_obj.has_next())
        self.previous_button.setEnabled(page_obj.has_previous())

    def edit_word(self):
        index = self.words_table.currentRow() + self.row * (self.page_number - 1)
        dictionary = self.dictionaries[self.dict_combo.currentIndex()]
        word = Word.objects.filter(dictionary=dictionary.abbrev) \
                    .order_by('original')[index]
        edit_word = AddWordWidget(self)
        edit_word.word = word
        edit_word.words_widget = self
        edit_word.show()
Beispiel #11
0
class ApBbaDlg(QDialog):
    def __init__(self, parent=None, **kwargs):
        super(ApBbaDlg, self).__init__(parent)

        self.bpms = []
        self.quads = []
        self.corrs = []
        self.quad_dkicks = []
        self.cor_dkicks = []

        self.bba = ap.bba.BbaBowtie()

        self.table = QTableWidget(0, 5)
        self.table.setMinimumHeight(120)
        self.table.setMinimumWidth(500)
        self.table.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        hdview = QHeaderView(Qt.Horizontal)
        self.table.setHorizontalHeaderLabels(["QUAD", "BPM.field", "BPM center", "Corr", "Kick"])

        fmbox = QFormLayout()
        self.subprogress = QProgressBar()
        self.subprogress.setTextVisible(True)
        self.subprogress.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
        self.progress = QProgressBar()
        self.progress.setTextVisible(True)
        self.progress.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)
        fmbox.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow)
        fmbox.addRow("Current BPM", self.subprogress)
        fmbox.addRow("All Alignment", self.progress)
        # self.progress.setMaximum(self.repeatbox.value())
        vbox = QVBoxLayout()
        vbox.addWidget(self.table)
        vbox.addLayout(fmbox)

        # hbox.addStretch()
        self.widtab = QTabWidget()

        vbox.addWidget(self.widtab)

        self.setLayout(vbox)

        self.connect(self.widtab, SIGNAL("currentChanged(int)"), self.activateResult)
        self.connect(self.table, SIGNAL("cellClicked(int, int)"), self.activateResult)
        # self.bbathread = ApBbaThread()
        # self.connect(self.bbathread,
        #             SIGNAL("aligned(QString, QString, float, float)"),
        #             self.setResult)
        # self.connect(self.bbathread,
        #             SIGNAL("startAlign(QString, QString, QString)"),
        #             self.appendRecord)

        # self.connect(self.bbathread,
        #             SIGNAL("aligned(QString, QString, float, float)"),
        #             self.bbadlg.appendResult)

    def setInput(self, **kwargs):
        self.bpms = kwargs.get("bpms", [])
        self.quads = kwargs.get("quads", [])
        self.cors = kwargs.get("cors", [])
        self.quad_dkicks = kwargs.get("quad_dkicks", [])
        self.cor_dkicks = kwargs.get("cor_dkicks", [])

    def runAlignment(self, **kwargs):
        self.setInput(**kwargs)
        # self.bbathread.start()
        print "Starting %d measurements" % len(self.bpms)
        self.progress.setMaximum(len(self.bpms))
        self.subprogress.setMaximum(100)
        from cothread.catools import caget, caput

        print __file__, "BBA align", caget("V:2-SR:C30-BI:G2{PH1:11}SA:X")
        self.table.setRowCount(len(self.bpms))
        for i, bpmrec in enumerate(self.bpms):
            print i, bpmrec[0].name, self.quads[i][0].name
            self.bba.setInput(bpmrec, self.quads[i], self.cors[i], self.quad_dkicks[i], self.cor_dkicks[i])
            # self.emit(SIGNAL("startAlign(QString, QString, QString)"),
            #          self.quads[i][0].name, bpmrec[0].name, bpmrec[1])
            self.setNames(i, self.quads[i][0].name, bpmrec[0].name, bpmrec[1], self.cors[i][0].name)
            self.bba.align(verbose=2, guihook=QApplication.processEvents, logger=None, progress=self.subprogress)

            cv1 = BbaMplCanvas()
            cv2 = BbaMplCanvas()
            self.bba.plot(cv1.axes, cv2.axes, factor=(1e6, 1e6))
            cv1.draw()
            cv2.draw()

            wid = QWidget(self)
            hbox = QHBoxLayout()
            hbox.addWidget(cv1)
            hbox.addWidget(cv2)
            wid.setLayout(hbox)
            self.widtab.addTab(wid, "%s.%s" % (bpmrec[0].name, bpmrec[1]))
            self.widtab.setCurrentIndex(i)

            # time.sleep(.1)

            # self.emit(SIGNAL("aligned(QString, QString, float, float)"),
            #          bpmrec[0].name, bpmrec[1], 0.0, 0.0)
            self.setResult(i, bpmrec[0].name, bpmrec[1], self.bba.bpm_fitted, self.bba.cor_fitted)
            self.progress.setValue(i + 1)

    def activateResult(self, i=0, j=0):
        if i < self.widtab.count() and i != self.widtab.currentIndex():
            self.widtab.setCurrentIndex(i)
        if i < self.table.rowCount() and i != self.table.currentRow():
            self.table.setCurrentCell(i, 1)

    def setNames(self, i, quadname, bpmname, fld, corname):
        self.table.setItem(i, 0, QTableWidgetItem(quadname))
        self.table.setItem(i, 1, QTableWidgetItem("{0}.{1}".format(bpmname, fld)))
        self.table.setItem(i, 3, QTableWidgetItem(corname))

    def setResult(self, i, bpmname, fld, bpmval, corval):
        # self.table.setItem(n, 1, QTableWidgetItem(bpmname))
        # self.table.setItem(n, 2, QTableWidgetItem(fld))
        self.table.setItem(i, 2, QTableWidgetItem("%g" % bpmval))
        self.table.setItem(i, 4, QTableWidgetItem("%g" % corval))
        self.table.setCurrentCell(i, 1)
Beispiel #12
0
class ThirdPart(QWizardPage):
    def __init__(self):
        super(ThirdPart, self).__init__()
        self.completed = False
        self.setTitle(u'第三方库设置')
        self.setSubTitle(u'需要设置的第三方库')
        rootLayout = QVBoxLayout()
        rootLayout.setContentsMargins(14, 20, 10, 20)

        self.tw_interface = QTableWidget(0, 3)
        headerLabels = QStringList()
        headerLabels.append(u'库名')
        headerLabels.append(u'库路径')
        headerLabels.append(u'打开')
        self.tw_interface.setHorizontalHeaderLabels(headerLabels)
        self.tw_interface.setSelectionBehavior(1)
        self.tw_interface.setRowCount(0)
        self.tw_interface.setColumnWidth(0, 200)
        self.tw_interface.setColumnWidth(1, 280)
        self.tw_interface.horizontalHeader().setStretchLastSection(True)

        self.mhlayout = QHBoxLayout()
        on_new_btn = QPushButton()
        on_new_btn.setText(u'添加类库')
        on_new_btn.clicked.connect(self.on_new)

        on_delete_btn = QPushButton()
        on_delete_btn.setText(u'删除类库')
        on_delete_btn.clicked.connect(self.on_delete)

        space = QSpacerItem(40, 28, QSizePolicy.Expanding)
        self.mhlayout.addSpacerItem(space)
        self.mhlayout.addWidget(on_new_btn)
        self.mhlayout.addWidget(on_delete_btn)

        rootLayout.addWidget(self.tw_interface)
        rootLayout.addLayout(self.mhlayout)
        self.setLayout(rootLayout)
        self.setStyleSheet(sheetstyle)

        self.alloneEnv = os.getenv('ALLONEDIR', '../..').replace('\\', '/')

    def on_new(self):
        rowIndex = self.tw_interface.rowCount()
        self.tw_interface.setRowCount(rowIndex + 1)
        ptn = self.add_button(rowIndex)
        self.tw_interface.setCellWidget(rowIndex, 2, ptn)

    def on_delete(self):
        rowIndex = self.tw_interface.currentRow()
        if rowIndex != -1:
            self.tw_interface.removeRow(rowIndex)

    def updateTable(self, id):
        filePath = QFileDialog.getOpenFileName(self, "请选择库", self.alloneEnv,
                                               "Library(*.lib)")
        if filePath.isEmpty():
            return
        fileinfo = QFileInfo(filePath)
        libPath = fileinfo.absoluteDir().absolutePath()
        libName = fileinfo.baseName()
        # 支持选择文件后与系统ALLONEDIR比较一下变成相对路径
        # 并且能够手动输入相对路径或包含$(ALLONEDIR)的相对路径
        env = QString(os.getenv('ALLONEDIR', '../..').replace('\\', '/'))
        if env.endsWith('/'):
            env.remove(env.lastIndexOf('/'), 1)
        if libPath.contains(env):
            libPath.replace(env, QString('$$ALLONEDIR'))

        self.tw_interface.setItem(id, 1, QTableWidgetItem(libPath))
        self.tw_interface.setItem(id, 0, QTableWidgetItem(libName))

    def add_button(self, id):
        widget = QWidget()
        fileBtn = QPushButton()
        fileBtn.setText(u'浏览...')
        fileBtn.clicked.connect(lambda: self.updateTable(id))
        hLayout = QHBoxLayout()
        hLayout.addWidget(fileBtn)
        hLayout.setAlignment(Qt.AlignHCenter)
        hLayout.setContentsMargins(0, 0, 0, 0)
        widget.setLayout(hLayout)
        return widget

    def initializePage(self):
        super(ThirdPart, self).initializePage()
        self.tw_interface.setRowCount(len(app.g_configurations.thirdpart_lib))
        row = 0
        for libinfo in app.g_configurations.thirdpart_lib:
            twitem0 = QTableWidgetItem(QString(libinfo["libname"]))
            twitem1 = QTableWidgetItem(QString(libinfo["libpath"]))
            self.tw_interface.setItem(row, 0, twitem0)
            self.tw_interface.setItem(row, 1, twitem1)
            ptn = self.add_button(row)
            self.tw_interface.setCellWidget(row, 2, ptn)
            row += 1

    def validatePage(self):
        thirdpart_libs = []
        if self.tw_interface.rowCount() > 0:
            for i in range(self.tw_interface.rowCount()):
                libinfo = {"libname": "", "libpath": ""}
                libname = self.tw_interface.item(i, 0).text()
                libpath = self.tw_interface.item(i, 1).text()
                #print unicode(libname)
                #print unicode(libpath)
                libinfo["libname"] = unicode(libname)
                libinfo["libpath"] = unicode(libpath)
                thirdpart_libs.append(libinfo)

        print thirdpart_libs
        app.g_configurations.thirdpart_lib = thirdpart_libs
        return True
Beispiel #13
0
class ProfileDlg(QDialog):
    def __init__(self):
        QDialog.__init__(self)
        self.__setup_ui()
        self.__connect_slot()
        self.__settings = QSettings('__cyt', '__yt_ovs')
        #print self.__settings.fileName()
        set_str = to_python_str(self.__settings.value('__profile_record', '').toString())
        set_str = set_str if set_str is not '' else "[]"
        self.__record_list = json.loads(set_str)#[{'ip':'1.1.1.1','port':6641,'schema':'xxxx'},{...}]
        self.__list_to_table_item()
        self.click_ip = ''
        self.click_port = 0
        self.click_schema = ''

    def __setup_ui(self):
        self.setMaximumSize(500, 400)
        self.setMinimumSize(500, 400)

        v_layout = QVBoxLayout()

        #init table widget
        self.__profile_table = QTableWidget()
        self.__profile_table.setColumnCount(3)
        header_list = QStringList()
        header_list << 'ip' << 'port' << 'schema'
        self.__profile_table.setHorizontalHeaderLabels(header_list)
        self.__profile_table.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        self.__profile_table.setSelectionBehavior(QAbstractItemView.SelectRows)

        #init tool widget
        self.__tool_wid = QWidget()
        h_layout = QHBoxLayout()
        h_layout.setContentsMargins(0,0,0,0)

        self.__puls_btn = QPushButton()
        self.__puls_btn.setIcon(QIcon(ICON_IDR + 'arrow_plus.png'))
        self.__puls_btn.setIconSize(QSize(15, 15))
        self.__puls_btn.setMaximumSize(20, 20)

        self.__minus_btn = QPushButton()
        self.__minus_btn.setIcon(QIcon(ICON_IDR + 'arrow_minus.png'))
        self.__minus_btn.setIconSize(QSize(15, 15))
        self.__minus_btn.setMaximumSize(20, 20)

        h_layout.addWidget(self.__puls_btn,0)
        h_layout.addWidget(self.__minus_btn,0)
        h_layout.addStretch(1)
        self.__tool_wid.setLayout(h_layout)


        #v layout
        v_layout.addWidget(self.__profile_table,1)
        v_layout.addWidget(self.__tool_wid,0)

        v_layout.setSpacing(1)

        self.setLayout(v_layout)

    def __connect_slot(self):
        self.connect(self.__puls_btn, SIGNAL('clicked()'), self, SLOT('__on_plus_btn()'))
        self.connect(self.__minus_btn, SIGNAL('clicked()'), self, SLOT('__on_minus_btn()'))
        self.connect(self.__profile_table, SIGNAL('cellDoubleClicked (int,int)'), self, SLOT('__on_profile_double_click(int,int)'))

    def __add_record(self, ip, port, schema):

        count = self.__profile_table.rowCount()
        self.__profile_table.insertRow(count)

        ip_item = QTableWidgetItem(ip)
        ip_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
        item_font = ip_item.font()
        item_font.setPointSizeF(12)
        ip_item.setFont(item_font)

        port_item = QTableWidgetItem(port)
        port_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
        port_item.setFont(item_font)

        schema_item = QTableWidgetItem(schema)
        schema_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
        schema_item.setFont(item_font)



        self.__profile_table.setItem(count, 0, ip_item)
        self.__profile_table.setItem(count, 1, port_item)
        self.__profile_table.setItem(count, 2, schema_item)

    def __clear_table_data(self):
        row_count = self.__profile_table.rowCount()
        rev = [i for i in range(row_count)]
        rev.reverse()
        for i in rev:
            self.__profile_table.removeRow(i)

    def __list_to_table_item(self):
        self.__clear_table_data()
        for record in self.__record_list:
            self.__add_record(record['ip'], str(record['port']), record['schema'])
            #print record

    def __table_item_to_list(self):
        row_count = self.__profile_table.rowCount()
        self.__record_list = []
        for i in range(row_count):
            record = {}
            ip = to_python_str( self.__profile_table.item(i, 0).text() )
            port = int( self.__profile_table.item(i, 1).text() )
            schema = to_python_str(self.__profile_table.item(i, 2).text())
            record["ip"] = ip
            record["port"] = port
            record["schema"] = schema
            self.__record_list.append(record)

        print self.__record_list

    def __check_existed(self, ip, port, schema):
        has_code = con_has_code(ip, port, schema)


        for record in self.__record_list:
            exist_code = con_has_code(record["ip"], record["port"], record["schema"])
            if exist_code == has_code:
                return True

        return False


    def __record_to_settings(self):
        self.__settings.setValue('__profile_record', json.dumps(self.__record_list))


    @pyqtSlot()
    def __on_plus_btn(self):
        new_dlg = NewConnectionDlg()
        if new_dlg.exec_():
            # add to table_widget
            if self.__check_existed(new_dlg.host, new_dlg.port, new_dlg.schema):
                return
            self.__add_record(new_dlg.host, str(new_dlg.port), new_dlg.schema)

        self.__table_item_to_list()
        self.__record_to_settings()


    @pyqtSlot()
    def __on_minus_btn(self):
        select_row = self.__profile_table.currentRow()
        self.__profile_table.removeRow(select_row)

        self.__table_item_to_list()
        self.__record_to_settings()

    @pyqtSlot('int','int')
    def __on_profile_double_click(self, row, column):
        ip_item = self.__profile_table.item(row, 0)
        port_item = self.__profile_table.item(row, 1)
        schema_item = self.__profile_table.item(row, 2)

        self.click_ip = to_python_str(ip_item.text())
        self.click_port = int(port_item.text())
        self.click_schema = to_python_str(schema_item.text())

        self.accept()