File indexing completed on 2024-05-12 16:36:08
0001 /* This file is part of the KDE project 0002 Copyright 1999-2006 The KSpread Team <calligra-devel@kde.org> 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 "LocationComboBox.h" 0021 0022 // Sheets 0023 #include "CellStorage.h" 0024 #include "Map.h" 0025 #include "NamedAreaManager.h" 0026 #include "Selection.h" 0027 #include "Sheet.h" 0028 #include "SheetsDebug.h" 0029 0030 #include "commands/NamedAreaCommand.h" 0031 0032 // Qt 0033 #include <QKeyEvent> 0034 #include <QLineEdit> 0035 0036 using namespace Calligra::Sheets; 0037 0038 LocationComboBox::LocationComboBox(QWidget *_parent) 0039 : KComboBox(true, _parent) 0040 , m_selection(0) 0041 { 0042 setCompletionObject(&completionList, true); 0043 setCompletionMode(KCompletion::CompletionAuto); 0044 0045 connect(this, SIGNAL(activated(QString)), 0046 this, SLOT(slotActivateItem())); 0047 } 0048 0049 void LocationComboBox::setSelection(Selection *selection) 0050 { 0051 if (m_selection == selection) return; 0052 0053 completionList.clear(); 0054 clear(); 0055 if (m_selection) { 0056 if (m_selection->activeSheet()) { 0057 Map *const oldMap = m_selection->activeSheet()->map(); 0058 disconnect(oldMap->namedAreaManager(), SIGNAL(namedAreaAdded(QString)), this, SLOT(slotAddAreaName(QString))); 0059 disconnect(oldMap->namedAreaManager(), SIGNAL(namedAreaRemoved(QString)), this, SLOT(slotRemoveAreaName(QString))); 0060 } 0061 disconnect(m_selection, SIGNAL(activeSheetChanged(Sheet*)), this, SLOT(slotActiveSheetChanged(Sheet*))); 0062 disconnect(m_selection, SIGNAL(changed(Region)), this, SLOT(slotSelectionChanged())); 0063 } 0064 0065 m_selection = selection; 0066 0067 if (m_selection) { 0068 insertItem(0, QString()); 0069 updateAddress(); 0070 Sheet* sheet = m_selection->activeSheet(); 0071 if (sheet) { 0072 slotActiveSheetChanged(sheet); 0073 } else { 0074 connect(m_selection, SIGNAL(activeSheetChanged(Sheet*)), this, SLOT(slotActiveSheetChanged(Sheet*))); 0075 } 0076 connect(m_selection, SIGNAL(changed(Region)), this, SLOT(slotSelectionChanged())); 0077 } 0078 } 0079 0080 void LocationComboBox::slotActiveSheetChanged(Sheet *sheet) 0081 { 0082 if (!sheet) return; 0083 disconnect(this, SLOT(slotActiveSheetChanged(Sheet*))); 0084 0085 Map *const map = sheet->map(); 0086 const QList<QString> areaNames = map->namedAreaManager()->areaNames(); 0087 for (int i = 0; i < areaNames.count(); ++i) 0088 slotAddAreaName(areaNames[i]); 0089 0090 connect(map->namedAreaManager(), SIGNAL(namedAreaAdded(QString)), this, SLOT(slotAddAreaName(QString))); 0091 connect(map->namedAreaManager(), SIGNAL(namedAreaRemoved(QString)), this, SLOT(slotRemoveAreaName(QString))); 0092 } 0093 0094 void LocationComboBox::updateAddress() 0095 { 0096 if (!m_selection) return; 0097 0098 QString address; 0099 Selection *const selection = m_selection; 0100 Sheet *const sheet = m_selection->activeSheet(); 0101 if (sheet) { 0102 const QList< QPair<QRectF, QString> > names = sheet->cellStorage()->namedAreas(*selection); 0103 { 0104 QRect range; 0105 if (selection->isSingular()) range = QRect(selection->marker(), QSize(1, 1)); 0106 else range = selection->lastRange(); 0107 for (int i = 0; i < names.size(); i++) { 0108 if (names[i].first.toRect() == range) { 0109 address = names[i].second; 0110 } 0111 } 0112 } 0113 } 0114 if (sheet && sheet->getLcMode()) { 0115 if (selection->isSingular()) { 0116 address = 'L' + QString::number(selection->marker().y()) + 0117 'C' + QString::number(selection->marker().x()); 0118 } else { 0119 const QRect lastRange = selection->lastRange(); 0120 address = QString::number(lastRange.height()) + "Lx"; 0121 address += QString::number(lastRange.width()) + 'C'; 0122 } 0123 } else { 0124 address = selection->name(); 0125 } 0126 setItemText(0, address); 0127 setCurrentItem(0); 0128 lineEdit()->setText(address); 0129 } 0130 0131 void LocationComboBox::slotAddAreaName(const QString &_name) 0132 { 0133 insertItem(count(), _name); 0134 addCompletionItem(_name); 0135 } 0136 0137 void LocationComboBox::slotRemoveAreaName(const QString &_name) 0138 { 0139 for (int i = 0; i < count(); i++) { 0140 if (itemText(i) == _name) { 0141 removeItem(i); 0142 break; 0143 } 0144 } 0145 removeCompletionItem(_name); 0146 } 0147 0148 void LocationComboBox::addCompletionItem(const QString &_item) 0149 { 0150 if (completionList.items().contains(_item) == 0) { 0151 completionList.addItem(_item); 0152 debugSheetsUI << _item; 0153 } 0154 } 0155 0156 void LocationComboBox::removeCompletionItem(const QString &_item) 0157 { 0158 completionList.removeItem(_item); 0159 } 0160 0161 void LocationComboBox::slotActivateItem() 0162 { 0163 if (!m_selection) return; 0164 0165 if (activateItem()) { 0166 m_selection->scrollToCursor(); 0167 } 0168 } 0169 0170 bool LocationComboBox::activateItem() 0171 { 0172 if (!m_selection) return false; 0173 0174 Selection *const selection = m_selection; 0175 0176 // Set the focus back on the canvas. 0177 parentWidget()->setFocus(); 0178 0179 const QString text = lineEdit()->text(); 0180 // check whether an already existing named area was entered 0181 Region region = selection->activeSheet()->map()->namedAreaManager()->namedArea(text); 0182 if (region.isValid()) { 0183 // TODO Stefan: Merge the sheet change into Selection. 0184 if (region.firstSheet() != selection->activeSheet()) { 0185 selection->emitVisibleSheetRequested(region.firstSheet()); 0186 } 0187 selection->initialize(region); 0188 return true; 0189 } 0190 0191 // check whether a valid cell region was entered 0192 region = Region(text, selection->activeSheet()->map(), selection->activeSheet()); 0193 if (region.isValid()) { 0194 // TODO Stefan: Merge the sheet change into Selection. 0195 if (region.firstSheet() != selection->activeSheet()) { 0196 selection->emitVisibleSheetRequested(region.firstSheet()); 0197 } 0198 selection->initialize(region); 0199 return true; 0200 } 0201 0202 // A name for an area entered? 0203 // FIXME Stefan: allow all characters 0204 bool validName = true; 0205 for (int i = 0; i < text.length(); ++i) { 0206 if (!text[i].isLetter()) { 0207 validName = false; 0208 break; 0209 } 0210 } 0211 if (validName) { 0212 NamedAreaCommand* command = new NamedAreaCommand(); 0213 command->setSheet(selection->activeSheet()); 0214 command->setAreaName(text); 0215 command->add(Region(selection->lastRange(), selection->activeSheet())); 0216 if (command->execute()) 0217 return true; 0218 else 0219 delete command; 0220 } 0221 return false; 0222 } 0223 0224 0225 void LocationComboBox::keyPressEvent(QKeyEvent * _ev) 0226 { 0227 if (!m_selection) return; 0228 0229 Selection *const selection = m_selection; 0230 0231 // Do not handle special keys and accelerators. This is 0232 // done by KComboBox. 0233 if (_ev->modifiers() & (Qt::AltModifier | Qt::ControlModifier)) { 0234 KComboBox::keyPressEvent(_ev); 0235 // Never allow that keys are passed on to the parent. 0236 _ev->accept(); // QKeyEvent 0237 0238 return; 0239 } 0240 0241 // Handle some special keys here. Eve 0242 switch (_ev->key()) { 0243 case Qt::Key_Return: 0244 case Qt::Key_Enter: { 0245 if (activateItem()) { 0246 selection->scrollToCursor(); 0247 return; 0248 } 0249 _ev->accept(); // QKeyEvent 0250 } 0251 break; 0252 // Escape pressed, restore original value 0253 case Qt::Key_Escape: 0254 updateAddress(); 0255 parentWidget()->setFocus(); 0256 _ev->accept(); // QKeyEvent 0257 break; 0258 default: 0259 KComboBox::keyPressEvent(_ev); 0260 // Never allow that keys are passed on to the parent. 0261 _ev->accept(); // QKeyEvent 0262 } 0263 } 0264 0265 void LocationComboBox::slotSelectionChanged() 0266 { 0267 if (!m_selection->referenceSelectionMode()) { 0268 updateAddress(); 0269 } 0270 }