Kaydet (Commit) 97dcf778 authored tarafından Miklos Vajna's avatar Miklos Vajna

Related: fdo#65090 DOCX import: handle w:hMerge cell property

Change-Id: I82f334426715fd1a1f0105b86f763d41e66f32da
üst bb562304
......@@ -1660,6 +1660,16 @@ DECLARE_OOXMLIMPORT_TEST(testRPrChangeClosed, "rprchange_closed.docx")
CPPUNIT_ASSERT_EQUAL(false, hasProperty(getRun(getParagraph(2), 1), "RedlineType"));
}
DECLARE_OOXMLIMPORT_TEST(testFdo65090, "fdo65090.docx")
{
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables( ), uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XTableRows> xTableRows(xTextTable->getRows(), uno::UNO_QUERY);
// The first row had two cells, instead of a single horizontally merged one.
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty< uno::Sequence<text::TableColumnSeparator> >(xTableRows->getByIndex(0), "TableColumnSeparators").getLength());
}
#endif
CPPUNIT_PLUGIN_IMPLEMENT();
......
......@@ -539,7 +539,7 @@ TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo
#define CNF_LAST_ROW_LAST_COLUMN 0x002
#define CNF_LAST_ROW_FIRST_COLUMN 0x001
CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(TableInfo & rInfo)
CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(TableInfo & rInfo, std::vector<HorizontallyMergedCell>& rMerges)
{
#ifdef DEBUG_DMAPPER_TABLE_HANDLER
dmapper_logger->startElement("getCellProperties");
......@@ -699,6 +699,25 @@ CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(Tabl
aCellIterator->get()->Insert( PROP_BOTTOM_BORDER_DISTANCE,
uno::makeAny((sal_Int32) rInfo.nBottomBorderDistance ) );
// Horizontal merge is not an UNO property, extract that info here to rMerges, and then remove it from the map.
const PropertyMap::const_iterator aHorizontalMergeIter = aCellIterator->get()->find(PROP_HORIZONTAL_MERGE);
if (aHorizontalMergeIter != aCellIterator->get()->end())
{
if (aHorizontalMergeIter->second.getValue().get<sal_Bool>())
{
// first cell in a merge
HorizontallyMergedCell aMerge(nRow, nCell);
rMerges.push_back(aMerge);
}
else if (!rMerges.empty())
{
// resuming an earlier merge
HorizontallyMergedCell& rMerge = rMerges.back();
rMerge.m_nLastRow = nRow;
rMerge.m_nLastCol = nCell;
}
aCellIterator->get()->erase(PROP_HORIZONTAL_MERGE);
}
pSingleCellProperties[nCell] = aCellIterator->get()->GetPropertyValues();
#ifdef DEBUG_DMAPPER_TABLE_HANDLER
dmapper_logger->endElement();
......@@ -816,7 +835,8 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel)
aTableInfo.pTableStyle = endTableGetTableStyle(aTableInfo, aFrameProperties);
// expands to uno::Sequence< Sequence< beans::PropertyValues > >
CellPropertyValuesSeq_t aCellProperties = endTableGetCellProperties(aTableInfo);
std::vector<HorizontallyMergedCell> aMerges;
CellPropertyValuesSeq_t aCellProperties = endTableGetCellProperties(aTableInfo, aMerges);
RowPropertyValuesSeq_t aRowProperties = endTableGetRowProperties();
......@@ -849,8 +869,27 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel)
aTableInfo.aTableProperties);
if (xTable.is())
{
m_xTableRange = xTable->getAnchor( );
if (!aMerges.empty())
{
// Perform horizontal merges in reverse order, so the fact that merging changes the position of cells won't cause a problem for us.
for (std::vector<HorizontallyMergedCell>::reverse_iterator it = aMerges.rbegin(); it != aMerges.rend(); ++it)
{
uno::Reference<table::XCellRange> xCellRange(xTable, uno::UNO_QUERY_THROW);
uno::Reference<beans::XPropertySet> xCell(xCellRange->getCellByPosition(it->m_nFirstCol, it->m_nFirstRow), uno::UNO_QUERY_THROW);
OUString aFirst = xCell->getPropertyValue("CellName").get<OUString>();
xCell.set(xCellRange->getCellByPosition(it->m_nLastCol, it->m_nLastRow), uno::UNO_QUERY_THROW);
OUString aLast = xCell->getPropertyValue("CellName").get<OUString>();
uno::Reference<text::XTextTableCursor> xCursor = xTable->createCursorByCellName(aFirst);
xCursor->gotoCellByName(aLast, true);
xCursor->mergeRange();
}
}
}
// OOXML table style may container paragraph properties, apply these now.
for (int i = 0; i < aTableInfo.aTableProperties.getLength(); ++i)
{
......
......@@ -48,6 +48,21 @@ typedef std::vector<PropertyMapVector1> PropertyMapVector2;
class DomainMapper_Impl;
class TableStyleSheetEntry;
struct TableInfo;
/// A horizontally merged cell is in fact a range of cells till its merge is performed.
struct HorizontallyMergedCell
{
sal_Int32 m_nFirstRow;
sal_Int32 m_nFirstCol;
sal_Int32 m_nLastRow;
sal_Int32 m_nLastCol;
HorizontallyMergedCell(sal_Int32 nFirstRow, sal_Int32 nFirstCol)
: m_nFirstRow(nFirstRow),
m_nFirstCol(nFirstCol)
{
}
};
class WRITERFILTER_DLLPRIVATE DomainMapperTableHandler : public TableDataHandler<Handle_t , TablePropertyMapPtr >
{
TextReference_t m_xText;
......@@ -67,7 +82,7 @@ class WRITERFILTER_DLLPRIVATE DomainMapperTableHandler : public TableDataHandler
sal_Int32 m_nRowIndex;
TableStyleSheetEntry * endTableGetTableStyle(TableInfo & rInfo, uno::Sequence<beans::PropertyValue>& rFrameProperties);
CellPropertyValuesSeq_t endTableGetCellProperties(TableInfo & rInfo);
CellPropertyValuesSeq_t endTableGetCellProperties(TableInfo & rInfo, std::vector<HorizontallyMergedCell>& rMerges);
RowPropertyValuesSeq_t endTableGetRowProperties();
public:
......
......@@ -309,6 +309,14 @@ bool DomainMapperTableManager::sprm(Sprm & rSprm)
cellProps( pMergeProps);
}
break;
case NS_ooxml::LN_CT_TcPrBase_hMerge:
{
// values can be: LN_Value_ST_Merge_restart, LN_Value_ST_Merge_continue, in reality the second one is a 0
TablePropertyMapPtr pMergeProps(new TablePropertyMap());
pMergeProps->Insert(PROP_HORIZONTAL_MERGE, uno::makeAny(bool(sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_ST_Merge_restart)));
cellProps(pMergeProps);
}
break;
case NS_ooxml::LN_CT_TcPrBase_gridSpan: //number of grid positions spanned by this cell
{
#ifdef DEBUG_DOMAINMAPPER
......
......@@ -359,6 +359,7 @@ OUString PropertyNameSupplier::GetName( PropertyIds eId ) const
case PROP_CHAR_THEME_ORIGINAL_COLOR : sName = "CharThemeOriginalColor"; break;
case PROP_CHAR_THEME_COLOR_SHADE : sName = "CharThemeColorShade"; break;
case PROP_CHAR_THEME_FILL : sName = "CharThemeFill"; break;
case PROP_HORIZONTAL_MERGE: sName = "HorizontalMerge"; break;
}
::std::pair<PropertyNameMap_t::iterator,bool> aInsertIt =
m_pImpl->aNameMap.insert( PropertyNameMap_t::value_type( eId, sName ));
......
......@@ -330,6 +330,7 @@ enum PropertyIds
,PROP_CHAR_THEME_ORIGINAL_COLOR
,PROP_CHAR_THEME_COLOR_SHADE
,PROP_CHAR_THEME_FILL
,PROP_HORIZONTAL_MERGE
};
struct PropertyNameSupplier_Impl;
class PropertyNameSupplier
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment