File indexing completed on 2024-05-12 16:36:05
0001 /* This file is part of the KDE project 0002 Copyright 2006-2008 Stefan Nikolaus <stefan.nikolaus@kdemail.net> 0003 Copyright 2005-2006 Raphael Langerhorst <raphael.langerhorst@kdemail.net> 0004 Copyright 2002-2005 Ariya Hidayat <ariya@kde.org> 0005 Copyright 1999-2003 Laurent Montel <montel@kde.org> 0006 Copyright 2002-2003 Norbert Andres <nandres@web.de> 0007 Copyright 2002-2003 Philipp Mueller <philipp.mueller@gmx.de> 0008 Copyright 2002-2003 John Dailey <dailey@vt.edu> 0009 Copyright 1999-2003 David Faure <faure@kde.org> 0010 Copyright 1999-2001 Simon Hausmann <hausmann@kde.org> 0011 Copyright 1998-2000 Torben Weis <weis@kde.org> 0012 0013 This library is free software; you can redistribute it and/or 0014 modify it under the terms of the GNU Library General Public 0015 License as published by the Free Software Foundation; either 0016 version 2 of the License, or(at your option) any later version. 0017 0018 This library is distributed in the hope that it will be useful, 0019 but WITHOUT ANY WARRANTY; without even the implied warranty of 0020 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0021 Library General Public License for more details. 0022 0023 You should have received a copy of the GNU Library General Public License 0024 along with this library; see the file COPYING.LIB. If not, write to 0025 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0026 Boston, MA 02110-1301, USA. 0027 */ 0028 0029 #include "CellToolBase.h" 0030 #include "CellToolBase_p.h" 0031 0032 // Sheets 0033 #include "ActionOptionWidget.h" 0034 #include "ApplicationSettings.h" 0035 #include "AutoFillStrategy.h" 0036 #include "CalculationSettings.h" 0037 #include "Cell.h" 0038 #include "CellEditor.h" 0039 #include "CellView.h" 0040 #include "Damages.h" 0041 #include "database/Database.h" 0042 #include "database/FilterPopup.h" 0043 #include "DragAndDropStrategy.h" 0044 #include "ExternalEditor.h" 0045 #include "HyperlinkStrategy.h" 0046 #include "tests/inspector.h" 0047 #include "LocationComboBox.h" 0048 #include "Map.h" 0049 #include "MergeStrategy.h" 0050 #include "NamedAreaManager.h" 0051 #include "PasteStrategy.h" 0052 #include "RowFormatStorage.h" 0053 #include "SelectionStrategy.h" 0054 #include "Sheet.h" 0055 #include "SheetView.h" 0056 #include "StyleManager.h" 0057 #include "CellStorage.h" 0058 #include "Value.h" 0059 #include "ValueConverter.h" 0060 #include "odf/SheetsOdf.h" 0061 0062 // commands 0063 #include "commands/AutoFilterCommand.h" 0064 #include "commands/BorderColorCommand.h" 0065 #include "commands/CommentCommand.h" 0066 #include "commands/ConditionCommand.h" 0067 #include "commands/CopyCommand.h" 0068 #include "commands/DataManipulators.h" 0069 #include "commands/DeleteCommand.h" 0070 #include "commands/IndentationCommand.h" 0071 #include "commands/LinkCommand.h" 0072 #include "commands/MergeCommand.h" 0073 #include "commands/PageBreakCommand.h" 0074 #include "commands/PasteCommand.h" 0075 #include "commands/PrecisionCommand.h" 0076 #include "commands/RowColumnManipulators.h" 0077 #include "commands/SortManipulator.h" 0078 #include "commands/SpellCheckCommand.h" 0079 #include "commands/StyleCommand.h" 0080 #include "commands/ValidityCommand.h" 0081 0082 // dialogs 0083 #include "dialogs/AddNamedAreaDialog.h" 0084 #include "dialogs/AngleDialog.h" 0085 #include "dialogs/AutoFormatDialog.h" 0086 #include "dialogs/CharacterSelectDialog.h" 0087 #include "dialogs/CommentDialog.h" 0088 #include "dialogs/ConditionalDialog.h" 0089 #include "dialogs/ConsolidateDialog.h" 0090 #include "dialogs/CSVDialog.h" 0091 #include "dialogs/DatabaseDialog.h" 0092 #include "dialogs/DocumentSettingsDialog.h" 0093 #include "dialogs/GoalSeekDialog.h" 0094 #include "dialogs/GotoDialog.h" 0095 #include "dialogs/InsertDialog.h" 0096 #include "dialogs/LayoutDialog.h" 0097 #include "dialogs/LinkDialog.h" 0098 #include "dialogs/ListDialog.h" 0099 #include "dialogs/NamedAreaDialog.h" 0100 #include "dialogs/PasteInsertDialog.h" 0101 #include "dialogs/Resize2Dialog.h" 0102 #include "dialogs/SeriesDialog.h" 0103 #include "dialogs/ShowColRowDialog.h" 0104 #include "dialogs/SortDialog.h" 0105 #include "dialogs/SpecialPasteDialog.h" 0106 #include "dialogs/StyleManagerDialog.h" 0107 #include "dialogs/SubtotalDialog.h" 0108 #include "dialogs/ValidityDialog.h" 0109 #include "dialogs/pivot.h" 0110 0111 // Calligra 0112 #include <KoCanvasBase.h> 0113 #include <KoCanvasController.h> 0114 #include <KoColorPopupAction.h> 0115 #include <KoPointerEvent.h> 0116 #include <KoSelection.h> 0117 #include <KoShape.h> 0118 #include <KoViewConverter.h> 0119 #include <KoColor.h> 0120 #include <KoIcon.h> 0121 0122 // KF5 0123 #include <kfind.h> 0124 #include <kfontaction.h> 0125 #include <kfontsizeaction.h> 0126 #include <klocale.h> 0127 #include <kmessagebox.h> 0128 #include <kreplace.h> 0129 #include <kstandardaction.h> 0130 #include <ktoggleaction.h> 0131 0132 // Qt 0133 #include <QStandardPaths> 0134 #include <QInputDialog> 0135 #include <QBuffer> 0136 #include <QHash> 0137 #include <QMenu> 0138 #include <QPainter> 0139 #ifndef QT_NO_SQL 0140 #include <QSqlDatabase> 0141 #endif 0142 0143 #ifndef NDEBUG 0144 #include <QTableView> 0145 #include "SheetModel.h" 0146 #endif 0147 0148 using namespace Calligra::Sheets; 0149 0150 CellToolBase::CellToolBase(KoCanvasBase* canvas) 0151 : KoInteractionTool(canvas) 0152 , d(new Private(this)) 0153 { 0154 d->cellEditor = 0; 0155 d->externalEditor = 0; 0156 d->formulaDialog = 0; 0157 d->specialCharDialog = 0; 0158 d->initialized = false; 0159 d->popupListChoose = 0; 0160 d->lastEditorWithFocus = EmbeddedEditor; 0161 0162 d->findOptions = 0; 0163 d->findLeftColumn = 0; 0164 d->findRightColumn = 0; 0165 d->findTopRow = 0; 0166 d->findBottomRow = 0; 0167 d->typeValue = FindOption::Value; 0168 d->directionValue = FindOption::Row; 0169 d->find = 0; 0170 d->replace = 0; 0171 d->replaceCommand = 0; 0172 0173 d->searchInSheets.currentSheet = 0; 0174 d->searchInSheets.firstSheet = 0; 0175 0176 // Create the extra and ones with extended names for the context menu. 0177 d->createPopupMenuActions(); 0178 0179 // Create the actions. 0180 QAction* action = 0; 0181 0182 // -- cell style actions -- 0183 0184 action = new QAction(koIcon("cell_layout"), i18n("Cell Format..."), this); 0185 action->setIconText(i18n("Format")); 0186 addAction("cellStyle", action); 0187 action->setShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_F)); 0188 connect(action, SIGNAL(triggered(bool)), this, SLOT(cellStyle())); 0189 action->setToolTip(i18n("Set the cell formatting")); 0190 0191 action = new QAction(i18n("Default"), this); 0192 addAction("setDefaultStyle", action); 0193 connect(action, SIGNAL(triggered(bool)), this, SLOT(setDefaultStyle())); 0194 action->setToolTip(i18n("Resets to the default format")); 0195 0196 action = new QAction(i18n("Style Manager..."), this); 0197 addAction("styleDialog", action); 0198 connect(action, SIGNAL(triggered(bool)), this, SLOT(styleDialog())); 0199 action->setToolTip(i18n("Edit and organize cell styles")); 0200 0201 action = new KSelectAction(i18n("Style"), this); 0202 addAction("setStyle", action); 0203 action->setToolTip(i18n("Apply a predefined style to the selected cells")); 0204 connect(action, SIGNAL(triggered(QString)), this, SLOT(setStyle(QString))); 0205 0206 action = new QAction(i18n("Create Style From Cell..."), this); 0207 action->setIconText(i18n("Style From Cell")); 0208 addAction("createStyleFromCell", action); 0209 connect(action, SIGNAL(triggered(bool)), this, SLOT(createStyleFromCell())); 0210 action->setToolTip(i18n("Create a new style based on the currently selected cell")); 0211 0212 // -- font actions -- 0213 0214 action = new KToggleAction(koIcon("format-text-bold"), i18n("Bold"), this); 0215 addAction("bold", action); 0216 action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B)); 0217 connect(action, SIGNAL(triggered(bool)), this, SLOT(bold(bool))); 0218 0219 action = new KToggleAction(koIcon("format-text-italic"), i18n("Italic"), this); 0220 addAction("italic", action); 0221 action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_I)); 0222 connect(action, SIGNAL(triggered(bool)), this, SLOT(italic(bool))); 0223 0224 action = new KToggleAction(koIcon("format-text-underline"), i18n("Underline"), this); 0225 addAction("underline", action); 0226 action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U)); 0227 connect(action, SIGNAL(triggered(bool)), this, SLOT(underline(bool))); 0228 0229 action = new KToggleAction(koIcon("format-text-strikethrough"), i18n("Strike Out"), this); 0230 addAction("strikeOut", action); 0231 connect(action, SIGNAL(triggered(bool)), this, SLOT(strikeOut(bool))); 0232 0233 action = new KFontAction(i18n("Select Font..."), this); 0234 action->setIconText(i18n("Font")); 0235 addAction("font", action); 0236 connect(action, SIGNAL(triggered(QString)), this, SLOT(font(QString))); 0237 0238 action = new KFontSizeAction(i18n("Select Font Size"), this); 0239 action->setIconText(i18n("Font Size")); 0240 addAction("fontSize", action); 0241 connect(action, SIGNAL(fontSizeChanged(int)), this, SLOT(fontSize(int))); 0242 0243 action = new QAction(koIcon("format-font-size-more"), i18n("Increase Font Size"), this); 0244 addAction("increaseFontSize", action); 0245 connect(action, SIGNAL(triggered(bool)), this, SLOT(increaseFontSize())); 0246 0247 action = new QAction(koIcon("format-font-size-less"), i18n("Decrease Font Size"), this); 0248 addAction("decreaseFontSize", action); 0249 connect(action, SIGNAL(triggered(bool)), this, SLOT(decreaseFontSize())); 0250 0251 action = new KoColorPopupAction(this); 0252 action->setIcon(koIcon("format-text-color")); 0253 action->setText(i18n("Text Color")); 0254 action->setToolTip(i18n("Set the text color")); 0255 addAction("textColor", action); 0256 connect(action, SIGNAL(colorChanged(KoColor)), this, SLOT(changeTextColor(KoColor))); 0257 0258 // -- horizontal alignment actions -- 0259 0260 QActionGroup* groupAlign = new QActionGroup(this); 0261 action = new KToggleAction(koIcon("format-justify-left"), i18n("Align Left"), this); 0262 action->setIconText(i18n("Left")); 0263 addAction("alignLeft", action); 0264 connect(action, SIGNAL(triggered(bool)), this, SLOT(alignLeft(bool))); 0265 action->setToolTip(i18n("Left justify the cell contents")); 0266 action->setActionGroup(groupAlign); 0267 0268 action = new KToggleAction(koIcon("format-justify-center"), i18n("Align Center"), this); 0269 action->setIconText(i18n("Center")); 0270 addAction("alignCenter", action); 0271 connect(action, SIGNAL(triggered(bool)), this, SLOT(alignCenter(bool))); 0272 action->setToolTip(i18n("Center the cell contents")); 0273 action->setActionGroup(groupAlign); 0274 0275 action = new KToggleAction(koIcon("format-justify-right"), i18n("Align Right"), this); 0276 action->setIconText(i18n("Right")); 0277 addAction("alignRight", action); 0278 connect(action, SIGNAL(triggered(bool)), this, SLOT(alignRight(bool))); 0279 action->setToolTip(i18n("Right justify the cell contents")); 0280 action->setActionGroup(groupAlign); 0281 0282 // -- vertical alignment actions -- 0283 0284 QActionGroup* groupPos = new QActionGroup(this); 0285 action = new KToggleAction(koIcon("format-align-vertical-top"), i18n("Align Top"), this); 0286 action->setIconText(i18n("Top")); 0287 addAction("alignTop", action); 0288 connect(action, SIGNAL(triggered(bool)), this, SLOT(alignTop(bool))); 0289 action->setToolTip(i18n("Align cell contents along the top of the cell")); 0290 action->setActionGroup(groupPos); 0291 0292 action = new KToggleAction(koIcon("format-align-vertical-center"), i18n("Align Middle"), this); 0293 action->setIconText(i18n("Middle")); 0294 addAction("alignMiddle", action); 0295 connect(action, SIGNAL(triggered(bool)), this, SLOT(alignMiddle(bool))); 0296 action->setToolTip(i18n("Align cell contents centered in the cell")); 0297 action->setActionGroup(groupPos); 0298 0299 action = new KToggleAction(koIcon("format-align-vertical-bottom"), i18n("Align Bottom"), this); 0300 action->setIconText(i18n("Bottom")); 0301 addAction("alignBottom", action); 0302 connect(action, SIGNAL(triggered(bool)), this, SLOT(alignBottom(bool))); 0303 action->setToolTip(i18n("Align cell contents along the bottom of the cell")); 0304 action->setActionGroup(groupPos); 0305 0306 // -- border actions -- 0307 0308 action = new QAction(koIcon("format-border-set-left"), i18n("Border Left"), this); 0309 action->setIconText(i18n("Left")); 0310 addAction("borderLeft", action); 0311 connect(action, SIGNAL(triggered(bool)), this, SLOT(borderLeft())); 0312 action->setToolTip(i18n("Set a left border to the selected area")); 0313 0314 action = new QAction(koIcon("format-border-set-right"), i18n("Border Right"), this); 0315 action->setIconText(i18n("Right")); 0316 addAction("borderRight", action); 0317 connect(action, SIGNAL(triggered(bool)), this, SLOT(borderRight())); 0318 action->setToolTip(i18n("Set a right border to the selected area")); 0319 0320 action = new QAction(koIcon("format-border-set-top"), i18n("Border Top"), this); 0321 action->setIconText(i18n("Top")); 0322 addAction("borderTop", action); 0323 connect(action, SIGNAL(triggered(bool)), this, SLOT(borderTop())); 0324 action->setToolTip(i18n("Set a top border to the selected area")); 0325 0326 action = new QAction(koIcon("format-border-set-bottom"), i18n("Border Bottom"), this); 0327 action->setIconText(i18n("Bottom")); 0328 addAction("borderBottom", action); 0329 connect(action, SIGNAL(triggered(bool)), this, SLOT(borderBottom())); 0330 action->setToolTip(i18n("Set a bottom border to the selected area")); 0331 0332 action = new QAction(koIcon("format-border-set-all"), i18n("All Borders"), this); 0333 action->setIconText(i18n("All")); 0334 addAction("borderAll", action); 0335 connect(action, SIGNAL(triggered(bool)), this, SLOT(borderAll())); 0336 action->setToolTip(i18n("Set a border around all cells in the selected area")); 0337 0338 action = new QAction(koIcon("format-border-set-none"), i18n("No Borders"), this); 0339 action->setIconText(i18n("None")); 0340 addAction("borderRemove", action); 0341 connect(action, SIGNAL(triggered(bool)), this, SLOT(borderRemove())); 0342 action->setToolTip(i18n("Remove all borders in the selected area")); 0343 0344 action = new QAction(koIcon("format-border-set-external"), i18n("Border Outline"), this); 0345 action->setIconText(i18n("Outline")); 0346 addAction("borderOutline", action); 0347 connect(action, SIGNAL(triggered(bool)), this, SLOT(borderOutline())); 0348 action->setToolTip(i18n("Set a border to the outline of the selected area")); 0349 0350 action = new KoColorPopupAction(this); 0351 action->setIcon(koIcon("format-stroke-color")); 0352 action->setToolTip(i18n("Select a new border color")); 0353 action->setText(i18n("Border Color")); 0354 static_cast<KoColorPopupAction*>(action)->setCurrentColor(Qt::black); 0355 addAction("borderColor", action); 0356 connect(action, SIGNAL(colorChanged(KoColor)), this, SLOT(borderColor(KoColor))); 0357 0358 // -- text layout actions -- 0359 0360 action = new KToggleAction(koIcon("multirow"), i18n("Wrap Text"), this); 0361 action->setIconText(i18n("Wrap")); 0362 addAction("wrapText", action); 0363 connect(action, SIGNAL(triggered(bool)), this, SLOT(wrapText(bool))); 0364 action->setToolTip(i18n("Make the cell text wrap onto multiple lines")); 0365 0366 action = new KToggleAction(koIcon("format-text-direction-vertical"), i18n("Vertical Text"), this); 0367 action->setIconText(i18n("Vertical")); 0368 addAction("verticalText", action); 0369 connect(action, SIGNAL(triggered(bool)), this, SLOT(verticalText(bool))); 0370 action->setToolTip(i18n("Print cell contents vertically")); 0371 0372 action = new QAction(QIcon::fromTheme(QApplication::isRightToLeft() ? koIconName("format-indent-less") : koIconName("format-indent-more")), i18n("Increase Indent"), this); 0373 addAction("increaseIndentation", action); 0374 connect(action, SIGNAL(triggered(bool)), this, SLOT(increaseIndentation())); 0375 action->setToolTip(i18n("Increase the indentation")); 0376 0377 action = new QAction(QIcon::fromTheme(QApplication::isRightToLeft() ? koIconName("format-indent-more") : koIconName("format-indent-less")), i18n("Decrease Indent"), this); 0378 addAction("decreaseIndentation", action); 0379 connect(action, SIGNAL(triggered(bool)), this, SLOT(decreaseIndentation())); 0380 action->setToolTip(i18n("Decrease the indentation")); 0381 0382 action = new QAction(i18n("Change Angle..."), this); 0383 action->setIconText(i18n("Angle")); 0384 addAction("changeAngle", action); 0385 connect(action, SIGNAL(triggered(bool)), this, SLOT(changeAngle())); 0386 action->setToolTip(i18n("Change the angle that cell contents are printed")); 0387 0388 // -- value format actions -- 0389 0390 action = new KToggleAction(koIcon("format-number-percent"), i18n("Percent Format"), this); 0391 action->setIconText(i18n("Percent")); 0392 addAction("percent", action); 0393 connect(action, SIGNAL(triggered(bool)), this, SLOT(percent(bool))); 0394 action->setToolTip(i18n("Set the cell formatting to look like a percentage")); 0395 0396 action = new KToggleAction(koIcon("format-currency"), i18n("Money Format"), this); 0397 action->setIconText(i18n("Money")); 0398 addAction("currency", action); 0399 connect(action, SIGNAL(triggered(bool)), this, SLOT(currency(bool))); 0400 action->setToolTip(i18n("Set the cell formatting to look like your local currency")); 0401 0402 action = new QAction(koIcon("format-precision-more"), i18n("Increase Precision"), this); 0403 addAction("increasePrecision", action); 0404 connect(action, SIGNAL(triggered(bool)), this, SLOT(increasePrecision())); 0405 action->setToolTip(i18n("Increase the decimal precision shown onscreen")); 0406 0407 action = new QAction(koIcon("format-precision-less"), i18n("Decrease Precision"), this); 0408 addAction("decreasePrecision", action); 0409 connect(action, SIGNAL(triggered(bool)), this, SLOT(decreasePrecision())); 0410 action->setToolTip(i18n("Decrease the decimal precision shown onscreen")); 0411 0412 // -- misc style attribute actions -- 0413 0414 action = new QAction(koIconWanted("no icon in Kate, but LO has one", "format-text-uppercase"), i18n("Upper Case"), this); 0415 action->setIconText(i18n("Upper")); 0416 addAction("toUpperCase", action); 0417 connect(action, SIGNAL(triggered(bool)), this, SLOT(toUpperCase())); 0418 action->setToolTip(i18n("Convert all letters to upper case")); 0419 0420 action = new QAction(koIconWanted("no icon in Kate, but LO has one", "format-text-lowercase"), i18n("Lower Case"), this); 0421 action->setIconText(i18n("Lower")); 0422 addAction("toLowerCase", action); 0423 connect(action, SIGNAL(triggered(bool)), this, SLOT(toLowerCase())); 0424 action->setToolTip(i18n("Convert all letters to lower case")); 0425 0426 action = new QAction(koIcon("format-text-capitalize"), i18n("Convert First Letter to Upper Case"), this); 0427 action->setIconText(i18n("First Letter Upper")); 0428 addAction("firstLetterToUpperCase", action); 0429 connect(action, SIGNAL(triggered(bool)), this, SLOT(firstLetterToUpperCase())); 0430 action->setToolTip(i18n("Capitalize the first letter")); 0431 0432 action = new KoColorPopupAction(this); 0433 action->setIcon(koIcon("format-fill-color")); 0434 action->setToolTip(i18n("Set the background color")); 0435 action->setText(i18n("Background Color")); 0436 addAction("backgroundColor", action); 0437 connect(action, SIGNAL(colorChanged(KoColor)), this, SLOT(changeBackgroundColor(KoColor))); 0438 0439 // -- cell merging actions -- 0440 0441 action = new QAction(koIcon("mergecell"), i18n("Merge Cells"), this); 0442 addAction("mergeCells", action); 0443 connect(action, SIGNAL(triggered(bool)), this, SLOT(mergeCells())); 0444 action->setToolTip(i18n("Merge the selected region")); 0445 0446 action = new QAction(koIcon("mergecell-horizontal"), i18n("Merge Cells Horizontally"), this); 0447 action->setToolTip(i18n("Merge the selected region horizontally")); 0448 addAction("mergeCellsHorizontal", action); 0449 connect(action, SIGNAL(triggered(bool)), this, SLOT(mergeCellsHorizontal())); 0450 0451 action = new QAction(koIcon("mergecell-vertical"), i18n("Merge Cells Vertically"), this); 0452 action->setToolTip(i18n("Merge the selected region vertically")); 0453 addAction("mergeCellsVertical", action); 0454 connect(action, SIGNAL(triggered(bool)), this, SLOT(mergeCellsVertical())); 0455 0456 action = new QAction(koIcon("dissociatecell"), i18n("Dissociate Cells"), this); 0457 action->setToolTip(i18n("Unmerge the selected region")); 0458 addAction("dissociateCells", action); 0459 connect(action, SIGNAL(triggered(bool)), this, SLOT(dissociateCells())); 0460 0461 // -- column & row actions -- 0462 0463 action = new QAction(koIcon("resizecol"), i18n("Resize Column..."), this); 0464 addAction("resizeCol", action); 0465 connect(action, SIGNAL(triggered(bool)), this, SLOT(resizeColumn())); 0466 action->setToolTip(i18n("Change the width of a column")); 0467 0468 action = new QAction(koIcon("edit-table-insert-column-left"), i18n("Columns"), this); 0469 action->setIconText(i18n("Insert Columns")); 0470 action->setToolTip(i18n("Inserts a new column into the spreadsheet")); 0471 addAction("insertColumn", action); 0472 connect(action, SIGNAL(triggered(bool)), this, SLOT(insertColumn())); 0473 0474 action = new QAction(koIcon("edit-table-delete-column"), i18n("Columns"), this); 0475 action->setIconText(i18n("Remove Columns")); 0476 action->setToolTip(i18n("Removes the selected columns from the spreadsheet")); 0477 addAction("deleteColumn", action); 0478 connect(action, SIGNAL(triggered(bool)), this, SLOT(deleteColumn())); 0479 0480 action = new QAction(koIcon("hide_table_column"), i18n("Hide Columns"), this); 0481 addAction("hideColumn", action); 0482 connect(action, SIGNAL(triggered(bool)), this, SLOT(hideColumn())); 0483 action->setToolTip(i18n("Hide the column from this")); 0484 0485 action = new QAction(koIcon("show_table_column"), i18n("Show Columns..."), this); 0486 addAction("showColumn", action); 0487 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotShowColumnDialog())); 0488 action->setToolTip(i18n("Show hidden columns")); 0489 0490 action = new QAction(koIcon("adjustcol"), i18n("Equalize Column"), this); 0491 addAction("equalizeCol", action); 0492 connect(action, SIGNAL(triggered(bool)), this, SLOT(equalizeColumn())); 0493 action->setToolTip(i18n("Resizes selected columns to be the same size")); 0494 0495 action = new QAction(koIcon("show_table_column"), i18n("Show Columns"), this); 0496 addAction("showSelColumns", action); 0497 connect(action, SIGNAL(triggered(bool)), this, SLOT(showColumn())); 0498 action->setToolTip(i18n("Show hidden columns in the selection")); 0499 action->setEnabled(false); 0500 0501 action = new QAction(koIcon("resizerow"), i18n("Resize Row..."), this); 0502 addAction("resizeRow", action); 0503 connect(action, SIGNAL(triggered(bool)), this, SLOT(resizeRow())); 0504 action->setToolTip(i18n("Change the height of a row")); 0505 0506 action = new QAction(koIcon("edit-table-insert-row-above"), i18n("Rows"), this); 0507 action->setIconText(i18n("Insert Rows")); 0508 action->setToolTip(i18n("Inserts a new row into the spreadsheet")); 0509 addAction("insertRow", action); 0510 connect(action, SIGNAL(triggered(bool)), this, SLOT(insertRow())); 0511 0512 action = new QAction(koIcon("edit-table-delete-row"), i18n("Rows"), this); 0513 action->setIconText(i18n("Remove Rows")); 0514 action->setToolTip(i18n("Removes a row from the spreadsheet")); 0515 addAction("deleteRow", action); 0516 connect(action, SIGNAL(triggered(bool)), this, SLOT(deleteRow())); 0517 0518 action = new QAction(koIcon("hide_table_row"), i18n("Hide Rows"), this); 0519 addAction("hideRow", action); 0520 connect(action, SIGNAL(triggered(bool)), this, SLOT(hideRow())); 0521 action->setToolTip(i18n("Hide a row from this")); 0522 0523 action = new QAction(koIcon("show_table_row"), i18n("Show Rows..."), this); 0524 addAction("showRow", action); 0525 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotShowRowDialog())); 0526 action->setToolTip(i18n("Show hidden rows")); 0527 0528 action = new QAction(koIcon("adjustrow"), i18n("Equalize Row"), this); 0529 addAction("equalizeRow", action); 0530 connect(action, SIGNAL(triggered(bool)), this, SLOT(equalizeRow())); 0531 action->setToolTip(i18n("Resizes selected rows to be the same size")); 0532 0533 action = new QAction(koIcon("show_table_row"), i18n("Show Rows"), this); 0534 addAction("showSelRows", action); 0535 connect(action, SIGNAL(triggered(bool)), this, SLOT(showRow())); 0536 action->setEnabled(false); 0537 action->setToolTip(i18n("Show hidden rows in the selection")); 0538 0539 action = new QAction(i18n("Adjust Row && Column"), this); 0540 addAction("adjust", action); 0541 connect(action, SIGNAL(triggered(bool)), this, SLOT(adjust())); 0542 action->setToolTip(i18n("Adjusts row/column size so that the contents will fit")); 0543 0544 // -- cell insert/remove actions -- 0545 0546 action = new QAction(koIcon("insertcell"), i18n("Cells..."), this); 0547 action->setIconText(i18n("Insert Cells...")); 0548 action->setToolTip(i18n("Insert a blank cell into the spreadsheet")); 0549 addAction("insertCell", action); 0550 connect(action, SIGNAL(triggered(bool)), this, SLOT(insertCells())); 0551 0552 action = new QAction(koIcon("removecell"), i18n("Cells..."), this); 0553 action->setIconText(i18n("Remove Cells...")); 0554 action->setToolTip(i18n("Removes the cells from the spreadsheet")); 0555 addAction("deleteCell", action); 0556 connect(action, SIGNAL(triggered(bool)), this, SLOT(deleteCells())); 0557 0558 // -- cell content actions -- 0559 0560 action = new QAction(koIcon("deletecell"), i18n("All"), this); 0561 action->setIconText(i18n("Clear All")); 0562 action->setToolTip(i18n("Clear all contents and formatting of the current cell")); 0563 addAction("clearAll", action); 0564 connect(action, SIGNAL(triggered(bool)), this, SLOT(clearAll())); 0565 0566 action = new QAction(koIcon("edit-clear"), i18n("Contents"), this); 0567 action->setIconText(i18n("Clear Contents")); 0568 action->setToolTip(i18n("Remove the contents of the current cell")); 0569 addAction("clearContents", action); 0570 connect(action, SIGNAL(triggered(bool)), this, SLOT(clearContents())); 0571 0572 action = new QAction(koIcon("edit-comment"), i18n("Comment..."), this); 0573 action->setToolTip(i18n("Edit a comment for this cell")); 0574 addAction("comment", action); 0575 connect(action, SIGNAL(triggered(bool)), this, SLOT(comment())); 0576 0577 action = new QAction(koIcon("delete-comment"), i18n("Comment"), this); 0578 action->setIconText(i18n("Remove Comment")); 0579 action->setToolTip(i18n("Remove this cell's comment")); 0580 addAction("clearComment", action); 0581 connect(action, SIGNAL(triggered(bool)), this, SLOT(clearComment())); 0582 0583 action = new QAction(i18n("Conditional Styles..."), this); 0584 action->setToolTip(i18n("Set cell style based on certain conditions")); 0585 addAction("conditional", action); 0586 connect(action, SIGNAL(triggered(bool)), this, SLOT(conditional())); 0587 0588 action = new QAction(i18n("Conditional Styles"), this); 0589 action->setIconText(i18n("Remove Conditional Styles")); 0590 action->setToolTip(i18n("Remove the conditional cell styles")); 0591 addAction("clearConditional", action); 0592 connect(action, SIGNAL(triggered(bool)), this, SLOT(clearConditionalStyles())); 0593 0594 action = new QAction(koIcon("insert-link"), i18n("&Link..."), this); 0595 addAction("insertHyperlink", action); 0596 connect(action, SIGNAL(triggered(bool)), this, SLOT(insertHyperlink())); 0597 action->setToolTip(i18n("Insert an Internet hyperlink")); 0598 0599 action = new QAction(i18n("Link"), this); 0600 action->setIconText(i18n("Remove Link")); 0601 action->setToolTip(i18n("Remove a link")); 0602 addAction("clearHyperlink", action); 0603 connect(action, SIGNAL(triggered(bool)), this, SLOT(clearHyperlink())); 0604 0605 action = new QAction(i18n("Validity..."), this); 0606 action->setToolTip(i18n("Set tests to confirm cell data is valid")); 0607 addAction("validity", action); 0608 connect(action, SIGNAL(triggered(bool)), this, SLOT(validity())); 0609 0610 action = new QAction(i18n("Validity"), this); 0611 action->setIconText(i18n("Remove Validity")); 0612 action->setToolTip(i18n("Remove the validity tests on this cell")); 0613 addAction("clearValidity", action); 0614 connect(action, SIGNAL(triggered(bool)), this, SLOT(clearValidity())); 0615 0616 // -- sorting/filtering action -- 0617 0618 action = new QAction(i18n("&Sort..."), this); 0619 addAction("sort", action); 0620 connect(action, SIGNAL(triggered(bool)), this, SLOT(sort())); 0621 action->setToolTip(i18n("Sort a group of cells")); 0622 0623 action = new QAction(koIcon("view-sort-descending"), i18n("Sort &Decreasing"), this); 0624 addAction("sortDec", action); 0625 connect(action, SIGNAL(triggered(bool)), this, SLOT(sortDec())); 0626 action->setToolTip(i18n("Sort a group of cells in decreasing(last to first) order")); 0627 0628 action = new QAction(koIcon("view-sort-ascending"), i18n("Sort &Increasing"), this); 0629 addAction("sortInc", action); 0630 connect(action, SIGNAL(triggered(bool)), this, SLOT(sortInc())); 0631 action->setToolTip(i18n("Sort a group of cells in ascending(first to last) order")); 0632 0633 action = new QAction(koIcon("view-filter"), i18n("&Auto-Filter"), this); 0634 addAction("autoFilter", action); 0635 connect(action, SIGNAL(triggered(bool)), this, SLOT(autoFilter())); 0636 action->setToolTip(i18n("Add an automatic filter to a cell range")); 0637 0638 // -- fill actions -- 0639 0640 action = new QAction(/*koIcon("arrow-left"), */i18n("&Left"), this); 0641 addAction("fillLeft", action); 0642 connect(action, SIGNAL(triggered(bool)), this, SLOT(fillLeft())); 0643 0644 action = new QAction(/*koIcon("arrow-right"), */i18n("&Right"), this); 0645 addAction("fillRight", action); 0646 connect(action, SIGNAL(triggered(bool)), this, SLOT(fillRight())); 0647 0648 action = new QAction(/*koIcon("arrow-up"), */i18n("&Up"), this); 0649 addAction("fillUp", action); 0650 connect(action, SIGNAL(triggered(bool)), this, SLOT(fillUp())); 0651 0652 action = new QAction(/*koIcon("arrow-down"), */i18n("&Down"), this); 0653 addAction("fillDown", action); 0654 connect(action, SIGNAL(triggered(bool)), this, SLOT(fillDown())); 0655 0656 action = new QAction(koIcon("black_sum"), i18n("Autosum"), this); 0657 addAction("autoSum", action); 0658 connect(action, SIGNAL(triggered(bool)), this, SLOT(autoSum())); 0659 action->setToolTip(i18n("Insert the 'sum' function")); 0660 0661 // -- data insert actions -- 0662 0663 action = new QAction(koIcon("series"), i18n("&Series..."), this); 0664 addAction("insertSeries", action); 0665 connect(action, SIGNAL(triggered(bool)), this, SLOT(insertSeries())); 0666 action ->setToolTip(i18n("Insert a series")); 0667 0668 action = new QAction(koIcon("insert-math-expression"), i18n("&Function..."), this); 0669 addAction("insertFormula", action); 0670 connect(action, SIGNAL(triggered(bool)), this, SLOT(insertFormula())); 0671 action->setToolTip(i18n("Insert math expression")); 0672 0673 action = new QAction(koIcon("character-set"), i18n("S&pecial Character..."), this); 0674 addAction("insertSpecialChar", action); 0675 action->setToolTip(i18n("Insert one or more symbols or letters not found on the keyboard")); 0676 connect(action, SIGNAL(triggered(bool)), this, SLOT(insertSpecialChar())); 0677 0678 #ifndef QT_NO_SQL 0679 action = new QAction(koIcon("network-server-database"), i18n("From &Database..."), this); 0680 action->setIconText(i18n("Database")); 0681 addAction("insertFromDatabase", action); 0682 connect(action, SIGNAL(triggered(bool)), this, SLOT(insertFromDatabase())); 0683 action->setToolTip(i18n("Insert data from a SQL database")); 0684 #endif 0685 0686 action = new QAction(koIcon("text-plain"), i18n("From &Text File..."), this); 0687 action->setIconText(i18n("Text File")); 0688 addAction("insertFromTextfile", action); 0689 connect(action, SIGNAL(triggered(bool)), this, SLOT(insertFromTextfile())); 0690 action->setToolTip(i18n("Insert data from a text file to the current cursor position/selection")); 0691 0692 action = new QAction(koIcon("edit-paste"), i18n("From &Clipboard..."), this); 0693 action->setIconText(i18n("Clipboard")); 0694 addAction("insertFromClipboard", action); 0695 connect(action, SIGNAL(triggered(bool)), this, SLOT(insertFromClipboard())); 0696 action->setToolTip(i18n("Insert CSV data from the clipboard to the current cursor position/selection")); 0697 0698 action = new QAction(i18n("&Text to Columns..."), this); 0699 addAction("textToColumns", action); 0700 connect(action, SIGNAL(triggered(bool)), this, SLOT(textToColumns())); 0701 action->setToolTip(i18n("Expand the content of cells to multiple columns")); 0702 0703 action = new QAction(i18n("Custom Lists..."), this); 0704 addAction("sortList", action); 0705 connect(action, SIGNAL(triggered(bool)), this, SLOT(sortList())); 0706 action->setToolTip(i18n("Create custom lists for sorting or autofill")); 0707 0708 action = new QAction(i18n("&Consolidate..."), this); 0709 addAction("consolidate", action); 0710 connect(action, SIGNAL(triggered(bool)), this, SLOT(consolidate())); 0711 action->setToolTip(i18n("Create a region of summary data from a group of similar regions")); 0712 0713 action = new QAction(i18n("&Goal Seek..."), this); 0714 addAction("goalSeek", action); 0715 connect(action, SIGNAL(triggered(bool)), this, SLOT(goalSeek())); 0716 action->setToolTip(i18n("Repeating calculation to find a specific value")); 0717 0718 action = new QAction(i18n("&Subtotals..."), this); 0719 addAction("subtotals", action); 0720 connect(action, SIGNAL(triggered(bool)), this, SLOT(subtotals())); 0721 action->setToolTip(i18n("Create different kind of subtotals to a list or database")); 0722 0723 action = new QAction(i18n("&Pivot Tables..."), this); 0724 addAction("Pivot", action); 0725 connect(action, SIGNAL(triggered(bool)), this, SLOT(pivot())); 0726 action->setToolTip(i18n("Create Pivot Tables")); 0727 0728 action = new QAction(i18n("Area Name..."), this); 0729 addAction("setAreaName", action); 0730 connect(action, SIGNAL(triggered(bool)), this, SLOT(setAreaName())); 0731 action->setToolTip(i18n("Set a name for a region of the spreadsheet")); 0732 0733 action = new QAction(i18n("Named Areas..."), this); 0734 action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_G)); 0735 action->setIconText(i18n("Named Areas")); 0736 action->setIcon(koIcon("bookmarks")); 0737 action->setToolTip(i18n("Edit or select named areas")); 0738 addAction("namedAreaDialog", action); 0739 connect(action, SIGNAL(triggered(bool)), this, SLOT(namedAreaDialog())); 0740 0741 action = new KSelectAction(i18n("Formula Selection"), this); 0742 addAction("formulaSelection", action); 0743 action->setToolTip(i18n("Insert a function")); 0744 QStringList functionList; 0745 functionList.append("SUM"); 0746 functionList.append("AVERAGE"); 0747 functionList.append("IF"); 0748 functionList.append("COUNT"); 0749 functionList.append("MIN"); 0750 functionList.append("MAX"); 0751 functionList.append(i18n("Others...")); 0752 static_cast<KSelectAction*>(action)->setItems(functionList); 0753 static_cast<KSelectAction*>(action)->setComboWidth(80); 0754 static_cast<KSelectAction*>(action)->setCurrentItem(0); 0755 connect(action, SIGNAL(triggered(QString)), this, SLOT(formulaSelection(QString))); 0756 0757 // -- general editing actions -- 0758 0759 action = new QAction(koIcon("cell_edit"), i18n("Modify Cell"), this); 0760 addAction("editCell", action); 0761 action->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_M)); 0762 connect(action, SIGNAL(triggered(bool)), this, SLOT(edit())); 0763 action->setToolTip(i18n("Edit the highlighted cell")); 0764 0765 action = KStandardAction::cut(this, SLOT(cut()), this); 0766 action->setToolTip(i18n("Move the cell object to the clipboard")); 0767 addAction("cut", action); 0768 0769 action = KStandardAction::copy(this, SLOT(copy()), this); 0770 action->setToolTip(i18n("Copy the cell object to the clipboard")); 0771 addAction("copy", action); 0772 0773 action = KStandardAction::paste(this, SLOT(paste()), this); 0774 action->setToolTip(i18n("Paste the contents of the clipboard at the cursor")); 0775 addAction("paste", action); 0776 0777 action = new QAction(koIcon("special_paste"), i18n("Special Paste..."), this); 0778 addAction("specialPaste", action); 0779 connect(action, SIGNAL(triggered(bool)), this, SLOT(specialPaste())); 0780 action->setToolTip(i18n("Paste the contents of the clipboard with special options")); 0781 0782 action = new QAction(koIcon("insertcellcopy"), i18n("Paste with Insertion"), this); 0783 addAction("pasteWithInsertion", action); 0784 connect(action, SIGNAL(triggered(bool)), this, SLOT(pasteWithInsertion())); 0785 action->setToolTip(i18n("Inserts a cell from the clipboard into the spreadsheet")); 0786 0787 action = KStandardAction::selectAll(this, SLOT(selectAll()), this); 0788 action->setToolTip(i18n("Selects all cells in the current sheet")); 0789 addAction("selectAll", action); 0790 0791 action = KStandardAction::find(this, SLOT(find()), this); 0792 addAction("edit_find", action); 0793 0794 action = KStandardAction::findNext(this, SLOT(findNext()), this); 0795 addAction("edit_find_next", action); 0796 0797 action = KStandardAction::findPrev(this, SLOT(findPrevious()), this); 0798 addAction("edit_find_last", action); 0799 0800 action = KStandardAction::replace(this, SLOT(replace()), this); 0801 addAction("edit_replace", action); 0802 0803 // -- misc actions -- 0804 0805 action = new QAction(koIcon("go-jump"), i18n("Goto Cell..."), this); 0806 action->setIconText(i18n("Goto")); 0807 action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_G)); 0808 addAction("gotoCell", action); 0809 connect(action, SIGNAL(triggered(bool)), this, SLOT(gotoCell())); 0810 action->setToolTip(i18n("Move to a particular cell")); 0811 0812 action = KStandardAction::spelling(this, SLOT(spellCheck()), this); 0813 action->setToolTip(i18n("Check the spelling")); 0814 addAction("tools_spelling", action); 0815 0816 action = new QAction(koIconWanted("not used in UI, but devs might do, so nice to have", "inspector"), i18n("Run Inspector..."), this); 0817 addAction("inspector", action); 0818 action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I)); 0819 connect(action, SIGNAL(triggered(bool)), this, SLOT(inspector())); 0820 0821 #ifndef NDEBUG 0822 action = new QAction(koIcon("table"), i18n("Show QTableView..."), this); 0823 addAction("qTableView", action); 0824 action->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_T)); 0825 connect(action, SIGNAL(triggered(bool)), this, SLOT(qTableView())); 0826 #endif 0827 0828 action = new QAction(i18n("Auto-Format..."), this); 0829 addAction("sheetFormat", action); 0830 connect(action, SIGNAL(triggered(bool)), this, SLOT(sheetFormat())); 0831 action->setToolTip(i18n("Set the worksheet formatting")); 0832 0833 action = new QAction(koIcon("application-vnd.oasis.opendocument.spreadsheet"), i18n("Document Settings..."), this); 0834 addAction("documentSettingsDialog", action); 0835 connect(action, SIGNAL(triggered(bool)), this, SLOT(documentSettingsDialog())); 0836 action->setToolTip(i18n("Show document settings dialog")); 0837 0838 action = new KToggleAction(i18n("Break Before Column"), this); 0839 addAction("format_break_before_column", action); 0840 connect(action, SIGNAL(triggered(bool)), this, SLOT(breakBeforeColumn(bool))); 0841 action->setIconText(i18n("Column Break")); 0842 action->setToolTip(i18n("Set a manual page break before the column")); 0843 0844 action = new KToggleAction(i18n("Break Before Row"), this); 0845 addAction("format_break_before_row", action); 0846 connect(action, SIGNAL(triggered(bool)), this, SLOT(breakBeforeRow(bool))); 0847 action->setIconText(i18n("Row Break")); 0848 action->setToolTip(i18n("Set a manual page break before the row")); 0849 0850 // Editor actions: 0851 // Set up the permutation of the reference fixations action. 0852 action = new QAction(i18n("Permute reference fixation"), this); 0853 addAction("permuteFixation", action); 0854 action->setShortcut(Qt::Key_F4); 0855 // connect on creation of the embedded editor 0856 action->setIconText(i18n("Permute fixation")); 0857 action->setToolTip(i18n("Permute the fixation of the reference at the text cursor")); 0858 0859 setTextMode(true); 0860 0861 } 0862 0863 CellToolBase::~CellToolBase() 0864 { 0865 delete d->formulaDialog; 0866 delete d->popupListChoose; 0867 delete d->cellEditor; 0868 qDeleteAll(d->popupMenuActions); 0869 qDeleteAll(actions()); 0870 delete d; 0871 } 0872 0873 void CellToolBase::paint(QPainter &painter, const KoViewConverter &viewConverter) 0874 { 0875 KoShape::applyConversion(painter, viewConverter); 0876 painter.translate(offset()); // the table shape offset 0877 const QRectF paintRect = QRectF(QPointF(), size()); 0878 0879 /* paint the selection */ 0880 d->paintReferenceSelection(painter, paintRect); 0881 d->paintSelection(painter, paintRect); 0882 } 0883 0884 void CellToolBase::paintReferenceSelection(QPainter &painter, const QRectF &paintRect) 0885 { 0886 d->paintReferenceSelection(painter, paintRect); 0887 } 0888 0889 void CellToolBase::paintSelection(QPainter &painter, const QRectF &paintRect) 0890 { 0891 d->paintSelection(painter, paintRect); 0892 } 0893 0894 void CellToolBase::mousePressEvent(KoPointerEvent* event) 0895 { 0896 KoInteractionTool::mousePressEvent(event); 0897 } 0898 0899 void CellToolBase::mouseMoveEvent(KoPointerEvent* event) 0900 { 0901 // Special handling for drag'n'drop. 0902 if (DragAndDropStrategy *const strategy = dynamic_cast<DragAndDropStrategy*>(currentStrategy())) { 0903 // FIXME Stefan: QDrag*Event and QDropEvent are not handled by KoInteractionTool YET: 0904 // Cancel the strategy after the drag has started. 0905 if (strategy->dragStarted()) { 0906 cancelCurrentStrategy(); 0907 } 0908 KoInteractionTool::mouseMoveEvent(event); 0909 return; 0910 } 0911 // Indicators are not necessary if there's a strategy. 0912 if (currentStrategy()) { 0913 return KoInteractionTool::mouseMoveEvent(event); 0914 } 0915 0916 Sheet *const sheet = selection()->activeSheet(); 0917 0918 // Get info about where the event occurred. 0919 QPointF position = event->point - offset(); // the shape offset, not the scrolling one. 0920 0921 // Diagonal cursor, if the selection handle was hit. 0922 if (SelectionStrategy::hitTestReferenceSizeGrip(canvas(), selection(), position) || 0923 SelectionStrategy::hitTestSelectionSizeGrip(canvas(), selection(), position)) { 0924 if (selection()->activeSheet()->layoutDirection() == Qt::RightToLeft) { 0925 useCursor(Qt::SizeBDiagCursor); 0926 } else { 0927 useCursor(Qt::SizeFDiagCursor); 0928 } 0929 return KoInteractionTool::mouseMoveEvent(event); 0930 } 0931 0932 // Hand cursor, if the selected area was hit. 0933 if (!selection()->referenceSelectionMode()) { 0934 const Region::ConstIterator end(selection()->constEnd()); 0935 for (Region::ConstIterator it(selection()->constBegin()); it != end; ++it) { 0936 const QRect range = (*it)->rect(); 0937 if (sheet->cellCoordinatesToDocument(range).contains(position)) { 0938 useCursor(Qt::PointingHandCursor); 0939 return KoInteractionTool::mouseMoveEvent(event); 0940 } 0941 } 0942 } 0943 0944 // In which cell did the user click? 0945 qreal xpos; 0946 qreal ypos; 0947 const int col = this->selection()->activeSheet()->leftColumn(position.x(), xpos); 0948 const int row = this->selection()->activeSheet()->topRow(position.y(), ypos); 0949 // Check boundaries. 0950 if (col < 1 || row < 1 || col > maxCol() || row > maxRow()) { 0951 debugSheetsUI << "col or row is out of range:" << "col:" << col << " row:" << row; 0952 } else { 0953 const Cell cell = Cell(selection()->activeSheet(), col, row).masterCell(); 0954 SheetView* const sheetView = this->sheetView(selection()->activeSheet()); 0955 0956 QString url; 0957 const CellView& cellView = sheetView->cellView(col, row); 0958 if (selection()->activeSheet()->layoutDirection() == Qt::RightToLeft) { 0959 url = cellView.testAnchor(sheetView, cell, cell.width() - position.x() + xpos, position.y() - ypos); 0960 } else { 0961 url = cellView.testAnchor(sheetView, cell, position.x() - xpos, position.y() - ypos); 0962 } 0963 if (!url.isEmpty()) { 0964 useCursor(Qt::PointingHandCursor); 0965 return KoInteractionTool::mouseMoveEvent(event); 0966 } 0967 } 0968 0969 // Reset to normal cursor. 0970 useCursor(Qt::ArrowCursor); 0971 KoInteractionTool::mouseMoveEvent(event); 0972 } 0973 0974 void CellToolBase::mouseReleaseEvent(KoPointerEvent* event) 0975 { 0976 KoInteractionTool::mouseReleaseEvent(event); 0977 scrollToCell(selection()->cursor()); 0978 } 0979 0980 void CellToolBase::mouseDoubleClickEvent(KoPointerEvent* event) 0981 { 0982 Q_UNUSED(event) 0983 cancelCurrentStrategy(); 0984 scrollToCell(selection()->cursor()); 0985 createEditor(false /* keep content */, true, true /*full editing*/); 0986 } 0987 0988 void CellToolBase::keyPressEvent(QKeyEvent* event) 0989 { 0990 register Sheet * const sheet = selection()->activeSheet(); 0991 if (!sheet) { 0992 return; 0993 } 0994 0995 // Don't handle the remaining special keys. 0996 if (event->modifiers() & (Qt::AltModifier | Qt::ControlModifier) && 0997 (event->key() != Qt::Key_Down) && 0998 (event->key() != Qt::Key_Up) && 0999 (event->key() != Qt::Key_Right) && 1000 (event->key() != Qt::Key_Left) && 1001 (event->key() != Qt::Key_Home) && 1002 (event->key() != Qt::Key_Enter) && 1003 (event->key() != Qt::Key_Return)) { 1004 event->ignore(); // QKeyEvent 1005 return; 1006 } 1007 1008 // Check for formatting key combination CTRL + ... 1009 // Qt::Key_Exclam, Qt::Key_At, Qt::Key_Ampersand, Qt::Key_Dollar 1010 // Qt::Key_Percent, Qt::Key_AsciiCircum, Qt::Key_NumberSign 1011 if (d->formatKeyPress(event)) { 1012 return; 1013 } 1014 1015 #if 0 1016 // TODO move this to the contextMenuEvent of the view. 1017 // keyPressEvent() is not called with the contextMenuKey, 1018 // it's handled separately by Qt. 1019 if (event->key() == KGlobalSettings::contextMenuKey()) { 1020 int row = d->canvas->selection()->marker().y(); 1021 int col = d->canvas->selection()->marker().x(); 1022 QPointF p(sheet->columnPosition(col), sheet->rowPosition(row)); 1023 d->canvas->view()->openPopupMenu(d->canvas->mapToGlobal(p.toPoint())); 1024 } 1025 #endif 1026 switch (event->key()) { 1027 case Qt::Key_Return: 1028 case Qt::Key_Enter: 1029 d->processEnterKey(event); 1030 return; 1031 break; 1032 case Qt::Key_Down: 1033 case Qt::Key_Up: 1034 case Qt::Key_Left: 1035 case Qt::Key_Right: 1036 case Qt::Key_Tab: /* a tab behaves just like a right/left arrow */ 1037 case Qt::Key_Backtab: /* and so does Shift+Tab */ 1038 if (event->modifiers() & Qt::ControlModifier) { 1039 if (!d->processControlArrowKey(event)) 1040 return; 1041 } else { 1042 d->processArrowKey(event); 1043 return; 1044 } 1045 break; 1046 1047 case Qt::Key_Escape: 1048 d->processEscapeKey(event); 1049 return; 1050 break; 1051 1052 case Qt::Key_Home: 1053 if (!d->processHomeKey(event)) 1054 return; 1055 break; 1056 1057 case Qt::Key_End: 1058 if (!d->processEndKey(event)) 1059 return; 1060 break; 1061 1062 case Qt::Key_PageUp: /* Page Up */ 1063 if (!d->processPriorKey(event)) 1064 return; 1065 break; 1066 1067 case Qt::Key_PageDown: /* Page Down */ 1068 if (!d->processNextKey(event)) 1069 return; 1070 break; 1071 1072 case Qt::Key_Backspace: 1073 case Qt::Key_Delete: 1074 clearContents(); 1075 break; 1076 1077 case Qt::Key_F2: 1078 edit(); 1079 break; 1080 1081 default: 1082 d->processOtherKey(event); 1083 return; 1084 break; 1085 } 1086 } 1087 1088 void CellToolBase::inputMethodEvent(QInputMethodEvent * event) 1089 { 1090 // Send it to the embedded editor. 1091 if (editor()) { 1092 QApplication::sendEvent(editor()->widget(), event); 1093 } 1094 } 1095 1096 void CellToolBase::activate(ToolActivation toolActivation, const QSet<KoShape*> &shapes) 1097 { 1098 Q_UNUSED(toolActivation); 1099 Q_UNUSED(shapes); 1100 1101 if (!d->initialized) { 1102 init(); 1103 d->initialized = true; 1104 } 1105 1106 useCursor(Qt::ArrowCursor); 1107 1108 1109 // paint the selection rectangle 1110 selection()->update(); 1111 populateWordCollection(); 1112 // Initialize cell style selection action. 1113 const StyleManager* styleManager = selection()->activeSheet()->map()->styleManager(); 1114 static_cast<KSelectAction*>(this->action("setStyle"))->setItems(styleManager->styleNames()); 1115 1116 // Establish connections. 1117 connect(selection(), SIGNAL(changed(Region)), 1118 this, SLOT(selectionChanged(Region))); 1119 connect(selection(), SIGNAL(closeEditor(bool,bool)), 1120 this, SLOT(deleteEditor(bool,bool))); 1121 connect(selection(), SIGNAL(modified(Region)), 1122 this, SLOT(updateEditor())); 1123 connect(selection(), SIGNAL(activeSheetChanged(Sheet*)), 1124 this, SLOT(activeSheetChanged(Sheet*))); 1125 connect(selection(), SIGNAL(requestFocusEditor()), 1126 this, SLOT(focusEditorRequested())); 1127 connect(selection(), SIGNAL(documentReadWriteToggled(bool)), 1128 this, SLOT(documentReadWriteToggled(bool))); 1129 connect(selection(), SIGNAL(sheetProtectionToggled(bool)), 1130 this, SLOT(sheetProtectionToggled(bool))); 1131 } 1132 1133 void CellToolBase::deactivate() 1134 { 1135 Selection *sel = selection(); 1136 // Disconnect. 1137 if (sel) disconnect(sel, 0, this, 0); 1138 // close the cell editor 1139 deleteEditor(true); // save changes 1140 // clear the selection rectangle 1141 if (sel) sel->update(); 1142 } 1143 1144 void CellToolBase::init() 1145 { 1146 } 1147 1148 QList<QPointer<QWidget> > CellToolBase::createOptionWidgets() 1149 { 1150 QList<QPointer<QWidget> > widgets; 1151 1152 QString xmlName = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "calligrasheets/CellToolOptionWidgets.xml"); 1153 debugSheets << xmlName; 1154 if (xmlName.isEmpty()) { 1155 warnSheets << "couldn't find CellToolOptionWidgets.xml file"; 1156 return widgets; 1157 } 1158 1159 QFile f(xmlName); 1160 if (!f.open(QIODevice::ReadOnly)) { 1161 warnSheets << "couldn't open CellToolOptionWidgets.xml file"; 1162 return widgets; 1163 } 1164 1165 QDomDocument doc(QString::fromLatin1("optionWidgets")); 1166 QString errorMsg; 1167 int errorLine, errorCol; 1168 if (!doc.setContent(&f, &errorMsg, &errorLine, &errorCol)) { 1169 f.close(); 1170 warnSheets << "couldn't parse CellToolOptionWidgets.xml file:" << errorMsg << "on line" << errorLine << "column" << errorCol; 1171 return widgets; 1172 } 1173 f.close(); 1174 1175 QDomNodeList widgetNodes = doc.elementsByTagName("optionWidget"); 1176 for (int i = 0; i < widgetNodes.size(); ++i) { 1177 QDomElement e = widgetNodes.at(i).toElement(); 1178 widgets.append(new ActionOptionWidget(this, e)); 1179 } 1180 1181 return widgets; 1182 } 1183 1184 // TODO: while this event sends the offset-adjusted position, the subsequent handleMouseMove calls do not. This means that they all contain the offset adjustment themselves, which is a needless duplication. Should be improved. 1185 KoInteractionStrategy* CellToolBase::createStrategy(KoPointerEvent* event) 1186 { 1187 // Get info about where the event occurred. 1188 QPointF position = event->point - offset(); // the shape offset, not the scrolling one. 1189 1190 // Autofilling or merging, if the selection handle was hit. 1191 if (SelectionStrategy::hitTestSelectionSizeGrip(canvas(), selection(), position)) { 1192 if (event->button() == Qt::LeftButton) 1193 return new AutoFillStrategy(this, position, event->modifiers()); 1194 else if (event->button() == Qt::MidButton) 1195 return new MergeStrategy(this, position, event->modifiers()); 1196 } 1197 1198 // Pasting with the middle mouse button. 1199 if (event->button() == Qt::MidButton) { 1200 return new PasteStrategy(this, position, event->modifiers()); 1201 } 1202 1203 // Check, if the selected area was hit. 1204 bool hitSelection = false; 1205 Region::ConstIterator end = selection()->constEnd(); 1206 for (Region::ConstIterator it = selection()->constBegin(); it != end; ++it) { 1207 const QRect range = (*it)->rect(); 1208 if (selection()->activeSheet()->cellCoordinatesToDocument(range).contains(position)) { 1209 // Context menu with the right mouse button. 1210 if (event->button() == Qt::RightButton) { 1211 // Setup the context menu. 1212 setPopupActionList(d->popupActionList()); 1213 event->ignore(); 1214 return 0; // Act directly; no further strategy needed. 1215 } 1216 hitSelection = true; 1217 break; 1218 } 1219 } 1220 1221 // In which cell did the user click? 1222 qreal xpos; 1223 qreal ypos; 1224 const int col = this->selection()->activeSheet()->leftColumn(position.x(), xpos); 1225 const int row = this->selection()->activeSheet()->topRow(position.y(), ypos); 1226 // Check boundaries. 1227 if (col > maxCol() || row > maxRow()) { 1228 debugSheetsUI << "col or row is out of range:" << "col:" << col << " row:" << row; 1229 } else { 1230 // Context menu with the right mouse button. 1231 if (event->button() == Qt::RightButton) { 1232 selection()->initialize(QPoint(col, row), selection()->activeSheet()); 1233 // Setup the context menu. 1234 setPopupActionList(d->popupActionList()); 1235 event->ignore(); 1236 return 0; // Act directly; no further strategy needed. 1237 } else { 1238 const Cell cell = Cell(selection()->activeSheet(), col, row).masterCell(); 1239 SheetView* const sheetView = this->sheetView(selection()->activeSheet()); 1240 1241 // Filter button hit. 1242 const double offsetX = canvas()->canvasController()->canvasOffsetX(); 1243 const double offsetY = canvas()->canvasController()->canvasOffsetY(); 1244 const QPointF p1 = QPointF(xpos, ypos) - offset(); // the shape offset, not the scrolling one. 1245 const QSizeF s1(cell.width(), cell.height()); 1246 const QRectF cellRect = canvas()->viewConverter()->documentToView(QRectF(p1, s1)); 1247 const QRect cellViewRect = cellRect.translated(offsetX, offsetY).toRect(); 1248 if (sheetView->cellView(col, row).hitTestFilterButton(cell, cellViewRect, event->pos())) { 1249 Database database = cell.database(); 1250 FilterPopup::showPopup(canvas()->canvasWidget(), cell, cellViewRect, &database); 1251 return 0; // Act directly; no further strategy needed. 1252 } 1253 1254 // Hyperlink hit. 1255 QString url; 1256 const CellView& cellView = sheetView->cellView(col, row); 1257 if (selection()->activeSheet()->layoutDirection() == Qt::RightToLeft) { 1258 url = cellView.testAnchor(sheetView, cell, cell.width() - position.x() + xpos, position.y() - ypos); 1259 } else { 1260 url = cellView.testAnchor(sheetView, cell, position.x() - xpos, position.y() - ypos); 1261 } 1262 if (!url.isEmpty()) { 1263 return new HyperlinkStrategy(this, position, 1264 event->modifiers(), url, cellView.textRect()); 1265 } 1266 } 1267 } 1268 1269 // Do we want to drag and drop the selection? 1270 bool wantDragDrop = hitSelection; 1271 if (event->modifiers() & Qt::ControlModifier) wantDragDrop = false; // no drag&drop if Ctrl is pressed 1272 QRect selRect = selection()->boundingRect(); 1273 // no drag&drop if it's a single cell, assume they want a selection 1274 if ((selRect.width() <= 1) && (selRect.height() <= 1)) wantDragDrop = false; 1275 if (selection()->referenceSelectionMode()) wantDragDrop = false; 1276 if (wantDragDrop) 1277 return new DragAndDropStrategy(this, position, event->modifiers()); 1278 1279 return new SelectionStrategy(this, position, event->modifiers()); 1280 } 1281 1282 void CellToolBase::selectionChanged(const Region& region) 1283 { 1284 Q_UNUSED(region); 1285 if (!d->externalEditor) { 1286 return; 1287 } 1288 // Update the editor, if the reference selection is enabled. 1289 if (editor() && selection()->referenceSelectionMode()) { 1290 // First, update the formula expression. This will send a signal with 1291 // the new expression to the external editor, which does not have focus 1292 // yet (the canvas has). If it would have, it would also send a signal 1293 // to inform the embedded editor about a changed text. 1294 editor()->selectionChanged(); 1295 // Focus the embedded or external editor after updating the expression. 1296 focusEditorRequested(); 1297 return; 1298 } 1299 1300 // State of manual page breaks before columns/rows. 1301 bool columnBreakChecked = false; 1302 bool columnBreakEnabled = false; 1303 bool rowBreakChecked = false; 1304 bool rowBreakEnabled = false; 1305 const Region::ConstIterator end(selection()->constEnd()); 1306 for (Region::ConstIterator it = selection()->constBegin(); it != end; ++it) { 1307 const Sheet *const sheet = (*it)->sheet(); 1308 if (!sheet) { 1309 continue; 1310 } 1311 const QRect range = (*it)->rect(); 1312 const int column = range.left(); 1313 const int row = range.top(); 1314 columnBreakChecked |= sheet->columnFormat(column)->hasPageBreak(); 1315 columnBreakEnabled |= (column != 1); 1316 rowBreakChecked |= sheet->rowFormats()->hasPageBreak(row); 1317 rowBreakEnabled |= (row != 1); 1318 } 1319 action("format_break_before_column")->setChecked(columnBreakChecked); 1320 action("format_break_before_column")->setEnabled(columnBreakEnabled); 1321 action("format_break_before_row")->setChecked(rowBreakChecked); 1322 action("format_break_before_row")->setEnabled(rowBreakEnabled); 1323 1324 const Cell cell = Cell(selection()->activeSheet(), selection()->cursor()); 1325 if (!cell) { 1326 return; 1327 } 1328 d->updateEditor(cell); 1329 d->updateActions(cell); 1330 1331 if (selection()->activeSheet()->isProtected()) { 1332 const Style style = cell.style(); 1333 if (style.notProtected()) { 1334 if (selection()->isSingular()) { 1335 if (!action("bold")->isEnabled()) { 1336 d->setProtectedActionsEnabled(true); 1337 } 1338 } else { // more than one cell 1339 if (action("bold")->isEnabled()) { 1340 d->setProtectedActionsEnabled(false); 1341 } 1342 } 1343 } else { 1344 if (action("bold")->isEnabled()) { 1345 d->setProtectedActionsEnabled(false); 1346 } 1347 } 1348 } 1349 } 1350 1351 void CellToolBase::scrollToCell(const QPoint &location) 1352 { 1353 Sheet *const sheet = selection()->activeSheet(); 1354 1355 // Adjust the maximum accessed column and row for the scrollbars. 1356 sheetView(sheet)->updateAccessedCellRange(location); 1357 1358 // The cell geometry expanded by some pixels in each direction. 1359 const Cell cell = Cell(sheet, location).masterCell(); 1360 const double xpos = sheet->columnPosition(cell.cellPosition().x()); 1361 const double ypos = sheet->rowPosition(cell.cellPosition().y()); 1362 const double pixelWidth = canvas()->viewConverter()->viewToDocumentX(1); 1363 const double pixelHeight = canvas()->viewConverter()->viewToDocumentY(1); 1364 QRectF rect(xpos, ypos, cell.width(), cell.height()); 1365 rect.adjust(-2*pixelWidth, -2*pixelHeight, +2*pixelWidth, +2*pixelHeight); 1366 rect = rect & QRectF(QPointF(0.0, 0.0), sheet->documentSize()); 1367 1368 // Scroll to cell. 1369 canvas()->canvasController()->ensureVisible(canvas()->viewConverter()->documentToView(rect), true); 1370 } 1371 1372 CellEditorBase* CellToolBase::editor() const 1373 { 1374 return d->cellEditor; 1375 } 1376 1377 void CellToolBase::setLastEditorWithFocus(Editor editor) 1378 { 1379 d->lastEditorWithFocus = editor; 1380 } 1381 1382 bool CellToolBase::createEditor(bool clear, bool focus, bool captureArrows) 1383 { 1384 const Cell cell(selection()->activeSheet(), selection()->marker()); 1385 if (selection()->activeSheet()->isProtected() && !cell.style().notProtected()) 1386 return false; 1387 1388 if (!editor()) { 1389 d->cellEditor = new CellEditor(this, d->wordCollection,canvas()->canvasWidget()); 1390 d->cellEditor->setEditorFont(cell.style().font(), true, canvas()->viewConverter()); 1391 connect(action("permuteFixation"), SIGNAL(triggered(bool)), 1392 d->cellEditor, SLOT(permuteFixation())); 1393 1394 if(d->externalEditor) { 1395 connect(d->cellEditor, SIGNAL(textChanged(QString)), 1396 d->externalEditor, SLOT(setText(QString))); 1397 connect(d->externalEditor, SIGNAL(textChanged(QString)), 1398 d->cellEditor, SLOT(setText(QString))); 1399 d->externalEditor->applyAction()->setEnabled(true); 1400 d->externalEditor->cancelAction()->setEnabled(true); 1401 } 1402 1403 double w = cell.width(); 1404 double h = cell.height(); 1405 double min_w = cell.width(); 1406 double min_h = cell.height(); 1407 1408 double xpos = selection()->activeSheet()->columnPosition(selection()->marker().x()); 1409 xpos += canvas()->viewConverter()->viewToDocumentX(canvas()->canvasController()->canvasOffsetX()); 1410 1411 Qt::LayoutDirection sheetDir = selection()->activeSheet()->layoutDirection(); 1412 bool rtlText = cell.displayText().isRightToLeft(); 1413 1414 // if sheet and cell direction don't match, then the editor's location 1415 // needs to be shifted backwards so that it's right above the cell's text 1416 if (w > 0 && ((sheetDir == Qt::RightToLeft && !rtlText) || 1417 (sheetDir == Qt::LeftToRight && rtlText))) 1418 xpos -= w - min_w; 1419 1420 // paint editor above correct cell if sheet direction is RTL 1421 if (sheetDir == Qt::RightToLeft) { 1422 double dwidth = canvas()->viewConverter()->viewToDocumentX(canvas()->canvasWidget()->width()); 1423 double w2 = qMax(w, min_w); 1424 xpos = dwidth - w2 - xpos; 1425 } 1426 1427 double ypos = selection()->activeSheet()->rowPosition(selection()->marker().y()); 1428 ypos += canvas()->viewConverter()->viewToDocumentY(canvas()->canvasController()->canvasOffsetY()); 1429 1430 // Setup the editor's palette. 1431 const Style style = cell.effectiveStyle(); 1432 QPalette editorPalette(d->cellEditor->palette()); 1433 QColor color = style.fontColor(); 1434 if (!color.isValid()) 1435 color = canvas()->canvasWidget()->palette().text().color(); 1436 editorPalette.setColor(QPalette::Text, color); 1437 color = style.backgroundColor(); 1438 if (!color.isValid()) 1439 color = editorPalette.base().color(); 1440 editorPalette.setColor(QPalette::Background, color); 1441 d->cellEditor->setPalette(editorPalette); 1442 1443 // apply (table shape) offset 1444 xpos += offset().x(); 1445 ypos += offset().y(); 1446 1447 const QRectF rect(xpos + 0.5, ypos + 0.5, w - 0.5, h - 0.5); //needed to circumvent rounding issue with height/width 1448 const QRectF zoomedRect = canvas()->viewConverter()->documentToView(rect); 1449 d->cellEditor->setGeometry(zoomedRect.toRect().adjusted(1, 1, -1, -1)); 1450 d->cellEditor->setMinimumSize(QSize((int)canvas()->viewConverter()->documentToViewX(min_w) - 1, 1451 (int)canvas()->viewConverter()->documentToViewY(min_h) - 1)); 1452 d->cellEditor->show(); 1453 1454 // Laurent 2001-12-05 1455 // Don't add focus when we create a new editor and 1456 // we select text in edit widget otherwise we don't delete 1457 // selected text. 1458 if (focus) 1459 d->cellEditor->setFocus(); 1460 1461 // clear the selection rectangle 1462 selection()->update(); 1463 } 1464 1465 d->cellEditor->setCaptureArrowKeys(captureArrows); 1466 1467 if (!clear && !cell.isNull()) { 1468 d->cellEditor->setText(cell.userInput()); 1469 // place cursor at the end 1470 int pos = d->cellEditor->toPlainText().length(); 1471 d->cellEditor->setCursorPosition(pos); 1472 if (d->externalEditor) d->externalEditor->setCursorPosition(pos); 1473 } 1474 return true; 1475 } 1476 1477 void CellToolBase::populateWordCollection() 1478 { 1479 const CellStorage* cellstore=selection()->activeSheet()->cellStorage(); 1480 ValueConverter *conv=0,*conv2=0; 1481 int lastrow=cellstore->rows(); 1482 int lastcolumn=cellstore->columns(); 1483 if( lastrow < 2000 && lastcolumn < 20) { 1484 for (int j=1 ; j <= lastcolumn ; j++) { 1485 for (int i=1; i<=lastrow ; i++) { 1486 Value val=Cell( selection()->activeSheet(), j, i).value(); 1487 if(val.isString()) { 1488 QString value=conv->toString( conv2->asString(val) ); 1489 1490 if(!d->wordCollection.values(j).contains(value)){ 1491 d->wordCollection.insertMulti(j, value); 1492 } 1493 } 1494 } 1495 } 1496 } 1497 } 1498 1499 void CellToolBase::deleteEditor(bool saveChanges, bool expandMatrix) 1500 { 1501 if (!d->cellEditor) { 1502 return; 1503 } 1504 const QString userInput = d->cellEditor->toPlainText(); 1505 d->cellEditor->hide(); 1506 // Delete the cell editor first and after that update the document. 1507 // That means we get a synchronous repaint after the cell editor 1508 // widget is gone. Otherwise we may get painting errors. 1509 delete d->cellEditor; 1510 d->cellEditor = 0; 1511 1512 delete d->formulaDialog; 1513 d->formulaDialog = 0; 1514 1515 if (saveChanges) { 1516 applyUserInput(userInput, expandMatrix); 1517 } else { 1518 selection()->update(); 1519 } 1520 if (d->externalEditor) { 1521 d->externalEditor->applyAction()->setEnabled(false); 1522 d->externalEditor->cancelAction()->setEnabled(false); 1523 } 1524 canvas()->canvasWidget()->setFocus(); 1525 } 1526 1527 void CellToolBase::activeSheetChanged(Sheet* sheet) 1528 { 1529 #ifdef NDEBUG 1530 Q_UNUSED(sheet); 1531 #else 1532 Q_ASSERT(selection()->activeSheet() == sheet); 1533 #endif 1534 populateWordCollection(); 1535 if (!selection()->referenceSelectionMode()) { 1536 return; 1537 } 1538 if (editor()) { 1539 if (selection()->originSheet() != selection()->activeSheet()) { 1540 editor()->widget()->hide(); 1541 } else { 1542 editor()->widget()->show(); 1543 } 1544 } 1545 focusEditorRequested(); 1546 } 1547 1548 void CellToolBase::updateEditor() 1549 { 1550 if (!d->externalEditor) { 1551 return; 1552 } 1553 const Cell cell = Cell(selection()->activeSheet(), selection()->cursor()); 1554 if (!cell) { 1555 return; 1556 } 1557 d->updateEditor(cell); 1558 } 1559 1560 void CellToolBase::focusEditorRequested() 1561 { 1562 // Nothing to do, if not in editing mode. 1563 if (!editor()) { 1564 return; 1565 } 1566 // If we are in editing mode, we redirect the focus to the CellEditor or ExternalEditor. 1567 // This screws up <Tab> though (David) 1568 if (selection()->originSheet() != selection()->activeSheet()) { 1569 // Always focus the external editor, if not on the origin sheet. 1570 if (d->externalEditor) d->externalEditor->setFocus(); 1571 } else { 1572 // Focus the last active editor, if on the origin sheet. 1573 if (d->lastEditorWithFocus == EmbeddedEditor) { 1574 editor()->widget()->setFocus(); 1575 } else { 1576 if (d->externalEditor) d->externalEditor->setFocus(); 1577 } 1578 } 1579 } 1580 1581 void CellToolBase::applyUserInput(const QString &userInput, bool expandMatrix) 1582 { 1583 QString text = userInput; 1584 if (!text.isEmpty() && text.at(0) == '=') { 1585 //a formula 1586 int openParenthese = text.count('('); 1587 int closeParenthese = text.count(')'); 1588 int diff = qAbs(openParenthese - closeParenthese); 1589 if (openParenthese > closeParenthese) { 1590 for (int i = 0; i < diff; ++i) { 1591 text += ')'; 1592 } 1593 } 1594 } 1595 DataManipulator* command = new DataManipulator(); 1596 command->setSheet(selection()->activeSheet()); 1597 command->setValue(Value(text)); 1598 command->setParsing(true); 1599 command->setExpandMatrix(expandMatrix); 1600 command->add(expandMatrix ? *selection() : Region(selection()->cursor(), selection()->activeSheet())); 1601 command->execute(canvas()); 1602 1603 if (expandMatrix && selection()->isSingular()) 1604 selection()->initialize(*command); 1605 1606 Cell cell = Cell(selection()->activeSheet(), selection()->marker()); 1607 if (cell.value().isString() && !text.isEmpty() && !text.at(0).isDigit() && !cell.isFormula()) { 1608 selection()->activeSheet()->map()->addStringCompletion(text); 1609 } 1610 } 1611 1612 void CellToolBase::documentReadWriteToggled(bool readWrite) 1613 { 1614 d->setProtectedActionsEnabled(readWrite); 1615 } 1616 1617 void CellToolBase::sheetProtectionToggled(bool protect) 1618 { 1619 d->setProtectedActionsEnabled(!protect); 1620 } 1621 1622 void CellToolBase::cellStyle() 1623 { 1624 QPointer<CellFormatDialog> dialog = new CellFormatDialog(canvas()->canvasWidget(), selection()); 1625 dialog->exec(); 1626 delete dialog; 1627 } 1628 1629 void CellToolBase::setDefaultStyle() 1630 { 1631 StyleCommand* command = new StyleCommand(); 1632 command->setSheet(selection()->activeSheet()); 1633 command->setDefault(); 1634 command->add(*selection()); 1635 command->execute(canvas()); 1636 } 1637 1638 void CellToolBase::styleDialog() 1639 { 1640 Map* const map = selection()->activeSheet()->map(); 1641 StyleManager* const styleManager = map->styleManager(); 1642 QPointer<StyleManagerDialog> dialog = new StyleManagerDialog(canvas()->canvasWidget(), selection(), styleManager); 1643 dialog->exec(); 1644 delete dialog; 1645 1646 static_cast<KSelectAction*>(action("setStyle"))->setItems(styleManager->styleNames()); 1647 if (selection()->activeSheet()) 1648 map->addDamage(new CellDamage(selection()->activeSheet(), Region(1, 1, maxCol(), maxRow()), CellDamage::Appearance)); 1649 canvas()->canvasWidget()->update(); 1650 } 1651 1652 void CellToolBase::setStyle(const QString& stylename) 1653 { 1654 debugSheets << "CellToolBase::setStyle(" << stylename << ")"; 1655 if (selection()->activeSheet()->map()->styleManager()->style(stylename)) { 1656 StyleCommand* command = new StyleCommand(); 1657 command->setSheet(selection()->activeSheet()); 1658 command->setParentName(stylename); 1659 command->add(*selection()); 1660 command->execute(canvas()); 1661 } 1662 } 1663 1664 void CellToolBase::createStyleFromCell() 1665 { 1666 QPoint p(selection()->marker()); 1667 Cell cell = Cell(selection()->activeSheet(), p.x(), p.y()); 1668 1669 bool ok = false; 1670 QString styleName(""); 1671 1672 while (true) { 1673 styleName = QInputDialog::getText(canvas()->canvasWidget(), 1674 i18n("Create Style From Cell"), 1675 i18n("Enter name:"), QLineEdit::Normal, styleName, &ok); 1676 1677 if (!ok) // User pushed an OK button. 1678 return; 1679 1680 styleName = styleName.trimmed(); 1681 1682 if (styleName.length() < 1) { 1683 KMessageBox::sorry(canvas()->canvasWidget(), i18n("The style name cannot be empty.")); 1684 continue; 1685 } 1686 1687 if (selection()->activeSheet()->map()->styleManager()->style(styleName) != 0) { 1688 KMessageBox::sorry(canvas()->canvasWidget(), i18n("A style with this name already exists.")); 1689 continue; 1690 } 1691 break; 1692 } 1693 1694 const Style cellStyle = cell.style(); 1695 CustomStyle* style = new CustomStyle(styleName); 1696 style->merge(cellStyle); 1697 1698 selection()->activeSheet()->map()->styleManager()->insertStyle(style); 1699 cell.setStyle(*style); 1700 QStringList functionList(static_cast<KSelectAction*>(action("setStyle"))->items()); 1701 functionList.push_back(styleName); 1702 static_cast<KSelectAction*>(action("setStyle"))->setItems(functionList); 1703 } 1704 1705 void CellToolBase::bold(bool enable) 1706 { 1707 StyleCommand* command = new StyleCommand(); 1708 command->setSheet(selection()->activeSheet()); 1709 command->setText(kundo2_i18n("Change Font")); 1710 command->setFontBold(enable); 1711 command->add(*selection()); 1712 command->execute(canvas()); 1713 if (editor()) { 1714 const Cell cell = Cell(selection()->activeSheet(), selection()->marker()); 1715 editor()->setEditorFont(cell.style().font(), true, canvas()->viewConverter()); 1716 } 1717 } 1718 1719 void CellToolBase::underline(bool enable) 1720 { 1721 StyleCommand* command = new StyleCommand(); 1722 command->setSheet(selection()->activeSheet()); 1723 command->setText(kundo2_i18n("Change Font")); 1724 command->setFontUnderline(enable); 1725 command->add(*selection()); 1726 command->execute(canvas()); 1727 if (editor()) { 1728 const Cell cell = Cell(selection()->activeSheet(), selection()->marker()); 1729 editor()->setEditorFont(cell.style().font(), true, canvas()->viewConverter()); 1730 } 1731 } 1732 1733 void CellToolBase::strikeOut(bool enable) 1734 { 1735 StyleCommand* command = new StyleCommand(); 1736 command->setSheet(selection()->activeSheet()); 1737 command->setText(kundo2_i18n("Change Font")); 1738 command->setFontStrike(enable); 1739 command->add(*selection()); 1740 command->execute(canvas()); 1741 if (editor()) { 1742 const Cell cell = Cell(selection()->activeSheet(), selection()->marker()); 1743 editor()->setEditorFont(cell.style().font(), true, canvas()->viewConverter()); 1744 } 1745 } 1746 1747 1748 void CellToolBase::italic(bool enable) 1749 { 1750 StyleCommand* command = new StyleCommand(); 1751 command->setSheet(selection()->activeSheet()); 1752 command->setText(kundo2_i18n("Change Font")); 1753 command->setFontItalic(enable); 1754 command->add(*selection()); 1755 command->execute(canvas()); 1756 if (editor()) { 1757 const Cell cell = Cell(selection()->activeSheet(), selection()->marker()); 1758 editor()->setEditorFont(cell.style().font(), true, canvas()->viewConverter()); 1759 } 1760 } 1761 1762 void CellToolBase::font(const QString& font) 1763 { 1764 StyleCommand* command = new StyleCommand(); 1765 command->setSheet(selection()->activeSheet()); 1766 command->setText(kundo2_i18n("Change Font")); 1767 command->setFontFamily(font.toLatin1()); 1768 command->add(*selection()); 1769 command->execute(canvas()); 1770 // Don't leave the focus in the toolbars combo box ... 1771 if (editor()) { 1772 const Style style = Cell(selection()->activeSheet(), selection()->marker()).style(); 1773 editor()->setEditorFont(style.font(), true, canvas()->viewConverter()); 1774 focusEditorRequested(); 1775 } else { 1776 canvas()->canvasWidget()->setFocus(); 1777 } 1778 } 1779 1780 void CellToolBase::fontSize(int size) 1781 { 1782 StyleCommand* command = new StyleCommand(); 1783 command->setSheet(selection()->activeSheet()); 1784 command->setText(kundo2_i18n("Change Font")); 1785 command->setFontSize(size); 1786 command->add(*selection()); 1787 command->execute(canvas()); 1788 // Don't leave the focus in the toolbars combo box ... 1789 if (editor()) { 1790 const Cell cell(selection()->activeSheet(), selection()->marker()); 1791 editor()->setEditorFont(cell.style().font(), true, canvas()->viewConverter()); 1792 focusEditorRequested(); 1793 } else { 1794 canvas()->canvasWidget()->setFocus(); 1795 } 1796 } 1797 1798 void CellToolBase::increaseFontSize() 1799 { 1800 const Style style = Cell(selection()->activeSheet(), selection()->marker()).style(); 1801 const int size = style.fontSize(); 1802 1803 StyleCommand* command = new StyleCommand(); 1804 command->setSheet(selection()->activeSheet()); 1805 command->setText(kundo2_i18n("Change Font")); 1806 command->setFontSize(size + 1); 1807 command->add(*selection()); 1808 command->execute(canvas()); 1809 } 1810 1811 void CellToolBase::decreaseFontSize() 1812 { 1813 const Style style = Cell(selection()->activeSheet(), selection()->marker()).style(); 1814 const int size = style.fontSize(); 1815 1816 StyleCommand* command = new StyleCommand(); 1817 command->setSheet(selection()->activeSheet()); 1818 command->setText(kundo2_i18n("Change Font")); 1819 command->setFontSize(size - 1); 1820 command->add(*selection()); 1821 command->execute(canvas()); 1822 } 1823 1824 void CellToolBase::changeTextColor(const KoColor &color) 1825 { 1826 StyleCommand* command = new StyleCommand(); 1827 command->setSheet(selection()->activeSheet()); 1828 command->setText(kundo2_i18n("Change Text Color")); 1829 command->setFontColor(color.toQColor()); 1830 command->add(*selection()); 1831 command->execute(canvas()); 1832 } 1833 1834 void CellToolBase::alignLeft(bool enable) 1835 { 1836 StyleCommand* command = new StyleCommand(); 1837 command->setSheet(selection()->activeSheet()); 1838 command->setText(kundo2_i18n("Change Horizontal Alignment")); 1839 command->setHorizontalAlignment(enable ? Style::Left : Style::HAlignUndefined); 1840 command->add(*selection()); 1841 command->execute(canvas()); 1842 } 1843 1844 void CellToolBase::alignRight(bool enable) 1845 { 1846 StyleCommand* command = new StyleCommand(); 1847 command->setSheet(selection()->activeSheet()); 1848 command->setText(kundo2_i18n("Change Horizontal Alignment")); 1849 command->setHorizontalAlignment(enable ? Style::Right : Style::HAlignUndefined); 1850 command->add(*selection()); 1851 command->execute(canvas()); 1852 } 1853 1854 void CellToolBase::alignCenter(bool enable) 1855 { 1856 StyleCommand* command = new StyleCommand(); 1857 command->setSheet(selection()->activeSheet()); 1858 command->setText(kundo2_i18n("Change Horizontal Alignment")); 1859 command->setHorizontalAlignment(enable ? Style::Center : Style::HAlignUndefined); 1860 command->add(*selection()); 1861 command->execute(canvas()); 1862 } 1863 1864 void CellToolBase::alignTop(bool enable) 1865 { 1866 StyleCommand* command = new StyleCommand(); 1867 command->setSheet(selection()->activeSheet()); 1868 command->setText(kundo2_i18n("Change Vertical Alignment")); 1869 command->setVerticalAlignment(enable ? Style::Top : Style::VAlignUndefined); 1870 command->add(*selection()); 1871 command->execute(canvas()); 1872 } 1873 1874 void CellToolBase::alignBottom(bool enable) 1875 { 1876 StyleCommand* command = new StyleCommand(); 1877 command->setSheet(selection()->activeSheet()); 1878 command->setText(kundo2_i18n("Change Vertical Alignment")); 1879 command->setVerticalAlignment(enable ? Style::Bottom : Style::VAlignUndefined); 1880 command->add(*selection()); 1881 command->execute(canvas()); 1882 } 1883 1884 void CellToolBase::alignMiddle(bool enable) 1885 { 1886 StyleCommand* command = new StyleCommand(); 1887 command->setSheet(selection()->activeSheet()); 1888 command->setText(kundo2_i18n("Change Vertical Alignment")); 1889 command->setVerticalAlignment(enable ? Style::Middle : Style::VAlignUndefined); 1890 command->add(*selection()); 1891 command->execute(canvas()); 1892 } 1893 1894 void CellToolBase::borderLeft() 1895 { 1896 QColor color = static_cast<KoColorPopupAction*>(action("borderColor"))->currentColor(); 1897 StyleCommand* command = new StyleCommand(); 1898 command->setSheet(selection()->activeSheet()); 1899 command->setText(kundo2_i18n("Change Border")); 1900 if (selection()->activeSheet()->layoutDirection() == Qt::RightToLeft) 1901 command->setRightBorderPen(QPen(color, 1, Qt::SolidLine)); 1902 else 1903 command->setLeftBorderPen(QPen(color, 1, Qt::SolidLine)); 1904 command->add(*selection()); 1905 command->execute(canvas()); 1906 } 1907 1908 void CellToolBase::borderRight() 1909 { 1910 QColor color = static_cast<KoColorPopupAction*>(action("borderColor"))->currentColor(); 1911 StyleCommand* command = new StyleCommand(); 1912 command->setSheet(selection()->activeSheet()); 1913 command->setText(kundo2_i18n("Change Border")); 1914 if (selection()->activeSheet()->layoutDirection() == Qt::RightToLeft) 1915 command->setLeftBorderPen(QPen(color, 1, Qt::SolidLine)); 1916 else 1917 command->setRightBorderPen(QPen(color, 1, Qt::SolidLine)); 1918 command->add(*selection()); 1919 command->execute(canvas()); 1920 } 1921 1922 void CellToolBase::borderTop() 1923 { 1924 QColor color = static_cast<KoColorPopupAction*>(action("borderColor"))->currentColor(); 1925 StyleCommand* command = new StyleCommand(); 1926 command->setSheet(selection()->activeSheet()); 1927 command->setText(kundo2_i18n("Change Border")); 1928 command->setTopBorderPen(QPen(color, 1, Qt::SolidLine)); 1929 command->add(*selection()); 1930 command->execute(canvas()); 1931 } 1932 1933 void CellToolBase::borderBottom() 1934 { 1935 QColor color = static_cast<KoColorPopupAction*>(action("borderColor"))->currentColor(); 1936 StyleCommand* command = new StyleCommand(); 1937 command->setSheet(selection()->activeSheet()); 1938 command->setText(kundo2_i18n("Change Border")); 1939 command->setBottomBorderPen(QPen(color, 1, Qt::SolidLine)); 1940 command->add(*selection()); 1941 command->execute(canvas()); 1942 } 1943 1944 void CellToolBase::borderAll() 1945 { 1946 QColor color = static_cast<KoColorPopupAction*>(action("borderColor"))->currentColor(); 1947 StyleCommand* command = new StyleCommand(); 1948 command->setSheet(selection()->activeSheet()); 1949 command->setText(kundo2_i18n("Change Border")); 1950 command->setTopBorderPen(QPen(color, 1, Qt::SolidLine)); 1951 command->setBottomBorderPen(QPen(color, 1, Qt::SolidLine)); 1952 command->setLeftBorderPen(QPen(color, 1, Qt::SolidLine)); 1953 command->setRightBorderPen(QPen(color, 1, Qt::SolidLine)); 1954 command->setHorizontalPen(QPen(color, 1, Qt::SolidLine)); 1955 command->setVerticalPen(QPen(color, 1, Qt::SolidLine)); 1956 command->add(*selection()); 1957 command->execute(canvas()); 1958 } 1959 1960 void CellToolBase::borderRemove() 1961 { 1962 StyleCommand* command = new StyleCommand(); 1963 command->setSheet(selection()->activeSheet()); 1964 command->setText(kundo2_i18n("Change Border")); 1965 command->setTopBorderPen(QPen(Qt::NoPen)); 1966 command->setBottomBorderPen(QPen(Qt::NoPen)); 1967 command->setLeftBorderPen(QPen(Qt::NoPen)); 1968 command->setRightBorderPen(QPen(Qt::NoPen)); 1969 command->setHorizontalPen(QPen(Qt::NoPen)); 1970 command->setVerticalPen(QPen(Qt::NoPen)); 1971 command->add(*selection()); 1972 command->execute(canvas()); 1973 } 1974 1975 void CellToolBase::borderOutline() 1976 { 1977 QColor color = static_cast<KoColorPopupAction*>(action("borderColor"))->currentColor(); 1978 StyleCommand* command = new StyleCommand(); 1979 command->setSheet(selection()->activeSheet()); 1980 command->setText(kundo2_i18n("Change Border")); 1981 command->setTopBorderPen(QPen(color, 1, Qt::SolidLine)); 1982 command->setBottomBorderPen(QPen(color, 1, Qt::SolidLine)); 1983 command->setLeftBorderPen(QPen(color, 1, Qt::SolidLine)); 1984 command->setRightBorderPen(QPen(color, 1, Qt::SolidLine)); 1985 command->add(*selection()); 1986 command->execute(canvas()); 1987 } 1988 1989 void CellToolBase::borderColor(const KoColor &color) 1990 { 1991 BorderColorCommand* command = new BorderColorCommand(); 1992 command->setSheet(selection()->activeSheet()); 1993 command->setColor(color.toQColor()); 1994 command->add(*selection()); 1995 command->execute(canvas()); 1996 } 1997 1998 void CellToolBase::wrapText(bool enable) 1999 { 2000 StyleCommand* command = new StyleCommand(); 2001 command->setSheet(selection()->activeSheet()); 2002 command->setText(kundo2_i18n("Wrap Text")); 2003 command->setMultiRow(enable); 2004 command->setVerticalText(false); 2005 command->setAngle(0); 2006 command->add(*selection()); 2007 command->execute(canvas()); 2008 } 2009 2010 void CellToolBase::verticalText(bool enable) 2011 { 2012 StyleCommand* command = new StyleCommand(); 2013 command->setSheet(selection()->activeSheet()); 2014 command->setText(kundo2_i18n("Vertical Text")); 2015 command->setVerticalText(enable); 2016 command->setMultiRow(false); 2017 command->setAngle(0); 2018 command->add(*selection()); 2019 command->execute(canvas()); 2020 } 2021 2022 void CellToolBase::increaseIndentation() 2023 { 2024 IndentationCommand* command = new IndentationCommand(); 2025 command->setSheet(selection()->activeSheet()); 2026 command->add(*selection()); 2027 if (!command->execute()) 2028 delete command; 2029 } 2030 2031 void CellToolBase::decreaseIndentation() 2032 { 2033 IndentationCommand* command = new IndentationCommand(); 2034 command->setSheet(selection()->activeSheet()); 2035 command->setReverse(true); 2036 command->add(*selection()); 2037 if (!command->execute()) 2038 delete command; 2039 } 2040 2041 void CellToolBase::changeAngle() 2042 { 2043 QPointer<AngleDialog> dialog = new AngleDialog(canvas()->canvasWidget(), selection()); 2044 dialog->exec(); 2045 delete dialog; 2046 } 2047 2048 void CellToolBase::percent(bool enable) 2049 { 2050 StyleCommand* command = new StyleCommand(); 2051 command->setSheet(selection()->activeSheet()); 2052 command->setText(kundo2_i18n("Format Percent")); 2053 command->setFormatType(enable ? Format::Percentage : Format::Generic); 2054 command->add(*selection()); 2055 command->execute(canvas()); 2056 } 2057 2058 void CellToolBase::currency(bool enable) 2059 { 2060 StyleCommand* command = new StyleCommand(); 2061 command->setSheet(selection()->activeSheet()); 2062 command->setText(kundo2_i18n("Format Money")); 2063 command->setFormatType(enable ? Format::Money : Format::Generic); 2064 command->setPrecision(enable ? selection()->activeSheet()->map()->calculationSettings()->locale()->monetaryDecimalPlaces() : 0); 2065 2066 command->add(*selection()); 2067 command->execute(canvas()); 2068 } 2069 2070 void CellToolBase::increasePrecision() 2071 { 2072 PrecisionCommand* command = new PrecisionCommand(); 2073 command->setSheet(selection()->activeSheet()); 2074 command->add(*selection()); 2075 if (!command->execute()) 2076 delete command; 2077 } 2078 2079 void CellToolBase::decreasePrecision() 2080 { 2081 PrecisionCommand* command = new PrecisionCommand(); 2082 command->setSheet(selection()->activeSheet()); 2083 command->setReverse(true); 2084 command->add(*selection()); 2085 if (!command->execute()) 2086 delete command; 2087 } 2088 2089 void CellToolBase::toUpperCase() 2090 { 2091 CaseManipulator* command = new CaseManipulator; 2092 command->setSheet(selection()->activeSheet()); 2093 command->setText(kundo2_i18n("Switch to uppercase")); 2094 command->changeMode(CaseManipulator::Upper); 2095 command->add(*selection()); 2096 command->execute(canvas()); 2097 } 2098 2099 void CellToolBase::toLowerCase() 2100 { 2101 CaseManipulator* command = new CaseManipulator; 2102 command->setSheet(selection()->activeSheet()); 2103 command->setText(kundo2_i18n("Switch to lowercase")); 2104 command->changeMode(CaseManipulator::Lower); 2105 command->add(*selection()); 2106 command->execute(canvas()); 2107 } 2108 2109 void CellToolBase::firstLetterToUpperCase() 2110 { 2111 CaseManipulator* command = new CaseManipulator; 2112 command->setSheet(selection()->activeSheet()); 2113 command->setText(kundo2_i18n("First letter uppercase")); 2114 command->changeMode(CaseManipulator::FirstUpper); 2115 command->add(*selection()); 2116 command->execute(canvas()); 2117 } 2118 2119 void CellToolBase::changeBackgroundColor(const KoColor &color) 2120 { 2121 StyleCommand* command = new StyleCommand(); 2122 command->setSheet(selection()->activeSheet()); 2123 command->setText(kundo2_i18n("Change Background Color")); 2124 command->setBackgroundColor(color.toQColor()); 2125 command->add(*selection()); 2126 command->execute(canvas()); 2127 } 2128 2129 void CellToolBase::mergeCells() 2130 { 2131 // sanity check 2132 if (selection()->activeSheet()->isProtected()) { 2133 return; 2134 } 2135 if (selection()->activeSheet()->map()->isProtected()) { 2136 return; 2137 } 2138 MergeCommand* const command = new MergeCommand(); 2139 command->setSheet(selection()->activeSheet()); 2140 command->setSelection(selection()); 2141 command->setHorizontalMerge(false); 2142 command->setVerticalMerge(false); 2143 command->add(*selection()); 2144 command->execute(canvas()); 2145 } 2146 2147 void CellToolBase::mergeCellsHorizontal() 2148 { 2149 // sanity check 2150 if (selection()->activeSheet()->isProtected()) { 2151 return; 2152 } 2153 if (selection()->activeSheet()->map()->isProtected()) { 2154 return; 2155 } 2156 MergeCommand* const command = new MergeCommand(); 2157 command->setSheet(selection()->activeSheet()); 2158 command->setHorizontalMerge(true); 2159 command->setVerticalMerge(false); 2160 command->setSelection(selection()); 2161 command->add(*selection()); 2162 command->execute(canvas()); 2163 } 2164 2165 void CellToolBase::mergeCellsVertical() 2166 { 2167 // sanity check 2168 if (selection()->activeSheet()->isProtected()) { 2169 return; 2170 } 2171 if (selection()->activeSheet()->map()->isProtected()) { 2172 return; 2173 } 2174 MergeCommand* const command = new MergeCommand(); 2175 command->setSheet(selection()->activeSheet()); 2176 command->setHorizontalMerge(false); 2177 command->setVerticalMerge(true); 2178 command->setSelection(selection()); 2179 command->add(*selection()); 2180 command->execute(canvas()); 2181 } 2182 2183 void CellToolBase::dissociateCells() 2184 { 2185 // sanity check 2186 if (selection()->activeSheet()->isProtected()) { 2187 return; 2188 } 2189 if (selection()->activeSheet()->map()->isProtected()) { 2190 return; 2191 } 2192 MergeCommand* const command = new MergeCommand(); 2193 command->setSheet(selection()->activeSheet()); 2194 command->setReverse(true); 2195 command->setSelection(selection()); 2196 command->add(*selection()); 2197 command->execute(canvas()); 2198 } 2199 2200 void CellToolBase::resizeColumn() 2201 { 2202 if (selection()->isRowSelected()) 2203 KMessageBox::error(canvas()->canvasWidget(), i18n("Area is too large.")); 2204 else { 2205 QPointer<ResizeColumn> dialog = new ResizeColumn(canvas()->canvasWidget(), selection()); 2206 dialog->exec(); 2207 delete dialog; 2208 } 2209 } 2210 2211 void CellToolBase::insertColumn() 2212 { 2213 InsertDeleteColumnManipulator* command = new InsertDeleteColumnManipulator(); 2214 command->setSheet(selection()->activeSheet()); 2215 command->add(*selection()); 2216 command->execute(canvas()); 2217 } 2218 2219 void CellToolBase::deleteColumn() 2220 { 2221 InsertDeleteColumnManipulator* command = new InsertDeleteColumnManipulator(); 2222 command->setSheet(selection()->activeSheet()); 2223 command->setReverse(true); 2224 command->add(*selection()); 2225 command->execute(canvas()); 2226 } 2227 2228 void CellToolBase::hideColumn() 2229 { 2230 if (selection()->isRowSelected()) { 2231 KMessageBox::error(canvas()->canvasWidget(), i18n("Area is too large.")); 2232 return; 2233 } 2234 2235 HideShowManipulator* command = new HideShowManipulator(); 2236 command->setSheet(selection()->activeSheet()); 2237 command->setManipulateColumns(true); 2238 command->add(*selection()); 2239 command->execute(canvas()); 2240 } 2241 2242 void CellToolBase::showColumn() 2243 { 2244 if (selection()->isRowSelected()) { 2245 KMessageBox::error(canvas()->canvasWidget(), i18n("Area is too large.")); 2246 return; 2247 } 2248 2249 HideShowManipulator* command = new HideShowManipulator(); 2250 command->setSheet(selection()->activeSheet()); 2251 command->setManipulateColumns(true); 2252 command->setReverse(true); 2253 command->add(*selection()); 2254 command->execute(canvas()); 2255 } 2256 2257 void CellToolBase::slotShowColumnDialog() 2258 { 2259 QPointer<ShowColRow> dialog = new ShowColRow(canvas()->canvasWidget(), selection(), ShowColRow::Column); 2260 dialog->exec(); 2261 delete dialog; 2262 } 2263 2264 void CellToolBase::equalizeColumn() 2265 { 2266 if (selection()->isRowSelected()) 2267 KMessageBox::error(canvas()->canvasWidget(), i18n("Area is too large.")); 2268 else { 2269 const QRect range = selection()->lastRange(); 2270 const ColumnFormat* columnFormat = selection()->activeSheet()->columnFormat(range.left()); 2271 double size = columnFormat->width(); 2272 if (range.left() == range.right()) 2273 return; 2274 for (int i = range.left() + 1; i <= range.right(); ++i) 2275 size = qMax(selection()->activeSheet()->columnFormat(i)->width(), size); 2276 2277 if (size != 0.0) { 2278 ResizeColumnManipulator* command = new ResizeColumnManipulator(); 2279 command->setSheet(selection()->activeSheet()); 2280 command->setSize(qMax(2.0, size)); 2281 command->add(*selection()); 2282 if (!command->execute()) 2283 delete command; 2284 } else { // hide 2285 HideShowManipulator* command = new HideShowManipulator(); 2286 command->setSheet(selection()->activeSheet()); 2287 command->setManipulateColumns(true); 2288 command->add(*selection()); 2289 if (!command->execute()) 2290 delete command; 2291 } 2292 } 2293 } 2294 2295 void CellToolBase::adjustColumn() 2296 { 2297 AdjustColumnRowManipulator* command = new AdjustColumnRowManipulator(); 2298 command->setSheet(selection()->activeSheet()); 2299 command->setAdjustColumn(true); 2300 command->add(*selection()); 2301 command->execute(canvas()); 2302 } 2303 2304 void CellToolBase::resizeRow() 2305 { 2306 if (selection()->isColumnSelected()) 2307 KMessageBox::error(canvas()->canvasWidget(), i18n("Area is too large.")); 2308 else { 2309 QPointer<ResizeRow> dialog = new ResizeRow(canvas()->canvasWidget(), selection()); 2310 dialog->exec(); 2311 delete dialog; 2312 } 2313 } 2314 2315 void CellToolBase::insertRow() 2316 { 2317 InsertDeleteRowManipulator* command = new InsertDeleteRowManipulator(); 2318 command->setSheet(selection()->activeSheet()); 2319 command->add(*selection()); 2320 command->execute(canvas()); 2321 } 2322 2323 void CellToolBase::deleteRow() 2324 { 2325 InsertDeleteRowManipulator* command = new InsertDeleteRowManipulator(); 2326 command->setSheet(selection()->activeSheet()); 2327 command->setReverse(true); 2328 command->add(*selection()); 2329 command->execute(canvas()); 2330 } 2331 2332 void CellToolBase::hideRow() 2333 { 2334 if (selection()->isColumnSelected()) { 2335 KMessageBox::error(canvas()->canvasWidget(), i18n("Area is too large.")); 2336 return; 2337 } 2338 2339 HideShowManipulator* command = new HideShowManipulator(); 2340 command->setSheet(selection()->activeSheet()); 2341 command->setManipulateRows(true); 2342 command->add(*selection()); 2343 command->execute(canvas()); 2344 } 2345 2346 void CellToolBase::showRow() 2347 { 2348 if (selection()->isColumnSelected()) { 2349 KMessageBox::error(canvas()->canvasWidget(), i18n("Area is too large.")); 2350 return; 2351 } 2352 2353 HideShowManipulator* command = new HideShowManipulator(); 2354 command->setSheet(selection()->activeSheet()); 2355 command->setManipulateRows(true); 2356 command->setReverse(true); 2357 command->add(*selection()); 2358 command->execute(canvas()); 2359 } 2360 2361 void CellToolBase::slotShowRowDialog() 2362 { 2363 QPointer<ShowColRow> dialog = new ShowColRow(canvas()->canvasWidget(), selection(), ShowColRow::Row); 2364 dialog->exec(); 2365 delete dialog; 2366 } 2367 2368 void CellToolBase::equalizeRow() 2369 { 2370 if (selection()->isColumnSelected()) 2371 KMessageBox::error(canvas()->canvasWidget(), i18n("Area is too large.")); 2372 else { 2373 const QRect range = selection()->lastRange(); 2374 qreal size = selection()->activeSheet()->rowFormats()->rowHeight(range.top()); 2375 if (range.top() == range.bottom()) 2376 return; 2377 for (int i = range.top() + 1; i <= range.bottom(); ++i) { 2378 int lastRow; 2379 size = qMax(selection()->activeSheet()->rowFormats()->rowHeight(i, &lastRow), static_cast<qreal>(size)); 2380 i = lastRow; 2381 } 2382 2383 if (size != 0.0) { 2384 ResizeRowManipulator* command = new ResizeRowManipulator(); 2385 command->setSheet(selection()->activeSheet()); 2386 command->setSize(qMax(qreal(2.0), size)); 2387 command->add(*selection()); 2388 if (!command->execute()) 2389 delete command; 2390 } else { // hide 2391 HideShowManipulator* command = new HideShowManipulator(); 2392 command->setSheet(selection()->activeSheet()); 2393 command->setManipulateRows(true); 2394 command->add(*selection()); 2395 if (!command->execute()) 2396 delete command; 2397 } 2398 } 2399 } 2400 2401 void CellToolBase::adjustRow() 2402 { 2403 AdjustColumnRowManipulator* command = new AdjustColumnRowManipulator(); 2404 command->setSheet(selection()->activeSheet()); 2405 command->setAdjustRow(true); 2406 command->add(*selection()); 2407 command->execute(canvas()); 2408 } 2409 2410 void CellToolBase::adjust() 2411 { 2412 AdjustColumnRowManipulator* command = new AdjustColumnRowManipulator(); 2413 command->setSheet(selection()->activeSheet()); 2414 command->setAdjustColumn(true); 2415 command->setAdjustRow(true); 2416 command->add(*selection()); 2417 command->execute(canvas()); 2418 } 2419 2420 void CellToolBase::insertCells() 2421 { 2422 QPointer<InsertDialog> dialog = new InsertDialog(canvas()->canvasWidget(), selection(), InsertDialog::Insert); 2423 dialog->exec(); 2424 delete dialog; 2425 } 2426 2427 void CellToolBase::deleteCells() 2428 { 2429 QPointer<InsertDialog> dialog = new InsertDialog(canvas()->canvasWidget(), selection(), InsertDialog::Remove); 2430 dialog->exec(); 2431 delete dialog; 2432 } 2433 2434 void CellToolBase::clearAll() 2435 { 2436 DeleteCommand* command = new DeleteCommand(); 2437 command->setSheet(selection()->activeSheet()); 2438 command->add(*selection()); 2439 command->execute(canvas()); 2440 } 2441 2442 void CellToolBase::clearContents() 2443 { 2444 // TODO Stefan: Actually this check belongs into the command! 2445 if (selection()->activeSheet()->areaIsEmpty(*selection())) 2446 return; 2447 2448 DataManipulator* command = new DataManipulator(); 2449 command->setSheet(selection()->activeSheet()); 2450 command->setText(kundo2_i18n("Clear Text")); 2451 // parsing gets set only so that parseUserInput is called as it should be, 2452 // no actual parsing shall be done 2453 command->setParsing(true); 2454 command->setValue(Value("")); 2455 command->add(*selection()); 2456 command->execute(canvas()); 2457 } 2458 2459 void CellToolBase::comment() 2460 { 2461 QPointer<CommentDialog> dialog = new CommentDialog(canvas()->canvasWidget(), selection()); 2462 dialog->exec(); 2463 delete dialog; 2464 } 2465 2466 void CellToolBase::clearComment() 2467 { 2468 // TODO Stefan: Actually this check belongs into the command! 2469 if (selection()->activeSheet()->areaIsEmpty(*selection(), Sheet::Comment)) 2470 return; 2471 2472 CommentCommand* command = new CommentCommand(); 2473 command->setSheet(selection()->activeSheet()); 2474 command->setText(kundo2_i18n("Remove Comment")); 2475 command->setComment(QString()); 2476 command->add(*selection()); 2477 command->execute(canvas()); 2478 } 2479 2480 void CellToolBase::conditional() 2481 { 2482 QPointer<ConditionalDialog> dialog = new ConditionalDialog(canvas()->canvasWidget(), selection()); 2483 dialog->exec(); 2484 delete dialog; 2485 } 2486 2487 void CellToolBase::clearConditionalStyles() 2488 { 2489 // TODO Stefan: Actually this check belongs into the command! 2490 if (selection()->activeSheet()->areaIsEmpty(*selection(), Sheet::ConditionalCellAttribute)) 2491 return; 2492 2493 ConditionCommand* command = new ConditionCommand(); 2494 command->setSheet(selection()->activeSheet()); 2495 command->setConditionList(QLinkedList<Conditional>()); 2496 command->add(*selection()); 2497 command->execute(canvas()); 2498 } 2499 2500 void CellToolBase::insertHyperlink() 2501 { 2502 selection()->emitAboutToModify(); 2503 2504 QPoint marker(selection()->marker()); 2505 Cell cell(selection()->activeSheet(), marker); 2506 2507 QPointer<LinkDialog> dialog = new LinkDialog(canvas()->canvasWidget(), selection()); 2508 dialog->setWindowTitle(i18n("Insert Link")); 2509 if (!cell.isNull()) { 2510 dialog->setText(cell.userInput()); 2511 if (!cell.link().isEmpty()) { 2512 dialog->setWindowTitle(i18n("Edit Link")); 2513 dialog->setLink(cell.link()); 2514 } 2515 } 2516 2517 if (dialog->exec() == KoDialog::Accepted) { 2518 cell = Cell(selection()->activeSheet(), marker); 2519 2520 LinkCommand* command = new LinkCommand(cell, dialog->text(), dialog->link()); 2521 canvas()->addCommand(command); 2522 2523 //refresh editWidget 2524 selection()->emitModified(); 2525 } 2526 delete dialog; 2527 } 2528 2529 void CellToolBase::clearHyperlink() 2530 { 2531 QPoint marker(selection()->marker()); 2532 Cell cell(selection()->activeSheet(), marker); 2533 if (!cell) 2534 return; 2535 if (cell.link().isEmpty()) 2536 return; 2537 2538 LinkCommand* command = new LinkCommand(cell, QString(), QString()); 2539 canvas()->addCommand(command); 2540 2541 selection()->emitModified(); 2542 } 2543 2544 void CellToolBase::validity() 2545 { 2546 QPointer<ValidityDialog> dialog = new ValidityDialog(canvas()->canvasWidget(), selection()); 2547 dialog->exec(); 2548 delete dialog; 2549 } 2550 2551 void CellToolBase::clearValidity() 2552 { 2553 // TODO Stefan: Actually this check belongs into the command! 2554 if (selection()->activeSheet()->areaIsEmpty(*selection(), Sheet::Validity)) 2555 return; 2556 2557 ValidityCommand* command = new ValidityCommand(); 2558 command->setSheet(selection()->activeSheet()); 2559 command->setValidity(Validity()); // empty object removes validity 2560 command->add(*selection()); 2561 command->execute(canvas()); 2562 } 2563 2564 void CellToolBase::sort() 2565 { 2566 if (selection()->isSingular()) { 2567 KMessageBox::error(canvas()->canvasWidget(), i18n("You must select multiple cells.")); 2568 return; 2569 } 2570 2571 QPointer<SortDialog> dialog = new SortDialog(canvas()->canvasWidget(), selection()); 2572 dialog->exec(); 2573 delete dialog; 2574 } 2575 2576 void CellToolBase::sortInc() 2577 { 2578 if (selection()->isSingular()) { 2579 KMessageBox::error(canvas()->canvasWidget(), i18n("You must select multiple cells.")); 2580 return; 2581 } 2582 2583 SortManipulator* command = new SortManipulator(); 2584 command->setSheet(selection()->activeSheet()); 2585 2586 // Entire row(s) selected ? Or just one row ? Sort by columns if yes. 2587 QRect range = selection()->lastRange(); 2588 bool sortCols = selection()->isRowSelected(); 2589 sortCols = sortCols || (range.top() == range.bottom()); 2590 command->setSortRows(!sortCols); 2591 command->addCriterion(0, Qt::AscendingOrder, Qt::CaseInsensitive); 2592 command->add(*selection()); 2593 command->execute(canvas()); 2594 2595 selection()->emitModified(); 2596 } 2597 2598 void CellToolBase::sortDec() 2599 { 2600 if (selection()->isSingular()) { 2601 KMessageBox::error(canvas()->canvasWidget(), i18n("You must select multiple cells.")); 2602 return; 2603 } 2604 2605 SortManipulator* command = new SortManipulator(); 2606 command->setSheet(selection()->activeSheet()); 2607 2608 // Entire row(s) selected ? Or just one row ? Sort by rows if yes. 2609 QRect range = selection()->lastRange(); 2610 bool sortCols = selection()->isRowSelected(); 2611 sortCols = sortCols || (range.top() == range.bottom()); 2612 command->setSortRows(!sortCols); 2613 command->addCriterion(0, Qt::DescendingOrder, Qt::CaseInsensitive); 2614 command->add(*selection()); 2615 command->execute(canvas()); 2616 2617 selection()->emitModified(); 2618 } 2619 2620 void CellToolBase::autoFilter() 2621 { 2622 AutoFilterCommand* command = new AutoFilterCommand(); 2623 command->setSheet(selection()->activeSheet()); 2624 command->add(*selection()); 2625 command->execute(canvas()); 2626 } 2627 2628 void CellToolBase::fillLeft() 2629 { 2630 FillManipulator* command = new FillManipulator(); 2631 command->setSheet(selection()->activeSheet()); 2632 command->setDirection(FillManipulator::Left); 2633 command->add(*selection()); 2634 command->execute(canvas()); 2635 } 2636 2637 void CellToolBase::fillRight() 2638 { 2639 FillManipulator* command = new FillManipulator(); 2640 command->setSheet(selection()->activeSheet()); 2641 command->setDirection(FillManipulator::Right); 2642 command->add(*selection()); 2643 command->execute(canvas()); 2644 } 2645 2646 void CellToolBase::fillUp() 2647 { 2648 FillManipulator* command = new FillManipulator(); 2649 command->setSheet(selection()->activeSheet()); 2650 command->setDirection(FillManipulator::Up); 2651 command->add(*selection()); 2652 command->execute(canvas()); 2653 } 2654 2655 void CellToolBase::fillDown() 2656 { 2657 FillManipulator* command = new FillManipulator(); 2658 command->setSheet(selection()->activeSheet()); 2659 command->setDirection(FillManipulator::Down); 2660 command->add(*selection()); 2661 command->execute(canvas()); 2662 } 2663 2664 void CellToolBase::autoSum() 2665 { 2666 selection()->emitAboutToModify(); 2667 2668 //Get the selected range and remove the current cell from it(as that is 2669 //where the result of the autosum will be stored - perhaps change 2670 //this behaviour??) 2671 QRect sel = selection()->lastRange(); 2672 2673 if (sel.height() > 1) { 2674 if (selection()->marker().y() == sel.top()) 2675 sel.setTop(sel.top() + 1); 2676 if (selection()->marker().y() == sel.bottom()) 2677 sel.setBottom(sel.bottom() - 1); 2678 } else { 2679 if (sel.width() > 1) { 2680 if (selection()->marker().x() == sel.left()) 2681 sel.setLeft(sel.left() + 1); 2682 2683 if (selection()->marker().x() == sel.right()) 2684 sel.setRight(sel.right() - 1); 2685 } else { 2686 sel = QRect(); 2687 2688 // only 1 cell selected 2689 // try to automagically find cells the user wants to sum up 2690 2691 int start = -1, end = -1; 2692 2693 if ((selection()->marker().y() > 1) && Cell(selection()->activeSheet(), selection()->marker().x(), selection()->marker().y() - 1).value().isNumber()) { 2694 // check cells above the current one 2695 start = end = selection()->marker().y() - 1; 2696 for (--start; (start > 0) && Cell(selection()->activeSheet(), selection()->marker().x(), start).value().isNumber(); --start) ; 2697 2698 const Region region(QRect(QPoint(selection()->marker().x(), start + 1), 2699 QPoint(selection()->marker().x(), end)), selection()->activeSheet()); 2700 const QString str = region.name(selection()->activeSheet()); 2701 2702 createEditor(true, true, true); 2703 editor()->setText("=SUM(" + str + ')'); 2704 editor()->setCursorPosition(5 + str.length()); 2705 return; 2706 } else if ((selection()->marker().x() > 1) && Cell(selection()->activeSheet(), selection()->marker().x() - 1, selection()->marker().y()).value().isNumber()) { 2707 // check cells to the left of the current one 2708 start = end = selection()->marker().x() - 1; 2709 for (--start; (start > 0) && Cell(selection()->activeSheet(), start, selection()->marker().y()).value().isNumber(); --start) ; 2710 2711 const Region region(QRect(QPoint(start + 1, selection()->marker().y()), 2712 QPoint(end, selection()->marker().y())), selection()->activeSheet()); 2713 const QString str = region.name(selection()->activeSheet()); 2714 2715 createEditor(true, true, true); 2716 editor()->setText("=SUM(" + str + ')'); 2717 editor()->setCursorPosition(5 + str.length()); 2718 return; 2719 } 2720 } 2721 } 2722 2723 if ((sel.width() > 1) && (sel.height() > 1)) 2724 sel = QRect(); 2725 2726 createEditor(true, true, true); 2727 2728 const Region region(sel, selection()->activeSheet()); 2729 if (region.isValid()) { 2730 editor()->setText("=SUM(" + region.name(selection()->activeSheet()) + ')'); 2731 deleteEditor(true); 2732 } else { 2733 selection()->startReferenceSelection(); 2734 editor()->setText("=SUM()"); 2735 editor()->setCursorPosition(5); 2736 } 2737 } 2738 2739 void CellToolBase::insertSeries() 2740 { 2741 selection()->emitAboutToModify(); 2742 QPointer<SeriesDialog> dialog = new SeriesDialog(canvas()->canvasWidget(), selection()); 2743 dialog->exec(); 2744 delete dialog; 2745 } 2746 2747 void CellToolBase::insertSpecialChar() 2748 { 2749 QString fontFamily = Cell(selection()->activeSheet(), selection()->marker()).style().fontFamily(); 2750 QChar c = ' '; 2751 2752 if (d->specialCharDialog == 0) { 2753 d->specialCharDialog = new CharacterSelectDialog(canvas()->canvasWidget(), "SpecialCharDialog", fontFamily, c, false); 2754 connect(d->specialCharDialog, SIGNAL(insertChar(QChar,QString)), 2755 this, SLOT(specialChar(QChar,QString))); 2756 connect(d->specialCharDialog, SIGNAL(finished()), 2757 this, SLOT(specialCharDialogClosed())); 2758 } 2759 d->specialCharDialog->show(); 2760 } 2761 2762 void CellToolBase::specialCharDialogClosed() 2763 { 2764 if (d->specialCharDialog) { 2765 disconnect(d->specialCharDialog, SIGNAL(insertChar(QChar,QString)), 2766 this, SLOT(specialChar(QChar,QString))); 2767 disconnect(d->specialCharDialog, SIGNAL(finished()), 2768 this, SLOT(specialCharDialogClosed())); 2769 d->specialCharDialog->deleteLater(); 2770 d->specialCharDialog = 0; 2771 } 2772 } 2773 2774 void CellToolBase::specialChar(QChar character, const QString& fontName) 2775 { 2776 const Style style = Cell(selection()->activeSheet(), selection()->marker()).style(); 2777 if (style.fontFamily() != fontName) { 2778 Style newStyle; 2779 newStyle.setFontFamily(fontName); 2780 selection()->activeSheet()->cellStorage()->setStyle(Region(selection()->marker()), newStyle); 2781 } 2782 QKeyEvent keyEvent(QEvent::KeyPress, 0, Qt::NoModifier, QString(character)); 2783 if (!editor()) { 2784 createEditor(); 2785 } 2786 QApplication::sendEvent(editor()->widget(), &keyEvent); 2787 } 2788 2789 void CellToolBase::insertFormula() 2790 { 2791 if (! d->formulaDialog) { 2792 if (! createEditor()) 2793 return; 2794 d->formulaDialog = new FormulaDialog(canvas()->canvasWidget(), selection(), editor()); 2795 } 2796 d->formulaDialog->show(); // dialog deletes itself later 2797 } 2798 2799 void CellToolBase::insertFromDatabase() 2800 { 2801 #ifndef QT_NO_SQL 2802 selection()->emitAboutToModify(); 2803 2804 QStringList str = QSqlDatabase::drivers(); 2805 if (str.isEmpty()) { 2806 KMessageBox::error(canvas()->canvasWidget(), i18n("No database drivers available. To use this feature you need " 2807 "to install the necessary Qt database drivers.")); 2808 return; 2809 } 2810 2811 QPointer<DatabaseDialog> dialog = new DatabaseDialog(canvas()->canvasWidget(), selection()); 2812 dialog->exec(); 2813 delete dialog; 2814 #endif 2815 } 2816 2817 void CellToolBase::insertFromTextfile() 2818 { 2819 selection()->emitAboutToModify(); 2820 2821 QPointer<CSVDialog> dialog = new CSVDialog(canvas()->canvasWidget(), selection(), CSVDialog::File); 2822 dialog->setDecimalSymbol(selection()->activeSheet()->map()->calculationSettings()->locale()->decimalSymbol()); 2823 dialog->setThousandsSeparator(selection()->activeSheet()->map()->calculationSettings()->locale()->thousandsSeparator()); 2824 if (!dialog->canceled()) 2825 dialog->exec(); 2826 delete dialog; 2827 } 2828 2829 void CellToolBase::insertFromClipboard() 2830 { 2831 selection()->emitAboutToModify(); 2832 2833 QPointer<CSVDialog> dialog = new CSVDialog(canvas()->canvasWidget(), selection(), CSVDialog::Clipboard); 2834 dialog->setDecimalSymbol(selection()->activeSheet()->map()->calculationSettings()->locale()->decimalSymbol()); 2835 dialog->setThousandsSeparator(selection()->activeSheet()->map()->calculationSettings()->locale()->thousandsSeparator()); 2836 QString oldDelimiter = dialog->delimiter(); 2837 dialog->setDelimiter(QString()); 2838 if (!dialog->canceled()) 2839 dialog->exec(); 2840 dialog->setDelimiter(oldDelimiter); 2841 delete dialog; 2842 } 2843 2844 void CellToolBase::textToColumns() 2845 { 2846 selection()->emitAboutToModify(); 2847 2848 QRect area = selection()->lastRange(); 2849 area.setRight(area.left()); // only use the first column 2850 Region oldSelection = *selection(); // store 2851 selection()->initialize(area); 2852 2853 QPointer<CSVDialog> dialog = new CSVDialog(canvas()->canvasWidget(), selection(), CSVDialog::Column); 2854 dialog->setDecimalSymbol(selection()->activeSheet()->map()->calculationSettings()->locale()->decimalSymbol()); 2855 dialog->setThousandsSeparator(selection()->activeSheet()->map()->calculationSettings()->locale()->thousandsSeparator()); 2856 if (!dialog->canceled()) 2857 dialog->exec(); 2858 else 2859 selection()->initialize(oldSelection); 2860 delete dialog; 2861 } 2862 2863 void CellToolBase::sortList() 2864 { 2865 QPointer<ListDialog> dialog = new ListDialog(canvas()->canvasWidget()); 2866 dialog->exec(); 2867 delete dialog; 2868 } 2869 2870 void CellToolBase::consolidate() 2871 { 2872 selection()->emitAboutToModify(); 2873 ConsolidateDialog * dialog = new ConsolidateDialog(canvas()->canvasWidget(), selection()); 2874 dialog->show(); // dialog deletes itself later 2875 } 2876 2877 void CellToolBase::goalSeek() 2878 { 2879 selection()->emitAboutToModify(); 2880 2881 GoalSeekDialog* dialog = new GoalSeekDialog(canvas()->canvasWidget(), selection()); 2882 dialog->show(); // dialog deletes itself later 2883 } 2884 2885 void CellToolBase::subtotals() 2886 { 2887 if ((selection()->lastRange().width() < 2) || (selection()->lastRange().height() < 2)) { 2888 KMessageBox::error(canvas()->canvasWidget(), i18n("You must select multiple cells.")); 2889 return; 2890 } 2891 2892 QPointer<SubtotalDialog> dialog = new SubtotalDialog(canvas()->canvasWidget(), selection()); 2893 dialog->exec(); 2894 delete dialog; 2895 } 2896 2897 void CellToolBase::pivot() 2898 { 2899 if ((selection()->lastRange().width() < 2) || (selection()->lastRange().height() < 2)) { 2900 KMessageBox::error(canvas()->canvasWidget(), i18n("You must select multiple cells.")); 2901 return; 2902 } 2903 2904 QPointer<Pivot> dialog = new Pivot(canvas()->canvasWidget(), selection()); 2905 dialog->exec(); 2906 delete dialog; 2907 } 2908 2909 void CellToolBase::setAreaName() 2910 { 2911 QPointer<AddNamedAreaDialog> dialog = new AddNamedAreaDialog(canvas()->canvasWidget(), selection()); 2912 dialog->exec(); 2913 delete dialog; 2914 } 2915 2916 void CellToolBase::namedAreaDialog() 2917 { 2918 QPointer<NamedAreaDialog> dialog = new NamedAreaDialog(canvas()->canvasWidget(), selection()); 2919 dialog->exec(); 2920 delete dialog; 2921 } 2922 2923 void CellToolBase::formulaSelection(const QString& expression) 2924 { 2925 if (expression == i18n("Others...")) { 2926 insertFormula(); 2927 return; 2928 } 2929 2930 createEditor(); 2931 FormulaDialog* dialog = new FormulaDialog(canvas()->canvasWidget(), selection(), editor(), expression); 2932 dialog->show(); // dialog deletes itself later 2933 } 2934 2935 void CellToolBase::edit() 2936 { 2937 // Not yet in edit mode? 2938 if (!editor()) { 2939 createEditor(false /* keep content */, true, true /*capture arrow keys*/); 2940 return; 2941 } 2942 2943 // If the editor doesn't allow cursor movement, enable it now (enters real editing mode) 2944 if (!editor()->captureArrowKeys()) { 2945 editor()->setCaptureArrowKeys(true); 2946 return; 2947 } 2948 2949 // Switch focus. 2950 if (editor()->widget()->hasFocus()) { 2951 if (d->externalEditor) d->externalEditor->setFocus(); 2952 } else { 2953 editor()->widget()->setFocus(); 2954 } 2955 } 2956 2957 void CellToolBase::cut() 2958 { 2959 if (editor()) { 2960 editor()->cut(); 2961 selection()->emitModified(); 2962 return; 2963 } 2964 2965 QDomDocument doc = CopyCommand::saveAsXml(*selection(), true); 2966 doc.documentElement().setAttribute("cut", selection()->Region::name()); 2967 2968 // Save to buffer 2969 QBuffer buffer; 2970 buffer.open(QIODevice::WriteOnly); 2971 QTextStream str(&buffer); 2972 str.setCodec("UTF-8"); 2973 str << doc; 2974 buffer.close(); 2975 2976 QMimeData* mimeData = new QMimeData(); 2977 mimeData->setText(CopyCommand::saveAsPlainText(*selection())); 2978 mimeData->setData("application/x-kspread-snippet", buffer.buffer()); 2979 2980 QApplication::clipboard()->setMimeData(mimeData); 2981 2982 DeleteCommand* command = new DeleteCommand(); 2983 command->setText(kundo2_i18n("Cut")); 2984 command->setSheet(selection()->activeSheet()); 2985 command->add(*selection()); 2986 command->execute(); 2987 2988 selection()->emitModified(); 2989 } 2990 2991 void CellToolBase::copy() const 2992 { 2993 Selection* selection = const_cast<CellToolBase*>(this)->selection(); 2994 if (editor()) { 2995 editor()->copy(); 2996 return; 2997 } 2998 2999 QDomDocument doc = CopyCommand::saveAsXml(*selection); 3000 3001 // Save to buffer 3002 QBuffer buffer; 3003 buffer.open(QIODevice::WriteOnly); 3004 QTextStream str(&buffer); 3005 str.setCodec("UTF-8"); 3006 str << doc; 3007 buffer.close(); 3008 3009 QMimeData* mimeData = new QMimeData(); 3010 mimeData->setText(CopyCommand::saveAsPlainText(*selection)); 3011 mimeData->setData("application/x-kspread-snippet", buffer.buffer()); 3012 3013 QApplication::clipboard()->setMimeData(mimeData); 3014 } 3015 3016 bool CellToolBase::paste() 3017 { 3018 if (!selection()->activeSheet()->map()->isReadWrite()) // don't paste into a read only document 3019 return false; 3020 3021 const QMimeData* mimeData = QApplication::clipboard()->mimeData(QClipboard::Clipboard); 3022 3023 if (mimeData->hasFormat("application/vnd.oasis.opendocument.spreadsheet")) { 3024 QByteArray returnedTypeMime = "application/vnd.oasis.opendocument.spreadsheet"; 3025 QByteArray arr = mimeData->data(returnedTypeMime); 3026 if (arr.isEmpty()) 3027 return false; 3028 QBuffer buffer(&arr); 3029 Map *map = selection()->activeSheet()->map(); 3030 if (!Odf::paste(buffer, map)) return false; 3031 } 3032 3033 if (!editor()) { 3034 const QMimeData* mimedata = QApplication::clipboard()->mimeData(); 3035 if (!mimedata->hasFormat("application/x-kspread-snippet") && 3036 !mimedata->hasHtml() && mimedata->hasText() && 3037 mimeData->text().split('\n').count() >= 2 ) 3038 { 3039 insertFromClipboard(); 3040 } else { 3041 //debugSheetsUI <<"Pasting. Rect=" << selection()->lastRange() <<" bytes"; 3042 PasteCommand *const command = new PasteCommand(); 3043 command->setSheet(selection()->activeSheet()); 3044 command->add(*selection()); 3045 command->setMimeData(mimedata); 3046 command->setPasteFC(true); 3047 command->execute(canvas()); 3048 } 3049 d->updateEditor(Cell(selection()->activeSheet(), selection()->cursor())); 3050 } else { 3051 editor()->paste(); 3052 } 3053 selection()->emitModified(); 3054 return true; 3055 } 3056 3057 void CellToolBase::specialPaste() 3058 { 3059 QPointer<SpecialPasteDialog> dialog = new SpecialPasteDialog(canvas()->canvasWidget(), selection()); 3060 if (dialog->exec()) { 3061 selection()->emitModified(); 3062 } 3063 delete dialog; 3064 } 3065 3066 void CellToolBase::pasteWithInsertion() 3067 { 3068 const QMimeData *const mimeData = QApplication::clipboard()->mimeData(); 3069 if (!PasteCommand::unknownShiftDirection(mimeData)) { 3070 PasteCommand *const command = new PasteCommand(); 3071 command->setSheet(selection()->activeSheet()); 3072 command->add(*selection()); 3073 command->setMimeData(mimeData); 3074 command->setInsertionMode(PasteCommand::ShiftCells); 3075 command->execute(canvas()); 3076 } else { 3077 QPointer<PasteInsertDialog> dialog= new PasteInsertDialog(canvas()->canvasWidget(), selection()); 3078 dialog->exec(); 3079 delete dialog; 3080 } 3081 d->updateEditor(Cell(selection()->activeSheet(), selection()->cursor())); 3082 } 3083 3084 void CellToolBase::deleteSelection() 3085 { 3086 clearContents(); 3087 } 3088 3089 void CellToolBase::selectAll() 3090 { 3091 selection()->selectAll(); 3092 } 3093 3094 void CellToolBase::find() 3095 { 3096 QPointer<FindDlg> dialog = new FindDlg(canvas()->canvasWidget(), "Find", d->findOptions, d->findStrings); 3097 dialog->setHasSelection(!selection()->isSingular()); 3098 dialog->setHasCursor(true); 3099 if (KFindDialog::Accepted != dialog->exec()) 3100 return; 3101 3102 // Save for next time 3103 d->findOptions = dialog->options(); 3104 d->findStrings = dialog->findHistory(); 3105 d->typeValue = dialog->searchType(); 3106 d->directionValue = dialog->searchDirection(); 3107 3108 // Create the KFind object 3109 delete d->find; 3110 delete d->replace; 3111 d->find = new KFind(dialog->pattern(), dialog->options(), canvas()->canvasWidget()); 3112 d->replace = 0; 3113 d->replaceCommand = 0; 3114 3115 d->searchInSheets.currentSheet = selection()->activeSheet(); 3116 d->searchInSheets.firstSheet = d->searchInSheets.currentSheet; 3117 3118 initFindReplace(); 3119 findNext(); 3120 delete dialog; 3121 } 3122 3123 // Initialize a find or replace operation, using d->find or d->replace, 3124 // and d->findOptions. 3125 void CellToolBase::initFindReplace() 3126 { 3127 KFind* findObj = d->find ? d->find : d->replace; 3128 Q_ASSERT(findObj); 3129 connect(findObj, SIGNAL(highlight(QString,int,int)), 3130 this, SLOT(slotHighlight(QString,int,int))); 3131 connect(findObj, SIGNAL(findNext()), 3132 this, SLOT(findNext())); 3133 3134 bool bck = d->findOptions & KFind::FindBackwards; 3135 Sheet* currentSheet = d->searchInSheets.currentSheet; 3136 3137 QRect region = (d->findOptions & KFind::SelectedText) 3138 ? selection()->lastRange() 3139 : QRect(1, 1, currentSheet->cellStorage()->columns(), currentSheet->cellStorage()->rows()); // All cells 3140 3141 int colStart = !bck ? region.left() : region.right(); 3142 int colEnd = !bck ? region.right() : region.left(); 3143 int rowStart = !bck ? region.top() : region.bottom(); 3144 int rowEnd = !bck ? region.bottom() : region.top(); 3145 3146 d->findLeftColumn = region.left(); 3147 d->findRightColumn = region.right(); 3148 d->findTopRow = region.top(); 3149 d->findBottomRow = region.bottom(); 3150 3151 d->findStart = QPoint(colStart, rowStart); 3152 d->findPos = (d->findOptions & KFind::FromCursor) ? selection()->marker() : d->findStart; 3153 d->findEnd = QPoint(colEnd, rowEnd); 3154 //debugSheets << d->findPos <<" to" << d->findEnd; 3155 //debugSheets <<"leftcol=" << d->findLeftColumn <<" rightcol=" << d->findRightColumn; 3156 } 3157 3158 void CellToolBase::findNext() 3159 { 3160 KFind* findObj = d->find ? d->find : d->replace; 3161 if (!findObj) { 3162 find(); 3163 return; 3164 } 3165 KFind::Result res = KFind::NoMatch; 3166 Cell cell = findNextCell(); 3167 bool forw = !(d->findOptions & KFind::FindBackwards); 3168 while (res == KFind::NoMatch && !cell.isNull()) { 3169 if (findObj->needData()) { 3170 if (d->typeValue == FindOption::Note) 3171 findObj->setData(cell.comment()); 3172 else 3173 findObj->setData(cell.userInput()); 3174 d->findPos = QPoint(cell.column(), cell.row()); 3175 //debugSheets <<"setData(cell" << d->findPos << ')'; 3176 } 3177 3178 // Let KFind inspect the text fragment, and display a dialog if a match is found 3179 if (d->find) 3180 res = d->find->find(); 3181 else 3182 res = d->replace->replace(); 3183 3184 if (res == KFind::NoMatch) { 3185 // Go to next cell, skipping unwanted cells 3186 if (d->directionValue == FindOption::Row) { 3187 if (forw) 3188 ++d->findPos.rx(); 3189 else 3190 --d->findPos.rx(); 3191 } else { 3192 if (forw) 3193 ++d->findPos.ry(); 3194 else 3195 --d->findPos.ry(); 3196 } 3197 cell = findNextCell(); 3198 } 3199 } 3200 3201 if (res == KFind::NoMatch) { 3202 //emitUndoRedo(); 3203 //removeHighlight(); 3204 if (findObj->shouldRestart()) { 3205 d->findOptions &= ~KFind::FromCursor; 3206 d->findPos = d->findStart; 3207 findObj->resetCounts(); 3208 findNext(); 3209 } else { // done, close the 'find next' dialog 3210 if (d->find) 3211 d->find->closeFindNextDialog(); 3212 else { 3213 canvas()->addCommand(d->replaceCommand); 3214 d->replaceCommand = 0; 3215 d->replace->closeReplaceNextDialog(); 3216 } 3217 } 3218 } 3219 else if (!cell.isNull()) { 3220 // move to the cell 3221 if (cell.sheet() != selection()->activeSheet()) 3222 selection()->emitVisibleSheetRequested(cell.sheet()); 3223 selection()->initialize (Region (cell.column(), cell.row(), cell.sheet()), cell.sheet()); 3224 scrollToCell (selection()->cursor()); 3225 } 3226 } 3227 3228 Cell CellToolBase::nextFindValidCell(int col, int row) 3229 { 3230 Cell cell = Cell(d->searchInSheets.currentSheet, col, row); 3231 if (cell.isDefault() || cell.isPartOfMerged() || cell.isFormula()) 3232 cell = Cell(); 3233 if (d->typeValue == FindOption::Note && !cell.isNull() && cell.comment().isEmpty()) 3234 cell = Cell(); 3235 return cell; 3236 } 3237 3238 Cell CellToolBase::findNextCell() 3239 { 3240 // cellStorage()->firstInRow / cellStorage()->nextInRow would be faster at doing that, 3241 // but it doesn't seem to be easy to combine it with 'start a column d->find.x()'... 3242 3243 Sheet* sheet = d->searchInSheets.currentSheet; 3244 Cell cell; 3245 bool forw = !(d->findOptions & KFind::FindBackwards); 3246 int col = d->findPos.x(); 3247 int row = d->findPos.y(); 3248 int maxRow = sheet->cellStorage()->rows(); 3249 // warnSheets <<"findNextCell starting at" << col << ',' << row <<" forw=" << forw; 3250 3251 if (d->directionValue == FindOption::Row) { 3252 while (!cell && (row >= d->findTopRow) && (row <= d->findBottomRow) && (forw ? row <= maxRow : row >= 0)) { 3253 while (!cell && (forw ? col <= d->findRightColumn : col >= d->findLeftColumn)) { 3254 cell = nextFindValidCell(col, row); 3255 if (forw) ++col; 3256 else --col; 3257 } 3258 if (!cell.isNull()) 3259 break; 3260 // Prepare looking in the next row 3261 if (forw) { 3262 col = d->findLeftColumn; 3263 ++row; 3264 } else { 3265 col = d->findRightColumn; 3266 --row; 3267 } 3268 //warnSheets <<"next row:" << col << ',' << row; 3269 } 3270 } else { 3271 while (!cell && (forw ? col <= d->findRightColumn : col >= d->findLeftColumn)) { 3272 while (!cell && (row >= d->findTopRow) && (row <= d->findBottomRow) && (forw ? row <= maxRow : row >= 0)) { 3273 cell = nextFindValidCell(col, row); 3274 if (forw) ++row; 3275 else --row; 3276 } 3277 if (!cell.isNull()) 3278 break; 3279 // Prepare looking in the next col 3280 if (forw) { 3281 row = d->findTopRow; 3282 ++col; 3283 } else { 3284 row = d->findBottomRow; 3285 --col; 3286 } 3287 //debugSheets <<"next row:" << col << ',' << row; 3288 } 3289 } 3290 // if (!cell) 3291 // No more next cell - TODO go to next sheet (if not looking in a selection) 3292 // (and make d->findEnd(max, max) in that case...) 3293 // if (cell.isNull()) warnSheets<<"returning null"<<endl; 3294 // else warnSheets <<" returning" << cell; 3295 3296 return cell; 3297 } 3298 3299 void CellToolBase::findPrevious() 3300 { 3301 KFind* findObj = d->find ? d->find : d->replace; 3302 if (!findObj) { 3303 find(); 3304 return; 3305 } 3306 //debugSheets <<"findPrevious"; 3307 int opt = d->findOptions; 3308 bool forw = !(opt & KFind::FindBackwards); 3309 if (forw) 3310 d->findOptions = (opt | KFind::FindBackwards); 3311 else 3312 d->findOptions = (opt & ~KFind::FindBackwards); 3313 3314 findNext(); 3315 3316 d->findOptions = opt; // restore initial options 3317 } 3318 3319 void CellToolBase::replace() 3320 { 3321 QPointer<SearchDlg> dialog = new SearchDlg(canvas()->canvasWidget(), "Replace", d->findOptions, d->findStrings, d->replaceStrings); 3322 dialog->setHasSelection(!selection()->isSingular()); 3323 dialog->setHasCursor(true); 3324 if (KReplaceDialog::Accepted != dialog->exec()) 3325 return; 3326 3327 d->findOptions = dialog->options(); 3328 d->findStrings = dialog->findHistory(); 3329 d->replaceStrings = dialog->replacementHistory(); 3330 d->typeValue = dialog->searchType(); 3331 3332 delete d->find; 3333 delete d->replace; 3334 d->find = 0; 3335 // NOTE Stefan: Avoid beginning of line replacements with nothing which 3336 // will lead to an infinite loop (Bug #125535). The reason 3337 // for this is unclear to me, but who cares and who would 3338 // want to do something like this, häh?! 3339 if (dialog->pattern() == "^" && dialog->replacement().isEmpty()) 3340 return; 3341 d->replace = new KReplace(dialog->pattern(), dialog->replacement(), dialog->options()); 3342 3343 d->searchInSheets.currentSheet = selection()->activeSheet(); 3344 d->searchInSheets.firstSheet = d->searchInSheets.currentSheet; 3345 initFindReplace(); 3346 connect(d->replace, SIGNAL(replace(QString,int,int,int)), 3347 this, SLOT(slotReplace(QString,int,int,int))); 3348 3349 d->replaceCommand = new KUndo2Command(kundo2_i18n("Replace")); 3350 3351 findNext(); 3352 delete dialog; 3353 3354 #if 0 3355 // Refresh the editWidget 3356 // TODO - after a replacement only? 3357 Cell cell = Cell(activeSheet(), selection()->marker()); 3358 if (cell.userInput() != 0) 3359 d->editWidget->setText(cell.userInput()); 3360 else 3361 d->editWidget->setText(""); 3362 #endif 3363 } 3364 3365 void CellToolBase::slotHighlight(const QString &/*text*/, int /*matchingIndex*/, int /*matchedLength*/) 3366 { 3367 selection()->initialize(d->findPos); 3368 QDialog *dialog = 0; 3369 if (d->find) 3370 dialog = d->find->findNextDialog(); 3371 else 3372 dialog = d->replace->replaceNextDialog(); 3373 debugSheets << " baseDialog :" << dialog; 3374 QRect globalRect(d->findPos, d->findEnd); 3375 globalRect.moveTopLeft(canvas()->canvasWidget()->mapToGlobal(globalRect.topLeft())); 3376 KoDialog::avoidArea(dialog, QRect(d->findPos, d->findEnd)); 3377 } 3378 3379 void CellToolBase::slotReplace(const QString &newText, int, int, int) 3380 { 3381 if (d->typeValue == FindOption::Value) { 3382 DataManipulator* command = new DataManipulator(d->replaceCommand); 3383 command->setParsing(true); 3384 command->setSheet(d->searchInSheets.currentSheet); 3385 command->setValue(Value(newText)); 3386 command->add(Region(d->findPos, d->searchInSheets.currentSheet)); 3387 } else if (d->typeValue == FindOption::Note) { 3388 CommentCommand* command = new CommentCommand(d->replaceCommand); 3389 command->setComment(newText); 3390 command->setSheet(d->searchInSheets.currentSheet); 3391 command->add(Region(d->findPos, d->searchInSheets.currentSheet)); 3392 } 3393 } 3394 3395 void CellToolBase::gotoCell() 3396 { 3397 QPointer<GotoDialog> dialog = new GotoDialog(canvas()->canvasWidget(), selection()); 3398 dialog->exec(); 3399 delete dialog; 3400 scrollToCell(selection()->cursor()); 3401 } 3402 3403 void CellToolBase::spellCheck() 3404 { 3405 SpellCheckCommand* command = new SpellCheckCommand(*selection(), canvas()); 3406 command->start(); 3407 } 3408 3409 void CellToolBase::inspector() 3410 { 3411 // useful to inspect objects 3412 Cell cell(selection()->activeSheet(), selection()->marker()); 3413 QPointer<Calligra::Sheets::Inspector> ins = new Calligra::Sheets::Inspector(cell); 3414 ins->exec(); 3415 delete ins; 3416 } 3417 3418 void CellToolBase::qTableView() 3419 { 3420 #ifndef NDEBUG 3421 QPointer<KoDialog> dialog = new KoDialog(canvas()->canvasWidget()); 3422 QTableView* const view = new QTableView(dialog); 3423 SheetModel* const model = new SheetModel(selection()->activeSheet()); 3424 view->setModel(model); 3425 dialog->setCaption("Read{Only,Write}TableModel Test"); 3426 dialog->setMainWidget(view); 3427 dialog->exec(); 3428 delete dialog; 3429 delete model; 3430 #endif 3431 } 3432 3433 void CellToolBase::sheetFormat() 3434 { 3435 QPointer<AutoFormatDialog> dialog = new AutoFormatDialog(canvas()->canvasWidget(), selection()); 3436 dialog->exec(); 3437 delete dialog; 3438 } 3439 3440 void CellToolBase::listChoosePopupMenu() 3441 { 3442 if (!selection()->activeSheet()->map()->isReadWrite()) { 3443 return; 3444 } 3445 3446 delete d->popupListChoose; 3447 d->popupListChoose = new QMenu(); 3448 3449 const Sheet *const sheet = selection()->activeSheet(); 3450 const Cell cursorCell(sheet, selection()->cursor()); 3451 const QString text = cursorCell.userInput(); 3452 const CellStorage *const storage = sheet->cellStorage(); 3453 3454 QStringList itemList; 3455 const Region::ConstIterator end(selection()->constEnd()); 3456 for (Region::ConstIterator it(selection()->constBegin()); it != end; ++it) { 3457 const QRect range = (*it)->rect(); 3458 if (cursorCell.column() < range.left() || cursorCell.column() > range.right()) { 3459 continue; // next range 3460 } 3461 Cell cell; 3462 if (range.top() == 1) { 3463 cell = storage->firstInColumn(cursorCell.column(), CellStorage::Values); 3464 } else { 3465 cell = storage->nextInColumn(cursorCell.column(), range.top() - 1, CellStorage::Values); 3466 } 3467 while (!cell.isNull() && cell.row() <= range.bottom()) { 3468 if (!cell.isPartOfMerged() && !(cell == cursorCell)) { 3469 const QString userInput = cell.userInput(); 3470 if (cell.value().isString() && userInput != text && !userInput.isEmpty()) { 3471 if (itemList.indexOf(userInput) == -1) { 3472 itemList.append(userInput); 3473 } 3474 } 3475 } 3476 cell = storage->nextInColumn(cell.column(), cell.row(), CellStorage::Values); 3477 } 3478 } 3479 3480 for (QStringList::ConstIterator it = itemList.constBegin(); it != itemList.constEnd(); ++it) { 3481 d->popupListChoose->addAction((*it)); 3482 } 3483 3484 if (itemList.isEmpty()) { 3485 return; 3486 } 3487 double tx = sheet->columnPosition(selection()->marker().x()); 3488 double ty = sheet->rowPosition(selection()->marker().y()); 3489 double h = cursorCell.height(); 3490 if (sheetView(sheet)->obscuresCells(selection()->marker())) { 3491 const CellView& cellView = sheetView(sheet)->cellView(selection()->marker().x(), selection()->marker().y()); 3492 h = cellView.cellHeight(); 3493 } 3494 ty += h; 3495 3496 if (selection()->activeSheet()->layoutDirection() == Qt::RightToLeft) { 3497 tx = canvas()->canvasWidget()->width() - tx; 3498 } 3499 3500 QPoint p((int)tx, (int)ty); 3501 QPoint p2 = canvas()->canvasWidget()->mapToGlobal(p); 3502 3503 if (selection()->activeSheet()->layoutDirection() == Qt::RightToLeft) { 3504 p2.setX(p2.x() - d->popupListChoose->sizeHint().width() + 1); 3505 } 3506 3507 d->popupListChoose->popup(p2); 3508 connect(d->popupListChoose, SIGNAL(triggered(QAction*)), 3509 this, SLOT(listChooseItemSelected(QAction*))); 3510 } 3511 3512 3513 void CellToolBase::listChooseItemSelected(QAction* action) 3514 { 3515 const Cell cell(selection()->activeSheet(), selection()->marker()); 3516 if (action->text() == cell.userInput()) 3517 return; 3518 3519 DataManipulator *command = new DataManipulator; 3520 command->setSheet(selection()->activeSheet()); 3521 command->setValue(Value(action->text())); 3522 command->setParsing(true); 3523 command->add(selection()->marker()); 3524 command->execute(canvas()); 3525 } 3526 3527 void CellToolBase::documentSettingsDialog() 3528 { 3529 QPointer<DocumentSettingsDialog> dialog = new DocumentSettingsDialog(selection(), canvas()->canvasWidget()); 3530 dialog->exec(); 3531 delete dialog; 3532 } 3533 3534 void CellToolBase::breakBeforeColumn(bool enable) 3535 { 3536 PageBreakCommand *command = new PageBreakCommand(); 3537 command->setSheet(selection()->activeSheet()); 3538 command->setMode(PageBreakCommand::BreakBeforeColumn); 3539 command->setReverse(!enable); 3540 command->add(*selection()); 3541 command->execute(canvas()); 3542 } 3543 3544 void CellToolBase::breakBeforeRow(bool enable) 3545 { 3546 PageBreakCommand *command = new PageBreakCommand(); 3547 command->setSheet(selection()->activeSheet()); 3548 command->setMode(PageBreakCommand::BreakBeforeRow); 3549 command->setReverse(!enable); 3550 command->add(*selection()); 3551 command->execute(canvas()); 3552 } 3553 3554 void CellToolBase::setExternalEditor(Calligra::Sheets::ExternalEditor *editor) 3555 { 3556 d->externalEditor = editor; 3557 }