916.2.1
by Ian Clatworthy
Basic qplugins implementation |
1 |
# Copyright (C) 2009 Canonical Ltd
|
2 |
#
|
|
3 |
# This program is free software; you can redistribute it and/or modify
|
|
4 |
# it under the terms of the GNU General Public License as published by
|
|
5 |
# the Free Software Foundation; either version 2 of the License, or
|
|
6 |
# (at your option) any later version.
|
|
7 |
#
|
|
8 |
# This program is distributed in the hope that it will be useful,
|
|
9 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11 |
# GNU General Public License for more details.
|
|
12 |
#
|
|
13 |
# You should have received a copy of the GNU General Public License
|
|
14 |
# along with this program; if not, write to the Free Software
|
|
15 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
16 |
||
17 |
||
18 |
from PyQt4 import QtGui |
|
19 |
from PyQt4.QtCore import Qt, QVariant |
|
20 |
||
21 |
||
22 |
class QBzrConditionalDataView(QtGui.QFrame): |
|
23 |
"""A list/table/tree with a label.
|
|
24 |
|
|
25 |
Only the label is shown when the data model is empty.
|
|
26 |
"""
|
|
27 |
||
28 |
def __init__(self, type, listmode_or_headers, label_text, |
|
29 |
details, parent=None): |
|
30 |
"""Construct the view.
|
|
31 |
||
32 |
:param type: one of list, table, tree
|
|
33 |
:param listmode_or_headers: For lists, set the initial list view
|
|
34 |
mode: True => list, False => icon.
|
|
35 |
For tables and trees, the list of headers.
|
|
36 |
:param label_text: text for label. May contain %(rows)d to substitute
|
|
37 |
the row count.
|
|
38 |
:param details: if non-None, a QWidget to show in a details panel.
|
|
39 |
:param parent: parent widget
|
|
40 |
"""
|
|
41 |
QtGui.QFrame.__init__(self, parent) |
|
42 |
||
43 |
# Build the model & view for the data
|
|
44 |
self._type = type |
|
45 |
columns = listmode_or_headers |
|
46 |
if type == 'list': |
|
47 |
self._view = QtGui.QListView() |
|
48 |
self._view.setResizeMode(QtGui.QListView.Adjust) |
|
49 |
self._view.setWrapping(True) |
|
50 |
if listmode_or_headers: |
|
51 |
self._view.setViewMode(QtGui.QListView.ListMode) |
|
52 |
else: |
|
53 |
self._view.setViewMode(QtGui.QListView.IconMode) |
|
54 |
columns = ['Name'] |
|
55 |
# TODO: we could add a combo-box here letting the user decide
|
|
56 |
# on list vs icons. Would we need a way to switch it off?
|
|
57 |
elif type == 'tree': |
|
58 |
self._view = QtGui.QTreeView() |
|
59 |
elif type == 'table': |
|
60 |
self._view = QtGui.QTableView() |
|
61 |
self._model = QtGui.QStandardItemModel(0, len(columns)) |
|
62 |
self._model.setHorizontalHeaderLabels(columns) |
|
63 |
# Make the view read-only, and enable multi-selection of items
|
|
64 |
self._view.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) |
|
65 |
self._view.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows) |
|
66 |
self._view.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) |
|
67 |
self._view.setModel(self._model) |
|
68 |
||
69 |
# Build the label
|
|
70 |
self._label_text = label_text |
|
71 |
if label_text: |
|
72 |
self._label = QtGui.QLabel() |
|
73 |
self._update_label_text() |
|
74 |
||
75 |
# Put them together
|
|
76 |
layout = QtGui.QVBoxLayout() |
|
77 |
if details: |
|
78 |
splitter = QtGui.QSplitter() |
|
79 |
splitter.setOrientation(Qt.Vertical) |
|
80 |
splitter.addWidget(self._view) |
|
81 |
splitter.addWidget(details) |
|
82 |
layout.addWidget(splitter) |
|
83 |
else: |
|
84 |
layout.addWidget(self._view) |
|
85 |
if label_text: |
|
86 |
layout.addWidget(self._label) |
|
87 |
self.setLayout(layout) |
|
88 |
||
89 |
def view(self): |
|
90 |
"""Get the view object (QAbstractItemView)."""
|
|
91 |
return self._view |
|
92 |
||
93 |
def label(self): |
|
94 |
"""Get the label object (QLabel)."""
|
|
95 |
return self._label |
|
96 |
||
97 |
def setData(self, tuple_list, decoration_provider=None): |
|
98 |
"""Reset the model to have the data shown.
|
|
99 |
||
100 |
:param tuple_list: a list of tuples. Each tuple should have
|
|
101 |
len(headers) items.
|
|
102 |
:param decoration_provider: a callable taking the row number
|
|
103 |
and record. It returns the icon to display in the first column
|
|
104 |
or None if none.
|
|
105 |
"""
|
|
106 |
# Update the model
|
|
107 |
row_count = len(tuple_list) |
|
108 |
model = self._model |
|
109 |
model.setRowCount(row_count) |
|
110 |
cell_role = Qt.DisplayRole |
|
111 |
for row, record in enumerate(tuple_list): |
|
112 |
if decoration_provider: |
|
113 |
icon = decoration_provider(row, record) |
|
114 |
if icon: |
|
115 |
index = model.index(row, 0) |
|
116 |
model.setData(index, QVariant(icon), Qt.DecorationRole) |
|
117 |
for col, value in enumerate(record): |
|
118 |
#print "putting %s into %d,%d" % (value, row, col)
|
|
119 |
index = model.index(row, col) |
|
120 |
model.setData(index, QVariant(value or ''), cell_role) |
|
121 |
||
122 |
# Update the view & label
|
|
123 |
self._view.setVisible(row_count > 0) |
|
124 |
if self._type in ['tree', 'table']: |
|
125 |
self._view.resizeColumnToContents(0) |
|
126 |
self._update_label_text(row_count) |
|
127 |
||
128 |
def _update_label_text(self, row_count=0): |
|
129 |
if self._label_text: |
|
130 |
text = self._label_text % {'rows': row_count} |
|
131 |
self._label.setText(text) |