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>
|
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>
|
|
|
|
#include <rtl/strbuf.hxx>
|
|
|
|
#include <salhelper/thread.hxx>
|
2013-11-21 15:23:09 +01:00
|
|
|
#include <sfx2/linkmgr.hxx>
|
2013-11-18 13:31:39 +01:00
|
|
|
#include <sfx2/viewfrm.hxx>
|
2013-11-22 16:14:11 +01:00
|
|
|
#include <arealink.hxx>
|
2013-11-08 22:15:36 +01:00
|
|
|
#include <asciiopt.hxx>
|
2013-11-25 12:01:57 +01:00
|
|
|
#include <datastreamdlg.hxx>
|
2013-11-18 13:31:39 +01:00
|
|
|
#include <dbfunc.hxx>
|
2013-11-08 22:15:36 +01:00
|
|
|
#include <docsh.hxx>
|
2013-11-19 13:57:58 +01:00
|
|
|
#include <documentimport.hxx>
|
2013-11-08 22:15:36 +01:00
|
|
|
#include <impex.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-11-08 22:15:36 +01:00
|
|
|
|
2013-11-20 17:09:41 +01:00
|
|
|
#include <queue>
|
|
|
|
|
2013-12-17 10:19:57 -05:00
|
|
|
namespace sc {
|
|
|
|
|
2013-11-08 22:15:36 +01:00
|
|
|
namespace datastreams {
|
|
|
|
|
2013-12-12 16:09:11 +01:00
|
|
|
class CallerThread : public salhelper::Thread
|
|
|
|
{
|
|
|
|
DataStream *mpDataStream;
|
|
|
|
public:
|
|
|
|
osl::Condition maStart;
|
|
|
|
bool mbTerminate;
|
|
|
|
|
|
|
|
CallerThread(DataStream *pData):
|
|
|
|
Thread("CallerThread")
|
|
|
|
,mpDataStream(pData)
|
|
|
|
,mbTerminate(false)
|
|
|
|
{}
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual void execute()
|
|
|
|
{
|
|
|
|
while (!mbTerminate)
|
|
|
|
{
|
|
|
|
// wait for a small amount of time, so that
|
|
|
|
// painting methods have a chance to be called.
|
|
|
|
// And also to make UI more responsive.
|
|
|
|
TimeValue const aTime = {0, 100000};
|
|
|
|
maStart.wait();
|
|
|
|
maStart.reset();
|
|
|
|
if (!mbTerminate)
|
|
|
|
while (mpDataStream->ImportData())
|
|
|
|
wait(aTime);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-11-20 17:09:41 +01:00
|
|
|
class ReaderThread : public salhelper::Thread
|
|
|
|
{
|
|
|
|
SvStream *mpStream;
|
|
|
|
public:
|
|
|
|
bool mbTerminateReading;
|
|
|
|
osl::Condition maProduceResume;
|
|
|
|
osl::Condition maConsumeResume;
|
|
|
|
osl::Mutex maLinesProtector;
|
|
|
|
std::queue<LinesList* > maPendingLines;
|
|
|
|
std::queue<LinesList* > maUsedLines;
|
|
|
|
|
|
|
|
ReaderThread(SvStream *pData):
|
|
|
|
Thread("ReaderThread")
|
|
|
|
,mpStream(pData)
|
|
|
|
,mbTerminateReading(false)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ~ReaderThread()
|
|
|
|
{
|
|
|
|
delete mpStream;
|
|
|
|
while (!maPendingLines.empty())
|
|
|
|
{
|
|
|
|
delete maPendingLines.front();
|
|
|
|
maPendingLines.pop();
|
|
|
|
}
|
|
|
|
while (!maUsedLines.empty())
|
|
|
|
{
|
|
|
|
delete maUsedLines.front();
|
|
|
|
maUsedLines.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-20 17:59:15 +01:00
|
|
|
void endThread()
|
2013-11-20 17:09:41 +01:00
|
|
|
{
|
|
|
|
mbTerminateReading = true;
|
|
|
|
maProduceResume.set();
|
|
|
|
join();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual void execute() SAL_OVERRIDE
|
|
|
|
{
|
|
|
|
while (!mbTerminateReading)
|
|
|
|
{
|
|
|
|
LinesList *pLines = 0;
|
|
|
|
osl::ResettableMutexGuard aGuard(maLinesProtector);
|
|
|
|
if (!maUsedLines.empty())
|
|
|
|
{
|
|
|
|
pLines = maUsedLines.front();
|
|
|
|
maUsedLines.pop();
|
|
|
|
aGuard.clear(); // unlock
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
aGuard.clear(); // unlock
|
|
|
|
pLines = new LinesList(10);
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < pLines->size(); ++i)
|
|
|
|
mpStream->ReadLine( pLines->at(i) );
|
|
|
|
aGuard.reset(); // lock
|
|
|
|
while (!mbTerminateReading && maPendingLines.size() >= 8)
|
|
|
|
{ // pause reading for a bit
|
|
|
|
aGuard.clear(); // unlock
|
|
|
|
maProduceResume.wait();
|
|
|
|
maProduceResume.reset();
|
|
|
|
aGuard.reset(); // lock
|
|
|
|
}
|
|
|
|
maPendingLines.push(pLines);
|
|
|
|
maConsumeResume.set();
|
|
|
|
if (!mpStream->good())
|
|
|
|
mbTerminateReading = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-11-08 22:15:36 +01:00
|
|
|
}
|
|
|
|
|
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-11-21 21:20:17 +01:00
|
|
|
DataStream* DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
|
|
|
|
sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings)
|
2013-11-21 15:23:09 +01:00
|
|
|
{
|
2013-11-22 16:14:11 +01:00
|
|
|
// Each DataStream needs a destination area in order to be exported.
|
|
|
|
// There can be only one ScAreaLink / DataStream per cell.
|
|
|
|
// So - if we don't need range (DataStream with mbValuesInLine == false),
|
|
|
|
// just find a free cell for now.
|
|
|
|
ScRange aDestArea;
|
2013-12-17 14:21:07 -05:00
|
|
|
sal_uInt16 nRes = aDestArea.Parse(rRange, pShell->GetDocument());
|
|
|
|
if ((nRes & SCA_VALID) != SCA_VALID)
|
|
|
|
// Invalid range string.
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
sfx2::LinkManager* pLinkManager = pShell->GetDocument()->GetLinkManager();
|
2013-11-22 16:14:11 +01:00
|
|
|
sal_uInt16 nLinkPos = 0;
|
|
|
|
while (nLinkPos < pLinkManager->GetLinks().size())
|
|
|
|
{
|
|
|
|
sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
|
|
|
|
if (rRange.isEmpty())
|
|
|
|
{
|
2013-12-17 16:11:52 -05:00
|
|
|
if ( (pBase->ISA(ScAreaLink) && static_cast<ScAreaLink*>
|
2013-11-22 16:14:11 +01:00
|
|
|
(&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
|
2013-12-17 16:11:52 -05:00
|
|
|
|| (pBase->ISA(DataStream) && static_cast<DataStream*>
|
2013-11-22 16:14:11 +01:00
|
|
|
(&(*pBase))->GetRange().aStart == aDestArea.aStart) )
|
|
|
|
{
|
|
|
|
aDestArea.Move(0, 1, 0);
|
|
|
|
nLinkPos = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
++nLinkPos;
|
|
|
|
}
|
2013-12-17 16:11:52 -05:00
|
|
|
else if ( (pBase->ISA(ScAreaLink) && static_cast<ScAreaLink*>
|
2013-11-22 16:14:11 +01:00
|
|
|
(&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
|
2013-12-17 16:11:52 -05:00
|
|
|
|| (pBase->ISA(DataStream) && static_cast<DataStream*>
|
2013-11-22 16:14:11 +01:00
|
|
|
(&(*pBase))->GetRange().aStart == aDestArea.aStart) )
|
|
|
|
{
|
|
|
|
pLinkManager->Remove( pBase );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
++nLinkPos;
|
|
|
|
}
|
|
|
|
|
2013-12-17 14:21:07 -05:00
|
|
|
DataStream* pLink = new DataStream(pShell, rURL, aDestArea, nLimit, rMove, nSettings);
|
2013-11-21 15:23:09 +01:00
|
|
|
pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rURL, NULL, NULL );
|
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 11:36:18 -05:00
|
|
|
sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings) :
|
|
|
|
mpDocShell(pShell),
|
|
|
|
mpDoc(mpDocShell->GetDocument()),
|
|
|
|
maDocAccess(*mpDoc),
|
|
|
|
meMove(NO_MOVE),
|
|
|
|
mbRunning(false),
|
|
|
|
mpLines(0),
|
|
|
|
mnLinesCount(0),
|
2013-12-17 16:11:52 -05:00
|
|
|
mnRepaintCounter(0),
|
|
|
|
mnCurRow(0)
|
2013-11-08 22:15:36 +01:00
|
|
|
{
|
2013-12-12 16:09:11 +01:00
|
|
|
mxThread = new datastreams::CallerThread( this );
|
|
|
|
mxThread->launch();
|
|
|
|
|
2013-11-22 16:14:11 +01:00
|
|
|
Decode(rURL, rRange, nLimit, rMove, 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-12 16:09:11 +01:00
|
|
|
mxThread->mbTerminate = true;
|
|
|
|
mxThread->maStart.set();
|
|
|
|
mxThread->join();
|
2013-11-20 17:09:41 +01:00
|
|
|
if (mxReaderThread.is())
|
2013-11-20 17:59:15 +01:00
|
|
|
mxReaderThread->endThread();
|
2013-11-28 10:47:15 +01:00
|
|
|
delete mpLines;
|
2013-11-20 17:09:41 +01:00
|
|
|
}
|
|
|
|
|
2013-11-21 15:23:09 +01:00
|
|
|
OString DataStream::ConsumeLine()
|
2013-11-20 17:09:41 +01:00
|
|
|
{
|
|
|
|
if (!mpLines || mnLinesCount >= mpLines->size())
|
|
|
|
{
|
|
|
|
mnLinesCount = 0;
|
2013-11-21 21:20:17 +01:00
|
|
|
if (mxReaderThread->mbTerminateReading)
|
|
|
|
return OString();
|
2013-11-20 17:09:41 +01:00
|
|
|
osl::ResettableMutexGuard aGuard(mxReaderThread->maLinesProtector);
|
|
|
|
if (mpLines)
|
|
|
|
mxReaderThread->maUsedLines.push(mpLines);
|
|
|
|
while (mxReaderThread->maPendingLines.empty())
|
|
|
|
{
|
|
|
|
aGuard.clear(); // unlock
|
|
|
|
mxReaderThread->maConsumeResume.wait();
|
|
|
|
mxReaderThread->maConsumeResume.reset();
|
|
|
|
aGuard.reset(); // lock
|
|
|
|
}
|
|
|
|
mpLines = mxReaderThread->maPendingLines.front();
|
|
|
|
mxReaderThread->maPendingLines.pop();
|
|
|
|
if (mxReaderThread->maPendingLines.size() <= 4)
|
|
|
|
mxReaderThread->maProduceResume.set(); // start producer again
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
if (mpEndRange)
|
|
|
|
aRange.aEnd = mpEndRange->aEnd;
|
|
|
|
return aRange;
|
|
|
|
}
|
|
|
|
|
2013-12-17 14:09:25 -05:00
|
|
|
void DataStream::Decode(const OUString& rURL, const ScRange& rRange,
|
2013-11-25 12:01:57 +01:00
|
|
|
sal_Int32 nLimit, const OUString& rMove, const sal_uInt32 nSettings)
|
2013-11-21 15:23:09 +01:00
|
|
|
{
|
2013-11-22 16:14:11 +01:00
|
|
|
msURL = rURL;
|
|
|
|
mnLimit = nLimit;
|
|
|
|
msMove = rMove;
|
|
|
|
mnSettings = nSettings;
|
2013-11-25 12:01:57 +01:00
|
|
|
mpEndRange.reset( NULL );
|
|
|
|
|
2013-11-22 16:14:11 +01:00
|
|
|
mbValuesInLine = mnSettings & VALUES_IN_LINE;
|
2013-11-21 15:23:09 +01:00
|
|
|
|
2013-11-22 16:14:11 +01:00
|
|
|
if (msMove == "NO_MOVE")
|
2013-11-21 15:23:09 +01:00
|
|
|
meMove = NO_MOVE;
|
2013-11-22 16:14:11 +01:00
|
|
|
else if (msMove == "RANGE_DOWN")
|
2013-11-21 15:23:09 +01:00
|
|
|
meMove = RANGE_DOWN;
|
2013-11-22 16:14:11 +01:00
|
|
|
else if (msMove == "MOVE_DOWN")
|
2013-11-21 15:23:09 +01:00
|
|
|
meMove = MOVE_DOWN;
|
2013-11-25 12:01:57 +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;
|
|
|
|
if (nLimit && aRange.aStart.Row() + nLimit - 1 < MAXROW)
|
2013-11-25 12:01:57 +01:00
|
|
|
{
|
2013-12-17 16:11:52 -05:00
|
|
|
mpEndRange.reset(new ScRange(aRange));
|
2013-12-17 14:09:25 -05:00
|
|
|
mpEndRange->Move(0, nLimit-1, 0);
|
2013-11-25 12:01:57 +01:00
|
|
|
}
|
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-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);
|
|
|
|
mxReaderThread = new datastreams::ReaderThread( pStream );
|
|
|
|
mxReaderThread->launch();
|
|
|
|
}
|
2013-11-08 22:15:36 +01:00
|
|
|
mbRunning = true;
|
2013-12-12 16:09:11 +01:00
|
|
|
mxThread->maStart.set();
|
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-11-08 22:15:36 +01:00
|
|
|
mbRunning = false;
|
2013-12-12 16:09:11 +01:00
|
|
|
Repaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataStream::Repaint()
|
|
|
|
{
|
|
|
|
SCROW nEndRow = mpEndRange ? mpEndRange->aEnd.Row() : MAXROW;
|
|
|
|
ScRange aRange(maStartRange.aStart);
|
2013-12-17 16:11:52 -05:00
|
|
|
aRange.aEnd = ScAddress(maStartRange.aEnd.Col(), nEndRow, maStartRange.aStart.Tab());
|
2013-12-12 16:09:11 +01:00
|
|
|
|
2013-12-17 11:36:18 -05:00
|
|
|
mpDocShell->PostPaint(aRange, PAINT_GRID);
|
2013-12-17 00:05:22 -05:00
|
|
|
mnRepaintCounter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataStream::Broadcast()
|
|
|
|
{
|
2013-12-17 11:36:18 -05:00
|
|
|
mpDoc->BroadcastCells(maBroadcastRanges, SC_HINT_DATACHANGED);
|
2013-12-17 00:05:22 -05:00
|
|
|
maBroadcastRanges.RemoveAll();
|
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-12-17 16:11:52 -05:00
|
|
|
if (!mpEndRange)
|
|
|
|
return;
|
|
|
|
|
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 16:11:52 -05:00
|
|
|
if (mnCurRow == mpEndRange->aStart.Row())
|
2013-11-11 22:26:54 +01:00
|
|
|
meMove = MOVE_UP;
|
|
|
|
break;
|
|
|
|
case MOVE_UP:
|
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 11:36:18 -05:00
|
|
|
mpDoc->DeleteRow(maStartRange);
|
|
|
|
mpDoc->InsertRow(*mpEndRange);
|
2013-11-11 22:26:54 +01:00
|
|
|
break;
|
|
|
|
case MOVE_DOWN:
|
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.
|
|
|
|
mpDoc->DeleteRow(*mpEndRange);
|
|
|
|
mpDoc->InsertRow(maStartRange);
|
2013-11-11 22:26:54 +01:00
|
|
|
break;
|
|
|
|
case NO_MOVE:
|
|
|
|
break;
|
2013-11-08 22:15:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-27 12:42:59 +01:00
|
|
|
IMPL_LINK_NOARG(DataStream, RefreshHdl)
|
|
|
|
{
|
|
|
|
ImportData();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-27 18:00:42 +01:00
|
|
|
// lcl_ScanString and Text2Doc is simplified version
|
|
|
|
// of code from sc/source/ui/docshell/impex.cxx
|
|
|
|
const sal_Unicode* lcl_ScanString( const sal_Unicode* p, OUString& rString, sal_Unicode cStr)
|
|
|
|
{
|
|
|
|
const sal_Unicode* p0 = p;
|
|
|
|
for( ;; )
|
|
|
|
{
|
|
|
|
if (!*p)
|
|
|
|
break;
|
|
|
|
if (*p == cStr)
|
|
|
|
{
|
|
|
|
if (*++p != cStr)
|
|
|
|
break;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
if (p0 < p)
|
|
|
|
if (rString.getLength() + (p - p0) <= STRING_MAXLEN)
|
|
|
|
rString += OUString( p0, sal::static_int_cast<sal_Int32>( p - p0 ) );
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DataStream::Text2Doc()
|
|
|
|
{
|
|
|
|
sal_Unicode cSep(',');
|
|
|
|
sal_Unicode cStr('"');
|
2013-12-17 16:11:52 -05:00
|
|
|
SCCOL nStartCol = maStartRange.aStart.Col();
|
|
|
|
SCCOL nEndCol = maStartRange.aEnd.Col();
|
2013-11-27 18:00:42 +01:00
|
|
|
OUString aCell;
|
2013-12-17 11:36:18 -05:00
|
|
|
ScDocumentImport aDocImport(*mpDoc);
|
2013-12-17 16:11:52 -05:00
|
|
|
|
|
|
|
SCCOL nCol = nStartCol;
|
|
|
|
OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) );
|
|
|
|
const sal_Unicode* p = sLine.getStr();
|
|
|
|
while (*p)
|
2013-11-27 18:00:42 +01:00
|
|
|
{
|
2013-12-17 16:11:52 -05:00
|
|
|
aCell = "";
|
|
|
|
const sal_Unicode* q = p;
|
|
|
|
while (*p && *p != cSep)
|
2013-11-27 18:00:42 +01:00
|
|
|
{
|
2013-12-17 16:11:52 -05:00
|
|
|
// Always look for a pairing quote and ignore separator in between.
|
|
|
|
while (*p && *p == cStr)
|
|
|
|
q = p = lcl_ScanString(p, aCell, cStr);
|
|
|
|
// All until next separator or quote.
|
|
|
|
while (*p && *p != cSep && *p != cStr)
|
2013-11-27 18:00:42 +01:00
|
|
|
++p;
|
2013-12-17 16:11:52 -05:00
|
|
|
if (aCell.getLength() + (p - q) <= STRING_MAXLEN)
|
|
|
|
aCell += OUString( q, sal::static_int_cast<sal_Int32>( p - q ) );
|
|
|
|
q = p;
|
|
|
|
}
|
|
|
|
if (*p)
|
|
|
|
++p;
|
|
|
|
if (nCol <= nEndCol)
|
|
|
|
{
|
|
|
|
ScAddress aAddress(nCol, mnCurRow, maStartRange.aStart.Tab());
|
|
|
|
if (aCell == "0" || ( aCell.indexOf(':') == -1 && aCell.toDouble() ))
|
|
|
|
aDocImport.setNumericCell(aAddress, aCell.toDouble());
|
|
|
|
else
|
|
|
|
aDocImport.setStringCell(aAddress, aCell);
|
2013-11-27 18:00:42 +01:00
|
|
|
}
|
2013-12-17 16:11:52 -05:00
|
|
|
++nCol;
|
2013-11-27 18:00:42 +01:00
|
|
|
}
|
2013-12-17 16:11:52 -05:00
|
|
|
++mnRepaintCounter;
|
2013-12-17 00:05:22 -05:00
|
|
|
|
2013-11-27 18:00:42 +01:00
|
|
|
aDocImport.finalize();
|
2013-12-17 00:05:22 -05:00
|
|
|
|
2013-12-17 16:11:52 -05:00
|
|
|
ScRange aBCRange(nStartCol, mnCurRow, maStartRange.aStart.Tab(), nEndCol, mnCurRow, maStartRange.aStart.Tab());
|
2013-12-17 00:05:22 -05:00
|
|
|
maBroadcastRanges.Join(aBCRange);
|
2013-11-27 18:00:42 +01:00
|
|
|
}
|
|
|
|
|
2013-11-21 15:23:09 +01:00
|
|
|
bool DataStream::ImportData()
|
2013-11-08 22:15:36 +01:00
|
|
|
{
|
2013-12-12 16:09:11 +01:00
|
|
|
SolarMutexGuard aGuard;
|
2013-12-12 14:46:34 +01:00
|
|
|
if (ScDocShell::GetViewData()->GetViewShell()->NeedsRepaint())
|
|
|
|
return mbRunning;
|
|
|
|
|
2013-11-11 22:26:54 +01:00
|
|
|
MoveData();
|
2013-11-19 13:57:58 +01:00
|
|
|
if (mbValuesInLine)
|
|
|
|
{
|
2013-11-27 18:00:42 +01:00
|
|
|
// do CSV import
|
|
|
|
Text2Doc();
|
2013-11-19 13:57:58 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-12-17 11:36:18 -05:00
|
|
|
ScDocumentImport aDocImport(*mpDoc);
|
2013-11-19 13:57:58 +01:00
|
|
|
// read more lines at once but not too much
|
|
|
|
for (int i = 0; i < 10; ++i)
|
|
|
|
{
|
2013-11-20 17:09:41 +01:00
|
|
|
OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) );
|
2013-11-19 13:57:58 +01:00
|
|
|
if (sLine.indexOf(',') <= 0)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
OUString sAddress( sLine.copy(0, sLine.indexOf(',')) );
|
|
|
|
OUString sValue( sLine.copy(sLine.indexOf(',') + 1) );
|
|
|
|
ScAddress aAddress;
|
2013-12-17 11:36:18 -05:00
|
|
|
aAddress.Parse(sAddress, mpDoc);
|
2013-11-19 13:57:58 +01:00
|
|
|
if (!aAddress.IsValid())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (sValue == "0" || ( sValue.indexOf(':') == -1 && sValue.toDouble() ))
|
|
|
|
aDocImport.setNumericCell(aAddress, sValue.toDouble());
|
|
|
|
else
|
|
|
|
aDocImport.setStringCell(aAddress, sValue);
|
2013-12-17 00:05:22 -05:00
|
|
|
maBroadcastRanges.Join(aAddress);
|
2013-11-19 13:57:58 +01:00
|
|
|
}
|
|
|
|
aDocImport.finalize();
|
|
|
|
}
|
2013-12-17 11:36:18 -05:00
|
|
|
mpDocShell->SetDocumentModified();
|
2013-11-11 22:26:54 +01:00
|
|
|
if (meMove == NO_MOVE)
|
2013-11-08 22:15:36 +01:00
|
|
|
return mbRunning;
|
|
|
|
|
2013-11-11 22:26:54 +01:00
|
|
|
if (meMove == RANGE_DOWN)
|
|
|
|
{
|
2013-12-17 16:11:52 -05:00
|
|
|
++mnCurRow;
|
2013-12-17 11:36:18 -05:00
|
|
|
mpDocShell->GetViewData()->GetView()->AlignToCursor(
|
2013-12-17 16:11:52 -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
|
|
|
|
|
|
|
if (mnRepaintCounter > 100)
|
|
|
|
Repaint();
|
2013-11-08 22:15:36 +01:00
|
|
|
|
|
|
|
return mbRunning;
|
|
|
|
}
|
|
|
|
|
2013-11-21 21:20:17 +01:00
|
|
|
sfx2::SvBaseLink::UpdateResult DataStream::DataChanged(
|
|
|
|
const OUString& , const css::uno::Any& )
|
|
|
|
{
|
2013-11-29 16:00:59 +01:00
|
|
|
MakeToolbarVisible();
|
2013-11-27 15:48:32 +01:00
|
|
|
StopImport();
|
|
|
|
bool bStart = true;
|
|
|
|
if (mnSettings & SCRIPT_STREAM && !mxReaderThread.is() &&
|
|
|
|
officecfg::Office::Common::Security::Scripting::MacroSecurityLevel::get() >= 1)
|
|
|
|
{
|
|
|
|
MessageDialog aQBox( NULL, "QueryRunStreamScriptDialog", "modules/scalc/ui/queryrunstreamscriptdialog.ui");
|
|
|
|
aQBox.set_primary_text( aQBox.get_primary_text().replaceFirst("%URL", msURL) );
|
|
|
|
if (RET_YES != aQBox.Execute())
|
|
|
|
bStart = false;
|
|
|
|
}
|
|
|
|
if (bStart)
|
|
|
|
StartImport();
|
2013-11-21 21:20:17 +01:00
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2013-12-17 14:09:25 -05:00
|
|
|
void DataStream::Edit( Window* pWindow, const Link& )
|
2013-11-21 15:23:09 +01:00
|
|
|
{
|
2013-12-17 11:36:18 -05:00
|
|
|
DataStreamDlg aDialog(mpDocShell, pWindow);
|
2013-12-17 14:09:25 -05:00
|
|
|
aDialog.Init(msURL, maStartRange, mnLimit, msMove, mnSettings);
|
2013-11-25 12:01:57 +01:00
|
|
|
if (aDialog.Execute() == RET_OK)
|
|
|
|
{
|
|
|
|
bool bWasRunning = mbRunning;
|
2013-11-27 12:42:59 +01:00
|
|
|
StopImport();
|
2013-11-25 12:01:57 +01:00
|
|
|
aDialog.StartStream(this);
|
|
|
|
if (bWasRunning)
|
2013-11-27 12:42:59 +01:00
|
|
|
StartImport();
|
2013-11-25 12:01:57 +01:00
|
|
|
}
|
2013-11-21 15:23:09 +01:00
|
|
|
}
|
|
|
|
|
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: */
|