views:

689

answers:

1

Hi all,

Im writing a little python program that goes through an XML file and does some replacement of tags. It takes three arguments, a path from whcih it creates a directory tree, the XML file its reading and the xml file its outputting to. It works fine from the command line just passing in arguments. As its not just for me, i thought id put a Qt front on it. Below is the majority of the Qt front. MOVtoMXF is the class that does all the replacement. So you can see that im basically just grabbing strings and feeding them into the class that ive already made and tested.

class Form(QDialog):

    def ConnectButtons(self):
        self.connect(self.pathBrowseB, SIGNAL("clicked()"), self.pathFileBrowse)
        self.connect(self.xmlFileBrowseB, SIGNAL("clicked()"), self.xmlFileBrowse)
        self.connect(self.outputFileBrowseB, SIGNAL("clicked()"), self.outputFileBrowse)

    def accept(self):
        path = self.pathBox.displayText()
        xmlFile = self.xmlFileBox.displayText()
        outFileName = self.outfileNameBox.displayText()
        print path + "  " + xmlFile + " " + outFileName
        mov1 = MOVtoMXF.MOVtoMXF(path, xmlFile, outFileName)
        mov1.ScanFile()
        self.done()

    def pathFileBrowse(self):
        file = str(QFileDialog.getExistingDirectory(self, "Select Directory"))
        self.pathBox.setText(file)

    def xmlFileBrowse(self):
        file = str(QFileDialog.getOpenFileName(self, "Save File"))
        self.xmlFileBox.setText(file)

    def outputFileBrowse(self):
        file = str(QFileDialog.getSaveFileName(self, "Save File"))
        self.outfileNameBox.setText(file)

the probelm is that when i feed in a Path, it now comes back with an error, either the directory doesnt exist, or if I have a trailing slash on the end that

File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/posixpath.py", line 62, in join elif path == '' or path.endswith('/'):

I think its probably some mismatch between the QFileDialog, the QString its passing back and the string the my python expects. but im not sure how to go about fixing it.

Im running on Max OS X 10.5.6 pyQt 4.4.4 QT 4.4.0

thanks for any help you can give.

Mark

+1  A: 

Two potential solutions.

Method 1:

If you must use the displayText() method, I suggest you wrap the call to displayText() with an explicit string cast:

path = str(self.pathBox.displayText()) 
xmlFile = str(self.xmlFileBox.displayText()) 
outFileName = str(self.outfileNameBox.displayText())

The reason is that displayText() returns what I believe is a constant memory reference at the C++ level, meaning that you are not being returned a copy of the QString, but actually whatever QString is available at the memory reference.

When you call the displayText() function, it is the string you expected, but eventually it is something else when the contents at the memory reference are changed. I have noticed this peculiarity with several methods on different controls, most notably QDateEdit/QDateTimeEdit/QTimeEdit controls, where I typically have to make an explicit copy of, say, the QDate returned by the date() function of QDateEdit by wrapping it in a QDate constructor.

Method 2:

Otherwise, use the text() method instead. The QString returned is a constant value, instead of a constant memory reference. See this doc:

http://doc.trolltech.com/4.4/qlineedit.html#text-prop

displayText : const QString 
text : QString

Update:

It looks like Riverbank will be addressing this problem in future versions of PyQt in case anybody is still having this problem:

PyQt4 Roadmap

Implicit Copying of const&

Implemented in current snapshots.

When PyQt wraps a const& value returned by a C++ function it wraps the address of the value itself. Also, it does not enforce the const attribute. This can cause unexpected behavour (and program crashes) either by the underlying value disappearing or the value being unexpectedly modified.

The correct way to handle this is to explicitly make a copy of the value using its type's copy constructor. However, that is not Pythonic and knowing that it needs to be done requires knowledge of the C++ API.

PyQt will be changed so that it will automatically invoke the copy constructor and will wrap the copy.

Chris Cameron