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
131
|
# Copyright (C) 2009 Canonical Ltd
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from PyQt4 import QtGui
from PyQt4.QtCore import Qt, QVariant
class QBzrConditionalDataView(QtGui.QFrame):
"""A list/table/tree with a label.
Only the label is shown when the data model is empty.
"""
def __init__(self, type, listmode_or_headers, label_text,
details, parent=None):
"""Construct the view.
:param type: one of list, table, tree
:param listmode_or_headers: For lists, set the initial list view
mode: True => list, False => icon.
For tables and trees, the list of headers.
:param label_text: text for label. May contain %(rows)d to substitute
the row count.
:param details: if non-None, a QWidget to show in a details panel.
:param parent: parent widget
"""
QtGui.QFrame.__init__(self, parent)
# Build the model & view for the data
self._type = type
columns = listmode_or_headers
if type == 'list':
self._view = QtGui.QListView()
self._view.setResizeMode(QtGui.QListView.Adjust)
self._view.setWrapping(True)
if listmode_or_headers:
self._view.setViewMode(QtGui.QListView.ListMode)
else:
self._view.setViewMode(QtGui.QListView.IconMode)
columns = ['Name']
# TODO: we could add a combo-box here letting the user decide
# on list vs icons. Would we need a way to switch it off?
elif type == 'tree':
self._view = QtGui.QTreeView()
elif type == 'table':
self._view = QtGui.QTableView()
self._model = QtGui.QStandardItemModel(0, len(columns))
self._model.setHorizontalHeaderLabels(columns)
# Make the view read-only, and enable multi-selection of items
self._view.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
self._view.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
self._view.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self._view.setModel(self._model)
# Build the label
self._label_text = label_text
if label_text:
self._label = QtGui.QLabel()
self._update_label_text()
# Put them together
layout = QtGui.QVBoxLayout()
if details:
splitter = QtGui.QSplitter()
splitter.setOrientation(Qt.Vertical)
splitter.addWidget(self._view)
splitter.addWidget(details)
layout.addWidget(splitter)
else:
layout.addWidget(self._view)
if label_text:
layout.addWidget(self._label)
self.setLayout(layout)
def view(self):
"""Get the view object (QAbstractItemView)."""
return self._view
def label(self):
"""Get the label object (QLabel)."""
return self._label
def setData(self, tuple_list, decoration_provider=None):
"""Reset the model to have the data shown.
:param tuple_list: a list of tuples. Each tuple should have
len(headers) items.
:param decoration_provider: a callable taking the row number
and record. It returns the icon to display in the first column
or None if none.
"""
# Update the model
row_count = len(tuple_list)
model = self._model
model.setRowCount(row_count)
cell_role = Qt.DisplayRole
for row, record in enumerate(tuple_list):
if decoration_provider:
icon = decoration_provider(row, record)
if icon:
index = model.index(row, 0)
model.setData(index, QVariant(icon), Qt.DecorationRole)
for col, value in enumerate(record):
#print "putting %s into %d,%d" % (value, row, col)
index = model.index(row, col)
model.setData(index, QVariant(value or ''), cell_role)
# Update the view & label
self._view.setVisible(row_count > 0)
if self._type in ['tree', 'table']:
self._view.resizeColumnToContents(0)
self._update_label_text(row_count)
def _update_label_text(self, row_count=0):
if self._label_text:
text = self._label_text % {'rows': row_count}
self._label.setText(text)
|