tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / view / tabvwsha.cxx
blobb796a05d9821b841df6685845760523244ecfae7
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 <com/sun/star/table/BorderLineStyle.hpp>
21 #include <officecfg/Office/Calc.hxx>
23 #include <comphelper/lok.hxx>
24 #include <editeng/boxitem.hxx>
25 #include <editeng/langitem.hxx>
26 #include <o3tl/temporary.hxx>
27 #include <sfx2/bindings.hxx>
28 #include <sfx2/request.hxx>
29 #include <sfx2/sfxdlg.hxx>
30 #include <sfx2/sidebar/Sidebar.hxx>
31 #include <sfx2/viewfrm.hxx>
32 #include <sfx2/dispatch.hxx>
33 #include <sfx2/newstyle.hxx>
34 #include <sfx2/tplpitem.hxx>
35 #include <svl/ilstitem.hxx>
36 #include <svl/numformat.hxx>
37 #include <svl/zformat.hxx>
38 #include <svl/int64item.hxx>
39 #include <svl/ptitem.hxx>
40 #include <svl/srchitem.hxx>
41 #include <svl/srchdefs.hxx>
42 #include <svl/stritem.hxx>
43 #include <svl/whiter.hxx>
44 #include <svx/numinf.hxx>
45 #include <svx/xbtmpit.hxx>
46 #include <svx/xlndsit.hxx>
47 #include <svx/xlnstit.hxx>
48 #include <svx/xlnedit.hxx>
49 #include <svx/xflgrit.hxx>
50 #include <svx/xflftrit.hxx>
51 #include <svx/xflhtit.hxx>
52 #include <svx/zoomslideritem.hxx>
54 #include <global.hxx>
55 #include <appoptio.hxx>
56 #include <attrib.hxx>
57 #include <cellform.hxx>
58 #include <cellvalue.hxx>
59 #include <compiler.hxx>
60 #include <docsh.hxx>
61 #include <document.hxx>
62 #include <formulacell.hxx>
63 #include <globstr.hrc>
64 #include <inputhdl.hxx>
65 #include <inputwin.hxx>
66 #include <markdata.hxx>
67 #include <patattr.hxx>
68 #include <sc.hrc>
69 #include <scabstdlg.hxx>
70 #include <scitems.hxx>
71 #include <scmod.hxx>
72 #include <scresid.hxx>
73 #include <stlpool.hxx>
74 #include <tabvwsh.hxx>
75 #include <tokenarray.hxx>
76 #include <viewdata.hxx>
77 #include <printfun.hxx>
78 #include <undostyl.hxx>
79 #include <futext.hxx>
81 #include <memory>
83 using namespace com::sun::star;
85 bool ScTabViewShell::GetFunction( OUString& rFuncStr, FormulaError nErrCode )
87 sal_uInt32 nFuncs = ScModule::get()->GetAppOptions().GetStatusFunc();
88 ScViewData& rViewData = GetViewData();
89 ScMarkData& rMark = rViewData.GetMarkData();
90 bool bIgnoreError = (rMark.IsMarked() || rMark.IsMultiMarked());
91 bool bFirst = true;
92 for ( sal_uInt16 nFunc = 0; nFunc < 32; nFunc++ )
94 if ( !(nFuncs & (1U << nFunc)) )
95 continue;
96 ScSubTotalFunc eFunc = static_cast<ScSubTotalFunc>(nFunc);
98 if (bIgnoreError && (eFunc == SUBTOTAL_FUNC_CNT || eFunc == SUBTOTAL_FUNC_CNT2))
99 nErrCode = FormulaError::NONE;
101 if (nErrCode != FormulaError::NONE)
103 rFuncStr = ScGlobal::GetLongErrorString(nErrCode);
104 return true;
107 TranslateId pGlobStrId;
108 switch (eFunc)
110 case SUBTOTAL_FUNC_AVE: pGlobStrId = STR_FUN_TEXT_AVG; break;
111 case SUBTOTAL_FUNC_CNT: pGlobStrId = STR_FUN_TEXT_COUNT; break;
112 case SUBTOTAL_FUNC_CNT2: pGlobStrId = STR_FUN_TEXT_COUNT2; break;
113 case SUBTOTAL_FUNC_MAX: pGlobStrId = STR_FUN_TEXT_MAX; break;
114 case SUBTOTAL_FUNC_MIN: pGlobStrId = STR_FUN_TEXT_MIN; break;
115 case SUBTOTAL_FUNC_SUM: pGlobStrId = STR_FUN_TEXT_SUM; break;
116 case SUBTOTAL_FUNC_SELECTION_COUNT: pGlobStrId = STR_FUN_TEXT_SELECTION_COUNT; break;
118 default:
120 // added to avoid warnings
123 if (pGlobStrId)
125 ScDocument& rDoc = rViewData.GetDocument();
126 SCCOL nPosX = rViewData.GetCurX();
127 SCROW nPosY = rViewData.GetCurY();
128 SCTAB nTab = rViewData.GetTabNo();
130 OUString aStr = ScResId(pGlobStrId) + ": ";
132 ScAddress aCursor( nPosX, nPosY, nTab );
133 double nVal;
134 if ( rDoc.GetSelectionFunction( eFunc, aCursor, rMark, nVal ) )
136 if ( nVal == 0.0 )
137 aStr += "0";
138 else
140 // Number in the standard format, the other on the cursor position
141 ScInterpreterContext& rContext = rDoc.GetNonThreadedContext();
142 sal_uInt32 nNumFmt = 0;
143 if ( eFunc != SUBTOTAL_FUNC_CNT && eFunc != SUBTOTAL_FUNC_CNT2 && eFunc != SUBTOTAL_FUNC_SELECTION_COUNT)
145 // number format from attributes or formula
146 nNumFmt = rDoc.GetNumberFormat( nPosX, nPosY, nTab );
147 // If the number format is time (without date) and the
148 // result is not within 24 hours, use a duration
149 // format. Summing date+time doesn't make much sense
150 // otherwise but we also don't want to display duration
151 // for a single date+time value.
152 if (nVal < 0.0 || nVal >= 1.0)
154 const SvNumberformat* pFormat = rContext.NFGetFormatEntry(nNumFmt);
155 if (pFormat && (pFormat->GetType() == SvNumFormatType::TIME))
156 nNumFmt = rContext.NFGetTimeFormat( nVal, pFormat->GetLanguage(), true);
160 OUString aValStr;
161 const Color* pDummy;
162 rContext.NFGetOutputString( nVal, nNumFmt, aValStr, &pDummy );
163 aStr += aValStr;
166 if ( bFirst )
168 rFuncStr += aStr;
169 bFirst = false;
171 else
172 rFuncStr += "; " + aStr;
176 return !rFuncStr.isEmpty();
179 // Functions that are disabled, depending on the selection
180 // Default:
181 // SID_DELETE,
182 // SID_DELETE_CONTENTS,
183 // FID_DELETE_CELL
184 // FID_VALIDATION
186 void ScTabViewShell::GetState( SfxItemSet& rSet )
188 ScViewData& rViewData = GetViewData();
189 ScDocument& rDoc = rViewData.GetDocument();
190 ScDocShell* pDocShell = rViewData.GetDocShell();
191 ScMarkData& rMark = rViewData.GetMarkData();
192 SCCOL nPosX = rViewData.GetCurX();
193 SCROW nPosY = rViewData.GetCurY();
194 SCTAB nTab = rViewData.GetTabNo();
196 SfxViewFrame& rThisFrame = GetViewFrame();
197 bool bOle = GetViewFrame().GetFrame().IsInPlace();
199 SCTAB nTabSelCount = rMark.GetSelectCount();
201 SfxWhichIter aIter(rSet);
202 sal_uInt16 nWhich = aIter.FirstWhich();
204 while ( nWhich )
206 switch ( nWhich )
208 case FID_CHG_COMMENT:
210 ScDocShell* pDocSh = GetViewData().GetDocShell();
211 ScAddress aPos( nPosX, nPosY, nTab );
212 if ( pDocSh->IsReadOnly() || !pDocSh->GetChangeAction(aPos) || pDocSh->IsDocShared() )
213 rSet.DisableItem( nWhich );
215 break;
217 case SID_OPENDLG_EDIT_PRINTAREA:
218 case SID_ADD_PRINTAREA:
219 case SID_DEFINE_PRINTAREA:
221 if ( pDocShell && pDocShell->IsDocShared() )
223 rSet.DisableItem( nWhich );
226 break;
228 case SID_DELETE_PRINTAREA:
229 if ( pDocShell && pDocShell->IsDocShared() )
231 rSet.DisableItem( nWhich );
233 else if (rDoc.IsPrintEntireSheet(nTab))
234 rSet.DisableItem(nWhich);
235 break;
237 case SID_STATUS_PAGESTYLE:
238 case SID_HFEDIT:
239 GetViewData().GetDocShell()->GetStatePageStyle( rSet, nTab );
240 break;
242 case SID_SEARCH_ITEM:
244 SvxSearchItem aItem(ScGlobal::GetSearchItem()); // make a copy.
245 // Search on current selection if a range is marked.
246 aItem.SetSelection(rMark.IsMarked());
247 rSet.Put(aItem);
248 break;
251 case SID_SEARCH_OPTIONS:
253 // Anything goes
254 SearchOptionFlags nOptions = SearchOptionFlags::ALL;
256 // No replacement if ReadOnly
257 if (GetViewData().GetDocShell()->IsReadOnly())
258 nOptions &= ~SearchOptionFlags( SearchOptionFlags::REPLACE | SearchOptionFlags::REPLACE_ALL );
259 rSet.Put( SfxUInt16Item( nWhich, static_cast<sal_uInt16>(nOptions) ) );
261 break;
263 case SID_CURRENTCELL:
265 ScAddress aScAddress( GetViewData().GetCurX(), GetViewData().GetCurY(), 0 );
266 OUString aAddr(aScAddress.Format(ScRefFlags::ADDR_ABS, nullptr, rDoc.GetAddressConvention()));
267 SfxStringItem aPosItem( SID_CURRENTCELL, aAddr );
269 rSet.Put( aPosItem );
271 break;
273 case SID_CURRENTTAB:
274 // Table for Basic is 1-based
275 rSet.Put( SfxUInt16Item( nWhich, static_cast<sal_uInt16>(GetViewData().GetTabNo()) + 1 ) );
276 break;
278 case SID_CURRENTDOC:
279 rSet.Put( SfxStringItem( nWhich, GetViewData().GetDocShell()->GetTitle() ) );
280 break;
282 case FID_TOGGLEINPUTLINE:
284 sal_uInt16 nId = ScInputWindowWrapper::GetChildWindowId();
286 if ( rThisFrame.KnowsChildWindow( nId ) )
288 SfxChildWindow* pWnd = rThisFrame.GetChildWindow( nId );
289 rSet.Put( SfxBoolItem( nWhich, pWnd != nullptr ) );
291 else
292 rSet.DisableItem( nWhich );
294 break;
296 case FID_DEL_MANUALBREAKS:
297 if (!rDoc.HasManualBreaks(nTab))
298 rSet.DisableItem( nWhich );
299 break;
301 case FID_RESET_PRINTZOOM:
303 // disable if already set to default
305 OUString aStyleName = rDoc.GetPageStyle( nTab );
306 ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
307 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName,
308 SfxStyleFamily::Page );
309 OSL_ENSURE( pStyleSheet, "PageStyle not found" );
310 if ( pStyleSheet )
312 SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
313 sal_uInt16 nScale = rStyleSet.Get(ATTR_PAGE_SCALE).GetValue();
314 sal_uInt16 nPages = rStyleSet.Get(ATTR_PAGE_SCALETOPAGES).GetValue();
315 if ( nScale == 100 && nPages == 0 )
316 rSet.DisableItem( nWhich );
319 break;
321 case SID_ZOOM_IN:
323 const Fraction& rZoomY = GetViewData().GetZoomY();
324 tools::Long nZoom = tools::Long(rZoomY * 100);
325 if (nZoom >= MAXZOOM)
326 rSet.DisableItem(nWhich);
328 break;
329 case SID_ZOOM_OUT:
331 const Fraction& rZoomY = GetViewData().GetZoomY();
332 tools::Long nZoom = tools::Long(rZoomY * 100);
333 if (nZoom <= MINZOOM)
334 rSet.DisableItem(nWhich);
336 break;
338 case FID_SCALE:
339 case SID_ATTR_ZOOM:
340 if ( bOle )
341 rSet.DisableItem( nWhich );
342 else
344 const Fraction& rOldY = GetViewData().GetZoomY();
345 sal_uInt16 nZoom = static_cast<sal_uInt16>(tools::Long( rOldY * 100 ));
346 rSet.Put( SvxZoomItem( SvxZoomType::PERCENT, nZoom, TypedWhichId<SvxZoomItem>(nWhich) ) );
348 break;
350 case SID_ATTR_ZOOMSLIDER:
352 if ( bOle )
353 rSet.DisableItem( nWhich );
354 else
356 const Fraction& rOldY = GetViewData().GetZoomY();
357 sal_uInt16 nCurrentZoom = static_cast<sal_uInt16>(tools::Long( rOldY * 100 ));
359 if( nCurrentZoom )
361 SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM, MAXZOOM, SID_ATTR_ZOOMSLIDER );
362 aZoomSliderItem.AddSnappingPoint( 100 );
363 rSet.Put( aZoomSliderItem );
367 break;
369 case FID_FUNCTION_BOX:
371 const bool bBoxOpen = ::sfx2::sidebar::Sidebar::IsPanelVisible(u"ScFunctionsPanel",
372 rThisFrame.GetFrame().GetFrameInterface());
373 rSet.Put(SfxBoolItem(nWhich, bBoxOpen));
374 break;
377 case FID_TOGGLESYNTAX:
378 rSet.Put(SfxBoolItem(nWhich, GetViewData().IsSyntaxMode()));
379 break;
381 case FID_TOGGLECOLROWHIGHLIGHTING:
382 rSet.Put(SfxBoolItem(
383 nWhich,
384 officecfg::Office::Calc::Content::Display::ColumnRowHighlighting::get()));
385 break;
387 case FID_TOGGLEHEADERS:
388 rSet.Put(SfxBoolItem(nWhich, GetViewData().IsHeaderMode()));
389 break;
391 case FID_TOGGLEFORMULA:
393 const ScViewOptions& rOpts = rViewData.GetOptions();
394 bool bFormulaMode = rOpts.GetOption( VOPT_FORMULAS );
395 rSet.Put(SfxBoolItem(nWhich, bFormulaMode ));
397 break;
399 case FID_NORMALVIEWMODE:
400 case FID_PAGEBREAKMODE:
401 // always handle both slots - they exclude each other
402 if ( bOle )
404 rSet.DisableItem( FID_NORMALVIEWMODE );
405 rSet.DisableItem( FID_PAGEBREAKMODE );
407 else
409 rSet.Put(SfxBoolItem(FID_NORMALVIEWMODE, !GetViewData().IsPagebreakMode()));
410 rSet.Put(SfxBoolItem(FID_PAGEBREAKMODE, GetViewData().IsPagebreakMode()));
412 break;
414 case FID_PROTECT_DOC:
416 if ( pDocShell && pDocShell->IsDocShared() )
418 rSet.DisableItem( nWhich );
420 else
422 rSet.Put( SfxBoolItem( nWhich, rDoc.IsDocProtected() ) );
425 break;
427 case FID_PROTECT_TABLE:
429 if ( pDocShell && pDocShell->IsDocShared() )
431 rSet.DisableItem( nWhich );
433 else
435 rSet.Put( SfxBoolItem( nWhich, rDoc.IsTabProtected( nTab ) ) );
438 break;
440 case SID_AUTO_OUTLINE:
442 if (rDoc.GetChangeTrack()!=nullptr || GetViewData().IsMultiMarked())
444 rSet.DisableItem( nWhich );
447 break;
449 case SID_OUTLINE_DELETEALL:
451 SCTAB nOlTab = GetViewData().GetTabNo();
452 ScOutlineTable* pOlTable = rDoc.GetOutlineTable( nOlTab );
453 if (pOlTable == nullptr)
454 rSet.DisableItem( nWhich );
456 break;
458 case SID_WINDOW_SPLIT:
459 rSet.Put(SfxBoolItem(nWhich,
460 rViewData.GetHSplitMode() == SC_SPLIT_NORMAL ||
461 rViewData.GetVSplitMode() == SC_SPLIT_NORMAL ));
462 break;
464 case SID_WINDOW_FIX:
465 if(!comphelper::LibreOfficeKit::isActive())
467 rSet.Put(SfxBoolItem(nWhich,
468 rViewData.GetHSplitMode() == SC_SPLIT_FIX ||
469 rViewData.GetVSplitMode() == SC_SPLIT_FIX ));
471 else
473 rSet.Put(SfxBoolItem(nWhich,
474 rViewData.GetLOKSheetFreezeIndex(true) > 0 ||
475 rViewData.GetLOKSheetFreezeIndex(false) > 0 ));
477 break;
479 case SID_WINDOW_FIX_COL:
480 case SID_WINDOW_FIX_ROW:
482 Point aPos;
483 bool bIsCol = (nWhich == SID_WINDOW_FIX_COL);
484 aPos.setX(rViewData.GetLOKSheetFreezeIndex(bIsCol));
485 aPos.setY(rViewData.GetTabNo());
486 rSet.Put(SfxPointItem(nWhich, aPos));
488 break;
490 case FID_CHG_SHOW:
492 if ( rDoc.GetChangeTrack() == nullptr || ( pDocShell && pDocShell->IsDocShared() ) )
493 rSet.DisableItem( nWhich );
495 break;
496 case FID_CHG_ACCEPT:
499 ( !rDoc.GetChangeTrack() && !rThisFrame.HasChildWindow(FID_CHG_ACCEPT) )
501 ( pDocShell && pDocShell->IsDocShared() )
504 rSet.DisableItem( nWhich);
506 else
508 rSet.Put(SfxBoolItem(FID_CHG_ACCEPT,
509 rThisFrame.HasChildWindow(FID_CHG_ACCEPT)));
512 break;
514 case SID_FORMATPAGE:
515 // in protected tables
516 if ( pDocShell && ( pDocShell->IsReadOnly() || pDocShell->IsDocShared() ) )
517 rSet.DisableItem( nWhich );
518 break;
520 case SID_PRINTPREVIEW:
521 // Toggle slot needs a State
522 rSet.Put( SfxBoolItem( nWhich, false ) );
523 break;
525 case SID_READONLY_MODE:
526 rSet.Put( SfxBoolItem( nWhich, GetViewData().GetDocShell()->IsReadOnly() ) );
527 break;
529 case FID_TAB_DESELECTALL:
530 if ( nTabSelCount == 1 )
531 rSet.DisableItem( nWhich ); // enabled only if several sheets are selected
532 break;
534 case FID_TOGGLEHIDDENCOLROW:
535 const svtools::ColorConfig& rColorCfg = ScModule::get()->GetColorConfig();
536 rSet.Put( SfxBoolItem( nWhich, rColorCfg.GetColorValue(svtools::CALCHIDDENROWCOL).bIsVisible) );
537 break;
539 } // switch ( nWitch )
540 nWhich = aIter.NextWhich();
541 } // while ( nWitch )
544 void ScTabViewShell::ExecuteCellFormatDlg(SfxRequest& rReq, const OUString &rName)
546 ScDocument& rDoc = GetViewData().GetDocument();
548 std::shared_ptr<SvxBoxItem> aLineOuter(std::make_shared<SvxBoxItem>(ATTR_BORDER));
549 std::shared_ptr<SvxBoxInfoItem> aLineInner(std::make_shared<SvxBoxInfoItem>(ATTR_BORDER_INNER));
551 const ScPatternAttr* pOldAttrs = GetSelectionPattern();
553 auto xOldSet = std::make_shared<SfxItemSet>(pOldAttrs->GetItemSet());
555 xOldSet->MergeRange(XATTR_FILLSTYLE, XATTR_FILLCOLOR);
557 xOldSet->MergeRange(SID_ATTR_BORDER_STYLES, SID_ATTR_BORDER_DEFAULT_WIDTH);
559 // We only allow these border line types.
560 std::vector<sal_Int32> aBorderStyles{
561 table::BorderLineStyle::SOLID,
562 table::BorderLineStyle::DOTTED,
563 table::BorderLineStyle::DASHED,
564 table::BorderLineStyle::FINE_DASHED,
565 table::BorderLineStyle::DASH_DOT,
566 table::BorderLineStyle::DASH_DOT_DOT,
567 table::BorderLineStyle::DOUBLE_THIN };
569 xOldSet->Put(SfxIntegerListItem(SID_ATTR_BORDER_STYLES, std::move(aBorderStyles)));
571 // Set the default border width to 0.75 points.
572 SfxInt64Item aBorderWidthItem(SID_ATTR_BORDER_DEFAULT_WIDTH, 75);
573 xOldSet->Put(aBorderWidthItem);
575 // Get border items and put them in the set:
576 GetSelectionFrame( aLineOuter, aLineInner );
578 //Fix border incorrect for RTL fdo#62399
579 if( rDoc.IsLayoutRTL( GetViewData().GetTabNo() ) )
581 std::unique_ptr<SvxBoxItem> aNewFrame(aLineOuter->Clone());
582 std::unique_ptr<SvxBoxInfoItem> aTempInfo(aLineInner->Clone());
584 if ( aLineInner->IsValid(SvxBoxInfoItemValidFlags::LEFT) )
585 aNewFrame->SetLine( aLineOuter->GetLeft(), SvxBoxItemLine::RIGHT );
586 if ( aLineInner->IsValid(SvxBoxInfoItemValidFlags::RIGHT) )
587 aNewFrame->SetLine( aLineOuter->GetRight(), SvxBoxItemLine::LEFT );
589 aLineInner->SetValid( SvxBoxInfoItemValidFlags::LEFT, aTempInfo->IsValid(SvxBoxInfoItemValidFlags::RIGHT));
590 aLineInner->SetValid( SvxBoxInfoItemValidFlags::RIGHT, aTempInfo->IsValid(SvxBoxInfoItemValidFlags::LEFT));
592 xOldSet->Put( std::move(aNewFrame) );
594 else
596 xOldSet->Put( *aLineOuter );
599 xOldSet->Put( *aLineInner );
601 // Generate NumberFormat Value from Value and Language and box it.
602 xOldSet->Put( SfxUInt32Item( ATTR_VALUE_FORMAT,
603 pOldAttrs->GetNumberFormat( rDoc.GetFormatTable() ) ) );
605 std::unique_ptr<SvxNumberInfoItem> pNumberInfoItem = MakeNumberInfoItem(rDoc, GetViewData());
606 xOldSet->MergeRange( SID_ATTR_NUMBERFORMAT_INFO, SID_ATTR_NUMBERFORMAT_INFO );
607 xOldSet->Put( std::move(pNumberInfoItem) );
609 bInFormatDialog = true;
610 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
612 VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScAttrDlg(GetFrameWeld(), xOldSet.get()));
614 if (!rName.isEmpty())
615 pDlg->SetCurPageId(rName);
617 auto xRequest = std::make_shared<SfxRequest>(rReq);
618 rReq.Ignore(); // the 'old' request is not relevant any more
620 pDlg->StartExecuteAsync([pDlg, xOldSet=std::move(xOldSet), xRequest=std::move(xRequest), this](sal_Int32 nResult){
621 bInFormatDialog = false;
623 if ( nResult == RET_OK )
625 const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
626 if(const SvxNumberInfoItem* pItem = pOutSet->GetItemIfSet(SID_ATTR_NUMBERFORMAT_INFO))
628 UpdateNumberFormatter(*pItem);
631 ApplyAttributes(*pOutSet, *xOldSet);
633 xRequest->Done(*pOutSet);
636 pDlg->disposeOnce();
640 const OUString* ScTabViewShell::GetEditString() const
642 if (mpInputHandler)
643 return &mpInputHandler->GetEditString();
645 return nullptr;
648 bool ScTabViewShell::IsRefInputMode() const
650 if (ScModule* pScMod = ScModule::get())
652 if( pScMod->IsRefDialogOpen() )
653 return pScMod->IsFormulaMode();
654 if( pScMod->IsFormulaMode() )
656 ScInputHandler* pHdl = pScMod->GetInputHdl();
657 if ( pHdl )
659 const ScViewData& rViewData = GetViewData();
660 ScDocument& rDoc = rViewData.GetDocument();
661 const ScAddress aPos( rViewData.GetCurPos() );
662 const sal_uInt32 nIndex = rDoc.GetAttr(aPos, ATTR_VALUE_FORMAT )->GetValue();
663 const SvNumFormatType nType = rDoc.GetFormatTable()->GetType(nIndex);
664 if (nType == SvNumFormatType::TEXT)
666 return false;
668 OUString aString = pHdl->GetEditString();
669 if ( !pHdl->GetSelIsRef() && aString.getLength() > 1 &&
670 ( aString[0] == '+' || aString[0] == '-' ) )
672 ScCompiler aComp( rDoc, aPos, rDoc.GetGrammar() );
673 aComp.SetCloseBrackets( false );
674 std::unique_ptr<ScTokenArray> pArr(aComp.CompileString(aString));
675 if ( pArr && pArr->MayReferenceFollow() )
677 return true;
680 else
682 return true;
688 return false;
691 void ScTabViewShell::ExecuteInputDirect()
693 if ( !IsRefInputMode() )
695 if (ScModule* pScMod = ScModule::get())
697 pScMod->InputEnterHandler();
702 void ScTabViewShell::UpdateInputHandler( bool bForce /* = sal_False */, bool bStopEditing /* = sal_True */ )
704 ScInputHandler* pHdl = mpInputHandler ? mpInputHandler.get() : ScModule::get()->GetInputHdl();
706 if ( pHdl )
708 OUString aString;
709 const EditTextObject* pObject = nullptr;
710 ScViewData& rViewData = GetViewData();
711 ScDocument& rDoc = rViewData.GetDocument();
712 SCCOL nPosX = rViewData.GetCurX();
713 SCROW nPosY = rViewData.GetCurY();
714 SCTAB nTab = rViewData.GetTabNo();
715 SCTAB nStartTab = 0;
716 SCTAB nEndTab = 0;
717 SCCOL nStartCol = 0;
718 SCROW nStartRow = 0;
719 SCCOL nEndCol = 0;
720 SCROW nEndRow = 0;
721 ScAddress aPos = rViewData.GetCurPos();
723 rViewData.GetSimpleArea( nStartCol, nStartRow, nStartTab,
724 nEndCol, nEndRow, nEndTab );
726 PutInOrder( nStartCol, nEndCol );
727 PutInOrder( nStartRow, nEndRow );
728 PutInOrder( nStartTab, nEndTab );
730 bool bHideFormula = false;
731 bool bHideAll = false;
733 if (rDoc.IsTabProtected(nTab))
735 const ScProtectionAttr* pProt = rDoc.GetAttr( nPosX,nPosY,nTab,
736 ATTR_PROTECTION);
737 bHideFormula = pProt->GetHideFormula();
738 bHideAll = pProt->GetHideCell();
741 if (!bHideAll)
743 ScRefCellValue rCell(rDoc, aPos);
744 if (rCell.getType() == CELLTYPE_FORMULA)
746 if (!bHideFormula)
747 aString = rCell.getFormula()->GetFormula();
749 else if (rCell.getType() == CELLTYPE_EDIT)
751 pObject = rCell.getEditText();
753 else
755 ScInterpreterContext& rContext = rDoc.GetNonThreadedContext();
756 sal_uInt32 nNumFmt = rDoc.GetNumberFormat( ScRange(aPos) );
758 aString = ScCellFormat::GetInputString( rCell, nNumFmt, &rContext, rDoc );
759 if (rCell.getType() == CELLTYPE_STRING)
761 // Put a ' in front if necessary, so that the string is not
762 // unintentionally interpreted as a number, and to show the
763 // user that it is a string (#35060#).
764 // If cell is not formatted as Text, a leading apostrophe
765 // needs another prepended, also '=' or '+' or '-'
766 // otherwise starting a formula.
767 // NOTE: this corresponds with
768 // sc/source/core/data/column3.cxx ScColumn::ParseString()
769 // removing one apostrophe.
770 // For number format Text IsNumberFormat() would never
771 // result in numeric anyway.
772 if (!rContext.NFIsTextFormat(nNumFmt) && (aString.startsWith("'")
773 || aString.startsWith("=") || aString.startsWith("+") || aString.startsWith("-")
774 || rContext.NFIsNumberFormat(aString, nNumFmt, o3tl::temporary(double()))))
775 aString = "'" + aString;
780 ScInputHdlState aState( ScAddress( nPosX, nPosY, nTab ),
781 ScAddress( nStartCol, nStartRow, nTab ),
782 ScAddress( nEndCol, nEndRow, nTab ),
783 aString,
784 pObject );
786 // if using the view's local input handler, this view can always be set
787 // as current view inside NotifyChange.
788 ScTabViewShell* pSourceSh = mpInputHandler ? this : nullptr;
790 pHdl->NotifyChange( &aState, bForce, pSourceSh, bStopEditing );
793 SfxBindings& rBindings = GetViewFrame().GetBindings();
794 rBindings.Invalidate( SID_STATUS_SUM ); // always together with the input row
795 rBindings.Invalidate( SID_ATTR_SIZE );
796 rBindings.Invalidate( SID_TABLE_CELL );
799 void ScTabViewShell::UpdateInputHandlerCellAdjust( SvxCellHorJustify eJust )
801 if( ScInputHandler* pHdl = mpInputHandler ? mpInputHandler.get() : ScModule::get()->GetInputHdl() )
802 pHdl->UpdateCellAdjust( eJust );
805 void ScTabViewShell::ExecuteSave( SfxRequest& rReq )
807 // only SID_SAVEDOC / SID_SAVEASDOC
808 bool bCommitChanges = true;
809 const SfxItemSet* pReqArgs = rReq.GetArgs();
810 const SfxPoolItem* pItem;
812 if (pReqArgs && pReqArgs->HasItem(FN_PARAM_1, &pItem))
813 bCommitChanges = !static_cast<const SfxBoolItem*>(pItem)->GetValue();
815 // Finish entering unless 'DontTerminateEdit' is specified, even if a formula is being processed
816 if (bCommitChanges)
818 bool bLOKActive = comphelper::LibreOfficeKit::isActive();
820 // Disable error dialog box when about to save in lok mode as
821 // this ultimately invokes SvpSalInstance::DoYield() when we want
822 // to save immediately without committing any erroneous input in possibly
823 // a cell with validation rules. After save is complete the user
824 // can continue editing.
825 ScModule::get()->InputEnterHandler(ScEnterMode::NORMAL, bLOKActive /* bBeforeSavingInLOK */);
827 if (bLOKActive)
829 // Normally this isn't needed, but in Calc when editing a cell formula
830 // and manually saving (without changing cells or hitting enter), while
831 // InputEnterHandler will mark the doc as modified (when it is), because
832 // we will save the doc immediately afterwards, the modified state event
833 // is clobbered. To avoid that, we need to update SID_DOC_MODIFIED so that
834 // a possible state of "true" after "InputEnterHandler" will be sent
835 // as a notification. It is important that the notification goes through
836 // normal process (cache) rather than directly notifying the views.
837 // Otherwise, because there is a previous state of "false" in cache, the
838 // "false" state after saving will be ignored.
839 // This will work only if .uno:ModifiedStatus message will be removed from
840 // the mechanism that keeps in the message queue only last message of
841 // a particular status even if the values are different.
842 if (SfxBindings* pBindings = GetViewData().GetDocShell()->GetViewBindings())
843 pBindings->Update(SID_DOC_MODIFIED);
847 if ( GetViewData().GetDocShell()->IsDocShared() )
849 GetViewData().GetDocShell()->SetDocumentModified();
852 // otherwise as normal
853 GetViewData().GetDocShell()->ExecuteSlot( rReq );
856 void ScTabViewShell::GetSaveState( SfxItemSet& rSet )
858 SfxShell* pDocSh = GetViewData().GetDocShell();
860 SfxWhichIter aIter(rSet);
861 sal_uInt16 nWhich = aIter.FirstWhich();
862 while( nWhich )
864 if ( nWhich != SID_SAVEDOC || !GetViewData().GetDocShell()->IsDocShared() )
866 // get state from DocShell
867 pDocSh->GetSlotState( nWhich, nullptr, &rSet );
869 nWhich = aIter.NextWhich();
873 void ScTabViewShell::ExecDrawOpt( const SfxRequest& rReq )
875 ScViewOptions aViewOptions = GetViewData().GetOptions();
876 ScGridOptions aGridOptions = aViewOptions.GetGridOptions();
878 SfxBindings& rBindings = GetViewFrame().GetBindings();
879 const SfxItemSet* pArgs = rReq.GetArgs();
880 const SfxPoolItem* pItem;
881 sal_uInt16 nSlotId = rReq.GetSlot();
882 switch (nSlotId)
884 case SID_GRID_VISIBLE:
885 if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET )
887 aGridOptions.SetGridVisible( static_cast<const SfxBoolItem*>(pItem)->GetValue() );
888 aViewOptions.SetGridOptions(aGridOptions);
889 rBindings.Invalidate(SID_GRID_VISIBLE);
891 break;
893 case SID_GRID_USE:
894 if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET )
896 aGridOptions.SetUseGridSnap( static_cast<const SfxBoolItem*>(pItem)->GetValue() );
897 aViewOptions.SetGridOptions(aGridOptions);
898 rBindings.Invalidate(SID_GRID_USE);
900 break;
902 case SID_HELPLINES_MOVE:
903 if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET )
905 aViewOptions.SetOption( VOPT_HELPLINES, static_cast<const SfxBoolItem*>(pItem)->GetValue() );
906 rBindings.Invalidate(SID_HELPLINES_MOVE);
908 break;
911 GetViewData().SetOptions(aViewOptions);
914 void ScTabViewShell::GetDrawOptState( SfxItemSet& rSet )
916 SfxBoolItem aBool;
918 const ScViewOptions& rViewOptions = GetViewData().GetOptions();
919 const ScGridOptions& rGridOptions = rViewOptions.GetGridOptions();
921 aBool.SetValue(rGridOptions.GetGridVisible());
922 aBool.SetWhich( SID_GRID_VISIBLE );
923 rSet.Put( aBool );
925 aBool.SetValue(rGridOptions.GetUseGridSnap());
926 aBool.SetWhich( SID_GRID_USE );
927 rSet.Put( aBool );
929 aBool.SetValue(rViewOptions.GetOption( VOPT_HELPLINES ));
930 aBool.SetWhich( SID_HELPLINES_MOVE );
931 rSet.Put( aBool );
934 void ScTabViewShell::ExecStyle( SfxRequest& rReq )
936 const SfxItemSet* pArgs = rReq.GetArgs();
937 const sal_uInt16 nSlotId = rReq.GetSlot();
938 if ( !pArgs && nSlotId != SID_STYLE_NEW_BY_EXAMPLE && nSlotId != SID_STYLE_UPDATE_BY_EXAMPLE )
940 // in case of vertical toolbar
941 GetDispatcher()->Execute( SID_STYLE_DESIGNER, SfxCallMode::ASYNCHRON | SfxCallMode::RECORD );
942 return;
945 SfxBindings& rBindings = GetViewData().GetBindings();
946 const SCTAB nCurTab = GetViewData().GetTabNo();
947 ScDocShell* pDocSh = GetViewData().GetDocShell();
948 ScDocument& rDoc = pDocSh->GetDocument();
949 ScMarkData& rMark = GetViewData().GetMarkData();
950 ScModule* pScMod = ScModule::get();
951 SdrObject* pEditObject = GetDrawView()->GetTextEditObject();
952 OutlinerView* pOLV = GetDrawView()->GetTextEditOutlinerView();
953 ESelection aSelection = pOLV ? pOLV->GetSelection() : ESelection();
954 OUString aRefName;
955 bool bUndo = rDoc.IsUndoEnabled();
957 SfxStyleSheetBasePool* pStylePool = rDoc.GetStyleSheetPool();
958 SfxStyleSheetBase* pStyleSheet = nullptr;
960 bool bStyleToMarked = false;
961 bool bListAction = false;
962 bool bAddUndo = false; // add ScUndoModifyStyle (style modified)
963 auto xOldData = std::make_shared<ScStyleSaveData>(); // for undo/redo
964 auto xNewData = std::make_shared<ScStyleSaveData>();
966 SfxStyleFamily eFamily = SfxStyleFamily::Para;
967 const SfxUInt16Item* pFamItem;
968 const SfxStringItem* pFamilyNameItem;
969 if ( pArgs && (pFamItem = pArgs->GetItemIfSet( SID_STYLE_FAMILY )) )
970 eFamily = static_cast<SfxStyleFamily>(pFamItem->GetValue());
971 else if ( pArgs && (pFamilyNameItem = pArgs->GetItemIfSet( SID_STYLE_FAMILYNAME )) )
973 const OUString& sFamily = pFamilyNameItem->GetValue();
974 if (sFamily == "CellStyles")
975 eFamily = SfxStyleFamily::Para;
976 else if (sFamily == "PageStyles")
977 eFamily = SfxStyleFamily::Page;
978 else if (sFamily == "GraphicStyles")
979 eFamily = SfxStyleFamily::Frame;
982 OUString aStyleName;
983 sal_uInt16 nRetMask = 0xffff;
985 switch ( nSlotId )
987 case SID_STYLE_NEW:
989 const SfxPoolItem* pNameItem;
990 if (pArgs && SfxItemState::SET == pArgs->GetItemState( nSlotId, true, &pNameItem ))
991 aStyleName = static_cast<const SfxStringItem*>(pNameItem)->GetValue();
993 const SfxStringItem* pRefItem=nullptr;
994 if (pArgs && (pRefItem = pArgs->GetItemIfSet( SID_STYLE_REFERENCE )))
996 aRefName = pRefItem->GetValue();
999 pStyleSheet = &(pStylePool->Make( aStyleName, eFamily,
1000 SfxStyleSearchBits::UserDefined ) );
1002 if (pStyleSheet->HasParentSupport())
1003 pStyleSheet->SetParent(aRefName);
1005 break;
1007 case SID_STYLE_APPLY:
1009 const SfxStringItem* pNameItem = rReq.GetArg<SfxStringItem>(SID_APPLY_STYLE);
1010 const SfxStringItem* pFamilyItem = rReq.GetArg<SfxStringItem>(SID_STYLE_FAMILYNAME);
1011 if ( pFamilyItem && pNameItem )
1015 css::uno::Reference< css::container::XNameAccess > xStyles;
1016 css::uno::Reference< css::container::XNameAccess > xCont = pDocSh->GetModel()->getStyleFamilies();
1017 xCont->getByName(pFamilyItem->GetValue()) >>= xStyles;
1018 css::uno::Reference< css::beans::XPropertySet > xInfo;
1019 xStyles->getByName( pNameItem->GetValue() ) >>= xInfo;
1020 OUString aUIName;
1021 xInfo->getPropertyValue(u"DisplayName"_ustr) >>= aUIName;
1022 if ( !aUIName.isEmpty() )
1023 rReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aUIName ) );
1025 catch( css::uno::Exception& )
1029 [[fallthrough]];
1031 case SID_STYLE_EDIT:
1032 case SID_STYLE_DELETE:
1033 case SID_STYLE_HIDE:
1034 case SID_STYLE_SHOW:
1035 case SID_STYLE_NEW_BY_EXAMPLE:
1037 const SfxPoolItem* pNameItem;
1038 if (pArgs && SfxItemState::SET == pArgs->GetItemState(nSlotId, true, &pNameItem))
1039 aStyleName = static_cast<const SfxStringItem*>(pNameItem)->GetValue();
1040 else if ( nSlotId == SID_STYLE_NEW_BY_EXAMPLE )
1042 weld::Window* pDialogParent = rReq.GetFrameWeld();
1043 if (!pDialogParent)
1044 pDialogParent = GetFrameWeld();
1045 SfxNewStyleDlg aDlg(pDialogParent, *pStylePool, eFamily);
1046 if (aDlg.run() != RET_OK)
1047 return;
1048 aStyleName = aDlg.GetName();
1051 pStyleSheet = pStylePool->Find( aStyleName, eFamily );
1053 xOldData->InitFromStyle( pStyleSheet );
1055 break;
1057 case SID_STYLE_WATERCAN:
1059 bool bWaterCan = pScMod->GetIsWaterCan();
1061 if( !bWaterCan )
1063 const SfxPoolItem* pItem;
1065 if (pArgs && SfxItemState::SET == pArgs->GetItemState(nSlotId, true, &pItem))
1067 const SfxStringItem* pStrItem = dynamic_cast< const SfxStringItem *>( pItem );
1068 if ( pStrItem )
1070 aStyleName = pStrItem->GetValue();
1071 pStyleSheet = pStylePool->Find( aStyleName, eFamily );
1073 if ( pStyleSheet )
1075 static_cast<ScStyleSheetPool*>(pStylePool)->
1076 SetActualStyleSheet( pStyleSheet );
1077 rReq.Done();
1083 if ( !bWaterCan && pStyleSheet )
1085 pScMod->SetWaterCan( true );
1086 SetActivePointer( PointerStyle::Fill );
1087 rReq.Done();
1089 else
1091 pScMod->SetWaterCan( false );
1092 SetActivePointer( PointerStyle::Arrow );
1093 rReq.Done();
1096 break;
1098 default:
1099 break;
1102 // set new style for paintbrush format mode
1103 if ( nSlotId == SID_STYLE_APPLY && pScMod->GetIsWaterCan() && pStyleSheet )
1104 static_cast<ScStyleSheetPool*>(pStylePool)->SetActualStyleSheet( pStyleSheet );
1106 switch ( eFamily )
1108 case SfxStyleFamily::Para:
1110 switch ( nSlotId )
1112 case SID_STYLE_DELETE:
1114 if ( pStyleSheet )
1116 RemoveStyleSheetInUse( pStyleSheet );
1117 pStylePool->Remove( pStyleSheet );
1118 InvalidateAttribs();
1119 nRetMask = sal_uInt16(true);
1120 bAddUndo = true;
1121 rReq.Done();
1123 else
1124 nRetMask = sal_uInt16(false);
1126 break;
1128 case SID_STYLE_HIDE:
1129 case SID_STYLE_SHOW:
1131 if ( pStyleSheet )
1133 pStyleSheet->SetHidden( nSlotId == SID_STYLE_HIDE );
1134 InvalidateAttribs();
1135 rReq.Done();
1137 else
1138 nRetMask = sal_uInt16(false);
1140 break;
1142 case SID_STYLE_APPLY:
1144 if ( pStyleSheet && !pScMod->GetIsWaterCan() )
1146 // apply style sheet to document
1147 SetStyleSheetToMarked( static_cast<SfxStyleSheet*>(pStyleSheet) );
1148 InvalidateAttribs();
1149 rReq.Done();
1152 break;
1154 case SID_STYLE_NEW_BY_EXAMPLE:
1155 case SID_STYLE_UPDATE_BY_EXAMPLE:
1157 // create/replace style sheet by attributes
1158 // at cursor position:
1160 const ScPatternAttr* pAttrItem = nullptr;
1162 // The query if marked, was always wrong here,
1163 // so now no more, and just from the cursor.
1164 // If attributes are to be removed from the selection, still need to be
1165 // cautious not to adopt items from templates
1166 // (GetSelectionPattern also collects items from originals) (# 44748 #)
1167 SCCOL nCol = GetViewData().GetCurX();
1168 SCROW nRow = GetViewData().GetCurY();
1169 pAttrItem = rDoc.GetPattern( nCol, nRow, nCurTab );
1171 SfxItemSet aAttrSet = pAttrItem->GetItemSet();
1172 aAttrSet.ClearItem( ATTR_MERGE );
1173 aAttrSet.ClearItem( ATTR_MERGE_FLAG );
1175 // Do not adopt conditional formatting and validity,
1176 // because they can not be edited in the template
1177 aAttrSet.ClearItem( ATTR_VALIDDATA );
1178 aAttrSet.ClearItem( ATTR_CONDITIONAL );
1180 if ( SID_STYLE_NEW_BY_EXAMPLE == nSlotId )
1182 if ( bUndo )
1184 OUString aUndo = ScResId( STR_UNDO_EDITCELLSTYLE );
1185 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo, 0, GetViewShellId() );
1186 bListAction = true;
1189 bool bConvertBack = false;
1190 SfxStyleSheet* pSheetInUse = const_cast<SfxStyleSheet*>(GetStyleSheetFromMarked());
1192 // when a new style is present and is used in the selection,
1193 // then the parent can not be adopted:
1194 if ( pStyleSheet && pSheetInUse && pStyleSheet == pSheetInUse )
1195 pSheetInUse = nullptr;
1197 // if already present, first remove ...
1198 if ( pStyleSheet )
1200 // style pointer to names before erase,
1201 // otherwise cells will get invalid pointer
1202 //!!! As it happens, a method that does it for a particular style
1203 rDoc.getCellAttributeHelper().AllStylesToNames();
1204 bConvertBack = true;
1205 pStylePool->Remove(pStyleSheet);
1208 // ...and create new
1209 pStyleSheet = &pStylePool->Make( aStyleName, eFamily,
1210 SfxStyleSearchBits::UserDefined );
1212 // when a style is present, then this will become
1213 // the parent of the new style:
1214 if ( pSheetInUse && pStyleSheet->HasParentSupport() )
1215 pStyleSheet->SetParent( pSheetInUse->GetName() );
1217 if ( bConvertBack )
1218 // Name to style pointer
1219 rDoc.getCellAttributeHelper().UpdateAllStyleSheets(rDoc);
1220 else
1221 rDoc.getCellAttributeHelper().CellStyleCreated(rDoc, aStyleName);
1223 // Adopt attribute and use style
1224 pStyleSheet->GetItemSet().Put( aAttrSet );
1225 UpdateStyleSheetInUse( pStyleSheet );
1227 // call SetStyleSheetToMarked after adding the ScUndoModifyStyle
1228 // (pStyleSheet pointer is used!)
1229 bStyleToMarked = true;
1231 else // ( nSlotId == SID_STYLE_UPDATE_BY_EXAMPLE )
1233 pStyleSheet = const_cast<SfxStyleSheet*>(GetStyleSheetFromMarked());
1235 if ( pStyleSheet )
1237 xOldData->InitFromStyle( pStyleSheet );
1239 if ( bUndo )
1241 OUString aUndo = ScResId( STR_UNDO_EDITCELLSTYLE );
1242 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo, 0, GetViewShellId() );
1243 bListAction = true;
1246 pStyleSheet->GetItemSet().Put( aAttrSet );
1247 UpdateStyleSheetInUse( pStyleSheet );
1249 // call SetStyleSheetToMarked after adding the ScUndoModifyStyle
1250 // (pStyleSheet pointer is used!)
1251 bStyleToMarked = true;
1255 xNewData->InitFromStyle( pStyleSheet );
1256 bAddUndo = true;
1257 rReq.Done();
1259 break;
1261 default:
1262 break;
1264 } // case SfxStyleFamily::Para:
1265 break;
1267 case SfxStyleFamily::Page:
1269 switch ( nSlotId )
1271 case SID_STYLE_DELETE:
1273 nRetMask = sal_uInt16( nullptr != pStyleSheet );
1274 if ( pStyleSheet )
1276 if ( rDoc.RemovePageStyleInUse( pStyleSheet->GetName() ) )
1278 ScPrintFunc( pDocSh, GetPrinter(true), nCurTab ).UpdatePages();
1279 rBindings.Invalidate( SID_STATUS_PAGESTYLE );
1280 rBindings.Invalidate( FID_RESET_PRINTZOOM );
1282 pStylePool->Remove( pStyleSheet );
1283 rBindings.Invalidate( SID_STYLE_FAMILY4 );
1284 pDocSh->SetDocumentModified();
1285 bAddUndo = true;
1286 rReq.Done();
1289 break;
1291 case SID_STYLE_HIDE:
1292 case SID_STYLE_SHOW:
1294 nRetMask = sal_uInt16( nullptr != pStyleSheet );
1295 if ( pStyleSheet )
1297 pStyleSheet->SetHidden( nSlotId == SID_STYLE_HIDE );
1298 rBindings.Invalidate( SID_STYLE_FAMILY4 );
1299 pDocSh->SetDocumentModified();
1300 rReq.Done();
1303 break;
1305 case SID_STYLE_APPLY:
1307 nRetMask = sal_uInt16( nullptr != pStyleSheet );
1308 if ( pStyleSheet && !pScMod->GetIsWaterCan() )
1310 std::unique_ptr<ScUndoApplyPageStyle> pUndoAction;
1311 SCTAB nTabCount = rDoc.GetTableCount();
1312 for (const auto& rTab : rMark)
1314 if (rTab >= nTabCount)
1315 break;
1316 OUString aOldName = rDoc.GetPageStyle( rTab );
1317 if ( aOldName != aStyleName )
1319 rDoc.SetPageStyle( rTab, aStyleName );
1320 ScPrintFunc( pDocSh, GetPrinter(true), rTab ).UpdatePages();
1321 if( !pUndoAction )
1322 pUndoAction.reset(new ScUndoApplyPageStyle( pDocSh, aStyleName ));
1323 pUndoAction->AddSheetAction( rTab, aOldName );
1326 if( pUndoAction )
1328 pDocSh->GetUndoManager()->AddUndoAction( std::move(pUndoAction) );
1329 pDocSh->SetDocumentModified();
1330 rBindings.Invalidate( SID_STYLE_FAMILY4 );
1331 rBindings.Invalidate( SID_STATUS_PAGESTYLE );
1332 rBindings.Invalidate( FID_RESET_PRINTZOOM );
1334 rReq.Done();
1337 break;
1339 case SID_STYLE_NEW_BY_EXAMPLE:
1341 const OUString aStrCurStyle = rDoc.GetPageStyle( nCurTab );
1343 if ( aStrCurStyle != aStyleName )
1345 SfxStyleSheetBase* pCurStyle = pStylePool->Find( aStrCurStyle, eFamily );
1346 SfxItemSet aAttrSet = pCurStyle->GetItemSet();
1347 SCTAB nInTab;
1348 bool bUsed = rDoc.IsPageStyleInUse( aStyleName, &nInTab );
1350 // if already present, first remove...
1351 if ( pStyleSheet )
1352 pStylePool->Remove( pStyleSheet );
1354 // ...and create new
1355 pStyleSheet = &pStylePool->Make( aStyleName, eFamily,
1356 SfxStyleSearchBits::UserDefined );
1358 // Adopt attribute
1359 pStyleSheet->GetItemSet().Put( aAttrSet );
1360 pDocSh->SetDocumentModified();
1362 // If being used -> Update
1363 if ( bUsed )
1364 ScPrintFunc( pDocSh, GetPrinter(true), nInTab ).UpdatePages();
1366 xNewData->InitFromStyle( pStyleSheet );
1367 bAddUndo = true;
1368 rReq.Done();
1369 nRetMask = sal_uInt16(true);
1372 break;
1374 default:
1375 break;
1376 } // switch ( nSlotId )
1377 } // case SfxStyleFamily::Page:
1378 break;
1380 case SfxStyleFamily::Frame:
1382 switch ( nSlotId )
1384 case SID_STYLE_DELETE:
1386 if ( pStyleSheet )
1388 pStylePool->Remove( pStyleSheet );
1389 InvalidateAttribs();
1390 pDocSh->SetDocumentModified();
1391 nRetMask = sal_uInt16(true);
1392 bAddUndo = true;
1393 rReq.Done();
1395 else
1396 nRetMask = sal_uInt16(false);
1398 break;
1400 case SID_STYLE_HIDE:
1401 case SID_STYLE_SHOW:
1403 if ( pStyleSheet )
1405 pStyleSheet->SetHidden( nSlotId == SID_STYLE_HIDE );
1406 InvalidateAttribs();
1407 rReq.Done();
1409 else
1410 nRetMask = sal_uInt16(false);
1412 break;
1414 case SID_STYLE_APPLY:
1416 if ( pStyleSheet && !pScMod->GetIsWaterCan() )
1418 GetScDrawView()->ScEndTextEdit();
1419 GetScDrawView()->SetStyleSheet(static_cast<SfxStyleSheet*>(pStyleSheet), false);
1421 GetScDrawView()->InvalidateAttribs();
1422 InvalidateAttribs();
1423 rReq.Done();
1426 break;
1428 case SID_STYLE_NEW_BY_EXAMPLE:
1429 case SID_STYLE_UPDATE_BY_EXAMPLE:
1431 if (nSlotId == SID_STYLE_NEW_BY_EXAMPLE)
1433 pStyleSheet = &pStylePool->Make( aStyleName, eFamily, SfxStyleSearchBits::UserDefined );
1435 // when a style is present, then this will become
1436 // the parent of the new style:
1437 if (SfxStyleSheet* pOldStyle = GetDrawView()->GetStyleSheet())
1438 pStyleSheet->SetParent(pOldStyle->GetName());
1440 else
1442 pStyleSheet = GetDrawView()->GetStyleSheet();
1443 xOldData->InitFromStyle( pStyleSheet );
1446 if ( bUndo )
1448 OUString aUndo = ScResId( STR_UNDO_EDITGRAPHICSTYLE );
1449 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo, 0, GetViewShellId() );
1450 bListAction = true;
1453 SfxItemSet aCoreSet(GetDrawView()->GetModel().GetItemPool());
1454 GetDrawView()->GetAttributes(aCoreSet, true);
1456 SfxItemSet* pStyleSet = &pStyleSheet->GetItemSet();
1457 pStyleSet->Put(aCoreSet);
1458 static_cast<SfxStyleSheet*>(pStyleSheet)->Broadcast(SfxHint(SfxHintId::DataChanged));
1460 xNewData->InitFromStyle( pStyleSheet );
1461 bAddUndo = true;
1463 // call SetStyleSheet after adding the ScUndoModifyStyle
1464 // (pStyleSheet pointer is used!)
1465 bStyleToMarked = true;
1466 rReq.Done();
1468 break;
1469 default:
1470 break;
1473 break;
1474 default:
1475 break;
1476 } // switch ( eFamily )
1478 // create new or process through Dialog:
1479 if ( nSlotId == SID_STYLE_NEW || nSlotId == SID_STYLE_EDIT )
1481 if (pStyleSheet)
1483 ExecuteStyleEdit(rReq, pStyleSheet, nRetMask, nSlotId, bAddUndo, bUndo,
1484 xOldData, xNewData, eFamily, bStyleToMarked, bListAction, pEditObject, aSelection);
1485 return; // skip calling ExecuteStyleEditPost because we invoked an async dialog
1489 ExecuteStyleEditPost(rReq, pStyleSheet, nSlotId, nRetMask, bAddUndo, bUndo,
1490 eFamily, *xOldData, *xNewData, bStyleToMarked, bListAction, pEditObject, aSelection);
1493 void ScTabViewShell::ExecuteStyleEdit(SfxRequest& rReq, SfxStyleSheetBase* pStyleSheet, sal_uInt16 nRetMask,
1494 sal_uInt16 nSlotId, bool bAddUndo, bool bUndo,
1495 const std::shared_ptr<ScStyleSaveData>& rOldData,
1496 const std::shared_ptr<ScStyleSaveData>& rNewData, SfxStyleFamily eFamily,
1497 bool bStyleToMarked, bool bListAction,
1498 SdrObject* pEditObject, ESelection aSelection)
1500 ScDocShell* pDocSh = GetViewData().GetDocShell();
1501 ScDocument& rDoc = pDocSh->GetDocument();
1502 SfxStyleFamily eFam = pStyleSheet->GetFamily();
1503 VclPtr<SfxAbstractTabDialog> pDlg;
1504 bool bPage = false;
1506 // Store old Items from the style
1507 std::shared_ptr<SfxItemSet> xOldSet = std::make_shared<SfxItemSet>(pStyleSheet->GetItemSet());
1508 OUString aOldName = pStyleSheet->GetName();
1510 switch ( eFam )
1512 case SfxStyleFamily::Page:
1513 bPage = true;
1514 break;
1516 case SfxStyleFamily::Para:
1518 SfxItemSet& rSet = pStyleSheet->GetItemSet();
1520 if ( const SfxUInt32Item* pItem = rSet.GetItemIfSet( ATTR_VALUE_FORMAT,
1521 false ) )
1523 // Produce and format NumberFormat Value from Value and Language
1524 sal_uLong nFormat = pItem->GetValue();
1525 LanguageType eLang =
1526 rSet.Get(ATTR_LANGUAGE_FORMAT ).GetLanguage();
1527 sal_uLong nLangFormat = rDoc.GetFormatTable()->
1528 GetFormatForLanguageIfBuiltIn( nFormat, eLang );
1529 if ( nLangFormat != nFormat )
1531 SfxUInt32Item aNewItem( ATTR_VALUE_FORMAT, nLangFormat );
1532 rSet.Put( aNewItem );
1533 xOldSet->Put( aNewItem );
1534 // Also in aOldSet for comparison after the dialog,
1535 // Otherwise might miss a language change
1539 std::unique_ptr<SvxNumberInfoItem> pNumberInfoItem(
1540 ScTabViewShell::MakeNumberInfoItem(rDoc, GetViewData()));
1542 pDocSh->PutItem( *pNumberInfoItem );
1543 bPage = false;
1545 // Definitely a SvxBoxInfoItem with Table = sal_False in set:
1546 // (If there is no item, the dialogue will also delete the
1547 // BORDER_OUTER SvxBoxItem from the Template Set)
1548 if ( rSet.GetItemState( ATTR_BORDER_INNER, false ) != SfxItemState::SET )
1550 SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER );
1551 aBoxInfoItem.SetTable(false); // no inner lines
1552 aBoxInfoItem.SetDist(true);
1553 aBoxInfoItem.SetMinDist(false);
1554 rSet.Put( aBoxInfoItem );
1557 break;
1559 case SfxStyleFamily::Frame:
1560 default:
1561 break;
1564 SetInFormatDialog(true);
1566 SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
1567 rStyleSet.MergeRange( XATTR_FILL_FIRST, XATTR_FILL_LAST );
1569 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
1571 weld::Window* pDialogParent = rReq.GetFrameWeld();
1572 if (!pDialogParent)
1573 pDialogParent = GetFrameWeld();
1575 if (eFam == SfxStyleFamily::Frame)
1576 pDlg = pFact->CreateScDrawStyleDlg(pDialogParent, *pStyleSheet, GetDrawView());
1577 else
1578 pDlg = pFact->CreateScStyleDlg(pDialogParent, *pStyleSheet, bPage);
1580 auto xRequest = std::make_shared<SfxRequest>(rReq);
1581 rReq.Ignore(); // the 'old' request is not relevant any more
1582 pDlg->StartExecuteAsync(
1583 [this, pDlg, xRequest=std::move(xRequest), pStyleSheet,
1584 nRetMask, xOldSet=std::move(xOldSet), nSlotId, bAddUndo, bUndo,
1585 xOldData = rOldData, xNewData = rNewData, aOldName, eFamily, bStyleToMarked,
1586 bListAction, pEditObject, aSelection]
1587 (sal_Int32 nResult) mutable -> void
1589 SetInFormatDialog(false);
1590 ExecuteStyleEditDialog(pDlg, pStyleSheet, nResult, nRetMask, xOldSet, nSlotId,
1591 bAddUndo, *xNewData, aOldName);
1592 pDlg->disposeOnce();
1593 ExecuteStyleEditPost(*xRequest, pStyleSheet, nSlotId, nRetMask, bAddUndo, bUndo, eFamily,
1594 *xOldData, *xNewData, bStyleToMarked, bListAction, pEditObject, aSelection);
1599 void ScTabViewShell::ExecuteStyleEditDialog(VclPtr<SfxAbstractTabDialog> pDlg,
1600 SfxStyleSheetBase* pStyleSheet, sal_uInt16 nResult,
1601 sal_uInt16& rnRetMask, std::shared_ptr<SfxItemSet> xOldSet, const sal_uInt16 nSlotId,
1602 bool& rbAddUndo, ScStyleSaveData& rNewData, std::u16string_view aOldName)
1604 ScDocShell* pDocSh = GetViewData().GetDocShell();
1605 ScDocument& rDoc = pDocSh->GetDocument();
1606 SfxBindings& rBindings = GetViewData().GetBindings();
1607 SfxStyleSheetBasePool* pStylePool = rDoc.GetStyleSheetPool();
1608 SfxStyleFamily eFam = pStyleSheet->GetFamily();
1609 if ( nResult == RET_OK )
1611 const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
1613 if ( pOutSet )
1615 rnRetMask = sal_uInt16(pStyleSheet->GetMask());
1617 // Attribute comparisons (earlier in ModifyStyleSheet) now here
1618 // with the old values (the style is already changed)
1619 if ( SfxStyleFamily::Para == eFam )
1621 SfxItemSet& rNewSet = pStyleSheet->GetItemSet();
1622 bool bNumFormatChanged;
1623 if ( ScGlobal::CheckWidthInvalidate(
1624 bNumFormatChanged, rNewSet, *xOldSet ) )
1625 rDoc.InvalidateTextWidth( nullptr, nullptr, bNumFormatChanged );
1627 SCTAB nTabCount = rDoc.GetTableCount();
1628 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
1629 rDoc.SetStreamValid(nTab, false);
1631 sal_uLong nOldFormat = xOldSet->Get( ATTR_VALUE_FORMAT ).GetValue();
1632 sal_uLong nNewFormat = rNewSet.Get( ATTR_VALUE_FORMAT ).GetValue();
1633 if ( nNewFormat != nOldFormat )
1635 ScInterpreterContext& rContext = rDoc.GetNonThreadedContext();
1636 const SvNumberformat* pOld = rContext.NFGetFormatEntry( nOldFormat );
1637 const SvNumberformat* pNew = rContext.NFGetFormatEntry( nNewFormat );
1638 if ( pOld && pNew && pOld->GetLanguage() != pNew->GetLanguage() )
1639 rNewSet.Put( SvxLanguageItem(
1640 pNew->GetLanguage(), ATTR_LANGUAGE_FORMAT ) );
1643 rDoc.getCellAttributeHelper().CellStyleCreated(rDoc, pStyleSheet->GetName());
1645 else if ( SfxStyleFamily::Page == eFam )
1647 //! Here also queries for Page Styles
1649 OUString aNewName = pStyleSheet->GetName();
1650 if ( aNewName != aOldName &&
1651 rDoc.RenamePageStyleInUse( aOldName, aNewName ) )
1653 rBindings.Invalidate( SID_STATUS_PAGESTYLE );
1654 rBindings.Invalidate( FID_RESET_PRINTZOOM );
1657 rDoc.ModifyStyleSheet( *pStyleSheet, *pOutSet );
1658 rBindings.Invalidate( FID_RESET_PRINTZOOM );
1660 else
1662 SfxItemSet& rAttr = pStyleSheet->GetItemSet();
1663 sdr::properties::CleanupFillProperties(rAttr);
1665 // check for unique names of named items for xml
1666 auto checkForUniqueItem = [&] (auto nWhichId)
1668 if (auto pOldItem = rAttr.GetItemIfSet(nWhichId, false))
1670 if (auto pNewItem = pOldItem->checkForUniqueItem(GetDrawView()->GetModel()))
1671 rAttr.Put(std::move(pNewItem));
1675 checkForUniqueItem(XATTR_FILLBITMAP);
1676 checkForUniqueItem(XATTR_LINEDASH);
1677 checkForUniqueItem(XATTR_LINESTART);
1678 checkForUniqueItem(XATTR_LINEEND);
1679 checkForUniqueItem(XATTR_FILLGRADIENT);
1680 checkForUniqueItem(XATTR_FILLFLOATTRANSPARENCE);
1681 checkForUniqueItem(XATTR_FILLHATCH);
1683 static_cast<SfxStyleSheet*>(pStyleSheet)->Broadcast(SfxHint(SfxHintId::DataChanged));
1684 GetScDrawView()->InvalidateAttribs();
1687 pDocSh->SetDocumentModified();
1689 if ( SfxStyleFamily::Para == eFam )
1691 ScTabViewShell::UpdateNumberFormatter(
1692 *( pDocSh->GetItem(SID_ATTR_NUMBERFORMAT_INFO) ));
1694 UpdateStyleSheetInUse( pStyleSheet );
1695 InvalidateAttribs();
1698 rNewData.InitFromStyle( pStyleSheet );
1699 rbAddUndo = true;
1702 else
1704 if ( nSlotId == SID_STYLE_NEW )
1705 pStylePool->Remove( pStyleSheet );
1706 else
1708 // If in the meantime something was painted with the
1709 // temporary changed item set
1710 pDocSh->PostPaintGridAll();
1715 void ScTabViewShell::ExecuteStyleEditPost(SfxRequest& rReq, SfxStyleSheetBase* pStyleSheet,
1716 sal_uInt16 nSlotId, sal_uInt16 nRetMask, bool bAddUndo, bool bUndo,
1717 const SfxStyleFamily eFamily,
1718 ScStyleSaveData& rOldData, ScStyleSaveData& rNewData,
1719 bool bStyleToMarked, bool bListAction,
1720 SdrObject* pEditObject, ESelection aSelection)
1722 ScDocShell* pDocSh = GetViewData().GetDocShell();
1724 rReq.SetReturnValue( SfxUInt16Item( nSlotId, nRetMask ) );
1726 if ( bAddUndo && bUndo)
1727 pDocSh->GetUndoManager()->AddUndoAction(
1728 std::make_unique<ScUndoModifyStyle>( pDocSh, eFamily, rOldData, rNewData ) );
1730 if ( bStyleToMarked )
1732 // call SetStyleSheetToMarked after adding the ScUndoModifyStyle,
1733 // so redo will find the modified style
1734 if (eFamily == SfxStyleFamily::Para)
1736 SetStyleSheetToMarked( static_cast<SfxStyleSheet*>(pStyleSheet) );
1738 else if (eFamily == SfxStyleFamily::Frame)
1740 GetScDrawView()->ScEndTextEdit();
1741 GetScDrawView()->SetStyleSheet( static_cast<SfxStyleSheet*>(pStyleSheet), false );
1743 InvalidateAttribs();
1746 if ( bListAction )
1747 pDocSh->GetUndoManager()->LeaveListAction();
1749 // The above call to ScEndTextEdit left us in an inconsistent state:
1750 // Text editing isn't active, but the text edit shell still is. And we
1751 // couldn't just deactivate it fully, because in case of editing a
1752 // comment, that will make the comment disappear. So let's try to
1753 // reactivate text editing instead:
1754 auto pFuText = dynamic_cast<FuText*>(GetDrawFuncPtr());
1755 if (pFuText && pEditObject != GetDrawView()->GetTextEditObject())
1757 pFuText->SetInEditMode(pEditObject);
1758 if (GetDrawView()->GetTextEditOutlinerView())
1759 GetDrawView()->GetTextEditOutlinerView()->SetSelection(aSelection);
1763 void ScTabViewShell::GetStyleState( SfxItemSet& rSet )
1765 ScDocument& rDoc = GetViewData().GetDocument();
1766 SfxStyleSheetBasePool* pStylePool = rDoc.GetStyleSheetPool();
1768 bool bProtected = false;
1769 SCTAB nTabCount = rDoc.GetTableCount();
1770 for (SCTAB i=0; i<nTabCount && !bProtected; i++)
1771 if (rDoc.IsTabProtected(i)) // look after protected table
1772 bProtected = true;
1774 SfxWhichIter aIter(rSet);
1775 sal_uInt16 nWhich = aIter.FirstWhich();
1776 sal_uInt16 nSlotId = 0;
1778 while ( nWhich )
1780 nSlotId = SfxItemPool::IsWhich( nWhich )
1781 ? GetPool().GetSlotId( nWhich )
1782 : nWhich;
1784 switch ( nSlotId )
1786 case SID_STYLE_APPLY:
1787 if ( !pStylePool )
1788 rSet.DisableItem( nSlotId );
1789 break;
1791 case SID_STYLE_FAMILY2: // cell style sheets
1793 SfxStyleSheet* pStyleSheet = const_cast<SfxStyleSheet*>(GetStyleSheetFromMarked());
1795 if ( pStyleSheet )
1796 rSet.Put( SfxTemplateItem( nSlotId, pStyleSheet->GetName() ) );
1797 else
1798 rSet.Put( SfxTemplateItem( nSlotId, OUString() ) );
1800 break;
1802 case SID_STYLE_FAMILY3: // drawing style sheets
1804 SfxStyleSheet* pStyleSheet = GetDrawView()->GetStyleSheet();
1806 if ( pStyleSheet )
1807 rSet.Put( SfxTemplateItem( nSlotId, pStyleSheet->GetName() ) );
1808 else
1809 rSet.Put( SfxTemplateItem( nSlotId, OUString() ) );
1811 break;
1813 case SID_STYLE_FAMILY4: // page style sheets
1815 SCTAB nCurTab = GetViewData().GetTabNo();
1816 OUString aPageStyle = rDoc.GetPageStyle( nCurTab );
1817 SfxStyleSheet* pStyleSheet = pStylePool ? static_cast<SfxStyleSheet*>(pStylePool->
1818 Find( aPageStyle, SfxStyleFamily::Page )) : nullptr;
1820 if ( pStyleSheet )
1821 rSet.Put( SfxTemplateItem( nSlotId, aPageStyle ) );
1822 else
1823 rSet.Put( SfxTemplateItem( nSlotId, OUString() ) );
1825 break;
1827 case SID_STYLE_WATERCAN:
1829 rSet.Put(SfxBoolItem(nSlotId, ScModule::get()->GetIsWaterCan()));
1831 break;
1833 case SID_STYLE_UPDATE_BY_EXAMPLE:
1835 std::unique_ptr<SfxUInt16Item> pFamilyItem;
1836 GetViewFrame().GetBindings().QueryState(SID_STYLE_FAMILY, pFamilyItem);
1838 bool bPage = pFamilyItem && SfxStyleFamily::Page == static_cast<SfxStyleFamily>(pFamilyItem->GetValue());
1840 if ( bProtected || bPage )
1841 rSet.DisableItem( nSlotId );
1843 break;
1845 case SID_STYLE_EDIT:
1846 case SID_STYLE_DELETE:
1847 case SID_STYLE_HIDE:
1848 case SID_STYLE_SHOW:
1850 std::unique_ptr<SfxUInt16Item> pFamilyItem;
1851 GetViewFrame().GetBindings().QueryState(SID_STYLE_FAMILY, pFamilyItem);
1852 bool bPage = pFamilyItem && SfxStyleFamily::Page == static_cast<SfxStyleFamily>(pFamilyItem->GetValue());
1854 if ( bProtected && !bPage )
1855 rSet.DisableItem( nSlotId );
1857 break;
1859 default:
1860 break;
1863 nWhich = aIter.NextWhich();
1867 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */