File indexing completed on 2024-04-28 16:21:16
0001 /* This file is part of the KDE project 0002 Copyright 2007 Stefan Nikolaus <stefan.nikolaus@kdemail.net> 0003 Copyright (C) 2008 Thomas Zander <zander@kde.org> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "Binding.h" 0022 #include "BindingModel.h" 0023 0024 #include <QRect> 0025 0026 #include "SheetsDebug.h" 0027 0028 #include "CellStorage.h" 0029 #include "Map.h" 0030 #include "Sheet.h" 0031 #include "Value.h" 0032 0033 using namespace Calligra::Sheets; 0034 0035 class Q_DECL_HIDDEN Binding::Private : public QSharedData 0036 { 0037 public: 0038 BindingModel* model; 0039 Private(Binding *q) : model(new BindingModel(q)) {} 0040 ~Private() { delete model; } 0041 }; 0042 0043 0044 Binding::Binding() 0045 : d(new Private(this)) 0046 { 0047 } 0048 0049 Binding::Binding(const Region& region) 0050 : d(new Private(this)) 0051 { 0052 Q_ASSERT(region.isValid()); 0053 d->model->setRegion(region); 0054 } 0055 0056 Binding::Binding(const Binding& other) 0057 : d(other.d) 0058 { 0059 } 0060 0061 Binding::~Binding() 0062 { 0063 } 0064 0065 bool Binding::isEmpty() const 0066 { 0067 return d->model->region().isEmpty(); 0068 } 0069 0070 QAbstractItemModel* Binding::model() const 0071 { 0072 return d->model; 0073 } 0074 0075 const Calligra::Sheets::Region& Binding::region() const 0076 { 0077 return d->model->region(); 0078 } 0079 0080 void Binding::setRegion(const Region& region) 0081 { 0082 d->model->setRegion(region); 0083 } 0084 0085 void Binding::update(const Region& region) 0086 { 0087 QRect rect; 0088 Region changedRegion; 0089 const QPoint offset = d->model->region().firstRange().topLeft(); 0090 const QRect range = d->model->region().firstRange(); 0091 const Sheet* sheet = d->model->region().firstSheet(); 0092 Region::ConstIterator end(region.constEnd()); 0093 for (Region::ConstIterator it = region.constBegin(); it != end; ++it) { 0094 if (sheet != (*it)->sheet()) 0095 continue; 0096 rect = range & (*it)->rect(); 0097 rect.translate(-offset.x(), -offset.y()); 0098 if (rect.isValid()) { 0099 d->model->emitDataChanged(rect); 0100 changedRegion.add(rect, (*it)->sheet()); 0101 } 0102 } 0103 d->model->emitChanged(changedRegion); 0104 } 0105 0106 void Binding::operator=(const Binding & other) 0107 { 0108 d = other.d; 0109 } 0110 0111 bool Binding::operator==(const Binding& other) const 0112 { 0113 return d == other.d; 0114 } 0115 0116 bool Binding::operator<(const Binding& other) const 0117 { 0118 return d < other.d; 0119 } 0120 0121 QHash<QString, QVector<QRect> > BindingModel::cellRegion() const 0122 { 0123 QHash<QString, QVector<QRect> > answer; 0124 Region::ConstIterator end = m_region.constEnd(); 0125 for (Region::ConstIterator it = m_region.constBegin(); it != end; ++it) { 0126 if (!(*it)->isValid()) { 0127 continue; 0128 } 0129 answer[(*it)->name()].append((*it)->rect()); 0130 } 0131 return answer; 0132 } 0133 0134 bool BindingModel::setCellRegion(const QString& regionName) 0135 { 0136 Q_ASSERT(m_region.isValid()); 0137 Q_ASSERT(m_region.firstSheet()); 0138 const Map* const map = m_region.firstSheet()->map(); 0139 const Region region = Region(regionName, map); 0140 if (!region.isValid()) { 0141 debugSheets << qPrintable(regionName) << "is not a valid region."; 0142 return false; 0143 } 0144 // Clear the old binding. 0145 Region::ConstIterator end = m_region.constEnd(); 0146 for (Region::ConstIterator it = m_region.constBegin(); it != end; ++it) { 0147 if (!(*it)->isValid()) { 0148 continue; 0149 } 0150 // FIXME Stefan: This may also clear other bindings! 0151 (*it)->sheet()->cellStorage()->setBinding(Region((*it)->rect(), (*it)->sheet()), Binding()); 0152 } 0153 // Set the new region 0154 m_region = region; 0155 end = m_region.constEnd(); 0156 for (Region::ConstIterator it = m_region.constBegin(); it != end; ++it) { 0157 if (!(*it)->isValid()) { 0158 continue; 0159 } 0160 (*it)->sheet()->cellStorage()->setBinding(Region((*it)->rect(), (*it)->sheet()), *m_binding); 0161 } 0162 return true; 0163 } 0164 0165 0166 /////// BindingModel 0167 0168 BindingModel::BindingModel(Binding* binding, QObject *parent) 0169 : QAbstractTableModel(parent) 0170 , m_binding(binding) 0171 { 0172 } 0173 0174 bool BindingModel::isCellRegionValid(const QString& regionName) const 0175 { 0176 Q_CHECK_PTR(m_region.firstSheet()); 0177 Q_CHECK_PTR(m_region.firstSheet()->map()); 0178 return Region(regionName, m_region.firstSheet()->map()).isValid(); 0179 } 0180 0181 void BindingModel::emitChanged(const Region& region) 0182 { 0183 emit changed(region); 0184 } 0185 0186 void BindingModel::emitDataChanged(const QRect& rect) 0187 { 0188 const QPoint tl = rect.topLeft(); 0189 const QPoint br = rect.bottomRight(); 0190 //debugSheetsUI << "emit QAbstractItemModel::dataChanged" << QString("%1:%2").arg(tl).arg(br); 0191 emit dataChanged(index(tl.y(), tl.x()), index(br.y(), br.x())); 0192 } 0193 0194 QVariant BindingModel::data(const QModelIndex& index, int role) const 0195 { 0196 if ((m_region.isEmpty()) || (role != Qt::EditRole && role != Qt::DisplayRole)) 0197 return QVariant(); 0198 const QPoint offset = m_region.firstRange().topLeft(); 0199 const Sheet* sheet = m_region.firstSheet(); 0200 int row = offset.y() + index.row(); 0201 int column = offset.x() + index.column(); 0202 Value value = sheet->cellStorage()->value(column, row); 0203 0204 switch (role) { 0205 case Qt::DisplayRole: { 0206 // return the in the cell displayed test 0207 Cell c(sheet, column, row); 0208 bool showFormula = false; 0209 return c.displayText(Style(), &value, &showFormula); 0210 } 0211 case Qt::EditRole: { 0212 // return the actual cell value 0213 // KoChart::Value is either: 0214 // - a double (interpreted as a value) 0215 // - a QString (interpreted as a label) 0216 // - a QDateTime (interpreted as a date/time value) 0217 // - Invalid (interpreted as empty) 0218 QVariant variant; 0219 switch (value.type()) { 0220 case Value::Float: 0221 case Value::Integer: 0222 if (value.format() == Value::fmt_DateTime || 0223 value.format() == Value::fmt_Date || 0224 value.format() == Value::fmt_Time) { 0225 variant.setValue<QDateTime>(value.asDateTime(sheet->map()->calculationSettings())); 0226 break; 0227 } // fall through 0228 case Value::Boolean: 0229 case Value::Complex: 0230 case Value::Array: 0231 variant.setValue<double>(numToDouble(value.asFloat())); 0232 break; 0233 case Value::String: 0234 case Value::Error: 0235 variant.setValue<QString>(value.asString()); 0236 break; 0237 case Value::Empty: 0238 case Value::CellRange: 0239 default: 0240 break; 0241 } 0242 return variant; 0243 } 0244 } 0245 //debugSheets << index.column() <<"," << index.row() <<"," << variant; 0246 return QVariant(); 0247 } 0248 0249 const Calligra::Sheets::Region& BindingModel::region() const 0250 { 0251 return m_region; 0252 } 0253 0254 QVariant BindingModel::headerData(int section, Qt::Orientation orientation, int role) const 0255 { 0256 if ((m_region.isEmpty()) || (role != Qt::EditRole && role != Qt::DisplayRole)) 0257 return QVariant(); 0258 const QPoint offset = m_region.firstRange().topLeft(); 0259 const int col = (orientation == Qt::Vertical) ? offset.x() : offset.x() + section; 0260 const int row = (orientation == Qt::Vertical) ? offset.y() + section : offset.y(); 0261 const Sheet* sheet = m_region.firstSheet(); 0262 const Value value = sheet->cellStorage()->value(col, row); 0263 return value.asVariant(); 0264 } 0265 0266 int BindingModel::rowCount(const QModelIndex& parent) const 0267 { 0268 Q_UNUSED(parent); 0269 return m_region.isEmpty() ? 0 : m_region.firstRange().height(); 0270 } 0271 0272 int BindingModel::columnCount(const QModelIndex& parent) const 0273 { 0274 Q_UNUSED(parent); 0275 return m_region.isEmpty() ? 0 : m_region.firstRange().width(); 0276 } 0277 0278 void BindingModel::setRegion(const Region& region) 0279 { 0280 m_region = region; 0281 }