class InstalledWidget(QWidget):

    def __init__(self, parent, installed):
        QWidget.__init__(self)
        self._parent = parent
        self._installed = installed
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 3)
        self._table.removeRow(0)
        vbox.addWidget(self._table)
        set_data(self._installed, self._table)
        btnUninstall = QPushButton('Uninstall')
        btnUninstall.setMaximumWidth(100)
        vbox.addWidget(btnUninstall)

        self.connect(btnUninstall, SIGNAL("clicked()"), self._uninstall_plugins)

    def add_table_items(self, plugs):
        self._installed += plugs
        set_data(self._installed, self._table)

    def _uninstall_plugins(self):
        rows = self._table.rowCount()
        pos = rows - 1
        for i in xrange(rows):
            if self._table.item(pos-i, 0) is not None and \
                self._table.item(pos-i, 0).checkState() == Qt.Checked:
                self._parent.mark_as_available(self._installed.pop(pos-i))
                self._table.removeRow(pos-i)

    def reset_table(self, installed):
        self._installed = installed
        while self._table.rowCount() > 0:
            self._table.removeRow(0)
        set_data(self._installed, self._table)
Пример #2
0
    def add_new_table(self, rel, name):
        import itertools

        table = QTableWidget()
        table.setRowCount(0)
        table.setColumnCount(0)

        data = itertools.chain([rel.fields], rel.content)

        for row_data in data:
            row = table.rowCount()
            table.setColumnCount(len(row_data))
            for col, text in enumerate(row_data):
                item = QTableWidgetItem()
                item.setText(text)
                if row == 0:
                    table.setHorizontalHeaderItem(col, item)
                else:
                    table.setItem(row - 1, col, item)
            table.insertRow(row)
        table.removeRow(table.rowCount() - 1)
        self.stacked.addWidget(table)
        self.stacked.setCurrentIndex(self.stacked.count() - 1)
        lateral = Pireal.get_service("lateral")
        lateral.add_item_list([name])
class InstalledWidget(QWidget):

    def __init__(self, parent, installed):
        QWidget.__init__(self)
        self._parent = parent
        self._installed = installed
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 3)
        self._table.removeRow(0)
        vbox.addWidget(self._table)
        set_data(self._installed, self._table)
        btnUninstall = QPushButton('Uninstall')
        btnUninstall.setMaximumWidth(100)
        vbox.addWidget(btnUninstall)

        self.connect(btnUninstall, SIGNAL("clicked()"), self._uninstall_plugins)

    def add_table_items(self, plugs):
        self._installed += plugs
        set_data(self._installed, self._table)

    def _uninstall_plugins(self):
        rows = self._table.rowCount()
        pos = rows - 1
        for i in xrange(rows):
            if self._table.item(pos-i, 0) is not None and \
                self._table.item(pos-i, 0).checkState() == Qt.Checked:
                self._parent.mark_as_available(self._installed.pop(pos-i))
                self._table.removeRow(pos-i)

    def reset_table(self, installed):
        self._installed = installed
        while self._table.rowCount() > 0:
            self._table.removeRow(0)
        set_data(self._installed, self._table)
Пример #4
0
class WellLogEditDialog(QDialog):
    def __init__(self, current_well_name, current_log_name):
        super(WellLogEditDialog, self).__init__()
        self.well = ppp.Well(
            str(CONF.well_dir / ".{}".format(current_well_name)))
        self.current_log_name = current_log_name
        self.well_log = self.well.get_log(current_log_name)

        self.resize(300, 400)
        self.initUI()
        self.button_box.accepted.connect(self.save_edit)
        self.button_box.rejected.connect(self.close)

    def initUI(self):
        self.setWindowIcon(QIcon(':/icon/edit_icon'))
        self.setWindowTitle("Edit Log {}".format(self.current_log_name))
        self.layout = QGridLayout(self)
        # add a QTableWidget
        self.tableWidget = QTableWidget(self)
        self.tableWidget.setColumnCount(2)
        self.tableWidget.setRowCount(0)
        self.tableWidget.setHorizontalHeaderItem(0, QTableWidgetItem("Depth"))
        self.tableWidget.setHorizontalHeaderItem(1, QTableWidgetItem("Data"))
        n = len(self.well_log.depth)
        self.tableWidget.setRowCount(n)
        for i, (de,
                da) in enumerate(zip(self.well_log.depth, self.well_log.data)):
            self.tableWidget.setItem(i, 0, QTableWidgetItem(str(de)))
            self.tableWidget.setItem(i, 1, QTableWidgetItem(str(da)))
        self.layout.addWidget(self.tableWidget)
        # add QDialogButtonBox
        self.button_box = QDialogButtonBox(self)
        self.button_box.setStandardButtons(QDialogButtonBox.Save
                                           | QDialogButtonBox.Cancel)
        self.layout.addWidget(self.button_box)

    def save_edit(self):
        depth_tb = [float(self.tableWidget.item(irow, 0).text()) \
            for irow in range(self.tableWidget.rowCount())]
        data_tb = [float(self.tableWidget.item(irow, 1).text()) \
            for irow in range(self.tableWidget.rowCount())]
        temp_log = ppp.Log()
        temp_log.depth = depth_tb
        temp_log.data = data_tb
        if temp_log != self.well_log:
            reply = QMessageBox.question(
                self, "Save",
                "Log Data has been edited,\nAre you willing to save changes?",
                QMessageBox.Yes, QMessageBox.Cancel)
            if reply == QMessageBox.Yes:
                self.well.update_log(self.current_log_name, temp_log)
                self.well.save_well()
        self.close()
class UpdatesWidget(QWidget):

    def __init__(self, parent, updates):
        QWidget.__init__(self)
        self._parent = parent
        self._updates = updates
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 3)
        self._table.removeRow(0)
        vbox.addWidget(self._table)
        set_data(updates, self._table)
        btnUpdate = QPushButton('Update')
        btnUpdate.setMaximumWidth(100)
        vbox.addWidget(btnUpdate)

        self.connect(btnUpdate, SIGNAL("clicked()"), self._update_plugins)

    def _update_plugins(self):
        rows = self._table.rowCount()
        pos = rows - 1
        plugins = []
        for i in xrange(rows):
            if self._table.item(pos-i, 0) is not None and \
                self._table.item(pos-i, 0).checkState() == Qt.Checked:
                plugins.append(self._updates.pop(pos-i))
                self._table.removeRow(pos-i)
                self._parent.update_plugin(plugins)
Пример #6
0
class SchemeWidget(QWidget):
    def __init__(self, parent, schemes):
        QWidget.__init__(self)
        self._parent = parent
        self._schemes = schemes
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 2)
        self._table.removeRow(0)
        vbox.addWidget(self._table)
        set_data(self._schemes, self._table)
        btnUninstall = QPushButton('Download')
        btnUninstall.setMaximumWidth(100)
        vbox.addWidget(btnUninstall)

        self.connect(btnUninstall, SIGNAL("clicked()"), self._download_scheme)

    def _download_scheme(self):
        rows = self._table.rowCount()
        pos = rows - 1
        schemes = []
        for i in xrange(rows):
            if self._table.item(pos - i, 0) is not None and \
              self._table.item(pos - i, 0).checkState() == Qt.Checked:
                schemes.append(self._schemes.pop(pos - i))
                self._table.removeRow(pos - i)
        self._parent.download_scheme(schemes)
Пример #7
0
class SchemeWidget(QWidget):

    def __init__(self, parent, schemes):
        QWidget.__init__(self)
        self._parent = parent
        self._schemes = schemes
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 2)
        self._table.removeRow(0)
        vbox.addWidget(self._table)
        set_data(self._schemes, self._table)
        btnUninstall = QPushButton('Download')
        btnUninstall.setMaximumWidth(100)
        vbox.addWidget(btnUninstall)

        self.connect(btnUninstall, SIGNAL("clicked()"), self._download_scheme)

    def _download_scheme(self):
        rows = self._table.rowCount()
        pos = rows - 1
        schemes = []
        for i in xrange(rows):
            if self._table.item(pos - i, 0) is not None and \
              self._table.item(pos - i, 0).checkState() == Qt.Checked:
                schemes.append(self._schemes.pop(pos - i))
                self._table.removeRow(pos - i)
        self._parent.download_scheme(schemes)
class UpdatesWidget(QWidget):

    def __init__(self, parent, updates):
        QWidget.__init__(self)
        self._parent = parent
        self._updates = updates
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 3)
        self._table.removeRow(0)
        vbox.addWidget(self._table)
        set_data(updates, self._table)
        btnUpdate = QPushButton('Update')
        btnUpdate.setMaximumWidth(100)
        vbox.addWidget(btnUpdate)

        self.connect(btnUpdate, SIGNAL("clicked()"), self._update_plugins)

    def _update_plugins(self):
        rows = self._table.rowCount()
        pos = rows - 1
        plugins = []
        for i in xrange(rows):
            if self._table.item(pos-i, 0) is not None and \
                self._table.item(pos-i, 0).checkState() == Qt.Checked:
                plugins.append(self._updates.pop(pos-i))
                self._table.removeRow(pos-i)
        self._parent.update_plugin(plugins)
Пример #9
0
    def load_relation(self, filenames=[]):
        """ Load relation from file """

        import csv
        from PyQt4.QtGui import QTableWidgetItem, QTableWidget
        from src.core import relation

        if not filenames:
            native_dialog = QFileDialog.DontUseNativeDialog
            directory = os.path.expanduser("~")
            ffilter = settings.RFILES.split(';;')[-1]
            filenames = QFileDialog.getOpenFileNames(self,
                                                     self.tr("Abrir Archivo"),
                                                     directory, ffilter,
                                                     native_dialog)
            if not filenames:
                return
        lateral = Pireal.get_service("lateral")
        for filename in filenames:
            rel = relation.Relation(filename)
            relation_name = os.path.splitext(os.path.basename(filename))[0]
            self.table_widget.relations[relation_name] = rel
            table = QTableWidget()
            with open(filename, newline='') as f:
                table.setRowCount(0)
                table.setColumnCount(0)
                csv_reader = csv.reader(f)
                for row_data in csv_reader:
                    row = table.rowCount()
                    table.setColumnCount(len(row_data))
                    for column, data in enumerate(row_data):
                        item = QTableWidgetItem()
                        item.setText(data)
                        if row == 0:
                            table.setHorizontalHeaderItem(column, item)
                        else:
                            table.setItem(row - 1, column, item)
                    table.insertRow(row)
                table.removeRow(table.rowCount() - 1)
            self.table_widget.stacked.addWidget(table)
        #FIXME: names
        names = [os.path.splitext(os.path.basename(i))[0]
                 for i in filenames]
        lateral.add_item_list(names)
        lateral.show()
class AvailableWidget(QWidget):

    def __init__(self, parent, available):
        QWidget.__init__(self)
        self._parent = parent
        self._available = available
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 3)
        self._table.removeRow(0)
        vbox.addWidget(self._table)
        set_data(available, self._table)
        btnInstall = QPushButton('Install')
        btnInstall.setMaximumWidth(100)
        vbox.addWidget(btnInstall)

        hbox = QHBoxLayout()
        hbox.addWidget(QLabel('Add an external Plugin. URL Zip File:'))
        self.link = QLineEdit()
        hbox.addWidget(self.link)
        btnAdd = QPushButton('Add')
        hbox.addWidget(btnAdd)
        vbox.addLayout(hbox)
        lblExternalPlugin = QLabel('(Write the URL of the Plugin and press "Add")')
        lblExternalPlugin.setAlignment(Qt.AlignRight)
        vbox.addWidget(lblExternalPlugin)

        self.connect(btnInstall, SIGNAL("clicked()"), self._install_plugins)
        self.connect(btnAdd, SIGNAL("clicked()"), self._install_external)

    def _install_plugins(self):
        rows = self._table.rowCount()
        pos = rows - 1
        plugins = []
        for i in xrange(rows):
            if self._table.item(pos-i, 0) is not None and \
              self._table.item(pos-i, 0).checkState() == Qt.Checked:
                plugins.append(self._available.pop(pos-i))
                self._table.removeRow(pos-i)
        self._parent.download_plugins(plugins)

    def _install_external(self):
        if self.link.text().isEmpty():
            QMessageBox.information(self, 'External Plugins', 'URL from Plugin missing...')
            return
        plug = [
            manage_files.get_module_name(str(self.link.text())),
            'External Plugin',
            '1.0',
            str(self.link.text())
            ]
        self._parent.download_plugins(plug)
        self.link.setText('')

    def add_table_items(self, plugs):
        self._available += plugs
        set_data(self._available, self._table)
Пример #11
0
class InstalledWidget(QWidget):
    """
    This widget show the installed plugins
    """

    def __init__(self, parent, installed):
        QWidget.__init__(self, parent)
        self._parent = parent
        self._installed = installed
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 2)
        self._table.setSelectionMode(QTableWidget.SingleSelection)
        self._table.removeRow(0)
        vbox.addWidget(self._table)
        ui_tools.load_table(self._table, (self.tr('Name'), self.tr('Version')),
            _format_for_table(installed))
        self._table.setColumnWidth(0, 500)
        self._table.setSortingEnabled(True)
        self._table.setAlternatingRowColors(True)
        btnUninstall = QPushButton(self.tr("Uninstall"))
        btnUninstall.setMaximumWidth(100)
        vbox.addWidget(btnUninstall)

        self.connect(btnUninstall, SIGNAL("clicked()"),
            self._uninstall_plugins)
        self.connect(self._table, SIGNAL("itemSelectionChanged()"),
            self._show_item_description)

    def _show_item_description(self):
        item = self._table.currentItem()
        if item is not None:
            data = list(item.data(Qt.UserRole))
            self._parent.show_plugin_info(data)

    def remove_item(self, plugin_name):
        plugin = _get_plugin(plugin_name, self._installed)
        self._installed.remove(plugin)

    def add_table_items(self, plugs):
        self._installed += plugs
        data = _format_for_table(self._installed)
        ui_tools.load_table(self._table, (self.tr('Name'), self.tr('Version')),
            data)

    def _uninstall_plugins(self):
        data = _format_for_table(self._installed)
        plugins = ui_tools.remove_get_selected_items(self._table, data)
        self._parent.mark_as_available(plugins)

    def reset_table(self, installed):
        self._installed = installed
        while self._table.rowCount() > 0:
            self._table.removeRow(0)
        ui_tools.load_table(self._table, (self.tr('Name'), self.tr('Version')),
            self._installed)
Пример #12
0
class InstalledWidget(QWidget):
    """
    This widget show the installed plugins
    """

    def __init__(self, parent, installed):
        QWidget.__init__(self, parent)
        self._parent = parent
        self._installed = installed
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 2)
        self._table.setSelectionMode(QTableWidget.SingleSelection)
        self._table.removeRow(0)
        vbox.addWidget(self._table)
        ui_tools.load_table(self._table, (self.tr('Name'), self.tr('Version')),
            _format_for_table(installed))
        self._table.setColumnWidth(0, 500)
        btnUninstall = QPushButton(self.tr("Uninstall"))
        btnUninstall.setMaximumWidth(100)
        vbox.addWidget(btnUninstall)

        self.connect(btnUninstall, SIGNAL("clicked()"),
            self._uninstall_plugins)
        self.connect(self._table, SIGNAL("itemSelectionChanged()"),
            self._show_item_description)

    def _show_item_description(self):
        item = self._table.currentItem()
        if item is not None:
            data = list(item.data(Qt.UserRole))
            self._parent.show_plugin_info(data)

    def remove_item(self, plugin_name):
        plugin = _get_plugin(plugin_name, self._installed)
        self._installed.remove(plugin)

    def add_table_items(self, plugs):
        self._installed += plugs
        data = _format_for_table(self._installed)
        ui_tools.load_table(self._table, (self.tr('Name'), self.tr('Version')),
            data)

    def _uninstall_plugins(self):
        data = _format_for_table(self._installed)
        plugins = ui_tools.remove_get_selected_items(self._table, data)
        self._parent.mark_as_available(plugins)

    def reset_table(self, installed):
        self._installed = installed
        while self._table.rowCount() > 0:
            self._table.removeRow(0)
        ui_tools.load_table(self._table, (self.tr('Name'), self.tr('Version')),
            self._installed)
Пример #13
0
class AvailableWidget(QWidget):

    def __init__(self, parent, available):
        QWidget.__init__(self)
        self._parent = parent
        self._available = available
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 3)
        self._table.removeRow(0)
        vbox.addWidget(self._table)
        set_data(available, self._table)
        btnInstall = QPushButton('Install')
        btnInstall.setMaximumWidth(100)
        vbox.addWidget(btnInstall)

        hbox = QHBoxLayout()
        hbox.addWidget(QLabel('Add an external Plugin. URL Zip File:'))
        self.link = QLineEdit()
        hbox.addWidget(self.link)
        btnAdd = QPushButton('Add')
        hbox.addWidget(btnAdd)
        vbox.addLayout(hbox)

        self.connect(btnInstall, SIGNAL("clicked()"), self._install_plugins)
        self.connect(btnAdd, SIGNAL("clicked()"), self._install_external)

    def _install_plugins(self):
        rows = self._table.rowCount()
        pos = rows - 1
        plugins = []
        for i in xrange(rows):
            if self._table.item(pos-i, 0) is not None and \
              self._table.item(pos-i, 0).checkState() == Qt.Checked:
                plugins.append(self._available.pop(pos-i))
                self._table.removeRow(pos-i)
                self._parent.download_plugins(plugins)

    def _install_external(self):
        plug = [
            manage_files.get_module_name(str(self.link.text())),
            'External Plugin',
            '1.0',
            str(self.link.text())
            ]
        self._parent.download_plugins(plug)
        self.link.setText('')

    def add_table_items(self, plugs):
        self._available += plugs
        set_data(self._available, self._table)
class AvailableWidget(QWidget):
    def __init__(self, parent, available):
        QWidget.__init__(self)
        self._parent = parent
        self._available = available
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 3)
        self._table.removeRow(0)
        vbox.addWidget(self._table)
        set_data(available, self._table)
        btnInstall = QPushButton("Install")
        btnInstall.setMaximumWidth(100)
        vbox.addWidget(btnInstall)

        hbox = QHBoxLayout()
        hbox.addWidget(QLabel("Add an external Plugin. URL Zip File:"))
        self.link = QLineEdit()
        hbox.addWidget(self.link)
        btnAdd = QPushButton("Add")
        hbox.addWidget(btnAdd)
        vbox.addLayout(hbox)
        lblExternalPlugin = QLabel('(Write the URL of the Plugin and press "Add")')
        lblExternalPlugin.setAlignment(Qt.AlignRight)
        vbox.addWidget(lblExternalPlugin)

        self.connect(btnInstall, SIGNAL("clicked()"), self._install_plugins)
        self.connect(btnAdd, SIGNAL("clicked()"), self._install_external)

    def _install_plugins(self):
        rows = self._table.rowCount()
        pos = rows - 1
        plugins = []
        for i in xrange(rows):
            if self._table.item(pos - i, 0) is not None and self._table.item(pos - i, 0).checkState() == Qt.Checked:
                plugins.append(self._available.pop(pos - i))
                self._table.removeRow(pos - i)
        self._parent.download_plugins(plugins)

    def _install_external(self):
        if self.link.text().isEmpty():
            QMessageBox.information(self, "External Plugins", "URL from Plugin missing...")
            return
        plug = [manage_files.get_module_name(str(self.link.text())), "External Plugin", "1.0", str(self.link.text())]
        self._parent.download_plugins(plug)
        self.link.setText("")

    def add_table_items(self, plugs):
        self._available += plugs
        set_data(self._available, self._table)
Пример #15
0
class InstalledWidget(QWidget):
    """
    This widget show the installed plugins
    """

    def __init__(self, parent, installed):
        QWidget.__init__(self, parent)
        self._parent = parent
        self._installed = installed
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 5)
        self._table.removeRow(0)
        self._headers = ('Name', 'Version', 'Description', "Authors", "Web")
        vbox.addWidget(self._table)
        ui_tools.load_table(self._table, self._headers,
            _format_for_table(installed))
        self._table.setColumnWidth(0, 200)
        btnUninstall = QPushButton(self.tr("Uninstall"))
        btnUninstall.setMaximumWidth(100)
        vbox.addWidget(btnUninstall)

        self.connect(btnUninstall, SIGNAL("clicked()"),
            self._uninstall_plugins)

    def remove_item(self, plugin_name):
        plugin = _get_plugin(plugin_name, self._installed)
        self._installed.remove(plugin)

    def add_table_items(self, plugs):
        self._installed += plugs
        data = _format_for_table(self._installed)
        ui_tools.load_table(self._table, self._headers, data)

    def _uninstall_plugins(self):
        data = _format_for_table(self._installed)
        plugins = ui_tools.remove_get_selected_items(self._table, data)
        self._parent.mark_as_available(plugins)

    def reset_table(self, installed):
        self._installed = installed
        while self._table.rowCount() > 0:
            self._table.removeRow(0)
        ui_tools.load_table(self._table, self._headers, self._installed)
Пример #16
0
    def saveZotero(self):
        #Write what happens to save to zotero here
        rows = range(0,
                     QTableWidget.rowCount(self.dlgTable.tableWidget_Zotero))
        for row in rows:
            #get the itemID(zotero key) and geometry cells from the table - itemAt(x,y)
            itemKey = self.dlgTable.tableWidget_Zotero.item(row, 0).text()
            extraString = self.dlgTable.tableWidget_Zotero.item(row, 4).text()
            QgsMessageLog.logMessage(
                "row: %s  itemKey: %s  extraString: %s" %
                (row, itemKey, extraString), 'LiteratureMapper',
                QgsMessageLog.INFO)

            request_url = 'https://api.zotero.org/users/%s/items/%s' % (
                self.userID, itemKey)
            item_request = requests.get(request_url)
            QgsMessageLog.logMessage(
                "Item Request Response: %s" % item_request.status_code,
                'LiteratureMapper', QgsMessageLog.INFO)
            item_json = json.load(urllib2.urlopen(request_url))
            item_json['data']['extra'] = extraString
            item_json = json.dumps(item_json)
            put_request = requests.put(request_url,
                                       data=item_json,
                                       headers={
                                           'Authorization':
                                           'Bearer %s' % (self.apiKey),
                                           'Content-Type':
                                           'application/json'
                                       })
            QgsMessageLog.logMessage(
                "Put Response: %s" % put_request.status_code,
                'LiteratureMapper', QgsMessageLog.INFO)
            statuscode = put_request.status_code
        # Message bar for result
        # TODO: make it check all the results, not just the last one
        if statuscode == 204:
            self.iface.messageBar().pushMessage("Locations saved to Zotero.",
                                                level=4)
            #QMessageBox.information(self.dlgTable(),"Info", "Locations Saved")
        else:
            self.iface.messageBar().pushMessage(
                "Failed to save locations to Zotero", level=3)
Пример #17
0
class InstalledWidget(QWidget):
    """
    This widget show the installed plugins
    """
    def __init__(self, parent, installed):
        QWidget.__init__(self, parent)
        self._parent = parent
        self._installed = installed
        vbox = QVBoxLayout(self)
        self._table = QTableWidget(1, 5)
        self._table.removeRow(0)
        self._headers = ('Name', 'Version', 'Description', "Authors", "Web")
        vbox.addWidget(self._table)
        ui_tools.load_table(self._table, self._headers,
                            _format_for_table(installed))
        self._table.setColumnWidth(0, 200)
        btnUninstall = QPushButton(self.tr("Uninstall"))
        btnUninstall.setMaximumWidth(100)
        vbox.addWidget(btnUninstall)

        self.connect(btnUninstall, SIGNAL("clicked()"),
                     self._uninstall_plugins)

    def remove_item(self, plugin_name):
        plugin = _get_plugin(plugin_name, self._installed)
        self._installed.remove(plugin)

    def add_table_items(self, plugs):
        self._installed += plugs
        data = _format_for_table(self._installed)
        ui_tools.load_table(self._table, self._headers, data)

    def _uninstall_plugins(self):
        data = _format_for_table(self._installed)
        plugins = ui_tools.remove_get_selected_items(self._table, data)
        self._parent.mark_as_available(plugins)

    def reset_table(self, installed):
        self._installed = installed
        while self._table.rowCount() > 0:
            self._table.removeRow(0)
        ui_tools.load_table(self._table, self._headers, self._installed)
Пример #18
0
class SimpleListDlg(QDialog):
    def __init__(self, parent = None, datalist = None, mode='r'):
        super(SimpleListDlg, self).__init__(parent)
        self.tbl = QTableWidget()
        self.mode = mode # read only or write 'r'/'w'
        self.values = []
        if datalist is not None:
            data = datalist.toList()
            self.tbl.setRowCount(len(data))
            self.tbl.setColumnCount(1)
            for i,val in enumerate(data):
                #print i, val.toFloat()
                self.values.append(val.toFloat()[0])
                it = QTableWidgetItem("%g" % val.toFloat()[0])
                if self.mode == 'r':
                    it.setFlags(it.flags() & ~Qt.ItemIsEditable)
                self.tbl.setItem(i,0,it)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok|
                                     QDialogButtonBox.Cancel)
        layout = QVBoxLayout()
        layout.addWidget(self.tbl)
        layout.addWidget(buttonBox)
        self.setLayout(layout)

        self.connect(buttonBox, SIGNAL("accepted()"), self.accept)
        self.connect(buttonBox, SIGNAL("rejected()"), self.reject)


    def accept(self):
        self.values = []
        for i in range(self.tbl.rowCount()):
            v = self.tbl.item(i,0).data(Qt.EditRole).toFloat()
            if self.mode == 'w': self.values.append(v[0])
        self.done(0)

    def reject(self):
        self.values = []
        self.done(0)
Пример #19
0
class SimpleListDlg(QDialog):
    def __init__(self, parent = None, datalist = None, mode='r'):
        super(SimpleListDlg, self).__init__(parent)
        self.tbl = QTableWidget()
        self.mode = mode # read only or write 'r'/'w'
        self.values = []
        if datalist is not None:
            data = datalist.toList()
            self.tbl.setRowCount(len(data))
            self.tbl.setColumnCount(1)
            for i,val in enumerate(data):
                #print i, val.toFloat()
                self.values.append(val.toFloat()[0])
                it = QTableWidgetItem("%g" % val.toFloat()[0])
                if self.mode == 'r': 
                    it.setFlags(it.flags() & ~Qt.ItemIsEditable)
                self.tbl.setItem(i,0,it)
        
        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok|
                                     QDialogButtonBox.Cancel)
        layout = QVBoxLayout()
        layout.addWidget(self.tbl)
        layout.addWidget(buttonBox)
        self.setLayout(layout)

        self.connect(buttonBox, SIGNAL("accepted()"), self.accept)
        self.connect(buttonBox, SIGNAL("rejected()"), self.reject)


    def accept(self):
        self.values = []
        for i in range(self.tbl.rowCount()):
            v = self.tbl.item(i,0).data(Qt.EditRole).toFloat()
            if self.mode == 'w': self.values.append(v[0])
        self.done(0)

    def reject(self):
        self.values = []
        self.done(0)
    def saveZotero(self):
        # Write what happens to save to zotero here
        rows = range(0, QTableWidget.rowCount(self.dlgTable.tableWidget_Zotero))
        for row in rows:
            # get the itemID(zotero key) and geometry cells from the table - itemAt(x,y)
            itemKey = self.dlgTable.tableWidget_Zotero.item(row, 0).text()
            extraString = self.dlgTable.tableWidget_Zotero.item(row, 4).text()
            QgsMessageLog.logMessage(
                "row: %s  itemKey: %s  extraString: %s" % (row, itemKey, extraString),
                "LiteratureMapper",
                QgsMessageLog.INFO,
            )

            request_url = "https://api.zotero.org/users/%s/items/%s" % (self.userID, itemKey)
            item_request = requests.get(request_url)
            QgsMessageLog.logMessage(
                "Item Request Response: %s" % item_request.status_code, "LiteratureMapper", QgsMessageLog.INFO
            )
            item_json = json.load(urllib2.urlopen(request_url))
            item_json["data"]["extra"] = extraString
            item_json = json.dumps(item_json)
            put_request = requests.put(
                request_url,
                data=item_json,
                headers={"Authorization": "Bearer %s" % (self.apiKey), "Content-Type": "application/json"},
            )
            QgsMessageLog.logMessage(
                "Put Response: %s" % put_request.status_code, "LiteratureMapper", QgsMessageLog.INFO
            )
            statuscode = put_request.status_code
        # Message bar for result
        # TODO: make it check all the results, not just the last one
        if statuscode == 204:
            self.iface.messageBar().pushMessage("Locations saved to Zotero.", level=4)
            # QMessageBox.information(self.dlgTable(),"Info", "Locations Saved")
        else:
            self.iface.messageBar().pushMessage("Failed to save locations to Zotero", level=3)
Пример #21
0
class GraphDialog(QDialog):

    edit_patterns = 0
    edit_curves = 1

    titles = {edit_patterns: 'Pattern editor', edit_curves: 'Curve editor'}

    labels = {edit_patterns: 'Patterns', edit_curves: 'Curves'}

    def __init__(self, dockwidget, parent, params, edit_type):

        QDialog.__init__(self, parent)
        main_lay = QVBoxLayout(self)
        self.dockwidget = dockwidget
        self.params = params
        self.edit_type = edit_type

        self.x_label = ''
        self.y_label = ''

        self.setMinimumWidth(600)
        self.setMinimumHeight(400)

        self.setWindowTitle(self.titles[edit_type])  # TODO: softcode
        self.setWindowModality(QtCore.Qt.ApplicationModal)

        self.current = None

        self.current_saved = False

        # File
        self.lbl_file = QLabel('File:')
        self.fra_file = QFrame()
        self.fra_file.setContentsMargins(0, 0, 0, 0)
        fra_file_lay = QHBoxLayout(self.fra_file)

        if edit_type == self.edit_patterns:
            self.txt_file = QLineEdit(self.params.patterns_file)
        elif edit_type == self.edit_curves:
            self.txt_file = QLineEdit(self.params.curves_file)

        self.txt_file.setReadOnly(True)
        self.txt_file.setAlignment(QtCore.Qt.AlignLeft
                                   | QtCore.Qt.AlignVCenter)
        self.txt_file.setSizePolicy(QSizePolicy.MinimumExpanding,
                                    QSizePolicy.Minimum)
        fra_file_lay.addWidget(self.txt_file)
        self.btn_file = QPushButton('Change')  # TODO: softcode
        self.btn_file.clicked.connect(self.import_file)
        fra_file_lay.addWidget(self.btn_file)
        fra_file_lay.setContentsMargins(0, 0, 0, 0)

        self.lbl_list = QLabel(self.labels[edit_type])
        self.lst_list = QListWidget()
        self.lst_list.currentItemChanged.connect(self.list_item_changed)

        # Form
        self.fra_form = QFrame()
        fra_form1_lay = QFormLayout(self.fra_form)
        fra_form1_lay.setContentsMargins(0, 0, 0, 0)
        fra_form1_lay.addRow(self.lbl_list, self.lst_list)

        # Buttons
        self.fra_buttons = QFrame()
        fra_buttons_lay = QHBoxLayout(self.fra_buttons)
        fra_buttons_lay.setContentsMargins(0, 0, 0, 0)

        if self.edit_type == self.edit_patterns:
            ele_name = 'pattern'
        elif self.edit_type == self.edit_curves:
            ele_name = 'curve'

        self.btn_new = QPushButton('New ' + ele_name)  # TODO: softcode
        self.btn_new.clicked.connect(self.new_element)
        fra_buttons_lay.addWidget(self.btn_new)

        self.btn_import = QPushButton('Import ' + ele_name +
                                      's')  # TODO: softcode
        self.btn_import.clicked.connect(self.import_file)
        fra_buttons_lay.addWidget(self.btn_import)

        self.btn_save = QPushButton('Save current ' +
                                    ele_name)  # TODO: softcode
        self.btn_save.clicked.connect(self.save)
        fra_buttons_lay.addWidget(self.btn_save)

        self.btn_del = QPushButton('Delete current ' +
                                   ele_name)  # TODO: softcode
        self.btn_del.clicked.connect(self.del_item)
        fra_buttons_lay.addWidget(self.btn_del)

        # ID
        self.lbl_id = QLabel('ID:')
        self.txt_id = QLineEdit()
        self.txt_id.setSizePolicy(QSizePolicy.Maximum,
                                  QSizePolicy.MinimumExpanding)
        self.lbl_desc = QLabel('Desc.:')
        self.txt_desc = QLineEdit()

        self.fra_id = QFrame()
        fra_id_lay = QHBoxLayout(self.fra_id)
        fra_id_lay.addWidget(self.lbl_id)
        fra_id_lay.addWidget(self.txt_id)
        fra_id_lay.addWidget(self.lbl_desc)
        fra_id_lay.addWidget(self.txt_desc)

        # Table form
        self.table = QTableWidget(self)
        self.rows_nr = 24
        self.cols_nr = 2
        self.table.setRowCount(self.rows_nr)
        self.table.setColumnCount(self.cols_nr)
        self.table.verticalHeader().setVisible(False)

        # Initialize empty table
        self.clear_table()

        self.table.itemChanged.connect(self.data_changed)

        self.fra_table = QFrame()
        fra_table_lay = QVBoxLayout(self.fra_table)
        fra_table_lay.setContentsMargins(0, 0, 0, 0)

        if edit_type == self.edit_curves:
            self.fra_pump_type = QFrame()
            fra_pump_type_lay = QFormLayout(self.fra_pump_type)

            self.lbl_pump_type = QLabel('Curve type:')  # TODO: softcode
            self.cbo_pump_type = QComboBox()

            for key, name in Curve.type_names.iteritems():
                self.cbo_pump_type.addItem(name, key)

            fra_pump_type_lay.addRow(self.lbl_pump_type, self.cbo_pump_type)

            fra_table_lay.addWidget(self.fra_pump_type)

            self.cbo_pump_type.activated.connect(self.cbo_pump_type_activated)

        fra_table_lay.addWidget(self.table)
        self.btn_add_row = QPushButton('Add row')
        self.btn_add_row.clicked.connect(self.add_row)
        fra_table_lay.addWidget(self.btn_add_row)

        # Graph canvas
        self.fra_graph = QFrame()
        self.static_canvas = StaticMplCanvas(self.fra_graph,
                                             width=5,
                                             height=4,
                                             dpi=100)
        fra_graph_lay = QVBoxLayout(self.fra_graph)
        fra_graph_lay.addWidget(self.static_canvas)

        # Top frame
        self.fra_top = QFrame()
        fra_top_lay = QVBoxLayout(self.fra_top)
        fra_top_lay.addWidget(self.fra_form)
        fra_top_lay.addWidget(self.fra_id)
        fra_top_lay.addWidget(self.fra_buttons)

        # Bottom frame
        self.fra_bottom = QFrame()
        fra_bottom_lay = QHBoxLayout(self.fra_bottom)
        fra_bottom_lay.addWidget(self.fra_table)
        fra_bottom_lay.addWidget(self.fra_graph)

        # Main
        main_lay.addWidget(self.fra_top)
        main_lay.addWidget(self.fra_bottom)

        # Get existing patterns/curves
        self.need_to_update_graph = False
        if self.edit_type == self.edit_patterns:
            for pattern_id, pattern in self.params.patterns.iteritems():
                self.lst_list.addItem(pattern.id)

        elif self.edit_type == self.edit_curves:
            for curve_id, curve in self.params.curves.iteritems():
                self.lst_list.addItem(curve.id)

        if self.lst_list.count() > 0:
            self.lst_list.setCurrentRow(0)
            self.txt_id.setEnabled(True)
            self.txt_desc.setEnabled(True)
            self.btn_save.setEnabled(True)
            self.btn_del.setEnabled(True)
            self.table.setEnabled(True)
            self.table.setEditTriggers(QAbstractItemView.AllEditTriggers)
        else:
            self.txt_id.setEnabled(False)
            self.txt_desc.setEnabled(False)
            self.btn_save.setEnabled(False)
            self.btn_del.setEnabled(False)
            self.table.setEnabled(False)
            self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)

        self.new_dialog = None
        self.need_to_update_graph = True

    def cbo_pump_type_activated(self):
        self.update_table_headers()
        self.update_graph()

    def add_row(self):
        row_pos = self.table.rowCount()
        self.table.insertRow(row_pos)
        col = 0
        item = QTableWidgetItem(str(row_pos))

        if self.edit_type == self.edit_patterns:
            self.table.setItem(row_pos, col, item)
            item.setFlags(QtCore.Qt.ItemIsSelectable)

    def setVisible(self, bool):
        QDialog.setVisible(self, bool)

        self.update_table_headers()
        self.update_graph()

    def list_item_changed(self):

        p_index = self.lst_list.currentRow()

        flags = Qt.ItemFlags()
        flags != Qt.ItemIsEnabled

        # Clear table
        self.clear_table()

        self.need_to_update_graph = False
        if p_index >= 0:

            self.table.setRowCount(0)

            if self.edit_type == self.edit_patterns:
                self.current = self.params.patterns[
                    self.lst_list.currentItem().text()]
                for v in range(len(self.current.values)):

                    row_pos = self.table.rowCount()
                    self.table.insertRow(row_pos)

                    item = QTableWidgetItem(str(v))
                    item.setFlags(flags)
                    self.table.setItem(v, 0, item)
                    self.table.setItem(
                        v, 1, QTableWidgetItem(str(self.current.values[v])))

            elif self.edit_type == self.edit_curves:
                self.current = self.params.curves[
                    self.lst_list.currentItem().text()]
                for v in range(len(self.current.xs)):

                    row_pos = self.table.rowCount()
                    self.table.insertRow(row_pos)

                    self.table.setItem(
                        v, 0, QTableWidgetItem(str(self.current.xs[v])))
                    self.table.setItem(
                        v, 1, QTableWidgetItem(str(self.current.ys[v])))

                curve_type = self.current.type
                self.cbo_pump_type.setCurrentIndex(curve_type)

            # Update GUI
            self.txt_id.setText(self.current.id)
            self.txt_desc.setText(self.current.desc)

            self.update_table_headers()

            # Update graph
            self.need_to_update_graph = True
            self.update_graph()

        else:

            # No curves
            self.txt_id.setText('')
            self.txt_desc.setText('')

            # Update table and chart
            self.need_to_update_graph = False
            for v in range(self.table.columnCount()):
                self.table.setItem(v, 1, QTableWidgetItem(''))

            self.need_to_update_graph = True
            self.update_graph()

    def import_file(self):

        config_file = ConfigFile(Parameters.config_file_path)

        directory = None
        if self.edit_type == GraphDialog.edit_curves:
            directory = self.params.last_curves_dir
        elif self.edit_type == GraphDialog.edit_patterns:
            directory = self.params.last_patterns_dir

        if directory is None:
            directory = self.params.last_project_dir

        file_path = QFileDialog.getOpenFileName(self, 'Select file', directory,
                                                'Files (*.txt *.inp)')

        if file_path is None or file_path == '':
            return
        else:
            if self.edit_type == GraphDialog.edit_patterns:
                # Save patterns file path in configuration file
                config_file.set_patterns_file_path(file_path)
                Parameters.patterns_file = file_path
            elif self.edit_type == GraphDialog.edit_curves:
                # Save curve file path in configuration file
                config_file.set_curves_file_path(file_path)
                Parameters.curves_file = file_path

        self.read(file_path)

    def read(self, file_path):

        self.lst_list.clear()

        if self.edit_type == self.edit_patterns:
            InpFile.read_patterns(self.params, file_path)
            for pattern_id, pattern in self.params.patterns.iteritems():
                # desc = ' (' + pattern.desc + ')' if pattern.desc is not None else ''
                self.lst_list.addItem(pattern.id)
                self.params.patterns[pattern.id] = pattern

        elif self.edit_type == self.edit_curves:
            InpFile.read_curves(self.params, file_path)
            for curve_id, curve in self.params.curves.iteritems():
                # desc = ' (' + curve.desc + ')' if curve.desc is not None else ''
                self.lst_list.addItem(curve.id)
                self.params.curves[curve.id] = curve

        if self.lst_list.count() > 0:
            self.lst_list.setCurrentRow(0)

    def new_element(self):

        old_ids = []
        if self.edit_type == self.edit_patterns:
            for pattern in self.params.patterns.itervalues():
                old_ids.append(pattern.id)
        elif self.edit_type == self.edit_curves:
            for curve in self.params.curves.itervalues():
                old_ids.append(curve.id)
        self.new_dialog = NewIdDialog(self, old_ids)
        self.new_dialog.exec_()

        new_id = self.new_dialog.get_newid()
        description = self.new_dialog.get_description()
        if new_id is None or description is None:
            return

        if self.edit_type == self.edit_patterns:
            new_pattern = Pattern(new_id, description)
            self.params.patterns[new_pattern.id] = new_pattern
            self.lst_list.addItem(new_pattern.id)
        elif self.edit_type == self.edit_curves:
            curve_type = self.cbo_pump_type.itemData(
                self.cbo_pump_type.currentIndex())
            new_curve = Curve(new_id, curve_type, desc=description)
            self.params.curves[new_curve.id] = new_curve
            self.lst_list.addItem(new_curve.id)

        self.lst_list.setCurrentRow(self.lst_list.count() - 1)

        self.txt_id.setText(new_id)
        self.txt_desc.setText(description)

        # Clear table
        self.clear_table()
        self.static_canvas.axes.clear()

        self.txt_id.setEnabled(True)
        self.txt_desc.setEnabled(True)
        self.btn_save.setEnabled(True)
        self.btn_del.setEnabled(True)
        self.table.setEnabled(True)
        self.table.setEditTriggers(QAbstractItemView.AllEditTriggers)

    def save(self):

        self.need_to_update_graph = False

        # Check for ID
        if not self.txt_id.text():
            QMessageBox.warning(
                self,
                Parameters.plug_in_name,
                u'Please specify the ID.',  # TODO: softcode
                QMessageBox.Ok)
            return

        if self.edit_type == GraphDialog.edit_patterns:
            values = []
            for row in range(self.table.rowCount()):
                item = self.table.item(row, 1)
                if item is not None and item.text() != '':
                    values.append(self.from_item_to_val(item))
                else:
                    values.append('0')

            pattern = Pattern(self.txt_id.text(), self.txt_desc.text(), values)

            old_patterns = self.params.patterns
            old_patterns[pattern.id] = pattern
            self.params.patterns = old_patterns

            self.lst_list.currentItem().setText(pattern.id)

        elif self.edit_type == GraphDialog.edit_curves:

            # Check for ID unique
            xs = []
            ys = []
            for row in range(self.table.rowCount()):
                item_x = self.table.item(row, 0)
                item_y = self.table.item(row, 1)

                if item_x.text() != '' and item_y.text() != '':
                    xs.append(self.from_item_to_val(item_x))
                    ys.append(self.from_item_to_val(item_y))

            curve_type = self.cbo_pump_type.itemData(
                self.cbo_pump_type.currentIndex())
            curve = Curve(self.txt_id.text(), curve_type, self.txt_desc.text())
            for v in range(len(xs)):
                curve.append_xy(xs[v], ys[v])

            old_curves = self.params.curves
            old_curves[curve.id] = curve
            self.params.curves = old_curves

            self.lst_list.currentItem().setText(curve.id)

            # Update GUI
            self.dockwidget.update_curves_combo()

        # self.read()
        self.need_to_update_graph = True

    def clear_table(self):

        self.need_to_update_graph = False
        for r in range(self.table.rowCount()):
            self.table.setItem(r, 0, QTableWidgetItem(None))
            self.table.setItem(r, 1, QTableWidgetItem(None))

        for row in range(self.rows_nr):
            for col in range(self.cols_nr):
                if self.edit_type == self.edit_patterns:
                    if col == 0:
                        item = QTableWidgetItem(str(row))
                        self.table.setItem(row, col, item)
                        item.setFlags(QtCore.Qt.ItemIsSelectable)
                    # elif col == 1 and row == 0:
                    #     item = QTableWidgetItem(str(1))
                    #     self.table.setItem(row, col, item)
                    #     item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)

                # elif self.edit_type == self.edit_curves:
                # if row == 0:
                # item = QTableWidgetItem(str(0))
                # self.table.setItem(row, 0, item)
                # item = QTableWidgetItem(str(1))
                # self.table.setItem(row, 1, item)
                # item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        self.need_to_update_graph = True

    def del_item(self):
        selected_row = self.lst_list.currentRow()
        name = self.lst_list.currentItem().text()
        if selected_row < 0:
            return

        self.lst_list.takeItem(selected_row)
        if self.lst_list.count() == 0:
            self.txt_id.setEnabled(False)
            self.txt_desc.setEnabled(False)
            self.btn_save.setEnabled(False)
            self.btn_del.setEnabled(False)
            self.table.setEnabled(False)
            self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)

        if self.edit_type == GraphDialog.edit_curves:
            del self.params.curves[name]
            # Update GUI
            self.dockwidget.update_curves_combo()
        elif self.edit_type == GraphDialog.edit_patterns:
            del self.params.patterns[name]
            # Update GUI
            self.dockwidget.update_patterns_combo()

    def data_changed(self):

        if self.need_to_update_graph:
            self.update_graph()

    def update_table_headers(self):
        if self.edit_type == self.edit_patterns:
            self.x_label = 'Time period'
            self.y_label = 'Multiplier'
        elif self.edit_type == self.edit_curves:
            cbo_data = self.cbo_pump_type.itemData(
                self.cbo_pump_type.currentIndex())
            if cbo_data == Curve.type_efficiency:
                self.x_label = 'Flow ' + '[' + self.params.options.flow_units + ']'
                self.y_label = 'Efficiency ' + '[' + self.params.options.units_deltaz[
                    self.params.options.units] + ']'
            if cbo_data == Curve.type_headloss:
                self.x_label = 'Flow ' + '[' + self.params.options.flow_units + ']'
                self.y_label = 'Headloss ' + '[' + self.params.options.units_deltaz[
                    self.params.options.units] + ']'
            if cbo_data == Curve.type_pump:
                self.x_label = 'Flow ' + '[' + self.params.options.flow_units + ']'
                self.y_label = 'Head ' + '[' + self.params.options.units_deltaz[
                    self.params.options.units] + ']'
            if cbo_data == Curve.type_volume:
                self.x_label = 'Height ' + '[' + self.params.options.flow_units + ']'
                self.y_label = 'Volume ' + '[' + self.params.options.units_deltaz[
                    self.params.options.units] + ']'

        self.table.setHorizontalHeaderLabels([self.x_label,
                                              self.y_label])  # TODO: softcode

    def update_graph(self):

        if not self.need_to_update_graph:
            return

        xs = []
        ys = []

        for row in range(self.table.rowCount()):
            item = self.table.item(row, 0)
            x = self.from_item_to_val(item)
            item = self.table.item(row, 1)
            y = self.from_item_to_val(item)

            if x is not None:
                xs.append(float(x))
            if y is not None:
                ys.append(float(y))

        if len(xs) == 0 or len(ys) == 0:
            self.static_canvas.clear()
            return

        xys_t = zip(xs, ys)
        xys_t.sort()

        xys = zip(*xys_t)
        xs = xys[0]
        ys = xys[1]

        if self.edit_type == self.edit_patterns:
            y_axis_label = 'Mult. avg.: ' + '{0:.2f}'.format(
                (numpy.average(ys)))
            self.static_canvas.draw_bars_graph(
                ys,
                time_period=self.params.times.pattern_timestep,
                y_axes_label=y_axis_label)

        elif self.edit_type == self.edit_curves:

            # Account for different types of curves
            cbo_data = self.cbo_pump_type.itemData(
                self.cbo_pump_type.currentIndex())

            series_length = min(len(xs), len(ys))

            # Need to account for different types of curves
            if cbo_data == Curve.type_efficiency or cbo_data == Curve.type_headloss or cbo_data == Curve.type_volume:
                self.static_canvas.draw_line_graph(xs[:series_length],
                                                   ys[:series_length],
                                                   self.x_label, self.y_label)

            elif cbo_data == Curve.type_pump:
                if series_length == 1 or series_length == 3:
                    if series_length == 1:
                        # 3 curve points
                        curve_xs = [0, xs[0], xs[0] * 2]
                        curve_ys = [ys[0] * 1.33, ys[0], 0]
                        # y = a * x^2 + b * x + c

                    elif series_length == 3:
                        # 3 curve points
                        curve_xs = [xs[0], xs[1], xs[2]]
                        curve_ys = [ys[0], ys[1], ys[2]]

                    (a, b, c) = numpy.polyfit(curve_xs, curve_ys, 2)

                    # Create a few interpolated values
                    interp_xs = []
                    interp_ys = []
                    n_vals = 30
                    for v in range(n_vals + 1):
                        x = (curve_xs[2] - curve_xs[0]) / n_vals * v
                        interp_xs.append(x)
                        y = a * x**2 + b * x + c
                        interp_ys.append(y)

                    self.static_canvas.draw_line_graph(interp_xs, interp_ys,
                                                       self.x_label,
                                                       self.y_label)

                else:
                    self.static_canvas.draw_line_graph(xs[:series_length],
                                                       ys[:series_length],
                                                       self.x_label,
                                                       self.y_label)

    def from_item_to_val(self, item):

        if item is None:
            value = None
        else:
            value = item.text()
        try:
            value = float(value)
            value = max(value, 0)

        except:
            value = None

        return value
Пример #22
0
class Main(plugin.Plugin):
    " Main Class "

    def initialize(self, *args, **kwargs):
        " Init Main Class "
        super(Main, self).initialize(*args, **kwargs)
        self.scriptPath, self.scriptArgs = "", []
        self.profilerPath, self.tempPath = profilerPath, tempPath
        self.output = " ERROR: FAIL: No output ! "

        self.process = QProcess()
        self.process.finished.connect(self.on_process_finished)
        self.process.error.connect(self.on_process_error)

        self.tabWidget, self.stat = QTabWidget(), QWidget()
        self.tabWidget.tabCloseRequested.connect(
            lambda: self.tabWidget.setTabPosition(1) if self.tabWidget.
            tabPosition() == 0 else self.tabWidget.setTabPosition(0))
        self.tabWidget.setStyleSheet('QTabBar{font-weight:bold;}')
        self.tabWidget.setMovable(True)
        self.tabWidget.setTabsClosable(True)
        self.vboxlayout1 = QVBoxLayout(self.stat)
        self.hboxlayout1 = QHBoxLayout()
        self.filterTableLabel = QLabel("<b>Type to Search : </b>", self.stat)
        self.hboxlayout1.addWidget(self.filterTableLabel)
        self.filterTableLineEdit = QLineEdit(self.stat)
        self.filterTableLineEdit.setPlaceholderText(' Type to Search . . . ')
        self.hboxlayout1.addWidget(self.filterTableLineEdit)
        self.filterHintTableLabel = QLabel(" ? ", self.stat)
        self.hboxlayout1.addWidget(self.filterHintTableLabel)
        self.vboxlayout1.addLayout(self.hboxlayout1)
        self.tableWidget = QTableWidget(self.stat)
        self.tableWidget.setAlternatingRowColors(True)
        self.tableWidget.setColumnCount(8)
        self.tableWidget.setRowCount(2)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(2, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(3, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(4, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(5, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(6, item)
        item = QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(7, item)
        self.tableWidget.itemDoubleClicked.connect(
            self.on_tableWidget_itemDoubleClicked)
        self.vboxlayout1.addWidget(self.tableWidget)
        self.tabWidget.addTab(self.stat, " ? ")

        self.source = QWidget()
        self.gridlayout = QGridLayout(self.source)
        self.scintillaWarningLabel = QLabel(
            "QScintilla is not installed!. Falling back to basic text edit!.",
            self.source)
        self.gridlayout.addWidget(self.scintillaWarningLabel, 1, 0, 1, 2)
        self.sourceTreeWidget = QTreeWidget(self.source)
        self.sourceTreeWidget.setAlternatingRowColors(True)
        self.sourceTreeWidget.itemActivated.connect(
            self.on_sourceTreeWidget_itemActivated)
        self.sourceTreeWidget.itemClicked.connect(
            self.on_sourceTreeWidget_itemClicked)
        self.sourceTreeWidget.itemDoubleClicked.connect(
            self.on_sourceTreeWidget_itemClicked)

        self.gridlayout.addWidget(self.sourceTreeWidget, 0, 0, 1, 1)
        self.sourceTextEdit = QTextEdit(self.source)
        self.sourceTextEdit.setReadOnly(True)
        self.gridlayout.addWidget(self.sourceTextEdit, 0, 1, 1, 1)
        self.tabWidget.addTab(self.source, " ? ")

        self.result = QWidget()
        self.vlayout = QVBoxLayout(self.result)
        self.globalStatGroupBox = QGroupBox(self.result)
        self.hboxlayout = QHBoxLayout(self.globalStatGroupBox)
        self.totalTimeLcdNumber = QLCDNumber(self.globalStatGroupBox)
        self.totalTimeLcdNumber.setSegmentStyle(QLCDNumber.Filled)
        self.totalTimeLcdNumber.setNumDigits(7)
        self.totalTimeLcdNumber.display(1000000)
        self.totalTimeLcdNumber.setFrameShape(QFrame.StyledPanel)
        self.totalTimeLcdNumber.setSizePolicy(QSizePolicy.Expanding,
                                              QSizePolicy.Expanding)
        self.hboxlayout.addWidget(self.totalTimeLcdNumber)
        self.tTimeLabel = QLabel("<b>Total Time (Sec)</b>",
                                 self.globalStatGroupBox)
        self.tTimeLabel.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.hboxlayout.addWidget(self.tTimeLabel)
        self.numCallLcdNumber = QLCDNumber(self.globalStatGroupBox)
        self.numCallLcdNumber.setNumDigits(7)
        self.numCallLcdNumber.display(1000000)
        self.numCallLcdNumber.setSegmentStyle(QLCDNumber.Filled)
        self.numCallLcdNumber.setFrameShape(QFrame.StyledPanel)
        self.numCallLcdNumber.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Expanding)
        self.hboxlayout.addWidget(self.numCallLcdNumber)
        self.numCallLabel = QLabel("<b>Number of calls</b>",
                                   self.globalStatGroupBox)
        self.numCallLabel.setSizePolicy(QSizePolicy.Minimum,
                                        QSizePolicy.Minimum)
        self.hboxlayout.addWidget(self.numCallLabel)
        self.primCallLcdNumber = QLCDNumber(self.globalStatGroupBox)
        self.primCallLcdNumber.setSegmentStyle(QLCDNumber.Filled)
        self.primCallLcdNumber.setFrameShape(QFrame.StyledPanel)
        self.primCallLcdNumber.setNumDigits(7)
        self.primCallLcdNumber.display(1000000)
        self.primCallLcdNumber.setSizePolicy(QSizePolicy.Expanding,
                                             QSizePolicy.Expanding)
        self.hboxlayout.addWidget(self.primCallLcdNumber)
        self.primCallLabel = QLabel("<b>Primitive calls (%)</b>",
                                    self.globalStatGroupBox)
        self.primCallLabel.setSizePolicy(QSizePolicy.Minimum,
                                         QSizePolicy.Minimum)
        self.hboxlayout.addWidget(self.primCallLabel)
        self.vlayout.addWidget(self.globalStatGroupBox)
        try:
            from PyKDE4.kdeui import KRatingWidget
            self.rating = KRatingWidget(self.globalStatGroupBox)
            self.rating.setToolTip('Profiling Performance Rating')
        except ImportError:
            pass
        self.tabWidget.addTab(self.result, " Get Results ! ")

        self.resgraph = QWidget()
        self.vlayout2 = QVBoxLayout(self.result)
        self.graphz = QGroupBox(self.resgraph)
        self.hboxlayout2 = QHBoxLayout(self.graphz)
        try:
            from PyKDE4.kdeui import KLed
            KLed(self.graphz)
        except ImportError:
            pass
        self.hboxlayout2.addWidget(
            QLabel('''
            Work in Progress  :)  Not Ready Yet'''))
        self.vlayout2.addWidget(self.graphz)
        self.tabWidget.addTab(self.resgraph, " Graphs and Charts ")

        self.pathz = QWidget()
        self.vlayout3 = QVBoxLayout(self.pathz)
        self.patz = QGroupBox(self.pathz)
        self.hboxlayout3 = QVBoxLayout(self.patz)
        self.profilepath = QLineEdit(profilerPath)
        self.getprofile = QPushButton(QIcon.fromTheme("document-open"), 'Open')
        self.getprofile.setToolTip(
            'Dont touch if you dont know what are doing')
        self.getprofile.clicked.connect(lambda: self.profilepath.setText(
            str(
                QFileDialog.getOpenFileName(
                    self.patz, ' Open the profile.py file ',
                    path.expanduser("~"), ';;(profile.py)'))))
        self.hboxlayout3.addWidget(
            QLabel(
                '<center><b>Profile.py Python Library Full Path:</b></center>')
        )
        self.hboxlayout3.addWidget(self.profilepath)
        self.hboxlayout3.addWidget(self.getprofile)

        self.argGroupBox = QGroupBox(self.pathz)
        self.hbxlayout = QHBoxLayout(self.argGroupBox)
        self.argLineEdit = QLineEdit(self.argGroupBox)
        self.argLineEdit.setToolTip(
            'Not touch if you dont know what are doing')
        self.argLineEdit.setPlaceholderText(
            'Dont touch if you dont know what are doing')
        self.hbxlayout.addWidget(
            QLabel('<b>Additional Profile Arguments:</b>'))
        self.hbxlayout.addWidget(self.argLineEdit)
        self.hboxlayout3.addWidget(self.argGroupBox)

        self.vlayout3.addWidget(self.patz)
        self.tabWidget.addTab(self.pathz, " Paths and Configs ")

        self.outp = QWidget()
        self.vlayout4 = QVBoxLayout(self.outp)
        self.outgro = QGroupBox(self.outp)
        self.outgro.setTitle(" MultiProcessing Output Logs ")
        self.hboxlayout4 = QVBoxLayout(self.outgro)
        self.outputlog = QTextEdit()
        self.outputlog.setText('''
        I do not fear computers, I fear the lack of them.   -Isaac Asimov ''')
        self.hboxlayout4.addWidget(self.outputlog)
        self.vlayout4.addWidget(self.outgro)
        self.tabWidget.addTab(self.outp, " Logs ")

        self.actionNew_profiling = QAction(QIcon.fromTheme("document-new"),
                                           'New Profiling', self)
        self.actionLoad_profile = QAction(QIcon.fromTheme("document-open"),
                                          'Open Profiling', self)
        self.actionClean = QAction(QIcon.fromTheme("edit-clear"), 'Clean',
                                   self)
        self.actionClean.triggered.connect(lambda: self.clearContent)
        self.actionAbout = QAction(QIcon.fromTheme("help-about"), 'About',
                                   self)
        self.actionAbout.triggered.connect(lambda: QMessageBox.about(
            self.dock, __doc__, ', '.join(
                (__doc__, __license__, __author__, __email__))))
        self.actionSave_profile = QAction(QIcon.fromTheme("document-save"),
                                          'Save Profiling', self)
        self.actionManual = QAction(QIcon.fromTheme("help-contents"), 'Help',
                                    self)
        self.actionManual.triggered.connect(lambda: open_new_tab(
            'http://docs.python.org/library/profile.html'))

        self.tabWidget.setCurrentIndex(2)

        self.globalStatGroupBox.setTitle("Global Statistics")
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText("Number of Calls")
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText("Total Time")
        item = self.tableWidget.horizontalHeaderItem(2)
        item.setText("Per Call")
        item = self.tableWidget.horizontalHeaderItem(3)
        item.setText("Cumulative Time")
        item = self.tableWidget.horizontalHeaderItem(4)
        item.setText("Per Call")
        item = self.tableWidget.horizontalHeaderItem(5)
        item.setText("Filename")
        item = self.tableWidget.horizontalHeaderItem(6)
        item.setText("Line")
        item = self.tableWidget.horizontalHeaderItem(7)
        item.setText("Function")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.stat),
                                  "Statistics per Function")

        self.sourceTreeWidget.headerItem().setText(0, "Source files")
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.source),
                                  "Sources Navigator")
        #######################################################################

        self.scrollable, self.dock = QScrollArea(), QDockWidget()
        self.scrollable.setWidgetResizable(True)
        self.scrollable.setWidget(self.tabWidget)
        self.dock.setWindowTitle(__doc__)
        self.dock.setStyleSheet('QDockWidget::title{text-align: center;}')
        self.dock.setWidget(self.scrollable)
        QToolBar(self.dock).addActions(
            (self.actionNew_profiling, self.actionClean,
             self.actionSave_profile, self.actionLoad_profile,
             self.actionManual, self.actionAbout))

        self.actionNew_profiling.triggered.connect(
            self.on_actionNew_profiling_triggered)
        self.actionLoad_profile.triggered.connect(
            self.on_actionLoad_profile_triggered)
        self.actionSave_profile.triggered.connect(
            self.on_actionSave_profile_triggered)

        self.locator.get_service('misc').add_widget(
            self.dock, QIcon.fromTheme("document-open-recent"), __doc__)

        if QSCI:
            # Scintilla source editor management
            self.scintillaWarningLabel.setText(' QScintilla is Ready ! ')
            layout = self.source.layout()
            layout.removeWidget(self.sourceTextEdit)
            self.sourceTextEdit = Qsci.QsciScintilla(self.source)
            layout.addWidget(self.sourceTextEdit, 0, 1)
            doc = self.sourceTextEdit
            doc.setLexer(Qsci.QsciLexerPython(self.sourceTextEdit))
            doc.setReadOnly(True)
            doc.setEdgeMode(Qsci.QsciScintilla.EdgeLine)
            doc.setEdgeColumn(80)
            doc.setEdgeColor(QColor("#FF0000"))
            doc.setFolding(Qsci.QsciScintilla.BoxedTreeFoldStyle)
            doc.setBraceMatching(Qsci.QsciScintilla.SloppyBraceMatch)
            doc.setCaretLineVisible(True)
            doc.setMarginLineNumbers(1, True)
            doc.setMarginWidth(1, 25)
            doc.setTabWidth(4)
            doc.setEolMode(Qsci.QsciScintilla.EolUnix)
            self.marker = {}
            for color in COLORS:
                mnr = doc.markerDefine(Qsci.QsciScintilla.Background)
                doc.setMarkerBackgroundColor(color, mnr)
                self.marker[color] = mnr
        self.currentSourcePath = None

        # Connect table and tree filter edit signal to unique slot
        self.filterTableLineEdit.textEdited.connect(
            self.on_filterLineEdit_textEdited)

        # Timer to display filter hint message
        self.filterHintTimer = QTimer(self)
        self.filterHintTimer.setSingleShot(True)
        self.filterHintTimer.timeout.connect(self.on_filterHintTimer_timeout)

        # Timer to start search
        self.filterSearchTimer = QTimer(self)
        self.filterSearchTimer.setSingleShot(True)
        self.filterSearchTimer.timeout.connect(
            self.on_filterSearchTimer_timeout)

        self.tabLoaded = {}
        for i in range(10):
            self.tabLoaded[i] = False
        self.backgroundTreeMatchedItems = {}
        self.resizeWidgetToContent(self.tableWidget)

    def on_actionNew_profiling_triggered(self):
        self.clearContent()
        self.scriptPath = str(
            QFileDialog.getOpenFileName(self.dock,
                                        "Choose your script to profile",
                                        path.expanduser("~"),
                                        "Python (*.py *.pyw)"))
        commandLine = [
            self.profilerPath, "-o", self.tempPath, self.scriptPath
        ] + self.scriptArgs
        commandLine = " ".join(commandLine)
        ##if self.termCheckBox.checkState() == Qt.Checked:
        #termList = ["xterm", "aterm"]
        #for term in termList:
        #termPath = which(term)
        #if termPath:
        #break
        #commandLine = """%s -e "%s ; echo 'Press ENTER Exit' ; read" """ \
        #% (termPath, commandLine)
        self.process.start(commandLine)
        if not self.process.waitForStarted():
            print((" ERROR: {} failed!".format(commandLine)))
            return

    def on_process_finished(self, exitStatus):
        ' whan the process end '
        print((" INFO: OK: QProcess is %s" % self.process.exitCode()))
        self.output = self.process.readAll().data()
        if not self.output:
            self.output = " ERROR: FAIL: No output ! "
        self.outputlog.setText(self.output + str(self.process.exitCode()))
        if path.exists(self.tempPath):
            self.setStat(self.tempPath)
            remove(self.tempPath)
        else:
            self.outputlog.setText(" ERROR: QProcess FAIL: Profiling failed.")
        self.tabWidget.setCurrentIndex(2)

    def on_process_error(self, error):
        ' when the process fail, I hope you never see this '
        print(" ERROR: QProcess FAIL: Profiler Dead, wheres your God now ? ")
        if error == QProcess.FailedToStart:
            self.outputlog.setText(" ERROR: FAIL: Profiler execution failed ")
        elif error == QProcess.Crashed:
            self.outputlog.setText(" ERROR: FAIL: Profiler execution crashed ")
        else:
            self.outputlog.setText(" ERROR: FAIL: Profiler unknown error ")

    def on_actionLoad_profile_triggered(self):
        """Load a previous profile sessions"""
        statPath = str(
            QFileDialog.getOpenFileName(self.dock, "Open profile dump",
                                        path.expanduser("~"),
                                        "Profile file (*)"))
        if statPath:
            self.clearContent()
            print(' INFO: OK: Loading profiling from ' + statPath)
            self.setStat(statPath)

    def on_actionSave_profile_triggered(self):
        """Save a profile sessions"""
        statPath = str(
            QFileDialog.getSaveFileName(self.dock, "Save profile dump",
                                        path.expanduser("~"),
                                        "Profile file (*)"))
        if statPath:
            #TODO: handle error case and give feelback to user
            print(' INFO: OK: Saving profiling to ' + statPath)
            self.stat.save(statPath)

    #=======================================================================#
    # Common parts                                                          #
    #=======================================================================#

    def on_tabWidget_currentChanged(self, index):
        """slot for tab change"""
        # Kill search and hint timer if running to avoid cross effect
        for timer in (self.filterHintTimer, self.filterSearchTimer):
            if timer.isActive():
                timer.stop()
        if not self.stat:
            #No stat loaded, nothing to do
            return
        self.populateTable()
        self.populateSource()

    def on_filterLineEdit_textEdited(self, text):
        """slot for filter change (table or tree"""
        if self.filterSearchTimer.isActive():
            # Already runnning, stop it
            self.filterSearchTimer.stop()
        # Start timer
        self.filterSearchTimer.start(300)

    def on_filterHintTimer_timeout(self):
        """Timeout to warn user about text length"""
        print("timeout")
        tab = self.tabWidget.currentIndex()
        if tab == TAB_FUNCTIONSTAT:
            label = self.filterHintTableLabel
        label.setText("Type > 2 characters to search")

    def on_filterSearchTimer_timeout(self):
        """timeout to start search"""
        tab = self.tabWidget.currentIndex()
        if tab == TAB_FUNCTIONSTAT:
            text = self.filterTableLineEdit.text()
            label = self.filterHintTableLabel
            edit = self.filterTableLineEdit
            widget = self.tableWidget
        else:
            print("Unknow tab for filterSearch timeout !")

        print(("do search for %s" % text))
        if not len(text):
            # Empty keyword, just clean all
            if self.filterHintTimer.isActive():
                self.filterHintTimer.stop()
            label.setText(" ? ")
            self.warnUSer(True, edit)
            self.clearSearch()
            return
        if len(text) < 2:
            # Don't filter if text is too short and tell it to user
            self.filterHintTimer.start(600)
            return
        else:
            if self.filterHintTimer.isActive():
                self.filterHintTimer.stop()
            label.setText(" ? ")

        # Search
        self.clearSearch()
        matchedItems = []
        if tab == TAB_FUNCTIONSTAT:
            # Find items
            matchedItems = widget.findItems(text, Qt.MatchContains)
            widget.setSortingEnabled(False)
            matchedRows = [item.row() for item in matchedItems]
            # Hide matched items
            header = widget.verticalHeader()
            for row in range(widget.rowCount()):
                if row not in matchedRows:
                    header.hideSection(row)
            widget.setSortingEnabled(True)
        else:
            print(" Unknow tab for filterSearch timeout ! ")

        print(("got %s members" % len(matchedItems)))
        self.warnUSer(matchedItems, edit)
        self.resizeWidgetToContent(widget)

    def resizeWidgetToContent(self, widget):
        """Resize all columns according to content"""
        for i in range(widget.columnCount()):
            widget.resizeColumnToContents(i)

    def clearSearch(self):
        """Clean search result
        For table, show all items
        For tree, remove colored items"""
        tab = self.tabWidget.currentIndex()
        if tab == TAB_FUNCTIONSTAT:
            header = self.tableWidget.verticalHeader()
            if header.hiddenSectionCount():
                for i in range(header.count()):
                    if header.isSectionHidden(i):
                        header.showSection(i)

    def clearContent(self):
        # Clear tabs
        self.tableWidget.clearContents()
        self.sourceTreeWidget.clear()
        # Reset LCD numbers
        for lcdNumber in (self.totalTimeLcdNumber, self.numCallLcdNumber,
                          self.primCallLcdNumber):
            lcdNumber.display(1000000)
        # Reset stat
        self.pstat = None
        # Disable save as menu
        self.actionSave_profile.setEnabled(False)
        # Mark all tabs as unloaded
        for i in range(10):
            self.tabLoaded[i] = False

    def warnUSer(self, result, inputWidget):
        palette = inputWidget.palette()
        if result:
            palette.setColor(QPalette.Normal, QPalette.Base,
                             QColor(255, 255, 255))
        else:
            palette.setColor(QPalette.Normal, QPalette.Base,
                             QColor(255, 136, 138))
        inputWidget.setPalette(palette)
        inputWidget.update()

    def setStat(self, statPath):
        self.stat = Stat(path=statPath)
        # Global stat update
        self.totalTimeLcdNumber.display(self.stat.getTotalTime())
        self.numCallLcdNumber.display(self.stat.getCallNumber())
        self.primCallLcdNumber.display(self.stat.getPrimitiveCallRatio())
        # Refresh current tab
        self.on_tabWidget_currentChanged(self.tabWidget.currentIndex())
        # Activate save as menu
        self.actionSave_profile.setEnabled(True)
        try:
            self.rating.setMaxRating(10)
            self.rating.setRating(
                int(self.stat.getPrimitiveCallRatio()) / 10 - 1)
        except:
            pass

    #========================================================================#
    # Statistics table                                                      #
    #=======================================================================#

    def populateTable(self):
        row = 0
        rowCount = self.stat.getStatNumber()
        progress = QProgressDialog("Populating statistics table...", "Abort",
                                   0, 2 * rowCount)
        self.tableWidget.setSortingEnabled(False)
        self.tableWidget.setRowCount(rowCount)

        progress.setWindowModality(Qt.WindowModal)
        for (key, value) in self.stat.getStatItems():
            #ncalls
            item = StatTableWidgetItem(str(value[0]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_NCALLS, item)
            colorTableItem(item, self.stat.getCallNumber(), value[0])
            #total time
            item = StatTableWidgetItem(str(value[2]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_TTIME, item)
            colorTableItem(item, self.stat.getTotalTime(), value[2])
            #per call (total time)
            if value[0] != 0:
                tPerCall = str(value[2] / value[0])
                cPerCall = str(value[3] / value[0])
            else:
                tPerCall = ""
                cPerCall = ""
            item = StatTableWidgetItem(tPerCall)
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_TPERCALL, item)
            colorTableItem(
                item,
                100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(),
                tPerCall)
            #per call (cumulative time)
            item = StatTableWidgetItem(cPerCall)
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_CPERCALL, item)
            colorTableItem(
                item,
                100.0 * self.stat.getTotalTime() / self.stat.getCallNumber(),
                cPerCall)
            #cumulative time
            item = StatTableWidgetItem(str(value[3]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_CTIME, item)
            colorTableItem(item, self.stat.getTotalTime(), value[3])
            #Filename
            self.tableWidget.setItem(row, STAT_FILENAME,
                                     StatTableWidgetItem(str(key[0])))
            #Line
            item = StatTableWidgetItem(str(key[1]))
            item.setTextAlignment(Qt.AlignRight)
            self.tableWidget.setItem(row, STAT_LINE, item)
            #Function name
            self.tableWidget.setItem(row, STAT_FUNCTION,
                                     StatTableWidgetItem(str(key[2])))
            row += 1
            # Store it in stat hash array
            self.stat.setStatLink(item, key, TAB_FUNCTIONSTAT)
            progress.setValue(row)
            if progress.wasCanceled():
                return

        for i in range(self.tableWidget.rowCount()):
            progress.setValue(row + i)
            for j in range(self.tableWidget.columnCount()):
                item = self.tableWidget.item(i, j)
                if item:
                    item.setFlags(Qt.ItemIsEnabled)

        self.tableWidget.setSortingEnabled(True)
        self.resizeWidgetToContent(self.tableWidget)
        progress.setValue(2 * rowCount)

    def on_tableWidget_itemDoubleClicked(self, item):
        matchedItems = []
        filename = str(self.tableWidget.item(item.row(), STAT_FILENAME).text())
        if not filename or filename.startswith("<"):
            # No source code associated, return immediatly
            return
        function = self.tableWidget.item(item.row(), STAT_FUNCTION).text()
        line = self.tableWidget.item(item.row(), STAT_LINE).text()

        self.on_tabWidget_currentChanged(TAB_SOURCE)  # load source tab
        function = "%s (%s)" % (function, line)
        fathers = self.sourceTreeWidget.findItems(filename, Qt.MatchContains,
                                                  SOURCE_FILENAME)
        print(("find %s father" % len(fathers)))
        for father in fathers:
            findItems(father, function, SOURCE_FILENAME, matchedItems)
        print(("find %s items" % len(matchedItems)))

        if matchedItems:
            self.tabWidget.setCurrentIndex(TAB_SOURCE)
            self.sourceTreeWidget.scrollToItem(matchedItems[0])
            self.on_sourceTreeWidget_itemClicked(matchedItems[0],
                                                 SOURCE_FILENAME)
            matchedItems[0].setSelected(True)
        else:
            print("oups, item found but cannot scroll to it !")

    #=======================================================================#
    # Source explorer                                                      #
    #=====================================================================#

    def populateSource(self):
        items = {}
        for stat in self.stat.getStatKeys():
            source = stat[0]
            function = "%s (%s)" % (stat[2], stat[1])
            if source in ("", "profile") or source.startswith("<"):
                continue
            # Create the function child
            child = QTreeWidgetItem([function])
            # Store it in stat hash array
            self.stat.setStatLink(child, stat, TAB_SOURCE)
            if source in items:
                father = items[source]
            else:
                # Create the father
                father = QTreeWidgetItem([source])
                items[source] = father
            father.addChild(child)
        self.sourceTreeWidget.setSortingEnabled(False)
        for value in list(items.values()):
            self.sourceTreeWidget.addTopLevelItem(value)
        self.sourceTreeWidget.setSortingEnabled(True)

    def on_sourceTreeWidget_itemActivated(self, item, column):
        self.on_sourceTreeWidget_itemClicked(item, column)

    def on_sourceTreeWidget_itemClicked(self, item, column):
        line = 0
        parent = item.parent()
        if QSCI:
            doc = self.sourceTextEdit
        if parent:
            pathz = parent.text(column)
            result = match("(.*) \(([0-9]+)\)", item.text(column))
            if result:
                try:
                    function = str(result.group(1))
                    line = int(result.group(2))
                except ValueError:
                    # We got garbage... falling back to line 0
                    pass
        else:
            pathz = item.text(column)
        pathz = path.abspath(str(pathz))
        if self.currentSourcePath != pathz:
            # Need to load source
            self.currentSourcePath == pathz
            try:
                if QSCI:
                    doc.clear()
                    doc.insert(file(pathz).read())
                else:
                    self.sourceTextEdit.setPlainText(file(pathz).read())
            except IOError:
                QMessageBox.warning(self, "Error",
                                    "Source file could not be found",
                                    QMessageBox.Ok)
                return

            if QSCI:
                for function, line in [(i[2], i[1])
                                       for i in self.stat.getStatKeys()
                                       if i[0] == pathz]:
                    # expr, regexp, case sensitive, whole word, wrap, forward
                    doc.findFirst("def", False, True, True, False, True, line,
                                  0, True)
                    end, foo = doc.getCursorPosition()
                    time = self.stat.getStatTotalTime((pathz, line, function))
                    colorSource(doc, self.stat.getTotalTime(), time, line, end,
                                self.marker)
        if QSCI:
            doc.ensureLineVisible(line)
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_()
Пример #24
0
class CameraWindow(PyDialog):
    def __init__(self, data, win_parent=None):
        """
        +--------+
        | Camera |
        +--------+---------------+
        |  Camera Name           |
        |  +-------------------+ |
        |  |                   | |
        |  |                   | |
        |  |                   | |
        |  |                   | |
        |  |                   | |
        |  +-------------------+ |
        |                        |
        | Name xxx       Save    |
        | Delete   Set           |
        |                        |
        |    Apply   OK  Cancel  |
        +--------+---------------+
        """
        PyDialog.__init__(self, data, win_parent)
        self.setWindowTitle('Camera Views')
        #self.setWindowIcon(view_icon)

        self._default_name = 'Camera'
        self.out_data['clicked_ok'] = False

        self.cameras = deepcopy(data['cameras'])
        self.names = sorted(self.cameras.keys())

        self.name = QLabel("Name:")
        self.name_edit = QLineEdit(str(self._default_name))

        self.delete_button = QPushButton("Delete")
        self.set_button = QPushButton("Set")
        self.save_button = QPushButton("Save")

        # closing
        self.apply_button = QPushButton("Apply")
        #self.ok_button = QPushButton("OK")
        self.close_button = QPushButton("Close")
        self.cancel_button = QPushButton("Cancel")

        self.table = QTableWidget()
        names_text = []
        for iname, name in enumerate(self.names):
            name_text = QTableWidgetItem(str(name))
            names_text.append(name_text)
        self.create_layout(names_text)
        self.set_connections()

    def create_layout(self, names_text):
        nrows = len(self.names)
        table = self.table
        table.setRowCount(nrows)
        table.setColumnCount(1)
        headers = [QString('Camera Name')]
        table.setHorizontalHeaderLabels(headers)

        header = table.horizontalHeader()
        header.setStretchLastSection(True)

        for iname, name_text in enumerate(names_text):
            # row, col, value
            table.setItem(iname, 0, name_text)
        table.resizeRowsToContents()

        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.apply_button)
        #ok_cancel_box.addWidget(self.ok_button)
        ok_cancel_box.addWidget(self.close_button)
        ok_cancel_box.addWidget(self.cancel_button)

        grid = QGridLayout()

        irow = 0
        grid.addWidget(self.name, irow, 0)
        grid.addWidget(self.name_edit, irow, 1)
        grid.addWidget(self.save_button, irow, 2)
        irow += 1

        grid.addWidget(self.delete_button, irow, 0)
        grid.addWidget(self.set_button, irow, 1)
        irow += 1


        vbox = QVBoxLayout()
        vbox.addWidget(self.table)

        vbox.addLayout(grid)
        vbox.addStretch()
        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def set_connections(self):
        if qt_version == 4:
            self.connect(self.set_button, QtCore.SIGNAL('clicked()'), self.on_set)
            self.connect(self.save_button, QtCore.SIGNAL('clicked()'), self.on_save)
            self.connect(self.delete_button, QtCore.SIGNAL('clicked()'), self.on_delete)

            self.connect(self.apply_button, QtCore.SIGNAL('clicked()'), self.on_apply)
            #self.connect(self.ok_button, QtCore.SIGNAL('clicked()'), self.on_ok)
            self.connect(self.close_button, QtCore.SIGNAL('clicked()'), self.on_close)
            self.connect(self.cancel_button, QtCore.SIGNAL('clicked()'), self.on_cancel)
        else:
            self.set_button.clicked.connect(self.on_set)
            self.save_button.clicked.connect(self.on_save)
            self.delete_button.clicked.connect(self.on_delete)
            self.apply_button.clicked.connect(self.on_apply)
            self.close_button.clicked.connect(self.on_close)
            self.cancel_button.clicked.connect(self.on_cancel)

    def on_set(self):
        objs = self.table.selectedIndexes()
        if len(objs) == 1:
            obj = objs[0]
            irow = obj.row()
            name = self.names[irow]
            #print('name =', name)
            self.set_camera(name)
            return True
        return False

    def on_save(self):
        name = str(self.name_edit.text()).strip()
        if name in self.cameras:
            return
        irow = self.nrows
        if len(name):
            self.table.insertRow(irow)
            name_text = QTableWidgetItem(str(name))
            self.table.setItem(irow, 0, name_text)
            self.name_edit.setText('')
            self.save_camera(name)

    def set_camera(self, name):
        camera_data = self.cameras[name]
        if self.win_parent is None:
            return
        self.win_parent.on_set_camera_data(camera_data)

    def save_camera(self, name):
        self.names.append(name)
        if self.win_parent is None:
            self.cameras[name] = None
            return

        self.cameras[name] = self.win_parent.get_camera_data()

    #@property
    #def camera(self):

    @property
    def nrows(self):
        return self.table.rowCount()

    def on_delete(self):
        irows = []
        for obj in self.table.selectedIndexes():
            irow = obj.row()
            irows.append(irow)
        irows.sort()

        for irow in reversed(irows):
            self.table.removeRow(irow)
            #print('delete', self.names)
            name = self.names.pop(irow)
            del self.cameras[name]
            #print('  removing irow=%s name=%r' % (irow, name))

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

    @staticmethod
    def check_name(cell):
        text = str(cell.text()).strip()
        if len(text):
            cell.setStyleSheet("QLineEdit{background: white;}")
            return text, True
        else:
            cell.setStyleSheet("QLineEdit{background: red;}")
            return None, False

    #def on_validate(self):
        #name_value, flag0 = self.check_name(self.name_edit)
        #if flag0:
            #self.out_data['cameras'] = self.cameras
            #self.out_data['clicked_ok'] = True
            #return True
        #return False

    def on_apply(self):
        passed = self.on_set()
        #if passed:
        #    self.win_parent.create_plane(self.out_data)
        return passed

    def on_close(self):
        self.out_data['clicked_ok'] = True
        self.out_data['cameras'] = self.cameras
        self.close()

    def on_ok(self):
        passed = self.on_apply()
        if passed:
            name = str(self.name_edit.text()).strip()
            self.out_data['name'] = name
            self.out_data['cameras'] = self.cameras
            self.out_data['clicked_ok'] = True
            self.close()
            #self.destroy()

    def on_cancel(self):
        self.close()
class wavListDialog(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.prm = self.parent().parent().prm
        self.audioManager = audioManager(self)
        self.currLocale = self.parent().parent().prm['currentLocale']
        self.currLocale.setNumberOptions(self.currLocale.OmitGroupSeparator | self.currLocale.RejectGroupSeparator)
        self.isPlaying = False
      
        self.sizer = QGridLayout() 
        self.v1Sizer = QVBoxLayout()
        
        self.wavsTableWidget = QTableWidget()
        self.wavsTableWidget.setColumnCount(4)
        self.wavsTableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.wavsTableWidget.setSelectionMode(QAbstractItemView.ExtendedSelection)
        
        self.wavsTableWidget.setHorizontalHeaderLabels([self.tr("File"), self.tr('Use'), self.tr("RMS Level"), 'id'])
        self.quidColumn = 3
        self.wavsTableWidget.hideColumn(self.quidColumn)
        self.wavsTableWidget.cellDoubleClicked[int,int].connect(self.onCellDoubleClicked)

        
        #ADD wav BUTTON
        self.addWavButton = QPushButton(self.tr("Add Wav"), self)
        self.addWavButton.clicked.connect(self.onClickAddWavButton)
        #REMOVE wav BUTTON
        self.removeWavButton = QPushButton(self.tr("Remove Wav"), self)
        self.removeWavButton.clicked.connect(self.onClickRemoveWavButton)

        #PLAY wav BUTTON
        self.playWavButton = QPushButton(self.tr("Play Wav"), self)
        self.playWavButton.clicked.connect(self.onClickPlayWavButton)
        #STOP wav BUTTON
        self.stopWavButton = QPushButton(self.tr("Stop Playing"), self)
        self.stopWavButton.clicked.connect(self.onClickStopWavButton)
       
        self.v1Sizer.addWidget(self.addWavButton)
        self.v1Sizer.addWidget(self.removeWavButton)
        self.v1Sizer.addWidget(self.playWavButton)
        self.v1Sizer.addWidget(self.stopWavButton)
     
        self.v1Sizer.addStretch()

        self.wavsList = {}
    
        for i in range(len(self.parent().wavsPref['endMessageFiles'])):
            currCount = i+1
            thisID = self.parent().wavsPref['endMessageFilesID'][i]
            self.wavsList[thisID] = {}
            self.wavsList[thisID]['file'] = self.parent().wavsPref['endMessageFiles'][i]
            self.wavsList[thisID]['use'] = self.parent().wavsPref['endMessageFilesUse'][i]
            self.wavsList[thisID]['level'] = self.parent().wavsPref['endMessageLevels'][i]
            self.wavsTableWidget.setRowCount(currCount)
            n = 0
            newItem = QTableWidgetItem(self.wavsList[thisID]['file'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount-1, n, newItem)
            n = n+1
            newItem = QTableWidgetItem(self.wavsList[thisID]['use'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount-1, n, newItem)
            n = n+1
            newItem = QTableWidgetItem(self.currLocale.toString(self.wavsList[thisID]['level']))
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount-1, n, newItem)
            n = n+1
            self.wavsList[thisID]['qid'] = QTableWidgetItem(thisID)
            self.wavsTableWidget.setItem(currCount-1, n, self.wavsList[thisID]['qid'])

     
        buttonBox = QDialogButtonBox(QDialogButtonBox.Apply|QDialogButtonBox.Ok|QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)

        self.sizer.addLayout(self.v1Sizer, 0, 0)
        self.sizer.addWidget(self.wavsTableWidget,0,1)
        self.sizer.addWidget(buttonBox, 1,1)
        self.setLayout(self.sizer)
        self.setWindowTitle(self.tr("Edit Wavs"))
        self.show()


    def onCellDoubleClicked(self, row, col):
        if col == 0:
            pass
        elif col == 1:
            self.onEditUse()
        elif col == 2:
            self.onEditLevel()

    def onEditLevel(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            msg = self.tr('RMS Level:')
            text, ok = QInputDialog.getDouble(self, self.tr('Input Dialog'), msg, self.wavsList[selectedSound]['level'])
            if ok:
                self.wavsTableWidget.item(self.wavsList[selectedSound]['qid'].row(), 2).setText(self.currLocale.toString(text))
                self.wavsList[selectedSound]['level'] = text

    def onEditUse(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            if self.wavsTableWidget.item(self.wavsList[selectedSound]['qid'].row(), 1).text() == "\u2012":
                self.wavsTableWidget.item(self.wavsList[selectedSound]['qid'].row(), 1).setText("\u2713")
                self.wavsList[selectedSound]['use'] = "\u2713"
            else:
                self.wavsTableWidget.item(self.wavsList[selectedSound]['qid'].row(), 1).setText("\u2012")
                self.wavsList[selectedSound]['use'] = "\u2012"
    def findSelectedItemIds(self):
        selItems = self.wavsTableWidget.selectedItems()
        selItemsRows = []
        for i in range(len(selItems)):
            selItemsRows.append(selItems[i].row())
        selItemsRows = unique(selItemsRows)
        selItemsIds = []
        for i in range(len(selItemsRows)):
            selItemsIds.append(str(self.wavsTableWidget.item(selItemsRows[i], self.quidColumn).text()))
        return selItemsIds

    def permanentApply(self):
        self.wavListToPass = {}
        self.wavListToPass['endMessageFiles'] = []
        self.wavListToPass['endMessageFilesUse'] = []
        self.wavListToPass['endMessageFilesID'] = []
        self.wavListToPass['endMessageLevels'] = []

        keys = sorted(self.wavsList.keys())
        for key in keys:
            self.wavListToPass['endMessageFiles'].append(str(self.wavsList[key]['file']))
            self.wavListToPass['endMessageFilesUse'].append(self.wavsList[key]['use'])
            self.wavListToPass['endMessageLevels'].append(self.wavsList[key]['level'])
            self.wavListToPass['endMessageFilesID'].append(key)
      

    def onClickAddWavButton(self):
        fName = QFileDialog.getOpenFileName(self, self.tr("Choose wav file to load"), '', self.tr("wav files (*.wav);;All Files (*)"))[0]
        if len(fName) > 0: #if the user didn't press cancel

            if len(self.wavsList.keys()) > 0:
                keys = sorted(self.wavsList.keys())
                thisID = str(int(keys[-1])+1)
            else:
                thisID = "1"
            currCount = self.wavsTableWidget.rowCount() + 1

            self.wavsList[thisID] = {}
            self.wavsList[thisID]['file'] = fName
            self.wavsList[thisID]['use'] = "\u2713"
            self.wavsList[thisID]['level'] = 60
            self.wavsTableWidget.setRowCount(currCount)
            n = 0
            newItem = QTableWidgetItem(self.wavsList[thisID]['file'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount-1, n, newItem)
            n = n+1
            newItem = QTableWidgetItem(self.wavsList[thisID]['use'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount-1, n, newItem)
            n = n+1
            newItem = QTableWidgetItem(self.currLocale.toString(self.wavsList[thisID]['level']))
            newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount-1, n, newItem)
            n = n+1
            self.wavsList[thisID]['qid'] = QTableWidgetItem(thisID)
            self.wavsTableWidget.setItem(currCount-1, n, self.wavsList[thisID]['qid'])
      

    def onClickRemoveWavButton(self):
        ids = self.findSelectedItemIds()
        for i in range(len(ids)):
            selectedWavs = ids[i]
            self.wavsTableWidget.removeRow(self.wavsList[selectedWavs]['qid'].row())
            del self.wavsList[selectedWavs]

    def onClickPlayWavButton(self):
        ids = self.findSelectedItemIds()
        if len(ids) < 1:
            QMessageBox.warning(self, self.tr('Warning'), self.tr('No files selected for playing'))
        else:
            if len(ids) > 1:
                pass #maybe say on the status bar that only the first one will be played
            selectedWav = ids[0]
            fName = self.wavsList[selectedWav]['file']
            level = self.wavsList[selectedWav]['level']
            nBits = self.currLocale.toInt(self.parent().parent().nBitsChooser.currentText())[0]
            maxLevel = float(self.prm['phones']['phonesMaxLevel'][self.parent().parent().phonesChooser.currentIndex()])
            msgSnd, fs = self.audioManager.loadWavFile(fName, level, maxLevel, 'Both')
            self.isPlaying = True
            if self.prm['pref']['sound']['playCommand'] in ["alsaaudio","pyaudio"]:
                self.playThread = threadedAudioPlayer(self.parent().parent())
            else:
                self.playThread = threadedExternalAudioPlayer(self.parent().parent())
            self.playThread.playThreadedSound(msgSnd, fs, nBits, self.prm['pref']['sound']['playCommand'], False, 'tmp.wav')
            if self.playThread.isFinished == True:
                self.isPlaying = False
    def onClickStopWavButton(self):
        if self.isPlaying == True:
            self.playThread.terminate()
          
        
    def closeEvent(self, event):
        if self.isPlaying == True:
            self.playThread.terminate()
        event.accept()
        
    def accept(self): #reimplement accept (i.e. ok button)
        if self.isPlaying == True:
            self.playThread.terminate()
        QDialog.accept(self)
    def reject(self): #reimplement reject
        if self.isPlaying == True:
            self.playThread.terminate()
        QDialog.reject(self)
Пример #26
0
class multirun_widget(QWidget):
    """Widget for editing multirun values.

    Keyword arguments:
    tr    -- a translate instance that contains the experimental sequence
    nrows -- number of rows = number of multirun steps.
    ncols -- number of columns = number of channels to change in one step.
    order -- the order to produce the variables list in:
        ascending  - with repeats next to each other
        descending - with repeats next to each other
        random     - completely randomise the order
        coarse random - randomise order but repeats next to each other
        unsorted   - make an ascending list, then repeat the list
    """
    multirun_vals = pyqtSignal(np.ndarray)  # the array of multirun values
    progress = pyqtSignal(str)  # string detailing the progress of the multirun

    def __init__(self, tr, nrows=1, ncols=1, order='ascending'):
        super().__init__()
        self.tr = tr  # translator for the current sequence
        self.mrtr = tr.copy()  # translator for multirun sequence
        self.msglist = []  # list of multirun sequences as XML string
        self.ind = 0  # index for how far through the multirun we are
        self.nrows = nrows
        self.ncols = ncols
        self.types = OrderedDict([('measure', int), ('measure_prefix', str),
                                  ('1st hist ID', int),
                                  ('Variable label', str), ('Order', str),
                                  ('Type', strlist),
                                  ('Analogue type', strlist),
                                  ('Time step name', listlist),
                                  ('Analogue channel', listlist),
                                  ('runs included', listlist),
                                  ('Last time step run', str),
                                  ('Last time step end', str),
                                  ('# omitted', int), ('# in hist', int),
                                  ('list index', strlist)])
        self.ui_param = OrderedDict([
            ('measure', 0), ('measure_prefix', 'Measure0'),
            ('1st hist ID', -1), ('Variable label', ''), ('Order', order),
            ('Type', ['Time step length'] * ncols),
            ('Analogue type', ['Fast analogue'] * ncols),
            ('Time step name', [[]] * ncols),
            ('Analogue channel', [[]] * ncols),
            ('runs included', [[] for i in range(nrows)]),
            ('Last time step run',
             r'C:\Users\lab\Desktop\DExTer 1.4\Last Timesteps\feb2020_940and812.evt'
             ),
            ('Last time step end',
             r'C:\Users\lab\Desktop\DExTer 1.4\Last Timesteps\feb2020_940and812.evt'
             ), ('# omitted', 5), ('# in hist', 100),
            ('list index', ['0'] * ncols)
        ])
        self.awg_args = [
            'duration_[ms]', 'off_time_[us]', 'freqs_input_[MHz]',
            'start_freq_[MHz]', 'end_freq_[MHz]', 'hybridicity',
            'num_of_traps', 'distance_[um]', 'tot_amp_[mV]', 'dc_offset_[mV]',
            'start_amp', 'end_amp', 'start_output_[Hz]', 'end_output_[Hz]',
            'freq_amp', 'mod_freq_[kHz]', 'mod_depth', 'freq_phase_[deg]',
            'freq_adjust', 'amp_adjust', 'freqs_output_[Hz]', 'num_of_samples',
            'duration_loop_[ms]', 'number_of_cycles'
        ]
        self.dds_args = [
            'Freq', 'Phase', 'Amp', 'Start_add', 'End_add', 'Step_rate',
            'Sweep_start', 'Sweep_end', 'Pos_step', 'Neg_step',
            'Pos_step_rate', 'Neg_step_rate'
        ]
        self.slm_args = [
            'f', 'period', 'angle', 'radius', 'gradient', 'shift', 'radial',
            'azimuthal', 'amplitude'
        ]
        self.column_options = [
            'Analogue voltage', 'AWG1 chan : seg', 'AWG2 chan : seg',
            'DDS1 port : profile', 'DDS2 module : profile', 'SLM holograms'
        ]  # these analogue types require the analogue options
        self.col_range_text = [''] * ncols
        self.COM = ['RB1A', 'RB2', 'RB3', 'RB4',
                    'RB1B']  # DDS COM port connections
        self.COM2 = ['1557', '977', '1013', '420']  # DDS2 module connections
        self.mr_param = copy.deepcopy(
            self.ui_param)  # parameters used for current multirun
        self.mr_vals = []  # multirun values for the current multirun
        self.mr_queue = [
        ]  # list of parameters, sequences, and values to queue up for future multiruns
        self.appending = False  # whether the current multirun will be appended on to the displayed results
        self.multirun = False  # whether a multirun is running or not
        self.QueueWindow = QMainWindow()  # window for editing mr queue
        self.QueueWindow.setStyleSheet("background-color: cyan;")
        self.queue_ui = Ui_QueueWindow(self.mr_queue)
        self.queue_ui.setupUi(self.QueueWindow)
        self.init_UI()  # make the widgets
        self.ss = sequenceSaver(self.mrtr, self.mr_vals, self.mr_param,
                                '')  # used to save sequences

    def make_label_edit(self,
                        label_text,
                        layout,
                        position=[0, 0, 1, 1],
                        default_text='',
                        validator=None):
        """Make a QLabel with an accompanying QLineEdit and add them to the 
        given layout with an input validator. The position argument should
        be [row number, column number, row width, column width]."""
        label = QLabel(label_text, self)
        layout.addWidget(label, *position)
        line_edit = QLineEdit(self)
        if np.size(position) == 4:
            position[1] += 1
        layout.addWidget(line_edit, *position)
        line_edit.setText(default_text)
        line_edit.setValidator(validator)
        return label, line_edit

    def init_UI(self):
        """Create all of the widget objects required"""
        layout = QVBoxLayout()
        self.setLayout(layout)

        # place scroll bars if the contents of the window are too large
        scroll = QScrollArea(self)
        layout.addWidget(scroll)
        scroll_content = QWidget(scroll)
        scroll.setWidgetResizable(True)
        scroll.setFixedHeight(800)
        self.grid = QGridLayout()
        scroll_content.setLayout(self.grid)

        #### validators for user input ####
        double_validator = QDoubleValidator()  # floats
        int_validator = QIntValidator(0, 10000000)  # positive integers
        msr_validator = QIntValidator(-1, 1000000)  # integers >= -1
        nat_validator = QIntValidator(1, 10000000)  # natural numbers
        col_validator = QIntValidator(1,
                                      self.ncols - 1)  # for number of columns

        #### table dimensions and ordering ####
        # choose the number of rows = number of multirun steps
        labels = ['# Omit', '# in Histogram', '# Columns', '# Rows']
        default = ['5', '100', str(self.ncols), str(self.nrows)]
        vldtr = [int_validator, nat_validator, nat_validator, nat_validator]
        self.omit_edit, self.nhist_edit, self.cols_edit, self.rows_edit = [
            self.make_label_edit(labels[i], self.grid, [0, 2 * i, 1, 1],
                                 default[i], vldtr[i])[1] for i in range(4)
        ]
        self.cols_edit.textChanged[str].connect(self.change_array_size)
        self.rows_edit.textChanged[str].connect(self.change_array_size)
        self.omit_edit.editingFinished.connect(self.update_repeats)
        self.nhist_edit.editingFinished.connect(self.update_repeats)

        # choose the order
        self.order_edit = QComboBox(self)
        self.order_edit.addItems(
            ['ascending', 'descending', 'random', 'coarse random', 'unsorted'])
        self.grid.addWidget(self.order_edit, 0, 8, 1, 1)

        #### create multirun list of values ####
        # metadata for the multirun list: which channels and timesteps
        self.measures = OrderedDict()
        labels = ['Variable label', 'measure', 'measure_prefix', '1st hist ID']
        defaults = ['Variable 0', '0', 'Measure0', '0']
        for i in range(len(labels)):
            label = QLabel(labels[i], self)
            self.grid.addWidget(label, i + 1, 0, 1, 1)
            self.measures[labels[i]] = QLineEdit(defaults[i], self)
            self.measures[labels[i]].textChanged.connect(self.update_all_stats)
            self.grid.addWidget(self.measures[labels[i]], i + 1, 1, 1, 3)
        self.measures['measure'].setValidator(int_validator)
        self.measures['1st hist ID'].setValidator(msr_validator)
        label.setText('1st ID (-1 to append)')  # change label

        self.chan_choices = OrderedDict()
        labels = [
            'Type', 'Time step name', 'Analogue type', 'Analogue channel'
        ]
        sht = self.tr.get_esc()[2][2:]  # 'Sequence header top'
        options = [
            [
                'Time step length', 'Analogue voltage', 'GPIB',
                'AWG1 chan : seg', 'AWG2 chan : seg', 'DDS1 port : profile',
                'DDS2 module : profile', 'SLM holograms', 'Other'
            ],
            list(
                map(str.__add__, [str(i) for i in range(len(sht))],
                    [': ' + hc[6][1].text for hc in sht])),  # time step names
            ['Fast analogue', 'Slow analogue'],
            self.get_anlg_chans('Fast')
        ]
        positions = [[1, 4, 3, 2], [1, 6, 6, 1], [1, 7, 3, 1], [1, 8, 6, 1]]
        widgets = [QComboBox, QListWidget]
        for i in range(0, len(labels)):
            self.chan_choices[labels[i]] = widgets[i % 2]()
            if i % 2:
                self.chan_choices[labels[i]].setSelectionMode(3)
            self.chan_choices[labels[i]].addItems(options[i])
            self.grid.addWidget(self.chan_choices[labels[i]], *positions[i])
        self.chan_choices['Type'].currentTextChanged[str].connect(
            self.change_mr_type)
        self.chan_choices['Analogue type'].currentTextChanged[str].connect(
            self.change_mr_anlg_type)
        self.chan_choices['Analogue channel'].setEnabled(False)

        # enter desired time step selection via python cmd
        self.index_slice = QLineEdit('range(0,1,2)', self)
        self.grid.addWidget(self.index_slice, 3, 4, 3, 2)
        self.apply_slice_btn = QPushButton('Apply range', self)
        self.grid.addWidget(self.apply_slice_btn, 4, 4, 3, 2)
        self.apply_slice_btn.clicked.connect(self.apply_slice)

        # AWG takes a list for some arguments, so needs an index
        label = QLabel('List index:', self)
        self.grid.addWidget(label, 3, 7, 3, 1)
        self.list_index = QLineEdit('0', self)
        self.grid.addWidget(self.list_index, 4, 7, 3, 1)
        self.list_index.setValidator(int_validator)
        self.list_index.textEdited[str].connect(self.save_chan_selection)

        # add a new list of multirun values to the array
        self.col_index = self.make_label_edit('column index:',
                                              self.grid,
                                              position=[5, 0, 1, 1],
                                              default_text='0',
                                              validator=col_validator)[1]
        self.col_range = QLineEdit('np.linspace(0,1,%s)' % (self.nrows), self)
        self.grid.addWidget(self.col_range, 5, 2, 1, 2)
        # show the previously selected channels for this column:
        self.chan_choices['Time step name'].itemClicked.connect(
            self.save_chan_selection)
        self.chan_choices['Analogue channel'].itemClicked.connect(
            self.save_chan_selection)
        self.col_range.editingFinished.connect(self.save_chan_selection)
        self.col_index.textChanged[str].connect(self.set_chan_listbox)

        # add the column to the multirun values array
        add_var_button = QPushButton('Add column', self)
        add_var_button.clicked.connect(self.add_column_to_array)
        add_var_button.resize(add_var_button.sizeHint())
        self.grid.addWidget(add_var_button, 6, 0, 1, 1)

        # clear the current list of user variables
        clear_vars_button = QPushButton('Clear', self)
        clear_vars_button.clicked.connect(self.clear_array)
        clear_vars_button.resize(clear_vars_button.sizeHint())
        self.grid.addWidget(clear_vars_button, 6, 1, 1, 1)

        # suggest new measure when multirun started
        self.suggest_button = QPushButton('Auto-increment measure',
                                          self,
                                          checkable=True,
                                          checked=True)
        self.suggest_button.resize(self.suggest_button.sizeHint())
        self.grid.addWidget(self.suggest_button, 6, 2, 1, 2)

        # choose last time step for multirun
        lts_label = QLabel('Last time step: ', self)
        self.grid.addWidget(lts_label, 7, 0, 1, 1)
        self.last_step_run_edit = self.make_label_edit('Running: ',
                                                       self.grid,
                                                       position=[7, 1, 1,
                                                                 3])[1]
        self.last_step_run_edit.setText(self.ui_param['Last time step run'])
        self.last_step_run_edit.textChanged[str].connect(self.update_last_step)
        self.last_step_end_edit = self.make_label_edit('End: ',
                                                       self.grid,
                                                       position=[7, 5, 1,
                                                                 3])[1]
        self.last_step_end_edit.setText(self.ui_param['Last time step end'])
        self.last_step_end_edit.textChanged[str].connect(self.update_last_step)

        # display current progress
        multirun_progress = QLabel(
            'User variable: , omit 0 of 0 files, 0 of 100 histogram files, 0% complete'
        )
        self.grid.addWidget(multirun_progress, 8, 0, 1, 12)
        reset_slot(self.progress, multirun_progress.setText, True)

        # table stores multirun values:
        self.table = QTableWidget(self.nrows, self.ncols)
        self.reset_array()
        self.grid.addWidget(self.table, 9, 0, 20, 12)

        scroll.setWidget(scroll_content)

    #### #### array editing functions #### ####

    def reset_array(self, newvals=None):
        """Empty the table of its values. If newvals are supplied then it
        should have the right shape (rows, cols) so that it can be used
        to fill the table items."""
        self.table.setHorizontalHeaderLabels(list(map(str, range(self.ncols))))
        if not newvals:
            newvals = [[''] * self.ncols] * self.nrows
        for i in range(self.table.rowCount()):
            for j in range(self.ncols):
                self.table.setItem(i, j, QTableWidgetItem())
                self.table.item(i, j).setText(newvals[i][j])

    def clear_array(self):
        """Empty the table of its values and reset the selected channels."""
        self.reset_array()
        self.ui_param['Type'] = ['Time step length'] * self.ncols
        self.ui_param['Analogue type'] = ['Fast analogue'] * self.ncols
        self.ui_param['Time step name'] = [[]] * self.ncols
        self.ui_param['Analogue channel'] = [[]] * self.ncols
        self.ui_param['list index'] = ['0'] * self.ncols
        self.col_range_text = self.col_range_text[:self.ncols] + [''] * (
            self.ncols - len(self.col_range_text))
        self.set_chan_listbox(0)

    def check_table(self):
        """Check that there are values in each of the cells of the array."""
        try:
            for i in range(self.table.rowCount()):
                for j in range(self.table.columnCount()):
                    _ = float(self.table.item(i, j).text())
            return 1
        except ValueError:
            return 0

    def get_table(self):
        """Return a list of all the values in the multirun array table"""
        return [[
            self.table.item(i, j).text()
            for j in range(self.table.columnCount())
        ] for i in range(self.table.rowCount())]

    def change_array_size(self):
        """Update the size of the multirun array based on the number of rows
        and columns specified in the line edit."""
        self.nrows = int(self.rows_edit.text()) if self.rows_edit.text() else 1
        if self.nrows < 1:
            self.nrows = 1
        self.table.setRowCount(self.nrows)
        self.ncols = int(self.cols_edit.text()) if self.cols_edit.text() else 1
        if self.ncols < 1:
            self.ncols = 1
        self.table.setColumnCount(self.ncols)
        self.col_index.setValidator(QIntValidator(1, self.ncols - 1))
        if self.col_index.text() and int(
                self.col_index.text()) > self.ncols - 1:
            self.col_index.setText(str(self.ncols - 1))
        self.reset_array()
        self.col_range_text = self.col_range_text[:self.ncols] + [''] * (
            self.ncols - len(self.col_range_text))
        self.ui_param['runs included'] = [[] for i in range(self.nrows)]
        for key, default in zip([
                'Type', 'Analogue type', 'Time step name', 'Analogue channel',
                'list index'
        ], ['Time step length', 'Fast analogue', [], [], '0']):
            for i in range(len(self.ui_param[key]), self.ncols):
                self.ui_param[key].append(default)
            if len(self.ui_param[key]) > self.ncols:
                self.ui_param[key] = self.ui_param[key][:self.ncols]

    def update_all_stats(self, toggle=False):
        """Shorthand to update the values of the stats dictionary from the text
        labels."""
        self.update_repeats()
        self.update_last_step()
        for key in self.measures.keys(
        ):  # ['Variable label', 'measure', 'measure_prefix', '1st hist ID']
            if self.measures[key].text(
            ):  # don't do anything if the line edit is empty
                try:
                    self.ui_param[key] = self.types[key](
                        self.measures[key].text())
                except:
                    pass  # probably while user was typing the '-' in '-1'

    def update_repeats(self, txt=''):
        """Take the current values of the line edits and use them to set the
        number of omitted and number of included runs in a histogram."""
        self.ui_param['# omitted'] = int(
            self.omit_edit.text()) if self.omit_edit.text() else 0
        self.ui_param['# in hist'] = int(
            self.nhist_edit.text()) if self.nhist_edit.text() else 1

    def update_last_step(self, txt=''):
        """Save the current values of the last time step file paths."""
        self.ui_param['Last time step run'] = self.last_step_run_edit.text()
        self.ui_param['Last time step end'] = self.last_step_end_edit.text()

    def apply_slice(self):
        """Use the text in the index slice line edit to select time steps"""
        try:
            self.chan_choices['Time step name'].clearSelection()
            for i in eval(self.index_slice.text()):
                try:
                    self.chan_choices['Time step name'].item(i).setSelected(
                        True)
                except AttributeError:
                    pass  # index out of range
            self.save_chan_selection()
        except (TypeError, ValueError, NameError) as e:
            warning('Invalid selection command for multirun timesteps "' +
                    self.index_slice.text() + '".\n' + str(e))

    def add_column_to_array(self):
        """Make a list of values and add it to the given column 
        in the multirun values array. The function is chosen by the user.
        Values are repeated a set number of times, ordered according to the 
        ComboBox text. The selected channels are stored in lists."""
        try:  # make the list of values
            table = np.array(self.get_table()).T
            c = [column.astype(float) for column in table if '' not in column]
            vals = eval(self.col_range.text())
        except Exception as e:
            warning('Add column to multirun: invalid syntax "' +
                    self.col_range.text() + '".\n' + str(e))
            return 0
        col = int(self.col_index.text()) if self.col_index.text() else 0
        # store the selected channels
        self.ui_param['Order'] = self.order_edit.currentText()
        for key in self.measures.keys(
        ):  # ['Variable label', 'measure', 'measure_prefix', '1st hist ID']
            if self.measures[key].text(
            ):  # don't do anything if the line edit is empty
                self.ui_param[key] = self.types[key](self.measures[key].text())
        # order the list of values
        if self.ui_param['Order'] == 'descending':
            vals = list(reversed(vals))
        elif 'random' in self.ui_param['Order']:
            vals = list(vals)
            shuffle(vals)
        for i in range(self.table.rowCount()):
            try:  # set vals in table cells
                self.table.item(i, col).setText('%.4f' % vals[i])
            except IndexError:  # occurs if invalid range
                self.table.item(i, col).setText('')

    #### multirun channel selection ####

    def reset_sequence(self, tr):
        """Update the translator object used to get the experimental sequence.
        This is used to set the labels for time step names and channel names.
        Note: the multirun sequence mrtr is not affected."""
        self.tr = tr
        self.change_mr_type(self.chan_choices['Type'].currentText())
        # note: selected channels might have changed order
        self.set_chan_listbox(self.col_index.text())

    def save_chan_selection(self, arg=None):
        """When the user changes the selection of channels/timesteps for the
        given column, save it. The selection will be reloaded if the user
        changes the column and then comes back."""
        try:
            if self.col_index.text():
                col = int(self.col_index.text())
                for key in ['Type', 'Analogue type']:
                    self.ui_param[key][col] = self.chan_choices[
                        key].currentText()
                for key in ['Time step name', 'Analogue channel']:
                    self.ui_param[key][col] = list(
                        map(self.chan_choices[key].row,
                            self.chan_choices[key].selectedItems()))
                self.ui_param['list index'][col] = int(
                    self.list_index.text()) if self.list_index.text() else 0
                self.col_range_text[col] = self.col_range.text()
        except (ValueError, IndexError) as e:
            error("Multirun couldn't save channel choices for column " +
                  self.col_index.text() + '.\n' + str(e))

    def set_chan_listbox(self, col):
        """Set the selected channels and timesteps with the values
        previously stored for the given column col. If there were
        no values stored previously or the index is out of range,
        reset the selection."""
        try:
            col = int(col) if col else 0
            mrtype = self.ui_param['Type'][col]
            antype = self.ui_param['Analogue type'][col]
            sel = {
                'Time step name':
                self.ui_param['Time step name'][col],
                'Analogue channel':
                self.ui_param['Analogue channel'][col] if any(
                    mrtype == x for x in self.column_options) else []
            }
            list_ind = self.ui_param['list index'][col]
            col_range_txt = self.col_range_text[col]
        except (IndexError, ValueError):
            mrtype, antype = 'Time step length', 'Fast analogue'
            sel = {'Time step name': [], 'Analogue channel': []}
            list_ind = 0
            col_range_txt = ''
        self.col_range.setText(col_range_txt)
        self.list_index.setText(str(list_ind))
        self.chan_choices['Type'].setCurrentText(mrtype)
        self.chan_choices['Analogue type'].setCurrentText(antype)
        self.chan_choices['Analogue channel'].setEnabled(
            any(mrtype == x for x in self.column_options))
        for key in ['Time step name', 'Analogue channel']:
            self.chan_choices[key].setCurrentRow(
                0, QItemSelectionModel.Clear)  # clear previous selection
            try:
                for i in sel[key]:  # select items at the stored indices
                    self.chan_choices[key].item(i).setSelected(True)
            except IndexError:
                pass  # perhaps sequence was updated but using old selection indices
            except AttributeError as e:
                warning(
                    "Couldn't set channels for the loaded multirun parameters. Load the sequence first, then load multirun parameters.\n"
                    + str(e))

    def setListboxFlag(self, listbox, flag):
        """Set the items of the listbox all have the given flag.
        e.g. self.setListboxFlag(self.chan_choices['Time step name'], ~Qt.ItemIsEditable)"""
        for i in range(listbox.count()):
            item = listbox.item(i)
            item.setFlags(item.flags() | flag)

    def get_anlg_chans(self, speed):
        """Return a list of name labels for the analogue channels.
        speed -- 'Fast' or 'Slow'"""
        chans = self.tr.get_esc()[5 if speed == 'Fast' else 10][2:]
        return [c[2][1].text + ': ' + c[3][1].text for c in chans]

    def change_mr_type(self, newtype):
        """Enable/Disable list boxes to reflect the multirun type:
        newtype[str] -- Time step length: only needs timesteps
                     -- Analogue voltage: also needs channels
                     -- AWG: takes float values but with a list index."""
        sht = self.tr.get_esc()[2][2:]  # 'Sequence header top'
        if newtype == 'AWG1 chan : seg' or newtype == 'AWG2 chan : seg':
            self.chan_choices['Time step name'].clear()
            self.chan_choices['Time step name'].addItems(
                [str(i) + ', ' + str(j) for j in range(100) for i in range(2)])
            reset_slot(
                self.chan_choices['Analogue type'].currentTextChanged[str],
                self.change_mr_anlg_type, False)
            self.chan_choices['Analogue type'].clear()
            self.chan_choices['Analogue type'].addItems(['AWG Parameter'])
            self.chan_choices['Analogue channel'].setEnabled(True)
            self.chan_choices['Analogue channel'].clear()
            self.chan_choices['Analogue channel'].addItems(self.awg_args)
        elif 'DDS' in newtype:
            self.chan_choices['Time step name'].clear()
            if 'DDS2' in newtype:
                ddsoptions = [
                    '%s : P%s - ' % (i + 1, j) + self.COM2[i] for i in range(4)
                    for j in range(8)
                ]
                for i in range(4):
                    ddsoptions.insert(i * 9 + 8,
                                      '%s : aux - ' % (i + 1) + self.COM2[i])
            else:
                ddsoptions = [
                    'COM%s : P%s - ' % (i + 7, j) + self.COM[i]
                    for i in range(5) for j in range(8)
                ]
                for i in range(5):
                    ddsoptions.insert(i * 9 + 8,
                                      'COM%s : aux - ' % (i + 7) + self.COM[i])
            self.chan_choices['Time step name'].addItems(ddsoptions)
            reset_slot(
                self.chan_choices['Analogue type'].currentTextChanged[str],
                self.change_mr_anlg_type, False)
            self.chan_choices['Analogue type'].clear()
            self.chan_choices['Analogue type'].addItems(['DDS Parameter'])
            self.chan_choices['Analogue channel'].setEnabled(True)
            self.chan_choices['Analogue channel'].clear()
            self.chan_choices['Analogue channel'].addItems(self.dds_args)
        elif newtype == 'SLM holograms':
            self.chan_choices['Time step name'].clear()
            slmoptions = ['Hologram %s' % (i) for i in range(9)]
            self.chan_choices['Time step name'].addItems(slmoptions)
            reset_slot(
                self.chan_choices['Analogue type'].currentTextChanged[str],
                self.change_mr_anlg_type, False)
            self.chan_choices['Analogue type'].clear()
            self.chan_choices['Analogue type'].addItems(['Hologram Parameter'])
            self.chan_choices['Analogue channel'].setEnabled(True)
            self.chan_choices['Analogue channel'].clear()
            self.chan_choices['Analogue channel'].addItems(self.slm_args)
        else:
            if any(self.chan_choices['Analogue type'].currentText() == x
                   for x in
                   ['AWG Parameter', 'DDS Parameter', 'Hologram Parameter']):
                self.chan_choices['Analogue type'].clear()
                self.chan_choices['Analogue type'].addItems(
                    ['Fast analogue', 'Slow analogue'])
                self.chan_choices['Analogue type'].currentTextChanged[
                    str].connect(self.change_mr_anlg_type)
        if newtype == 'Other':
            self.chan_choices['Analogue channel'].setEnabled(False)
            self.chan_choices['Time step name'].clear()
            self.chan_choices['Time step name'].addItems(['Variable'])
        elif newtype == 'Time step length':
            self.chan_choices['Analogue channel'].setEnabled(False)
            self.chan_choices['Time step name'].clear()
            self.chan_choices['Time step name'].addItems(
                list(
                    map(str.__add__, [str(i) for i in range(len(sht))],
                        [': ' + hc[6][1].text
                         for hc in sht])))  # time step names
        elif newtype == 'Analogue voltage':
            self.chan_choices['Time step name'].clear()
            self.chan_choices['Time step name'].addItems(
                list(
                    map(str.__add__, [str(i) for i in range(len(sht))],
                        [': ' + hc[6][1].text
                         for hc in sht])))  # time step names
            self.chan_choices['Analogue channel'].setEnabled(True)
            self.chan_choices['Analogue channel'].clear()
            self.chan_choices['Analogue channel'].addItems(
                self.get_anlg_chans(
                    self.chan_choices['Analogue type'].currentText().split(
                        ' ')[0]))

    def change_mr_anlg_type(self, newtype):
        """Change the analogue channels listbox when fast/slow
        analogue channels are selected."""
        if self.chan_choices['Analogue channel'].isEnabled():
            self.chan_choices['Analogue channel'].clear()
            self.chan_choices['Analogue channel'].addItems(
                self.get_anlg_chans(
                    self.chan_choices['Analogue type'].currentText().split(
                        ' ')[0]))

    def get_next_index(self, rn):
        """Choose the next index from the rows of the table to use
        in the multirun, based on the order chosen.
        rn: the ID of the current run within the multirun.
        make rn modulo nrows so that there isn't an index error on the last run."""
        # if self.mr_param['Order'] == 'unsorted':
        #     return rn % self.nrows
        # elif self.mr_param['Order'] == 'random':
        #     return randint(0, self.nrows - 1)
        # else: # if descending, ascending, or coarse random, the order has already been set
        return (rn // (self.mr_param['# omitted'] + self.mr_param['# in hist'])
                ) % len(self.mr_param['runs included']
                        )  # ID of histogram in repetition cycle

    def get_next_sequence(self, i=None):
        """Use the values in the multirun array to make the next
        sequence to run in the multirun. Uses saved mr_param not UI"""
        if i == None: i = self.ind  # row index
        esc = self.mrtr.get_esc()  # shorthand
        num_s = len(esc[2]) - 2  # number of steps
        try:
            for col in range(len(self.mr_vals[i])):  # edit the sequence
                try:
                    val = float(self.mr_vals[i][col])
                    if self.mr_param['Type'][col] == 'Time step length':
                        for head in [2, 9]:
                            for t in self.mr_param['Time step name'][col]:
                                esc[head][t + 2][3][1].text = str(val)
                    elif self.mr_param['Type'][col] == 'Analogue voltage':
                        for t in self.mr_param['Time step name'][col]:
                            for c in self.mr_param['Analogue channel'][col]:
                                if 'Fast' in self.mr_param['Analogue type'][
                                        col]:
                                    esc[6][t + c * num_s +
                                           3][3][1].text = str(val)
                                else:
                                    esc[11][t + c * num_s +
                                            3][3][1].text = str(val)
                except ValueError as e:
                    pass  # non-float variable
            self.mrtr.set_routine_name('Multirun ' + self.mr_param['Variable label'] + \
                    ': ' + self.mr_vals[i][0] + ' (%s / %s)'%(i+1, len(self.mr_vals)))
        except IndexError as e:
            error('Multirun failed to edit sequence at ' +
                  self.mr_param['Variable label'] + ' = ' +
                  self.mr_vals[i][0] + '\n' + str(e))
        return self.mrtr.write_to_str()

    def get_all_sequences(self, save_dir=''):
        """Use the multirun array vals to make all of
        the sequences that will be used in the multirun, then
        store these as a list of XML strings."""
        self.msglist = []
        for i in range(len(self.mr_vals)):
            self.msglist.append(self.get_next_sequence(i))
        if not self.ss.isRunning():
            self.ss = sequenceSaver(self.mrtr, self.mr_vals, self.mr_param,
                                    save_dir)
            self.ss.start(self.ss.LowestPriority)  # save the sequences
        else:  # a backup if the first is busy saving sequences
            self.s2 = sequenceSaver(self.mrtr, self.mr_vals, self.mr_param,
                                    save_dir)
            self.s2.start(self.s2.LowestPriority)

    #### save and load parameters ####

    def view_mr_queue(self):
        """Show the window for editing the multirun queue"""
        self.queue_ui.updateList()
        self.QueueWindow.show()

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

    def save_mr_params(self, save_file_name=''):
        """Save the variable label, measure, measure prefix, # runs omitted, 
        # runs per histogram, multirun type, list of timesteps, multirun 
        # analogue type, list of channels, and array of variables."""
        if not save_file_name:
            save_file_name = self.try_browse(
                title='Save File',
                file_type='csv(*.csv);;all (*)',
                open_func=QFileDialog.getSaveFileName)
        if save_file_name:
            if hasattr(self.sender(),
                       'text') and self.sender().text() == 'Save Parameters':
                params, vals = self.ui_param, self.get_table()  # save from UI
            else:
                params, vals = self.mr_param, self.mr_vals  # save from multirun
            try:
                with open(save_file_name, 'w+') as f:
                    f.write('Multirun list of variables:\n')
                    f.write(';'.join([
                        ','.join(
                            [vals[row][col] for col in range(len(vals[0]))])
                        for row in range(len(vals))
                    ]) + '\n')
                    f.write(';'.join(params.keys()) + '\n')
                    f.write(';'.join(map(str, list(params.values()))))
            except (PermissionError, FileNotFoundError) as e:
                error("Couldn't save Multirun params to file: %s\n" %
                      save_file_name + str(e))

    def load_mr_params(self, load_file_name=''):
        """Load the multirun variables array from a file."""
        if not load_file_name:
            load_file_name = self.try_browse(
                title='Load File',
                file_type='csv(*.csv);;all (*)',
                open_func=QFileDialog.getOpenFileName)
        if load_file_name:
            with open(load_file_name, 'r') as f:
                _ = f.readline()
                vals = [
                    x.split(',')
                    for x in f.readline().replace('\n', '').split(';')
                ]
                header = f.readline().replace('\n', '').split(';')
                params = f.readline().split(';')
            for i in range(len(header)):
                if header[i] in self.ui_param:
                    try:
                        self.ui_param[header[i]] = self.types[header[i]](
                            params[i])
                    except ValueError as e:
                        error(
                            'Multirun editor could not load parameter: %s\n' %
                            params[i] + str(e))
            # store values in case they're overwritten after setText()
            nrows, ncols = np.shape(vals)  # update array of values
            col = int(self.col_index.text()) if self.col_index.text() else 0
            nhist, nomit = map(
                str, [self.ui_param['# in hist'], self.ui_param['# omitted']])
            runstep, endstep = self.ui_param[
                'Last time step run'], self.ui_param['Last time step end']
            # then update the label edits
            for key in self.measures.keys(
            ):  # update variable label and measure
                reset_slot(self.measures[key].textChanged,
                           self.update_all_stats, False)
                self.measures[key].setText(str(self.ui_param[key]))
                reset_slot(self.measures[key].textChanged,
                           self.update_all_stats, True)
            self.set_chan_listbox(col if col < ncols else 0)
            self.rows_edit.setText(str(nrows))  # triggers change_array_size
            self.cols_edit.setText(str(ncols))
            self.change_array_size()  # don't wait for it to be triggered
            self.reset_array(vals)
            self.nhist_edit.setText(nhist)
            self.omit_edit.setText(nomit)
            self.last_step_run_edit.setText(
                runstep)  # triggers update_last_step
            self.last_step_end_edit.setText(endstep)
            for i in range(
                    len(header)
            ):  # restore values as change_array_size loads defaults
                if header[i] in self.ui_param:
                    try:
                        self.ui_param[header[i]] = self.types[header[i]](
                            params[i])
                    except ValueError as e:
                        pass

    def check_mr_params(self, save_results_path='.'):
        """Check that the multirun parameters are valid before adding it to the queue"""
        if 'PyDex default empty sequence' in self.tr.get_routine_name():
            QMessageBox.warning(
                self, 'No sequence loaded',
                'You must load a sequence before starting a multirun.')
            return 0
        results_path = os.path.join(save_results_path,
                                    self.ui_param['measure_prefix'])
        self.appending = False
        # first check if the measure folder already exists with some files in
        imax = -1
        try:
            filelist = os.listdir(results_path)
            for fname in filelist:
                if 'params' in fname:
                    try:  # look for multirun parameters file
                        with open(os.path.join(results_path, fname), 'r') as f:
                            _ = f.readline()
                            vals = f.readline().replace('\n', '').split(';')
                            header = f.readline().replace('\n', '').split(';')
                            params = f.readline().split(';')
                            imax = max(
                                imax,
                                len(vals) +
                                int(params[header.index('1st hist ID')]) - 1)
                    except:
                        pass
        except (FileNotFoundError, PermissionError):
            pass
        # then check the multirun queue
        for m in self.mr_queue:
            if self.ui_param['measure_prefix'] == m[0]['measure_prefix']:
                imax = max(imax, len(m[2]) + m[0]['1st hist ID'] - 1)

        if self.ui_param['1st hist ID'] == -1:  # append at the end
            self.appending = True
            self.ui_param['1st hist ID'] = imax + 1 if imax >= 0 else 0

        if (os.path.isdir(results_path) or self.ui_param['measure_prefix'] in [
                x[0]['measure_prefix'] for x in self.mr_queue
        ]) and imax >= self.ui_param['1st hist ID']:
            # this measure exists, check if user wants to overwrite
            reply = QMessageBox.question(
                self, 'Confirm Overwrite',
                "Results path already exists, do you want to overwrite the csv and dat files?\n"
                + results_path, QMessageBox.Yes | QMessageBox.No,
                QMessageBox.No)
            if reply == QMessageBox.No:
                if self.appending:  # if appending, reset ui_param to -1. Also happens at end of multirun in runid.py
                    self.measures['1st hist ID'].setText('')
                    self.measures['1st hist ID'].setText('-1')
                return 0
            # elif reply == QMessageBox.Yes:
            #     try:
            #         for fn in os.listdir(results_path):
            #             if '.csv' in fn or '.dat' in fn:
            #                 os.remove(os.path.join(results_path, fn))
            #     except Exception as e:
            #         warning('Multirun could not remove files from '+results_dir+'\n'+str(e))

        # parameters are valid, add to queue
        self.mr_queue.append([
            copy.deepcopy(self.ui_param),
            self.tr.copy(),
            self.get_table(), self.appending
        ])
        if self.appending:  # if appending, reset ui_param to -1. Also happens at end of multirun in runid.py
            self.measures['1st hist ID'].setText('')
            self.measures['1st hist ID'].setText('-1')
        if self.suggest_button.isChecked(
        ):  # suggest new multirun measure ID and prefix
            n = self.ui_param['measure'] + 1
            self.measures['measure'].setText(str(n))
            self.measures['measure_prefix'].setText('Measure' + str(n))
        return 1
Пример #27
0
class LabelAssistDialog(QDialog):
    """
    A simple UI for showing bookmarks and navigating to them.

    FIXME: For now, this window is tied to a particular lane.
           If your project has more than one lane, then each one
           will have it's own bookmark window, which is kinda dumb.
    """
    def __init__(self, parent, topLevelOperatorView):
        super(LabelAssistDialog, self).__init__(parent)
        
        # Create thread router to populate table on main thread
        self.threadRouter = ThreadRouter(self)
        
        # Set object classification operator view
        self.topLevelOperatorView = topLevelOperatorView
        
        self.setWindowTitle("Label Assist")
        self.setMinimumWidth(500)
        self.setMinimumHeight(700)

        layout = QGridLayout() 
        layout.setContentsMargins(10, 10, 10, 10)
                       
        # Show variable importance table
        rows = 0
        columns = 4
        self.table = QTableWidget(rows, columns)   
        self.table.setHorizontalHeaderLabels(['Frame', 'Max Area', 'Min Area', 'Labels'])
        self.table.verticalHeader().setVisible(False)     
        
        # Select full row on-click and call capture double click
        self.table.setSelectionBehavior(QTableView.SelectRows);
        self.table.doubleClicked.connect(self._captureDoubleClick)
                
        layout.addWidget(self.table, 1, 0, 3, 2) 

        # Create progress bar
        self.progressBar = QProgressBar()
        self.progressBar.setMinimum(0)
        self.progressBar.setMaximum(0)
        self.progressBar.hide()
        layout.addWidget(self.progressBar, 4, 0, 1, 2)

        # Create button to populate table
        self.computeButton = QPushButton('Compute object info')
        self.computeButton.clicked.connect(self._triggerTableUpdate)
        layout.addWidget(self.computeButton, 5, 0)
        
        # Create close button
        closeButton = QPushButton('Close')
        closeButton.clicked.connect(self.close)
        layout.addWidget(closeButton, 5, 1)
        
        # Set dialog layout
        self.setLayout(layout)       


    def _triggerTableUpdate(self):
        # Check that object area is included in selected features
        featureNames = self.topLevelOperatorView.SelectedFeatures.value
        
        if 'Standard Object Features' not in featureNames or 'Count' not in featureNames['Standard Object Features']:
            box = QMessageBox(QMessageBox.Warning,
                  'Warning',
                  'Object area is not a selected feature. Please select this feature on: \"Standard Object Features > Shape > Size in pixels\"',
                  QMessageBox.NoButton,
                  self)
            box.show()
            return 
        
        # Clear table
        self.table.clearContents()
        self.table.setRowCount(0)
        self.table.setSortingEnabled(False)
        self.progressBar.show()
        self.computeButton.setEnabled(False)

        def compute_features_for_frame(tIndex, t, features): 
            # Compute features and labels (called in parallel from request pool)
            roi = [slice(None) for i in range(len(self.topLevelOperatorView.LabelImages.meta.shape))]
            roi[tIndex] = slice(t, t+1)
            roi = tuple(roi)

            frame = self.topLevelOperatorView.SegmentationImages(roi).wait()           
            frame = frame.squeeze().astype(numpy.uint32, copy=False)
            
            # Dirty trick: We don't care what we're passing here for the 'image' parameter,
            # but vigra insists that we pass *something*, so we'll cast the label image as float32.
            features[t] = vigra.analysis.extractRegionFeatures(frame.view(numpy.float32),
                                                               frame,
                                                               ['Count'],
                                                               ignoreLabel=0)
            
        tIndex = self.topLevelOperatorView.SegmentationImages.meta.axistags.index('t')
        tMax = self.topLevelOperatorView.SegmentationImages.meta.shape[tIndex]     
        
        features = {}
        labels = {}

        def compute_all_features():
            # Compute features in parallel
            pool = RequestPool()
            for t in range(tMax):
                pool.add( Request( partial(compute_features_for_frame, tIndex, t, features) ) )
            pool.wait()
            
        # Compute labels
        labels = self.topLevelOperatorView.LabelInputs([]).wait()
            
        req = Request(compute_all_features)
        req.notify_finished( partial(self._populateTable, features, labels) )
        req.submit()

    @threadRouted
    def _populateTable(self, features, labels, *args):
        self.progressBar.hide()
        self.computeButton.setEnabled(True)
                
        for time, feature in features.iteritems():
            # Insert row
            rowNum = self.table.rowCount()
            self.table.insertRow(self.table.rowCount())
            
            # Get max and min object areas
            areas = feature['Count']#objectFeatures['Standard Object Features']['Count']
            maxObjArea = numpy.max(areas[numpy.nonzero(areas)])
            minObjArea = numpy.min(areas[numpy.nonzero(areas)])
            
            # Get number of labeled objects
            labelNum = numpy.count_nonzero(labels[time])
            
            # Load fram number
            item = QTableWidgetItem(str(time))
            item.setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            self.table.setItem(rowNum, 0, item) 

            # Load max object areas
            item = QTableWidgetItemWithFloatSorting(str("{: .02f}".format(maxObjArea)))
            item.setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            self.table.setItem(rowNum, 1, item)
                
            # Load min object areas
            item = QTableWidgetItemWithFloatSorting(str("{: .02f}".format(minObjArea)))
            item.setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            self.table.setItem(rowNum, 2, item)
            
            # Load label numbers
            item = QTableWidgetItemWithFloatSorting(str("{: .01f}".format(labelNum)))
            item.setFlags( Qt.ItemIsSelectable |  Qt.ItemIsEnabled )
            self.table.setItem(rowNum, 3, item)
        
        # Resize column size to fit dialog size
        self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch)   
        
        # Sort by max object area
        self.table.setSortingEnabled(True)                         
        self.table.sortByColumn(1) 
        

    def _captureDoubleClick(self):
        # Navigate to selected frame
        index = self.table.selectedIndexes()[0]
        frameStr = self.table.model().data(index).toString()
        
        if frameStr:
            frameNum = int(frameStr)
            self.parent().editor.posModel.time = frameNum
Пример #28
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()
Пример #29
0
class OWxsh_waviness(widget.OWWidget):
    name = "xsh_waviness"
    id = "orange.widgets.preprocessor.xsh_waviness"
    description = "xoppy application to compute..."
    icon = "icons/waviness.png"
    author = "Luca Rebuffi"
    maintainer_email = "[email protected]; [email protected]"
    priority = 10
    category = ""
    keywords = ["xoppy", "xsh_waviness"]

    outputs = [{"name": "PreProcessor_Data",
                "type": ShadowPreProcessorData,
                "doc": "PreProcessor Data",
                "id": "PreProcessor_Data"}]

    want_main_area = 1
    want_control_area = 1

    WIDGET_WIDTH = 1100
    WIDGET_HEIGHT = 650

    xx = None
    yy = None
    zz = None

    number_of_points_x = Setting(10)
    number_of_points_y = Setting(100)

    dimension_x = Setting(20.1)
    dimension_y = Setting(113.1)

    estimated_slope_error = Setting(0.9)
    montecarlo_seed = Setting(2387427)

    waviness_file_name = Setting('waviness.dat')

    harmonic_maximum_index = Setting(60)

    data = Setting({'c': ['0.3',
                          '0.1',
                          '0.1',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.3',
                          '0.0',
                          '0.0',
                          '0.3',
                          '0.0',
                          '0.0',
                          '0.5',
                          '0.0',
                          '0.0',
                          '0.2',
                          '0.2',
                          '0.2',
                          '0.9',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.4',
                          '0.0',
                          '0.0',
                          '0.4',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.6',
                          '0.6',
                          '0.0',
                          '0.4',
                          '0.4',
                          '0.0',
                          '0.4',
                          '0.4',
                          '0.1',
                          '0.4',
                          '0.4',
                          '0.1',
                          '0.2',
                          '0.2',
                          '0.0',
                          '0.2',
                          '0.2',
                          '0.0',
                          '0.3',
                          '0.3',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0'],
                    'y': ['0.0',
                          '-0.1',
                          '-0.1',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.03',
                          '0.0',
                          '0.0',
                          '0.2',
                          '0.0',
                          '0.0',
                          '0.2',
                          '0.0',
                          '0.0',
                          '0.1',
                          '0.1',
                          '0.1',
                          '0.1',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.01',
                          '0.0',
                          '0.0',
                          '0.03',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.02',
                          '0.02',
                          '0.0',
                          '0.1',
                          '0.1',
                          '0.0',
                          '0.1',
                          '0.1',
                          '0.0',
                          '0.1',
                          '0.1',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.3',
                          '0.3',
                          '0.0',
                          '0.2',
                          '0.2',
                          '0.0',
                          '0.2',
                          '0.2',
                          '0.0',
                          '0.2',
                          '0.2',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0'],
                    'g': ['0.0',
                          '0.3',
                          '0.3',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.05',
                          '0.0',
                          '0.0',
                          '0.05',
                          '0.0',
                          '0.0',
                          '0.1',
                          '0.0',
                          '0.0',
                          '0.05',
                          '0.05',
                          '0.05',
                          '0.2',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.1',
                          '0.0',
                          '0.0',
                          '0.1',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.2',
                          '0.2',
                          '0.0',
                          '0.1',
                          '0.1',
                          '0.0',
                          '0.1',
                          '0.1',
                          '0.0',
                          '0.1',
                          '0.1',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.1',
                          '0.1',
                          '0.0',
                          '0.2',
                          '0.2',
                          '0.0',
                          '0.1',
                          '0.1',
                          '0.0',
                          '0.1',
                          '0.1',
                          '0.0',
                          '0.0',
                          '0.0',
                          '0.0']})

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

        geom = QApplication.desktop().availableGeometry()
        self.setGeometry(QRect(round(geom.width() * 0.05),
                               round(geom.height() * 0.05),
                               round(min(geom.width() * 0.98, self.WIDGET_WIDTH)),
                               round(min(geom.height() * 0.95, self.WIDGET_HEIGHT))))

        gen_box = ShadowGui.widgetBox(self.controlArea, "Waviness Parameters", addSpace=True, orientation="horizontal",
                                      width=500)

        tabs_setting = gui.tabWidget(gen_box)

        tab_input = ShadowGui.createTabPage(tabs_setting, "Input Parameter")
        tab_harmonics = ShadowGui.createTabPage(tabs_setting, "Harmonics")
        tab_out = ShadowGui.createTabPage(tabs_setting, "Output")

        self.input_box = ShadowGui.widgetBox(tab_input, "Inputs", addSpace=True, orientation="vertical", width=470)

        gui.button(self.input_box, self, "Load xsh_waviness input file ...", callback=self.load_inp_file)

        gui.separator(self.input_box)

        ShadowGui.lineEdit(self.input_box, self, "number_of_points_x", "Number of Points (<201)           X (width)",
                           labelWidth=300, valueType=int, orientation="horizontal")
        ShadowGui.lineEdit(self.input_box, self, "number_of_points_y",
                           "                                                 Y (length)", labelWidth=300, valueType=int,
                           orientation="horizontal")

        gui.separator(self.input_box)

        ShadowGui.lineEdit(self.input_box, self, "dimension_x", "Dimensions [cm]                        X (width)",
                           labelWidth=300, valueType=float, orientation="horizontal")
        ShadowGui.lineEdit(self.input_box, self, "dimension_y",
                           "                                                 Y (length)", labelWidth=300,
                           valueType=float, orientation="horizontal")

        gui.separator(self.input_box)

        ShadowGui.lineEdit(self.input_box, self, "estimated_slope_error", "Estimated slope error [arcsec]",
                           labelWidth=300, valueType=float, orientation="horizontal")
        ShadowGui.lineEdit(self.input_box, self, "montecarlo_seed", "Monte Carlo initial seed", labelWidth=300,
                           valueType=int, orientation="horizontal")

        self.output_box = ShadowGui.widgetBox(tab_input, "Outputs", addSpace=True, orientation="vertical", width=470)

        self.select_file_box = ShadowGui.widgetBox(self.output_box, "", addSpace=True, orientation="horizontal")

        gui.separator(self.output_box)

        gui.button(self.output_box, self, "Write xsh_waviness input file (optional) ...", callback=self.write_inp_file)

        ShadowGui.lineEdit(self.select_file_box, self, "waviness_file_name", "Output File Name", labelWidth=120,
                           valueType=str, orientation="horizontal")

        self.harmonics_box = ShadowGui.widgetBox(tab_harmonics, "Harmonics", addSpace=True, orientation="vertical",
                                                 width=470, height=690)

        ShadowGui.lineEdit(self.harmonics_box, self, "harmonic_maximum_index", "Harmonic Maximum Index", labelWidth=300,
                           valueType=int, orientation="horizontal", callback=self.set_harmonics)

        gui.separator(self.harmonics_box)

        self.scrollarea = QScrollArea()
        self.scrollarea.setMaximumWidth(400)

        self.harmonics_box.layout().addWidget(self.scrollarea, alignment=Qt.AlignHCenter)

        self.shadow_output = QTextEdit()
        self.shadow_output.setReadOnly(True)

        out_box = ShadowGui.widgetBox(tab_out, "System Output", addSpace=True, orientation="horizontal", height=600)
        out_box.layout().addWidget(self.shadow_output)

        button_box = ShadowGui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal")

        button = gui.button(button_box, self, "Calculate Waviness", callback=self.calculate_waviness)
        button.setFixedHeight(45)
        button.setFixedWidth(170)

        button = gui.button(button_box, self, "Generate Waviness File", callback=self.generate_waviness_file)
        font = QFont(button.font())
        font.setBold(True)
        button.setFont(font)
        palette = QPalette(button.palette())  # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('Dark Blue'))
        button.setPalette(palette)  # assign new palette
        button.setFixedHeight(45)
        button.setFixedWidth(200)

        button = gui.button(button_box, self, "Reset Fields", callback=self.call_reset_settings)
        font = QFont(button.font())
        font.setItalic(True)
        button.setFont(font)
        palette = QPalette(button.palette())  # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('Dark Red'))
        button.setPalette(palette)  # assign new palette
        button.setFixedHeight(45)
        button.setFixedWidth(120)

        gui.rubber(self.controlArea)

        self.figure = Figure(figsize=(600, 600))
        self.figure.patch.set_facecolor('white')

        self.axis = self.figure.add_subplot(111, projection='3d')

        self.axis.set_xlabel("X (cm)")
        self.axis.set_ylabel("Y (cm)")
        self.axis.set_zlabel("Z (µm)")

        self.figure_canvas = FigureCanvasQTAgg(self.figure)
        self.mainArea.layout().addWidget(self.figure_canvas)

        gui.rubber(self.mainArea)

    def restoreWidgetPosition(self):
        super().restoreWidgetPosition()

        self.table = QTableWidget(self.harmonic_maximum_index + 1, 3)
        self.table.setAlternatingRowColors(True)
        self.table.horizontalHeader().setResizeMode(QHeaderView.Fixed)

        for i in range(0, 3):
            self.table.setColumnWidth(i, 70)

        horHeaders = []
        verHeaders = []

        for n, key in enumerate(sorted(self.data.keys())):
            horHeaders.append(key)

            for m, item in enumerate(self.data[key]):
                table_item = QTableWidgetItem(str(item))
                table_item.setTextAlignment(Qt.AlignRight)
                self.table.setItem(m, n, table_item)
                verHeaders.append(str(m))

        self.table.setHorizontalHeaderLabels(horHeaders)
        self.table.setVerticalHeaderLabels(verHeaders)
        self.table.resizeRowsToContents()

        self.table.itemChanged.connect(self.table_item_changed)

        self.scrollarea.setWidget(self.table)
        self.scrollarea.setWidgetResizable(1)

        gui.rubber(self.controlArea)

    def reload_harmonics_table(self):
        horHeaders = []
        verHeaders = []

        self.table.itemChanged.disconnect(self.table_item_changed)

        self.table.clear()

        row_count = self.table.rowCount()

        for n in range(0, row_count):
            self.table.removeRow(0)

        for index in range(0, self.harmonic_maximum_index + 1):
            self.table.insertRow(0)

        for n, key in enumerate(sorted(self.data.keys())):
            horHeaders.append(key)

            for m, item in enumerate(self.data[key]):
                table_item = QTableWidgetItem(str(item))
                table_item.setTextAlignment(Qt.AlignRight)
                self.table.setItem(m, n, table_item)
                verHeaders.append(str(m))

        self.table.setHorizontalHeaderLabels(horHeaders)
        self.table.setVerticalHeaderLabels(verHeaders)

        self.table.resizeRowsToContents()

        for i in range(0, 3):
            self.table.setColumnWidth(i, 70)

        self.table.itemChanged.connect(self.table_item_changed)

    def table_item_changed(self):
        dict = {}
        message = ""
        error_row_index = -1
        error_column_index = -1
        previous_value = ""

        try:
            row_count = self.harmonic_maximum_index + 1

            for column_index in range(0, self.table.columnCount()):
                column_name = self.table.horizontalHeaderItem(column_index).data(0)

                row_content = []

                for row_index in range(0, row_count):
                    if not self.table.item(row_index, column_index) is None:
                        message = "Value at row " + str(
                            row_index) + " and column \'" + column_name + "\' is not numeric"
                        error_row_index = row_index
                        error_column_index = column_index
                        previous_value = self.data[column_name][row_index]

                        value = float(self.table.item(row_index, column_index).data(0))  # to raise exception

                        row_content.append(str(value))

                dict[column_name] = row_content

            self.data = dict
        except ValueError:
            QMessageBox.critical(self, "QMessageBox.critical()",
                                 message + "\nValue is reset to previous value",
                                 QMessageBox.Ok)

            table_item = QTableWidgetItem(previous_value)
            table_item.setTextAlignment(Qt.AlignRight)
            self.table.setItem(error_row_index, error_column_index, table_item)
            self.table.setCurrentCell(error_row_index, error_column_index)

        except Exception as exception:
            QMessageBox.critical(self, "QMessageBox.critical()",
                                 exception.args[0],
                                 QMessageBox.Ok)

    def set_harmonics(self):
        if self.harmonic_maximum_index < 0:
            QMessageBox.critical(self, "QMessageBox.critical()",
                                 "Harmonic Maximum Index should be a positive integer number",
                                 QMessageBox.Ok)
        else:
            row_count = len(self.data["c"])

            if self.harmonic_maximum_index + 1 > row_count:
                for n, key in enumerate(sorted(self.data.keys())):
                    for m in range(row_count, self.harmonic_maximum_index + 1):
                        self.data[key].append('0.0')
            else:
                for n, key in enumerate(sorted(self.data.keys())):
                    self.data[key] = copy.deepcopy(self.data[key][0: self.harmonic_maximum_index + 1])

            self.reload_harmonics_table()

    def load_inp_file(self):
        file_name = QFileDialog.getOpenFileName(self, "Select a input file for XSH_WAVINESS", ".", "*.inp")

        if not file_name is None:
            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            if not file_name.strip() == "":
                dict = ST.waviness_read(file=file_name)

                self.number_of_points_x = dict["npointx"]
                self.number_of_points_y = dict["npointy"]
                self.dimension_y = dict["xlength"]
                self.dimension_x = dict["width"]
                self.estimated_slope_error = dict["slp"]
                self.montecarlo_seed = dict["iseed"]
                self.waviness_file_name = dict["file"].strip('\n\r').strip()
                self.harmonic_maximum_index = dict["nharmonics"]

                self.data["c"] = self.to_str_array(dict["c"])
                self.data["y"] = self.to_str_array(dict["y"])
                self.data["g"] = self.to_str_array(dict["g"])

                self.reload_harmonics_table()

    def write_inp_file(self):
        try:
            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            self.check_fields()

            file_name = self.waviness_file_name.strip().split(sep=".dat")[0] + ".inp"

            dict = {}

            dict["npointx"] = self.number_of_points_x
            dict["npointy"] = self.number_of_points_y
            dict["xlength"] = self.dimension_y
            dict["width"] = self.dimension_x
            dict["slp"] = self.estimated_slope_error
            dict["iseed"] = self.montecarlo_seed
            dict["file"] = self.waviness_file_name.strip('\n\r')
            dict["nharmonics"] = self.harmonic_maximum_index

            dict["c"] = self.to_float_array(self.data["c"])
            dict["y"] = self.to_float_array(self.data["y"])
            dict["g"] = self.to_float_array(self.data["g"])

            ST.waviness_write(dict, file=file_name)

            QMessageBox.information(self, "QMessageBox.information()",
                                    "File \'" + file_name + "\' written to disk",
                                    QMessageBox.Ok)

        except Exception as exception:
            QMessageBox.critical(self, "QMessageBox.critical()",
                                 exception.args[0],
                                 QMessageBox.Ok)

    def calculate_waviness(self):
        try:
            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            self.check_fields()

            xx, yy, zz = ST.waviness_calc(npointx=self.number_of_points_x,
                                          npointy=self.number_of_points_y,
                                          width=self.dimension_x,
                                          xlength=self.dimension_y,
                                          slp=self.estimated_slope_error,
                                          nharmonics=self.harmonic_maximum_index,
                                          iseed=self.montecarlo_seed,
                                          c=self.to_float_array(self.data["c"]),
                                          y=self.to_float_array(self.data["y"]),
                                          g=self.to_float_array(self.data["g"]))
            self.xx = xx
            self.yy = yy
            self.zz = zz

            self.axis.clear()

            x_to_plot, y_to_plot = numpy.meshgrid(xx, yy)
            z_to_plot = []

            for y_index in range(0, len(yy)):
                z_array = []
                for x_index in range(0, len(xx)):
                    z_array.append(1e4 * float(zz[x_index][y_index]))  # to micron
                z_to_plot.append(z_array)

            z_to_plot = numpy.array(z_to_plot)

            self.axis.plot_surface(x_to_plot, y_to_plot, z_to_plot,
                                   rstride=1, cstride=1, cmap=cm.autumn, linewidth=0.5, antialiased=True)

            slope, sloperms = ST.slopes(zz, xx, yy)

            title = ' Slope error rms in X direction: %f arcsec' % (sloperms[0]) + '\n' + \
                    '                                            : %f urad' % (sloperms[2]) + '\n' + \
                    ' Slope error rms in Y direction: %f arcsec' % (sloperms[1]) + '\n' + \
                    '                                            : %f urad' % (sloperms[3])

            self.axis.set_xlabel("X (cm)")
            self.axis.set_ylabel("Y (cm)")
            self.axis.set_zlabel("Z (µm)")
            self.axis.set_title(title)
            self.axis.mouse_init()

            self.figure_canvas.draw()

            QMessageBox.information(self, "QMessageBox.information()",
                                    "Waviness calculated: if the result is satisfactory,\nclick \'Generate Waviness File\' to complete the operation ",
                                    QMessageBox.Ok)
        except Exception as exception:
            QMessageBox.critical(self, "QMessageBox.critical()",
                                 exception.args[0],
                                 QMessageBox.Ok)


    def generate_waviness_file(self):
        if not self.zz is None and not self.yy is None and not self.xx is None:
            if not self.waviness_file_name is None:
                self.waviness_file_name = self.waviness_file_name.strip()

                if self.waviness_file_name == "": raise Exception("Output File Name missing")
            else:
                raise Exception("Output File Name missing")

            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            ST.write_shadow_surface(self.zz.T, self.xx, self.yy, outFile=self.waviness_file_name)
            QMessageBox.information(self, "QMessageBox.information()",
                                    "Waviness file " + self.waviness_file_name + " written on disk",
                                    QMessageBox.Ok)

            self.send("PreProcessor_Data", ShadowPreProcessorData(waviness_data_file=self.waviness_file_name))

    def call_reset_settings(self):
        if ConfirmDialog.confirmed(parent=self, message="Confirm Reset of the Fields?"):
            try:
                self.resetSettings()
                self.reload_harmonics_table()
            except:
                pass

    def check_fields(self):
        self.number_of_points_x = ShadowGui.checkStrictlyPositiveNumber(self.number_of_points_x, "Number of Points X")
        self.number_of_points_y = ShadowGui.checkStrictlyPositiveNumber(self.number_of_points_y, "Number of Points Y")

        self.dimension_x = ShadowGui.checkStrictlyPositiveNumber(self.dimension_x, "Dimension X")
        self.dimension_y = ShadowGui.checkStrictlyPositiveNumber(self.dimension_y, "Dimension Y")

        self.estimated_slope_error = ShadowGui.checkPositiveNumber(self.estimated_slope_error, "Estimated slope error")
        self.montecarlo_seed = ShadowGui.checkPositiveNumber(self.montecarlo_seed, "Monte Carlo initial seed")

        self.harmonic_maximum_index = ShadowGui.checkPositiveNumber(self.harmonic_maximum_index,
                                                                    "Harmonic Maximum Index")

        if not self.waviness_file_name is None:
            self.waviness_file_name = self.waviness_file_name.strip()

            if self.waviness_file_name == "": raise Exception("Output File Name missing")
        else:
            raise Exception("Output File Name missing")


    def to_float_array(self, string_array):
        float_array = []

        for index in range(len(string_array)):
            float_array.append(float(string_array[index]))

        return float_array

    def to_str_array(self, float_array):
        string_array = []

        for index in range(len(float_array)):
            string_array.append(str(float_array[index]))

        return string_array

    def writeStdOut(self, text):
        cursor = self.shadow_output.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.shadow_output.setTextCursor(cursor)
        self.shadow_output.ensureCursorVisible()
Пример #30
0
class wavListDialog(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.prm = self.parent().parent().prm
        self.audioManager = audioManager(self)
        self.currLocale = self.parent().parent().prm['currentLocale']
        self.currLocale.setNumberOptions(
            self.currLocale.OmitGroupSeparator
            | self.currLocale.RejectGroupSeparator)
        self.isPlaying = False

        self.sizer = QGridLayout()
        self.v1Sizer = QVBoxLayout()

        self.wavsTableWidget = QTableWidget()
        self.wavsTableWidget.setColumnCount(4)
        self.wavsTableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.wavsTableWidget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)

        self.wavsTableWidget.setHorizontalHeaderLabels(
            [self.tr("File"),
             self.tr('Use'),
             self.tr("RMS Level"), 'id'])
        self.quidColumn = 3
        self.wavsTableWidget.hideColumn(self.quidColumn)
        self.wavsTableWidget.cellDoubleClicked[int, int].connect(
            self.onCellDoubleClicked)

        #ADD wav BUTTON
        self.addWavButton = QPushButton(self.tr("Add Wav"), self)
        self.addWavButton.clicked.connect(self.onClickAddWavButton)
        #REMOVE wav BUTTON
        self.removeWavButton = QPushButton(self.tr("Remove Wav"), self)
        self.removeWavButton.clicked.connect(self.onClickRemoveWavButton)

        #PLAY wav BUTTON
        self.playWavButton = QPushButton(self.tr("Play Wav"), self)
        self.playWavButton.clicked.connect(self.onClickPlayWavButton)
        #STOP wav BUTTON
        self.stopWavButton = QPushButton(self.tr("Stop Playing"), self)
        self.stopWavButton.clicked.connect(self.onClickStopWavButton)

        self.v1Sizer.addWidget(self.addWavButton)
        self.v1Sizer.addWidget(self.removeWavButton)
        self.v1Sizer.addWidget(self.playWavButton)
        self.v1Sizer.addWidget(self.stopWavButton)

        self.v1Sizer.addStretch()

        self.wavsList = {}

        for i in range(len(self.parent().wavsPref['endMessageFiles'])):
            currCount = i + 1
            thisID = self.parent().wavsPref['endMessageFilesID'][i]
            self.wavsList[thisID] = {}
            self.wavsList[thisID]['file'] = self.parent(
            ).wavsPref['endMessageFiles'][i]
            self.wavsList[thisID]['use'] = self.parent(
            ).wavsPref['endMessageFilesUse'][i]
            self.wavsList[thisID]['level'] = self.parent(
            ).wavsPref['endMessageLevels'][i]
            self.wavsTableWidget.setRowCount(currCount)
            n = 0
            newItem = QTableWidgetItem(self.wavsList[thisID]['file'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount - 1, n, newItem)
            n = n + 1
            newItem = QTableWidgetItem(self.wavsList[thisID]['use'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount - 1, n, newItem)
            n = n + 1
            newItem = QTableWidgetItem(
                self.currLocale.toString(self.wavsList[thisID]['level']))
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount - 1, n, newItem)
            n = n + 1
            self.wavsList[thisID]['qid'] = QTableWidgetItem(thisID)
            self.wavsTableWidget.setItem(currCount - 1, n,
                                         self.wavsList[thisID]['qid'])

        buttonBox = QDialogButtonBox(QDialogButtonBox.Apply
                                     | QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)

        self.sizer.addLayout(self.v1Sizer, 0, 0)
        self.sizer.addWidget(self.wavsTableWidget, 0, 1)
        self.sizer.addWidget(buttonBox, 1, 1)
        self.setLayout(self.sizer)
        self.setWindowTitle(self.tr("Edit Wavs"))
        self.show()

    def onCellDoubleClicked(self, row, col):
        if col == 0:
            pass
        elif col == 1:
            self.onEditUse()
        elif col == 2:
            self.onEditLevel()

    def onEditLevel(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            msg = self.tr('RMS Level:')
            text, ok = QInputDialog.getDouble(
                self, self.tr('Input Dialog'), msg,
                self.wavsList[selectedSound]['level'])
            if ok:
                self.wavsTableWidget.item(
                    self.wavsList[selectedSound]['qid'].row(),
                    2).setText(self.currLocale.toString(text))
                self.wavsList[selectedSound]['level'] = text

    def onEditUse(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            if self.wavsTableWidget.item(
                    self.wavsList[selectedSound]['qid'].row(),
                    1).text() == "\u2012":
                self.wavsTableWidget.item(
                    self.wavsList[selectedSound]['qid'].row(),
                    1).setText("\u2713")
                self.wavsList[selectedSound]['use'] = "\u2713"
            else:
                self.wavsTableWidget.item(
                    self.wavsList[selectedSound]['qid'].row(),
                    1).setText("\u2012")
                self.wavsList[selectedSound]['use'] = "\u2012"

    def findSelectedItemIds(self):
        selItems = self.wavsTableWidget.selectedItems()
        selItemsRows = []
        for i in range(len(selItems)):
            selItemsRows.append(selItems[i].row())
        selItemsRows = unique(selItemsRows)
        selItemsIds = []
        for i in range(len(selItemsRows)):
            selItemsIds.append(
                str(
                    self.wavsTableWidget.item(selItemsRows[i],
                                              self.quidColumn).text()))
        return selItemsIds

    def permanentApply(self):
        self.wavListToPass = {}
        self.wavListToPass['endMessageFiles'] = []
        self.wavListToPass['endMessageFilesUse'] = []
        self.wavListToPass['endMessageFilesID'] = []
        self.wavListToPass['endMessageLevels'] = []

        keys = sorted(self.wavsList.keys())
        for key in keys:
            self.wavListToPass['endMessageFiles'].append(
                str(self.wavsList[key]['file']))
            self.wavListToPass['endMessageFilesUse'].append(
                self.wavsList[key]['use'])
            self.wavListToPass['endMessageLevels'].append(
                self.wavsList[key]['level'])
            self.wavListToPass['endMessageFilesID'].append(key)

    def onClickAddWavButton(self):
        fName = QFileDialog.getOpenFileName(
            self, self.tr("Choose wav file to load"), '',
            self.tr("wav files (*.wav);;All Files (*)"))[0]
        if len(fName) > 0:  #if the user didn't press cancel

            if len(self.wavsList.keys()) > 0:
                keys = sorted(self.wavsList.keys())
                thisID = str(int(keys[-1]) + 1)
            else:
                thisID = "1"
            currCount = self.wavsTableWidget.rowCount() + 1

            self.wavsList[thisID] = {}
            self.wavsList[thisID]['file'] = fName
            self.wavsList[thisID]['use'] = "\u2713"
            self.wavsList[thisID]['level'] = 60
            self.wavsTableWidget.setRowCount(currCount)
            n = 0
            newItem = QTableWidgetItem(self.wavsList[thisID]['file'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount - 1, n, newItem)
            n = n + 1
            newItem = QTableWidgetItem(self.wavsList[thisID]['use'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount - 1, n, newItem)
            n = n + 1
            newItem = QTableWidgetItem(
                self.currLocale.toString(self.wavsList[thisID]['level']))
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.wavsTableWidget.setItem(currCount - 1, n, newItem)
            n = n + 1
            self.wavsList[thisID]['qid'] = QTableWidgetItem(thisID)
            self.wavsTableWidget.setItem(currCount - 1, n,
                                         self.wavsList[thisID]['qid'])

    def onClickRemoveWavButton(self):
        ids = self.findSelectedItemIds()
        for i in range(len(ids)):
            selectedWavs = ids[i]
            self.wavsTableWidget.removeRow(
                self.wavsList[selectedWavs]['qid'].row())
            del self.wavsList[selectedWavs]

    def onClickPlayWavButton(self):
        ids = self.findSelectedItemIds()
        if len(ids) < 1:
            QMessageBox.warning(self, self.tr('Warning'),
                                self.tr('No files selected for playing'))
        else:
            if len(ids) > 1:
                pass  #maybe say on the status bar that only the first one will be played
            selectedWav = ids[0]
            fName = self.wavsList[selectedWav]['file']
            level = self.wavsList[selectedWav]['level']
            nBits = self.currLocale.toInt(
                self.parent().parent().nBitsChooser.currentText())[0]
            maxLevel = float(self.prm['phones']['phonesMaxLevel'][
                self.parent().parent().phonesChooser.currentIndex()])
            msgSnd, fs = self.audioManager.loadWavFile(fName, level, maxLevel,
                                                       'Both')
            self.isPlaying = True
            if self.prm['pref']['sound']['playCommand'] in [
                    "alsaaudio", "pyaudio"
            ]:
                self.playThread = threadedAudioPlayer(self.parent().parent())
            else:
                self.playThread = threadedExternalAudioPlayer(
                    self.parent().parent())
            self.playThread.playThreadedSound(
                msgSnd, fs, nBits, self.prm['pref']['sound']['playCommand'],
                False, 'tmp.wav')
            if self.playThread.isFinished == True:
                self.isPlaying = False

    def onClickStopWavButton(self):
        if self.isPlaying == True:
            self.playThread.terminate()

    def closeEvent(self, event):
        if self.isPlaying == True:
            self.playThread.terminate()
        event.accept()

    def accept(self):  #reimplement accept (i.e. ok button)
        if self.isPlaying == True:
            self.playThread.terminate()
        QDialog.accept(self)

    def reject(self):  #reimplement reject
        if self.isPlaying == True:
            self.playThread.terminate()
        QDialog.reject(self)
Пример #31
0
class DataItemWidget(QWidget):
    __EXTRA_COLUMN_WIDTH = 20

    def __init__(self, me_cls, data):
        QWidget.__init__(self)
        self.__me_cls = me_cls
        self.__setup_ui()
        self.__data = data
        self.__init_data()
        self.__connect_slot()

    def __setup_ui(self):

        v_layout = QVBoxLayout()

        self.__tool_widget = ToolWidget()

        self.__tool_widget.setMaximumHeight(40)

        self.__data_table_widget = QTableWidget()
        self.__data_table_widget.horizontalHeader().setStretchLastSection(True)
        self.__data_table_widget.horizontalHeader().setResizeMode(
            0, QHeaderView.Fixed)

        v_layout.setSpacing(0)
        v_layout.setContentsMargins(0, 0, 0, 0)
        v_layout.addWidget(self.__tool_widget, 0)
        v_layout.addWidget(self.__data_table_widget, 1)
        self.setLayout(v_layout)

    def __connect_slot(self):
        pass
        #self.connect(self.__tool_widget,SIGNAL('refresh_btn_clicked()'), self ,SLOT('__on_refresh_signal()'))

    def __init_data(self):

        self.__data_table_widget.clearContents()

        # init header
        #self.__colume_names = yt_connection.get_table_colume_names(self.__table_name)
        self.__colume_names = [x.field.name for x in self.__me_cls.attributes]
        #self.__colume_names.insert(0,'entity_id')

        #print self.__colume_names

        self.__data_table_widget.setColumnCount(len(self.__colume_names))
        head_list = QStringList()
        for colume in self.__colume_names:
            head_list << colume

        self.__data_table_widget.setHorizontalHeaderLabels(head_list)

        # default the header column both sides are coverd, these codes add __EXTRA_COLUMN_WIDTH to the header column width
        # and reise column width in function self.__adjust_table_colume()
        self.__data_table_widget.horizontalHeader().setResizeMode(
            QHeaderView.ResizeToContents)
        self.__record_colume_header_width()
        self.__data_table_widget.horizontalHeader().setResizeMode(
            QHeaderView.Interactive)

        self.__record_colume_header_width()

        show_data = []
        for entity_id, value in self.__data.items():
            item = value.obj_data.copy()
            item['managed_entity_id'] = entity_id
            show_data.append(item)

        self.__update_table(show_data)

        # init data
        # data = yt_connection.get_table_data(self.__table_name)
        #
        # self.__update_table(data)
        self.__adjust_table_colume()

    def __record_colume_header_width(self):
        count = self.__data_table_widget.columnCount()
        self.__column_widths = []
        for i in range(count):
            self.__column_widths.append(
                self.__data_table_widget.columnWidth(i) +
                self.__EXTRA_COLUMN_WIDTH)

    '''
    data like this
    [
    {u'direction': 'to-lport', 
    u'name': '[]', 
    u'priority': '100', 
    u'log': 'true', 
    u'action': 'drop', 
    u'external_ids': '{"neutron:lport"="5fb77332-2035-4f72-8e57-7415b02489c9"}', 
    u'match': '"outport==\\"inside-vm2\\""', 
    u'severity': '[]',
    'uuid': '2890a832-1c83-4b8e-8b40-2928817012cc'}
    ]

    '''

    def __update_table(self, data):
        self.__data_table_widget.clearContents()

        row_num = 0
        for row in data:
            self.__data_table_widget.insertRow(row_num)
            colume_num = 0
            for colume in self.__colume_names:
                if row.has_key(colume):
                    item_str = str(row[colume])
                else:
                    item_str = 'None'
                table_wid_item = QTableWidgetItem(item_str)
                table_wid_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)

                self.__data_table_widget.setItem(row_num, colume_num,
                                                 table_wid_item)
                colume_num += 1
            row_num += 1

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

    def __adjust_table_colume(self):
        self.__data_table_widget.resizeColumnsToContents()
        count = self.__data_table_widget.columnCount()
        for i in range(count):
            col_wid = self.__data_table_widget.columnWidth(i)
            if col_wid < self.__column_widths[i]:
                self.__data_table_widget.setColumnWidth(
                    i, self.__column_widths[i])
Пример #32
0
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)
Пример #33
0
class OrbitCorrGeneral(QtGui.QWidget):
    """
    A general orbit correction or local bump panel.
    """
    def __init__(self, bpms, cors, parent = None):
        super(OrbitCorrGeneral, self).__init__(parent)

        self.bpms, self.cors = bpms, cors
        self.sb = [bpm.sb for bpm in self.bpms]
        self.x0, self.y0 = None, None
        self._update_current_orbit()

        self.table = QTableWidget(len(self.bpms), 9)
        self.table.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        hdview = QHeaderView(Qt.Horizontal)
        self.table.setHorizontalHeaderLabels(
            ['BPM Name', 's', "Beta X", "Beta Y",
             "Eta X", 'X Bump', 'Y Bump', "Target X", "Target Y"])
        self._twiss = getTwiss([b.name for b in self.bpms],
                               ["s", "betax", "betay", "etax"])
        for i,bpm in enumerate(self.bpms):
            it = QTableWidgetItem(bpm.name)
            it.setFlags(it.flags() & (~Qt.ItemIsEditable))
            self.table.setItem(i, 0, it)

            it = QTableWidgetItem(str(bpm.sb))
            it.setFlags(it.flags() & (~Qt.ItemIsEditable))
            #it.setMinimumWidth(80)
            self.table.setItem(i, 1, it)
            self.table.setItem(i, 2,
                               QTableWidgetItem("%.4f" % self._twiss[i,1]))
            self.table.setItem(i, 3,
                               QTableWidgetItem("%.4f" % self._twiss[i,2]))
            self.table.setItem(i, 4,
                               QTableWidgetItem("%.4f" % self._twiss[i,3]))

            for j in range(5, 9):
                it = QTableWidgetItem(str(0.0))
                it.setData(Qt.DisplayRole, str(0.0))
                it.setFlags(it.flags() | Qt.ItemIsEditable)
                self.table.setItem(i, j, it)
            # use the current orbit
            #self.table.item(i,4).setData(Qt.DisplayRole, str(self.x0[i]))
            #self.table.item(i,5).setData(Qt.DisplayRole, str(self.y0[i]))

        #self.connect(self.table, SIGNAL("cellClicked(int, int)"),
        #             self._cell_clicked)
        self.table.resizeColumnsToContents()
        #self.table.horizontalHeader().setStretchLastSection(True)
        #for i in range(4):
        #    print "width", i, self.table.columnWidth(i)
        #self.table.setColumnWidth(0, 300)
        self.table.setColumnWidth(1, 80)

        vbox1 = QtGui.QVBoxLayout()
        frmbox = QFormLayout()
        self.base_orbit_box = QtGui.QComboBox()
        #self.base_orbit_box.addItems([
        #        "Current Orbit", "All Zeros"])
        self.base_orbit_box.addItems(["All Zeros", "Current Orbit"])
        frmbox.addRow("Orbit Base", self.base_orbit_box)
        grp = QtGui.QGroupBox("Local Bump")
        grp.setLayout(frmbox)
        vbox1.addWidget(grp)

        frmbox = QFormLayout()
        hln1 = QtGui.QFrame()
        hln1.setLineWidth(3)
        hln1.setFrameStyle(QtGui.QFrame.Sunken)
        hln1.setFrameShape(QtGui.QFrame.HLine)
        frmbox.addRow(hln1)
        self.repeatbox = QSpinBox()
        self.repeatbox.setRange(1, 20)
        self.repeatbox.setValue(3)
        # or connect the returnPressed() signal
        frmbox.addRow("&Repeat correction", self.repeatbox)

        self.rcondbox = QLineEdit()
        self.rcondbox.setValidator(QDoubleValidator(0, 1, 0, self))
        self.rcondbox.setText("1e-2")
        frmbox.addRow("r&cond for SVD", self.rcondbox)

        self.scalebox = QDoubleSpinBox()
        self.scalebox.setRange(0.01, 5.00)
        self.scalebox.setSingleStep(0.01)
        self.scalebox.setValue(0.68)
        frmbox.addRow("&Scale correctors", self.scalebox)

        #hln2 = QtGui.QFrame()
        #hln2.setLineWidth(3)
        #hln2.setFrameStyle(QtGui.QFrame.Sunken)
        #hln2.setFrameShape(QtGui.QFrame.HLine)
        #frmbox.addRow(hln2)

        self.progress = QProgressBar()
        self.progress.setMaximum(self.repeatbox.value())
        self.progress.setMaximumHeight(15)
        frmbox.addRow("Progress", self.progress)
        grp = QtGui.QGroupBox("Correction")
        grp.setLayout(frmbox)
        vbox1.addWidget(grp)

        #vbox.addStretch(1.0)
        #self.qdb = QDialogButtonBox(self)
        #self.qdb.addButton("APP", QDialogButtonBox.ApplyRole)
        #self.qdb.addButton("R", QDialogButtonBox.ResetRole)
        #btn.setDefault(True)
        #self.qdb.addButton(QDialogButtonBox.Cancel)
        #self.qdb.addButton(QDialogButtonBox.Help)

        gbox = QtGui.QGridLayout()
        btn = QPushButton("Clear")
        self.connect(btn, SIGNAL("clicked()"), self.resetBumps)
        gbox.addWidget(btn, 0, 1)
        self.correctOrbitBtn = QPushButton("Apply")
        #self.correctOrbitBtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.correctOrbitBtn.setStyleSheet("QPushButton:disabled { color: gray }");
        self.connect(self.correctOrbitBtn, SIGNAL("clicked()"), self.call_apply)
        self.correctOrbitBtn.setDefault(True)
        gbox.addWidget(self.correctOrbitBtn, 1, 1)
        gbox.setColumnStretch(0, 1)

        vbox1.addStretch()
        vbox1.addLayout(gbox)

        hbox1 = QtGui.QHBoxLayout()
        hbox1.addWidget(self.table, 2)
        hbox1.addLayout(vbox1, 0)
        self.setLayout(hbox1)

        self.connect(self.base_orbit_box,
                     SIGNAL("currentIndexChanged(QString)"),
                     self.updateTargetOrbit)
        self.connect(self.repeatbox, SIGNAL("valueChanged(int)"),
                     self.progress.setMaximum)
        self.connect(self.table, SIGNAL("cellChanged (int, int)"),
                     self.updateBump)

        #self.updateTargetOrbit(self.base_orbit_box.currentText())

    def _update_current_orbit(self):
        pvx = [bpm.pv(field="x", handle="readback")[0] for bpm in self.bpms]
        pvy = [bpm.pv(field="y", handle="readback")[0] for bpm in self.bpms]
        self.x0 = [float(v) if v.ok else np.nan for v in catools.caget(pvx)]
        self.y0 = [float(v) if v.ok else np.nan for v in catools.caget(pvy)]

    def resetBumps(self):
        jx0, jy0 = 5, 6
        for i in range(self.table.rowCount()):
            self.table.item(i, jx0).setData(Qt.DisplayRole, str(0.0))
            self.table.item(i, jy0).setData(Qt.DisplayRole, str(0.0))
        #self.updateTargetOrbit(self.base_orbit_box.currentText())

    def call_apply(self):
        #print "apply the orbit"
        obt = []
        jx, jy = 7, 8
        for i in range(self.table.rowCount()):
            x1,err = self.table.item(i, jx).data(Qt.DisplayRole).toFloat()
            y1,err = self.table.item(i, jy).data(Qt.DisplayRole).toFloat()
            obt.append([x1, y1])

        self.correctOrbitBtn.setEnabled(False)
        nrepeat = self.repeatbox.value()
        kw = { "scale": float(self.scalebox.text()),
               "rcond": float(self.rcondbox.text()) }
        self.progress.setValue(0)
        QApplication.processEvents()
        for i in range(nrepeat):
            err, msg = setLocalBump(self.bpms, self.cors, obt, **kw)
            self.progress.setValue(i+1)
            QApplication.processEvents()
            if err != 0:
                QtGui.QMessageBox.critical(
                    self, "Local Orbit Bump",
                    "ERROR: {0}\nAbort.".format(msg),
                    QtGui.QMessageBox.Ok)
                #self.progress.setValue(0)
                break

        self.correctOrbitBtn.setEnabled(True)

    def getTargetOrbit(self):
        x = [self.table.item(i,7).data(Qt.DisplayRole).toFloat()[0]
             for i in range(self.table.rowCount())]
        y = [self.table.item(i,8).data(Qt.DisplayRole).toFloat()[0]
             for i in range(self.table.rowCount())]
        return (self.sb, x), (self.sb, y)

    def updateTargetOrbit(self, baseobt):
        if baseobt == "All Zeros":
            jx0, jx1 = 5, 7
            jy0, jy1 = 6, 8
            for i in range(self.table.rowCount()):
                it0 = self.table.item(i, jx0)
                it1 = self.table.item(i, jx1)
                it1.setData(Qt.DisplayRole, it0.data(Qt.DisplayRole))
                it0 = self.table.item(i, jy0)
                it1 = self.table.item(i, jy1)
                it1.setData(Qt.DisplayRole, it0.data(Qt.DisplayRole))
        elif baseobt == "Current Orbit":
            self._update_current_orbit()
            jx0, jx1 = 5, 7
            jy0, jy1 = 6, 8
            for i in range(self.table.rowCount()):
                dx0,err = self.table.item(i, jx0).data(Qt.DisplayRole).toFloat()
                it = self.table.item(i, jx1)
                it.setData(Qt.DisplayRole, self.x0[i] + dx0)

                dy0,err = self.table.item(i, jy0).data(Qt.DisplayRole).toFloat()
                it = self.table.item(i, jy1)
                it.setData(Qt.DisplayRole, self.y0[i] + dy0)
        #self._update_orbit_plot()
        x, y = self.getTargetOrbit()
        self.emit(SIGNAL("targetOrbitChanged(PyQt_PyObject, PyQt_PyObject)"),
                  x, y)

    def updateBump(self, row, col):
        #print "updating ", row, col
        if col == 5 or col == 6:
            self.updateTargetOrbit(self.base_orbit_box.currentText())
Пример #34
0
class CorrectorViewer(QtGui.QWidget):
    """
    List all corrector and select part to lower table
    """
    def __init__(self, cors, field, parent=None, nmax=4):
        super(CorrectorViewer, self).__init__(parent)
        self._nmax  = nmax
        self._field = field
        self._cors  = cors
        self._corlst1 = QtGui.QTreeWidget()
        self._header = dict([("Element", 0), ("Family", 1), ("s [m]", 2),
                             ("Alpha X", 3), ("Alpha Y", 4), ("Beta X", 5),
                             ("Beta Y", 6), ("Phi X", 7), ("Phi Y", 8),
                             ("Eta X", 9)])
        self._twiss = np.zeros((len(self._cors), 8), 'd')
        self._tunes = getTunes(source="database")
        self._corlst1.setColumnCount(len(self._header))
        self._corlst1.setHeaderLabels(
            sorted(self._header, key=self._header.get))
        self._corlst1.header().setStretchLastSection(False)
        prevcell = None
        for i,c in enumerate(self._cors):
            if c.cell and (prevcell is None or c.cell != prevcell.text(0)):
                # a new parent
                prevcell = QtGui.QTreeWidgetItem()
                prevcell.setText(0, c.cell)
                self._corlst1.addTopLevelItem(prevcell)
            it = QtGui.QTreeWidgetItem()
            it.setData(0, Qt.UserRole, i)
            it.setText(self._header["Element"], c.name)
            it.setText(self._header["Family"], c.family)
            it.setText(self._header["s [m]"], "%.3f" % c.sb)
            try:
                tw = getTwiss(c.name,
                              ["s", "alphax", "alphay", "betax", "betay",
                               "phix", "phiy", "etax"])
                self._twiss[i,:] = tw[0,:]
                it.setText(self._header["Alpha X"], "%.4f" % self._twiss[i,1])
                it.setText(self._header["Alpha Y"], "%.4f" % self._twiss[i,2])
                it.setText(self._header["Beta X"],  "%.4f" % self._twiss[i,3])
                it.setText(self._header["Beta Y"],  "%.4f" % self._twiss[i,4])
                it.setText(self._header["Phi X"],   "%.4f" % self._twiss[i,5])
                it.setText(self._header["Phi Y"],   "%.4f" % self._twiss[i,6])
                it.setText(self._header["Eta X"],   "%.4f" % self._twiss[i,7])
            except:
                it.setDisabled(True)
                pass

            if c.cell:
                prevcell.addChild(it)
            else:
                self._corlst1.addTopLevelItem(it)
                prevcell = it
            for j in range(2, len(self._header)):
                it.setTextAlignment(j, Qt.AlignRight)
        self._corlst1.expandAll()
        for i in range(len(self._header)):
            self._corlst1.resizeColumnToContents(i)
        #self._corlst1.setColumnWidth(0, 150)

        #self.elemlst.setSelectionMode(QAbstractItemView.MultiSelection)
        columns = ['Corrector', 's', 'Alpha', 'Beta',
                   'Phi', "dPhi", "Initial Bump", "Cur. Sp", "dBump",
                   "Final Rb"]
        self.table4 = QTableWidget(0, len(columns))
        #self.table4.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        hdview = QHeaderView(Qt.Horizontal)
        self.table4.setHorizontalHeaderLabels(columns)
        #for i in range(4):
        #    for j in range(len(columns)):
        #        it = QTableWidgetItem()
        #        if j > 0: it.setTextAlignment(
        #            Qt.AlignRight | Qt.AlignVCenter)
        #        if columns[j] != "dKick":
        #            it.setFlags(it.flags() & (~Qt.ItemIsEditable))
        #        self.table4.setItem(i, j, it)
        #self.table4.resizeColumnsToContents()
        #self.table4.horizontalHeader().setStretchLastSection(True)
        #hrow = self.table4.rowHeight(0)
        #htbl = (hrow * 4) + self.table4.horizontalHeader().height() +\
        #    2*self.table4.frameWidth()
        #self.table4.setMinimumHeight(htbl + 10)
        #self.table4.setMaximumHeight(htbl + 15)
        #self.table4.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        #print "Size:", htbl + 10
        self.table4.resize(self.table4.width(), 150)

        splitter = QtGui.QSplitter(Qt.Vertical)
        splitter.addWidget(self._corlst1)
        splitter.addWidget(self.table4)
        vbox1 = QtGui.QVBoxLayout()
        vbox1.addWidget(splitter)
        self.setLayout(vbox1)

        self.connect(self._corlst1, SIGNAL("doubleClicked(QModelIndex)"),
                     self.addCorrector)
        #self.connect(self.src, SIGNAL("returnPressed()"),
        #             self._calc_source)
        #self.connect(self.table4, SIGNAL("cellChanged(int, int)"),
        #             self.updateTable)

        #self.connect(self.table4, SIGNAL("doubleClicked(QModelIndex)"),
        #             self.delCorrector)
        self._x0 = fget(self._cors, "x", handle="setpoint", unitsys=None)
        self._y0 = fget(self._cors, "y", handle="setpoint", unitsys=None)


    def addCorrector(self, idx):
        if not self._corlst1.selectedItems(): return
        #print self._corlst1.itemFromIndex(idx).text(0)
        nrow = self.table4.rowCount()
        if nrow >= self._nmax:
            QtGui.QMessageBox.critical(
                self, "Local Orbit Bump",
                "ERROR: We need only {0} correctors.".format(self._nmax),
                QtGui.QMessageBox.Ok)
                #self.progress.setValue(0)
            return
        self.table4.setRowCount(nrow+1)
        it0 = self._corlst1.selectedItems()[-1]
        icor, ok = it0.data(0, Qt.UserRole).toInt()
        if icor < 0: return
        newc = self._cors[icor]
        for j in range(self.table4.columnCount()):
            it = QTableWidgetItem()
            if j > 0: it.setTextAlignment(
                Qt.AlignRight | Qt.AlignVCenter)
            header = self.table4.horizontalHeaderItem(j)
            if header.text() != "dBump":
                it.setFlags(it.flags() & (~Qt.ItemIsEditable))
            else:
                it.setData(Qt.DisplayRole, "0")
                it.setData(Qt.UserRole, 0.0)
            self.table4.setItem(nrow, j, it)
        self.table4.item(nrow,0).setData(Qt.UserRole, icor)
        for j,h in [(0, "Element"), (1, "s [m]")]:
            self.table4.item(nrow,j).setData(Qt.DisplayRole,
                                          it0.text(self._header[h]))
        for j in range(self._corlst1.columnCount()):
            it0.setForeground(j, Qt.red)
        it0.setDisabled(True)
        self.emit(SIGNAL("correctorAdded(PyQt_PyObject)"), newc)
        # use initial values

        self.updateTwiss()
        self.updateCorReadings()
        self.table4.resizeColumnsToContents()
        if self.table4.rowCount() == self._nmax:
            #print "All correctors are ready"
            self.emit(SIGNAL("correctorsComplete()"))

    def updateTwiss(self):
        if self._field == "x":
            jl = [self._header[h] for h in ["Alpha X", "Beta X", "Phi X"]]
            nu = self._tunes[0]
        elif self._field == "y":
            jl = [self._header[h] for h in ["Alpha Y", "Beta Y", "Phi Y"]]
            nu = self._tunes[1]
        else:
            raise RuntimeError("unknown cor field {0}".format(self._field))
        #print "index:", jl
        # if rows provided use it, otherwise use all
        for i in range(self.table4.rowCount()):
            elemname = self.table4.item(i,0).data(Qt.DisplayRole).toString()
            it0 = self._corlst1.findItems(
                elemname, Qt.MatchExactly | Qt.MatchRecursive)[0]

            self.table4.item(i,2).setText(it0.text(jl[0]))
            self.table4.item(i,3).setText(it0.text(jl[1]))
            self.table4.item(i,4).setText(it0.text(jl[2]))
            self.table4.item(i,4).setData(Qt.UserRole, float(it0.text(jl[2])))

            if i == 0:
                self.table4.item(i,5).setText("0.0")
                self.table4.item(i,5).setData(Qt.UserRole, 0.0)
            else:
                dph, ok = self.table4.item(i-1,5).data(Qt.UserRole).toFloat()
                ph0, ok = self.table4.item(i-1,4).data(Qt.UserRole).toFloat()
                ph1, ok = self.table4.item(i,4).data(Qt.UserRole).toFloat()
                dph = dph + ph1 - ph0
                if ph1 < ph0:
                    dph = dph + 2.0*np.pi*nu
                #print "Updating twiss:", i, dph
                self.table4.item(i,5).setData(Qt.UserRole, dph)
                self.table4.item(i,5).setText("%.5g" % dph)
            icor, ok = self.table4.item(i,0).data(Qt.UserRole).toInt()
            #c = self._cors[icor]
            #kick = self._cors[icor].get(self._field, unitsys=None)
            #self.table4.item(i,6).setData(Qt.UserRole, kick)
            #self.table4.item(i,6).setText("%.5g" % kick)
        #self.updateKickReadings(col=0)

    def clear(self):
        for i in range(self.table4.rowCount()):
            elemname = self.table4.item(i,0).data(Qt.DisplayRole).toString()
            it0 = self._corlst1.findItems(
                elemname, Qt.MatchExactly | Qt.MatchRecursive)[0]
            it0.setDisabled(False)
            for j in range(self._corlst1.columnCount()):
                it0.setForeground(j, Qt.black)
        self.table4.setRowCount(0)

    def updateCorReadings(self):
        for i in range(self.table4.rowCount()):
            icor, ok = self.table4.item(i,0).data(Qt.UserRole).toInt()
            cor = self._cors[icor]
            if self._field == "x":
                self.table4.item(i,6).setData(Qt.UserRole, self._x0[icor])
                self.table4.item(i,6).setText("%.5g" % self._x0[icor])
            elif self._field == "y":
                self.table4.item(i,6).setData(Qt.UserRole, self._y0[icor])
                self.table4.item(i,6).setText("%.5g" % self._y0[icor])
            kicksp = cor.get(self._field, handle="setpoint", unitsys=None)
            self.table4.item(i,7).setData(Qt.UserRole, float(kicksp))
            self.table4.item(i,7).setText("%.5g" % kicksp)
            kickrb = cor.get(self._field, handle="readback", unitsys=None)
            self.table4.item(i,9).setData(Qt.UserRole, float(kickrb))
            self.table4.item(i,9).setText("%.5g" % kickrb)


    def updateDbump(self, dkick):
        nrow = min(self.table4.rowCount(), len(dkick))
        for i in range(nrow):
            # dbump column is 8
            it = self.table4.item(i, 8)
            if dkick[i] is None:
                it.setData(Qt.DisplayRole, "")
                it.setData(Qt.UserRole, 0.0)
            else:
                it.setData(Qt.UserRole, float(dkick[i]))
                it.setData(Qt.DisplayRole, "{0}".format(dkick[i]))
        self.updateCorReadings()
        self.table4.resizeColumnsToContents()
        #print "(0,7)", self.table4.item(0, 7).data(Qt.UserRole).toFloat()
        #print "(0,7)", self.table4.item(0, 7).data(Qt.DisplayRole).toFloat()

    def applyKick(self):
        nrow = self.table4.rowCount()
        for i in range(nrow):
            icor, ok = self.table4.item(i,0).data(Qt.UserRole).toInt()
            cor = self._cors[icor]
            # Current SP: 7, dBump 8
            k0, ok = self.table4.item(i, 7).data(Qt.UserRole).toFloat()
            dk, ok = self.table4.item(i, 8).data(Qt.UserRole).toFloat()
            #print "Setting {0} {1}+{2} [A]".format(cor.name, k0, dk)
            cor.put(self._field, k0+dk, unitsys=None)

        # update the final readings
        self.updateCorReadings()

    def getTwiss(self):
        tw = {"s": [], "Alpha": [], "Beta": [],
              "Phi": [], "dPhi": []}
        nrow = self.table4.rowCount()
        for j in range(self.table4.columnCount()):
            header = self.table4.horizontalHeaderItem(j)
            if header.text() not in tw.keys():
                continue
            k = str(header.text())
            for i in range(nrow):
                it = self.table4.item(i, j)
                v0, ok0 = it.data(Qt.UserRole).toFloat()
                v1, ok1 = it.data(Qt.DisplayRole).toFloat()
                if ok0:
                    tw[k].append(v0)
                elif ok1:
                    tw[k].append(v1)
                else:
                    tw[k].append(np.nan)
        return tw

    def selectedCorrectors(self):
        ret = []
        for i in range(self.table4.rowCount()):
            icor, ok = self.table4.item(i,0).data(Qt.UserRole).toInt()
            ret.append(self._cors[icor])
        return ret

    def resetCorrectors(self):
        for i in range(self.table4.rowCount()):
            icor, ok = self.table4.item(i,0).data(Qt.UserRole).toInt()
            cor = self._cors[icor]
            if self._field == "x":
                kick = self._x0[icor]
            elif self._field == "y":
                kick = self._y0[icor]
            cor.put(self._field, kick, unitsys=None)
Пример #35
0
class PatternsTable(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.grid = QGridLayout()
        self.setLayout(self.grid)
        self.patternArea()
        self.patternTable()

    def createPattern(self, name, x):
        label = name.lower() + "Label"
        type = name.lower() + "Type"
        entry = name.lower() + "Entry"
        setattr(self, label, QLabel(name))
        setattr(self, entry, QLineEdit())
        setattr(self, type, QComboBox())
        labelobj = getattr(self, label)
        typeobj = getattr(self, type)
        entryobj = getattr(self, entry)
        typeobj.addItem("Hexadecimal")
        typeobj.addItem("String")
        self.grid.addWidget(labelobj, x, 0)
        self.grid.addWidget(entryobj, x, 1)
        self.grid.addWidget(typeobj, x, 2)


    def patternArea(self):
        self.filetypeLabel = QLabel("File type")
        self.filetype = QLineEdit()
        self.alignedLabel = QLabel("block aligned")
        self.aligned = QCheckBox()
        self.windowLabel = QLabel("Window size")
        self.window = QSpinBox()
        self.window.setSuffix(" bytes")
        self.window.setRange(0, 2500000)
        self.window.setSingleStep(100)
        self.addEntry = QPushButton("add")
        self.connect(self.addEntry, SIGNAL("clicked()"), self.insertPattern)
        self.grid.addWidget(self.filetypeLabel, 0, 0)
        self.grid.addWidget(self.filetype, 0, 1, 1, 2)
        self.createPattern("Header", 2)
        self.createPattern("Footer", 3)
        self.grid.addWidget(self.windowLabel, 4, 0)
        self.grid.addWidget(self.window, 4, 1)
        self.grid.addWidget(self.alignedLabel, 5, 0)
        self.grid.addWidget(self.aligned, 5, 1)
        self.grid.addWidget(self.addEntry, 6, 1)


    def patternTable(self):
        self.patterns = QTableWidget()
        self.patterns.setShowGrid(False)
        self.patterns.setColumnCount(5)
        self.patterns.setHorizontalHeaderLabels(["Filetype", "Header", "Footer", "Window", "Block aligned"])
        self.patterns.horizontalHeader().setStretchLastSection(True)
        self.connect(self.patterns.verticalHeader(), SIGNAL("sectionClicked(int)"), self.patterns.removeRow)
        self.grid.addWidget(self.patterns, 7, 0, 1, 3)
        

    def warning(self, msg):
        msgBox = QMessageBox(self)
        msgBox.setText(msg)
        msgBox.setIcon(QMessageBox.Warning)
        msgBox.exec_()

    def validate(self, **kwargs):
        msg = ""

        if len(kwargs["type"]) == 0:
            msg = "Type must be defined"
        else:
            for i in kwargs["type"]:
                if i not in string.letters:
                    msg = "Type's characters must be in the following set\n\n" + string.letters
                    break
            rowCount = self.patterns.rowCount()
            for row in range(0, rowCount):
                if str(self.patterns.item(row, 0).text()) == kwargs["type"]:
                    msg = "Type <" + kwargs["type"] + " > already defined"
        if msg != "":
            self.warning(msg)
            return False

        if kwargs["headerType"] == "Hexadecimal" and not self.isHex(kwargs["header"]):
            msg = "Header must be an even number of chars"
            self.warning(msg)
            return False
        
        if len(kwargs["header"]) == 0:
            msg = "Header must be provided"
            self.warning(msg)
            return False

        if kwargs["footerType"] == "Hexadecimal" and not self.isHex(kwargs["header"]):
            msg = "Footer must be an even number of chars"
            self.warning(msg)
            return False

        if kwargs["window"] <= 0:
            msg = "Window size must be greater than 0"
            self.warning(msg)
            return False

        return True


    def insertPattern(self):
        filetype = str(self.filetype.text())
        header = str(self.headerEntry.text())
        headerType = str(self.headerType.currentText())
        footer = str(self.footerEntry.text())
        footerType = str(self.footerType.currentText())
        window = self.window.text()
        aligned = self.aligned.isChecked()

        #Validate most of provided items
        kwargs = {"type": filetype, "header": header, "headerType": headerType, 
                  "footer": footer, "footerType": footerType, "window": int(window.replace(" bytes", ""))}
        if not self.validate(**kwargs):
            return

        filetypeItem = QTableWidgetItem(filetype)
        headerItem = QTableWidgetItem(header + " (" + headerType[0:3] + ")")
        footerItem = QTableWidgetItem(footer + " (" + footerType[0:3] + ")")
        windowItem = QTableWidgetItem(window)
        alignedItem = QTableWidgetItem(str(aligned))
        self.patterns.insertRow(self.patterns.rowCount())
        vertHeader = QTableWidgetItem(QIcon(":closetab.png"), "")
        row = self.patterns.rowCount() - 1
        self.patterns.setVerticalHeaderItem(row, vertHeader)
        self.patterns.setItem(row, 0, filetypeItem)
        self.patterns.setItem(row, 1, headerItem)
        self.patterns.setItem(row, 2, footerItem)
        self.patterns.setItem(row, 3, windowItem)
        self.patterns.setItem(row, 4, alignedItem)
        self.patterns.resizeRowToContents(row)

        
    def isHex(self, str):
        HEXCHAR = "0123456789abcdefABCDEF"
        hexStr = ""
        even = False
        for i in range(len(str)):
            if str[i] in HEXCHAR:
                if even == True:
                    even = False
                else:
                    even = True
            else:
                return False
        if even:
            return False
        return True
    

    def toHex(self, str):
        HEXCHAR = "0123456789abcdefABCDEF"
        hexStr = ""
        evenhex = ""
        for i in range(len(str)):
            if str[i] in HEXCHAR:
                if len(evenhex) == 1:
                    hexStr += chr(int(evenhex+str[i], 16))
                    evenhex = ""
                else:
                    evenhex = str[i]
            else:
                raise ValueError, "argument 'str' contains not valid characters"
        if len(evenhex) != 0:
            raise ValueError, "argument 'str' must be an even number of char"
        return hexStr


    def textToPattern(self, text):
        idx = text.find("(")
        pattern = ""
        if idx != -1:
            type = text[idx+1:idx+4]
            pattern = text[0:idx-1]
            if type == "Hex":
                pattern = self.toHex(pattern)
        return pattern


    def selectedItems(self):
        selected = {}
        rowCount = self.patterns.rowCount()
        for row in range(0, rowCount):
            filetype = str(self.patterns.item(row, 0).text())
            selected[filetype] = []
            pattern = []
            pattern.append(self.textToPattern(str(self.patterns.item(row, 1).text())))
            pattern.append(self.textToPattern(str(self.patterns.item(row, 2).text())))
            pattern.append(int(self.patterns.item(row, 3).text().replace(" bytes", "")))
            selected[filetype].append([pattern])
            if self.patterns.item(row, 4).text() == "True":
                selected[filetype].append(True)
            else:
                selected[filetype].append(False)
        return selected
Пример #36
0
class PvTunerDlg(QDialog):
    COL = 6
    COL_ELEMENT  = 0
    COL_FIELD    = 1
    COL_PV       = 2
    COL_STEPSIZE = 3
    COL_READBACK = 4
    COL_SETPOINT = 5
    FMT_READBACK = "%.4e"
    def __init__(self, parent=None):  
        super(PvTunerDlg, self).__init__(parent)

        self.setAttribute(Qt.WA_DeleteOnClose)

        #self.inputBox = QLineEdit("PL2G2C01A.x")
        #self.inputBox = QLineEdit("CXH2G6C01B.x")
        self.inputBox = QLineEdit("PL2G2C01A")

        addPvBtn = QPushButton("add")

        self.table = QTableWidget(0, PvTunerDlg.COL)
        self.table.setHorizontalHeaderLabels(["Element", "Field", "PV",
                 "Stepsize", "Readback", "setpoint"])
        #self.table.horizontalHeader().setStretchLastSection(True)
        #self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok)

        box = QGridLayout()
        box.addWidget(self.inputBox, 0, 0)
        box.addWidget(addPvBtn, 0, 1)
        box.addWidget(self.table, 1, 0, 1, 2)
        box.addWidget(buttonBox, 2, 0)

        self.setLayout(box)

        self.pvs_rb = []
        self.pvs_rb_val_flat = []
        self.pvs_sp = []
        self.pvmoni = []
        self.spinbox = []
        self.connect(addPvBtn, SIGNAL("clicked()"), self.addPv)
        self.connect(buttonBox, SIGNAL("accepted()"), self.accept)
        #self.connect(self.table, SIGNAL("cellChanged"), self.updatePv)
        self.connect(buttonBox.button(QDialogButtonBox.Ok),
                     SIGNAL("clicked()"), self.close)
        self.connect(self.table, SIGNAL("cellClicked(int, int)"),
                     self._cell_clicked)


    def _cell_clicked(self, row, column):
        #print row, column
        if column in [self.COL_PV, self.COL_STEPSIZE]:
            item = self.table.item(row, column)
            if not item: return
            item.setFlags(item.flags() | Qt.ItemIsEditable)

    def _appendRecord(self, name):
        vec = name.split('.')
        if len(vec) > 2:
            QMessageBox.critical(None, "ERROR", "format is wrong")
            return

        if len(vec) == 1:
            elem, field = vec[0], 'value'
        elif len(vec) == 2:
            elem, field = vec

        elemobj = hla.getElements(elem)
        if elemobj:
            # pvsrb is a list
            pvsrb = elemobj.pv(field=field, handle='readback')
            self.pvs_rb.append(pvsrb)
            pvssp = elemobj.pv(field=field, handle='setpoint')
            self.pvs_sp.append(pvssp)
        else:
            QMessageBox.critical(None, "ERROR", "element %s not found" % elem)
            return

        # expand one row
        m, n = self.table.rowCount(), self.table.columnCount()
        self.table.insertRow(m)

        # add cells
        item = QTableWidgetItem(elem)
        item.setFlags(item.flags() & (~Qt.ItemIsEditable))
        self.table.setItem(m, self.COL_ELEMENT, item)
        
        item = QTableWidgetItem(field)
        item.setFlags(item.flags() & (~Qt.ItemIsEditable))
        self.table.setItem(m, self.COL_FIELD, item)

        
        item = QTableWidgetItem(', '.join(pvsrb))
        #item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled)
        self.table.setItem(m, self.COL_PV, item)

        readval = ['%.4e' % v for v in caget(pvsrb)]
        item = QTableWidgetItem(', '.join(readval))
        item.setFlags(item.flags() & (~Qt.ItemIsEditable))
        self.table.setItem(m, self.COL_READBACK, item)

        # set the stepsize of PV
        stepsize = 0.00001
        if pvssp:
            item = QTableWidgetItem('%f' % stepsize)
            item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            self.table.setItem(m, self.COL_STEPSIZE, item)

            self.spinbox.append(QDoubleSpinBox(self.table))
            self.spinbox[-1].setRange(-100, 100)
            #self.spinbox[-1].setValue(float(10.0))
            self.spinbox[-1].setSingleStep(stepsize)
            self.spinbox[-1].setDecimals(10)
            
            self.spinbox[-1].valueChanged.connect(self._writePv)
            
            self.table.setCellWidget(m, self.COL_SETPOINT, self.spinbox[-1])

            sp = float(caget(pvssp)[0])
            #print "setpoint:", pvssp, sp, type(sp)
            self.spinbox[-1].setValue(-1e-5)
            #print "connected", self.spinbox[-1].value()
        else:
            item = self.table.item(m, self.COL_STEPSIZE)
            if item: item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            item = self.table.item(m, self.COL_SETPOINT)
            if item: item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            self.spinbox.append(None)

        self.table.resizeColumnsToContents()

        
    def addPv(self):
        self._appendRecord(str(self.inputBox.text()))
        self._updateMonitors()

    def minimalSizeHint(self):
        return QSize(800, 600)


    def _writePv(self, v):
        """
        """
        c = QObject.sender(self)
        i = self.spinbox.index(c)
        #print i, c.text(), "changed"

        #print self.pvs_sp[i], v
        caput(self.pvs_sp[i], v)

    def _updateMonitors(self):
        """
        prepare the PV list for camonitor
        """
        #print "Updating monitors"
        pvs = []
        self.pvs_rb_val = []
        for i in range(self.table.rowCount()):
            for j in range(len(self.pvs_rb[i])):
                self.pvs_rb_val.append([i, 0.0])
            pvs.extend(self.pvs_rb[i])
        
        for p in self.pvmoni: p.close()
        self.pvmoni = camonitor(pvs, self._updatePvValues)
        #print self.pvmoni
        #print pvs
        #print self.pvs_rb_val


    def _updatePvValues(self, val, idx):
        #print idx, val
        s = []
        for i, v in enumerate(self.pvs_rb_val):
            if v[0] == self.pvs_rb_val[idx][0]:
                s.append(self.FMT_READBACK % val)
        #print s
        item = self.table.item(self.pvs_rb_val[idx][0], self.COL_READBACK)
        item.setText(','.join(s))

    def closePvMonitors(self):
        #print "Closing PV Monitors"
        for p in self.pvmoni: p.close()

        pass

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

    def close(self):
        self.closePvMonitors()
        return True
Пример #37
0
class phonesDialog(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.prm = self.parent().prm
        self.currLocale = self.parent().prm['currentLocale']
        self.currLocale.setNumberOptions(
            self.currLocale.OmitGroupSeparator
            | self.currLocale.RejectGroupSeparator)
        screen = QDesktopWidget().screenGeometry()
        self.resize(screen.width() / 2.5, screen.height() / 3)
        self.isPlaying = False
        #self.audioManager = audioManager(self)
        #self.playThread = threadedPlayer(self)

        self.sizer = QGridLayout()
        self.v1Sizer = QVBoxLayout()
        self.v2Sizer = QVBoxLayout()
        self.calibSizer = QGridLayout()

        self.phonesTableWidget = QTableWidget()
        self.phonesTableWidget.setColumnCount(4)
        self.phonesTableWidget.setSelectionBehavior(
            QAbstractItemView.SelectRows)
        self.phonesTableWidget.setSelectionMode(
            QAbstractItemView.ExtendedSelection)

        self.phonesTableWidget.setHorizontalHeaderLabels([
            self.tr('Phones'),
            self.tr('Max Level'),
            self.tr('Default'), 'id'
        ])
        self.phonesTableWidget.hideColumn(3)
        self.phonesTableWidget.cellDoubleClicked[int, int].connect(
            self.onCellDoubleClicked)

        #RENAME Phones BUTTON
        self.renamePhonesButton = QPushButton(self.tr("Rename Phones"), self)
        self.renamePhonesButton.clicked.connect(self.onEditLabel)
        #Change Level Phones BUTTON
        self.changeLevelPhonesButton = QPushButton(self.tr("Change Max Level"),
                                                   self)
        self.changeLevelPhonesButton.clicked.connect(self.onEditMaxLevel)

        #ADD Phones BUTTON
        self.addPhonesButton = QPushButton(self.tr("Add Phones"), self)
        self.addPhonesButton.clicked.connect(self.onClickAddPhonesButton)
        #REMOVE Phones BUTTON
        self.removePhonesButton = QPushButton(self.tr("Remove Phones"), self)
        self.removePhonesButton.clicked.connect(self.onClickRemovePhonesButton)
        #Set Default Phones BUTTON
        self.setDefaultPhonesButton = QPushButton(self.tr("Set Default"), self)
        self.setDefaultPhonesButton.clicked.connect(self.onEditDefault)

        self.v1Sizer.addWidget(self.renamePhonesButton)
        self.v1Sizer.addWidget(self.changeLevelPhonesButton)
        self.v1Sizer.addWidget(self.addPhonesButton)
        self.v1Sizer.addWidget(self.removePhonesButton)
        self.v1Sizer.addWidget(self.setDefaultPhonesButton)
        self.v1Sizer.addStretch()
        self.phonesList = {}

        for i in range(len(self.prm['phones']['phonesChoices'])):
            currCount = i + 1
            thisID = self.prm['phones']['phonesID'][i]
            self.phonesList[thisID] = {}
            self.phonesList[thisID]['label'] = self.prm['phones'][
                'phonesChoices'][i]
            self.phonesList[thisID]['maxLevel'] = self.prm['phones'][
                'phonesMaxLevel'][i]
            self.phonesList[thisID]['default'] = self.prm['phones'][
                'defaultPhones'][i]
            self.phonesTableWidget.setRowCount(currCount)
            newItem = QTableWidgetItem(self.phonesList[thisID]['label'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.phonesTableWidget.setItem(currCount - 1, 0, newItem)
            newItem = QTableWidgetItem(
                self.currLocale.toString(self.phonesList[thisID]['maxLevel']))
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.phonesTableWidget.setItem(currCount - 1, 1, newItem)
            newItem = QTableWidgetItem(self.phonesList[thisID]['default'])
            newItem.setFlags(QtCore.Qt.ItemIsSelectable
                             | QtCore.Qt.ItemIsEnabled)
            self.phonesTableWidget.setItem(currCount - 1, 2, newItem)
            self.phonesList[thisID]['qid'] = QTableWidgetItem(thisID)
            self.phonesTableWidget.setItem(currCount - 1, 3,
                                           self.phonesList[thisID]['qid'])

        ##CALIBRATION TONE
        n = 0
        self.calLabel = QLabel(self.tr('Calibration Tone:'), self)
        self.calibSizer.addWidget(self.calLabel, n, 0, 1, 2)
        n = n + 1
        self.toneFreqLabel = QLabel(self.tr('Frequency (Hz)'), self)
        self.toneFreqTF = QLineEdit("1000")
        self.toneFreqTF.setValidator(QDoubleValidator(self))
        self.calibSizer.addWidget(self.toneFreqLabel, n, 0)
        self.calibSizer.addWidget(self.toneFreqTF, n, 1)
        n = n + 1
        self.toneLevLabel = QLabel(self.tr('Level (dB)'), self)
        self.toneLevTF = QLineEdit("60")
        self.toneLevTF.setValidator(QDoubleValidator(self))
        self.calibSizer.addWidget(self.toneLevLabel, n, 0)
        self.calibSizer.addWidget(self.toneLevTF, n, 1)
        n = n + 1
        self.toneDurLabel = QLabel(self.tr('Duration (ms)'), self)
        self.toneDurTF = QLineEdit("980")
        self.toneDurTF.setValidator(QDoubleValidator(self))
        self.calibSizer.addWidget(self.toneDurLabel, n, 0)
        self.calibSizer.addWidget(self.toneDurTF, n, 1)
        n = n + 1
        self.toneRampsLabel = QLabel(self.tr('Ramps (ms)'), self)
        self.toneRampsTF = QLineEdit("10")
        self.toneRampsTF.setValidator(QDoubleValidator(self))
        self.calibSizer.addWidget(self.toneRampsLabel, n, 0)
        self.calibSizer.addWidget(self.toneRampsTF, n, 1)
        n = n + 1
        self.earLabel = QLabel(self.tr('Ear:'), self)
        self.earChooser = QComboBox()
        self.earChooser.addItems(
            [self.tr("Right"),
             self.tr("Left"),
             self.tr("Both")])
        self.calibSizer.addWidget(self.earLabel, n, 0)
        self.calibSizer.addWidget(self.earChooser, n, 1)
        n = n + 1
        self.playCalibButton = QPushButton(self.tr("Play"), self)
        self.playCalibButton.clicked.connect(self.onClickPlayCalibButton)
        self.playCalibButton.setIcon(
            QIcon.fromTheme("media-playback-start",
                            QIcon(":/media-playback-start")))
        self.calibSizer.addWidget(self.playCalibButton, n, 0, 1, 2)
        n = n + 1
        self.stopCalibButton = QPushButton(self.tr("Stop"), self)
        self.stopCalibButton.clicked.connect(self.onClickStopCalibButton)
        self.stopCalibButton.setIcon(
            QIcon.fromTheme("media-playback-stop",
                            QIcon(":/media-playback-stop")))
        self.calibSizer.addWidget(self.stopCalibButton, n, 0, 1, 2)
        if self.prm['pref']['sound']['playCommand'] in [
                "alsaaudio", "pyaudio"
        ]:
            self.stopCalibButton.show()
        else:
            self.stopCalibButton.hide()

        buttonBox = QDialogButtonBox(QDialogButtonBox.Apply
                                     | QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)
        buttonBox.button(QDialogButtonBox.Apply).clicked.connect(
            self.permanentApply)

        self.sizer.addLayout(self.v1Sizer, 0, 0)
        self.v2Sizer.addLayout(self.calibSizer)
        self.v2Sizer.addStretch()
        self.sizer.addWidget(self.phonesTableWidget, 0, 1)
        self.sizer.addLayout(self.v2Sizer, 0, 2)
        self.sizer.addWidget(buttonBox, 1, 1, 1, 2)
        self.sizer.setColumnStretch(1, 2)
        self.setLayout(self.sizer)
        self.setWindowTitle(self.tr("Edit Phones"))
        self.show()

    def onCellDoubleClicked(self, row, col):
        if col == 0:
            self.onEditLabel()
        elif col == 1:
            self.onEditMaxLevel()
        elif col == 2:
            self.onEditDefault()

    def onEditLabel(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Only one label can be renamed at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            msg = self.tr('New name:')
            text, ok = QInputDialog.getText(self, self.tr('Input Dialog'), msg)
            if ok:
                self.phonesTableWidget.item(
                    self.phonesList[selectedSound]['qid'].row(),
                    0).setText(text)
                self.phonesList[selectedSound]['label'] = text

    def onEditMaxLevel(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            msg = self.tr('Level:')
            text, ok = QInputDialog.getDouble(
                self, self.tr('Input Dialog'), msg,
                self.phonesList[selectedSound]['maxLevel'])
            if ok:
                self.phonesTableWidget.item(
                    self.phonesList[selectedSound]['qid'].row(),
                    1).setText(self.currLocale.toString(text))
                self.phonesList[selectedSound]['maxLevel'] = text

    def onEditDefault(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Only one item can be edited at a time'))
        elif len(ids) < 1:
            pass
        else:
            selectedSound = ids[0]
            for i in range(self.phonesTableWidget.rowCount()):
                self.phonesTableWidget.item(i, 2).setText("\u2012")
                self.phonesList[str(self.phonesTableWidget.item(
                    i, 3).text())]['default'] = "\u2012"
            self.phonesTableWidget.item(
                self.phonesList[selectedSound]['qid'].row(),
                2).setText("\u2713")
            self.phonesList[selectedSound]['default'] = "\u2713"

    def findSelectedItemIds(self):
        selItems = self.phonesTableWidget.selectedItems()
        selItemsRows = []
        for i in range(len(selItems)):
            selItemsRows.append(selItems[i].row())
        selItemsRows = unique(selItemsRows)
        selItemsIds = []
        for i in range(len(selItemsRows)):
            selItemsIds.append(
                str(self.phonesTableWidget.item(selItemsRows[i], 3).text()))
        return selItemsIds

    def permanentApply(self):
        self.prm['phones']['phonesChoices'] = []
        self.prm['phones']['phonesMaxLevel'] = []
        self.prm['phones']['defaultPhones'] = []
        self.prm['phones']['phonesID'] = []

        keys = sorted(self.phonesList.keys())
        for key in keys:
            self.prm['phones']['phonesChoices'].append(
                str(self.phonesList[key]['label']))
            self.prm['phones']['phonesMaxLevel'].append(
                self.phonesList[key]['maxLevel'])
            self.prm['phones']['defaultPhones'].append(
                self.phonesList[key]['default'])
            self.prm['phones']['phonesID'].append(key)
        f = open(self.parent().prm['phonesPrefFile'], 'wb')
        pickle.dump(self.parent().prm['phones'], f)
        f.close()
        for i in range(self.parent().phonesChooser.count()):
            self.parent().phonesChooser.removeItem(0)
        self.parent().phonesChooser.addItems(
            self.prm['phones']['phonesChoices'])

    def onClickAddPhonesButton(self):
        keys = sorted(self.phonesList.keys())
        thisID = str(int(keys[-1]) + 1)
        currCount = self.phonesTableWidget.rowCount() + 1

        self.phonesList[thisID] = {}
        self.phonesList[thisID]['label'] = 'Phones' + ' ' + str(currCount)
        self.phonesList[thisID]['maxLevel'] = 100
        self.phonesList[thisID]['default'] = "\u2012"
        self.phonesTableWidget.setRowCount(currCount)
        newItem = QTableWidgetItem(self.phonesList[thisID]['label'])
        newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        self.phonesTableWidget.setItem(currCount - 1, 0, newItem)
        newItem = QTableWidgetItem(
            self.currLocale.toString(self.phonesList[thisID]['maxLevel']))
        newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        self.phonesTableWidget.setItem(currCount - 1, 1, newItem)
        newItem = QTableWidgetItem(self.phonesList[thisID]['default'])
        newItem.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
        self.phonesTableWidget.setItem(currCount - 1, 2, newItem)
        self.phonesList[thisID]['qid'] = QTableWidgetItem(thisID)
        self.phonesTableWidget.setItem(currCount - 1, 3,
                                       self.phonesList[thisID]['qid'])

    def onClickRemovePhonesButton(self):
        if self.phonesTableWidget.rowCount() == 1:
            ret = QMessageBox.warning(
                self, self.tr("Warning"),
                self.tr("Only one phone left. Cannot remove!"), QMessageBox.Ok)
        else:
            ids = self.findSelectedItemIds()
            wasDefault = False
            for i in range(len(ids)):
                selectedPhones = ids[i]
                if self.phonesTableWidget.item(
                        self.phonesList[selectedPhones]['qid'].row(),
                        2).text() == "\u2713":
                    wasDefault = True
                self.phonesTableWidget.removeRow(
                    self.phonesList[selectedPhones]['qid'].row())
                del self.phonesList[selectedPhones]
            if wasDefault == True:
                self.phonesTableWidget.item(0, 2).setText("\u2713")
                self.phonesList[str(self.phonesTableWidget.item(
                    0, 3).text())]['default'] = "\u2713"

    def onClickPlayCalibButton(self):
        ids = self.findSelectedItemIds()
        if len(ids) > 1:
            QMessageBox.warning(
                self, self.tr('Warning'),
                self.tr('Only one label can be renamed at a time'))
            return
        elif len(ids) < 1:
            QMessageBox.warning(self, self.tr('Warning'),
                                self.tr('Please, select a phone in the table'))
            return
        else:
            selectedSound = ids[0]
            calMaxLev = self.phonesList[selectedSound]['maxLevel']
            frequency = self.currLocale.toDouble(self.toneFreqTF.text())[0]
            level = self.currLocale.toDouble(self.toneLevTF.text())[0]
            duration = self.currLocale.toDouble(self.toneDurTF.text())[0]
            ramp = self.currLocale.toDouble(self.toneRampsTF.text())[0]
            channel = self.earChooser.currentText()
            fs = self.currLocale.toInt(self.parent().sampRateTF.text())[0]
            nBits = self.currLocale.toInt(
                self.parent().nBitsChooser.currentText())[0]
            calTone = pureTone(frequency, 0, level, duration, ramp, channel,
                               fs, calMaxLev)
            self.isPlaying = True
            if self.prm['pref']['sound']['playCommand'] in [
                    "alsaaudio", "pyaudio"
            ]:
                self.playThread = threadedAudioPlayer(self.parent())
            else:
                self.playThread = threadedExternalAudioPlayer(self.parent())
            self.playThread.playThreadedSound(
                calTone, fs, nBits, self.prm['pref']['sound']['playCommand'],
                True, 'calibrationTone.wav')
            if self.playThread.isFinished() == True:
                self.isPlaying = False

    def onClickStopCalibButton(self):
        if self.isPlaying == True:
            self.playThread.terminate()
            #self.playThread.__del__()

    def closeEvent(self, event):
        if self.isPlaying == True:
            #self.playThread.__del__()
            self.playThread.terminate()
        event.accept()

    def accept(self):  #reimplement accept (i.e. ok button)
        if self.isPlaying == True:
            #self.playThread.__del__()
            self.playThread.terminate()
        QDialog.accept(self)

    def reject(self):  #reimplement reject
        if self.isPlaying == True:
            #self.playThread.__del__()
            self.playThread.terminate()
        QDialog.reject(self)
Пример #38
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)
Пример #39
0
class PatternsTable(QWidget):
    def __init__(self):
        QWidget.__init__(self)
        self.grid = QGridLayout()
        self.setLayout(self.grid)
        self.patternArea()
        self.patternTable()

    def createPattern(self, name, x):
        label = name.lower() + "Label"
        type = name.lower() + "Type"
        entry = name.lower() + "Entry"
        setattr(self, label, QLabel(name))
        setattr(self, entry, QLineEdit())
        setattr(self, type, QComboBox())
        labelobj = getattr(self, label)
        typeobj = getattr(self, type)
        entryobj = getattr(self, entry)
        typeobj.addItem("Hexadecimal")
        typeobj.addItem("String")
        self.grid.addWidget(labelobj, x, 0)
        self.grid.addWidget(entryobj, x, 1)
        self.grid.addWidget(typeobj, x, 2)


    def patternArea(self):
        self.filetypeLabel = QLabel("File type")
        self.filetype = QLineEdit()
        self.alignedLabel = QLabel("block aligned")
        self.aligned = QCheckBox()
        self.windowLabel = QLabel("Window size")
        self.window = QSpinBox()
        self.window.setSuffix(" bytes")
        self.window.setRange(0, 2500000)
        self.window.setSingleStep(100)
        self.addEntry = QPushButton("add")
        self.connect(self.addEntry, SIGNAL("clicked()"), self.insertPattern)
        self.grid.addWidget(self.filetypeLabel, 0, 0)
        self.grid.addWidget(self.filetype, 0, 1, 1, 2)
        self.createPattern("Header", 2)
        self.createPattern("Footer", 3)
        self.grid.addWidget(self.windowLabel, 4, 0)
        self.grid.addWidget(self.window, 4, 1)
        self.grid.addWidget(self.alignedLabel, 5, 0)
        self.grid.addWidget(self.aligned, 5, 1)
        self.grid.addWidget(self.addEntry, 6, 1)


    def patternTable(self):
        self.patterns = QTableWidget()
        self.patterns.setShowGrid(False)
        self.patterns.setColumnCount(5)
        self.patterns.setHorizontalHeaderLabels(["Filetype", "Header", "Footer", "Window", "Block aligned"])
        self.patterns.horizontalHeader().setStretchLastSection(True)
        self.connect(self.patterns.verticalHeader(), SIGNAL("sectionClicked(int)"), self.patterns.removeRow)
        self.grid.addWidget(self.patterns, 7, 0, 1, 3)
        

    def warning(self, msg):
        msgBox = QMessageBox(self)
        msgBox.setText(msg)
        msgBox.setIcon(QMessageBox.Warning)
        msgBox.exec_()

    def validate(self, **kwargs):
        msg = ""

        if len(kwargs["type"]) == 0:
            msg = "Type must be defined"
        else:
            for i in kwargs["type"]:
                if i not in string.letters:
                    msg = "Type's characters must be in the following set\n\n" + string.letters
                    break
            rowCount = self.patterns.rowCount()
            for row in range(0, rowCount):
                if str(self.patterns.item(row, 0).text()) == kwargs["type"]:
                    msg = "Type <" + kwargs["type"] + " > already defined"
        if msg != "":
            self.warning(msg)
            return False

        if kwargs["headerType"] == "Hexadecimal" and not self.isHex(kwargs["header"]):
            msg = "Header must be an even number of chars"
            self.warning(msg)
            return False
        
        if len(kwargs["header"]) == 0:
            msg = "Header must be provided"
            self.warning(msg)
            return False

        if kwargs["footerType"] == "Hexadecimal" and not self.isHex(kwargs["footer"]):
            msg = "Footer must be an even number of chars"
            self.warning(msg)
            return False

        if kwargs["window"] <= 0:
            msg = "Window size must be greater than 0"
            self.warning(msg)
            return False

        return True


    def insertPattern(self):
        filetype = str(self.filetype.text())
        header = str(self.headerEntry.text())
        headerType = str(self.headerType.currentText())
        footer = str(self.footerEntry.text())
        footerType = str(self.footerType.currentText())
        window = self.window.text()
        aligned = self.aligned.isChecked()

        #Validate most of provided items
        kwargs = {"type": filetype, "header": header, "headerType": headerType, 
                  "footer": footer, "footerType": footerType, "window": int(window.replace(" bytes", ""))}
        if not self.validate(**kwargs):
            return

        filetypeItem = QTableWidgetItem(filetype)
        headerItem = QTableWidgetItem(header + " (" + headerType[0:3] + ")")
        footerItem = QTableWidgetItem(footer + " (" + footerType[0:3] + ")")
        windowItem = QTableWidgetItem(window)
        alignedItem = QTableWidgetItem(str(aligned))
        self.patterns.insertRow(self.patterns.rowCount())
        vertHeader = QTableWidgetItem(QIcon(":closetab.png"), "")
        row = self.patterns.rowCount() - 1
        self.patterns.setVerticalHeaderItem(row, vertHeader)
        self.patterns.setItem(row, 0, filetypeItem)
        self.patterns.setItem(row, 1, headerItem)
        self.patterns.setItem(row, 2, footerItem)
        self.patterns.setItem(row, 3, windowItem)
        self.patterns.setItem(row, 4, alignedItem)
        self.patterns.resizeRowToContents(row)

        
    def isHex(self, hstr):
        HEXCHAR = "0123456789abcdefABCDEF"
        if len(hstr) % 2 != 0:
            return False
        even = False
        for i in range(len(hstr)):
            if hstr[i] not in HEXCHAR:
                return False
        return True
    

    def toHex(self, str):
        HEXCHAR = "0123456789abcdefABCDEF"
        hexStr = ""
        evenhex = ""
        for i in range(len(str)):
            if str[i] in HEXCHAR:
                if len(evenhex) == 1:
                    hexStr += chr(int(evenhex+str[i], 16))
                    evenhex = ""
                else:
                    evenhex = str[i]
            else:
                raise ValueError, "argument 'str' contains not valid characters"
        if len(evenhex) != 0:
            raise ValueError, "argument 'str' must be an even number of char"
        return hexStr


    def textToPattern(self, text):
        idx = text.find("(")
        pattern = ""
        if idx != -1:
            type = text[idx+1:idx+4]
            pattern = text[0:idx-1]
            if type == "Hex":
                pattern = self.toHex(pattern)
        return pattern


    def selectedItems(self):
        selected = {}
        rowCount = self.patterns.rowCount()
        for row in range(0, rowCount):
            filetype = str(self.patterns.item(row, 0).text())
            selected[filetype] = []
            pattern = []
            pattern.append(self.textToPattern(str(self.patterns.item(row, 1).text())))
            pattern.append(self.textToPattern(str(self.patterns.item(row, 2).text())))
            pattern.append(int(self.patterns.item(row, 3).text().replace(" bytes", "")))
            selected[filetype].append([pattern])
            if self.patterns.item(row, 4).text() == "True":
                selected[filetype].append(True)
            else:
                selected[filetype].append(False)
        return selected
Пример #40
0
class ActionEditorDialog(QWidget):

    # Redefine the tr() function for this class.
    def tr(self, text):
    
        return qApp.translate("ActionEditorDialog", text)

    def __init__(self, actions, parent=None):
    
        super(ActionEditorDialog, self).__init__(parent)
        self.actions = actions

        help = QLabel(translate("Shortcut Settings", '<b>Double click a cell in the Shortcut Column' \
            ' to <br />modify the key sequence.</b>'))
        
        self.actionTable = QTableWidget(self)
        self.actionTable.setSelectionBehavior(QTableWidget.SelectRows)
        self.actionTable.setEditTriggers(QTableWidget.DoubleClicked)
        self.actionTable.setColumnCount(2)
        self.actionTable.setHorizontalHeaderLabels(
            [translate("Shortcut Settings", "Description"),
            translate("Shortcut Settings", "Shortcut")]
            )
        self.actionTable.horizontalHeader().setStretchLastSection(True)
        self.actionTable.verticalHeader().hide()
        self.actionTable.setItemDelegate(ActionEditorDelegate(self))
        
        self.connect(self.actionTable, SIGNAL("cellChanged(int, int)"),
                     self.validateAction)
        
        row = 0
        for action in self.actions:
        
            if action.text().isEmpty():
                continue
            
            self.actionTable.insertRow(self.actionTable.rowCount())
            
            item = QTableWidgetItem()
            item.setText(action.text())
            item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
            self.actionTable.setItem(row, 0, item)
            
            item = QTableWidgetItem()
            item.setText(action.shortcut().toString())
            item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsEditable | Qt.ItemIsSelectable)
            item.oldShortcutText = item.text()
            self.actionTable.setItem(row, 1, item)
            
            row += 1
        
        self.actionTable.resizeColumnsToContents()
                
        mainLayout = QVBoxLayout()
        mainLayout.addWidget(help)
        mainLayout.setMargin(8)
        mainLayout.setSpacing(8)
        mainLayout.addWidget(self.actionTable)
        self.setLayout(mainLayout)
        self._model = self.actionTable.model()
        self._model.edited = False
        self.actionTable.model().edited = False
        
        self.setWindowTitle(translate("Shortcut Settings", "Edit Shortcuts"))
    
    def applySettings(self, control=None):
        if not self._model.edited:
            return
    
        row = 0
        for action in self.actions:
        
            if not action.text().isEmpty():
                action.setText(self.actionTable.item(row, 0).text())
                action.setShortcut(QKeySequence(self.actionTable.item(row, 1).text()))
                row += 1
        self.saveSettings(self.actions)
        self._model.edited = False
    
    def _loadSettings(self, actions):
        
        cparser = PuddleConfig(os.path.join(CONFIGDIR, 'user_shortcuts'))

        for action in actions:
            shortcut = cparser.get('shortcuts', unicode(action.text()), '')
            if shortcut:
                action.setShortcut(QKeySequence(shortcut))
    
    _loadSettings = classmethod(_loadSettings)
    
    def saveSettings(self, actions):
        
        cparser = PuddleConfig(os.path.join(CONFIGDIR, 'user_shortcuts'))
        for action in actions:
            shortcut = unicode(action.shortcut().toString())
            cparser.set('shortcuts', unicode(action.text()), shortcut)
    
    saveSettings = classmethod(saveSettings)
    
    def validateAction(self, row, column):
    
        if column != 1:
            return
        
        item = self.actionTable.item(row, column)
        shortcutText = QKeySequence(item.text()).toString()
        thisRow = self.actionTable.row(item)
        
        if not shortcutText.isEmpty():
            for row in range(self.actionTable.rowCount()):
                if row == thisRow:
                    continue
                
                other = self.actionTable.item(row, 1)
                
                if other.text() == shortcutText:
                    other.setText(item.oldShortcutText)
                    break
            
            item.setText(shortcutText)
            item.oldShortcutText = shortcutText
        
        self.actionTable.resizeColumnToContents(1)
Пример #41
0
class CameraWindow(PyDialog):
    def __init__(self, data, win_parent=None):
        """
        +--------+
        | Camera |
        +--------+---------------+
        |  Camera Name           |
        |  +-------------------+ |
        |  |                   | |
        |  |                   | |
        |  |                   | |
        |  |                   | |
        |  |                   | |
        |  +-------------------+ |
        |                        |
        | Name xxx       Save    |
        | Delete   Set           |
        |                        |
        |    Apply   OK  Cancel  |
        +--------+---------------+
        """
        PyDialog.__init__(self, data, win_parent)
        self.setWindowTitle('Camera Views')
        #self.setWindowIcon(view_icon)

        self._default_name = 'Camera'
        self.out_data['clicked_ok'] = False

        self.cameras = deepcopy(data['cameras'])
        self.names = sorted(self.cameras.keys())

        self.name = QLabel("Name:")
        self.name_edit = QLineEdit(str(self._default_name))

        self.delete_button = QPushButton("Delete")
        self.set_button = QPushButton("Set")
        self.save_button = QPushButton("Save")

        # closing
        self.apply_button = QPushButton("Apply")
        #self.ok_button = QPushButton("OK")
        self.close_button = QPushButton("Close")
        self.cancel_button = QPushButton("Cancel")

        self.table = QTableWidget()
        names_text = []
        for iname, name in enumerate(self.names):
            name_text = QTableWidgetItem(str(name))
            names_text.append(name_text)
        self.create_layout(names_text)
        self.set_connections()

    def create_layout(self, names_text):
        nrows = len(self.names)
        table = self.table
        table.setRowCount(nrows)
        table.setColumnCount(1)
        headers = [QString('Camera Name')]
        table.setHorizontalHeaderLabels(headers)

        header = table.horizontalHeader()
        header.setStretchLastSection(True)

        for iname, name_text in enumerate(names_text):
            # row, col, value
            table.setItem(iname, 0, name_text)
        table.resizeRowsToContents()

        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.apply_button)
        #ok_cancel_box.addWidget(self.ok_button)
        ok_cancel_box.addWidget(self.close_button)
        ok_cancel_box.addWidget(self.cancel_button)

        grid = QGridLayout()

        irow = 0
        grid.addWidget(self.name, irow, 0)
        grid.addWidget(self.name_edit, irow, 1)
        grid.addWidget(self.save_button, irow, 2)
        irow += 1

        grid.addWidget(self.delete_button, irow, 0)
        grid.addWidget(self.set_button, irow, 1)
        irow += 1

        vbox = QVBoxLayout()
        vbox.addWidget(self.table)

        vbox.addLayout(grid)
        vbox.addStretch()
        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def set_connections(self):
        #if qt_version == 4:
        #self.connect(self.ok_button, QtCore.SIGNAL('clicked()'), self.on_ok)
        self.set_button.clicked.connect(self.on_set)
        self.save_button.clicked.connect(self.on_save)
        self.delete_button.clicked.connect(self.on_delete)
        self.apply_button.clicked.connect(self.on_apply)
        self.close_button.clicked.connect(self.on_close)
        self.cancel_button.clicked.connect(self.on_cancel)

    def on_set(self):
        objs = self.table.selectedIndexes()
        if len(objs) == 1:
            obj = objs[0]
            irow = obj.row()
            name = self.names[irow]
            self.set_camera(name)
            return True
        return False

    def on_save(self):
        name = str(self.name_edit.text()).strip()
        if name in self.cameras:
            return
        irow = self.nrows
        if len(name):
            self.table.insertRow(irow)
            name_text = QTableWidgetItem(str(name))
            self.table.setItem(irow, 0, name_text)
            self.name_edit.setText('')
            self.save_camera(name)

    def set_camera(self, name):
        camera_data = self.cameras[name]
        if self.win_parent is None:
            return
        self.win_parent.on_set_camera_data(camera_data)

    def save_camera(self, name):
        self.names.append(name)
        if self.win_parent is None:
            self.cameras[name] = None
            return

        self.cameras[name] = self.win_parent.get_camera_data()

    #@property
    #def camera(self):

    @property
    def nrows(self):
        return self.table.rowCount()

    def on_delete(self):
        irows = []
        for obj in self.table.selectedIndexes():
            irow = obj.row()
            irows.append(irow)
        irows.sort()

        for irow in reversed(irows):
            self.table.removeRow(irow)
            #print('delete', self.names)
            name = self.names.pop(irow)
            del self.cameras[name]
            #print('  removing irow=%s name=%r' % (irow, name))

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

    @staticmethod
    def check_name(cell):
        text = str(cell.text()).strip()
        if len(text):
            cell.setStyleSheet("QLineEdit{background: white;}")
            return text, True
        else:
            cell.setStyleSheet("QLineEdit{background: red;}")
            return None, False

    #def on_validate(self):
    #name_value, flag0 = self.check_name(self.name_edit)
    #if flag0:
    #self.out_data['cameras'] = self.cameras
    #self.out_data['clicked_ok'] = True
    #return True
    #return False

    def on_apply(self):
        passed = self.on_set()
        #if passed:
        #    self.win_parent.create_plane(self.out_data)
        return passed

    def on_close(self):
        self.out_data['clicked_ok'] = True
        self.out_data['cameras'] = self.cameras
        self.close()

    def on_ok(self):
        passed = self.on_apply()
        if passed:
            name = str(self.name_edit.text()).strip()
            self.out_data['name'] = name
            self.out_data['cameras'] = self.cameras
            self.out_data['clicked_ok'] = True
            self.close()
            #self.destroy()

    def on_cancel(self):
        self.close()
Пример #42
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)
Пример #43
0
class TableCatalogOTF(QObject):

    runCatalog = pyqtSignal(str)

    def __init__(self):
        def initGui():
            self.tableWidget.setWindowTitle("Catalog OTF")
            self.tableWidget.setSortingEnabled(False)
            msgtrans = QCoreApplication.translate("CatalogOTF", "Layer,Total")
            headers = msgtrans.split(',')
            self.tableWidget.setColumnCount(len(headers))
            self.tableWidget.setHorizontalHeaderLabels(headers)
            self.tableWidget.resizeColumnsToContents()

        super(TableCatalogOTF, self).__init__()
        self.tableWidget = QTableWidget()
        initGui()

    def _getRowLayerID(self, layerID):
        for row in range(self.tableWidget.rowCount()):
            if layerID == self.tableWidget.cellWidget(row, 0).objectName():
                return row
        return -1

    def _changedText(self, layerID, name, column):
        row = self._getRowLayerID(layerID)
        if row != -1:
            wgt = self.tableWidget.cellWidget(
                row, column) if column == 0 else self.tableWidget.item(
                    row, column)
            wgt.setText(name)
            wgt.setToolTip(name)
            self.tableWidget.resizeColumnsToContents()

    @pyqtSlot()
    def _onRunCatalog(self):
        btn = self.sender()
        icon = QIcon(joinPath(dirname(__file__), 'cancel_red.svg'))
        btn.setIcon(icon)
        layerID = btn.objectName()
        self.runCatalog.emit(layerID)

    @pyqtSlot()
    def _onSelectionChanged(self):
        layer = self.sender()
        row = self._getRowLayerID(layer.id())
        if row != -1:
            wgt = self.tableWidget.cellWidget(row, 0)
            nameIcon = 'check_green.svg' if layer.selectedFeatureCount(
            ) == 0 else 'check_yellow.svg'
            icon = QIcon(joinPath(dirname(__file__), nameIcon))
            wgt.setIcon(icon)

    @pyqtSlot("QgsVectorLayer")
    def insertRow(self, layer):
        row = self.tableWidget.rowCount()
        self.tableWidget.insertRow(row)

        column = 0  # Layer
        layerName = layer.name()
        nameIcon = 'check_green.svg' if layer.selectedFeatureCount(
        ) == 0 else 'check_yellow.svg'
        icon = QIcon(joinPath(dirname(__file__), nameIcon))
        btn = QPushButton(icon, layerName, self.tableWidget)
        btn.setObjectName(layer.id())
        btn.setToolTip(layerName)
        btn.clicked.connect(self._onRunCatalog)
        layer.selectionChanged.connect(self._onSelectionChanged)
        self.tableWidget.setCellWidget(row, column, btn)

        column = 1  # Total

        msgtrans = QCoreApplication.translate("CatalogOTF", "None")
        item = QTableWidgetItem(msgtrans)
        item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        self.tableWidget.setItem(row, column, item)

        self.tableWidget.resizeColumnsToContents()

    @pyqtSlot(str)
    def removeRow(self, layerID):
        row = self._getRowLayerID(layerID)
        if row != -1:
            self.tableWidget.removeRow(row)

    @pyqtSlot(str, str)
    def changedNameLayer(self, layerID, name):
        self._changedText(layerID, name, 0)

    @pyqtSlot(str, str)
    def changedTotal(self, layerID, value):
        self._changedText(layerID, value, 1)

    @pyqtSlot(str, bool)
    def changedIconRun(self, layerID, selected):
        row = self._getRowLayerID(layerID)
        if row != -1:
            btn = self.tableWidget.cellWidget(row, 0)
            nameIcon = 'check_green.svg' if not selected else 'check_yellow.svg'
            icon = QIcon(joinPath(dirname(__file__), nameIcon))
            btn.setIcon(icon)
            btn.setEnabled(True)

    @pyqtSlot(str)
    def killed(self, layerID):
        row = self._getRowLayerID(layerID)
        if row != -1:
            btn = self.tableWidget.cellWidget(row, 0)
            btn.setEnabled(False)

    def widget(self):
        return self.tableWidget
Пример #44
0
class Search(QDialog):

    def __init__(self, parent=None):
        super(Search, self).__init__(parent=parent)

        self.create_layout()
        self.create_connections()

    def create_layout(self):
        label = QLabel("Your query:")
        self.query_edit = QLineEdit()
        self.find_button = QPushButton("Search")
        self.get_button = QPushButton("Get selected books")

        self.table = QTableWidget()
        self.table.setColumnCount(3)
        self.table.setHorizontalHeaderLabels(['Select', 'Name', 'URL'])

        hbox = QHBoxLayout()
        hbox.addWidget(label)
        hbox.addWidget(self.query_edit)
        hbox.addWidget(self.find_button)

        vbox = QVBoxLayout()
        vbox.addLayout(hbox)
        vbox.addWidget(self.table)
        vbox.addWidget(self.get_button)

        self.setLayout(vbox)

    def create_connections(self):
        self.connect(self.find_button, SIGNAL('clicked()'), self.render_result)
        self.connect(self.get_button, SIGNAL('clicked()'), self.download)

    def render_result(self):
        query = self.query_edit.text()
        if not query:
            return

        self.feed = FeedBooks()
        response = self.feed.search(str(query))

        if not response:
            QMessageBox.critical(self, 'Error', 'Could not get any result')
            return

        self.table.clear()
        self.table.setHorizontalHeaderLabels(['Select', 'Title', 'URL'])
        self.table.setRowCount(len(response[1]))

        for i, name in enumerate(zip(response[1], response[3])):
            item = QTableWidgetItem(1)
            item.data(Qt.CheckStateRole)
            item.setCheckState(Qt.Checked)
            self.table.setItem(i, 0, item)

            for j in range(2):
                item = QTableWidgetItem(name[j])
                item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
                self.table.setItem(i, j+1, item)

        self.table.resizeColumnsToContents()

    def download(self):
        rows = self.table.rowCount()

        progress = QProgressDialog("Downloading books...", "Abort download", 0,
                                   rows, self)
        progress.setWindowModality(Qt.WindowModal)
        progress.show()

        to_download = [self.table.item(row, 2).text() for row in range(rows) if
                       self.table.item(row, 0).checkState() == Qt.Checked]

        for i, book in enumerate(to_download):
            progress.setValue(i)
            book_id = self.feed.download(str(book))
            if not book_id:
                QMessageBox.critical(self, 'Error', 'Could not download the '
                                     'book')
            elif book_id != -1:
                book = Book(book_id)
                insert_library(book)

            if progress.wasCanceled():
                break

        progress.setValue(rows)
        progress.close()
        self.parent().library.refresh()
Пример #45
0
class OrbitCorrGeneral(QtGui.QWidget):
    """
    A general orbit correction or local bump panel.
    """
    def __init__(self, bpms, cors, parent = None):
        super(OrbitCorrGeneral, self).__init__(parent)

        self.bpms, self.cors = bpms, cors
        self.sb = [bpm.sb for bpm in self.bpms]
        self.x0, self.y0 = None, None
        self._update_current_orbit()

        self.table = QTableWidget(len(self.bpms), 9)
        self.table.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        hdview = QHeaderView(Qt.Horizontal)
        self.table.setHorizontalHeaderLabels(
            ['BPM Name', 's', "Beta X", "Beta Y",
             "Eta X", 'X Bump', 'Y Bump', "Target X", "Target Y"])
        self._twiss = getTwiss([b.name for b in self.bpms],
                               ["s", "betax", "betay", "etax"])
        for i,bpm in enumerate(self.bpms):
            it = QTableWidgetItem(bpm.name)
            it.setFlags(it.flags() & (~Qt.ItemIsEditable))
            self.table.setItem(i, 0, it)

            it = QTableWidgetItem(str(bpm.sb))
            it.setFlags(it.flags() & (~Qt.ItemIsEditable))
            #it.setMinimumWidth(80)
            self.table.setItem(i, 1, it)
            self.table.setItem(i, 2,
                               QTableWidgetItem("%.4f" % self._twiss[i,1]))
            self.table.setItem(i, 3,
                               QTableWidgetItem("%.4f" % self._twiss[i,2]))
            self.table.setItem(i, 4,
                               QTableWidgetItem("%.4f" % self._twiss[i,3]))

            for j in range(5, 9):
                it = QTableWidgetItem(str(0.0))
                it.setData(Qt.DisplayRole, str(0.0))
                it.setFlags(it.flags() | Qt.ItemIsEditable)
                self.table.setItem(i, j, it) 
            # use the current orbit 
            #self.table.item(i,4).setData(Qt.DisplayRole, str(self.x0[i]))
            #self.table.item(i,5).setData(Qt.DisplayRole, str(self.y0[i]))

        #self.connect(self.table, SIGNAL("cellClicked(int, int)"),
        #             self._cell_clicked)
        self.table.resizeColumnsToContents()
        #self.table.horizontalHeader().setStretchLastSection(True)
        #for i in range(4):
        #    print "width", i, self.table.columnWidth(i)
        #self.table.setColumnWidth(0, 300)
        self.table.setColumnWidth(1, 80)

        vbox1 = QtGui.QVBoxLayout()
        frmbox = QFormLayout()
        self.base_orbit_box = QtGui.QComboBox()
        #self.base_orbit_box.addItems([
        #        "Current Orbit", "All Zeros"])
        self.base_orbit_box.addItems(["All Zeros", "Current Orbit"])
        frmbox.addRow("Orbit Base", self.base_orbit_box)
        grp = QtGui.QGroupBox("Local Bump")
        grp.setLayout(frmbox)
        vbox1.addWidget(grp)

        frmbox = QFormLayout()
        hln1 = QtGui.QFrame()
        hln1.setLineWidth(3)
        hln1.setFrameStyle(QtGui.QFrame.Sunken)
        hln1.setFrameShape(QtGui.QFrame.HLine)
        frmbox.addRow(hln1)
        self.repeatbox = QSpinBox()
        self.repeatbox.setRange(1, 20)
        self.repeatbox.setValue(3)
        # or connect the returnPressed() signal
        frmbox.addRow("&Repeat correction", self.repeatbox)

        self.rcondbox = QLineEdit()
        self.rcondbox.setValidator(QDoubleValidator(0, 1, 0, self))
        self.rcondbox.setText("1e-2")
        frmbox.addRow("r&cond for SVD", self.rcondbox)

        self.scalebox = QDoubleSpinBox()
        self.scalebox.setRange(0.01, 5.00)
        self.scalebox.setSingleStep(0.01)
        self.scalebox.setValue(0.68)
        frmbox.addRow("&Scale correctors", self.scalebox)

        #hln2 = QtGui.QFrame()
        #hln2.setLineWidth(3)
        #hln2.setFrameStyle(QtGui.QFrame.Sunken)
        #hln2.setFrameShape(QtGui.QFrame.HLine)
        #frmbox.addRow(hln2)

        self.progress = QProgressBar()
        self.progress.setMaximum(self.repeatbox.value())
        self.progress.setMaximumHeight(15)
        frmbox.addRow("Progress", self.progress)
        grp = QtGui.QGroupBox("Correction")
        grp.setLayout(frmbox)
        vbox1.addWidget(grp)

        #vbox.addStretch(1.0)
        #self.qdb = QDialogButtonBox(self)
        #self.qdb.addButton("APP", QDialogButtonBox.ApplyRole)
        #self.qdb.addButton("R", QDialogButtonBox.ResetRole)
        #btn.setDefault(True)
        #self.qdb.addButton(QDialogButtonBox.Cancel)
        #self.qdb.addButton(QDialogButtonBox.Help)

        gbox = QtGui.QGridLayout()
        btn = QPushButton("Clear")
        self.connect(btn, SIGNAL("clicked()"), self.resetBumps)
        gbox.addWidget(btn, 0, 1)
        self.correctOrbitBtn = QPushButton("Apply")
        #self.correctOrbitBtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.correctOrbitBtn.setStyleSheet("QPushButton:disabled { color: gray }");
        self.connect(self.correctOrbitBtn, SIGNAL("clicked()"), self.call_apply)
        self.correctOrbitBtn.setDefault(True)
        gbox.addWidget(self.correctOrbitBtn, 1, 1)
        gbox.setColumnStretch(0, 1)

        vbox1.addStretch()
        vbox1.addLayout(gbox)
        
        hbox1 = QtGui.QHBoxLayout()
        hbox1.addWidget(self.table, 2)
        hbox1.addLayout(vbox1, 0)
        self.setLayout(hbox1)

        self.connect(self.base_orbit_box,
                     SIGNAL("currentIndexChanged(QString)"), 
                     self.updateTargetOrbit)
        self.connect(self.repeatbox, SIGNAL("valueChanged(int)"),
                     self.progress.setMaximum)
        self.connect(self.table, SIGNAL("cellChanged (int, int)"),
                     self.updateBump)

        #self.updateTargetOrbit(self.base_orbit_box.currentText())

    def _update_current_orbit(self):
        pvx = [bpm.pv(field="x", handle="readback")[0] for bpm in self.bpms]
        pvy = [bpm.pv(field="y", handle="readback")[0] for bpm in self.bpms]
        self.x0 = [float(v) if v.ok else np.nan for v in catools.caget(pvx)]
        self.y0 = [float(v) if v.ok else np.nan for v in catools.caget(pvy)]

    def resetBumps(self):
        jx0, jy0 = 5, 6
        for i in range(self.table.rowCount()):
            self.table.item(i, jx0).setData(Qt.DisplayRole, str(0.0))
            self.table.item(i, jy0).setData(Qt.DisplayRole, str(0.0))
        #self.updateTargetOrbit(self.base_orbit_box.currentText())

    def call_apply(self):
        #print "apply the orbit"
        obt = []
        jx, jy = 7, 8
        for i in range(self.table.rowCount()):
            x1,err = self.table.item(i, jx).data(Qt.DisplayRole).toFloat()
            y1,err = self.table.item(i, jy).data(Qt.DisplayRole).toFloat()
            obt.append([x1, y1])

        self.correctOrbitBtn.setEnabled(False)
        nrepeat = self.repeatbox.value()
        kw = { "scale": float(self.scalebox.text()),
               "rcond": float(self.rcondbox.text()) }
        self.progress.setValue(0)
        QApplication.processEvents()
        for i in range(nrepeat):
            err, msg = setLocalBump(self.bpms, self.cors, obt, **kw)
            self.progress.setValue(i+1)
            QApplication.processEvents()
            if err != 0:
                QtGui.QMessageBox.critical(
                    self, "Local Orbit Bump", 
                    "ERROR: {0}\nAbort.".format(msg),
                    QtGui.QMessageBox.Ok)
                #self.progress.setValue(0)
                break
       
        self.correctOrbitBtn.setEnabled(True)

    def getTargetOrbit(self):
        x = [self.table.item(i,7).data(Qt.DisplayRole).toFloat()[0]
             for i in range(self.table.rowCount())]
        y = [self.table.item(i,8).data(Qt.DisplayRole).toFloat()[0]
             for i in range(self.table.rowCount())]
        return (self.sb, x), (self.sb, y)

    def updateTargetOrbit(self, baseobt):
        if baseobt == "All Zeros":
            jx0, jx1 = 5, 7
            jy0, jy1 = 6, 8
            for i in range(self.table.rowCount()):
                it0 = self.table.item(i, jx0)
                it1 = self.table.item(i, jx1)
                it1.setData(Qt.DisplayRole, it0.data(Qt.DisplayRole))
                it0 = self.table.item(i, jy0)
                it1 = self.table.item(i, jy1)
                it1.setData(Qt.DisplayRole, it0.data(Qt.DisplayRole))
        elif baseobt == "Current Orbit":
            self._update_current_orbit()
            jx0, jx1 = 5, 7
            jy0, jy1 = 6, 8
            for i in range(self.table.rowCount()):
                dx0,err = self.table.item(i, jx0).data(Qt.DisplayRole).toFloat()
                it = self.table.item(i, jx1)
                it.setData(Qt.DisplayRole, self.x0[i] + dx0)

                dy0,err = self.table.item(i, jy0).data(Qt.DisplayRole).toFloat()
                it = self.table.item(i, jy1)
                it.setData(Qt.DisplayRole, self.y0[i] + dy0)
        #self._update_orbit_plot()
        x, y = self.getTargetOrbit()
        self.emit(SIGNAL("targetOrbitChanged(PyQt_PyObject, PyQt_PyObject)"),
                  x, y)

    def updateBump(self, row, col):
        #print "updating ", row, col
        if col == 5 or col == 6:
            self.updateTargetOrbit(self.base_orbit_box.currentText())
Пример #46
0
class GroupsPostView(QDialog):
    """
    +------------------------+
    |  Groups : Post/Delete  |
    +------------------------+
    |                        |
    |   check1      Name1    |
    |   check2      Name2    |
    |   check3      Name3    |
    |                        |
    |       SetAsMain        |
    |   Apply   OK   Close   |
    +------------------------+
    """
    def __init__(self, data, win_parent=None):
        self.win_parent = win_parent
        #Init the base class

        groups = data['groups']
        inames = data['inames']
        self.imain = data['imain']
        self.names = [group.name for group in groups]
        self.white = (255, 255, 255)
        self.light_grey = (211, 211, 211)
        self.inames = inames
        self.shown_set = data['shown']
        self.deleted_groups = set([])
        #self.inames = argsort(self.names)
        #print('inames =', inames)

        anames = array(self.names)
        for iname, name in enumerate(anames[self.inames]):
            print('name[%s] = %r' % (iname, name))

        # ignore these...
        #self._default_name = data['name']
        #self._default_coords = data['coords']
        #self._default_elements = data['elements']
        #self._default_color = data['color']

        #self.coords_pound = data['coords_pound']
        #self.elements_pound = data['elements_pound']

        #self._default_is_discrete = data['is_discrete']

        self.out_data = data

        QDialog.__init__(self, win_parent)
        #self.setupUi(self)
        self.setWindowTitle('Groups: Post/View')
        self.create_widgets()
        self.create_layout()
        self.set_connections()
        #self.show()

    def create_widgets(self):
        # main/delete/supergroup
        self.set_as_main_button = QPushButton("Set As Main")
        self.create_super_group_button = QPushButton("Create Super Group")
        self.delete_groups_button = QPushButton("Delete Groups")
        self.revert_groups_button = QPushButton("Revert Groups")

        self.show_groups_button = QPushButton("Show Groups")
        self.hide_groups_button = QPushButton("Hide Groups")

        # closing
        self.apply_button = QPushButton("Apply")
        self.ok_button = QPushButton("OK")
        self.cancel_button = QPushButton("Cancel")

        #table
        self.table = QTableWidget()
        self.checks = []
        self.names_text = []

        bold = QtGui.QFont()
        bold.setBold(True)
        bold.setItalic(True)
        bold.setWeight(75)
        anames = array(self.names)
        for iname, name in enumerate(anames[self.inames]):
            check = QTableWidgetItem()
            check.setCheckState(False)

            # TODO: create right click menu ???
            name_text = QTableWidgetItem(str(name))
            if iname == self.imain:
                name_text.setFont(bold)
                self.shown_set.add(iname)
                check.setCheckState(2)
                name_text.setBackground(QtGui.QColor(*self.light_grey))
            elif iname in self.shown_set:
                name_text.setBackground(QtGui.QColor(*self.light_grey))

            self.checks.append(check)
            self.names_text.append(name_text)

    def create_layout(self):
        nrows = len(self.names)
        table = self.table
        table.setRowCount(nrows)
        table.setColumnCount(2)
        headers = [QString('Operate On'), QString('Name')]
        table.setHorizontalHeaderLabels(headers)

        header = table.horizontalHeader()
        header.setStretchLastSection(True)

        #table.setAlternatingRowColors(True)

        #header = table.verticalHeader()
        #header.setStretchLastSection(True)
        #table.resize(400, 250)

        #heighti = table.rowHeight(0)
        #total_height = nrows * heighti
        #table.setMaximumHeight(total_height)
        #table.resize(total_height, None)

        #for iname, name in enumerate(self.names[self.inames]):
        #print('name[%s] = %r' % (iname, name))
        for iname in self.inames:
            check = self.checks[iname]
            name_text = self.names_text[iname]
            # row, col, value
            table.setItem(iname, 0, check)
            table.setItem(iname, 1, name_text)
        table.resizeRowsToContents()
        #table.horizontalHeaderItem(1).setTextAlignment(QtCore.AlignHCenter)

        #= QVBoxLayout()
        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.apply_button)
        ok_cancel_box.addWidget(self.ok_button)
        ok_cancel_box.addWidget(self.cancel_button)

        vbox = QVBoxLayout()
        vbox.addWidget(table)
        vbox.addWidget(self.set_as_main_button)
        #vbox.addWidget(self.create_super_group_button)

        vbox.addStretch()
        vbox.addWidget(self.show_groups_button)
        vbox.addWidget(self.hide_groups_button)
        vbox.addStretch()
        vbox.addWidget(self.delete_groups_button)
        vbox.addWidget(self.revert_groups_button)
        vbox.addStretch()

        vbox.addStretch()
        vbox.addLayout(ok_cancel_box)

        self.setLayout(vbox)

    def set_connections(self):
        if qt_version == 4:
            self.connect(self.set_as_main_button, QtCore.SIGNAL('clicked()'), self.on_set_as_main)
            self.connect(self.delete_groups_button, QtCore.SIGNAL('clicked()'), self.on_delete_groups)
            self.connect(self.revert_groups_button, QtCore.SIGNAL('clicked()'), self.on_revert_groups)

            self.connect(self.show_groups_button, QtCore.SIGNAL('clicked()'), self.on_show_groups)
            self.connect(self.hide_groups_button, QtCore.SIGNAL('clicked()'), self.on_hide_groups)

            self.connect(self.create_super_group_button, QtCore.SIGNAL('clicked()'), self.on_create_super_group)

            self.connect(self.apply_button, QtCore.SIGNAL('clicked()'), self.on_apply)
            self.connect(self.ok_button, QtCore.SIGNAL('clicked()'), self.on_ok)
            self.connect(self.cancel_button, QtCore.SIGNAL('clicked()'), self.on_cancel)
        else:
            self.set_as_main_button.clicked.connect(self.on_set_as_main)
            self.delete_groups_button.clicked.connect(self.on_delete_groups)
            self.revert_groups_button.clicked.connect(self.on_revert_groups)

            self.show_groups_button.clicked.connect(self.on_show_groups)
            self.hide_groups_button.clicked.connect(self.on_hide_groups)

            self.create_super_group_button.clicked.connect(self.on_create_super_group)

            self.apply_button.clicked.connect(self.on_apply)
            self.ok_button.clicked.connect(self.on_ok)
            self.cancel_button.clicked.connect(self.on_cancel)

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

    @property
    def nrows(self):
        return self.table.rowCount()

    def on_hide_groups(self):
        self._set_highlight(self.white)

    def on_show_groups(self):
        self._set_highlight(self.light_grey)

    def _set_highlight(self, color):
        for irow in range(self.nrows):
            check = self.checks[irow]
            is_checked = check.checkState()

            # 0 - unchecked
            # 1 - partially checked (invalid)
            # 2 - checked
            if is_checked:
                name_text = self.names_text[irow]
                name_text.setBackground(QtGui.QColor(*color))

    def on_delete_groups(self):
        for irow in range(self.nrows):
            check = self.checks[irow]
            is_checked = check.checkState()

            # 0 - unchecked
            # 1 - partially checked (invalid)
            # 2 - checked
            if irow == 0 and is_checked:
                # TODO: change this to a log
                print('error deleting group ALL...change this to a log')
                #self.window_parent.log
                return
            if is_checked:
                self.table.hideRow(irow)
                self.deleted_groups.add(irow)
                check.setCheckState(0)

        if self.imain > 0 and self.shown_set == set([0]):
            bold = QtGui.QFont()
            bold.setBold(True)
            bold.setItalic(True)

            self.imain = 0
            irow = 0
            check = self.checks[irow]
            name_text = self.names_texts[irow]
            name_text.setFont(bold)
            name_text.setBackground(QtGui.QColor(*self.light_grey))

    def on_revert_groups(self):
        for irow in range(self.nrows):
            self.table.showRow(irow)
        self.deleted_groups = set([])

    def on_create_super_group(self):
        inames = [iname for iname, check in enumerate(self.checks)
                  if bool(check.checkState())]

        if not len(inames):
            # TODO: add logging
            print('nothing is checked...')
            return
        if inames[0] == 0:
            # TODO: add logging
            print("cannot include 'ALL' in supergroup...")
            return

        name = 'SuperGroup'
        # popup gui and get a name

        irow = self.table.rowCount()
        self.table.insertRow(irow)


        check = QTableWidgetItem()
        check.setCheckState(False)
        name_text = QTableWidgetItem(str(name))

        self.names.extend(name)
        self.names_text.append(name_text)
        self.checks.append(check)

        self.table.setItem(irow, 0, check)
        self.table.setItem(irow, 1, name_text)


    def on_set_as_main(self):
        bold = QtGui.QFont()
        bold.setBold(True)
        bold.setItalic(True)

        normal = QtGui.QFont()
        normal.setBold(False)
        normal.setItalic(False)

        imain = None
        imain_set = False
        for irow in range(self.nrows):
            check = self.checks[irow]
            name_text = self.names_text[irow]
            is_checked = check.checkState()

            # 0 - unchecked
            # 1 - partially checked (invalid)
            # 2 - checked
            if is_checked and not imain_set:
                # TODO: change this to a log
                #self.window_parent.log
                imain_set = True
                imain = irow
                name_text.setFont(bold)
                name_text.setBackground(QtGui.QColor(*self.light_grey))
                self.shown_set.add(irow)
            elif irow == self.imain:
                name_text.setFont(normal)
                if irow == 0:
                    name_text.setBackground(QtGui.QColor(*self.white))
                    if irow in self.shown_set:
                        self.shown_set.remove(irow)
                elif imain == 0:
                    name_text.setBackground(QtGui.QColor(*self.white))
                    self.shown_set.remove(imain)
        self.imain = imain

    def get_main_group(self):
        return self.imain

    def get_shown_group(self):
        return self.shown_set

    def get_deleted_groups(self):
        return self.deleted_groups

    def on_validate(self):
        flag0 = flag1 = flag2 = True
        main_group_id = self.get_main_group()
        shown_groups_ids = self.get_shown_group()
        deleted_group_ids = self.get_deleted_groups()

        if flag0 and flag1 and flag2:
            self.out_data['imain'] = main_group_id
            self.out_data['shown'] = shown_groups_ids
            self.out_data['remove'] = deleted_group_ids
            self.out_data['clicked_ok'] = True
            return True
        return False

    def on_apply(self):
        passed = self.on_validate()
        if passed:
            self.win_parent.on_post_group(self.out_data)

    def on_ok(self):
        passed = self.on_validate()
        if passed:
            self.close()
            #self.destroy()

    def on_cancel(self):
        self.close()
Пример #47
0
class CorrectorViewer(QtGui.QWidget):
    """
    List all corrector and select part to lower table
    """
    def __init__(self, cors, field, parent=None, nmax=4):
        super(CorrectorViewer, self).__init__(parent)
        self._nmax  = nmax
        self._field = field
        self._cors  = cors
        self._corlst1 = QtGui.QTreeWidget()
        self._header = dict([("Element", 0), ("Family", 1), ("s [m]", 2),
                             ("Alpha X", 3), ("Alpha Y", 4), ("Beta X", 5),
                             ("Beta Y", 6), ("Phi X", 7), ("Phi Y", 8),
                             ("Eta X", 9)])
        self._twiss = np.zeros((len(self._cors), 8), 'd')
        self._tunes = getTunes(source="database")
        self._corlst1.setColumnCount(len(self._header))
        self._corlst1.setHeaderLabels(
            sorted(self._header, key=self._header.get))
        self._corlst1.header().setStretchLastSection(False)
        prevcell = None
        for i,c in enumerate(self._cors):
            if c.cell and (prevcell is None or c.cell != prevcell.text(0)):
                # a new parent
                prevcell = QtGui.QTreeWidgetItem()
                prevcell.setText(0, c.cell)
                self._corlst1.addTopLevelItem(prevcell)
            it = QtGui.QTreeWidgetItem()
            it.setData(0, Qt.UserRole, i)
            it.setText(self._header["Element"], c.name)
            it.setText(self._header["Family"], c.family)
            it.setText(self._header["s [m]"], "%.3f" % c.sb)
            try:
                tw = getTwiss(c.name, 
                              ["s", "alphax", "alphay", "betax", "betay",
                               "phix", "phiy", "etax"])
                self._twiss[i,:] = tw[0,:]
                it.setText(self._header["Alpha X"], "%.4f" % self._twiss[i,1])
                it.setText(self._header["Alpha Y"], "%.4f" % self._twiss[i,2])
                it.setText(self._header["Beta X"],  "%.4f" % self._twiss[i,3])
                it.setText(self._header["Beta Y"],  "%.4f" % self._twiss[i,4])
                it.setText(self._header["Phi X"],   "%.4f" % self._twiss[i,5])
                it.setText(self._header["Phi Y"],   "%.4f" % self._twiss[i,6])
                it.setText(self._header["Eta X"],   "%.4f" % self._twiss[i,7])
            except:
                it.setDisabled(True)
                pass

            if c.cell:
                prevcell.addChild(it)
            else:
                self._corlst1.addTopLevelItem(it)
                prevcell = it
            for j in range(2, len(self._header)):
                it.setTextAlignment(j, Qt.AlignRight)
        self._corlst1.expandAll()
        for i in range(len(self._header)):
            self._corlst1.resizeColumnToContents(i)
        #self._corlst1.setColumnWidth(0, 150)

        #self.elemlst.setSelectionMode(QAbstractItemView.MultiSelection)
        columns = ['Corrector', 's', 'Alpha', 'Beta',
                   'Phi', "dPhi", "Initial Bump", "Cur. Sp", "dBump",
                   "Final Rb"]
        self.table4 = QTableWidget(0, len(columns))
        #self.table4.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        hdview = QHeaderView(Qt.Horizontal)
        self.table4.setHorizontalHeaderLabels(columns)
        #for i in range(4):
        #    for j in range(len(columns)):
        #        it = QTableWidgetItem()
        #        if j > 0: it.setTextAlignment(
        #            Qt.AlignRight | Qt.AlignVCenter)
        #        if columns[j] != "dKick":
        #            it.setFlags(it.flags() & (~Qt.ItemIsEditable))
        #        self.table4.setItem(i, j, it)
        #self.table4.resizeColumnsToContents()
        #self.table4.horizontalHeader().setStretchLastSection(True)
        #hrow = self.table4.rowHeight(0)
        #htbl = (hrow * 4) + self.table4.horizontalHeader().height() +\
        #    2*self.table4.frameWidth()
        #self.table4.setMinimumHeight(htbl + 10)
        #self.table4.setMaximumHeight(htbl + 15)
        #self.table4.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        #print "Size:", htbl + 10
        self.table4.resize(self.table4.width(), 150)

        splitter = QtGui.QSplitter(Qt.Vertical)
        splitter.addWidget(self._corlst1)
        splitter.addWidget(self.table4)
        vbox1 = QtGui.QVBoxLayout()
        vbox1.addWidget(splitter)
        self.setLayout(vbox1)

        self.connect(self._corlst1, SIGNAL("doubleClicked(QModelIndex)"),
                     self.addCorrector)
        #self.connect(self.src, SIGNAL("returnPressed()"),
        #             self._calc_source)
        #self.connect(self.table4, SIGNAL("cellChanged(int, int)"),
        #             self.updateTable)

        #self.connect(self.table4, SIGNAL("doubleClicked(QModelIndex)"),
        #             self.delCorrector)
        self._x0 = fget(self._cors, "x", handle="setpoint", unitsys=None)
        self._y0 = fget(self._cors, "y", handle="setpoint", unitsys=None)


    def addCorrector(self, idx):
        if not self._corlst1.selectedItems(): return
        #print self._corlst1.itemFromIndex(idx).text(0)
        nrow = self.table4.rowCount()
        if nrow >= self._nmax:
            QtGui.QMessageBox.critical(
                self, "Local Orbit Bump", 
                "ERROR: We need only {0} correctors.".format(self._nmax),
                QtGui.QMessageBox.Ok)
                #self.progress.setValue(0)
            return
        self.table4.setRowCount(nrow+1)
        it0 = self._corlst1.selectedItems()[-1]
        icor, ok = it0.data(0, Qt.UserRole).toInt()
        if icor < 0: return
        newc = self._cors[icor]
        for j in range(self.table4.columnCount()):
            it = QTableWidgetItem()
            if j > 0: it.setTextAlignment(
                Qt.AlignRight | Qt.AlignVCenter)
            header = self.table4.horizontalHeaderItem(j)
            if header.text() != "dBump":
                it.setFlags(it.flags() & (~Qt.ItemIsEditable))
            else:
                it.setData(Qt.DisplayRole, "0")
                it.setData(Qt.UserRole, 0.0)
            self.table4.setItem(nrow, j, it)
        self.table4.item(nrow,0).setData(Qt.UserRole, icor)
        for j,h in [(0, "Element"), (1, "s [m]")]:
            self.table4.item(nrow,j).setData(Qt.DisplayRole,
                                          it0.text(self._header[h]))
        for j in range(self._corlst1.columnCount()):
            it0.setForeground(j, Qt.red)
        it0.setDisabled(True)
        self.emit(SIGNAL("correctorAdded(PyQt_PyObject)"), newc)
        # use initial values

        self.updateTwiss()
        self.updateCorReadings()
        self.table4.resizeColumnsToContents()
        if self.table4.rowCount() == self._nmax:
            #print "All correctors are ready"
            self.emit(SIGNAL("correctorsComplete()"))

    def updateTwiss(self):
        if self._field == "x":
            jl = [self._header[h] for h in ["Alpha X", "Beta X", "Phi X"]]
            nu = self._tunes[0]
        elif self._field == "y":
            jl = [self._header[h] for h in ["Alpha Y", "Beta Y", "Phi Y"]]
            nu = self._tunes[1]
        else:
            raise RuntimeError("unknown cor field {0}".format(self._field))
        #print "index:", jl
        # if rows provided use it, otherwise use all
        for i in range(self.table4.rowCount()):
            elemname = self.table4.item(i,0).data(Qt.DisplayRole).toString()
            it0 = self._corlst1.findItems(
                elemname, Qt.MatchExactly | Qt.MatchRecursive)[0]
            
            self.table4.item(i,2).setText(it0.text(jl[0]))
            self.table4.item(i,3).setText(it0.text(jl[1]))
            self.table4.item(i,4).setText(it0.text(jl[2]))
            self.table4.item(i,4).setData(Qt.UserRole, float(it0.text(jl[2])))

            if i == 0:
                self.table4.item(i,5).setText("0.0")
                self.table4.item(i,5).setData(Qt.UserRole, 0.0)
            else:
                dph, ok = self.table4.item(i-1,5).data(Qt.UserRole).toFloat()
                ph0, ok = self.table4.item(i-1,4).data(Qt.UserRole).toFloat()
                ph1, ok = self.table4.item(i,4).data(Qt.UserRole).toFloat()
                dph = dph + ph1 - ph0
                if ph1 < ph0:
                    dph = dph + 2.0*np.pi*nu
                #print "Updating twiss:", i, dph
                self.table4.item(i,5).setData(Qt.UserRole, dph)
                self.table4.item(i,5).setText("%.5g" % dph)
            icor, ok = self.table4.item(i,0).data(Qt.UserRole).toInt()
            #c = self._cors[icor]
            #kick = self._cors[icor].get(self._field, unitsys=None)
            #self.table4.item(i,6).setData(Qt.UserRole, kick)
            #self.table4.item(i,6).setText("%.5g" % kick)
        #self.updateKickReadings(col=0)

    def clear(self):
        for i in range(self.table4.rowCount()):
            elemname = self.table4.item(i,0).data(Qt.DisplayRole).toString()
            it0 = self._corlst1.findItems(
                elemname, Qt.MatchExactly | Qt.MatchRecursive)[0]
            it0.setDisabled(False)
            for j in range(self._corlst1.columnCount()):
                it0.setForeground(j, Qt.black)
        self.table4.setRowCount(0)
    
    def updateCorReadings(self):
        for i in range(self.table4.rowCount()):
            icor, ok = self.table4.item(i,0).data(Qt.UserRole).toInt()
            cor = self._cors[icor]
            if self._field == "x":
                self.table4.item(i,6).setData(Qt.UserRole, self._x0[icor])
                self.table4.item(i,6).setText("%.5g" % self._x0[icor])
            elif self._field == "y":
                self.table4.item(i,6).setData(Qt.UserRole, self._y0[icor])
                self.table4.item(i,6).setText("%.5g" % self._y0[icor])
            kicksp = cor.get(self._field, handle="setpoint", unitsys=None)
            self.table4.item(i,7).setData(Qt.UserRole, float(kicksp))
            self.table4.item(i,7).setText("%.5g" % kicksp)
            kickrb = cor.get(self._field, handle="readback", unitsys=None)
            self.table4.item(i,9).setData(Qt.UserRole, float(kickrb))
            self.table4.item(i,9).setText("%.5g" % kickrb)


    def updateDbump(self, dkick):
        nrow = min(self.table4.rowCount(), len(dkick))
        for i in range(nrow):
            # dbump column is 8
            it = self.table4.item(i, 8)
            if dkick[i] is None:
                it.setData(Qt.DisplayRole, "")
                it.setData(Qt.UserRole, 0.0)
            else:
                it.setData(Qt.UserRole, float(dkick[i]))
                it.setData(Qt.DisplayRole, "{0}".format(dkick[i]))
        self.updateCorReadings()
        self.table4.resizeColumnsToContents()
        #print "(0,7)", self.table4.item(0, 7).data(Qt.UserRole).toFloat()
        #print "(0,7)", self.table4.item(0, 7).data(Qt.DisplayRole).toFloat()

    def applyKick(self):
        nrow = self.table4.rowCount()
        for i in range(nrow):
            icor, ok = self.table4.item(i,0).data(Qt.UserRole).toInt()
            cor = self._cors[icor]
            # Current SP: 7, dBump 8
            k0, ok = self.table4.item(i, 7).data(Qt.UserRole).toFloat()
            dk, ok = self.table4.item(i, 8).data(Qt.UserRole).toFloat()
            #print "Setting {0} {1}+{2} [A]".format(cor.name, k0, dk)
            cor.put(self._field, k0+dk, unitsys=None)

        # update the final readings
        self.updateCorReadings()

    def getTwiss(self):
        tw = {"s": [], "Alpha": [], "Beta": [],
              "Phi": [], "dPhi": []}
        nrow = self.table4.rowCount()
        for j in range(self.table4.columnCount()):
            header = self.table4.horizontalHeaderItem(j)
            if header.text() not in tw.keys():
                continue
            k = str(header.text())
            for i in range(nrow):
                it = self.table4.item(i, j)
                v0, ok0 = it.data(Qt.UserRole).toFloat()
                v1, ok1 = it.data(Qt.DisplayRole).toFloat()
                if ok0:
                    tw[k].append(v0)
                elif ok1:
                    tw[k].append(v1)
                else:
                    tw[k].append(np.nan)
        return tw

    def selectedCorrectors(self):
        ret = []
        for i in range(self.table4.rowCount()):
            icor, ok = self.table4.item(i,0).data(Qt.UserRole).toInt()
            ret.append(self._cors[icor])
        return ret

    def resetCorrectors(self):
        for i in range(self.table4.rowCount()):
            icor, ok = self.table4.item(i,0).data(Qt.UserRole).toInt()
            cor = self._cors[icor]
            if self._field == "x":
                kick = self._x0[icor]
            elif self._field == "y":
                kick = self._y0[icor]
            cor.put(self._field, kick, unitsys=None)
Пример #48
0
class LabelAssistDialog(QDialog):
    """
    A simple UI for showing bookmarks and navigating to them.

    FIXME: For now, this window is tied to a particular lane.
           If your project has more than one lane, then each one
           will have it's own bookmark window, which is kinda dumb.
    """
    def __init__(self, parent, topLevelOperatorView):
        super(LabelAssistDialog, self).__init__(parent)

        # Create thread router to populate table on main thread
        self.threadRouter = ThreadRouter(self)

        # Set object classification operator view
        self.topLevelOperatorView = topLevelOperatorView

        self.setWindowTitle("Label Assist")
        self.setMinimumWidth(500)
        self.setMinimumHeight(700)

        layout = QGridLayout()
        layout.setContentsMargins(10, 10, 10, 10)

        # Show variable importance table
        rows = 0
        columns = 4
        self.table = QTableWidget(rows, columns)
        self.table.setHorizontalHeaderLabels(
            ['Frame', 'Max Area', 'Min Area', 'Labels'])
        self.table.verticalHeader().setVisible(False)

        # Select full row on-click and call capture double click
        self.table.setSelectionBehavior(QTableView.SelectRows)
        self.table.doubleClicked.connect(self._captureDoubleClick)

        layout.addWidget(self.table, 1, 0, 3, 2)

        # Create progress bar
        self.progressBar = QProgressBar()
        self.progressBar.setMinimum(0)
        self.progressBar.setMaximum(0)
        self.progressBar.hide()
        layout.addWidget(self.progressBar, 4, 0, 1, 2)

        # Create button to populate table
        self.computeButton = QPushButton('Compute object info')
        self.computeButton.clicked.connect(self._triggerTableUpdate)
        layout.addWidget(self.computeButton, 5, 0)

        # Create close button
        closeButton = QPushButton('Close')
        closeButton.clicked.connect(self.close)
        layout.addWidget(closeButton, 5, 1)

        # Set dialog layout
        self.setLayout(layout)

    def _triggerTableUpdate(self):
        # Check that object area is included in selected features
        featureNames = self.topLevelOperatorView.SelectedFeatures.value

        if 'Standard Object Features' not in featureNames or 'Count' not in featureNames[
                'Standard Object Features']:
            box = QMessageBox(
                QMessageBox.Warning, 'Warning',
                'Object area is not a selected feature. Please select this feature on: \"Standard Object Features > Shape > Size in pixels\"',
                QMessageBox.NoButton, self)
            box.show()
            return

        # Clear table
        self.table.clearContents()
        self.table.setRowCount(0)
        self.table.setSortingEnabled(False)
        self.progressBar.show()
        self.computeButton.setEnabled(False)

        # Compute object features and number of labels per frame
        def compute_features():
            features = self.topLevelOperatorView.ObjectFeatures([]).wait()
            labels = self.topLevelOperatorView.LabelInputs([]).wait()
            return features, labels

        req = Request(compute_features)
        req.notify_finished(self._populateTable)
        req.submit()

    @threadRouted
    def _populateTable(self, features_and_labels):
        features, labels = features_and_labels
        self.progressBar.hide()
        self.computeButton.setEnabled(True)

        for frame, objectFeatures in features.iteritems():
            # Insert row
            rowNum = self.table.rowCount()
            self.table.insertRow(self.table.rowCount())

            # Get max and min object areas
            areas = objectFeatures['Standard Object Features']['Count']
            maxObjArea = numpy.max(areas[numpy.nonzero(areas)])
            minObjArea = numpy.min(areas[numpy.nonzero(areas)])

            # Get number of labeled objects
            labelNum = numpy.count_nonzero(labels[frame])

            # Load fram number
            item = QTableWidgetItem(str(frame))
            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.table.setItem(rowNum, 0, item)

            # Load max object areas
            item = QTableWidgetItemWithFloatSorting(
                str("{: .02f}".format(maxObjArea)))
            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.table.setItem(rowNum, 1, item)

            # Load min object areas
            item = QTableWidgetItemWithFloatSorting(
                str("{: .02f}".format(minObjArea)))
            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.table.setItem(rowNum, 2, item)

            # Load label numbers
            item = QTableWidgetItemWithFloatSorting(
                str("{: .01f}".format(labelNum)))
            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.table.setItem(rowNum, 3, item)

        # Resize column size to fit dialog size
        self.table.horizontalHeader().setResizeMode(QHeaderView.Stretch)

        # Sort by max object area
        self.table.setSortingEnabled(True)
        self.table.sortByColumn(1)

    def _captureDoubleClick(self):
        # Navigate to selected frame
        index = self.table.selectedIndexes()[0]
        frameStr = self.table.model().data(index).toString()

        if frameStr:
            frameNum = int(frameStr)
            self.parent().editor.posModel.time = frameNum
Пример #49
0
class GroupsPostView(QDialog):
    """
    +------------------------+
    |  Groups : Post/Delete  |
    +------------------------+
    |                        |
    |   check1      Name1    |
    |   check2      Name2    |
    |   check3      Name3    |
    |                        |
    |       SetAsMain        |
    |   Apply   OK   Close   |
    +------------------------+
    """
    def __init__(self, data, win_parent=None):
        self.win_parent = win_parent
        #Init the base class

        groups = data['groups']
        inames = data['inames']
        self.imain = data['imain']
        self.names = [group.name for group in groups]
        self.white = (255, 255, 255)
        self.light_grey = (211, 211, 211)
        self.inames = inames
        self.shown_set = data['shown']
        self.deleted_groups = set([])
        #self.inames = argsort(self.names)
        #print('inames =', inames)

        anames = array(self.names)
        for iname, name in enumerate(anames[self.inames]):
            print('name[%s] = %r' % (iname, name))

        # ignore these...
        #self._default_name = data['name']
        #self._default_coords = data['coords']
        #self._default_elements = data['elements']
        #self._default_color = data['color']

        #self.coords_pound = data['coords_pound']
        #self.elements_pound = data['elements_pound']

        #self._default_is_discrete = data['is_discrete']

        self.out_data = data

        QDialog.__init__(self, win_parent)
        #self.setupUi(self)
        self.setWindowTitle('Groups: Post/View')
        self.create_widgets()
        self.create_layout()
        self.set_connections()
        #self.show()

    def create_widgets(self):
        # main/delete/supergroup
        self.set_as_main_button = QPushButton("Set As Main")
        self.create_super_group_button = QPushButton("Create Super Group")
        self.delete_groups_button = QPushButton("Delete Groups")
        self.revert_groups_button = QPushButton("Revert Groups")

        self.show_groups_button = QPushButton("Show Groups")
        self.hide_groups_button = QPushButton("Hide Groups")

        # closing
        self.apply_button = QPushButton("Apply")
        self.ok_button = QPushButton("OK")
        self.cancel_button = QPushButton("Cancel")

        #table
        self.table = QTableWidget()
        self.checks = []
        self.names_text = []

        bold = QtGui.QFont()
        bold.setBold(True)
        bold.setItalic(True)
        bold.setWeight(75)
        anames = array(self.names)
        for iname, name in enumerate(anames[self.inames]):
            check = QTableWidgetItem()
            check.setCheckState(False)

            # TODO: create right click menu ???
            name_text = QTableWidgetItem(str(name))
            if iname == self.imain:
                name_text.setFont(bold)
                self.shown_set.add(iname)
                check.setCheckState(2)
                name_text.setBackground(QtGui.QColor(*self.light_grey))
            elif iname in self.shown_set:
                name_text.setBackground(QtGui.QColor(*self.light_grey))

            self.checks.append(check)
            self.names_text.append(name_text)

    def create_layout(self):
        nrows = len(self.names)
        table = self.table
        table.setRowCount(nrows)
        table.setColumnCount(2)
        headers = [QString('Operate On'), QString('Name')]
        table.setHorizontalHeaderLabels(headers)

        header = table.horizontalHeader()
        header.setStretchLastSection(True)

        #table.setAlternatingRowColors(True)

        #header = table.verticalHeader()
        #header.setStretchLastSection(True)
        #table.resize(400, 250)

        #heighti = table.rowHeight(0)
        #total_height = nrows * heighti
        #table.setMaximumHeight(total_height)
        #table.resize(total_height, None)

        #for iname, name in enumerate(self.names[self.inames]):
        #print('name[%s] = %r' % (iname, name))
        for iname in self.inames:
            check = self.checks[iname]
            name_text = self.names_text[iname]
            # row, col, value
            table.setItem(iname, 0, check)
            table.setItem(iname, 1, name_text)
        table.resizeRowsToContents()
        #table.horizontalHeaderItem(1).setTextAlignment(QtCore.AlignHCenter)

        #= QVBoxLayout()
        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.apply_button)
        ok_cancel_box.addWidget(self.ok_button)
        ok_cancel_box.addWidget(self.cancel_button)

        vbox = QVBoxLayout()
        vbox.addWidget(table)
        vbox.addWidget(self.set_as_main_button)
        #vbox.addWidget(self.create_super_group_button)

        vbox.addStretch()
        vbox.addWidget(self.show_groups_button)
        vbox.addWidget(self.hide_groups_button)
        vbox.addStretch()
        vbox.addWidget(self.delete_groups_button)
        vbox.addWidget(self.revert_groups_button)
        vbox.addStretch()

        vbox.addStretch()
        vbox.addLayout(ok_cancel_box)

        self.setLayout(vbox)

    def set_connections(self):
        if qt_version == 4:
            self.connect(self.set_as_main_button, QtCore.SIGNAL('clicked()'),
                         self.on_set_as_main)
            self.connect(self.delete_groups_button, QtCore.SIGNAL('clicked()'),
                         self.on_delete_groups)
            self.connect(self.revert_groups_button, QtCore.SIGNAL('clicked()'),
                         self.on_revert_groups)

            self.connect(self.show_groups_button, QtCore.SIGNAL('clicked()'),
                         self.on_show_groups)
            self.connect(self.hide_groups_button, QtCore.SIGNAL('clicked()'),
                         self.on_hide_groups)

            self.connect(self.create_super_group_button,
                         QtCore.SIGNAL('clicked()'),
                         self.on_create_super_group)

            self.connect(self.apply_button, QtCore.SIGNAL('clicked()'),
                         self.on_apply)
            self.connect(self.ok_button, QtCore.SIGNAL('clicked()'),
                         self.on_ok)
            self.connect(self.cancel_button, QtCore.SIGNAL('clicked()'),
                         self.on_cancel)
        else:
            self.set_as_main_button.clicked.connect(self.on_set_as_main)
            self.delete_groups_button.clicked.connect(self.on_delete_groups)
            self.revert_groups_button.clicked.connect(self.on_revert_groups)

            self.show_groups_button.clicked.connect(self.on_show_groups)
            self.hide_groups_button.clicked.connect(self.on_hide_groups)

            self.create_super_group_button.clicked.connect(
                self.on_create_super_group)

            self.apply_button.clicked.connect(self.on_apply)
            self.ok_button.clicked.connect(self.on_ok)
            self.cancel_button.clicked.connect(self.on_cancel)

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

    @property
    def nrows(self):
        return self.table.rowCount()

    def on_hide_groups(self):
        self._set_highlight(self.white)

    def on_show_groups(self):
        self._set_highlight(self.light_grey)

    def _set_highlight(self, color):
        for irow in range(self.nrows):
            check = self.checks[irow]
            is_checked = check.checkState()

            # 0 - unchecked
            # 1 - partially checked (invalid)
            # 2 - checked
            if is_checked:
                name_text = self.names_text[irow]
                name_text.setBackground(QtGui.QColor(*color))

    def on_delete_groups(self):
        for irow in range(self.nrows):
            check = self.checks[irow]
            is_checked = check.checkState()

            # 0 - unchecked
            # 1 - partially checked (invalid)
            # 2 - checked
            if irow == 0 and is_checked:
                # TODO: change this to a log
                print('error deleting group ALL...change this to a log')
                #self.window_parent.log
                return
            if is_checked:
                self.table.hideRow(irow)
                self.deleted_groups.add(irow)
                check.setCheckState(0)

        if self.imain > 0 and self.shown_set == set([0]):
            bold = QtGui.QFont()
            bold.setBold(True)
            bold.setItalic(True)

            self.imain = 0
            irow = 0
            check = self.checks[irow]
            name_text = self.names_texts[irow]
            name_text.setFont(bold)
            name_text.setBackground(QtGui.QColor(*self.light_grey))

    def on_revert_groups(self):
        for irow in range(self.nrows):
            self.table.showRow(irow)
        self.deleted_groups = set([])

    def on_create_super_group(self):
        inames = [
            iname for iname, check in enumerate(self.checks)
            if bool(check.checkState())
        ]

        if not len(inames):
            # TODO: add logging
            print('nothing is checked...')
            return
        if inames[0] == 0:
            # TODO: add logging
            print("cannot include 'ALL' in supergroup...")
            return

        name = 'SuperGroup'
        # popup gui and get a name

        irow = self.table.rowCount()
        self.table.insertRow(irow)

        check = QTableWidgetItem()
        check.setCheckState(False)
        name_text = QTableWidgetItem(str(name))

        self.names.extend(name)
        self.names_text.append(name_text)
        self.checks.append(check)

        self.table.setItem(irow, 0, check)
        self.table.setItem(irow, 1, name_text)

    def on_set_as_main(self):
        bold = QtGui.QFont()
        bold.setBold(True)
        bold.setItalic(True)

        normal = QtGui.QFont()
        normal.setBold(False)
        normal.setItalic(False)

        imain = None
        imain_set = False
        for irow in range(self.nrows):
            check = self.checks[irow]
            name_text = self.names_text[irow]
            is_checked = check.checkState()

            # 0 - unchecked
            # 1 - partially checked (invalid)
            # 2 - checked
            if is_checked and not imain_set:
                # TODO: change this to a log
                #self.window_parent.log
                imain_set = True
                imain = irow
                name_text.setFont(bold)
                name_text.setBackground(QtGui.QColor(*self.light_grey))
                self.shown_set.add(irow)
            elif irow == self.imain:
                name_text.setFont(normal)
                if irow == 0:
                    name_text.setBackground(QtGui.QColor(*self.white))
                    if irow in self.shown_set:
                        self.shown_set.remove(irow)
                elif imain == 0:
                    name_text.setBackground(QtGui.QColor(*self.white))
                    self.shown_set.remove(imain)
        self.imain = imain

    def get_main_group(self):
        return self.imain

    def get_shown_group(self):
        return self.shown_set

    def get_deleted_groups(self):
        return self.deleted_groups

    def on_validate(self):
        flag0 = flag1 = flag2 = True
        main_group_id = self.get_main_group()
        shown_groups_ids = self.get_shown_group()
        deleted_group_ids = self.get_deleted_groups()

        if flag0 and flag1 and flag2:
            self.out_data['imain'] = main_group_id
            self.out_data['shown'] = shown_groups_ids
            self.out_data['remove'] = deleted_group_ids
            self.out_data['clicked_ok'] = True
            return True
        return False

    def on_apply(self):
        passed = self.on_validate()
        if passed:
            self.win_parent.on_post_group(self.out_data)

    def on_ok(self):
        passed = self.on_validate()
        if passed:
            self.close()
            #self.destroy()

    def on_cancel(self):
        self.close()
Пример #50
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)
Пример #51
0
class UpdateDialog(QDialog):

    def __init__(self, update_script):
        super(UpdateDialog, self).__init__(None, Qt.Window)
        self.updates_to_run = []
        self.setWindowTitle("emzed updates")
        self.setWindowModality(Qt.WindowModal)
        self.setMinimumWidth(600)
        self.update_script = update_script
        self.setup_widgets()
        self.setup_layout()
        self.connect_signals()

        wd = QApplication.desktop().width()
        hd = QApplication.desktop().height()
        w = self.size().width()
        h = self.size().height()
        self.move((wd - w) / 2, (hd - h) / 2)

    def showEvent(self, evt):

        self.setCursor(Qt.WaitCursor)

        class WorkerThread(QThread):

            def run(self, script=self.update_script, parent=self):
                try:
                    for method, args in script(parent.add_info_line, parent.add_update_info):
                        self.emit(SIGNAL("execute_method(PyQt_PyObject, PyQt_PyObject)"), method, args)
                except:
                    import traceback
                    tb = traceback.format_exc()
                    self.emit(SIGNAL("execute_method(PyQt_PyObject, PyQt_PyObject)"), parent.add_info_line, (tb,))
                self.emit(SIGNAL("update_query_finished()"))


        self.t = WorkerThread()
        self.connect(self.t, SIGNAL("update_query_finished()"), self.start_to_interact)
        self.connect(
            self.t, SIGNAL("execute_method(PyQt_PyObject,PyQt_PyObject)"), self.execute_method)

        try:
            self.t.start()
        finally:
            self.setCursor(Qt.ArrowCursor)

    def execute_method(self, meth, args):
        meth(*args)

    def start_to_interact(self):
        self.ok_button.setEnabled(True)

    def setup_widgets(self):
        self.label_info = QLabel("updates from exchange folder:")
        self.info = QTextEdit(self)
        self.info.setReadOnly(1)

        self.label_updates = QLabel("updates from internet:")
        self.updates = QTableWidget(0, 3)
        self.updates.setHorizontalHeaderLabels(["updater", "info", "try updatde ?"])
        self.updates.verticalHeader().hide()
        self.updates.horizontalHeader().setResizeMode(0, QHeaderView.Stretch)
        self.updates.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)

        self.ok_button = QPushButton("OK")
        self.ok_button.setEnabled(False)

    def setup_layout(self):
        layout = QVBoxLayout()
        self.setLayout(layout)
        layout.addWidget(self.label_info)
        layout.addWidget(self.info)
        layout.addWidget(self.label_updates)
        layout.addWidget(self.updates)
        button_layout = QHBoxLayout()
        button_layout.addStretch()
        button_layout.addWidget(self.ok_button)
        layout.addLayout(button_layout)

    def connect_signals(self):
        self.connect(self.ok_button, SIGNAL("pressed()"), self.accept)

    def ok_button_pressed(self):
        self.info.append("hi")
        self.add_update_info("updater", "info")

    def _item(self, content, is_checkable):
        item = QTableWidgetItem(str(content))
        if is_checkable:
            item.setCheckState(Qt.Unchecked)
        item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsSelectable)
        return item

    def add_update_info(self, updater_id, info, with_checkbox=True):
        i = self.updates.rowCount()
        self.updates.insertRow(i)
        self.updates.setItem(i, 0, self._item(updater_id, False))
        self.updates.setItem(i, 1, self._item(info, False))
        if True or with_checkbox:
            self.updates.setItem(i, 2, self._item("", True))

    def add_info_line(self, txt):
        self.info.append(txt)

    def get_updates_to_run(self):
        return self.updates_to_run

    def accept(self):
        for i in range(self.updates.rowCount()):
            updater_id = str(self.updates.item(i, 0).text())
            item = self.updates.item(i, 2)
            if item is not None:  # some cells in column are empty
                checked = self.updates.item(i, 2).checkState() == Qt.Checked
                if checked:
                    self.updates_to_run.append(updater_id)
        super(UpdateDialog, self).accept()
Пример #52
0
class UpdateDialog(QDialog):

    def __init__(self, update_script):
        super(UpdateDialog, self).__init__(None, Qt.Window)
        self.updates_to_run = []
        self.setWindowTitle("emzed updates")
        self.setWindowModality(Qt.WindowModal)
        self.setMinimumWidth(600)
        self.update_script = update_script
        self.setup_widgets()
        self.setup_layout()
        self.connect_signals()

        wd = QApplication.desktop().width()
        hd = QApplication.desktop().height()
        w = self.size().width()
        h = self.size().height()
        self.move((wd - w) / 2, (hd - h) / 2)

    def showEvent(self, evt):

        self.setCursor(Qt.WaitCursor)

        class WorkerThread(QThread):

            def run(self, script=self.update_script, parent=self):
                try:
                    for method, args in script(parent.add_info_line, parent.add_update_info):
                        self.emit(SIGNAL("execute_method(PyQt_PyObject, PyQt_PyObject)"), method, args)
                except:
                    import traceback
                    tb = traceback.format_exc()
                    self.emit(SIGNAL("execute_method(PyQt_PyObject, PyQt_PyObject)"), parent.add_info_line, (tb,))
                self.emit(SIGNAL("update_query_finished()"))


        self.t = WorkerThread()
        self.connect(self.t, SIGNAL("update_query_finished()"), self.start_to_interact)
        self.connect(
            self.t, SIGNAL("execute_method(PyQt_PyObject,PyQt_PyObject)"), self.execute_method)

        try:
            self.t.start()
        finally:
            self.setCursor(Qt.ArrowCursor)

    def execute_method(self, meth, args):
        meth(*args)

    def start_to_interact(self):
        self.ok_button.setEnabled(True)

    def setup_widgets(self):
        self.label_info = QLabel("updates from exchange folder:")
        self.info = QTextEdit(self)
        self.info.setReadOnly(1)

        self.label_updates = QLabel("updates from internet:")
        self.updates = QTableWidget(0, 3)
        self.updates.setHorizontalHeaderLabels(["updater", "info", "try updatde ?"])
        self.updates.verticalHeader().hide()
        self.updates.horizontalHeader().setResizeMode(0, QHeaderView.Stretch)
        self.updates.horizontalHeader().setResizeMode(1, QHeaderView.Stretch)

        self.ok_button = QPushButton("OK")
        self.ok_button.setEnabled(False)

    def setup_layout(self):
        layout = QVBoxLayout()
        self.setLayout(layout)
        layout.addWidget(self.label_info)
        layout.addWidget(self.info)
        layout.addWidget(self.label_updates)
        layout.addWidget(self.updates)
        button_layout = QHBoxLayout()
        button_layout.addStretch()
        button_layout.addWidget(self.ok_button)
        layout.addLayout(button_layout)

    def connect_signals(self):
        self.connect(self.ok_button, SIGNAL("pressed()"), self.accept)

    def ok_button_pressed(self):
        self.info.append("hi")
        self.add_update_info("updater", "info")

    def _item(self, content, is_checkable):
        item = QTableWidgetItem(content)
        if is_checkable:
            item.setCheckState(Qt.Unchecked)
        item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsSelectable)
        return item

    def add_update_info(self, updater_id, info, with_checkbox=True):
        i = self.updates.rowCount()
        self.updates.insertRow(i)
        self.updates.setItem(i, 0, self._item(updater_id, False))
        self.updates.setItem(i, 1, self._item(info, False))
        if True or with_checkbox:
            self.updates.setItem(i, 2, self._item("", True))

    def add_info_line(self, txt):
        self.info.append(txt)

    def get_updates_to_run(self):
        return self.updates_to_run

    def accept(self):
        for i in range(self.updates.rowCount()):
            updater_id = str(self.updates.item(i, 0).text())
            item = self.updates.item(i, 2)
            if item is not None:  # some cells in column are empty
                checked = self.updates.item(i, 2).checkState() == Qt.Checked
                if checked:
                    self.updates_to_run.append(updater_id)
        super(UpdateDialog, self).accept()
Пример #53
0
class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        logging.info(u'创建主窗口...')

        QtGui.QMainWindow.__init__(self, parent)

        tabs = QtGui.QTabWidget(self)

        tab2 = QtGui.QWidget()
        tab3 = QtGui.QWidget()

        self.console = MyConsole(parent=self)

        # tab2 - self.console
        self.console.setMinimumSize(1500, 800)
        scroll = QtGui.QScrollArea()
        scroll.setWidget(self.console)
        scroll.setAutoFillBackground(True)
        scroll.setWidgetResizable(True)
        vbox = QtGui.QVBoxLayout()
        vbox.addWidget(scroll)
        tab2.setLayout(vbox)

        # tab3 -
        self.viewEntry = QTableWidget(0, 12)
        self.viewEntry.setHorizontalHeaderLabels(
                [u'期数', u'时间', u'冠军', u'亚军', u'第三名', u'第四名', u'第五名', u'第六名', u'第七名', u'第八名', u'第九名', u'第十名'])
        self.viewEntry.horizontalHeader().setStretchLastSection(True)
        self.viewEntry.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)

        vbox3 = QtGui.QVBoxLayout()
        vbox3.addWidget(self.viewEntry)
        tab3.setLayout(vbox3)
        tabs.addTab(tab2, u"控制台")
        tabs.addTab(tab3, u"开奖结果")

        tabs.resize(1500, 800)
        self.resize(1500, 800)
        self.tabs = tabs
        self.tab2 = tab2
        self.tab3 = tab3
        self.scroll = scroll
        # 禁止最大化
        self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)

        from myutil.tool.Overlay import Overlay
        self.setCentralWidget(self.tabs)
        self.overlay = Overlay(self.centralWidget())
        self.overlay.hide()

        self.show()

    @pyqtSlot(str)
    def mySetWindowTitle(self, title):
        self.setWindowTitle(title)

    @pyqtSlot(str, list)
    def completeHistoryResultData(self, timesnow, open_balls):
        logging.info(u"【主窗口-历史数据展板-填充之】")
        for i in range(len(open_balls)):
            newItem = QTableWidgetItem(str(open_balls[i]))
            self.viewEntry.setItem(0, 2 + i, newItem)
        logging.info(u"【主窗口-历史数据展板-填充完毕】")

    @pyqtSlot(str, list)
    def appendHistoryResultData(self, timesnow, open_balls):
        logging.info(u"【主窗口-历史数据展板-追加】")
        time_str = MyTool.getCurrentTimeStr()
        self.viewEntry.insertRow(0)
        # 期数
        newItem = QTableWidgetItem(str(int(timesnow) - 1))
        self.viewEntry.setItem(0, 0, newItem)
        # 时间
        newItem = QTableWidgetItem(time_str)
        self.viewEntry.setItem(0, 1, newItem)

        for i in range(len(open_balls)):
            newItem = QTableWidgetItem(str(open_balls[i]))
            self.viewEntry.setItem(0, 2 + i, newItem)
        logging.info(u"【主窗口-历史数据展板-追加完毕】")

    @pyqtSlot(list)
    def updateHistoryResultData(self, data_list):
        logging.info(u"【主窗口-历史数据展板-大更新】################START HistoryResultData################")
        # 先清空...
        self.viewEntry.clearContents()
        self.viewEntry.setRowCount(0)

        for period in data_list:
            # 添加一行
            row = self.viewEntry.rowCount()
            self.viewEntry.insertRow(row)

            # 期数
            newItem = QTableWidgetItem(period[0])
            self.viewEntry.setItem(row, 0, newItem)

            # 时间
            newItem = QTableWidgetItem(str(period[1]))
            self.viewEntry.setItem(row, 1, newItem)
            if self.console.play_mode in [common.PLAYMODE_PK10, common.PLAYMODE_XYFT]:
                for i in range(10):
                    newItem = QTableWidgetItem(str(period[2 + i]))
                    self.viewEntry.setItem(row, 2 + i, newItem)
            else:
                for i in range(5):
                    newItem = QTableWidgetItem(str(period[2 + i]))
                    self.viewEntry.setItem(row, 2 + i, newItem)

        logging.info(u"【主窗口-历史数据展板-大更新】################END HistoryResultData################")

    def closeEvent(self, event):
        reply = QtGui.QMessageBox.question(self, u'退出', u"您确定离开吗?", QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
        if reply == QtGui.QMessageBox.Yes:
            # 关闭http连接...
            from common.common import req_session
            req_session.close()

            event.accept()
        else:
            event.ignore()

    def resizeEvent(self, event):
        self.overlay.resize(event.size())
        event.accept()
Пример #54
0
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()
Пример #55
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()
Пример #56
0
class OWdabam_height_profile(OWWidget):
    name = "DABAM Height Profile"
    id = "dabam_height_profile"
    description = "Calculation of mirror surface error profile"
    icon = "icons/dabam.png"
    author = "Luca Rebuffi"
    maintainer_email = "[email protected]; [email protected]"
    priority = 6
    category = ""
    keywords = ["dabam_height_profile"]

    outputs = [{"name": "PreProcessor_Data",
                "type": ShadowPreProcessorData,
                "doc": "PreProcessor Data",
                "id": "PreProcessor_Data"}]

    want_main_area = 1
    want_control_area = 1

    MAX_WIDTH = 1320
    MAX_HEIGHT = 700

    IMAGE_WIDTH = 860
    IMAGE_HEIGHT = 645

    CONTROL_AREA_WIDTH = 405
    TABS_AREA_HEIGHT = 618

    xx = None
    yy = None
    zz = None

    entry_number = Setting(1)

    shape=Setting(0)
    slope_error_from = Setting(0.0)
    slope_error_to = Setting(1.5)
    dimension_y_from = Setting(0.0)
    dimension_y_to = Setting(200.0)

    use_undetrended = Setting(0)

    step_x = Setting(1.0)
    dimension_x = Setting(10.0)

    center_y = Setting(1)
    modify_y = Setting(0)
    new_length = Setting(200.0)
    filler_value = Setting(0.0)

    scale_factor_y = Setting(1.0)
    renormalize_y = Setting(1)
    error_type_y = Setting(0)
    rms_y = Setting(0.9)

    dabam_profile_index = Setting(1)

    heigth_profile_file_name = Setting('mirror.dat')

    tab=[]

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

        self.runaction = widget.OWAction("Calculate Height Profile", self)
        self.runaction.triggered.connect(self.calculate_heigth_profile_ni)
        self.addAction(self.runaction)

        self.runaction = widget.OWAction("Generate Height Profile File", self)
        self.runaction.triggered.connect(self.generate_heigth_profile_file_ni)
        self.addAction(self.runaction)

        geom = QApplication.desktop().availableGeometry()
        self.setGeometry(QRect(round(geom.width() * 0.05),
                               round(geom.height() * 0.05),
                               round(min(geom.width() * 0.98, self.MAX_WIDTH)),
                               round(min(geom.height() * 0.95, self.MAX_HEIGHT))))

        self.setMaximumHeight(self.geometry().height())
        self.setMaximumWidth(self.geometry().width())

        # DABAM INITIALIZATION
        self.server = dabam.dabam()
        self.server.set_input_silent(True)

        gui.separator(self.controlArea)

        button_box = oasysgui.widgetBox(self.controlArea, "", addSpace=False, orientation="horizontal")

        button = gui.button(button_box, self, "Calculate Height\nProfile", callback=self.calculate_heigth_profile)
        button.setFixedHeight(45)

        button = gui.button(button_box, self, "Generate Height\nProfile File", callback=self.generate_heigth_profile_file)
        font = QFont(button.font())
        font.setBold(True)
        button.setFont(font)
        palette = QPalette(button.palette())  # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('Dark Blue'))
        button.setPalette(palette)  # assign new palette
        button.setFixedHeight(45)
        button.setFixedWidth(150)

        button = gui.button(button_box, self, "Reset Fields", callback=self.call_reset_settings)
        font = QFont(button.font())
        font.setItalic(True)
        button.setFont(font)
        palette = QPalette(button.palette())  # make a copy of the palette
        palette.setColor(QPalette.ButtonText, QColor('Dark Red'))
        button.setPalette(palette)  # assign new palette
        button.setFixedHeight(45)

        gui.separator(self.controlArea)

        tabs_setting = gui.tabWidget(self.controlArea)
        tabs_setting.setFixedHeight(self.TABS_AREA_HEIGHT)
        tabs_setting.setFixedWidth(self.CONTROL_AREA_WIDTH-5)

        tab_input = oasysgui.createTabPage(tabs_setting, "DABAM Search Setting")
        tab_gener = oasysgui.createTabPage(tabs_setting, "DABAM Generation Setting")
        tab_out = oasysgui.createTabPage(tabs_setting, "Output")

        manual_box = oasysgui.widgetBox(tab_input, "Manual Entry", addSpace=True, orientation="vertical")

        oasysgui.lineEdit(manual_box, self, "entry_number", "Entry Number",
                           labelWidth=300, valueType=int, orientation="horizontal")

        gui.separator(manual_box)

        button = gui.button(manual_box, self, "Retrieve Profile", callback=self.retrieve_profile)
        button.setFixedHeight(35)
        button.setFixedWidth(self.CONTROL_AREA_WIDTH-35)

        input_box = oasysgui.widgetBox(tab_input, "Search Parameters", addSpace=True, orientation="vertical")

        gui.comboBox(input_box, self, "shape", label="Mirror Shape", labelWidth=300,
                     items=["All", "Plane", "Cylindrical", "Elliptical", "Toroidal", "Spherical"],
                     sendSelectedValue=False, orientation="horizontal")

        gui.separator(input_box)
        
        input_box_1 = oasysgui.widgetBox(input_box, "", addSpace=True, orientation="horizontal")

        oasysgui.lineEdit(input_box_1, self, "slope_error_from", "Slope Error From (" + u"\u03BC" + "rad)",
                           labelWidth=150, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(input_box_1, self, "slope_error_to", "To (" + u"\u03BC" + "rad)",
                           labelWidth=60, valueType=float, orientation="horizontal")

        input_box_2 = oasysgui.widgetBox(input_box, "", addSpace=True, orientation="horizontal")

        self.le_dimension_y_from = oasysgui.lineEdit(input_box_2, self, "dimension_y_from", "Mirror Length From",
                           labelWidth=150, valueType=float, orientation="horizontal")
        self.le_dimension_y_to = oasysgui.lineEdit(input_box_2, self, "dimension_y_to", "To",
                           labelWidth=60, valueType=float, orientation="horizontal")

        table_box = oasysgui.widgetBox(tab_input, "Search Results", addSpace=True, orientation="vertical", height=290)

        self.overlay_search = Overlay(table_box, self.search_profiles)
        self.overlay_search.hide()

        button = gui.button(input_box, self, "Search", callback=self.overlay_search.show)
        button.setFixedHeight(35)
        button.setFixedWidth(self.CONTROL_AREA_WIDTH-35)

        gui.comboBox(table_box, self, "use_undetrended", label="Use Undetrended Profile", labelWidth=300,
                     items=["No", "Yes"], callback=self.table_item_clicked, sendSelectedValue=False, orientation="horizontal")

        gui.separator(table_box)

        self.scrollarea = QScrollArea()
        self.scrollarea.setMinimumWidth(self.CONTROL_AREA_WIDTH-35)

        table_box.layout().addWidget(self.scrollarea, alignment=Qt.AlignHCenter)

        self.table = QTableWidget(1, 5)
        self.table.setAlternatingRowColors(True)
        self.table.horizontalHeader().setResizeMode(QHeaderView.Fixed)
        self.table.verticalHeader().setVisible(False)

        self.table.setColumnWidth(0, 40)
        self.table.setColumnWidth(1, 70)
        self.table.setColumnWidth(2, 70)
        self.table.setColumnWidth(3, 85)
        self.table.setColumnWidth(4, 80)

        self.table.resizeRowsToContents()
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.table.itemClicked.connect(self.table_item_clicked)

        self.scrollarea.setWidget(self.table)
        self.scrollarea.setWidgetResizable(1)

        output_profile_box = oasysgui.widgetBox(tab_gener, "Surface Generation Parameters", addSpace=True, orientation="vertical", height=270)

        self.le_dimension_x = oasysgui.lineEdit(output_profile_box, self, "dimension_x", "Width",
                           labelWidth=300, valueType=float, orientation="horizontal")
        self.le_step_x = oasysgui.lineEdit(output_profile_box, self, "step_x", "Step Width",
                           labelWidth=300, valueType=float, orientation="horizontal")

        gui.comboBox(output_profile_box, self, "center_y", label="Center Profile in the middle of O.E.", labelWidth=300,
                     items=["No", "Yes"], sendSelectedValue=False, orientation="horizontal")

        gui.comboBox(output_profile_box, self, "modify_y", label="Modify Length?", labelWidth=240,
                     items=["No", "Rescale to new length", "Fit to new length (fill or cut)"], callback=self.set_ModifyY, sendSelectedValue=False, orientation="horizontal")

        self.modify_box_1 = oasysgui.widgetBox(output_profile_box, "", addSpace=False, orientation="vertical", height=50)

        self.modify_box_2 = oasysgui.widgetBox(output_profile_box, "", addSpace=False, orientation="vertical", height=50)
        oasysgui.lineEdit(self.modify_box_2, self, "scale_factor_y", "Scale Factor", labelWidth=300, valueType=float, orientation="horizontal")

        self.modify_box_3 = oasysgui.widgetBox(output_profile_box, "", addSpace=False, orientation="vertical", height=50)
        self.le_new_length = oasysgui.lineEdit(self.modify_box_3, self, "new_length", "New Length", labelWidth=300, valueType=float, orientation="horizontal")
        oasysgui.lineEdit(self.modify_box_3, self, "filler_value", "Filler Value (if new length > profile length) [nm]", labelWidth=300, valueType=float, orientation="horizontal")

        self.set_ModifyY()

        gui.comboBox(output_profile_box, self, "renormalize_y", label="Renormalize Length Profile to different RMS", labelWidth=300,
                     items=["No", "Yes"], callback=self.set_RenormalizeY, sendSelectedValue=False, orientation="horizontal")

        self.output_profile_box_1 = oasysgui.widgetBox(output_profile_box, "", addSpace=True, orientation="vertical")

        gui.comboBox(self.output_profile_box_1, self, "error_type_y", label="Normalization to", labelWidth=270,
                     items=["Figure Error (nm)", "Slope Error (" + u"\u03BC" + "rad)"],
                     sendSelectedValue=False, orientation="horizontal")

        oasysgui.lineEdit(self.output_profile_box_1, self, "rms_y", "Rms Value",
                           labelWidth=300, valueType=float, orientation="horizontal")

        self.set_RenormalizeY()

        output_box = oasysgui.widgetBox(tab_gener, "Outputs", addSpace=True, orientation="vertical")

        select_file_box = oasysgui.widgetBox(output_box, "", addSpace=True, orientation="horizontal")

        self.le_heigth_profile_file_name = oasysgui.lineEdit(select_file_box, self, "heigth_profile_file_name", "Output File Name",
                                                        labelWidth=120, valueType=str, orientation="horizontal")

        gui.button(select_file_box, self, "...", callback=self.selectFile)

        self.shadow_output = QTextEdit()
        self.shadow_output.setReadOnly(True)

        out_box = oasysgui.widgetBox(tab_out, "System Output", addSpace=True, orientation="horizontal", height=500)
        out_box.layout().addWidget(self.shadow_output)

        gui.rubber(self.controlArea)

        self.initializeTabs()

        gui.rubber(self.mainArea)

        self.overlay_search.raise_()

    def resizeEvent(self, event):
        self.overlay_search.resize(self.CONTROL_AREA_WIDTH - 15, 290)
        event.accept()

    def after_change_workspace_units(self):
        self.si_to_user_units = 1e2 / self.workspace_units_to_cm

        self.horHeaders = ["Entry", "Shape", "Length\n[" + self.workspace_units_label + "]", "Heights St.Dev.\n[nm]",  "Slopes St.Dev.\n[" + u"\u03BC" + "rad]"]
        self.table.setHorizontalHeaderLabels(self.horHeaders)
        self.plot_canvas[0].setGraphXLabel("Y [" + self.workspace_units_label + "]")
        self.plot_canvas[1].setGraphXLabel("Y [" + self.workspace_units_label + "]")
        self.axis.set_xlabel("X [" + self.workspace_units_label + "]")
        self.axis.set_ylabel("Y [" + self.workspace_units_label + "]")

        label = self.le_dimension_y_from.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_dimension_y_to.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_dimension_x.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_step_x.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")
        label = self.le_new_length.parent().layout().itemAt(0).widget()
        label.setText(label.text() + " [" + self.workspace_units_label + "]")

    def initializeTabs(self):
        self.tabs = gui.tabWidget(self.mainArea)

        self.tab = [gui.createTabPage(self.tabs, "Info"),
                    gui.createTabPage(self.tabs, "Heights Profile"),
                    gui.createTabPage(self.tabs, "Slopes Profile"),
                    gui.createTabPage(self.tabs, "PSD Heights"),
                    gui.createTabPage(self.tabs, "CSD Heights"),
                    gui.createTabPage(self.tabs, "ACF"),
                    gui.createTabPage(self.tabs, "Generated 2D Profile"),
        ]

        for tab in self.tab:
            tab.setFixedHeight(self.IMAGE_HEIGHT)
            tab.setFixedWidth(self.IMAGE_WIDTH)

        self.plot_canvas = [None, None, None, None, None, None]

        self.plot_canvas[0] = PlotWindow(roi=False, control=False, position=True, plugins=False)
        self.plot_canvas[0].setDefaultPlotLines(True)
        self.plot_canvas[0].setActiveCurveColor(color='darkblue')
        self.plot_canvas[0].setGraphYLabel("Z [nm]")
        self.plot_canvas[0].setGraphTitle("Heights Profile")
        self.plot_canvas[0].setDrawModeEnabled(True, 'rectangle')
        self.plot_canvas[0].setZoomModeEnabled(True)

        self.plot_canvas[1] = PlotWindow(roi=False, control=False, position=True, plugins=False)
        self.plot_canvas[1].setDefaultPlotLines(True)
        self.plot_canvas[1].setActiveCurveColor(color='darkblue')
        self.plot_canvas[1].setGraphYLabel("Zp [$\mu$rad]")
        self.plot_canvas[1].setGraphTitle("Slopes Profile")
        self.plot_canvas[1].setDrawModeEnabled(True, 'rectangle')
        self.plot_canvas[1].setZoomModeEnabled(True)

        self.plot_canvas[2] = PlotWindow(roi=False, control=False, position=True, plugins=False)
        self.plot_canvas[2].setDefaultPlotLines(True)
        self.plot_canvas[2].setActiveCurveColor(color='darkblue')
        self.plot_canvas[2].setGraphXLabel("f [m^-1]")
        self.plot_canvas[2].setGraphYLabel("PSD [m^3]")
        self.plot_canvas[2].setGraphTitle("Power Spectral Density of Heights Profile")
        self.plot_canvas[2].setDrawModeEnabled(True, 'rectangle')
        self.plot_canvas[2].setZoomModeEnabled(True)
        self.plot_canvas[2].setXAxisLogarithmic(True)
        self.plot_canvas[2].setYAxisLogarithmic(True)

        self.plot_canvas[3] = PlotWindow(roi=False, control=False, position=True, plugins=False)
        self.plot_canvas[3].setDefaultPlotLines(True)
        self.plot_canvas[3].setActiveCurveColor(color='darkblue')
        self.plot_canvas[3].setGraphXLabel("f [m^-1]")
        self.plot_canvas[3].setGraphYLabel("CSD [m^3]")
        self.plot_canvas[3].setGraphTitle("Cumulative Spectral Density of Heights Profile")
        self.plot_canvas[3].setDrawModeEnabled(True, 'rectangle')
        self.plot_canvas[3].setZoomModeEnabled(True)
        self.plot_canvas[3].setXAxisLogarithmic(True)

        self.plot_canvas[4] = PlotWindow(roi=False, control=False, position=True, plugins=False)
        self.plot_canvas[4].setDefaultPlotLines(True)
        self.plot_canvas[4].setActiveCurveColor(color='darkblue')
        self.plot_canvas[4].setGraphXLabel("Length [m]")
        self.plot_canvas[4].setGraphYLabel("ACF")
        self.plot_canvas[4].setGraphTitle("Autocovariance Function of Heights Profile")
        self.plot_canvas[4].setDrawModeEnabled(True, 'rectangle')
        self.plot_canvas[4].setZoomModeEnabled(True)

        self.figure = Figure(figsize=(self.IMAGE_HEIGHT, self.IMAGE_HEIGHT)) # QUADRATA!
        self.figure.patch.set_facecolor('white')

        self.axis = self.figure.add_subplot(111, projection='3d')

        self.axis.set_zlabel("Z [nm]")

        self.plot_canvas[5] = FigureCanvasQTAgg(self.figure)

        self.profileInfo = QTextEdit()
        self.profileInfo.setReadOnly(True)
        self.profileInfo.setMinimumHeight(self.IMAGE_HEIGHT-5)
        self.profileInfo.setMaximumHeight(self.IMAGE_HEIGHT-5)
        self.profileInfo.setMinimumWidth(310)
        self.profileInfo.setMaximumWidth(310)

        profile_box = oasysgui.widgetBox(self.tab[0], "", addSpace=True, orientation="horizontal", height = self.IMAGE_HEIGHT, width=320)
        profile_box.layout().addWidget(self.profileInfo)

        for index in range(0, 6):
            self.tab[index+1].layout().addWidget(self.plot_canvas[index])

        self.tabs.setCurrentIndex(1)

    def plot_dabam_graph(self, plot_canvas_index, curve_name, x_values, y_values, xtitle, ytitle, color='blue', replace=True):
        self.plot_canvas[plot_canvas_index].addCurve(x_values, y_values, curve_name, symbol='', color=color, replace=replace) #'+', '^', ','
        self.plot_canvas[plot_canvas_index].setGraphXLabel(xtitle)
        self.plot_canvas[plot_canvas_index].setGraphYLabel(ytitle)
        self.plot_canvas[plot_canvas_index].replot()

    def set_ModifyY(self):
        self.modify_box_1.setVisible(self.modify_y == 0)
        self.modify_box_2.setVisible(self.modify_y == 1)
        self.modify_box_3.setVisible(self.modify_y == 2)

    def set_RenormalizeY(self):
        self.output_profile_box_1.setVisible(self.renormalize_y==1)

    def table_item_clicked(self):
        if self.table.selectionModel().hasSelection():
            if not self.table.rowCount() == 0:
                if not self.table.item(0, 0) is None:
                    row = self.table.selectionModel().selectedRows()[0].row()
                    self.entry_number = int(self.table.item(row, 0).text())

                    self.retrieve_profile()

    def retrieve_profile(self):
        try:
            if self.entry_number is None or self.entry_number <= 0:
                raise Exception("Entry number should be a strictly positive integer number")

            self.server.load(self.entry_number)
            self.profileInfo.setText(self.server.info_profiles())
            self.plot_canvas[0].setGraphTitle(
                "Heights Profile. St.Dev.=%.3f nm" % (self.server.stdev_profile_heights() * 1e9))
            self.plot_canvas[1].setGraphTitle(
                "Slopes Profile. St.Dev.=%.3f $\mu$rad" % (self.server.stdev_profile_slopes() * 1e6))
            if self.use_undetrended == 0:
                self.plot_dabam_graph(0, "heights_profile", self.si_to_user_units * self.server.y,
                                      1e9 * self.server.zHeights, "Y [" + self.workspace_units_label + "]", "Z [nm]")
                self.plot_dabam_graph(1, "slopes_profile", self.si_to_user_units * self.server.y, 1e6 * self.server.zSlopes,
                                      "Y [" + self.workspace_units_label + "]", "Zp [$\mu$rad]")
            else:
                self.plot_dabam_graph(0, "heights_profile", self.si_to_user_units * self.server.y,
                                      1e9 * self.server.zHeightsUndetrended, "Y [" + self.workspace_units_label + "]",
                                      "Z [nm]")
                self.plot_dabam_graph(1, "slopes_profile", self.si_to_user_units * self.server.y,
                                      1e6 * self.server.zSlopesUndetrended, "Y [" + self.workspace_units_label + "]",
                                      "Zp [$\mu$rad]")
            y = self.server.f ** (self.server.powerlaw["hgt_pendent"]) * 10 ** self.server.powerlaw["hgt_shift"]
            i0 = self.server.powerlaw["index_from"]
            i1 = self.server.powerlaw["index_to"]
            beta = -self.server.powerlaw["hgt_pendent"]
            self.plot_canvas[2].setGraphTitle(
                "Power Spectral Density of Heights Profile (beta=%.2f,Df=%.2f)" % (beta, (5 - beta) / 2))
            self.plot_dabam_graph(2, "psd_heights_2", self.server.f, self.server.psdHeights, "f [m^-1]", "PSD [m^3]")
            self.plot_dabam_graph(2, "psd_heights_1", self.server.f, y, "f [m^-1]", "PSD [m^3]", color='green',
                                  replace=False)
            self.plot_dabam_graph(2, "psd_heights_3", self.server.f[i0:i1], y[i0:i1], "f [m^-1]", "PSD [m^3]", color='red',
                                  replace=False)
            self.plot_dabam_graph(3, "csd", self.server.f, self.server.csd_heights(), "f [m^-1]", "CSD [m^3]")
            c1, c2, c3 = dabam.autocorrelationfunction(self.server.y, self.server.zHeights)
            self.plot_canvas[4].setGraphTitle(
                "Autocovariance Function of Heights Profile.\nAutocorrelation Length (ACF=0.5)=%.3f m" % (c3))
            self.plot_dabam_graph(4, "acf", c1[0:-1], c2, "Length [m]", "Heights Autocovariance")
            # surface error removal
            if not self.zz is None and not self.yy is None and not self.xx is None:
                self.xx = None
                self.yy = None
                self.zz = None
                self.axis.set_title("")
                self.axis.clear()
                self.plot_canvas[5].draw()

            if (self.tabs.currentIndex()==6): self.tabs.setCurrentIndex(1)

        except Exception as exception:
            QMessageBox.critical(self, "Error",
                                 exception.args[0],
                                 QMessageBox.Ok)

            #raise exception


    def search_profiles(self):
        try:
            self.table.itemClicked.disconnect(self.table_item_clicked)
            self.table.clear()

            row_count = self.table.rowCount()
            for n in range(0, row_count):
                self.table.removeRow(0)

            self.table.setHorizontalHeaderLabels(self.horHeaders)

            profiles = dabam.dabam_summary_dictionary(surface=self.get_dabam_shape(),
                                                      slp_err_from=self.slope_error_from*1e-6,
                                                      slp_err_to=self.slope_error_to*1e-6,
                                                      length_from=self.dimension_y_from / self.si_to_user_units,
                                                      length_to=self.dimension_y_to / self.si_to_user_units)

            for index in range(0, len(profiles)):
                self.table.insertRow(0)

            for index in range(0, len(profiles)):
                table_item = QTableWidgetItem(str(profiles[index]["entry"]))
                table_item.setTextAlignment(Qt.AlignCenter)
                self.table.setItem(index, 0, table_item)
                table_item = QTableWidgetItem(str(profiles[index]["surface"]))
                table_item.setTextAlignment(Qt.AlignLeft)
                self.table.setItem(index, 1, table_item)
                table_item = QTableWidgetItem(str(numpy.round(profiles[index]["length"]*self.si_to_user_units, 3)))
                table_item.setTextAlignment(Qt.AlignRight)
                self.table.setItem(index, 2, table_item)
                table_item = QTableWidgetItem(str(numpy.round(profiles[index]["hgt_err"]*1e9, 3)))
                table_item.setTextAlignment(Qt.AlignRight)
                self.table.setItem(index, 3, table_item)
                table_item = QTableWidgetItem(str(numpy.round(profiles[index]["slp_err"]*1e6, 3)))
                table_item.setTextAlignment(Qt.AlignRight)
                self.table.setItem(index, 4, table_item)

            self.table.setHorizontalHeaderLabels(self.horHeaders)
            self.table.resizeRowsToContents()
            self.table.setSelectionBehavior(QAbstractItemView.SelectRows)

            self.table.itemClicked.connect(self.table_item_clicked)

            self.overlay_search.hide()

        except Exception as exception:
            self.overlay_search.hide()

            QMessageBox.critical(self, "Error",
                                 exception.args[0],
                                 QMessageBox.Ok)

    def get_dabam_shape(self):
        if self.shape == 0: return None
        elif self.shape == 1: return "plane"
        elif self.shape == 2: return "cylindrical"
        elif self.shape == 3: return "elliptical"
        elif self.shape == 4: return "toroidal"
        elif self.shape == 5: return "spherical"

    def calculate_heigth_profile_ni(self):
        self.calculate_heigth_profile(not_interactive_mode=True)

    def calculate_heigth_profile(self, not_interactive_mode=False):
        try:
            if self.server.y is None: raise Exception("No Profile Selected")

            sys.stdout = EmittingStream(textWritten=self.writeStdOut)

            self.check_fields()

            combination = "EF"

            if self.modify_y == 2:
                profile_1D_y_x_temp = self.si_to_user_units * self.server.y
                if self.use_undetrended == 0: profile_1D_y_y_temp = self.si_to_user_units * self.server.zHeights
                else: profile_1D_y_y_temp = self.si_to_user_units * self.server.zHeightsUndetrended

                first_coord = profile_1D_y_x_temp[0]
                second_coord  = profile_1D_y_x_temp[1]
                last_coord = profile_1D_y_x_temp[-1]
                step = numpy.abs(second_coord - first_coord)
                length = numpy.abs(last_coord - first_coord)
                n_points_old = len(profile_1D_y_x_temp)

                if self.new_length > length:
                    difference = self.new_length - length

                    n_added_points = int(difference/step)
                    if difference % step == 0:
                        n_added_points += 1
                    if n_added_points % 2 != 0:
                        n_added_points += 1


                    profile_1D_y_x = numpy.arange(n_added_points + n_points_old) * step
                    profile_1D_y_y = numpy.ones(n_added_points + n_points_old) * self.filler_value * 1e-9 * self.si_to_user_units
                    profile_1D_y_y[int(n_added_points/2) : n_points_old + int(n_added_points/2)] = profile_1D_y_y_temp
                elif self.new_length < length:
                    difference = length - self.new_length

                    n_removed_points = int(difference/step)
                    if difference % step == 0:
                        n_removed_points -= 1
                    if n_removed_points % 2 != 0:
                        n_removed_points -= 1

                    if n_removed_points >= 2:
                        profile_1D_y_x = profile_1D_y_x_temp[0 : (n_points_old - n_removed_points)]
                        profile_1D_y_y = profile_1D_y_y_temp[(int(n_removed_points/2) - 1) : (n_points_old - int(n_removed_points/2) - 1)]

                    else:
                        profile_1D_y_x = profile_1D_y_x_temp
                        profile_1D_y_y = profile_1D_y_y_temp
                else:
                    profile_1D_y_x = profile_1D_y_x_temp
                    profile_1D_y_y = profile_1D_y_y_temp

            else:
                if self.modify_y == 0:
                    profile_1D_y_x = self.si_to_user_units * self.server.y
                elif self.modify_y == 1:
                    profile_1D_y_x = self.si_to_user_units * self.server.y * self.scale_factor_y

                if self.use_undetrended == 0: profile_1D_y_y = self.si_to_user_units * self.server.zHeights
                else: profile_1D_y_y = self.si_to_user_units * self.server.zHeightsUndetrended


            if self.center_y:
                first_coord = profile_1D_y_x[0]
                last_coord = profile_1D_y_x[-1]
                length = numpy.abs(last_coord - first_coord)

                profile_1D_y_x_temp = numpy.linspace(-length/2, length/2, len(profile_1D_y_x))

                profile_1D_y_x = profile_1D_y_x_temp

            if self.renormalize_y == 0:
                rms_y = None
            else:
                if self.error_type_y == profiles_simulation.FIGURE_ERROR:
                    rms_y = self.si_to_user_units * self.rms_y * 1e-9   # from nm to user units
                else:
                    rms_y = self.rms_y * 1e-6 # from urad to rad

            xx, yy, zz = profiles_simulation.simulate_profile_2D(combination = combination,
                                                                 error_type_l = self.error_type_y,
                                                                 rms_l = rms_y,
                                                                 x_l = profile_1D_y_x,
                                                                 y_l = profile_1D_y_y,
                                                                 mirror_width = self.dimension_x,
                                                                 step_w = self.step_x,
                                                                 rms_w = 0.0)

            self.xx = xx
            self.yy = yy
            self.zz = zz # in user units

            self.axis.clear()

            x_to_plot, y_to_plot = numpy.meshgrid(xx, yy)
            z_to_plot = zz * 1e9 / self.si_to_user_units #nm

            self.axis.plot_surface(x_to_plot, y_to_plot, z_to_plot,
                                   rstride=1, cstride=1, cmap=cm.autumn, linewidth=0.5, antialiased=True)

            sloperms = profiles_simulation.slopes(zz.T, xx, yy, return_only_rms=1)

            title = ' Slope error rms in X direction: %f $\mu$rad' % (sloperms[0]*1e6) + '\n' + \
                    ' Slope error rms in Y direction: %f $\mu$rad' % (sloperms[1]*1e6)

            self.axis.set_xlabel("X [" + self.workspace_units_label + "]")
            self.axis.set_ylabel("Y [" + self.workspace_units_label + "]")
            self.axis.set_zlabel("Z [nm]")

            self.axis.set_title(title)
            self.axis.mouse_init()

            if not not_interactive_mode:
                try:
                    self.plot_canvas[5].draw()
                except:
                    pass

                self.tabs.setCurrentIndex(6)

                QMessageBox.information(self, "QMessageBox.information()",
                                        "Height Profile calculated: if the result is satisfactory,\nclick \'Generate Height Profile File\' to complete the operation ",
                                        QMessageBox.Ok)
        except Exception as exception:
            QMessageBox.critical(self, "Error",
                                 exception.args[0],
                                 QMessageBox.Ok)

            #raise exception

    def generate_heigth_profile_file_ni(self):
        self.generate_heigth_profile_file(not_interactive_mode=True)

    def generate_heigth_profile_file(self, not_interactive_mode=False):
        if not self.zz is None and not self.yy is None and not self.xx is None:
            try:
                congruence.checkDir(self.heigth_profile_file_name)

                sys.stdout = EmittingStream(textWritten=self.writeStdOut)

                ST.write_shadow_surface(self.zz, self.xx, self.yy, outFile=congruence.checkFileName(self.heigth_profile_file_name))
                if not not_interactive_mode:
                    QMessageBox.information(self, "QMessageBox.information()",
                                            "Height Profile file " + self.heigth_profile_file_name + " written on disk",
                                            QMessageBox.Ok)
                if self.modify_y == 0:
                    dimension_y = self.si_to_user_units * (self.server.y[-1] - self.server.y[0])
                if self.modify_y == 1:
                    dimension_y = self.si_to_user_units * (self.server.y[-1] - self.server.y[0]) * self.scale_factor_y
                elif self.modify_y == 2:
                    dimension_y = self.new_length

                self.send("PreProcessor_Data", ShadowPreProcessorData(error_profile_data_file=self.heigth_profile_file_name,
                                                                      error_profile_x_dim=self.dimension_x,
                                                                      error_profile_y_dim=dimension_y))
            except Exception as exception:
                QMessageBox.critical(self, "Error",
                                     exception.args[0],
                                     QMessageBox.Ok)

    def call_reset_settings(self):
        if ConfirmDialog.confirmed(parent=self, message="Confirm Reset of the Fields?"):
            try:
                self.resetSettings()
            except:
                pass

    def check_fields(self):
        self.dimension_x = congruence.checkStrictlyPositiveNumber(self.dimension_x, "Dimension X")
        self.step_x = congruence.checkStrictlyPositiveNumber(self.step_x, "Step X")
        if self.step_x > self.dimension_x/2:
            raise Exception("Step Width should be smaller than or equal to Width/2")
        if self.modify_y == 1:
            self.scale_factor_y = congruence.checkStrictlyPositiveNumber(self.scale_factor_y, "Scale Factor")
        elif self.modify_y == 2:
            self.new_length = congruence.checkStrictlyPositiveNumber(self.new_length, "New Length")

        if self.renormalize_y == 1:
            self.rms_y = congruence.checkPositiveNumber(self.rms_y, "Rms Y")

        congruence.checkDir(self.heigth_profile_file_name)

    def writeStdOut(self, text):
        cursor = self.shadow_output.textCursor()
        cursor.movePosition(QTextCursor.End)
        cursor.insertText(text)
        self.shadow_output.setTextCursor(cursor)
        self.shadow_output.ensureCursorVisible()

    def selectFile(self):
        self.le_heigth_profile_file_name.setText(oasysgui.selectFileFromDialog(self, self.heigth_profile_file_name, "Select Output File", file_extension_filter="Data Files (*.dat)"))
Пример #57
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
Пример #58
0
class PvTunerDlg(QDialog):
    COL = 6
    COL_ELEMENT = 0
    COL_FIELD = 1
    COL_PV = 2
    COL_STEPSIZE = 3
    COL_READBACK = 4
    COL_SETPOINT = 5
    FMT_READBACK = "%.4e"

    def __init__(self, parent=None):
        super(PvTunerDlg, self).__init__(parent)

        self.setAttribute(Qt.WA_DeleteOnClose)

        #self.inputBox = QLineEdit("PL2G2C01A.x")
        #self.inputBox = QLineEdit("CXH2G6C01B.x")
        self.inputBox = QLineEdit("PL2G2C01A")

        addPvBtn = QPushButton("add")

        self.table = QTableWidget(0, PvTunerDlg.COL)
        self.table.setHorizontalHeaderLabels(
            ["Element", "Field", "PV", "Stepsize", "Readback", "setpoint"])
        #self.table.horizontalHeader().setStretchLastSection(True)
        #self.table.setEditTriggers(QAbstractItemView.NoEditTriggers)

        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok)

        box = QGridLayout()
        box.addWidget(self.inputBox, 0, 0)
        box.addWidget(addPvBtn, 0, 1)
        box.addWidget(self.table, 1, 0, 1, 2)
        box.addWidget(buttonBox, 2, 0)

        self.setLayout(box)

        self.pvs_rb = []
        self.pvs_rb_val_flat = []
        self.pvs_sp = []
        self.pvmoni = []
        self.spinbox = []
        self.connect(addPvBtn, SIGNAL("clicked()"), self.addPv)
        self.connect(buttonBox, SIGNAL("accepted()"), self.accept)
        #self.connect(self.table, SIGNAL("cellChanged"), self.updatePv)
        self.connect(buttonBox.button(QDialogButtonBox.Ok),
                     SIGNAL("clicked()"), self.close)
        self.connect(self.table, SIGNAL("cellClicked(int, int)"),
                     self._cell_clicked)

    def _cell_clicked(self, row, column):
        #print row, column
        if column in [self.COL_PV, self.COL_STEPSIZE]:
            item = self.table.item(row, column)
            if not item: return
            item.setFlags(item.flags() | Qt.ItemIsEditable)

    def _appendRecord(self, name):
        vec = name.split('.')
        if len(vec) > 2:
            QMessageBox.critical(None, "ERROR", "format is wrong")
            return

        if len(vec) == 1:
            elem, field = vec[0], 'value'
        elif len(vec) == 2:
            elem, field = vec

        elemobj = hla.getElements(elem)
        if elemobj:
            # pvsrb is a list
            pvsrb = elemobj.pv(field=field, handle='readback')
            self.pvs_rb.append(pvsrb)
            pvssp = elemobj.pv(field=field, handle='setpoint')
            self.pvs_sp.append(pvssp)
        else:
            QMessageBox.critical(None, "ERROR", "element %s not found" % elem)
            return

        # expand one row
        m, n = self.table.rowCount(), self.table.columnCount()
        self.table.insertRow(m)

        # add cells
        item = QTableWidgetItem(elem)
        item.setFlags(item.flags() & (~Qt.ItemIsEditable))
        self.table.setItem(m, self.COL_ELEMENT, item)

        item = QTableWidgetItem(field)
        item.setFlags(item.flags() & (~Qt.ItemIsEditable))
        self.table.setItem(m, self.COL_FIELD, item)

        item = QTableWidgetItem(', '.join(pvsrb))
        #item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled)
        self.table.setItem(m, self.COL_PV, item)

        readval = ['%.4e' % v for v in caget(pvsrb)]
        item = QTableWidgetItem(', '.join(readval))
        item.setFlags(item.flags() & (~Qt.ItemIsEditable))
        self.table.setItem(m, self.COL_READBACK, item)

        # set the stepsize of PV
        stepsize = 0.00001
        if pvssp:
            item = QTableWidgetItem('%f' % stepsize)
            item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            self.table.setItem(m, self.COL_STEPSIZE, item)

            self.spinbox.append(QDoubleSpinBox(self.table))
            self.spinbox[-1].setRange(-100, 100)
            #self.spinbox[-1].setValue(float(10.0))
            self.spinbox[-1].setSingleStep(stepsize)
            self.spinbox[-1].setDecimals(10)

            self.spinbox[-1].valueChanged.connect(self._writePv)

            self.table.setCellWidget(m, self.COL_SETPOINT, self.spinbox[-1])

            sp = float(caget(pvssp)[0])
            #print "setpoint:", pvssp, sp, type(sp)
            self.spinbox[-1].setValue(-1e-5)
            #print "connected", self.spinbox[-1].value()
        else:
            item = self.table.item(m, self.COL_STEPSIZE)
            if item: item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            item = self.table.item(m, self.COL_SETPOINT)
            if item: item.setFlags(item.flags() & (~Qt.ItemIsEditable))
            self.spinbox.append(None)

        self.table.resizeColumnsToContents()

    def addPv(self):
        self._appendRecord(str(self.inputBox.text()))
        self._updateMonitors()

    def minimalSizeHint(self):
        return QSize(800, 600)

    def _writePv(self, v):
        """
        """
        c = QObject.sender(self)
        i = self.spinbox.index(c)
        #print i, c.text(), "changed"

        #print self.pvs_sp[i], v
        caput(self.pvs_sp[i], v)

    def _updateMonitors(self):
        """
        prepare the PV list for camonitor
        """
        #print "Updating monitors"
        pvs = []
        self.pvs_rb_val = []
        for i in range(self.table.rowCount()):
            for j in range(len(self.pvs_rb[i])):
                self.pvs_rb_val.append([i, 0.0])
            pvs.extend(self.pvs_rb[i])

        for p in self.pvmoni:
            p.close()
        self.pvmoni = camonitor(pvs, self._updatePvValues)
        #print self.pvmoni
        #print pvs
        #print self.pvs_rb_val

    def _updatePvValues(self, val, idx):
        #print idx, val
        s = []
        for i, v in enumerate(self.pvs_rb_val):
            if v[0] == self.pvs_rb_val[idx][0]:
                s.append(self.FMT_READBACK % val)
        #print s
        item = self.table.item(self.pvs_rb_val[idx][0], self.COL_READBACK)
        item.setText(','.join(s))

    def closePvMonitors(self):
        #print "Closing PV Monitors"
        for p in self.pvmoni:
            p.close()

        pass

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

    def close(self):
        self.closePvMonitors()
        return True
Пример #59
0
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()