tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / view / cellsh3.cxx
blob033ecf8982cb9f452418aa4c7b4c060ec5f32b0b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <scitems.hxx>
21 #include <editeng/editview.hxx>
22 #include <editeng/editeng.hxx>
23 #include <formula/formulahelper.hxx>
24 #include <sfx2/viewfrm.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <sfx2/dispatch.hxx>
27 #include <sfx2/request.hxx>
28 #include <svl/stritem.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/weld.hxx>
31 #include <globstr.hrc>
32 #include <scresid.hxx>
33 #include <scmod.hxx>
34 #include <appoptio.hxx>
35 #include <tabvwsh.hxx>
36 #include <document.hxx>
37 #include <sc.hrc>
38 #include <reffact.hxx>
39 #include <uiitems.hxx>
40 #include <autoform.hxx>
41 #include <cellsh.hxx>
42 #include <inputhdl.hxx>
43 #include <inputopt.hxx>
44 #include <editable.hxx>
45 #include <funcdesc.hxx>
46 #include <markdata.hxx>
47 #include <scabstdlg.hxx>
48 #include <columnspanset.hxx>
49 #include <comphelper/lok.hxx>
50 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
51 #include <inputwin.hxx>
52 #include <officecfg/Office/Calc.hxx>
54 #include <memory>
56 using sc::TwipsToEvenHMM;
58 namespace
60 /// Rid ourselves of unwanted " quoted json characters.
61 OString escapeJSON(const OUString &aStr)
63 OUString aEscaped = aStr;
64 aEscaped = aEscaped.replaceAll("\n", " ");
65 aEscaped = aEscaped.replaceAll("\"", "'");
66 return OUStringToOString(aEscaped, RTL_TEXTENCODING_UTF8);
69 void lcl_lokGetWholeFunctionList()
71 const SfxViewShell* pViewShell = SfxViewShell::Current();
72 if (!(comphelper::LibreOfficeKit::isActive()
73 && pViewShell && pViewShell->isLOKMobilePhone()))
74 return;
76 const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
77 sal_uInt32 nListCount = pFuncList->GetCount();
78 std::set<OUString> aFuncNameOrderedSet;
79 for(sal_uInt32 i = 0; i < nListCount; ++i)
81 const ScFuncDesc* pDesc = pFuncList->GetFunction( i );
82 if ( pDesc->mxFuncName )
84 aFuncNameOrderedSet.insert(*pDesc->mxFuncName);
87 ScFunctionMgr* pFuncManager = ScGlobal::GetStarCalcFunctionMgr();
88 if (!(pFuncManager && aFuncNameOrderedSet.size()))
89 return;
91 OStringBuffer aPayload(
92 "{ \"wholeList\": true, "
93 "\"categories\": [ ");
95 formula::FormulaHelper aHelper(pFuncManager);
96 sal_uInt32 nCategoryCount = pFuncManager->getCount();
97 for (sal_uInt32 i = 0; i < nCategoryCount; ++i)
99 OUString sCategoryName = ScFunctionMgr::GetCategoryName(i);
100 aPayload.append("{"
101 "\"name\": \""
102 + escapeJSON(sCategoryName)
103 + "\"}, ");
105 sal_Int32 nLen = aPayload.getLength();
106 aPayload[nLen - 2] = ' ';
107 aPayload[nLen - 1] = ']';
108 aPayload.append(", ");
110 OUString aDescFuncNameStr;
111 aPayload.append("\"functions\": [ ");
112 sal_uInt32 nCurIndex = 0;
113 for (const OUString& aFuncNameStr : aFuncNameOrderedSet)
115 aDescFuncNameStr = aFuncNameStr + "()";
116 sal_Int32 nNextFStart = 0;
117 const formula::IFunctionDescription* ppFDesc;
118 ::std::vector< OUString > aArgs;
119 OUString eqPlusFuncName = "=" + aDescFuncNameStr;
120 if ( aHelper.GetNextFunc( eqPlusFuncName, false, nNextFStart, nullptr, &ppFDesc, &aArgs ) )
122 if ( ppFDesc && !ppFDesc->getFunctionName().isEmpty() )
124 if (ppFDesc->getCategory())
126 aPayload.append("{"
127 "\"index\": "
128 + OString::number(static_cast<sal_Int64>(nCurIndex))
129 + ", "
130 "\"category\": "
131 + OString::number(static_cast<sal_Int64>(ppFDesc->getCategory()->getNumber()))
132 + ", "
133 "\"signature\": \""
134 + escapeJSON(ppFDesc->getSignature())
135 + "\", "
136 "\"description\": \""
137 + escapeJSON(ppFDesc->getDescription())
138 + "\"}, ");
142 ++nCurIndex;
144 nLen = aPayload.getLength();
145 aPayload[nLen - 2] = ' ';
146 aPayload[nLen - 1] = ']';
147 aPayload.append(" }");
149 OString s = aPayload.makeStringAndClear();
150 pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CALC_FUNCTION_LIST, s);
153 } // end namespace
155 void ScCellShell::Execute( SfxRequest& rReq )
157 ScTabViewShell* pTabViewShell = GetViewData().GetViewShell();
158 SfxBindings& rBindings = pTabViewShell->GetViewFrame().GetBindings();
159 ScModule* pScMod = ScModule::get();
160 const SfxItemSet* pReqArgs = rReq.GetArgs();
161 sal_uInt16 nSlot = rReq.GetSlot();
163 if (nSlot != SID_CURRENTCELL) // this comes with MouseButtonUp
164 pTabViewShell->HideListBox(); // Autofilter-DropDown-Listbox
166 if ( GetViewData().HasEditView( GetViewData().GetActivePart() ) )
168 switch ( nSlot )
170 // when opening a reference-dialog the subshell may not be switched
171 // (on closing the dialog StopEditShell is called)
172 case SID_OPENDLG_FUNCTION:
173 // inplace leads to trouble with EditShell ...
174 //! cannot always be switched ????
175 if (!pTabViewShell->GetViewFrame().GetFrame().IsInPlace())
176 pTabViewShell->SetDontSwitch(true); // do not switch off EditShell
177 [[fallthrough]];
179 case FID_CELL_FORMAT:
180 case SID_ENABLE_HYPHENATION:
181 case SID_DATA_SELECT:
182 case SID_OPENDLG_CONSOLIDATE:
183 case SID_OPENDLG_SOLVE:
184 case SID_OPENDLG_OPTSOLVER:
186 pScMod->InputEnterHandler();
187 pTabViewShell->UpdateInputHandler();
189 pTabViewShell->SetDontSwitch(false);
191 break;
193 default:
194 break;
198 switch ( nSlot )
200 case SID_STATUS_SELMODE:
201 if ( pReqArgs )
203 /* 0: STD Click cancels selection
204 * 1: ER Click extends selection
205 * 2: ERG Click defines further selection
207 sal_uInt16 nMode = static_cast<const SfxUInt16Item&>(pReqArgs->Get( nSlot )).GetValue();
209 switch ( nMode )
211 case 1: nMode = KEY_SHIFT; break;
212 case 2: nMode = KEY_MOD1; break; // control-key
213 case 0:
214 default:
215 nMode = 0;
218 pTabViewShell->LockModifiers( nMode );
220 else
222 // no arguments (also executed by double click on the status bar controller):
223 // advance to next selection mode
225 sal_uInt16 nModifiers = pTabViewShell->GetLockedModifiers();
226 switch ( nModifiers )
228 case KEY_SHIFT: nModifiers = KEY_MOD1; break; // EXT -> ADD
229 case KEY_MOD1: nModifiers = 0; break; // ADD -> STD
230 default: nModifiers = KEY_SHIFT; break; // STD -> EXT
232 pTabViewShell->LockModifiers( nModifiers );
235 rBindings.Invalidate( SID_STATUS_SELMODE );
236 rReq.Done();
237 break;
239 // SID_STATUS_SELMODE_NORM is not used ???
241 case SID_STATUS_SELMODE_NORM:
242 pTabViewShell->LockModifiers( 0 );
243 rBindings.Invalidate( SID_STATUS_SELMODE );
244 break;
246 // SID_STATUS_SELMODE_ERG / SID_STATUS_SELMODE_ERW as toggles:
248 case SID_STATUS_SELMODE_ERG:
249 if ( pTabViewShell->GetLockedModifiers() & KEY_MOD1 )
250 pTabViewShell->LockModifiers( 0 );
251 else
252 pTabViewShell->LockModifiers( KEY_MOD1 );
253 rBindings.Invalidate( SID_STATUS_SELMODE );
254 break;
256 case SID_STATUS_SELMODE_ERW:
257 if ( pTabViewShell->GetLockedModifiers() & KEY_SHIFT )
258 pTabViewShell->LockModifiers( 0 );
259 else
260 pTabViewShell->LockModifiers( KEY_SHIFT );
261 rBindings.Invalidate( SID_STATUS_SELMODE );
262 break;
264 case SID_ENTER_STRING:
266 if ( pReqArgs )
268 // In the LOK case, we want to set the document modified state
269 // right away at the start of the edit, so that the content is
270 // saved even when the user leaves the document before hitting
271 // Enter
272 // NOTE: This also means we want to set the modified state
273 // regardless of the DontCommit parameter's value.
274 if (comphelper::LibreOfficeKit::isActive() && !GetViewData().GetDocShell()->IsModified())
276 GetViewData().GetDocShell()->SetModified();
277 rBindings.Invalidate(SID_SAVEDOC);
278 rBindings.Invalidate(SID_DOC_MODIFIED);
281 OUString aStr( pReqArgs->Get( SID_ENTER_STRING ).GetValue() );
282 const SfxPoolItem* pDontCommitItem;
283 bool bCommit = true;
284 if (pReqArgs->HasItem(FN_PARAM_1, &pDontCommitItem))
285 bCommit = !(static_cast<const SfxBoolItem*>(pDontCommitItem)->GetValue());
287 ScInputHandler* pHdl = pScMod->GetInputHdl(pTabViewShell);
288 if (bCommit)
290 pTabViewShell->EnterData( GetViewData().GetCurX(),
291 GetViewData().GetCurY(),
292 GetViewData().GetTabNo(),
293 aStr, nullptr,
294 true /*bMatrixExpand*/);
296 else if (pHdl)
298 pScMod->SetInputMode(SC_INPUT_TABLE);
300 EditView* pTableView = pHdl->GetActiveView();
301 pHdl->DataChanging();
302 if (pTableView)
303 pTableView->getEditEngine().SetText(aStr);
304 pHdl->DataChanged();
306 pScMod->SetInputMode(SC_INPUT_NONE);
309 if ( !pHdl || !pHdl->IsInEnterHandler() )
311 // UpdateInputHandler is needed after the cell content
312 // has changed, but if called from EnterHandler, UpdateInputHandler
313 // will be called later when moving the cursor.
314 pTabViewShell->UpdateInputHandler();
317 rReq.Done();
319 // no GrabFocus here, as otherwise on a Mac the tab jumps before the
320 // sideview, when the input was not finished
321 // (GrabFocus is called in KillEditView)
324 break;
326 case SID_INSERT_MATRIX:
328 if ( pReqArgs )
330 OUString aStr = static_cast<const SfxStringItem&>(pReqArgs->
331 Get( SID_INSERT_MATRIX )).GetValue();
332 ScDocument& rDoc = GetViewData().GetDocument();
333 pTabViewShell->EnterMatrix( aStr, rDoc.GetGrammar() );
334 rReq.Done();
337 break;
339 case FID_INPUTLINE_ENTER:
340 case FID_INPUTLINE_BLOCK:
341 case FID_INPUTLINE_MATRIX:
343 if( pReqArgs == nullptr ) //XXX temporary HACK to avoid GPF
344 break;
346 const ScInputStatusItem* pStatusItem
347 = static_cast<const ScInputStatusItem*>(&pReqArgs->
348 Get( FID_INPUTLINE_STATUS ));
350 const ScAddress& aCursorPos = pStatusItem->GetPos();
351 const OUString& aString = pStatusItem->GetString();
352 const EditTextObject* pData = pStatusItem->GetEditData();
354 if (pData)
356 if (nSlot == FID_INPUTLINE_BLOCK)
358 pTabViewShell->EnterBlock( aString, pData );
360 else if ( !aString.isEmpty() && ( aString[0] == '=' || aString[0] == '+' || aString[0] == '-' ) )
362 pTabViewShell->EnterData( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(),
363 aString, pData, true /*bMatrixExpand*/);
365 else
367 pTabViewShell->EnterData(aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), *pData);
370 else
372 if (nSlot == FID_INPUTLINE_ENTER)
374 if (
375 aCursorPos.Col() == GetViewData().GetCurX() &&
376 aCursorPos.Row() == GetViewData().GetCurY() &&
377 aCursorPos.Tab() == GetViewData().GetTabNo()
380 SfxStringItem aItem( SID_ENTER_STRING, aString );
382 const SfxPoolItem* aArgs[2];
383 aArgs[0] = &aItem;
384 aArgs[1] = nullptr;
385 rBindings.Execute( SID_ENTER_STRING, aArgs );
387 else
389 pTabViewShell->EnterData( aCursorPos.Col(),
390 aCursorPos.Row(),
391 aCursorPos.Tab(),
392 aString, nullptr,
393 true /*bMatrixExpand*/);
394 rReq.Done();
397 else if (nSlot == FID_INPUTLINE_BLOCK)
399 pTabViewShell->EnterBlock( aString, nullptr );
400 rReq.Done();
402 else
404 ScDocument& rDoc = GetViewData().GetDocument();
405 pTabViewShell->EnterMatrix( aString, rDoc.GetGrammar() );
406 rReq.Done();
410 pTabViewShell->SetAutoSpellData(
411 aCursorPos.Col(), aCursorPos.Row(), pStatusItem->GetMisspellRanges());
413 // no GrabFocus here, as otherwise on a Mac the tab jumps before the
414 // sideview, when the input was not finished
415 // (GrabFocus is called in KillEditView)
417 break;
419 case SID_OPENDLG_FUNCTION:
421 const SfxViewShell* pViewShell = SfxViewShell::Current();
422 if (comphelper::LibreOfficeKit::isActive()
423 && pViewShell && pViewShell->isLOKMobilePhone())
425 // not set the dialog id in the mobile case or we would
426 // not be able to get cell address pasted in the edit view
427 // by just tapping on them
428 lcl_lokGetWholeFunctionList();
430 else
432 sal_uInt16 nId = SID_OPENDLG_FUNCTION;
433 SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
434 SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
435 bool bVis = comphelper::LibreOfficeKit::isActive() || pWnd == nullptr;
436 pScMod->SetRefDialog( nId, bVis );
438 rReq.Ignore();
440 break;
442 case SID_OPENDLG_CONSOLIDATE:
444 sal_uInt16 nId = ScConsolidateDlgWrapper::GetChildWindowId();
445 SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
446 SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
448 pScMod->SetRefDialog( nId, pWnd == nullptr );
450 break;
452 case SID_EASY_CONDITIONAL_FORMAT_DIALOG:
454 if (pReqArgs != nullptr)
456 const SfxPoolItem* pFormat;
457 if (pReqArgs->HasItem( FN_PARAM_1, &pFormat))
459 sal_Int16 nFormat = static_cast<const SfxInt16Item*>(pFormat)->GetValue();
460 sal_uInt16 nId = sc::ConditionalFormatEasyDialogWrapper::GetChildWindowId();
461 SfxViewFrame& rViewFrame = pTabViewShell->GetViewFrame();
462 SfxChildWindow* pWindow = rViewFrame.GetChildWindow(nId);
463 GetViewData().GetDocument().SetEasyConditionalFormatDialogData(
464 std::make_unique<ScConditionMode>(
465 static_cast<ScConditionMode>(nFormat)));
467 pScMod->SetRefDialog( nId, pWindow == nullptr );
471 break;
473 case FID_CELL_FORMAT:
475 if ( pReqArgs != nullptr )
477 // set cell attribute without dialog:
478 SfxItemSet aEmptySet(SfxItemSet::makeFixedSfxItemSet<ATTR_PATTERN_START, ATTR_PATTERN_END>(*pReqArgs->GetPool()));
479 // SfxItemSetFixed<ATTR_PATTERN_START, ATTR_PATTERN_END> aEmptySet( *pReqArgs->GetPool() );
481 SfxItemSetFixed<ATTR_PATTERN_START, ATTR_PATTERN_END> aNewSet( *pReqArgs->GetPool() );
483 const SfxPoolItem* pAttr = nullptr;
484 sal_uInt16 nWhich = 0;
486 for ( nWhich=ATTR_PATTERN_START; nWhich<=ATTR_PATTERN_END; nWhich++ )
487 if ( pReqArgs->GetItemState( nWhich, true, &pAttr ) == SfxItemState::SET )
488 aNewSet.Put( *pAttr );
490 pTabViewShell->ApplyAttributes( aNewSet, aEmptySet );
492 rReq.Done();
494 else
496 pTabViewShell->ExecuteCellFormatDlg( rReq, u""_ustr );
499 break;
501 case SID_ENABLE_HYPHENATION:
502 pTabViewShell->ExecuteCellFormatDlg(rReq, u"alignment"_ustr);
503 break;
505 case SID_PROPERTY_PANEL_CELLTEXT_DLG:
506 pTabViewShell->ExecuteCellFormatDlg( rReq, u"font"_ustr );
507 break;
509 case SID_CELL_FORMAT_BORDER:
510 pTabViewShell->ExecuteCellFormatDlg( rReq, u"borders"_ustr );
511 break;
513 case SID_CHAR_DLG_EFFECT:
514 pTabViewShell->ExecuteCellFormatDlg( rReq, u"fonteffects"_ustr );
515 break;
517 case SID_OPENDLG_SOLVE:
519 sal_uInt16 nId = ScSolverDlgWrapper::GetChildWindowId();
520 SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
521 SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
523 pScMod->SetRefDialog( nId, pWnd == nullptr );
525 break;
527 case SID_OPENDLG_OPTSOLVER:
529 sal_uInt16 nId = ScOptSolverDlgWrapper::GetChildWindowId();
530 SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
531 SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
533 pScMod->SetRefDialog( nId, pWnd == nullptr );
535 break;
537 case SID_OPENDLG_TABOP:
539 sal_uInt16 nId = ScTabOpDlgWrapper::GetChildWindowId();
540 SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
541 SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
543 pScMod->SetRefDialog( nId, pWnd == nullptr );
545 break;
547 case SID_SCENARIOS:
549 ScDocument& rDoc = GetViewData().GetDocument();
550 ScMarkData& rMark = GetViewData().GetMarkData();
551 SCTAB nTab = GetViewData().GetTabNo();
553 if ( rDoc.IsScenario(nTab) )
555 rMark.MarkToMulti();
556 if ( rMark.IsMultiMarked() )
559 bool bExtend = rReq.IsAPI();
560 if (!bExtend)
562 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pTabViewShell->GetFrameWeld(),
563 VclMessageType::Question, VclButtonsType::YesNo,
564 ScResId(STR_UPDATE_SCENARIO)));
565 xQueryBox->set_default_response(RET_YES);
566 bExtend = xQueryBox->run() == RET_YES;
569 if (bExtend)
571 pTabViewShell->ExtendScenario();
572 rReq.Done();
575 else if( ! rReq.IsAPI() )
577 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(pTabViewShell->GetFrameWeld(),
578 VclMessageType::Warning, VclButtonsType::Ok,
579 ScResId(STR_NOAREASELECTED)));
580 xErrorBox->run();
583 else
585 rMark.MarkToMulti();
586 if ( rMark.IsMultiMarked() )
588 SCTAB i=1;
589 OUString aBaseName;
590 OUString aName;
591 Color aColor;
592 ScScenarioFlags nFlags;
594 OUString aTmp;
595 rDoc.GetName(nTab, aTmp);
596 aBaseName = aTmp + "_" + ScResId(STR_SCENARIO) + "_";
598 // first test, if the prefix is recognised as valid,
599 // else avoid only doubles
600 bool bPrefix = ScDocument::ValidTabName( aBaseName );
601 OSL_ENSURE(bPrefix, "invalid sheet name");
603 while ( rDoc.IsScenario(nTab+i) )
604 i++;
606 bool bValid;
607 SCTAB nDummy;
610 aName = aBaseName + OUString::number( i );
611 if (bPrefix)
612 bValid = rDoc.ValidNewTabName( aName );
613 else
614 bValid = !rDoc.GetTable( aName, nDummy );
615 ++i;
617 while ( !bValid && i <= MAXTAB + 2 );
619 if ( pReqArgs != nullptr )
621 OUString aArgName;
622 OUString aArgComment;
623 if ( const SfxStringItem* pItem = pReqArgs->GetItemIfSet( SID_SCENARIOS ) )
624 aArgName = pItem->GetValue();
625 if ( const SfxStringItem* pItem = pReqArgs->GetItemIfSet( SID_NEW_TABLENAME ) )
626 aArgComment = pItem->GetValue();
628 aColor = COL_LIGHTGRAY; // Default
629 nFlags = ScScenarioFlags::NONE; // not TwoWay
631 pTabViewShell->MakeScenario( aArgName, aArgComment, aColor, nFlags );
632 if( ! rReq.IsAPI() )
633 rReq.Done();
635 else
637 bool bSheetProtected = rDoc.IsTabProtected(nTab);
638 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
640 ScopedVclPtr<AbstractScNewScenarioDlg> pNewDlg(pFact->CreateScNewScenarioDlg(pTabViewShell->GetFrameWeld(), aName, false, bSheetProtected));
641 if ( pNewDlg->Execute() == RET_OK )
643 OUString aComment;
644 pNewDlg->GetScenarioData( aName, aComment, aColor, nFlags );
645 pTabViewShell->MakeScenario( aName, aComment, aColor, nFlags );
647 rReq.AppendItem( SfxStringItem( SID_SCENARIOS, aName ) );
648 rReq.AppendItem( SfxStringItem( SID_NEW_TABLENAME, aComment ) );
649 rReq.Done();
653 else if( ! rReq.IsAPI() )
655 pTabViewShell->ErrorMessage(STR_ERR_NEWSCENARIO);
659 break;
661 case SID_SELECTALL:
663 SCTAB nTab = GetViewData().GetTabNo();
664 SCCOL nStartCol = GetViewData().GetCurX();
665 SCROW nStartRow = GetViewData().GetCurY();
666 SCCOL nEndCol = nStartCol;
667 SCROW nEndRow = nStartRow;
668 bool bCanMark = false;
670 ScMarkData& rMarkdata = GetViewData().GetMarkData();
671 const bool bSelectFirst(officecfg::Office::Calc::Input::SelectRangeBeforeAll::get());
673 if (bSelectFirst && !rMarkdata.IsMarked())
675 const ScDocument& rDoc = GetViewData().GetDocument();
676 rDoc.GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, true, false );
677 bCanMark = nStartCol != nEndCol || nStartRow != nEndRow;
680 if (bCanMark)
682 const ScRange aRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab);
683 pTabViewShell->MarkRange(aRange, false);
685 else
686 pTabViewShell->SelectAll();
688 rReq.Done();
690 break;
692 case FID_ROW_HEIGHT:
694 const SfxPoolItem* pRow;
695 const SfxUInt16Item* pHeight;
696 sal_uInt16 nHeight;
698 if ( pReqArgs && (pHeight = pReqArgs->GetItemIfSet( FID_ROW_HEIGHT )) &&
699 pReqArgs->HasItem( FN_PARAM_1, &pRow ) )
701 std::vector<sc::ColRowSpan> aRanges;
702 SCCOLROW nRow = static_cast<const SfxInt32Item*>(pRow)->GetValue() - 1;
703 nHeight = pHeight->GetValue();
704 ScMarkData& rMark = GetViewData().GetMarkData();
706 if ( rMark.IsRowMarked( static_cast<SCROW>(nRow) ) )
708 aRanges = rMark.GetMarkedRowSpans();
710 else
712 aRanges.emplace_back(nRow, nRow);
715 pTabViewShell->SetWidthOrHeight(false, aRanges, SC_SIZE_DIRECT, o3tl::toTwips(nHeight, o3tl::Length::mm100));
717 else if ( pReqArgs && (pHeight = pReqArgs->GetItemIfSet( FID_ROW_HEIGHT )) )
719 nHeight = pHeight->GetValue();
721 // #101390#; the value of the macro is in HMM so use convertMm100ToTwip to convert
722 pTabViewShell->SetMarkedWidthOrHeight( false, SC_SIZE_DIRECT,
723 o3tl::toTwips(nHeight, o3tl::Length::mm100));
724 if( ! rReq.IsAPI() )
725 rReq.Done();
727 else
729 ScViewData& rData = GetViewData();
730 FieldUnit eMetric = pScMod->GetAppOptions().GetAppMetric();
731 sal_uInt16 nCurHeight = rData.GetDocument().
732 GetRowHeight( rData.GetCurY(),
733 rData.GetTabNo() );
734 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
735 VclPtr<AbstractScMetricInputDlg> pDlg(pFact->CreateScMetricInputDlg(
736 pTabViewShell->GetFrameWeld(), u"RowHeightDialog"_ustr, nCurHeight,
737 rData.GetDocument().GetSheetOptimalMinRowHeight(rData.GetTabNo()),
738 eMetric, 2, MAX_ROW_HEIGHT));
740 pDlg->StartExecuteAsync([pDlg, pTabViewShell](sal_Int32 nResult){
741 if (nResult == RET_OK)
743 SfxRequest pRequest(pTabViewShell->GetViewFrame(), FID_ROW_HEIGHT);
744 tools::Long nVal = pDlg->GetInputValue();
745 pTabViewShell->SetMarkedWidthOrHeight( false, SC_SIZE_DIRECT, static_cast<sal_uInt16>(nVal) );
747 // #101390#; the value of the macro should be in HMM so use TwipsToEvenHMM to convert
748 pRequest.AppendItem( SfxUInt16Item( FID_ROW_HEIGHT, static_cast<sal_uInt16>(TwipsToEvenHMM(nVal)) ) );
749 pRequest.Done();
751 pDlg->disposeOnce();
755 break;
757 case FID_ROW_OPT_HEIGHT:
759 if ( pReqArgs )
761 const SfxUInt16Item& rUInt16Item = pReqArgs->Get( FID_ROW_OPT_HEIGHT );
763 // #101390#; the value of the macro is in HMM so use convertMm100ToTwip to convert
764 pTabViewShell->SetMarkedWidthOrHeight( false, SC_SIZE_OPTIMAL,
765 o3tl::toTwips(rUInt16Item.GetValue(), o3tl::Length::mm100) );
766 ScGlobal::nLastRowHeightExtra = rUInt16Item.GetValue();
768 if( ! rReq.IsAPI() )
769 rReq.Done();
771 else
773 FieldUnit eMetric = pScMod->GetAppOptions().GetAppMetric();
775 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
776 VclPtr<AbstractScMetricInputDlg> pDlg(pFact->CreateScMetricInputDlg(
777 pTabViewShell->GetFrameWeld(), u"OptimalRowHeightDialog"_ustr,
778 ScGlobal::nLastRowHeightExtra, 0, eMetric, 2, MAX_EXTRA_HEIGHT));
780 pDlg->StartExecuteAsync([pDlg, pTabViewShell](sal_Int32 nResult){
781 if ( nResult == RET_OK )
783 SfxRequest pRequest(pTabViewShell->GetViewFrame(), FID_ROW_OPT_HEIGHT);
784 tools::Long nVal = pDlg->GetInputValue();
785 pTabViewShell->SetMarkedWidthOrHeight( false, SC_SIZE_OPTIMAL, static_cast<sal_uInt16>(nVal) );
786 ScGlobal::nLastRowHeightExtra = nVal;
788 // #101390#; the value of the macro should be in HMM so use TwipsToEvenHMM to convert
789 pRequest.AppendItem( SfxUInt16Item( FID_ROW_OPT_HEIGHT, static_cast<sal_uInt16>(TwipsToEvenHMM(nVal)) ) );
790 pRequest.Done();
792 pDlg->disposeOnce();
796 break;
798 case FID_COL_WIDTH:
800 const SfxPoolItem* pColumn;
801 const SfxUInt16Item* pWidth;
802 sal_uInt16 nWidth;
804 if ( pReqArgs && (pWidth = pReqArgs->GetItemIfSet( FID_COL_WIDTH )) &&
805 pReqArgs->HasItem( FN_PARAM_1, &pColumn ) )
807 std::vector<sc::ColRowSpan> aRanges;
808 SCCOLROW nColumn = static_cast<const SfxUInt16Item*>(pColumn)->GetValue() - 1;
809 nWidth = pWidth->GetValue();
810 ScMarkData& rMark = GetViewData().GetMarkData();
812 if ( rMark.IsColumnMarked( static_cast<SCCOL>(nColumn) ) )
814 aRanges = rMark.GetMarkedColSpans();
816 else
818 aRanges.emplace_back(nColumn, nColumn);
821 pTabViewShell->SetWidthOrHeight(true, aRanges, SC_SIZE_DIRECT, o3tl::toTwips(nWidth, o3tl::Length::mm100));
823 else if ( pReqArgs && (pWidth = pReqArgs->GetItemIfSet( FID_COL_WIDTH )) )
825 nWidth = pWidth->GetValue();
827 // #101390#; the value of the macro is in HMM so use convertMm100ToTwip to convert
828 pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_DIRECT,
829 o3tl::toTwips(nWidth, o3tl::Length::mm100));
830 if( ! rReq.IsAPI() )
831 rReq.Done();
833 else
835 FieldUnit eMetric = pScMod->GetAppOptions().GetAppMetric();
836 ScViewData& rData = GetViewData();
837 sal_uInt16 nCurHeight = rData.GetDocument().
838 GetColWidth( rData.GetCurX(),
839 rData.GetTabNo() );
840 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
841 VclPtr<AbstractScMetricInputDlg> pDlg(pFact->CreateScMetricInputDlg(
842 pTabViewShell->GetFrameWeld(), u"ColWidthDialog"_ustr, nCurHeight,
843 STD_COL_WIDTH, eMetric, 2, MAX_COL_WIDTH));
845 pDlg->StartExecuteAsync([pDlg, pTabViewShell](sal_Int32 nResult){
846 if ( nResult == RET_OK )
848 SfxRequest pRequest(pTabViewShell->GetViewFrame(), FID_COL_WIDTH);
849 tools::Long nVal = pDlg->GetInputValue();
850 pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_DIRECT, static_cast<sal_uInt16>(nVal) );
852 // #101390#; the value of the macro should be in HMM so use TwipsToEvenHMM to convert
853 pRequest.AppendItem( SfxUInt16Item( FID_COL_WIDTH, static_cast<sal_uInt16>(TwipsToEvenHMM(nVal))) );
854 pRequest.Done();
856 pDlg->disposeOnce();
860 break;
862 case FID_COL_OPT_WIDTH:
864 if ( pReqArgs )
866 const SfxUInt16Item& rUInt16Item = pReqArgs->Get( FID_COL_OPT_WIDTH );
868 // #101390#; the value of the macro is in HMM so use convertMm100ToTwip to convert
869 pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_OPTIMAL,
870 o3tl::toTwips(rUInt16Item.GetValue(), o3tl::Length::mm100) );
871 ScGlobal::nLastColWidthExtra = rUInt16Item.GetValue();
873 if( ! rReq.IsAPI() )
874 rReq.Done();
876 else
878 FieldUnit eMetric = pScMod->GetAppOptions().GetAppMetric();
880 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
881 VclPtr<AbstractScMetricInputDlg> pDlg(pFact->CreateScMetricInputDlg(
882 pTabViewShell->GetFrameWeld(), u"OptimalColWidthDialog"_ustr,
883 ScGlobal::nLastColWidthExtra, STD_EXTRA_WIDTH, eMetric, 2, MAX_EXTRA_WIDTH));
885 pDlg->StartExecuteAsync([pDlg, pTabViewShell](sal_Int32 nResult){
886 SfxRequest pRequest(pTabViewShell->GetViewFrame(), FID_COL_OPT_WIDTH);
887 if ( nResult == RET_OK )
889 tools::Long nVal = pDlg->GetInputValue();
890 pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_OPTIMAL, static_cast<sal_uInt16>(nVal) );
891 ScGlobal::nLastColWidthExtra = nVal;
893 // #101390#; the value of the macro should be in HMM so use TwipsToEvenHMM to convert
894 pRequest.AppendItem( SfxUInt16Item( FID_COL_OPT_WIDTH, static_cast<sal_uInt16>(TwipsToEvenHMM(nVal)) ) );
895 pRequest.Done();
897 pDlg->disposeOnce();
901 break;
903 case FID_COL_OPT_DIRECT:
904 pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_OPTIMAL, STD_EXTRA_WIDTH );
905 rReq.Done();
906 break;
908 case FID_ROW_HIDE:
909 pTabViewShell->SetMarkedWidthOrHeight( false, SC_SIZE_DIRECT, 0 );
910 rReq.Done();
911 break;
912 case FID_ROW_SHOW:
913 pTabViewShell->SetMarkedWidthOrHeight( false, SC_SIZE_SHOW, 0 );
914 rReq.Done();
915 break;
916 case FID_COL_HIDE:
917 pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_DIRECT, 0 );
918 rReq.Done();
919 break;
920 case FID_COL_SHOW:
921 pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_SHOW, 0 );
922 rReq.Done();
923 break;
925 case SID_CELL_FORMAT_RESET:
927 pTabViewShell->DeleteContents( InsertDeleteFlags::HARDATTR | InsertDeleteFlags::EDITATTR );
928 rReq.Done();
930 break;
932 case FID_MERGE_ON:
933 case FID_MERGE_OFF:
934 case FID_MERGE_TOGGLE:
936 if ( !GetViewData().GetDocument().GetChangeTrack() )
938 // test whether to merge or to split
939 bool bMerge = false;
940 bool bCenter = false;
941 switch( nSlot )
943 case FID_MERGE_ON:
944 bMerge = true;
945 break;
946 case FID_MERGE_OFF:
947 bMerge = false;
948 break;
949 case FID_MERGE_TOGGLE:
951 bCenter = true;
952 std::unique_ptr<SfxPoolItem> pItem;
953 if( rBindings.QueryState( nSlot, pItem ) >= SfxItemState::DEFAULT )
954 bMerge = !static_cast< SfxBoolItem* >( pItem.get() )->GetValue();
956 break;
959 if( bMerge )
961 // merge - check if to move contents of covered cells
962 bool bMoveContents = false;
963 bool bApi = rReq.IsAPI();
964 const SfxPoolItem* pItem;
965 if ( pReqArgs &&
966 pReqArgs->GetItemState(nSlot, true, &pItem) == SfxItemState::SET )
968 assert(dynamic_cast<const SfxBoolItem*>( pItem) && "wrong item");
969 bMoveContents = static_cast<const SfxBoolItem*>(pItem)->GetValue();
972 pTabViewShell->MergeCells( bApi, bMoveContents, bCenter, nSlot );
974 else
976 // split cells
977 if (pTabViewShell->RemoveMerge())
979 rBindings.Invalidate( nSlot );
980 rReq.Done();
983 break;
986 break;
988 case SID_AUTOFORMAT:
990 weld::Window* pDlgParent = pTabViewShell->GetFrameWeld();
991 SCCOL nStartCol;
992 SCROW nStartRow;
993 SCTAB nStartTab;
994 SCCOL nEndCol;
995 SCROW nEndRow;
996 SCTAB nEndTab;
998 const ScMarkData& rMark = GetViewData().GetMarkData();
999 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
1000 pTabViewShell->MarkDataArea();
1002 GetViewData().GetSimpleArea( nStartCol,nStartRow,nStartTab,
1003 nEndCol,nEndRow,nEndTab );
1005 if ( ( std::abs(nEndCol-nStartCol) > 1 )
1006 && ( std::abs(nEndRow-nStartRow) > 1 ) )
1008 if ( pReqArgs )
1010 const SfxStringItem& rNameItem = pReqArgs->Get( SID_AUTOFORMAT );
1011 ScAutoFormat* pFormat = ScGlobal::GetOrCreateAutoFormat();
1012 ScAutoFormat::const_iterator it = pFormat->find(rNameItem.GetValue());
1013 ScAutoFormat::const_iterator itBeg = pFormat->begin();
1014 size_t nIndex = std::distance(itBeg, it);
1016 pTabViewShell->AutoFormat( nIndex );
1018 if( ! rReq.IsAPI() )
1019 rReq.Done();
1021 else
1023 ScGlobal::ClearAutoFormat();
1024 std::unique_ptr<ScAutoFormatData> pNewEntry(pTabViewShell->CreateAutoFormatData());
1025 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
1027 ScopedVclPtr<AbstractScAutoFormatDlg> pDlg(pFact->CreateScAutoFormatDlg(pDlgParent, ScGlobal::GetOrCreateAutoFormat(), pNewEntry.get(), GetViewData()));
1029 if ( pDlg->Execute() == RET_OK )
1031 ScEditableTester aTester( pTabViewShell );
1032 if ( !aTester.IsEditable() )
1034 pTabViewShell->ErrorMessage(aTester.GetMessageId());
1036 else
1038 pTabViewShell->AutoFormat( pDlg->GetIndex() );
1040 rReq.AppendItem( SfxStringItem( SID_AUTOFORMAT, pDlg->GetCurrFormatName() ) );
1041 rReq.Done();
1046 else
1048 std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(pDlgParent,
1049 VclMessageType::Warning, VclButtonsType::Ok,
1050 ScResId(STR_INVALID_AFAREA)));
1051 xErrorBox->run();
1054 break;
1056 case SID_CANCEL:
1058 if (GetViewData().HasEditView(GetViewData().GetActivePart()))
1059 pScMod->InputCancelHandler();
1060 else if (pTabViewShell->HasPaintBrush())
1061 pTabViewShell->ResetBrushDocument(); // abort format paint brush
1062 else if (pTabViewShell->HasHintWindow())
1063 pTabViewShell->RemoveHintWindow();
1064 else if( ScViewUtil::IsFullScreen( *pTabViewShell ) )
1065 ScViewUtil::SetFullScreen( *pTabViewShell, false );
1066 else
1068 // TODO/LATER: when is this code executed?
1069 pTabViewShell->Escape();
1072 break;
1074 case SID_ACCEPT_FORMULA:
1076 if (GetViewData().HasEditView(GetViewData().GetActivePart()))
1077 pScMod->InputEnterHandler();
1079 break;
1081 case SID_START_FORMULA:
1083 ScInputHandler* pInputHandler = pScMod->GetInputHdl();
1084 if (pInputHandler && pInputHandler->GetInputWindow())
1085 pInputHandler->GetInputWindow()->StartFormula();
1087 break;
1089 case SID_DATA_SELECT:
1090 pTabViewShell->StartDataSelect();
1091 break;
1093 case SID_DETECTIVE_FILLMODE:
1095 bool bOldMode = pTabViewShell->IsAuditShell();
1096 pTabViewShell->SetAuditShell( !bOldMode );
1097 pTabViewShell->Invalidate( nSlot );
1099 break;
1101 case FID_INPUTLINE_STATUS:
1102 OSL_FAIL("Execute from InputLine status");
1103 break;
1105 case SID_STATUS_DOCPOS:
1106 // Launch navigator.
1107 GetViewData().GetDispatcher().Execute(
1108 SID_NAVIGATOR, SfxCallMode::SYNCHRON|SfxCallMode::RECORD );
1109 break;
1111 case SID_MARKAREA:
1112 // called from Basic at the hidden view to select a range in the visible view
1113 OSL_FAIL("old slot SID_MARKAREA");
1114 break;
1116 case FID_MOVE_KEEP_INSERT_MODE:
1118 const SfxBoolItem* pEnabledArg = rReq.GetArg<SfxBoolItem>(FID_MOVE_KEEP_INSERT_MODE);
1119 if (!pEnabledArg) {
1120 SAL_WARN("sfx.appl", "FID_MOVE_KEEP_INSERT_MODE: must specify if you would like this to be enabled");
1121 break;
1124 ScInputOptions aInputOptions = pScMod->GetInputOptions();
1126 aInputOptions.SetMoveKeepEdit(pEnabledArg->GetValue());
1127 pScMod->SetInputOptions(aInputOptions);
1129 if (comphelper::LibreOfficeKit::isActive())
1130 pTabViewShell->SetMoveKeepEdit(pEnabledArg->GetValue());
1132 break;
1135 default:
1136 OSL_FAIL("ScCellShell::Execute: unknown slot");
1137 break;
1141 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */