Python Forum
Read Write CSV (Qt5)
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Read Write CSV (Qt5)
#1
for tab delimited CSV
(Open, Save, Preview, Print, Contextual Menu)
made in Linux


File on Github

#!/usr/bin/python3
#-*- coding:utf-8 -*-
import csv, codecs 
import os

from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
from PyQt5.QtGui import QImage, QPainter
from PyQt5.QtCore import QFile

class MyWindow(QtWidgets.QWidget):
   def __init__(self, fileName, parent=None):
       super(MyWindow, self).__init__(parent)
       self.fileName = ""
       self.fname = "Liste"
       self.model =  QtGui.QStandardItemModel(self)

       self.tableView = QtWidgets.QTableView(self)
       self.tableView.setStyleSheet(stylesheet(self))
       self.tableView.setModel(self.model)
       self.tableView.horizontalHeader().setStretchLastSection(True)
       self.tableView.setShowGrid(True)
       self.tableView.setGeometry(10, 50, 780, 645)
       self.model.dataChanged.connect(self.finishedEdit)

       self.pushButtonLoad = QtWidgets.QPushButton(self)
       self.pushButtonLoad.setText("Load CSV")
       self.pushButtonLoad.clicked.connect(self.loadCsv)
       self.pushButtonLoad.setFixedWidth(80)
       self.pushButtonLoad.setStyleSheet(stylesheet(self))

       self.pushButtonWrite = QtWidgets.QPushButton(self)
       self.pushButtonWrite.setText("Save CSV")
       self.pushButtonWrite.clicked.connect(self.writeCsv)
       self.pushButtonWrite.setFixedWidth(80)
       self.pushButtonWrite.setStyleSheet(stylesheet(self))

       self.pushButtonPreview = QtWidgets.QPushButton(self)
       self.pushButtonPreview.setText("Print Preview")
       self.pushButtonPreview.clicked.connect(self.handlePreview)
       self.pushButtonPreview.setFixedWidth(80)
       self.pushButtonPreview.setStyleSheet(stylesheet(self))

       self.pushButtonPrint = QtWidgets.QPushButton(self)
       self.pushButtonPrint.setText("Print")
       self.pushButtonPrint.clicked.connect(self.handlePrint)
       self.pushButtonPrint.setFixedWidth(80)
       self.pushButtonPrint.setStyleSheet(stylesheet(self))

       self.pushAddRow = QtWidgets.QPushButton(self)
       self.pushAddRow.setText("add Row")
       self.pushAddRow.clicked.connect(self.addRow)
       self.pushAddRow.setFixedWidth(80)
       self.pushAddRow.setStyleSheet(stylesheet(self))

       self.pushDeleteRow = QtWidgets.QPushButton(self)
       self.pushDeleteRow.setText("delete Row")
       self.pushDeleteRow.clicked.connect(self.removeRow)
       self.pushDeleteRow.setFixedWidth(80)
       self.pushDeleteRow.setStyleSheet(stylesheet(self))

       self.pushAddColumn = QtWidgets.QPushButton(self)
       self.pushAddColumn.setText("add Column")
       self.pushAddColumn.clicked.connect(self.addColumn)
       self.pushAddColumn.setFixedWidth(80)
       self.pushAddColumn.setStyleSheet(stylesheet(self))

       self.pushDeleteColumn = QtWidgets.QPushButton(self)
       self.pushDeleteColumn.setText("delete Column")
       self.pushDeleteColumn.clicked.connect(self.removeColumn)
       self.pushDeleteColumn.setFixedWidth(86)
       self.pushDeleteColumn.setStyleSheet(stylesheet(self))

       self.pushClear = QtWidgets.QPushButton(self)
       self.pushClear.setText("Clear")
       self.pushClear.clicked.connect(self.clearList)
       self.pushClear.setFixedWidth(60)
       self.pushClear.setStyleSheet(stylesheet(self))

       grid = QtWidgets.QGridLayout()
       grid.setSpacing(10)
       grid.addWidget(self.pushButtonLoad, 0, 0)
       grid.addWidget(self.pushButtonWrite, 0, 1)
       grid.addWidget(self.pushAddRow, 0, 2)
       grid.addWidget(self.pushDeleteRow, 0, 3)
       grid.addWidget(self.pushAddColumn, 0, 4)
       grid.addWidget(self.pushDeleteColumn, 0, 5)
       grid.addWidget(self.pushClear, 0, 6)
       grid.addWidget(self.pushButtonPreview, 0, 7)
       grid.addWidget(self.pushButtonPrint, 0, 8, 1, 1, QtCore.Qt.AlignRight)
       grid.addWidget(self.tableView, 1, 0, 1, 9)
       self.setLayout(grid)

       item = QtGui.QStandardItem()
       self.model.appendRow(item)
       self.model.setData(self.model.index(0, 0), "", 0)
       self.tableView.resizeColumnsToContents()

   def loadCsv(self, fileName):
       fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open CSV",
               (QtCore.QDir.homePath()), "CSV (*.csv *.tsv)")

       if fileName:
           print(fileName)
           ff = open(fileName, 'r')
           mytext = ff.read()
#            print(mytext)
           ff.close()
           f = open(fileName, 'r')
           with f:
               self.fname = os.path.splitext(str(fileName))[0].split("/")[-1]
               self.setWindowTitle(self.fname)
               if mytext.count(';') <= mytext.count('\t'):
                   reader = csv.reader(f, delimiter = '\t')
                   self.model.clear()
                   for row in reader:    
                       items = [QtGui.QStandardItem(field) for field in row]
                       self.model.appendRow(items)
                   self.tableView.resizeColumnsToContents()
               else:
                   reader = csv.reader(f, delimiter = ';')
                   self.model.clear()
                   for row in reader:    
                       items = [QtGui.QStandardItem(field) for field in row]
                       self.model.appendRow(items)
                   self.tableView.resizeColumnsToContents()

   def writeCsv(self, fileName):
       # find empty cells
       for row in range(self.model.rowCount()):
           for column in range(self.model.columnCount()):
               myitem = self.model.item(row,column)
               if myitem is None:
                   item = QtGui.QStandardItem("")
                   self.model.setItem(row, column, item)
       fileName, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Save File", 
                       (QtCore.QDir.homePath() + "/" + self.fname + ".csv"),"CSV Files (*.csv)")
       if fileName:
           print(fileName)
           f = open(fileName, 'w')
           with f:
               writer = csv.writer(f, delimiter = '\t')
               for rowNumber in range(self.model.rowCount()):
                   fields = [self.model.data(self.model.index(rowNumber, columnNumber),
                                        QtCore.Qt.DisplayRole)
                    for columnNumber in range(self.model.columnCount())]
                   writer.writerow(fields)
               self.fname = os.path.splitext(str(fileName))[0].split("/")[-1]
               self.setWindowTitle(self.fname)

   def handlePrint(self):
       dialog = QtPrintSupport.QPrintDialog()
       if dialog.exec_() == QtWidgets.QDialog.Accepted:
           self.handlePaintRequest(dialog.printer())

   def handlePreview(self):
       dialog = QtPrintSupport.QPrintPreviewDialog()
       dialog.setFixedSize(1000,700)
       dialog.paintRequested.connect(self.handlePaintRequest)
       dialog.exec_()

   def handlePaintRequest(self, printer):
       # find empty cells
       for row in range(self.model.rowCount()):
           for column in range(self.model.columnCount()):
               myitem = self.model.item(row,column)
               if myitem is None:
                   item = QtGui.QStandardItem("")
                   self.model.setItem(row, column, item)
       printer.setDocName(self.fname)
       document = QtGui.QTextDocument()
       cursor = QtGui.QTextCursor(document)
       model = self.tableView.model()
       table = cursor.insertTable(model.rowCount(), model.columnCount())
       for row in range(table.rows()):
           for column in range(table.columns()):
               cursor.insertText(model.item(row, column).text())
               cursor.movePosition(QtGui.QTextCursor.NextCell)
       document.print_(printer)

   def removeRow(self):
       model = self.model
       indices = self.tableView.selectionModel().selectedRows() 
       for index in sorted(indices):
           model.removeRow(index.row()) 

   def addRow(self):
       item = QtGui.QStandardItem("")
       self.model.appendRow(item)

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

   def removeColumn(self):
       model = self.model
       indices = self.tableView.selectionModel().selectedColumns() 
       for index in sorted(indices):
           model.removeColumn(index.column()) 

   def addColumn(self):
       count = self.model.columnCount()
       print (count)
       self.model.setColumnCount(count + 1)
       self.model.setData(self.model.index(0, count), "", 0)
       self.tableView.resizeColumnsToContents()

   def finishedEdit(self):
       self.tableView.resizeColumnsToContents()

   def contextMenuEvent(self, event):
       self.menu = QtWidgets.QMenu(self)
       # copy
       copyAction = QtWidgets.QAction('Copy', self)
       copyAction.triggered.connect(lambda: self.copyByContext(event))
       # paste
       pasteAction = QtWidgets.QAction('Paste', self)
       pasteAction.triggered.connect(lambda: self.pasteByContext(event))
       # cut
       cutAction = QtWidgets.QAction('Cut', self)
       cutAction.triggered.connect(lambda: self.cutByContext(event))
       # delete selected Row
       removeAction = QtWidgets.QAction('delete Row', self)
       removeAction.triggered.connect(lambda: self.deleteRowByContext(event))
       # add Row after
       addAction = QtWidgets.QAction('insert new Row after', self)
       addAction.triggered.connect(lambda: self.addRowByContext(event))
       # add Row before
       addAction2 = QtWidgets.QAction('insert new Row before', self)
       addAction2.triggered.connect(lambda: self.addRowByContext2(event))
       # add Column before
       addColumnBeforeAction = QtWidgets.QAction('insert new Column before', self)
       addColumnBeforeAction.triggered.connect(lambda: self.addColumnBeforeByContext(event))
       # add Column after
       addColumnAfterAction = QtWidgets.QAction('insert new Column after', self)
       addColumnAfterAction.triggered.connect(lambda: self.addColumnAfterByContext(event))
       # delete Column
       deleteColumnAction = QtWidgets.QAction('delete Column', self)
       deleteColumnAction.triggered.connect(lambda: self.deleteColumnByContext(event))
       # add other required actions
       self.menu.addAction(copyAction)
       self.menu.addAction(pasteAction)
       self.menu.addAction(cutAction)
       self.menu.addSeparator()
       self.menu.addAction(addAction)
       self.menu.addAction(addAction2)
       self.menu.addSeparator()
       self.menu.addAction(addColumnBeforeAction)
       self.menu.addAction(addColumnAfterAction)
       self.menu.addSeparator()
       self.menu.addAction(removeAction)
       self.menu.addAction(deleteColumnAction)
       self.menu.popup(QtGui.QCursor.pos())

   def deleteRowByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           row = i.row()
           self.model.removeRow(row)
           print("Row " + str(row) + " deleted")
           self.tableView.selectRow(row)

   def addRowByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           row = i.row() + 1
           self.model.insertRow(row)
           print("Row at " + str(row) + " inserted")
           self.tableView.selectRow(row)

   def addRowByContext2(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           row = i.row()
           self.model.insertRow(row)
           print("Row at " + str(row) + " inserted")
           self.tableView.selectRow(row)

   def addColumnBeforeByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           col = i.column()
           self.model.insertColumn(col)
           print("Column at " + str(col) + " inserted")

   def addColumnAfterByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           col = i.column() + 1
           self.model.insertColumn(col)
           print("Column at " + str(col) + " inserted")

   def deleteColumnByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           col = i.column()
           self.model.removeColumn(col)
           print("Column at " + str(col) + " removed")

   def copyByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           row = i.row()
           col = i.column()
           myitem = self.model.item(row,col)
           if myitem is not None:
               clip = QtWidgets.QApplication.clipboard()
               clip.setText(myitem.text())

   def pasteByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           row = i.row()
           col = i.column()
           myitem = self.model.item(row,col)
           clip = QtWidgets.QApplication.clipboard()
           myitem.setText(clip.text())

   def cutByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           row = i.row()
           col = i.column()
           myitem = self.model.item(row,col)
           if myitem is not None:
               clip = QtWidgets.QApplication.clipboard()
               clip.setText(myitem.text())
               myitem.setText("")

def stylesheet(self):
       return """
       QTableView
       {
border: 1px solid grey;
border-radius: 0px;
font-size: 12px;
        background-color: #f8f8f8;
selection-color: white;
selection-background-color: #00ED56;
       }

QTableView QTableCornerButton::section {
    background: #D6D1D1;
    border: 1px outset black;
}

QPushButton
{
font-size: 11px;
border: 1px inset grey;
height: 24px;
width: 80px;
color: black;
background-color: #e8e8e8;
background-position: bottom-left;
} 

QPushButton::hover
{
border: 2px inset goldenrod;
font-weight: bold;
color: #e8e8e8;
background-color: green;
} 
"""

if __name__ == "__main__":
   import sys

   app = QtWidgets.QApplication(sys.argv)
   app.setApplicationName('MyWindow')
   main = MyWindow('')
   main.setMinimumSize(820, 300)
   main.setGeometry(0,0,820,700)
   main.setWindowTitle("CSV Viewer")
   main.show()

sys.exit(app.exec_())
Reply
#2
(Jan-25-2017, 04:38 PM)Axel_Erfurt Wrote: for tab delimited CSV
(Open, Save, Preview, Print, Contextual Menu)
made in Linux


File on Github

#!/usr/bin/python3
#-*- coding:utf-8 -*-
import csv, codecs 
import os

from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
from PyQt5.QtGui import QImage, QPainter
from PyQt5.QtCore import QFile

class MyWindow(QtWidgets.QWidget):
   def __init__(self, fileName, parent=None):
       super(MyWindow, self).__init__(parent)
       self.fileName = ""
       self.fname = "Liste"
       self.model =  QtGui.QStandardItemModel(self)

       self.tableView = QtWidgets.QTableView(self)
       self.tableView.setStyleSheet(stylesheet(self))
       self.tableView.setModel(self.model)
       self.tableView.horizontalHeader().setStretchLastSection(True)
       self.tableView.setShowGrid(True)
       self.tableView.setGeometry(10, 50, 780, 645)
       self.model.dataChanged.connect(self.finishedEdit)

       self.pushButtonLoad = QtWidgets.QPushButton(self)
       self.pushButtonLoad.setText("Load CSV")
       self.pushButtonLoad.clicked.connect(self.loadCsv)
       self.pushButtonLoad.setFixedWidth(80)
       self.pushButtonLoad.setStyleSheet(stylesheet(self))

       self.pushButtonWrite = QtWidgets.QPushButton(self)
       self.pushButtonWrite.setText("Save CSV")
       self.pushButtonWrite.clicked.connect(self.writeCsv)
       self.pushButtonWrite.setFixedWidth(80)
       self.pushButtonWrite.setStyleSheet(stylesheet(self))

       self.pushButtonPreview = QtWidgets.QPushButton(self)
       self.pushButtonPreview.setText("Print Preview")
       self.pushButtonPreview.clicked.connect(self.handlePreview)
       self.pushButtonPreview.setFixedWidth(80)
       self.pushButtonPreview.setStyleSheet(stylesheet(self))

       self.pushButtonPrint = QtWidgets.QPushButton(self)
       self.pushButtonPrint.setText("Print")
       self.pushButtonPrint.clicked.connect(self.handlePrint)
       self.pushButtonPrint.setFixedWidth(80)
       self.pushButtonPrint.setStyleSheet(stylesheet(self))

       self.pushAddRow = QtWidgets.QPushButton(self)
       self.pushAddRow.setText("add Row")
       self.pushAddRow.clicked.connect(self.addRow)
       self.pushAddRow.setFixedWidth(80)
       self.pushAddRow.setStyleSheet(stylesheet(self))

       self.pushDeleteRow = QtWidgets.QPushButton(self)
       self.pushDeleteRow.setText("delete Row")
       self.pushDeleteRow.clicked.connect(self.removeRow)
       self.pushDeleteRow.setFixedWidth(80)
       self.pushDeleteRow.setStyleSheet(stylesheet(self))

       self.pushAddColumn = QtWidgets.QPushButton(self)
       self.pushAddColumn.setText("add Column")
       self.pushAddColumn.clicked.connect(self.addColumn)
       self.pushAddColumn.setFixedWidth(80)
       self.pushAddColumn.setStyleSheet(stylesheet(self))

       self.pushDeleteColumn = QtWidgets.QPushButton(self)
       self.pushDeleteColumn.setText("delete Column")
       self.pushDeleteColumn.clicked.connect(self.removeColumn)
       self.pushDeleteColumn.setFixedWidth(86)
       self.pushDeleteColumn.setStyleSheet(stylesheet(self))

       self.pushClear = QtWidgets.QPushButton(self)
       self.pushClear.setText("Clear")
       self.pushClear.clicked.connect(self.clearList)
       self.pushClear.setFixedWidth(60)
       self.pushClear.setStyleSheet(stylesheet(self))

       grid = QtWidgets.QGridLayout()
       grid.setSpacing(10)
       grid.addWidget(self.pushButtonLoad, 0, 0)
       grid.addWidget(self.pushButtonWrite, 0, 1)
       grid.addWidget(self.pushAddRow, 0, 2)
       grid.addWidget(self.pushDeleteRow, 0, 3)
       grid.addWidget(self.pushAddColumn, 0, 4)
       grid.addWidget(self.pushDeleteColumn, 0, 5)
       grid.addWidget(self.pushClear, 0, 6)
       grid.addWidget(self.pushButtonPreview, 0, 7)
       grid.addWidget(self.pushButtonPrint, 0, 8, 1, 1, QtCore.Qt.AlignRight)
       grid.addWidget(self.tableView, 1, 0, 1, 9)
       self.setLayout(grid)

       item = QtGui.QStandardItem()
       self.model.appendRow(item)
       self.model.setData(self.model.index(0, 0), "", 0)
       self.tableView.resizeColumnsToContents()

   def loadCsv(self, fileName):
       fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open CSV",
               (QtCore.QDir.homePath()), "CSV (*.csv *.tsv)")

       if fileName:
           print(fileName)
           ff = open(fileName, 'r')
           mytext = ff.read()
#            print(mytext)
           ff.close()
           f = open(fileName, 'r')
           with f:
               self.fname = os.path.splitext(str(fileName))[0].split("/")[-1]
               self.setWindowTitle(self.fname)
               if mytext.count(';') <= mytext.count('\t'):
                   reader = csv.reader(f, delimiter = '\t')
                   self.model.clear()
                   for row in reader:    
                       items = [QtGui.QStandardItem(field) for field in row]
                       self.model.appendRow(items)
                   self.tableView.resizeColumnsToContents()
               else:
                   reader = csv.reader(f, delimiter = ';')
                   self.model.clear()
                   for row in reader:    
                       items = [QtGui.QStandardItem(field) for field in row]
                       self.model.appendRow(items)
                   self.tableView.resizeColumnsToContents()

   def writeCsv(self, fileName):
       # find empty cells
       for row in range(self.model.rowCount()):
           for column in range(self.model.columnCount()):
               myitem = self.model.item(row,column)
               if myitem is None:
                   item = QtGui.QStandardItem("")
                   self.model.setItem(row, column, item)
       fileName, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Save File", 
                       (QtCore.QDir.homePath() + "/" + self.fname + ".csv"),"CSV Files (*.csv)")
       if fileName:
           print(fileName)
           f = open(fileName, 'w')
           with f:
               writer = csv.writer(f, delimiter = '\t')
               for rowNumber in range(self.model.rowCount()):
                   fields = [self.model.data(self.model.index(rowNumber, columnNumber),
                                        QtCore.Qt.DisplayRole)
                    for columnNumber in range(self.model.columnCount())]
                   writer.writerow(fields)
               self.fname = os.path.splitext(str(fileName))[0].split("/")[-1]
               self.setWindowTitle(self.fname)

   def handlePrint(self):
       dialog = QtPrintSupport.QPrintDialog()
       if dialog.exec_() == QtWidgets.QDialog.Accepted:
           self.handlePaintRequest(dialog.printer())

   def handlePreview(self):
       dialog = QtPrintSupport.QPrintPreviewDialog()
       dialog.setFixedSize(1000,700)
       dialog.paintRequested.connect(self.handlePaintRequest)
       dialog.exec_()

   def handlePaintRequest(self, printer):
       # find empty cells
       for row in range(self.model.rowCount()):
           for column in range(self.model.columnCount()):
               myitem = self.model.item(row,column)
               if myitem is None:
                   item = QtGui.QStandardItem("")
                   self.model.setItem(row, column, item)
       printer.setDocName(self.fname)
       document = QtGui.QTextDocument()
       cursor = QtGui.QTextCursor(document)
       model = self.tableView.model()
       table = cursor.insertTable(model.rowCount(), model.columnCount())
       for row in range(table.rows()):
           for column in range(table.columns()):
               cursor.insertText(model.item(row, column).text())
               cursor.movePosition(QtGui.QTextCursor.NextCell)
       document.print_(printer)

   def removeRow(self):
       model = self.model
       indices = self.tableView.selectionModel().selectedRows() 
       for index in sorted(indices):
           model.removeRow(index.row()) 

   def addRow(self):
       item = QtGui.QStandardItem("")
       self.model.appendRow(item)

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

   def removeColumn(self):
       model = self.model
       indices = self.tableView.selectionModel().selectedColumns() 
       for index in sorted(indices):
           model.removeColumn(index.column()) 

   def addColumn(self):
       count = self.model.columnCount()
       print (count)
       self.model.setColumnCount(count + 1)
       self.model.setData(self.model.index(0, count), "", 0)
       self.tableView.resizeColumnsToContents()

   def finishedEdit(self):
       self.tableView.resizeColumnsToContents()

   def contextMenuEvent(self, event):
       self.menu = QtWidgets.QMenu(self)
       # copy
       copyAction = QtWidgets.QAction('Copy', self)
       copyAction.triggered.connect(lambda: self.copyByContext(event))
       # paste
       pasteAction = QtWidgets.QAction('Paste', self)
       pasteAction.triggered.connect(lambda: self.pasteByContext(event))
       # cut
       cutAction = QtWidgets.QAction('Cut', self)
       cutAction.triggered.connect(lambda: self.cutByContext(event))
       # delete selected Row
       removeAction = QtWidgets.QAction('delete Row', self)
       removeAction.triggered.connect(lambda: self.deleteRowByContext(event))
       # add Row after
       addAction = QtWidgets.QAction('insert new Row after', self)
       addAction.triggered.connect(lambda: self.addRowByContext(event))
       # add Row before
       addAction2 = QtWidgets.QAction('insert new Row before', self)
       addAction2.triggered.connect(lambda: self.addRowByContext2(event))
       # add Column before
       addColumnBeforeAction = QtWidgets.QAction('insert new Column before', self)
       addColumnBeforeAction.triggered.connect(lambda: self.addColumnBeforeByContext(event))
       # add Column after
       addColumnAfterAction = QtWidgets.QAction('insert new Column after', self)
       addColumnAfterAction.triggered.connect(lambda: self.addColumnAfterByContext(event))
       # delete Column
       deleteColumnAction = QtWidgets.QAction('delete Column', self)
       deleteColumnAction.triggered.connect(lambda: self.deleteColumnByContext(event))
       # add other required actions
       self.menu.addAction(copyAction)
       self.menu.addAction(pasteAction)
       self.menu.addAction(cutAction)
       self.menu.addSeparator()
       self.menu.addAction(addAction)
       self.menu.addAction(addAction2)
       self.menu.addSeparator()
       self.menu.addAction(addColumnBeforeAction)
       self.menu.addAction(addColumnAfterAction)
       self.menu.addSeparator()
       self.menu.addAction(removeAction)
       self.menu.addAction(deleteColumnAction)
       self.menu.popup(QtGui.QCursor.pos())

   def deleteRowByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           row = i.row()
           self.model.removeRow(row)
           print("Row " + str(row) + " deleted")
           self.tableView.selectRow(row)

   def addRowByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           row = i.row() + 1
           self.model.insertRow(row)
           print("Row at " + str(row) + " inserted")
           self.tableView.selectRow(row)

   def addRowByContext2(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           row = i.row()
           self.model.insertRow(row)
           print("Row at " + str(row) + " inserted")
           self.tableView.selectRow(row)

   def addColumnBeforeByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           col = i.column()
           self.model.insertColumn(col)
           print("Column at " + str(col) + " inserted")

   def addColumnAfterByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           col = i.column() + 1
           self.model.insertColumn(col)
           print("Column at " + str(col) + " inserted")

   def deleteColumnByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           col = i.column()
           self.model.removeColumn(col)
           print("Column at " + str(col) + " removed")

   def copyByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           row = i.row()
           col = i.column()
           myitem = self.model.item(row,col)
           if myitem is not None:
               clip = QtWidgets.QApplication.clipboard()
               clip.setText(myitem.text())

   def pasteByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           row = i.row()
           col = i.column()
           myitem = self.model.item(row,col)
           clip = QtWidgets.QApplication.clipboard()
           myitem.setText(clip.text())

   def cutByContext(self, event):
       for i in self.tableView.selectionModel().selection().indexes():
           row = i.row()
           col = i.column()
           myitem = self.model.item(row,col)
           if myitem is not None:
               clip = QtWidgets.QApplication.clipboard()
               clip.setText(myitem.text())
               myitem.setText("")

def stylesheet(self):
       return """
       QTableView
       {
border: 1px solid grey;
border-radius: 0px;
font-size: 12px;
        background-color: #f8f8f8;
selection-color: white;
selection-background-color: #00ED56;
       }

QTableView QTableCornerButton::section {
    background: #D6D1D1;
    border: 1px outset black;
}

QPushButton
{
font-size: 11px;
border: 1px inset grey;
height: 24px;
width: 80px;
color: black;
background-color: #e8e8e8;
background-position: bottom-left;
} 

QPushButton::hover
{
border: 2px inset goldenrod;
font-weight: bold;
color: #e8e8e8;
background-color: green;
} 
"""

if __name__ == "__main__":
   import sys

   app = QtWidgets.QApplication(sys.argv)
   app.setApplicationName('MyWindow')
   main = MyWindow('')
   main.setMinimumSize(820, 300)
   main.setGeometry(0,0,820,700)
   main.setWindowTitle("CSV Viewer")
   main.show()

sys.exit(app.exec_())
Your the man! this is going to help me a lot moving a project that entails similar function plus some other hurdles from tkinter int pyqt..... I am having and issue loading the csv?.... i run linux so no excel.... mmmm, and I do see where the csv row/headers get called but??? in any case +1rep sirrr
Reply
#3
another version using QTableWidget

#!/usr/bin/python3
#-*- coding:utf-8 -*-
import csv, codecs 
import os
from PyQt5 import QtPrintSupport
from PyQt5.QtGui import QImage, QPainter, QIcon, QKeySequence, QIcon, QTextCursor, QCursor, QDropEvent, QTextDocument, QTextTableFormat, QColor
from PyQt5.QtCore import QFile, QSettings, Qt, QFileInfo, QItemSelectionModel, QDir
from PyQt5.QtWidgets import (QMainWindow , QAction, QWidget, QLineEdit, QMessageBox, QAbstractItemView, QApplication, 
                                                            QTableWidget, QTableWidgetItem, QGridLayout, QFileDialog, QMenu, QInputDialog)

class TableWidgetDragRows(QTableWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.viewport().setAcceptDrops(True)
        self.setDragDropOverwriteMode(False)
        self.setDropIndicatorShown(True)

        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setSelectionBehavior(QAbstractItemView.SelectItems)
        self.setDragDropMode(QAbstractItemView.InternalMove)

    def dropEvent(self, event: QDropEvent):
        if not event.isAccepted() and event.source() == self:
            drop_row = self.drop_on(event)

            rows = sorted(set(item.row() for item in self.selectedItems()))
            rows_to_move = [[QTableWidgetItem(self.item(row_index, column_index)) for column_index in range(self.columnCount())]
                            for row_index in rows]
            for row_index in reversed(rows):
                self.removeRow(row_index)
                if row_index < drop_row:
                    drop_row -= 1

            for row_index, data in enumerate(rows_to_move):
                row_index += drop_row
                self.insertRow(row_index)
                for column_index, column_data in enumerate(data):
                    self.setItem(row_index, column_index, column_data)
            event.accept()
            for row_index in range(len(rows_to_move)):
                self.item(drop_row + row_index, 0).setSelected(True)
                self.item(drop_row + row_index, 1).setSelected(True)
        super().dropEvent(event)

    def drop_on(self, event):
        index = self.indexAt(event.pos())
        if not index.isValid():
            return self.rowCount()

        return index.row() + 1 if self.is_below(event.pos(), index) else index.row()

    def is_below(self, pos, index):
        rect = self.visualRect(index)
        margin = 2
        if pos.y() - rect.top() < margin:
            return False
        elif rect.bottom() - pos.y() < margin:
            return True
        # noinspection PyTypeChecker
        return rect.contains(pos, True) and not (int(self.model().flags(index)) & Qt.ItemIsDropEnabled) and pos.y() >= rect.center().y()

class MyWindow(QMainWindow):
    def __init__(self, aPath, parent=None):
        super(MyWindow, self).__init__(parent)
#        QIcon.setThemeName('gnome')
        self.mycolumn = 0
        self.MaxRecentFiles = 5
        self.windowList = []
        self.recentFileActs = []
        self.settings = QSettings('Axel Schneider', 'CSVEditor')
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.isChanged = False
        self.fileName = ""
        self.fname = "Liste"
        self.mytext = ""
        self.colored = False
        ### QTableView seetings
        self.tableView = TableWidgetDragRows()
#        self.tableView.setStyleSheet(stylesheet(self))
        self.tableView.horizontalHeader().setStretchLastSection(True)
        self.tableView.setGridStyle(1)
        self.tableView.setCornerButtonEnabled(False)
        self.tableView.setShowGrid(True)
        self.tableView.selectionModel().selectionChanged.connect(self.getdata)
        self.tableView.setEditTriggers(QAbstractItemView.DoubleClicked) 
        self.tableView.cellChanged.connect(self.finishedEdit)
        self.tableView.cellClicked.connect(self.makeAllWhite)
        self.tableView.setDropIndicatorShown(True)

        self.findBar = QLineEdit()
        self.findBar.addAction(QIcon.fromTheme("gtk-find"), 0)
        self.findBar.setPlaceholderText("find")
        self.findBar.setFixedWidth(200)
        self.findBar.returnPressed.connect(self.findText)

        self.editLine = QLineEdit()
        self.editLine.returnPressed.connect(self.updateCell)

        grid = QGridLayout()
        grid.setSpacing(1)
        grid.addWidget(self.editLine, 0, 0)
        grid.addWidget(self.findBar, 0, 1)
        grid.addWidget(self.tableView, 1, 0, 1, 3)

        mywidget = QWidget()
        mywidget.setLayout(grid)
        self.setCentralWidget(mywidget)
        self.isChanged = False

        self.createActions()
        self.createMenuBar()

        self.setStyleSheet(stylesheet(self))

        self.readSettings()

        self.msg("Welcome to CSV Reader")
#        self.statusBar().setStyleSheet(stylesheet(self))

        if len(sys.argv) > 1:
            print(sys.argv[1])
            self.fileName = sys.argv[1]
            self.loadCsvOnOpen(self.fileName)
            self.msg(self.fileName + "loaded")
        else:
            self.msg("Ready")
            self.addRow()
            self.isChanged = False

    def changeSelection(self):
        self.tableView.setSelectionMode(QAbstractItemView.ExtendedSelection)

    def updateCell(self):
        if self.tableView.selectionModel().hasSelection():
            row = self.selectedRow()
            column = self.selectedColumn()
            newtext = QTableWidgetItem(self.editLine.text())
            self.tableView.setItem(row, column, newtext)


    def getdata(self):
        if self.tableView.selectionModel().hasSelection():
            row = self.selectedRow()
            column = self.selectedColumn()
            if not self.tableView.item(row, column) == None:
                name = self.tableView.item(row, column).text()
            else:
                name = ""
            self.msg("'" + name + "' on Row: " + str(row + 1) + " - Column: " + str(column + 1))
            self.editLine.setText(name)

    def selectedRow(self):
        if self.tableView.selectionModel().hasSelection():
            row =  self.tableView.selectionModel().selectedIndexes()[0].row()
            return int(row)

    def selectedColumn(self):
        column =  self.tableView.selectionModel().selectedIndexes()[0].column()
        return int(column)

    def findText(self):
        self.findTableItems()
        self.changeSelection()

    def findTableItems(self):
        self.tableView.setSelectionMode(QAbstractItemView.MultiSelection)
        findText = self.findBar.text()
        self.tableView.clearSelection()
        if findText.isnumeric():
            items = self.tableView.findItems(findText, Qt.MatchExactly)
        else:
            items = self.tableView.findItems(findText, Qt.MatchContains)
        if items:
            self.colored = True
            self.makeAllWhite()
            for item in items:
                item.setBackground(Qt.yellow)
            self.colored = True
#                self.tableView.selectRow(item.row())

    def findThis(self):
        self.tableView.setSelectionMode(QAbstractItemView.MultiSelection)
        self.tableView.clearSelection()
        items = self.tableView.findItems(self.mytext, Qt.MatchContains)
        if items:
            self.colored = True
            self.makeAllWhite()
            for item in items:
                item.setBackground(Qt.yellow)
        self.changeSelection()
        self.colored = True

    def msgbox(self, message):
        QMessageBox.warning(self, "Message", message)

    def createMenuBar(self):
        bar=self.menuBar()
        self.filemenu=bar.addMenu("File")
        self.separatorAct = self.filemenu.addSeparator()
        self.filemenu.addAction(QIcon.fromTheme("document-new"), "New",  self.newCsv, QKeySequence.New) 
        self.filemenu.addAction(QIcon.fromTheme("document-open"), "Open",  self.loadCsv, QKeySequence.Open) 
        self.filemenu.addAction(QIcon.fromTheme("document-save"), "Save",  self.saveOnQuit, QKeySequence.Save) 
        self.filemenu.addAction(QIcon.fromTheme("document-save-as"), "Save as ...",  self.writeCsv, QKeySequence.SaveAs) 
        self.filemenu.addSeparator()
        self.filemenu.addAction(QIcon.fromTheme("document-print-preview"), "Print Preview",  self.handlePreview, "Shift+Ctrl+P")
        self.filemenu.addAction(QIcon.fromTheme("document-print"), "Print",  self.handlePrint, QKeySequence.Print) 
        self.filemenu.addSeparator()
        for i in range(self.MaxRecentFiles):
            self.filemenu.addAction(self.recentFileActs[i])
        self.updateRecentFileActions()
        self.filemenu.addSeparator()
        self.clearRecentAct = QAction("clear Recent Files List", self, triggered=self.clearRecentFiles)
        self.clearRecentAct.setIcon(QIcon.fromTheme("edit-clear"))
        self.filemenu.addAction(self.clearRecentAct)
        self.filemenu.addSeparator()
        self.filemenu.addAction(QIcon.fromTheme("application-exit"), "Exit",  self.handleQuit, QKeySequence.Quit) 

        self.editmenu=bar.addMenu("Edit")
        self.editmenu.addAction(QIcon.fromTheme("add"), "add Row",  self.addRow) 
        self.editmenu.addAction(QIcon.fromTheme("edit-delete"), "remove Row",  self.removeRow) 
        self.editmenu.addSeparator()
        self.editmenu.addAction(QIcon.fromTheme("add"), "add Column",  self.addColumn) 
        self.editmenu.addAction(QIcon.fromTheme("edit-delete"), "remove Column",  self.removeColumn) 
        self.editmenu.addSeparator()
        self.editmenu.addAction(QIcon.fromTheme("edit-clear"), "clear List",  self.clearList)
        self.editmenu.addSeparator()
        self.editmenu.addAction(QIcon.fromTheme("pane-show-symbolic"), "toggle horizontal Headers",  self.toggleHorizHeaders) 
        self.editmenu.addAction(QIcon.fromTheme("pane-hide-symbolic"), "toggle vertical Headers",  self.toggleVertHeaders) 
        self.editmenu.addAction(self.whiteAction)

    def toggleHorizHeaders(self):
        if  self.tableView.horizontalHeader().isVisible():
            self.tableView.horizontalHeader().setVisible(False)
        else:
            self.tableView.horizontalHeader().setVisible(True)

    def toggleVertHeaders(self):
        if  self.tableView.verticalHeader().isVisible():
            self.tableView.verticalHeader().setVisible(False)
        else:
            self.tableView.verticalHeader().setVisible(True)

    def createActions(self):
        # all items white BG
        self.whiteAction = QAction(QIcon.fromTheme("edit-color"), "all items white background", self)
        self.whiteAction.triggered.connect(lambda: self.makeAllWhite())
        for i in range(self.MaxRecentFiles):
            self.recentFileActs.append(
                   QAction(self, visible=False,
                            triggered=self.openRecentFile))

    def openRecentFile(self):
        action = self.sender()
        if action:
            if self.isChanged == True:
                quit_msg = "<b>The Document was changed.<br>Do you want to save changes?</ b>"
                reply = QMessageBox.question(self, 'Save Confirmation', 
                         quit_msg, QMessageBox.Yes, QMessageBox.No)
                if reply == QMessageBox.Yes:
                    self.saveOnQuit()
            file = action.data()
            if QFile.exists(file):
                self.loadCsvOnOpen(file)
            else:
                self.msg("File not exists")

    def handleQuit(self):
        quit()

    def loadCsvOnOpen(self, fileName):
        if fileName:
            f = open(fileName, 'r', encoding='utf-8')
            self.tableView.setRowCount(0)
            self.tableView.setColumnCount(0)
            for rowdata in csv.reader(f, delimiter='\t'):
                row = self.tableView.rowCount()
                self.tableView.insertRow(row)
                self.tableView.setColumnCount(len(rowdata))
                for column, data in enumerate(rowdata):
                    item = QTableWidgetItem(data)
                    self.tableView.setItem(row, column, item)
        self.tableView.selectRow(0)
        self.isChanged = False
        self.setCurrentFile(fileName)
        self.tableView.resizeColumnsToContents()
        self.tableView.resizeRowsToContents()
        self.msg(fileName + " loaded")

    def loadCsv(self):
        if self.isChanged == True:
            quit_msg = "<b>The Document was changed.<br>Do you want to save changes?</ b>"
            reply = QMessageBox.question(self, 'Save Confirmation', 
                     quit_msg, QMessageBox.Yes, QMessageBox.No)
            if reply == QMessageBox.Yes:
                self.saveOnQuit()
        fileName, _ = QFileDialog.getOpenFileName(self, "Open CSV",
        (QDir.homePath() + "/Dokumente/CSV"), "CSV (*.csv *.tsv *.txt)")
        if fileName:
            self.loadCsvOnOpen(fileName)

    def newCsv(self):
        if self.isChanged == True:
            quit_msg = "<b>The Document was changed.<br>Do you want to save changes?</ b>"
            reply = QMessageBox.question(self, 'Save Confirmation', 
                     quit_msg, QMessageBox.Yes, QMessageBox.No)
            if reply == QMessageBox.Yes:
                self.saveOnQuit()
        i = 0
        for row in range(self.tableView.rowCount()):
            self.tableView.removeRow(i)
            i =+ 1
        j = 0
        for column in range(self.tableView.columnCount()):
            self.tableView.removeColumn(j)
            j =+ 1 
        self.tableView.clearContents()
        self.fileName = ""
        self.setWindowTitle('New' + "[*]")    
        self.isChanged = False

    def writeCsv(self):
        path, _ = QFileDialog.getSaveFileName(self, 'Save File', QDir.homePath() + "/export.csv", "CSV Files(*.csv *.txt)")
        if path:
            with open(path, 'w') as stream:
                print("saving", path)
                writer = csv.writer(stream, delimiter='\t')
                for row in range(self.tableView.rowCount()):
                    rowdata = []
                    for column in range(self.tableView.columnCount()):
                        item = self.tableView.item(row, column)
                        if item is not None:
                            rowdata.append(item.text())
                        else:
                            rowdata.append('')
                    writer.writerow(rowdata)
        self.isChanged = False
        self.setCurrentFile(path)

    def handlePrint(self):
        if self.tableView.rowCount() == 0:
            self.msg("no rows")
        else:
            dialog = QtPrintSupport.QPrintDialog()
            if dialog.exec_() == QDialog.Accepted:
                self.handlePaintRequest(dialog.printer())
                self.msg("Document printed")

    def handlePreview(self):
        if self.tableView.rowCount() == 0:
            self.msg("no rows")
        else:
            dialog = QtPrintSupport.QPrintPreviewDialog()
            dialog.setFixedSize(1000,700)
            dialog.paintRequested.connect(self.handlePaintRequest)
            dialog.exec_()
            self.msg("Print Preview closed")

    def handlePaintRequest(self, printer):
        # find empty cells
        for row in range(self.tableView.rowCount()):
            for column in range(self.tableView.columnCount()):
                myitem = self.tableView.item(row,column)
                if myitem is None:
                    item = QTableWidgetItem("")
                    self.tableView.setItem(row, column, item)
        printer.setDocName(self.fname)
        document = QTextDocument()
        cursor = QTextCursor(document)
        model = self.tableView.model()
        tableFormat = QTextTableFormat()
        tableFormat.setBorder(0.2)
        tableFormat.setBorderStyle(3)
        tableFormat.setCellSpacing(0);
        tableFormat.setTopMargin(0);
        tableFormat.setCellPadding(4)
        table = cursor.insertTable(model.rowCount(), model.columnCount(), tableFormat)
        for row in range(table.rows()):
            for column in range(table.columns()):
                cursor.insertText(self.tableView.item(row, column).text())
                cursor.movePosition(QTextCursor.NextCell)
        document.print_(printer)

    def removeRow(self):
        if self.tableView.rowCount() > 0:
            row = self.selectedRow()
            tableView.removeRow(row)
            self.isChanged = True

    def addRow(self):
        if self.tableView.rowCount() > 0:
            if self.tableView.selectionModel().hasSelection():
                row = self.selectedRow()
                item = QTableWidgetItem("")
                self.tableView.insertRow(row, 0, item)
            else:
                row = 0
                item = QTableWidgetItem("")
                self.tableView.insertRow(row, 0, item)
                self.tableView.selectRow(0)    
        else:
            self.tableView.setRowCount(1)
        if self.tableView.columnCount() == 0:
            self.addColumn()
            self.tableView.selectRow(0)
        self.isChanged = True

    def clearList(self):
        self.tableView.clear()
        self.isChanged = True

    def removeColumn(self):
        self.tableView.removeColumn(self.selectedColumn())
        self.isChanged = True

    def addColumn(self):
        count = self.tableView.columnCount()
        self.tableView.setColumnCount(count + 1)
        self.tableView.resizeColumnsToContents()
        self.isChanged = True
        if self.tableView.rowCount() == 0:
            self.addRow()
            self.tableView.selectRow(0) 

    def makeAllWhite(self):
        if self.colored == True:
            for row in range(self.tableView.rowCount()):
                for column in range(self.tableView.columnCount()):
                    item = self.tableView.item(row, column)
                    if item is not None:
                        item.setBackground(QColor("#fbfbfb"))
                        self.colored = False

    def finishedEdit(self):
        self.isChanged = True

    def contextMenuEvent(self, event):
        self.menu = QMenu(self)
        if self.tableView.selectionModel().hasSelection():
            # copy
            copyAction = QAction(QIcon.fromTheme("edit-copy"), 'Copy Cell', self)
            copyAction.triggered.connect(lambda: self.copyByContext(event))
            # paste
            pasteAction = QAction(QIcon.fromTheme("edit-paste"), 'Paste Cell', self)
            pasteAction.triggered.connect(lambda: self.pasteByContext(event))
            # cut
            cutAction = QAction(QIcon.fromTheme("edit-cut"), 'Cut Cell', self)
            cutAction.triggered.connect(lambda: self.cutByContext(event))
            # delete selected Row
            removeAction = QAction(QIcon.fromTheme("edit-delete"), 'delete Row', self)
            removeAction.triggered.connect(lambda: self.deleteRowByContext(event))
            # add Row after
            addAction = QAction(QIcon.fromTheme("add"), 'insert new Row after', self)
            addAction.triggered.connect(lambda: self.addRowByContext(event))
            # add Row before
            addAction2 = QAction(QIcon.fromTheme("add"),'insert new Row before', self)
            addAction2.triggered.connect(lambda: self.addRowByContext2(event))
            # add Column before
            addColumnBeforeAction = QAction(QIcon.fromTheme("add"),'insert new Column before', self)
            addColumnBeforeAction.triggered.connect(lambda: self.addColumnBeforeByContext(event))
            # add Column after
            addColumnAfterAction = QAction(QIcon.fromTheme("add"),'insert new Column after', self)
            addColumnAfterAction.triggered.connect(lambda: self.addColumnAfterByContext(event))
            # delete Column
            deleteColumnAction = QAction(QIcon.fromTheme("edit-delete"), 'delete Column', self)
            deleteColumnAction.triggered.connect(lambda: self.deleteColumnByContext(event))
            # replace all
            row = self.selectedRow()
            col = self.selectedColumn()
            myitem = self.tableView.item(row,col)
            if myitem is not None:
                self.mytext = myitem.text()
            replaceThisAction = QAction(QIcon.fromTheme("edit-find-and-replace"), "replace all occurrences of '" + self.mytext + "'", self)
            replaceThisAction.triggered.connect(lambda: self.replaceThis())
            # find all
            findThisAction = QAction(QIcon.fromTheme("edit-find"), "find all rows contains '" + self.mytext + "'", self)
            findThisAction.triggered.connect(lambda: self.findThis())
            ###
            self.menu.addAction(copyAction)
            self.menu.addAction(pasteAction)
            self.menu.addAction(cutAction)
            self.menu.addSeparator()
            self.menu.addAction(addAction)
            self.menu.addAction(addAction2)
            self.menu.addSeparator()
            self.menu.addAction(addColumnBeforeAction)
            self.menu.addAction(addColumnAfterAction)
            self.menu.addSeparator()
            self.menu.addAction(removeAction)
            self.menu.addAction(deleteColumnAction)
            self.menu.addSeparator()
            self.menu.addAction(replaceThisAction)
            self.menu.addAction(findThisAction)
            self.menu.addSeparator()
            self.menu.addAction(self.whiteAction)
            self.menu.popup(QCursor.pos())

    def replaceThis(self):
        row = self.selectedRow()
        col = self.selectedColumn()
        myitem = self.tableView.item(row,col)
        if myitem is not None:
            mytext = myitem.text()
            dlg = QInputDialog()
            newtext, ok = dlg.getText(self, "Replace all", "replace all <b>" + mytext + " </b> with:", QLineEdit.Normal, "", Qt.Dialog)
            if ok:
                items = self.tableView.findItems(mytext, Qt.MatchExactly)
                if items:
                    for item in items:
                        newItem = QTableWidgetItem(newtext)
                        self.tableView.setItem(item.row(),item.column(), newItem)

    def deleteRowByContext(self, event):
        row = self.selectedRow()
        self.tableView.removeRow(row)
        self.msg("Row " + str(row) + " deleted")
        self.tableView.selectRow(row)
        self.isChanged = True

    def addRowByContext(self, event):
        if self.tableView.columnCount() == 0:
            self.tableView.setColumnCount(1) 
        if self.tableView.rowCount() == 0:
            self.tableView.setRowCount(1) 
            self.tableView.selectRow(0)
        else:
            row = self.selectedRow()
            self.tableView.insertRow(row + 1)
            self.msg("Row at " + str(row) + " inserted")
            self.tableView.selectRow(row + 1)
        self.isChanged = True

    def addRowByContext2(self, event):
        if self.tableView.columnCount() == 0:
            self.tableView.setColumnCount(1) 
        if self.tableView.rowCount() == 0:
            self.tableView.setRowCount(1) 
            self.tableView.selectRow(0)
        else:
            row = self.selectedRow() 
            self.tableView.insertRow(row)
            self.msg("Row at " + str(row) + " inserted")
            self.tableView.selectRow(row)
        self.isChanged = True

    def addColumnBeforeByContext(self, event):
        if self.tableView.columnCount() == 0:
            self.tableView.setColumnCount(1) 
        else:
            col = self.selectedColumn()
            self.tableView.insertColumn(col)
            self.msg("Column at " + str(col) + " inserted")
        if self.tableView.rowCount() == 0:
            self.tableView.setRowCount(1) 
        self.isChanged = True

    def addColumnAfterByContext(self, event):
        if self.tableView.columnCount() == 0:
            self.tableView.setColumnCount(1) 
        else:
            col = self.selectedColumn() + 1
            self.tableView.insertColumn(col)
            self.msg("Column at " + str(col) + " inserted")
        if self.tableView.rowCount() == 0:
            self.tableView.setRowCount(1) 
        self.isChanged = True

    def deleteColumnByContext(self, event):
        col = self.selectedColumn()
        self.tableView.removeColumn(col)
        self.msg("Column at " + str(col) + " removed")
        self.isChanged = True

    def copyByContext(self, event):
        row = self.selectedRow()
        col = self.selectedColumn()
        myitem = self.tableView.item(row,col)
        if myitem is not None:
            clip = QApplication.clipboard()
            clip.setText(myitem.text())

    def pasteByContext(self, event):
        row = self.selectedRow()
        col = self.selectedColumn()
        clip = QApplication.clipboard()
        newItem = QTableWidgetItem(clip.text())
        self.tableView.setItem(row,col, newItem)
        self.tableView.resizeColumnsToContents()
        self.isChanged = True

    def cutByContext(self, event):
        row = self.selectedRow()
        col = self.selectedColumn()
        myitem = self.tableView.item(row,col)
        if myitem is not None:
            clip = QApplication.clipboard()
            clip.setText(myitem.text())
            newItem = QTableWidgetItem("")
            self.tableView.setItem(row,col, newItem)
            self.isChanged = True

    def closeEvent(self, event):
        if self.isChanged == True:
            quit_msg = "<b>The document was changed.<br>Do you want to save the changes?</ b>"
            reply = QMessageBox.question(self, 'Save Confirmation', 
                     quit_msg, QMessageBox.Yes, QMessageBox.No)
            if reply == QMessageBox.Yes:
                event.accept()
                self.saveOnQuit()
        self.saveSettings()
        print("Goodbye ...")

    def readSettings(self):
        print("reading settings")
        if self.settings.contains("geometry"):
            self.setGeometry(self.settings.value('geometry'))
        if self.settings.contains("horHeader"):
            if self.settings.value('horHeader') == "true":    
                self.tableView.horizontalHeader().setVisible(True)
            else:
                self.tableView.horizontalHeader().setVisible(False)
        if self.settings.contains("vertHeader"):
            if self.settings.value('vertHeader') == "true":    
                self.tableView.verticalHeader().setVisible(True)
            else:
                self.tableView.verticalHeader().setVisible(False)

    def saveSettings(self):
        print("saving settings")
        self.settings.setValue('geometry', self.geometry())
        self.settings.setValue('horHeader', self.tableView.horizontalHeader().isVisible())
        self.settings.setValue('vertHeader', self.tableView.verticalHeader().isVisible())

    def saveOnQuit(self):
        if self.fileName == "":
            self.writeCsv()
        else:
            path = self.fileName
            with open(path, 'w') as stream:
                print("saving", path)
                writer = csv.writer(stream, delimiter='\t')
                for row in range(self.tableView.rowCount()):
                    rowdata = []
                    for column in range(self.tableView.columnCount()):
                        item = self.tableView.item(row, column)
                        if item is not None:
                            rowdata.append(item.text())
                        else:
                            rowdata.append('')
                    writer.writerow(rowdata)
        self.isChanged = False

    def setCurrentFile(self, fileName):
        self.fileName = fileName
        self.fname = os.path.splitext(str(fileName))[0].split("/")[-1]
        if self.fileName:
            self.setWindowTitle(self.strippedName(self.fileName) + "[*]")
        else:
            self.setWindowTitle("no File")      
        
        files = self.settings.value('recentFileList', [])

        try:
            files.remove(fileName)
        except ValueError:
            pass

        files.insert(0, fileName)
        del files[self.MaxRecentFiles:]

        self.settings.setValue('recentFileList', files)

        for widget in QApplication.topLevelWidgets():
            if isinstance(widget, MyWindow):
                widget.updateRecentFileActions()

    def updateRecentFileActions(self):
        mytext = ""
        files = self.settings.value('recentFileList', [])
        numRecentFiles = min(len(files), self.MaxRecentFiles)

        for i in range(numRecentFiles):
            text = "&%d %s" % (i + 1, self.strippedName(files[i]))
            self.recentFileActs[i].setText(text)
            self.recentFileActs[i].setData(files[i])
            self.recentFileActs[i].setVisible(True)
            self.recentFileActs[i].setIcon(QIcon.fromTheme("gnome-mime-text-x"))
            
        for j in range(numRecentFiles, self.MaxRecentFiles):
            self.recentFileActs[j].setVisible(False)

        self.separatorAct.setVisible((numRecentFiles > 0))
            
    def clearRecentFiles(self, fileName):
#        self.settings.clear()
        mf = []
        self.settings.setValue('recentFileList', mf)
        self.updateRecentFileActions()

    def strippedName(self, fullFileName):
        return QFileInfo(fullFileName).fileName()

    def msg(self, message):
        self.statusBar().showMessage(message)

def stylesheet(self):
        return """
        QTableWidget
        {
            border: 0.5px solid lightgrey;
            border-radius: 0px;
            font-family: Noto Sans;
            font-size: 9pt;
            background-color: #fbfbfb;
            selection-color: #ffffff
        }
        QTableWidget::item:hover
        {   
            color: black;
            background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #cfbb72, stop:1 #d3d7cf);           
        }
        
        QTableWidget::item:selected 
        {
            color: #F4F4F4;
            background: qlineargradient(x1:0, y1:0, x1:2, y1:2, stop:0 #bfc3fb, stop:1 #324864);
        } 
        QStatusBar
        {
            font-size: 7pt;
            color: #717171
        }
        QLineEdit
        {
           color: #484848;
            background-color: #fbfbfb;
        }
    """

if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    app.setApplicationName('MyWindow')
    main = MyWindow('')
    main.setMinimumSize(820, 300)
    main.setWindowTitle("CSV Viewer")
    main.show()

sys.exit(app.exec_())
Reply
#4
newer version on github
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020