def __init__(self, database, main_spectrum = None):
     super(ReferenceSpectraDialog, self).__init__()
     self.main_spectrum = main_spectrum
     self.ui = Ui_ReferenceSpectraDialog()
     self.ui.setupUi(self)
     self.reference_catalogues = ReferenceCatalogues(database)
     self.full_model = QStandardItemModel()
     self.catalogues_model = QStandardItemModel()
     self.ui.catalogue.setModel(self.catalogues_model)
     self.ui.catalogue.currentTextChanged.connect(lambda txt: self.populate())
     for catname, cat in self.reference_catalogues.catalogues.items():
         row = QStandardItem(catname)
         row.setData(cat)
         self.catalogues_model.appendRow(row)
     
     self.model = QSortFilterProxyModel()
     self.model.setSourceModel(self.full_model)
     self.model.setFilterCaseSensitivity(Qt.CaseInsensitive)
     self.model.setFilterKeyColumn(0)
     self.ui.entries.setModel(self.model)
     self.ui.type_filter.currentTextChanged.connect(lambda txt: self.model.setFilterWildcard("{}*".format(txt) ) )
     self.ui.buttonBox.button(QDialogButtonBox.Open).setEnabled(False)
     self.ui.entries.selectionModel().selectionChanged.connect(lambda selected, deselected: self.ui.buttonBox.button(QDialogButtonBox.Open).setEnabled(len(selected.indexes()) > 0)  )
     self.accepted.connect(self.load_fits)
     self.populate()
Example #2
0
    def on_add_group(self):
        """
        Create a popup dialog that has a single list view of all the
        groups that are not yet added. 
        """

        # figure out who is added.
        groups_added = set()
        model = self.groupsListView.model()
        for i in range(model.rowCount()):
            groups_added.add(model.data(model.index(i, 0), Qt.UserRole))
            

        # Add rows for each unadded group
        model = QStandardItemModel()
        for g in Groups:
            if g in groups_added: continue

            model.appendRow(GroupItem(g))

        dialog = GetItemDialog(
            title="Choose a Group to Add",
            labelText="Groups",
            createText="Create a new Group",
            new_dialog_cls=CreateGroupWidget,
            item_cls=GroupItem,
            model=model
        )

        if dialog.exec() == QDialog.Accepted:
            model = self.groupsListView.model()
            model.appendRow(GroupItem(dialog.selection))
Example #3
0
class ConfigTableViewWidget(QDialog, Ui_ConfigTableViewWidget):
    """
    Class documentation goes here.
    """
    def __init__(self, availableScalars, scalarsToShow, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget (QWidget)
        """
        super().__init__(parent)
        self.setupUi(self)
        
        self.ValueListModel = QStandardItemModel()

        for value in availableScalars:                   
            item = QStandardItem(value)
            check = Qt.Checked if value in scalarsToShow else Qt.Unchecked
            item.setCheckState(check)
            item.setCheckable(True)
            self.ValueListModel.appendRow(item)
        
        
        self.ValueListView.setModel(self.ValueListModel)
        
    def setVisibleValues(self):
        setVisible = []
        for row in range(self.ValueListModel.rowCount()):
            item = self.ValueListModel.item(row)                  
            if item.checkState() == Qt.Checked:
                setVisible.append(item.text())
                
        return setVisible
Example #4
0
class FileListView(QListView):

    def __init__(self):
        super().__init__()
        self.setEditTriggers(QAbstractItemView.NoEditTriggers)

    """画像ファイル抽出&リスト追加処理"""
    def addFiles(self, files):
        itemCount = 0
        imageFiles = []
        self.model = QStandardItemModel()
        for file in files:
            if self.__isImage(file):
                imageFiles.append(file)
                item = QStandardItem(file)
                if itemCount % 2 == 0:
                    item.setBackground(QBrush(QColor(221, 222, 211)))
                self.model.appendRow(QStandardItem(item))
                itemCount += 1
        if itemCount == 0:
            QMessageBox.information(None, "No Image Files!",
                            "指定ディレクトリには画像がありません。")
        self.setModel(self.model)
        return imageFiles

    """画像ファイル選別処理(拡張子より選別)"""
    def __isImage(self, file):
        ext = os.path.splitext(file)[1].lower()
        return ext in [".jpg", ".jpeg", ".png", ".gif"]
Example #5
0
    def __init__(self, parent=None):
        super(UniverseTreeView, self).__init__(parent)

        model = QStandardItemModel()
        self.setModel(model)

        root_item = model.invisibleRootItem()

        self.areas_item = QStandardItem("Areas")
        self.areas_item.setData(Areas, Qt.UserRole)
        self.areas_item.setEditable(False)
        root_item.appendRow(self.areas_item)

        Areas.added.connect(self.init_areas)
        Areas.removed.connect(self.init_areas)
        Areas.reset.connect(self.init_areas)


        self.characters_item = QStandardItem("Characters")
        self.characters_item.setData(Characters, Qt.UserRole)
        self.characters_item.setEditable(False)
        root_item.appendRow(self.characters_item)

        Characters.added.connect(self.init_characters)
        Characters.removed.connect(self.init_characters)
        Characters.reset.connect(self.init_characters)


        self.races_item = QStandardItem("Races")
        self.races_item.setEditable(False)
        self.races_item.setData(Races, Qt.UserRole)
        root_item.appendRow(self.races_item)

        Races.added.connect(self.init_races)
        Races.removed.connect(self.init_races)
        Races.reset.connect(self.init_races)


        self.item_prototypes_item = QStandardItem("Item Prototypes")
        self.item_prototypes_item.setData(ItemPrototypes, Qt.UserRole)
        self.item_prototypes_item.setEditable(False)
        root_item.appendRow(self.item_prototypes_item)

        ItemPrototypes.added.connect(self.init_item_prototypes)
        ItemPrototypes.removed.connect(self.init_item_prototypes)
        ItemPrototypes.reset.connect(self.init_item_prototypes)


        self.groups_item = QStandardItem("Groups")
        self.groups_item.setData(Groups, Qt.UserRole)
        self.groups_item.setEditable(False)
        root_item.appendRow(self.groups_item)

        Groups.added.connect(self.init_groups)
        Groups.removed.connect(self.init_groups)
        Groups.reset.connect(self.init_groups)

        self.init_all()

        self.activated.connect(self.item_activated)
Example #6
0
def main(args):
    def split_and_strip(s, splitter):
        return [s.strip() for s in line.split(splitter)]

    app = QApplication(args)
    model = QStandardItemModel()
    file = QFile(QFileInfo(__file__).absolutePath() + '/grades.txt')
    if file.open(QFile.ReadOnly):
        line = file.readLine(200).decode('utf-8')
        header = split_and_strip(line, ',')
        model.setHorizontalHeaderLabels(header)
        row = 0
        while file.canReadLine():
            line = file.readLine(200).decode('utf-8')
            if not line.startswith('#') and ',' in line:
                fields = split_and_strip(line, ',')
                for col, field in enumerate(fields):
                    newItem = QStandardItem(field)
                    model.setItem(row, col, newItem)
                row += 1
    file.close()
    tableView = FreezeTableWidget(model)
    tableView.setWindowTitle("Frozen Column Example")
    tableView.resize(560, 680)
    tableView.show()
    return app.exec_()
Example #7
0
    def onFileDropped(self, filename):
        filename = parse.unquote(filename)
        if filename.startswith('file:/'):
            filename = filename[6:]
        print(filename)
        if os.path.isfile(filename) is not True:
            return

        tree = ET.parse(filename)
        root = tree.getroot()
        self.currentDict = XmlDictConfig(root)
        '''
        QList<QStandardItem *> preparedRow =prepareRow("first", "second", "third");
        QStandardItem *item = standardModel->invisibleRootItem();
        // adding a row to the invisible root item produces a root element
        item->appendRow(preparedRow);

        QList<QStandardItem *> secondRow =prepareRow("111", "222", "333");
        // adding a row to an item starts a subtree
        preparedRow.first()->appendRow(secondRow);

        treeView->setModel(standardModel);
        treeView->expandAll();
        '''
        standardModel = QStandardItemModel()
        preparedRow = (QStandardItem("Title"), QStandardItem("Description"))
        item = standardModel.invisibleRootItem()
        item.appendRow(preparedRow)
        self.addDictTree(self.currentDict, item)
        self.contents.setModel(standardModel)
        self.contents.expandAll()

        print("dict reading finished")
Example #8
0
 def setupModel(self):
     self.model = QStandardItemModel(3, 2, self)
     self.model.setHeaderData(0, Qt.Horizontal, "목록")
     self.model.setHeaderData(1, Qt.Horizontal, "읽기여부")
     self.model2 = QStandardItemModel(3, 2, self)
     self.model2.setHeaderData(0, Qt.Horizontal, "학습여부")
     self.model2.setHeaderData(1, Qt.Horizontal, "개수")
Example #9
0
class FileInspector(QTreeView):
    """docstring for FileInspector"""
    
    def __init__(self, parent=None):
        super(FileInspector, self).__init__(parent)
        self.model = QStandardItemModel(self)
        self.setModel(self.model)
        self.file_info = None
        header = QStandardItem('')
        self.model.setHorizontalHeaderItem(0, header)
    
    def populate(self, file_info=None, db_file=None):
        if file_info is not None:
            self.file_info = file_info
            db_file = FileInspectorHelper.get_or_insert_file(file_info)
        self.model.clear()
        if db_file:
            for classe in db_file.classes:
                parent = QStandardItem("{0}:".format(classe.name))
                for method in classe.methods:
                    parent.appendRow(QStandardItem("{0}()".\
                        format(method.name)))
                self.model.appendRow(parent)
            for function in db_file.functions:
                self.model.appendRow(QStandardItem("{0}()".\
                    format(function.name)))
        
        name = db_file.name if db_file else file_info.fileName()
        header = QStandardItem(name)
        self.model.setHorizontalHeaderItem(0, header)
        self.expandAll()
    
    @pyqtSlot(QFileInfo)
    def onFileItemActivated(self, file_info):
        self.populate(file_info)
Example #10
0
    def test_replace_tape_widget_should_destroy_old_tape_and_put_a_new_one_on_the_panel(self):
        old_tape_widget = self.window.tape_widget

        assert isinstance(old_tape_widget, TapeWidget)
        assert self.window.centralWidget() == old_tape_widget

        old_tape_widget.add_note()
        old_tape_widget.add_note()
        old_note1 = item_to_note(old_tape_widget.model().item(0))
        old_note2 = item_to_note(old_tape_widget.model().item(1))

        new_note = Note(
            body       = "Y",
            tags       = ["Z"],
            created_at = datetime.utcnow()
        )

        new_model = QStandardItemModel()
        new_item  = QStandardItem()
        set_item_note(new_item, new_note)
        new_model.appendRow(new_item)

        self.window._replace_tape_widget(new_model)

        self.assertTrue(isinstance(self.window.tape_widget, TapeWidget))
        self.assertNotEqual(self.window.tape_widget, old_tape_widget)
        self.assertEqual(len(list(self.window.tape_widget.notes())), 1)
        self.assertEqual(self.window.tape_widget.model(), new_model)
        self.assertEqual(item_to_note(self.window.tape_widget.model().item(0)), new_note)
        self.assertTrue(self.window.centralWidget() == self.window.tape_widget)
Example #11
0
 def __init__(self, database, settings, plot_widget, axes = None, enable_picker = True, selection_mode = 'multi'):
     super(LinesDialog, self).__init__()
     self.axes = axes if axes else plot_widget.axes
     self.database = database
     self.plot_widget = plot_widget
     self.settings = settings
     self.ui = Ui_LinesDialog()
     self.ui.setupUi(self)
     self.restoreGeometry(self.settings.value('pick_lines_geometry', QByteArray()))
     self.model = QStandardItemModel()
     self.elements_model = QStandardItemModel()
     self.ui.lines.setModel(self.model)
     self.ui.elements.setModel(self.elements_model)
     c = self.database.cursor()
     self.elements_model.appendRow(LinesDialog.__element_item([0, '', 'All']))
     elements = c.execute("SELECT z, code, name FROM elements ORDER BY z ASC")
     for element in elements:
         self.elements_model.appendRow(LinesDialog.__element_item(element))
     
     self.ui.elements.currentTextChanged.connect(lambda t: self.populate())
     self.ui.lambda_from.editingFinished.connect(self.populate)
     self.ui.name.editingFinished.connect(self.populate)
     self.ui.sp_types.toggled.connect(self.populate)
     self.ui.lambda_to.editingFinished.connect(self.populate)
     self.accepted.connect(self.collect_selected_lines)
     self.populate()
     self.ui.pick_wavelengths.setEnabled(enable_picker)
     self.ui.pick_wavelengths.clicked.connect(self.pick_wavelengths_clicked)
     self.ui.lines.setSelectionMode({'multi':QTableView.MultiSelection, 'single':QTableView.SingleSelection}[selection_mode])
Example #12
0
 def __init_tree_view(self):
     self.__treeView = QTreeView()
     self.__treeView.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
     rect = self.__treeView.geometry()
     rect.setWidth(self.__WINDOW_WIDTH / 4)
     self.__treeView.setGeometry(rect)
     model = QStandardItemModel()
     model.setHorizontalHeaderItem(0, QStandardItem(self.__DATABASE))
     self.__treeView.setModel(model)
Example #13
0
    def __init__(self, stack, references, stackname, settings, getcri, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget
        @type QWidget
        """
        super().__init__(parent)
        self.setupUi(self)        
        self.setAttribute(Qt.WA_DeleteOnClose)
        
        self.originalStack = stack
        self.stack = copy.deepcopy(stack)
        self.references = references
        self.StackName = stackname
        self.settings = settings
        self.getCRI = getcri
        
        self.referenceDataSelected = {}
        self.referenceList = []
        for key, value in self.references.items():
            if value[0]:
                self.referenceList.append([key, False]) # name and selection for fitting 
        self.referenceListModel = QStandardItemModel()
        self.referenceListModel.itemChanged.connect(self.updateReferences)
        self.referenceListView.setModel(self.referenceListModel)
        self.fillReferences()
        
        self.parameterModel = QStandardItemModel() #TreeOfParametersModel()
        self.parameterTreeView.setModel(self.parameterModel)
        self.parameterModel.setHorizontalHeaderLabels(['Parameter', 'Value'])
        self.root = self.parameterModel.invisibleRootItem()
        self.fillParameterTree()
        

        
        # configurations
        self.noOfFitIterations = 100
        methods = ['Nelder-Mead', 'Powell', 'CG', 'BFGS', 'L-BFGS-B', 'TNC', 'COBYLA', 'SLSQP']
        self.tolerance = 1e-3
         # with Jacobian necessary: 'Newton-CG', 'dogleg',  'trust-ncg'
        self.configuration = dict([
                        ('method', methods[0]),
                        ('noOfIterations', self.noOfFitIterations), 
                        ('tolerance', self.tolerance), 
                        ('plotInBetween',  True)
                        ])
        self.methodCB.addItems(methods)
        self.noOfIterationsSB.setValue(self.noOfFitIterations) 
        self.toleranceSB.setValue(self.tolerance)
        
        try:
            self.runOptics()
        except:
            self.done(0)
            QMessageBox.warning(self, "error", 'Error - could not calculate current stack.\nPlease check stack definition until simple simulation is running.',
                QMessageBox.StandardButtons(QMessageBox.Close))
Example #14
0
    def _get_config_model():
        data = DataStorage()
        configurations_order = data.get_configurations_order()
        model = QStandardItemModel()

        for name in configurations_order:
            item = create_new_list_item(name)
            model.appendRow(item)

        return model
Example #15
0
 def __init__(self, networkAccessManager, parent=None):
     """
     Constructor
     
     @param networkAccessManager reference to the network access manager
         (QNetworkAccessManager)
     @param parent reference to the parent widget (QWidget)
     """
     super(E5NetworkMonitor, self).__init__(parent)
     self.setupUi(self)
     self.setWindowFlags(Qt.Window)
     
     self.__requestHeaders = QStandardItemModel(self)
     self.__requestHeaders.setHorizontalHeaderLabels(
         [self.tr("Name"), self.tr("Value")])
     self.requestHeadersList.setModel(self.__requestHeaders)
     self.requestHeadersList.horizontalHeader().setStretchLastSection(True)
     self.requestHeadersList.doubleClicked.connect(self.__showHeaderDetails)
     
     self.__replyHeaders = QStandardItemModel(self)
     self.__replyHeaders.setHorizontalHeaderLabels(
         [self.tr("Name"), self.tr("Value")])
     self.responseHeadersList.setModel(self.__replyHeaders)
     self.responseHeadersList.horizontalHeader().setStretchLastSection(True)
     self.responseHeadersList.doubleClicked.connect(
         self.__showHeaderDetails)
     
     self.requestsList.horizontalHeader().setStretchLastSection(True)
     self.requestsList.verticalHeader().setMinimumSectionSize(-1)
     
     self.__proxyModel = QSortFilterProxyModel(self)
     self.__proxyModel.setFilterKeyColumn(-1)
     self.searchEdit.textChanged.connect(
         self.__proxyModel.setFilterFixedString)
     
     self.removeButton.clicked.connect(self.requestsList.removeSelected)
     self.removeAllButton.clicked.connect(self.requestsList.removeAll)
     
     self.__model = E5RequestModel(networkAccessManager, self)
     self.__proxyModel.setSourceModel(self.__model)
     self.requestsList.setModel(self.__proxyModel)
     self.__proxyModel.rowsInserted.connect(
         self.requestsList.scrollToBottom)
     self.requestsList.selectionModel()\
         .currentChanged[QModelIndex, QModelIndex]\
         .connect(self.__currentChanged)
     
     fm = self.fontMetrics()
     em = fm.width("m")
     self.requestsList.horizontalHeader().resizeSection(0, em * 5)
     self.requestsList.horizontalHeader().resizeSection(1, em * 20)
     self.requestsList.horizontalHeader().resizeSection(3, em * 5)
     self.requestsList.horizontalHeader().resizeSection(4, em * 15)
     
     self.__headersDlg = None
Example #16
0
    def set_data(self):
        group = self.obj

        self.setWindowTitle("{} (Group)".format(group.name))
        self.nameValueLabel.setText(group.name)

        model = QStandardItemModel()
        self.charactersListView.setModel(model)
        for c in group.characters:
            item = CharacterItem(c)
            model.appendRow(item)
Example #17
0
def createModel(parent,rows,cols,colNames):
    model=QStandardItemModel(rows, cols+1, parent)
    i=0
    for c in colNames:
        model.setHeaderData(i, Qt.Horizontal, c)
        i+=1
    proxyModel=QSortFilterProxyModel()
    proxyModel.setDynamicSortFilter(True)
    proxyModel.setSourceModel(model)
    proxyModel.setFilterKeyColumn(0)
    return proxyModel
 def set_table_data(self, data):
     table_model = QStandardItemModel()
     table_model.setHorizontalHeaderLabels(['Keyword', 'Count'])
     for row in data:
         qrow = []
         for item in row:
             qitem = QStandardItem(str(item))
             qrow.append(qitem)
         table_model.appendRow(qrow)
     self.table.setModel(table_model)
     self.table.resizeColumnsToContents()
     self.table.resizeRowsToContents()
Example #19
0
File: main.py Project: damekr/chat
def fillUserList(newUser=None):
    model = QStandardItemModel()
    mylist = ['asd', 'wqe', 'wqra', 'tewt4']
    if newUser:
        mylist += newUser
        print(mylist)
    for item in mylist:
        myitem = QStandardItem(item)
        myitem.setEditable(0)
        model.appendRow(myitem)
    myapp.listView.setModel(model)
    myapp.listView.doubleClicked.connect(openConversationWindow)
class SettingWindow(QWidget):
#	on_addButtonClicked=pyqtSignal()
#	on_removeButtonClicked=pyqtSignal()
#	on_okButtonClicked=pyqtSignal()
	finished=pyqtSignal()
	def __init__(self):
		QWidget.__init__(self)
		self.listview=QListView(self)
		self.addButton=QPushButton(self)
		self.removeButton=QPushButton(self)
		self.resize(630,440)
		self.okButton=QPushButton(self)
		self.listview.setGeometry(30,30,410,351)
		self.addButton.setGeometry(490,40,80,22)
		self.addButton.setText("add")
		self.addButton.clicked.connect(self.click_add)
		self.removeButton.setGeometry(490,80,80,22)
		self.removeButton.setText("remove")
		self.removeButton.clicked.connect(self.click_remove)
		self.okButton.setGeometry(490,150,80,22)
		self.okButton.setText("ok")
		self.okButton.clicked.connect(self.click_ok)
#		self.aw=null


		self.fresh()
	def click_ok(self):
		self.finished.emit()
		self.close()
	def click_add(self):
		self.aw=AddWindow()
		self.aw.show()
		self.aw.okSig.connect(self.fresh)
	def click_remove(self):
		self.remove()
	def fresh(self):
		confFile=open("conf","r")
		self.listModel=QStandardItemModel()
		self.itemList=cPickle.load(confFile)
		confFile.close()
		for  item in self.itemList:
			itemView=QStandardItem(QIcon(item.path),item.name)
			itemView.setEditable(False)
			self.listModel.appendRow(itemView)
			self.listview.setModel(self.listModel)
	def remove(self):
		index=self.listview.currentIndex().row()
		self.itemList.pop(index)
		self.listModel.removeRow(index)
		confFile=open("conf","w")
		cPickle.dump(self.itemList,confFile)
		confFile.close()
Example #21
0
	def createModel(self):
		model = QStandardItemModel(0, 3)

		model.setHeaderData(0, Qt.Horizontal, "Name")
		model.setHeaderData(1, Qt.Horizontal, "Phone")
		model.setHeaderData(2, Qt.Horizontal, "Address")
		model.setHeaderData(3, Qt.Horizontal, "")

		return model
Example #22
0
    def create_table(self, rela):
        table = custom_table.Table()
        model = QStandardItemModel()
        table.setModel(model)
        model.setHorizontalHeaderLabels(rela.header)

        for row_count, row in enumerate(rela.content):
            for col_count, data in enumerate(row):
                item = QStandardItem(data)
                item.setFlags(item.flags() & ~Qt.ItemIsEditable)
                model.setItem(row_count, col_count, item)

        return table
Example #23
0
    def data(self, index, role=Qt.DisplayRole):
        if index.parent().isValid() and \
                        index.parent().column() == Plot.steps and \
                        index.column() == PlotStep.meta:
            if role == Qt.TextAlignmentRole:
                return Qt.AlignRight | Qt.AlignVCenter
            elif role == Qt.ForegroundRole:
                return QBrush(Qt.gray)
            else:
                return QStandardItemModel.data(self, index, role)

        else:
            return QStandardItemModel.data(self, index, role)
    def __init__(self, parent=None):
        super(UniverseTreeView, self).__init__(parent)

        model = QStandardItemModel()
        self.setModel(model)

        root_item = model.invisibleRootItem()
        self.characters_item = QStandardItem("Characters")
        self.characters_item.setEditable(False)

        self.races_item = QStandardItem("Races")
        self.races_item.setEditable(False)

        self.skills_item = QStandardItem("Skills")
        self.skills_item.setEditable(False)

        self.personalities_item = QStandardItem("Personalities")
        self.personalities_item.setEditable(False)

        self.backgrounds_item = QStandardItem("Backgrounds")
        self.backgrounds_item.setEditable(False)

        root_item.appendRow(self.characters_item)
        root_item.appendRow(self.races_item)
        root_item.appendRow(self.skills_item)
        root_item.appendRow(self.personalities_item)
        root_item.appendRow(self.backgrounds_item)
        
        self.init_all()

        GlobalData.character_added.connect(self.init_characters)
        GlobalData.character_removed.connect(self.init_characters)
        GlobalData.characters_reset.connect(self.init_characters)

        GlobalData.race_added.connect(self.init_races)
        GlobalData.race_removed.connect(self.init_races)
        GlobalData.races_reset.connect(self.init_races)

        GlobalData.skill_added.connect(self.init_skills)
        GlobalData.skill_removed.connect(self.init_skills)
        GlobalData.skills_reset.connect(self.init_skills)

        GlobalData.personality_added.connect(self.init_personalities)
        GlobalData.personality_removed.connect(self.init_personalities)
        GlobalData.personalities_reset.connect(self.init_personalities)

        GlobalData.background_added.connect(self.init_backgrounds)
        GlobalData.background_removed.connect(self.init_backgrounds)
        GlobalData.backgrounds_reset.connect(self.init_backgrounds)
        
        self.activated.connect(self.item_activated)
Example #25
0
class RefsUI(object):

    def __init__(self, window, uaclient):
        self.window = window
        self.uaclient = uaclient
        self.model = QStandardItemModel()
        self.window.ui.refView.setModel(self.model)
        self.window.ui.refView.horizontalHeader().setSectionResizeMode(1)

        self.window.ui.treeView.activated.connect(self.show_refs)
        self.window.ui.treeView.clicked.connect(self.show_refs)

    def clear(self):
        self.model.clear()

    def show_refs(self, idx):
        node = self.window.get_current_node(idx)
        self.model.clear()
        if node:
            self._show_refs(node)

    def _show_refs(self, node):
        self.model.setHorizontalHeaderLabels(['ReferenceType', 'NodeId', "BrowseName", "TypeDefinition"])
        try:
            refs = self.uaclient.get_all_refs(node)
        except Exception as ex:
            self.window.show_error(ex)
            raise
        for ref in refs:
            self.model.appendRow([QStandardItem(str(ref.ReferenceTypeId)),
                                  QStandardItem(str(ref.NodeId)),
                                  QStandardItem(str(ref.BrowseName)),
                                  QStandardItem(str(ref.TypeDefinition))])
Example #26
0
    def test_set_model_replace_the_model_with_a_new_one(self):
        new_model = QStandardItemModel()
        item      = QStandardItem()
        set_item_note(item, self.notes[0])
        new_model.appendRow(item)

        assert self.tape_widget.model().rowCount() == 0

        self.tape_widget.set_model(new_model)

        self.assertEqual(self.tape_widget.model(), new_model)
        self.assertEqual(self.tape_widget.proxy_model().sourceModel(), new_model)
        self.assertEqual(self.tape_widget.model().rowCount(), 1)
        self.assertEqual(self.tape_widget.model().item(0, 0), item)
    def setup_table(self, rela):
        # Table model
        model = QStandardItemModel()
        self.table.setModel(model)
        # Set header
        model.setHorizontalHeaderLabels(rela.header)

        # Populate table
        for row_count, row in enumerate(rela.content):
            for col_count, data in enumerate(row):
                item = QStandardItem()
                item.setText(data)
                item.setToolTip(data)
                model.setItem(row_count, col_count, item)
class ListCategory(QSortFilterProxyModel):

    """Expose a list of items as a category for the CompletionModel."""

    def __init__(self, name, items, delete_func=None, parent=None):
        super().__init__(parent)
        self.name = name
        self.srcmodel = QStandardItemModel(parent=self)
        self._pattern = ''
        # ListCategory filters all columns
        self.columns_to_filter = [0, 1, 2]
        self.setFilterKeyColumn(-1)
        for item in items:
            self.srcmodel.appendRow([QStandardItem(x) for x in item])
        self.setSourceModel(self.srcmodel)
        self.delete_func = delete_func

    def set_pattern(self, val):
        """Setter for pattern.

        Args:
            val: The value to set.
        """
        self._pattern = val
        val = re.sub(r' +', r' ', val)  # See #1919
        val = re.escape(val)
        val = val.replace(r'\ ', '.*')
        rx = QRegExp(val, Qt.CaseInsensitive)
        self.setFilterRegExp(rx)
        self.invalidate()
        sortcol = 0
        self.sort(sortcol)

    def lessThan(self, _lindex, rindex):
        """Custom sorting implementation.

        Prefers all items which start with self._pattern. Other than that, keep
        items in their original order.

        Args:
            _lindex: The QModelIndex of the left item (*left* < right)
            rindex: The QModelIndex of the right item (left < *right*)

        Return:
            True if left < right, else False
        """
        qtutils.ensure_valid(rindex)
        right = self.srcmodel.data(rindex)
        return not right.startswith(self._pattern)
Example #29
0
    def __init__(self, parent=None):
        super(MDIHistory, self).__init__(parent)
        self.setMinimumSize(QSize(300, 200))    
        self.setWindowTitle("PyQt5 editor test example") 

        lay = QVBoxLayout()
        lay.setContentsMargins(0,0,0,0)
        self.setLayout(lay)

        self.list = QListView()
        self.list.setEditTriggers(QListView.NoEditTriggers)
        self.list.activated.connect(self.activated)
        self.list.setAlternatingRowColors(True)
        self.list.selectionChanged = self.selectionChanged
        self.model = QStandardItemModel(self.list)


        self.MDILine = MDILine()
        self.MDILine.soft_keyboard = False
        self.MDILine.line_up = self.line_up
        self.MDILine.line_down = self.line_down

        # add widgets
        lay.addWidget(self.list)
        lay.addWidget(self.MDILine)
        self.reload()
Example #30
0
    def __init__(self, parentWidget):
        QWidget.__init__(self, parentWidget)
        
        self.editorWidget = parentWidget.editorWidget   # TODO: Review class structure

        self.searching = False
        self.ui = Ui_SearchWidget()
        self.ui.setupUi(self)
        self.resultListModel = QStandardItemModel(self.ui.resultList)
        self.ui.resultWidget.setCurrentIndex(0)
        self.ui.resultList.setModel(self.resultListModel)
        self.ui.resultList.selectionModel().selectionChanged.connect(self.doResultSelected)

        self.startIcon = QIcon(':/icons/search-global-start.png')
        self.stopIcon = QIcon(':/icons/search-global-stop.png')
        self.ui.startStopButton.setIcon(self.startIcon)

        self.ui.searchInput.returnPressed.connect(self.doReturnKey)
        self.ui.startStopButton.clicked.connect(self.doStartStopButton)

        self.workerThread = QThread()
        self.worker = SearchWorker()
        self.worker.moveToThread(self.workerThread)
        self.startWork.connect(self.worker.startSearch)
        self.worker.searchDone.connect(self.searchDone)
        self.worker.addMatch.connect(self.addMatch)
        # self.stopWork.connect(self.worker.stopSearch)
        self.workerThread.start()
Example #31
0
class ElfInfo(DwarfDialog):
    onShowMemoryRequest = pyqtSignal(str, name='onShowMemoryRequest')

    def __init__(self, parent=None, file_path=None):
        super().__init__(parent=parent)
        h_box = QHBoxLayout(self)
        self._ident_titles = ['EI_MAG0', 'EI_MAG1', 'EI_MAG2', 'EI_MAG3', 'EI_CLASS', 'EI_DATA', 'EI_VERSION', 'EI_OSABI', 'EI_ABIVERSION', 'EI_PAD']
        self.elf_info = DwarfListView(self)
        self.elf_info.setRootIsDecorated(True)
        self.elf_info.setExpandsOnDoubleClick(True)
        self.elf_info.setContextMenuPolicy(Qt.CustomContextMenu)
        self.elf_info.customContextMenuRequested.connect(self._on_context_menu)
        h_box.addWidget(self.elf_info)
        self._elf_info_mdl = QStandardItemModel(0, 2)
        self._elf_info_mdl.setHeaderData(0, Qt.Horizontal, 'Name')
        self._elf_info_mdl.setHeaderData(1, Qt.Horizontal, 'Value')
        self.elf_info.setModel(self._elf_info_mdl)
        self.elf_info.doubleClicked.connect(self._on_dblclicked)
        self.title = "ELF Info"
        self._elf_file_path = None
        self.setLayout(h_box)
        if file_path:
            self.set_elf_file(file_path)

    def set_elf_file(self, file_path):
        self._elf_file_path = file_path
        self.title = 'ELF Info for ' + file_path
        self._elf_info_mdl.insertRow(0, [QStandardItem('File'), QStandardItem(file_path)])

    def set_parsed_data(self, parsed_data):
        parent_item = self._elf_info_mdl.item(0)
        if 'endian' in parsed_data:
            parent_item.appendRow([QStandardItem('Endian'), QStandardItem(parsed_data['endian'])])
        if 'is64bit' in parsed_data:
            txt = 'No'
            if parsed_data['is64bit']:
                txt = 'Yes'
            parent_item.appendRow([QStandardItem('64Bit'), QStandardItem(txt)])

        if 'header' in parsed_data:
            elf_header = QStandardItem('ELF Header')
            parent_item.appendRow([elf_header])
            for d in parsed_data['header']:
                if d == 'e_ident':
                    ident_item = QStandardItem(d)
                    elf_header.appendRow([ident_item, QStandardItem(str(parsed_data['header'][d]))])
                    a = 0
                    for i in parsed_data['header'][d]:
                        if a >= len(self._ident_titles):
                            a = len(self._ident_titles) - 1
                        ident_item.appendRow([QStandardItem(self._ident_titles[a]), QStandardItem(str(i))])
                        a += 1
                else:
                    elf_header.appendRow([QStandardItem(d), QStandardItem(hex(parsed_data['header'][d]))])

        if 'programheaders' in parsed_data:
            prog_headers_item = QStandardItem('Program Headers')
            parent_item.appendRow([prog_headers_item])
            i = 1
            for header in parsed_data['programheaders']:
                header_item = QStandardItem("%d" % i)
                prog_headers_item.appendRow([header_item])
                i += 1
                for d in header:
                    header_item.appendRow([QStandardItem(d), QStandardItem(hex(header[d]))])

        if 'sectionheaders' in parsed_data:
            sect_headers = QStandardItem('Section Headers')
            parent_item.appendRow([sect_headers])
            i = 1
            for header in parsed_data['sectionheaders']:
                txt = header['name']
                if not txt:
                    txt = 'NULL'
                header_item = QStandardItem(txt)
                sect_headers.appendRow([header_item])
                i += 1
                for d in header:
                    if d == 'name':
                        continue
                    elif d == 'data' and header[d]:
                        data_item = QStandardItem('Data')
                        header_item.appendRow(data_item)
                        base = self.parent().dwarf.dwarf_api('findModule', self._elf_file_path)['base']
                        for ptr in header[d]:
                            if int(ptr):
                                va = hex(int(base, 16) + int(ptr))
                                fo = hex(int(ptr))
                                if self.elf_info.uppercase_hex:
                                    va = va.upper().replace('0X', '0x')
                                    fo = fo.upper().replace('0X', '0x')
                                data_item.appendRow([QStandardItem(va), QStandardItem('FileOffset: ' + fo)])
                    else:
                        header_item.appendRow([QStandardItem(d), QStandardItem(hex(header[d]))])

            self.elf_info.expandAll()
            self.elf_info.resizeColumnToContents(0)
            self.elf_info.resizeColumnToContents(1)
            self.setMinimumWidth(self.elf_info.columnWidth(0) + self.elf_info.columnWidth(1) + 50)
            self.setMinimumHeight(400)
            self.elf_info.collapseAll()
            self.elf_info.expandToDepth(1)


    def _on_dblclicked(self, model_index):
        if model_index.column() == 0 and model_index.data():
            if model_index.data().startswith('0x'):
                self.onShowMemoryRequest.emit(model_index.data())

    def _on_context_menu(self, pos):
        model_index = self.elf_info.indexAt(pos)
        if model_index.column() == 0 and model_index.data():
            if model_index.data().startswith('0x'):
                context_menu = QMenu()
                context_menu.addAction('Add to Bookmarks', lambda: self.parent().bookmarks_panel.insert_bookmark(model_index.data(), 'init_array'))
                context_menu.addAction('Copy Address', lambda: utils.copy_hex_to_clipboard(model_index.data()))
                # show contextmenu
                glbl_pt = self.elf_info.mapToGlobal(pos)
                context_menu.exec_(glbl_pt)
Example #32
0
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):

         self.srvList=["",
                               "master_mercury230",
                               "master_modbusRTU",
                               "master_modbusTCP",
                               "master_http",
                               "master_dcon",
                               "master_ping"]
         self.slvList=["","opcUA","modbusTCP"]

         if(os.name=='nt'):

             self.appPath=os.path.abspath(sys.argv[0]).replace(os.path.basename(__file__),'')


             self.imgPath=self.appPath+"img\\"
             self.dbPath=self.appPath+"db\\srvDb.db"

         else:
             self.appPath=os.path.abspath(sys.argv[0]).replace(os.path.basename(__file__),'')
             self.imgPath=self.appPath+"img/"
             self.dbPath=self.appPath+"db/srvDb.db"


         self.versionPr='ScadaPy Конфигуратор сервера v.3.11'
         self.setGeometry(400, 200, 1000, 520)
         self.setWindowTitle(self.versionPr)
         self.setWindowIcon(QIcon( self.imgPath+'gnome-monitor.png'))
         self.h=self.frameGeometry().height()

         font = QFont()
         font.setPointSize(12)


         self.label0=QLabel(self)
         self.label0.setFont(font)
         self.label0.move(400, 60)
         self.label0.resize(300,25)
         self.label0.setText("ID сервера")
         self.label00=QLabel(self)
         self.label00.setFont(font)
         self.label00.move(550, 60)
         self.label00.resize(300,25)
         self.label00.setText("")

         self.label1=QLabel(self)
         self.label1.setFont(font)
         self.label1.move(400, 90)
         self.label1.resize(140,25)
         self.label1.setText("Название сервера")
         self.srvName = QLineEdit(self)
         self.srvName.setToolTip('Пример: Сервер Маш.Зала №1')
         self.srvName.move(550, 90)
         self.srvName.setFont(font)
         self.srvName.resize(300,25)

         self.label2=QLabel(self)
         self.label2.setFont(font)
         self.label2.move(400, 120)
         self.label2.resize(140,25)
         self.label2.setText("Slave IP address")
         self.slaveIP = QLineEdit(self)
         self.slaveIP.setToolTip('Пример: 192.168.0.111')
         self.slaveIP.move(550, 120)
         self.slaveIP.setFont(font)
         self.slaveIP.resize(300,25)


         self.label2=QLabel(self)
         self.label2.setFont(font)
         self.label2.move(400, 150)
         self.label2.resize(140,25)
         self.label2.setText("Slave Port")
         self.slavePort = QLineEdit(self)
         self.slavePort.setToolTip('Пример modbus: 502\nПример opcua: 4840')
         self.slavePort.move(550, 150)
         self.slavePort.setFont(font)
         self.slavePort.resize(100,25)

         self.label7=QLabel(self)
         self.label7.setFont(font)
         self.label7.move(680, 150)
         self.label7.resize(140,25)
         self.label7.setText("Timeout")
         self.serverTimeout = QLineEdit(self)
         self.serverTimeout.setToolTip('Пример ms: 1 ')
         self.serverTimeout.move(750, 150)
         self.serverTimeout.setFont(font)
         self.serverTimeout.resize(100,25)




         self.label3=QLabel(self)
         self.label3.setFont(font)
         self.label3.move(400, 180)
         self.label3.resize(140,25)
         self.label3.setText("Тип Master")
         self.label3=QLabel(self)
         self.label3.setFont(font)
         self.label3.move(550, 180)
         self.label3.resize(340,25)
         self.label3.setText("---")

         self.combo1 = QComboBox(self)
         self.combo1.move(550, 210)
         self.combo1.setFont(font)
         self.combo1.resize(320,25)
         self.combo1.addItems(self.srvList)

         self.label4=QLabel(self)
         self.label4.setFont(font)
         self.label4.move(400, 240)
         self.label4.resize(140,25)
         self.label4.setText("Тип Slave")
         self.label4=QLabel(self)
         self.label4.setFont(font)
         self.label4.move(550, 240)
         self.label4.resize(340,25)
         self.label4.setText("---")

         self.combo2 = QComboBox(self)
         self.combo2.move(550, 270)
         self.combo2.setFont(font)
         self.combo2.resize(320,25)
         self.combo2.addItems(self.slvList)

         self.label5=QLabel(self)
         self.label5.setFont(font)
         self.label5.move(400, 300)
         self.label5.resize(140,25)
         self.label5.setText("Порт /dev/tty*")
         self.tty=QLineEdit(self)
         self.tty.setToolTip('Пример linux: /dev/ttyUSB0\nПример windows: com19')
         self.tty.setFont(font)
         self.tty.move(550, 300)
         self.tty.resize(150,25)

         self.label6=QLabel(self)
         self.label6.setFont(font)
         self.label6.move(720, 300)
         self.label6.resize(140,25)
         self.label6.setText("скорость")
         self.ttySpeed=QLineEdit(self)
         self.ttySpeed.setToolTip('Пример : 9600')
         self.ttySpeed.setFont(font)
         self.ttySpeed.move(800, 300)
         self.ttySpeed.resize(150,25)



         exitAction = QAction(QIcon( self.imgPath+'exit.png'), '&Выход', self)
         exitAction.setShortcut('Ctrl+Q')
         exitAction.setStatusTip('Выход из программы')
         exitAction.triggered.connect(qApp.quit)


         addServerAction = QAction(QIcon(self.imgPath+'add.png'), '&Добавить', self)
         addServerAction.setStatusTip('Добавить сервер')
         addServerAction.triggered.connect(self.addNewServer)

         delServerAction = QAction(QIcon(self.imgPath+'button_cancel.png'), '&Удалить', self)
         delServerAction.setStatusTip('Удалить сервер')
         delServerAction.triggered.connect(self.delServer)


         saveServerAction = QAction(QIcon(self.imgPath+'filesave.png'), '&Сохранить', self)
         saveServerAction.setStatusTip('Сохранить сервер')
         saveServerAction.triggered.connect(self.saveServer)

         saveScr = QAction(QIcon(self.imgPath+'bottom.png'), '&Сохранить скрипт', self)
         saveScr.setStatusTip('Сохранить скрипт')
         saveScr.triggered.connect(self.saveScr)

         runScr = QAction(QIcon(self.imgPath+'run.png'), '&Запустить скрипт', self)
         runScr.setStatusTip('Запустить скрипт')
         runScr.triggered.connect(self.runScr)


         menubar = self.menuBar()
         fileMenu = menubar.addMenu('&Команды')
         fileMenu.addAction(addServerAction)
         fileMenu.addAction(delServerAction)
         fileMenu.addAction(saveServerAction)
         fileMenu.addAction(saveScr)
         fileMenu.addAction(runScr)
         fileMenu.addAction(exitAction)


         self.toolbar = self.addToolBar('Выход')
         self.toolbar.addAction(exitAction)
         self.toolbar.addAction(addServerAction)
         self.toolbar.addAction(delServerAction)
         self.toolbar.addAction(saveServerAction)
         self.toolbar.addAction(saveScr)
         self.toolbar.addAction(runScr)




        # self.statusBar().showMessage('Загрузка данных')

         self.treeView = QTreeView(self)
         self.treeView.setFont(font)
         self.treeView.setObjectName("treeView")
         self.model = QStandardItemModel()
         self.treeView.setModel(self.model)
         self.header = ['Название сервера']
         self.model.setHorizontalHeaderLabels(self.header)

         self.sqlLoad()
         self.treeView.clicked.connect(self.onClickItem)





         self.frameTable = QFrame(self)
         self.frameTable.move(380, 350)
         self.frameTable.setFont(font)
         self.frameTable.resize(1350,950)
         self.frameTable.setVisible(True)

         self.addRow = QPushButton(self.frameTable)
         self.addRow.setIcon(QIcon(self.imgPath+'add.png'))
         self.addRow.move(10, 10)
         self.addRow.resize(30,30)
         self.addRow.clicked.connect(self.addRowTable)

         self.saveTable = QPushButton(self.frameTable)
         self.saveTable.setIcon(QIcon(self.imgPath+'filesave.png'))
         self.saveTable.resize(30,30)
         self.saveTable.move(50, 10)
         self.saveTable.clicked.connect(self.saveRowTable)


         self.treeTable = QTableWidget(self.frameTable)
         fontTable = QFont()
         fontTable.setPointSize(10)
         self.treeTable.setFont(fontTable)

         self.show()









    def addRowTable(self):
         self.treeTable.insertRow(self.treeTable.rowCount())


    def getDataPing(self):
             self.treeTable.clear()
             self.treeTable.setColumnCount(2)
             self.treeTable.setRowCount(1)
             self.treeTable.setHorizontalHeaderLabels(['IP адрес сервера','Имя переменной'])
             self.treeTable.resizeColumnsToContents()
             self.treeTable.setColumnWidth(0, 380)
             self.treeTable.setColumnWidth(1, 400)



             connDb = sqlite3.connect(self.dbPath)
             cursor = connDb.cursor()
             cursor.execute("select ip,name from  master_ping where serverId = "+self.label00.text())
             dt=cursor.fetchall()
             self.treeTable.setRowCount(len(dt))
             for i in range(0,len(dt)):
                 self.treeTable.setItem(i, 0, QTableWidgetItem(dt[i][0]))
                 self.treeTable.setItem(i, 1, QTableWidgetItem(dt[i][1]))
                 i+=1

    def getDataMercury(self):
             self.treeTable.clear()
             self.treeTable.setColumnCount(2)
             self.treeTable.setRowCount(1)
             self.treeTable.setHorizontalHeaderLabels(['Сетевой адрес счетчика','Имя переменной'])
             self.treeTable.resizeColumnsToContents()
             self.treeTable.setColumnWidth(0, 380)
             self.treeTable.setColumnWidth(1, 400)



             connDb = sqlite3.connect(self.dbPath)
             cursor = connDb.cursor()
             cursor.execute("select netAdr, serNum from  master_mercury230 where serverId = "+self.label00.text())
             dt=cursor.fetchall()
             self.treeTable.setRowCount(len(dt))
             for i in range(0,len(dt)):
                 self.treeTable.setItem(i, 0, QTableWidgetItem(dt[i][0]))
                 self.treeTable.setItem(i, 1, QTableWidgetItem(dt[i][1]))
                 i+=1

    def getDataModbusTCP(self):
             self.treeTable.clear()
             self.treeTable.setColumnCount(8)
             self.treeTable.setRowCount(1)
             self.treeTable.setHorizontalHeaderLabels(['IP адрес','Порт','Адрес\nRTU','Название регистра','Адрес\nячейки','Кол-во\nячеек','Адрес на\nсервере','Имя переменной'])
             self.treeTable.resizeColumnsToContents()
             self.treeTable.setColumnWidth(0, 110)
             self.treeTable.setColumnWidth(1, 50)
             self.treeTable.setColumnWidth(2, 80)
             self.treeTable.setColumnWidth(3, 220)
             self.treeTable.setColumnWidth(4, 80)
             self.treeTable.setColumnWidth(5, 80)
             self.treeTable.setColumnWidth(6, 80)
             self.treeTable.setColumnWidth(7, 160)



             connDb = sqlite3.connect(self.dbPath)
             cursor = connDb.cursor()
             cursor.execute("select ip,port,adrRtu,reg,fromAdr,fromCount,toAdr,comment serNum from  master_modbusTCP where serverId = "+self.label00.text())
             dt=cursor.fetchall()
             self.treeTable.setRowCount(len(dt))
             for i in range(0,len(dt)):
                 self.treeTable.setItem(i, 0, QTableWidgetItem(dt[i][0]))
                 self.treeTable.setItem(i, 1, QTableWidgetItem(dt[i][1]))
                 self.treeTable.setItem(i, 2, QTableWidgetItem(dt[i][2]))
                 self.treeTable.setItem(i, 3, QTableWidgetItem(dt[i][3]))
                 self.treeTable.setItem(i, 4, QTableWidgetItem(dt[i][4]))
                 self.treeTable.setItem(i, 5, QTableWidgetItem(dt[i][5]))
                 self.treeTable.setItem(i, 6, QTableWidgetItem(dt[i][6]))
                 self.treeTable.setItem(i, 7, QTableWidgetItem(dt[i][7]))
                 i+=1


    def getDataHttp(self):
             self.treeTable.clear()
             self.treeTable.setColumnCount(7)
             self.treeTable.setRowCount(1)
             self.treeTable.setHorizontalHeaderLabels(['Адрес http','Название регистра','modbus-Адрес ячейки\nopc-тип переменной','Количество \nячеек','Объект','Login','Password'])
             self.treeTable.resizeColumnsToContents()
             self.treeTable.setColumnWidth(0, 310)
             self.treeTable.setColumnWidth(1, 160)
             self.treeTable.setColumnWidth(2, 150)
             self.treeTable.setColumnWidth(3, 120)
             self.treeTable.setColumnWidth(4, 120)
             self.treeTable.setColumnWidth(5, 120)
             self.treeTable.setColumnWidth(6, 120)


             connDb = sqlite3.connect(self.dbPath)
             cursor = connDb.cursor()
             cursor.execute("select ip,reg,toAdr,fromCount,comment,login,password from  master_http where serverId = "+self.label00.text())
             dt=cursor.fetchall()
             self.treeTable.setRowCount(len(dt))
             for i in range(0,len(dt)):
                 self.treeTable.setItem(i, 0, QTableWidgetItem(dt[i][0]))
                 self.treeTable.setItem(i, 1, QTableWidgetItem(dt[i][1]))
                 self.treeTable.setItem(i, 2, QTableWidgetItem(dt[i][2]))
                 self.treeTable.setItem(i, 3, QTableWidgetItem(dt[i][3]))
                 self.treeTable.setItem(i, 4, QTableWidgetItem(dt[i][4]))
                 self.treeTable.setItem(i, 5, QTableWidgetItem(dt[i][5]))
                 self.treeTable.setItem(i, 6, QTableWidgetItem(dt[i][6]))


                 i+=1




    def getDataDcon(self):
             self.treeTable.clear()
             self.treeTable.setColumnCount(4)
             self.treeTable.setRowCount(1)
             self.treeTable.setHorizontalHeaderLabels(['Модель','Адрес\nRTU','Адрес ячейки на\nсервере','Имя переменной'])
             self.treeTable.resizeColumnsToContents()
             self.treeTable.setColumnWidth(0, 110)
             self.treeTable.setColumnWidth(1, 80)
             self.treeTable.setColumnWidth(2, 120)
             self.treeTable.setColumnWidth(3, 320)



             connDb = sqlite3.connect(self.dbPath)
             cursor = connDb.cursor()
             cursor.execute("select model,adrRtu,toAdr,comment from  master_dcon where serverId = "+self.label00.text())
             dt=cursor.fetchall()
             self.treeTable.setRowCount(len(dt))
             for i in range(0,len(dt)):
                 self.treeTable.setItem(i, 0, QTableWidgetItem(dt[i][0]))
                 self.treeTable.setItem(i, 1, QTableWidgetItem(dt[i][1]))
                 self.treeTable.setItem(i, 2, QTableWidgetItem(dt[i][2]))
                 self.treeTable.setItem(i, 3, QTableWidgetItem(dt[i][3]))
                 i+=1

    def getDataModbusRTU(self):
             self.treeTable.clear()
             self.treeTable.setColumnCount(6)
             self.treeTable.setRowCount(1)
             self.treeTable.setHorizontalHeaderLabels(['Адрес\nRTU','Название регистра','Адрес\nячейки','Кол-во\nячеек','Адрес на\nсервере','Имя переменной'])
             self.treeTable.resizeColumnsToContents()
             self.treeTable.setColumnWidth(0, 50)
             self.treeTable.setColumnWidth(1, 220)
             self.treeTable.setColumnWidth(2, 80)
             self.treeTable.setColumnWidth(3, 80)
             self.treeTable.setColumnWidth(4, 80)
             self.treeTable.setColumnWidth(5, 220)




             connDb = sqlite3.connect(self.dbPath)
             cursor = connDb.cursor()
             cursor.execute("select adrRtu,reg,fromAdr,fromCount,toAdr,comment serNum from  master_modbusRTU where serverId = "+self.label00.text())
             dt=cursor.fetchall()
             self.treeTable.setRowCount(len(dt))
             for i in range(0,len(dt)):
                 self.treeTable.setItem(i, 0, QTableWidgetItem(dt[i][0]))
                 self.treeTable.setItem(i, 1, QTableWidgetItem(dt[i][1]))
                 self.treeTable.setItem(i, 2, QTableWidgetItem(dt[i][2]))
                 self.treeTable.setItem(i, 3, QTableWidgetItem(dt[i][3]))
                 self.treeTable.setItem(i, 4, QTableWidgetItem(dt[i][4]))
                 self.treeTable.setItem(i, 5, QTableWidgetItem(dt[i][5]))
                 i+=1

    def saveRowTable(self):
             connDb = sqlite3.connect(self.dbPath)
             cursor = connDb.cursor()


             if(self.label3.text()=="master_ping"):
                 cursor.execute("delete from master_ping where serverId= '"+self.label00.text()+"'" )
                 connDb.commit()

                 for i in range(0,self.treeTable.rowCount()):

                     try:
                         if(     len(self.treeTable.item(i,0).text()) > 0 and
                                 len(self.treeTable.item(i,1).text()) > 0 ):

                             cursor.execute("INSERT INTO master_ping(serverId,ip,name,valid)\
                             VALUES('"+self.label00.text()+"','"+self.treeTable.item(i,0).text()+"'\
                             ,'"+self.treeTable.item(i,1).text()+"',1)" )
                             connDb.commit()
                     except Exception as e:
                     #print(e)
                         pass
                     i+=1
                 self.getDataPing()





             if(self.label3.text()=="master_mercury230"):
                 cursor.execute("delete from master_mercury230 where serverId= '"+self.label00.text()+"'" )
                 connDb.commit()

                 for i in range(0,self.treeTable.rowCount()):
                     try:
                         if(     len(self.treeTable.item(i,0).text()) > 0 and
                                 len(self.treeTable.item(i,1).text()) > 0 ):

                             cursor.execute("INSERT INTO master_mercury230(serverId,netAdr,serNum,valid)\
                             VALUES('"+self.label00.text()+"','"+self.treeTable.item(i,0).text()+"'\
                             ,'"+self.treeTable.item(i,1).text()+"',1)" )
                             connDb.commit()
                     except Exception as e:
                     #print(e)
                         pass
                     i+=1
                 self.getDataMercury()


             if(self.label3.text()=="master_modbusTCP"):
                 cursor.execute("delete from master_modbusTCP where serverId= '"+self.label00.text()+"'" )
                 connDb.commit()

                 for i in range(0,self.treeTable.rowCount()):
                         try:
                             if(     len(self.treeTable.item(i,0).text()) > 0 and
                                     len(self.treeTable.item(i,1).text()) > 0 and
                                     len(self.treeTable.item(i,2).text()) > 0 and
                                     len(self.treeTable.item(i,3).text()) > 0 and
                                     len(self.treeTable.item(i,4).text()) > 0 and
                                     len(self.treeTable.item(i,5).text()) > 0 and
                                     len(self.treeTable.item(i,6).text()) > 0 and
                                     len(self.treeTable.item(i,7).text()) > 0 ):

                                 cursor.execute("INSERT INTO master_modbusTCP(serverId,ip,port,adrRtu,reg,fromAdr,fromCount,toAdr,comment,valid)\
                                 VALUES('"+self.label00.text()+"',\
                                 '"+self.treeTable.item(i,0).text()+"',\
                                 '"+self.treeTable.item(i,1).text()+"',\
                                 '"+self.treeTable.item(i,2).text()+"',\
                                 '"+self.treeTable.item(i,3).text()+"',\
                                 '"+self.treeTable.item(i,4).text()+"',\
                                 '"+self.treeTable.item(i,5).text()+"',\
                                 '"+self.treeTable.item(i,6).text()+"',\
                                 '"+self.treeTable.item(i,7).text()+"',\
                                 1)" )
                                 connDb.commit()
                         except Exception as e:
                             #print(e)
                             pass
                         i+=1
                 self.getDataModbusTCP()

             if(self.label3.text()=="master_modbusRTU"):
                 cursor.execute("delete from master_modbusRTU where serverId= '"+self.label00.text()+"'" )
                 connDb.commit()

                 for i in range(0,self.treeTable.rowCount()):
                         try:
                             if(     len(self.treeTable.item(i,0).text()) > 0 and
                                     len(self.treeTable.item(i,1).text()) > 0 and
                                     len(self.treeTable.item(i,2).text()) > 0 and
                                     len(self.treeTable.item(i,3).text()) > 0 and
                                     len(self.treeTable.item(i,4).text()) > 0 and
                                     len(self.treeTable.item(i,5).text()) > 0 ):

                                 cursor.execute("INSERT INTO master_modbusRTU(serverId,adrRtu,reg,fromAdr,fromCount,toAdr,comment,valid)\
                                 VALUES('"+self.label00.text()+"',\
                                 '"+self.treeTable.item(i,0).text()+"',\
                                 '"+self.treeTable.item(i,1).text()+"',\
                                 '"+self.treeTable.item(i,2).text()+"',\
                                 '"+self.treeTable.item(i,3).text()+"',\
                                 '"+self.treeTable.item(i,4).text()+"',\
                                 '"+self.treeTable.item(i,5).text()+"',\
                                 1)" )
                                 connDb.commit()
                         except Exception as e:
                             #print(e)
                             pass
                         i+=1
                 self.getDataModbusRTU()


             if(self.label3.text()=="master_dcon"):
                 cursor.execute("delete from master_dcon where serverId= '"+self.label00.text()+"'" )
                 connDb.commit()

                 for i in range(0,self.treeTable.rowCount()):
                         try:
                             if(     len(self.treeTable.item(i,0).text()) > 0 and
                                     len(self.treeTable.item(i,1).text()) > 0 and
                                     len(self.treeTable.item(i,2).text()) > 0 and
                                     len(self.treeTable.item(i,3).text()) > 0  ):

                                 cursor.execute("INSERT INTO master_dcon (serverId,model,adrRtu,toAdr,comment,valid)\
                                 VALUES('"+self.label00.text()+"',\
                                 '"+self.treeTable.item(i,0).text()+"',\
                                 '"+self.treeTable.item(i,1).text()+"',\
                                 '"+self.treeTable.item(i,2).text()+"',\
                                 '"+self.treeTable.item(i,3).text()+"',\
                                 1)" )
                                 connDb.commit()
                         except Exception as e:
                             #print(e)
                             pass
                         i+=1
                 self.getDataDcon()

             if(self.label3.text()=="master_http"):
                 cursor.execute("delete from master_http where serverId= '"+self.label00.text()+"'" )
                 connDb.commit()

                 for i in range(0,self.treeTable.rowCount()):
                         try:
                             if(     len(self.treeTable.item(i,0).text()) > 0 and
                                     len(self.treeTable.item(i,1).text()) > 0 and
                                     len(self.treeTable.item(i,2).text()) > 0 and
                                     len(self.treeTable.item(i,3).text()) > 0  ):

                                 cursor.execute("INSERT INTO master_http (serverId,ip,reg,toAdr,fromCount,comment,login,password,valid)\
                                 VALUES('"+self.label00.text()+"',\
                                 '"+self.treeTable.item(i,0).text()+"',\
                                 '"+self.treeTable.item(i,1).text()+"',\
                                 '"+self.treeTable.item(i,2).text()+"',\
                                 '"+self.treeTable.item(i,3).text()+"',\
                                 '"+self.treeTable.item(i,4).text()+"',\
                                 '"+self.treeTable.item(i,5).text()+"',\
                                 '"+self.treeTable.item(i,6).text()+"',\
                                 1)" )
                                 connDb.commit()
                         except Exception as e:
                             print(e)
                             pass
                         i+=1
                 self.getDataHttp()







    def truePanel (self,index):
         if(index == 'master_ping'):
             self.getDataPing()

         if(index == 'master_mercury230'):
             self.getDataMercury()
         if(index == 'master_modbusTCP'):
             self.getDataModbusTCP()
         if(index == 'master_modbusRTU'):
             self.getDataModbusRTU()
         if(index == 'master_dcon'):
             self.getDataDcon()
         if(index == 'master_http'):
             self.getDataHttp()



    def onClickItem (self):
         self.treeTable.clear()
         self.treeTable.setRowCount(0)
         self.srvName.setText("")
         self.label00.setText("")
         self.slaveIP.setText("")
         self.slavePort.setText("")
         self.label3.setText("")
         self.tty.setText("")
         self.ttySpeed.setText("")
         self.label4.setText("")
         self.serverTimeout.setText("")



         try:

             self.slaveIP.setEnabled(True)
             self.slavePort.setEnabled(True)
             self.tty.setEnabled(True)
             self.ttySpeed.setEnabled(True)

             index_list =[i.data() for i in self.treeView.selectedIndexes()]
             s=index_list[0].split(':')
             self.srvName.setText(s[1])
             self.label00.setText(s[0])

             connDb = sqlite3.connect(self.dbPath)
             cursor = connDb.cursor()
             cursor.execute("select ip, port,stype,mtype,tty,speed,timeout from  servers where id = "+s[0])
             dt=cursor.fetchone()
             self.slaveIP.setText(dt[0])
             self.slavePort.setText(dt[1])
             self.label4.setText(dt[2])
             self.label3.setText(dt[3])
             self.tty.setText(dt[4])
             self.ttySpeed.setText(dt[5])
             self.serverTimeout.setText(dt[6])

             self.slvList[0]=dt[2]
             self.srvList[0]=dt[3]
             self.truePanel (self.label3.text())



         except Exception as e:
             index_list =[i.data() for i in self.treeView.selectedIndexes()]
             self.srvName.setText(index_list[0])
             self.slaveIP.setEnabled(False)
             self.slavePort.setEnabled(False)
             self.tty.setEnabled(False)
             self.ttySpeed.setEnabled(False)
            # print(e)

         self.combo1.clear()
         self.combo1.addItems(self.srvList)
         self.combo2.clear()
         self.combo2.addItems(self.slvList)



    def addNewServer(self):
         sender = self.sender()
         self.statusBar().showMessage('Добавление нового сервера')
         self.model.appendRow(QStandardItem("Новый Сервер "))






    def closeEvent(self, event):
         reply = QMessageBox.question(self, 'Сообщение', "Вы уверены, что хотите выйти?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
         if reply == QMessageBox.Yes:
            event.accept()
         else:
             event.ignore()

    def resizeEvent(self,event):
         self.h=self.frameGeometry().height()
         self.treeView.setGeometry(QtCore.QRect(0, 60, 350, self.h-120))
         self.treeTable.setGeometry(QtCore.QRect(10, 50, 1140, self.h-460))
         self.frameTable.setGeometry(QtCore.QRect(380, 350, 1150, self.h-400))



    def sqlLoad(self):
         connDb = sqlite3.connect(self.dbPath)
         cursor = connDb.cursor()
         for row in cursor.execute('SELECT name, id FROM servers where valid=1 ORDER BY id'):
             self.model.appendRow(QStandardItem(str(row[1])+":"+row[0]))

    def saveServer(self):
         self.treeTable.clear()
         self.truePanel ("")
         connDb = sqlite3.connect(self.dbPath)
         cursor = connDb.cursor()
         if(len(self.label00.text())>0 and int(self.label00.text()) >0):
             if(len(self.srvName.text()) > 1):
                 connDb.execute("update servers set name ='"+self.srvName.text()+ "', ip = '"+self.slaveIP.text()+"', port = '"+self.slavePort.text()+"'\
                 ,mtype='"+self.combo1.currentText()+"',stype='"+self.combo2.currentText()+"',tty='"+self.tty.text()+"'\
                 ,speed='"+self.ttySpeed.text()+"',timeout='"+self.serverTimeout.text()+"' where id = "+self.label00.text()+" ")
                 connDb.commit()
                 cursor.execute("select ip, port, mtype,stype,tty,speed,timeout from  servers where id = "+self.label00.text())
                 dt=cursor.fetchone()
                 self.slaveIP.setText(dt[0])
                 self.slavePort.setText(dt[1])
                 self.label3.setText(dt[2])
                 self.label4.setText(dt[3])
                 self.tty.setText(dt[4])
                 self.ttySpeed.setText(dt[5])
                 self.slvList[0]=dt[3]
                 self.srvList[0]=dt[2]
                 self.serverTimeout.setText(dt[6])

         else:
             try:
                 if(len(self.srvName.text()) > 1):
                     cursor.execute("INSERT INTO servers(name,valid)  VALUES( '"+self.srvName.text()+"',1)" )



                     connDb.commit()
             except Exception as e:
                 print(e)
                 pass

         self.model.clear()
         self.model.setHorizontalHeaderLabels(self.header)
         cursor = connDb.cursor()
         for row in cursor.execute('SELECT name, id FROM servers where valid=1 ORDER BY id'):
             self.model.appendRow(QStandardItem(str(row[1])+":"+row[0]))
         self.combo1.clear()
         self.combo1.addItems(self.srvList)
         self.combo2.clear()
         self.combo2.addItems(self.slvList)
         self.truePanel (self.label3.text())

    def saveScr(self):
             pathFolder = self.appPath
             if(os.name=='nt'):
                 slash='\\'
                 bat='.bat'
                 rem ='rem '
                 command = 'start '
             else:
                 slash='/'
                 bat='.sh'
                 rem='# '
                 command=''

             f=open(pathFolder +'scr'+slash+'start_'+self.label00.text() + bat,'w')
             f.write(rem+'Скрипт создан в программе \''+self.versionPr+'\'\n')
             f.write(rem+'Название сервера \''+self.srvName.text()+'\'\n')
             f.write(rem+'Slave адрес \''+self.slaveIP.text()+'\'\n')
             f.write(rem+'Slave порт \''+self.slavePort.text()+'\'\n')
             f.write(rem+'Тип master \''+self.label3.text()+'\'\n')
             f.write(rem+'Тип slave \''+self.label4.text()+'\'\n')
             f.write(rem+'Интерфейс tty \''+self.tty.text()+'\'\n')
             f.write(rem+'Скорость tty \''+self.ttySpeed.text()+'\'\n')

             if(self.label4.text() == 'opcUA' and self.label3.text() =='master_modbusTCP'):
                 f.write(command+sys.executable+' '+pathFolder +'source'+slash+'opcua_master_tcp.py '+self.label00.text() +' '+pathFolder +'db'+slash+'srvDb.db')
             if(self.label4.text() == 'opcUA' and self.label3.text() =='master_ping'):
                 f.write(command+sys.executable+' '+pathFolder +'source'+slash+'opcua_master_ping.py '+self.label00.text() +' '+pathFolder +'db'+slash+'srvDb.db')
             if(self.label4.text() == 'opcUA' and self.label3.text() =='master_dcon'):
                 f.write(command+sys.executable+' '+pathFolder +'source'+slash+'opcua_master_dcon.py '+self.label00.text() +' '+pathFolder +'db'+slash+'srvDb.db')
             if(self.label4.text() == 'opcUA' and self.label3.text() =='master_mercury230'):
                 f.write(command+sys.executable+' '+pathFolder +'source'+slash+'opcua_master_mercury230.py '+self.label00.text() +' '+pathFolder +'db'+slash+'srvDb.db')
             if(self.label4.text() == 'opcUA' and self.label3.text() =='master_modbusRTU'):
                 f.write(command+sys.executable+' '+pathFolder +'source'+slash+'opcua_master_rtu.py '+self.label00.text() +' '+pathFolder +'db'+slash+'srvDb.db')
             if(self.label4.text() == 'opcUA' and self.label3.text() =='master_http'):
                 f.write(command+sys.executable+' '+pathFolder +'source'+slash+'opcua_master_http.py '+self.label00.text() +' '+pathFolder +'db'+slash+'srvDb.db')


             if(self.label4.text() == 'modbusTCP' and self.label3.text() =='master_modbusTCP'):
                 f.write(command+sys.executable+' '+pathFolder +'source'+slash+'modbustcp_master_tcp.py '+self.label00.text() +' '+pathFolder +'db'+slash+'srvDb.db')
             if(self.label4.text() == 'modbusTCP' and self.label3.text() =='master_ping'):
                 f.write(command+sys.executable+' '+pathFolder +'source'+slash+'modbustcp_master_ping.py '+self.label00.text() +' '+pathFolder +'db'+slash+'srvDb.db')
             if(self.label4.text() == 'modbusTCP' and self.label3.text() =='master_dcon'):
                 f.write(command+sys.executable+' '+pathFolder +'source'+slash+'modbustcp_master_dcon.py '+self.label00.text() +' '+pathFolder +'db'+slash+'srvDb.db')
             if(self.label4.text() == 'modbusTCP' and self.label3.text() =='master_mercury230'):
                 f.write(command+sys.executable+' '+pathFolder +'source'+slash+'modbustcp_master_mercury230.py '+self.label00.text() +' '+pathFolder +'db'+slash+'srvDb.db')
             if(self.label4.text() == 'modbusTCP' and self.label3.text() =='master_modbusRTU'):
                 f.write(command+sys.executable+' '+pathFolder +'source'+slash+'modbustcp_master_rtu.py '+self.label00.text() +' '+pathFolder +'db'+slash+'srvDb.db')
             if(self.label4.text() == 'modbusTCP' and self.label3.text() =='master_http'):
                 f.write(command+sys.executable+' '+pathFolder +'source'+slash+'modbustcp_master_http.py '+self.label00.text() +' '+pathFolder +'db'+slash+'srvDb.db')



             f.close()
             ret = pathFolder +''+slash+'scr'+slash+'start_'+self.label00.text() + bat
             return ret

    def runScr(self):

             if(os.name=='nt'):
                 os.system(self.saveScr())
             else:
                 os.system('chmod 777 '+self.saveScr())
                 os.system('xfce4-terminal --command=\'sudo '+self.saveScr()+'\'')





    def delServer(self):
         self.treeTable.clear()
         self.treeTable.setRowCount(0)
         connDb = sqlite3.connect(self.dbPath)

         if(len(self.label00.text())>0 and int(self.label00.text()) >0):
             if(len(self.srvName.text()) > 1):
                 connDb.execute("update servers set valid=0 where id = "+self.label00.text()+" ")
                 connDb.commit()


         self.model.clear()
         self.model.setHorizontalHeaderLabels(self.header)
         cursor = connDb.cursor()
         for row in cursor.execute('SELECT name, id FROM servers where valid=1 ORDER BY id'):
             self.model.appendRow(QStandardItem(str(row[1])+":"+row[0]))

         self.slaveIP.setText("")
         self.slavePort.setText("")
         self.label3.setText("")
         self.srvName.setText("")
Example #33
0
    def initUI(self):

         self.srvList=["",
                               "master_mercury230",
                               "master_modbusRTU",
                               "master_modbusTCP",
                               "master_http",
                               "master_dcon",
                               "master_ping"]
         self.slvList=["","opcUA","modbusTCP"]

         if(os.name=='nt'):

             self.appPath=os.path.abspath(sys.argv[0]).replace(os.path.basename(__file__),'')


             self.imgPath=self.appPath+"img\\"
             self.dbPath=self.appPath+"db\\srvDb.db"

         else:
             self.appPath=os.path.abspath(sys.argv[0]).replace(os.path.basename(__file__),'')
             self.imgPath=self.appPath+"img/"
             self.dbPath=self.appPath+"db/srvDb.db"


         self.versionPr='ScadaPy Конфигуратор сервера v.3.11'
         self.setGeometry(400, 200, 1000, 520)
         self.setWindowTitle(self.versionPr)
         self.setWindowIcon(QIcon( self.imgPath+'gnome-monitor.png'))
         self.h=self.frameGeometry().height()

         font = QFont()
         font.setPointSize(12)


         self.label0=QLabel(self)
         self.label0.setFont(font)
         self.label0.move(400, 60)
         self.label0.resize(300,25)
         self.label0.setText("ID сервера")
         self.label00=QLabel(self)
         self.label00.setFont(font)
         self.label00.move(550, 60)
         self.label00.resize(300,25)
         self.label00.setText("")

         self.label1=QLabel(self)
         self.label1.setFont(font)
         self.label1.move(400, 90)
         self.label1.resize(140,25)
         self.label1.setText("Название сервера")
         self.srvName = QLineEdit(self)
         self.srvName.setToolTip('Пример: Сервер Маш.Зала №1')
         self.srvName.move(550, 90)
         self.srvName.setFont(font)
         self.srvName.resize(300,25)

         self.label2=QLabel(self)
         self.label2.setFont(font)
         self.label2.move(400, 120)
         self.label2.resize(140,25)
         self.label2.setText("Slave IP address")
         self.slaveIP = QLineEdit(self)
         self.slaveIP.setToolTip('Пример: 192.168.0.111')
         self.slaveIP.move(550, 120)
         self.slaveIP.setFont(font)
         self.slaveIP.resize(300,25)


         self.label2=QLabel(self)
         self.label2.setFont(font)
         self.label2.move(400, 150)
         self.label2.resize(140,25)
         self.label2.setText("Slave Port")
         self.slavePort = QLineEdit(self)
         self.slavePort.setToolTip('Пример modbus: 502\nПример opcua: 4840')
         self.slavePort.move(550, 150)
         self.slavePort.setFont(font)
         self.slavePort.resize(100,25)

         self.label7=QLabel(self)
         self.label7.setFont(font)
         self.label7.move(680, 150)
         self.label7.resize(140,25)
         self.label7.setText("Timeout")
         self.serverTimeout = QLineEdit(self)
         self.serverTimeout.setToolTip('Пример ms: 1 ')
         self.serverTimeout.move(750, 150)
         self.serverTimeout.setFont(font)
         self.serverTimeout.resize(100,25)




         self.label3=QLabel(self)
         self.label3.setFont(font)
         self.label3.move(400, 180)
         self.label3.resize(140,25)
         self.label3.setText("Тип Master")
         self.label3=QLabel(self)
         self.label3.setFont(font)
         self.label3.move(550, 180)
         self.label3.resize(340,25)
         self.label3.setText("---")

         self.combo1 = QComboBox(self)
         self.combo1.move(550, 210)
         self.combo1.setFont(font)
         self.combo1.resize(320,25)
         self.combo1.addItems(self.srvList)

         self.label4=QLabel(self)
         self.label4.setFont(font)
         self.label4.move(400, 240)
         self.label4.resize(140,25)
         self.label4.setText("Тип Slave")
         self.label4=QLabel(self)
         self.label4.setFont(font)
         self.label4.move(550, 240)
         self.label4.resize(340,25)
         self.label4.setText("---")

         self.combo2 = QComboBox(self)
         self.combo2.move(550, 270)
         self.combo2.setFont(font)
         self.combo2.resize(320,25)
         self.combo2.addItems(self.slvList)

         self.label5=QLabel(self)
         self.label5.setFont(font)
         self.label5.move(400, 300)
         self.label5.resize(140,25)
         self.label5.setText("Порт /dev/tty*")
         self.tty=QLineEdit(self)
         self.tty.setToolTip('Пример linux: /dev/ttyUSB0\nПример windows: com19')
         self.tty.setFont(font)
         self.tty.move(550, 300)
         self.tty.resize(150,25)

         self.label6=QLabel(self)
         self.label6.setFont(font)
         self.label6.move(720, 300)
         self.label6.resize(140,25)
         self.label6.setText("скорость")
         self.ttySpeed=QLineEdit(self)
         self.ttySpeed.setToolTip('Пример : 9600')
         self.ttySpeed.setFont(font)
         self.ttySpeed.move(800, 300)
         self.ttySpeed.resize(150,25)



         exitAction = QAction(QIcon( self.imgPath+'exit.png'), '&Выход', self)
         exitAction.setShortcut('Ctrl+Q')
         exitAction.setStatusTip('Выход из программы')
         exitAction.triggered.connect(qApp.quit)


         addServerAction = QAction(QIcon(self.imgPath+'add.png'), '&Добавить', self)
         addServerAction.setStatusTip('Добавить сервер')
         addServerAction.triggered.connect(self.addNewServer)

         delServerAction = QAction(QIcon(self.imgPath+'button_cancel.png'), '&Удалить', self)
         delServerAction.setStatusTip('Удалить сервер')
         delServerAction.triggered.connect(self.delServer)


         saveServerAction = QAction(QIcon(self.imgPath+'filesave.png'), '&Сохранить', self)
         saveServerAction.setStatusTip('Сохранить сервер')
         saveServerAction.triggered.connect(self.saveServer)

         saveScr = QAction(QIcon(self.imgPath+'bottom.png'), '&Сохранить скрипт', self)
         saveScr.setStatusTip('Сохранить скрипт')
         saveScr.triggered.connect(self.saveScr)

         runScr = QAction(QIcon(self.imgPath+'run.png'), '&Запустить скрипт', self)
         runScr.setStatusTip('Запустить скрипт')
         runScr.triggered.connect(self.runScr)


         menubar = self.menuBar()
         fileMenu = menubar.addMenu('&Команды')
         fileMenu.addAction(addServerAction)
         fileMenu.addAction(delServerAction)
         fileMenu.addAction(saveServerAction)
         fileMenu.addAction(saveScr)
         fileMenu.addAction(runScr)
         fileMenu.addAction(exitAction)


         self.toolbar = self.addToolBar('Выход')
         self.toolbar.addAction(exitAction)
         self.toolbar.addAction(addServerAction)
         self.toolbar.addAction(delServerAction)
         self.toolbar.addAction(saveServerAction)
         self.toolbar.addAction(saveScr)
         self.toolbar.addAction(runScr)




        # self.statusBar().showMessage('Загрузка данных')

         self.treeView = QTreeView(self)
         self.treeView.setFont(font)
         self.treeView.setObjectName("treeView")
         self.model = QStandardItemModel()
         self.treeView.setModel(self.model)
         self.header = ['Название сервера']
         self.model.setHorizontalHeaderLabels(self.header)

         self.sqlLoad()
         self.treeView.clicked.connect(self.onClickItem)





         self.frameTable = QFrame(self)
         self.frameTable.move(380, 350)
         self.frameTable.setFont(font)
         self.frameTable.resize(1350,950)
         self.frameTable.setVisible(True)

         self.addRow = QPushButton(self.frameTable)
         self.addRow.setIcon(QIcon(self.imgPath+'add.png'))
         self.addRow.move(10, 10)
         self.addRow.resize(30,30)
         self.addRow.clicked.connect(self.addRowTable)

         self.saveTable = QPushButton(self.frameTable)
         self.saveTable.setIcon(QIcon(self.imgPath+'filesave.png'))
         self.saveTable.resize(30,30)
         self.saveTable.move(50, 10)
         self.saveTable.clicked.connect(self.saveRowTable)


         self.treeTable = QTableWidget(self.frameTable)
         fontTable = QFont()
         fontTable.setPointSize(10)
         self.treeTable.setFont(fontTable)

         self.show()
Example #34
0
class StepListView:
    def __init__(self, main_window):
        self.main_window = main_window
        self.lst_steps: CustomStepsListView = self.main_window.lst_steps
        self.controller = StepListController(self, self.main_window.world)

        # menu
        delete_action = QAction("Delete", self.lst_steps)
        delete_action.triggered.connect(self.on_delete_selected_item)

        self.menu = QMenu()
        self.menu.addAction(delete_action)

        # setup model
        self.model = QStandardItemModel()
        self.lst_steps.setModel(self.model)
        self.lst_steps.setItemDelegate(StepItemDelegate())

        # ui events
        self.lst_steps.selectionModel().currentChanged.connect(
            self.on_step_selected)
        self.lst_steps.setContextMenuPolicy(Qt.CustomContextMenu)
        self.lst_steps.customContextMenuRequested.connect(
            self.on_display_context_menu)
        self.lst_steps.dropEventSignal.connect(self.on_drop_event)

    def on_drop_event(self, model_index: QModelIndex):
        selected_model_indexes = self.lst_steps.selectedIndexes()
        self.delete_steps_by_indexes(selected_model_indexes,
                                     delete_from_db=False)

        def step_with_order(order):
            step_entity = self.model.item(order).data(STEP_LIST_OBJECT_ROLE)
            step_entity.order = order
            return step_entity

        steps = [step_with_order(n) for n in range(self.model.rowCount())]
        self.controller.update_multiple_steps(steps)

    def get_step_entity_at_index(self, model_index):
        return model_index.data(STEP_LIST_OBJECT_ROLE)

    def select_step_at_index(self, model_index):
        self.lst_steps.setCurrentIndex(model_index)

    def indexes_for_selected_rows(self):
        return self.lst_steps.selectedIndexes()

    def delete_steps_by_indexes(self, model_indexes, delete_from_db=True):
        for items in reversed(sorted(model_indexes)):
            if delete_from_db:
                step_entity: StepEntity = self.get_step_entity_at_index(items)
                self.controller.delete_step(step_entity)
            self.model.takeRow(items.row())

    def on_delete_selected_item(self):
        selected_model_indexes = self.indexes_for_selected_rows()
        if not selected_model_indexes:
            return

        self.delete_steps_by_indexes(selected_model_indexes)

        before_first_row_to_delete = selected_model_indexes[0].row() - 1
        if before_first_row_to_delete >= 0:
            previous_item: QStandardItem = self.model.item(
                before_first_row_to_delete)
            if previous_item:
                self.select_step_at_index(previous_item.index())

    def on_display_context_menu(self, position):
        index: QModelIndex = self.lst_steps.indexAt(position)
        if not index.isValid():
            return

        global_position = self.lst_steps.viewport().mapToGlobal(position)
        self.menu.exec_(global_position)

    def clear_steps(self):
        self.model.clear()

    def update_steps(self, steps):
        for step in steps:
            self.add_step_widget(step, select_item=False)

    def select_step_at(self, position):
        first_item: QStandardItem = self.model.item(position)
        self.lst_steps.setCurrentIndex(first_item.index())

    def add_step_widget(self, step: StepEntity, select_item=True):
        logging.info("Adding a new widget for {}".format(step))
        step_item = QStandardItem("({}) {}".format(step.step_type.value,
                                                   step.title))
        step_item.setData(step, STEP_LIST_OBJECT_ROLE)
        step_item.setData(QVariant(step.id), STEP_LIST_ID_ROLE)
        step_item.setDragEnabled(True)
        step_item.setDropEnabled(False)
        self.model.appendRow(step_item)

        if select_item:
            index = self.model.indexFromItem(step_item)
            self.lst_steps.setCurrentIndex(index)

    def on_step_selected(self, current: QModelIndex):
        if not current:
            return

        selected_step_id = current.data(STEP_LIST_ID_ROLE)
        self.controller.trigger_step_selected(selected_step_id)
Example #35
0
class E5NetworkMonitor(QDialog, Ui_E5NetworkMonitor):
    """
    Class implementing a network monitor dialog.
    """
    _monitor = None
    
    @classmethod
    def instance(cls, networkAccessManager):
        """
        Class method to get a reference to our singleton.
        
        @param networkAccessManager reference to the network access manager
            (QNetworkAccessManager)
        @return reference to the network monitor singleton (E5NetworkMonitor)
        """
        if cls._monitor is None:
            cls._monitor = E5NetworkMonitor(networkAccessManager)
        
        return cls._monitor
    
    @classmethod
    def closeMonitor(cls):
        """
        Class method to close the monitor dialog.
        """
        if cls._monitor is not None:
            cls._monitor.close()
    
    def __init__(self, networkAccessManager, parent=None):
        """
        Constructor
        
        @param networkAccessManager reference to the network access manager
            (QNetworkAccessManager)
        @param parent reference to the parent widget (QWidget)
        """
        super(E5NetworkMonitor, self).__init__(parent)
        self.setupUi(self)
        self.setWindowFlags(Qt.Window)
        
        self.__requestHeaders = QStandardItemModel(self)
        self.__requestHeaders.setHorizontalHeaderLabels(
            [self.tr("Name"), self.tr("Value")])
        self.requestHeadersList.setModel(self.__requestHeaders)
        self.requestHeadersList.horizontalHeader().setStretchLastSection(True)
        self.requestHeadersList.doubleClicked.connect(self.__showHeaderDetails)
        
        self.__replyHeaders = QStandardItemModel(self)
        self.__replyHeaders.setHorizontalHeaderLabels(
            [self.tr("Name"), self.tr("Value")])
        self.responseHeadersList.setModel(self.__replyHeaders)
        self.responseHeadersList.horizontalHeader().setStretchLastSection(True)
        self.responseHeadersList.doubleClicked.connect(
            self.__showHeaderDetails)
        
        self.requestsList.horizontalHeader().setStretchLastSection(True)
        self.requestsList.verticalHeader().setMinimumSectionSize(-1)
        
        self.__proxyModel = QSortFilterProxyModel(self)
        self.__proxyModel.setFilterKeyColumn(-1)
        self.searchEdit.textChanged.connect(
            self.__proxyModel.setFilterFixedString)
        
        self.removeButton.clicked.connect(self.requestsList.removeSelected)
        self.removeAllButton.clicked.connect(self.requestsList.removeAll)
        
        self.__model = E5RequestModel(networkAccessManager, self)
        self.__proxyModel.setSourceModel(self.__model)
        self.requestsList.setModel(self.__proxyModel)
        self.__proxyModel.rowsInserted.connect(
            self.requestsList.scrollToBottom)
        self.requestsList.selectionModel()\
            .currentChanged[QModelIndex, QModelIndex]\
            .connect(self.__currentChanged)
        
        fm = self.fontMetrics()
        em = fm.width("m")
        self.requestsList.horizontalHeader().resizeSection(0, em * 5)
        self.requestsList.horizontalHeader().resizeSection(1, em * 20)
        self.requestsList.horizontalHeader().resizeSection(3, em * 5)
        self.requestsList.horizontalHeader().resizeSection(4, em * 15)
        
        self.__headersDlg = None
    
    def closeEvent(self, evt):
        """
        Protected method called upon closing the dialog.
        
        @param evt reference to the close event object (QCloseEvent)
        """
        self.__class__._monitor = None
        super(E5NetworkMonitor, self).closeEvent(evt)
    
    def reject(self):
        """
        Public slot to close the dialog with a Reject status.
        """
        self.__class__._monitor = None
        super(E5NetworkMonitor, self).reject()
    
    def __currentChanged(self, current, previous):
        """
        Private slot to handle a change of the current index.
        
        @param current new current index (QModelIndex)
        @param previous old current index (QModelIndex)
        """
        self.__requestHeaders.setRowCount(0)
        self.__replyHeaders.setRowCount(0)
        
        if not current.isValid():
            return
        
        row = self.__proxyModel.mapToSource(current).row()
        
        req = self.__model.requests[row].request
        
        for header in req.rawHeaderList():
            self.__requestHeaders.insertRows(0, 1, QModelIndex())
            self.__requestHeaders.setData(
                self.__requestHeaders.index(0, 0),
                str(header, "utf-8"))
            self.__requestHeaders.setData(
                self.__requestHeaders.index(0, 1),
                str(req.rawHeader(header), "utf-8"))
            self.__requestHeaders.item(0, 0).setFlags(
                Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.__requestHeaders.item(0, 1).setFlags(
                Qt.ItemIsSelectable | Qt.ItemIsEnabled)
        
        for header in self.__model.requests[row].replyHeaders:
            self.__replyHeaders.insertRows(0, 1, QModelIndex())
            self.__replyHeaders.setData(
                self.__replyHeaders.index(0, 0),
                header[0])
            self.__replyHeaders.setData(
                self.__replyHeaders.index(0, 1),
                header[1])
            self.__replyHeaders.item(0, 0).setFlags(
                Qt.ItemIsSelectable | Qt.ItemIsEnabled)
            self.__replyHeaders.item(0, 1).setFlags(
                Qt.ItemIsSelectable | Qt.ItemIsEnabled)
    
    def __showHeaderDetails(self, index):
        """
        Private slot to show a dialog with the header details.
        
        @param index index of the entry to show (QModelIndex)
        """
        if not index.isValid():
            return
        
        headerList = self.sender()
        if headerList is None:
            return
        
        row = index.row()
        name = headerList.model().data(headerList.model().index(row, 0))
        value = headerList.model().data(headerList.model().index(row, 1))
        if self.__headersDlg is None:
            from .E5NetworkHeaderDetailsDialog import \
                E5NetworkHeaderDetailsDialog
            self.__headersDlg = E5NetworkHeaderDetailsDialog(self)
        self.__headersDlg.setData(name, value)
        self.__headersDlg.show()
class SkipOnlyDialog(QDialog):
    def __init__(self, columns=None, skip=None, only=None, parent=None):
        super(SkipOnlyDialog, self).__init__(parent)
        self.setWindowTitle("Select Columns")
        self.columns = columns
        self.selected_variables = (
            []
        )  # Names of selected variables.  Only updated when accepting the dialog.
        # Select 'only' by default (unless a skip list is passed in)
        # starting_only and only are booleans to indicate whether 'only' is selected
        # starting_selected and selected are boolean arrays to indicate whether each variable is selected
        if skip is not None:
            self.starting_only = False
            self.starting_selected = [(c in skip) for c in self.columns]
        elif only is not None:
            self.starting_only = True
            self.starting_selected = [(c in only) for c in self.columns]
        elif skip is None and only is None:
            self.starting_only = True
            self.starting_selected = [False for _ in self.columns]
        else:
            raise ValueError("Can't pass both 'skip' and 'only'")

        # Available- Left Side
        self.left_model = QStandardItemModel(self)
        self.left_proxy = QSortFilterProxyModel(self)
        self.left_proxy.setSourceModel(self.left_model)
        self.left_proxy.setFilterKeyColumn(0)  # Filters based on the only column
        self.left_proxy.setFilterCaseSensitivity(
            Qt.CaseInsensitive
        )  # Case insensitive search
        # Selected - Right side
        self.right_model = QStandardItemModel()
        self.right_proxy = QSortFilterProxyModel(self)
        self.right_proxy.setSourceModel(self.right_model)
        self.right_proxy.setFilterKeyColumn(0)  # Filters based on the only column
        self.right_proxy.setFilterCaseSensitivity(
            Qt.CaseInsensitive
        )  # Case insensitive search

        # Setup Layout
        layout = QGridLayout(self)
        layout.setColumnStretch(0, 2)
        layout.setColumnStretch(1, 1)
        layout.setColumnStretch(2, 2)

        # Left Side Group Box ("Available")
        left_list_box = QGroupBox("Available Variables")
        left_list_box_layout = QVBoxLayout()
        # Multiselect listing available columns
        self.left_list = QListView(self)
        self.left_list.setModel(self.left_proxy)
        self.left_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.left_list.selectionModel().selectionChanged.connect(
            self.left_selected_change
        )
        self.left_list.setEditTriggers(QAbstractItemView.NoEditTriggers)
        left_list_box_layout.addWidget(self.left_list)
        # Add a search box
        self.left_list_search = QLineEdit(parent=self)
        self.left_list_search.setPlaceholderText("Search...")
        self.left_list_search.textChanged.connect(self.left_proxy.setFilterFixedString)
        left_list_box_layout.addWidget(self.left_list_search)
        # Set layout and add to the main layout
        left_list_box.setLayout(left_list_box_layout)
        layout.addWidget(left_list_box, 0, 0)

        # Add/Remove Buttons
        btns = QWidget()
        btns_layout = QVBoxLayout()
        btns.setLayout(btns_layout)
        # Add
        self.btn_add = QPushButton(text="Add ->", parent=self)
        self.btn_add.clicked.connect(self.add)
        self.btn_add.setEnabled(False)
        btns_layout.addWidget(self.btn_add)
        # Remove
        self.btn_remove = QPushButton(text="<- Remove", parent=self)
        self.btn_remove.clicked.connect(self.remove)
        self.btn_remove.setEnabled(False)
        btns_layout.addWidget(self.btn_remove)
        # Undo Changes
        self.btn_undo = QPushButton(text="Undo Changes", parent=self)
        self.btn_undo.clicked.connect(self.undo)
        self.btn_undo.setEnabled(False)
        btns_layout.addWidget(self.btn_undo)
        # Reset
        self.btn_reset = QPushButton(text="Reset", parent=self)
        self.btn_reset.clicked.connect(self.reset)
        self.btn_reset.setEnabled(False)
        btns_layout.addWidget(self.btn_reset)
        # Add to layout
        layout.addWidget(btns, 0, 1)

        # Right Side Group Box ("Selected")
        right_list_box = QGroupBox("Selected Variables")
        right_list_box_layout = QVBoxLayout()
        # Multiselect listing current selected columns
        self.right_list = QListView(self)
        self.right_list.setModel(self.right_proxy)
        self.right_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.right_list.selectionModel().selectionChanged.connect(
            self.right_selected_change
        )
        self.right_list.setEditTriggers(QAbstractItemView.NoEditTriggers)
        right_list_box_layout.addWidget(self.right_list)
        # Add a search box
        self.right_list_search = QLineEdit(parent=self)
        self.right_list_search.setPlaceholderText("Search...")
        self.right_list_search.textChanged.connect(
            self.right_proxy.setFilterFixedString
        )
        right_list_box_layout.addWidget(self.right_list_search)
        # Set layout and add to the main layout
        right_list_box.setLayout(right_list_box_layout)
        layout.addWidget(right_list_box, 0, 2)

        # Radio Select for Skip/Only
        self.radio_btns = QGroupBox("Skip Selected or Only Selected")
        radio_btns_layout = QHBoxLayout()
        self.radio_btns.setLayout(radio_btns_layout)
        self.radio_skip = QRadioButton("skip")
        radio_btns_layout.addWidget(self.radio_skip)
        self.radio_only = QRadioButton("only")
        self.radio_only.setChecked(True)
        radio_btns_layout.addWidget(self.radio_only)
        # If either button changes, a toggle signal is called for each one.  No need to pass the "checked" parameter.
        self.radio_skip.toggled.connect(lambda is_checked: self.update_result())
        layout.addWidget(self.radio_btns, 1, 2)

        # Result label
        self.result_label = QLabel(parent=self)
        self.result_label.setText("0 Variables to be used")
        layout.addWidget(self.result_label, 2, 0)

        # Ok/Cancel
        QBtn = QDialogButtonBox.Ok | QDialogButtonBox.Cancel

        self.buttonBox = QDialogButtonBox(QBtn)
        self.buttonBox.accepted.connect(self.submit)
        self.buttonBox.rejected.connect(self.reject)
        layout.addWidget(self.buttonBox, 2, 2)

        # Run reset to initialize
        self.undo()

    def undo(self):
        """
        Reset both list views and set the parameters ('only' and 'selected') to their starting values
        """
        # Clear lists
        self.left_model.clear()
        self.right_model.clear()
        # Set to the starting state
        self.selected = (
            self.starting_selected.copy()
        )  # Take a copy, don't refer to the same list
        self.only = self.starting_only
        for v, is_selected in zip(self.columns, self.selected):
            if not is_selected:
                self.left_model.appendRow(QStandardItem(v))
            else:
                self.right_model.appendRow(QStandardItem(v))
        self.update_result()
        self.btn_undo.setEnabled(False)  # No reason to undo twice

    def reset(self):
        """
        Remove the initialized state to do a complete reset
        """
        self.starting_only = True
        self.starting_selected = [False for _ in self.columns]
        self.undo()
        self.btn_reset.setEnabled(False)  # No reason to reset twice

    def left_selected_change(self):
        """
        Track the currently selected rows on the left
        """
        left_selected_num = len(self.left_list.selectedIndexes())
        if left_selected_num == 0:
            self.btn_add.setEnabled(False)
        else:
            self.btn_add.setEnabled(True)

    def right_selected_change(self):
        """
        track the currently selected rows on the right
        """
        right_selected_num = len(self.right_list.selectedIndexes())
        if right_selected_num == 0:
            self.btn_remove.setEnabled(False)
        else:
            self.btn_remove.setEnabled(True)

    def reset_list(self, side):
        """Clear the search field and show the full list"""
        if side == "available":
            self.left_list_search.setText("")
            self.left_model.clear()
            for v, is_selected in zip(self.columns, self.selected):
                if not is_selected:
                    self.left_model.appendRow(QStandardItem(v))
        elif side == "selected":
            self.right_list_search.setText("")
            self.right_model.clear()
            for v, is_selected in zip(self.columns, self.selected):
                if is_selected:
                    self.right_model.appendRow(QStandardItem(v))

    def add(self):
        """
        Move currently selected columns on the left to the right side
        """
        # Clear any right-side search
        self.reset_list("selected")
        # Get selection rows (indexed directly in the model)
        left_selected = sorted(
            [
                self.left_proxy.mapToSource(idx).row()
                for idx in self.left_list.selectedIndexes()
            ]
        )
        # Move items
        for idx in left_selected:
            item = self.left_model.takeItem(idx)
            self.right_model.appendRow(item)
            # Mark as selected
            col_idx = self.columns.index(item.text())
            self.selected[col_idx] = True
        # Delete rows after moving them (don't do it during because it causes index changes)
        for idx in reversed(
            left_selected
        ):  # Remove in reverse order, otherwise index changes
            self.left_model.removeRow(idx)
        # Update label
        self.update_result()
        # Disable Add since nothing is now selected
        self.btn_add.setEnabled(False)

    def remove(self):
        """
        Move currently selected columns on the right to the left side
        """
        # Clear any left-side search
        self.reset_list("available")
        # Get selection rows (indexed directly in the model)
        right_selected = sorted(
            [
                self.right_proxy.mapToSource(idx).row()
                for idx in self.right_list.selectedIndexes()
            ]
        )
        # Move items
        for idx in right_selected:
            item = self.right_model.takeItem(idx)
            self.left_model.appendRow(item)
            # Mark as not selected
            col_idx = self.columns.index(item.text())
            self.selected[col_idx] = False
        # Delete rows after moving them (don't do it during because it causes index changes)
        for idx in reversed(
            right_selected
        ):  # Remove in reverse order, otherwise index changes
            self.right_model.removeRow(idx)
        # Update label
        self.update_result()
        # Disable Remove since nothing is now selected
        self.btn_remove.setEnabled(False)

    def update_result(self):
        """
        Update the tracking of what variables will be used
        """
        self.only = self.radio_only.isChecked()
        num_selected = sum(self.selected)
        if num_selected == 0:
            self.result_label.setText(f"Using all {len(self.columns):,} variables")
        elif self.only:
            self.result_label.setText(
                f"Only using {num_selected:,} of {len(self.columns):,} variables"
            )
        else:
            self.result_label.setText(
                f"Skipping {num_selected:,} of {len(self.columns):,} variables"
            )

        # Set the undo button status
        if self.selected == self.starting_selected and self.only == self.starting_only:
            # In the starting state
            self.btn_undo.setEnabled(False)
        else:
            self.btn_undo.setEnabled(True)

        # Set the reset button status
        if num_selected == 0 and self.only:
            # In the default state
            self.btn_reset.setEnabled(False)
        else:
            self.btn_reset.setEnabled(True)

    def submit(self):
        # TODO: Add any warnings here
        self.selected_variables = [
            c for (c, is_selected) in zip(self.columns, self.selected) if is_selected
        ]
        self.accept()

    @staticmethod
    def get_skip_only(columns=None, skip=None, only=None, parent=None):
        if columns is None:
            return "No columns", None, None
        # Launch dialog to select skip and only
        dlg = SkipOnlyDialog(columns, skip, only, parent)
        result = dlg.exec_()
        # Get info from the dialog
        label = dlg.result_label.text()
        if dlg.only:
            skip = None
            only = dlg.selected_variables
        else:
            skip = dlg.selected_variables
            only = None
        # Return
        return label, skip, only
Example #37
0
    def initUI(self):
        mainLayout = QVBoxLayout()

        grid1 = QGridLayout()
        grid1.setSpacing(10)

        # 消息框
        self.msgbox = QTextBrowser()
        self.msgbox.setReadOnly(True)
        self.msgbox.append(info)
        grid1.addWidget(self.msgbox, 0, 0, 1, 4)

        # 发送消息框
        self.input = QLineEdit()
        self.send_msg = QPushButton('发送')
        grid1.addWidget(self.input, 1, 0, 1, 3)
        grid1.addWidget(self.send_msg, 1, 3, 1, 1)
        self.send_msg.clicked.connect(self.sendMsg)

        # 消息发送板块
        msgGroupBox = QGroupBox('消息发送')
        msgGroupBox.setLayout(grid1)

        # 文件传输板块
        fileGroupBox = QGroupBox('文件传输')
        grid2 = QGridLayout()
        grid2.setSpacing(10)

        # 选择工作文件夹
        lbw = QLabel('文件夹:')
        self.fpath = QLineEdit('./cfile')
        sel_f = QPushButton('选择文件夹')
        grid2.addWidget(lbw, 2, 0, 1, 1)
        grid2.addWidget(self.fpath, 2, 1, 1, 3)
        grid2.addWidget(sel_f, 2, 4, 1, 1)
        sel_f.clicked.connect(self.showDialog)

        # 展示本机文件列表
        lbcf = QLabel('本机文件:')
        self.cflist = QListView()
        self.cmodel = QStandardItemModel(self.cflist)
        grid2.addWidget(lbcf, 4, 0, 1, 2)
        grid2.addWidget(self.cflist, 5, 0, 8, 2)

        # 展示服务器文件列表
        lbsf = QLabel('服务器文件:')
        self.sflist = QListView()
        self.smodel = QStandardItemModel(self.sflist)
        grid2.addWidget(lbsf, 4, 3, 1, 2)
        grid2.addWidget(self.sflist, 5, 3, 8, 2)

        # 添加操作按钮
        self.bsend = QToolButton()
        self.brec = QToolButton()
        self.bsend.setArrowType(Qt.RightArrow)
        self.brec.setArrowType(Qt.LeftArrow)
        self.brec.setEnabled(False)
        self.bsend.setEnabled(False)
        grid2.addWidget(self.bsend, 7, 2, 1, 1)
        grid2.addWidget(self.brec, 9, 2, 1, 1)
        self.bsend.clicked.connect(
            lambda: self.getList(self.cmodel, self.clist_num, 'sendf'))
        self.brec.clicked.connect(
            lambda: self.getList(self.smodel, self.slist_num, 'dwnf'))

        self.cmodel.itemChanged.connect(
            lambda: self.onChanged(self.clist_num, self.bsend))
        self.smodel.itemChanged.connect(
            lambda: self.onChanged(self.slist_num, self.brec))

        # 添加进度条
        self.pro = QProgressBar()
        grid2.addWidget(self.pro, 13, 0, 1, 5)

        fileGroupBox.setLayout(grid2)

        mainLayout.addWidget(msgGroupBox)
        mainLayout.addWidget(fileGroupBox)

        self.setLayout(mainLayout)

        self.resize(640, 640)
Example #38
0
class TableView(QTableView):
    def __init__(self, parent=None):
        super(TableView, self).__init__(parent)
        self.resize(800, 600)
        self.setContextMenuPolicy(Qt.ActionsContextMenu)  # 右键菜单
        self.setEditTriggers(self.NoEditTriggers)  # 禁止编辑
        self.doubleClicked.connect(self.onDoubleClick)
        self.addAction(QAction("复制", self, triggered=self.copyData))
        self.myModel = QStandardItemModel()  # model
        self.initHeader()  # 初始化表头
        self.setModel(self.myModel)
        self.initData()  # 初始化模拟数据

    def onDoubleClick(self, index):
        print(index.row(), index.column(), index.data())

    def keyPressEvent(self, event):
        super(TableView, self).keyPressEvent(event)
        # Ctrl + C
        if event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_C:
            self.copyData()

    def copyData(self):
        count = len(self.selectedIndexes())
        if count == 0:
            return
        if count == 1:  # 只复制了一个
            QApplication.clipboard().setText(
                self.selectedIndexes()[0].data())  # 复制到剪贴板中
            QMessageBox.information(self, "提示", "已复制一个数据")
            return
        rows = set()
        cols = set()
        for index in self.selectedIndexes():  # 得到所有选择的
            rows.add(index.row())
            cols.add(index.column())
            # print(index.row(),index.column(),index.data())
        if len(rows) == 1:  # 一行
            QApplication.clipboard().setText("\t".join(
                [index.data() for index in self.selectedIndexes()]))  # 复制
            QMessageBox.information(self, "提示", "已复制一行数据")
            return
        if len(cols) == 1:  # 一列
            QApplication.clipboard().setText("\r\n".join(
                [index.data() for index in self.selectedIndexes()]))  # 复制
            QMessageBox.information(self, "提示", "已复制一列数据")
            return
        mirow, marow = min(rows), max(rows)  # 最(少/多)行
        micol, macol = min(cols), max(cols)  # 最(少/多)列
        print(mirow, marow, micol, macol)
        arrays = [["" for _ in range(macol - micol + 1)]
                  for _ in range(marow - mirow + 1)]  # 创建二维数组(并排除前面的空行和空列)
        print(arrays)
        # 填充数据
        for index in self.selectedIndexes():  # 遍历所有选择的
            arrays[index.row() - mirow][index.column() - micol] = index.data()
        print(arrays)
        data = ""  # 最后的结果
        for row in arrays:
            data += "\t".join(row) + "\r\n"
        print(data)
        QApplication.clipboard().setText(data)  # 复制到剪贴板中
        QMessageBox.information(self, "提示", "已复制")

    def initHeader(self):
        for i in range(5):
            self.myModel.setHorizontalHeaderItem(
                i, QStandardItem("表头" + str(i + 1)))

    def initData(self):
        for row in range(100):
            for col in range(5):
                self.myModel.setItem(
                    row, col,
                    QStandardItem("row: {row},col: {col}".format(row=row + 1,
                                                                 col=col + 1)))
Example #39
0
class ContextPanel(QTabWidget):
    # consts
    CONTEXT_TYPE_NATIVE = 0
    CONTEXT_TYPE_JAVA = 1
    CONTEXT_TYPE_EMULATOR = 2

    onShowMemoryRequest = pyqtSignal(str, name='onShowMemoryRequest')

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

        self._app_window = parent
        self.setAutoFillBackground(True)

        self._nativectx_model = QStandardItemModel(0, 4)
        self._nativectx_model.setHeaderData(0, Qt.Horizontal, 'Reg')
        self._nativectx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                            Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._nativectx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(2, Qt.Horizontal, 'Decimal')
        #self._nativectx_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(3, Qt.Horizontal, 'Telescope')

        self._nativectx_list = DwarfListView()
        self._nativectx_list.setModel(self._nativectx_model)

        self._nativectx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._nativectx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._nativectx_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self._nativectx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._nativectx_list.customContextMenuRequested.connect(
            self._on_native_contextmenu)

        self._emulatorctx_model = QStandardItemModel(0, 3)
        self._emulatorctx_model.setHeaderData(0, Qt.Horizontal, 'Reg')
        self._emulatorctx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._emulatorctx_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._emulatorctx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._emulatorctx_model.setHeaderData(2, Qt.Horizontal, 'Decimal')

        self._emulatorctx_list = DwarfListView()
        self._emulatorctx_list.setModel(self._emulatorctx_model)

        self._emulatorctx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._emulatorctx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)

        self._emulatorctx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._emulatorctx_list.customContextMenuRequested.connect(
            self._on_emulator_contextmenu)

        self._javactx_model = QStandardItemModel(0, 3)
        self._javactx_model.setHeaderData(0, Qt.Horizontal, 'Argument')
        self._javactx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                          Qt.TextAlignmentRole)
        self._javactx_model.setHeaderData(1, Qt.Horizontal, 'Class')
        #self._javactx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._javactx_model.setHeaderData(2, Qt.Horizontal, 'Value')

        self._javactx_list = DwarfListView()
        self._javactx_list.setModel(self._javactx_model)

        self._javactx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._javactx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._javactx_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self._javactx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._javactx_list.customContextMenuRequested.connect(
            self._on_java_contextmenu)

        self.addTab(self._nativectx_list, 'Native')
        self.show_context_tab('Native')

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def clear(self):
        self._nativectx_list.clear()
        self._emulatorctx_list.clear()
        self._javactx_list.clear()

    def set_context(self, ptr, context_type, context):
        if isinstance(context, str):
            context = json.loads(context)

        if context_type == ContextPanel.CONTEXT_TYPE_NATIVE:
            self._nativectx_list.clear()
            self._set_native_context(ptr, context)
        elif context_type == ContextPanel.CONTEXT_TYPE_JAVA:
            self._javactx_list.clear()
            self._set_java_context(ptr, context)
        elif context_type == ContextPanel.CONTEXT_TYPE_EMULATOR:
            self._emulatorctx_list.clear()
            self._set_emulator_context(ptr, context)
        else:
            raise Exception('unknown context type')

    def have_context(self):
        return self.count() > 0

    def show_context_tab(self, tab_name):
        index = 0
        tab_name = tab_name.join(tab_name.split()).lower()
        if tab_name == 'native':
            index = self.indexOf(self._nativectx_list)
        elif tab_name == 'emulator':
            index = self.indexOf(self._emulatorctx_list)
        elif tab_name == 'java':
            index = self.indexOf(self._javactx_list)

        if self.count() > 0:
            self.setCurrentIndex(index)

    def _set_native_context(self, ptr, context):
        if self.indexOf(self._nativectx_list) == -1:
            self.addTab(self._nativectx_list, 'Native')
            self.show_context_tab('Native')
        else:
            self.show_context_tab('Native')

        context_ptr = ptr

        reg_order = []
        if self._app_window.dwarf.arch == 'arm':  # arm
            reg_order = ['r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9', 'r10', 'r11', 'r12', 'r13', 'r14',
                         'r15', 'sp', 'lr', 'sb', 'sl', 'fp', 'ip', 'pc']
        elif self._app_window.dwarf.arch == 'arm64':
            reg_order = ['x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10', 'x11', 'x12', 'x13', 'x14',
                         'x15', 'x16', 'x17', 'x18', 'x19', 'x20', 'x21', 'x22', 'x23', 'x24', 'x25', 'x26', 'x27',
                         'x28', 'x29', 'x30', 'w0', 'w1', 'w2', 'w3', 'w4', 'w5', 'w6', 'w7', 'w8', 'w9', 'w10', 'w11',
                         'w12', 'w13', 'w14', 'w15', 'w16', 'w17', 'w18', 'w19', 'w20', 'w21', 'w22', 'w23', 'w24',
                         'w25', 'w26', 'w27', 'w28', 'w29', 'w30', 'sp', 'lr', 'fp', 'wsp', 'wzr', 'xzr', 'nzcv',
                         'ip0', 'ip1', 's0', 's1', 's2', 's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10', 's11', 's12',
                         's13', 's14', 's15', 's16', 's17', 's18', 's19', 's20', 's21', 's22', 's23', 's24', 's25',
                         's26', 's27', 's28', 's29', 's30', 's31', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7',
                         'd8', 'd9', 'd10', 'd11', 'd12', 'd13', 'd14', 'd15', 'd16', 'd17', 'd18', 'd19', 'd20',
                         'd21', 'd22', 'd23', 'd24', 'd25', 'd26', 'd27', 'd28', 'd29', 'd30', 'd31', 'q0', 'q1', 'q2',
                         'q3', 'q4', 'q5', 'q6', 'q7', 'q8', 'q9', 'q10', 'q11', 'q12', 'q13', 'q14', 'q15', 'q16',
                         'q17', 'q18', 'q19', 'q20', 'q21', 'q22', 'q23', 'q24', 'q25', 'q26', 'q27', 'q28', 'q29',
                         'q30', 'q31', 'sp', 'lr', 'sb', 'sl', 'fp', 'ip', 'pc']
        elif self._app_window.dwarf.arch == 'ia32':
            reg_order = ['eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'esp', 'r8d', 'r9d', 'r10d', 'r11d', 'r12d', 'r13d',
                         'r14d', 'r15d', 'ebp', 'eip', 'sp', 'pc']
        elif self._app_window.dwarf.arch == 'x64':  # x64
            reg_order = ['rax', 'rbx', 'rcx', 'rdx', 'rsi', 'rdi', 'rbp', 'rsp', 'r8', 'r9', 'r10', 'r11', 'r12',
                         'r13', 'r14', 'r15', 'esp', 'ebp', 'rip', 'eip', 'sp', 'pc']

        sorted_regs = {b: i for i, b in enumerate(reg_order)}

        for register in sorted(context, key=lambda x: sorted_regs[x]):
            reg_name = QStandardItem()
            reg_name.setTextAlignment(Qt.AlignCenter)
            if context[register]['isValidPointer']:
                reg_name.setForeground(Qt.red)
                reg_name.setData(context_ptr)

            value_x = QStandardItem()
            # value_x.setTextAlignment(Qt.AlignCenter)
            value_dec = QStandardItem()
            # value_dec.setTextAlignment(Qt.AlignCenter)
            telescope = QStandardItem()

            reg_name.setText(register)

            if context[register] is not None:
                str_fmt = '0x{0:x}'
                if self._nativectx_list.uppercase_hex:
                    str_fmt = '0x{0:X}'

                value_x.setText(
                    str_fmt.format(int(context[register]['value'], 16)))

                value_dec.setText('{0:d}'.format(
                    int(context[register]['value'], 16)))

                if context[register]['isValidPointer']:
                    if 'telescope' in context[register] and context[register][
                            'telescope'] is not None:
                        telescope = QStandardItem()
                        telescope.setText(
                            str(context[register]['telescope'][1]))
                        if context[register]['telescope'][0] == 2:
                            telescope.setData(
                                context[register]['telescope'][1],
                                Qt.UserRole + 1)

                        if context[register]['telescope'][0] == 0:
                            telescope.setForeground(Qt.darkGreen)
                        elif context[register]['telescope'][0] == 2:
                            telescope.setForeground(Qt.white)
                        elif context[register]['telescope'][0] != 1:
                            telescope.setForeground(Qt.darkGray)

            self._nativectx_model.appendRow([reg_name, value_x, value_dec, telescope])
            self._nativectx_list.resizeColumnToContents(0)

    def _set_emulator_context(self, ptr, context):
        if self.indexOf(self._emulatorctx_list) == -1:
            self.addTab(self._emulatorctx_list, 'Emulator')
            self.show_context_tab('Emulator')
        else:
            self.show_context_tab('Emulator')

        context_ptr = ptr

        context = context.__dict__

        for register in sorted(context):
            # todo: ???
            if register.startswith('_'):
                continue

            reg_name = QStandardItem()
            reg_name.setTextAlignment(Qt.AlignCenter)
            reg_name.setForeground(QColor('#39c'))
            value_x = QStandardItem()
            # value_x.setTextAlignment(Qt.AlignCenter)
            value_dec = QStandardItem()
            # value_dec.setTextAlignment(Qt.AlignCenter)

            reg_name.setText(register)
            reg_name.setData(context_ptr)

            if context[register] is not None:
                if isinstance(context[register], int):
                    str_fmt = '0x{0:x}'
                    if self._emulatorctx_list.uppercase_hex:
                        str_fmt = '0x{0:X}'

                    value_x.setText(str_fmt.format(context[register]))

                    value_dec.setText('{0:d}'.format(context[register]))

            self._emulatorctx_model.appendRow([reg_name, value_x, value_dec])
            self._emulatorctx_list.resizeColumnToContents(0)
            self._emulatorctx_list.resizeColumnToContents(1)

    def _set_java_context(self, ptr, context):
        if self.indexOf(self._javactx_list) == -1:
            self.addTab(self._javactx_list, 'Java')
            self.show_context_tab('Java')
        else:
            self.show_context_tab('Java')

        for arg in context:
            _arg = QStandardItem()
            _arg.setText(arg)

            _class = QStandardItem()
            _class.setText(context[arg]['className'])
            if isinstance(context[arg]['handle'], str):
                _class.setForeground(Qt.lightGray)

            _value = QStandardItem()
            if context[arg] is not None:
                _value.setText('null')
                _value.setForeground(Qt.gray)

            self._javactx_model.appendRow([_arg, _class, _value])
            self._javactx_list.resizeColumnToContents(0)
            self._javactx_list.resizeColumnToContents(1)

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_native_contextmenu(self, pos):
        index = self._nativectx_list.indexAt(pos).row()
        glbl_pt = self._nativectx_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self._nativectx_model.item(index, 1).text()))
            context_menu.addAction(
                'Jump to address', lambda: self._app_window.jump_to_address(
                    self._nativectx_model.item(index, 1).text()))
        context_menu.exec_(glbl_pt)

    def _on_emulator_contextmenu(self, pos):
        index = self._emulatorctx_list.indexAt(pos).row()
        glbl_pt = self._emulatorctx_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            pass
        context_menu.exec_(glbl_pt)

    def _on_java_contextmenu(self, pos):
        index = self._javactx_list.indexAt(pos).row()
        glbl_pt = self._javactx_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            pass
        context_menu.exec_(glbl_pt)
Example #40
0
class ContextWidget(QTabWidget):
    # consts
    CONTEXT_TYPE_NATIVE = 0
    CONTEXT_TYPE_JAVA = 1

    onShowMemoryRequest = pyqtSignal(str, name='onShowMemoryRequest')

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

        self._app_window = parent
        self.setAutoFillBackground(True)

        self._app_window.dwarf.onContextChanged.connect(
            self._on_context_changed)

        self._nativectx_model = QStandardItemModel(0, 4)
        self._nativectx_model.setHeaderData(0, Qt.Horizontal, 'Reg')
        self._nativectx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                            Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._nativectx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                            Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(2, Qt.Horizontal, 'Decimal')
        self._nativectx_model.setHeaderData(3, Qt.Horizontal, 'Telescope')

        self._nativectx_list = DwarfListView()
        self._nativectx_list.setModel(self._nativectx_model)

        self._nativectx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._nativectx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._nativectx_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self._nativectx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._nativectx_list.customContextMenuRequested.connect(
            self._on_native_contextmenu)

        self._javactx_model = QStandardItemModel(0, 3)
        self._javactx_model.setHeaderData(0, Qt.Horizontal, 'Argument')
        self._javactx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                          Qt.TextAlignmentRole)
        self._javactx_model.setHeaderData(1, Qt.Horizontal, 'Class')
        self._javactx_model.setHeaderData(2, Qt.Horizontal, 'Value')

        self._javactx_list = DwarfListView()
        self._javactx_list.setModel(self._javactx_model)

        self._javactx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._javactx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._javactx_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self._javactx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._javactx_list.customContextMenuRequested.connect(
            self._on_java_contextmenu)

        self.addTab(self._nativectx_list, 'Native')
        self.show_context_tab('Native')

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def clear(self):
        self._nativectx_list.clear()
        self._javactx_list.clear()

    def set_context(self, ptr, context_type, context):
        if isinstance(context, str):
            context = json.loads(context)

        if context_type == ContextWidget.CONTEXT_TYPE_NATIVE:
            self._nativectx_list.clear()
            self._set_native_context(ptr, context)
        elif context_type == ContextWidget.CONTEXT_TYPE_JAVA:
            self._javactx_list.clear()
            self._set_java_context(ptr, context)
        else:
            raise Exception('unknown context type')

    def have_context(self):
        return self.count() > 0

    def show_context_tab(self, tab_name):
        index = 0
        tab_name = tab_name.join(tab_name.split()).lower()
        if tab_name == 'native':
            index = self.indexOf(self._nativectx_list)
        elif tab_name == 'java':
            index = self.indexOf(self._javactx_list)

        if self.count() > 0:
            self.setCurrentIndex(index)

    def _set_native_context(self, ptr, context):
        if self.indexOf(self._nativectx_list) == -1:
            self.addTab(self._nativectx_list, 'Native')
            self.show_context_tab('Native')
        else:
            self.show_context_tab('Native')

        context_ptr = ptr
        sorted_regs = self.get_sort_order()

        for register in sorted(context,
                               key=lambda x: sorted_regs[x]
                               if x in sorted_regs else len(sorted_regs)):
            reg_name = QStandardItem()
            reg_name.setTextAlignment(Qt.AlignCenter)
            if context[register]['isValidPointer']:
                reg_name.setData(context_ptr, Qt.UserRole + 1)

            value_x = QStandardItem()
            if context[register]['isValidPointer']:
                value_x.setForeground(Qt.red)

            value_dec = QStandardItem()
            telescope = QStandardItem()

            reg_name.setText(register)

            if context[register] is not None:
                str_fmt = '0x{0:x}'
                if self._nativectx_list.uppercase_hex:
                    str_fmt = '0x{0:X}'

                value_x.setText(
                    str_fmt.format(int(context[register]['value'], 16)))

                value_dec.setText('{0:d}'.format(
                    int(context[register]['value'], 16)))

                if context[register]['isValidPointer']:
                    if 'telescope' in context[register] and context[register][
                            'telescope'] is not None:
                        telescope = QStandardItem()

                        telescope_value = str(
                            context[register]['telescope'][1]).replace(
                                '\n', ' ')
                        if len(telescope_value) > 50:
                            telescope_value = telescope_value[:50] + '...'

                        telescope.setText(telescope_value)
                        if context[register]['telescope'][0] == 2:
                            telescope.setData(
                                context[register]['telescope'][1],
                                Qt.UserRole + 1)

                        if context[register]['telescope'][0] == 0:
                            telescope.setForeground(Qt.darkGreen)
                        elif context[register]['telescope'][0] == 2:
                            telescope.setForeground(Qt.white)
                        elif context[register]['telescope'][0] != 1:
                            telescope.setForeground(Qt.darkGray)

            self._nativectx_model.appendRow(
                [reg_name, value_x, value_dec, telescope])
            self._nativectx_list.resizeColumnToContents(0)

    def _set_java_context(self, ptr, context):
        if self.indexOf(self._javactx_list) == -1:
            self.addTab(self._javactx_list, 'Java')
            self.show_context_tab('Java')
        else:
            self.show_context_tab('Java')

        for arg in context:
            _arg = QStandardItem()
            _arg.setText(arg)

            _class = QStandardItem()
            _class.setText(context[arg]['className'])
            if isinstance(context[arg]['handle'], str):
                _class.setForeground(Qt.lightGray)

            _value = QStandardItem()
            if 'arg' not in context[arg] or context[arg]['arg'] is None:
                _value.setText('null')
                _value.setForeground(Qt.gray)
            else:
                _value.setText(context[arg]['arg'])

            self._javactx_model.appendRow([_arg, _class, _value])
            self._javactx_list.resizeColumnToContents(0)
            self._javactx_list.resizeColumnToContents(1)

    def get_sort_order(self):
        reg_order = []
        if self._app_window.dwarf.arch == 'arm':  # arm
            reg_order = [
                'r0', 'r1', 'r2', 'r3', 'r4', 'r5', 'r6', 'r7', 'r8', 'r9',
                'r10', 'r11', 'r12', 'r13', 'r14', 'r15', 'sp', 'lr', 'sb',
                'sl', 'fp', 'ip', 'pc', 'cspr'
            ]
        elif self._app_window.dwarf.arch == 'arm64':
            reg_order = [
                'x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9',
                'x10', 'x11', 'x12', 'x13', 'x14', 'x15', 'x16', 'x17', 'x18',
                'x19', 'x20', 'x21', 'x22', 'x23', 'x24', 'x25', 'x26', 'x27',
                'x28', 'x29', 'x30', 'w0', 'w1', 'w2', 'w3', 'w4', 'w5', 'w6',
                'w7', 'w8', 'w9', 'w10', 'w11', 'w12', 'w13', 'w14', 'w15',
                'w16', 'w17', 'w18', 'w19', 'w20', 'w21', 'w22', 'w23', 'w24',
                'w25', 'w26', 'w27', 'w28', 'w29', 'w30', 'sp', 'lr', 'fp',
                'wsp', 'wzr', 'xzr', 'nzcv', 'ip0', 'ip1', 's0', 's1', 's2',
                's3', 's4', 's5', 's6', 's7', 's8', 's9', 's10', 's11', 's12',
                's13', 's14', 's15', 's16', 's17', 's18', 's19', 's20', 's21',
                's22', 's23', 's24', 's25', 's26', 's27', 's28', 's29', 's30',
                's31', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8',
                'd9', 'd10', 'd11', 'd12', 'd13', 'd14', 'd15', 'd16', 'd17',
                'd18', 'd19', 'd20', 'd21', 'd22', 'd23', 'd24', 'd25', 'd26',
                'd27', 'd28', 'd29', 'd30', 'd31', 'q0', 'q1', 'q2', 'q3',
                'q4', 'q5', 'q6', 'q7', 'q8', 'q9', 'q10', 'q11', 'q12', 'q13',
                'q14', 'q15', 'q16', 'q17', 'q18', 'q19', 'q20', 'q21', 'q22',
                'q23', 'q24', 'q25', 'q26', 'q27', 'q28', 'q29', 'q30', 'q31',
                'sp', 'lr', 'sb', 'sl', 'fp', 'ip', 'pc', 'cspr'
            ]
        elif self._app_window.dwarf.arch == 'ia32':
            reg_order = [
                'eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'esp', 'r8d', 'r9d',
                'r10d', 'r11d', 'r12d', 'r13d', 'r14d', 'r15d', 'ebp', 'eip',
                'sp', 'pc'
            ]
        elif self._app_window.dwarf.arch == 'x64':  # x64
            reg_order = [
                'rax', 'rbx', 'rcx', 'rdx', 'rsi', 'rdi', 'rbp', 'rsp', 'r8',
                'r9', 'r10', 'r11', 'r12', 'r13', 'r14', 'r15', 'esp', 'ebp',
                'rip', 'eip', 'sp', 'pc'
            ]

        sorted_regs = {b: i for i, b in enumerate(reg_order)}
        return sorted_regs

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_native_contextmenu(self, pos):
        index = self._nativectx_list.indexAt(pos).row()
        glbl_pt = self._nativectx_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            item = self._nativectx_model.item(index, 1)
            dec = self._nativectx_model.item(index, 2)
            telescope = self._nativectx_model.item(index, 3)
            # show contextmenu
            if self._nativectx_model.item(index, 0).data(Qt.UserRole + 1):
                context_menu.addAction(
                    'Jump to {0}'.format(item.text()),
                    lambda: self._app_window.jump_to_address(item.text()))
                context_menu.addSeparator()
            # copy menu
            context_sub_menu = QMenu('Copy', context_menu)
            context_sub_menu.addAction(
                'Value', lambda: utils.copy_str_to_clipboard(item.text()))
            if dec.text():
                context_sub_menu.addAction(
                    'Decimal', lambda: utils.copy_str_to_clipboard(dec.text()))
            if telescope.text():
                context_sub_menu.addAction(
                    'Telescope',
                    lambda: utils.copy_str_to_clipboard(telescope.text()))
            context_menu.addMenu(context_sub_menu)

            context_menu.exec_(glbl_pt)

    def _on_java_contextmenu(self, pos):
        index = self._javactx_list.indexAt(pos).row()
        glbl_pt = self._javactx_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            # show contextmenu
            argument = self._javactx_model.item(index, 1)
            _class = self._javactx_model.item(index, 2)
            value = self._javactx_model.item(index, 3)
            context_sub_menu = QMenu('Copy', context_menu)
            context_sub_menu.addAction(
                'Argument',
                lambda: utils.copy_str_to_clipboard(argument.text()))
            if _class.text():
                context_sub_menu.addAction(
                    'Class',
                    lambda: utils.copy_str_to_clipboard(_class.text()))
            if value:
                if value.text():
                    context_sub_menu.addAction(
                        'Value',
                        lambda: utils.copy_str_to_clipboard(value.text()))
            context_menu.addMenu(context_sub_menu)
            context_menu.exec_(glbl_pt)

    def _on_context_changed(self, reg_name, reg_val):
        x_in = 0
        for c in reg_val:
            if c.lower() not in '1234567890abcdef':
                if c.lower() == 'x' and x_in == 0:
                    x_in += 1
                    continue

                self._app_window.dwarf.onLogToConsole.emit(
                    'error: invalid reg_value: ' + reg_val +
                    ' - expected dec/hex')
                return

        if isinstance(reg_val, str) and reg_val.startswith('0x'):
            try:
                reg_val = int(reg_val, 16)
            except ValueError:
                self._app_window.dwarf.onLogToConsole.emit(
                    'error: invalid reg_value: ' + reg_val +
                    ' - expected dec/hex')
                return
        try:
            reg_val = int(reg_val)
        except ValueError:
            self._app_window.dwarf.onLogToConsole.emit(
                'error: invalid reg_value: ' + reg_val + ' - expected dec/hex')
            return

        reg_val = hex(reg_val)
        was_found, find_result = self._nativectx_list.contains_text(
            reg_name, True, True, True)
        if was_found:
            if len(find_result) == 1:
                find_result = find_result[0]
                if self._nativectx_model.item(find_result[0],
                                              0).text() == reg_name:
                    str_fmt = '0x{0:x}'
                    if self._nativectx_list.uppercase_hex:
                        str_fmt = '0x{0:X}'

                    value_x = str_fmt.format(int(reg_val, 16))

                    value_dec = '{0:d}'.format(int(reg_val, 16))
                    self._nativectx_model.item(find_result[0],
                                               1).setText(value_x)
                    self._nativectx_model.item(find_result[0],
                                               2).setText(value_dec)
                    self._nativectx_model.item(find_result[0], 3).setText("")
Example #41
0
class RefsWidget(QObject):

    error = pyqtSignal(Exception)
    reference_changed = pyqtSignal(Node)

    def __init__(self, view):
        super().__init__(view)
        self.view = view
        self.model = QStandardItemModel()

        self.view.setModel(self.model)
        self.settings = QSettings()
        self.model.setHorizontalHeaderLabels(['ReferenceType', 'NodeId', "BrowseName", "TypeDefinition"])
        state = self.settings.value("WindowState/refs_widget_state", None)
        if state is not None:
            self.view.horizontalHeader().restoreState(state)
        self.node = None

        self.reloadAction = QAction("Reload", self.model)
        self.reloadAction.triggered.connect(self.reload)

        self.view.setContextMenuPolicy(Qt.CustomContextMenu)
        self.view.customContextMenuRequested.connect(self.showContextMenu)
        self._contextMenu = QMenu()
        self._contextMenu.addAction(self.reloadAction)

    def showContextMenu(self, position):
        if not self.node:
            return
        self._contextMenu.exec_(self.view.viewport().mapToGlobal(position))

    def clear(self):
        # remove all rows but not header
        self.model.removeRows(0, self.model.rowCount())
        self.node = None

    @trycatchslot
    def reload(self):
        node = self.node
        self.clear()
        self.show_refs(node)

    def save_state(self):
        self.settings.setValue("WindowState/refs_widget_state", self.view.horizontalHeader().saveState())

    def show_refs(self, node):
        self.clear()
        self.node = node
        self._show_refs(node)

    def _show_refs(self, node):
        try:
            refs = node.get_children_descriptions(refs=ua.ObjectIds.References)
        except Exception as ex:
            self.error.emit(ex)
            raise
        for ref in refs:
            self._add_ref_row(ref)

    def _add_ref_row(self, ref):
        if ref.ReferenceTypeId.Identifier in ua.ObjectIdNames:
            typename = ua.ObjectIdNames[ref.ReferenceTypeId.Identifier]
        else:
            typename = str(ref.ReferenceTypeId)
        if ref.NodeId.NamespaceIndex == 0 and ref.NodeId.Identifier in ua.ObjectIdNames:
            nodeid = ua.ObjectIdNames[ref.NodeId.Identifier]
        else:
            nodeid = ref.NodeId.to_string()
        if ref.TypeDefinition.Identifier in ua.ObjectIdNames:
            typedef = ua.ObjectIdNames[ref.TypeDefinition.Identifier]
        else:
            typedef = ref.TypeDefinition.to_string()
        titem = QStandardItem(typename)
        titem.setData(ref, Qt.UserRole)
        self.model.appendRow([
            titem,
            QStandardItem(nodeid),
            QStandardItem(ref.BrowseName.to_string()),
            QStandardItem(typedef)
        ])
Example #42
0
class KeysTab(GalacteekTab):
    def __init__(self, *args, **kw):
        super().__init__(*args, **kw)

        self.resolveTimeout = 60 * 5
        self.keysW = QWidget()
        self.addToLayout(self.keysW)
        self.ui = ui_keys.Ui_KeysForm()
        self.ui.setupUi(self.keysW)

        self.ui.addKeyButton.clicked.connect(self.onAddKeyClicked)
        self.ui.deleteKeyButton.clicked.connect(
            lambda *args: ensure(self.onDelKeyClicked()))

        self.model = QStandardItemModel(parent=self)

        self.ui.treeKeys = KeysView()
        self.ui.treeKeys.doubleClicked.connect(self.onItemDoubleClicked)
        self.ui.treeKeys.setModel(self.model)

        self.ui.verticalLayout.addWidget(self.ui.treeKeys)

        self.setupModel()
        self.app.task(self.listKeys)

    def setupModel(self):
        self.model.clear()
        self.model.setColumnCount(3)
        self.model.setHorizontalHeaderLabels(
            [iKeyName(), iP2PKey(), iKeyResolve()])
        self.ui.treeKeys.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.ui.treeKeys.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)

    async def onDelKeyClicked(self):
        idx = self.ui.treeKeys.currentIndex()
        if not idx.isValid():
            return messageBox('Invalid key')

        idxName = self.model.index(idx.row(), 0, idx.parent())
        keyName = self.model.data(idxName)

        if not keyName:
            return

        reply = await questionBoxAsync(
            'Delete key', 'Delete IPNS key <b>{key}</b> ?'.format(key=keyName))

        if reply is True:
            self.app.task(self.delKey, keyName)

    def onAddKeyClicked(self):
        runDialog(AddKeyDialog, self.app, parent=self)

    @ipfsOp
    async def delKey(self, ipfsop, name):
        if await ipfsop.keysRemove(name):
            modelDelete(self.model, name)
        self.updateKeysList()

    @ipfsOp
    async def listKeys(self, ipfsop):
        keys = await ipfsop.keys()
        for key in keys:
            found = modelSearch(self.model, search=key['Name'])
            if len(found) > 0:
                continue

            nameItem = UneditableItem(key['Name'])
            nameItem.setToolTip(key['Name'])

            resolveItem = KeyResolvedItem('')
            self.model.appendRow([nameItem, KeyItem(key['Id']), resolveItem])

            self.app.task(self.keyResolve, key, resolveItem)

    @ipfsOp
    async def keyResolve(self, ipfsop, key, item):
        if not isinstance(item, KeyResolvedItem):
            return

        now = datetime.now()

        update = False
        if item.resolvedLast is None:
            update = True

        if isinstance(item.resolvedLast, datetime):
            delta = now - item.resolvedLast
            if delta.seconds > self.resolveTimeout:
                update = True

        if update is True:
            resolved = await ipfsop.nameResolve(key['Id'])

            if isinstance(resolved, dict):
                rPath = resolved.get('Path')
                if not rPath:
                    item.setBackground(QBrush(QColor('red')))
                elif item.resolvesTo and rPath != item.resolvesTo:
                    color = QColor('#c1f0c1')
                    item.setBackground(QBrush(color))
                else:
                    item.setBackground(QBrush(Qt.NoBrush))

                if rPath and IPFSPath(rPath).valid:
                    item.resolvesTo = rPath
                    item.setText(rPath)
                    item.setToolTip("{path}\n\nResolved date: {date}".format(
                        path=rPath,
                        date=now.isoformat(sep=' ', timespec='seconds')))
            else:
                item.setText(iUnknown())

            item.resolvedLast = now

        # Ensure another one
        self.app.loop.call_later(self.resolveTimeout, self.app.task,
                                 self.keyResolve, key, item)

    def updateKeysList(self):
        self.app.task(self.listKeys)

    def onItemDoubleClicked(self, index):
        # Browse IPNS key associated with current item on double-click
        keyHash = self.model.data(self.model.index(index.row(), 1))
        self.gWindow.addBrowserTab().browseIpnsKey(keyHash)
Example #43
0
class App(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):

        self.srvList = ["", "opcUA", "modbusTCP"]

        if (os.name == 'nt'):

            self.appPath = os.path.abspath(sys.argv[0]).replace(
                os.path.basename(__file__), '')
            self.imgPath = self.appPath + "img\\"
            self.dbPath = self.appPath + "db\\webDb.db"
            #import self.appPath+srvconf

        else:
            self.appPath = os.path.abspath(sys.argv[0]).replace(
                os.path.basename(__file__), '')
            self.imgPath = self.appPath + "img/"
            self.dbPath = self.appPath + "db/webDb.db"

        self.versionPr = 'ScadaPy Web JSON Сервер v.3.14'
        self.setGeometry(300, 100, 1500, 820)
        self.setWindowTitle(self.versionPr)
        self.setWindowIcon(QIcon(self.imgPath + 'Globe.png'))
        self.h = self.frameGeometry().height()
        self.w = self.frameGeometry().width()
        self.setStyleSheet("background-color: #FFF8E7;")

        font = QFont()
        font.setPointSize(12)

        self.label0 = QLabel(self)
        self.label0.setFont(font)
        self.label0.move(400, 60)
        self.label0.resize(300, 25)
        self.label0.setText("ID сервера")
        self.label00 = QLabel(self)
        self.label00.setFont(font)
        self.label00.move(550, 60)
        self.label00.resize(300, 25)
        self.label00.setText("")

        self.label1 = QLabel(self)
        self.label1.setFont(font)
        self.label1.move(400, 90)
        self.label1.resize(140, 25)
        self.label1.setText("Название сервера")
        self.srvName = QLineEdit(self)
        self.srvName.setToolTip('Пример: Сервер Маш.Зала №1')
        self.srvName.move(550, 90)
        self.srvName.setFont(font)
        self.srvName.resize(300, 25)

        self.label2 = QLabel(self)
        self.label2.setFont(font)
        self.label2.move(400, 120)
        self.label2.resize(140, 25)
        self.label2.setText("Http IP address")
        self.slaveIP = QLineEdit(self)
        self.slaveIP.setToolTip('Пример: 192.168.0.111')
        self.slaveIP.move(550, 120)
        self.slaveIP.setFont(font)
        self.slaveIP.resize(300, 25)

        self.label2 = QLabel(self)
        self.label2.setFont(font)
        self.label2.move(400, 150)
        self.label2.resize(140, 25)
        self.label2.setText("Http Port")
        self.slavePort = QLineEdit(self)
        self.slavePort.setToolTip('Пример : 8080')
        self.slavePort.move(550, 150)
        self.slavePort.setFont(font)
        self.slavePort.resize(100, 25)

        self.label7 = QLabel(self)
        self.label7.setFont(font)
        self.label7.move(680, 150)
        self.label7.resize(140, 25)
        self.label7.setText("Timeout")

        self.serverTimeout = QLineEdit(self)
        self.serverTimeout.setToolTip('Пример ms: 1 ')
        self.serverTimeout.move(750, 150)
        self.serverTimeout.setFont(font)
        self.serverTimeout.resize(100, 25)

        self.label8 = QLabel(self)
        self.label8.setFont(font)
        self.label8.move(400, 180)
        self.label8.resize(140, 25)
        self.label8.setText("Login")
        self.serverLogin = QLineEdit(self)
        self.serverLogin.setToolTip('Имя пользователя')
        self.serverLogin.move(550, 180)
        self.serverLogin.setFont(font)
        self.serverLogin.resize(100, 25)

        self.label9 = QLabel(self)
        self.label9.setFont(font)
        self.label9.move(680, 180)
        self.label9.resize(140, 25)
        self.label9.setText("Password")
        self.serverPassword = QLineEdit(self)
        self.serverPassword.setToolTip('Пароль')
        self.serverPassword.move(750, 180)
        self.serverPassword.setFont(font)
        self.serverPassword.resize(100, 25)

        exitAction = QAction(QIcon(self.imgPath + 'exit.png'), '&Выход', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Выход из программы')
        exitAction.triggered.connect(qApp.quit)

        addServerAction = QAction(QIcon(self.imgPath + 'add.png'), '&Добавить',
                                  self)
        addServerAction.setStatusTip('Добавить сервер')
        addServerAction.triggered.connect(self.addNewServer)

        delServerAction = QAction(QIcon(self.imgPath + 'button_cancel.png'),
                                  '&Удалить', self)
        delServerAction.setStatusTip('Удалить сервер')
        delServerAction.triggered.connect(self.delServer)

        saveServerAction = QAction(QIcon(self.imgPath + 'filesave.png'),
                                   '&Сохранить', self)
        saveServerAction.setStatusTip('Сохранить сервер')
        saveServerAction.triggered.connect(self.saveServer)

        saveScr = QAction(QIcon(self.imgPath + 'bottom.png'),
                          '&Сохранить скрипт', self)
        saveScr.setStatusTip('Сохранить скрипт')
        saveScr.triggered.connect(self.saveScr)

        runScr = QAction(QIcon(self.imgPath + 'run.png'), '&Запустить скрипт',
                         self)
        runScr.setStatusTip('Запустить скрипт')
        runScr.triggered.connect(self.runScr)

        runConf = QAction(QIcon(self.imgPath + 'app.png'),
                          '&Запустить конфигуратор', self)
        runConf.setStatusTip('Запустить конфигуратор')
        runConf.triggered.connect(self.runConf)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&Команды')
        fileMenu.addAction(addServerAction)
        fileMenu.addAction(delServerAction)
        fileMenu.addAction(saveServerAction)
        fileMenu.addAction(saveScr)
        fileMenu.addAction(runScr)
        fileMenu.addAction(exitAction)

        self.toolbar = self.addToolBar('Выход')
        self.toolbar.addAction(exitAction)
        self.toolbar.addAction(addServerAction)
        self.toolbar.addAction(delServerAction)
        self.toolbar.addAction(saveServerAction)
        self.toolbar.addAction(saveScr)
        self.toolbar.addAction(runScr)
        self.toolbar.addAction(runConf)

        # self.statusBar().showMessage('Загрузка данных')

        self.treeView = QTreeView(self)
        self.treeView.setFont(font)
        self.treeView.setObjectName("treeView")
        self.model = QStandardItemModel()
        self.treeView.setModel(self.model)
        self.treeView.setStyleSheet("background-color: white;")
        self.header = ['Название сервера']
        self.model.setHorizontalHeaderLabels(self.header)

        self.sqlLoad()
        self.treeView.clicked.connect(self.onClickItem)

        self.frameTable = QFrame(self)
        self.frameTable.setVisible(True)

        self.addRow = QPushButton(self.frameTable)
        self.addRow.setIcon(QIcon(self.imgPath + 'add.png'))
        self.addRow.move(10, 10)
        self.addRow.resize(30, 30)
        self.addRow.clicked.connect(self.addItemTree)

        self.saveTable = QPushButton(self.frameTable)
        self.saveTable.setIcon(QIcon(self.imgPath + 'filesave.png'))
        self.saveTable.resize(30, 30)
        self.saveTable.move(50, 10)
        self.saveTable.clicked.connect(self.saveData)

        ####################################################################

        self.treeTable = QTableWidget(self.frameTable)
        self.treeTable.setStyleSheet("background-color: white;")
        fontTable = QFont()
        fontTable.setPointSize(10)
        self.treeTable.setFont(fontTable)

        #        self.show()
        self.showMaximized()

    def addItemTree(self):
        items = ("modbus_tcp", "opc_ua")
        item, okPressed = QInputDialog.getItem(self, "Добавить тип сервера",
                                               "Тип:", items, 0, False)
        if okPressed and item:
            self.treeTable.insertRow(self.treeTable.rowCount())
            self.treeTable.setItem(self.treeTable.rowCount() - 1, 0,
                                   QTableWidgetItem(item))

    def getData(self):
        self.treeTable.clear()
        self.treeTable.setColumnCount(10)
        #self.treeTable.setRowCount(1)
        self.treeTable.setHorizontalHeaderLabels([
            'Тип сервера', 'Имя переменной', 'Имя параметра', 'IP адрес',
            'Порт', 'Логин', 'Пароль', 'Timeout', 'Адрес ячейки', 'Количество'
        ])
        self.treeTable.resizeColumnsToContents()
        self.treeTable.setColumnWidth(0, 120)
        self.treeTable.setColumnWidth(1, 170)
        self.treeTable.setColumnWidth(2, 170)
        self.treeTable.setColumnWidth(3, 140)
        self.treeTable.setColumnWidth(4, 80)
        self.treeTable.setColumnWidth(5, 120)
        self.treeTable.setColumnWidth(6, 120)
        self.treeTable.setColumnWidth(7, 80)
        self.treeTable.setColumnWidth(8, 120)
        self.treeTable.setColumnWidth(9, 80)

        connDb = sqlite3.connect(self.dbPath)
        cursor = connDb.cursor()
        cursor.execute(
            "select type,var,param,ip,port,login,password,t,regadr,regcount from  master where serverId = "
            + self.label00.text())
        dt = cursor.fetchall()
        self.treeTable.setRowCount(len(dt))
        for i in range(0, len(dt)):
            self.treeTable.setItem(i, 0, QTableWidgetItem(dt[i][0]))
            self.treeTable.setItem(i, 1, QTableWidgetItem(dt[i][1]))
            self.treeTable.setItem(i, 2, QTableWidgetItem(dt[i][2]))
            self.treeTable.setItem(i, 3, QTableWidgetItem(dt[i][3]))
            self.treeTable.setItem(i, 4, QTableWidgetItem(dt[i][4]))
            self.treeTable.setItem(i, 5, QTableWidgetItem(dt[i][5]))
            self.treeTable.setItem(i, 6, QTableWidgetItem(dt[i][6]))
            self.treeTable.setItem(i, 7, QTableWidgetItem(dt[i][7]))
            self.treeTable.setItem(i, 8, QTableWidgetItem(dt[i][8]))
            self.treeTable.setItem(i, 9, QTableWidgetItem(dt[i][9]))

            i += 1

    def saveData(self):
        connDb = sqlite3.connect(self.dbPath)
        cursor = connDb.cursor()
        cursor.execute("delete from master where serverId= '" +
                       self.label00.text() + "'")
        connDb.commit()

        for i in range(0, self.treeTable.rowCount()):
            try:
                if (len(self.treeTable.item(i, 0).text()) > 0
                        and len(self.treeTable.item(i, 1).text()) > 0
                        and len(self.treeTable.item(i, 2).text()) > 0
                        and len(self.treeTable.item(i, 3).text()) > 0
                        and len(self.treeTable.item(i, 4).text()) > 0
                        and len(self.treeTable.item(i, 5).text()) > 0
                        and len(self.treeTable.item(i, 6).text()) > 0
                        and len(self.treeTable.item(i, 7).text()) > 0
                        and len(self.treeTable.item(i, 8).text()) > 0):

                    cursor.execute(
                        "INSERT INTO master(serverId,type,var,param,ip,port,login,password,t,regadr,regcount,valid)\
                                 VALUES('" + self.label00.text() + "',\
                                 '" + self.treeTable.item(i, 0).text() + "',\
                                 '" + self.treeTable.item(i, 1).text() + "',\
                                 '" + self.treeTable.item(i, 2).text() + "',\
                                 '" + self.treeTable.item(i, 3).text() + "',\
                                 '" + self.treeTable.item(i, 4).text() + "',\
                                 '" + self.treeTable.item(i, 5).text() + "',\
                                 '" + self.treeTable.item(i, 6).text() + "',\
                                 '" + self.treeTable.item(i, 7).text() + "',\
                                 '" + self.treeTable.item(i, 8).text() + "',\
                                 '" + self.treeTable.item(i, 9).text() + "',\
                                 1)")
                    connDb.commit()
            except Exception as e:
                print(e)
                pass
            i += 1
        self.getData()

    def truePanel(self):
        self.getData()

    def onClickItem(self):
        self.treeTable.clear()
        self.treeTable.setRowCount(0)
        self.srvName.setText("")
        self.label00.setText("")
        self.slaveIP.setText("")
        self.slavePort.setText("")
        self.serverTimeout.setText("")
        self.serverLogin.setText("")
        self.serverPassword.setText("")

        try:
            self.slaveIP.setEnabled(True)
            self.slavePort.setEnabled(True)
            index_list = [i.data() for i in self.treeView.selectedIndexes()]
            s = index_list[0].split(':')
            self.srvName.setText(s[1])
            self.label00.setText(s[0])

            connDb = sqlite3.connect(self.dbPath)
            cursor = connDb.cursor()
            cursor.execute(
                "select ip, port,timeout,login,password from  servers where id = "
                + s[0])
            dt = cursor.fetchone()
            self.slaveIP.setText(dt[0])
            self.slavePort.setText(dt[1])
            self.serverTimeout.setText(dt[2])
            self.serverLogin.setText(dt[3])
            self.serverPassword.setText(dt[4])
            self.truePanel()

        except Exception as e:
            index_list = [i.data() for i in self.treeView.selectedIndexes()]
            self.srvName.setText(index_list[0])
            self.slaveIP.setEnabled(False)
            self.slavePort.setEnabled(False)
            print(e)

    def addNewServer(self):
        sender = self.sender()
        self.statusBar().showMessage('Добавление нового сервера')
        self.model.appendRow(QStandardItem("Новый Сервер "))

    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Сообщение',
                                     "Вы уверены, что хотите выйти?",
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()

    def resizeEvent(self, event):
        self.h = self.frameGeometry().height()
        self.treeView.setGeometry(QtCore.QRect(0, 60, 350, self.h - 120))
        self.treeTable.setGeometry(
            QtCore.QRect(10, 50, self.w - 270, self.h - 320))
        self.frameTable.setGeometry(
            QtCore.QRect(350, 210, self.w - 250, self.h - 260))

    def sqlLoad(self):
        connDb = sqlite3.connect(self.dbPath)
        cursor = connDb.cursor()
        for row in cursor.execute(
                'SELECT name, id FROM servers where valid=1 ORDER BY id'):
            self.model.appendRow(QStandardItem(str(row[1]) + ":" + row[0]))

    def saveServer(self):
        self.treeTable.clear()

        connDb = sqlite3.connect(self.dbPath)
        cursor = connDb.cursor()
        if (len(self.label00.text()) > 0 and int(self.label00.text()) > 0):
            if (len(self.srvName.text()) > 1):
                connDb.execute("update servers set name ='" +
                               self.srvName.text() + "', ip = '" +
                               self.slaveIP.text() + "', port = '" +
                               self.slavePort.text() + "'\
                 ,timeout='" + self.serverTimeout.text() + "', login='******',password='******' where id = " +
                               self.label00.text() + " ")
                connDb.commit()
                cursor.execute(
                    "select ip,port,timeout,login,password from  servers where id = "
                    + self.label00.text())
                dt = cursor.fetchone()
                self.slaveIP.setText(dt[0])
                self.slavePort.setText(dt[1])
                self.serverTimeout.setText(dt[2])
                self.serverLogin.setText(dt[3])
                self.serverPassword.setText(dt[4])

                self.truePanel()
        else:
            try:
                if (len(self.srvName.text()) > 1):
                    cursor.execute(
                        "INSERT INTO servers(name,valid)  VALUES( '" +
                        self.srvName.text() + "',1)")

                    connDb.commit()
            except Exception as e:
                #print(e)
                pass

        self.model.clear()
        self.model.setHorizontalHeaderLabels(self.header)
        cursor = connDb.cursor()
        for row in cursor.execute(
                'SELECT name, id FROM servers where valid=1 ORDER BY id'):
            self.model.appendRow(QStandardItem(str(row[1]) + ":" + row[0]))

    #  self.truePanel()

    def saveScr(self):

        try:
            pathFolder = self.appPath
            if (os.name == 'nt'):
                slash = '\\'
                bat = '.bat'
                rem = 'rem '
                command = 'start '
            else:
                slash = '/'
                bat = '.sh'
                rem = '# '
                command = ''

            f = open(
                pathFolder + 'scr' + slash + 'web_' + self.label00.text() +
                bat, 'w')
            print(pathFolder + 'scr' + slash + 'web_' + self.label00.text() +
                  bat)
            f.write(rem + 'Скрипт создан в программе \'' + self.versionPr +
                    '\'\n')
            f.write(rem + 'Сервер Web \'' + self.srvName.text() + '\'\n')
            f.write(rem + 'Http адрес \'' + self.slaveIP.text() + '\'\n')
            f.write(rem + 'Http порт \'' + self.slavePort.text() + '\'\n')

            f.write(command + sys.executable + ' ' + pathFolder + 'source' +
                    slash + 'websrv.py ' + self.label00.text() + ' ' +
                    pathFolder + 'db' + slash + 'webDb.db')
            f.close()
            ret = pathFolder + '' + slash + 'scr' + slash + 'web_' + self.label00.text(
            ) + bat

        except Exception as e:
            print(e)

        return ret

    def runScr(self):

        if (os.name == 'nt'):
            os.system(self.saveScr())
        else:
            os.system('chmod 777 ' + self.saveScr())
            os.system('xfce4-terminal --command=\'sudo ' + self.saveScr() +
                      '\'')

    def runConf(self):
        if (os.name == 'nt'):

            self.appPath = os.path.abspath(sys.argv[0]).replace(
                os.path.basename(__file__), '')
            os.system(sys.executable + " " + self.appPath + "srvconf.py")

        else:
            self.appPath = os.path.abspath(sys.argv[0]).replace(
                os.path.basename(__file__), '')
            os.system(sys.executable + " " + self.appPath + "srvconf.py")

    def delServer(self):
        self.treeTable.clear()
        self.treeTable.setRowCount(0)
        connDb = sqlite3.connect(self.dbPath)

        if (len(self.label00.text()) > 0 and int(self.label00.text()) > 0):
            if (len(self.srvName.text()) > 1):
                connDb.execute("update servers set valid=0 where id = " +
                               self.label00.text() + " ")
                connDb.commit()

        self.model.clear()
        self.model.setHorizontalHeaderLabels(self.header)
        cursor = connDb.cursor()
        for row in cursor.execute(
                'SELECT name, id FROM servers where valid=1 ORDER BY id'):
            self.model.appendRow(QStandardItem(str(row[1]) + ":" + row[0]))

        self.slaveIP.setText("")
        self.slavePort.setText("")
        # self.label3.setText("")
        self.srvName.setText("")
    def __init__(self, columns=None, skip=None, only=None, parent=None):
        super(SkipOnlyDialog, self).__init__(parent)
        self.setWindowTitle("Select Columns")
        self.columns = columns
        self.selected_variables = (
            []
        )  # Names of selected variables.  Only updated when accepting the dialog.
        # Select 'only' by default (unless a skip list is passed in)
        # starting_only and only are booleans to indicate whether 'only' is selected
        # starting_selected and selected are boolean arrays to indicate whether each variable is selected
        if skip is not None:
            self.starting_only = False
            self.starting_selected = [(c in skip) for c in self.columns]
        elif only is not None:
            self.starting_only = True
            self.starting_selected = [(c in only) for c in self.columns]
        elif skip is None and only is None:
            self.starting_only = True
            self.starting_selected = [False for _ in self.columns]
        else:
            raise ValueError("Can't pass both 'skip' and 'only'")

        # Available- Left Side
        self.left_model = QStandardItemModel(self)
        self.left_proxy = QSortFilterProxyModel(self)
        self.left_proxy.setSourceModel(self.left_model)
        self.left_proxy.setFilterKeyColumn(0)  # Filters based on the only column
        self.left_proxy.setFilterCaseSensitivity(
            Qt.CaseInsensitive
        )  # Case insensitive search
        # Selected - Right side
        self.right_model = QStandardItemModel()
        self.right_proxy = QSortFilterProxyModel(self)
        self.right_proxy.setSourceModel(self.right_model)
        self.right_proxy.setFilterKeyColumn(0)  # Filters based on the only column
        self.right_proxy.setFilterCaseSensitivity(
            Qt.CaseInsensitive
        )  # Case insensitive search

        # Setup Layout
        layout = QGridLayout(self)
        layout.setColumnStretch(0, 2)
        layout.setColumnStretch(1, 1)
        layout.setColumnStretch(2, 2)

        # Left Side Group Box ("Available")
        left_list_box = QGroupBox("Available Variables")
        left_list_box_layout = QVBoxLayout()
        # Multiselect listing available columns
        self.left_list = QListView(self)
        self.left_list.setModel(self.left_proxy)
        self.left_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.left_list.selectionModel().selectionChanged.connect(
            self.left_selected_change
        )
        self.left_list.setEditTriggers(QAbstractItemView.NoEditTriggers)
        left_list_box_layout.addWidget(self.left_list)
        # Add a search box
        self.left_list_search = QLineEdit(parent=self)
        self.left_list_search.setPlaceholderText("Search...")
        self.left_list_search.textChanged.connect(self.left_proxy.setFilterFixedString)
        left_list_box_layout.addWidget(self.left_list_search)
        # Set layout and add to the main layout
        left_list_box.setLayout(left_list_box_layout)
        layout.addWidget(left_list_box, 0, 0)

        # Add/Remove Buttons
        btns = QWidget()
        btns_layout = QVBoxLayout()
        btns.setLayout(btns_layout)
        # Add
        self.btn_add = QPushButton(text="Add ->", parent=self)
        self.btn_add.clicked.connect(self.add)
        self.btn_add.setEnabled(False)
        btns_layout.addWidget(self.btn_add)
        # Remove
        self.btn_remove = QPushButton(text="<- Remove", parent=self)
        self.btn_remove.clicked.connect(self.remove)
        self.btn_remove.setEnabled(False)
        btns_layout.addWidget(self.btn_remove)
        # Undo Changes
        self.btn_undo = QPushButton(text="Undo Changes", parent=self)
        self.btn_undo.clicked.connect(self.undo)
        self.btn_undo.setEnabled(False)
        btns_layout.addWidget(self.btn_undo)
        # Reset
        self.btn_reset = QPushButton(text="Reset", parent=self)
        self.btn_reset.clicked.connect(self.reset)
        self.btn_reset.setEnabled(False)
        btns_layout.addWidget(self.btn_reset)
        # Add to layout
        layout.addWidget(btns, 0, 1)

        # Right Side Group Box ("Selected")
        right_list_box = QGroupBox("Selected Variables")
        right_list_box_layout = QVBoxLayout()
        # Multiselect listing current selected columns
        self.right_list = QListView(self)
        self.right_list.setModel(self.right_proxy)
        self.right_list.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.right_list.selectionModel().selectionChanged.connect(
            self.right_selected_change
        )
        self.right_list.setEditTriggers(QAbstractItemView.NoEditTriggers)
        right_list_box_layout.addWidget(self.right_list)
        # Add a search box
        self.right_list_search = QLineEdit(parent=self)
        self.right_list_search.setPlaceholderText("Search...")
        self.right_list_search.textChanged.connect(
            self.right_proxy.setFilterFixedString
        )
        right_list_box_layout.addWidget(self.right_list_search)
        # Set layout and add to the main layout
        right_list_box.setLayout(right_list_box_layout)
        layout.addWidget(right_list_box, 0, 2)

        # Radio Select for Skip/Only
        self.radio_btns = QGroupBox("Skip Selected or Only Selected")
        radio_btns_layout = QHBoxLayout()
        self.radio_btns.setLayout(radio_btns_layout)
        self.radio_skip = QRadioButton("skip")
        radio_btns_layout.addWidget(self.radio_skip)
        self.radio_only = QRadioButton("only")
        self.radio_only.setChecked(True)
        radio_btns_layout.addWidget(self.radio_only)
        # If either button changes, a toggle signal is called for each one.  No need to pass the "checked" parameter.
        self.radio_skip.toggled.connect(lambda is_checked: self.update_result())
        layout.addWidget(self.radio_btns, 1, 2)

        # Result label
        self.result_label = QLabel(parent=self)
        self.result_label.setText("0 Variables to be used")
        layout.addWidget(self.result_label, 2, 0)

        # Ok/Cancel
        QBtn = QDialogButtonBox.Ok | QDialogButtonBox.Cancel

        self.buttonBox = QDialogButtonBox(QBtn)
        self.buttonBox.accepted.connect(self.submit)
        self.buttonBox.rejected.connect(self.reject)
        layout.addWidget(self.buttonBox, 2, 2)

        # Run reset to initialize
        self.undo()
Example #45
0
    def __init__(self, parent=None):  # pylint: disable=too-many-statements
        super(BookmarksWidget, self).__init__(parent=parent)

        self._app_window = parent

        if self._app_window.dwarf is None:
            print('BookmarksPanel created before Dwarf exists')
            return

        self.bookmarks = {}

        self._bookmarks_list = DwarfListView()
        self._bookmarks_list.doubleClicked.connect(self._on_double_clicked)
        self._bookmarks_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._bookmarks_list.customContextMenuRequested.connect(
            self._on_contextmenu)

        self._bookmarks_model = QStandardItemModel(0, 2)
        self._bookmarks_model.setHeaderData(0, Qt.Horizontal, 'Address')
        self._bookmarks_model.setHeaderData(1, Qt.Horizontal, 'Notes')

        self._bookmarks_list.setModel(self._bookmarks_model)

        self._bookmarks_list.header().setStretchLastSection(False)
        self._bookmarks_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents | QHeaderView.Interactive)
        self._bookmarks_list.header().setSectionResizeMode(
            1, QHeaderView.Stretch | QHeaderView.Interactive)

        v_box = QVBoxLayout(self)
        v_box.setContentsMargins(0, 0, 0, 0)
        v_box.addWidget(self._bookmarks_list)
        #header = QHeaderView(Qt.Horizontal, self)

        h_box = QHBoxLayout()
        h_box.setContentsMargins(5, 2, 5, 5)
        self.btn1 = QPushButton(
            QIcon(utils.resource_path('assets/icons/plus.svg')), '')
        self.btn1.setFixedSize(20, 20)
        self.btn1.clicked.connect(lambda: self._create_bookmark(-1))
        btn2 = QPushButton(QIcon(utils.resource_path('assets/icons/dash.svg')),
                           '')
        btn2.setFixedSize(20, 20)
        btn2.clicked.connect(self.delete_items)
        btn3 = QPushButton(
            QIcon(utils.resource_path('assets/icons/trashcan.svg')), '')
        btn3.setFixedSize(20, 20)
        btn3.clicked.connect(self.clear_list)
        h_box.addWidget(self.btn1)
        h_box.addWidget(btn2)
        h_box.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Preferred))
        h_box.addWidget(btn3)
        # header.setLayout(h_box)
        # header.setFixedHeight(25)
        # v_box.addWidget(header)
        v_box.addLayout(h_box)
        self.setLayout(v_box)

        self._bold_font = QFont(self._bookmarks_list.font())
        self._bold_font.setBold(True)

        shortcut_addnative = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_B),
                                       self._app_window, self._create_bookmark)
        shortcut_addnative.setAutoRepeat(False)
Example #46
0
class AddressList(MyTreeView):

    class Columns(IntEnum):
        TYPE = 0
        ADDRESS = 1
        LABEL = 2
        COIN_BALANCE = 3
        FIAT_BALANCE = 4
        NUM_TXS = 5

    filter_columns = [Columns.TYPE, Columns.ADDRESS, Columns.LABEL, Columns.COIN_BALANCE]

    ROLE_SORT_ORDER = Qt.UserRole + 1000

    def __init__(self, parent):
        super().__init__(parent, self.create_menu, stretch_column=self.Columns.LABEL)
        self.wallet = self.parent.wallet
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setSortingEnabled(True)
        self.show_change = AddressTypeFilter.ALL  # type: AddressTypeFilter
        self.show_used = AddressUsageStateFilter.ALL  # type: AddressUsageStateFilter
        self.change_button = QComboBox(self)
        self.change_button.currentIndexChanged.connect(self.toggle_change)
        for addr_type in AddressTypeFilter.__members__.values():  # type: AddressTypeFilter
            self.change_button.addItem(addr_type.ui_text())
        self.used_button = QComboBox(self)
        self.used_button.currentIndexChanged.connect(self.toggle_used)
        for addr_usage_state in AddressUsageStateFilter.__members__.values():  # type: AddressUsageStateFilter
            self.used_button.addItem(addr_usage_state.ui_text())
        self.std_model = QStandardItemModel(self)
        self.proxy = MySortModel(self, sort_role=self.ROLE_SORT_ORDER)
        self.proxy.setSourceModel(self.std_model)
        self.setModel(self.proxy)
        self.update()
        self.sortByColumn(self.Columns.TYPE, Qt.AscendingOrder)

    def get_toolbar_buttons(self):
        return QLabel(_("Filter:")), self.change_button, self.used_button

    def on_hide_toolbar(self):
        self.show_change = AddressTypeFilter.ALL  # type: AddressTypeFilter
        self.show_used = AddressUsageStateFilter.ALL  # type: AddressUsageStateFilter
        self.update()

    def save_toolbar_state(self, state, config):
        config.set_key('show_toolbar_addresses', state)

    def refresh_headers(self):
        fx = self.parent.fx
        if fx and fx.get_fiat_address_config():
            ccy = fx.get_currency()
        else:
            ccy = _('Fiat')
        headers = {
            self.Columns.TYPE: _('Type'),
            self.Columns.ADDRESS: _('Address'),
            self.Columns.LABEL: _('Label'),
            self.Columns.COIN_BALANCE: _('Balance'),
            self.Columns.FIAT_BALANCE: ccy + ' ' + _('Balance'),
            self.Columns.NUM_TXS: _('Tx'),
        }
        self.update_headers(headers)

    def toggle_change(self, state: int):
        if state == self.show_change:
            return
        self.show_change = AddressTypeFilter(state)
        self.update()

    def toggle_used(self, state: int):
        if state == self.show_used:
            return
        self.show_used = AddressUsageStateFilter(state)
        self.update()

    @profiler
    def update(self):
        if self.maybe_defer_update():
            return
        current_address = self.current_item_user_role(col=self.Columns.LABEL)
        if self.show_change == AddressTypeFilter.RECEIVING:
            addr_list = self.wallet.get_receiving_addresses()
        elif self.show_change == AddressTypeFilter.CHANGE:
            addr_list = self.wallet.get_change_addresses()
        else:
            addr_list = self.wallet.get_addresses()
        self.proxy.setDynamicSortFilter(False)  # temp. disable re-sorting after every change
        self.std_model.clear()
        self.refresh_headers()
        fx = self.parent.fx
        set_address = None
        addresses_beyond_gap_limit = self.wallet.get_all_known_addresses_beyond_gap_limit()
        for address in addr_list:
            num = self.wallet.get_address_history_len(address)
            label = self.wallet.labels.get(address, '')
            c, u, x = self.wallet.get_addr_balance(address)
            balance = c + u + x
            is_used_and_empty = self.wallet.is_used(address) and balance == 0
            if self.show_used == AddressUsageStateFilter.UNUSED and (balance or is_used_and_empty):
                continue
            if self.show_used == AddressUsageStateFilter.FUNDED and balance == 0:
                continue
            if self.show_used == AddressUsageStateFilter.USED_AND_EMPTY and not is_used_and_empty:
                continue
            balance_text = self.parent.format_amount(balance, whitespaces=True)
            # create item
            if fx and fx.get_fiat_address_config():
                rate = fx.exchange_rate()
                fiat_balance = fx.value_str(balance, rate)
            else:
                fiat_balance = ''
            labels = ['', address, label, balance_text, fiat_balance, "%d"%num]
            address_item = [QStandardItem(e) for e in labels]
            # align text and set fonts
            for i, item in enumerate(address_item):
                item.setTextAlignment(Qt.AlignVCenter)
                if i not in (self.Columns.TYPE, self.Columns.LABEL):
                    item.setFont(QFont(MONOSPACE_FONT))
            self.set_editability(address_item)
            address_item[self.Columns.FIAT_BALANCE].setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
            # setup column 0
            if self.wallet.is_change(address):
                address_item[self.Columns.TYPE].setText(_('change'))
                address_item[self.Columns.TYPE].setBackground(ColorScheme.YELLOW.as_color(True))
            else:
                address_item[self.Columns.TYPE].setText(_('receiving'))
                address_item[self.Columns.TYPE].setBackground(ColorScheme.GREEN.as_color(True))
            address_item[self.Columns.LABEL].setData(address, Qt.UserRole)
            address_path = self.wallet.get_address_index(address)
            address_item[self.Columns.TYPE].setData(address_path, self.ROLE_SORT_ORDER)
            address_path_str = self.wallet.get_address_path_str(address)
            if address_path_str is not None:
                address_item[self.Columns.TYPE].setToolTip(address_path_str)
            address_item[self.Columns.FIAT_BALANCE].setData(balance, self.ROLE_SORT_ORDER)
            # setup column 1
            if self.wallet.is_frozen_address(address):
                address_item[self.Columns.ADDRESS].setBackground(ColorScheme.BLUE.as_color(True))
            if address in addresses_beyond_gap_limit:
                address_item[self.Columns.ADDRESS].setBackground(ColorScheme.RED.as_color(True))
            # add item
            count = self.std_model.rowCount()
            self.std_model.insertRow(count, address_item)
            address_idx = self.std_model.index(count, self.Columns.LABEL)
            if address == current_address:
                set_address = QPersistentModelIndex(address_idx)
        self.set_current_idx(set_address)
        # show/hide columns
        if fx and fx.get_fiat_address_config():
            self.showColumn(self.Columns.FIAT_BALANCE)
        else:
            self.hideColumn(self.Columns.FIAT_BALANCE)
        self.filter()
        self.proxy.setDynamicSortFilter(True)

    def create_menu(self, position):
        from electrum.wallet import Multisig_Wallet
        is_multisig = isinstance(self.wallet, Multisig_Wallet)
        can_delete = self.wallet.can_delete_address()
        selected = self.selected_in_column(self.Columns.ADDRESS)
        if not selected:
            return
        multi_select = len(selected) > 1
        addrs = [self.item_from_index(item).text() for item in selected]
        menu = QMenu()
        if not multi_select:
            idx = self.indexAt(position)
            if not idx.isValid():
                return
            item = self.item_from_index(idx)
            if not item:
                return
            addr = addrs[0]
            addr_column_title = self.std_model.horizontalHeaderItem(self.Columns.LABEL).text()
            addr_idx = idx.sibling(idx.row(), self.Columns.LABEL)
            self.add_copy_menu(menu, idx)
            menu.addAction(_('Details'), lambda: self.parent.show_address(addr))
            persistent = QPersistentModelIndex(addr_idx)
            menu.addAction(_("Edit {}").format(addr_column_title), lambda p=persistent: self.edit(QModelIndex(p)))
            #menu.addAction(_("Request payment"), lambda: self.parent.receive_at(addr))
            if self.wallet.can_export():
                menu.addAction(_("Private key"), lambda: self.parent.show_private_key(addr))
            if not is_multisig and not self.wallet.is_watching_only():
                menu.addAction(_("Sign/verify message"), lambda: self.parent.sign_verify_message(addr))
                menu.addAction(_("Encrypt/decrypt message"), lambda: self.parent.encrypt_message(addr))
            if can_delete:
                menu.addAction(_("Remove from wallet"), lambda: self.parent.remove_address(addr))
            addr_URL = block_explorer_URL(self.config, 'addr', addr)
            if addr_URL:
                menu.addAction(_("View on block explorer"), lambda: webopen(addr_URL))

            if not self.wallet.is_frozen_address(addr):
                menu.addAction(_("Freeze"), lambda: self.parent.set_frozen_state_of_addresses([addr], True))
            else:
                menu.addAction(_("Unfreeze"), lambda: self.parent.set_frozen_state_of_addresses([addr], False))

        coins = self.wallet.get_spendable_coins(addrs)
        if coins:
            menu.addAction(_("Spend from"), lambda: self.parent.utxo_list.set_spend_list(coins))

        run_hook('receive_menu', menu, addrs, self.wallet)
        menu.exec_(self.viewport().mapToGlobal(position))

    def place_text_on_clipboard(self, text: str, *, title: str = None) -> None:
        if is_address(text):
            try:
                self.wallet.check_address_for_corruption(text)
            except InternalAddressCorruption as e:
                self.parent.show_error(str(e))
                raise
        super().place_text_on_clipboard(text, title=title)
Example #47
0
class BookmarksWidget(QWidget):
    def __init__(self, parent=None):  # pylint: disable=too-many-statements
        super(BookmarksWidget, self).__init__(parent=parent)

        self._app_window = parent

        if self._app_window.dwarf is None:
            print('BookmarksPanel created before Dwarf exists')
            return

        self.bookmarks = {}

        self._bookmarks_list = DwarfListView()
        self._bookmarks_list.doubleClicked.connect(self._on_double_clicked)
        self._bookmarks_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._bookmarks_list.customContextMenuRequested.connect(
            self._on_contextmenu)

        self._bookmarks_model = QStandardItemModel(0, 2)
        self._bookmarks_model.setHeaderData(0, Qt.Horizontal, 'Address')
        self._bookmarks_model.setHeaderData(1, Qt.Horizontal, 'Notes')

        self._bookmarks_list.setModel(self._bookmarks_model)

        self._bookmarks_list.header().setStretchLastSection(False)
        self._bookmarks_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents | QHeaderView.Interactive)
        self._bookmarks_list.header().setSectionResizeMode(
            1, QHeaderView.Stretch | QHeaderView.Interactive)

        v_box = QVBoxLayout(self)
        v_box.setContentsMargins(0, 0, 0, 0)
        v_box.addWidget(self._bookmarks_list)
        #header = QHeaderView(Qt.Horizontal, self)

        h_box = QHBoxLayout()
        h_box.setContentsMargins(5, 2, 5, 5)
        self.btn1 = QPushButton(
            QIcon(utils.resource_path('assets/icons/plus.svg')), '')
        self.btn1.setFixedSize(20, 20)
        self.btn1.clicked.connect(lambda: self._create_bookmark(-1))
        btn2 = QPushButton(QIcon(utils.resource_path('assets/icons/dash.svg')),
                           '')
        btn2.setFixedSize(20, 20)
        btn2.clicked.connect(self.delete_items)
        btn3 = QPushButton(
            QIcon(utils.resource_path('assets/icons/trashcan.svg')), '')
        btn3.setFixedSize(20, 20)
        btn3.clicked.connect(self.clear_list)
        h_box.addWidget(self.btn1)
        h_box.addWidget(btn2)
        h_box.addSpacerItem(
            QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Preferred))
        h_box.addWidget(btn3)
        # header.setLayout(h_box)
        # header.setFixedHeight(25)
        # v_box.addWidget(header)
        v_box.addLayout(h_box)
        self.setLayout(v_box)

        self._bold_font = QFont(self._bookmarks_list.font())
        self._bold_font.setBold(True)

        shortcut_addnative = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_B),
                                       self._app_window, self._create_bookmark)
        shortcut_addnative.setAutoRepeat(False)

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def delete_items(self):
        """ Delete selected Items
        """
        index = self._bookmarks_list.selectionModel().currentIndex().row()
        if index != -1:
            self._on_delete_bookmark(index)
            self._bookmarks_model.removeRow(index)

    def clear_list(self):
        """ Clear the List
        """
        # go through all items and tell it gets removed
        for item in range(self._bookmarks_model.rowCount()):
            self._on_delete_bookmark(item)

        if self._bookmarks_model.rowCount() > 0:
            # something was wrong it should be empty
            self._bookmarks_model.removeRows(0,
                                             self._bookmarks_model.rowCount())

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_double_clicked(self, index):
        index = self._bookmarks_list.selectionModel().currentIndex().row()
        if index != -1:
            addr = self._bookmarks_model.item(index, 0).text()
            if addr:
                self._app_window.jump_to_address(addr, view=1)

    def _on_contextmenu(self, pos):
        context_menu = QMenu(self)
        index = self._bookmarks_list.indexAt(pos).row()
        if index != -1:
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self._bookmarks_model.item(index, 0).text()))
            context_menu.addAction(
                'Jump to address', lambda: self._app_window.jump_to_address(
                    self._bookmarks_model.item(index, 0).text()))

            # todo: add breakpoint address menu

            context_menu.addSeparator()
            context_menu.addAction('Edit',
                                   lambda: self._create_bookmark(index=index))
            context_menu.addAction('Delete',
                                   lambda: self._on_delete_bookmark(index))
            context_menu.addSeparator()
            if self._bookmarks_list.search_enabled:
                context_menu.addSeparator()
                context_menu.addAction('Search',
                                       self._bookmarks_list._on_cm_search)
                context_menu.addSeparator()
        context_menu.addAction('New', self._create_bookmark)
        global_pt = self._bookmarks_list.mapToGlobal(pos)
        context_menu.exec(global_pt)

    # + button
    def _create_bookmark(self, index=-1, ptr='', note=''):
        if ptr == '':
            if isinstance(index, int) and index >= 0:
                ptr = self._bookmarks_model.item(index, 0).text()
                note = self._bookmarks_model.item(index, 1).text()

            ptr, _ = InputDialog.input_pointer(parent=self._app_window,
                                               input_content=ptr)
        else:
            ptr = utils.parse_ptr(ptr)

        if ptr > 0:
            ptr = hex(ptr)
            if self._bookmarks_list.uppercase_hex:
                ptr = ptr.upper().replace('0X', '0x')

            index = self._bookmarks_model.findItems(ptr, Qt.MatchExactly)
            if len(index) > 0:
                index = index[0].row()
                note = self._bookmarks_model.item(index, 1).text()
            else:
                index = -1

            accept = note != ''
            if note == '':
                accept, note = InputDialog.input(hint='Insert notes for %s' %
                                                 ptr,
                                                 input_content=note)
            if accept:
                if index < 0:
                    self.insert_bookmark(ptr, note)
                else:
                    item = self._bookmarks_model.item(index, 0)
                    item.setText(ptr)
                    item = self._bookmarks_model.item(index, 1)
                    item.setText(note)

                self.bookmarks[ptr] = note

    def insert_bookmark(self, ptr_as_hex, note):
        if self._bookmarks_list.uppercase_hex:
            ptr_as_hex = ptr_as_hex.upper().replace('0X', '0x')

        self._bookmarks_model.appendRow(
            [QStandardItem(ptr_as_hex),
             QStandardItem(note)])
        self._bookmarks_list.resizeColumnToContents(0)

    def is_address_bookmarked(self, ptr):
        return utils.parse_ptr(ptr) in self.bookmarks

    # shortcuts/menu
    def _on_delete_bookmark(self, index):
        ptr = self._bookmarks_model.item(index, 0).text()
        del self.bookmarks[ptr]

        self._bookmarks_model.removeRow(index)
    def __init__(self, *args):
        super(TableViewSelectTypes, self).__init__(args[1])

        self.tableView = args[1]
        self._text = ''

        gMainWindow = GlobalObjs.GetValue('MainWindow')

        self.setModal(True)
        #self.setModel(True)
        self.setWindowTitle('Select Type')

        self.vboxLayout = QtWidgets.QVBoxLayout(self)
        self.tree = QTreeView(self)
        self.model = QStandardItemModel(self)
        self.tree.setHeaderHidden(True)

        self.tree.setModel(self.model)

        self.bacisItem = QStandardItem()
        self.bacisItem.setText('BasicTypes')
        self.bacisItem.setFlags(QtCore.Qt.ItemIsEnabled)
        self.model.appendRow(self.bacisItem)
        self.tree.expand(self.bacisItem.index())

        for v in GridTableView.BasicTypes:
            item = QStandardItem()
            item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
            item.setText(v)
            item.setData(True)
            self.bacisItem.appendRow(item)

        if self.tableView.Model.activeColumn != args[2]:
            self.otherItem = QStandardItem()
            self.otherItem.setText('Other')
            self.otherItem.setFlags(QtCore.Qt.ItemIsEnabled)
            self.model.appendRow(self.otherItem)
            self.tree.expand(self.otherItem.index())

            def LoadOtherTypes(item, parent):
                for i in range(0, item.rowCount()):
                    childItem = item.child(i, 0)
                    if childItem.data(Qt.UserRole + 2) == self.tableView.Model:
                        continue

                    itemAdd = QStandardItem()
                    itemAdd.setText(childItem.text())

                    if childItem.data() == 3:
                        itemAdd.setFlags(QtCore.Qt.ItemIsEnabled
                                         | QtCore.Qt.ItemIsSelectable)
                    else:
                        itemAdd.setFlags(QtCore.Qt.ItemIsEnabled)
                        LoadOtherTypes(childItem, itemAdd)

                    parent.appendRow(itemAdd)

            LoadOtherTypes(gMainWindow.TreeRootItem, self.otherItem)

        self.vboxLayout.addWidget(self.tree)

        self.tree.doubleClicked.connect(self.OnDoubleClicked)
        self.tree.setFocus()

        self.show()
Example #49
0
class InvoiceList(MyTreeView):
    class Columns(IntEnum):
        DATE = 0
        DESCRIPTION = 1
        AMOUNT = 2
        STATUS = 3

    headers = {
        Columns.DATE: _('Date'),
        Columns.DESCRIPTION: _('Description'),
        Columns.AMOUNT: _('Amount'),
        Columns.STATUS: _('Status'),
    }
    filter_columns = [Columns.DATE, Columns.DESCRIPTION, Columns.AMOUNT]

    def __init__(self, parent):
        super().__init__(parent,
                         self.create_menu,
                         stretch_column=self.Columns.DESCRIPTION,
                         editable_columns=[])
        self.std_model = QStandardItemModel(self)
        self.proxy = MySortModel(self, sort_role=ROLE_SORT_ORDER)
        self.proxy.setSourceModel(self.std_model)
        self.setModel(self.proxy)
        self.setSortingEnabled(True)
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.update()

    def update_item(self, key, invoice: Invoice):
        model = self.std_model
        for row in range(0, model.rowCount()):
            item = model.item(row, 0)
            if item.data(ROLE_REQUEST_ID) == key:
                break
        else:
            return
        status_item = model.item(row, self.Columns.STATUS)
        status = self.parent.wallet.get_invoice_status(invoice)
        status_str = invoice.get_status_str(status)
        if self.parent.wallet.lnworker:
            log = self.parent.wallet.lnworker.logs.get(key)
            if log and status == PR_INFLIGHT:
                status_str += '... (%d)' % len(log)
        status_item.setText(status_str)
        status_item.setIcon(read_QIcon(pr_icons.get(status)))

    def update(self):
        # not calling maybe_defer_update() as it interferes with conditional-visibility
        self.proxy.setDynamicSortFilter(
            False)  # temp. disable re-sorting after every change
        self.std_model.clear()
        self.update_headers(self.__class__.headers)
        for idx, item in enumerate(self.parent.wallet.get_invoices()):
            if item.is_lightning():
                key = item.rhash
                icon_name = 'lightning.png'
            else:
                key = item.id
                icon_name = 'bitcoin.png'
                if item.bip70:
                    icon_name = 'seal.png'
            status = self.parent.wallet.get_invoice_status(item)
            status_str = item.get_status_str(status)
            message = item.message
            amount = item.amount
            timestamp = item.time or 0
            date_str = format_time(timestamp) if timestamp else _('Unknown')
            amount_str = self.parent.format_amount(amount, whitespaces=True)
            labels = [date_str, message, amount_str, status_str]
            items = [QStandardItem(e) for e in labels]
            self.set_editability(items)
            items[self.Columns.DATE].setIcon(read_QIcon(icon_name))
            items[self.Columns.STATUS].setIcon(read_QIcon(
                pr_icons.get(status)))
            items[self.Columns.DATE].setData(key, role=ROLE_REQUEST_ID)
            items[self.Columns.DATE].setData(item.type, role=ROLE_REQUEST_TYPE)
            items[self.Columns.DATE].setData(timestamp, role=ROLE_SORT_ORDER)
            self.std_model.insertRow(idx, items)
        self.filter()
        self.proxy.setDynamicSortFilter(True)
        # sort requests by date
        self.sortByColumn(self.Columns.DATE, Qt.DescendingOrder)
        # hide list if empty
        if self.parent.isVisible():
            b = self.std_model.rowCount() > 0
            self.setVisible(b)
            self.parent.invoices_label.setVisible(b)

    def create_menu(self, position):
        wallet = self.parent.wallet
        items = self.selected_in_column(0)
        if len(items) > 1:
            keys = [item.data(ROLE_REQUEST_ID) for item in items]
            invoices = [wallet.invoices.get(key) for key in keys]
            can_batch_pay = all([
                i.type == PR_TYPE_ONCHAIN
                and wallet.get_invoice_status(i) == PR_UNPAID for i in invoices
            ])
            menu = QMenu(self)
            if can_batch_pay:
                menu.addAction(
                    _("Batch pay invoices"),
                    lambda: self.parent.pay_multiple_invoices(invoices))
            menu.addAction(_("Delete invoices"),
                           lambda: self.parent.delete_invoices(keys))
            menu.exec_(self.viewport().mapToGlobal(position))
            return
        idx = self.indexAt(position)
        item = self.item_from_index(idx)
        item_col0 = self.item_from_index(
            idx.sibling(idx.row(), self.Columns.DATE))
        if not item or not item_col0:
            return
        key = item_col0.data(ROLE_REQUEST_ID)
        invoice = self.parent.wallet.get_invoice(key)
        menu = QMenu(self)
        self.add_copy_menu(menu, idx)
        if invoice.is_lightning():
            menu.addAction(_("Details"),
                           lambda: self.parent.show_lightning_invoice(invoice))
        else:
            if len(invoice.outputs) == 1:
                menu.addAction(
                    _("Copy Address"),
                    lambda: self.parent.do_copy(invoice.get_address(),
                                                title='Bitcoin Address'))
            menu.addAction(_("Details"),
                           lambda: self.parent.show_onchain_invoice(invoice))
        status = wallet.get_invoice_status(invoice)
        if status == PR_UNPAID:
            menu.addAction(_("Pay"),
                           lambda: self.parent.do_pay_invoice(invoice))
        if status == PR_FAILED:
            menu.addAction(_("Retry"),
                           lambda: self.parent.do_pay_invoice(invoice))
        if self.parent.wallet.lnworker:
            log = self.parent.wallet.lnworker.logs.get(key)
            if log:
                menu.addAction(_("View log"), lambda: self.show_log(key, log))
        menu.addAction(_("Delete"), lambda: self.parent.delete_invoices([key]))
        menu.exec_(self.viewport().mapToGlobal(position))

    def show_log(self, key, log: Sequence[PaymentAttemptLog]):
        d = WindowModalDialog(self, _("Payment log"))
        d.setMinimumWidth(600)
        vbox = QVBoxLayout(d)
        log_w = QTreeWidget()
        log_w.setHeaderLabels([_('Hops'), _('Channel ID'), _('Message')])
        log_w.header().setSectionResizeMode(2, QHeaderView.Stretch)
        log_w.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
        for payment_attempt_log in log:
            route_str, chan_str, message = payment_attempt_log.formatted_tuple(
            )
            x = QTreeWidgetItem([route_str, chan_str, message])
            log_w.addTopLevelItem(x)
        vbox.addWidget(log_w)
        vbox.addLayout(Buttons(CloseButton(d)))
        d.exec_()
class TableViewSelectTypes(QtWidgets.QDialog):
    def setText(self, text):
        self._text = text

        if text in GridTableView.BasicTypes:
            self.tree.expand(self.bacisItem.index())
            for i in range(self.bacisItem.rowCount()):
                childItem = self.bacisItem.child(i, 0)
                if childItem.text() == text:
                    self.tree.setCurrentIndex(childItem.index())

        else:
            self.tree.expand(self.otherItem.index())
            names = text.split('.')
            parentItem = self.otherItem
            for v in names:
                isBreak = False
                for i in range(parentItem.rowCount()):
                    if isBreak == True:
                        continue

                    if parentItem.child(i, 0).text() == v:
                        parentItem = parentItem.child(i, 0)
                        self.tree.expand(parentItem.index())
                        isBreak = True
                        continue

            self.tree.setCurrentIndex(parentItem.index())

    def text(self):
        return self._text

    def __init__(self, *args):
        super(TableViewSelectTypes, self).__init__(args[1])

        self.tableView = args[1]
        self._text = ''

        gMainWindow = GlobalObjs.GetValue('MainWindow')

        self.setModal(True)
        #self.setModel(True)
        self.setWindowTitle('Select Type')

        self.vboxLayout = QtWidgets.QVBoxLayout(self)
        self.tree = QTreeView(self)
        self.model = QStandardItemModel(self)
        self.tree.setHeaderHidden(True)

        self.tree.setModel(self.model)

        self.bacisItem = QStandardItem()
        self.bacisItem.setText('BasicTypes')
        self.bacisItem.setFlags(QtCore.Qt.ItemIsEnabled)
        self.model.appendRow(self.bacisItem)
        self.tree.expand(self.bacisItem.index())

        for v in GridTableView.BasicTypes:
            item = QStandardItem()
            item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable)
            item.setText(v)
            item.setData(True)
            self.bacisItem.appendRow(item)

        if self.tableView.Model.activeColumn != args[2]:
            self.otherItem = QStandardItem()
            self.otherItem.setText('Other')
            self.otherItem.setFlags(QtCore.Qt.ItemIsEnabled)
            self.model.appendRow(self.otherItem)
            self.tree.expand(self.otherItem.index())

            def LoadOtherTypes(item, parent):
                for i in range(0, item.rowCount()):
                    childItem = item.child(i, 0)
                    if childItem.data(Qt.UserRole + 2) == self.tableView.Model:
                        continue

                    itemAdd = QStandardItem()
                    itemAdd.setText(childItem.text())

                    if childItem.data() == 3:
                        itemAdd.setFlags(QtCore.Qt.ItemIsEnabled
                                         | QtCore.Qt.ItemIsSelectable)
                    else:
                        itemAdd.setFlags(QtCore.Qt.ItemIsEnabled)
                        LoadOtherTypes(childItem, itemAdd)

                    parent.appendRow(itemAdd)

            LoadOtherTypes(gMainWindow.TreeRootItem, self.otherItem)

        self.vboxLayout.addWidget(self.tree)

        self.tree.doubleClicked.connect(self.OnDoubleClicked)
        self.tree.setFocus()

        self.show()

    def OnDoubleClicked(self, index):
        item = self.model.itemFromIndex(index)
        if item.flags(
        ) == QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable:
            if item.data() == True:
                self.setText(index.data())
            else:
                names = []
                parent = index
                while True:
                    names.append(parent.data())
                    parent = parent.parent()
                    if parent.isValid() == False or self.otherItem.index(
                    ) == parent:
                        break

                self.setText('.'.join(reversed(names)))

            self.done(QtWidgets.QDialog.Accepted)
    def __init__(self, parent=None):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        super(MainWindow, self).__init__(parent=parent)
        self.setupUi(self)

        #   Set up song list (left hand side of screen)
        self.SongListModel = QStandardItemModel()
        self.SongList.setModel(self.SongListModel)

        # Work out the directory where the python/executable lives - preferences are within this dir.
        self.HomeDirectory = os.getcwd()
        self.SongPreferencesFileName = self.HomeDirectory + '\\OpenSongViewerPrefs.json'

        IntroText = "Hello there<br><br>"
        IntroText = IntroText + "<i>OpenSongViewer version " + VersionNumber + "   "
        IntroText = IntroText + VersionInformation + "</i><br><br>"

        IntroText = IntroText + "Remember to set the location of your OpenSong songs in the preferences<br><br>"

        IntroText = IntroText + "Click on <br>"
        IntroText = IntroText + " * Add - to add a song to the song list<br>"
        IntroText = IntroText + " * Rem - to remove the current selected song to the song list<br>"
        IntroText = IntroText + " * Edit - to edit the current selected song to the song list<br><br>"

        IntroText = IntroText + "Remember to save your song list using 'Song List' -> 'Save As...' - it'll retain order and keys<br>"
        IntroText = IntroText + "Remember to check your current preferences under the file menu<br>"
        IntroText = IntroText + "<br>"

        IntroText = IntroText + "Changelog:<br>"
        IntroText = IntroText + "0.5 - bugfix - when transposing and base key was 'B' the value key didn't update<br>"
        IntroText = IntroText + " * Improvement - when you select a song in the songlist, you can now use right and left cursor or arrows under the songlist to move up and down the list<br>"
        IntroText = IntroText + " * Improvement - new preference setting - when editing, you can choose to always edit in the original base key, or edit in the current transposed value<br>"
        IntroText = IntroText + " - NOTE - if you edit in the current transposed value, this will overwrite the original base key<br>"
        IntroText = IntroText + " - this means that chord characters can move slightly when the base key switches from a single to a double character  - e.g. 'C' to 'Db'<br>"

        self.SongText.setText(IntroText)

        # try to pull in the preferences
        try:
            with open(self.SongPreferencesFileName) as f:
                SongPreferences = json.load(f)

        except:
            # none found - set default prefs.
            SongPreferences['PREFSVER'] = '0.5'
            SongPreferences['SONGDIR'] = self.HomeDirectory
            SongPreferences['DEFAULTFONTSIZE'] = '25'
            SongPreferences['DEFAULTPAGESIZE'] = '38'
            SongPreferences['SHARPFLAT_C'] = 'C#'
            SongPreferences['SHARPFLAT_D'] = 'D#'
            SongPreferences['SHARPFLAT_F'] = 'F#'
            SongPreferences['SHARPFLAT_G'] = 'G#'
            SongPreferences['SHARPFLAT_A'] = 'A#'
            SongPreferences['EDIT_USE_ORIGINALKEY'] = 'ORIGINALKEY'

        if type(SongPreferences) is list:
            # V0.1 preferences used lists instead of dict - convert and re-save
            print('Old V0.1 preferences file format - upgraded to v0.2')
            OLDPrefs = SongPreferences
            SongPreferences = {}
            SongPreferences['PREFSVER'] = '0.2'
            SongPreferences['SONGDIR'] = OLDPrefs[0][1]

            # Overwrite old file
            with open(self.SongPreferencesFileName, 'w') as f:
                json.dump(SongPreferences, f)

        if SongPreferences['PREFSVER'] == '0.2':
            #   Upgrade preferences values - put in default values.
            SongPreferences['PREFSVER'] = '0.3'
            SongPreferences['DEFAULTFONTSIZE'] = '25'
            SongPreferences['SHARPFLAT_C'] = 'C#'
            SongPreferences['SHARPFLAT_D'] = 'D#'
            SongPreferences['SHARPFLAT_F'] = 'F#'
            SongPreferences['SHARPFLAT_G'] = 'G#'
            SongPreferences['SHARPFLAT_A'] = 'A#'

        if SongPreferences['PREFSVER'] == '0.3':
            SongPreferences['PREFSVER'] = '0.4'
            SongPreferences['DEFAULTPAGESIZE'] = '38'

        if SongPreferences['PREFSVER'] == '0.4':
            #   0.5 brings in edit use original key, or use transposed value
            #       normal is to keep the base key
            SongPreferences['PREFSVER'] = '0.5'
            SongPreferences['EDIT_USE_ORIGINALKEY'] = 'ORIGINALKEY'

        self.InterpretPreferences()

        #   Wire up the buttons
        self.AddSong.clicked.connect(self.AddNewSong)
        self.DeleteSong.clicked.connect(self.DelSelectedSong)
        self.EditSong.clicked.connect(self.EditCurrentSong)

        self.SongList.clicked.connect(self.SongListSelected)

        self.TransposeMinus.clicked.connect(self.TransposeMinusSelected)
        self.TransposePlus.clicked.connect(self.TransposePlusSelected)
        self.actionClear_List.triggered.connect(self.ClearAll)
        self.actionEdit.triggered.connect(self.EditCurrentSong)
        self.actionNew.triggered.connect(self.NewSong)

        self.actionSave_Song_List.triggered.connect(self.SaveSongList)
        self.actionLoad_Song_List.triggered.connect(self.LoadSongList)
        self.actionSave_Song_List_As.triggered.connect(self.SaveSongListAs)

        self.actionPreferences.triggered.connect(self.UpdatePrefs)
        self.actionAbout.triggered.connect(self.AboutWindow)

        self.NextSong.clicked.connect(self.MoveNextSong)
        self.PrevSong.clicked.connect(self.MovePrevSong)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):

    CurrentSong = ''
    CurrentSongKey = ''
    CurrentOffset = 0

    # Directory that holds the song files - picked up from preferences
    SongLocation = ''

    # Directory holding this program
    HomeDirectory = ''
    # Location and name of preferences file - this is held in the same directory as the program
    SongPreferencesFileName = ''

    #   Default songlist file name - we save after change (transpose etc)
    SaveFileName = 'SongData.json'

    def __init__(self, parent=None):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        super(MainWindow, self).__init__(parent=parent)
        self.setupUi(self)

        #   Set up song list (left hand side of screen)
        self.SongListModel = QStandardItemModel()
        self.SongList.setModel(self.SongListModel)

        # Work out the directory where the python/executable lives - preferences are within this dir.
        self.HomeDirectory = os.getcwd()
        self.SongPreferencesFileName = self.HomeDirectory + '\\OpenSongViewerPrefs.json'

        IntroText = "Hello there<br><br>"
        IntroText = IntroText + "<i>OpenSongViewer version " + VersionNumber + "   "
        IntroText = IntroText + VersionInformation + "</i><br><br>"

        IntroText = IntroText + "Remember to set the location of your OpenSong songs in the preferences<br><br>"

        IntroText = IntroText + "Click on <br>"
        IntroText = IntroText + " * Add - to add a song to the song list<br>"
        IntroText = IntroText + " * Rem - to remove the current selected song to the song list<br>"
        IntroText = IntroText + " * Edit - to edit the current selected song to the song list<br><br>"

        IntroText = IntroText + "Remember to save your song list using 'Song List' -> 'Save As...' - it'll retain order and keys<br>"
        IntroText = IntroText + "Remember to check your current preferences under the file menu<br>"
        IntroText = IntroText + "<br>"

        IntroText = IntroText + "Changelog:<br>"
        IntroText = IntroText + "0.5 - bugfix - when transposing and base key was 'B' the value key didn't update<br>"
        IntroText = IntroText + " * Improvement - when you select a song in the songlist, you can now use right and left cursor or arrows under the songlist to move up and down the list<br>"
        IntroText = IntroText + " * Improvement - new preference setting - when editing, you can choose to always edit in the original base key, or edit in the current transposed value<br>"
        IntroText = IntroText + " - NOTE - if you edit in the current transposed value, this will overwrite the original base key<br>"
        IntroText = IntroText + " - this means that chord characters can move slightly when the base key switches from a single to a double character  - e.g. 'C' to 'Db'<br>"

        self.SongText.setText(IntroText)

        # try to pull in the preferences
        try:
            with open(self.SongPreferencesFileName) as f:
                SongPreferences = json.load(f)

        except:
            # none found - set default prefs.
            SongPreferences['PREFSVER'] = '0.5'
            SongPreferences['SONGDIR'] = self.HomeDirectory
            SongPreferences['DEFAULTFONTSIZE'] = '25'
            SongPreferences['DEFAULTPAGESIZE'] = '38'
            SongPreferences['SHARPFLAT_C'] = 'C#'
            SongPreferences['SHARPFLAT_D'] = 'D#'
            SongPreferences['SHARPFLAT_F'] = 'F#'
            SongPreferences['SHARPFLAT_G'] = 'G#'
            SongPreferences['SHARPFLAT_A'] = 'A#'
            SongPreferences['EDIT_USE_ORIGINALKEY'] = 'ORIGINALKEY'

        if type(SongPreferences) is list:
            # V0.1 preferences used lists instead of dict - convert and re-save
            print('Old V0.1 preferences file format - upgraded to v0.2')
            OLDPrefs = SongPreferences
            SongPreferences = {}
            SongPreferences['PREFSVER'] = '0.2'
            SongPreferences['SONGDIR'] = OLDPrefs[0][1]

            # Overwrite old file
            with open(self.SongPreferencesFileName, 'w') as f:
                json.dump(SongPreferences, f)

        if SongPreferences['PREFSVER'] == '0.2':
            #   Upgrade preferences values - put in default values.
            SongPreferences['PREFSVER'] = '0.3'
            SongPreferences['DEFAULTFONTSIZE'] = '25'
            SongPreferences['SHARPFLAT_C'] = 'C#'
            SongPreferences['SHARPFLAT_D'] = 'D#'
            SongPreferences['SHARPFLAT_F'] = 'F#'
            SongPreferences['SHARPFLAT_G'] = 'G#'
            SongPreferences['SHARPFLAT_A'] = 'A#'

        if SongPreferences['PREFSVER'] == '0.3':
            SongPreferences['PREFSVER'] = '0.4'
            SongPreferences['DEFAULTPAGESIZE'] = '38'

        if SongPreferences['PREFSVER'] == '0.4':
            #   0.5 brings in edit use original key, or use transposed value
            #       normal is to keep the base key
            SongPreferences['PREFSVER'] = '0.5'
            SongPreferences['EDIT_USE_ORIGINALKEY'] = 'ORIGINALKEY'

        self.InterpretPreferences()

        #   Wire up the buttons
        self.AddSong.clicked.connect(self.AddNewSong)
        self.DeleteSong.clicked.connect(self.DelSelectedSong)
        self.EditSong.clicked.connect(self.EditCurrentSong)

        self.SongList.clicked.connect(self.SongListSelected)

        self.TransposeMinus.clicked.connect(self.TransposeMinusSelected)
        self.TransposePlus.clicked.connect(self.TransposePlusSelected)
        self.actionClear_List.triggered.connect(self.ClearAll)
        self.actionEdit.triggered.connect(self.EditCurrentSong)
        self.actionNew.triggered.connect(self.NewSong)

        self.actionSave_Song_List.triggered.connect(self.SaveSongList)
        self.actionLoad_Song_List.triggered.connect(self.LoadSongList)
        self.actionSave_Song_List_As.triggered.connect(self.SaveSongListAs)

        self.actionPreferences.triggered.connect(self.UpdatePrefs)
        self.actionAbout.triggered.connect(self.AboutWindow)

        self.NextSong.clicked.connect(self.MoveNextSong)
        self.PrevSong.clicked.connect(self.MovePrevSong)

    #   Do anything based on preferences settings - copy values to variables etc.
    def InterpretPreferences(self):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        # Go through the preferences and set variables.

        self.SongLocation = SongPreferences['SONGDIR']

    #   General routine to ask a query on screen
    def AskQuery(self, QueryTitle, QueryText):

        resp = QMessageBox.question(self, QueryTitle, QueryText,
                                    QMessageBox.Yes | QMessageBox.No,
                                    QMessageBox.No)

        if resp == 16384:
            return "YES"
        else:
            return "NO"

    #   General routine to ask a query on screen
    def OkMessage(self, QueryTitle, QueryText):

        resp = QMessageBox.question(self, QueryTitle, QueryText,
                                    QMessageBox.Ok, QMessageBox.Ok)

    #   Save the current song list, but specify a location.
    def SaveSongListAs(self):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        # Set the new default file name for songs.
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        SaveFile = QFileDialog.getSaveFileName(self, 'Save Song List As',
                                               self.SongLocation)

        # Get the file name
        Fname = SaveFile[0]

        # Linux / windows
        if os.sep == '\\':
            Fname = Fname.replace('/', '\\')

        # set the new default file name for songs
        self.SaveFileName = Fname

        # and save the songlist
        self.SaveSongList()

    def NavigateSong(self, Direction):
        #   Improvement 20210401
        #   Click in the Main SongList - you can then use right and left keys to
        #   move through the songs instead of having to click on specific songs
        #   its slightly more efficient when playing live...

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        #   Get the total rows in the list, so we can wrap around
        TotalRows = self.SongListModel.rowCount()
        #   And the current song
        CurrentSelected = self.SongList.currentIndex().row()

        if Direction == "DOWN":
            NewSelected = CurrentSelected + 1
            print("Next song")
        else:
            NewSelected = CurrentSelected - 1
            print("Previous song")

        #   We only want to do stuff if there's a list there...
        if TotalRows > 0:

            #   Do we need to wrap around?
            if NewSelected < 0:
                NewSelected = TotalRows - 1
            if NewSelected >= TotalRows:
                NewSelected = 0

            # print("Total:"+str(TotalRows)+" Current:"+str(CurrentSelected)+" New:"+str(NewSelected))

            #   Set the updated selection value
            index = self.SongListModel.index(NewSelected, 0, QModelIndex())
            self.SongList.setCurrentIndex(index)

            #   To display the song, we need the song title, so get it from the list...
            SongTitle = self.SongListModel.index(NewSelected, 0).data()

            #   and display the updated song.
            self.DisplaySong(SongTitle)

    def MoveNextSong(self):

        self.NavigateSong("DOWN")

    def MovePrevSong(self):
        self.NavigateSong("UP")

    def keyPressEvent(self, event):

        #   Improvement 20210401
        #   Click in the Main SongList - you can then use right and left keys to
        #   move through the songs instead of having to click on specific songs
        #   its slightly more efficient when playing live...

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        #   Get the total rows in the list, so we can wrap around
        TotalRows = self.SongListModel.rowCount()
        #   And the current song
        CurrentSelected = self.SongList.currentIndex().row()
        #   Use -1 as 'no movement'
        NewSelected = -1

        #   If we press right or left, capture it and set NewSelected
        if event.key() == Qt.Key_Right:
            print("Right pressed")
            self.NavigateSong("DOWN")
        if event.key() == Qt.Key_Left:
            print("Left pressed")
            self.NavigateSong("UP")

    #   Save the song list to the current default file name
    def SaveSongList(self):
        # Take the current songdata and save this to a file e.g. 'SongData.json'

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        SaveFileName = self.SaveFileName
        with open(SaveFileName, 'w') as f:
            json.dump(SongDataList, f)

        print("Saved updated song list " + SaveFileName)

    #   Load a song list
    def LoadSongList(self):
        # Identify and load songdata, then update the screen.

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName = QFileDialog.getOpenFileName(self, 'Open file',
                                               self.SongLocation,
                                               'OpenFile(*)')

        if fileName and len(fileName[0]) > 0:

            #   If Windows, change the separator
            FName = fileName[0]
            if os.sep == '\\':
                FName = FName.replace('/', '\\')

            # Set the default from now on...
            self.SaveFileName = FName

            # Now, open then file and read the JSON data.

            with open(FName) as f:
                SongDataList = json.load(f)

            # Clear out and populate the song list panel.

            self.SongListModel.clear()

            # Add the files to the on-screen list
            Ptr = 0

            try:
                while Ptr < len(SongDataList):
                    FName = SongDataList[Ptr][4]
                    item = QStandardItem(FName)
                    self.SongListModel.appendRow(item)
                    Ptr = Ptr + 1
            except:
                self.OkMessage(
                    'Load error',
                    'Song list file is not compatible with this version - sorry'
                )

    #   Given a song name, find the location within the main song array and return the number
    def LocateSong(self, SongName):

        #   Locate the song...

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        Ptr = 0
        RetValue = -1

        while Ptr < len(SongDataList) and RetValue == -1:

            if SongDataList[Ptr][4] == SongName:
                # Located the song information...
                RetValue = Ptr

            Ptr = Ptr + 1

        return RetValue

    #   Transpose - go down a key
    def TransposeMinusSelected(self):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        #   Locate the song...
        SongPtr = self.LocateSong(self.CurrentSong)

        if SongPtr > -1:
            # got a valid song..

            print("Located song")

            # Take it down a key
            SongDataList[SongPtr][3] -= 1

            # 0 1  2 3  4 5 6  7 8  9  10 11
            # c c# d d# e f f# g g# a  a# b

            # Wraparound if necessary
            if SongDataList[SongPtr][3] < 0:
                SongDataList[SongPtr][3] = 11

            # now re-display
            self.DisplaySong(self.CurrentSong)

            # we've made a change to the song set - save the list
            self.SaveSongList()

    #   Transpost - go up a key
    def TransposePlusSelected(self):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        #   Locate the song...
        SongPtr = self.LocateSong(self.CurrentSong)

        if SongPtr > -1:
            # got a valid song..

            print("Located song")

            # take it up a key
            SongDataList[SongPtr][3] += 1

            # 0 1  2 3  4 5 6  7 8  9  10 11
            # c c# d d# e f f# g g# a  a# b

            # too high - wraparound
            if SongDataList[SongPtr][3] > 11:
                SongDataList[SongPtr][3] = 0

            # now re-display
            self.DisplaySong(self.CurrentSong)

            # we've made a change - save the song set.
            self.SaveSongList()

    #   Given a song name, put the song text onto screen
    #   Note - if the song offset is not zero, it transposes to the correct chord
    #          we don't ever overwrite the original chords - we re-work out each time
    #          doing it this way means that the positioning won't change if you keep transposing.
    def DisplaySong(self, SongName):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        #   Locate the song...
        Ptr = self.LocateSong(SongName)

        if Ptr > -1:

            #   Located the song information...

            SongText = SongDataList[Ptr][1]
            SongKey = SongDataList[Ptr][2]
            SongOffset = SongDataList[Ptr][3]

            ActualSongKey = Derive_Actual_Song_Key(SongKey, SongOffset)

            self.CurrentSong = SongName
            self.CurrentSongKey = SongKey
            self.CurrentOffset = SongOffset

            #  In order to have the display in columns and have different colours for particular items etc
            #  we use a HTML viewer to display the song text.
            #  This means we can apply style sheets - however, it appears the HTML viewer doesn't
            #  fully implement HTML?
            SongTextHeader = "<html><head>"
            SongTextHeader = SongTextHeader + "<style>"
            SongTextHeader = SongTextHeader + "body { background-color: #555555;} "
            SongTextHeader = SongTextHeader + "p { font-size: " + SongPreferences[
                'DEFAULTFONTSIZE'] + "px; margin: 0px;} "
            SongTextHeader = SongTextHeader + "table { width: 100%; border: 2px solid black; padding 20px;} "
            SongTextHeader = SongTextHeader + "tr { width: 100%; border: 2px solid black; padding 20px;} "
            SongTextHeader = SongTextHeader + "td { border: 2px solid black; padding 5px; background-color: #eeeeee;} "
            SongTextHeader = SongTextHeader + "</style>"
            SongTextHeader = SongTextHeader + "</head>"
            SongTextHeader = SongTextHeader + "<body>"

            OutputSongText = "<table><tr><td>"

            OutputSongText = OutputSongText + Derive_Song_Text(
                "YES", SongText, SongKey, SongOffset)

            #   SongText is in 'SongText' variable - chords are defined with lines beginning with '.'
            #   First, split the string on newlines.

            #SongTextLines = SongText.split('\n')

            #   Now, go through the lines...

            #Ptr2 = 0

            #SongTextLineNumber = 0

            # Work through all the lines of text
            #while Ptr2 < (len(SongTextLines)-1):

            # Put the line we're working with into a working variable
            #    TextLine = SongTextLines[Ptr2]

            # If its not a blank line
            #    if len(TextLine) > 0:

            # is it a command line?
            #        if TextLine[0] == '.':

            #   Line begins with '.' - it contains chords - need to work through letter by letter

            #            Ptr3 = 0    # pointer into the text line
            #            OutputLine = ''   # converted line

            # Create a temp line with extra spaces at the end - so we don't read past the end of line.
            #            TempLine = TextLine + "   "

            #            while Ptr3 < len( TextLine ):

            #                NewValue = ord(TextLine[Ptr3])

            #                if 65 <= NewValue <= 71:
            # This is a key value

            # Get the chord
            #                    NewString = TextLine[Ptr3]

            # Check: is this a minor or sharp?
            #                    if (TempLine[Ptr3+1] == 'M') or (TempLine[Ptr3+1] == '#') or (TempLine[Ptr3+1] == 'b'):
            #                        NewString = NewString+TextLine[Ptr3+1]
            #                        Ptr3 = Ptr3+1
            # Check: is this a minor or sharp?
            #                        if (TempLine[Ptr3+1] == 'M') or (TempLine[Ptr3+1] == '#') or (TempLine[Ptr3+1] == 'b'):
            #                            NewString = NewString+TextLine[Ptr3+1]
            #                            Ptr3 = Ptr3+1

            # NewString now contains the chord - convert it...
            #                    UpdatedChord = self.ConvertChord(NewString,SongOffset)

            #                    OutputLine = OutputLine+UpdatedChord

            #                else:
            #                    OutputLine = OutputLine+TextLine[Ptr3]

            #                Ptr3 = Ptr3+1

            # Now put bold around it..
            #            OutputLine = "<b>"+OutputLine+"</b>"
            #        else:
            #            OutputLine = TextLine
            #    else:
            # its a blank line
            #        OutputLine = '\n '

            # If we're too far down, go to another display column
            #    if SongTextLineNumber > int(self.SongPreferences['DEFAULTPAGESIZE']) or "===" in TextLine:
            #        SongTextLineNumber = 1
            #        OutputLine = OutputLine+'</td><td>'
            # print("NewLine")

            #    TextLine = "<p>"+OutputLine+"&nbsp;&nbsp;&nbsp;&nbsp;</p>"

            #    SongText = SongText+'\n'+TextLine

            #    Ptr2 = Ptr2+1
            #    SongTextLineNumber = SongTextLineNumber+1

            SongLyricsDisplay = OutputSongText.replace('\n.', '<b> ').replace(
                '\n ', '</b> ').replace(' ', '&nbsp;')

            SongLyricsDisplay = SongLyricsDisplay.replace('SUS', 'sus')

            SongLyricsDisplay = SongLyricsDisplay.replace(
                '[', '<b><font color='
                'red'
                '>[').replace(']', ']</font></b>')

            SongLyricsDisplay = SongTextHeader + SongLyricsDisplay + '</td></tr></table></body></html>'

            # print(SongLyricsDisplay)

            self.SongText.setText(SongLyricsDisplay)
            self.CurrentKey.setText(SongKeys_Alt[ActualSongKey])

    #   User has clicked on a song on the on-screen list - display the song.
    def SongListSelected(self, index):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        #   This is the selected song...
        SelectedString = index.data()

        self.DisplaySong(SelectedString)

    #   Remove a song from the song list on screen
    def DelSelectedSong(self):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        # del the currently selected song - i.e. 'self.CurrentSong'

        Result = self.AskQuery("Remove Song from list?",
                               "Delete " + self.CurrentSong)

        if Result == "YES":
            # Yes - delete the item in the on-screen list
            listItems = self.SongList.selectedIndexes()
            if not listItems:
                return
            for item in listItems:
                self.SongListModel.removeRow(item.row())

            Ptr = self.LocateSong(self.CurrentSong)

            if Ptr >= 0:
                ToRemove = SongDataList[Ptr]
                SongDataList.remove(ToRemove)

            print("Removed: " + self.CurrentSong)

    #   Clear the song list on-screen and data structure
    def ClearAll(self):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        Result = self.AskQuery("Clear Songlist?", "Clear Songlist?")

        if Result == "YES":
            self.SongListModel.clear()
            SongDataList = []

            print("Cleared")

    #   Save a specific song name from the data structure to a song file
    #   Save the file in 'OpenSong' format (xml)
    def SaveSong(self, SongName):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        #   Locate the given song
        Ptr = self.LocateSong(self.CurrentSong)

        if Ptr >= 0:
            #   Get the data about the song
            SingleSongData = SongDataList[Ptr]

            #   Get the default song location and add the song name
            Fname = self.SongLocation + '/' + SongName

            #   Linux / windows
            if os.sep == '\\':
                Fname = Fname.replace('/', '\\')

            # 0.4: Open the original song we're going to overwrite
            #      and grab the data from it - so that we preserve
            #      the information when we overwrite
            #      if the song is 'brand new' then we'll not be able
            #      to open, and should go through the exception handler
            #      and we can set default values.

            # If the file already exists, read the file in and overwrite
            # individual elements
            # otherwise create a file from scratch.
            if os.path.isfile(Fname):

                try:
                    with open(Fname, 'r') as Originalfile:
                        SongData = Originalfile.read()

                    # tree contains the tree structure
                    tree = ET.ElementTree(ET.fromstring(SongData))

                    # Overwrite the items within the XML...
                    tree.find('title').text = SingleSongData[4]
                    tree.find('lyrics').text = SingleSongData[1]
                    tree.find('key').text = SingleSongData[2]

                    # overwrite the original file with the updated values
                    tree.write(Fname)

                except:

                    self.OkMessage("Problem overwriting file...",
                                   sys.exc_info()[0])

            else:

                # the file doesn't exist - so we need to create a new file from scratch

                #   Work out the text to save.
                New_FileName = Fname
                New_SongText = '<?xml version="1.0" encoding="UTF-8"?>\n'
                New_SongText = New_SongText + '<song>\n'
                New_SongText = New_SongText + '<title>' + SingleSongData[
                    4] + '</title>\n'
                New_SongText = New_SongText + '  <lyrics>'
                New_SongText = New_SongText + SingleSongData[1] + '\n'
                New_SongText = New_SongText + '  </lyrics>\n'
                New_SongText = New_SongText + '<author></author>\n'
                New_SongText = New_SongText + '<copyright></copyright>\n'
                New_SongText = New_SongText + '<hymn_number></hymn_number>\n'
                New_SongText = New_SongText + '<presentation></presentation>\n'
                New_SongText = New_SongText + '<ccli></ccli>\n'
                New_SongText = New_SongText + '<capo print = "false"></capo>\n'
                New_SongText = New_SongText + '<key>' + SingleSongData[
                    2] + '</key>\n'
                New_SongText = New_SongText + '<aka></aka>\n'
                New_SongText = New_SongText + '<key_line></key_line>\n'
                New_SongText = New_SongText + '<user1></user1>\n'
                New_SongText = New_SongText + '<user2></user2>\n'
                New_SongText = New_SongText + '<user3></user3>\n'
                New_SongText = New_SongText + '<theme></theme>\n'
                New_SongText = New_SongText + '<linked_songs></linked_songs>\n'
                New_SongText = New_SongText + '<tempo></tempo>\n'
                New_SongText = New_SongText + '<time_sig></time_sig>\n'
                New_SongText = New_SongText + '<backgrounds resize="body" keep_aspect="false" link="false" background_as_text="false"/>\n'
                New_SongText = New_SongText + '</song>\n'

                #   and write out the file
                with open(New_FileName, 'w') as myfile:
                    myfile.write(New_SongText)

    #   User has clicked on 'Edit'
    def EditCurrentSong(self):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        #   Locate the song
        Ptr = self.LocateSong(self.CurrentSong)

        if Ptr > -1:
            SingleSongData = SongDataList[Ptr]

            #   Initialise and show the song
            dlg = EditWindow(SingleSongData)

            #   Activate the window on screen
            if dlg.exec_():
                print("Success!")
                #   Copy the song data to the main data structure
                SongDataList[Ptr][
                    0] = self.SongLocation + '/' + dlg.ui.FName.text()
                SongDataList[Ptr][1] = dlg.ui.SongText.toPlainText()
                SongDataList[Ptr][2] = dlg.ui.SongKey.currentText()
                SongDataList[Ptr][3] = 0
                SongDataList[Ptr][4] = dlg.ui.FName.text()
                self.DisplaySong(self.CurrentSong)
                self.SaveSong(self.CurrentSong)
                print('Edited song saved')
            else:
                print("Cancel!")

    #   User has selected to add a new song
    def NewSong(self):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        # Create a blank song
        SingleSongData = ['a', 'a', 'a', 0, 'a']
        SingleSongData[0] = self.SongLocation + '/New Song'
        SingleSongData[1] = '.C\n Words'
        SingleSongData[2] = 'C'
        SingleSongData[3] = 0
        SingleSongData[4] = 'New Song'

        # Initialise the edit window
        dlg = EditWindow(SingleSongData)

        # Activate the edit window
        if dlg.exec_():
            print("Success!")
            SingleSongData[0] = self.SongLocation + '/' + dlg.ui.FName.text()
            SingleSongData[1] = dlg.ui.SongText.toPlainText()
            SingleSongData[2] = dlg.ui.SongKey.currentText()
            SingleSongData[3] = 0
            SingleSongData[4] = dlg.ui.FName.text()

            #   Up to this point its the same as edit - however, now we need to add the
            #   new song to the on-screen list, and display.
            SongDataList.append(SingleSongData)
            self.CurrentSong = SingleSongData[4]
            item = QStandardItem(self.CurrentSong)
            self.SongListModel.appendRow(item)
            self.DisplaySong(self.CurrentSong)
            self.SaveSong(self.CurrentSong)
        else:
            print("Cancel!")

    #   User has selected to add a song to the list
    def AddNewSong(self):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        #   get the user to select a song.
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        fileName = QFileDialog.getOpenFileName(self, 'Open file',
                                               self.SongLocation,
                                               'OpenFile(*)')

        if fileName and len(fileName[0]) > 0:

            #   If Windows, change the separator
            FName = fileName[0]
            #   windows/linux
            if os.sep == '\\':
                FName = FName.replace('/', '\\')
            FName = FName.replace(self.SongLocation + '\\', '')
            item = QStandardItem(os.path.basename(FName))
            self.SongListModel.appendRow(item)

            #   Read in the song data, to add to the list...

            print("reading file...")

            with open(FName, 'r') as myfile:
                SongData = myfile.read()

            print("getting data")

            tree = ET.ElementTree(ET.fromstring(SongData))

            #   Interpret the XML into the main data structure
            print("getting lyrics")

            SongLyrics = list(tree.iter('lyrics'))

            print("getting key")

            KeyData = tree.find('key')

            if KeyData is None:
                SongKeyValue = 'C'
            else:
                SongKey = list(tree.iter('key'))
                if SongKey[0].text is None:
                    SongKeyValue = 'C'
                else:
                    SongKeyValue = SongKey[0].text

            print("create list element")
            # Create list element, SongName, LyricsText, Key, OffsetToKey
            print("Filename:" + FName)
            print("Lyrics:" + SongLyrics[0].text)
            print("Key:" + SongKeyValue)

            # Data structure
            # 0 - full file and path name
            # 1 - lyrics text
            # 2 - Base key
            # 3 - Offset
            # 4 - Basename (just the file name)
            NewSongData = [
                FName, SongLyrics[0].text, SongKeyValue, 0,
                os.path.basename(FName)
            ]

            print("append into songdata")
            SongDataList.append(NewSongData)
            print("added")

            self.SaveSongList()

    def CleanString(self, InputString):

        OutputString = ""
        for Ptr in range(0, len(InputString)):
            if InputString[
                    Ptr] in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ()[]=:-":
                OutputString += InputString[Ptr]

        return OutputString

    #   User has selected to edit prefs
    def UpdatePrefs(self):

        global SongDataList
        global SongKeys
        global SongKeys_Alt
        global SongPreferences

        #   Initialise window
        dlg = Prefs()

        #   Activate preferences screen
        if dlg.exec_():
            print("Success!")

            #   Pick up the values from screen
            SongPreferences['PREFSVER'] = '0.5'
            SongPreferences['SONGDIR'] = dlg.ui.SongDirectory.text()

            SongPreferences[
                'DEFAULTFONTSIZE'] = dlg.ui.DefaultFontSize.currentText()
            SongPreferences['DEFAULTPAGESIZE'] = dlg.ui.PageSize.currentText()

            if dlg.ui.radioButton_Cs.isChecked():
                SongPreferences['SHARPFLAT_C'] = 'C#'
            else:
                SongPreferences['SHARPFLAT_C'] = 'Db'

            if dlg.ui.radioButton_Ds.isChecked():
                SongPreferences['SHARPFLAT_D'] = 'D#'
            else:
                SongPreferences['SHARPFLAT_D'] = 'Eb'

            if dlg.ui.radioButton_Fs.isChecked():
                SongPreferences['SHARPFLAT_F'] = 'F#'
            else:
                SongPreferences['SHARPFLAT_F'] = 'Gb'

            if dlg.ui.radioButton_Gs.isChecked():
                SongPreferences['SHARPFLAT_G'] = 'G#'
            else:
                SongPreferences['SHARPFLAT_G'] = 'Ab'

            if dlg.ui.radioButton_As.isChecked():
                SongPreferences['SHARPFLAT_A'] = 'A#'
            else:
                SongPreferences['SHARPFLAT_A'] = 'Bb'

            #   0.5 20210402 - edit using original key or transposed key
            if dlg.ui.EditOriginalKey.isChecked():
                SongPreferences['EDIT_USE_ORIGINALKEY'] = 'ORIGINALKEY'
            else:
                SongPreferences['EDIT_USE_ORIGINALKEY'] = 'TRANSPOSEDKEY'

            with open(self.SongPreferencesFileName, 'w') as f:
                json.dump(SongPreferences, f)

            # Set up preference variables.
            self.InterpretPreferences()

        else:
            print("Cancel!")

    def AboutWindow(self):
        #   Initialise window
        dlg = AboutWindow()

        #   Activate preferences screen - user just has to click on OK
        dlg.exec_()
Example #53
0
class Window(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        #fix stuff imposible to do in qtdesigner
        #remove dock titlebar for addressbar
        w = QWidget()
        self.ui.addrDockWidget.setTitleBarWidget(w)
        #tabify some docks
        self.tabifyDockWidget(self.ui.evDockWidget, self.ui.subDockWidget)
        self.tabifyDockWidget(self.ui.subDockWidget, self.ui.refDockWidget)

        # init widgets
        self.ui.statusBar.hide()
        self.ui.addrComboBox.insertItem(-1, "opc.tcp://localhost:4841/")
        self.ui.addrComboBox.insertItem(
            1, "opc.tcp://localhost:53530/OPCUA/SimulationServer/")
        self.ui.addrComboBox.insertItem(1, "opc.tcp://10.0.5.15:49320/")

        self.attr_model = QStandardItemModel()
        self.refs_model = QStandardItemModel()
        self.sub_model = QStandardItemModel()
        self.ui.attrView.setModel(self.attr_model)
        self.ui.refView.setModel(self.refs_model)
        self.ui.subView.setModel(self.sub_model)

        self.model = MyModel(self)
        self.model.clear()
        self.model.error.connect(self.show_error)
        self.ui.treeView.setModel(self.model)
        self.ui.treeView.setUniformRowHeights(True)
        self.ui.treeView.setSelectionBehavior(QAbstractItemView.SelectRows)

        self.uaclient = UaClient()
        self.ui.connectButton.clicked.connect(self._connect)
        self.ui.disconnectButton.clicked.connect(self._disconnect)
        self.ui.treeView.activated.connect(self._show_attrs_and_refs)
        self.ui.treeView.clicked.connect(self._show_attrs_and_refs)
        self.ui.treeView.expanded.connect(self._fit)

        self.ui.actionSubscribeDataChange.triggered.connect(self._subscribe)
        self.ui.actionSubscribeEvent.triggered.connect(self._subscribeEvent)
        self.ui.actionConnect.triggered.connect(self._connect)
        self.ui.actionDisconnect.triggered.connect(self._disconnect)

        self.ui.attrRefreshButton.clicked.connect(self.show_attrs)

        # context menu
        self.ui.treeView.addAction(self.ui.actionSubscribeDataChange)
        self.ui.treeView.addAction(self.ui.actionSubscribeEvent)
        self.ui.treeView.addAction(self.ui.actionUnsubscribe)

        # handle subscriptions
        self._subhandler = SubHandler(self.sub_model)

    def show_error(self, msg, level=1):
        print("showing error: ", msg, level)
        self.ui.statusBar.show()
        self.ui.statusBar.setStyleSheet(
            "QStatusBar { background-color : red; color : black; }")
        #self.ui.statusBar.clear()
        self.ui.statusBar.showMessage(str(msg))
        QTimer.singleShot(1500, self.ui.statusBar.hide)

    def _fit(self, idx):
        self.ui.treeView.resizeColumnToContents(0)

    def _subscribeEvent(self):
        self.showError("Not Implemented")

    def _subscribe(self):
        idx = self.ui.treeView.currentIndex()
        it = self.model.itemFromIndex(idx)
        if not id:
            self.show_error("No item currently selected")
        node = it.data()
        attrs = self.uaclient.get_node_attrs(node)
        self.sub_model.setHorizontalHeaderLabels(
            ["DisplayName", "Browse Name", 'NodeId', "Value"])
        item = QStandardItem(attrs[1])
        self.sub_model.appendRow(
            [item, QStandardItem(attrs[2]),
             QStandardItem(attrs[3])])
        try:
            # FIXME use handle to unsubscribe!!!
            handle = self.uaclient.subscribe(node, self._subhandler)
        except Exception as ex:
            self.show_error(ex)
            idx = self.sub_model.indexFromItem(item)
            self.sub_model.takeRow(idx.row())

    def unsubscribe(self):
        idx = self.ui.treeView.currentIndex()
        it = self.model.itemFromIndex(idx)
        if not id:
            print("No item currently selected")
        node = it.data()
        self.uaclient.unsubscribe(node)

    def _show_attrs_and_refs(self, idx):
        node = self.get_current_node(idx)
        if node:
            self._show_attrs(node)
            self._show_refs(node)

    def get_current_node(self, idx=None):
        if idx is None:
            idx = self.ui.treeView.currentIndex()
        it = self.model.itemFromIndex(idx)
        if not it:
            return None
        node = it.data()
        if not node:
            print("No node for item:", it, it.text())
            return None
        return node

    def show_attrs(self):
        node = self.get_current_node()
        if node:
            self._show_attrs(node)
        else:
            self.attr_model.clear()

    def _show_refs(self, node):
        self.refs_model.clear()
        self.refs_model.setHorizontalHeaderLabels(
            ['ReferenceType', 'NodeId', "BrowseName", "TypeDefinition"])
        try:
            refs = self.uaclient.get_all_refs(node)
        except Exception as ex:
            self.show_error(ex)
            raise
        for ref in refs:
            self.refs_model.appendRow([
                QStandardItem(str(ref.ReferenceTypeId)),
                QStandardItem(str(ref.NodeId)),
                QStandardItem(str(ref.BrowseName)),
                QStandardItem(str(ref.TypeDefinition))
            ])
        self.ui.refView.resizeColumnToContents(0)
        self.ui.refView.resizeColumnToContents(1)
        self.ui.refView.resizeColumnToContents(2)
        self.ui.refView.resizeColumnToContents(3)

    def _show_attrs(self, node):
        try:
            attrs = self.uaclient.get_all_attrs(node)
        except Exception as ex:
            self.show_error(ex)
            raise
        self.attr_model.clear()
        self.attr_model.setHorizontalHeaderLabels(['Attribute', 'Value'])
        for k, v in attrs.items():
            self.attr_model.appendRow(
                [QStandardItem(k), QStandardItem(str(v))])
        self.ui.attrView.resizeColumnToContents(0)
        self.ui.attrView.resizeColumnToContents(1)

    def _connect(self):
        uri = self.ui.addrComboBox.currentText()
        try:
            self.uaclient.connect(uri)
        except Exception as ex:
            self.show_error(ex)
            raise

        self.model.client = self.uaclient
        self.model.clear()
        self.model.add_item(self.uaclient.get_root_attrs())
        self.ui.treeView.resizeColumnToContents(0)
        self.ui.treeView.resizeColumnToContents(1)
        self.ui.treeView.resizeColumnToContents(2)

    def _disconnect(self):
        try:
            self.uaclient.disconnect()
        except Exception as ex:
            self.show_error(ex)
            raise
        finally:
            self.model.clear()
            self.sub_model.clear()
            self.model.client = None

    def closeEvent(self, event):
        self._disconnect()
        event.accept()
Example #54
0
class QWTree(QTreeView):
    """Widget for tree
    """
    dic_smodes = {
        'single': QAbstractItemView.SingleSelection,
        'contiguous': QAbstractItemView.ContiguousSelection,
        'extended': QAbstractItemView.ExtendedSelection,
        'multi': QAbstractItemView.MultiSelection,
        'no selection': QAbstractItemView.NoSelection
    }

    def __init__(self, parent=None):

        QTreeView.__init__(self, parent)
        #self._name = self.__class__.__name__

        icon.set_icons()

        self.model = QStandardItemModel()
        self.set_selection_mode()

        self.fill_tree_model()  # defines self.model

        self.setModel(self.model)
        self.setAnimated(True)

        self.set_style()
        self.show_tool_tips()

        self.expanded.connect(self.on_item_expanded)
        self.collapsed.connect(self.on_item_collapsed)
        #self.model.itemChanged.connect(self.on_item_changed)
        self.connect_item_selected_to(self.on_item_selected)
        self.clicked[QModelIndex].connect(self.on_click)
        #self.doubleClicked[QModelIndex].connect(self.on_double_click)

    def set_selection_mode(self, smode='extended'):
        logger.debug('Set selection mode: %s' % smode)
        mode = self.dic_smodes[smode]
        self.setSelectionMode(mode)

    def connect_item_selected_to(self, recipient):
        self.selectionModel().currentChanged[QModelIndex,
                                             QModelIndex].connect(recipient)

    def disconnect_item_selected_from(self, recipient):
        self.selectionModel().currentChanged[QModelIndex,
                                             QModelIndex].disconnect(recipient)

    def selected_indexes(self):
        return self.selectedIndexes()

    def selected_items(self):
        indexes = self.selectedIndexes()
        return [self.model.itemFromIndex(i) for i in self.selectedIndexes()]

    def clear_model(self):
        rows = self.model.rowCount()
        self.model.removeRows(0, rows)

    def fill_tree_model(self):
        self.clear_model()
        for k in range(0, 4):
            parentItem = self.model.invisibleRootItem()
            parentItem.setIcon(icon.icon_folder_open)
            for i in range(0, k):
                item = QStandardItem('itemA %s %s' % (k, i))
                item.setIcon(icon.icon_table)
                item.setCheckable(True)
                parentItem.appendRow(item)
                item = QStandardItem('itemB %s %s' % (k, i))
                item.setIcon(icon.icon_folder_closed)
                parentItem.appendRow(item)
                parentItem = item
                logger.debug('append item %s' % (item.text()))

    def on_item_expanded(self, ind):
        item = self.model.itemFromIndex(ind)  # get QStandardItem
        if item.hasChildren():
            item.setIcon(icon.icon_folder_open)
        #msg = 'on_item_expanded: %s' % item.text()
        #logger.debug(msg)

    def on_item_collapsed(self, ind):
        item = self.model.itemFromIndex(ind)
        if item.hasChildren():
            item.setIcon(icon.icon_folder_closed)
        #msg = 'on_item_collapsed: %s' % item.text()
        #logger.debug(msg)

    def on_item_selected(self, selected, deselected):
        itemsel = self.model.itemFromIndex(selected)
        if itemsel is not None:
            parent = itemsel.parent()
            parname = parent.text() if parent is not None else None
            msg = 'selected item: %s row: %d parent: %s' % (
                itemsel.text(), selected.row(), parname)
            logger.debug(msg)

        #itemdes = self.model.itemFromIndex(deselected)
        #if itemdes is not None :
        #    msg = 'on_item_selected row: %d deselected %s' % (deselected.row(), itemdes.text())
        #    logger.debug(msg)

    def on_item_changed(self, item):
        state = ['UNCHECKED', 'TRISTATE', 'CHECKED'][item.checkState()]
        msg = 'on_item_changed: item "%s", is at state %s' % (item.text(),
                                                              state)
        logger.debug(msg)

    def on_click(self, index):
        item = self.model.itemFromIndex(index)
        parent = item.parent()
        spar = parent.text() if parent is not None else None
        msg = 'clicked item: %s parent: %s' % (item.text(), spar
                                               )  # index.row()
        logger.debug(msg)

    def on_double_click(self, index):
        item = self.model.itemFromIndex(index)
        msg = 'on_double_click item in row:%02d text: %s' % (index.row(),
                                                             item.text())
        logger.debug(msg)

    #--------------------------
    #--------------------------

    def process_expand(self):
        logger.debug('process_expand')
        #self.model.set_all_group_icons(self.icon_expand)
        self.expandAll()
        #self.tree_view_is_expanded = True

    def process_collapse(self):
        logger.debug('process_collapse')
        #self.model.set_all_group_icons(self.icon_collapse)
        self.collapseAll()
        #self.tree_view_is_expanded = False

    #def expand_collapse(self):
    #    if self.isExpanded() : self.collapseAll()
    #    else                 : self.expandAll()

    #--------------------------
    #--------------------------
    #--------------------------

    def show_tool_tips(self):
        self.setToolTip('Tree model')

    def set_style(self):
        self.header().hide()
        #from psana.graphqt.Styles import style
        self.setWindowIcon(icon.icon_monitor)
        self.setContentsMargins(0, 0, 0, 0)
        self.setStyleSheet("QTreeView::item:hover{background-color:#00FFAA;}")

    #def resizeEvent(self, e):
    #pass
    #self.frame.setGeometry(self.rect())
    #logger.debug('resizeEvent')

    #def moveEvent(self, e):
    #logger.debug('moveEvent')
    #self.position = self.mapToGlobal(self.pos())
    #self.position = self.pos()
    #logger.debug('moveEvent - pos:' + str(self.position), __name__)
    #pass

    def closeEvent(self, e):
        logger.debug('closeEvent')
        QTreeView.closeEvent(self, e)
        #try    : self.gui_win.close()
        #except : pass

        #try    : del self.gui_win
        #except : pass

    def on_exit(self):
        logger.debug('on_exit')
        self.close()

    if __name__ == "__main__":

        def key_usage(self):
            return 'Keys:'\
                   '\n  ESC - exit'\
                   '\n  E - expand'\
                   '\n  C - collapse'\
                   '\n'

        def keyPressEvent(self, e):
            #logger.debug('keyPressEvent, key = %s'%e.key())
            if e.key() == Qt.Key_Escape:
                self.close()

            elif e.key() == Qt.Key_E:
                self.process_expand()

            elif e.key() == Qt.Key_C:
                self.process_collapse()

            else:
                logger.debug(self.key_usage())
Example #55
0
 def clear(self):
     QStandardItemModel.clear(self)
     self._fetched = []
     self.setHorizontalHeaderLabels(['Name', "Browse Name", 'NodeId'])
Example #56
0
    def initUI(self):

        self.srvList = ["", "opcUA", "modbusTCP"]

        if (os.name == 'nt'):

            self.appPath = os.path.abspath(sys.argv[0]).replace(
                os.path.basename(__file__), '')
            self.imgPath = self.appPath + "img\\"
            self.dbPath = self.appPath + "db\\webDb.db"
            #import self.appPath+srvconf

        else:
            self.appPath = os.path.abspath(sys.argv[0]).replace(
                os.path.basename(__file__), '')
            self.imgPath = self.appPath + "img/"
            self.dbPath = self.appPath + "db/webDb.db"

        self.versionPr = 'ScadaPy Web JSON Сервер v.3.14'
        self.setGeometry(300, 100, 1500, 820)
        self.setWindowTitle(self.versionPr)
        self.setWindowIcon(QIcon(self.imgPath + 'Globe.png'))
        self.h = self.frameGeometry().height()
        self.w = self.frameGeometry().width()
        self.setStyleSheet("background-color: #FFF8E7;")

        font = QFont()
        font.setPointSize(12)

        self.label0 = QLabel(self)
        self.label0.setFont(font)
        self.label0.move(400, 60)
        self.label0.resize(300, 25)
        self.label0.setText("ID сервера")
        self.label00 = QLabel(self)
        self.label00.setFont(font)
        self.label00.move(550, 60)
        self.label00.resize(300, 25)
        self.label00.setText("")

        self.label1 = QLabel(self)
        self.label1.setFont(font)
        self.label1.move(400, 90)
        self.label1.resize(140, 25)
        self.label1.setText("Название сервера")
        self.srvName = QLineEdit(self)
        self.srvName.setToolTip('Пример: Сервер Маш.Зала №1')
        self.srvName.move(550, 90)
        self.srvName.setFont(font)
        self.srvName.resize(300, 25)

        self.label2 = QLabel(self)
        self.label2.setFont(font)
        self.label2.move(400, 120)
        self.label2.resize(140, 25)
        self.label2.setText("Http IP address")
        self.slaveIP = QLineEdit(self)
        self.slaveIP.setToolTip('Пример: 192.168.0.111')
        self.slaveIP.move(550, 120)
        self.slaveIP.setFont(font)
        self.slaveIP.resize(300, 25)

        self.label2 = QLabel(self)
        self.label2.setFont(font)
        self.label2.move(400, 150)
        self.label2.resize(140, 25)
        self.label2.setText("Http Port")
        self.slavePort = QLineEdit(self)
        self.slavePort.setToolTip('Пример : 8080')
        self.slavePort.move(550, 150)
        self.slavePort.setFont(font)
        self.slavePort.resize(100, 25)

        self.label7 = QLabel(self)
        self.label7.setFont(font)
        self.label7.move(680, 150)
        self.label7.resize(140, 25)
        self.label7.setText("Timeout")

        self.serverTimeout = QLineEdit(self)
        self.serverTimeout.setToolTip('Пример ms: 1 ')
        self.serverTimeout.move(750, 150)
        self.serverTimeout.setFont(font)
        self.serverTimeout.resize(100, 25)

        self.label8 = QLabel(self)
        self.label8.setFont(font)
        self.label8.move(400, 180)
        self.label8.resize(140, 25)
        self.label8.setText("Login")
        self.serverLogin = QLineEdit(self)
        self.serverLogin.setToolTip('Имя пользователя')
        self.serverLogin.move(550, 180)
        self.serverLogin.setFont(font)
        self.serverLogin.resize(100, 25)

        self.label9 = QLabel(self)
        self.label9.setFont(font)
        self.label9.move(680, 180)
        self.label9.resize(140, 25)
        self.label9.setText("Password")
        self.serverPassword = QLineEdit(self)
        self.serverPassword.setToolTip('Пароль')
        self.serverPassword.move(750, 180)
        self.serverPassword.setFont(font)
        self.serverPassword.resize(100, 25)

        exitAction = QAction(QIcon(self.imgPath + 'exit.png'), '&Выход', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Выход из программы')
        exitAction.triggered.connect(qApp.quit)

        addServerAction = QAction(QIcon(self.imgPath + 'add.png'), '&Добавить',
                                  self)
        addServerAction.setStatusTip('Добавить сервер')
        addServerAction.triggered.connect(self.addNewServer)

        delServerAction = QAction(QIcon(self.imgPath + 'button_cancel.png'),
                                  '&Удалить', self)
        delServerAction.setStatusTip('Удалить сервер')
        delServerAction.triggered.connect(self.delServer)

        saveServerAction = QAction(QIcon(self.imgPath + 'filesave.png'),
                                   '&Сохранить', self)
        saveServerAction.setStatusTip('Сохранить сервер')
        saveServerAction.triggered.connect(self.saveServer)

        saveScr = QAction(QIcon(self.imgPath + 'bottom.png'),
                          '&Сохранить скрипт', self)
        saveScr.setStatusTip('Сохранить скрипт')
        saveScr.triggered.connect(self.saveScr)

        runScr = QAction(QIcon(self.imgPath + 'run.png'), '&Запустить скрипт',
                         self)
        runScr.setStatusTip('Запустить скрипт')
        runScr.triggered.connect(self.runScr)

        runConf = QAction(QIcon(self.imgPath + 'app.png'),
                          '&Запустить конфигуратор', self)
        runConf.setStatusTip('Запустить конфигуратор')
        runConf.triggered.connect(self.runConf)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&Команды')
        fileMenu.addAction(addServerAction)
        fileMenu.addAction(delServerAction)
        fileMenu.addAction(saveServerAction)
        fileMenu.addAction(saveScr)
        fileMenu.addAction(runScr)
        fileMenu.addAction(exitAction)

        self.toolbar = self.addToolBar('Выход')
        self.toolbar.addAction(exitAction)
        self.toolbar.addAction(addServerAction)
        self.toolbar.addAction(delServerAction)
        self.toolbar.addAction(saveServerAction)
        self.toolbar.addAction(saveScr)
        self.toolbar.addAction(runScr)
        self.toolbar.addAction(runConf)

        # self.statusBar().showMessage('Загрузка данных')

        self.treeView = QTreeView(self)
        self.treeView.setFont(font)
        self.treeView.setObjectName("treeView")
        self.model = QStandardItemModel()
        self.treeView.setModel(self.model)
        self.treeView.setStyleSheet("background-color: white;")
        self.header = ['Название сервера']
        self.model.setHorizontalHeaderLabels(self.header)

        self.sqlLoad()
        self.treeView.clicked.connect(self.onClickItem)

        self.frameTable = QFrame(self)
        self.frameTable.setVisible(True)

        self.addRow = QPushButton(self.frameTable)
        self.addRow.setIcon(QIcon(self.imgPath + 'add.png'))
        self.addRow.move(10, 10)
        self.addRow.resize(30, 30)
        self.addRow.clicked.connect(self.addItemTree)

        self.saveTable = QPushButton(self.frameTable)
        self.saveTable.setIcon(QIcon(self.imgPath + 'filesave.png'))
        self.saveTable.resize(30, 30)
        self.saveTable.move(50, 10)
        self.saveTable.clicked.connect(self.saveData)

        ####################################################################

        self.treeTable = QTableWidget(self.frameTable)
        self.treeTable.setStyleSheet("background-color: white;")
        fontTable = QFont()
        fontTable.setPointSize(10)
        self.treeTable.setFont(fontTable)

        #        self.show()
        self.showMaximized()
Example #57
0
    def setupTab1(self, tab1):
        """Basic widgets for preview panel"""
        scrollContainer = QVBoxLayout()
        scrollArea = QScrollArea()
        scrollArea.setWidgetResizable(True)
        mainWidget = QWidget()
        layout = QVBoxLayout()
        mainWidget.setLayout(layout)
        mainWidget.setMinimumSize(QSize(420, 800))
        scrollArea.setWidget(mainWidget)
        scrollContainer.addWidget(scrollArea)
        tab1.setLayout(scrollContainer)

        # Label TextBox
        group1 = QGroupBox("Text")
        group1.setCheckable(True)
        group1layout = QHBoxLayout()
        group1.setLayout(group1layout)
        layout.addWidget(group1)
        layoutCol1 = QFormLayout()
        layoutCol2 = QFormLayout()
        group1layout.addLayout(layoutCol1)
        group1layout.addLayout(layoutCol2)

        label1 = QLabel(self.tr("User Name(&Id):"))
        text1 = QLineEdit("default")
        label1.setBuddy(text1)
        label2 = QLabel(self.tr("data 1:"))
        text2 = QLineEdit()
        text2.setPlaceholderText(self.tr("input"))
        lebel3 = QLabel(self.tr("<b>Pasword</b>:"))
        text3 = QLineEdit("******")
        text3.setEchoMode(QLineEdit.Password)
        label4 = QLabel(self.tr("link label:"))
        label5 = QLabel(
            self.
            tr("<a href='https://github.com/hustlei/'>github.com/hustlei</a>"))
        label5.setOpenExternalLinks(True)
        label6 = QLabel(self.tr("icon label:"))
        label7 = QLabel("icon")
        label7.setPixmap(QPixmap(":appres.img/book_address.png"))
        layoutCol1.addRow(label1, text1)
        layoutCol1.addRow(label2, text2)
        layoutCol1.addRow(lebel3, text3)
        layoutCol1.addRow(label4, label5)
        layoutCol1.addRow(label6, label7)

        text4 = QLineEdit()
        text4.setInputMask("0000-00-00")
        text5 = QLineEdit()
        text5.setInputMask("HH:HH:HH:HH:HH:HH;_")
        text6 = QLineEdit()
        text6.setInputMask("XXXXXX")
        text7 = QLineEdit()
        validator1 = QDoubleValidator()
        validator1.setRange(0, 100)
        validator1.setDecimals(2)
        text7.setValidator(validator1)
        text8 = QLineEdit()
        validator2 = QRegExpValidator()
        reg = QRegExp("[a-zA-Z0-9]+$")
        validator2.setRegExp(reg)
        text8.setValidator(validator2)
        layoutCol2.addRow(self.tr("Date Mask:"), text4)
        layoutCol2.addRow(self.tr("Mac Mask"), text5)
        layoutCol2.addRow(self.tr("String Mask"), text6)
        layoutCol2.addRow(self.tr("Double Validate:"), text7)
        layoutCol2.addRow(self.tr("Regexp Validate:"), text8)

        text9 = QLineEdit()
        text9.setPlaceholderText("input email")
        text9.setToolTip("please input a email address.")
        model = QStandardItemModel(0, 1, self)
        completer = QCompleter(model, self)
        text9.setCompleter(completer)

        def textch(texts):
            if "@" in texts:
                return
            strList = [
                "@163.com", "@qq.com", "@gmail.com", "@hotmail.com", "@126.com"
            ]
            model.removeRows(0, model.rowCount())
            for i in strList:
                model.insertRow(0)
                model.setData(model.index(0, 0), texts + i)

        text9.textChanged.connect(textch)
        text10 = QLineEdit("ReadOnly")
        text10.setReadOnly(True)
        layoutCol1.addRow(self.tr("auto complete:"), text9)
        layoutCol2.addRow("Readonly:", text10)

        # Button
        group2 = QGroupBox("Button")
        group2.setCheckable(True)
        group2layout = QVBoxLayout()
        group2.setLayout(group2layout)
        layout.addWidget(group2)
        layoutRow1 = QHBoxLayout()
        layoutRow2 = QHBoxLayout()
        group2layout.addLayout(layoutRow1)
        group2layout.addLayout(layoutRow2)

        btn1 = QPushButton("Button")
        btn2 = QPushButton("IconBtn")
        btn2.setIcon(QIcon(":appres.img/yes.png"))
        btn3 = QPushButton("Disabled")
        btn3.setEnabled(False)
        btn4 = QPushButton("Default")
        btn4.setDefault(True)

        btn5 = QPushButton("Switch")
        btn5.setCheckable(True)
        btn6 = QToolButton()
        # btn6.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        btn6.setText("ToolButton")
        btn6.setPopupMode(QToolButton.MenuButtonPopup)
        m = QMenu()
        m.addAction("action1")
        m.addAction("action2")
        m.addAction("action3")
        btn6.setMenu(m)
        btn7 = QCommandLinkButton("LinkBtn")
        layoutRow1.addWidget(btn1)
        layoutRow1.addWidget(btn2)
        layoutRow1.addWidget(btn3)
        layoutRow1.addWidget(btn4)
        layoutRow2.addWidget(btn5)
        layoutRow2.addWidget(btn6)
        layoutRow2.addWidget(btn7)

        # Checkable Item
        group3 = QGroupBox("Checkable")
        group3Layout = QVBoxLayout()
        layoutRow1 = QHBoxLayout()
        layoutRow2 = QHBoxLayout()
        group3Layout.addLayout(layoutRow1)
        group3Layout.addLayout(layoutRow2)
        group3.setLayout(group3Layout)
        layout.addWidget(group3)

        group3.setCheckable(True)
        ch1 = QRadioButton("Radio")
        ch2 = QRadioButton("Iconradio")
        ch2.setIcon(QIcon(":appres.img/Flag_blueHS.png"))
        ch3 = QRadioButton("Iconradio")
        ch3.setIcon(QIcon(":appres.img/Flag_greenHS.png"))
        ch4 = QRadioButton("Disable")
        ch4.setEnabled(False)
        ch5 = QCheckBox("CheckBox")
        ch6 = QCheckBox("CheckBox")
        ch6.setIcon(QIcon(":appres.img/Flag_blueHS.png"))
        ch7 = QCheckBox("TriState")
        ch7.setTristate(True)
        ch7.setCheckState(Qt.PartiallyChecked)
        ch8 = QCheckBox("Disable")
        ch8.setEnabled(False)
        layoutRow1.addWidget(ch1)
        layoutRow1.addWidget(ch2)
        layoutRow1.addWidget(ch3)
        layoutRow1.addWidget(ch4)
        layoutRow2.addWidget(ch5)
        layoutRow2.addWidget(ch6)
        layoutRow2.addWidget(ch7)
        layoutRow2.addWidget(ch8)

        # Selecting Input
        group4 = QGroupBox("Selectable")
        group4.setCheckable(True)
        group4Layout = QVBoxLayout()
        layoutRow1 = QHBoxLayout()
        group4Layout.addLayout(layoutRow1)
        group4.setLayout(group4Layout)
        layout.addWidget(group4)

        s1 = QSpinBox()
        s1.setValue(50)
        s2 = QDoubleSpinBox()
        s2.setRange(0, 1)
        s2.setValue(0.5)
        s3 = QComboBox()
        s3.addItems(["aaa", "bbb", "ccc"])
        s3.setEditable(True)
        s3.setCurrentIndex(2)
        s4 = QComboBox()
        s4.addItems(["aaa", "bbb", "ccc"])
        layoutRow1.addWidget(s1)
        layoutRow1.addWidget(s2)
        layoutRow1.addWidget(s3)
        layoutRow1.addWidget(s4)

        # TextEdit
        group5 = QGroupBox("TextEdit")
        group5.setCheckable(True)
        group5Layout = QVBoxLayout()
        group5.setLayout(group5Layout)
        layout.addWidget(group5)

        group5Layout.addWidget(
            QTextEdit(
                self.
                tr("If you do not leave me, I will be by your side until the end."
                   )))

        layout.addStretch(1)
Example #58
0
    def __init__(self, parent=None):
        super(ContextPanel, self).__init__(parent=parent)

        self._app_window = parent
        self.setAutoFillBackground(True)

        self._nativectx_model = QStandardItemModel(0, 4)
        self._nativectx_model.setHeaderData(0, Qt.Horizontal, 'Reg')
        self._nativectx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                            Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._nativectx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(2, Qt.Horizontal, 'Decimal')
        #self._nativectx_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._nativectx_model.setHeaderData(3, Qt.Horizontal, 'Telescope')

        self._nativectx_list = DwarfListView()
        self._nativectx_list.setModel(self._nativectx_model)

        self._nativectx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._nativectx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._nativectx_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self._nativectx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._nativectx_list.customContextMenuRequested.connect(
            self._on_native_contextmenu)

        self._emulatorctx_model = QStandardItemModel(0, 3)
        self._emulatorctx_model.setHeaderData(0, Qt.Horizontal, 'Reg')
        self._emulatorctx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                              Qt.TextAlignmentRole)
        self._emulatorctx_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._emulatorctx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._emulatorctx_model.setHeaderData(2, Qt.Horizontal, 'Decimal')

        self._emulatorctx_list = DwarfListView()
        self._emulatorctx_list.setModel(self._emulatorctx_model)

        self._emulatorctx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._emulatorctx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)

        self._emulatorctx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._emulatorctx_list.customContextMenuRequested.connect(
            self._on_emulator_contextmenu)

        self._javactx_model = QStandardItemModel(0, 3)
        self._javactx_model.setHeaderData(0, Qt.Horizontal, 'Argument')
        self._javactx_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter,
                                          Qt.TextAlignmentRole)
        self._javactx_model.setHeaderData(1, Qt.Horizontal, 'Class')
        #self._javactx_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
        self._javactx_model.setHeaderData(2, Qt.Horizontal, 'Value')

        self._javactx_list = DwarfListView()
        self._javactx_list.setModel(self._javactx_model)

        self._javactx_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._javactx_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self._javactx_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self._javactx_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self._javactx_list.customContextMenuRequested.connect(
            self._on_java_contextmenu)

        self.addTab(self._nativectx_list, 'Native')
        self.show_context_tab('Native')
Example #59
0
class RequestList(MyTreeView):
    class Columns(IntEnum):
        DATE = 0
        DESCRIPTION = 1
        AMOUNT = 2
        STATUS = 3

    headers = {
        Columns.DATE: _('Date'),
        Columns.DESCRIPTION: _('Description'),
        Columns.AMOUNT: _('Amount'),
        Columns.STATUS: _('Status'),
    }
    filter_columns = [Columns.DATE, Columns.DESCRIPTION, Columns.AMOUNT]

    def __init__(self, parent: 'ElectrumWindow'):
        super().__init__(parent,
                         self.create_menu,
                         stretch_column=self.Columns.DESCRIPTION,
                         editable_columns=[])
        self.wallet = self.parent.wallet
        self.std_model = QStandardItemModel(self)
        self.proxy = MySortModel(self, sort_role=ROLE_SORT_ORDER)
        self.proxy.setSourceModel(self.std_model)
        self.setModel(self.proxy)
        self.setSortingEnabled(True)
        self.selectionModel().currentRowChanged.connect(self.item_changed)
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.update()

    def select_key(self, key):
        for i in range(self.model().rowCount()):
            item = self.model().index(i, self.Columns.DATE)
            row_key = item.data(ROLE_KEY)
            if key == row_key:
                self.selectionModel().setCurrentIndex(
                    item, QItemSelectionModel.SelectCurrent
                    | QItemSelectionModel.Rows)
                break

    def item_changed(self, idx: Optional[QModelIndex]):
        if idx is None:
            self.parent.receive_payreq_e.setText('')
            self.parent.receive_address_e.setText('')
            return
        if not idx.isValid():
            return
        # TODO use siblingAtColumn when min Qt version is >=5.11
        item = self.item_from_index(idx.sibling(idx.row(), self.Columns.DATE))
        key = item.data(ROLE_KEY)
        req = self.wallet.get_request(key)
        if req is None:
            self.update()
            return
        self.parent.receive_payreq_e.setText(
            self.parent.wallet.get_request_URI(req))
        self.parent.receive_address_e.setText(req.get_address())
        self.parent.receive_payreq_e.repaint()  # macOS hack (similar to #4777)
        self.parent.receive_address_e.repaint(
        )  # macOS hack (similar to #4777)

    def clearSelection(self):
        super().clearSelection()
        self.selectionModel().clearCurrentIndex()

    def refresh_status(self):
        m = self.std_model
        for r in range(m.rowCount()):
            idx = m.index(r, self.Columns.STATUS)
            date_idx = idx.sibling(idx.row(), self.Columns.DATE)
            date_item = m.itemFromIndex(date_idx)
            status_item = m.itemFromIndex(idx)
            key = date_item.data(ROLE_KEY)
            req = self.wallet.get_request(key)
            if req:
                status = self.parent.wallet.get_request_status(key)
                status_str = req.get_status_str(status)
                status_item.setText(status_str)
                status_item.setIcon(read_QIcon(pr_icons.get(status)))

    def update_item(self, key, invoice: Invoice):
        model = self.std_model
        for row in range(0, model.rowCount()):
            item = model.item(row, 0)
            if item.data(ROLE_KEY) == key:
                break
        else:
            return
        status_item = model.item(row, self.Columns.STATUS)
        status = self.parent.wallet.get_request_status(key)
        status_str = invoice.get_status_str(status)
        status_item.setText(status_str)
        status_item.setIcon(read_QIcon(pr_icons.get(status)))

    def update(self):
        # not calling maybe_defer_update() as it interferes with conditional-visibility
        self.parent.update_receive_address_styling()
        self.proxy.setDynamicSortFilter(
            False)  # temp. disable re-sorting after every change
        self.std_model.clear()
        self.update_headers(self.__class__.headers)
        for req in self.wallet.get_unpaid_requests():
            key = self.wallet.get_key_for_receive_request(req)
            status = self.parent.wallet.get_request_status(key)
            status_str = req.get_status_str(status)
            request_type = req.type
            timestamp = req.time
            amount = req.get_amount_sat()
            message = req.message
            date = format_time(timestamp)
            amount_str = self.parent.format_amount(amount) if amount else ""
            labels = [date, message, amount_str, status_str]
            icon = read_QIcon("zcashcoin.png")
            tooltip = 'onchain request'
            items = [QStandardItem(e) for e in labels]
            self.set_editability(items)
            items[self.Columns.DATE].setData(request_type, ROLE_REQUEST_TYPE)
            items[self.Columns.DATE].setData(key, ROLE_KEY)
            items[self.Columns.DATE].setData(timestamp, ROLE_SORT_ORDER)
            items[self.Columns.DATE].setIcon(icon)
            items[self.Columns.STATUS].setIcon(read_QIcon(
                pr_icons.get(status)))
            items[self.Columns.DATE].setToolTip(tooltip)
            self.std_model.insertRow(self.std_model.rowCount(), items)
        self.filter()
        self.proxy.setDynamicSortFilter(True)
        # sort requests by date
        self.sortByColumn(self.Columns.DATE, Qt.DescendingOrder)
        # hide list if empty
        if self.parent.isVisible():
            b = self.std_model.rowCount() > 0
            self.setVisible(b)
            self.parent.receive_requests_label.setVisible(b)
            if not b:
                # list got hidden, so selected item should also be cleared:
                self.item_changed(None)

    def create_menu(self, position):
        items = self.selected_in_column(0)
        if len(items) > 1:
            keys = [item.data(ROLE_KEY) for item in items]
            menu = QMenu(self)
            menu.addAction(_("Delete requests"),
                           lambda: self.parent.delete_requests(keys))
            menu.exec_(self.viewport().mapToGlobal(position))
            return
        idx = self.indexAt(position)
        # TODO use siblingAtColumn when min Qt version is >=5.11
        item = self.item_from_index(idx.sibling(idx.row(), self.Columns.DATE))
        if not item:
            return
        key = item.data(ROLE_KEY)
        req = self.wallet.get_request(key)
        if req is None:
            self.update()
            return
        menu = QMenu(self)
        self.add_copy_menu(menu, idx)
        URI = self.wallet.get_request_URI(req)
        menu.addAction(_("Copy Request"),
                       lambda: self.parent.do_copy(URI, title='Zcash URI'))
        menu.addAction(
            _("Copy Address"),
            lambda: self.parent.do_copy(req.get_address(),
                                        title='Zcash Address'))
        #if 'view_url' in req:
        #    menu.addAction(_("View in web browser"), lambda: webopen(req['view_url']))
        menu.addAction(_("Delete"), lambda: self.parent.delete_requests([key]))
        run_hook('receive_list_menu', self.parent, menu, key)
        menu.exec_(self.viewport().mapToGlobal(position))
Example #60
0
class CForm(QWidget):

    statSignal = pyqtSignal()  # 更新窗口状态的信号
    sendSignal = pyqtSignal(dict)  # 发送数据的信号

    def __init__(self, ur):
        super().__init__()
        self.ur = ur
        self.clist_num = 0  # 本机文件数量
        self.slist_num = 0  # 服务器文件数量

        self.initUI()

    # 绘制主界面
    def initUI(self):
        mainLayout = QVBoxLayout()

        grid1 = QGridLayout()
        grid1.setSpacing(10)

        # 消息框
        self.msgbox = QTextBrowser()
        self.msgbox.setReadOnly(True)
        self.msgbox.append(info)
        grid1.addWidget(self.msgbox, 0, 0, 1, 4)

        # 发送消息框
        self.input = QLineEdit()
        self.send_msg = QPushButton('发送')
        grid1.addWidget(self.input, 1, 0, 1, 3)
        grid1.addWidget(self.send_msg, 1, 3, 1, 1)
        self.send_msg.clicked.connect(self.sendMsg)

        # 消息发送板块
        msgGroupBox = QGroupBox('消息发送')
        msgGroupBox.setLayout(grid1)

        # 文件传输板块
        fileGroupBox = QGroupBox('文件传输')
        grid2 = QGridLayout()
        grid2.setSpacing(10)

        # 选择工作文件夹
        lbw = QLabel('文件夹:')
        self.fpath = QLineEdit('./cfile')
        sel_f = QPushButton('选择文件夹')
        grid2.addWidget(lbw, 2, 0, 1, 1)
        grid2.addWidget(self.fpath, 2, 1, 1, 3)
        grid2.addWidget(sel_f, 2, 4, 1, 1)
        sel_f.clicked.connect(self.showDialog)

        # 展示本机文件列表
        lbcf = QLabel('本机文件:')
        self.cflist = QListView()
        self.cmodel = QStandardItemModel(self.cflist)
        grid2.addWidget(lbcf, 4, 0, 1, 2)
        grid2.addWidget(self.cflist, 5, 0, 8, 2)

        # 展示服务器文件列表
        lbsf = QLabel('服务器文件:')
        self.sflist = QListView()
        self.smodel = QStandardItemModel(self.sflist)
        grid2.addWidget(lbsf, 4, 3, 1, 2)
        grid2.addWidget(self.sflist, 5, 3, 8, 2)

        # 添加操作按钮
        self.bsend = QToolButton()
        self.brec = QToolButton()
        self.bsend.setArrowType(Qt.RightArrow)
        self.brec.setArrowType(Qt.LeftArrow)
        self.brec.setEnabled(False)
        self.bsend.setEnabled(False)
        grid2.addWidget(self.bsend, 7, 2, 1, 1)
        grid2.addWidget(self.brec, 9, 2, 1, 1)
        self.bsend.clicked.connect(
            lambda: self.getList(self.cmodel, self.clist_num, 'sendf'))
        self.brec.clicked.connect(
            lambda: self.getList(self.smodel, self.slist_num, 'dwnf'))

        self.cmodel.itemChanged.connect(
            lambda: self.onChanged(self.clist_num, self.bsend))
        self.smodel.itemChanged.connect(
            lambda: self.onChanged(self.slist_num, self.brec))

        # 添加进度条
        self.pro = QProgressBar()
        grid2.addWidget(self.pro, 13, 0, 1, 5)

        fileGroupBox.setLayout(grid2)

        mainLayout.addWidget(msgGroupBox)
        mainLayout.addWidget(fileGroupBox)

        self.setLayout(mainLayout)

        self.resize(640, 640)

    # 跳出文件夹选择对话框
    def showDialog(self):
        upath = QFileDialog.getExistingDirectory(self, '选择文件夹', '.')
        if not upath:
            upath = './cfile'
        self.fpath.setText(upath)
        self.upCList(upath)

    # 更新客户端文件列表
    def upCList(self, upath):
        self.cmodel.clear()
        f_list = [f for f in listdir(upath) if isfile(join(upath, f))]
        self.clist_num = len(f_list)
        for fname in f_list:
            item = QStandardItem()
            item.setText(fname)
            item.setCheckable(True)
            self.cmodel.appendRow(item)  # 将新文件添加进视图中

        self.cflist.setModel(self.cmodel)

    # 更新服务器文件列表
    def upSList(self, slist):
        self.smodel.clear()
        self.slist_num = len(slist)
        for fname in slist:
            item = QStandardItem()
            item.setText(fname)
            item.setCheckable(True)
            self.smodel.appendRow(item)  # 将新文件添加进视图中

        self.sflist.setModel(self.smodel)

    # 获取用户选择的文件列表
    def getList(self, model, num, tp):
        path = self.fpath.text()
        # 遍历整个视图
        for i in range(num):
            data = {'type': tp, 'cnt': {'ur': self.ur}}
            data['cnt']['path'] = path

            item = model.item(i)
            # 如果该选项被选中
            if item and item.checkState() == 2:
                fname = item.text()
                data['cnt']['fname'] = fname
                if tp == 'sendf':
                    fsize = getsize(path + '/' + fname)
                    # 判断是否为空文件
                    if fsize > 0:
                        data['cnt']['fsize'] = fsize
                    else:
                        # 空文件报错
                        self.statSignal.emit(fname + '为空文件,无法发送!')
                        continue
                self.sendSignal.emit(data)

    # 设置发送下载按钮的可以状态
    def onChanged(self, num, btn):
        sender = self.sender()
        flag = False
        for i in range(num):
            item = sender.item(i)
            if item and item.checkState() == 2:
                flag = True

        btn.setEnabled(flag)

    # 设置进度条最大值
    def setProMax(self, num):
        self.pro.setMaximum(num)

    # 更新进度条
    def upPro(self, num):
        self.pro.setValue(num)

    # 发送信息
    def sendMsg(self):
        now = time.strftime('%H:%M:%S')
        msg = self.input.text()
        self.msgbox.append('%-15s: %-40s' %
                           ('本机(' + now + ')', msg))  # 将信息在对话框中显示
        data = {'type': 'msg', 'cnt': {'ur': self.ur, 'msg': msg}}  # 封装发送的数据
        self.sendSignal.emit(data)
        self.input.clear()

    # 显示服务器的信息
    def showMsg(self, msg):
        now = time.strftime('%H:%M:%S')
        self.msgbox.append('%-15s: %-40s' % ('服务器(' + now + ')', msg))