Exemplo n.º 1
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)
Exemplo n.º 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))
Exemplo n.º 3
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)
Exemplo n.º 4
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))])
Exemplo n.º 5
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
Exemplo n.º 6
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"]
Exemplo n.º 7
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
Exemplo n.º 8
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)
Exemplo n.º 9
0
Arquivo: main.py Projeto: 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)
 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()
Exemplo n.º 11
0
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()
Exemplo n.º 12
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)
Exemplo n.º 13
0
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)
Exemplo n.º 14
0
class EventUI(object):

    def __init__(self, window, uaclient):
        self.window = window
        self.uaclient = uaclient
        self._handler = EventHandler()
        self._subscribed_nodes = []  # FIXME: not really needed
        self.model = QStandardItemModel()
        self.window.ui.evView.setModel(self.model)
        self.window.ui.actionSubscribeEvent.triggered.connect(self._subscribe)
        self.window.ui.actionUnsubscribeEvents.triggered.connect(self._unsubscribe)
        # context menu
        self.window.ui.treeView.addAction(self.window.ui.actionSubscribeEvent)
        self.window.ui.treeView.addAction(self.window.ui.actionUnsubscribeEvents)
        self._handler.event_fired.connect(self._update_event_model, type=Qt.QueuedConnection)

    def clear(self):
        self._subscribed_nodes = []
        self.model.clear()

    def _subscribe(self):
        node = self.window.get_current_node()
        if node is None:
            return
        if node in self._subscribed_nodes:
            print("allready subscribed to event for node: ", node)
            return
        self.window.ui.evDockWidget.raise_()
        try:
            self.uaclient.subscribe_events(node, self._handler)
        except Exception as ex:
            self.window.show_error(ex)
            raise
        else:
            self._subscribed_nodes.append(node)

    def _unsubscribe(self):
        node = self.window.get_current_node()
        if node is None:
            return
        self._subscribed_nodes.remove(node)
        self.uaclient.unsubscribe_events(node)

    def _update_event_model(self, event):
        self.model.appendRow([QStandardItem(str(event))])
Exemplo n.º 15
0
class TagChooser(QListView):
	changed = Signal()

	def __init__(self, db):
		super(TagChooser,self).__init__()
		self.db = db

		self.filter = u''

		self.data = QStandardItemModel()
		self.proxy = QSortFilterProxyModel()
		self.proxy.setSourceModel(self.data)
		self.setModel(self.proxy)

		self.data.itemChanged.connect(self.changed)
		for t in sorted(self.db.list_tags()):
			item = QStandardItem(t)
			item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
			item.setCheckState(Qt.Unchecked)
			self.data.appendRow(item)

	def setTags(self, tags):
		for i in range(self.data.rowCount()):
			item = self.data.item(i)
			if item.text() in tags:
				item.setCheckState(Qt.Checked)
			else:
				item.setCheckState(Qt.Unchecked)

	def selectedTags(self):
		tags = []
		for i in range(self.data.rowCount()):
			item = self.data.item(i)
			if item.checkState() == Qt.Checked:
				tags.append(item.text())
		return tags

	def matchingFiles(self):
		tags = self.selectedTags()

		if not tags:
			return []
		res = list(self.db.find_files_by_tags(tags))
		res.sort()
		return res
class viewTable(QDialog):   
    def __init__(self, parent=None):
        fileName = filedialog.askopenfilename()
        if fileName != '':
            k = fileName.rfind("/")
            self.parent = parent
            self.parent.statusbar.showMessage("Opening dataset...")
            QWidget.__init__(self,parent)
            self.setWindowFlags(Qt.Window)
            self.setObjectName("dialog1")
            self.setGeometry(100,100,400,400)
            self.setWindowTitle(fileName[k+1:])
            self.setWindowIcon(QIcon('NSlogo.png'))
            self.model = QStandardItemModel(self)
            
            with open(fileName, "r") as fileInput:
                for row in csv.reader(fileInput, delimiter='\t'):    
                    items = [
                        QStandardItem(field)
                        for field in row
                    ]
                    self.model.appendRow(items)
        
            self.tableView = QTableView(self)
            self.tableView.setModel(self.model)

            self.layoutVertical = QVBoxLayout(self)
            self.layoutVertical.addWidget(self.tableView)

            self.parent = parent

            self.showMaximized()
            self.show()
            
            self.parent.ui.logOutput.append("VIEWED:")
            print("VIEWED:")
            self.parent.ui.logOutput.append("      " + str(fileName.split('/')[-1]))
            print("      " + str(fileName.split('/')[-1]))

    def closeEvent(self, event):
        self.model.clear()
        self.parent.ui.logOutput.append("")
        self.parent.statusbar.showMessage("Welcome back!")
Exemplo n.º 17
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:
            typename = ua.ObjectIdNames[ref.ReferenceTypeId.Identifier]
            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()
            self.model.appendRow([QStandardItem(typename),
                                  QStandardItem(nodeid),
                                  QStandardItem(ref.BrowseName.to_string()),
                                  QStandardItem(typedef)
                                  ])
Exemplo n.º 18
0
    def initUI(self):

        Model=QStandardItemModel()
        Model.setColumnCount(3)
        Model.setHorizontalHeaderLabels(["clmn1","clmn2","clmn3"])
        Model.appendRow([QStandardItem(11),QStandardItem(12),QStandardItem(13)])
        Model.appendRow([QStandardItem(21),QStandardItem(22),QStandardItem(23)])

        Table=QTableView(self)
        Table.setModel(Model)
        ButDeleg=ButtonDelegate(Table)
        Table.setItemDelegateForColumn(1,ButDeleg)
        TXTDelegate=PlainTextEditDelegate()
        Table.setItemDelegateForColumn(0,TXTDelegate)
        ButDeleg.clicked.connect(self.Prnt)

        mainLayout = QVBoxLayout()
        mainLayout.setContentsMargins(0,0,0,0)
        mainLayout.addWidget(Table)
        self.setLayout(mainLayout)
Exemplo n.º 19
0
class RefsWidget(QObject):

    error = pyqtSignal(str)

    def __init__(self, view):
        self.view = view
        QObject.__init__(self, view)
        self.model = QStandardItemModel()
        self.view.setModel(self.model)
        self.view.horizontalHeader().setSectionResizeMode(1)

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

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

    def _show_refs(self, node):
        self.model.setHorizontalHeaderLabels(['ReferenceType', 'NodeId', "BrowseName", "TypeDefinition"])
        try:
            refs = node.get_children_descriptions(refs=ua.ObjectIds.References)
        except Exception as ex:
            self.error.emit(ex)
            raise
        for ref in refs:
            typename = ua.ObjectIdNames[ref.ReferenceTypeId.Identifier]
            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()
            self.model.appendRow([QStandardItem(typename),
                                  QStandardItem(nodeid),
                                  QStandardItem(ref.BrowseName.to_string()),
                                  QStandardItem(typedef)
                                 ])
Exemplo n.º 20
0
    def analyzePhrase(self):
        root = self.mw.mdlOutline.rootItem
        nMin = self.spnPhraseMin.value()
        nMax = self.spnPhraseMax.value()

        def listPhrases(item, nMin, nMax):
            txt = item.text()

            # Split into words
            lst = re.findall(r"[\w']+", txt)            # Ignores punctuation
            # lst = re.findall(r"[\w']+|[.,!?;]", txt)  # Includes punctuation
            phrases = []

            # Make tuples of n-length
            for n in range(nMin, nMax + 1):
                for l in range(len(lst) - n + 1):
                    phrases.append(tuple(lst[l:l+n]))

            for c in item.children():
                phrases += listPhrases(c, nMin, nMax)

            return phrases

        lst = listPhrases(root, nMin, nMax)

        # Count
        count = Counter(lst)

        # Showing
        mdl = QStandardItemModel()
        mdl.setHorizontalHeaderLabels([self.tr("Phrases"), self.tr("Frequency")])
        for i in count.most_common():
            word = QStandardItem(" ".join(i[0]))
            number = QStandardItem()
            number.setData(i[1], Qt.DisplayRole)
            if i[1] > 1:
                mdl.appendRow([word, number])

        self.tblPhrase.setModel(mdl)
Exemplo n.º 21
0
    def reset(self):
        # Either way, we are going to replace the model.
        model = QStandardItemModel()
        self.groupsListView.setModel(model)

        if self.obj:
            # Reset to the original area
            area = self.obj

            # Set the window title
            self.setWindowTitle("Edit {} (Area)".format(area.name))

            # Set the name line edit
            self.nameLineEdit.setText(area.name)

            for g in area.groups:
                model.appendRow(GroupItem(g))

        else:
            # Set the defaults
            self.setWindowTitle("Create Area")
            self.nameLineEdit.setText("")
Exemplo n.º 22
0
    def analyzeWord(self):
        root = self.mw.mdlOutline.rootItem

        exclude = self.txtWordExclude.toPlainText().split(",")
        exclude = [e.strip().lower() for e in exclude]

        def listWords(item):
            txt = item.text()

            lst = re.findall(r"[\w']+", txt)
            for c in item.children():
                lst += listWords(c)

            return lst

        lst = listWords(root)
        lst2 = []

        # Cleaning
        for i in lst:
            if len(i) >= self.spnWordMin.value() and not i.lower() in exclude:
                lst2.append(i.lower())

        # Count
        count = Counter(lst2)

        # Showing
        mdl = QStandardItemModel()
        mdl.setHorizontalHeaderLabels([self.tr("Word"), self.tr("Frequency")])
        for i in count.most_common():
            word = QStandardItem(i[0])
            number = QStandardItem()
            number.setData(i[1], Qt.DisplayRole)
            mdl.appendRow([word, number])

        self.tblWord.setModel(mdl)
Exemplo n.º 23
0
class LinklistWidget(QListView):
    
    resultSelected = pyqtSignal(str)

    def __init__(self, parent):
        QListView.__init__(self, parent)

        self.resultListModel = QStandardItemModel(self)
        self.setModel(self.resultListModel)
        self.selectionModel().selectionChanged.connect(self.doItemSelected)

    def doItemSelected(self, selectedtItem, idx2):
        indexes = selectedtItem.indexes()
        if len(indexes) == 1:
            item = self.resultListModel.itemFromIndex(indexes[0])
            pageId = item.text()
            self.resultSelected.emit(pageId)

    def setContents(self, linkList):
        self.resultListModel.clear()
        for item in linkList:
            resultItem = QStandardItem(item)
            resultItem.setEditable(False)
            self.resultListModel.appendRow(resultItem)
Exemplo n.º 24
0
class DataChangeUI(object):
    def __init__(self, window, uaclient):
        self.window = window
        self.uaclient = uaclient
        self._subhandler = DataChangeHandler()
        self._subscribed_nodes = []
        self.model = QStandardItemModel()
        self.window.ui.subView.setModel(self.model)
        self.window.ui.subView.horizontalHeader().setSectionResizeMode(1)

        self.window.ui.actionSubscribeDataChange.triggered.connect(
            self._subscribe)
        self.window.ui.actionUnsubscribeDataChange.triggered.connect(
            self._unsubscribe)

        # populate contextual menu
        self.window.addAction(self.window.ui.actionSubscribeDataChange)
        self.window.addAction(self.window.ui.actionUnsubscribeDataChange)

        # handle subscriptions
        self._subhandler.data_change_fired.connect(
            self._update_subscription_model, type=Qt.QueuedConnection)

        # accept drops
        self.model.canDropMimeData = self.canDropMimeData
        self.model.dropMimeData = self.dropMimeData

    def canDropMimeData(self, mdata, action, row, column, parent):
        return True

    def dropMimeData(self, mdata, action, row, column, parent):
        node = self.uaclient.client.get_node(mdata.text())
        self._subscribe(node)
        return True

    def clear(self):
        self._subscribed_nodes = []
        self.model.clear()

    def show_error(self, *args):
        self.window.show_error(*args)

    @trycatchslot
    def _subscribe(self, node=None):
        if not isinstance(node, SyncNode):
            node = self.window.get_current_node()
            if node is None:
                return
        if node in self._subscribed_nodes:
            logger.warning("allready subscribed to node: %s ", node)
            return
        self.model.setHorizontalHeaderLabels(
            ["DisplayName", "Value", "Timestamp"])
        text = str(node.read_display_name().Text)
        row = [
            QStandardItem(text),
            QStandardItem("No Data yet"),
            QStandardItem("")
        ]
        row[0].setData(node)
        self.model.appendRow(row)
        self._subscribed_nodes.append(node)
        self.window.ui.subDockWidget.raise_()
        try:
            self.uaclient.subscribe_datachange(node, self._subhandler)
        except Exception as ex:
            self.window.show_error(ex)
            idx = self.model.indexFromItem(row[0])
            self.model.takeRow(idx.row())
            raise

    @trycatchslot
    def _unsubscribe(self):
        node = self.window.get_current_node()
        if node is None:
            return
        self.uaclient.unsubscribe_datachange(node)
        self._subscribed_nodes.remove(node)
        i = 0
        while self.model.item(i):
            item = self.model.item(i)
            if item.data() == node:
                self.model.removeRow(i)
            i += 1

    def _update_subscription_model(self, node, value, timestamp):
        i = 0
        while self.model.item(i):
            item = self.model.item(i)
            if item.data() == node:
                it = self.model.item(i, 1)
                it.setText(value)
                it_ts = self.model.item(i, 2)
                it_ts.setText(timestamp)
            i += 1
Exemplo n.º 25
0
class QmyMainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.setCentralWidget(self.ui.qSplitter)
        self.__ColCount = 6
        self.itemModel = QStandardItemModel(5, self.__ColCount, self)
        self.selectionModel = QItemSelectionModel(self.itemModel)
        self.selectionModel.currentChanged.connect(self.do_curChanged)

        self.__lastColumnTitle = "测井取样"
        self.__lastColumnFlags = (Qt.ItemIsSelectable | Qt.ItemIsUserCheckable
                                  | Qt.ItemIsEnabled)

        self.ui.qTableView.setModel(self.itemModel)
        self.ui.qTableView.setSelectionModel(self.selectionModel)

        oneOrMore = QAbstractItemView.ExtendedSelection
        self.ui.qTableView.setSelectionMode(oneOrMore)

        itemOrRow = QAbstractItemView.SelectItems
        self.ui.qTableView.setSelectionBehavior(itemOrRow)

        self.ui.qTableView.verticalHeader().setDefaultSectionSize(22)
        self.ui.qTableView.setAlternatingRowColors(True)

        self.ui.qTableView.setEnabled(False)

        self.qLabel1 = QLabel("当前单元格:", self)
        self.qLabel1.setMinimumWidth(180)
        self.qLabel2 = QLabel("单元格内容:", self)
        self.qLabel2.setMinimumWidth(150)
        self.qLabel3 = QLabel("当前文件:", self)
        self.ui.qStatusBar.addWidget(self.qLabel1)
        self.ui.qStatusBar.addWidget(self.qLabel2)
        self.ui.qStatusBar.addPermanentWidget(self.qLabel3)

    def __iniModelFromStringList(self, allLines):
        rowCnt = len(allLines)
        self.itemModel.setRowCount(rowCnt - 1)
        headerText = allLines[0].strip()
        headerList = headerText.split("\t")
        self.itemModel.setHorizontalHeaderLabels(headerList)
        self.__lastColumnTitle = headerList[len(headerList) - 1]
        lastColNo = self.__ColCount - 1
        for i in range(rowCnt - 1):
            lineText = allLines[i + 1].strip()
            strList = lineText.split("\t")
            for j in range(self.__ColCount - 1):
                item = QStandardItem(strList[j])
                self.itemModel.setItem(i, j, item)

            item = QStandardItem(self.__lastColumnTitle)
            item.setFlags(self.__lastColumnFlags)
            item.setCheckable(True)
            if (strList[lastColNo] == "0"):
                item.setCheckState(Qt.Unchecked)
            else:
                item.setCheckState(Qt.Checked)
            self.itemModel.setItem(i, lastColNo, item)

    def __setCellAlignment(self, align=Qt.AlignHCenter):
        if (not self.selectionModel.hasSelection()):
            return
        selectedIndex = self.selectionModel.selectedIndexes()
        count = len(selectedIndex)
        for i in range(count):
            index = selectedIndex[i]
            item = self.itemModel.itemFromIndex(index)
            item.setTextAlignment(align)

    @pyqtSlot()
    def on_qAction1_triggered(self):  # 打开文件
        curPath = os.getcwd()
        filename, flt = QFileDialog.getOpenFileName(
            self, "打开一个文件", curPath, "井斜数据文件(*.txt);;所有文件(*.*)")
        if (filename == ""):
            return
        self.qLabel3.setText("当前文件:" + filename)
        self.ui.qPlainTextEdit.clear()
        aFile = open(filename, 'r')
        allLines = aFile.readlines()
        aFile.close()

        for strLine in allLines:
            self.ui.qPlainTextEdit.appendPlainText(strLine.strip())

        self.__iniModelFromStringList(allLines)
        self.ui.qTableView.setEnabled(True)
        self.ui.qAction2.setEnabled(True)
        self.ui.qAction3.setEnabled(True)
        self.ui.qAction4.setEnabled(True)
        self.ui.qAction5.setEnabled(True)
        self.ui.qAction6.setEnabled(True)

    @pyqtSlot()
    def on_qAction2_triggered(self):  # 另存文件
        curPath = os.getcwd()
        filename, flt = QFileDialog.getSaveFileName(
            self, "保存文件", curPath, "井斜数据文件(*.txt);;所有文件(*.*)")
        if (filename == ""):
            return
        self.on_qAction3_triggered()
        aFile = open(filename, "w")
        aFile.write(self.ui.qPlainTextEdit.toPlainText())
        aFile.close()

    @pyqtSlot()
    def on_qAction4_triggered(self):  # 添加行
        itemList = []
        for i in range(self.__ColCount - 1):
            item = QStandardItem("0")
            itemList.append(item)

        item = QStandardItem(self.__lastColumnTitle)
        item.setCheckable(True)
        item.setFlags(self.__lastColumnFlags)
        itemList.append(item)

        self.itemModel.appendRow(itemList)
        curIndex = self.itemModel.index(self.itemModel.rowCount() - 1, 0)
        self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(curIndex,
                                            QItemSelectionModel.Select)

    @pyqtSlot()
    def on_qAction5_triggered(self):  # 插入行
        itemlist = []
        for i in range(self.__ColCount - 1):
            item = QStandardItem("0")
            itemlist.append(item)

        item = QStandardItem(self.__lastColumnTitle)
        item.setFlags(self.__lastColumnFlags)
        item.setCheckable(True)
        item.setCheckState(Qt.Checked)
        itemlist.append(item)

        curIndex = self.selectionModel.currentIndex()
        self.itemModel.insertRow(curIndex.row(), itemlist)
        self.selectionModel.clearSelection()
        self.selectionModel.setCurrentIndex(curIndex,
                                            QItemSelectionModel.Select)

    @pyqtSlot()
    def on_qAction6_triggered(self):  # 删除行
        curIndex = self.selectionModel.currentIndex()
        self.itemModel.removeRow(curIndex.row())

    @pyqtSlot()
    def on_qAction7_triggered(self):  # 居左
        self.__setCellAlignment(Qt.AlignLeft | Qt.AlignVCenter)

    @pyqtSlot()
    def on_qAction8_triggered(self):  # 居中
        self.__setCellAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

    @pyqtSlot()
    def on_qAction9_triggered(self):  # 居右
        self.__setCellAlignment(Qt.AlignRight | Qt.AlignVCenter)

    @pyqtSlot(bool)
    def on_qAction10_triggered(self, checked):  # 粗体
        if (not self.selectionModel.hasSelection()):
            return
        selectedIndex = self.selectionModel.selectedIndexes()
        count = len(selectedIndex)
        for i in range(count):
            index = selectedIndex[i]
            item = self.itemModel.itemFromIndex(index)
            font = item.font()
            font.setBold(checked)
            item.setFont(font)

    @pyqtSlot()
    def on_qAction3_triggered(self):  # 模型数据
        self.ui.qPlainTextEdit.clear()
        lineStr = ""
        for i in range(self.itemModel.columnCount() - 1):
            item = self.itemModel.horizontalHeaderItem(i)
            lineStr = lineStr + item.text() + "\t"
        item = self.itemModel.horizontalHeaderItem(self.__ColCount - 1)
        lineStr = lineStr + item.text()
        self.ui.qPlainTextEdit.appendPlainText(lineStr)

        for i in range(self.itemModel.rowCount()):
            lineStr = ""
            for j in range(self.itemModel.columnCount() - 1):
                item = self.itemModel.item(i, j)
                lineStr = lineStr + item.text() + "\t"
            item = self.itemModel.item(i, self.__ColCount - 1)
            if (item.checkState() == Qt.Checked):
                lineStr = lineStr + "1"
            else:
                lineStr = lineStr + "0"
            self.ui.qPlainTextEdit.appendPlainText(lineStr)

    def do_curChanged(self, current, previous):
        if (current != None):
            text = "当前单元格:%d行,%d列" % (current.row(), current.column())
            self.qLabel1.setText(text)
            item = self.itemModel.itemFromIndex(current)
            self.qLabel2.setText("单元格内容:" + item.text())
            font = item.font()
            self.ui.qAction10.setChecked(font.bold())
Exemplo n.º 26
0
class VistaListaPrenotazioni(QWidget):
    def __init__(self, parent=None):
        super(VistaListaPrenotazioni, self).__init__(parent)

        self.controller = ControllerListaPrenotazioni()

        h_layout = QHBoxLayout()
        self.list_view = QListView()
        self.update_ui()
        h_layout.addWidget(self.list_view)

        buttons_layout = QVBoxLayout()
        open_button = QPushButton('Visualizza informazioni')
        open_button.setStyleSheet(
            'QPushButton {background-color: 	#E9CFEC ; color: black; border-style: outset;border-width: 6px;'
            'border-radius: 15px;border-color: #FA8072;padding: 6px}')
        open_button.clicked.connect(self.show_selected_info)
        buttons_layout.addWidget(open_button)
        new_button = QPushButton("Inserisci Prenotazione")
        new_button.setStyleSheet(
            'QPushButton {background-color: 	#C3FDB8; color: black; border-style: outset;border-width: 6px;'
            'border-radius: 15px;border-color: #3EB489;padding: 6px}')
        new_button.clicked.connect(self.visualizza_prenotazione)
        buttons_layout.addWidget(new_button)

        buttons_layout.addStretch()
        h_layout.addLayout(buttons_layout)

        self.setLayout(h_layout)
        self.resize(600, 300)
        self.setWindowTitle('Lista Prenotazioni')

    def update_ui(self):
        self.listview_model = QStandardItemModel(self.list_view)
        for prenotazione in self.controller.get_lista_delle_prenotazioni():
            item = QStandardItem()
            item.setText(prenotazione.cliente.cognome + " " +
                         prenotazione.cliente.nome)
            item.setEditable(False)
            font = item.font()
            font.setPointSize(18)
            item.setFont(font)
            self.listview_model.appendRow(item)
        self.list_view.setModel(self.listview_model)

    def show_selected_info(self):
        if len(self.list_view.selectedIndexes()) > 0:
            selected = self.list_view.selectedIndexes()[0].row()
            prenotazione_selezionata = self.controller.get_prenotazione_by_index(
                selected)
            self.vista_prenotazione = VistaPrenotazione(
                prenotazione_selezionata,
                self.controller.elimina_prenotazione_by_id, self.update_ui)
            self.vista_prenotazione.show()

    def visualizza_prenotazione(self):
        self.vista_inserisci_prenotazione = VistaInserisciPrenotazione(
            self.controller, self.update_ui)
        self.vista_inserisci_prenotazione.show()
        pass

    def closeEvent(self, event):
        self.controller.save_data()
Exemplo n.º 27
0
class ClientMainWindow(QMainWindow):
	"""
	Class is the main user window.
    Contains all the main logic of the client module.
    The window configuration is created in QTDesigner and loaded from
    converted file main_window_conv.py
	"""
	
	def __init__(self, database, transport, keys):
		super().__init__()
		# основные переменные
		self.database = database
		self.transport = transport
		
		# объект - дешифорвщик сообщений с предзагруженным ключём
		self.decrypter = PKCS1_OAEP.new(keys)
		
		# Загружаем конфигурацию окна из дизайнера
		self.ui = Ui_MainClientWindow()
		self.ui.setupUi(self)
		
		# Кнопка "Выход"
		self.ui.menu_exit.triggered.connect(qApp.exit)
		
		# Кнопка отправить сообщение
		self.ui.btn_send.clicked.connect(self.send_message)
		
		# "добавить контакт"
		self.ui.btn_add_contact.clicked.connect(self.add_contact_window)
		self.ui.menu_add_contact.triggered.connect(self.add_contact_window)
		
		# Удалить контакт
		self.ui.btn_remove_contact.clicked.connect(self.delete_contact_window)
		self.ui.menu_del_contact.triggered.connect(self.delete_contact_window)
		
		# Дополнительные требующиеся атрибуты
		self.contacts_model = None
		self.history_model = None
		self.messages = QMessageBox()
		self.current_chat = None
		self.current_chat_key = None
		self.encryptor = None
		self.ui.list_messages.setHorizontalScrollBarPolicy(
			Qt.ScrollBarAlwaysOff)
		self.ui.list_messages.setWordWrap(True)
		
		# Даблклик по листу контактов отправляется в обработчик
		self.ui.list_contacts.doubleClicked.connect(self.select_active_user)
		
		self.clients_list_update()
		self.set_disabled_input()
		self.show()
	
	def set_disabled_input(self):
		"""
		Method making input fields inactive
		:return:
		"""
		# Надпись  - получатель.
		self.ui.label_new_message.setText(
			'Для выбора получателя дважды кликните на нем в окне контактов.')
		self.ui.text_message.clear()
		if self.history_model:
			self.history_model.clear()
		
		# Поле ввода и кнопка отправки неактивны до выбора получателя.
		self.ui.btn_clear.setDisabled(True)
		self.ui.btn_send.setDisabled(True)
		self.ui.text_message.setDisabled(True)
		
		self.encryptor = None
		self.current_chat = None
		self.current_chat_key = None
	
	def history_list_update(self):
		"""
		The filling method of the corresponding QListView
        history of correspondence with the current interlocutor.
		:return:
		"""
		# Получаем историю сортированную по дате
		list = sorted(
			self.database.get_history(
				self.current_chat),
			key=lambda item: item[3])
		# Если модель не создана, создадим.
		if not self.history_model:
			self.history_model = QStandardItemModel()
			self.ui.list_messages.setModel(self.history_model)
		# Очистим от старых записей
		self.history_model.clear()
		# Берём не более 20 последних записей.
		length = len(list)
		start_index = 0
		if length > 20:
			start_index = length - 20
		# Заполнение модели записями, так-же стоит разделить входящие
		# и исходящие выравниванием и разным фоном.
		# отображает только последие 20 сообщений
		for i in range(start_index, length):
			item = list[i]
			if item[1] == 'in':
				mess = QStandardItem(
					f'Входящее от {item[3].replace(microsecond=0)}:\n {item[2]}')
				mess.setEditable(False)
				mess.setBackground(QBrush(QColor(255, 213, 213)))
				mess.setTextAlignment(Qt.AlignLeft)
				self.history_model.appendRow(mess)
			else:
				mess = QStandardItem(
					f'Исходящее от {item[3].replace(microsecond=0)}:\n {item[2]}')
				mess.setEditable(False)
				mess.setTextAlignment(Qt.AlignRight)
				mess.setBackground(QBrush(QColor(204, 255, 204)))
				self.history_model.appendRow(mess)
		self.ui.list_messages.scrollToBottom()
	
	def select_active_user(self):
		"""
		Double click event handler method on the contact list
		:return:
		"""
		# Выбранный пользователем (даблклик) находится в выделеном элементе в
		# QListView
		self.current_chat = self.ui.list_contacts.currentIndex().data()
		# вызываем основную функцию
		self.set_active_user()
	
	def set_active_user(self):
		"""
		A method for activating a chat with an interlocutor.
		:return:
		"""
		# Запрашиваем публичный ключ пользователя и создаём объект шифрования
		try:
			self.current_chat_key = self.transport.key_request(
				self.current_chat)
			client_log.debug(f'Загружен открытый ключ для {self.current_chat}')
			if self.current_chat_key:
				self.encryptor = PKCS1_OAEP.new(
					RSA.import_key(self.current_chat_key))
		except (OSError, json.JSONDecodeError):
			self.current_chat_key = None
			self.encryptor = None
			client_log.debug(f'Не удалось получить ключ для {self.current_chat}')
		
		# Если ключа нет то ошибка, что не удалось начать чат с пользователем
		if not self.current_chat_key:
			self.messages.warning(
				self, 'Ошибка', 'Для выбранного пользователя нет ключа шифрования.')
			return
		
		# Ставим надпись и активируем кнопки
		self.ui.label_new_message.setText(
			f'Введите сообщенние для {self.current_chat}:')
		self.ui.btn_clear.setDisabled(False)
		self.ui.btn_send.setDisabled(False)
		self.ui.text_message.setDisabled(False)
		
		# Заполняем окно историю сообщений по требуемому пользователю.
		self.history_list_update()
	
	def clients_list_update(self):
		"""
		Method for updating the contact list.
		:return:
		"""
		contacts_list = self.database.get_contacts()
		self.contacts_model = QStandardItemModel()
		for i in sorted(contacts_list):
			item = QStandardItem(i)
			item.setEditable(False)
			self.contacts_model.appendRow(item)
		self.ui.list_contacts.setModel(self.contacts_model)
	
	def add_contact_window(self):
		"""
		Method creating a window - a dialog for adding a contact
		:return:
		"""
		global select_dialog
		select_dialog = AddContactDialog(self.transport, self.database)
		select_dialog.btn_ok.clicked.connect(
			lambda: self.add_contact_action(select_dialog))
		select_dialog.show()
	
	def add_contact_action(self, item):
		"""
		Method to handle clicking the 'Add' button
		:param item:
		:return:
		"""
		new_contact = item.selector.currentText()
		self.add_contact(new_contact)
		item.close()
	
	def add_contact(self, new_contact):
		"""
		Method adding contact to server and client BD.
        After updating the databases, the contents of the window are also updated.
		:param new_contact:
		:return:
		"""
		try:
			self.transport.add_contact(new_contact)
		except ServerError as err:
			self.messages.critical(self, 'Ошибка сервера', err.text)
		except OSError as err:
			if err.errno:
				self.messages.critical(
					self, 'Ошибка', 'Потеряно соединение с сервером!')
				self.close()
			self.messages.critical(self, 'Ошибка', 'Таймаут соединения!')
		else:
			self.database.add_contact(new_contact)
			new_contact = QStandardItem(new_contact)
			new_contact.setEditable(False)
			self.contacts_model.appendRow(new_contact)
			client_log.info(f'Успешно добавлен контакт {new_contact}')
			self.messages.information(
				self, 'Успех', 'Контакт успешно добавлен.')
	
	def delete_contact_window(self):
		"""
		A method that creates a window for deleting a contact.
		:return:
		"""
		global remove_dialog
		remove_dialog = DelContactDialog(self.database)
		remove_dialog.btn_ok.clicked.connect(
			lambda: self.delete_contact(remove_dialog))
		remove_dialog.show()
	
	def delete_contact(self, item):
		"""
		Method for removing contact from server and client BD.
        After updating the databases, the contents of the window are also updated.
		:param item:
		:return:
		"""
		selected = item.selector.currentText()
		try:
			self.transport.remove_contact(selected)
		except ServerError as err:
			self.messages.critical(self, 'Ошибка сервера', err.text)
		except OSError as err:
			if err.errno:
				self.messages.critical(
					self, 'Ошибка', 'Потеряно соединение с сервером!')
				self.close()
			self.messages.critical(self, 'Ошибка', 'Таймаут соединения!')
		else:
			self.database.del_contact(selected)
			self.clients_list_update()
			client_log.info(f'Успешно удалён контакт {selected}')
			self.messages.information(self, 'Успех', 'Контакт успешно удалён.')
			item.close()
			# Если удалён активный пользователь, то деактивируем поля ввода.
			if selected == self.current_chat:
				self.current_chat = None
				self.set_disabled_input()
	
	def send_message(self):
		"""
		The function of sending a message to the current interlocutor.
		Implements message encryption and sending.
		"""
		# Текст в поле, проверяем что поле не пустое затем забирается сообщение
		# и поле очищается
		message_text = self.ui.text_message.toPlainText()
		self.ui.text_message.clear()
		if not message_text:
			return
		# Шифруем сообщение ключом получателя и упаковываем в base64.
		message_text_encrypted = self.encryptor.encrypt(
			message_text.encode('utf8'))
		message_text_encrypted_base64 = base64.b64encode(
			message_text_encrypted)
		try:
			self.transport.send_message(
				self.current_chat,
				message_text_encrypted_base64.decode('ascii'))
			pass
		except ServerError as err:
			self.messages.critical(self, 'Ошибка', err.text)
		except OSError as err:
			if err.errno:
				self.messages.critical(
					self, 'Ошибка', 'Потеряно соединение с сервером!')
				self.close()
			self.messages.critical(self, 'Ошибка', 'Таймаут соединения!')
		except (ConnectionResetError, ConnectionAbortedError):
			self.messages.critical(
				self, 'Ошибка', 'Потеряно соединение с сервером!')
			self.close()
		else:
			self.database.save_message(self.current_chat, 'out', message_text)
			client_log.debug(
				f'Отправлено сообщение для {self.current_chat}: {message_text}')
			self.history_list_update()
	
	@pyqtSlot(dict)
	def message(self, message):
		"""
		Slot handler of incoming messages, performs decryption
        received messages and their saving in the message history.
        Asks the user if the message is not from the current one
        interlocutor. Changes the interlocutor if necessary.
		:param message:
		:return:
		"""
		# Получаем строку байтов
		encrypted_message = base64.b64decode(message[MESSAGE_TEXT])
		# Декодируем строку, при ошибке выдаём сообщение и завершаем функцию
		try:
			decrypted_message = self.decrypter.decrypt(encrypted_message)
		except (ValueError, TypeError):
			self.messages.warning(
				self, 'Ошибка', 'Не удалось декодировать сообщение.')
			return
		# Сохраняем сообщение в базу и обновляем историю сообщений или
		# открываем новый чат.
		self.database.save_message(
			self.current_chat,
			'in',
			decrypted_message.decode('utf8'))
		
		sender = message[SENDER]
		if sender == self.current_chat:
			self.history_list_update()
		else:
			# Проверим есть ли такой пользователь у нас в контактах:
			if self.database.check_contact(sender):
				# Если есть, спрашиваем и желании открыть с ним чат и открываем
				# при желании
				if self.messages.question(
						self,
						'Новое сообщение',
						f'Получено новое сообщение от {sender}, открыть чат с ним?',
						QMessageBox.Yes,
						QMessageBox.No) == QMessageBox.Yes:
					self.current_chat = sender
					self.set_active_user()
			else:
				print('NO')
				# Раз нету,спрашиваем хотим ли добавить юзера в контакты.
				if self.messages.question(
						self,
						'Новое сообщение',
						f'Получено новое сообщение от {sender}.\n Данного пользователя нет в вашем контакт-листе.\n '
						f'Добавить в контакты и открыть чат с ним?',
						QMessageBox.Yes,
						QMessageBox.No) == QMessageBox.Yes:
					self.add_contact(sender)
					self.current_chat = sender
					# Нужно заново сохранить сообщение, иначе оно будет потеряно,
					# т.к. на момент предыдущего вызова контакта не было.
					self.database.save_message(
						self.current_chat, 'in', decrypted_message.decode('utf8'))
					self.set_active_user()
	
	@pyqtSlot()
	def connection_lost(self):
		"""
		Slot handler for lost connection to the server.
        Shows a warning window and exits the application.
		:return:
		"""
		self.messages.warning(
			self,
			'Сбой соединения',
			'Потеряно соединение с сервером. ')
		self.close()
	
	@pyqtSlot()
	def sig_205(self):
		"""
		Slot performing database update on server command
		"""
		if self.current_chat and not self.database.check_user(
				self.current_chat):
			self.messages.warning(
				self,
				'Сочувствую',
				'К сожалению собеседник был удалён с сервера.')
			self.set_disabled_input()
			self.current_chat = None
		self.clients_list_update()
	
	def make_connection(self, trans_obj):
		"""
		Method for connecting signals and slots
		:param trans_obj:
		:return:
		"""
		trans_obj.new_message.connect(self.message)
		trans_obj.connection_lost.connect(self.connection_lost)
		trans_obj.message_205.connect(self.sig_205)
Exemplo n.º 28
0
class DeleteDialog(QDialog):
    new_infos = pyqtSignal(object)

    def __init__(self, infos, parent=None):
        super(DeleteDialog, self).__init__(parent)
        self.infos = infos
        self.out = []
        self.initUI()
        self.setStyleSheet(dialog_qss_style)

    def set_file_icon(self, name):
        suffix = name.split(".")[-1]
        ico_path = "./icon/{}.gif".format(suffix)
        if os.path.isfile(ico_path):
            return QIcon(ico_path)
        else:
            return QIcon("./icon/file.ico")

    def initUI(self):
        self.setWindowTitle("确认删除")
        self.setWindowIcon(QIcon("./icon/delete.ico"))
        self.layout = QVBoxLayout()
        self.list_view = QListView()
        self.list_view.setViewMode(QListView.ListMode)
        # 列表
        self.slm = QStandardItem()
        self.model = QStandardItemModel()
        max_len = 10
        count = 0
        for i in self.infos:
            if i[2]:  # 有大小,是文件
                self.model.appendRow(
                    QStandardItem(self.set_file_icon(i[1]), i[1]))
            else:
                self.model.appendRow(
                    QStandardItem(QIcon("./icon/folder.gif"), i[1]))
            self.out.append({
                'fid': i[0],
                'is_file': True if i[2] else False,
                'name': i[1]
            })  # id,文件标示, 文件名
            count += 1
            if max_len < len(i[1]):  # 使用最大文件名长度
                max_len = len(i[1])
        self.list_view.setModel(self.model)

        self.lb_name = QLabel("尝试删除以下{}个文件(夹):".format(count))
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)

        self.layout.addWidget(self.lb_name)
        self.layout.addWidget(self.list_view)
        self.layout.addWidget(self.buttonBox)
        self.setLayout(self.layout)

        self.buttonBox.accepted.connect(self.btn_ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)
        self.setMinimumWidth(400)
        self.resize(int(max_len * 8), int(count * 34 + 60))

    def btn_ok(self):
        self.new_infos.emit(self.out)
Exemplo n.º 29
0
    def __init__(self,
                 *args,
                 mz_parent=None,
                 spectrum: np.ndarray = None,
                 base_path=None,
                 selection: dict = None,
                 **kwargs):
        super().__init__(*args, **kwargs)

        self._selected_index = QModelIndex()

        self.setupUi(self)
        self.setWindowFlags(Qt.Tool | Qt.CustomizeWindowHint
                            | Qt.WindowCloseButtonHint)

        if spectrum is not None:
            self.widgetSpectrumDetails.widgetSpectrum.set_spectrum2(
                spectrum, parent=mz_parent)

        self.current = selection['current'] if 'current' in selection else 0

        model = SpectraModel(base_path, selection)

        for i in range(model.columnCount()):
            if model.headerData(
                    i, Qt.Horizontal) == Spectrum.libraryquality.comment:
                self.tvSpectra.setItemDelegateForColumn(
                    i, LibraryQualityDelegate())
                break

        forbidden_cols = (model.column_index(Spectrum.id),
                          model.column_index(Spectrum.bank_id),
                          model.column_index(Spectrum.peaks))
        tree_model = QStandardItemModel()
        tree_model.setColumnCount(model.columnCount() - len(forbidden_cols))
        tree_model.setHorizontalHeaderLabels([
            model.headerData(section) for section in range(model.columnCount())
            if section not in forbidden_cols
        ])

        standards_item = QStandardItem(
            QIcon(":/icons/images/library-query.svg"), 'Standards')
        standards_item.setSelectable(False)
        standards_item.setData("standards", role=SpectraModel.TypeRole)
        tree_model.appendRow(standards_item)
        analogs_item = QStandardItem(
            QIcon(":/icons/images/library-query-analogs.svg"), 'Analogs')
        analogs_item.setSelectable(False)
        analogs_item.setData("analogs", role=SpectraModel.TypeRole)
        tree_model.appendRow(analogs_item)

        standards_rows = 0
        for row in range(model.rowCount()):
            values = []
            index = None
            for column in range(model.columnCount()):
                if column in forbidden_cols:
                    continue
                index = model.index(row, column)
                item = QStandardItem(str(model.data(index)))
                item.setEditable(False)
                values.append(item)
            if index is not None:
                if model.data(index, role=SpectraModel.TypeRole) == 'analogs':
                    analogs_item.appendRow(values)
                else:
                    standards_item.appendRow(values)
                    standards_rows += 1
        standards_item.setData(0, SpectraModel.RowRole)
        analogs_item.setData(standards_rows, SpectraModel.RowRole)

        self.tvSpectra.setModel(tree_model)
        self.tvSpectra.expandAll()
        self.widgetSpectrumDetails.setModel(model)
        self.widgetSpectrumDetails.widgetSpectrum.canvas.first_spectrum_label = "Database"
        self.widgetSpectrumDetails.widgetSpectrum.canvas.second_spectrum_label = "Experimental"

        # Connect events
        self.tvSpectra.selectionModel().currentChanged.connect(
            self.on_selection_changed)
Exemplo n.º 30
0
    def _populate_plan_ui(ui, model, plan):
        """
        Fill all widgets with current model data.
        """
        from PyQt5.QtGui import QStandardItemModel
        from PyQt5.QtGui import QStandardItem

        # ----------- General Info Tab ---------------------------
        ui.lineEdit.setText(plan.basename)
        ui.lineEdit_2.setText(plan.comment)
        ui.lineEdit_3.setText(str(plan.__uuid__))

        # ----------- Target Tab ---------------------------------
        voinames = [voi.name for voi in model.vdx.vois]

        # TARGET
        ui.comboBox.clear()
        for voi in model.vdx.vois:
            ui.comboBox.addItem(voi.name, voi)
            if plan.voi_target:
                _i = ui.comboBox.findData(voi)
                if _i == -1:  # not found
                    logger.warning("_populate_plan_ui() FIXME")
                else:
                    ui.comboBox.setCurrentIndex(_i)
            else:
                plan.voi_target = model.vdx.vois[0]
                ui.comboBox.setCurrentIndex(0)

        # OAR
        list = ui.listView
        # https://www.pythoncentral.io/pyside-pyqt-tutorial-qlistview-and-qstandarditemmodel/
        listmodel = QStandardItemModel(list)
        for voiname in voinames:
            item = QStandardItem(voiname)
            item.setCheckable(True)
            listmodel.appendRow(item)
        list.setModel(listmodel)

        # INCUBE
        ui.comboBox_2.clear()
        if model.dos:
            for dos in model.dos:
                ui.comboBox_2.addItem(dos.basename, dos)

            if plan.incube_basename:
                ui.comboBox_2.setEnabled(True)
                ui.checkBox.setChecked(True)
                _i = ui.comboBox_2.findText(dos.basename)
                if _i == -1:  # not found
                    logger.warning("_populate_plan_ui() FIXME 2")
                else:
                    ui.comboBox_2.setCurrentIndex(_i)
            else:
                plan.incube_basename = None
                ui.comboBox_2.setEnabled(False)
                ui.checkBox.setChecked(False)

        # TISSUE
        ui.comboBox_3.clear()
        ui.comboBox_3.addItem("(not implemented)")
        ui.comboBox_3.setEnabled(False)

        # RESIDUAL TISSUE
        ui.comboBox_4.clear()
        ui.comboBox_4.addItem("(not implemented)")
        ui.comboBox_4.setEnabled(False)

        # ----------- Dose Delivery Tab ---------------------------
        # TODO: Projectile
        PlanController._setup_plan_combobox(ui.comboBox_5, Plan.opt_methods)
        # TODO: Ripple filter

        # Target Dose Percent
        ui.doubleSpinBox.setValue(plan.target_dose_percent)
        ui.doubleSpinBox_4.setValue(plan.target_dose)

        # ----------- Optimization Tab ----------------------------
        # Iterations
        ui.spinBox.setValue(plan.iterations)
        ui.doubleSpinBox_2.setValue(plan.eps)
        ui.doubleSpinBox_3.setValue(plan.geps)

        PlanController._setup_plan_combobox(ui.comboBox_7, Plan.opt_methods)
        PlanController._setup_plan_combobox(ui.comboBox_8, Plan.opt_principles)
        PlanController._setup_plan_combobox(ui.comboBox_9, Plan.dose_algs)
        PlanController._setup_plan_combobox(ui.comboBox_10, Plan.bio_algs)
        PlanController._setup_plan_combobox(ui.comboBox_11, Plan.opt_algs)

        # ----------- Results Tab --------------------------------
        ui.checkBox_2.setChecked(plan.want_phys_dose)
        ui.checkBox_3.setChecked(plan.want_bio_dose)
        ui.checkBox_4.setChecked(plan.want_dlet)
        ui.checkBox_5.setChecked(plan.want_rst)
        ui.checkBox_6.setEnabled(False)
        ui.checkBox_7.setEnabled(False)
Exemplo n.º 31
0
class HelpWebSearchWidget(E5ClearableLineEdit):
    """
    Class implementing a web search widget for the web browser.
    
    @signal search(QUrl) emitted when the search should be done
    """
    search = pyqtSignal(QUrl)
    
    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget (QWidget)
        """
        super(HelpWebSearchWidget, self).__init__(parent)
        
        from E5Gui.E5LineEdit import E5LineEdit
        from E5Gui.E5LineEditButton import E5LineEditButton
        from .OpenSearch.OpenSearchManager import OpenSearchManager

        self.__mw = parent
        
        self.__openSearchManager = OpenSearchManager(self)
        self.__openSearchManager.currentEngineChanged.connect(
            self.__currentEngineChanged)
        self.__currentEngine = ""
        
        self.__enginesMenu = QMenu(self)
        
        self.__engineButton = E5LineEditButton(self)
        self.__engineButton.setMenu(self.__enginesMenu)
        self.addWidget(self.__engineButton, E5LineEdit.LeftSide)
        
        self.__searchButton = E5LineEditButton(self)
        self.__searchButton.setIcon(UI.PixmapCache.getIcon("webSearch.png"))
        self.addWidget(self.__searchButton, E5LineEdit.LeftSide)
        
        self.__model = QStandardItemModel(self)
        self.__completer = QCompleter()
        self.__completer.setModel(self.__model)
        self.__completer.setCompletionMode(
            QCompleter.UnfilteredPopupCompletion)
        self.__completer.setWidget(self)
        
        self.__searchButton.clicked.connect(self.__searchButtonClicked)
        self.textEdited.connect(self.__textEdited)
        self.returnPressed.connect(self.__searchNow)
        self.__completer.activated[QModelIndex].connect(
            self.__completerActivated)
        self.__completer.highlighted[QModelIndex].connect(
            self.__completerHighlighted)
        self.__enginesMenu.aboutToShow.connect(self.__showEnginesMenu)
        
        self.__suggestionsItem = None
        self.__suggestions = []
        self.__suggestTimer = None
        self.__suggestionsEnabled = Preferences.getHelp("WebSearchSuggestions")
        
        self.__recentSearchesItem = None
        self.__recentSearches = []
        self.__maxSavedSearches = 10
        
        self.__engine = None
        self.__loadSearches()
        self.__setupCompleterMenu()
        self.__currentEngineChanged()
    
    def __searchNow(self):
        """
        Private slot to perform the web search.
        """
        searchText = self.text()
        if not searchText:
            return
        
        globalSettings = QWebSettings.globalSettings()
        if not globalSettings.testAttribute(
                QWebSettings.PrivateBrowsingEnabled):
            if searchText in self.__recentSearches:
                self.__recentSearches.remove(searchText)
            self.__recentSearches.insert(0, searchText)
            if len(self.__recentSearches) > self.__maxSavedSearches:
                self.__recentSearches = \
                    self.__recentSearches[:self.__maxSavedSearches]
            self.__setupCompleterMenu()
        
        url = self.__openSearchManager.currentEngine().searchUrl(searchText)
        self.search.emit(url)
    
    def __setupCompleterMenu(self):
        """
        Private method to create the completer menu.
        """
        if not self.__suggestions or \
           (self.__model.rowCount() > 0 and
                self.__model.item(0) != self.__suggestionsItem):
            self.__model.clear()
            self.__suggestionsItem = None
        else:
            self.__model.removeRows(1, self.__model.rowCount() - 1)
        
        boldFont = QFont()
        boldFont.setBold(True)
        
        if self.__suggestions:
            if self.__model.rowCount() == 0:
                if not self.__suggestionsItem:
                    self.__suggestionsItem = QStandardItem(
                        self.tr("Suggestions"))
                    self.__suggestionsItem.setFont(boldFont)
                self.__model.appendRow(self.__suggestionsItem)
            
            for suggestion in self.__suggestions:
                self.__model.appendRow(QStandardItem(suggestion))
        
        if not self.__recentSearches:
            self.__recentSearchesItem = QStandardItem(
                self.tr("No Recent Searches"))
            self.__recentSearchesItem.setFont(boldFont)
            self.__model.appendRow(self.__recentSearchesItem)
        else:
            self.__recentSearchesItem = QStandardItem(
                self.tr("Recent Searches"))
            self.__recentSearchesItem.setFont(boldFont)
            self.__model.appendRow(self.__recentSearchesItem)
            for recentSearch in self.__recentSearches:
                self.__model.appendRow(QStandardItem(recentSearch))
        
        view = self.__completer.popup()
        view.setFixedHeight(view.sizeHintForRow(0) * self.__model.rowCount() +
                            view.frameWidth() * 2)
        
        self.__searchButton.setEnabled(
            bool(self.__recentSearches or self.__suggestions))
    
    def __completerActivated(self, index):
        """
        Private slot handling the selection of an entry from the completer.
        
        @param index index of the item (QModelIndex)
        """
        if self.__suggestionsItem and \
           self.__suggestionsItem.index().row() == index.row():
            return
        
        if self.__recentSearchesItem and \
           self.__recentSearchesItem.index().row() == index.row():
            return
        
        self.__searchNow()
    
    def __completerHighlighted(self, index):
        """
        Private slot handling the highlighting of an entry of the completer.
        
        @param index index of the item (QModelIndex)
        @return flah indicating a successful highlighting (boolean)
        """
        if self.__suggestionsItem and \
           self.__suggestionsItem.index().row() == index.row():
            return False
        
        if self.__recentSearchesItem and \
           self.__recentSearchesItem.index().row() == index.row():
            return False
        
        self.setText(index.data())
        return True
    
    def __textEdited(self, txt):
        """
        Private slot to handle changes of the search text.
        
        @param txt search text (string)
        """
        if self.__suggestionsEnabled:
            if self.__suggestTimer is None:
                self.__suggestTimer = QTimer(self)
                self.__suggestTimer.setSingleShot(True)
                self.__suggestTimer.setInterval(200)
                self.__suggestTimer.timeout.connect(self.__getSuggestions)
            self.__suggestTimer.start()
        else:
            self.__completer.setCompletionPrefix(txt)
            self.__completer.complete()
    
    def __getSuggestions(self):
        """
        Private slot to get search suggestions from the configured search
        engine.
        """
        searchText = self.text()
        if searchText:
            self.__openSearchManager.currentEngine()\
                .requestSuggestions(searchText)
    
    def __newSuggestions(self, suggestions):
        """
        Private slot to receive a new list of suggestions.
        
        @param suggestions list of suggestions (list of strings)
        """
        self.__suggestions = suggestions
        self.__setupCompleterMenu()
        self.__completer.complete()
    
    def __showEnginesMenu(self):
        """
        Private slot to handle the display of the engines menu.
        """
        self.__enginesMenu.clear()
        
        from .OpenSearch.OpenSearchEngineAction import OpenSearchEngineAction
        engineNames = self.__openSearchManager.allEnginesNames()
        for engineName in engineNames:
            engine = self.__openSearchManager.engine(engineName)
            action = OpenSearchEngineAction(engine, self.__enginesMenu)
            action.setData(engineName)
            action.triggered.connect(self.__changeCurrentEngine)
            self.__enginesMenu.addAction(action)
            
            if self.__openSearchManager.currentEngineName() == engineName:
                action.setCheckable(True)
                action.setChecked(True)
        
        ct = self.__mw.currentBrowser()
        linkedResources = ct.linkedResources("search")
        
        if len(linkedResources) > 0:
            self.__enginesMenu.addSeparator()
        
        for linkedResource in linkedResources:
            url = QUrl(linkedResource.href)
            title = linkedResource.title
            mimetype = linkedResource.type_
            
            if mimetype != "application/opensearchdescription+xml":
                continue
            if url.isEmpty():
                continue
            
            if url.isRelative():
                url = ct.url().resolved(url)
            
            if not title:
                if not ct.title():
                    title = url.host()
                else:
                    title = ct.title()
            
            action = self.__enginesMenu.addAction(
                self.tr("Add '{0}'").format(title),
                self.__addEngineFromUrl)
            action.setData(url)
            action.setIcon(ct.icon())
        
        self.__enginesMenu.addSeparator()
        self.__enginesMenu.addAction(self.__mw.searchEnginesAction())
        
        if self.__recentSearches:
            self.__enginesMenu.addAction(self.tr("Clear Recent Searches"),
                                         self.clear)
    
    def __changeCurrentEngine(self):
        """
        Private slot to handle the selection of a search engine.
        """
        action = self.sender()
        if action is not None:
            name = action.data()
            self.__openSearchManager.setCurrentEngineName(name)
    
    def __addEngineFromUrl(self):
        """
        Private slot to add a search engine given its URL.
        """
        action = self.sender()
        if action is not None:
            url = action.data()
            if not isinstance(url, QUrl):
                return
            
            self.__openSearchManager.addEngine(url)
    
    def __searchButtonClicked(self):
        """
        Private slot to show the search menu via the search button.
        """
        self.__setupCompleterMenu()
        self.__completer.complete()
    
    def clear(self):
        """
        Public method to clear all private data.
        """
        self.__recentSearches = []
        self.__setupCompleterMenu()
        super(HelpWebSearchWidget, self).clear()
        self.clearFocus()
    
    def preferencesChanged(self):
        """
        Public method to handle the change of preferences.
        """
        self.__suggestionsEnabled = Preferences.getHelp("WebSearchSuggestions")
        if not self.__suggestionsEnabled:
            self.__suggestions = []
            self.__setupCompleterMenu()
    
    def saveSearches(self):
        """
        Public method to save the recently performed web searches.
        """
        Preferences.Prefs.settings.setValue(
            'Help/WebSearches', self.__recentSearches)
    
    def __loadSearches(self):
        """
        Private method to load the recently performed web searches.
        """
        searches = Preferences.Prefs.settings.value('Help/WebSearches')
        if searches is not None:
            self.__recentSearches = searches
    
    def openSearchManager(self):
        """
        Public method to get a reference to the opensearch manager object.
        
        @return reference to the opensearch manager object (OpenSearchManager)
        """
        return self.__openSearchManager
    
    def __currentEngineChanged(self):
        """
        Private slot to track a change of the current search engine.
        """
        if self.__openSearchManager.engineExists(self.__currentEngine):
            oldEngine = self.__openSearchManager.engine(self.__currentEngine)
            oldEngine.imageChanged.disconnect(self.__engineImageChanged)
            if self.__suggestionsEnabled:
                oldEngine.suggestions.disconnect(self.__newSuggestions)
        
        newEngine = self.__openSearchManager.currentEngine()
        if newEngine.networkAccessManager() is None:
            newEngine.setNetworkAccessManager(self.__mw.networkAccessManager())
        newEngine.imageChanged.connect(self.__engineImageChanged)
        if self.__suggestionsEnabled:
            newEngine.suggestions.connect(self.__newSuggestions)
        
        self.setInactiveText(self.__openSearchManager.currentEngineName())
        self.__currentEngine = self.__openSearchManager.currentEngineName()
        self.__engineButton.setIcon(QIcon(QPixmap.fromImage(
            self.__openSearchManager.currentEngine().image())))
        self.__suggestions = []
        self.__setupCompleterMenu()
    
    def __engineImageChanged(self):
        """
        Private slot to handle a change of the current search engine icon.
        """
        self.__engineButton.setIcon(QIcon(QPixmap.fromImage(
            self.__openSearchManager.currentEngine().image())))
    
    def mousePressEvent(self, evt):
        """
        Protected method called by a mouse press event.
        
        @param evt reference to the mouse event (QMouseEvent)
        """
        if evt.button() == Qt.XButton1:
            self.__mw.currentBrowser().pageAction(QWebPage.Back).trigger()
        elif evt.button() == Qt.XButton2:
            self.__mw.currentBrowser().pageAction(QWebPage.Forward).trigger()
        else:
            super(HelpWebSearchWidget, self).mousePressEvent(evt)
Exemplo n.º 32
0
class EventUI(object):
    def __init__(self, window, uaclient):
        self.window = window
        self.uaclient = uaclient
        self._handler = EventHandler()
        self._subscribed_nodes = []  # FIXME: not really needed
        self.model = QStandardItemModel()
        self.window.ui.evView.setModel(self.model)
        self.window.ui.actionSubscribeEvent.triggered.connect(self._subscribe)
        self.window.ui.actionUnsubscribeEvents.triggered.connect(
            self._unsubscribe)
        # context menu
        self.window.addAction(self.window.ui.actionSubscribeEvent)
        self.window.addAction(self.window.ui.actionUnsubscribeEvents)
        self.window.addAction(self.window.ui.actionAddToGraph)
        self._handler.event_fired.connect(self._update_event_model,
                                          type=Qt.QueuedConnection)

        # accept drops
        self.model.canDropMimeData = self.canDropMimeData
        self.model.dropMimeData = self.dropMimeData

    def canDropMimeData(self, mdata, action, row, column, parent):
        return True

    def show_error(self, *args):
        self.window.show_error(*args)

    def dropMimeData(self, mdata, action, row, column, parent):
        node = self.uaclient.client.get_node(mdata.text())
        self._subscribe(node)
        return True

    def clear(self):
        self._subscribed_nodes = []
        self.model.clear()

    @trycatchslot
    def _subscribe(self, node=None):
        logger.info("Subscribing to %s", node)
        if not node:
            node = self.window.get_current_node()
            if node is None:
                return
        if node in self._subscribed_nodes:
            logger.info("already subscribed to event for node: %s", node)
            return
        logger.info("Subscribing to events for %s", node)
        self.window.ui.evDockWidget.raise_()
        try:
            self.uaclient.subscribe_events(node, self._handler)
        except Exception as ex:
            self.window.show_error(ex)
            raise
        else:
            self._subscribed_nodes.append(node)

    @trycatchslot
    def _unsubscribe(self):
        node = self.window.get_current_node()
        if node is None:
            return
        self._subscribed_nodes.remove(node)
        self.uaclient.unsubscribe_events(node)

    @trycatchslot
    def _update_event_model(self, event):
        self.model.appendRow([QStandardItem(str(event))])
Exemplo n.º 33
0
class PwdManager(QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowTitleHint)
        self.setWindowTitle('Password Manager')
        self.setFixedSize(400, 300)
        self.PwdViewer = QListView()
        self.PwdViewer.clicked.connect(self.ClickPwd)
        self.AddButton = QPushButton('Add')
        self.AddButton.clicked.connect(self.AddPwd)
        self.DelButton = QPushButton('Delete')
        self.DelButton.clicked.connect(self.DelPwd)
        self.PwdBox = QLineEdit()
        self.PwdBox.textEdited.connect(self.PwdChanged)

        vbox = QVBoxLayout()
        vbox.addWidget(self.AddButton)
        vbox.addWidget(self.DelButton)
        vbox.addStretch(1)
        hbox = QHBoxLayout()
        hbox.addWidget(self.PwdViewer)
        hbox.addLayout(vbox)
        MainBox = QVBoxLayout()
        MainBox.addWidget(self.PwdBox)
        MainBox.addLayout(hbox)
        self.setLayout(MainBox)

    def showEvent(self, event):
        self.center()
        self.LoadPwdToList()
        if self.Model.rowCount() == 0:
            self.AddPwd()
        self.IsChanged = False

    def closeEvent(self, event):
        self.RemoveEmpty()
        pwdf = open('password.pwd', 'w')
        for index in range(self.Model.rowCount()):
            pwdf.write(self.Model.data(self.Model.index(index, 0)) + '\n')
        pwdf.close()
        if self.IsChanged:
            self.done(1)
        else:
            self.done(0)

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

    def LoadPwdToList(self):
        if not os.path.exists(r'password.pwd'):
            open("password.pwd", "wb").close()
        pwdf = open('password.pwd', 'r')
        pwdlist = pwdf.read().splitlines()
        pwdf.close()
        self.Model = QStandardItemModel(self.PwdViewer)
        for pwd in pwdlist:
            item = QStandardItem(pwd)
            item.setEditable(False)
            self.Model.appendRow(item)
        self.PwdViewer.setModel(self.Model)
        self.PwdViewer.setCurrentIndex(self.Model.index(0, 0))
        self.GetPwd(self.PwdViewer.currentIndex())

    def ClickPwd(self, index):
        self.RemoveEmpty()
        if self.Model.rowCount() == 0:
            self.AddPwd()
        self.GetPwd(index)

    def GetPwd(self, index):
        self.PwdBox.setText(self.Model.data(index))
        self.PwdBox.setFocus()

    def PwdChanged(self):
        self.IsChanged = True
        self.Model.setData(self.PwdViewer.currentIndex(), self.PwdBox.text())
        if self.PwdBox.text() == '':
            self.DelPwd()

    def DelPwd(self):
        self.Model.removeRow(self.PwdViewer.currentIndex().row())
        self.GetPwd(self.PwdViewer.currentIndex())
        if self.Model.rowCount() == 0:
            self.AddPwd()

    def AddPwd(self):
        item = QStandardItem()
        item.setEditable(False)
        self.Model.appendRow(item)
        self.PwdViewer.setCurrentIndex(
            self.Model.index(self.Model.rowCount() - 1, 0))
        self.GetPwd(self.PwdViewer.currentIndex())

    def RemoveEmpty(self):
        for item in self.Model.findItems('', Qt.MatchFixedString):
            self.Model.removeRow(item.row())
Exemplo n.º 34
0
class SelectDialog(QDialog, Ui_SelectDialog):
    """description of class"""
    def __init__(self,
                 parent,
                 title,
                 text,
                 options,
                 enabledOptions=None,
                 headerOptions=[],
                 singleSelectionMode=True):
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self.setWindowTitle(title)
        self.label_text.setText(text)
        self.headerOptions = headerOptions
        self.singleSelectionMode = singleSelectionMode
        self.options = options
        self.initUi(options, enabledOptions, headerOptions,
                    singleSelectionMode)
        self.pushButton_sellectAll.clicked.connect(
            self.pushButton_selectAll_clicked)
        self.pushButton_deSellectAll.clicked.connect(
            self.pushButton_deSelectAll_clicked)
        self.listView_options.clicked.connect(self.listView_options_clicked)

    def initUi(self, options, enabledOptions, headerOptions,
               singleSelectionMode):
        boldFont = QFont()
        boldFont.setBold(True)

        # set the selection mode
        if not singleSelectionMode:
            self.listView_options.setSelectionMode(
                QAbstractItemView.ExtendedSelection)

        # create enableItems if none
        if enabledOptions is None:
            enabledOptions = [True for idx in range(len(options))]

        # Insert the choices
        self.standaredItemModel = QStandardItemModel(self.listView_options)
        self.standaredItemModel.itemChanged.connect(self.onItemChanged)
        for idx in range(len(options)):
            standaredItem = QStandardItem(options[idx])
            standaredItem.setSelectable(enabledOptions[idx])
            if idx in headerOptions:
                standaredItem.setFont(boldFont)
            self.standaredItemModel.appendRow(standaredItem)

        self.listView_options.setModel(self.standaredItemModel)

        # disable select all / de select all buttons if in single selection
        # mode
        if singleSelectionMode:
            self.pushButton_sellectAll.setDisabled(True)
            self.pushButton_deSellectAll.setDisabled(True)

    def onItemChanged(self, item):
        QMessageBox.information(self, "Selec Dialog Message",
                                "Selected Item :" + item.text())

    def selection(self):
        return [
            index.row() for index in
            self.listView_options.selectionModel().selectedIndexes()
        ]

    def pushButton_selectAll_clicked(self):
        selectIndexes = [
            idx for idx in range(self.standaredItemModel.rowCount())
        ]
        self.setSelected(selectIndexes, QItemSelectionModel.Select)

    def pushButton_deSelectAll_clicked(self):
        selectIndexes = [
            idx for idx in range(self.standaredItemModel.rowCount())
        ]
        self.setSelected(selectIndexes, QItemSelectionModel.Deselect)

    def setSelected(self, selectIndexes, newStatus):
        modelIndexes = [
            self.standaredItemModel.createIndex(rowIndex, 0)
            for rowIndex in selectIndexes
        ]
        selectionModel = self.listView_options.selectionModel()
        for modelIndex in modelIndexes:
            selectionModel.select(modelIndex, newStatus)

    @pyqtSlot("QModelIndex")
    def listView_options_clicked(self, modelIndex):
        if self.singleSelectionMode:
            return

        row = modelIndex.row()
        if row in self.headerOptions:
            indexInHeaderOptions = self.headerOptions.index(row)
            if indexInHeaderOptions == len(self.headerOptions) - 1:
                selectedIndexes = [
                    idx for idx in range(row, len(self.options))
                ]
            else:
                selectedIndexes = [
                    idx for idx in range(
                        row, self.headerOptions[indexInHeaderOptions + 1])
                ]
            selectionModel = self.listView_options.selectionModel()
            if modelIndex in selectionModel.selectedIndexes():
                newStatus = QItemSelectionModel.Select
            else:
                newStatus = QItemSelectionModel.Deselect
            self.setSelected(selectedIndexes, newStatus)
Exemplo n.º 35
0
class VistaListaProdotti(QWidget):
    def __init__(self, parent=None):
        super(VistaListaProdotti, self).__init__(parent)
        self.carrello = ControlloreCarrello()
        self.controller = ControlloreListaProdotti()
        self.setWindowIcon(QtGui.QIcon('logos/logo.png'))
        main_layout = QHBoxLayout()

        v_layout = QVBoxLayout()

        self.list_view = QListView()
        self.update_ui()

        #Crea un elenco fittizio sopra l'elenco reale per poter usare la barra di ricerca
        self.filter_proxy_model = QSortFilterProxyModel()
        self.filter_proxy_model.setSourceModel(self.listview_model)
        self.filter_proxy_model.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.filter_proxy_model.setFilterKeyColumn(0)

        self.list_view.setModel(self.filter_proxy_model)

        search_field = QLineEdit()
        search_field.setStyleSheet('font-size: 15px; height: 30px;')
        search_field.textChanged.connect(
            self.filter_proxy_model.setFilterRegExp)

        v_layout.addWidget(search_field)
        v_layout.addWidget(self.list_view)
        main_layout.addLayout(v_layout)

        buttons_layout = QVBoxLayout()

        buttons_layout.addItem(QSpacerItem(40, 40))

        #Bottone per aprire un prodotto
        open_button = QPushButton("Apri")
        open_button.clicked.connect(self.show_selected_info)
        buttons_layout.addWidget(open_button)

        #Bottone per creare un nuovo prodotto
        new_button = QPushButton("Nuovo")
        new_button.clicked.connect(self.show_new_prodotto)
        buttons_layout.addWidget(new_button)
        buttons_layout.addStretch()
        main_layout.addLayout(buttons_layout)

        self.setLayout(main_layout)
        self.resize(600, 300)
        self.setWindowTitle("Lista Prodotti")

    #Metodo che mostra a schermo le informazioni del prodotto selezionato
    def show_selected_info(self):
        try:
            sourceindex = self.list_view.selectedIndexes()[0].row()
            prodotto_selezionato = self.controller.get_prodotto_by_index(
                sourceindex)
            self.vista_prodotto = VistaProdotto(
                prodotto_selezionato, self.controller.elimina_prodotto_by_id,
                self.update_ui, self.carrello)
            self.vista_prodotto.show()
        except IndexError:
            QMessageBox.critical(self, 'Errore',
                                 'Per favore, seleziona un prodotto',
                                 QMessageBox.Ok, QMessageBox.Ok)

    #Metodo aprire la vista di inserimento del nuovo prodotto
    def show_new_prodotto(self):
        self.vista_inserisci_prodotto = VistaInserisciProdotto(
            self.controller, self.update_ui)
        self.vista_inserisci_prodotto.show()

    #Metodo che serve per generare e/o aggiornare la vista
    def update_ui(self):
        self.listview_model = QStandardItemModel(self.list_view)
        for prodotto in self.controller.get_lista_dei_prodotti():
            item = QStandardItem()
            item.setText(prodotto.marca + " " + prodotto.nome)
            item.setEditable(False)
            font = item.font()
            font.setPointSize(18)
            item.setFont(font)
            self.listview_model.appendRow(item)
        self.list_view.setModel(self.listview_model)

    # salva i dati sul file pickle alla chiusura della view
    def closeEvent(self, event):
        self.controller.save_data()

    #Metodo per collegare l'indice selezionato all'elenco fittizio all'indice dell'elenco reale
    def toSourceIndex(self, index):
        return self.filter_proxy_model.mapToSource(index).row()
Exemplo n.º 36
0
class QuickSettingsDocker(DockWidget):
    # Init the docker

    def __init__(self):
        super(QuickSettingsDocker, self).__init__()
        # make base-widget and layout
        widget = QWidget()
        layout = QVBoxLayout()
        widget.setLayout(layout)
        self.setWindowTitle("Quick Settings Docker")
        tabWidget = QTabWidget()

        self.brushSizeTableView = QListView()
        self.brushSizeTableView.setViewMode(QListView.IconMode)
        self.brushSizeTableView.setMovement(QListView.Static)
        self.brushSizeTableView.setResizeMode(QListView.Adjust)
        self.brushSizeTableView.setUniformItemSizes(True)
        self.brushSizeTableView.setSelectionMode(QListView.SingleSelection)

        self.brushOpacityTableView = QListView()
        self.brushOpacityTableView.setViewMode(QListView.IconMode)
        self.brushOpacityTableView.setMovement(QListView.Static)
        self.brushOpacityTableView.setResizeMode(QListView.Adjust)
        self.brushOpacityTableView.setUniformItemSizes(True)
        self.brushOpacityTableView.setSelectionMode(QListView.SingleSelection)

        self.brushFlowTableView = QListView()
        self.brushFlowTableView.setViewMode(QListView.IconMode)
        self.brushFlowTableView.setMovement(QListView.Static)
        self.brushFlowTableView.setResizeMode(QListView.Adjust)
        self.brushFlowTableView.setUniformItemSizes(True)
        self.brushFlowTableView.setSelectionMode(QListView.SingleSelection)

        tabWidget.addTab(self.brushSizeTableView, "Size")
        tabWidget.addTab(self.brushOpacityTableView, "Opacity")
        tabWidget.addTab(self.brushFlowTableView, "Flow")
        layout.addWidget(tabWidget)
        self.setWidget(widget)  # Add the widget to the docker.

        # amount of columns in each row for all the tables.

        # We want a grid with possible options to select.
        # To do this, we'll make a ListView widget and use a standarditemmodel for the entries.
        # The entries are filled out based on the sizes and opacity lists.

        # Sizes and opacity lists. The former is half-way copied from ptsai, the latter is based on personal experience of useful opacities.
        self.sizesList = [
            0.7, 1.0, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16,
            20, 25, 30, 35, 40, 50, 60, 70, 80, 100, 120, 160, 200, 250, 300,
            350, 400, 450, 500
        ]
        self.opacityList = [
            0.1, 0.5, 1, 5, 10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100
        ]
        self.brushSizeModel = QStandardItemModel()
        self.brushOpacityModel = QStandardItemModel()
        self.brushFlowModel = QStandardItemModel()
        self.fillSizesModel()
        self.fillOpacityModel()

        # Now we're done filling out our tables, we connect the views to the functions that'll change the settings.
        self.brushSizeTableView.clicked.connect(self.setBrushSize)
        self.brushOpacityTableView.clicked.connect(self.setBrushOpacity)
        self.brushFlowTableView.clicked.connect(self.setBrushFlow)

    def fillSizesModel(self):
        # First we empty the old model. We might wanna use this function in the future to fill it with the brushmask of the selected brush, but there's currently no API for recognising changes in the current brush nor is there a way to get its brushmask.
        self.brushSizeModel.clear()
        for s in range(len(self.sizesList)):
            # we're gonna itterate over our list, and make a new item for each entry.
            # We need to disable a bunch of stuff to make sure people won't do funny things to our entries.
            item = QStandardItem()
            item.setCheckable(False)
            item.setEditable(False)
            item.setDragEnabled(False)
            item.setText(str(self.sizesList[s]) + " px")
            # And from here on we'll make an icon.
            brushImage = QPixmap(64, 64)
            img = QImage(64, 64, QImage.Format_RGBA8888)
            circlePainter = QPainter()
            img.fill(Qt.transparent)
            circlePainter.begin(img)
            brush = QBrush(Qt.SolidPattern)
            brush.setColor(self.brushSizeTableView.palette().color(
                QPalette.Text))
            circlePainter.setBrush(brush)
            circlePainter.setPen(QPen(QBrush(Qt.transparent), 0))
            brushSize = max(min(self.sizesList[s], 64), 1)
            brushSize = brushSize * 0.5
            circlePainter.drawEllipse(QPointF(32, 32), brushSize, brushSize)
            circlePainter.end()
            brushImage = QPixmap.fromImage(img)
            # now we're done with drawing the icon, so we set it on the item.
            item.setIcon(QIcon(brushImage))
            self.brushSizeModel.appendRow(item)
        self.brushSizeTableView.setModel(self.brushSizeModel)

    def fillOpacityModel(self):
        self.brushOpacityModel.clear()
        self.brushFlowModel.clear()
        for s in range(len(self.opacityList)):
            # we're gonna itterate over our list, and make a new item for each entry.
            item = QStandardItem()
            item.setCheckable(False)
            item.setEditable(False)
            item.setDragEnabled(False)
            item.setText(str(self.opacityList[s]) + " %")
            brushImage = QPixmap(64, 64)
            img = QImage(64, 64, QImage.Format_RGBA8888)
            circlePainter = QPainter()
            img.fill(Qt.transparent)
            circlePainter.begin(img)
            brush = QBrush(Qt.SolidPattern)
            brush.setColor(self.brushSizeTableView.palette().color(
                QPalette.Text))
            circlePainter.setBrush(brush)
            circlePainter.setPen(QPen(QBrush(Qt.transparent), 0))
            circlePainter.setOpacity(float(self.opacityList[s]) / 100.0)
            circlePainter.drawEllipse(QPointF(32, 32), 32, 32)
            circlePainter.end()
            brushImage = QPixmap.fromImage(img)
            item.setIcon(QIcon(brushImage))
            # the flow and opacity models will use virtually the same items, but Qt would like us to make sure we understand
            # these are not really the same items, so hence the clone.
            itemFlow = item.clone()
            self.brushOpacityModel.appendRow(item)
            self.brushFlowModel.appendRow(itemFlow)
        self.brushOpacityTableView.setModel(self.brushOpacityModel)
        self.brushFlowTableView.setModel(self.brushFlowModel)

    def canvasChanged(self, canvas):
        pass

    @pyqtSlot('QModelIndex')
    def setBrushSize(self, index):
        i = index.row()
        brushSize = self.sizesList[i]
        if Application.activeWindow() and len(
                Application.activeWindow().views()) > 0:
            Application.activeWindow().views()[0].setBrushSize(brushSize)

    @pyqtSlot('QModelIndex')
    def setBrushOpacity(self, index):
        i = index.row()
        brushOpacity = float(self.opacityList[i]) / 100.0
        if Application.activeWindow() and len(
                Application.activeWindow().views()) > 0:
            Application.activeWindow().views()[0].setPaintingOpacity(
                brushOpacity)

    @pyqtSlot('QModelIndex')
    def setBrushFlow(self, index):
        i = index.row()
        brushOpacity = float(self.opacityList[i]) / 100.0
        if Application.activeWindow() and len(
                Application.activeWindow().views()) > 0:
            Application.activeWindow().views()[0].setPaintingFlow(brushOpacity)
Exemplo n.º 37
0
class AttrsUI(object):

    def __init__(self, window, uaclient):
        self.window = window
        self.uaclient = uaclient
        self.model = QStandardItemModel()
        self.window.ui.attrView.setModel(self.model)
        self.window.ui.attrView.doubleClicked.connect(self.edit_attr)
        self.model.itemChanged.connect(self.edit_attr_finished)
        self.window.ui.attrView.header().setSectionResizeMode(1)

        self.window.ui.treeView.activated.connect(self.show_attrs)
        self.window.ui.treeView.clicked.connect(self.show_attrs)
        self.window.ui.attrRefreshButton.clicked.connect(self.show_attrs)

        # Context menu
        self.window.ui.attrView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.window.ui.attrView.customContextMenuRequested.connect(self.showContextMenu)
        copyaction = QAction("&Copy Value", self.model)
        copyaction.triggered.connect(self._copy_value)
        self._contextMenu = QMenu()
        self._contextMenu.addAction(copyaction)

    def _check_edit(self, item):
        """
        filter only element we want to edit.
        take either idx eller item as argument
        """
        if item.column() != 1:
            return False
        name_item = self.model.item(item.row(), 0)
        if name_item.text() != "Value":
            return False
        return True

    def edit_attr(self, idx):
        if not self._check_edit(idx):
            return
        attritem = self.model.item(idx.row(), 0)
        if attritem.text() == "Value":
            self.window.ui.attrView.edit(idx)

    def edit_attr_finished(self, item):
        if not self._check_edit(item):
            return
        try:
            var = item.data()
            val = item.text()
            var = string_to_variant(val, var.VariantType)
            self.current_node.set_value(var)
        except Exception as ex:
            self.window.show_error(ex)
            raise
        finally:
            dv = self.current_node.get_data_value()
            item.setText(variant_to_string(dv.Value))
            name_item = self.model.item(item.row(), 0)
            name_item.child(0, 1).setText(val_to_string(dv.ServerTimestamp))
            name_item.child(1, 1).setText(val_to_string(dv.SourceTimestamp))

    def showContextMenu(self, position):
        item = self.get_current_item()
        if item:
            self._contextMenu.exec_(self.window.ui.attrView.mapToGlobal(position))

    def get_current_item(self, col_idx=0):
        idx = self.window.ui.attrView.currentIndex()
        return self.model.item(idx.row(), col_idx)

    def _copy_value(self, position):
        it = self.get_current_item(1)
        if it:
            QApplication.clipboard().setText(it.text())

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

    def show_attrs(self, idx):
        if not isinstance(idx, QModelIndex):
            idx = None
        self.current_node = self.window.get_current_node(idx)
        self.model.clear()
        if self.current_node:
            self._show_attrs(self.current_node)
        self.window.ui.attrView.expandAll()

    def _show_attrs(self, node):
        try:
            attrs = self.uaclient.get_all_attrs(node)
        except Exception as ex:
            self.window.show_error(ex)
            raise
        self.model.setHorizontalHeaderLabels(['Attribute', 'Value', 'DataType'])
        for name, dv in attrs:
            if name == "DataType":
                if isinstance(dv.Value.Value.Identifier, int) and dv.Value.Value.Identifier < 63:
                    string = ua.DataType_to_VariantType(dv.Value.Value).name
                elif dv.Value.Value.Identifier in ua.ObjectIdNames:
                    string = ua.ObjectIdNames[dv.Value.Value.Identifier]
                else:
                    string = dv.Value.Value.to_string()
            elif name in ("AccessLevel", "UserAccessLevel"):
                string = ",".join([e.name for e in ua.int_to_AccessLevel(dv.Value.Value)])
            elif name in ("WriteMask", "UserWriteMask"):
                string = ",".join([e.name for e in ua.int_to_WriteMask(dv.Value.Value)])
            elif name in ("EventNotifier"):
                string = ",".join([e.name for e in ua.int_to_EventNotifier(dv.Value.Value)])
            else:
                string = variant_to_string(dv.Value)
            name_item = QStandardItem(name)
            vitem = QStandardItem(string)
            vitem.setData(dv.Value)
            self.model.appendRow([name_item, vitem, QStandardItem(dv.Value.VariantType.name)])
            if name == "Value":
                string = val_to_string(dv.ServerTimestamp)
                name_item.appendRow([QStandardItem("Server Timestamp"), QStandardItem(string), QStandardItem(ua.VariantType.DateTime.name)])
                string = val_to_string(dv.SourceTimestamp)
                name_item.appendRow([QStandardItem("Source Timestamp"), QStandardItem(string), QStandardItem(ua.VariantType.DateTime.name)])
Exemplo n.º 38
0
class DataPanel(QSplitter):
    def __init__(self, app):
        super(DataPanel, self).__init__(app)

        self.app = app
        self.data = {}

        self.setOrientation(Qt.Horizontal)

        self._key_list_model = QStandardItemModel(0, 1)
        self.key_lists = DwarfListView(parent=self.app)
        self.key_lists.setHeaderHidden(True)
        self.key_lists.setModel(self._key_list_model)
        self.key_lists.selectionModel().selectionChanged.connect(
            self.item_selected)
        self.key_lists.setContextMenuPolicy(Qt.CustomContextMenu)
        self.key_lists.customContextMenuRequested.connect(
            self._on_context_menu)
        self.addWidget(self.key_lists)

        self.editor = QPlainTextEdit()
        self.addWidget(self.editor)

        self.hex_view = HexEditor(self.app)
        self.hex_view.have_context_menu = False
        self.hex_view.setVisible(False)
        self.addWidget(self.hex_view)
        #self.setStretchFactor(0, 8)
        self.setStretchFactor(1, 4)
        self.setStretchFactor(2, 4)

    def clear(self):
        self._key_list_model.clear()
        self.editor.setPlainText('')
        self.hex_view.clear_panel()

    def append_data(self, data_type, key, text_data):
        if key not in self.data:
            self._key_list_model.appendRow([QStandardItem(key)])
        self.data[key] = [data_type, text_data]

    def item_selected(self, item1, item2):
        item = self._key_list_model.itemFromIndex(item1.indexes()[0])
        if self.data[item.text()][0] == 'plain':
            self.hex_view.setVisible(False)
            self.editor.setVisible(True)
            self.editor.setPlainText(self.data[item.text()][1])
        else:
            data = self.data[item.text()][1]
            try:
                as_tx = data.decode('utf8')
                self.editor.setVisible(True)
                self.editor.setPlainText(as_tx)
            except:
                self.editor.setVisible(False)
            self.hex_view.setVisible(True)
            self.hex_view.bytes_per_line = 16
            self.hex_view.set_data(data)

    def _on_context_menu(self, pos):
        context_menu = QMenu(self)

        index = self.key_lists.indexAt(pos).row()
        if index != -1:
            context_menu.addAction('Clear', self.clear)
            global_pt = self.key_lists.mapToGlobal(pos)
            context_menu.exec(global_pt)
Exemplo n.º 39
0
class StackImages(QWidget):
    def __init__(self, fits_file, settings):
        QWidget.__init__(self)
        self.fits_file = fits_file
        self.ui = Ui_StackImages()
        self.ui.setupUi(self)
        self.settings = settings
        self.degrees = 0. # TODO 
        self.files_model = QStandardItemModel()
        self.files_model.setHorizontalHeaderLabels(['File', 'Quality', 'Align'])
        self.ui.files.setModel(self.files_model)
        self.__add_file_to_model(fits_file)
        self.plot = QtCommons.nestWidget(self.ui.plot, QImPlotWidget(self.__files_data()[0]['data'], cmap='gray'))
        self.__set_ref(0)
        self.toolbar = QToolBar()
        self.add = self.toolbar.addAction('Add', lambda: open_files_sticky('Open FITS Images',FITS_IMG_EXTS, self.__open, settings, IMPORT_IMG, parent=self ))
        self.remove = self.toolbar.addAction('Remove', self.__remove_selected_rows)
        self.reference_action = self.toolbar.addAction('Reference', lambda: self.__set_ref(self.ui.files.selectionModel().selectedRows()[0].row() ) )
        self.toolbar.addAction('Select alignment region', lambda: self.plot.add_rectangle_selector('select_align', self.__alignment_region_selected))
        self.toolbar.addAction('Rotate', lambda: self.rotate_dialog.show() )
        self.ui.files.selectionModel().selectionChanged.connect(lambda sel, unsel: self.__selection_changed() )
        self.ui.files.clicked.connect(lambda index: self.__draw_image(index.row()))
        #self.accepted.connect(self.stack)
        self.__selection_changed()
        
    def __selection_changed(self):
        sel = len(self.ui.files.selectionModel().selectedRows())
        self.remove.setEnabled(sel)
        self.reference_action.setEnabled(sel == 1)
        
    def __draw_image(self,index):
        image_view = self.plot.axes_image
        image_view.set_data(self.files_model.item(index).data()['data'])
        image_view.figure.canvas.draw()
        
    def __open(self, files):
        existing_files = [d['file'] for d in self.__files_data()]
        progress = QProgressDialog("Loading files", None, 0, len(files), self);
        progress.setWindowModality(Qt.WindowModal);
        progress.show()
        for index, file in enumerate(files):
            progress.setValue(index+1)
            QApplication.instance().processEvents()
            if file not in existing_files:
                self.__add_file(fits.open(file))
        
    def __row_index(self, data):
        return [i for i, d in enumerate(self.__files_data()) if d['file'] == data['file']][0]
    
    def __add_file_to_model(self, fits_file):
        item = QStandardItem(os.path.basename(fits_file.filename()))
        data = fits_file[0].data
        data = scipy.ndimage.interpolation.rotate(data, self.degrees, reshape=True, order=5, mode='constant')
        spatial = data.sum(1)
        profile = data.sum(0)
        roots = UnivariateSpline(range(0, len(spatial)), spatial-np.max(spatial)/2, s=0.2, k=3).roots()
        quality = roots[1]-roots[0]
        item.setData({'file': fits_file.filename(), 'fits': fits_file, 'data': data, 'spatial': spatial, 'profile': profile, 'quality': quality})
        
        offset = QStandardItem('N/A') # TODO

        quality_item = QStandardItem("")
        self.files_model.appendRow([item, quality_item, offset])
        return item
    
    def __add_file(self, fits_file):
        item = self.__add_file_to_model(fits_file)
        if self.files_model.rowCount() == 1:
            self.__set_ref(0)
        else:
            self.align(item.data())
        self.__update_qualities()
        
    def __update_qualities(self):
        qualities = [d['quality'] for d in self.__files_data()]
        self.qualities = (min(qualities), max(qualities))
        for index in range(0, self.files_model.rowCount()):
            self.files_model.item(index, 1).setText("{}%".format(self.__quality_percent(self.files_model.item(index).data()['quality'])))
        
    def __quality_percent(self, quality):
        return 100. - (100. * (quality-self.qualities[0]) / (self.qualities[1]-self.qualities[0]))
        
    def align(self, data):
        if data['file'] == self.reference['file']:
            self.__update_offset(data, (0, 0))
            return
        offset_range = lambda n: range(1-int(n), int(n)-1)
        offsets = lambda name, indexes: [ (pearsonr(self.reference[name][indexes[0]:indexes[1]], data[name][indexes[0]-offset:indexes[1]-offset] )[0], offset) for offset in offset_range(indexes[0]) ]
        x_offset = sorted(offsets('profile', self.reference_indexes['h']), key=lambda x: x[0])[-1]
        y_offset = sorted(offsets('spatial', self.reference_indexes['v']), key=lambda y: y[0])[-1]
        self.__update_offset(data, (x_offset[1], y_offset[1]))
        
    def __update_offset(self, data, offset):
        row = self.__row_index(data)
        self.files_model.item(row, 2).setText('{}, {}'.format(offset[0], offset[1]))
        data.update({'offset': {'x': offset[0], 'y': offset[1]}})
        self.files_model.item(row).setData(data)
        
    def __files_data(self):
        return [self.files_model.item(i).data() for i in range(0, self.files_model.rowCount())]
        
    def __remove_selected_rows(self):
        for row in sorted([r.row() for r in self.ui.files.selectionModel().selectedRows()], reverse=True):
            self.files_model.removeRows(row, 1)
        if self.files_model.rowCount() == 0:
            return
        if len([f for f in self.__files_data() if f['file'] == self.reference['file']]) == 0:
            self.__set_ref(0)
            
    def __set_ref(self, index):
        self.reference = self.files_model.item(index).data()
        self.rotate_dialog = RotateImageDialog(self.fits_file, 0)
        self.rotate_dialog.rotated.connect(self.__rotated)
        indexes = lambda data: (int(len(data)/4), int(len(data)/4*3))
        self.__set_reference_indexes(indexes(self.reference['profile']), indexes(self.reference['spatial']) )
        #self.reference_indexes = { 'h': indexes(self.reference['profile']), 'v': indexes(self.reference['spatial']) }
        for data in self.__files_data() :
            self.align(data)
            
    def __rotated(self):
        self.degrees = self.rotate_dialog.degrees()
        for index in range(0, self.files_model.rowCount()):
            self.files_model.removeRow(index)
        self.__add_file(self.fits_file)
        self.__draw_image(0)
            
    def __alignment_region_selected(self, eclick, erelease):
        self.__set_reference_indexes((eclick.xdata, erelease.xdata), (eclick.ydata, erelease.ydata))
        
    def __set_reference_indexes(self, x, y):
        self.reference_indexes = { 'h': x, 'v': y }
        self.__draw_reference_rect()
        
    def __draw_reference_rect(self):
        self.plot.rm_element('reference_indexes')
        x, y = self.reference_indexes['h'], self.reference_indexes['v']
        rect = Rectangle((x[0], y[0]), x[1]-x[0], y[1]-y[0], fill=True, alpha=0.3, color='green')
        self.plot.figure.axes[0].add_artist(rect)
        self.plot.add_element(rect, 'reference_indexes')
        self.plot.figure.canvas.draw()
        
    def stack(self):
        dataset = self.__files_data()
        median = MedianStacker(dataset).median()
        self.fits_file[0].data = median
Exemplo n.º 40
0
class Explorer(QWidget):
    """
    This class implements the diagram predicate node explorer.
    """
    def __init__(self, mainwindow):
        """
        Initialize the Explorer.
        :type mainwindow: MainWindow
        """
        super().__init__(mainwindow)
        self.expanded = {}
        self.searched = {}
        self.scrolled = {}
        self.mainview = None
        self.iconA = QIcon(':/icons/treeview-icon-attribute')
        self.iconC = QIcon(':/icons/treeview-icon-concept')
        self.iconD = QIcon(':/icons/treeview-icon-datarange')
        self.iconI = QIcon(':/icons/treeview-icon-instance')
        self.iconR = QIcon(':/icons/treeview-icon-role')
        self.iconV = QIcon(':/icons/treeview-icon-value')
        self.search = StringField(self)
        self.search.setAcceptDrops(False)
        self.search.setClearButtonEnabled(True)
        self.search.setPlaceholderText('Search...')
        self.search.setFixedHeight(30)
        self.model = QStandardItemModel(self)
        self.proxy = QSortFilterProxyModel(self)
        self.proxy.setDynamicSortFilter(False)
        self.proxy.setFilterCaseSensitivity(Qt.CaseInsensitive)
        self.proxy.setSortCaseSensitivity(Qt.CaseSensitive)
        self.proxy.setSourceModel(self.model)
        self.view = ExplorerView(mainwindow, self)
        self.view.setModel(self.proxy)
        self.mainLayout = QVBoxLayout(self)
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.mainLayout.addWidget(self.search)
        self.mainLayout.addWidget(self.view)
        self.setContentsMargins(0, 0, 0, 0)
        self.setMinimumWidth(216)
        self.setMinimumHeight(160)

        connect(self.view.doubleClicked, self.itemDoubleClicked)
        connect(self.view.pressed, self.itemPressed)
        connect(self.view.collapsed, self.itemCollapsed)
        connect(self.view.expanded, self.itemExpanded)
        connect(self.search.textChanged, self.filterItem)

    ####################################################################################################################
    #                                                                                                                  #
    #   EVENTS                                                                                                         #
    #                                                                                                                  #
    ####################################################################################################################

    def paintEvent(self, paintEvent):
        """
        This is needed for the widget to pick the stylesheet.
        :type paintEvent: QPaintEvent
        """
        option = QStyleOption()
        option.initFrom(self)
        painter = QPainter(self)
        style = self.style()
        style.drawPrimitive(QStyle.PE_Widget, option, painter, self)

    ####################################################################################################################
    #                                                                                                                  #
    #   SLOTS                                                                                                          #
    #                                                                                                                  #
    ####################################################################################################################

    @pyqtSlot('QGraphicsItem')
    def add(self, item):
        """
        Add a node in the tree view.
        :type item: AbstractItem
        """
        if item.node and item.predicate:
            parent = self.parentFor(item)
            if not parent:
                parent = ParentItem(item)
                parent.setIcon(self.iconFor(item))
                self.model.appendRow(parent)
                self.proxy.sort(0, Qt.AscendingOrder)
            child = ChildItem(item)
            child.setData(item)
            parent.appendRow(child)
            self.proxy.sort(0, Qt.AscendingOrder)

    @pyqtSlot(str)
    def filterItem(self, key):
        """
        Executed when the search box is filled with data.
        :type key: str
        """
        if self.mainview:
            self.proxy.setFilterFixedString(key)
            self.proxy.sort(Qt.AscendingOrder)
            self.searched[self.mainview] = key

    @pyqtSlot('QModelIndex')
    def itemCollapsed(self, index):
        """
        Executed when an item in the tree view is collapsed.
        :type index: QModelIndex
        """
        if self.mainview:
            if self.mainview in self.expanded:
                item = self.model.itemFromIndex(self.proxy.mapToSource(index))
                expanded = self.expanded[self.mainview]
                expanded.remove(item.text())

    @pyqtSlot('QModelIndex')
    def itemDoubleClicked(self, index):
        """
        Executed when an item in the tree view is double clicked.
        :type index: QModelIndex
        """
        item = self.model.itemFromIndex(self.proxy.mapToSource(index))
        node = item.data()
        if node:
            self.selectNode(node)
            self.focusNode(node)

    @pyqtSlot('QModelIndex')
    def itemExpanded(self, index):
        """
        Executed when an item in the tree view is expanded.
        :type index: QModelIndex
        """
        if self.mainview:
            item = self.model.itemFromIndex(self.proxy.mapToSource(index))
            if self.mainview not in self.expanded:
                self.expanded[self.mainview] = set()
            expanded = self.expanded[self.mainview]
            expanded.add(item.text())

    @pyqtSlot('QModelIndex')
    def itemPressed(self, index):
        """
        Executed when an item in the tree view is clicked.
        :type index: QModelIndex
        """
        item = self.model.itemFromIndex(self.proxy.mapToSource(index))
        node = item.data()
        if node:
            self.selectNode(node)

    @pyqtSlot('QGraphicsItem')
    def remove(self, item):
        """
        Remove a node from the tree view.
        :type item: AbstractItem
        """
        if item.node and item.predicate:
            parent = self.parentFor(item)
            if parent:
                child = self.childFor(parent, item)
                if child:
                    parent.removeRow(child.index().row())
                if not parent.rowCount():
                    self.model.removeRow(parent.index().row())

    ####################################################################################################################
    #                                                                                                                  #
    #   AUXILIARY METHODS                                                                                              #
    #                                                                                                                  #
    ####################################################################################################################

    @staticmethod
    def childFor(parent, node):
        """
        Search the item representing this node among parent children.
        :type parent: QStandardItem
        :type node: AbstractNode
        """
        key = ChildItem.key(node)
        for i in range(parent.rowCount()):
            child = parent.child(i)
            if child.text() == key:
                return child
        return None

    def parentFor(self, node):
        """
        Search the parent element of the given node.
        :type node: AbstractNode
        :rtype: QStandardItem
        """
        key = ParentItem.key(node)
        for i in self.model.findItems(key, Qt.MatchExactly):
            n = i.child(0).data()
            if node.item is n.item:
                return i
        return None

    ####################################################################################################################
    #                                                                                                                  #
    #   INTERFACE                                                                                                      #
    #                                                                                                                  #
    ####################################################################################################################

    def browse(self, view):
        """
        Set the widget to inspect the given view.
        :type view: MainView
        """
        self.reset()
        self.mainview = view

        if self.mainview:

            scene = self.mainview.scene()
            connect(scene.index.sgnItemAdded, self.add)
            connect(scene.index.sgnItemRemoved, self.remove)

            for item in scene.index.nodes():
                self.add(item)

            if self.mainview in self.expanded:
                expanded = self.expanded[self.mainview]
                for i in range(self.model.rowCount()):
                    item = self.model.item(i)
                    index = self.proxy.mapFromSource(
                        self.model.indexFromItem(item))
                    self.view.setExpanded(index, item.text() in expanded)

            key = ''
            if self.mainview in self.searched:
                key = self.searched[self.mainview]
            self.search.setText(key)

            if self.mainview in self.scrolled:
                rect = self.rect()
                item = first(self.model.findItems(
                    self.scrolled[self.mainview]))
                for i in range(self.model.rowCount()):
                    self.view.scrollTo(
                        self.proxy.mapFromSource(
                            self.model.indexFromItem(self.model.item(i))))
                    index = self.proxy.mapToSource(
                        self.view.indexAt(rect.topLeft()))
                    if self.model.itemFromIndex(index) is item:
                        break

    def reset(self):
        """
        Clear the widget from inspecting the current view.
        """
        if self.mainview:

            rect = self.rect()
            item = self.model.itemFromIndex(
                self.proxy.mapToSource(self.view.indexAt(rect.topLeft())))
            if item:
                node = item.data()
                key = ParentItem.key(node) if node else item.text()
                self.scrolled[self.mainview] = key
            else:
                self.scrolled.pop(self.mainview, None)

            try:
                scene = self.mainview.scene()
                disconnect(scene.index.sgnItemAdded, self.add)
                disconnect(scene.index.sgnItemRemoved, self.remove)
            except RuntimeError:
                pass
            finally:
                self.mainview = None

        self.model.clear()

    def flush(self, view):
        """
        Flush the cache of the given mainview.
        :type view: MainView
        """
        self.expanded.pop(view, None)
        self.searched.pop(view, None)
        self.scrolled.pop(view, None)

    def iconFor(self, node):
        """
        Returns the icon for the given node.
        :type node:
        """
        if node.item is Item.AttributeNode:
            return self.iconA
        if node.item is Item.ConceptNode:
            return self.iconC
        if node.item is Item.ValueDomainNode:
            return self.iconD
        if node.item is Item.ValueRestrictionNode:
            return self.iconD
        if node.item is Item.IndividualNode:
            if node.identity is Identity.Instance:
                return self.iconI
            if node.identity is Identity.Value:
                return self.iconV
        if node.item is Item.RoleNode:
            return self.iconR

    def focusNode(self, node):
        """
        Focus the given node in the main view.
        :type node: AbstractNode
        """
        if self.mainview:
            self.mainview.centerOn(node)

    def selectNode(self, node):
        """
        Select the given node in the main view.
        :type node: AbstractNode
        """
        if self.mainview:
            scene = self.mainview.scene()
            scene.clearSelection()
            node.setSelected(True)
Exemplo n.º 41
0
class ContextPanel(QTabWidget):
    # consts
    CONTEXT_TYPE_NATIVE = 0
    CONTEXT_TYPE_JAVA = 1

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

    def __init__(self, parent=None):
        super(ContextPanel, 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 == 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)
        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.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("")
Exemplo n.º 42
0
class comics_project_manager_docker(DockWidget):
    setupDictionary = {}
    stringName = i18n("Comics Manager")
    projecturl = None

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

        # Setup layout:
        base = QHBoxLayout()
        widget = QWidget()
        widget.setLayout(base)
        baseLayout = QSplitter()
        base.addWidget(baseLayout)
        self.setWidget(widget)
        buttonLayout = QVBoxLayout()
        buttonBox = QWidget()
        buttonBox.setLayout(buttonLayout)
        baseLayout.addWidget(buttonBox)

        # Comic page list and pages model
        self.comicPageList = QListView()
        self.comicPageList.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.comicPageList.setDragEnabled(True)
        self.comicPageList.setDragDropMode(QAbstractItemView.InternalMove)
        self.comicPageList.setDefaultDropAction(Qt.MoveAction)
        self.comicPageList.setAcceptDrops(True)
        self.comicPageList.setItemDelegate(comic_page_delegate())
        self.pagesModel = QStandardItemModel()
        self.comicPageList.doubleClicked.connect(self.slot_open_page)
        self.comicPageList.setIconSize(QSize(128, 128))
        # self.comicPageList.itemDelegate().closeEditor.connect(self.slot_write_description)
        self.pagesModel.layoutChanged.connect(self.slot_write_config)
        self.pagesModel.rowsInserted.connect(self.slot_write_config)
        self.pagesModel.rowsRemoved.connect(self.slot_write_config)
        self.pagesModel.rowsMoved.connect(self.slot_write_config)
        self.comicPageList.setModel(self.pagesModel)
        pageBox = QWidget()
        pageBox.setLayout(QVBoxLayout())
        zoomSlider = QSlider(Qt.Horizontal, None)
        zoomSlider.setRange(1, 8)
        zoomSlider.setValue(4)
        zoomSlider.setTickInterval(1)
        zoomSlider.setMinimumWidth(10)
        zoomSlider.valueChanged.connect(self.slot_scale_thumbnails)
        self.projectName = Elided_Text_Label()
        pageBox.layout().addWidget(self.projectName)
        pageBox.layout().addWidget(zoomSlider)
        pageBox.layout().addWidget(self.comicPageList)
        baseLayout.addWidget(pageBox)

        self.btn_project = QToolButton()
        self.btn_project.setPopupMode(QToolButton.MenuButtonPopup)
        self.btn_project.setSizePolicy(QSizePolicy.Minimum,
                                       QSizePolicy.Minimum)
        menu_project = QMenu()
        self.action_new_project = QAction(i18n("New Project"), self)
        self.action_new_project.triggered.connect(self.slot_new_project)
        self.action_load_project = QAction(i18n("Open Project"), self)
        self.action_load_project.triggered.connect(self.slot_open_config)
        menu_project.addAction(self.action_new_project)
        menu_project.addAction(self.action_load_project)
        self.btn_project.setMenu(menu_project)
        self.btn_project.setDefaultAction(self.action_load_project)
        buttonLayout.addWidget(self.btn_project)

        # Settings dropdown with actions for the different settings menus.
        self.btn_settings = QToolButton()
        self.btn_settings.setPopupMode(QToolButton.MenuButtonPopup)
        self.btn_settings.setSizePolicy(QSizePolicy.Minimum,
                                        QSizePolicy.Minimum)
        self.action_edit_project_settings = QAction(i18n("Project Settings"),
                                                    self)
        self.action_edit_project_settings.triggered.connect(
            self.slot_edit_project_settings)
        self.action_edit_meta_data = QAction(i18n("Meta Data"), self)
        self.action_edit_meta_data.triggered.connect(self.slot_edit_meta_data)
        self.action_edit_export_settings = QAction(i18n("Export Settings"),
                                                   self)
        self.action_edit_export_settings.triggered.connect(
            self.slot_edit_export_settings)
        menu_settings = QMenu()
        menu_settings.addAction(self.action_edit_project_settings)
        menu_settings.addAction(self.action_edit_meta_data)
        menu_settings.addAction(self.action_edit_export_settings)
        self.btn_settings.setDefaultAction(self.action_edit_project_settings)
        self.btn_settings.setMenu(menu_settings)
        buttonLayout.addWidget(self.btn_settings)
        self.btn_settings.setDisabled(True)

        # Add page drop down with different page actions.
        self.btn_add_page = QToolButton()
        self.btn_add_page.setPopupMode(QToolButton.MenuButtonPopup)
        self.btn_add_page.setSizePolicy(QSizePolicy.Minimum,
                                        QSizePolicy.Minimum)

        self.action_add_page = QAction(i18n("Add Page"), self)
        self.action_add_page.triggered.connect(self.slot_add_new_page_single)
        self.action_add_template = QAction(i18n("Add Page from Template"),
                                           self)
        self.action_add_template.triggered.connect(
            self.slot_add_new_page_from_template)
        self.action_add_existing = QAction(i18n("Add Existing Pages"), self)
        self.action_add_existing.triggered.connect(self.slot_add_page_from_url)
        self.action_remove_selected_page = QAction(i18n("Remove Page"), self)
        self.action_remove_selected_page.triggered.connect(
            self.slot_remove_selected_page)
        self.action_resize_all_pages = QAction(i18n("Batch Resize"), self)
        self.action_resize_all_pages.triggered.connect(self.slot_batch_resize)
        self.btn_add_page.setDefaultAction(self.action_add_page)
        self.action_show_page_viewer = QAction(i18n("View Page In Window"),
                                               self)
        self.action_show_page_viewer.triggered.connect(
            self.slot_show_page_viewer)
        self.action_scrape_authors = QAction(i18n("Scrape Author Info"), self)
        self.action_scrape_authors.setToolTip(
            i18n(
                "Search for author information in documents and add it to the author list. This does not check for duplicates."
            ))
        self.action_scrape_authors.triggered.connect(
            self.slot_scrape_author_list)
        self.action_scrape_translations = QAction(
            i18n("Scrape Text for Translation"), self)
        self.action_scrape_translations.triggered.connect(
            self.slot_scrape_translations)
        actionList = []
        menu_page = QMenu()
        actionList.append(self.action_add_page)
        actionList.append(self.action_add_template)
        actionList.append(self.action_add_existing)
        actionList.append(self.action_remove_selected_page)
        actionList.append(self.action_resize_all_pages)
        actionList.append(self.action_show_page_viewer)
        actionList.append(self.action_scrape_authors)
        actionList.append(self.action_scrape_translations)
        menu_page.addActions(actionList)
        self.btn_add_page.setMenu(menu_page)
        buttonLayout.addWidget(self.btn_add_page)
        self.btn_add_page.setDisabled(True)

        self.comicPageList.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.comicPageList.addActions(actionList)

        # Export button that... exports.
        self.btn_export = QPushButton(i18n("Export Comic"))
        self.btn_export.clicked.connect(self.slot_export)
        buttonLayout.addWidget(self.btn_export)
        self.btn_export.setDisabled(True)

        self.btn_project_url = QPushButton(i18n("Copy Location"))
        self.btn_project_url.setToolTip(
            i18n(
                "Copies the path of the project to the clipboard. Useful for quickly copying to a file manager or the like."
            ))
        self.btn_project_url.clicked.connect(self.slot_copy_project_url)
        self.btn_project_url.setDisabled(True)
        buttonLayout.addWidget(self.btn_project_url)

        self.page_viewer_dialog = comics_project_page_viewer.comics_project_page_viewer(
        )

        Application.notifier().imageSaved.connect(
            self.slot_check_for_page_update)

        buttonLayout.addItem(
            QSpacerItem(0, 0, QSizePolicy.Minimum,
                        QSizePolicy.MinimumExpanding))

    """
    Open the config file and load the json file into a dictionary.
    """

    def slot_open_config(self):
        self.path_to_config = QFileDialog.getOpenFileName(
            caption=i18n("Please select the JSON comic config file."),
            filter=str(i18n("JSON files") + "(*.json)"))[0]
        if os.path.exists(self.path_to_config) is True:
            configFile = open(self.path_to_config,
                              "r",
                              newline="",
                              encoding="utf-16")
            self.setupDictionary = json.load(configFile)
            self.projecturl = os.path.dirname(str(self.path_to_config))
            configFile.close()
            self.load_config()

    """
    Further config loading.
    """

    def load_config(self):
        self.projectName.setMainText(
            text=str(self.setupDictionary["projectName"]))
        self.fill_pages()
        self.btn_settings.setEnabled(True)
        self.btn_add_page.setEnabled(True)
        self.btn_export.setEnabled(True)
        self.btn_project_url.setEnabled(True)

    """
    Fill the pages model with the pages from the pages list.
    """

    def fill_pages(self):
        self.loadingPages = True
        self.pagesModel.clear()
        pagesList = []
        if "pages" in self.setupDictionary.keys():
            pagesList = self.setupDictionary["pages"]
        progress = QProgressDialog()
        progress.setMinimum(0)
        progress.setMaximum(len(pagesList))
        progress.setWindowTitle(i18n("Loading Pages..."))
        for url in pagesList:
            absurl = os.path.join(self.projecturl, url)
            if (os.path.exists(absurl)):
                #page = Application.openDocument(absurl)
                page = zipfile.ZipFile(absurl, "r")
                thumbnail = QImage.fromData(page.read("preview.png"))
                pageItem = QStandardItem()
                dataList = self.get_description_and_title(
                    page.read("documentinfo.xml"))
                if (dataList[0].isspace() or len(dataList[0]) < 1):
                    dataList[0] = os.path.basename(url)
                pageItem.setText(dataList[0].replace("_", " "))
                pageItem.setDragEnabled(True)
                pageItem.setDropEnabled(False)
                pageItem.setEditable(False)
                pageItem.setIcon(QIcon(QPixmap.fromImage(thumbnail)))
                pageItem.setData(dataList[1], role=CPE.DESCRIPTION)
                pageItem.setData(url, role=CPE.URL)
                pageItem.setData(dataList[2], role=CPE.KEYWORDS)
                pageItem.setData(dataList[3], role=CPE.LASTEDIT)
                pageItem.setData(dataList[4], role=CPE.EDITOR)
                pageItem.setToolTip(url)
                page.close()
                self.pagesModel.appendRow(pageItem)
                progress.setValue(progress.value() + 1)
        progress.setValue(len(pagesList))
        self.loadingPages = False

    """
    Function that is triggered by the zoomSlider
    Resizes the thumbnails.
    """

    def slot_scale_thumbnails(self, multiplier=4):
        self.comicPageList.setIconSize(QSize(multiplier * 32, multiplier * 32))

    """
    Function that takes the documentinfo.xml and parses it for the title, subject and abstract tags,
    to get the title and description.
    
    @returns a stringlist with the name on 0 and the description on 1.
    """

    def get_description_and_title(self, string):
        xmlDoc = ET.fromstring(string)
        calligra = str("{http://www.calligra.org/DTD/document-info}")
        name = ""
        if ET.iselement(xmlDoc[0].find(calligra + 'title')):
            name = xmlDoc[0].find(calligra + 'title').text
            if name is None:
                name = " "
        desc = ""
        if ET.iselement(xmlDoc[0].find(calligra + 'subject')):
            desc = xmlDoc[0].find(calligra + 'subject').text
        if desc is None or desc.isspace() or len(desc) < 1:
            if ET.iselement(xmlDoc[0].find(calligra + 'abstract')):
                desc = xmlDoc[0].find(calligra + 'abstract').text
                if desc is not None:
                    if desc.startswith("<![CDATA["):
                        desc = desc[len("<![CDATA["):]
                    if desc.startswith("]]>"):
                        desc = desc[:-len("]]>")]
        keywords = ""
        if ET.iselement(xmlDoc[0].find(calligra + 'keyword')):
            keywords = xmlDoc[0].find(calligra + 'keyword').text
        date = ""
        if ET.iselement(xmlDoc[0].find(calligra + 'date')):
            date = xmlDoc[0].find(calligra + 'date').text
        author = []
        if ET.iselement(xmlDoc[1].find(calligra + 'creator-first-name')):
            string = xmlDoc[1].find(calligra + 'creator-first-name').text
            if string is not None:
                author.append(string)
        if ET.iselement(xmlDoc[1].find(calligra + 'creator-last-name')):
            string = xmlDoc[1].find(calligra + 'creator-last-name').text
            if string is not None:
                author.append(string)
        if ET.iselement(xmlDoc[1].find(calligra + 'full-name')):
            string = xmlDoc[1].find(calligra + 'full-name').text
            if string is not None:
                author.append(string)

        return [name, desc, keywords, date, " ".join(author)]

    """
    Scrapes authors from the author data in the document info and puts them into the author list.
    Doesn't check for duplicates.
    """

    def slot_scrape_author_list(self):
        listOfAuthors = []
        if "authorList" in self.setupDictionary.keys():
            listOfAuthors = self.setupDictionary["authorList"]
        if "pages" in self.setupDictionary.keys():
            for relurl in self.setupDictionary["pages"]:
                absurl = os.path.join(self.projecturl, relurl)
                page = zipfile.ZipFile(absurl, "r")
                xmlDoc = ET.fromstring(page.read("documentinfo.xml"))
                calligra = str("{http://www.calligra.org/DTD/document-info}")
                authorelem = xmlDoc.find(calligra + 'author')
                author = {}
                if ET.iselement(authorelem.find(calligra + 'full-name')):
                    author["nickname"] = str(
                        authorelem.find(calligra + 'full-name').text)

                if ET.iselement(
                        authorelem.find(calligra + 'creator-first-name')):
                    author["first-name"] = str(
                        authorelem.find(calligra + 'creator-first-name').text)

                if ET.iselement(authorelem.find(calligra + 'initial')):
                    author["initials"] = str(
                        authorelem.find(calligra + 'initial').text)

                if ET.iselement(authorelem.find(calligra +
                                                'creator-last-name')):
                    author["last-name"] = str(
                        authorelem.find(calligra + 'creator-last-name').text)

                if ET.iselement(authorelem.find(calligra + 'email')):
                    author["email"] = str(
                        authorelem.find(calligra + 'email').text)

                if ET.iselement(authorelem.find(calligra + 'contact')):
                    contact = authorelem.find(calligra + 'contact')
                    contactMode = contact.get("type")
                    if contactMode == "email":
                        author["email"] = str(contact.text)
                    if contactMode == "homepage":
                        author["homepage"] = str(contact.text)

                if ET.iselement(authorelem.find(calligra + 'position')):
                    author["role"] = str(
                        authorelem.find(calligra + 'position').text)
                listOfAuthors.append(author)
                page.close()
        self.setupDictionary["authorList"] = listOfAuthors

    """
    Edit the general project settings like the project name, concept, pages location, export location, template location, metadata
    """

    def slot_edit_project_settings(self):
        dialog = comics_project_settings_dialog.comics_project_details_editor(
            self.projecturl)
        dialog.setConfig(self.setupDictionary, self.projecturl)

        if dialog.exec_() == QDialog.Accepted:
            self.setupDictionary = dialog.getConfig(self.setupDictionary)
            self.slot_write_config()
            self.projectName.setMainText(
                str(self.setupDictionary["projectName"]))

    """
    This allows users to select existing pages and add them to the pages list. The pages are currently not copied to the pages folder. Useful for existing projects.
    """

    def slot_add_page_from_url(self):
        # get the pages.
        urlList = QFileDialog.getOpenFileNames(
            caption=i18n("Which existing pages to add?"),
            directory=self.projecturl,
            filter=str(i18n("Krita files") + "(*.kra)"))[0]

        # get the existing pages list.
        pagesList = []
        if "pages" in self.setupDictionary.keys():
            pagesList = self.setupDictionary["pages"]

        # And add each url in the url list to the pages list and the model.
        for url in urlList:
            if self.projecturl not in urlList:
                newUrl = os.path.join(self.projecturl,
                                      self.setupDictionary["pagesLocation"],
                                      os.path.basename(url))
                shutil.move(url, newUrl)
                url = newUrl
            relative = os.path.relpath(url, self.projecturl)
            if url not in pagesList:
                page = zipfile.ZipFile(url, "r")
                thumbnail = QImage.fromData(page.read("preview.png"))
                dataList = self.get_description_and_title(
                    page.read("documentinfo.xml"))
                if (dataList[0].isspace() or len(dataList[0]) < 1):
                    dataList[0] = os.path.basename(url)
                newPageItem = QStandardItem()
                newPageItem.setIcon(QIcon(QPixmap.fromImage(thumbnail)))
                newPageItem.setDragEnabled(True)
                newPageItem.setDropEnabled(False)
                newPageItem.setEditable(False)
                newPageItem.setText(dataList[0].replace("_", " "))
                newPageItem.setData(dataList[1], role=CPE.DESCRIPTION)
                newPageItem.setData(relative, role=CPE.URL)
                newPageItem.setData(dataList[2], role=CPE.KEYWORDS)
                newPageItem.setData(dataList[3], role=CPE.LASTEDIT)
                newPageItem.setData(dataList[4], role=CPE.EDITOR)
                newPageItem.setToolTip(relative)
                page.close()
                self.pagesModel.appendRow(newPageItem)

    """
    Remove the selected page from the list of pages. This does not remove it from disk(far too dangerous).
    """

    def slot_remove_selected_page(self):
        index = self.comicPageList.currentIndex()
        self.pagesModel.removeRow(index.row())

    """
    This function adds a new page from the default template. If there's no default template, or the file does not exist, it will 
    show the create/import template dialog. It will remember the selected item as the default template.
    """

    def slot_add_new_page_single(self):
        templateUrl = "templatepage"
        templateExists = False

        if "singlePageTemplate" in self.setupDictionary.keys():
            templateUrl = self.setupDictionary["singlePageTemplate"]
        if os.path.exists(os.path.join(self.projecturl, templateUrl)):
            templateExists = True

        if templateExists is False:
            if "templateLocation" not in self.setupDictionary.keys():
                self.setupDictionary["templateLocation"] = os.path.relpath(
                    QFileDialog.getExistingDirectory(
                        caption=i18n("Where are the templates located?"),
                        options=QFileDialog.ShowDirsOnly), self.projecturl)

            templateDir = os.path.join(
                self.projecturl, self.setupDictionary["templateLocation"])
            template = comics_template_dialog.comics_template_dialog(
                templateDir)

            if template.exec_() == QDialog.Accepted:
                templateUrl = os.path.relpath(template.url(), self.projecturl)
                self.setupDictionary["singlePageTemplate"] = templateUrl
        if os.path.exists(os.path.join(self.projecturl, templateUrl)):
            self.add_new_page(templateUrl)

    """
    This function always asks for a template showing the new template window. This allows users to have multiple different
    templates created for back covers, spreads, other and have them accessible, while still having the convenience of a singular
    "add page" that adds a default.
    """

    def slot_add_new_page_from_template(self):
        if "templateLocation" not in self.setupDictionary.keys():
            self.setupDictionary["templateLocation"] = os.path.relpath(
                QFileDialog.getExistingDirectory(
                    caption=i18n("Where are the templates located?"),
                    options=QFileDialog.ShowDirsOnly), self.projecturl)

        templateDir = os.path.join(self.projecturl,
                                   self.setupDictionary["templateLocation"])
        template = comics_template_dialog.comics_template_dialog(templateDir)

        if template.exec_() == QDialog.Accepted:
            templateUrl = os.path.relpath(template.url(), self.projecturl)
            self.add_new_page(templateUrl)

    """
    This is the actual function that adds the template using the template url.
    It will attempt to name the new page projectName+number.
    """

    def add_new_page(self, templateUrl):

        # check for page list and or location.
        pagesList = []
        if "pages" in self.setupDictionary.keys():
            pagesList = self.setupDictionary["pages"]
        if not "pageNumber" in self.setupDictionary.keys():
            self.setupDictionary['pageNumber'] = 0

        if (str(self.setupDictionary["pagesLocation"]).isspace()):
            self.setupDictionary["pagesLocation"] = os.path.relpath(
                QFileDialog.getExistingDirectory(
                    caption=i18n("Where should the pages go?"),
                    options=QFileDialog.ShowDirsOnly), self.projecturl)

        # Search for the possible name.
        extraUnderscore = str()
        if str(self.setupDictionary["projectName"])[-1].isdigit():
            extraUnderscore = "_"
        self.setupDictionary['pageNumber'] += 1
        pageName = str(self.setupDictionary["projectName"]).replace(
            " ", "_") + extraUnderscore + str(
                format(self.setupDictionary['pageNumber'], "03d"))
        url = os.path.join(str(self.setupDictionary["pagesLocation"]),
                           pageName + ".kra")

        # open the page by opening the template and resaving it, or just opening it.
        absoluteUrl = os.path.join(self.projecturl, url)
        if (os.path.exists(absoluteUrl)):
            newPage = Application.openDocument(absoluteUrl)
        else:
            booltemplateExists = os.path.exists(
                os.path.join(self.projecturl, templateUrl))
            if booltemplateExists is False:
                templateUrl = os.path.relpath(
                    QFileDialog.getOpenFileName(
                        caption=i18n(
                            "Which image should be the basis the new page?"),
                        directory=self.projecturl,
                        filter=str(i18n("Krita files") + "(*.kra)"))[0],
                    self.projecturl)
            newPage = Application.openDocument(
                os.path.join(self.projecturl, templateUrl))
            newPage.waitForDone()
            newPage.setFileName(absoluteUrl)
            newPage.setName(pageName.replace("_", " "))
            newPage.save()
            newPage.waitForDone()

        # Get out the extra data for the standard item.
        newPageItem = QStandardItem()
        newPageItem.setIcon(
            QIcon(QPixmap.fromImage(newPage.thumbnail(256, 256))))
        newPageItem.setDragEnabled(True)
        newPageItem.setDropEnabled(False)
        newPageItem.setEditable(False)
        newPageItem.setText(pageName.replace("_", " "))
        newPageItem.setData("", role=CPE.DESCRIPTION)
        newPageItem.setData(url, role=CPE.URL)
        newPageItem.setData("", role=CPE.KEYWORDS)
        newPageItem.setData("", role=CPE.LASTEDIT)
        newPageItem.setData("", role=CPE.EDITOR)
        newPageItem.setToolTip(url)

        # close page document.
        while os.path.exists(absoluteUrl) is False:
            qApp.processEvents()

        newPage.close()

        # add item to page.
        self.pagesModel.appendRow(newPageItem)

    """
    Write to the json configuration file.
    This also checks the current state of the pages list.
    """

    def slot_write_config(self):

        # Don't load when the pages are still being loaded, otherwise we'll be overwriting our own pages list.
        if (self.loadingPages is False):
            print("CPMT: writing comic configuration...")

            # Generate a pages list from the pagesmodel.
            pagesList = []
            for i in range(self.pagesModel.rowCount()):
                index = self.pagesModel.index(i, 0)
                url = str(self.pagesModel.data(index, role=CPE.URL))
                if url not in pagesList:
                    pagesList.append(url)
            self.setupDictionary["pages"] = pagesList

            # Save to our json file.
            configFile = open(self.path_to_config,
                              "w",
                              newline="",
                              encoding="utf-16")
            json.dump(self.setupDictionary,
                      configFile,
                      indent=4,
                      sort_keys=True,
                      ensure_ascii=False)
            configFile.close()
            print("CPMT: done")

    """
    Open a page in the pagesmodel in Krita.
    """

    def slot_open_page(self, index):
        if index.column() is 0:
            # Get the absolute url from the relative one in the pages model.
            absoluteUrl = os.path.join(
                self.projecturl, str(self.pagesModel.data(index,
                                                          role=CPE.URL)))

            # Make sure the page exists.
            if os.path.exists(absoluteUrl):
                page = Application.openDocument(absoluteUrl)

                # Set the title to the filename if it was empty. It looks a bit neater.
                if page.name().isspace or len(page.name()) < 1:
                    page.setName(
                        str(self.pagesModel.data(index,
                                                 role=Qt.DisplayRole)).replace(
                                                     "_", " "))

                # Add views for the document so the user can use it.
                Application.activeWindow().addView(page)
                Application.setActiveDocument(page)
            else:
                print(
                    "CPMT: The page cannot be opened because the file doesn't exist:",
                    absoluteUrl)

    """
    Call up the metadata editor dialog. Only when the dialog is "Accepted" will the metadata be saved.
    """

    def slot_edit_meta_data(self):
        dialog = comics_metadata_dialog.comic_meta_data_editor()

        dialog.setConfig(self.setupDictionary)
        if (dialog.exec_() == QDialog.Accepted):
            self.setupDictionary = dialog.getConfig(self.setupDictionary)
            self.slot_write_config()

    """
    An attempt at making the description editable from the comic pages list.
    It is currently not working because ZipFile has no overwrite mechanism,
    and I don't have the energy to write one yet.
    """

    def slot_write_description(self, index):

        for row in range(self.pagesModel.rowCount()):
            index = self.pagesModel.index(row, 1)
            indexUrl = self.pagesModel.index(row, 0)
            absoluteUrl = os.path.join(
                self.projecturl,
                str(self.pagesModel.data(indexUrl, role=CPE.URL)))
            page = zipfile.ZipFile(absoluteUrl, "a")
            xmlDoc = ET.ElementTree()
            ET.register_namespace("",
                                  "http://www.calligra.org/DTD/document-info")
            location = os.path.join(self.projecturl, "documentinfo.xml")
            xmlDoc.parse(location)
            xmlroot = ET.fromstring(page.read("documentinfo.xml"))
            calligra = "{http://www.calligra.org/DTD/document-info}"
            aboutelem = xmlroot.find(calligra + 'about')
            if ET.iselement(aboutelem.find(calligra + 'subject')):
                desc = aboutelem.find(calligra + 'subject')
                desc.text = self.pagesModel.data(index, role=Qt.EditRole)
                xmlstring = ET.tostring(xmlroot,
                                        encoding='unicode',
                                        method='xml',
                                        short_empty_elements=False)
                page.writestr(zinfo_or_arcname="documentinfo.xml",
                              data=xmlstring)
                for document in Application.documents():
                    if str(document.fileName()) == str(absoluteUrl):
                        document.setDocumentInfo(xmlstring)
            page.close()

    """
    Calls up the export settings dialog. Only when accepted will the configuration be written.
    """

    def slot_edit_export_settings(self):
        dialog = comics_export_dialog.comic_export_setting_dialog()
        dialog.setConfig(self.setupDictionary)

        if (dialog.exec_() == QDialog.Accepted):
            self.setupDictionary = dialog.getConfig(self.setupDictionary)
            self.slot_write_config()

    """
    Export the comic. Won't work without export settings set.
    """

    def slot_export(self):

        #ensure there is a unique identifier
        if "uuid" not in self.setupDictionary.keys():
            uuid = str()
            if "acbfID" in self.setupDictionary.keys():
                uuid = str(self.setupDictionary["acbfID"])
            else:
                uuid = QUuid.createUuid().toString()
            self.setupDictionary["uuid"] = uuid

        exporter = comics_exporter.comicsExporter()
        exporter.set_config(self.setupDictionary, self.projecturl)
        exportSuccess = exporter.export()
        if exportSuccess:
            print(
                "CPMT: Export success! The files have been written to the export folder!"
            )
            QMessageBox.information(
                self, i18n("Export success"),
                i18n("The files have been written to the export folder."),
                QMessageBox.Ok)

    """
    Calls up the comics project setup wizard so users can create a new json file with the basic information.
    """

    def slot_new_project(self):
        setup = comics_project_setup_wizard.ComicsProjectSetupWizard()
        setup.showDialog()

    """
    This is triggered by any document save.
    It checks if the given url in in the pages list, and if so,
    updates the appropriate page thumbnail.
    This helps with the management of the pages, because the user
    will be able to see the thumbnails as a todo for the whole comic,
    giving a good overview over whether they still need to ink, color or
    the like for a given page, and it thus also rewards the user whenever
    they save.
    """

    def slot_check_for_page_update(self, url):
        if "pages" in self.setupDictionary.keys():
            relUrl = os.path.relpath(url, self.projecturl)
            if relUrl in self.setupDictionary["pages"]:
                index = self.pagesModel.index(
                    self.setupDictionary["pages"].index(relUrl), 0)
                if index.isValid():
                    pageItem = self.pagesModel.itemFromIndex(index)
                    page = zipfile.ZipFile(url, "r")
                    dataList = self.get_description_and_title(
                        page.read("documentinfo.xml"))
                    if (dataList[0].isspace() or len(dataList[0]) < 1):
                        dataList[0] = os.path.basename(url)
                    thumbnail = QImage.fromData(page.read("preview.png"))
                    pageItem.setIcon(QIcon(QPixmap.fromImage(thumbnail)))
                    pageItem.setText(dataList[0])
                    pageItem.setData(dataList[1], role=CPE.DESCRIPTION)
                    pageItem.setData(url, role=CPE.URL)
                    pageItem.setData(dataList[2], role=CPE.KEYWORDS)
                    pageItem.setData(dataList[3], role=CPE.LASTEDIT)
                    pageItem.setData(dataList[4], role=CPE.EDITOR)
                    self.pagesModel.setItem(index.row(), index.column(),
                                            pageItem)

    """
    Resize all the pages in the pages list.
    It will show a dialog with the options for resizing.
    Then, it will try to pop up a progress dialog while resizing.
    The progress dialog shows the remaining time and pages.
    """

    def slot_batch_resize(self):
        dialog = QDialog()
        dialog.setWindowTitle(i18n("Resize all Pages"))
        buttons = QDialogButtonBox(QDialogButtonBox.Ok
                                   | QDialogButtonBox.Cancel)
        buttons.accepted.connect(dialog.accept)
        buttons.rejected.connect(dialog.reject)
        sizesBox = comics_export_dialog.comic_export_resize_widget(
            "Scale", batch=True, fileType=False)
        exporterSizes = comics_exporter.sizesCalculator()
        dialog.setLayout(QVBoxLayout())
        dialog.layout().addWidget(sizesBox)
        dialog.layout().addWidget(buttons)

        if dialog.exec_() == QDialog.Accepted:
            progress = QProgressDialog(i18n("Resizing pages..."), str(), 0,
                                       len(self.setupDictionary["pages"]))
            progress.setWindowTitle(i18n("Resizing Pages"))
            progress.setCancelButton(None)
            timer = QElapsedTimer()
            timer.start()
            config = {}
            config = sizesBox.get_config(config)
            for p in range(len(self.setupDictionary["pages"])):
                absoluteUrl = os.path.join(self.projecturl,
                                           self.setupDictionary["pages"][p])
                progress.setValue(p)
                timePassed = timer.elapsed()
                if (p > 0):
                    timeEstimated = (len(self.setupDictionary["pages"]) -
                                     p) * (timePassed / p)
                    passedString = str(int(timePassed / 60000)) + ":" + format(
                        int(timePassed / 1000), "02d") + ":" + format(
                            timePassed % 1000, "03d")
                    estimatedString = str(int(
                        timeEstimated / 60000)) + ":" + format(
                            int(timeEstimated / 1000), "02d") + ":" + format(
                                int(timeEstimated % 1000), "03d")
                    progress.setLabelText(
                        str(
                            i18n(
                                "{pages} of {pagesTotal} done. \nTime passed: {passedString}:\n Estimated:{estimated}"
                            )).format(pages=p,
                                      pagesTotal=len(
                                          self.setupDictionary["pages"]),
                                      passedString=passedString,
                                      estimated=estimatedString))
                    qApp.processEvents()
                if os.path.exists(absoluteUrl):
                    doc = Application.openDocument(absoluteUrl)
                    listScales = exporterSizes.get_scale_from_resize_config(
                        config["Scale"], [
                            doc.width(),
                            doc.height(),
                            doc.resolution(),
                            doc.resolution()
                        ])
                    doc.scaleImage(listScales[0], listScales[1], listScales[2],
                                   listScales[3], "bicubic")
                    doc.waitForDone()
                    doc.save()
                    doc.waitForDone()
                    doc.close()

    def slot_show_page_viewer(self):
        index = int(self.comicPageList.currentIndex().row())
        self.page_viewer_dialog.load_comic(self.path_to_config)
        self.page_viewer_dialog.go_to_page_index(index)
        self.page_viewer_dialog.show()

    """
    Function to copy the current project location into the clipboard.
    This is useful for users because they'll be able to use that url to quickly
    move to the project location in outside applications.
    """

    def slot_copy_project_url(self):
        if self.projecturl is not None:
            clipboard = qApp.clipboard()
            clipboard.setText(str(self.projecturl))

    """
    Scrape text files with the textlayer keys for text, and put those in a POT
    file. This makes it possible to handle translations.
    """

    def slot_scrape_translations(self):
        translationFolder = self.setupDictionary.get("translationLocation",
                                                     "translations")
        fullTranslationPath = os.path.join(self.projecturl, translationFolder)
        os.makedirs(fullTranslationPath, exist_ok=True)
        textLayersToSearch = self.setupDictionary.get("textLayerNames",
                                                      ["text"])

        scraper = comics_project_translation_scraper.translation_scraper(
            self.projecturl, translationFolder, textLayersToSearch,
            self.setupDictionary["projectName"])
        # Run text scraper.
        language = self.setupDictionary.get("language", "en")
        metadata = {}
        metadata["title"] = self.setupDictionary.get("title", "")
        metadata["summary"] = self.setupDictionary.get("summary", "")
        metadata["keywords"] = ", ".join(
            self.setupDictionary.get("otherKeywords", [""]))
        metadata["transnotes"] = self.setupDictionary.get(
            "translatorHeader", "Translator's Notes")
        scraper.start(self.setupDictionary["pages"], language, metadata)
        QMessageBox.information(
            self, i18n("Scraping success"),
            str(i18n("POT file has been written to: {file}")).format(
                file=fullTranslationPath), QMessageBox.Ok)

    """
    This is required by the dockwidget class, otherwise unused.
    """

    def canvasChanged(self, canvas):
        pass
Exemplo n.º 43
0
class ModulesPanel(QWidget):
    """ ModulesPanel

        Signals:
            onAddHook([ptr, funcname]) - MenuItem AddHook
            onDumpBinary([ptr, size#int]) - MenuItem DumpBinary
            onModuleSelected([ptr, size#int]) - ModuleDoubleClicked
            onModuleFuncSelected(ptr) - FunctionDoubleClicked
    """
    # pylint: disable=too-many-instance-attributes

    onAddHook = pyqtSignal(list, name='onAddHook')
    onDumpBinary = pyqtSignal(list, name='onDumpBinary')
    onModuleSelected = pyqtSignal(list, name='onModuleSelected')
    onModuleFuncSelected = pyqtSignal(str, name='onModuleFuncSelected')

    def __init__(self, parent=None):  # pylint: disable=too-many-statements
        super(ModulesPanel, self).__init__(parent)
        self._app_window = parent

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

        self._app_window.dwarf.onSetModules.connect(self.set_modules)

        self._uppercase_hex = True

        # setup models
        self.modules_list = None
        self.modules_model = QStandardItemModel(0, 4, self)
        self.modules_model.setHeaderData(0, Qt.Horizontal, 'Name')
        self.modules_model.setHeaderData(1, Qt.Horizontal, 'Base')
        self.modules_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.modules_model.setHeaderData(2, Qt.Horizontal, 'Size')
        self.modules_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.modules_model.setHeaderData(3, Qt.Horizontal, 'Path')

        self.imports_list = None
        self.imports_model = QStandardItemModel(0, 4, self)
        self.imports_model.setHeaderData(0, Qt.Horizontal, 'Import')
        self.imports_model.setHeaderData(1, Qt.Horizontal, 'Address')
        self.imports_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.imports_model.setHeaderData(2, Qt.Horizontal, 'Module')
        self.imports_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.imports_model.setHeaderData(3, Qt.Horizontal, 'Type')

        self.exports_list = None
        self.exports_model = QStandardItemModel(0, 3, self)
        self.exports_model.setHeaderData(0, Qt.Horizontal, 'Export')
        self.exports_model.setHeaderData(1, Qt.Horizontal, 'Address')
        self.exports_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.exports_model.setHeaderData(2, Qt.Horizontal, 'Type')

        self.symbols_list = None
        self.symbols_model = QStandardItemModel(0, 3, self)
        self.symbols_model.setHeaderData(0, Qt.Horizontal, 'Export')
        self.symbols_model.setHeaderData(1, Qt.Horizontal, 'Address')
        self.symbols_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter,
                                         Qt.TextAlignmentRole)
        self.symbols_model.setHeaderData(2, Qt.Horizontal, 'Type')

        # setup ui
        main_wrapper = QVBoxLayout()
        main_wrapper.setContentsMargins(0, 0, 0, 0)
        h_box = QHBoxLayout()
        self.modules_list = DwarfListView()
        self.modules_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.modules_list.customContextMenuRequested.connect(
            self._on_modules_contextmenu)
        self.modules_list.setEditTriggers(self.modules_list.NoEditTriggers)
        self.modules_list.clicked.connect(self._module_clicked)
        self.modules_list.doubleClicked.connect(self._module_dblclicked)
        self.modules_list.setModel(self.modules_model)
        self.modules_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.modules_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.modules_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)
        h_box.addWidget(self.modules_list)
        self.modules_list.selectionModel().selectionChanged.connect(
            self._module_clicked)

        hv_box = QVBoxLayout()
        self.imports_list = DwarfListView()
        self.imports_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.imports_list.customContextMenuRequested.connect(
            self._on_imports_contextmenu)
        self.imports_list.setEditTriggers(self.modules_list.NoEditTriggers)
        self.imports_list.doubleClicked.connect(self._import_dblclicked)
        self.imports_list.setModel(self.imports_model)
        self.imports_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.imports_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.imports_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)
        self.imports_list.setVisible(False)
        self.exports_list = DwarfListView()
        self.exports_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.exports_list.customContextMenuRequested.connect(
            self._on_exports_contextmenu)
        self.exports_list.setEditTriggers(self.modules_list.NoEditTriggers)
        self.exports_list.doubleClicked.connect(self._export_dblclicked)
        self.exports_list.setModel(self.exports_model)
        self.exports_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.exports_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.exports_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)
        self.exports_list.setVisible(False)
        self.symbols_list = DwarfListView()
        self.symbols_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.symbols_list.doubleClicked.connect(self._symbol_dblclicked)
        self.symbols_list.setModel(self.symbols_model)
        self.symbols_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self.symbols_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.symbols_list.header().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)
        self.symbols_list.setVisible(False)
        hv_box.addWidget(self.imports_list)
        hv_box.addWidget(self.exports_list)
        hv_box.addWidget(self.symbols_list)
        h_box.addLayout(hv_box)
        main_wrapper.addLayout(h_box)
        self.setLayout(main_wrapper)

    # ************************************************************************
    # **************************** Properties ********************************
    # ************************************************************************
    @property
    def uppercase_hex(self):
        """ HexDisplayStyle
        """
        return self._uppercase_hex

    @uppercase_hex.setter
    def uppercase_hex(self, value):
        """ HexDisplayStyle
        """
        if isinstance(value, bool):
            self._uppercase_hex = value
        elif isinstance(value, str):
            self._uppercase_hex = (value == 'upper')

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def set_modules(self, modules):
        """ Fills the ModulesList with data
        """
        self.modules_list.clear()
        for module in modules:
            name = QStandardItem()
            name.setTextAlignment(Qt.AlignLeft)
            name.setText(module['name'])

            base = QStandardItem()
            base.setTextAlignment(Qt.AlignCenter)

            str_fmt = '0x{0:X}'
            if not self.uppercase_hex:
                str_fmt = '0x{0:x}'

            base.setText(str_fmt.format(int(module['base'], 16)))

            size = QStandardItem()
            size.setTextAlignment(Qt.AlignRight)
            size.setText("{0:,d}".format(int(module['size'])))

            path = QStandardItem()
            path.setTextAlignment(Qt.AlignLeft)
            path.setText(module['path'])

            self.modules_model.appendRow([name, base, size, path])

    def update_modules(self):
        """ DwarfApiCall updateModules
        """
        return self._app_window.dwarf.dwarf_api('updateModules')

    def set_imports(self, imports):
        """ Fills the ImportsList with data
        """
        self.imports_list.clear()
        for import_ in imports:
            name = QStandardItem()
            name.setTextAlignment(Qt.AlignLeft)
            name.setText(import_['name'])

            address = QStandardItem()
            address.setTextAlignment(Qt.AlignCenter)

            str_fmt = '0x{0:X}'
            if not self.uppercase_hex:
                str_fmt = '0x{0:x}'

            address.setText(str_fmt.format(int(import_['address'], 16)))

            module = QStandardItem()
            if 'module' in import_:
                module.setTextAlignment(Qt.AlignLeft)
                module.setText(import_['module'])

            type_ = QStandardItem()
            if 'type' in import_:
                type_.setTextAlignment(Qt.AlignLeft)
                type_.setText(import_['type'])

            self.imports_model.appendRow([name, address, module, type_])

    def set_exports(self, exports):
        """ Fills the ExportsList with data
        """
        self.exports_list.clear()
        for export in exports:
            name = QStandardItem()
            name.setTextAlignment(Qt.AlignLeft)
            name.setText(export['name'])

            address = QStandardItem()
            address.setTextAlignment(Qt.AlignCenter)
            str_fmt = '0x{0:X}'
            if not self.uppercase_hex:
                str_fmt = '0x{0:x}'
            address.setText(str_fmt.format(int(export['address'], 16)))

            type_ = QStandardItem()
            type_.setTextAlignment(Qt.AlignLeft)
            type_.setText(export['type'])

            self.exports_model.appendRow([name, address, type_])

    def set_symbols(self, symbols):
        """ Fills the SymbolsList with data
        """
        self.symbols_list.clear()
        for symbol in symbols:
            name = QStandardItem()
            name.setTextAlignment(Qt.AlignLeft)
            name.setText(symbol['name'])

            address = QStandardItem()
            address.setTextAlignment(Qt.AlignCenter)
            str_fmt = '0x{0:X}'
            if not self.uppercase_hex:
                str_fmt = '0x{0:x}'
            address.setText(str_fmt.format(int(symbol['address'], 16)))

            type_ = QStandardItem()
            type_.setTextAlignment(Qt.AlignLeft)
            type_.setText(symbol['type'])

            self.symbols_model.appendRow([name, address, type_])

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _module_clicked(self):
        """ Module Clicked updates imports/exports/symbols
        """
        module_index = self.modules_list.selectionModel().currentIndex().row()
        module = self.modules_model.item(module_index, 0)  # module name
        if module is None:
            return

        imports = self._app_window.dwarf.dwarf_api('enumerateImports',
                                                   module.text())
        if imports and (imports is not None):
            imports = json.loads(imports)
            if imports:
                self.set_imports(imports)
                self.imports_list.setVisible(True)
            else:
                self.imports_list.setVisible(False)

        exports = self._app_window.dwarf.dwarf_api('enumerateExports',
                                                   module.text())
        if exports and exports is not None:
            exports = json.loads(exports)
            if exports:
                self.set_exports(exports)
                self.exports_list.setVisible(True)
            else:
                self.exports_list.setVisible(False)

        symbols = self._app_window.dwarf.dwarf_api('enumerateSymbols',
                                                   module.text())
        if symbols and symbols is not None:
            symbols = json.loads(symbols)
            if symbols:
                self.set_symbols(symbols)
                self.symbols_list.setVisible(True)
            else:
                self.symbols_list.setVisible(False)

    def _module_dblclicked(self):
        """ Module DoubleClicked
        """
        module_index = self.modules_list.selectionModel().currentIndex().row()
        base = self.modules_model.item(module_index, 1).text()
        size = self.modules_model.item(module_index, 2).text().replace(',', '')
        self.onModuleSelected.emit([base, size])

    def _import_dblclicked(self):
        """ ImportFunction DoubleClicked
        """
        index = self.imports_list.selectionModel().currentIndex().row()
        addr = self.imports_model.item(index, 1).text()
        self.onModuleFuncSelected.emit(addr)

    def _export_dblclicked(self):
        """ ExportFunction DoubleClicked
        """
        index = self.exports_list.selectionModel().currentIndex().row()
        addr = self.exports_model.item(index, 1).text()
        self.onModuleFuncSelected.emit(addr)

    def _symbol_dblclicked(self):
        """ Symbol DoubleClicked
        """
        index = self.symbols_list.selectionModel().currentIndex().row()
        addr = self.symbols_model.item(index, 1).text()
        self.onModuleFuncSelected.emit(addr)

    def _on_modules_contextmenu(self, pos):
        """ Modules ContextMenu
        """
        index = self.modules_list.indexAt(pos).row()
        glbl_pt = self.modules_list.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            context_menu.addAction(
                'Dump Binary', lambda: self._on_dumpmodule(
                    self.modules_model.item(index, 1).text(),
                    self.modules_model.item(index, 2).text()))
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self.modules_model.item(index, 1).text()))
            context_menu.addSeparator()
            context_menu.addAction(
                'Copy Name', lambda: utils.copy_str_to_clipboard(
                    self.modules_model.item(index, 0).text()))
            context_menu.addAction(
                'Copy Path', lambda: utils.copy_str_to_clipboard(
                    self.modules_model.item(index, 3).text()))
            context_menu.addSeparator()

        context_menu.addAction('Refresh', self.update_modules)
        context_menu.exec_(glbl_pt)

    def _on_imports_contextmenu(self, pos):
        """ ImportList ContextMenu
        """
        index = self.imports_list.indexAt(pos).row()
        if index != -1:
            glbl_pt = self.imports_list.mapToGlobal(pos)
            context_menu = QMenu(self)
            func_name = self.imports_model.item(index, 0).text()
            addr = self.imports_model.item(index, 1).text()
            context_menu.addAction('Add Hook',
                                   lambda: self._add_hook(addr, func_name))
            context_menu.addSeparator()
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self.imports_model.item(index, 1).text()))
            context_menu.addSeparator()
            context_menu.addAction(
                'Copy FunctionName',
                lambda: utils.copy_str_to_clipboard(func_name))
            context_menu.addAction(
                'Copy ModuleName', lambda: utils.copy_str_to_clipboard(
                    self.imports_model.item(index, 2).text()))
            context_menu.exec_(glbl_pt)

    def _on_exports_contextmenu(self, pos):
        """ ExportsList ContextMenu
        """
        index = self.exports_list.indexAt(pos).row()
        if index != -1:
            glbl_pt = self.exports_list.mapToGlobal(pos)
            context_menu = QMenu(self)
            func_name = self.exports_model.item(index, 0).text()
            addr = self.exports_model.item(index, 1).text()
            context_menu.addAction('Add Hook',
                                   lambda: self._add_hook(addr, func_name))
            context_menu.addSeparator()
            context_menu.addAction(
                'Copy address', lambda: utils.copy_hex_to_clipboard(
                    self.exports_model.item(index, 1).text()))
            context_menu.addSeparator()
            context_menu.addAction(
                'Copy FunctionName',
                lambda: utils.copy_str_to_clipboard(func_name))
            context_menu.exec_(glbl_pt)

    def _on_dumpmodule(self, ptr, size):
        """ MenuItem DumpBinary
        """
        if isinstance(ptr, int):
            str_fmt = '0x{0:X}'
            if not self.uppercase_hex:
                str_fmt = '0x{0:x}'
            ptr = str_fmt.format(ptr)

        size = size.replace(',', '')
        self.onDumpBinary.emit([ptr, size])

    def _add_hook(self, ptr, name=None):
        """ MenuItem AddHook
        """
        if name is None:
            name = ptr
        if isinstance(ptr, str):
            if ptr.startswith('0x') or ptr.startswith('#'):
                self.onAddHook.emit([ptr, name])
        elif isinstance(ptr, int):
            str_fmt = '0x{0:x}'
            self.onAddHook.emit(str_fmt.format([ptr, name]))
Exemplo n.º 44
0
class AttrsUI(object):

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

        self.window.ui.treeView.activated.connect(self.show_attrs)
        self.window.ui.treeView.clicked.connect(self.show_attrs)
        self.window.ui.attrRefreshButton.clicked.connect(self.show_attrs)

        # Context menu
        self.window.ui.attrView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.window.ui.attrView.customContextMenuRequested.connect(self.showContextMenu)
        copyaction = QAction("&Copy Value", self.model)
        copyaction.triggered.connect(self._copy_value)
        self._contextMenu = QMenu()
        self._contextMenu.addAction(copyaction)

    def showContextMenu(self, position):
        item = self.get_current_item()
        if item:
            self._contextMenu.exec_(self.window.ui.attrView.mapToGlobal(position))

    def get_current_item(self, col_idx=0):
        idx = self.window.ui.attrView.currentIndex()
        return self.model.item(idx.row(), col_idx)

    def _copy_value(self, position):
        it = self.get_current_item(1)
        if it:
            QApplication.clipboard().setText(it.text())

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

    def show_attrs(self, idx):
        if not isinstance(idx, QModelIndex):
            idx = None
        node = self.window.get_current_node(idx)
        self.model.clear()
        if node:
            self._show_attrs(node)

    def _show_attrs(self, node):
        try:
            attrs = self.uaclient.get_all_attrs(node)
        except Exception as ex:
            self.window.show_error(ex)
            raise
        self.model.setHorizontalHeaderLabels(['Attribute', 'Value'])
        for k, v in attrs.items():
            if isinstance(v, (ua.NodeId)):
                v = str(v)
            elif isinstance(v, (ua.QualifiedName, ua.LocalizedText)):
                v = v.to_string()
            elif isinstance(v, Enum):
                v = repr(v)
            elif isinstance(v, ua.DataValue):
                v = repr(v)
            else:
                v = str(v)
            self.model.appendRow([QStandardItem(k), QStandardItem(v)])
Exemplo n.º 45
0
class UploadDialog(QDialog):
    """文件上传对话框"""
    new_infos = pyqtSignal(object)

    def __init__(self):
        super().__init__()
        self.cwd = os.getcwd()
        self.selected = []
        self.max_len = 400
        self.initUI()
        self.set_size()
        self.setStyleSheet(dialog_qss_style)

    def set_values(self, folder_name):
        self.setWindowTitle("上传文件至 ➩ " + str(folder_name))

    def initUI(self):
        self.setWindowTitle("上传文件")
        self.setWindowIcon(QIcon("./icon/upload.ico"))
        self.logo = QLabel()
        self.logo.setPixmap(QPixmap("./icon/logo3.gif"))
        self.logo.setStyleSheet("background-color:rgb(0,153,255);")
        self.logo.setAlignment(Qt.AlignCenter)

        # btn 1
        self.btn_chooseDir = QPushButton("选择文件夹", self)
        self.btn_chooseDir.setObjectName("btn_chooseDir")
        self.btn_chooseDir.setObjectName("btn_chooseDir")
        self.btn_chooseDir.setIcon(QIcon("./icon/folder.gif"))

        # btn 2
        self.btn_chooseMutiFile = QPushButton("选择多文件", self)
        self.btn_chooseDir.setObjectName("btn_chooseMutiFile")
        self.btn_chooseMutiFile.setObjectName("btn_chooseMutiFile")
        self.btn_chooseMutiFile.setIcon(QIcon("./icon/file.ico"))

        # btn 3
        self.btn_deleteSelect = QPushButton("删除", self)
        self.btn_deleteSelect.setObjectName("btn_deleteSelect")
        self.btn_deleteSelect.setIcon(QIcon("./icon/delete.ico"))

        # 列表
        self.list_view = QListView(self)
        self.list_view.setViewMode(QListView.ListMode)
        self.slm = QStandardItem()
        self.model = QStandardItemModel()
        self.list_view.setModel(self.model)
        self.model.removeRows(0, self.model.rowCount())  # 清除旧的选择
        self.list_view.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.list_view.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.list_view.setSelectionMode(QAbstractItemView.ExtendedSelection)

        self.buttonBox = QDialogButtonBox()
        self.buttonBox.setOrientation(Qt.Horizontal)
        self.buttonBox.setStandardButtons(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)

        grid = QGridLayout()
        grid.setSpacing(10)
        grid.addWidget(self.logo, 1, 0, 1, 3)
        grid.addWidget(self.btn_chooseDir, 2, 0)
        grid.addWidget(self.btn_chooseMutiFile, 2, 2)
        grid.addWidget(self.list_view, 3, 0, 2, 3)
        grid.addWidget(self.btn_deleteSelect, 5, 0)
        grid.addWidget(self.buttonBox, 5, 1, 1, 2)
        self.setLayout(grid)

        self.setMinimumWidth(350)

        # 设置信号
        self.btn_chooseDir.clicked.connect(self.slot_btn_chooseDir)
        self.btn_chooseMutiFile.clicked.connect(self.slot_btn_chooseMutiFile)
        self.btn_deleteSelect.clicked.connect(self.slot_btn_deleteSelect)

        self.buttonBox.accepted.connect(self.slot_btn_ok)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.clear_old)
        self.buttonBox.rejected.connect(self.reject)

    def set_size(self):
        rows = self.model.rowCount()
        for i in range(rows):
            m_len = int(len(self.model.item(i, 0).text()) * 4)
            if m_len > self.max_len:
                self.max_len = m_len
        rows = 10 if rows >= 10 else rows  # 限制最大高度
        self.resize(self.max_len, 250 + rows * 28)

    def clear_old(self):
        self.selected = []
        self.model.removeRows(0, self.model.rowCount())
        self.set_size()

    def slot_btn_ok(self):
        if self.selected:
            self.new_infos.emit(self.selected)
            self.clear_old()

    def slot_btn_deleteSelect(self):
        _indexes = self.list_view.selectionModel().selection().indexes()
        if not _indexes:
            return
        indexes = []
        for i in _indexes:  # 获取所选行号
            indexes.append(i.row())
        indexes = set(indexes)
        for i in sorted(indexes, reverse=True):
            self.selected.remove(self.model.item(i, 0).text())
            self.model.removeRow(i)
        self.set_size()

    def slot_btn_chooseDir(self):
        dir_choose = QFileDialog.getExistingDirectory(self, "选择文件夹",
                                                      self.cwd)  # 起始路径

        if dir_choose == "":
            return
        if dir_choose not in self.selected:
            self.selected.append(dir_choose)
            self.model.appendRow(
                QStandardItem(QIcon("./icon/folder.gif"), dir_choose))
            self.set_size()

    def slot_btn_chooseMutiFile(self):
        files, _ = QFileDialog.getOpenFileNames(self, "选择多文件", self.cwd,
                                                "All Files (*)")
        if len(files) == 0:
            return

        for _file in files:
            if _file not in self.selected:
                self.selected.append(_file)
                self.model.appendRow(
                    QStandardItem(QIcon("./icon/file.ico"), _file))
        self.set_size()
Exemplo n.º 46
0
class DataChangeUI(object):

    def __init__(self, window, uaclient, hub_manager):
        self.window = window
        self.uaclient = uaclient

        # FIXME IoT stuff
        self.hub_manager = hub_manager

        self._subhandler = DataChangeHandler(self.hub_manager)
        self._subscribed_nodes = []
        self.model = QStandardItemModel()
        self.window.ui.subView.setModel(self.model)
        self.window.ui.subView.horizontalHeader().setSectionResizeMode(1)

        self.window.ui.actionSubscribeDataChange.triggered.connect(self._subscribe)
        self.window.ui.actionUnsubscribeDataChange.triggered.connect(self._unsubscribe)

        # populate contextual menu
        self.window.ui.treeView.addAction(self.window.ui.actionSubscribeDataChange)
        self.window.ui.treeView.addAction(self.window.ui.actionUnsubscribeDataChange)

        # handle subscriptions
        self._subhandler.data_change_fired.connect(self._update_subscription_model, type=Qt.QueuedConnection)

    def clear(self):
        self._subscribed_nodes = []
        self.model.clear()

    def _subscribe(self):
        node = self.window.get_current_node()
        if node is None:
            return
        if node in self._subscribed_nodes:
            print("allready subscribed to node: ", node)
            return
        self.model.setHorizontalHeaderLabels(["DisplayName", "Value", "Timestamp"])
        row = [QStandardItem(node.display_name), QStandardItem("No Data yet"), QStandardItem("")]
        row[0].setData(node)
        self.model.appendRow(row)
        self._subscribed_nodes.append(node)
        self.window.ui.subDockWidget.raise_()
        try:
            self.uaclient.subscribe_datachange(node, self._subhandler)
        except Exception as ex:
            self.window.show_error(ex)
            idx = self.model.indexFromItem(row[0])
            self.model.takeRow(idx.row())

    def _unsubscribe(self):
        node = self.window.get_current_node()
        if node is None:
            return
        self.uaclient.unsubscribe_datachange(node)
        self._subscribed_nodes.remove(node)
        i = 0
        while self.model.item(i):
            item = self.model.item(i)
            if item.data() == node:
                self.model.removeRow(i)
            i += 1

    def _update_subscription_model(self, node, value, timestamp):
        i = 0
        while self.model.item(i):
            item = self.model.item(i)
            if item.data() == node:
                it = self.model.item(i, 1)
                it.setText(value)
                it_ts = self.model.item(i, 2)
                it_ts.setText(timestamp)
            i += 1
Exemplo n.º 47
0
class MainWindow(QMainWindow, Ui_MainWindow):
    sig_ctrl_reload = pyqtSignal()
    sig_net_args_update = pyqtSignal([str])
    sig_opt_args_update = pyqtSignal([str])
    sig_err_box = pyqtSignal([str])
    sig_set_state = pyqtSignal([int])
    sig_add_log = pyqtSignal([str])
    sig_update_pgbar = pyqtSignal([int])
    sig_update_table = pyqtSignal([list])

    data_model = None
    net = None
    training_Thread = None
    pause_flag = False
    stop_flag = False

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.setup_signal()
        self.config = Configs()
        self.init_table()
        self.sig_ctrl_reload.emit()

    def setup_signal(self):
        self.sig_ctrl_reload.connect(self.ctrl_reload)
        self.net_file_btn.clicked.connect(self.choose_net)
        self.net_args_btn.clicked.connect(self.net_args)
        self.load_net_btn.clicked.connect(self.load_net)
        self.opt_args_btn.clicked.connect(self.opt_args)
        self.param_file_btn.clicked.connect(self.choose_param)
        self.dir_edit_btn.clicked.connect(self.choose_dir)
        self.datadir_edit_btn.clicked.connect(self.choose_datadir)
        self.start_btn.clicked.connect(self.start_training)
        self.pause_btn.clicked.connect(self.pause_training)
        self.stop_btn.clicked.connect(self.stop_training)
        self.sig_net_args_update.connect(self.set_net_args)
        self.sig_opt_args_update.connect(self.set_opt_args)
        self.decay_btn_group.buttonClicked.connect(self.check_decay)
        self.param_btn_group.buttonClicked.connect(self.check_init)
        self.sig_err_box.connect(self.err_box)
        self.sig_set_state.connect(self.set_state)
        self.sig_add_log.connect(self.add_log)
        self.sig_update_pgbar.connect(self.update_pgbar)
        self.sig_update_table.connect(self.add_row)

    def init_table(self):
        self.data_model = QStandardItemModel(0, 7)
        headlist = [
            'Epoch', 'train_loss', 'train_acc', 'valid_loss', 'valid_acc',
            'lr', 'time'
        ]
        self.data_model.setHorizontalHeaderLabels(headlist)
        self.data_table.setModel(self.data_model)
        self.data_table.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        # self.data_table.horizontalHeader().setSectionResizeMode(
        #     QHeaderView.ResizeToContents)

    def ctrl_reload(self):
        # 控制页重置
        print('ctrl refresh')
        self.opt_box.clear()
        self.opt_box.addItems(
            ['sgd', 'nag', 'adagrad', 'adadelta', 'adam', 'rmsprop'])
        self.opt_box.setCurrentText(self.config.lr_cfg.optimizer)
        self.init_box.clear()
        self.init_box.addItems([
            'Normal', 'Orthogonal', 'Uniform', 'One', 'Zero', 'Xavier',
            'MSRAPrelu'
        ])
        self.init_box.setCurrentText(self.config.train_cfg.init)

        self.net_class_box.setText(self.config.net_cfg.class_name)
        self.net_name_box.setText(self.config.net_cfg.name)

        self.lr_box.setText(str(self.config.lr_cfg.lr))
        self.wd_box.setText(str(self.config.lr_cfg.wd))
        self.factor_epoch_box.setText(str(self.config.lr_cfg.factor_epoch))
        self.factor_pow_box.setText(str(self.config.lr_cfg.factor))
        self.warmup_box.setValue(self.config.lr_cfg.warmup)
        if self.config.lr_cfg.decay == 'factor':
            self.factor_decay_btn.setChecked(True)
            self.factor_epoch_box.setEnabled(True)
            self.factor_pow_box.setEnabled(True)
        else:
            self.cosine_decay_btn.setChecked(True)
            self.factor_epoch_box.setEnabled(False)
            self.factor_pow_box.setEnabled(False)

        self.workdir_box.setText(self.config.dir_cfg.dir)
        self.datadir_box.setText(self.config.dir_cfg.dataset)

        self.img_size_box.setValue(self.config.data_cfg.size)
        self.worker_box.setValue(self.config.data_cfg.worker)
        self.crop_btn.setChecked(self.config.data_cfg.crop)
        self.crop_pad_box.setValue(self.config.data_cfg.crop_pad)
        self.cutout_btn.setChecked(self.config.data_cfg.cutout)
        self.cutout_size_box.setValue(self.config.data_cfg.cutout_size)
        self.flip_btn.setChecked(self.config.data_cfg.flip)
        self.erase_btn.setChecked(self.config.data_cfg.erase)
        self.mixup_btn.setChecked(self.config.data_cfg.mixup)
        self.mixup_alpha_box.setText(str(self.config.data_cfg.alpha))

        self.epoch_box.setText(str(self.config.train_cfg.epoch))
        self.batchsize_box.setText(str(self.config.train_cfg.batchsize))
        if self.config.train_cfg.param_init:
            self.init_btn.setChecked(True)
            self.init_box.setEnabled(True)
            self.param_file_btn.setEnabled(False)
            self.init_btn.setChecked(True)
        else:
            self.load_param_btn.setChecked(True)
            self.param_file_btn.setEnabled(True)
            self.init_box.setEnabled(False)
            self.load_param_btn.setEnabled(True)
        self.gpu_num_box.setValue(self.config.train_cfg.gpu)
        self.gpu_num_box.setMaximum(mx.context.num_gpus())
        self.amp_btn.setChecked(self.config.train_cfg.amp)

        self.tensorboard_btn.setChecked(self.config.save_cfg.tensorboard)
        self.profiler_btn.setChecked(self.config.save_cfg.profiler)

        self.main_pgbar.setValue(0)
        self.sub_pgbar.setValue(0)

    def choose_net(self):
        print('choose_net')
        fileName, fileType = QFileDialog.getOpenFileName(
            self, "Choose Net", "./", "Python Files (*.py)")
        if fileName == '':
            print('No change.')
            # self.net_file_btn.setText('选择文件')
            return
        self.net_file_btn.setText(os.path.basename(fileName))
        self.config.net_cfg.filename = os.path.basename(fileName)
        self.config.net_cfg.dir = os.path.dirname(fileName)

    def net_args(self):
        print('net_args')
        dialog = Dialog(title='网络参数(字典)',
                        text=self.config.net_cfg.extra_arg,
                        signal=self.sig_net_args_update,
                        parent=self)
        dialog.show()

    def load_net(self):
        print('load net')
        self.config.net_cfg.class_name = self.net_class_box.text()
        if self.net_name_box.text() == '':
            self.config.net_cfg.name = self.net_class_box.text()
        else:
            self.config.net_cfg.name = self.net_name_box.text()
        self.load_net_btn.setText('Loading')
        t = Thread(target=self.load_net_by_config, name='load_net')
        t.start()

    def load_net_by_config(self):
        try:
            sys.path.append(self.config.net_cfg.dir)
            # print(sys.path)
            test = import_module(
                os.path.splitext(self.config.net_cfg.filename)[0])
            test = reload(test)
            # print(test)
            func = getattr(test, self.config.net_cfg.class_name)
            if self.config.net_cfg.extra_arg != '':
                self.net = func(kwargs=self.config.net_cfg.extra_arg)
            else:
                self.net = func()
            # X = mx.nd.uniform(shape=(1, 3, 32, 32))
            # self.net.initialize(init=mx.init.MSRAPrelu())
            # print(self.net(X))
            sys.path.remove(self.config.net_cfg.dir)
            self.load_net_btn.setText("成功读取" + self.config.net_cfg.name)
        except Exception as e:
            print(e)
            self.net = None
            self.load_net_btn.setText("读取失败")

    def opt_args(self):
        print('opt_args')
        dialog = Dialog(title='额外参数(字典)',
                        text=self.config.lr_cfg.extra_arg,
                        signal=self.sig_opt_args_update,
                        parent=self)
        dialog.show()

    def choose_param(self):
        print('choose_param')
        fileName, fileType = QFileDialog.getOpenFileName(
            self, "Choose Params", "./", "Python Files (*.params)")
        if fileName == '':
            print('No change.')
            # self.net_file_btn.setText('选择文件')
            return
        self.param_file_btn.setText(os.path.basename(fileName))
        self.config.train_cfg.param_file = fileName

    def choose_dir(self):
        print('choose_dir')
        wk_dir = QFileDialog.getExistingDirectory(self, "Choose Dir", "./")
        if wk_dir == '':
            print('No change.')
            # self.net_file_btn.setText('选择文件')
            return
        self.workdir_box.setText(wk_dir)
        self.config.dir_cfg.dir = wk_dir

    def choose_datadir(self):
        print('choose_datadir')
        wk_dir = QFileDialog.getExistingDirectory(self, "Choose Dataset Dir",
                                                  "./")
        if wk_dir == '':
            print('No change.')
            # self.net_file_btn.setText('选择文件')
            return
        self.datadir_box.setText(wk_dir)
        self.config.dir_cfg.dataset = wk_dir

    def start_training(self):
        if self.training_Thread is not None:
            if self.training_Thread.is_alive():
                self.pause_flag = False
                self.sig_set_state.emit(1)
                return
        print('start_training')
        self.sig_set_state.emit(-1)
        self.init_table()
        self.pause_flag = False
        self.stop_flag = False
        os.chdir(self.config.dir_cfg.dir)
        if self.net == None:
            self.sig_err_box.emit('未导入网络')
            self.sig_set_state.emit(0)
            return
        self.collect_config()
        logger = self.GuiLogger()
        logger.sig = self.sig_add_log
        self.training_Thread = Thread(target=train_net,
                                      args=(
                                          self.net,
                                          self.config,
                                          self.check_flag,
                                          logger,
                                          self.sig_set_state,
                                          self.sig_update_pgbar,
                                          self.sig_update_table,
                                      ))
        # train_net(self.net, self.config)
        self.training_Thread.start()

    def pause_training(self):
        print('pause_training')
        self.sig_set_state.emit(-1)
        self.pause_flag = True

    def stop_training(self):
        print('stop_training')
        self.sig_set_state.emit(-1)
        self.stop_flag = True
        self.net = None

    def set_net_args(self, argstr):
        print('Net args:' + argstr)
        self.config.net_cfg.extra_arg = argstr

    def set_opt_args(self, argstr):
        print('Opt args:' + argstr)
        self.config.lr_cfg.extra_arg = argstr

    def check_decay(self):
        # print(self.decay_btn_group.checkedId())
        if self.decay_btn_group.checkedId() == -2:
            self.config.lr_cfg.decay = 'factor'
            self.factor_epoch_box.setEnabled(True)
            self.factor_pow_box.setEnabled(True)
        else:
            self.config.lr_cfg.decay = 'cosine'
            self.factor_epoch_box.setEnabled(False)
            self.factor_pow_box.setEnabled(False)

    def check_init(self):
        # print(self.param_btn_group.checkedId())
        if self.param_btn_group.checkedId() == -3:
            self.config.train_cfg.param_init = True
            self.init_box.setEnabled(True)
            self.param_file_btn.setEnabled(False)
        else:
            self.config.train_cfg.param_init = False
            self.init_box.setEnabled(False)
            self.param_file_btn.setEnabled(True)

    def err_box(self, text='Error'):
        QMessageBox.critical(self, 'Error', text, QMessageBox.Ok)

    def collect_config(self):
        print('collect_config')

        self.config.lr_cfg.lr = float(self.lr_box.text())
        self.config.lr_cfg.wd = float(self.wd_box.text())
        self.config.lr_cfg.optimizer = self.opt_box.currentText()
        if self.cosine_decay_btn.isChecked():
            self.config.lr_cfg.decay = 'cosine'
        else:
            self.config.lr_cfg.decay = 'factor'
        self.config.lr_cfg.factor_epoch = int(self.factor_epoch_box.text())
        self.config.lr_cfg.factor = float(self.factor_pow_box.text())
        self.config.lr_cfg.warmup = self.warmup_box.value()

        self.config.data_cfg.size = self.img_size_box.value()
        self.config.data_cfg.worker = self.worker_box.value()
        self.config.data_cfg.crop = self.crop_btn.isChecked()
        self.config.data_cfg.crop_pad = self.crop_pad_box.value()
        self.config.data_cfg.cutout = self.cutout_btn.isChecked()
        self.config.data_cfg.cutout_size = self.cutout_size_box.value()
        self.config.data_cfg.flip = self.flip_btn.isChecked()
        self.config.data_cfg.erase = self.erase_btn.isChecked()
        self.config.data_cfg.mixup = self.mixup_btn.isChecked()
        self.config.data_cfg.alpha = float(self.mixup_alpha_box.text())

        self.config.train_cfg.epoch = int(self.epoch_box.text())
        self.config.train_cfg.batchsize = int(self.batchsize_box.text())
        if self.init_btn.isChecked():
            self.config.train_cfg.param_init = True
        else:
            self.config.train_cfg.param_init = False
        self.config.train_cfg.init = self.init_box.currentText()
        self.config.train_cfg.gpu = self.gpu_num_box.value()
        self.config.train_cfg.amp = self.amp_btn.isChecked()

        self.config.save_cfg.tensorboard = self.tensorboard_btn.isChecked()
        self.config.save_cfg.profiler = self.profiler_btn.isChecked()

    def check_flag(self):
        return [self.pause_flag, self.stop_flag]

    def add_log(self, text):
        self.log_box.append(text)
        # self.log_box.verticalScrollBar().setValue(
        #     self.log_box.verticalScrollBar().maximum())

    def set_state(self, state):
        if state == -1:
            print('waiting')
            self.start_btn.setEnabled(False)
            self.pause_btn.setEnabled(False)
            self.stop_btn.setEnabled(False)
            # mx.gpu(0).empty_cache()
        elif state == 0:
            print('init')
            self.start_btn.setEnabled(True)
            self.pause_btn.setEnabled(False)
            self.stop_btn.setEnabled(False)
        elif state == 1:
            print('start training')
            self.start_btn.setEnabled(False)
            self.pause_btn.setEnabled(True)
            self.stop_btn.setEnabled(True)
        elif state == 2:
            print('Pause')
            self.start_btn.setEnabled(True)
            self.pause_btn.setEnabled(False)
            self.stop_btn.setEnabled(True)

    def update_pgbar(self, iteration):
        iter_max = 50000 // self.config.train_cfg.batchsize
        if iteration == -1:
            self.main_pgbar.setMaximum(0)
            self.sub_pgbar.setMaximum(0)
            return
        self.main_pgbar.setMaximum(self.config.train_cfg.epoch)
        self.sub_pgbar.setMaximum(iter_max)
        self.main_pgbar.setValue(iteration // iter_max)
        main_percent = 100 * (iteration //
                              iter_max) / self.config.train_cfg.epoch
        self.label_main.setText('%.1f%%' % main_percent)
        self.sub_pgbar.setValue(iteration % iter_max)
        sub_percent = 100 * (iteration % iter_max) / iter_max
        self.label_sub.setText('%.1f%%' % sub_percent)

    def add_row(self, datalist):
        itemlist = []
        for data in datalist:
            itemlist.append(self.get_table_item(data))
        self.data_model.appendRow(itemlist)
        self.data_table.setModel(self.data_model)
        # self.data_table.verticalScrollBar().setValue(
        #     self.data_table.verticalScrollBar().maximum())
        self.data_table.scrollToBottom()
        # self.data_table.horizontalHeader().setSectionResizeMode(0,QHeaderView.ResizeToContents)

    def get_table_item(self, text):
        # print(type(text))
        if not isinstance(text, int):
            text = '%.6f' % text
        item = QStandardItem(str(text))
        item.setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
        return item

    class GuiLogger(logging.Handler):
        def emit(self, record):
            # implementation of append_line omitted
            self.sig.emit(self.format(record))

    def closeEvent(self, event):
        result = QMessageBox.question(self, "GUI Training",
                                      "Do you want to exit?",
                                      QMessageBox.Yes | QMessageBox.No)
        if (result == QMessageBox.Yes):
            self.stop_flag = True
            event.accept()
        else:
            event.ignore()
Exemplo n.º 48
0
class MDIHistory(QWidget, _HalWidgetBase):
    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()

    def _hal_init(self):
        STATUS.connect('state-off', lambda w: self.setEnabled(False))
        STATUS.connect('state-estop', lambda w: self.setEnabled(False))
        STATUS.connect(
            'interp-idle', lambda w: self.setEnabled(STATUS.machine_is_on(
            ) and (STATUS.is_all_homed() or INFO.NO_HOME_REQUIRED)))
        STATUS.connect('interp-run',
                       lambda w: self.setEnabled(not STATUS.is_auto_mode()))
        STATUS.connect('all-homed',
                       lambda w: self.setEnabled(STATUS.machine_is_on()))

    def reload(self, w=None):
        print 'RELOAD'
        try:
            fp = os.path.expanduser(INFO.MDI_HISTORY_PATH)
            with open(fp, 'r') as inputfile:
                for line in inputfile:
                    line = line.rstrip('\n')
                    item = QStandardItem(line)
                    self.model.appendRow(item)
            self.list.setModel(self.model)
            self.list.scrollToBottom()
        except Exception as e:
            print e
            LOG.error('File path is not valid: {}]n,()'.format(fp), e)

    def line_up(self):
        print 'up'

    def line_down(self):
        print 'down'

    def selectionChanged(self, old, new):
        cmd = self.getSelected()
        self.MDILine.setText(cmd)

    def getSelected(self):
        selected_indexes = self.list.selectedIndexes()
        selected_rows = [item.row() for item in selected_indexes]
        # iterates each selected row in descending order
        for selected_row in sorted(selected_rows, reverse=True):
            text = self.model.item(selected_row).text()
            return text

    def activated(self):
        cmd = self.getSelected()
        self.MDILine.setText(cmd)
        self.MDILine.submit()
        item = QStandardItem(cmd)
        self.model.appendRow(item)
        self.list.update()

    #########################################################################
    # This is how designer can interact with our widget properties.
    # designer will show the pyqtProperty properties in the editor
    # it will use the get set and reset calls to do those actions
    #########################################################################

    def set_soft_keyboard(self, data):
        self.MDILine.soft_keyboard = data

    def get_soft_keyboard(self):
        return self.MDILine.soft_keyboard

    def reset_soft_keyboard(self):
        self.MDILine.soft_keyboard = False

    # designer will show these properties in this order:
    soft_keyboard_option = pyqtProperty(bool, get_soft_keyboard,
                                        set_soft_keyboard, reset_soft_keyboard)
Exemplo n.º 49
0
class Audio:
    def __init__(self):
        self.mediaLength = 0
        self.mediaList = []
        self.formats = ['*.mp3', '*.ogg']
        self.playing = False
        self.initUI()

    def togglePlay(self):

        if len(self.mediaList) != 0:

            if self.playing:
                self.pause()
                self.playing = False
            else:
                self.play()
                self.playing = True

    def initUI(self):
        self.list = QListView()
        self.list.setWindowTitle("Music Files")
        self.list.setMinimumSize(300, 400)
        self.list.setSpacing(10)
        self.model = QStandardItemModel(self.list)
        self.resourceMusic = ResourceMusic()

        for root, dirs, files in os.walk("MusicFiles"):
            for extensions in self.formats:
                for filename in fnmatch.filter(files, extensions):
                    item = QStandardItem(filename)
                    item.setFont(QFont(filename, 10))
                    self.model.appendRow(item)
                    self.mediaList.append(item)

        self.mediaLength = len(self.mediaList)
        self.currentItem = 1
        self.prevItem = self.mediaLength

        if len(self.mediaList) != 0:
            self.mediaList[0].setBackground(QColor(97, 138, 204))

        self.list.setModel(self.model)
        self.list.show()

    def nextItem(self):

        if len(self.mediaList) != 0:

            if self.currentItem == self.mediaLength:
                self.prevItem = self.mediaLength
                self.currentItem = 1

            else:
                self.prevItem = self.currentItem
                self.currentItem = self.currentItem + 1

            self.mediaList[self.prevItem - 1].setBackground(QColor(35, 38, 41))
            self.mediaList[self.currentItem - 1].setBackground(
                QColor(97, 138, 204))

#    def previousItem(self):
#      if len(self.mediaList) != 0:
#        if self.currentItem == 1:
#            self.prevItem = 1
#            self.currentItem = self.mediaLength
#
#        else:
#            self.prevItem = self.currentItem
#            self.currentItem = self.currentItem - 1
#
#        self.mediaList[self.prevItem - 1].setBackground(QColor(35, 38, 41))
#        self.mediaList[self.currentItem - 1].setBackground(QColor(97, 138, 204))

    def play(self):
        print("Music Player : " +
              str(self.mediaList[self.currentItem - 1].text()))
        self.resourceMusic.playMusic(self.mediaList[self.currentItem -
                                                    1].text())
        return 1

    def pause(self):
        self.resourceMusic.pauseMusic()

    def stop(self):

        if len(self.mediaList) != 0:
            self.resourceMusic.stopMusic()
            self.playing = False

#    def resume(self):
#        self.resourceMusic.resumeMusic()

    def Close(self):
        self.list.close()
        return -1
Exemplo n.º 50
0
class ApkList(DwarfListView):
    """ Displays installed APKs
    """

    onApkSelected = pyqtSignal(list, name='onApkSelected')

    def __init__(self, parent=None, show_path=True):
        super(ApkList, self).__init__(parent=parent)

        self.adb = Adb()
        self.adb.device = parent.dwarf.device.id

        if not self.adb.available():
            return

        self.retrieve_thread = PackageRetrieveThread(self.adb)
        if self.retrieve_thread is not None:
            self.retrieve_thread.onAddPackage.connect(self._on_addpackage)

        if show_path:
            self.apk_model = QStandardItemModel(0, 2)
        else:
            self.apk_model = QStandardItemModel(0, 1)

        self.apk_model.setHeaderData(0, Qt.Horizontal, 'Name')

        if show_path:
            self.apk_model.setHeaderData(1, Qt.Horizontal, 'Path')

        self.setModel(self.apk_model)
        self.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)

        self.doubleClicked.connect(self._on_apk_selected)

        if self.retrieve_thread is not None:
            if not self.retrieve_thread.isRunning():
                self.retrieve_thread.start()

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def refresh(self):
        """ Refresh Packages
        """
        if self.retrieve_thread is not None:
            if not self.retrieve_thread.isRunning():
                self.clear()
                self.retrieve_thread.start()

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_addpackage(self, package):
        if package:
            name = QStandardItem()
            name.setText(package[0])

            if self.apk_model.columnCount() == 2:
                path = QStandardItem()
                path.setText(package[1])

                self.apk_model.appendRow([name, path])
            else:
                self.apk_model.appendRow([name])

    def _on_apk_selected(self, model_index):
        item = self.apk_model.itemFromIndex(model_index).row()
        if item != -1:
            package = self.apk_model.item(item, 0).text()
            if self.apk_model.columnCount() == 2:
                path = self.apk_model.item(item, 1).text()
                self.onApkSelected.emit([package, path])
            else:
                self.onApkSelected.emit([package, None])
Exemplo n.º 51
0
class BacktraceWidget(DwarfListView):

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

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

        self._app_window.dwarf.onBackTrace.connect(self.set_backtrace)

        self._model = QStandardItemModel(0, 2)
        self._model.setHeaderData(0, Qt.Horizontal, 'Address')
        self._model.setHeaderData(1, Qt.Horizontal, 'Symbol')
        self.setModel(self._model)

        self.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
        self.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
        self.doubleClicked.connect(self._item_double_clicked)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self._on_context_menu)
        self._mode = 'native'

    def set_backtrace(self, bt):
        if 'type' not in bt:
            return

        if 'bt' not in bt:
            return

        self.clear()

        if bt['type'] == 'native':
            self._mode = 'native'
            self._model.setHeaderData(0, Qt.Horizontal, 'Address')
            self._model.setHeaderData(1, Qt.Horizontal, 'Symbol')

            bt = bt['bt']

            for a in bt:
                addr = a['address']
                if self.uppercase_hex:
                    addr = addr.upper().replace('0X', '0x')

                addr_item = QStandardItem()
                addr_item.setText(addr)
                addr_item.setForeground(Qt.red)

                name = a['name']
                if name is None:
                    name = '-'

                self._model.appendRow([addr_item, QStandardItem(name)])

        elif bt['type'] == 'java':
            self._mode = 'java'
            self._model.setHeaderData(0, Qt.Horizontal, 'Method')
            self._model.setHeaderData(1, Qt.Horizontal, 'Source')

            bt = bt['bt']
            parts = bt.split('\n')
            for i in range(0, len(parts)):
                if i == 0:
                    continue
                p = parts[i].replace('\t', '')
                p = p.split('(')
                if len(p) != 2:
                    continue

                self._model.appendRow([
                    QStandardItem(p[0]),
                    QStandardItem(p[1].replace(')', ''))
                ])

    def _item_double_clicked(self, model_index):
        row = self._model.itemFromIndex(model_index).row()
        if row != -1:
            if self._mode == 'native':
                self.onShowMemoryRequest.emit(
                    ['bt', self._model.item(row, 0).text()])

    def _on_context_menu(self, pos):
        index = self.indexAt(pos).row()
        glbl_pt = self.mapToGlobal(pos)
        context_menu = QMenu(self)
        if index != -1:
            if self._mode == 'native':
                addr_item = self.model().item(index, 0).text()
                symbol_item = self.model().item(index, 1).text()
                # show contextmenu
                context_menu.addAction(
                    'Jump to {0}'.format(addr_item),
                    lambda: self.onShowMemoryRequest.emit(['bt', addr_item]))
                context_menu.addSeparator()
                context_menu.addAction(
                    'Copy Address',
                    lambda: utils.copy_hex_to_clipboard(addr_item))
                if symbol_item and symbol_item != '-':
                    context_menu.addAction(
                        'Copy Symbol',
                        lambda: utils.copy_str_to_clipboard(symbol_item))
            elif self._mode == 'java':
                method_item = self.model().item(index, 0).text()
                if method_item.startswith('at '):
                    method_item = method_item.replace('at ', '')

                source_item = self.model().item(index, 1).text()
                if ':' in source_item:
                    source_item = source_item.split(':')[0]
                # show contextmenu
                # context_menu.addAction('Jump to', lambda: self._app_window.jump_to_address(addr_item.text()))
                # context_menu.addSeparator()
                # TODO: add jumpto java
                context_menu.addAction(
                    'Copy Method',
                    lambda: utils.copy_str_to_clipboard(method_item))
                context_menu.addAction(
                    'Copy Source',
                    lambda: utils.copy_str_to_clipboard(source_item))

            context_menu.exec_(glbl_pt)
Exemplo n.º 52
0
class RefNodeSetsWidget(QObject):

    error = pyqtSignal(Exception)
    nodeset_added = pyqtSignal(str)
    nodeset_removed = pyqtSignal(str)

    def __init__(self, view):
        QObject.__init__(self, view)
        self.view = view
        self.model = QStandardItemModel()
        self.view.setModel(self.model)
        self.nodesets = []
        self.server_mgr = None
        self._nodeset_to_delete = None
        self.view.header().setSectionResizeMode(1)

        addNodeSetAction = QAction("Add Reference Node Set", self.model)
        addNodeSetAction.triggered.connect(self.add_nodeset)
        self.removeNodeSetAction = QAction("Remove Reference Node Set",
                                           self.model)
        self.removeNodeSetAction.triggered.connect(self.remove_nodeset)

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

    @trycatchslot
    def add_nodeset(self):
        path, ok = QFileDialog.getOpenFileName(
            self.view,
            caption="Import OPC UA XML Node Set",
            filter="XML Files (*.xml *.XML)",
            directory=".")
        if not ok:
            return None
        name = os.path.basename(path)
        if name in self.nodesets:
            return
        try:
            self.server_mgr.import_xml(path)
        except Exception as ex:
            self.error.emit(ex)
            raise

        item = QStandardItem(name)
        self.model.appendRow([item])
        self.nodesets.append(name)
        self.view.expandAll()
        self.nodeset_added.emit(path)

    @trycatchslot
    def remove_nodeset(self):
        idx = self.view.currentIndex()
        if not idx.isValid() or idx.row() == 0:
            return

        item = self.model.itemFromIndex(idx)
        name = item.text()
        self.nodesets.remove(name)
        self.model.removeRow(idx.row())
        self.nodeset_removed.emit(name)

    def set_server_mgr(self, server_mgr):
        self.server_mgr = server_mgr
        self.nodesets = []
        self.model.clear()
        self.model.setHorizontalHeaderLabels(['Node Sets'])
        item = QStandardItem("Opc.Ua.NodeSet2.xml")
        item.setFlags(Qt.NoItemFlags)
        self.model.appendRow([item])
        self.view.expandAll()

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

    @trycatchslot
    def showContextMenu(self, position):
        if not self.server_mgr:
            return
        idx = self.view.currentIndex()
        if not idx.isValid() or idx.row() == 0:
            self.removeNodeSetAction.setEnabled(False)
        else:
            self.removeNodeSetAction.setEnabled(True)
        self._contextMenu.exec_(self.view.viewport().mapToGlobal(position))
Exemplo n.º 53
0
class HelpWebSearchWidget(E5ClearableLineEdit):
    """
    Class implementing a web search widget for the web browser.
    
    @signal search(QUrl) emitted when the search should be done
    """
    search = pyqtSignal(QUrl)

    def __init__(self, parent=None):
        """
        Constructor
        
        @param parent reference to the parent widget (QWidget)
        """
        super(HelpWebSearchWidget, self).__init__(parent)

        from E5Gui.E5LineEdit import E5LineEdit
        from E5Gui.E5LineEditButton import E5LineEditButton
        from .OpenSearch.OpenSearchManager import OpenSearchManager

        self.__mw = parent

        self.__openSearchManager = OpenSearchManager(self)
        self.__openSearchManager.currentEngineChanged.connect(
            self.__currentEngineChanged)
        self.__currentEngine = ""

        self.__enginesMenu = QMenu(self)

        self.__engineButton = E5LineEditButton(self)
        self.__engineButton.setMenu(self.__enginesMenu)
        self.addWidget(self.__engineButton, E5LineEdit.LeftSide)

        self.__searchButton = E5LineEditButton(self)
        self.__searchButton.setIcon(UI.PixmapCache.getIcon("webSearch.png"))
        self.addWidget(self.__searchButton, E5LineEdit.LeftSide)

        self.__model = QStandardItemModel(self)
        self.__completer = QCompleter()
        self.__completer.setModel(self.__model)
        self.__completer.setCompletionMode(
            QCompleter.UnfilteredPopupCompletion)
        self.__completer.setWidget(self)

        self.__searchButton.clicked.connect(self.__searchButtonClicked)
        self.textEdited.connect(self.__textEdited)
        self.returnPressed.connect(self.__searchNow)
        self.__completer.activated[QModelIndex].connect(
            self.__completerActivated)
        self.__completer.highlighted[QModelIndex].connect(
            self.__completerHighlighted)
        self.__enginesMenu.aboutToShow.connect(self.__showEnginesMenu)

        self.__suggestionsItem = None
        self.__suggestions = []
        self.__suggestTimer = None
        self.__suggestionsEnabled = Preferences.getHelp("WebSearchSuggestions")

        self.__recentSearchesItem = None
        self.__recentSearches = []
        self.__maxSavedSearches = 10

        self.__engine = None
        self.__loadSearches()
        self.__setupCompleterMenu()
        self.__currentEngineChanged()

    def __searchNow(self):
        """
        Private slot to perform the web search.
        """
        searchText = self.text()
        if not searchText:
            return

        globalSettings = QWebSettings.globalSettings()
        if not globalSettings.testAttribute(
                QWebSettings.PrivateBrowsingEnabled):
            if searchText in self.__recentSearches:
                self.__recentSearches.remove(searchText)
            self.__recentSearches.insert(0, searchText)
            if len(self.__recentSearches) > self.__maxSavedSearches:
                self.__recentSearches = \
                    self.__recentSearches[:self.__maxSavedSearches]
            self.__setupCompleterMenu()

        url = self.__openSearchManager.currentEngine().searchUrl(searchText)
        self.search.emit(url)

    def __setupCompleterMenu(self):
        """
        Private method to create the completer menu.
        """
        if not self.__suggestions or \
           (self.__model.rowCount() > 0 and
                self.__model.item(0) != self.__suggestionsItem):
            self.__model.clear()
            self.__suggestionsItem = None
        else:
            self.__model.removeRows(1, self.__model.rowCount() - 1)

        boldFont = QFont()
        boldFont.setBold(True)

        if self.__suggestions:
            if self.__model.rowCount() == 0:
                if not self.__suggestionsItem:
                    self.__suggestionsItem = QStandardItem(
                        self.tr("Suggestions"))
                    self.__suggestionsItem.setFont(boldFont)
                self.__model.appendRow(self.__suggestionsItem)

            for suggestion in self.__suggestions:
                self.__model.appendRow(QStandardItem(suggestion))

        if not self.__recentSearches:
            self.__recentSearchesItem = QStandardItem(
                self.tr("No Recent Searches"))
            self.__recentSearchesItem.setFont(boldFont)
            self.__model.appendRow(self.__recentSearchesItem)
        else:
            self.__recentSearchesItem = QStandardItem(
                self.tr("Recent Searches"))
            self.__recentSearchesItem.setFont(boldFont)
            self.__model.appendRow(self.__recentSearchesItem)
            for recentSearch in self.__recentSearches:
                self.__model.appendRow(QStandardItem(recentSearch))

        view = self.__completer.popup()
        view.setFixedHeight(
            view.sizeHintForRow(0) * self.__model.rowCount() +
            view.frameWidth() * 2)

        self.__searchButton.setEnabled(
            bool(self.__recentSearches or self.__suggestions))

    def __completerActivated(self, index):
        """
        Private slot handling the selection of an entry from the completer.
        
        @param index index of the item (QModelIndex)
        """
        if self.__suggestionsItem and \
           self.__suggestionsItem.index().row() == index.row():
            return

        if self.__recentSearchesItem and \
           self.__recentSearchesItem.index().row() == index.row():
            return

        self.__searchNow()

    def __completerHighlighted(self, index):
        """
        Private slot handling the highlighting of an entry of the completer.
        
        @param index index of the item (QModelIndex)
        @return flah indicating a successful highlighting (boolean)
        """
        if self.__suggestionsItem and \
           self.__suggestionsItem.index().row() == index.row():
            return False

        if self.__recentSearchesItem and \
           self.__recentSearchesItem.index().row() == index.row():
            return False

        self.setText(index.data())
        return True

    def __textEdited(self, txt):
        """
        Private slot to handle changes of the search text.
        
        @param txt search text (string)
        """
        if self.__suggestionsEnabled:
            if self.__suggestTimer is None:
                self.__suggestTimer = QTimer(self)
                self.__suggestTimer.setSingleShot(True)
                self.__suggestTimer.setInterval(200)
                self.__suggestTimer.timeout.connect(self.__getSuggestions)
            self.__suggestTimer.start()
        else:
            self.__completer.setCompletionPrefix(txt)
            self.__completer.complete()

    def __getSuggestions(self):
        """
        Private slot to get search suggestions from the configured search
        engine.
        """
        searchText = self.text()
        if searchText:
            self.__openSearchManager.currentEngine()\
                .requestSuggestions(searchText)

    def __newSuggestions(self, suggestions):
        """
        Private slot to receive a new list of suggestions.
        
        @param suggestions list of suggestions (list of strings)
        """
        self.__suggestions = suggestions
        self.__setupCompleterMenu()
        self.__completer.complete()

    def __showEnginesMenu(self):
        """
        Private slot to handle the display of the engines menu.
        """
        self.__enginesMenu.clear()

        from .OpenSearch.OpenSearchEngineAction import OpenSearchEngineAction
        engineNames = self.__openSearchManager.allEnginesNames()
        for engineName in engineNames:
            engine = self.__openSearchManager.engine(engineName)
            action = OpenSearchEngineAction(engine, self.__enginesMenu)
            action.setData(engineName)
            action.triggered.connect(self.__changeCurrentEngine)
            self.__enginesMenu.addAction(action)

            if self.__openSearchManager.currentEngineName() == engineName:
                action.setCheckable(True)
                action.setChecked(True)

        ct = self.__mw.currentBrowser()
        linkedResources = ct.linkedResources("search")

        if len(linkedResources) > 0:
            self.__enginesMenu.addSeparator()

        for linkedResource in linkedResources:
            url = QUrl(linkedResource.href)
            title = linkedResource.title
            mimetype = linkedResource.type_

            if mimetype != "application/opensearchdescription+xml":
                continue
            if url.isEmpty():
                continue

            if url.isRelative():
                url = ct.url().resolved(url)

            if not title:
                if not ct.title():
                    title = url.host()
                else:
                    title = ct.title()

            action = self.__enginesMenu.addAction(
                self.tr("Add '{0}'").format(title), self.__addEngineFromUrl)
            action.setData(url)
            action.setIcon(ct.icon())

        self.__enginesMenu.addSeparator()
        self.__enginesMenu.addAction(self.__mw.searchEnginesAction())

        if self.__recentSearches:
            self.__enginesMenu.addAction(self.tr("Clear Recent Searches"),
                                         self.clear)

    def __changeCurrentEngine(self):
        """
        Private slot to handle the selection of a search engine.
        """
        action = self.sender()
        if action is not None:
            name = action.data()
            self.__openSearchManager.setCurrentEngineName(name)

    def __addEngineFromUrl(self):
        """
        Private slot to add a search engine given its URL.
        """
        action = self.sender()
        if action is not None:
            url = action.data()
            if not isinstance(url, QUrl):
                return

            self.__openSearchManager.addEngine(url)

    def __searchButtonClicked(self):
        """
        Private slot to show the search menu via the search button.
        """
        self.__setupCompleterMenu()
        self.__completer.complete()

    def clear(self):
        """
        Public method to clear all private data.
        """
        self.__recentSearches = []
        self.__setupCompleterMenu()
        super(HelpWebSearchWidget, self).clear()
        self.clearFocus()

    def preferencesChanged(self):
        """
        Public method to handle the change of preferences.
        """
        self.__suggestionsEnabled = Preferences.getHelp("WebSearchSuggestions")
        if not self.__suggestionsEnabled:
            self.__suggestions = []
            self.__setupCompleterMenu()

    def saveSearches(self):
        """
        Public method to save the recently performed web searches.
        """
        Preferences.Prefs.settings.setValue('Help/WebSearches',
                                            self.__recentSearches)

    def __loadSearches(self):
        """
        Private method to load the recently performed web searches.
        """
        searches = Preferences.Prefs.settings.value('Help/WebSearches')
        if searches is not None:
            self.__recentSearches = searches

    def openSearchManager(self):
        """
        Public method to get a reference to the opensearch manager object.
        
        @return reference to the opensearch manager object (OpenSearchManager)
        """
        return self.__openSearchManager

    def __currentEngineChanged(self):
        """
        Private slot to track a change of the current search engine.
        """
        if self.__openSearchManager.engineExists(self.__currentEngine):
            oldEngine = self.__openSearchManager.engine(self.__currentEngine)
            oldEngine.imageChanged.disconnect(self.__engineImageChanged)
            if self.__suggestionsEnabled:
                oldEngine.suggestions.disconnect(self.__newSuggestions)

        newEngine = self.__openSearchManager.currentEngine()
        if newEngine.networkAccessManager() is None:
            newEngine.setNetworkAccessManager(self.__mw.networkAccessManager())
        newEngine.imageChanged.connect(self.__engineImageChanged)
        if self.__suggestionsEnabled:
            newEngine.suggestions.connect(self.__newSuggestions)

        self.setInactiveText(self.__openSearchManager.currentEngineName())
        self.__currentEngine = self.__openSearchManager.currentEngineName()
        self.__engineButton.setIcon(
            QIcon(
                QPixmap.fromImage(
                    self.__openSearchManager.currentEngine().image())))
        self.__suggestions = []
        self.__setupCompleterMenu()

    def __engineImageChanged(self):
        """
        Private slot to handle a change of the current search engine icon.
        """
        self.__engineButton.setIcon(
            QIcon(
                QPixmap.fromImage(
                    self.__openSearchManager.currentEngine().image())))

    def mousePressEvent(self, evt):
        """
        Protected method called by a mouse press event.
        
        @param evt reference to the mouse event (QMouseEvent)
        """
        if evt.button() == Qt.XButton1:
            self.__mw.currentBrowser().pageAction(QWebPage.Back).trigger()
        elif evt.button() == Qt.XButton2:
            self.__mw.currentBrowser().pageAction(QWebPage.Forward).trigger()
        else:
            super(HelpWebSearchWidget, self).mousePressEvent(evt)
Exemplo n.º 54
0
class MainWindow(Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.filename = ":memory:"
        self.engine = create_engine('sqlite:///' + self.filename)
        Base.metadata.create_all(self.engine)
        self.Session = sessionmaker(bind=self.engine)
        self.session = self.Session()

    def setupUi(self, main_window):
        super().setupUi(main_window)

        #Toolbar
        self.actionAdd_student.triggered.connect(self.addStudent)
        self.actionAdd_subject.triggered.connect(self.addSubject)

        #File menu actions
        self.actionOpen.triggered.connect(self.openFile)
        self.actionSave.triggered.connect(self.saveFile)
        self.actionSave_as.triggered.connect(self.saveFileAs)
        self.actionQuit.triggered.connect(QApplication.instance().quit)

        #Help menu actions
        self.actionAbout.triggered.connect(self.showAbout)

        #Students dock
        self.studentLineEdit.textChanged['QString'].connect(
            self.searchStudents)

        self.student_model = QStandardItemModel()
        self.studentList.setModel(self.student_model)
        self.studentList.doubleClicked['QModelIndex'].connect(self.editStudent)
        self.studentList.selectionModel().selectionChanged[
            'QItemSelection',
            'QItemSelection'].connect(self.changeSelectedStudent)
        self.studentList.setSelectionMode(
            QAbstractItemView.SelectionMode.SingleSelection)
        self.updateStudentModel()

        #Subjects dock
        self.subjectLineEdit.textChanged['QString'].connect(
            self.searchSubjects)

        self.subject_model = QStandardItemModel()
        self.subjectList.setModel(self.subject_model)
        self.subjectList.doubleClicked['QModelIndex'].connect(self.editSubject)
        self.updateSubjectModel()

        #Main view
        self.schedule_model = QStandardItemModel(12, 7)
        self.scheduleView.setModel(self.schedule_model)
        self.scheduleView.horizontalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.scheduleView.verticalHeader().setSectionResizeMode(
            QHeaderView.Stretch)
        self.updateScheduleModel()

    def searchStudents(self, name):
        self.student_model.clear()
        for i in self.session.query(Student).filter(
                Student.name.ilike('%' + name + '%')):
            it = QStandardItem()
            it.setText(i.name)
            it.setData(i)
            it.setEditable(False)
            self.student_model.appendRow(it)

    def searchSubjects(self, name):
        self.subject_model.clear()
        for i in self.session.query(Subject).filter(
                Subject.name.ilike('%' + name + '%')):
            it = QStandardItem()
            it.setText(i.name)
            it.setData(i)
            it.setEditable(False)
            self.subject_model.appendRow(it)

    def updateStudentModel(self):
        self.searchStudents(self.studentLineEdit.text())

    def updateSubjectModel(self):
        self.searchSubjects(self.subjectLineEdit.text())

    def updateScheduleModel(self):
        self.schedule_model.clear()
        self.schedule_model.setHorizontalHeaderLabels([
            "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday",
            "Sunday"
        ])
        for i in DayOfWeek:
            for j in range(12):
                q = self.session.query(TimePlace).filter(
                    TimePlace.day == i, TimePlace.slot == j)
                subjects = []
                for tp in q:
                    subjects.append(' '.join(
                        [tp.subject.abbreviation, tp.place.name]))
                it = QStandardItem()
                it.setText('\n'.join(subjects))
                it.setEditable(False)
                self.schedule_model.setItem(j, int(i), it)

    def addStudent(self):
        dialog = QDialog()
        content = EditStudent(self.session)
        content.setupUi(dialog)
        dialog.exec_()
        self.updateStudentModel()
        self.updateScheduleModel()

    def addSubject(self):
        dialog = QDialog()
        content = EditSubject(self.session)
        content.setupUi(dialog)
        dialog.exec_()
        self.updateSubjectModel()
        self.updateScheduleModel()

    def editStudent(self, idx):
        dialog = QDialog()
        content = EditStudent(self.session,
                              self.student_model.itemFromIndex(idx).data())
        content.setupUi(dialog)
        dialog.exec_()
        self.updateStudentModel()
        self.updateScheduleModel()

    def editSubject(self, idx):
        dialog = QDialog()
        content = EditSubject(self.session,
                              self.subject_model.itemFromIndex(idx).data())
        content.setupUi(dialog)
        dialog.exec_()
        self.updateSubjectModel()
        self.updateScheduleModel()

    def changeSelectedStudent(self, selected, unselected):
        tps = []
        for s in selected:
            for i in s.indexes():
                student = self.student_model.itemFromIndex(i).data()
                for subject in student.subjects:
                    for tp in subject.time_places:
                        tps.append((tp.slot, int(tp.day)))

        crossed = QBrush(Qt.black, Qt.BDiagPattern)
        normal = QBrush(Qt.white)

        for i in range(12):
            for j in map(int, DayOfWeek):
                if (i, j) in tps:
                    self.schedule_model.item(i, j).setBackground(normal)
                else:
                    self.schedule_model.item(i, j).setBackground(crossed)

    def openFile(self):
        new_filename = QFileDialog.getOpenFileName(
            caption="Open file", filter="SQLite3 file (*.sqlite3)")[0]
        if new_filename:
            self.filename = new_filename
            self.engine.dispose()
            self.engine = create_engine('sqlite:///' + self.filename)
            Base.metadata.create_all(self.engine)
            self.Session = sessionmaker(bind=self.engine)
            self.session = self.Session()
            self.updateStudentModel()
            self.updateSubjectModel()
            self.updateScheduleModel()

    def saveFile(self):
        if self.filename == ':memory:':
            self.saveFileAs()
        else:
            self.session.commit()

    def saveFileAs(self):
        new_filename = QFileDialog.getSaveFileName(
            caption="Save file as", filter="SQLite3 file (*.sqlite3)")[0]
        if new_filename:
            new_engine = create_engine('sqlite:///' + new_filename)
            Base.metadata.drop_all(new_engine)
            Base.metadata.create_all(new_engine)
            tables = Base.metadata.tables
            for tbl in tables:
                data = self.engine.execute(tables[tbl].select()).fetchall()
                if data:
                    new_engine.execute(tables[tbl].insert(), data)
            self.engine.dispose()
            self.engine = new_engine
            self.Session = sessionmaker(bind=self.engine)
            self.session = self.Session()
            self.filename = new_filename
            self.updateSubjectModel()
            self.updateStudentModel()
            self.updateScheduleModel()

    def showAbout(self):
        dialog = QDialog()
        ui = About()
        ui.setupUi(dialog)
        dialog.exec_()
Exemplo n.º 55
0
class JavaExplorerPanel(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent=parent)

        self._app_window = parent

        self._handle_history = []

        self._setup_ui()
        self._setup_models()

    def _setup_ui(self):
        self.setContentsMargins(0, 0, 0, 0)

        top_font = QFont()
        top_font.setBold(True)
        top_font.setPixelSize(19)

        # main wrapper
        main_wrapper = QVBoxLayout()
        main_wrapper.setContentsMargins(1, 1, 1, 1)

        # wrapwdgt
        wrap_wdgt = QWidget()
        self._top_class_name = QLabel(wrap_wdgt)
        self._top_class_name.setContentsMargins(10, 10, 10, 10)
        self._top_class_name.setAttribute(Qt.WA_TranslucentBackground,
                                          True)  # keep this
        self._top_class_name.setFont(top_font)
        self._top_class_name.setStyleSheet('color: #ef5350;')
        wrap_wdgt.setMaximumHeight(self._top_class_name.height() + 20)

        main_wrapper.addWidget(wrap_wdgt)

        # left list
        left_wrap_wdgt = QWidget()

        left_v_box = QVBoxLayout(left_wrap_wdgt)
        left_v_box.setContentsMargins(0, 0, 0, 0)

        methods_label = QLabel('METHODS')
        font = methods_label.font()
        font.setBold(True)
        methods_label.setFont(font)
        methods_label.setContentsMargins(10, 0, 10, 2)
        methods_label.setAttribute(Qt.WA_TranslucentBackground,
                                   True)  # keep this
        left_v_box.addWidget(methods_label)

        self._methods_list = DwarfListView()
        left_v_box.addWidget(self._methods_list)

        # center list
        center_wrap_wdgt = QWidget()

        center_v_box = QVBoxLayout(center_wrap_wdgt)
        center_v_box.setContentsMargins(0, 0, 0, 0)

        methods_label = QLabel('NATIVE FIELDS')
        methods_label.setFont(font)
        methods_label.setContentsMargins(10, 0, 10, 2)
        methods_label.setAttribute(Qt.WA_TranslucentBackground,
                                   True)  # keep this
        center_v_box.addWidget(methods_label)

        self._native_fields_list = DwarfListView()
        self._native_fields_list.doubleClicked.connect(
            self._on_native_field_dblclicked)
        center_v_box.addWidget(self._native_fields_list)

        # right list
        right_wrap_wdgt = QWidget()

        right_v_box = QVBoxLayout(right_wrap_wdgt)
        right_v_box.setContentsMargins(0, 0, 0, 0)

        methods_label = QLabel('FIELDS')
        methods_label.setFont(font)
        methods_label.setContentsMargins(10, 0, 10, 2)
        methods_label.setAttribute(Qt.WA_TranslucentBackground,
                                   True)  # keep this
        right_v_box.addWidget(methods_label)

        self._fields_list = DwarfListView()
        self._fields_list.doubleClicked.connect(self._on_field_dblclicked)
        right_v_box.addWidget(self._fields_list)

        # main splitter
        main_splitter = QSplitter(Qt.Horizontal)
        main_splitter.setContentsMargins(0, 0, 0, 0)
        main_splitter.addWidget(left_wrap_wdgt)
        main_splitter.addWidget(center_wrap_wdgt)
        main_splitter.addWidget(right_wrap_wdgt)
        main_splitter.setSizes([250, 100, 100])

        main_wrapper.addWidget(main_splitter)
        main_wrapper.setSpacing(0)
        self.setLayout(main_wrapper)

    def _setup_models(self):
        # left list
        self._methods_model = QStandardItemModel(0, 3)
        self._methods_model.setHeaderData(0, Qt.Horizontal, 'Name')
        self._methods_model.setHeaderData(1, Qt.Horizontal, 'Return')
        self._methods_model.setHeaderData(2, Qt.Horizontal, 'Arguments')
        self._methods_list.setModel(self._methods_model)
        self._methods_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        self._methods_list.header().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        # center list
        self._native_fields_model = QStandardItemModel(0, 2)
        self._native_fields_model.setHeaderData(0, Qt.Horizontal, 'Name')
        self._native_fields_model.setHeaderData(1, Qt.Horizontal, 'Value')
        self._native_fields_list.setModel(self._native_fields_model)
        self._native_fields_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)
        # right list
        self._fields_model = QStandardItemModel(0, 2)
        self._fields_model.setHeaderData(0, Qt.Horizontal, 'Name')
        self._fields_model.setHeaderData(1, Qt.Horizontal, 'Class')
        self._fields_list.setModel(self._fields_model)
        self._fields_list.header().setSectionResizeMode(
            0, QHeaderView.ResizeToContents)

    # ************************************************************************
    # **************************** Functions *********************************
    # ************************************************************************
    def _set_data(self, data):
        if 'class' not in data:
            return

        self._top_class_name.setText(data['class'])
        data = data['data']

        self._methods_list.clear()
        self._native_fields_list.clear()
        self._fields_list.clear()

        for key in data:
            ref = data[key]
            if ref['type'] == 'function':
                if not key.startswith('$'):
                    self._add_method(key, ref)
            elif ref['type'] == 'object':
                if ref['handle'] is not None:
                    if not key.startswith('$'):
                        self._add_field(key, ref['value'], ref['handle'],
                                        ref['handle_class'])
            else:
                if not key.startswith('$'):
                    self._add_field(key, ref['value'], is_native=True)

        self._methods_list.sortByColumn(0, 0)
        self._native_fields_list.sortByColumn(0, 0)
        self._fields_list.sortByColumn(0, 0)

    def _add_method(self, name, ref):
        ref_overloads = ref['overloads']
        for _, ref_overload in enumerate(ref_overloads):
            args = []

            if 'args' in ref_overload:
                for arg in ref_overload['args']:
                    if 'className' in arg:
                        args.append(arg['className'])

            self._methods_model.appendRow([
                QStandardItem(name),
                QStandardItem(ref_overload['return']['className']),
                QStandardItem('(%s)' % ', '.join(args)),
            ])

    def _add_field(self,
                   name,
                   value,
                   handle=None,
                   handle_class=None,
                   is_native=False):
        if handle:
            handle = {'handle': handle, 'handle_class': handle_class}
            handle_item = QStandardItem(name)
            handle_item.setData(handle, Qt.UserRole + 1)
        else:
            handle_item = QStandardItem(name)

        if not is_native:
            self._fields_model.appendRow(
                [handle_item, QStandardItem(str(value))])
        else:
            self._native_fields_model.appendRow(
                [handle_item, QStandardItem(str(value))])

    def _set_handle(self, handle):
        data = self._app_window.dwarf.dwarf_api('javaExplorer', handle)
        if not data:
            return
        self._handle_history.append({'handle': handle})
        self._set_data(data)

    def _set_handle_arg(self, arg):
        data = self._app_window.dwarf.dwarf_api('javaExplorer', arg)
        if not data:
            return
        self._handle_history.append({'handle': arg})
        self._set_data(data)

    def clear_panel(self):
        self._top_class_name.setText('')
        self._handle_history = []
        self._methods_list.clear()
        self._native_fields_list.clear()
        self._fields_list.clear()

    def _back(self):
        if len(self._handle_history) < 2:
            return
        self._handle_history.pop()
        data = self._handle_history.pop(len(self._handle_history) -
                                        1)['handle']
        if isinstance(data, int):
            self._set_handle_arg(data)
        else:
            self._set_handle(data)

    # ************************************************************************
    # **************************** Handlers **********************************
    # ************************************************************************
    def _on_field_dblclicked(self, _):
        field_row = self._fields_list.selectionModel().currentIndex().row()
        if field_row >= 0:
            field_handle = self._fields_model.item(field_row,
                                                   0).data(Qt.UserRole + 1)
            if field_handle:
                self._set_handle(field_handle)

    def _on_native_field_dblclicked(self, _):
        field_row = self._native_fields_list.selectionModel().currentIndex(
        ).row()
        if field_row:
            field_handle = self._native_fields_model.item(
                field_row, 0).data(Qt.UserRole + 1)
            if field_handle:
                self._set_handle(field_handle)

    def keyPressEvent(self, event):  # pylint: disable=invalid-name
        if event.key() == Qt.Key_Backspace:
            self._back()

        return super().keyPressEvent(event)
Exemplo n.º 56
0
class AttrsUI(object):
    def __init__(self, window, uaclient):
        self.window = window
        self.uaclient = uaclient
        self.model = QStandardItemModel()
        self.window.ui.attrView.setModel(self.model)
        self.window.ui.attrView.header().setSectionResizeMode(1)

        self.window.ui.treeView.activated.connect(self.show_attrs)
        self.window.ui.treeView.clicked.connect(self.show_attrs)
        self.window.ui.attrRefreshButton.clicked.connect(self.show_attrs)

        # Context menu
        self.window.ui.attrView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.window.ui.attrView.customContextMenuRequested.connect(
            self.showContextMenu)
        copyaction = QAction("&Copy Value", self.model)
        copyaction.triggered.connect(self._copy_value)
        self._contextMenu = QMenu()
        self._contextMenu.addAction(copyaction)

    def showContextMenu(self, position):
        item = self.get_current_item()
        if item:
            self._contextMenu.exec_(
                self.window.ui.attrView.mapToGlobal(position))

    def get_current_item(self, col_idx=0):
        idx = self.window.ui.attrView.currentIndex()
        return self.model.item(idx.row(), col_idx)

    def _copy_value(self, position):
        it = self.get_current_item(1)
        if it:
            QApplication.clipboard().setText(it.text())

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

    def show_attrs(self, idx):
        if not isinstance(idx, QModelIndex):
            idx = None
        node = self.window.get_current_node(idx)
        self.model.clear()
        if node:
            self._show_attrs(node)

    def _show_attrs(self, node):
        try:
            attrs = self.uaclient.get_all_attrs(node)
        except Exception as ex:
            self.window.show_error(ex)
            raise
        self.model.setHorizontalHeaderLabels(['Attribute', 'Value'])
        for k, v in attrs.items():
            if isinstance(v, (ua.NodeId)):
                v = str(v)
            elif isinstance(v, (ua.QualifiedName, ua.LocalizedText)):
                v = v.to_string()
            elif isinstance(v, Enum):
                v = repr(v)
            elif isinstance(v, ua.DataValue):
                v = repr(v)
            else:
                v = str(v)
            self.model.appendRow([QStandardItem(k), QStandardItem(v)])
Exemplo n.º 57
0
class JavaTracePanel(QWidget):
    def __init__(self, app, *__args):
        super().__init__(app)
        self.app = app

        self.app.dwarf.onJavaTraceEvent.connect(self.on_event)
        self.app.dwarf.onEnumerateJavaClassesStart.connect(
            self.on_enumeration_start)
        self.app.dwarf.onEnumerateJavaClassesMatch.connect(
            self.on_enumeration_match)
        self.app.dwarf.onEnumerateJavaClassesComplete.connect(
            self.on_enumeration_complete)

        self.tracing = False
        self.trace_classes = []
        self.trace_depth = 0

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)

        self._record_icon = QIcon(
            utils.resource_path('assets/icons/record.png'))
        self._pause_icon = QIcon(utils.resource_path('assets/icons/pause.png'))
        self._stop_icon = QIcon(utils.resource_path('assets/icons/stop.png'))

        self._tool_bar = QToolBar()
        self._tool_bar.addAction('Start', self.start_trace)
        self._tool_bar.addAction('Pause', self.pause_trace)
        self._tool_bar.addAction('Stop', self.stop_trace)
        self._tool_bar.addSeparator()
        self._entries_lbl = QLabel('Entries: 0')
        self._entries_lbl.setStyleSheet('color: #ef5350;')
        self._entries_lbl.setContentsMargins(10, 0, 10, 2)
        self._entries_lbl.setAttribute(Qt.WA_TranslucentBackground,
                                       True)  # keep this
        self._entries_lbl.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
        self._entries_lbl.setSizePolicy(QSizePolicy.Expanding,
                                        QSizePolicy.Preferred)
        self._tool_bar.addWidget(self._entries_lbl)

        layout.addWidget(self._tool_bar)

        self.setup_splitter = QSplitter()
        self.events_list = JavaTraceView(self)
        self.events_list.setVisible(False)

        self.trace_list = DwarfListView()
        self.trace_list_model = QStandardItemModel(0, 1)
        self.trace_list_model.setHeaderData(0, Qt.Horizontal, 'Traced')
        self.trace_list.setModel(self.trace_list_model)

        self.trace_list.doubleClicked.connect(self.trace_list_double_click)

        self.class_list = DwarfListView()
        self.class_list_model = QStandardItemModel(0, 1)
        self.class_list_model.setHeaderData(0, Qt.Horizontal, 'Classes')
        self.class_list.setModel(self.class_list_model)

        self.class_list.setContextMenuPolicy(Qt.CustomContextMenu)
        self.class_list.customContextMenuRequested.connect(
            self.show_class_list_menu)
        self.class_list.doubleClicked.connect(self.class_list_double_click)

        self.current_class_search = ''

        bar = QScrollBar()
        bar.setFixedWidth(0)
        bar.setFixedHeight(0)
        self.trace_list.setHorizontalScrollBar(bar)
        bar = QScrollBar()
        bar.setFixedWidth(0)
        bar.setFixedHeight(0)
        self.class_list.setHorizontalScrollBar(bar)

        self.setup_splitter.addWidget(self.trace_list)
        self.setup_splitter.addWidget(self.class_list)

        layout.addWidget(self.setup_splitter)
        layout.addWidget(self.events_list)

        self.setLayout(layout)

    def class_list_double_click(self, item):
        item = self.class_list_model.itemFromIndex(item)
        try:
            if self.trace_classes.index(item.text()) >= 0:
                return
        except:
            pass
        self.trace_classes.append(item.text())
        self.trace_list_model.appendRow([QStandardItem(item.text())])
        self.trace_list_model.sort(0, Qt.AscendingOrder)

    def on_enumeration_start(self):
        self.class_list_model.setRowCount(0)

    def on_enumeration_match(self, java_class):
        try:
            if PREFIXED_CLASS.index(java_class) >= 0:
                try:
                    if self.trace_classes.index(java_class) >= 0:
                        return
                except:
                    pass
                self.trace_list_model.appendRow(QStandardItem(java_class))
                self.trace_classes.append(java_class)
        except:
            pass

        self.class_list_model.appendRow([QStandardItem(java_class)])

    def on_enumeration_complete(self):
        self.class_list_model.sort(0, Qt.AscendingOrder)
        self.trace_list_model.sort(0, Qt.AscendingOrder)

    def on_event(self, data):
        trace, event, clazz, data = data
        if trace == 'java_trace':
            self.events_list.add_event({
                'event': event,
                'class': clazz,
                'data': data.replace(',', ', ')
            })
            self._entries_lbl.setText('Events: %d' %
                                      len(self.events_list.data))

    def pause_trace(self):
        self.app.dwarf.dwarf_api('stopJavaTracer')
        self.tracing = False

    def show_class_list_menu(self, pos):
        menu = QMenu()
        search = menu.addAction('Search')
        action = menu.exec_(self.class_list.mapToGlobal(pos))
        if action:
            if action == search:
                self.class_list._on_cm_search()

    def start_trace(self):
        self.app.dwarf.dwarf_api('startJavaTracer', [self.trace_classes])
        self.trace_depth = 0
        self.tracing = True
        self.setup_splitter.setVisible(False)
        self.events_list.setVisible(True)

    def stop_trace(self):
        self.app.dwarf.dwarf_api('stopJavaTracer')
        self.tracing = False
        self.setup_splitter.setVisible(True)
        self.events_list.setVisible(False)
        self.events_list.clear()

    def trace_list_double_click(self, model_index):
        row = self.trace_list_model.itemFromIndex(model_index).row()
        if row != -1:
            trace_entry = self.trace_list_model.item(row, 0).text()

            if not trace_entry:
                return

            try:
                index = self.trace_classes.index(trace_entry)
                self.trace_classes.pop(index)
                self.trace_list_model.removeRow(row)
            except ValueError:
                pass

    def keyPressEvent(self, event):
        if event.modifiers() & Qt.ControlModifier:
            if event.key() == Qt.Key_F:
                self.search()
        super(JavaTracePanel, self).keyPressEvent(event)
Exemplo n.º 58
0
Arquivo: main.py Projeto: lordmauve/mu
class Window(QMainWindow):
    """
    Defines the look and characteristics of the application's main window.
    """

    title = _("Mu {}").format(__version__)
    icon = "icon"
    timer = None
    usb_checker = None
    serial = None
    repl = None
    plotter = None

    _zoom_in = pyqtSignal(int)
    _zoom_out = pyqtSignal(int)
    close_serial = pyqtSignal()
    write_to_serial = pyqtSignal(bytes)
    data_received = pyqtSignal(bytes)

    def zoom_in(self):
        """
        Handles zooming in.
        """
        self._zoom_in.emit(2)

    def zoom_out(self):
        """
        Handles zooming out.
        """
        self._zoom_out.emit(2)

    def connect_zoom(self, widget):
        """
        Connects a referenced widget to the zoom related signals.
        """
        self._zoom_in.connect(widget.zoomIn)
        self._zoom_out.connect(widget.zoomOut)

    @property
    def current_tab(self):
        """
        Returns the currently focussed tab.
        """
        return self.tabs.currentWidget()

    def set_read_only(self, is_readonly):
        """
        Set all tabs read-only.
        """
        self.read_only_tabs = is_readonly
        for tab in self.widgets:
            tab.setReadOnly(is_readonly)

    def get_load_path(self, folder):
        """
        Displays a dialog for selecting a file to load. Returns the selected
        path. Defaults to start in the referenced folder.
        """
        path, _ = QFileDialog.getOpenFileName(self.widget, 'Open file', folder,
                                              '*.py *.PY *.hex')
        logger.debug('Getting load path: {}'.format(path))
        return path

    def get_save_path(self, folder):
        """
        Displays a dialog for selecting a file to save. Returns the selected
        path. Defaults to start in the referenced folder.
        """
        path, _ = QFileDialog.getSaveFileName(self.widget, 'Save file', folder)
        logger.debug('Getting save path: {}'.format(path))
        return path

    def get_microbit_path(self, folder):
        """
        Displays a dialog for locating the location of the BBC micro:bit in the
        host computer's filesystem. Returns the selected path. Defaults to
        start in the referenced folder.
        """
        path = QFileDialog.getExistingDirectory(self.widget,
                                                'Locate BBC micro:bit', folder,
                                                QFileDialog.ShowDirsOnly)
        logger.debug('Getting micro:bit path: {}'.format(path))
        return path

    def add_tab(self, path, text, api):
        """
        Adds a tab with the referenced path and text to the editor.
        """
        new_tab = EditorPane(path, text)
        new_tab.connect_margin(self.breakpoint_toggle)
        new_tab_index = self.tabs.addTab(new_tab, new_tab.label)
        new_tab.set_api(api)

        @new_tab.modificationChanged.connect
        def on_modified():
            modified_tab_index = self.tabs.currentIndex()
            self.tabs.setTabText(modified_tab_index, new_tab.label)
            self.update_title(new_tab.label)

        self.tabs.setCurrentIndex(new_tab_index)
        self.connect_zoom(new_tab)
        self.set_theme(self.theme)
        new_tab.setFocus()
        if self.read_only_tabs:
            new_tab.setReadOnly(self.read_only_tabs)

    def focus_tab(self, tab):
        index = self.tabs.indexOf(tab)
        self.tabs.setCurrentIndex(index)
        tab.setFocus()

    @property
    def tab_count(self):
        """
        Returns the number of active tabs.
        """
        return self.tabs.count()

    @property
    def widgets(self):
        """
        Returns a list of references to the widgets representing tabs in the
        editor.
        """
        return [self.tabs.widget(i) for i in range(self.tab_count)]

    @property
    def modified(self):
        """
        Returns a boolean indication if there are any modified tabs in the
        editor.
        """
        for widget in self.widgets:
            if widget.isModified():
                return True
        return False

    def on_serial_read(self):
        """
        Called when the connected device is ready to send data via the serial
        connection. It reads all the available data, emits the data_received
        signal with the received bytes and, if appropriate, emits the
        tuple_received signal with the tuple created from the bytes received.
        """
        data = bytes(self.serial.readAll())  # get all the available bytes.
        self.data_received.emit(data)

    def open_serial_link(self, port):
        """
        Creates a new serial link instance.
        """
        self.input_buffer = []
        self.serial = QSerialPort()
        self.serial.setPortName(port)
        if self.serial.open(QIODevice.ReadWrite):
            self.serial.dataTerminalReady = True
            if not self.serial.isDataTerminalReady():
                # Using pyserial as a 'hack' to open the port and set DTR
                # as QtSerial does not seem to work on some Windows :(
                # See issues #281 and #302 for details.
                self.serial.close()
                pyser = serial.Serial(port)  # open serial port w/pyserial
                pyser.dtr = True
                pyser.close()
                self.serial.open(QIODevice.ReadWrite)
            self.serial.setBaudRate(115200)
            self.serial.readyRead.connect(self.on_serial_read)
        else:
            raise IOError("Cannot connect to device on port {}".format(port))

    def close_serial_link(self):
        """
        Close and clean up the currently open serial link.
        """
        self.serial.close()
        self.serial = None

    def add_filesystem(self, home, file_manager):
        """
        Adds the file system pane to the application.
        """
        self.fs_pane = FileSystemPane(home)
        self.fs = QDockWidget(_('Filesystem on micro:bit'))
        self.fs.setWidget(self.fs_pane)
        self.fs.setFeatures(QDockWidget.DockWidgetMovable)
        self.fs.setAllowedAreas(Qt.BottomDockWidgetArea)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.fs)
        self.fs_pane.setFocus()
        file_manager.on_list_files.connect(self.fs_pane.on_ls)
        self.fs_pane.list_files.connect(file_manager.ls)
        self.fs_pane.microbit_fs.put.connect(file_manager.put)
        self.fs_pane.microbit_fs.delete.connect(file_manager.delete)
        self.fs_pane.microbit_fs.list_files.connect(file_manager.ls)
        self.fs_pane.local_fs.get.connect(file_manager.get)
        self.fs_pane.local_fs.list_files.connect(file_manager.ls)
        file_manager.on_put_file.connect(self.fs_pane.microbit_fs.on_put)
        file_manager.on_delete_file.connect(self.fs_pane.microbit_fs.on_delete)
        file_manager.on_get_file.connect(self.fs_pane.local_fs.on_get)
        file_manager.on_list_fail.connect(self.fs_pane.on_ls_fail)
        file_manager.on_put_fail.connect(self.fs_pane.on_put_fail)
        file_manager.on_delete_fail.connect(self.fs_pane.on_delete_fail)
        file_manager.on_get_fail.connect(self.fs_pane.on_get_fail)
        self.connect_zoom(self.fs_pane)
        return self.fs_pane

    def add_micropython_repl(self, port, name):
        """
        Adds a MicroPython based REPL pane to the application.
        """
        if not self.serial:
            self.open_serial_link(port)
            # Send a Control-C / keyboard interrupt.
            self.serial.write(b'\x03')
        repl_pane = MicroPythonREPLPane(serial=self.serial, theme=self.theme)
        self.data_received.connect(repl_pane.process_bytes)
        self.add_repl(repl_pane, name)

    def add_micropython_plotter(self, port, name):
        """
        Adds a plotter that reads data from a serial connection.
        """
        if not self.serial:
            self.open_serial_link(port)
        plotter_pane = PlotterPane(theme=self.theme)
        self.data_received.connect(plotter_pane.process_bytes)
        self.add_plotter(plotter_pane, name)

    def add_jupyter_repl(self, kernel_manager, kernel_client):
        """
        Adds a Jupyter based REPL pane to the application.
        """
        kernel_manager.kernel.gui = 'qt4'
        kernel_client.start_channels()
        ipython_widget = JupyterREPLPane(theme=self.theme)
        ipython_widget.kernel_manager = kernel_manager
        ipython_widget.kernel_client = kernel_client
        self.add_repl(ipython_widget, _('Python3 (Jupyter)'))

    def add_repl(self, repl_pane, name):
        """
        Adds the referenced REPL pane to the application.
        """
        self.repl_pane = repl_pane
        self.repl = QDockWidget(_('{} REPL').format(name))
        self.repl.setWidget(repl_pane)
        self.repl.setFeatures(QDockWidget.DockWidgetMovable)
        self.repl.setAllowedAreas(Qt.BottomDockWidgetArea |
                                  Qt.LeftDockWidgetArea |
                                  Qt.RightDockWidgetArea)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.repl)
        self.connect_zoom(self.repl_pane)
        self.repl_pane.set_theme(self.theme)
        self.repl_pane.setFocus()

    def add_plotter(self, plotter_pane, name):
        """
        Adds the referenced plotter pane to the application.
        """
        self.plotter_pane = plotter_pane
        self.plotter = QDockWidget(_('{} Plotter').format(name))
        self.plotter.setWidget(plotter_pane)
        self.plotter.setFeatures(QDockWidget.DockWidgetMovable)
        self.plotter.setAllowedAreas(Qt.BottomDockWidgetArea |
                                     Qt.LeftDockWidgetArea |
                                     Qt.RightDockWidgetArea)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.plotter)
        self.plotter_pane.set_theme(self.theme)
        self.plotter_pane.setFocus()

    def add_python3_runner(self, script_name, working_directory,
                           interactive=False, debugger=False,
                           command_args=None, runner=None):
        """
        Display console output for the referenced Python script.

        The script will be run within the workspace_path directory.

        If interactive is True (default is False) the Python process will
        run in interactive mode (dropping the user into the REPL when the
        script completes).

        If debugger is True (default is False) the script will be run within
        a debug runner session. The debugger overrides the interactive flag
        (you cannot run the debugger in interactive mode).

        If there is a list of command_args (the default is None) then these
        will be passed as further arguments into the command run in the
        new process.

        If runner is give, this is used as the command to start the Python
        process.
        """
        self.process_runner = PythonProcessPane(self)
        self.runner = QDockWidget(_("Running: {}").format(
                                  os.path.basename(script_name)))
        self.runner.setWidget(self.process_runner)
        self.runner.setFeatures(QDockWidget.DockWidgetMovable)
        self.runner.setAllowedAreas(Qt.BottomDockWidgetArea |
                                    Qt.LeftDockWidgetArea |
                                    Qt.RightDockWidgetArea)
        self.addDockWidget(Qt.BottomDockWidgetArea, self.runner)
        self.process_runner.start_process(script_name, working_directory,
                                          interactive, debugger, command_args,
                                          runner)
        self.process_runner.setFocus()
        self.connect_zoom(self.process_runner)
        return self.process_runner

    def add_debug_inspector(self):
        """
        Display a debug inspector to view the call stack.
        """
        self.debug_inspector = DebugInspector()
        self.debug_model = QStandardItemModel()
        self.debug_inspector.setModel(self.debug_model)
        self.debug_inspector.setUniformRowHeights(True)
        self.inspector = QDockWidget(_('Debug Inspector'))
        self.inspector.setWidget(self.debug_inspector)
        self.inspector.setFeatures(QDockWidget.DockWidgetMovable)
        self.inspector.setAllowedAreas(Qt.BottomDockWidgetArea |
                                       Qt.LeftDockWidgetArea |
                                       Qt.RightDockWidgetArea)
        self.addDockWidget(Qt.RightDockWidgetArea, self.inspector)
        self.connect_zoom(self.debug_inspector)

    def update_debug_inspector(self, locals_dict):
        """
        Given the contents of a dict representation of the locals in the
        current stack frame, update the debug inspector with the new values.
        """
        excluded_names = ['__builtins__', '__debug_code__',
                          '__debug_script__', ]
        names = sorted([x for x in locals_dict if x not in excluded_names])
        self.debug_model.clear()
        self.debug_model.setHorizontalHeaderLabels([_('Name'), _('Value'), ])
        for name in names:
            try:
                # DANGER!
                val = eval(locals_dict[name])
            except Exception:
                val = None
            if isinstance(val, list):
                # Show a list consisting of rows of position/value
                list_item = QStandardItem(name)
                for i, i_val in enumerate(val):
                    list_item.appendRow([
                        QStandardItem(str(i)),
                        QStandardItem(repr(i_val))
                    ])
                self.debug_model.appendRow([
                    list_item,
                    QStandardItem(_('(A list of {} items.)').format(len(val)))
                ])
            elif isinstance(val, dict):
                # Show a dict consisting of rows of key/value pairs.
                dict_item = QStandardItem(name)
                for k, k_val in val.items():
                    dict_item.appendRow([
                        QStandardItem(repr(k)),
                        QStandardItem(repr(k_val))
                    ])
                self.debug_model.appendRow([
                    dict_item,
                    QStandardItem(_('(A dict of {} items.)').format(len(val)))
                ])
            else:
                self.debug_model.appendRow([
                    QStandardItem(name),
                    QStandardItem(locals_dict[name]),
                ])

    def remove_filesystem(self):
        """
        Removes the file system pane from the application.
        """
        if hasattr(self, 'fs') and self.fs:
            self.fs_pane = None
            self.fs.setParent(None)
            self.fs.deleteLater()
            self.fs = None

    def remove_repl(self):
        """
        Removes the REPL pane from the application.
        """
        if self.repl:
            self.repl_pane = None
            self.repl.setParent(None)
            self.repl.deleteLater()
            self.repl = None
            if not self.plotter:
                self.serial = None

    def remove_plotter(self):
        """
        Removes the plotter pane from the application.
        """
        if self.plotter:
            self.plotter_pane = None
            self.plotter.setParent(None)
            self.plotter.deleteLater()
            self.plotter = None
            if not self.repl:
                self.serial = None

    def remove_python_runner(self):
        """
        Removes the runner pane from the application.
        """
        if hasattr(self, 'runner') and self.runner:
            self.process_runner = None
            self.runner.setParent(None)
            self.runner.deleteLater()
            self.runner = None

    def remove_debug_inspector(self):
        """
        Removes the debug inspector pane from the application.
        """
        if hasattr(self, 'inspector') and self.inspector:
            self.debug_inspector = None
            self.debug_model = None
            self.inspector.setParent(None)
            self.inspector.deleteLater()
            self.inspector = None

    def set_theme(self, theme):
        """
        Sets the theme for the REPL and editor tabs.
        """
        self.theme = theme
        if theme == 'contrast':
            self.setStyleSheet(CONTRAST_STYLE)
            new_theme = ContrastTheme
            new_icon = 'theme_day'
        elif theme == 'night':
            new_theme = NightTheme
            new_icon = 'theme_contrast'
            self.setStyleSheet(NIGHT_STYLE)
        else:
            self.setStyleSheet(DAY_STYLE)
            new_theme = DayTheme
            new_icon = 'theme'
        for widget in self.widgets:
            widget.set_theme(new_theme)
        self.button_bar.slots['theme'].setIcon(load_icon(new_icon))
        if hasattr(self, 'repl') and self.repl:
            self.repl_pane.set_theme(theme)
        if hasattr(self, 'plotter') and self.plotter:
            self.plotter_pane.set_theme(theme)

    def show_logs(self, log, theme):
        """
        Display the referenced content of the log.
        """
        log_box = LogDisplay()
        log_box.setup(log, theme)
        log_box.exec()

    def show_message(self, message, information=None, icon=None):
        """
        Displays a modal message to the user.

        If information is passed in this will be set as the additional
        informative text in the modal dialog.

        Since this mechanism will be used mainly for warning users that
        something is awry the default icon is set to "Warning". It's possible
        to override the icon to one of the following settings: NoIcon,
        Question, Information, Warning or Critical.
        """
        message_box = QMessageBox(self)
        message_box.setText(message)
        message_box.setWindowTitle('Mu')
        if information:
            message_box.setInformativeText(information)
        if icon and hasattr(message_box, icon):
            message_box.setIcon(getattr(message_box, icon))
        else:
            message_box.setIcon(message_box.Warning)
        logger.debug(message)
        logger.debug(information)
        message_box.exec()

    def show_confirmation(self, message, information=None, icon=None):
        """
        Displays a modal message to the user to which they need to confirm or
        cancel.

        If information is passed in this will be set as the additional
        informative text in the modal dialog.

        Since this mechanism will be used mainly for warning users that
        something is awry the default icon is set to "Warning". It's possible
        to override the icon to one of the following settings: NoIcon,
        Question, Information, Warning or Critical.
        """
        message_box = QMessageBox()
        message_box.setText(message)
        message_box.setWindowTitle(_('Mu'))
        if information:
            message_box.setInformativeText(information)
        if icon and hasattr(message_box, icon):
            message_box.setIcon(getattr(message_box, icon))
        else:
            message_box.setIcon(message_box.Warning)
        message_box.setStandardButtons(message_box.Cancel | message_box.Ok)
        message_box.setDefaultButton(message_box.Cancel)
        logger.debug(message)
        logger.debug(information)
        return message_box.exec()

    def update_title(self, filename=None):
        """
        Updates the title bar of the application. If a filename (representing
        the name of the file currently the focus of the editor) is supplied,
        append it to the end of the title.
        """
        title = self.title
        if filename:
            title += ' - ' + filename
        self.setWindowTitle(title)

    def autosize_window(self):
        """
        Makes the editor 80% of the width*height of the screen and centres it.
        """
        screen = QDesktopWidget().screenGeometry()
        w = int(screen.width() * 0.8)
        h = int(screen.height() * 0.8)
        self.resize(w, h)
        size = self.geometry()
        self.move((screen.width() - size.width()) / 2,
                  (screen.height() - size.height()) / 2)

    def reset_annotations(self):
        """
        Resets the state of annotations on the current tab.
        """
        self.current_tab.reset_annotations()

    def annotate_code(self, feedback, annotation_type):
        """
        Given a list of annotations about the code in the current tab, add
        the annotations to the editor window so the user can make appropriate
        changes.
        """
        self.current_tab.annotate_code(feedback, annotation_type)

    def show_annotations(self):
        """
        Show the annotations added to the current tab.
        """
        self.current_tab.show_annotations()

    def setup(self, breakpoint_toggle, theme):
        """
        Sets up the window.

        Defines the various attributes of the window and defines how the user
        interface is laid out.
        """
        self.theme = theme
        self.breakpoint_toggle = breakpoint_toggle
        # Give the window a default icon, title and minimum size.
        self.setWindowIcon(load_icon(self.icon))
        self.update_title()
        self.read_only_tabs = False
        self.setMinimumSize(800, 400)

        self.widget = QWidget()

        widget_layout = QVBoxLayout()
        self.widget.setLayout(widget_layout)
        self.button_bar = ButtonBar(self.widget)
        self.tabs = FileTabs()
        self.tabs.setMovable(True)
        self.setCentralWidget(self.tabs)
        self.status_bar = StatusBar(parent=self)
        self.setStatusBar(self.status_bar)
        self.addToolBar(self.button_bar)
        self.show()
        self.autosize_window()

    def resizeEvent(self, resizeEvent):
        """
        Respond to window getting too small for the button bar to fit well.
        """
        size = resizeEvent.size()
        self.button_bar.set_responsive_mode(size.width(), size.height())

    def select_mode(self, modes, current_mode, theme):
        """
        Display the mode selector dialog and return the result.
        """
        mode_select = ModeSelector()
        mode_select.setup(modes, current_mode, theme)
        mode_select.exec()
        try:
            return mode_select.get_mode()
        except Exception as ex:
            return None

    def change_mode(self, mode):
        """
        Given a an object representing a mode, recreates the button bar with
        the expected functionality.
        """
        self.button_bar.change_mode(mode)
        # Update the autocomplete / tooltip APIs for each tab to the new mode.
        api = mode.api()
        for widget in self.widgets:
            widget.set_api(api)

    def set_usb_checker(self, duration, callback):
        """
        Sets up a timer that polls for USB changes via the "callback" every
        "duration" seconds.
        """
        self.usb_checker = QTimer()
        self.usb_checker.timeout.connect(callback)
        self.usb_checker.start(duration * 1000)

    def set_timer(self, duration, callback):
        """
        Set a repeating timer to call "callback" every "duration" seconds.
        """
        self.timer = QTimer()
        self.timer.timeout.connect(callback)
        self.timer.start(duration * 1000)  # Measured in milliseconds.

    def stop_timer(self):
        """
        Stop the repeating timer.
        """
        if self.timer:
            self.timer.stop()
            self.timer = None

    def connect_tab_rename(self, handler, shortcut):
        """
        Connect the double-click event on a tab and the keyboard shortcut to
        the referenced handler (causing the Save As dialog).
        """
        self.tabs.shortcut = QShortcut(QKeySequence(shortcut), self)
        self.tabs.shortcut.activated.connect(handler)
        self.tabs.tabBarDoubleClicked.connect(handler)

    def open_directory_from_os(self, path):
        """
        Given the path to a directoy, open the OS's built in filesystem
        explorer for that path. Works with Windows, OSX and Linux.
        """
        if sys.platform == 'win32':
            # Windows
            os.startfile(path)
        elif sys.platform == 'darwin':
            # OSX
            os.system('open "{}"'.format(path))
        else:
            # Assume freedesktop.org on unix-y.
            os.system('xdg-open "{}"'.format(path))
Exemplo n.º 59
0
class VideoPlayer(QWidget):

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

        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAcceptDrops(True)
        
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.StreamPlayback)
        self.mediaPlayer.setVolume(80)
        
        self.videoWidget = QVideoWidget(self)
        self.videoWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.videoWidget.setMinimumSize(QSize(640, 360))
        
        self.lbl = QLineEdit('00:00:00')
        self.lbl.setReadOnly(True)
        self.lbl.setFixedWidth(70)
        self.lbl.setUpdatesEnabled(True)
        self.lbl.setStyleSheet(stylesheet(self))

        self.elbl = QLineEdit('00:00:00')
        self.elbl.setReadOnly(True)
        self.elbl.setFixedWidth(70)
        self.elbl.setUpdatesEnabled(True)
        self.elbl.setStyleSheet(stylesheet(self))

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setFixedWidth(32)
        self.playButton.setStyleSheet("background-color: black")
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal, self)
        self.positionSlider.setStyleSheet(stylesheet(self))
        self.positionSlider.setRange(0, 100)
        self.positionSlider.sliderMoved.connect(self.setPosition)
        self.positionSlider.sliderMoved.connect(self.handleLabel)
        self.positionSlider.setSingleStep(2)
        self.positionSlider.setPageStep(20)
        self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True)

        self.clip = QApplication.clipboard()
        self.process = QProcess(self)
        self.process.readyRead.connect(self.dataReady)
        self.process.finished.connect(self.playFromURL)

        self.myurl = ""

        # channel list
        self.channelList = QListView(self)
        self.channelList.setMinimumSize(QSize(150, 0))
        self.channelList.setMaximumSize(QSize(150, 4000))
        self.channelList.setFrameShape(QFrame.Box)
        self.channelList.setObjectName("channelList")
        self.channelList.setStyleSheet("background-color: black; color: #585858;")
        self.channelList.setFocus()
        # for adding items to list must create a model
        self.model = QStandardItemModel()
        self.channelList.setModel(self.model)

        self.controlLayout = QHBoxLayout()
        self.controlLayout.setContentsMargins(5, 0, 5, 0)
        self.controlLayout.addWidget(self.playButton)
        self.controlLayout.addWidget(self.lbl)
        self.controlLayout.addWidget(self.positionSlider)
        self.controlLayout.addWidget(self.elbl)

        self.mainLayout = QHBoxLayout()

        # contains video and cotrol widgets to the left side
        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.addWidget(self.videoWidget)
        self.layout.addLayout(self.controlLayout)
        
        # adds channels list to the right
        self.mainLayout.addLayout(self.layout)
        self.mainLayout.addWidget(self.channelList)

        self.setLayout(self.mainLayout)

        self.myinfo = "©2020\nTIVOpy v1.0"

        self.widescreen = True

        #### shortcuts ####
        self.shortcut = QShortcut(QKeySequence("q"), self)
        self.shortcut.activated.connect(self.handleQuit)
        self.shortcut = QShortcut(QKeySequence("u"), self)
        self.shortcut.activated.connect(self.playFromURL)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Space), self)
        self.shortcut.activated.connect(self.play)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_F), self)
        self.shortcut.activated.connect(self.handleFullscreen)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Escape), self)
        self.shortcut.activated.connect(self.exitFullscreen)
        self.shortcut.activated.connect(self.handleFullscreen)
        self.shortcut = QShortcut(QKeySequence("i"), self)
        self.shortcut.activated.connect(self.handleInfo)
        self.shortcut = QShortcut(QKeySequence("s"), self)
        self.shortcut.activated.connect(self.toggleSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self)
        self.shortcut.activated.connect(self.backSlider)

        self.mediaPlayer.setVideoOutput(self.videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.positionChanged.connect(self.handleLabel)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

        self.populateChannelList()
        self.selectChannel()
        self.initialPlay()

    def playFromURL(self):
        self.mediaPlayer.pause()
        self.myurl = self.clip.text()
        self.mediaPlayer.setMedia(QMediaContent(QUrl(self.myurl)))
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()
        self.hideSlider()
        print(self.myurl)

    def dataReady(self):
        self.myurl = str(self.process.readAll(), encoding='utf8').rstrip()  ###
        self.myurl = self.myurl.partition("\n")[0]
        print(self.myurl)
        self.clip.setText(self.myurl)
        self.playFromURL()

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(
                self.style().standardIcon(QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(
                self.style().standardIcon(QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)
        mtime = QTime(0, 0, 0, 0)
        mtime = mtime.addMSecs(self.mediaPlayer.duration())
        self.elbl.setText(mtime.toString())

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

    def handleError(self):
        self.playButton.setEnabled(False)
        print("Error: ", self.mediaPlayer.errorString())

    def handleQuit(self):
        self.mediaPlayer.stop()
        print("Goodbye ...")
        app.quit()

    def contextMenuRequested(self, point):
        menu = QMenu()
        actionURL = menu.addAction(QIcon.fromTheme("browser"), "URL from Clipboard (u)")
        menu.addSeparator()
        actionToggle = menu.addAction(QIcon.fromTheme("next"), "Show / Hide Channels (s)")
        actionFull = menu.addAction(QIcon.fromTheme("view-fullscreen"), "Fullscreen (f)")
        menu.addSeparator()
        actionInfo = menu.addAction(QIcon.fromTheme("help-about"), "About (i)")
        menu.addSeparator()
        actionQuit = menu.addAction(QIcon.fromTheme("application-exit"), "Exit (q)")

        actionQuit.triggered.connect(self.handleQuit)
        actionFull.triggered.connect(self.handleFullscreen)
        actionInfo.triggered.connect(self.handleInfo)
        actionToggle.triggered.connect(self.toggleSlider)
        actionURL.triggered.connect(self.playFromURL)
        menu.exec_(self.mapToGlobal(point))

    def wheelEvent(self, event):
        mscale = event.angleDelta().y() / 13
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() + mscale)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def mouseDoubleClickEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.handleFullscreen()

    def handleFullscreen(self):
        if self.windowState() and Qt.WindowFullScreen:
            self.showNormal()
        else:
            self.showFullScreen()

    def exitFullscreen(self):
        self.showNormal()

    def handleInfo(self):
        QMessageBox.about(self, "About", self.myinfo)

    def toggleSlider(self):
        if self.positionSlider.isVisible():
            self.hideSlider()
        else:
            self.showSlider()

    def hideSlider(self):
        self.channelList.hide()
        self.playButton.hide()
        self.lbl.hide()
        self.positionSlider.hide()
        self.elbl.hide()

    def showSlider(self):
        self.channelList.show()
        self.playButton.show()
        self.lbl.show()
        self.positionSlider.show()
        self.elbl.show()
        self.channelList.setFocus()

    def forwardSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000 * 60)

    def backSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000 * 60)

    def volumeUp(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def volumeDown(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        elif event.mimeData().hasText():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        print("drop")
        if event.mimeData().hasUrls():
            url = event.mimeData().urls()[0].toString()
            print("url = ", url)
            self.mediaPlayer.stop()
            self.mediaPlayer.setMedia(QMediaContent(QUrl(url)))
            self.playButton.setEnabled(True)
            self.mediaPlayer.play()
        elif event.mimeData().hasText():
            mydrop = event.mimeData().text()
            print("generic url = ", mydrop)
            self.mediaPlayer.setMedia(QMediaContent(QUrl(mydrop)))
            self.playButton.setEnabled(True)
            self.mediaPlayer.play()
            self.hideSlider()

    def loadFilm(self, f):
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(f)))
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()

    def populateChannelList(self):
        # file must be in same directory as the script
        FILEPATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "canaletv.txt")
        # lines from file with "channel name" -- "link"
        channelArray = []
        # split file by line and adding it to the array
        with open(FILEPATH) as f:
            for line in f:
                channelArray.append(line.rstrip())
        # dictionary with key = channel name and value = link
        self.channelDict = dict(ch.split(" -- ") for ch in channelArray)
        for channel in self.channelDict.keys():
            item = QStandardItem(channel)
            self.model.appendRow(item)

    def selectedItemBehavior(self, index):
    # gets the link for the selected channel and plays it
        itms = self.channelList.selectedIndexes()
        for it in itms:
            channel = it.data()
            link = self.channelDict[channel]
            self.mediaPlayer.setMedia(QMediaContent(QUrl(link)))
            self.play()

    def selectChannel(self):
    # selecting channel from sidebar calls selectedItemBehavior
        self.selModel = self.channelList.selectionModel()
        self.selModel.selectionChanged.connect(self.selectedItemBehavior)

    def initialPlay(self):
    # play somenting when app opens
        self.mediaPlayer.setMedia(QMediaContent(QUrl("https://vid.hls.protv.ro/proxhdn/proxhd_3_34/index.m3u8?1")))
        self.play()

    def handleLabel(self):
        self.lbl.clear()
        mtime = QTime(0, 0, 0, 0)
        self.time = mtime.addMSecs(self.mediaPlayer.position())
        self.lbl.setText(self.time.toString())