LOK - Calc: Increase the row limit to 10.000 rows.

Change-Id: Ie91e4caf33d3b31df4c3de8dc6e78e223dc1e4b3
Reviewed-on: https://gerrit.libreoffice.org/34216
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Marco Cecchetti <mrcekets@gmail.com>
This commit is contained in:
Marco Cecchetti 2016-11-30 14:13:15 +01:00 committed by Marco Cecchetti
parent 1a1dbff33d
commit eb399d69aa
3 changed files with 307 additions and 75 deletions

View File

@ -592,46 +592,79 @@ void DesktopLOKTest::testRowColumnHeaders()
pDocument->pClass->initializeForRendering(pDocument, nullptr);
long nWidth = 0;
long nHeight = 0;
pDocument->m_pDocumentClass->getDocumentSize(pDocument, &nWidth, &nHeight);
long nX = rtl::math::round(nWidth / 4.0);
long nY = rtl::math::round(nHeight / 4.0);
nWidth = rtl::math::round(nWidth / 2.0);
nHeight = rtl::math::round(nHeight / 2.0);
std::stringstream aPayload;
aPayload << ".uno:ViewRowColumnHeaders?x=" << nX << "&y=" << nY << "&width=" << nWidth << "&height=" << nHeight;
boost::property_tree::ptree aTree;
char* pJSON = pDocument->m_pDocumentClass->getCommandValues(pDocument, ".uno:ViewRowColumnHeaders");
char* pJSON = pDocument->m_pDocumentClass->getCommandValues(pDocument, aPayload.str().c_str());
std::stringstream aStream(pJSON);
free(pJSON);
CPPUNIT_ASSERT(!aStream.str().empty());
boost::property_tree::read_json(aStream, aTree);
sal_Int32 nPrevious = 0;
bool bFirstHeader = true;
bool bNotEnoughHeaders = true;
for (boost::property_tree::ptree::value_type& rValue : aTree.get_child("rows"))
{
sal_Int32 nSize = OString(rValue.second.get<std::string>("size").c_str()).toInt32();
CPPUNIT_ASSERT(nSize > 0);
OString aText(rValue.second.get<std::string>("text").c_str());
if (!nPrevious)
// This failed, as the first item did not contain the text of the first row.
CPPUNIT_ASSERT_EQUAL(OString("1"), aText);
if (bFirstHeader)
{
CPPUNIT_ASSERT(nSize <= nY);
CPPUNIT_ASSERT_EQUAL(OString("11"), aText);
bFirstHeader = false;
}
else
{
// Make sure that size is absolute: the first two items have the same relative size.
CPPUNIT_ASSERT(nSize > 0);
CPPUNIT_ASSERT(nPrevious < nSize);
break;
if (nSize > nY + nHeight)
{
bNotEnoughHeaders = false;
break;
}
}
nPrevious = nSize;
}
CPPUNIT_ASSERT(!bNotEnoughHeaders);
nPrevious = 0;
bFirstHeader = true;
bNotEnoughHeaders = true;
for (boost::property_tree::ptree::value_type& rValue : aTree.get_child("columns"))
{
sal_Int32 nSize = OString(rValue.second.get<std::string>("size").c_str()).toInt32();
CPPUNIT_ASSERT(nSize > 0);
OString aText(rValue.second.get<std::string>("text").c_str());
if (!nPrevious)
CPPUNIT_ASSERT_EQUAL(OString("A"), aText);
if (bFirstHeader)
{
CPPUNIT_ASSERT(nSize <= nX);
CPPUNIT_ASSERT_EQUAL(OString("4"), aText);
bFirstHeader = false;
}
else
{
CPPUNIT_ASSERT(nSize > 0);
CPPUNIT_ASSERT(nPrevious < nSize);
break;
if (nSize > nX + nWidth)
{
bNotEnoughHeaders = false;
break;
}
}
nPrevious = nSize;
}
CPPUNIT_ASSERT(!bNotEnoughHeaders);
}
void DesktopLOKTest::testHiddenRowHeaders()
@ -640,29 +673,34 @@ void DesktopLOKTest::testHiddenRowHeaders()
pDocument->pClass->initializeForRendering(pDocument, nullptr);
long nX = 0;
long nY = 0;
long nWidth = 0;
long nHeight = 0;
pDocument->m_pDocumentClass->getDocumentSize(pDocument, &nWidth, &nHeight);
std::stringstream aPayload;
aPayload << ".uno:ViewRowColumnHeaders?x=" << nX << "&y=" << nY << "&width=" << nWidth << "&height=" << nHeight;
boost::property_tree::ptree aTree;
char* pJSON = pDocument->m_pDocumentClass->getCommandValues(pDocument, ".uno:ViewRowColumnHeaders");
char* pJSON = pDocument->m_pDocumentClass->getCommandValues(pDocument, aPayload.str().c_str());
std::stringstream aStream(pJSON);
free(pJSON);
CPPUNIT_ASSERT(!aStream.str().empty());
boost::property_tree::read_json(aStream, aTree);
sal_Int32 nPrevious = 0;
bool bFirst = true;
sal_Int32 nIndex = 0;
for (boost::property_tree::ptree::value_type& rValue : aTree.get_child("rows"))
{
sal_Int32 nSize = OString(rValue.second.get<std::string>("size").c_str()).toInt32();
CPPUNIT_ASSERT(nSize > 0);
if (bFirst)
bFirst = false;
else
if (nIndex++ == 2)
{
// nSize was 509, nPrevious was 254, i.e. hidden row wasn't reported as 0 height.
// nSize was 510, nPrevious was 255, i.e. hidden row wasn't reported as 0 height.
CPPUNIT_ASSERT_EQUAL(nPrevious, nSize);
break;
}
nPrevious = nSize;
}
}

View File

@ -71,7 +71,7 @@ const SCCOL MAXCOL = MAXCOLCOUNT - 1;
const SCTAB MAXTAB = MAXTABCOUNT - 1;
const SCCOLROW MAXCOLROW = MAXROW;
// Maximun tiled rendering values
const SCROW MAXTILEDROW = 1000;
const SCROW MAXTILEDROW = 10000;
// Limit the initial tab count to prevent users to set the count too high,
// which could cause the memory usage of blank documents to exceed the
// available system memory.

View File

@ -44,6 +44,9 @@
#include "AccessibilityHints.hxx"
#include "appoptio.hxx"
#include "attrib.hxx"
#include <comphelper/lok.hxx>
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <sfx2/lokhelper.hxx>
#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
@ -2307,82 +2310,273 @@ OUString ScTabView::getRowColumnHeaders(const Rectangle& rRectangle)
if (!pDoc)
return OUString();
SCCOL nEndCol = 0;
SCROW nEndRow = 0;
pDoc->GetTiledRenderingArea(aViewData.GetTabNo(), nEndCol, nEndRow);
rtl::OUStringBuffer aBuffer(256 + (50 * nEndRow) + (50 * nEndCol));
if (rRectangle.IsEmpty())
return OUString();
rtl::OUStringBuffer aBuffer(256);
aBuffer.append("{ \"commandName\": \".uno:ViewRowColumnHeaders\",\n");
SCROW nStartRow = 0;
SCROW nEndRow = 0;
SCCOL nStartCol = 0;
SCCOL nEndCol = 0;
/// *** start collecting ROWS ***
/// 1) compute start and end rows
long nTotalPixels = 0;
if (rRectangle.Top() < rRectangle.Bottom())
{
long nUpperBoundPx = rRectangle.Top() / TWIPS_PER_PIXEL;
long nLowerBoundPx = rRectangle.Bottom() / TWIPS_PER_PIXEL;
nEndRow = MAXTILEDROW;
for (SCROW nRow = 0; nRow <= MAXTILEDROW; ++nRow)
{
if (nTotalPixels > nLowerBoundPx)
{
nEndRow = nRow; // first row below the rectangle
break;
}
const sal_uInt16 nSize = pDoc->GetRowHeight(nRow, aViewData.GetTabNo());
const long nSizePx = ScViewData::ToPixel(nSize, 1.0 / TWIPS_PER_PIXEL);
nTotalPixels += nSizePx;
if (nTotalPixels < nUpperBoundPx)
{
nStartRow = nRow; // last row above the rectangle
continue;
}
}
nStartRow -= 1;
nEndRow += 2;
if (nStartRow < 0) nStartRow = 0;
if (nEndRow > MAXTILEDROW) nEndRow = MAXTILEDROW;
}
aBuffer.ensureCapacity( aBuffer.getCapacity() + (50 * (nEndRow - nStartRow + 1)) );
long nVisibleRows = nEndRow - nStartRow;
if (nVisibleRows < 25)
nVisibleRows = 25;
/// 2) if we are approaching current max tiled row, signal a size changed event
/// and invalidate the involved area
if (nEndRow > aViewData.GetMaxTiledRow() - nVisibleRows)
{
ScDocShell* pDocSh = aViewData.GetDocShell();
ScModelObj* pModelObj = pDocSh ? ScModelObj::getImplementation( pDocSh->GetModel() ) : nullptr;
Size aOldSize(0, 0);
if (pModelObj)
aOldSize = pModelObj->getDocumentSize();
aViewData.SetMaxTiledRow(std::min(std::max(nEndRow, aViewData.GetMaxTiledRow()) + nVisibleRows, (long)(MAXTILEDROW)));
Size aNewSize(0, 0);
if (pModelObj)
aNewSize = pModelObj->getDocumentSize();
if (pDocSh)
{
// Provide size in the payload, so clients don't have to
// call lok::Document::getDocumentSize().
std::stringstream ss;
ss << aNewSize.Width() << ", " << aNewSize.Height();
OString sSize = ss.str().c_str();
aViewData.GetViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_DOCUMENT_SIZE_CHANGED, sSize.getStr());
// New area extended to the bottom of the sheet after last row
// excluding overlapping area with aNewColArea
Rectangle aNewRowArea(0, aOldSize.getHeight(), aOldSize.getWidth(), aNewSize.getHeight());
// Only invalidate if spreadsheet extended to the bottom
if (aNewRowArea.getHeight())
{
SfxLokHelper::notifyInvalidation(aViewData.GetViewShell(), aNewRowArea.toString());
}
}
}
/// 3) create string data for rows
aBuffer.append("\"rows\": [\n");
long nTotal = 0;
long nTotalPixels = 0;
bool bFirstRow = true;
for (SCROW nRow = 0; nRow <= nEndRow; ++nRow)
if (nStartRow == 0 && nStartRow != nEndRow)
{
aBuffer.append("{ \"text\": \"").append("0").append("\", ");
aBuffer.append("\"size\": \"").append(OUString::number(0)).append("\" }");
bFirstRow = false;
}
nTotalPixels = 0;
for (SCROW nRow = 0; nRow < nEndRow; ++nRow)
{
// nSize will be 0 for hidden rows.
const sal_uInt16 nSize = pDoc->GetRowHeight(nRow, aViewData.GetTabNo());
const long nSizePixels = ScViewData::ToPixel(nSize, aViewData.GetPPTY());
const OUString aText = pRowBar[SC_SPLIT_BOTTOM]->GetEntryText(nRow);
const long nSizePx = ScViewData::ToPixel(nSize, 1.0 / TWIPS_PER_PIXEL);
nTotalPixels += nSizePx;
bool bSkip = false;
if (!rRectangle.IsEmpty())
{
long nTop = std::max(rRectangle.Top(), nTotal);
long nBottom = std::min(rRectangle.Bottom(), nTotal + nSize);
if (nBottom < nTop)
// They do not intersect.
bSkip = true;
}
if (!bSkip)
{
if (!bFirstRow)
aBuffer.append(", ");
if (nRow < nStartRow)
continue;
aBuffer.append("{ \"text\": \"").append(aText).append("\", ");
aBuffer.append("\"size\": \"").append(OUString::number((nTotalPixels + nSizePixels) / aViewData.GetPPTY())).append("\" }");
bFirstRow = false;
OUString aText = pRowBar[SC_SPLIT_BOTTOM]->GetEntryText(nRow);
if (!bFirstRow)
{
aBuffer.append(", ");
}
nTotal += nSize;
nTotalPixels += nSizePixels;
else
{
aText = OUString::number(nStartRow + 1);
}
aBuffer.append("{ \"text\": \"").append(aText).append("\", ");
aBuffer.append("\"size\": \"").append(OUString::number(nTotalPixels * TWIPS_PER_PIXEL)).append("\" }");
bFirstRow = false;
}
aBuffer.append("],\n\"columns\":\n[");
aBuffer.append("]");
/// end collecting ROWS
aBuffer.append(",\n");
/// *** start collecting COLS ***
/// 1) compute start and end columns
nTotal = 0;
nTotalPixels = 0;
bFirstRow = true;
for (SCCOL nCol = 0; nCol <= nEndCol; ++nCol)
if (rRectangle.Left() < rRectangle.Right())
{
const sal_uInt16 nSize = pDoc->GetColWidth(nCol, aViewData.GetTabNo());
const long nSizePixels = ScViewData::ToPixel(nSize, aViewData.GetPPTX());
const OUString aText = pColBar[SC_SPLIT_LEFT]->GetEntryText(nCol);
bool bSkip = false;
if (!rRectangle.IsEmpty())
long nLeftBoundPx = rRectangle.Left() / TWIPS_PER_PIXEL;
long nRightBoundPx = rRectangle.Right() / TWIPS_PER_PIXEL;
nEndCol = MAXCOL;
for (SCCOL nCol = 0; nCol <= MAXCOL; ++nCol)
{
long nLeft = std::max(rRectangle.Left(), nTotal);
long nRight = std::min(rRectangle.Right(), nTotal + nSize);
if (nRight < nLeft)
// They do not intersect.
bSkip = true;
}
if (!bSkip)
{
if (!bFirstRow)
aBuffer.append(", ");
if (nTotalPixels > nRightBoundPx)
{
nEndCol = nCol;
break;
}
aBuffer.append("{ \"text\": \"").append(aText).append("\", ");
aBuffer.append("\"size\": \"").append(OUString::number((nTotalPixels + nSizePixels) / aViewData.GetPPTX())).append("\" }");
bFirstRow = false;
const sal_uInt16 nSize = pDoc->GetColWidth(nCol, aViewData.GetTabNo());
const long nSizePx = ScViewData::ToPixel(nSize, 1.0 / TWIPS_PER_PIXEL);
nTotalPixels += nSizePx;
if (nTotalPixels < nLeftBoundPx)
{
nStartCol = nCol;
continue;
}
}
nTotal += nSize;
nTotalPixels += nSizePixels;
nStartCol -= 1;
nEndCol += 2;
if (nStartCol < 0) nStartCol = 0;
if (nEndCol > MAXCOL) nEndCol = MAXCOL;
}
aBuffer.append("]\n}");
return aBuffer.makeStringAndClear();
aBuffer.ensureCapacity( aBuffer.getCapacity() + (50 * (nEndCol - nStartCol + 1)) );
long nVisibleCols = nEndCol - nStartCol;
if (nVisibleCols < 10)
nVisibleCols = 10;
/// 2) if we are approaching current max tiled column, signal a size changed event
/// and invalidate the involved area
if (nEndCol > aViewData.GetMaxTiledCol() - nVisibleCols)
{
ScDocShell* pDocSh = aViewData.GetDocShell();
ScModelObj* pModelObj = pDocSh ? ScModelObj::getImplementation( pDocSh->GetModel() ) : nullptr;
Size aOldSize(0, 0);
if (pModelObj)
aOldSize = pModelObj->getDocumentSize();
aViewData.SetMaxTiledCol(std::min(std::max(nEndCol, aViewData.GetMaxTiledCol()) + nVisibleCols, (long)(MAXCOL)));
Size aNewSize(0, 0);
if (pModelObj)
aNewSize = pModelObj->getDocumentSize();
if (pDocSh)
{
// Provide size in the payload, so clients don't have to
// call lok::Document::getDocumentSize().
std::stringstream ss;
ss << aNewSize.Width() << ", " << aNewSize.Height();
OString sSize = ss.str().c_str();
aViewData.GetViewShell()->libreOfficeKitViewCallback(LOK_CALLBACK_DOCUMENT_SIZE_CHANGED, sSize.getStr());
// New area extended to the right of the sheet after last column
// including overlapping area with aNewRowArea
Rectangle aNewColArea(aOldSize.getWidth(), 0, aNewSize.getWidth(), aNewSize.getHeight());
// Only invalidate if spreadsheet extended to the bottom
if (aNewColArea.getWidth())
{
SfxLokHelper::notifyInvalidation(aViewData.GetViewShell(), aNewColArea.toString());
}
}
}
/// 3) create string data for columns
aBuffer.append("\"columns\": [\n");
bool bFirstCol = true;
if (nStartCol == 0 && nStartCol != nEndCol )
{
aBuffer.append("{ \"text\": \"").append("0").append("\", ");
aBuffer.append("\"size\": \"").append(OUString::number(0)).append("\" }");
bFirstCol = false;
}
nTotalPixels = 0;
for (SCCOL nCol = 0; nCol < nEndCol; ++nCol)
{
// nSize will be 0 for hidden columns.
const sal_uInt16 nSize = pDoc->GetColWidth(nCol, aViewData.GetTabNo());
const long nSizePx = ScViewData::ToPixel(nSize, 1.0 / TWIPS_PER_PIXEL);
nTotalPixels += nSizePx;
if (nCol < nStartCol)
continue;
OUString aText = pColBar[SC_SPLIT_LEFT]->GetEntryText(nCol);
if (!bFirstCol)
{
aBuffer.append(", ");
}
else
{
aText = OUString::number(nStartCol + 1);
}
aBuffer.append("{ \"text\": \"").append(aText).append("\", ");
aBuffer.append("\"size\": \"").append(OUString::number(nTotalPixels * TWIPS_PER_PIXEL)).append("\" }");
bFirstCol = false;
}
aBuffer.append("]");
/// end collecting COLs
aBuffer.append("\n}");
OUString sRet = aBuffer.makeStringAndClear();
return sRet;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */