tdf#95378 Writer Navigator document content tracking

This patch adds document content tracking for tables, frames, images,
OLE objects and drawing objects.

Change-Id: I99af15d2da9f4f97d8702b5a9cad4fc21b676166
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/101253
Tested-by: Jenkins
Reviewed-by: Jim Raykowski <raykowj@gmail.com>
This commit is contained in:
Jim Raykowski
2020-08-23 09:49:45 -08:00
parent 4ef5418552
commit dda71436b8

View File

@@ -1882,11 +1882,8 @@ IMPL_LINK_NOARG(SwContentTree, ContentDoubleClickHdl, weld::TreeView&, bool)
SwContent* pCnt = reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xEntry).toInt64());
assert(pCnt && "no UserData");
GotoContent(pCnt);
const ContentTypeId nActType = pCnt->GetParent()->GetType();
if (nActType == ContentTypeId::FRAME)
m_pActiveShell->EnterStdMode();
// fdo#36308 don't expand outlines on double-click
bConsumed = nActType == ContentTypeId::OUTLINE;
bConsumed = pCnt->GetParent()->GetType() == ContentTypeId::OUTLINE;
}
}
@@ -3087,6 +3084,42 @@ void SwContentTree::HideTree()
m_xTreeView->hide();
}
static void lcl_SelectByContentTypeAndName(SwContentTree* pThis, weld::TreeView& rContentTree,
const OUString& rContentTypeName, const OUString& rName)
{
if (!rName.isEmpty())
{
// find content type entry
std::unique_ptr<weld::TreeIter> xIter(rContentTree.make_iterator());
bool bFoundEntry = rContentTree.get_iter_first(*xIter);
while (bFoundEntry && rContentTypeName != rContentTree.get_text(*xIter))
bFoundEntry = rContentTree.iter_next_sibling(*xIter);
// find content type content entry and select it
if (bFoundEntry)
{
rContentTree.expand_row(*xIter); // assure content type entry is expanded
while (rContentTree.iter_next(*xIter) && lcl_IsContent(*xIter, rContentTree))
{
if (rName == rContentTree.get_text(*xIter))
{
// get first selected for comparison
std::unique_ptr<weld::TreeIter> xFirstSelected(rContentTree.make_iterator());
if (!rContentTree.get_selected(xFirstSelected.get()))
xFirstSelected.reset();
if (rContentTree.count_selected_rows() != 1 ||
rContentTree.iter_compare(*xIter, *xFirstSelected) != 0)
{
// unselect all entries and make passed entry visible and selected
rContentTree.set_cursor(*xIter);
pThis->Select();
}
break;
}
}
}
}
}
/** No idle with focus or while dragging */
IMPL_LINK_NOARG(SwContentTree, TimerUpdate, Timer *, void)
{
@@ -3136,72 +3169,131 @@ void SwContentTree::UpdateTracking()
if (State::HIDDEN == m_eState)
return;
// track document outline position at cursor
if (m_nOutlineTracking == 3) // no outline tracking
// m_bIgnoreViewChange is set on delete
if (m_bIgnoreViewChange)
{
m_bIgnoreViewChange = false;
return;
}
const SwOutlineNodes::size_type nActPos = GetWrtShell()->GetOutlinePos(MAXLEVEL); // find out where the cursor is
if (nActPos == SwOutlineNodes::npos)
return;
// only track if selection is already an outline
std::unique_ptr<weld::TreeIter> xFirstSelected(m_xTreeView->make_iterator());
if (!m_xTreeView->get_selected(xFirstSelected.get()))
xFirstSelected.reset();
if (xFirstSelected && lcl_IsContent(*xFirstSelected, *m_xTreeView) &&
reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xFirstSelected).toInt64())->GetParent()->GetType() != ContentTypeId::OUTLINE)
return;
if (xFirstSelected && lcl_IsContentType(*xFirstSelected, *m_xTreeView) &&
reinterpret_cast<SwContentType*>(m_xTreeView->get_id(*xFirstSelected).toInt64())->GetType() != ContentTypeId::OUTLINE)
return;
int nSelectedRows = m_xTreeView->count_selected_rows();
// find the outline in the tree and select it
m_xTreeView->all_foreach([this, nSelectedRows, nActPos, &xFirstSelected](weld::TreeIter& rEntry){
bool bRet = false;
if (lcl_IsContent(rEntry, *m_xTreeView) &&
reinterpret_cast<SwContent*>(m_xTreeView->get_id(rEntry).toInt64())->GetParent()->GetType() == ContentTypeId::OUTLINE)
// drawing
if ((m_pActiveShell->GetSelectionType() & (SelectionType::DrawObject |
SelectionType::DrawObjectEditMode)) &&
!(m_bIsRoot && m_nRootType != ContentTypeId::DRAWOBJECT))
{
SdrView* pSdrView = m_pActiveShell->GetDrawView();
if(pSdrView && 1 == pSdrView->GetMarkedObjectCount())
{
// might have been scrolled out of view by the user so leave it that way
if (reinterpret_cast<SwOutlineContent*>(m_xTreeView->get_id(rEntry).toInt64())->GetOutlinePos() == nActPos)
SdrObject* pSelected = pSdrView->GetMarkedObjectByIndex(0);
OUString aName(pSelected->GetName());
lcl_SelectByContentTypeAndName(this, *m_xTreeView,
SwResId(STR_CONTENT_TYPE_DRAWOBJECT), aName);
}
return;
}
// graphic, frame, and ole
OUString aContentTypeName;
if (m_pActiveShell->GetSelectionType() == SelectionType::Graphic &&
!(m_bIsRoot && m_nRootType != ContentTypeId::GRAPHIC))
aContentTypeName = SwResId(STR_CONTENT_TYPE_GRAPHIC);
else if (m_pActiveShell->GetSelectionType() == SelectionType::Frame &&
!(m_bIsRoot && m_nRootType != ContentTypeId::FRAME))
aContentTypeName = SwResId(STR_CONTENT_TYPE_FRAME);
else if (m_pActiveShell->GetSelectionType() == SelectionType::Ole &&
!(m_bIsRoot && m_nRootType != ContentTypeId::OLE))
aContentTypeName = SwResId(STR_CONTENT_TYPE_OLE);
if (!aContentTypeName.isEmpty())
{
OUString aName(m_pActiveShell->GetFlyName());
lcl_SelectByContentTypeAndName(this, *m_xTreeView, aContentTypeName, aName);
return;
}
// table
if (m_pActiveShell->IsCursorInTable() &&
!(m_bIsRoot && m_nRootType != ContentTypeId::TABLE))
{
if(m_pActiveShell->GetTableFormat())
{
OUString aName = m_pActiveShell->GetTableFormat()->GetName();
lcl_SelectByContentTypeAndName(this, *m_xTreeView, SwResId(STR_CONTENT_TYPE_TABLE),
aName);
}
return;
}
// outline
// find out where the cursor is
const SwOutlineNodes::size_type nActPos = GetWrtShell()->GetOutlinePos(MAXLEVEL);
if (!((m_bIsRoot && m_nRootType != ContentTypeId::OUTLINE) ||
m_nOutlineTracking == 3 || nActPos == SwOutlineNodes::npos))
{
// assure outline content type is expanded
// this assumes outline content type is first in treeview
std::unique_ptr<weld::TreeIter> xFirstEntry(m_xTreeView->make_iterator());
m_xTreeView->get_iter_first(*xFirstEntry);
m_xTreeView->expand_row(*xFirstEntry);
m_xTreeView->all_foreach([this, nActPos](weld::TreeIter& rEntry){
bool bRet = false;
if (lcl_IsContent(rEntry, *m_xTreeView) && reinterpret_cast<SwContent*>(
m_xTreeView->get_id(rEntry).toInt64())->GetParent()->GetType() ==
ContentTypeId::OUTLINE)
{
// only select if not already selected or tree has multiple entries selected
if (nSelectedRows != 1 || m_xTreeView->iter_compare(rEntry, *xFirstSelected) != 0)
if (reinterpret_cast<SwOutlineContent*>(
m_xTreeView->get_id(rEntry).toInt64())->GetOutlinePos() == nActPos)
{
if (m_nOutlineTracking == 2) // focused outline tracking
std::unique_ptr<weld::TreeIter> xFirstSelected(
m_xTreeView->make_iterator());
if (!m_xTreeView->get_selected(xFirstSelected.get()))
xFirstSelected.reset();
// only select if not already selected or tree has multiple entries selected
if (m_xTreeView->count_selected_rows() != 1 ||
m_xTreeView->iter_compare(rEntry, *xFirstSelected) != 0)
{
// collapse to children of root node
std::unique_ptr<weld::TreeIter> xChildEntry(m_xTreeView->make_iterator());
if (m_xTreeView->get_iter_first(*xChildEntry) && m_xTreeView->iter_children(*xChildEntry))
if (m_nOutlineTracking == 2) // focused outline tracking
{
do
// collapse to children of root node
std::unique_ptr<weld::TreeIter> xChildEntry(
m_xTreeView->make_iterator());
if (m_xTreeView->get_iter_first(*xChildEntry) &&
m_xTreeView->iter_children(*xChildEntry))
{
if (reinterpret_cast<SwContent*>(m_xTreeView->get_id(*xChildEntry).toInt64())->GetParent()->GetType() == ContentTypeId::OUTLINE)
m_xTreeView->collapse_row(*xChildEntry);
else
break;
do
{
if (reinterpret_cast<SwContent*>(
m_xTreeView->get_id(*xChildEntry).toInt64())->
GetParent()->GetType() == ContentTypeId::OUTLINE)
m_xTreeView->collapse_row(*xChildEntry);
else
break;
}
while (m_xTreeView->iter_next(*xChildEntry));
}
while (m_xTreeView->iter_next(*xChildEntry));
}
// unselect all entries, make pEntry visible, and select
m_xTreeView->set_cursor(rEntry);
Select();
}
m_xTreeView->set_cursor(rEntry); // unselect all entries, make pEntry visible, and select
Select();
bRet = true;
}
bRet = true;
}
}
else
{
// use of this break assumes outline content type is first in tree
if (lcl_IsContentType(rEntry, *m_xTreeView) &&
reinterpret_cast<SwContentType*>(m_xTreeView->get_id(rEntry).toInt64())->GetType() != ContentTypeId::OUTLINE)
bRet = true;
}
return bRet;
});
else
{
// use of this break assumes outline content type is first in tree
if (lcl_IsContentType(rEntry, *m_xTreeView) &&
reinterpret_cast<SwContentType*>(
m_xTreeView->get_id(rEntry).toInt64())->GetType() !=
ContentTypeId::OUTLINE)
bRet = true;
}
return bRet;
});
}
else
{
// clear treeview selections
m_xTreeView->unselect_all();
Select();
}
}
void SwContentTree::SelectOutlinesWithSelection()
@@ -3940,6 +4032,9 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode)
const ContentTypeId nType = pCnt->GetParent()->GetType();
sal_uInt16 nSlot = 0;
if(EditEntryMode::DELETE == nMode)
m_bIgnoreViewChange = true;
uno::Reference< container::XNameAccess > xNameAccess, xSecond, xThird;
switch(nType)
{
@@ -4134,7 +4229,7 @@ void SwContentTree::EditEntry(const weld::TreeIter& rEntry, EditEntryMode nMode)
}
if(nSlot)
m_pActiveShell->GetView().GetViewFrame()->
GetDispatcher()->Execute(nSlot, SfxCallMode::ASYNCHRON);
GetDispatcher()->Execute(nSlot, SfxCallMode::SYNCHRON);
else if(xNameAccess.is())
{
uno::Any aObj = xNameAccess->getByName(pCnt->GetName());