Read lines from a QTextEdit box

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 :slight_smile:

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 :slight_smile:

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 :slight_smile:

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 ^^