1 | /* This file is part of the KDE project |
2 | Copyright 2009 Stefan Nikolaus <stefan.nikolaus@kdemail.net> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Library General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2 of the License, or (at your option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Library General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to |
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "MapModel.h" |
21 | |
22 | #include "Map.h" |
23 | #include "ModelSupport.h" |
24 | #include "Sheet.h" |
25 | #include "SheetModel.h" |
26 | |
27 | #include "commands/SheetCommands.h" |
28 | |
29 | #include <KoIcon.h> |
30 | |
31 | using namespace Calligra::Sheets; |
32 | |
33 | class MapModel::Private |
34 | { |
35 | public: |
36 | Map* map; |
37 | |
38 | public: |
39 | bool isSheetIndex(const QModelIndex& index, const MapModel* mapModel) const; |
40 | }; |
41 | |
42 | bool MapModel::Private::isSheetIndex(const QModelIndex& index, const MapModel* mapModel) const |
43 | { |
44 | if (!index.parent().isValid()) { |
45 | return false; |
46 | } |
47 | // If it is a cell, the parent's (the sheet's) model has to be this model. |
48 | if (index.parent().model() != mapModel || index.parent().internalPointer() != map) { |
49 | return false; |
50 | } |
51 | // If it is a cell, the parent (the sheet) has no parent. |
52 | if (index.parent().parent().isValid()) { |
53 | return false; |
54 | } |
55 | // Do not exceed the sheet list. |
56 | if (index.parent().row() >= map->count()) { |
57 | return false; |
58 | } |
59 | // The index' (the cell's) model has to match the sheet model. |
60 | if (index.model() != map->sheet(index.parent().row())->model()) { |
61 | return false; |
62 | } |
63 | return true; |
64 | } |
65 | |
66 | |
67 | MapModel::MapModel(Map* map) |
68 | : QAbstractListModel(map) |
69 | , d(new Private) |
70 | { |
71 | d->map = map; |
72 | connect(d->map, SIGNAL(sheetAdded(Sheet*)), |
73 | this, SLOT(addSheet(Sheet*))); |
74 | connect(d->map, SIGNAL(sheetRemoved(Sheet*)), |
75 | this, SLOT(removeSheet(Sheet*))); |
76 | } |
77 | |
78 | MapModel::~MapModel() |
79 | { |
80 | delete d; |
81 | } |
82 | |
83 | QVariant MapModel::data(const QModelIndex &index, int role) const |
84 | { |
85 | if (!index.isValid()) { |
86 | return QVariant(); |
87 | } |
88 | // Propagation to sheet model |
89 | if (d->isSheetIndex(index, this)) { |
90 | return d->map->sheet(index.parent().row())->model()->data(index, role); |
91 | } |
92 | if (index.row() >= d->map->count()) { |
93 | return QVariant(); |
94 | } |
95 | // |
96 | const Sheet* const sheet = d->map->sheet(index.row()); |
97 | switch (role) { |
98 | case Qt::DisplayRole: |
99 | case Qt::EditRole: |
100 | return QVariant(sheet->sheetName()); |
101 | case Qt::DecorationRole: |
102 | return QVariant(koIcon("x-office-spreadsheet" )); |
103 | case VisibilityRole: |
104 | return QVariant(!sheet->isHidden()); |
105 | case ProtectionRole: |
106 | return QVariant(sheet->isProtected()); |
107 | default: |
108 | break; |
109 | } |
110 | return QVariant(); |
111 | } |
112 | |
113 | Qt::ItemFlags MapModel::flags(const QModelIndex &index) const |
114 | { |
115 | if (!index.isValid()) { |
116 | return Qt::NoItemFlags; |
117 | } |
118 | // Propagation to sheet model |
119 | if (d->isSheetIndex(index, this)) { |
120 | return d->map->sheet(index.parent().row())->model()->flags(index); |
121 | } |
122 | if (index.row() >= d->map->count()) { |
123 | return Qt::NoItemFlags; |
124 | } |
125 | |
126 | Qt::ItemFlags flags = Qt::ItemIsEnabled; |
127 | if (!d->map->isProtected()) { |
128 | flags |= Qt::ItemIsSelectable; |
129 | const Sheet* const sheet = d->map->sheet(index.row()); |
130 | if (!sheet->isProtected()) { |
131 | flags |= Qt::ItemIsEditable; |
132 | } |
133 | } |
134 | return flags; |
135 | } |
136 | |
137 | QVariant MapModel::(int section, Qt::Orientation orientation, int role) const |
138 | { |
139 | Q_UNUSED(orientation) |
140 | if (section == 0 && role == Qt::DisplayRole) { |
141 | return QVariant(i18n("Sheet name" )); |
142 | } |
143 | return QVariant(); |
144 | } |
145 | |
146 | QModelIndex MapModel::index(int row, int column, const QModelIndex &parent) const |
147 | { |
148 | QModelIndex index; |
149 | if (parent.isValid()) { |
150 | // If it is a cell, the parent's (the sheet's) model has to be this model. |
151 | if (parent.model() != this || parent.internalPointer() != d->map) { |
152 | return QModelIndex(); |
153 | } |
154 | // If it is a cell, the parent (the sheet) has no parent. |
155 | if (parent.parent().isValid()) { |
156 | return QModelIndex(); |
157 | } |
158 | // Do not exceed the sheet list. |
159 | if (parent.row() >= d->map->count()) { |
160 | return QModelIndex(); |
161 | } |
162 | Sheet* const sheet = d->map->sheet(index.parent().row()); |
163 | index = sheet->model()->index(row, column, parent); |
164 | } else { |
165 | index = createIndex(row, column, d->map); |
166 | } |
167 | return index; |
168 | } |
169 | |
170 | int MapModel::rowCount(const QModelIndex &parent) const |
171 | { |
172 | if (parent.isValid()) { |
173 | return 0; |
174 | } |
175 | return d->map->count(); |
176 | } |
177 | |
178 | bool MapModel::setData(const QModelIndex &index, const QVariant &value, int role) |
179 | { |
180 | // Propagation to sheet model |
181 | if (d->isSheetIndex(index, this)) { |
182 | return d->map->sheet(index.parent().row())->model()->setData(index, value, role); |
183 | } |
184 | |
185 | if (index.isValid() && index.row() < d->map->count()) { |
186 | Sheet* const sheet(d->map->sheet(index.row())); |
187 | switch (role) { |
188 | case Qt::EditRole: { |
189 | const QString name(value.toString()); |
190 | if (!name.isEmpty()) { |
191 | KUndo2Command* const command = new RenameSheetCommand(sheet, name); |
192 | emit addCommandRequested(command); |
193 | emit dataChanged(index, index); |
194 | return true; |
195 | } |
196 | break; |
197 | } |
198 | case VisibilityRole: |
199 | setHidden(sheet, value.toBool()); |
200 | break; |
201 | case ProtectionRole: |
202 | break; |
203 | default: |
204 | break; |
205 | } |
206 | } |
207 | return false; |
208 | } |
209 | |
210 | bool MapModel::setHidden(Sheet* sheet, bool hidden) |
211 | { |
212 | KUndo2Command* command; |
213 | if (hidden && !sheet->isHidden()) { |
214 | command = new HideSheetCommand(sheet); |
215 | } else if (!hidden && sheet->isHidden()) { |
216 | command = new ShowSheetCommand(sheet); |
217 | } else { |
218 | return false; // nothing to do |
219 | } |
220 | emit addCommandRequested(command); |
221 | return true; |
222 | } |
223 | |
224 | Map* MapModel::map() const |
225 | { |
226 | return d->map; |
227 | } |
228 | |
229 | void MapModel::addSheet(Sheet* sheet) |
230 | { |
231 | kDebug() << "Added sheet:" << sheet->sheetName(); |
232 | emit layoutChanged(); |
233 | } |
234 | |
235 | void MapModel::removeSheet(Sheet *sheet) |
236 | { |
237 | kDebug() << "Removed sheet:" << sheet->sheetName(); |
238 | emit layoutChanged(); |
239 | } |
240 | |
241 | #include "MapModel.moc" |
242 | |