File indexing completed on 2024-04-28 16:21:31
0001 /* This file is part of the KDE project 0002 Copyright 2009 Stefan Nikolaus stefan.nikolaus@kdemail.net 0003 0004 This library is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU Library General Public 0006 License as published by the Free Software Foundation; either 0007 version 2 of the License, or (at your option) any later version. 0008 0009 This library is distributed in the hope that it will be useful, 0010 but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 Library General Public License for more details. 0013 0014 You should have received a copy of the GNU Library General Public License 0015 along with this library; see the file COPYING.LIB. If not, write to 0016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "SheetModel.h" 0021 0022 // Sheets 0023 #include "Binding.h" 0024 #include "Cell.h" 0025 #include "CellStorage.h" 0026 #include "Condition.h" 0027 #include "database/Database.h" 0028 #include "Formula.h" 0029 #include "Map.h" 0030 #include "ModelSupport.h" 0031 #include "Sheet.h" 0032 #include "Style.h" 0033 #include "Validity.h" 0034 #include "Value.h" 0035 #include "ValueFormatter.h" 0036 0037 // Qt 0038 #include <QBrush> 0039 #include <QItemSelectionRange> 0040 #include <QSize> 0041 0042 using namespace Calligra::Sheets; 0043 0044 class Q_DECL_HIDDEN SheetModel::Private 0045 { 0046 public: 0047 Sheet* sheet; 0048 }; 0049 0050 SheetModel::SheetModel(Sheet* sheet) 0051 : QAbstractTableModel(sheet) 0052 , d(new Private) 0053 { 0054 d->sheet = sheet; 0055 } 0056 0057 SheetModel::~SheetModel() 0058 { 0059 delete d; 0060 } 0061 0062 int SheetModel::columnCount(const QModelIndex& parent) const 0063 { 0064 if (parent.isValid() && parent.internalPointer() != d->sheet->map()) { 0065 return 0; 0066 } 0067 return KS_colMax; 0068 } 0069 0070 QVariant SheetModel::data(const QModelIndex& index, int role) const 0071 { 0072 if (!index.isValid()) { 0073 return QVariant(); 0074 } 0075 if (index.model() != this) { 0076 return QVariant(); 0077 } 0078 if (index.internalPointer() != d->sheet) { 0079 return QVariant(); 0080 } 0081 if (index.parent().isValid()) { 0082 if (index.parent().internalPointer() != d->sheet->map()) { 0083 return QVariant(); 0084 } 0085 } 0086 // NOTE Model indices start from 0, while Calligra Sheets column/row indices start from 1. 0087 const Cell cell = Cell(d->sheet, index.column() + 1, index.row() + 1).masterCell(); 0088 const Style style = cell.effectiveStyle(); 0089 if (role == Qt::DisplayRole) { 0090 // Display a formula if warranted. If not, simply display the value. 0091 if (cell.isFormula() && d->sheet->getShowFormula() && 0092 !(d->sheet->isProtected() && style.hideFormula())) { 0093 return QVariant(cell.userInput()); 0094 } else if (d->sheet->getHideZero() && cell.value().isNumber() && cell.value().asFloat() == 0.0) { 0095 // Hide zero. 0096 return QVariant(); 0097 } else if (!cell.isEmpty()) { 0098 // Format the value appropriately and set the display text. 0099 // The format of the resulting value is used below to determine the alignment. 0100 Value value = d->sheet->map()->formatter()->formatText(cell.value(), style.formatType(), 0101 style.precision(), style.floatFormat(), 0102 style.prefix(), style.postfix(), 0103 style.currency().symbol()); 0104 return value.asString(); 0105 } 0106 } else if (role == Qt::EditRole) { 0107 return cell.userInput(); 0108 } else if (role == Qt::ToolTipRole) { 0109 return cell.comment(); 0110 } else if (role == Qt::SizeHintRole) { 0111 // TODO 0112 } else if (role == Qt::FontRole) { 0113 return style.font(); 0114 } else if (role == Qt::TextAlignmentRole) { 0115 // TODO 0116 } else if (role == Qt::BackgroundRole) { 0117 return style.backgroundBrush(); 0118 } else if (role == Qt::BackgroundColorRole) { 0119 return style.backgroundColor(); 0120 } else if (role == Qt::ForegroundRole) { 0121 return style.fontColor(); 0122 } 0123 const int column = index.column() + 1; 0124 const int row = index.row() + 1; 0125 CellStorage *const storage = d->sheet->cellStorage(); 0126 switch (role) { 0127 case UserInputRole: 0128 return storage->userInput(column, row); 0129 case FormulaRole: { 0130 QVariant data; 0131 data.setValue(storage->formula(column, row)); 0132 return data; 0133 } 0134 case ValueRole: { 0135 QVariant data; 0136 data.setValue(storage->value(column, row)); 0137 return data; 0138 } 0139 case LinkRole: 0140 return storage->link(column, row); 0141 } 0142 return QVariant(); 0143 } 0144 0145 Qt::ItemFlags SheetModel::flags(const QModelIndex& index) const 0146 { 0147 if (!index.isValid()) { 0148 return Qt::NoItemFlags; 0149 } 0150 if (index.model() != this) { 0151 return Qt::NoItemFlags; 0152 } 0153 if (index.internalPointer() != d->sheet) { 0154 return Qt::NoItemFlags; 0155 } 0156 if (index.parent().isValid()) { 0157 if (index.parent().internalPointer() != d->sheet->map()) { 0158 return Qt::NoItemFlags; 0159 } 0160 } 0161 return Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled; 0162 } 0163 0164 QVariant SheetModel::headerData(int section, Qt::Orientation orientation, int role) const 0165 { 0166 // NOTE Model indices start from 0, while Calligra Sheets column/row indices start from 1. 0167 if (role == Qt::DisplayRole) { 0168 if (orientation == Qt::Horizontal) { 0169 return Cell::columnName(section + 1); 0170 } else { 0171 return QString::number(section + 1); 0172 } 0173 } 0174 return QVariant(); 0175 } 0176 0177 QModelIndex SheetModel::index(int row, int column, const QModelIndex &parent) const 0178 { 0179 if (parent.isValid() && parent.internalPointer() != d->sheet->map()) { 0180 return QModelIndex(); 0181 } 0182 // A cell in our sheet? 0183 if (!parent.isValid()) { 0184 return createIndex(row, column, d->sheet); 0185 // Embedded in a MapModel? 0186 } else if (parent.internalPointer() == d->sheet->map()) { 0187 return createIndex(row, column, d->sheet); 0188 // A sub-table? 0189 } else if (parent.internalPointer() == this) { 0190 // TODO sub-tables 0191 } 0192 return QModelIndex(); 0193 } 0194 0195 int SheetModel::rowCount(const QModelIndex& parent) const 0196 { 0197 if (parent.isValid() && parent.internalPointer() != d->sheet->map()) { 0198 return 0; 0199 } 0200 return KS_rowMax; 0201 } 0202 0203 bool SheetModel::setData(const QModelIndex& index, const QVariant& value, int role) 0204 { 0205 if (!index.isValid()) { 0206 return false; 0207 } 0208 if (index.model() != this) { 0209 return false; 0210 } 0211 if (index.internalPointer() != d->sheet) { 0212 return false; 0213 } 0214 if (index.parent().isValid()) { 0215 if (index.parent().internalPointer() != d->sheet->map()) { 0216 return false; 0217 } 0218 } 0219 // NOTE Model indices start from 0, while Calligra Sheets column/row indices start from 1. 0220 const int column = index.column() + 1; 0221 const int row = index.row() + 1; 0222 Cell cell = Cell(sheet(), index.column() + 1, index.row() + 1).masterCell(); 0223 CellStorage *const storage = d->sheet->cellStorage(); 0224 switch (role) { 0225 case Qt::EditRole: 0226 cell.parseUserInput(value.toString()); 0227 break; 0228 case UserInputRole: 0229 storage->setUserInput(column, row, value.toString()); 0230 break; 0231 case FormulaRole: 0232 storage->setFormula(column, row, value.value<Formula>()); 0233 break; 0234 case ValueRole: 0235 storage->setValue(column, row, value.value<Value>()); 0236 break; 0237 case LinkRole: 0238 storage->setLink(column, row, value.toString()); 0239 break; 0240 default: 0241 return false; 0242 } 0243 emit dataChanged(index, index); 0244 return true; 0245 } 0246 0247 bool SheetModel::setData(const QItemSelectionRange &range, const QVariant &value, int role) 0248 { 0249 const Region region(toRange(range), d->sheet); 0250 CellStorage *const storage = d->sheet->cellStorage(); 0251 switch (role) { 0252 case CommentRole: 0253 storage->setComment(region, value.toString()); 0254 break; 0255 case ConditionRole: 0256 storage->setConditions(region, value.value<Conditions>()); 0257 break; 0258 case FusionedRangeRole: 0259 // TODO 0260 // storage->setFusion(region, value.value<bool>()); 0261 break; 0262 case LockedRangeRole: 0263 // TODO 0264 // storage->setMatrix(region, value.value<bool>()); 0265 break; 0266 case NamedAreaRole: { 0267 QString namedAreaName = value.toString(); 0268 if (namedAreaName.isEmpty()) 0269 return false; 0270 storage->emitInsertNamedArea(region, namedAreaName); 0271 break; 0272 } 0273 case SourceRangeRole: 0274 storage->setBinding(region, value.value<Binding>()); 0275 break; 0276 case StyleRole: 0277 // TODO 0278 // storage->setStyle(region, value.value<Style>()); 0279 break; 0280 case TargetRangeRole: 0281 storage->setDatabase(region, value.value<Database>()); 0282 break; 0283 case ValidityRole: 0284 storage->setValidity(region, value.value<Validity>()); 0285 break; 0286 default: 0287 return false; 0288 } 0289 emit dataChanged(range.topLeft(), range.bottomRight()); 0290 return true; 0291 } 0292 0293 bool SheetModel::setData(const QModelIndex &topLeft, const QModelIndex &bottomRight, 0294 const QVariant &value, int role) 0295 { 0296 return setData(QItemSelectionRange(topLeft, bottomRight), value, role); 0297 } 0298 0299 Sheet* SheetModel::sheet() const 0300 { 0301 return d->sheet; 0302 }