[Libreoffice-commits] core.git: editeng/source include/editeng include/svx officecfg/registry sd/inc sd/sdi sd/source sd/uiconfig svx/source
Justin Luth (via logerrit)
logerrit at kemper.freedesktop.org
Mon Jul 22 04:08:09 UTC 2019
editeng/source/editeng/editeng.cxx | 5
editeng/source/editeng/impedit3.cxx | 1
editeng/source/outliner/outliner.cxx | 13 +
include/editeng/editeng.hxx | 2
include/editeng/outliner.hxx | 2
include/svx/svdedtv.hxx | 4
officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu | 11 +
sd/inc/app.hrc | 1
sd/sdi/_drvwsh.sdi | 5
sd/sdi/sdraw.sdi | 17 ++
sd/source/ui/view/drviews2.cxx | 23 +++
sd/source/ui/view/drviewsj.cxx | 2
sd/uiconfig/sdraw/menubar/menubar.xml | 2
sd/uiconfig/sdraw/popupmenu/multiselect.xml | 1
svx/source/svdraw/svdedtv2.cxx | 67 ++++++++++
15 files changed, 150 insertions(+), 6 deletions(-)
New commits:
commit 82c3e68642de445064313e353812b54df76c7fe9
Author: Justin Luth <justin_luth at sil.org>
AuthorDate: Wed Jul 3 15:33:35 2019 +0300
Commit: Justin Luth <justin_luth at sil.org>
CommitDate: Mon Jul 22 06:07:29 2019 +0200
tdf#118370 Draw: add option to consolidate multiple textObjs
This gives the user a tool to consolidate multiple textboxes
into a single textbox. First the user selects a group of
textframes, and then runs the consolidate text function.
This will REPLACE the marked textframes with a single textbox
combining all of the text. The function inspects the text
fragments to see if they end in sentence-ending punctuation.
If not, then the next textbox's content is appended to it
instead of starting a new pargraph. It is the user's responsibility
to afterwards fix up paragraphing, and set paragraph properties.
The rational for this patch is to simplify making major text
changes on PDFs imported into Draw, since each paragraph is
currently broken into tiny character-property textbox fragments.
Copy/paste from the PDF itself doesn't keep character attributes,
so it is hard for a user to re-create the text.
This is related to tdf#32249, but as a comment says, a better
solution would be to write an entire text-focused PDF import,
rather than just pick up the pieces. And I agree, but considering
this simple patch took me a couple of weeks of frustration,
I'm obviously not the person to do that. And since the bug
has been open for 9 years, likely no one else will either.
Thus, this pick-up-the-pieces tool to help the end user.
This initial patch works only with textFrames, but can
easily be adjusted to consolidate other HasText() SdrObjects.
However, that tended to produce unexpected results, so everything
other than OBJ_TEXT is explicitly excluded.
(Thus general shapes with text, callouts, text-along-path etc
are ignored.)
Change-Id: I68a9a5b187bf320a8e671414c5cb22b07725fd52
Reviewed-on: https://gerrit.libreoffice.org/75043
Tested-by: Jenkins
Reviewed-by: Justin Luth <justin_luth at sil.org>
diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx
index cae8822cd48e..84b2f39df32d 100644
--- a/editeng/source/editeng/editeng.cxx
+++ b/editeng/source/editeng/editeng.cxx
@@ -1666,7 +1666,7 @@ bool EditEngine::IsInSelectionMode() const
pImpEditEngine->GetSelEngine().IsInSelection() );
}
-void EditEngine::InsertParagraph( sal_Int32 nPara, const EditTextObject& rTxtObj )
+void EditEngine::InsertParagraph( sal_Int32 nPara, const EditTextObject& rTxtObj, bool bAppend )
{
if ( nPara > GetParagraphCount() )
{
@@ -1683,6 +1683,9 @@ void EditEngine::InsertParagraph( sal_Int32 nPara, const EditTextObject& rTxtObj
pImpEditEngine->RemoveCharAttribs( nPara );
pImpEditEngine->InsertText( rTxtObj, EditSelection( aPaM, aPaM ) );
+ if ( bAppend && nPara )
+ pImpEditEngine->ConnectContents( nPara-1, /*bBackwards=*/false );
+
pImpEditEngine->UndoActionEnd();
pImpEditEngine->FormatAndUpdate();
diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx
index 976a94ea2f1a..99603db06493 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -3921,7 +3921,6 @@ EditPaM ImpEditEngine::ConnectContents( sal_Int32 nLeftNode, bool bBackward )
ContentNode* pRightNode = aEditDoc.GetObject( nLeftNode+1 );
DBG_ASSERT( pLeftNode, "Invalid left node in ConnectContents ");
DBG_ASSERT( pRightNode, "Invalid right node in ConnectContents ");
- DBG_ASSERT( IsInUndo(), "ConnectContent only for Undo()!" );
return ImpConnectParagraphs( pLeftNode, pRightNode, bBackward );
}
diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx
index 2d757fb23c9d..320dc6958355 100644
--- a/editeng/source/outliner/outliner.cxx
+++ b/editeng/source/outliner/outliner.cxx
@@ -602,7 +602,7 @@ void Outliner::SetText( const OutlinerParaObject& rPObj )
DBG_ASSERT( pEditEngine->GetParagraphCount()==rPObj.Count(),"SetText failed");
}
-void Outliner::AddText( const OutlinerParaObject& rPObj )
+void Outliner::AddText( const OutlinerParaObject& rPObj, bool bAppend )
{
bool bUpdate = pEditEngine->GetUpdateMode();
@@ -615,16 +615,25 @@ void Outliner::AddText( const OutlinerParaObject& rPObj )
pParaList->Clear();
pEditEngine->SetText(rPObj.GetTextObject());
nPara = 0;
+ bAppend = false;
}
else
{
nPara = pParaList->GetParagraphCount();
- pEditEngine->InsertParagraph( EE_PARA_APPEND, rPObj.GetTextObject() );
+ pEditEngine->InsertParagraph( EE_PARA_APPEND, rPObj.GetTextObject(), bAppend );
}
bFirstParaIsEmpty = false;
for( sal_Int32 n = 0; n < rPObj.Count(); n++ )
{
+ if ( n == 0 && bAppend )
+ {
+ // This first "paragraph" was just appended to an existing (incomplete) paragraph.
+ // Since no new paragraph will be added, the assumed increase-by-1 also won't happen.
+ --nPara;
+ continue;
+ }
+
Paragraph* pPara = new Paragraph( rPObj.GetParagraphData(n) );
pParaList->Append(std::unique_ptr<Paragraph>(pPara));
sal_Int32 nP = nPara+n;
diff --git a/include/editeng/editeng.hxx b/include/editeng/editeng.hxx
index e531b6c8d9f5..64581f930aab 100644
--- a/include/editeng/editeng.hxx
+++ b/include/editeng/editeng.hxx
@@ -299,7 +299,7 @@ public:
void SetText( const EditTextObject& rTextObject );
void RemoveParagraph(sal_Int32 nPara);
- void InsertParagraph(sal_Int32 nPara, const EditTextObject& rTxtObj);
+ void InsertParagraph(sal_Int32 nPara, const EditTextObject& rTxtObj, const bool bAppend = false);
void InsertParagraph(sal_Int32 nPara, const OUString& rText);
void SetText(sal_Int32 nPara, const OUString& rText);
diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx
index cc2505202e66..9d4037d6885c 100644
--- a/include/editeng/outliner.hxx
+++ b/include/editeng/outliner.hxx
@@ -676,7 +676,7 @@ public:
Paragraph* Insert( const OUString& rText, sal_Int32 nAbsPos = EE_PARA_APPEND, sal_Int16 nDepth = 0 );
void SetText( const OutlinerParaObject& );
- void AddText( const OutlinerParaObject& );
+ void AddText( const OutlinerParaObject&, bool bAppend = false );
void SetText( const OUString& rText, Paragraph* pParagraph );
OUString GetText( Paragraph const * pPara, sal_Int32 nParaCount=1 ) const;
diff --git a/include/svx/svdedtv.hxx b/include/svx/svdedtv.hxx
index 320d082d6b3a..1b662cde29c5 100644
--- a/include/svx/svdedtv.hxx
+++ b/include/svx/svdedtv.hxx
@@ -244,6 +244,10 @@ public:
bool IsCropAllowed() const;
bool IsDistortAllowed(bool bNoContortion=false) const;
+ // Consolidate the text from multiple, selected TextObjects,
+ // attempting to identify paragraph fragments and join them together
+ void CombineMarkedTextObjects();
+
// Unite several objects to a polygon:
// - rectangles/circles/text... are implicitly converted.
// - polygones are closed automatically
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu
index 2facd9bee872..abe7e7162e06 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/DrawImpressCommands.xcu
@@ -856,6 +856,17 @@
<value>1</value>
</prop>
</node>
+ <node oor:name=".uno:TextCombine" oor:op="replace">
+ <prop oor:name="Label" oor:type="xs:string">
+ <value xml:lang="en-US">Consolidate Text</value>
+ </prop>
+ <prop oor:name="TooltipLabel" oor:type="xs:string">
+ <value xml:lang="en-US">Merges text fragments from selected objects into one new textbox</value>
+ </prop>
+ <prop oor:name="Properties" oor:type="xs:int">
+ <value>1</value>
+ </prop>
+ </node>
<node oor:name=".uno:Combine" oor:op="replace">
<prop oor:name="Label" oor:type="xs:string">
<value xml:lang="en-US">Comb~ine</value>
diff --git a/sd/inc/app.hrc b/sd/inc/app.hrc
index 2738085f0ae5..9445f47cd0a7 100644
--- a/sd/inc/app.hrc
+++ b/sd/inc/app.hrc
@@ -94,6 +94,7 @@
// FREE
#define SID_POSITION (SID_SD_START+22)
// FREE
+#define SID_TEXT_COMBINE (SID_SD_START+25)
#define SID_COMBINE (SID_SD_START+26)
#define SID_NAME_GROUP (SID_SD_START+27)
#define SID_DRAWTBX_CONNECTORS (SID_SD_START+28)
diff --git a/sd/sdi/_drvwsh.sdi b/sd/sdi/_drvwsh.sdi
index 8dfdf71023de..3c98b281347f 100644
--- a/sd/sdi/_drvwsh.sdi
+++ b/sd/sdi/_drvwsh.sdi
@@ -469,6 +469,11 @@ interface DrawView
StateMethod = GetMenuState ;
FastCall = FALSE ;
]
+ SID_TEXT_COMBINE // ole : no, status : ?
+ [
+ ExecMethod = FuTemporary ;
+ StateMethod = GetMenuState ;
+ ]
SID_COMBINE // ole : no, status : ?
[
ExecMethod = FuTemporary ;
diff --git a/sd/sdi/sdraw.sdi b/sd/sdi/sdraw.sdi
index b1760f31bb3b..ad88ee8a09ab 100644
--- a/sd/sdi/sdraw.sdi
+++ b/sd/sdi/sdraw.sdi
@@ -330,6 +330,23 @@ SfxBoolItem ColorView SID_COLORVIEW
GroupId = SfxGroupId::View;
]
+SfxVoidItem TextCombine SID_TEXT_COMBINE
+()
+[
+ AutoUpdate = FALSE,
+ FastCall = FALSE,
+ ReadOnlyDoc = FALSE,
+ Toggle = FALSE,
+ Container = FALSE,
+ RecordAbsolute = FALSE,
+ RecordPerSet;
+
+ AccelConfig = TRUE,
+ MenuConfig = TRUE,
+ ToolBoxConfig = TRUE,
+ GroupId = SfxGroupId::Modify;
+]
+
SfxVoidItem Combine SID_COMBINE
()
[
diff --git a/sd/source/ui/view/drviews2.cxx b/sd/source/ui/view/drviews2.cxx
index a812d3be34f4..11025537247f 100644
--- a/sd/source/ui/view/drviews2.cxx
+++ b/sd/source/ui/view/drviews2.cxx
@@ -2598,6 +2598,29 @@ void DrawViewShell::FuTemporary(SfxRequest& rReq)
}
break;
+ case SID_TEXT_COMBINE: // BASIC
+ {
+ // End text edit to avoid conflicts
+ if(mpDrawView->IsTextEdit())
+ mpDrawView->SdrEndTextEdit();
+
+ if ( mpDrawView->IsPresObjSelected() )
+ {
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(GetFrameWeld(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ SdResId(STR_ACTION_NOTPOSSIBLE)));
+ xInfoBox->run();
+ }
+ else
+ {
+ WaitObject aWait( GetActiveWindow() );
+ mpDrawView->CombineMarkedTextObjects();
+ }
+ Cancel();
+ rReq.Done ();
+ }
+ break;
+
case SID_COMBINE: // BASIC
{
// End text edit to avoid conflicts
diff --git a/sd/source/ui/view/drviewsj.cxx b/sd/source/ui/view/drviewsj.cxx
index 32e05aefa4da..92917a72bf67 100644
--- a/sd/source/ui/view/drviewsj.cxx
+++ b/sd/source/ui/view/drviewsj.cxx
@@ -285,6 +285,7 @@ void DrawViewShell::GetMenuStateSel( SfxItemSet &rSet )
}
rSet.DisableItem(SID_GROUP);
+ rSet.DisableItem(SID_TEXT_COMBINE);
rSet.DisableItem(SID_COMBINE);
rSet.DisableItem(SID_DISTRIBUTE_DLG);
rSet.DisableItem(SID_POLY_MERGE);
@@ -493,6 +494,7 @@ void DrawViewShell::GetMenuStateSel( SfxItemSet &rSet )
rSet.DisableItem( SID_DISMANTLE );
rSet.DisableItem( SID_BREAK );
+ rSet.DisableItem( SID_TEXT_COMBINE );
rSet.DisableItem( SID_COMBINE );
rSet.DisableItem(SID_DISTRIBUTE_DLG);
rSet.DisableItem(SID_POLY_MERGE);
diff --git a/sd/uiconfig/sdraw/menubar/menubar.xml b/sd/uiconfig/sdraw/menubar/menubar.xml
index e8f139cb900a..579869a296b4 100644
--- a/sd/uiconfig/sdraw/menubar/menubar.xml
+++ b/sd/uiconfig/sdraw/menubar/menubar.xml
@@ -548,6 +548,8 @@
<menu:menuitem menu:id=".uno:Substract"/>
<menu:menuitem menu:id=".uno:Intersect"/>
<menu:menuseparator/>
+ <menu:menuitem menu:id=".uno:TextCombine"/>
+ <menu:menuseparator/>
<menu:menuitem menu:id=".uno:CopyObjects"/>
<menu:menuitem menu:id=".uno:Morphing"/>
<menu:menuseparator/>
diff --git a/sd/uiconfig/sdraw/popupmenu/multiselect.xml b/sd/uiconfig/sdraw/popupmenu/multiselect.xml
index cb88b0d81eae..86639b8ea309 100644
--- a/sd/uiconfig/sdraw/popupmenu/multiselect.xml
+++ b/sd/uiconfig/sdraw/popupmenu/multiselect.xml
@@ -73,6 +73,7 @@
<menu:menuitem menu:id=".uno:EqualizeHeight"/>
</menu:menupopup>
</menu:menu>
+ <menu:menuitem menu:id=".uno:TextCombine"/>
<menu:menuseparator/>
<menu:menuitem menu:id=".uno:FormatGroup"/>
<menu:menuitem menu:id=".uno:FormatUngroup"/>
diff --git a/svx/source/svdraw/svdedtv2.cxx b/svx/source/svdraw/svdedtv2.cxx
index 47dd34025de2..5a7bf23d64f4 100644
--- a/svx/source/svdraw/svdedtv2.cxx
+++ b/svx/source/svdraw/svdedtv2.cxx
@@ -21,6 +21,7 @@
#include <editeng/outliner.hxx>
#include <svx/svdundo.hxx>
#include <svx/svdogrp.hxx>
+#include <svx/svdoutl.hxx>
#include <svx/svdovirt.hxx>
#include <svx/svdopath.hxx>
#include <svx/svdpage.hxx>
@@ -33,6 +34,7 @@
#include <svx/sdshitm.hxx>
#include <svx/xfillit0.hxx>
#include <svx/xlineit0.hxx>
+#include <svx/xtextit0.hxx>
#include "svdfmtf.hxx"
#include "svdpdf.hxx"
#include <svx/svdetc.hxx>
@@ -45,6 +47,7 @@
#include <svx/strings.hrc>
#include <svx/svdoashp.hxx>
#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+#include <i18nutil/unicode.hxx>
#include <sal/log.hxx>
#include <tools/debug.hxx>
#include <memory>
@@ -1213,6 +1216,70 @@ void SdrEditView::EqualizeMarkedObjects(bool bWidth)
EndUndo();
}
+void SdrEditView::CombineMarkedTextObjects()
+{
+ SdrPageView* pPageView = GetSdrPageView();
+ if ( !pPageView || pPageView->IsLayerLocked( GetActiveLayer() ) )
+ return;
+
+ bool bUndo = IsUndoEnabled();
+
+ // Undo-String will be set later
+ if ( bUndo )
+ BegUndo();
+
+ SdrOutliner& rDrawOutliner = getSdrModelFromSdrView().GetDrawOutliner();
+
+ SdrObjListIter aIter( GetMarkedObjectList(), SdrIterMode::Flat);
+ while ( aIter.IsMore() )
+ {
+ SdrObject* pObj = aIter.Next();
+ SdrTextObj* pTextObj = dynamic_cast<SdrTextObj*>( pObj );
+ const OutlinerParaObject* pOPO = pTextObj ? pTextObj->GetOutlinerParaObject() : nullptr;
+ if ( pOPO && pTextObj->IsTextFrame()
+ && pTextObj->GetObjIdentifier() == OBJ_TEXT // not callouts (OBJ_CAPTION)
+ && !pTextObj->IsOutlText() // not impress presentation objects
+ && pTextObj->GetMergedItem(XATTR_FORMTXTSTYLE).GetValue() == XFormTextStyle::NONE // not Fontwork
+ )
+ {
+ // if the last paragraph does not end in paragraph-end punctuation (ignoring whitespace),
+ // assume this text should be added to the end of the last paragraph, instead of starting a new paragraph.
+ const sal_Int32 nPara = rDrawOutliner.GetParagraphCount();
+ const OUString sLastPara = nPara ? rDrawOutliner.GetText( rDrawOutliner.GetParagraph( nPara - 1 ) ) : "";
+ sal_Int32 n = sLastPara.getLength();
+ while ( n && unicode::isWhiteSpace( sLastPara[--n] ) )
+ ;
+ //TODO: find way to use Locale to identify sentence final punctuation. Copied IsSentenceAtEnd() from autofmt.cxx
+ const bool bAppend = !n || ( sLastPara[n] != '.' && sLastPara[n] != '?' && sLastPara[n] != '!' );
+ rDrawOutliner.AddText( *pOPO, bAppend );
+ }
+ else
+ {
+ // Unmark non-textboxes, because all marked objects are deleted at the end. AdjustMarkHdl later.
+ MarkObj(pObj, pPageView, /*bUnmark=*/true, /*bImpNoSetMarkHdl=*/true);
+ }
+ }
+
+ MarkListHasChanged();
+ AdjustMarkHdl();
+
+ if ( GetMarkedObjectCount() > 1 )
+ {
+ SdrRectObj* pReplacement = new SdrRectObj( getSdrModelFromSdrView(), OBJ_TEXT );
+ pReplacement->SetOutlinerParaObject( rDrawOutliner.CreateParaObject() );
+ pReplacement->SetSnapRect( GetMarkedObjRect() );
+
+ const SdrInsertFlags nFlags = SdrInsertFlags::DONTMARK | SdrInsertFlags::SETDEFLAYER;
+ if ( InsertObjectAtView( pReplacement, *pPageView, nFlags ) )
+ DeleteMarkedObj();
+ }
+
+ if ( bUndo )
+ EndUndo();
+
+ return;
+}
+
void SdrEditView::CombineMarkedObjects(bool bNoPolyPoly)
{
// #105899# Start of Combine-Undo put to front, else ConvertMarkedToPolyObj would
More information about the Libreoffice-commits
mailing list