I’m trying to store the text from a QTextEdit box and then put each line of the text into a list. Is there a function similar to readlines that will let me do that? The documentation for pyQT is less then helpful.:?:
Hey!
Use the C++ documentation for looking up individual class methods / references / examples
It has a method called toPlainText(), returns a QString instance.
QString has a method called split(…), takes several parameters. The first param is the only one you’ll need for this, and that’s the separator parameter, by passing "
" you split on new lines. This returns a QStringList, a Qt list.
If you want to play with a python list, just cast the QString which you got from toPlainTest with str(…) and then call split on that instead, since python string also has that method, which now returns a python list!
Thanks for the help, yeah I kept running into an error in some of my code saying I couldn’t use a QString because it requires the var to be a string, so I type casted it like you mentioned and that fixed it. I guess my issue is i’m trying to merge some code that was just python with a GUI using Qt and getting confused about when to use the python methods as opposed to the Qt methods. I’ll post my code when i’m done so you can see what i’m trying to do.Thanks
Here is the code I was talking about. I’ve heard many times that is useful to be able to batch through multiple files and change the text or small issues in them, so I figured that out but then decided to make a GUI and then a few other features that won’t limit it to just .ma files. THIS IS NOT FINISHED…I was just hoping for some feedback before I finish completely. It works for now, except the checkbox doesn’t do anything and the field for the input is ignored, i’m thinking of adding a backup switch that will make a copy of all the files and place in a diff dir before running the batch in case for whatever reason it screws something up. Any other features that might be useful? I’m sure this has been done many times by many people but I want to be able to do it too:D:
#============================
# BATCH EDIT UI
# Matt Murray 2011
#============================
#============================
# GLOBALS
#============================
import os
import sys
from PyQt4 import QtCore, QtGui
#============================
# GUI CODE
#============================
class MainWindow(QtGui.QDialog):
def __init__(self):
super(MainWindow, self).__init__()
#set some class globals
self.newDir = ''
self.newExten = ''
self.newReplace = []
self.oldReplace = []
#create the browse button
browseBtn = self.createBtn("&Browse", self.browse)
#create the run button
runBtn = self.createBtn("&Run Batch", self.runCall)
#create a combobox tht holds the recent dirs
self.dirComboBox = self.createComboBox(QtCore.QDir.currentPath())
dirLabel = QtGui.QLabel("In Directory:")
extLabel = QtGui.QLabel("With Extention:")
appendLabel = QtGui.QLabel("Append Only to End?")
oldLabel = QtGui.QLabel("Replace This:")
newLabel = QtGui.QLabel("With This:")
#create a label to display the number of files found in the dir
self.filesFoundLabel = QtGui.QLabel("0 file(s) found")
self.createFilesTable()
self.appendCheckBox = QtGui.QCheckBox()
#self.appendCheckBox.onCheck.connect(methodName)
#create a text field for common extensions
self.extTextEdit = QtGui.QLineEdit()
#create a text field to enter the text that needs replacing
self.oldTextEdit = QtGui.QTextEdit()
#create a text field to enter the text that will replace the old text
self.newTextEdit = QtGui.QTextEdit()
self.createMenu() #create the top menu that will house commonly used strings to be replaced
#set the layout for the window and add all widgets
mainLayout = QtGui.QGridLayout()
mainLayout.setMenuBar(self.menuBar)
mainLayout.addWidget(dirLabel, 0,0)
mainLayout.addWidget(self.dirComboBox, 0,1)
mainLayout.addWidget(browseBtn, 0, 2)
mainLayout.addWidget(extLabel, 1,0)
mainLayout.addWidget(self.extTextEdit, 1, 1)
mainLayout.addWidget(self.filesTable, 2,0,1,3)
mainLayout.addWidget(self.filesFoundLabel, 3,0,1,3)
mainLayout.addWidget(appendLabel, 4,0)
mainLayout.addWidget(self.appendCheckBox, 4,1)
mainLayout.addWidget(oldLabel, 5,0)
mainLayout.addWidget(self.oldTextEdit, 5,1,1,3)
mainLayout.addWidget(newLabel, 6,0)
mainLayout.addWidget(self.newTextEdit, 6,1,1,3)
mainLayout.addWidget(runBtn, 7,0,1,3)
self.setLayout(mainLayout)
self.setWindowTitle("Basic Layouts")
self.resize(400, 600)
def browse(self):
directory = QtGui.QFileDialog.getExistingDirectory(self, "Find File Directory", QtCore.QDir.currentPath())
if directory: #if the dir returns a value
if self.dirComboBox.findText(directory) == -1: #if there is no text in current sel of combo then add a anew Item there
self.dirComboBox.addItem(directory)
self.dirComboBox.setCurrentIndex(self.dirComboBox.findText(directory)) #set the most recent dir as the current sel of the combo
self.find()
def updateComboBox(self, comboBox):
if comboBox.findText(comboBox.currentText()) == -1:
comboBox.addItem(comboBox.currentText())
def find(self):
self.filesTable.setRowCount(0)
#fileName = self.fileComboBox.currentText()
text = 'ma' #self.extTextEdit.toPlainText()
path = self.dirComboBox.currentText()
self.updateComboBox(self.dirComboBox)
self.currentDir = QtCore.QDir(path)
#if not fileName:
fileName = "*"
files = self.currentDir.entryList([fileName], QtCore.QDir.Files | QtCore.QDir.NoSymLinks)
if text:
files = self.findFiles(files, text)
self.showFiles(files)
def findFiles(self, files, text):
progressDialog = QtGui.QProgressDialog(self)
progressDialog.setCancelButtonText("&Cancel")
progressDialog.setRange(0, files.count())
progressDialog.setWindowTitle("Find Files")
foundFiles = []
for i in range(files.count()):
progressDialog.setValue(i)
progressDialog.setLabelText("Searching file number" + str(i) + "of" + str(files.count()))
QtGui.qApp.processEvents()
if progressDialog.wasCanceled():
break
inFile = QtCore.QFile(self.currentDir.absoluteFilePath(files[i]))
if inFile.open(QtCore.QIODevice.ReadOnly):
stream = QtCore.QTextStream(inFile)
while not stream.atEnd():
if progressDialog.wasCanceled():
break
line = stream.readLine()
if text in line:
foundFiles.append(files[i])
break
progressDialog.close()
return foundFiles
def showFiles(self, files):
for fn in files:
file = QtCore.QFile(self.currentDir.absoluteFilePath(fn))
size = QtCore.QFileInfo(file).size()
fileNameItem = QtGui.QTableWidgetItem(fn)
fileNameItem.setFlags(fileNameItem.flags() ^ QtCore.Qt.ItemIsEditable)
sizeItem = QtGui.QTableWidgetItem(str((int((size + 1023)) / 1024)) + " KB")
sizeItem.setTextAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignRight)
sizeItem.setFlags(sizeItem.flags() ^ QtCore.Qt.ItemIsEditable)
row = self.filesTable.rowCount()
self.filesTable.insertRow(row)
self.filesTable.setItem(row, 0, fileNameItem)
self.filesTable.setItem(row, 1, sizeItem)
self.filesFoundLabel.setText(str(len(files)) + " file(s) found (Double click on a file to open it)")
def createBtn(self, text, method):
button = QtGui.QPushButton(text)
button.clicked.connect(method)
return button
def createComboBox(self, text=""):
combo = QtGui.QComboBox()
combo.setEditable(True)
combo.addItem(text)
combo.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Preferred)
return combo
def createFilesTable(self):
self.filesTable = QtGui.QTableWidget(0,2)
self.filesTable.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self.filesTable.setHorizontalHeaderLabels(("File Name", "Size"))
self.filesTable.horizontalHeader().setResizeMode(0, QtGui.QHeaderView.Stretch)
self.filesTable.verticalHeader().hide()
self.filesTable.setShowGrid(False)
self.filesTable.cellDoubleClicked.connect(self.openFileOfItem)
def openFileOfItem(self, row, column):
item = self.filesTable.item(row, 0)
print("clicked")
QtGui.QDesktopServices.openUrl(QtCore.QUrl(self.currentDir.absoluteFilePath(item.text())))
def createMenu(self):
print("made menu")
self.menuBar = QtGui.QMenuBar() #create a menu bar object
self.fileMenu = QtGui.QMenu("&File", self) # add an exit and file option
self.exitAction = self.fileMenu.addAction("E&xit")
self.menuBar.addMenu(self.fileMenu) #add the new menu option to the menu bar
self.exitAction.triggered.connect(self.accept) #connect a trigger event to the exit option
def runCall(self):
#get all the variables'values and pass them to function
self.newDir = self.dirComboBox.currentText()
self.newExten = 'ma' #self.extTextEdit.toPlainText()
#read lines of each text edit box and add to lists
newText = self.newTextEdit.toPlainText()
oldText = self.oldTextEdit.toPlainText()
self.newReplace = str(newText).split('
')
self.oldReplace = str(oldText).split('
')
self.runBatch(self.newDir, self.newExten, self.oldReplace, self.newReplace)
#================================================================================
# FUNCTIONALITY SECTION
#================================================================================
#//Name:
def runBatch(self, fileDIR, fileExtension, oldInfo, newInfo):
print(fileDIR)
print(fileExtension)
print(oldInfo)
print(newInfo)
thisDir = str(fileDIR)
#create a var for the file extension
fileExten = str(fileExtension)
#make a list for the strings that you want to replace
old = oldInfo
#make a list for the strings that you want to replace what is in the file
new = newInfo
# to get the current working dir use os.getcwd()
for dirpath, dirnames, filenames in os.walk(thisDir): #crawl the current folder and for each file in the folder do the following
for name in filenames: #loop through all the files
if name.split('.')[-1] == fileExten: #check and see if the extension if what extension you are trying to edit(ommit this line if not relevant to check)
absPath = os.path.join(dirpath, name) #create the absolute path for the file
if os.path.isfile(absPath): #check to see if the file is indeed a valid file to edit
fHandler = open(absPath, 'r') #open file for read mode
txt = fHandler.read() #read the lines in the file and store to variable
fHandler.close() #close the file back up
#replace the actual text
for oldString, newString in zip(old, new): #loop both lists in parallel [zip creates a tuple for each entry and guarantees left to right eval]
#if txt.rfind(oldString) > -1: #if string exists in file
if oldString in txt:
txt = txt.replace(oldString, newString) #out with the old and in with the new
fHandler = open(absPath, 'w') #open file for reading
fHandler.write(txt) #write the newly replaced text
fHandler.close() #close the file ...done!
#============================================
# END OF MAIN FUNCTIONS
#============================================
if __name__ == '__main__': #find the main constructro and execute
app = QtGui.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit(app.exec_())
It works completely fine on my computer
I made a file called .ma, added some random text in it.
Then I ran your program and replaced the contents of this ma file and it worked
What kind of errors are you getting and what version of PyQt are you using? They fixed the QString <===> python string issue at some point, maybe you have an old version.
I think it’s cool =} Another thing I would want is XML editing of certain nodes with certain attributes and batch through them!
EDIT: Oops haha, I read completely wrong, I thought that the problem still existed ^^!
EDIT2: Also, what about conditions :D? If X exists, replace Y with Z ^^