File indexing completed on 2024-05-12 16:36:09
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 "MapViewModel.h" 0021 0022 #include "Map.h" 0023 #include "ModelSupport.h" 0024 #include "Sheet.h" 0025 0026 #include "commands/SheetCommands.h" 0027 0028 #include "interfaces/ReadWriteTableModel.h" 0029 0030 #include <KoCanvasBase.h> 0031 #include <KoShapeManager.h> 0032 #include <KoIcon.h> 0033 0034 #include <kxmlguiclient.h> 0035 0036 using namespace Calligra::Sheets; 0037 0038 class MapViewModel::Private 0039 { 0040 public: 0041 Sheet* activeSheet; 0042 KoCanvasBase *canvas; 0043 KXMLGUIClient *xmlGuiClient; 0044 QActionGroup *gotoSheetActionGroup; 0045 }; 0046 0047 0048 MapViewModel::MapViewModel(Map *map, KoCanvasBase *canvas, KXMLGUIClient *xmlGuiClient) 0049 : MapModel(map) 0050 , d(new Private) 0051 { 0052 d->activeSheet = 0; 0053 d->canvas = canvas; 0054 d->xmlGuiClient = xmlGuiClient; 0055 d->gotoSheetActionGroup = new QActionGroup(this); 0056 0057 connect(d->gotoSheetActionGroup, SIGNAL(triggered(QAction*)), 0058 this, SLOT(gotoSheetActionTriggered(QAction*))); 0059 0060 // Add the initial controlled sheets. 0061 const QList<Sheet *> sheets = map->sheetList(); 0062 for (int i = 0; i < sheets.count(); ++i) { 0063 addSheet(sheets[i]); 0064 } 0065 } 0066 0067 MapViewModel::~MapViewModel() 0068 { 0069 delete d; 0070 } 0071 0072 QVariant MapViewModel::data(const QModelIndex &index, int role) const 0073 { 0074 // We handle only this role; the remaining ones go to the MapModel. 0075 if (role != ActivityRole && role != Qt::CheckStateRole) { 0076 return MapModel::data(index, role); 0077 } 0078 if (!index.isValid()) { 0079 return QVariant(); 0080 } 0081 if (index.parent().isValid()) { 0082 return MapModel::data(index, role); 0083 } 0084 if (index.row() >= map()->count()) { 0085 return QVariant(); 0086 } 0087 const Sheet* const sheet = map()->sheet(index.row()); 0088 return QVariant(sheet == d->activeSheet); 0089 } 0090 0091 Qt::ItemFlags MapViewModel::flags(const QModelIndex &index) const 0092 { 0093 if (!index.isValid()) { 0094 return Qt::NoItemFlags; 0095 } 0096 // Propagation to sheet model 0097 if (index.parent().isValid()) { 0098 return MapModel::flags(index); // The MapModel takes care of cell indices. 0099 } 0100 if (index.row() >= map()->count()) { 0101 return Qt::NoItemFlags; 0102 } 0103 return MapModel::flags(index) | Qt::ItemIsUserCheckable; 0104 } 0105 0106 bool MapViewModel::setData(const QModelIndex &index, const QVariant &value, int role) 0107 { 0108 // We handle only this role; the remaining ones go to the MapModel. 0109 if (role != ActivityRole && role != Qt::CheckStateRole) { 0110 return MapModel::setData(index, value, role); 0111 } 0112 if (!index.isValid()) { 0113 return false; 0114 } 0115 if (index.parent().isValid()) { 0116 return MapModel::setData(index, value, role); 0117 } 0118 if (index.row() >= map()->count()) { 0119 return false; 0120 } 0121 Sheet* const sheet(map()->sheet(index.row())); 0122 setActiveSheet(sheet); 0123 return true; 0124 } 0125 0126 Sheet* MapViewModel::activeSheet() const 0127 { 0128 return d->activeSheet; 0129 } 0130 0131 void MapViewModel::setActiveSheet(Sheet* sheet) 0132 { 0133 if (d->activeSheet == sheet) { 0134 return; 0135 } 0136 const QList<Sheet*> list = map()->sheetList(); 0137 const int oldRow = list.indexOf(d->activeSheet); 0138 const int newRow = list.indexOf(sheet); 0139 0140 // The sheet may be set to 0 for one exceptional case. 0141 d->activeSheet = sheet; 0142 0143 if (!sheet) { 0144 return; 0145 } 0146 0147 // Unhide, if necessary. 0148 if (sheet->isHidden()) { 0149 KUndo2Command* command = new ShowSheetCommand(sheet); 0150 d->canvas->addCommand(command); 0151 } 0152 0153 // Check the appropriate action of the goto sheet action group. 0154 const QList<QAction *> actions = d->gotoSheetActionGroup->actions(); 0155 for (int i = 0; i < actions.count(); ++i) { 0156 if (actions[i]->iconText() == sheet->sheetName()) { 0157 actions[i]->setChecked(true); 0158 break; 0159 } 0160 } 0161 0162 // Both sheets have to be in the list. If not, there won't be any signals. 0163 if (oldRow == -1 || newRow == -1) { 0164 return; 0165 } 0166 const QModelIndex oldIndex(index(oldRow, 0)); 0167 const QModelIndex newIndex(index(newRow, 0)); 0168 emit dataChanged(oldIndex, oldIndex); 0169 emit dataChanged(newIndex, newIndex); 0170 emit activeSheetChanged(sheet); 0171 } 0172 0173 void MapViewModel::addSheet(Sheet *sheet) 0174 { 0175 MapModel::addSheet(sheet); 0176 0177 connect(sheet, SIGNAL(shapeAdded(Sheet*,KoShape*)), 0178 this, SLOT(addShape(Sheet*,KoShape*))); 0179 connect(sheet, SIGNAL(shapeRemoved(Sheet*,KoShape*)), 0180 this, SLOT(removeShape(Sheet*,KoShape*))); 0181 0182 if (!d->xmlGuiClient) { 0183 return; 0184 } 0185 0186 // Update the goto sheet action group 0187 const QString name = sheet->sheetName(); 0188 QAction *action = new QAction(koIcon("x-office-spreadsheet"), name, this); 0189 action->setCheckable(true); 0190 action->setToolTip(i18nc("Activate sheet named foo", "Activate %1", name)); 0191 0192 d->gotoSheetActionGroup->addAction(action); 0193 0194 const QList<QAction *> actions = d->gotoSheetActionGroup->actions(); 0195 d->xmlGuiClient->unplugActionList("go_goto_sheet_actionlist"); 0196 d->xmlGuiClient->plugActionList("go_goto_sheet_actionlist", actions); 0197 } 0198 0199 void MapViewModel::removeSheet(Sheet *sheet) 0200 { 0201 MapModel::removeSheet(sheet); 0202 0203 disconnect(sheet, SIGNAL(shapeAdded(Sheet*,KoShape*)), 0204 this, SLOT(addShape(Sheet*,KoShape*))); 0205 disconnect(sheet, SIGNAL(shapeRemoved(Sheet*,KoShape*)), 0206 this, SLOT(removeShape(Sheet*,KoShape*))); 0207 0208 if (!d->xmlGuiClient) { 0209 return; 0210 } 0211 0212 // Update the goto sheet action group 0213 QAction *action = 0; 0214 const QList<QAction *> actions = d->gotoSheetActionGroup->actions(); 0215 for (int i = 0; i < actions.count(); ++i) { 0216 if (actions[i]->text() == sheet->sheetName()) { 0217 action = actions[i]; 0218 break; 0219 } 0220 } 0221 if (action) { 0222 d->gotoSheetActionGroup->removeAction(action); 0223 const QList<QAction *> actions = d->gotoSheetActionGroup->actions(); 0224 d->xmlGuiClient->unplugActionList("go_goto_sheet_actionlist"); 0225 d->xmlGuiClient->plugActionList("go_goto_sheet_actionlist", actions); 0226 } 0227 } 0228 0229 void MapViewModel::addShape(Sheet *sheet, KoShape *shape) 0230 { 0231 if (sheet == d->activeSheet) { 0232 d->canvas->shapeManager()->addShape(shape); 0233 } 0234 } 0235 0236 void MapViewModel::removeShape(Sheet *sheet, KoShape *shape) 0237 { 0238 if (sheet == d->activeSheet) { 0239 d->canvas->shapeManager()->remove(shape); 0240 } 0241 } 0242 0243 void MapViewModel::gotoSheetActionTriggered(QAction *action) 0244 { 0245 const QList<QAction *> actions = d->gotoSheetActionGroup->actions(); 0246 for (int i = 0; i < actions.count(); ++i) { 0247 if (actions[i]->text() == action->text()) { 0248 Sheet *const sheet = map()->findSheet(action->iconText()); 0249 if (sheet) { 0250 setActiveSheet(sheet); 0251 } else { // should not happen 0252 d->gotoSheetActionGroup->removeAction(action); 0253 } 0254 break; 0255 } 0256 } 0257 }