2013-11-08 22:15:36 +01:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/*
|
|
|
|
* This file is part of the LibreOffice project.
|
|
|
|
*
|
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
*/
|
|
|
|
|
2013-11-21 15:23:09 +01:00
|
|
|
#include <datastream.hxx>
|
2014-04-14 15:41:13 +02:00
|
|
|
#include <datastreamgettime.hxx>
|
2013-11-08 22:15:36 +01:00
|
|
|
|
2013-11-18 13:31:39 +01:00
|
|
|
#include <com/sun/star/frame/XLayoutManager.hpp>
|
|
|
|
#include <com/sun/star/ui/XUIElement.hpp>
|
2013-11-27 15:48:32 +01:00
|
|
|
#include <officecfg/Office/Common.hxx>
|
2013-11-08 22:15:36 +01:00
|
|
|
#include <osl/conditn.hxx>
|
2013-12-18 14:55:17 -05:00
|
|
|
#include <osl/time.h>
|
2013-11-08 22:15:36 +01:00
|
|
|
#include <rtl/strbuf.hxx>
|
|
|
|
#include <salhelper/thread.hxx>
|
2013-11-18 13:31:39 +01:00
|
|
|
#include <sfx2/viewfrm.hxx>
|
2013-11-25 12:01:57 +01:00
|
|
|
#include <datastreamdlg.hxx>
|
2013-11-08 22:15:36 +01:00
|
|
|
#include <docsh.hxx>
|
2013-11-19 13:57:58 +01:00
|
|
|
#include <rangelst.hxx>
|
2013-11-18 13:31:39 +01:00
|
|
|
#include <tabvwsh.hxx>
|
2013-11-11 22:26:54 +01:00
|
|
|
#include <viewdata.hxx>
|
2013-12-17 21:51:43 -05:00
|
|
|
#include <stringutil.hxx>
|
2013-12-18 23:51:27 -05:00
|
|
|
#include <documentlinkmgr.hxx>
|
2013-11-08 22:15:36 +01:00
|
|
|
|
2013-12-17 21:18:46 -05:00
|
|
|
#include <config_orcus.h>
|
|
|
|
|
|
|
|
#if ENABLE_ORCUS
|
|
|
|
#if defined WNT
|
|
|
|
#define __ORCUS_STATIC_LIB
|
|
|
|
#endif
|
|
|
|
#include <orcus/csv_parser.hpp>
|
|
|
|
#endif
|
|
|
|
|
2013-11-20 17:09:41 +01:00
|
|
|
#include <queue>
|
|
|
|
|
2013-12-17 10:19:57 -05:00
|
|
|
namespace sc {
|
|
|
|
|
2013-12-28 22:45:00 +00:00
|
|
|
enum {
|
|
|
|
DEBUG_TIME_IMPORT,
|
|
|
|
DEBUG_TIME_RECALC,
|
|
|
|
DEBUG_TIME_RENDER,
|
|
|
|
DEBUG_TIME_MAX
|
|
|
|
};
|
|
|
|
|
|
|
|
static double fTimes[DEBUG_TIME_MAX] = { 0.0, 0.0, 0.0 };
|
|
|
|
|
|
|
|
double datastream_get_time(int nIdx)
|
|
|
|
{
|
2014-01-19 18:39:56 +01:00
|
|
|
if( nIdx < 0 || nIdx >= (int)SAL_N_ELEMENTS( fTimes ) )
|
2013-12-28 22:45:00 +00:00
|
|
|
return -1;
|
|
|
|
return fTimes[ nIdx ];
|
|
|
|
}
|
|
|
|
|
2013-12-30 12:16:35 -05:00
|
|
|
namespace {
|
|
|
|
|
2013-12-18 14:55:17 -05:00
|
|
|
inline double getNow()
|
|
|
|
{
|
|
|
|
TimeValue now;
|
|
|
|
osl_getSystemTime(&now);
|
|
|
|
return static_cast<double>(now.Seconds) + static_cast<double>(now.Nanosec) / 1000000000.0;
|
|
|
|
}
|
|
|
|
|
2013-12-30 12:16:35 -05:00
|
|
|
#if ENABLE_ORCUS
|
|
|
|
|
|
|
|
class CSVHandler
|
|
|
|
{
|
|
|
|
DataStream::Line& mrLine;
|
|
|
|
size_t mnColCount;
|
|
|
|
size_t mnCols;
|
|
|
|
const char* mpLineHead;
|
|
|
|
|
|
|
|
public:
|
|
|
|
CSVHandler( DataStream::Line& rLine, size_t nColCount ) :
|
|
|
|
mrLine(rLine), mnColCount(nColCount), mnCols(0), mpLineHead(rLine.maLine.getStr()) {}
|
|
|
|
|
|
|
|
void begin_parse() {}
|
|
|
|
void end_parse() {}
|
|
|
|
void begin_row() {}
|
|
|
|
void end_row() {}
|
|
|
|
|
|
|
|
void cell(const char* p, size_t n)
|
|
|
|
{
|
|
|
|
if (mnCols >= mnColCount)
|
|
|
|
return;
|
|
|
|
|
|
|
|
DataStream::Cell aCell;
|
|
|
|
if (ScStringUtil::parseSimpleNumber(p, n, '.', ',', aCell.mfValue))
|
|
|
|
{
|
|
|
|
aCell.mbValue = true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
aCell.mbValue = false;
|
|
|
|
aCell.maStr.Pos = std::distance(mpLineHead, p);
|
|
|
|
aCell.maStr.Size = n;
|
|
|
|
}
|
|
|
|
mrLine.maCells.push_back(aCell);
|
|
|
|
|
|
|
|
++mnCols;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-11-08 22:15:36 +01:00
|
|
|
namespace datastreams {
|
|
|
|
|
2013-12-30 12:16:35 -05:00
|
|
|
void emptyLineQueue( std::queue<DataStream::LinesType*>& rQueue )
|
2013-12-27 21:57:25 -05:00
|
|
|
{
|
|
|
|
while (!rQueue.empty())
|
|
|
|
{
|
|
|
|
delete rQueue.front();
|
|
|
|
rQueue.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-20 17:09:41 +01:00
|
|
|
class ReaderThread : public salhelper::Thread
|
|
|
|
{
|
|
|
|
SvStream *mpStream;
|
2013-12-30 12:16:35 -05:00
|
|
|
size_t mnColCount;
|
2013-12-27 22:40:14 -05:00
|
|
|
bool mbTerminate;
|
|
|
|
osl::Mutex maMtxTerminate;
|
2013-12-27 23:22:54 -05:00
|
|
|
|
2013-12-30 12:16:35 -05:00
|
|
|
std::queue<DataStream::LinesType*> maPendingLines;
|
|
|
|
std::queue<DataStream::LinesType*> maUsedLines;
|
2013-12-27 23:22:54 -05:00
|
|
|
osl::Mutex maMtxLines;
|
|
|
|
|
|
|
|
osl::Condition maCondReadStream;
|
|
|
|
osl::Condition maCondConsume;
|
|
|
|
|
2013-12-30 12:16:35 -05:00
|
|
|
#if ENABLE_ORCUS
|
2014-01-08 13:17:28 +01:00
|
|
|
orcus::csv::parser_config maConfig;
|
2013-12-30 12:16:35 -05:00
|
|
|
#endif
|
|
|
|
|
2013-12-27 23:22:54 -05:00
|
|
|
public:
|
2013-11-20 17:09:41 +01:00
|
|
|
|
2013-12-30 12:16:35 -05:00
|
|
|
ReaderThread(SvStream *pData, size_t nColCount):
|
2013-12-27 22:40:14 -05:00
|
|
|
Thread("ReaderThread"),
|
|
|
|
mpStream(pData),
|
2013-12-30 12:16:35 -05:00
|
|
|
mnColCount(nColCount),
|
|
|
|
mbTerminate(false)
|
|
|
|
{
|
|
|
|
#if ENABLE_ORCUS
|
|
|
|
maConfig.delimiters.push_back(',');
|
|
|
|
maConfig.text_qualifier = '"';
|
|
|
|
#endif
|
|
|
|
}
|
2013-11-20 17:09:41 +01:00
|
|
|
|
|
|
|
virtual ~ReaderThread()
|
|
|
|
{
|
|
|
|
delete mpStream;
|
2013-12-27 21:57:25 -05:00
|
|
|
emptyLineQueue(maPendingLines);
|
|
|
|
emptyLineQueue(maUsedLines);
|
2013-11-20 17:09:41 +01:00
|
|
|
}
|
|
|
|
|
2013-12-27 22:40:14 -05:00
|
|
|
bool isTerminateRequested()
|
|
|
|
{
|
|
|
|
osl::MutexGuard aGuard(maMtxTerminate);
|
|
|
|
return mbTerminate;
|
|
|
|
}
|
|
|
|
|
|
|
|
void requestTerminate()
|
|
|
|
{
|
|
|
|
osl::MutexGuard aGuard(maMtxTerminate);
|
|
|
|
mbTerminate = true;
|
|
|
|
}
|
|
|
|
|
2013-11-20 17:59:15 +01:00
|
|
|
void endThread()
|
2013-11-20 17:09:41 +01:00
|
|
|
{
|
2013-12-27 22:40:14 -05:00
|
|
|
requestTerminate();
|
2013-12-27 23:22:54 -05:00
|
|
|
maCondReadStream.set();
|
|
|
|
}
|
|
|
|
|
|
|
|
void waitForNewLines()
|
|
|
|
{
|
|
|
|
maCondConsume.wait();
|
|
|
|
maCondConsume.reset();
|
|
|
|
}
|
|
|
|
|
2013-12-30 12:16:35 -05:00
|
|
|
DataStream::LinesType* popNewLines()
|
2013-12-27 23:22:54 -05:00
|
|
|
{
|
2013-12-30 12:16:35 -05:00
|
|
|
DataStream::LinesType* pLines = maPendingLines.front();
|
2013-12-27 23:22:54 -05:00
|
|
|
maPendingLines.pop();
|
|
|
|
return pLines;
|
|
|
|
}
|
|
|
|
|
|
|
|
void resumeReadStream()
|
|
|
|
{
|
|
|
|
if (maPendingLines.size() <= 4)
|
|
|
|
maCondReadStream.set(); // start producer again
|
|
|
|
}
|
|
|
|
|
|
|
|
bool hasNewLines()
|
|
|
|
{
|
|
|
|
return !maPendingLines.empty();
|
|
|
|
}
|
|
|
|
|
2013-12-30 12:16:35 -05:00
|
|
|
void pushUsedLines( DataStream::LinesType* pLines )
|
2013-12-27 23:22:54 -05:00
|
|
|
{
|
|
|
|
maUsedLines.push(pLines);
|
|
|
|
}
|
|
|
|
|
|
|
|
osl::Mutex& getLinesMutex()
|
|
|
|
{
|
|
|
|
return maMtxLines;
|
2013-11-20 17:09:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual void execute() SAL_OVERRIDE
|
|
|
|
{
|
2013-12-27 22:40:14 -05:00
|
|
|
while (!isTerminateRequested())
|
2013-11-20 17:09:41 +01:00
|
|
|
{
|
2013-12-30 12:16:35 -05:00
|
|
|
DataStream::LinesType* pLines = NULL;
|
2013-12-27 22:40:14 -05:00
|
|
|
osl::ResettableMutexGuard aGuard(maMtxLines);
|
2013-12-27 21:57:25 -05:00
|
|
|
|
2013-11-20 17:09:41 +01:00
|
|
|
if (!maUsedLines.empty())
|
|
|
|
{
|
2013-12-27 23:22:54 -05:00
|
|
|
// Re-use lines from previous runs.
|
2013-11-20 17:09:41 +01:00
|
|
|
pLines = maUsedLines.front();
|
|
|
|
maUsedLines.pop();
|
|
|
|
aGuard.clear(); // unlock
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
aGuard.clear(); // unlock
|
2013-12-30 12:16:35 -05:00
|
|
|
pLines = new DataStream::LinesType(10);
|
2013-11-20 17:09:41 +01:00
|
|
|
}
|
2013-12-27 21:57:25 -05:00
|
|
|
|
2013-12-27 23:22:54 -05:00
|
|
|
// Read & store new lines from stream.
|
2013-12-30 12:16:35 -05:00
|
|
|
for (size_t i = 0, n = pLines->size(); i < n; ++i)
|
|
|
|
{
|
|
|
|
DataStream::Line& rLine = (*pLines)[i];
|
|
|
|
rLine.maCells.clear();
|
|
|
|
mpStream->ReadLine(rLine.maLine);
|
2013-12-30 14:31:30 -05:00
|
|
|
#if ENABLE_ORCUS
|
2013-12-30 12:16:35 -05:00
|
|
|
CSVHandler aHdl(rLine, mnColCount);
|
|
|
|
orcus::csv_parser<CSVHandler> parser(rLine.maLine.getStr(), rLine.maLine.getLength(), aHdl, maConfig);
|
|
|
|
parser.parse();
|
2013-12-30 14:31:30 -05:00
|
|
|
#endif
|
2013-12-30 12:16:35 -05:00
|
|
|
}
|
2013-12-27 21:57:25 -05:00
|
|
|
|
2013-11-20 17:09:41 +01:00
|
|
|
aGuard.reset(); // lock
|
2013-12-27 22:40:14 -05:00
|
|
|
while (!isTerminateRequested() && maPendingLines.size() >= 8)
|
2013-12-27 21:57:25 -05:00
|
|
|
{
|
|
|
|
// pause reading for a bit
|
2013-11-20 17:09:41 +01:00
|
|
|
aGuard.clear(); // unlock
|
2013-12-27 23:22:54 -05:00
|
|
|
maCondReadStream.wait();
|
|
|
|
maCondReadStream.reset();
|
2013-11-20 17:09:41 +01:00
|
|
|
aGuard.reset(); // lock
|
|
|
|
}
|
|
|
|
maPendingLines.push(pLines);
|
2013-12-27 23:22:54 -05:00
|
|
|
maCondConsume.set();
|
2013-11-20 17:09:41 +01:00
|
|
|
if (!mpStream->good())
|
2013-12-27 22:40:14 -05:00
|
|
|
requestTerminate();
|
2013-11-20 17:09:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-11-08 22:15:36 +01:00
|
|
|
}
|
|
|
|
|
2013-12-30 12:16:35 -05:00
|
|
|
DataStream::Cell::Cell() : mfValue(0.0), mbValue(true) {}
|
|
|
|
|
|
|
|
DataStream::Cell::Cell( const Cell& r ) : mbValue(r.mbValue)
|
|
|
|
{
|
|
|
|
if (r.mbValue)
|
|
|
|
mfValue = r.mfValue;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
maStr.Pos = r.maStr.Pos;
|
|
|
|
maStr.Size = r.maStr.Size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-29 16:00:59 +01:00
|
|
|
void DataStream::MakeToolbarVisible()
|
2013-11-21 15:23:09 +01:00
|
|
|
{
|
|
|
|
css::uno::Reference< css::frame::XFrame > xFrame =
|
2013-11-29 16:00:59 +01:00
|
|
|
ScDocShell::GetViewData()->GetViewShell()->GetViewFrame()->GetFrame().GetFrameInterface();
|
2013-11-21 15:23:09 +01:00
|
|
|
if (!xFrame.is())
|
|
|
|
return;
|
|
|
|
|
|
|
|
css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY);
|
|
|
|
if (!xPropSet.is())
|
|
|
|
return;
|
|
|
|
|
|
|
|
css::uno::Reference< css::frame::XLayoutManager > xLayoutManager;
|
|
|
|
xPropSet->getPropertyValue("LayoutManager") >>= xLayoutManager;
|
|
|
|
if (!xLayoutManager.is())
|
|
|
|
return;
|
|
|
|
|
|
|
|
const OUString sResourceURL( "private:resource/toolbar/datastreams" );
|
|
|
|
css::uno::Reference< css::ui::XUIElement > xUIElement = xLayoutManager->getElement(sResourceURL);
|
|
|
|
if (!xUIElement.is())
|
|
|
|
{
|
|
|
|
xLayoutManager->createElement( sResourceURL );
|
|
|
|
xLayoutManager->showElement( sResourceURL );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-17 22:38:37 -05:00
|
|
|
DataStream* DataStream::Set(
|
|
|
|
ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
|
|
|
|
sal_Int32 nLimit, MoveType eMove, sal_uInt32 nSettings)
|
2013-11-21 15:23:09 +01:00
|
|
|
{
|
2013-12-18 23:51:27 -05:00
|
|
|
DataStream* pLink = new DataStream(pShell, rURL, rRange, nLimit, eMove, nSettings);
|
2014-06-18 12:14:29 +02:00
|
|
|
sc::DocumentLinkManager& rMgr = pShell->GetDocument().GetDocLinkManager();
|
2013-12-18 23:51:27 -05:00
|
|
|
rMgr.setDataStream(pLink);
|
2013-12-17 14:21:07 -05:00
|
|
|
return pLink;
|
2013-11-21 15:23:09 +01:00
|
|
|
}
|
|
|
|
|
2013-12-17 14:09:25 -05:00
|
|
|
DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const ScRange& rRange,
|
2013-12-17 22:38:37 -05:00
|
|
|
sal_Int32 nLimit, MoveType eMove, sal_uInt32 nSettings) :
|
2013-12-17 11:36:18 -05:00
|
|
|
mpDocShell(pShell),
|
2014-06-18 12:14:29 +02:00
|
|
|
maDocAccess(mpDocShell->GetDocument()),
|
2013-12-19 10:31:41 -05:00
|
|
|
meOrigMove(NO_MOVE),
|
2013-12-17 11:36:18 -05:00
|
|
|
meMove(NO_MOVE),
|
|
|
|
mbRunning(false),
|
2013-12-18 16:19:05 -05:00
|
|
|
mbValuesInLine(false),
|
|
|
|
mbRefreshOnEmptyLine(false),
|
2013-12-17 11:36:18 -05:00
|
|
|
mpLines(0),
|
|
|
|
mnLinesCount(0),
|
2013-12-18 14:55:17 -05:00
|
|
|
mnLinesSinceRefresh(0),
|
|
|
|
mfLastRefreshTime(0.0),
|
2013-12-17 16:11:52 -05:00
|
|
|
mnCurRow(0)
|
2013-11-08 22:15:36 +01:00
|
|
|
{
|
2013-12-30 15:43:21 -05:00
|
|
|
maImportTimer.SetTimeout(0);
|
|
|
|
maImportTimer.SetTimeoutHdl( LINK(this, DataStream, ImportTimerHdl) );
|
2013-12-12 16:09:11 +01:00
|
|
|
|
2013-12-17 22:38:37 -05:00
|
|
|
Decode(rURL, rRange, nLimit, eMove, nSettings);
|
2013-11-08 22:15:36 +01:00
|
|
|
}
|
|
|
|
|
2013-11-21 15:23:09 +01:00
|
|
|
DataStream::~DataStream()
|
2013-11-08 22:15:36 +01:00
|
|
|
{
|
|
|
|
if (mbRunning)
|
2013-11-27 12:42:59 +01:00
|
|
|
StopImport();
|
2013-12-30 15:43:21 -05:00
|
|
|
|
2013-11-20 17:09:41 +01:00
|
|
|
if (mxReaderThread.is())
|
2013-12-27 21:57:25 -05:00
|
|
|
{
|
2013-11-20 17:59:15 +01:00
|
|
|
mxReaderThread->endThread();
|
2013-12-27 21:57:25 -05:00
|
|
|
mxReaderThread->join();
|
|
|
|
}
|
2013-11-28 10:47:15 +01:00
|
|
|
delete mpLines;
|
2013-11-20 17:09:41 +01:00
|
|
|
}
|
|
|
|
|
2013-12-30 12:16:35 -05:00
|
|
|
DataStream::Line DataStream::ConsumeLine()
|
2013-11-20 17:09:41 +01:00
|
|
|
{
|
|
|
|
if (!mpLines || mnLinesCount >= mpLines->size())
|
|
|
|
{
|
|
|
|
mnLinesCount = 0;
|
2013-12-27 22:40:14 -05:00
|
|
|
if (mxReaderThread->isTerminateRequested())
|
2013-12-30 12:16:35 -05:00
|
|
|
return Line();
|
2013-12-27 22:40:14 -05:00
|
|
|
|
2013-12-27 23:22:54 -05:00
|
|
|
osl::ResettableMutexGuard aGuard(mxReaderThread->getLinesMutex());
|
2013-11-20 17:09:41 +01:00
|
|
|
if (mpLines)
|
2013-12-27 23:22:54 -05:00
|
|
|
mxReaderThread->pushUsedLines(mpLines);
|
2013-12-27 22:40:14 -05:00
|
|
|
|
2013-12-27 23:22:54 -05:00
|
|
|
while (!mxReaderThread->hasNewLines())
|
2013-11-20 17:09:41 +01:00
|
|
|
{
|
|
|
|
aGuard.clear(); // unlock
|
2013-12-27 23:22:54 -05:00
|
|
|
mxReaderThread->waitForNewLines();
|
2013-11-20 17:09:41 +01:00
|
|
|
aGuard.reset(); // lock
|
|
|
|
}
|
2013-12-27 22:40:14 -05:00
|
|
|
|
2013-12-27 23:22:54 -05:00
|
|
|
mpLines = mxReaderThread->popNewLines();
|
|
|
|
mxReaderThread->resumeReadStream();
|
2013-11-20 17:09:41 +01:00
|
|
|
}
|
|
|
|
return mpLines->at(mnLinesCount++);
|
2013-11-08 22:15:36 +01:00
|
|
|
}
|
|
|
|
|
2013-12-17 16:11:52 -05:00
|
|
|
ScRange DataStream::GetRange() const
|
|
|
|
{
|
|
|
|
ScRange aRange = maStartRange;
|
2013-12-19 01:20:13 -05:00
|
|
|
aRange.aEnd = maEndRange.aEnd;
|
2013-12-17 16:11:52 -05:00
|
|
|
return aRange;
|
|
|
|
}
|
|
|
|
|
2013-12-17 14:09:25 -05:00
|
|
|
void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
|
2013-12-17 22:38:37 -05:00
|
|
|
sal_Int32 nLimit, MoveType eMove, const sal_uInt32 nSettings)
|
2013-11-21 15:23:09 +01:00
|
|
|
{
|
2013-11-22 16:14:11 +01:00
|
|
|
msURL = rURL;
|
|
|
|
mnLimit = nLimit;
|
2013-12-17 22:38:37 -05:00
|
|
|
meMove = eMove;
|
2013-12-19 10:31:41 -05:00
|
|
|
meOrigMove = eMove;
|
2013-11-22 16:14:11 +01:00
|
|
|
mnSettings = nSettings;
|
2013-11-25 12:01:57 +01:00
|
|
|
|
2013-12-19 15:17:49 -05:00
|
|
|
mbValuesInLine = true; // always true.
|
2013-11-21 15:23:09 +01:00
|
|
|
|
2013-12-17 16:11:52 -05:00
|
|
|
mnCurRow = rRange.aStart.Row();
|
|
|
|
|
|
|
|
ScRange aRange = rRange;
|
|
|
|
if (aRange.aStart.Row() != aRange.aEnd.Row())
|
2013-12-17 14:09:25 -05:00
|
|
|
// We only allow this range to be one row tall.
|
2013-12-17 16:11:52 -05:00
|
|
|
aRange.aEnd.SetRow(aRange.aStart.Row());
|
2013-12-17 14:09:25 -05:00
|
|
|
|
2013-12-17 16:11:52 -05:00
|
|
|
maStartRange = aRange;
|
2013-12-19 01:20:13 -05:00
|
|
|
maEndRange = aRange;
|
|
|
|
if (nLimit == 0)
|
|
|
|
{
|
|
|
|
// Unlimited
|
|
|
|
maEndRange.aStart.SetRow(MAXROW);
|
|
|
|
}
|
|
|
|
else if (nLimit > 0)
|
2013-11-25 12:01:57 +01:00
|
|
|
{
|
2013-12-19 01:20:13 -05:00
|
|
|
// Limited.
|
|
|
|
maEndRange.aStart.IncRow(nLimit-1);
|
|
|
|
if (maEndRange.aStart.Row() > MAXROW)
|
|
|
|
maEndRange.aStart.SetRow(MAXROW);
|
2013-11-25 12:01:57 +01:00
|
|
|
}
|
2013-12-19 01:20:13 -05:00
|
|
|
|
|
|
|
maEndRange.aEnd.SetRow(maEndRange.aStart.Row());
|
2013-11-21 15:23:09 +01:00
|
|
|
}
|
|
|
|
|
2013-11-27 12:42:59 +01:00
|
|
|
void DataStream::StartImport()
|
2013-11-08 22:15:36 +01:00
|
|
|
{
|
2013-11-12 19:58:29 +01:00
|
|
|
if (mbRunning)
|
|
|
|
return;
|
2013-12-17 21:18:46 -05:00
|
|
|
|
2013-11-27 15:48:32 +01:00
|
|
|
if (!mxReaderThread.is())
|
|
|
|
{
|
|
|
|
SvStream *pStream = 0;
|
|
|
|
if (mnSettings & SCRIPT_STREAM)
|
|
|
|
pStream = new SvScriptStream(msURL);
|
|
|
|
else
|
|
|
|
pStream = new SvFileStream(msURL, STREAM_READ);
|
2013-12-30 12:16:35 -05:00
|
|
|
mxReaderThread = new datastreams::ReaderThread(pStream, maStartRange.aEnd.Col() - maStartRange.aStart.Col() + 1);
|
2013-11-27 15:48:32 +01:00
|
|
|
mxReaderThread->launch();
|
|
|
|
}
|
2013-11-08 22:15:36 +01:00
|
|
|
mbRunning = true;
|
2013-12-17 21:18:46 -05:00
|
|
|
maDocAccess.reset();
|
2013-12-30 15:43:21 -05:00
|
|
|
|
|
|
|
maImportTimer.Start();
|
2013-11-08 22:15:36 +01:00
|
|
|
}
|
|
|
|
|
2013-11-27 12:42:59 +01:00
|
|
|
void DataStream::StopImport()
|
2013-11-08 22:15:36 +01:00
|
|
|
{
|
2013-11-12 19:58:29 +01:00
|
|
|
if (!mbRunning)
|
|
|
|
return;
|
2013-12-17 21:18:46 -05:00
|
|
|
|
2013-11-08 22:15:36 +01:00
|
|
|
mbRunning = false;
|
2013-12-18 14:15:29 -05:00
|
|
|
Refresh();
|
2013-12-30 15:43:21 -05:00
|
|
|
maImportTimer.Stop();
|
2013-12-12 16:09:11 +01:00
|
|
|
}
|
|
|
|
|
2013-12-18 16:19:05 -05:00
|
|
|
void DataStream::SetRefreshOnEmptyLine( bool bVal )
|
|
|
|
{
|
|
|
|
mbRefreshOnEmptyLine = bVal;
|
|
|
|
}
|
|
|
|
|
2013-12-18 14:15:29 -05:00
|
|
|
void DataStream::Refresh()
|
2013-12-12 16:09:11 +01:00
|
|
|
{
|
2013-12-20 12:56:17 -05:00
|
|
|
Application::Yield();
|
2013-12-20 15:29:45 -05:00
|
|
|
|
2013-12-28 22:45:00 +00:00
|
|
|
double fStart = getNow();
|
|
|
|
|
2013-12-20 15:29:45 -05:00
|
|
|
// Hard recalc will repaint the grid area.
|
2013-12-18 14:15:29 -05:00
|
|
|
mpDocShell->DoHardRecalc(true);
|
2013-12-18 16:40:36 -05:00
|
|
|
mpDocShell->SetDocumentModified(true);
|
2013-12-18 14:55:17 -05:00
|
|
|
|
2013-12-28 22:45:00 +00:00
|
|
|
fTimes[ DEBUG_TIME_RECALC ] = getNow() - fStart;
|
|
|
|
|
2013-12-18 14:55:17 -05:00
|
|
|
mfLastRefreshTime = getNow();
|
|
|
|
mnLinesSinceRefresh = 0;
|
2013-11-08 22:15:36 +01:00
|
|
|
}
|
|
|
|
|
2013-11-21 15:23:09 +01:00
|
|
|
void DataStream::MoveData()
|
2013-11-08 22:15:36 +01:00
|
|
|
{
|
2013-11-11 22:26:54 +01:00
|
|
|
switch (meMove)
|
2013-11-08 22:15:36 +01:00
|
|
|
{
|
2013-11-11 22:26:54 +01:00
|
|
|
case RANGE_DOWN:
|
2013-12-17 21:18:46 -05:00
|
|
|
{
|
2013-12-19 01:20:13 -05:00
|
|
|
if (mnCurRow == maEndRange.aStart.Row())
|
2013-11-11 22:26:54 +01:00
|
|
|
meMove = MOVE_UP;
|
2013-12-17 21:18:46 -05:00
|
|
|
}
|
|
|
|
break;
|
2013-11-11 22:26:54 +01:00
|
|
|
case MOVE_UP:
|
2013-12-17 21:18:46 -05:00
|
|
|
{
|
2013-12-17 15:14:08 -05:00
|
|
|
// Remove the top row and shift the remaining rows upward. Then
|
|
|
|
// insert a new row at the end row position.
|
2013-12-17 21:18:46 -05:00
|
|
|
ScRange aRange = maStartRange;
|
2013-12-19 01:20:13 -05:00
|
|
|
aRange.aEnd = maEndRange.aEnd;
|
2013-12-17 21:18:46 -05:00
|
|
|
maDocAccess.shiftRangeUp(aRange);
|
|
|
|
}
|
|
|
|
break;
|
2013-11-11 22:26:54 +01:00
|
|
|
case MOVE_DOWN:
|
2013-12-17 21:18:46 -05:00
|
|
|
{
|
2013-12-17 15:14:08 -05:00
|
|
|
// Remove the end row and shift the remaining rows downward by
|
|
|
|
// inserting a new row at the top row.
|
2013-12-17 21:18:46 -05:00
|
|
|
ScRange aRange = maStartRange;
|
2013-12-19 01:20:13 -05:00
|
|
|
aRange.aEnd = maEndRange.aEnd;
|
2013-12-17 21:18:46 -05:00
|
|
|
maDocAccess.shiftRangeDown(aRange);
|
|
|
|
}
|
|
|
|
break;
|
2013-11-11 22:26:54 +01:00
|
|
|
case NO_MOVE:
|
2013-12-17 21:18:46 -05:00
|
|
|
default:
|
|
|
|
;
|
2013-11-08 22:15:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-17 21:18:46 -05:00
|
|
|
#if ENABLE_ORCUS
|
|
|
|
|
2013-11-27 18:00:42 +01:00
|
|
|
void DataStream::Text2Doc()
|
|
|
|
{
|
2013-12-30 12:16:35 -05:00
|
|
|
Line aLine = ConsumeLine();
|
|
|
|
if (aLine.maCells.empty() && mbRefreshOnEmptyLine)
|
2013-12-18 16:19:05 -05:00
|
|
|
{
|
|
|
|
// Empty line detected. Trigger refresh and discard it.
|
|
|
|
Refresh();
|
|
|
|
return;
|
|
|
|
}
|
2013-12-12 14:46:34 +01:00
|
|
|
|
2013-12-28 22:45:00 +00:00
|
|
|
double fStart = getNow();
|
|
|
|
|
2013-11-11 22:26:54 +01:00
|
|
|
MoveData();
|
2013-11-19 13:57:58 +01:00
|
|
|
{
|
2013-12-30 12:16:35 -05:00
|
|
|
std::vector<Cell>::const_iterator it = aLine.maCells.begin(), itEnd = aLine.maCells.end();
|
|
|
|
SCCOL nCol = maStartRange.aStart.Col();
|
|
|
|
const char* pLineHead = aLine.maLine.getStr();
|
|
|
|
for (; it != itEnd; ++it, ++nCol)
|
|
|
|
{
|
|
|
|
const Cell& rCell = *it;
|
|
|
|
if (rCell.mbValue)
|
|
|
|
{
|
|
|
|
maDocAccess.setNumericCell(
|
|
|
|
ScAddress(nCol, mnCurRow, maStartRange.aStart.Tab()), rCell.mfValue);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
maDocAccess.setStringCell(
|
|
|
|
ScAddress(nCol, mnCurRow, maStartRange.aStart.Tab()),
|
|
|
|
OUString(pLineHead+rCell.maStr.Pos, rCell.maStr.Size, RTL_TEXTENCODING_UTF8));
|
|
|
|
}
|
|
|
|
}
|
2013-11-19 13:57:58 +01:00
|
|
|
}
|
2013-12-17 21:18:46 -05:00
|
|
|
|
2013-12-28 22:45:00 +00:00
|
|
|
fTimes[ DEBUG_TIME_IMPORT ] = getNow() - fStart;
|
|
|
|
|
2013-11-11 22:26:54 +01:00
|
|
|
if (meMove == NO_MOVE)
|
2013-12-18 16:19:05 -05:00
|
|
|
return;
|
2013-11-08 22:15:36 +01:00
|
|
|
|
2013-11-11 22:26:54 +01:00
|
|
|
if (meMove == RANGE_DOWN)
|
|
|
|
{
|
2013-12-17 16:11:52 -05:00
|
|
|
++mnCurRow;
|
2014-06-18 12:14:29 +02:00
|
|
|
// mpDocShell->GetViewData().GetView()->AlignToCursor(
|
2013-12-17 21:51:43 -05:00
|
|
|
// maStartRange.aStart.Col(), mnCurRow, SC_FOLLOW_JUMP);
|
2013-11-11 22:26:54 +01:00
|
|
|
}
|
2013-12-12 16:09:11 +01:00
|
|
|
|
2013-12-18 14:55:17 -05:00
|
|
|
if (getNow() - mfLastRefreshTime > 0.1 && mnLinesSinceRefresh > 200)
|
|
|
|
// Refresh no more frequently than every 0.1 second, and wait until at
|
|
|
|
// least we have processed 200 lines.
|
2013-12-18 14:15:29 -05:00
|
|
|
Refresh();
|
2013-11-08 22:15:36 +01:00
|
|
|
|
2013-12-18 16:19:05 -05:00
|
|
|
++mnLinesSinceRefresh;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
void DataStream::Text2Doc() {}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
bool DataStream::ImportData()
|
|
|
|
{
|
|
|
|
if (!mbValuesInLine)
|
|
|
|
// We no longer support this mode. To be deleted later.
|
|
|
|
return false;
|
|
|
|
|
2013-12-20 15:29:45 -05:00
|
|
|
if (ScDocShell::GetViewData()->GetViewShell()->NeedsRepaint())
|
|
|
|
return mbRunning;
|
|
|
|
|
2013-12-18 16:19:05 -05:00
|
|
|
Text2Doc();
|
2013-11-08 22:15:36 +01:00
|
|
|
return mbRunning;
|
|
|
|
}
|
|
|
|
|
2013-12-30 15:43:21 -05:00
|
|
|
IMPL_LINK_NOARG(DataStream, ImportTimerHdl)
|
|
|
|
{
|
|
|
|
if (ImportData())
|
|
|
|
maImportTimer.Start();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-12-17 10:19:57 -05:00
|
|
|
} // namespace sc
|
|
|
|
|
2013-11-08 22:15:36 +01:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|