File: tableview.py

package info (click to toggle)
setools 4.6.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,600 kB
  • sloc: python: 24,485; makefile: 14
file content (130 lines) | stat: -rw-r--r-- 4,226 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# Copyright 2016, Chris PeBenito <pebenito@ieee.org>
#
# SPDX-License-Identifier: LGPL-2.1-only
#
#
import csv

from PyQt6 import QtCore, QtGui, QtWidgets

from .. import models

__all__ = ("SEToolsTableView",)


class SEToolsTableView(QtWidgets.QTableView):

    """
    QTableView class extended for saving CSV files and context menu actions
    provided by the model.
    """

    def contextMenuEvent(self, event: QtGui.QContextMenuEvent) -> None:  # type: ignore[override]
        """Handle the context menu event."""
        menu = QtWidgets.QMenu(self)
        menu.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose)

        # Add any actions provided by the model.
        index = self.indexAt(event.pos())
        if index.isValid():
            for action in self.model().data(index, models.ModelRoles.ContextMenuRole):
                action.setParent(menu)
                menu.addAction(action)

            menu.addSeparator()

        # Add the save to CSV action
        save_csv_action = QtGui.QAction("Save table to CSV...", self)
        save_csv_action.triggered.connect(self.choose_csv_save_location)
        menu.addAction(save_csv_action)
        menu.exec(event.globalPos())
        return

    def copy(self) -> None:
        datamodel = self.model()

        selected_text = []
        current_row: int = -1
        current_col: int = -1
        prev_row: int = -1
        prev_col: int = -1
        for index in sorted(self.selectionModel().selectedIndexes()):
            current_row = index.row()
            current_col = index.column()

            if prev_row is not None and current_row != prev_row:
                selected_text.append('\n')
            elif prev_col is not None and current_col != prev_col:
                selected_text.append('\t')

            selected_text.append(datamodel.data(index, models.ModelRoles.DisplayRole))

            prev_row = current_row
            prev_col = current_col

        cb = QtWidgets.QApplication.clipboard()
        assert cb, "No clipboard available, this is an SETools bug"  # type narrowing
        cb.setText("".join(selected_text))

    def cut(self) -> None:
        self.copy()

    def choose_csv_save_location(self) -> None:
        filename = QtWidgets.QFileDialog.getSaveFileName(
            self,
            "Save to CSV",
            "table.csv",
            "Comma Separated Values Spreadsheet (*.csv);;"
            "All Files (*)")[0]

        if filename:
            self.save_csv(filename)

    def save_csv(self, filename: str) -> None:
        """Save the current table data to the specified CSV file."""

        datamodel = self.model()
        row_count = datamodel.rowCount()
        col_count = datamodel.columnCount()

        with open(filename, 'w') as fd:
            writer = csv.writer(fd, quoting=csv.QUOTE_MINIMAL)

            # write headers
            csv_row = []
            for col in range(col_count):
                csv_row.append(datamodel.headerData(col,
                                                    QtCore.Qt.Orientation.Horizontal,
                                                    models.ModelRoles.DisplayRole))

            writer.writerow(csv_row)

            # write data
            for row in range(row_count):
                csv_row = []

                for col in range(col_count):
                    index = datamodel.index(row, col)
                    csv_row.append(datamodel.data(index, models.ModelRoles.DisplayRole))

                writer.writerow(csv_row)

    #
    # Overridden methods for typing purposes
    #

    # @typing.override
    def model(self) -> QtCore.QAbstractItemModel:
        """Type-narrowed model() method.  See QTableView.model() for more info."""
        model = super().model()
        assert model, "No model set, this is an SETools bug"
        return model

    # @typing.override
    def selectionModel(self) -> QtCore.QItemSelectionModel:
        """
        Type-narrowed selectionModel() method.  See QTableView.selectionModel() for more info.
        """
        selection_model = super().selectionModel()
        assert selection_model, "No selection model set, this is an SETools bug"
        return selection_model