summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--desktop/source/lib/init.cxx17
-rw-r--r--include/vcl/ITiledRenderable.hxx7
-rw-r--r--libreofficekit/source/gtk/lokdocview.cxx91
-rw-r--r--sw/inc/swmodule.hxx2
-rw-r--r--sw/inc/unotxdoc.hxx2
-rw-r--r--sw/qa/extras/tiledrendering/tiledrendering.cxx25
-rw-r--r--sw/source/uibase/app/swmodul1.cxx49
-rw-r--r--sw/source/uibase/uno/unotxdoc.cxx5
8 files changed, 167 insertions, 31 deletions
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index ead812baf6d4..fcb27d97a07c 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -2117,6 +2117,19 @@ static char* getTrackedChanges(LibreOfficeKitDocument* pThis)
return pJson;
}
+/// Returns the JSON representation of the redline author table.
+static char* getTrackedChangeAuthors(LibreOfficeKitDocument* pThis)
+{
+ ITiledRenderable* pDoc = getTiledRenderable(pThis);
+ if (!pDoc)
+ {
+ gImpl->maLastExceptionMsg = "Document doesn't support tiled rendering";
+ return nullptr;
+ }
+ OUString aAuthors = pDoc->getTrackedChangeAuthors();
+ return strdup(aAuthors.toUtf8().getStr());
+}
+
static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCommand)
{
SolarMutexGuard aGuard;
@@ -2145,6 +2158,10 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo
{
return getTrackedChanges(pThis);
}
+ else if (aCommand == ".uno:TrackedChangeAuthors")
+ {
+ return getTrackedChangeAuthors(pThis);
+ }
else if (aCommand.startsWith(aViewRowColumnHeaders))
{
ITiledRenderable* pDoc = getTiledRenderable(pThis);
diff --git a/include/vcl/ITiledRenderable.hxx b/include/vcl/ITiledRenderable.hxx
index 3a8a69743e9d..700a6bd4a283 100644
--- a/include/vcl/ITiledRenderable.hxx
+++ b/include/vcl/ITiledRenderable.hxx
@@ -207,6 +207,13 @@ public:
{
return OUString();
}
+
+ /// Implementation for
+ /// lok::Document::getCommandValues(".uno:TrackedChangeAuthors").
+ virtual OUString getTrackedChangeAuthors()
+ {
+ return OUString();
+ }
};
} // namespace vcl
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
index 786d827d92d5..8ec54a003a7f 100644
--- a/libreofficekit/source/gtk/lokdocview.cxx
+++ b/libreofficekit/source/gtk/lokdocview.cxx
@@ -904,6 +904,28 @@ static gboolean queueDraw(gpointer pData)
return G_SOURCE_REMOVE;
}
+/// Looks up the author string from initializeForRendering()'s rendering arguments.
+static std::string getAuthorRenderingArgument(LOKDocViewPrivate& priv)
+{
+ std::stringstream aStream;
+ aStream << priv->m_aRenderingArguments;
+ boost::property_tree::ptree aTree;
+ boost::property_tree::read_json(aStream, aTree);
+ std::string aRet;
+ for (const std::pair<std::string, boost::property_tree::ptree>& rPair : aTree)
+ {
+ if (rPair.first == ".uno:Author")
+ {
+ aRet = rPair.second.get<std::string>("value");
+ break;
+ }
+ }
+ return aRet;
+}
+
+/// Author string <-> View ID map
+static std::map<std::string, int> g_aAuthorViews;
+
/// Set up LOKDocView after the document is loaded, invoked on the main thread by openDocumentInThread() running in a thread.
static gboolean postDocumentLoad(gpointer pData)
{
@@ -913,6 +935,7 @@ static gboolean postDocumentLoad(gpointer pData)
std::unique_lock<std::mutex> aGuard(g_aLOKMutex);
priv->m_pDocument->pClass->initializeForRendering(priv->m_pDocument, priv->m_aRenderingArguments.c_str());
priv->m_nViewId = priv->m_pDocument->pClass->getView(priv->m_pDocument);
+ g_aAuthorViews[getAuthorRenderingArgument(priv)] = priv->m_nViewId;
priv->m_pDocument->pClass->registerCallback(priv->m_pDocument, callbackWorker, pLOKDocView);
priv->m_pDocument->pClass->getDocumentSize(priv->m_pDocument, &priv->m_nDocumentWidthTwips, &priv->m_nDocumentHeightTwips);
priv->m_nParts = priv->m_pDocument->pClass->getParts(priv->m_pDocument);
@@ -1586,29 +1609,53 @@ renderDocument(LOKDocView* pDocView, cairo_t* pCairo)
return FALSE;
}
-static const GdkRGBA& getDarkColor(int nViewId)
+static const GdkRGBA& getDarkColor(int nViewId, LOKDocViewPrivate& priv)
{
static std::map<int, GdkRGBA> aColorMap;
auto it = aColorMap.find(nViewId);
if (it != aColorMap.end())
return it->second;
- // Based on tools/colordata.hxx, COL_AUTHOR1_DARK..COL_AUTHOR9_DARK.
- static std::vector<GdkRGBA> aColors =
- {
- {((double)198)/255, ((double)146)/255, ((double)0)/255, 0},
- {((double)6)/255, ((double)70)/255, ((double)162)/255, 0},
- {((double)87)/255, ((double)157)/255, ((double)28)/255, 0},
- {((double)105)/255, ((double)43)/255, ((double)157)/255, 0},
- {((double)197)/255, ((double)0)/255, ((double)11)/255, 0},
- {((double)0)/255, ((double)128)/255, ((double)128)/255, 0},
- {((double)140)/255, ((double)132)/255, ((double)0)/255, 0},
- {((double)43)/255, ((double)85)/255, ((double)107)/255, 0},
- {((double)209)/255, ((double)118)/255, ((double)0)/255, 0},
- };
- static int nColorCounter = 0;
- GdkRGBA aColor = aColors[nColorCounter++ % aColors.size()];
- aColorMap[nViewId] = aColor;
+ if (priv->m_eDocumentType == LOK_DOCTYPE_TEXT)
+ {
+ char* pValues = priv->m_pDocument->pClass->getCommandValues(priv->m_pDocument, ".uno:TrackedChangeAuthors");
+ std::stringstream aInfo;
+ aInfo << "lok::Document::getCommandValues('.uno:TrackedChangeAuthors') returned '" << pValues << "'" << std::endl;
+ g_info("%s", aInfo.str().c_str());
+
+ std::stringstream aStream(pValues);
+ boost::property_tree::ptree aTree;
+ boost::property_tree::read_json(aStream, aTree);
+ for (const auto& rValue : aTree.get_child("authors"))
+ {
+ const std::string& rName = rValue.second.get<std::string>("name");
+ guint32 nColor = rValue.second.get<guint32>("color");
+ GdkRGBA aColor{((double)((guint8)((nColor)>>16)))/255, ((double)((guint8)(((guint16)(nColor)) >> 8)))/255, ((double)((guint8)(nColor)))/255, 0};
+ auto itAuthorViews = g_aAuthorViews.find(rName);
+ if (itAuthorViews != g_aAuthorViews.end())
+ aColorMap[itAuthorViews->second] = aColor;
+ }
+ }
+ else
+ {
+ // Based on tools/colordata.hxx, COL_AUTHOR1_DARK..COL_AUTHOR9_DARK.
+ static std::vector<GdkRGBA> aColors =
+ {
+ {((double)198)/255, ((double)146)/255, ((double)0)/255, 0},
+ {((double)6)/255, ((double)70)/255, ((double)162)/255, 0},
+ {((double)87)/255, ((double)157)/255, ((double)28)/255, 0},
+ {((double)105)/255, ((double)43)/255, ((double)157)/255, 0},
+ {((double)197)/255, ((double)0)/255, ((double)11)/255, 0},
+ {((double)0)/255, ((double)128)/255, ((double)128)/255, 0},
+ {((double)140)/255, ((double)132)/255, ((double)0)/255, 0},
+ {((double)43)/255, ((double)85)/255, ((double)107)/255, 0},
+ {((double)209)/255, ((double)118)/255, ((double)0)/255, 0},
+ };
+ static int nColorCounter = 0;
+ GdkRGBA aColor = aColors[nColorCounter++ % aColors.size()];
+ aColorMap[nViewId] = aColor;
+ }
+ assert(aColorMap.find(nViewId) != aColorMap.end());
return aColorMap[nViewId];
}
@@ -1650,7 +1697,7 @@ renderOverlay(LOKDocView* pDocView, cairo_t* pCairo)
// Set a minimal width if it would be 0.
rCursor.width = 30;
- const GdkRGBA& rDark = getDarkColor(rPair.first);
+ const GdkRGBA& rDark = getDarkColor(rPair.first, priv);
cairo_set_source_rgb(pCairo, rDark.red, rDark.green, rDark.blue);
cairo_rectangle(pCairo,
twipToPixel(rCursor.x, priv->m_fZoom),
@@ -1723,7 +1770,7 @@ renderOverlay(LOKDocView* pDocView, cairo_t* pCairo)
for (GdkRectangle& rRectangle : rPair.second.m_aRectangles)
{
- const GdkRGBA& rDark = getDarkColor(rPair.first);
+ const GdkRGBA& rDark = getDarkColor(rPair.first, priv);
// 75% transparency.
cairo_set_source_rgba(pCairo, rDark.red, rDark.green, rDark.blue, 0.25);
cairo_rectangle(pCairo,
@@ -1748,7 +1795,7 @@ renderOverlay(LOKDocView* pDocView, cairo_t* pCairo)
if (rRectangle.m_nPart != priv->m_nPartId && priv->m_eDocumentType != LOK_DOCTYPE_TEXT)
continue;
- const GdkRGBA& rDark = getDarkColor(rPair.first);
+ const GdkRGBA& rDark = getDarkColor(rPair.first, priv);
renderGraphicHandle(pDocView, pCairo, rRectangle.m_aRectangle, rDark);
}
@@ -1772,7 +1819,7 @@ renderOverlay(LOKDocView* pDocView, cairo_t* pCairo)
if (rCursor.m_nPart != priv->m_nPartId)
continue;
- const GdkRGBA& rDark = getDarkColor(rPair.first);
+ const GdkRGBA& rDark = getDarkColor(rPair.first, priv);
cairo_set_source_rgb(pCairo, rDark.red, rDark.green, rDark.blue);
cairo_rectangle(pCairo,
twipToPixel(rCursor.m_aRectangle.x, priv->m_fZoom),
@@ -1791,7 +1838,7 @@ renderOverlay(LOKDocView* pDocView, cairo_t* pCairo)
continue;
// Draw a rectangle.
- const GdkRGBA& rDark = getDarkColor(rPair.first);
+ const GdkRGBA& rDark = getDarkColor(rPair.first, priv);
cairo_set_source_rgb(pCairo, rDark.red, rDark.green, rDark.blue);
cairo_rectangle(pCairo,
twipToPixel(rRectangle.m_aRectangle.x, priv->m_fZoom),
diff --git a/sw/inc/swmodule.hxx b/sw/inc/swmodule.hxx
index 66cb66b8ff79..60bf7deb4d0a 100644
--- a/sw/inc/swmodule.hxx
+++ b/sw/inc/swmodule.hxx
@@ -187,6 +187,8 @@ public:
// Redlining.
sal_uInt16 GetRedlineAuthor();
OUString GetRedlineAuthor(sal_uInt16 nPos);
+ /// See SwXTextDocument::getTrackedChangeAuthors().
+ OUString GetRedlineAuthorInfo();
sal_uInt16 InsertRedlineAuthor(const OUString& rAuthor);
void SetRedlineAuthor(const OUString& rAuthor); // for unit tests
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index 8867994ca2e5..56d36debdb10 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -439,6 +439,8 @@ public:
virtual void setClientVisibleArea(const Rectangle& rRectangle) override;
/// @see vcl::ITiledRenderable::getPointer().
virtual Pointer getPointer() override;
+ /// @see vcl::ITiledRenderable::getTrackedChangeAuthors().
+ OUString getTrackedChangeAuthors() override;
// css::tiledrendering::XTiledRenderable
virtual void SAL_CALL paintTile( const ::css::uno::Any& Parent, ::sal_Int32 nOutputWidth, ::sal_Int32 nOutputHeight, ::sal_Int32 nTilePosX, ::sal_Int32 nTilePosY, ::sal_Int32 nTileWidth, ::sal_Int32 nTileHeight ) throw (::css::uno::RuntimeException, ::std::exception) override;
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index cce710aefd4c..f6fb64fe6652 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -75,6 +75,7 @@ public:
void testSetViewGraphicSelection();
void testCreateViewGraphicSelection();
void testCreateViewTextSelection();
+ void testRedlineColors();
CPPUNIT_TEST_SUITE(SwTiledRenderingTest);
CPPUNIT_TEST(testRegisterCallback);
@@ -113,6 +114,7 @@ public:
CPPUNIT_TEST(testSetViewGraphicSelection);
CPPUNIT_TEST(testCreateViewGraphicSelection);
CPPUNIT_TEST(testCreateViewTextSelection);
+ CPPUNIT_TEST(testRedlineColors);
CPPUNIT_TEST_SUITE_END();
private:
@@ -1430,6 +1432,29 @@ void SwTiledRenderingTest::testCreateViewTextSelection()
comphelper::LibreOfficeKit::setActive(false);
}
+void SwTiledRenderingTest::testRedlineColors()
+{
+ // Load a document.
+ comphelper::LibreOfficeKit::setActive();
+ SwXTextDocument* pXTextDocument = createDoc("dummy.fodt");
+
+ // Turn on track changes, type "zzz" at the end.
+ uno::Reference<beans::XPropertySet> xPropertySet(mxComponent, uno::UNO_QUERY);
+ xPropertySet->setPropertyValue("RecordChanges", uno::makeAny(true));
+ SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
+ pWrtShell->EndDoc();
+ pWrtShell->Insert("zzz");
+
+ // Assert that info about exactly one author is returned.
+ OUString aInfo = pXTextDocument->getTrackedChangeAuthors();
+ std::stringstream aStream(aInfo.toUtf8().getStr());
+ boost::property_tree::ptree aTree;
+ boost::property_tree::read_json(aStream, aTree);
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aTree.get_child("authors").size());
+
+ comphelper::LibreOfficeKit::setActive(false);
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(SwTiledRenderingTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/uibase/app/swmodul1.cxx b/sw/source/uibase/app/swmodul1.cxx
index 649937193ea2..ef0a992f5bf9 100644
--- a/sw/source/uibase/app/swmodul1.cxx
+++ b/sw/source/uibase/app/swmodul1.cxx
@@ -18,6 +18,7 @@
*/
#include <memory>
+#include <boost/property_tree/json_parser.hpp>
#include <hintids.hxx>
#include <sfx2/request.hxx>
@@ -423,6 +424,44 @@ OUString SwModule::GetRedlineAuthor(sal_uInt16 nPos)
return (*m_pAuthorNames)[nPos];
}
+static ColorData lcl_GetAuthorColor(sal_uInt16 nPos)
+{
+ static const ColorData aColArr[] =
+ {
+ COL_AUTHOR1_DARK, COL_AUTHOR2_DARK, COL_AUTHOR3_DARK,
+ COL_AUTHOR4_DARK, COL_AUTHOR5_DARK, COL_AUTHOR6_DARK,
+ COL_AUTHOR7_DARK, COL_AUTHOR8_DARK, COL_AUTHOR9_DARK
+ };
+
+ return aColArr[nPos % SAL_N_ELEMENTS(aColArr)];
+}
+
+/// Returns a JSON representation of a redline author.
+boost::property_tree::ptree lcl_AuthorToJson(const OUString& rAuthor, size_t nIndex)
+{
+ boost::property_tree::ptree aRet;
+ aRet.put("index", nIndex);
+ aRet.put("name", rAuthor.toUtf8().getStr());
+ aRet.put("color", lcl_GetAuthorColor(nIndex));
+ return aRet;
+}
+
+OUString SwModule::GetRedlineAuthorInfo()
+{
+ boost::property_tree::ptree aTable;
+ for (size_t nAuthor = 0; nAuthor < m_pAuthorNames->size(); ++nAuthor)
+ {
+ boost::property_tree::ptree aAuthor = lcl_AuthorToJson((*m_pAuthorNames)[nAuthor], nAuthor);
+ aTable.push_back(std::make_pair("", aAuthor));
+ }
+
+ boost::property_tree::ptree aTree;
+ aTree.add_child("authors", aTable);
+ std::stringstream aStream;
+ boost::property_tree::write_json(aStream, aTree);
+ return OUString::fromUtf8(aStream.str().c_str());
+}
+
sal_uInt16 SwModule::InsertRedlineAuthor(const OUString& rAuthor)
{
sal_uInt16 nPos = 0;
@@ -442,15 +481,7 @@ static void lcl_FillAuthorAttr( sal_uInt16 nAuthor, SfxItemSet &rSet,
Color aCol( rAttr.nColor );
if( COL_TRANSPARENT == rAttr.nColor )
- {
- static const ColorData aColArr[] = {
- COL_AUTHOR1_DARK, COL_AUTHOR2_DARK, COL_AUTHOR3_DARK,
- COL_AUTHOR4_DARK, COL_AUTHOR5_DARK, COL_AUTHOR6_DARK,
- COL_AUTHOR7_DARK, COL_AUTHOR8_DARK, COL_AUTHOR9_DARK };
-
- aCol.SetColor( aColArr[ nAuthor % (sizeof( aColArr ) /
- sizeof( aColArr[0] )) ] );
- }
+ aCol.SetColor(lcl_GetAuthorColor(nAuthor));
bool bBackGr = COL_NONE_COLOR == rAttr.nColor;
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index 1e10d09256a3..5e92ecb8fee1 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3199,6 +3199,11 @@ Pointer SwXTextDocument::getPointer()
return pWrtShell->GetView().GetEditWin().GetPointer();
}
+OUString SwXTextDocument::getTrackedChangeAuthors()
+{
+ return SW_MOD()->GetRedlineAuthorInfo();
+}
+
int SwXTextDocument::getPart()
{
SolarMutexGuard aGuard;