/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <memory>
#include <uiobject.hxx>
#include <rangeutl.hxx>
#include <gridwin.hxx>
#include <viewdata.hxx>
#include <viewfunc.hxx>
#include <dbfunc.hxx>
#include <tabvwsh.hxx>
#include <drwlayer.hxx>
#include <sfx2/sidebar/Sidebar.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/dispatch.hxx>
#include <appoptio.hxx>
#include <scmod.hxx>
#include <fudraw.hxx>
#include <postit.hxx>
#include <com/sun/star/embed/EmbedVerbs.hpp>
#include <svx/svditer.hxx>
#include <svx/svdobj.hxx>
#include <svx/svdoole2.hxx>
#include <sal/log.hxx>
namespace {
ScAddress get_address_from_string(const ScDocument& rDoc, std::u16string_view aStr)
{
ScAddress aAddr;
sal_Int32 nOffset = 0;
ScRangeStringConverter::GetAddressFromString(aAddr, aStr, rDoc, formula::FormulaGrammar::CONV_OOO, nOffset);
return aAddr;
}
ScRange get_range_from_string(const ScDocument& rDoc, std::u16string_view aStr)
{
ScRange aRange;
sal_Int32 nOffset = 0;
ScRangeStringConverter::GetRangeFromString(aRange, aStr, rDoc, formula::FormulaGrammar::CONV_OOO, nOffset);
return aRange;
}
}
ScGridWinUIObject::ScGridWinUIObject(const VclPtr<ScGridWindow>& xGridWin):
WindowUIObject(xGridWin),
mxGridWindow(xGridWin)
{
}
StringMap ScGridWinUIObject::get_state()
{
StringMap aMap = WindowUIObject::get_state();
aMap[u"SelectedTable"_ustr] = OUString::number(mxGridWindow->getViewData().GetTabNo());
aMap[u"CurrentColumn"_ustr] = OUString::number(mxGridWindow->getViewData().GetCurX());
aMap[u"CurrentRow"_ustr] = OUString::number(mxGridWindow->getViewData().GetCurY());
ScSplitPos eAlign = mxGridWindow->getViewData().GetActivePart();
ScHSplitPos eAlignX = WhichH(eAlign);
ScVSplitPos eAlignY = WhichV(eAlign);
aMap[u"TopVisibleRow"_ustr] = OUString::number(mxGridWindow->getViewData().GetPosY(eAlignY));
aMap[u"TopVisibleColumn"_ustr] = OUString::number(mxGridWindow->getViewData().GetPosX(eAlignX));
ScRangeList aMarkedArea = mxGridWindow->getViewData().GetMarkData().GetMarkedRanges();
OUString aMarkedAreaString;
ScRangeStringConverter::GetStringFromRangeList(aMarkedAreaString, &aMarkedArea, &mxGridWindow->getViewData().GetDocument(), formula::FormulaGrammar::CONV_OOO);
aMap[u"MarkedArea"_ustr] = aMarkedAreaString;
ScDocument& rDoc = mxGridWindow->getViewData().GetDocument();
ScAddress aPos( mxGridWindow->getViewData().GetCurX() , mxGridWindow->getViewData().GetCurY() , mxGridWindow->getViewData().GetTabNo() );
if ( rDoc.HasNote( aPos ) )
{
ScPostIt* pNote = rDoc.GetNote(aPos);
assert(pNote);
aMap[u"CurrentCellCommentText"_ustr] = pNote->GetText();
}
SCCOL nCol;
SCROW nRow;
aMap[u"CurrentTableHasData"_ustr] = OUString::boolean( rDoc.GetDataStart( mxGridWindow->getViewData().GetTabNo(), nCol, nRow ) );
nCol = mxGridWindow->getViewData().GetCurX();
nRow = 0;
aMap[u"CurrentColumnHasData"_ustr] = OUString::boolean( rDoc.GetPrintAreaVer( mxGridWindow->getViewData().GetTabNo(), nCol, nCol, nRow, true ) );
nRow = mxGridWindow->getViewData().GetCurY();
nCol = 0;
aMap[u"CurrentRowHasData"_ustr] = OUString::boolean( rDoc.GetPrintAreaHor( mxGridWindow->getViewData().GetTabNo(), nRow, nRow, nCol ) );
ScAppOptions aOpt = SC_MOD()->GetAppOptions();
aMap[u"Zoom"_ustr] = OUString::number( aOpt.GetZoom() );
return aMap;
}
ScDBFunc* ScGridWinUIObject::getDBFunc()
{
ScViewData& rViewData = mxGridWindow->getViewData();
ScDBFunc* pFunc = rViewData.GetView();
return pFunc;
}
ScDrawView* ScGridWinUIObject::getDrawView()
{
ScViewData& rViewData = mxGridWindow->getViewData();
ScDrawView* pDrawView = rViewData.GetScDrawView();
return pDrawView;
}
ScTabViewShell* ScGridWinUIObject::getViewShell()
{
ScViewData& rViewData = mxGridWindow->getViewData();
ScTabViewShell* pViewShell = rViewData.GetViewShell();
return pViewShell;
}
ScViewFunc* ScGridWinUIObject::getViewFunc()
{
ScViewData& rViewData = mxGridWindow->getViewData();
ScViewFunc* pViewFunc = rViewData.GetView();
return pViewFunc;
}
void ScGridWinUIObject::execute(const OUString& rAction,
const StringMap& rParameters)
{
if (rAction == "SELECT")
{
bool bExtend = false;
if (rParameters.find(u"EXTEND"_ustr) != rParameters.end())
{
auto itr = rParameters.find(u"EXTEND"_ustr);
if (itr->second.equalsIgnoreAsciiCase("true") || itr->second == "1")
bExtend = true;
}
if (rParameters.find(u"CELL"_ustr) != rParameters.end())
{
auto itr = rParameters.find(u"CELL"_ustr);
const OUString& rStr = itr->second;
ScAddress aAddr = get_address_from_string(mxGridWindow->getViewData().GetDocument(), rStr);
ScDBFunc* pFunc = getDBFunc();
pFunc->MarkRange(ScRange(aAddr), true, bExtend);
mxGridWindow->CursorChanged();
}
else if (rParameters.find(u"RANGE"_ustr) != rParameters.end())
{
auto itr = rParameters.find(u"RANGE"_ustr);
const OUString rStr = itr->second;
ScRange aRange = get_range_from_string(mxGridWindow->getViewData().GetDocument(), rStr);
ScDBFunc* pFunc = getDBFunc();
pFunc->MarkRange(aRange, true, bExtend);
mxGridWindow->CursorChanged();
}
else if (rParameters.find(u"TABLE"_ustr) != rParameters.end())
{
auto itr = rParameters.find(u"TABLE"_ustr);
const OUString rStr = itr->second;
sal_Int32 nTab = rStr.toUInt32();
ScTabView* pTabView = mxGridWindow->getViewData().GetView();
if (pTabView)
{
ScDocument& rDoc = mxGridWindow->getViewData().GetDocument();
if( nTab < rDoc.GetTableCount() )
pTabView->SetTabNo(nTab);
else
{
SAL_WARN("sc.uitest", "incorrect table number");
}
}
}
else if (rParameters.find(u"OBJECT"_ustr) != rParameters.end())
{
auto itr = rParameters.find(u"OBJECT"_ustr);
const OUString rStr = itr->second;
ScDrawView* pDrawView = getDrawView();
pDrawView->SelectObject(rStr);
}
else
{
SAL_WARN("sc.uitest", "unknown selection method");
}
}
else if (rAction == "DESELECT")
{
if (rParameters.find(u"OBJECT"_ustr) != rParameters.end())
{
ScDrawView* pDrawView = getDrawView();
pDrawView->UnmarkAll();
ScTabViewShell* pViewShell = getViewShell();
pViewShell->SetDrawShell(false);
}
}
else if (rAction == "ACTIVATE")
{
ScDrawView* pDrawView = getDrawView();
const SdrMarkList& rMarkList = pDrawView->GetMarkedObjectList();
if (rMarkList.GetMarkCount() == 1)
{
SdrMark* pMark = rMarkList.GetMark(0);
SdrObject* pObj = pMark->GetMarkedSdrObj();
SdrObjKind nSdrObjKind = pObj->GetObjIdentifier();
if (nSdrObjKind == SdrObjKind::OLE2)
{
ScTabViewShell* pViewShell = getViewShell();
pViewShell->ActivateObject(static_cast<SdrOle2Obj*>(pObj), css::embed::EmbedVerbs::MS_OLEVERB_PRIMARY);
}
else
{
SAL_WARN("sc.uitest", "can't activate non-ole objects");
}
}
else
SAL_WARN("sc.uitest", "can't activate the current selection");
}
else if (rAction == "LAUNCH")
{
if ( rParameters.find(u"AUTOFILTER"_ustr) != rParameters.end())
{
auto itrCol = rParameters.find(u"COL"_ustr);
if (itrCol == rParameters.end())
{
SAL_WARN("sc.uitest", "missing COL parameter");
return;
}
auto itrRow = rParameters.find(u"ROW"_ustr);
if (itrRow == rParameters.end())
{
SAL_WARN("sc.uitest", "missing ROW parameter");
return;
}
SCROW nRow = itrRow->second.toUInt32();
SCCOL nCol = itrCol->second.toUInt32();
mxGridWindow->LaunchAutoFilterMenu(nCol, nRow);
}
else if ( rParameters.find(u"PIVOTTABLE"_ustr) != rParameters.end())
{
auto itrCol = rParameters.find(u"COL"_ustr);
if (itrCol == rParameters.end())
{
SAL_WARN("sc.uitest", "missing COL parameter");
return;
}
auto itrRow = rParameters.find(u"ROW"_ustr);
if (itrRow == rParameters.end())
{
SAL_WARN("sc.uitest", "missing ROW parameter");
return;
}
SCROW nRow = itrRow->second.toUInt32();
SCCOL nCol = itrCol->second.toUInt32();
mxGridWindow->LaunchDPFieldMenu(nCol, nRow);
}
else if ( rParameters.find(u"SELECTMENU"_ustr) != rParameters.end())
{
auto itrCol = rParameters.find(u"COL"_ustr);
if (itrCol == rParameters.end())
{
SAL_WARN("sc.uitest", "missing COL parameter");
return;
}
auto itrRow = rParameters.find(u"ROW"_ustr);
if (itrRow == rParameters.end())
{
SAL_WARN("sc.uitest", "missing ROW parameter");
return;
}
SCROW nRow = itrRow->second.toUInt32();
SCCOL nCol = itrCol->second.toUInt32();
mxGridWindow->LaunchDataSelectMenu(nCol, nRow);
}
}
else if (rAction == "COMMENT")
{
if ( rParameters.find(u"OPEN"_ustr) != rParameters.end() )
{
ScViewFunc* pViewFunc = getViewFunc();
pViewFunc->EditNote();
}
else if ( rParameters.find(u"CLOSE"_ustr) != rParameters.end() )
{
FuDraw* pDraw = dynamic_cast<FuDraw*>(getViewFunc()->GetDrawFuncPtr());
assert(pDraw);
ScViewData& rViewData = mxGridWindow->getViewData();
rViewData.GetDispatcher().Execute( pDraw->GetSlotID() , SfxCallMode::SLOT | SfxCallMode::RECORD );
}
else if ( rParameters.find(u"SETTEXT"_ustr) != rParameters.end() )
{
auto itr = rParameters.find(u"SETTEXT"_ustr);
const OUString rStr = itr->second;
ScDocument& rDoc = mxGridWindow->getViewData().GetDocument();
ScAddress aPos( mxGridWindow->getViewData().GetCurX() , mxGridWindow->getViewData().GetCurY() , mxGridWindow->getViewData().GetTabNo() );
rDoc.GetOrCreateNote( aPos )->SetText( aPos , rStr );
}
}
else if (rAction == "SIDEBAR")
{
SfxViewFrame* pViewFrm = SfxViewFrame::Current();
assert(pViewFrm && "ScGridWinUIObject::execute: no viewframe");
pViewFrm->ShowChildWindow(SID_SIDEBAR);
auto itr = rParameters.find(u"PANEL"_ustr);
if (itr != rParameters.end())
{
OUString aVal = itr->second;
::sfx2::sidebar::Sidebar::ShowPanel(aVal, pViewFrm->GetFrame().GetFrameInterface());
}
}
else if (rAction == "SET")
{
if (rParameters.find(u"ZOOM"_ustr) != rParameters.end())
{
auto itr = rParameters.find(u"ZOOM"_ustr);
OUString aVal = itr->second;
sal_Int32 nVal = aVal.toInt32();
ScTabViewShell* pViewShell = getViewShell();
ScModule* pScMod = SC_MOD();
if( nVal )
{
ScAppOptions aNewOpt = pScMod->GetAppOptions();
aNewOpt.SetZoom( nVal );
pScMod->SetAppOptions( aNewOpt );
Fraction aFract( nVal, 100 );
pViewShell->SetZoom( aFract, aFract, true );
pViewShell->PaintGrid();
pViewShell->PaintTop();
pViewShell->PaintLeft();
}
}
}
else
{
WindowUIObject::execute(rAction, rParameters);
}
}
namespace {
ScDrawLayer* get_draw_layer(VclPtr<ScGridWindow> const & xGridWindow)
{
return xGridWindow->getViewData().GetDocument().GetDrawLayer();
}
SdrPage* get_draw_page(VclPtr<ScGridWindow> const & xGridWindow, SCTAB nTab)
{
ScDrawLayer* pDrawLayer = get_draw_layer(xGridWindow);
return pDrawLayer->GetPage(nTab);
}
std::set<OUString> collect_charts(VclPtr<ScGridWindow> const & xGridWindow)
{
SCTAB nTab = xGridWindow->getViewData().GetTabNo();
SdrPage* pPage = get_draw_page(xGridWindow, nTab);
std::set<OUString> aRet;
if (!pPage)
return aRet;
SdrObjListIter aIter( pPage, SdrIterMode::Flat );
SdrObject* pObject = aIter.Next();
while (pObject)
{
if (pObject->GetObjIdentifier() == SdrObjKind::OLE2)
{
aRet.insert(static_cast<SdrOle2Obj*>(pObject)->GetPersistName());
}
pObject = aIter.Next();
}
return aRet;
}
}
std::set<OUString> ScGridWinUIObject::get_children() const
{
std::set<OUString> aChildren = collect_charts(mxGridWindow);
return aChildren;
}
std::unique_ptr<UIObject> ScGridWinUIObject::get_child(const OUString& /*rID*/)
{
return nullptr;
}
std::unique_ptr<UIObject> ScGridWinUIObject::create(vcl::Window* pWindow)
{
ScGridWindow* pGridWin = dynamic_cast<ScGridWindow*>(pWindow);
assert(pGridWin);
return std::unique_ptr<UIObject>(new ScGridWinUIObject(pGridWin));
}
OUString ScGridWinUIObject::get_name() const
{
return u"ScGridWinUIObject"_ustr;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V530 The return value of function 'Execute' is required to be utilized.
↑ V522 There might be dereferencing of a potential null pointer 'pDraw'.