File indexing completed on 2024-04-28 16:21:24

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 "MapModel.h"
0021 
0022 #include "Map.h"
0023 #include "ModelSupport.h"
0024 #include "Sheet.h"
0025 #include "SheetModel.h"
0026 
0027 #include "commands/SheetCommands.h"
0028 
0029 #include <KoIcon.h>
0030 
0031 using namespace Calligra::Sheets;
0032 
0033 class MapModel::Private
0034 {
0035 public:
0036     Map* map;
0037 
0038 public:
0039     bool isSheetIndex(const QModelIndex& index, const MapModel* mapModel) const;
0040 };
0041 
0042 bool MapModel::Private::isSheetIndex(const QModelIndex& index, const MapModel* mapModel) const
0043 {
0044     if (!index.parent().isValid()) {
0045         return false;
0046     }
0047     // If it is a cell, the parent's (the sheet's) model has to be this model.
0048     if (index.parent().model() != mapModel || index.parent().internalPointer() != map) {
0049         return false;
0050     }
0051     // If it is a cell, the parent (the sheet) has no parent.
0052     if (index.parent().parent().isValid()) {
0053         return false;
0054     }
0055     // Do not exceed the sheet list.
0056     if (index.parent().row() >= map->count()) {
0057         return false;
0058     }
0059     // The index' (the cell's) model has to match the sheet model.
0060     if (index.model() != map->sheet(index.parent().row())->model()) {
0061         return false;
0062     }
0063     return true;
0064 }
0065 
0066 
0067 MapModel::MapModel(Map* map)
0068         : QAbstractListModel(map)
0069         , d(new Private)
0070 {
0071     d->map = map;
0072     connect(d->map, SIGNAL(sheetAdded(Sheet*)),
0073             this, SLOT(addSheet(Sheet*)));
0074     connect(d->map, SIGNAL(sheetRemoved(Sheet*)),
0075             this, SLOT(removeSheet(Sheet*)));
0076 }
0077 
0078 MapModel::~MapModel()
0079 {
0080     delete d;
0081 }
0082 
0083 QVariant MapModel::data(const QModelIndex &index, int role) const
0084 {
0085     if (!index.isValid()) {
0086         return QVariant();
0087     }
0088     // Propagation to sheet model
0089     if (d->isSheetIndex(index, this)) {
0090         return d->map->sheet(index.parent().row())->model()->data(index, role);
0091     }
0092     if (index.row() >= d->map->count()) {
0093         return QVariant();
0094     }
0095     //
0096     const Sheet* const sheet = d->map->sheet(index.row());
0097     switch (role) {
0098     case Qt::DisplayRole:
0099     case Qt::EditRole:
0100         return QVariant(sheet->sheetName());
0101     case Qt::DecorationRole:
0102         return QVariant(koIcon("x-office-spreadsheet"));
0103     case VisibilityRole:
0104         return QVariant(!sheet->isHidden());
0105     case ProtectionRole:
0106         return QVariant(sheet->isProtected());
0107     default:
0108         break;
0109     }
0110     return QVariant();
0111 }
0112 
0113 Qt::ItemFlags MapModel::flags(const QModelIndex &index) const
0114 {
0115     if (!index.isValid()) {
0116         return Qt::NoItemFlags;
0117     }
0118     // Propagation to sheet model
0119     if (d->isSheetIndex(index, this)) {
0120         return d->map->sheet(index.parent().row())->model()->flags(index);
0121     }
0122     if (index.row() >= d->map->count()) {
0123         return Qt::NoItemFlags;
0124     }
0125 
0126     Qt::ItemFlags flags = Qt::ItemIsEnabled;
0127     if (!d->map->isProtected()) {
0128         flags |= Qt::ItemIsSelectable;
0129         const Sheet* const sheet = d->map->sheet(index.row());
0130         if (!sheet->isProtected()) {
0131             flags |= Qt::ItemIsEditable;
0132         }
0133     }
0134     return flags;
0135 }
0136 
0137 QVariant MapModel::headerData(int section, Qt::Orientation orientation, int role) const
0138 {
0139     Q_UNUSED(orientation)
0140     if (section == 0 && role == Qt::DisplayRole) {
0141         return QVariant(i18n("Sheet name"));
0142     }
0143     return QVariant();
0144 }
0145 
0146 QModelIndex MapModel::index(int row, int column, const QModelIndex &parent) const
0147 {
0148     QModelIndex index;
0149     if (parent.isValid()) {
0150         // If it is a cell, the parent's (the sheet's) model has to be this model.
0151         if (parent.model() != this || parent.internalPointer() != d->map) {
0152             return QModelIndex();
0153         }
0154         // If it is a cell, the parent (the sheet) has no parent.
0155         if (parent.parent().isValid()) {
0156             return QModelIndex();
0157         }
0158         // Do not exceed the sheet list.
0159         if (parent.row() >= d->map->count()) {
0160             return QModelIndex();
0161         }
0162         Sheet* const sheet = d->map->sheet(index.parent().row());
0163         index = sheet->model()->index(row, column, parent);
0164     } else {
0165         index = createIndex(row, column, d->map);
0166     }
0167     return index;
0168 }
0169 
0170 int MapModel::rowCount(const QModelIndex &parent) const
0171 {
0172     if (parent.isValid()) {
0173         return 0;
0174     }
0175     return d->map->count();
0176 }
0177 
0178 bool MapModel::setData(const QModelIndex &index, const QVariant &value, int role)
0179 {
0180     // Propagation to sheet model
0181     if (d->isSheetIndex(index, this)) {
0182         return d->map->sheet(index.parent().row())->model()->setData(index, value, role);
0183     }
0184 
0185     if (index.isValid() && index.row() < d->map->count()) {
0186         Sheet* const sheet(d->map->sheet(index.row()));
0187         switch (role) {
0188         case Qt::EditRole: {
0189             const QString name(value.toString());
0190             if (!name.isEmpty()) {
0191                 KUndo2Command* const command = new RenameSheetCommand(sheet, name);
0192                 emit addCommandRequested(command);
0193                 emit dataChanged(index, index);
0194                 return true;
0195             }
0196             break;
0197         }
0198         case VisibilityRole:
0199             setHidden(sheet, value.toBool());
0200             break;
0201         case ProtectionRole:
0202             break;
0203         default:
0204             break;
0205         }
0206     }
0207     return false;
0208 }
0209 
0210 bool MapModel::setHidden(Sheet* sheet, bool hidden)
0211 {
0212     KUndo2Command* command;
0213     if (hidden && !sheet->isHidden()) {
0214         command = new HideSheetCommand(sheet);
0215     } else if (!hidden && sheet->isHidden()) {
0216         command = new ShowSheetCommand(sheet);
0217     } else {
0218         return false; // nothing to do
0219     }
0220     emit addCommandRequested(command);
0221     return true;
0222 }
0223 
0224 Map* MapModel::map() const
0225 {
0226     return d->map;
0227 }
0228 
0229 void MapModel::addSheet(Sheet* sheet)
0230 {
0231     debugSheets << "Added sheet:" << sheet->sheetName();
0232     emit layoutChanged();
0233 }
0234 
0235 void MapModel::removeSheet(Sheet *sheet)
0236 {
0237     debugSheets << "Removed sheet:" << sheet->sheetName();
0238     emit layoutChanged();
0239 }