Last active
February 5, 2023 18:45
-
-
Save mdmitry1/ec4f06e2809a6a9f0a34a8048d7c171c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3.11 | |
''' | |
https://www.pythonguis.com/tutorials/qtableview-modelviews-numpy-pandas/ | |
''' | |
from sys import argv, exit | |
from rich import print as rprint | |
from pandas import read_csv | |
from os import name as osname, popen | |
from os.path import realpath, basename, splitext, split | |
from re import sub | |
from argparse import ArgumentParser | |
from PyQt5.QtWidgets import QMainWindow, QApplication, QTableView, QHeaderView, QStyledItemDelegate, QStyle | |
from PyQt5.QtCore import Qt, QAbstractTableModel | |
from PyQt5.QtGui import QBrush, QColor, QPen | |
if 'nt' == osname: import ctypes | |
def get_screen_resolution(): | |
if 'nt' == osname: | |
user32 = ctypes.windll.user32 | |
return user32.GetSystemMetrics(0), user32.GetSystemMetrics(1) | |
else: | |
raw_string=popen("xdpyinfo | grep dimensions | cut -d':' -f2 | awk '{print $1}'").read() | |
resolution_string=raw_string.rstrip(raw_string[-1]) | |
xstr, ystr = resolution_string.split('x') | |
return int(xstr), int(ystr) | |
class TableModel(QAbstractTableModel): | |
def __init__(self, data): | |
super(TableModel, self).__init__() | |
self._data = data | |
def data(self, index, role): | |
if role == Qt.DisplayRole: return str(self._data.iloc[index.row(), index.column()]) | |
def rowCount(self, index): return self._data.shape[0] | |
def columnCount(self, index): return self._data.shape[1] | |
def headerData(self, section, orientation, role): | |
# section is the index of the column/row. | |
if role == Qt.DisplayRole: return str(self._data.columns[section]) if orientation == Qt.Horizontal \ | |
else str(self._data.index[section]+1) | |
class CustomDelegate(QStyledItemDelegate): | |
def __init__(self, parent=None): | |
super().__init__(parent) | |
def paint(self, painter, option, index): | |
if option.state & QStyle.State_HasFocus: painter.fillRect(option.rect, QBrush(QColor(210, 180, 140))) | |
else: painter.fillRect(option.rect, QBrush(QColor(0, 140, 0))) | |
pen = QPen(QColor("#ffffd7"), 2) | |
painter.setPen(pen) | |
painter.drawRect(option.rect) | |
super().paint(painter, option, index) | |
class MainWindow(QMainWindow): | |
def __init__(self,args, script_name): | |
super().__init__() | |
self.table = QTableView() | |
style='font-size: 16px; \ | |
background-color: lightgrey; \ | |
gridline-color: DarkViolet; \ | |
selection-background-color: blue' | |
if 'nt' == osname: style=sub("16px","20px",style) | |
self.table.setStyleSheet(style) | |
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents) | |
self.setWindowTitle(splitext(script_name)[0]) | |
try: | |
self.df = read_csv(args.file,sep=args.separator) \ | |
if args.header else read_csv(args.file,sep=args.separator,header=None) | |
except Exception as err: | |
rprint("\n[magenta] " + script_name + ":", "[red] ERROR: [/red]", "[red] " + str(err), "\n") | |
exit(1) | |
self.model = TableModel(self.df) | |
self.table.setModel(self.model) | |
self.table.setShowGrid(True) | |
self.table.setGridStyle(Qt.SolidLine) | |
self.setCentralWidget(self.table) | |
self.table.doubleClicked.connect(self.table_view_doubleClicked) | |
delegate = CustomDelegate() | |
self.table.setItemDelegate(delegate) | |
header = self.table.horizontalHeader() | |
table_width=0 | |
for col in range(0, self.df.shape[1]): | |
table_width += header.sectionSize(col) | |
table_height = self.table.verticalHeader().sectionSize(0)*self.df.shape[0] | |
screen_w, screen_h = get_screen_resolution() | |
self.resize(min(screen_w-100,table_width+50),min(screen_h-100,table_height+50)) | |
selection_model=self.table.selectionModel() | |
selection_model.selectionChanged.connect(self.on_selection_changed) | |
def on_selection_changed(self, index): | |
print("Selection has been changed") | |
def table_view_doubleClicked(self, index): | |
row = index.row() | |
column = index.column() | |
value=self.df.iloc[row,column] | |
print(f"Row: {row+1}, Column: {column+1}, value = {value}") | |
def main(): | |
parser = ArgumentParser() | |
parser.add_argument('--file', '-f', default="/dev/stdin") | |
parser.add_argument('--header', '-hdr', default=None, action='store_true') | |
parser.add_argument('--separator', '-s', default='\s+') | |
args=parser.parse_args() | |
app=QApplication(argv) | |
window=MainWindow(args, basename(realpath(argv[0]))) | |
window.show() | |
exit(app.exec_()) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment