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:
@@ -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());
|
||||
|
Reference in New Issue
Block a user