From 47bc56725a37834888680986844b5d7630a6581d Mon Sep 17 00:00:00 2001 From: Matúš Kukan Date: Thu, 21 Nov 2013 15:23:09 +0100 Subject: Rework data streams to be more like file links (ScAreaLink). By inheriting from sfx2::SvBaseLink and storing in sfx2::LinkManager we can have more data streams and see / remove them in Edit -> Links... dialog. Also rename to DataStream to avoid confusion. Change-Id: I9c3b89020324af7be082f9e6e1cd479aeb72fe81 --- sc/source/ui/docshell/datastream.cxx | 368 +++++++++++++++++++++++++++++++ sc/source/ui/inc/cellsh.hxx | 3 - sc/source/ui/inc/datastream.hxx | 68 ++++++ sc/source/ui/inc/datastreamdlg.hxx | 49 ++++ sc/source/ui/inc/datastreams.hxx | 62 ------ sc/source/ui/miscdlgs/datastreamdlg.cxx | 98 ++++++++ sc/source/ui/miscdlgs/datastreams.cxx | 339 ---------------------------- sc/source/ui/miscdlgs/datastreamsdlg.cxx | 135 ------------ sc/source/ui/view/cellsh.cxx | 2 - sc/source/ui/view/cellsh2.cxx | 36 ++- 10 files changed, 611 insertions(+), 549 deletions(-) create mode 100644 sc/source/ui/docshell/datastream.cxx create mode 100644 sc/source/ui/inc/datastream.hxx create mode 100644 sc/source/ui/inc/datastreamdlg.hxx delete mode 100644 sc/source/ui/inc/datastreams.hxx create mode 100644 sc/source/ui/miscdlgs/datastreamdlg.cxx delete mode 100644 sc/source/ui/miscdlgs/datastreams.cxx delete mode 100644 sc/source/ui/miscdlgs/datastreamsdlg.cxx (limited to 'sc/source') diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx new file mode 100644 index 000000000000..d58c72c29b51 --- /dev/null +++ b/sc/source/ui/docshell/datastream.cxx @@ -0,0 +1,368 @@ +/* -*- 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/. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace datastreams { + +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); + }; + } +}; + +class ReaderThread : public salhelper::Thread +{ + SvStream *mpStream; +public: + bool mbTerminateReading; + osl::Condition maProduceResume; + osl::Condition maConsumeResume; + osl::Mutex maLinesProtector; + std::queue maPendingLines; + std::queue 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(); + } + } + + void endThread() + { + 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; + } + } +}; + +} + +static void lcl_MakeToolbarVisible(SfxViewFrame *pViewFrame) +{ + css::uno::Reference< css::frame::XFrame > xFrame = + pViewFrame->GetFrame().GetFrameInterface(); + 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 ); + } +} + +void DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUString& rRange, sal_Int32 nLimit, const OUString& rMove) +{ + sfx2::SvBaseLink *pLink = 0; + pLink = new DataStream( pShell, rURL, rRange, nLimit, rMove ); + sfx2::LinkManager* pLinkManager = pShell->GetDocument()->GetLinkManager(); + pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rURL, NULL, NULL ); + + lcl_MakeToolbarVisible(pShell->GetViewData()->GetViewShell()->GetViewFrame()); +} + +DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, + const OUString& rRange, sal_Int32 nLimit, const OUString& rMove) + : mpScDocShell(pShell) + , mpScDocument(mpScDocShell->GetDocument()) + , meMove(NO_MOVE) + , mbRunning(false) + , mpLines(0) + , mnLinesCount(0) + , mpRange(new ScRange()) + , mpEndRange(NULL) +{ + mxThread = new datastreams::CallerThread( this ); + mxThread->launch(); + + Decode(rURL, rRange, rMove); + + mpStartRange.reset( new ScRange(*mpRange.get()) ); + sal_Int32 nHeight = mpRange->aEnd.Row() - mpRange->aStart.Row() + 1; + nLimit = nHeight * (nLimit / nHeight); + if (nLimit && mpRange->aStart.Row() + nLimit - 1 < MAXROW) + { + mpEndRange.reset( new ScRange(*mpRange) ); + mpEndRange->Move(0, nLimit - nHeight, 0); + } +} + +DataStream::~DataStream() +{ + if (mbRunning) + Stop(); + mxThread->mbTerminate = true; + mxThread->maStart.set(); + mxThread->join(); + if (mxReaderThread.is()) + mxReaderThread->endThread(); +} + +OString DataStream::ConsumeLine() +{ + if (!mpLines || mnLinesCount >= mpLines->size()) + { + mnLinesCount = 0; + 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++); +} + +void DataStream::Decode( const OUString& rURL, const OUString& rRange, const OUString& rMove) +{ + sal_Int32 nIndex = rURL.indexOf(sfx2::cTokenSeparator); + SvStream *pStream = 0; + if (nIndex != -1) + pStream = new SvScriptStream(rURL.copy(0, nIndex)); + else + pStream = new SvFileStream(rURL, STREAM_READ); + mxReaderThread = new datastreams::ReaderThread( pStream ); + mxReaderThread->launch(); + + mbValuesInLine = !rRange.isEmpty(); + if (!mbValuesInLine) + return; + + mpRange->Parse(rRange, mpScDocument); + + if (rMove == "NO_MOVE") + meMove = NO_MOVE; + else if (rMove == "RANGE_DOWN") + meMove = RANGE_DOWN; + else if (rMove == "MOVE_DOWN") + meMove = MOVE_DOWN; +} + +void DataStream::Start() +{ + if (mbRunning) + return; + mbIsUndoEnabled = mpScDocument->IsUndoEnabled(); + mpScDocument->EnableUndo(false); + mbRunning = true; + mxThread->maStart.set(); +} + +void DataStream::Stop() +{ + if (!mbRunning) + return; + mbRunning = false; + mpScDocument->EnableUndo(mbIsUndoEnabled); +} + +void DataStream::MoveData() +{ + switch (meMove) + { + case RANGE_DOWN: + if (mpRange->aStart == mpEndRange->aStart) + meMove = MOVE_UP; + break; + case MOVE_UP: + mpScDocument->DeleteRow(*mpStartRange); + mpScDocument->InsertRow(*mpEndRange); + break; + case MOVE_DOWN: + if (mpEndRange.get()) + mpScDocument->DeleteRow(*mpEndRange); + mpScDocument->InsertRow(*mpRange); + break; + case NO_MOVE: + break; + } +} + +bool DataStream::ImportData() +{ + SolarMutexGuard aGuard; + MoveData(); + if (mbValuesInLine) + { + SCROW nHeight = mpRange->aEnd.Row() - mpRange->aStart.Row() + 1; + OStringBuffer aBuf; + while (nHeight--) + { + aBuf.append(ConsumeLine()); + aBuf.append('\n'); + } + SvMemoryStream aMemoryStream((void *)aBuf.getStr(), aBuf.getLength(), STREAM_READ); + ScImportExport aImport(mpScDocument, *mpRange); + aImport.SetSeparator(','); + aImport.ImportStream(aMemoryStream, OUString(), FORMAT_STRING); + } + else + { + ScRangeList aRangeList; + ScDocumentImport aDocImport(*mpScDocument); + // read more lines at once but not too much + for (int i = 0; i < 10; ++i) + { + OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) ); + if (sLine.indexOf(',') <= 0) + continue; + + OUString sAddress( sLine.copy(0, sLine.indexOf(',')) ); + OUString sValue( sLine.copy(sLine.indexOf(',') + 1) ); + ScAddress aAddress; + aAddress.Parse(sAddress, mpScDocument); + if (!aAddress.IsValid()) + continue; + + if (sValue == "0" || ( sValue.indexOf(':') == -1 && sValue.toDouble() )) + aDocImport.setNumericCell(aAddress, sValue.toDouble()); + else + aDocImport.setStringCell(aAddress, sValue); + aRangeList.Join(aAddress); + } + aDocImport.finalize(); + mpScDocShell->PostPaint( aRangeList, PAINT_GRID ); + } + // ImportStream calls PostPaint for relevant area, + // we need to call it explicitly only when moving rows. + if (meMove == NO_MOVE) + return mbRunning; + + if (meMove == RANGE_DOWN) + { + mpRange->Move(0, mpRange->aEnd.Row() - mpRange->aStart.Row() + 1, 0); + mpScDocShell->GetViewData()->GetView()->AlignToCursor( + mpRange->aStart.Col(), mpRange->aStart.Row(), SC_FOLLOW_JUMP); + } + SCROW aEndRow = mpEndRange.get() ? mpEndRange->aEnd.Row() : MAXROW; + mpScDocShell->PostPaint( ScRange( mpStartRange->aStart, ScAddress( mpRange->aEnd.Col(), + aEndRow, mpRange->aStart.Tab()) ), PAINT_GRID ); + + return mbRunning; +} + +void DataStream::Edit(Window* , const Link& ) +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/cellsh.hxx b/sc/source/ui/inc/cellsh.hxx index d7be8ac993d7..b44eb9f25904 100644 --- a/sc/source/ui/inc/cellsh.hxx +++ b/sc/source/ui/inc/cellsh.hxx @@ -33,19 +33,16 @@ class SvxClipboardFmtItem; class TransferableDataHelper; class TransferableClipboardListener; class AbstractScLinkedAreaDlg; -class DataStreams; struct CellShell_Impl { TransferableClipboardListener* m_pClipEvtLstnr; AbstractScLinkedAreaDlg* m_pLinkedDlg; - DataStreams* m_pDataStreams; SfxRequest* m_pRequest; CellShell_Impl() : m_pClipEvtLstnr( NULL ), m_pLinkedDlg( NULL ), - m_pDataStreams( NULL ), m_pRequest( NULL ) {} }; diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx new file mode 100644 index 000000000000..6da62c9cd41e --- /dev/null +++ b/sc/source/ui/inc/datastream.hxx @@ -0,0 +1,68 @@ +/* -*- 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/. + */ + +#include + +#include +#include +#include + +#include +#include +#include + +namespace datastreams { + class CallerThread; + class ReaderThread; +} +class ScDocShell; +class ScDocument; +class ScRange; +class Window; + +typedef std::vector LinesList; + +class DataStream : boost::noncopyable, public sfx2::SvBaseLink +{ + OString ConsumeLine(); + void Decode(const OUString& rURL, const OUString& rRange, const OUString& rMove); + void MoveData(); + +public: + enum MoveEnum { NO_MOVE, RANGE_DOWN, MOVE_DOWN, MOVE_UP }; + + static void Set(ScDocShell *pShell, const OUString& rURL, + const OUString& rRange, sal_Int32 nLimit, const OUString& rMove); + + DataStream(ScDocShell *pShell, const OUString& rURL, + const OUString& rRange, sal_Int32 nLimit, const OUString& rMove); + virtual ~DataStream() SAL_OVERRIDE; + virtual void Edit(Window* , const Link& ) SAL_OVERRIDE; + + bool ImportData(); + void Start(); + void Stop(); + +private: + ScDocShell *mpScDocShell; + ScDocument *mpScDocument; + MoveEnum meMove; + bool mbRunning; + bool mbIsUndoEnabled; + bool mbValuesInLine; + LinesList *mpLines; + size_t mnLinesCount; + boost::scoped_ptr mpRange; + boost::scoped_ptr mpStartRange; + boost::scoped_ptr mpEndRange; + rtl::Reference mxThread; + rtl::Reference mxReaderThread; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/datastreamdlg.hxx b/sc/source/ui/inc/datastreamdlg.hxx new file mode 100644 index 000000000000..cb469d78600c --- /dev/null +++ b/sc/source/ui/inc/datastreamdlg.hxx @@ -0,0 +1,49 @@ +/* -*- 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/. + */ + +#include + +#include +#include +#include + +class ScDocShell; +class SvtURLBox; + +class DataStreamDlg : public ModalDialog +{ + ScDocShell *mpDocShell; + + SvtURLBox* m_pCbUrl; + PushButton* m_pBtnBrowse; + RadioButton* m_pRBScriptData; + RadioButton* m_pRBValuesInLine; + RadioButton* m_pRBAddressValue; + RadioButton* m_pRBRangeDown; + RadioButton* m_pRBNoMove; + RadioButton* m_pRBMaxLimit; + Edit* m_pEdRange; + Edit* m_pEdLimit; + OKButton* m_pBtnOk; + VclFrame* m_pVclFrameLimit; + VclFrame* m_pVclFrameMove; + VclFrame* m_pVclFrameRange; + + DECL_LINK(UpdateHdl, void *); + DECL_LINK(BrowseHdl, void *); + + void UpdateEnable(); + +public: + DataStreamDlg(ScDocShell *pDocShell, Window* pParent); + ~DataStreamDlg() {} + void StartStream(); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/inc/datastreams.hxx b/sc/source/ui/inc/datastreams.hxx deleted file mode 100644 index 93d157483b23..000000000000 --- a/sc/source/ui/inc/datastreams.hxx +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- 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/. - */ - -#include - -#include -#include - -#include -#include -#include - -namespace datastreams { - class CallerThread; - class ReaderThread; -} -class ScDocShell; -class ScDocument; -class ScRange; -class SvStream; -class Window; - -typedef std::vector LinesList; - -class DataStreams : boost::noncopyable -{ -public: - enum MoveEnum { NO_MOVE, RANGE_DOWN, MOVE_DOWN, MOVE_UP }; - DataStreams(ScDocShell *pScDocShell); - ~DataStreams(); - OString ConsumeLine(); - bool ImportData(); - void MoveData(); - void Set(SvStream *pStream, bool bValuesInLine, - const OUString& rRange, sal_Int32 nLimit, MoveEnum eMove); - void ShowDialog(Window *pParent); - void Start(); - void Stop(); - -private: - ScDocShell *mpScDocShell; - ScDocument *mpScDocument; - MoveEnum meMove; - bool mbRunning; - bool mbIsUndoEnabled; - bool mbValuesInLine; - LinesList *mpLines; - size_t mnLinesCount; - boost::scoped_ptr mpRange; - boost::scoped_ptr mpStartRange; - boost::scoped_ptr mpEndRange; - rtl::Reference mxThread; - rtl::Reference mxReaderThread; -}; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx new file mode 100644 index 000000000000..cd2d2c4f5666 --- /dev/null +++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx @@ -0,0 +1,98 @@ +/* -*- 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/. + */ + +#include + +#include +#include +#include +#include +#include + +DataStreamDlg::DataStreamDlg(ScDocShell *pDocShell, Window* pParent) + : ModalDialog(pParent, "DataStreamDialog", "modules/scalc/ui/datastreams.ui") + , mpDocShell(pDocShell) +{ + get(m_pCbUrl, "url"); + get(m_pBtnBrowse, "browse"); + get(m_pRBScriptData, "scriptdata"); + get(m_pRBValuesInLine, "valuesinline"); + get(m_pRBAddressValue, "addressvalue"); + get(m_pRBRangeDown, "rangedown"); + get(m_pRBNoMove, "nomove"); + get(m_pRBMaxLimit, "maxlimit"); + get(m_pEdRange, "range"); + get(m_pEdLimit, "limit"); + get(m_pBtnOk, "ok"); + get(m_pVclFrameLimit, "framelimit"); + get(m_pVclFrameMove, "framemove"); + get(m_pVclFrameRange, "framerange"); + + m_pCbUrl->SetSelectHdl( LINK( this, DataStreamDlg, UpdateHdl ) ); + m_pRBAddressValue->SetClickHdl( LINK( this, DataStreamDlg, UpdateHdl ) ); + m_pRBValuesInLine->SetClickHdl( LINK( this, DataStreamDlg, UpdateHdl ) ); + m_pEdRange->SetModifyHdl( LINK( this, DataStreamDlg, UpdateHdl ) ); + m_pBtnBrowse->SetClickHdl( LINK( this, DataStreamDlg, BrowseHdl ) ); + UpdateEnable(); +} + +IMPL_LINK_NOARG(DataStreamDlg, BrowseHdl) +{ + sfx2::FileDialogHelper aFileDialog(0, 0); + if ( aFileDialog.Execute() != ERRCODE_NONE ) + return 0; + + m_pCbUrl->SetText( aFileDialog.GetPath() ); + UpdateEnable(); + return 0; +} + +IMPL_LINK_NOARG(DataStreamDlg, UpdateHdl) +{ + UpdateEnable(); + return 0; +} + +void DataStreamDlg::UpdateEnable() +{ + bool bOk = !m_pCbUrl->GetURL().isEmpty(); + if (m_pRBAddressValue->IsChecked()) + { + m_pVclFrameLimit->Hide(); + m_pVclFrameMove->Hide(); + m_pVclFrameRange->Hide(); + } + else + { + m_pVclFrameLimit->Show(true); + m_pVclFrameMove->Show(); + m_pVclFrameRange->Show(); + bOk = bOk && !m_pEdRange->GetText().isEmpty(); + } + m_pBtnOk->Enable(bOk); +} + +void DataStreamDlg::StartStream() +{ + sal_Int32 nLimit = 0; + if (m_pRBMaxLimit->IsChecked()) + nLimit = m_pEdLimit->GetText().toInt32(); + OUString rURL = m_pCbUrl->GetText(); + if (m_pRBScriptData->IsChecked()) + rURL += OUString(sfx2::cTokenSeparator); + DataStream::Set( mpDocShell, + rURL, + m_pEdRange->GetText(), + nLimit, + m_pRBNoMove->IsChecked() ? OUString("NO_MOVE") : m_pRBRangeDown->IsChecked() + ? OUString("RANGE_DOWN") : OUString("MOVE_DOWN") + ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/miscdlgs/datastreams.cxx b/sc/source/ui/miscdlgs/datastreams.cxx deleted file mode 100644 index 59d3b39d6099..000000000000 --- a/sc/source/ui/miscdlgs/datastreams.cxx +++ /dev/null @@ -1,339 +0,0 @@ -/* -*- 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/. - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace datastreams { - -class CallerThread : public salhelper::Thread -{ - DataStreams *mpDataStreams; -public: - osl::Condition maStart; - bool mbTerminate; - - CallerThread(DataStreams *pData): - Thread("CallerThread") - ,mpDataStreams(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 (mpDataStreams->ImportData()) - wait(aTime); - }; - } -}; - -class ReaderThread : public salhelper::Thread -{ - SvStream *mpStream; -public: - bool mbTerminateReading; - osl::Condition maProduceResume; - osl::Condition maConsumeResume; - osl::Mutex maLinesProtector; - std::queue maPendingLines; - std::queue 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(); - } - } - - void endThread() - { - 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; - } - } -}; - -} - -DataStreams::DataStreams(ScDocShell *pScDocShell): - mpScDocShell(pScDocShell) - , mpScDocument(mpScDocShell->GetDocument()) - , meMove(NO_MOVE) - , mbRunning(false) - , mpLines(0) - , mnLinesCount(0) -{ - mxThread = new datastreams::CallerThread( this ); - mxThread->launch(); -} - -DataStreams::~DataStreams() -{ - if (mbRunning) - Stop(); - mxThread->mbTerminate = true; - mxThread->maStart.set(); - mxThread->join(); - if (mxReaderThread.is()) - mxReaderThread->endThread(); -} - -OString DataStreams::ConsumeLine() -{ - if (!mpLines || mnLinesCount >= mpLines->size()) - { - mnLinesCount = 0; - 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++); -} - -void DataStreams::Start() -{ - if (mbRunning) - return; - mbIsUndoEnabled = mpScDocument->IsUndoEnabled(); - mpScDocument->EnableUndo(false); - mbRunning = true; - mxThread->maStart.set(); - css::uno::Reference< css::frame::XFrame > xFrame = - mpScDocShell->GetViewData()->GetViewShell()->GetViewFrame()->GetFrame().GetFrameInterface(); - 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 ); - } -} - -void DataStreams::Stop() -{ - if (!mbRunning) - return; - mbRunning = false; - mpScDocument->EnableUndo(mbIsUndoEnabled); -} - -void DataStreams::Set(SvStream *pStream, bool bValuesInLine, - const OUString& rRange, sal_Int32 nLimit, MoveEnum eMove) -{ - if (mxReaderThread.is()) - mxReaderThread->endThread(); - mxReaderThread = new datastreams::ReaderThread( pStream ); - mxReaderThread->launch(); - - mpEndRange.reset( NULL ); - mpRange.reset ( new ScRange() ); - mbValuesInLine = bValuesInLine; - if (!mbValuesInLine) - { - meMove = NO_MOVE; - return; - } - - mpRange->Parse(rRange, mpScDocument); - mpStartRange.reset( new ScRange(*mpRange.get()) ); - meMove = eMove; - sal_Int32 nHeight = mpRange->aEnd.Row() - mpRange->aStart.Row() + 1; - nLimit = nHeight * (nLimit / nHeight); - if (nLimit && mpRange->aStart.Row() + nLimit - 1 < MAXROW) - { - mpEndRange.reset( new ScRange(*mpRange) ); - mpEndRange->Move(0, nLimit - nHeight, 0); - } -} - -void DataStreams::MoveData() -{ - switch (meMove) - { - case RANGE_DOWN: - if (mpRange->aStart == mpEndRange->aStart) - meMove = MOVE_UP; - break; - case MOVE_UP: - mpScDocument->DeleteRow(*mpStartRange); - mpScDocument->InsertRow(*mpEndRange); - break; - case MOVE_DOWN: - if (mpEndRange.get()) - mpScDocument->DeleteRow(*mpEndRange); - mpScDocument->InsertRow(*mpRange); - break; - case NO_MOVE: - break; - } -} - -bool DataStreams::ImportData() -{ - SolarMutexGuard aGuard; - MoveData(); - if (mbValuesInLine) - { - SCROW nHeight = mpRange->aEnd.Row() - mpRange->aStart.Row() + 1; - OStringBuffer aBuf; - while (nHeight--) - { - aBuf.append(ConsumeLine()); - aBuf.append('\n'); - } - SvMemoryStream aMemoryStream((void *)aBuf.getStr(), aBuf.getLength(), STREAM_READ); - ScImportExport aImport(mpScDocument, *mpRange); - aImport.SetSeparator(','); - aImport.ImportStream(aMemoryStream, OUString(), FORMAT_STRING); - } - else - { - ScRangeList aRangeList; - ScDocumentImport aDocImport(*mpScDocument); - // read more lines at once but not too much - for (int i = 0; i < 10; ++i) - { - OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) ); - if (sLine.indexOf(',') <= 0) - continue; - - OUString sAddress( sLine.copy(0, sLine.indexOf(',')) ); - OUString sValue( sLine.copy(sLine.indexOf(',') + 1) ); - ScAddress aAddress; - aAddress.Parse(sAddress, mpScDocument); - if (!aAddress.IsValid()) - continue; - - if (sValue == "0" || ( sValue.indexOf(':') == -1 && sValue.toDouble() )) - aDocImport.setNumericCell(aAddress, sValue.toDouble()); - else - aDocImport.setStringCell(aAddress, sValue); - aRangeList.Join(aAddress); - } - aDocImport.finalize(); - mpScDocShell->PostPaint( aRangeList, PAINT_GRID ); - } - // ImportStream calls PostPaint for relevant area, - // we need to call it explicitly only when moving rows. - if (meMove == NO_MOVE) - return mbRunning; - - if (meMove == RANGE_DOWN) - { - mpRange->Move(0, mpRange->aEnd.Row() - mpRange->aStart.Row() + 1, 0); - mpScDocShell->GetViewData()->GetView()->AlignToCursor( - mpRange->aStart.Col(), mpRange->aStart.Row(), SC_FOLLOW_JUMP); - } - SCROW aEndRow = mpEndRange.get() ? mpEndRange->aEnd.Row() : MAXROW; - mpScDocShell->PostPaint( ScRange( mpStartRange->aStart, ScAddress( mpRange->aEnd.Col(), - aEndRow, mpRange->aStart.Tab()) ), PAINT_GRID ); - - return mbRunning; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/miscdlgs/datastreamsdlg.cxx b/sc/source/ui/miscdlgs/datastreamsdlg.cxx deleted file mode 100644 index bacb67aeedd6..000000000000 --- a/sc/source/ui/miscdlgs/datastreamsdlg.cxx +++ /dev/null @@ -1,135 +0,0 @@ -/* -*- 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/. - */ - -#include -#include -#include -#include -#include - -namespace { - -class DataStreamsDlg : public ModalDialog -{ - DataStreams *mpDataStreams; - - SvtURLBox* m_pCbUrl; - PushButton* m_pBtnBrowse; - RadioButton* m_pRBScriptData; - RadioButton* m_pRBValuesInLine; - RadioButton* m_pRBAddressValue; - RadioButton* m_pRBRangeDown; - RadioButton* m_pRBNoMove; - RadioButton* m_pRBMaxLimit; - Edit* m_pEdRange; - Edit* m_pEdLimit; - OKButton* m_pBtnOk; - VclFrame* m_pVclFrameLimit; - VclFrame* m_pVclFrameMove; - VclFrame* m_pVclFrameRange; - - DECL_LINK(UpdateHdl, void *); - DECL_LINK(BrowseHdl, void *); - - void UpdateEnable(); - -public: - DataStreamsDlg(DataStreams *pDataStreams, Window* pParent); - ~DataStreamsDlg() {} - void Start(); -}; - -DataStreamsDlg::DataStreamsDlg(DataStreams *pDataStreams, Window* pParent) - : ModalDialog(pParent, "DataStreamsDialog", "modules/scalc/ui/datastreams.ui") - , mpDataStreams(pDataStreams) -{ - get(m_pCbUrl, "url"); - get(m_pBtnBrowse, "browse"); - get(m_pRBScriptData, "scriptdata"); - get(m_pRBValuesInLine, "valuesinline"); - get(m_pRBAddressValue, "addressvalue"); - get(m_pRBRangeDown, "rangedown"); - get(m_pRBNoMove, "nomove"); - get(m_pRBMaxLimit, "maxlimit"); - get(m_pEdRange, "range"); - get(m_pEdLimit, "limit"); - get(m_pBtnOk, "ok"); - get(m_pVclFrameLimit, "framelimit"); - get(m_pVclFrameMove, "framemove"); - get(m_pVclFrameRange, "framerange"); - - m_pCbUrl->SetSelectHdl( LINK( this, DataStreamsDlg, UpdateHdl ) ); - m_pRBAddressValue->SetClickHdl( LINK( this, DataStreamsDlg, UpdateHdl ) ); - m_pRBValuesInLine->SetClickHdl( LINK( this, DataStreamsDlg, UpdateHdl ) ); - m_pEdRange->SetModifyHdl( LINK( this, DataStreamsDlg, UpdateHdl ) ); - m_pBtnBrowse->SetClickHdl( LINK( this, DataStreamsDlg, BrowseHdl ) ); - UpdateEnable(); -} - -void DataStreamsDlg::Start() -{ - sal_Int32 nLimit = 0; - if (m_pRBMaxLimit->IsChecked()) - nLimit = m_pEdLimit->GetText().toInt32(); - mpDataStreams->Set( - (m_pRBScriptData->IsChecked() ? - dynamic_cast( new SvScriptStream(m_pCbUrl->GetText()) ) : - dynamic_cast( new SvFileStream(m_pCbUrl->GetText(), STREAM_READ) )), - m_pRBValuesInLine->IsChecked(), - m_pEdRange->GetText(), nLimit, (m_pRBNoMove->IsChecked() ? DataStreams::NO_MOVE : - m_pRBRangeDown->IsChecked() ? DataStreams::RANGE_DOWN : DataStreams::MOVE_DOWN) ); - mpDataStreams->Start(); -} - -IMPL_LINK_NOARG(DataStreamsDlg, BrowseHdl) -{ - sfx2::FileDialogHelper aFileDialog(0, 0); - if ( aFileDialog.Execute() != ERRCODE_NONE ) - return 0; - - m_pCbUrl->SetText( aFileDialog.GetPath() ); - UpdateEnable(); - return 0; -} - -IMPL_LINK_NOARG(DataStreamsDlg, UpdateHdl) -{ - UpdateEnable(); - return 0; -} - -void DataStreamsDlg::UpdateEnable() -{ - bool bOk = !m_pCbUrl->GetURL().isEmpty(); - if (m_pRBAddressValue->IsChecked()) - { - m_pVclFrameLimit->Hide(); - m_pVclFrameMove->Hide(); - m_pVclFrameRange->Hide(); - } - else - { - m_pVclFrameLimit->Show(true); - m_pVclFrameMove->Show(); - m_pVclFrameRange->Show(); - bOk = bOk && !m_pEdRange->GetText().isEmpty(); - } - m_pBtnOk->Enable(bOk); -} - -} - -void DataStreams::ShowDialog(Window *pParent) -{ - DataStreamsDlg aDialog(this, pParent); - if (aDialog.Execute() == RET_OK) - aDialog.Start(); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx index ec69f05a0c3a..cf9d13b8c313 100644 --- a/sc/source/ui/view/cellsh.cxx +++ b/sc/source/ui/view/cellsh.cxx @@ -55,7 +55,6 @@ #include "postit.hxx" #include "cliputil.hxx" #include "clipparam.hxx" -#include "datastreams.hxx" #include "markdata.hxx" //------------------------------------------------------------------ @@ -99,7 +98,6 @@ ScCellShell::~ScCellShell() } delete pImpl->m_pLinkedDlg; - delete pImpl->m_pDataStreams; delete pImpl->m_pRequest; delete pImpl; } diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx index 4450bd9437f7..aceb41cea89b 100644 --- a/sc/source/ui/view/cellsh2.cxx +++ b/sc/source/ui/view/cellsh2.cxx @@ -20,6 +20,7 @@ #include "scitems.hxx" #include #include +#include #include #include #include @@ -56,7 +57,8 @@ #include "scabstdlg.hxx" #include "impex.hxx" #include "asciiopt.hxx" -#include "datastreams.hxx" +#include "datastream.hxx" +#include "datastreamdlg.hxx" #include "queryentry.hxx" #include "markdata.hxx" @@ -734,17 +736,35 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq ) } break; case SID_DATA_STREAMS: - if (!pImpl->m_pDataStreams) - pImpl->m_pDataStreams = new DataStreams(GetViewData()->GetDocShell()); - pImpl->m_pDataStreams->ShowDialog( pTabViewShell->GetDialogParent() ); + { + DataStreamDlg aDialog( GetViewData()->GetDocShell(), pTabViewShell->GetDialogParent() ); + if (aDialog.Execute() == RET_OK) + aDialog.StartStream(); + } break; case SID_DATA_STREAMS_PLAY: - if (pImpl->m_pDataStreams) - pImpl->m_pDataStreams->Start(); + { + ScDocument *pDoc = GetViewData()->GetDocument(); + if (pDoc->GetLinkManager()) + { + const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks(); + for (size_t i = 0; i < rLinks.size(); i++) + if (DataStream *pStream = dynamic_cast(&(*(*rLinks[i])))) + pStream->Start(); + } + } break; case SID_DATA_STREAMS_STOP: - if (pImpl->m_pDataStreams) - pImpl->m_pDataStreams->Stop(); + { + ScDocument *pDoc = GetViewData()->GetDocument(); + if (pDoc->GetLinkManager()) + { + const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks(); + for (size_t i = 0; i < rLinks.size(); i++) + if (DataStream *pStream = dynamic_cast(&(*(*rLinks[i])))) + pStream->Stop(); + } + } break; case SID_MANAGE_XML_SOURCE: ExecuteXMLSourceDialog(); -- cgit