I have this following code snippet to evaluate rowsMoved. I have used the QT editor and don't want to have to subclass (as other examples seem to want to show) and do are replaceWidget for every list widget in the program
So i stumbled upon rowsMoved though #vince in PySide: Drag and drop files into QListWidget
self.win.list_SocketGroups.model().rowsMoved.connect(self.my_method)
#Slot()
def my_method(self, parent, start, end, destination, row):
print("my_method, rows moved parent", type(parent), parent)
print("my_method, rows moved start", type(start), start)
print("my_method, rows moved end", type(end), end)
print("my_method, rows moved destination", type(destination), destination)
print("my_method, rows moved row", type(row), row)
print()
the output is :
<PySide6.QtWidgets.QLineEdit(0x26890824100, name="lineedit_SkillLabel") at 0x00000268913140C0>
my_method, rows moved parent <class 'PySide6.QtCore.QModelIndex'> <PySide6.QtCore.QModelIndex(-1,-1,0x0,QObject(0x0)) at 0x000002689998AEC0>
my_method, rows moved start <class 'int'> 0
my_method, rows moved end <class 'int'> 0
my_method, rows moved destination <class 'PySide6.QtCore.QModelIndex'> <PySide6.QtCore.QModelIndex(-1,-1,0x0,QObject(0x0)) at 0x000002689600D8C0>
my_method, rows moved row <class 'int'> 2
<PySide6.QtWidgets.QLineEdit(0x26890824100, name="lineedit_SkillLabel") at 0x00000268913140C0>
my_method, rows moved parent <class 'PySide6.QtCore.QModelIndex'> <PySide6.QtCore.QModelIndex(-1,-1,0x0,QObject(0x0)) at 0x000002689998AEC0>
my_method, rows moved start <class 'int'> 0
my_method, rows moved end <class 'int'> 0
my_method, rows moved destination <class 'PySide6.QtCore.QModelIndex'> <PySide6.QtCore.QModelIndex(-1,-1,0x0,QObject(0x0)) at 0x000002689600D8C0>
my_method, rows moved row <class 'int'> 2
<PySide6.QtWidgets.QLineEdit(0x26890824100, name="lineedit_SkillLabel") at 0x00000268913140C0>
my_method, rows moved parent <class 'PySide6.QtCore.QModelIndex'> <PySide6.QtCore.QModelIndex(-1,-1,0x0,QObject(0x0)) at 0x000002689998AEC0>
my_method, rows moved start <class 'int'> 0
my_method, rows moved end <class 'int'> 0
my_method, rows moved destination <class 'PySide6.QtCore.QModelIndex'> <PySide6.QtCore.QModelIndex(-1,-1,0x0,QObject(0x0)) at 0x000002689600D8C0>
my_method, rows moved row <class 'int'> 2
<PySide6.QtWidgets.QLineEdit(0x26890824100, name="lineedit_SkillLabel") at 0x00000268913140C0>
my_method, rows moved parent <class 'PySide6.QtCore.QModelIndex'> <PySide6.QtCore.QModelIndex(-1,-1,0x0,QObject(0x0)) at 0x000002689998AEC0>
my_method, rows moved start <class 'int'> 0
my_method, rows moved end <class 'int'> 0
my_method, rows moved destination <class 'PySide6.QtCore.QModelIndex'> <PySide6.QtCore.QModelIndex(-1,-1,0x0,QObject(0x0)) at 0x000002689600D8C0>
my_method, rows moved row <class 'int'> 2
As can be seen, it is called four times, with the same information.
The Question:
Was there something I was to do to acknowledge the call, like an event has event.accept and ignore, to stop the call coming through four times ?
Thanks
Related
I'm using a European Space Agency API to query (result can be viewed here) for satellite image metadata to parse into python objects.
Using the requests library I can successfully get the result in XML format and then read the content with lxml. I am able to find the elements and explore the tree as expected:
# loading the response into an ElementTree
tree = etree.fromstring(response.content)
root = tree.getroot()
ns = root.nsmap
# get the first entry element and its summary
e = root.find('entry',ns)
summary = e.find('summary',ns).text
print summary
>> 'Date: 2018-11-28T09:10:56.879Z, Instrument: OLCI, Mode: , Satellite: Sentinel-3, Size: 713.99 MB'
The entry element has several date descendants with different values of the attriubute name:
for d in e.findall('date',ns):
print d.tag, d.attrib
>> {http://www.w3.org/2005/Atom}date {'name': 'creationdate'}
{http://www.w3.org/2005/Atom}date {'name': 'beginposition'}
{http://www.w3.org/2005/Atom}date {'name': 'endposition'}
{http://www.w3.org/2005/Atom}date {'name': 'ingestiondate'}
I want to grab the beginposition date element using XPath syntax [#attrib='value'] but it just returns None. Even just searching for a date element with the name attribute ([#attrib]) returns None:
dt_begin = e.find('date[#name="beginposition"]',ns) # dt_begin is None
dt_begin = e.find('date[#name]',ns) # dt_begin is None
The entry element includes other children that exhibit the same behaviour e.g. multiple str elements also with differing name attributes.
Has anyone encountered anything similar or is there something I'm missing? I'm using Python 2.7.14 with lxml 4.2.4
It looks like an explicit prefix is needed when a predicate ([#name="beginposition"]) is used. Here is a test program:
from lxml import etree
print etree.LXML_VERSION
tree = etree.parse("data.xml")
ns1 = tree.getroot().nsmap
print ns1
print tree.find('entry', ns1)
print tree.find('entry/date', ns1)
print tree.find('entry/date[#name="beginposition"]', ns1)
ns2 = {"atom": 'http://www.w3.org/2005/Atom'}
print tree.find('atom:entry', ns2)
print tree.find('atom:entry/atom:date', ns2)
print tree.find('atom:entry/atom:date[#name="beginposition"]', ns2)
Output:
(4, 2, 5, 0)
{None: 'http://www.w3.org/2005/Atom', 'opensearch': 'http://a9.com/-/spec/opensearch/1.1/'}
<Element {http://www.w3.org/2005/Atom}entry at 0x7f8987750b90>
<Element {http://www.w3.org/2005/Atom}date at 0x7f89877503f8>
None
<Element {http://www.w3.org/2005/Atom}entry at 0x7f8987750098>
<Element {http://www.w3.org/2005/Atom}date at 0x7f898774a950>
<Element {http://www.w3.org/2005/Atom}date at 0x7f898774a7a0>
So I right now I have a list of edges of a graph. With this list, I'm trying to build a adjacency map, in which its key is an edge and the value is a list of edges that are adjacent to the edge. I'm using a nested loop that compares each edge in the list to every other edge in the list. However, this is not building a map that I expect it to. Below is my code:
def build_adjacency
#paths.each do |start_path|
#paths.each do |end_path|
# 3 cases for edge adcency
if (start_path.end_node == end_path.start_node) || (start_path.start_node == end_path.end_node) || (start_path.start_node == end_path.start_node)
if #adjacency_map.has_key?("#{start_path}".to_s)
#adjacency_map[:"#{start_path}".to_s] << end_path
else
value = [end_path]
#adjacency_map[:"#{start_path}".to_s] = value
end
end
end
end
end
I also tried array.combination but that is not working either. Thank you for the help.
Test input: (start node, end node, color, type)
A B R C
B E B C
B C B T
C D G T
Output for #adjacency_map:
C:\Users\Jin\Documents\Mines\Algorithms (CSCI 406)\Project_3>ruby graph.rb
Key: A B R C Value: [#<Path:0x2548a28 #start_node="A", #end_node="B", #color=
"R", #type="C">, #<Path:0x2548968 #start_node="B", #end_node="E", #color="B", #t
ype="C">, #<Path:0x25488a8 #start_node="B", #end_node="C", #color="B", #type="T"
>, #<Path:0x25487e8 #start_node="C", #end_node="D", #color="G", #type="T">]
Key: B E B C Value: [#<Path:0x2548a28 #start_node="A", #end_node="B", #color=
"R", #type="C">, #<Path:0x2548968 #start_node="B", #end_node="E", #color="B", #t
ype="C">, #<Path:0x25488a8 #start_node="B", #end_node="C", #color="B", #type="T"
>, #<Path:0x25487e8 #start_node="C", #end_node="D", #color="G", #type="T">]
Key: B C B T Value: [#<Path:0x2548a28 #start_node="A", #end_node="B", #color=
"R", #type="C">, #<Path:0x2548968 #start_node="B", #end_node="E", #color="B", #t
ype="C">, #<Path:0x25488a8 #start_node="B", #end_node="C", #color="B", #type="T"
>, #<Path:0x25487e8 #start_node="C", #end_node="D", #color="G", #type="T">]
Key: C D G T Value: [#<Path:0x2548a28 #start_node="A", #end_node="B", #color=
"R", #type="C">, #<Path:0x2548968 #start_node="B", #end_node="E", #color="B", #t
ype="C">, #<Path:0x25488a8 #start_node="B", #end_node="C", #color="B", #type="T"
>, #<Path:0x25487e8 #start_node="C", #end_node="D", #color="G", #type="T">]
The following is strange:
:"#{start_path}".to_s
What ever class your object start_path is, you convert it to a string via interpolation, than convert it to a symbol, only to then convert it to a string again. You can just use strings as hash keys. And in your call to has_key? you have not used the colon. (should normally make no difference)
Also, if you unsure about you implemented the condition correctly, I recommend to create a method to encapsulate it. Especially when the condition has a semantic meaning.
It seems that only problem with your code that it's not checking if start_path and end_path are the same. So, it adds unnecessary "A-B is adjacent to A-B" into your map.
Maybe you should try just add one line?
def build_adjacency
#paths.each do |start_path|
#paths.each do |end_path|
next if start_path == end_path # this one!
# 3 cases for edge adcency
if (start_path.end_node == end_path.start_node) || (start_path.start_node == end_path.end_node) || (start_path.start_node == end_path.start_node)
if #adjacency_map.has_key?("#{start_path}".to_s)
#adjacency_map[:"#{start_path}".to_s] << end_path
else
value = [end_path]
#adjacency_map[:"#{start_path}".to_s] = value
end
end
end
end
end
Here's my full code, reproducing the solution: https://gist.github.com/zverok/6785c213fd78430cd423
I am trying to run this code in QTP which is for deleting records from a grid. This code
dgRows = SwfWindow("PWC - [PWC]").SwfWindow("Region Master").SwfTable("dgMaster").RowCount
For i = 1 To dgRows
SwfWindow("PWC - [PWC]").SwfWindow("Region Master").SwfTable("dgMaster").SelectCell i-1,0
'row of data grid begins with 0, hence i -1
SwfWindow("PWC - [PWC]").SwfWindow("Region Master").SwfButton("DELETE").Click
Swfwindow("PWC - [PWC]").SwfWindow("Region Master").SwfWindow("RegionMaster").SwfButton("Insert").Click
deleteCode = closePrompt()
If deleteCode = 15 Then 'closePrompt returns 15 when record is successfully deleted
i = i - 1 'As record is deleted, grid has lost one record and for loop will exit early by one record or throw error.
dgoRows = SwfWindow("PWC - [PWC]").SwfWindow("Region Master").SwfTable("dgMaster").RowCount
End If
Next
This piece of code runs from 1 to number of rows in a grid (dgRows).
If there are 3 rows, it will run thrice and delete records if possible. If 1 record is deleted,
the grid loses a record. Hence I am trying to adjust the value of i and dgRows by the code
i = i - 1 'As record is deleted, grid has lost one record and
for loop will exit early by one record or throw error.
dgoRows = SwfWindow("PWC - [PWC]").SwfWindow("Region Master").SwfTable("dgMaster").RowCount
'Updating new value of dgRows so that QTP does not click on a row for value of i that does not
exist.
I try to illustrate the issues I am facing with this piece of code
dgRows = SwfWindow("PWC - [PWC]").SwfWindow("Region
Master").SwfTable("dgMaster").RowCount
After row is deleted, it does not dynamically get the no of rows in the grid when the for loop iterates. Hence i value becomes equal to 3 rows but actually in the grid there is one row as 2 records have been deleted, thus QTP tries to click on a cell with i value 3 but doesn't find it and throws an error.
Can anyone tell me why doesn't ("dgMaster").RowCount update itself or how to update it when the for loop runs next?
In VBScript a for loop only evaluates the limit once.
Proof:
limit = 4
For i = 1 to limit
limit = limit - 1
document.write(i & " - " & limit & "<br>")
Next
Output:
1 - 3
2 - 2
3 - 1
4 - 0
You should use a While loop instead
dgRows = SwfWindow("PWC - [PWC]").SwfWindow("Region Master").SwfTable("dgMaster").RowCount
i = 1 ' I would use 0 but I'm keeping the code as close to original as possible
While i <= dgRows
i = i + 1
SwfWindow("PWC - [PWC]").SwfWindow("Region Master").SwfTable("dgMaster").SelectCell i-1,0
'row of data grid begins with 0, hence i -1
SwfWindow("PWC - [PWC]").SwfWindow("Region Master").SwfButton("DELETE").Click
Swfwindow("PWC - [PWC]").SwfWindow("Region Master").SwfWindow("RegionMaster").SwfButton("Insert").Click
deleteCode = closePrompt()
If deleteCode = 15 Then 'closePrompt returns 15 when record is successfully deleted
i = i - 1 'As record is deleted, grid has lost one record and for loop will exit early by one record or throw error.
dgoRows = SwfWindow("PWC - [PWC]").SwfWindow("Region Master").SwfTable("dgMaster").RowCount
End If
WEnd
My main window launches a top-level window with a sub-frame (to browse/select a directory) along with 'load' and 'add directory' buttons at the bottom. The 'add directory' button deletes all the directory entry subframes (but leaves the buttons), checks that there are no duplicates directories entered or empty strings, and recreates subframes for valid entries and creates another one left blank.
The problem is that when I click the 'add directory' button, the buttons end up on top. Is there a way to fix the buttons to the bottom of the window?
In Main class:
def add_directory
dir_window = TkToplevel.new(#root) {title 'Directories'}
dir_frame = Tk::Tile::Frame.new(dir_window) {padding "3 3 12 12"}.grid(:sticky => 'nsew')
DirectoryFrame.show(dir_frame)
loadDirectoriesButtonClicked = proc {load_files}
Tk::Tile::Button.new(dir_frame) {text 'Load directories'; command loadDirectoriesButtonClicked}.grid(:column=>0, :sticky=>'s')
addDirButtonClicked = proc {DirectoryFrame.show(dir_frame)}
Tk::Tile::Button.new(dir_frame) {text '+'; width 2; command addDirButtonClicked}.grid(:column=>1, :sticky=>'sw')
end
In directory frame class:
class DirectoryFrame < Tk::Tile::Frame
##directory_frames = []
##directories = []
def self.show(parent_frame)
if !(##directory_frames.nil? || ##directory_frames.empty?)
directories
remove_frames(parent_frame)
end
##directories.delete("")
if !(##directories.nil? || ##directories.empty?)
##directories.each do |dir|
dir_frame = DirectoryFrame.new(parent_frame)
dir_frame.directory = dir
##directory_frames << dir_frame
end
end
##directory_frames << DirectoryFrame.new(parent_frame)
refresh
end
def self.refresh
##directory_frames.each_with_index do |dir_frame, index|
dir_frame.grid(:row=>index, :sticky=>'ew')
end
end
If you don't specify which row to put a widget on when you grid it in, Tk picks the row with number one larger than the current largest used row number. This is often just fine, but is wrong for you. Instead, you should explicitly put your buttons in a row with a large number (e.g., 1000), and then have a counter of inserted rows that you use to decide which new explicit row to do the insertion on.
+--------------------+
| row 1 |
+--------------------+
| row 2 |
+--------------------+
| row 3 |
+--------------------+
| ... empty ... |
+--------------------+
| row 1000 |
+--------------------+
The other alternative is to put the buttons in a frame with another inner frame that holds the gridded space that you are adding rows into.
+----------------------+
|+--------------------+|
|| row 1 ||
|+--------------------+|
|| row 2 ||
|+--------------------+|
|| row 3 ||
|+--------------------+|
+----------------------+
| buttons |
+----------------------+
Either technique will work.
I have a QTreewidget that works fine if I have just one level on my treelist. If I decide to add child sublevels, it gives me an error. Here is the code, that works nice only without the "childs" lines on it (see after "child 1" and "child 2").
def eqpt_centralwdg(self,MainWindow):
self.centralwidget = QtGui.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.colorTreeWidget = QtGui.QTreeWidget(self.centralwidget)
self.colorTreeWidget.setGeometry(QtCore.QRect(60, 60, 191, 141))
self.colorTreeWidget.setObjectName("colorTreeWidget")
# father root 1
item = QtGui.QTreeWidgetItem(self.colorTreeWidget)
#child 1 - from father 1
item = QtGui.QTreeWidgetItem(item)
#child 2 - from father 1
item = QtGui.QTreeWidgetItem(item)
# father root 2
item = QtGui.QTreeWidgetItem(self.colorTreeWidget)
self.connect(self.colorTreeWidget, QtCore.SIGNAL('itemClicked(QTreeWidgetItem*, int)'), self.eqpt_activateInput)
MainWindow.setCentralWidget(self.centralwidget)
def eqpt_retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)
self.colorTreeWidget.headerItem().setText(0, QtGui.QApplication.translate("MainWindow", "color", None, QtGui.QApplication.UnicodeUTF8)
__sortingEnabled = self.colorTreeWidget.isSortingEnabled()
self.colorTreeWidget.setSortingEnabled(False)
# father root 1
self.colorTreeWidget.topLevelItem(0).setText(0, QtGui.QApplication.translate("MainWindow", "Yellow", None, QtGui.QApplication.UnicodeUTF8)
#child 1 - from father 1
self.colorTreeWidget.topLevelItem(0).child(0).setText(0, QtGui.QApplication.translate("MainWindow", "Yellow Sun", None, QtGui.QApplication.UnicodeUTF8))
#child 2 - from father 1
self.colorTreeWidget.topLevelItem(0).child(1).setText(0, QtGui.QApplication.translate("MainWindow", "Yellow Gold", None, QtGui.QApplication.UnicodeUTF8))
# father root 2
self.colorTreeWidget.topLevelItem(1).setText(0, QtGui.QApplication.translate("MainWindow", "Blue", None, QtGui.QApplication.UnicodeUTF8)
self.colorTreeWidget.setSortingEnabled(__sortingEnabled)
Here is the output, when it works
def eqpt_activateInput(self,item,col):
print "Qtree ok! pressed"
print item.text(col)
if I exclude the lines related to the "child 1" and "child 2" from the code, it runs. Otherwise, it gives me the error:
AttributeError: 'NoneType' object has no attribute 'setText'
I used the Qt Designer to generate the code, and added some lines to trigger events.
Any hints or suggestions are highly appreciated.
Your tree nodes look like this:
Node 1
Node 1.1
Node 1.1.1
Node 2
(forgive me for the poor presentation)
In your code you're accessing the first top level node's second child:
#child 2 - from father 1
self.colorTreeWidget.topLevelItem(0).child(1)...
but it doesn't exist, since you mistakenly (I assume) added the child for the wrong node.
In general I wouldn't build your tree that way, you can see how confusing it gets, while this:
parent = QtGui.QTreeWidgetItem(self.colorTreeWidget)
firstchild = QtGui.QTreeWidgetItem(parent)
secondchild = QtGui.QTreeWidgetItem(parent)
parent = QtGui.QTreeWidgetItem(self.colorTreeWidget)
with unique names for each node is much more clear.
Or even this:
parent = QtGui.QTreeWidgetItem(self.colorTreeWidget)
parent.addChild(...)
parent.addChild(...)
Solved!
Here is the solution:
parent1 = QtGui.QTreeWidgetItem(self.colorTreeWidget)
child1_1 = QtGui.QTreeWidgetItem()
child1_2 = QtGui.QTreeWidgetItem()
parent1.addChild(child1_1)
parent1.addChild(child1_2)
Now it works properly.
Thanks again for the suggestions and comments!