######################################################################################################################
# Copyright (C) 2017-2020 Spine project consortium
# This file is part of Spine Toolbox.
# Spine Toolbox is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General
# Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
# any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
# Public License for more details. You should have received a copy of the GNU Lesser General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
######################################################################################################################
"""
Custom QTableView classes that support copy-paste and the like.
:author: M. Marin (KTH)
:date: 18.5.2018
"""
from PySide2.QtWidgets import QTableView, QApplication
from PySide2.QtCore import Qt, Slot, QItemSelectionModel
from PySide2.QtGui import QKeySequence
from .pivot_table_header_view import PivotTableHeaderView
[docs]class PivotTableView(QTableView):
"""Custom QTableView class with pivot capabilities.
Attributes:
parent (QWidget): The parent of this view
"""
def __init__(self, parent=None):
"""Initialize the class."""
super().__init__(parent)
self.clipboard = QApplication.clipboard()
self.clipboard_text = self.clipboard.text()
self.clipboard.dataChanged.connect(self.clipboard_data_changed)
h_header = PivotTableHeaderView(Qt.Horizontal, "columns", self)
v_header = PivotTableHeaderView(Qt.Vertical, "rows", self)
self.setHorizontalHeader(h_header)
self.setVerticalHeader(v_header)
h_header.setContextMenuPolicy(Qt.CustomContextMenu)
@Slot(name="clipboard_data_changed")
[docs] def clipboard_data_changed(self):
self.clipboard_text = self.clipboard.text()
[docs] def keyPressEvent(self, event):
"""Copy and paste to and from clipboard in Excel-like format."""
if event.matches(QKeySequence.Copy):
selection = self.selectionModel().selection()
if not selection:
super().keyPressEvent(event)
return
# Take only the first selection in case of multiple selection.
first = selection.first()
content = ""
v_header = self.verticalHeader()
h_header = self.horizontalHeader()
for i in range(first.top(), first.bottom() + 1):
if v_header.isSectionHidden(i):
continue
row = list()
for j in range(first.left(), first.right() + 1):
if h_header.isSectionHidden(j):
continue
row.append(str(self.model().index(i, j).data(Qt.DisplayRole)))
content += "\t".join(row)
content += "\n"
self.clipboard.setText(content)
elif event.matches(QKeySequence.Paste):
if not self.clipboard_text:
super().keyPressEvent(event)
return
top_left_index = self.currentIndex()
if not top_left_index.isValid():
super().keyPressEvent(event)
return
data = [line.split('\t') for line in self.clipboard_text.split('\n')[0:-1]]
self.selectionModel().select(top_left_index, QItemSelectionModel.Select)
self.model().paste_data(top_left_index, data)
else:
super().keyPressEvent(event)