[Libreoffice-commits] core.git: Branch 'feature/datastreams' - 6 commits - icon-themes/galaxy sc/Library_sc.mk sc/source sc/uiconfig

Matúš Kukan matus.kukan at collabora.com
Mon Nov 25 14:31:31 PST 2013


Rebased ref, commits from common ancestor:
commit 8adca9722aed0e712c281e25d66c3087e47c696c
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Mon Nov 25 12:01:57 2013 +0100

    Allow to edit data stream from Edit-> Links... dialog.
    
    Change-Id: Ibb456da55f04c39ddb7b58eb71ca488cf209edb5

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 68fb7cc..759a984 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -18,6 +18,7 @@
 #include <sfx2/viewfrm.hxx>
 #include <arealink.hxx>
 #include <asciiopt.hxx>
+#include <datastreamdlg.hxx>
 #include <dbfunc.hxx>
 #include <docsh.hxx>
 #include <documentimport.hxx>
@@ -418,8 +419,18 @@ sfx2::SvBaseLink::UpdateResult DataStream::DataChanged(
     return SUCCESS;
 }
 
-void DataStream::Edit(Window* , const Link& )
+void DataStream::Edit(Window* pWindow, const Link& )
 {
+    DataStreamDlg aDialog(mpScDocShell, pWindow);
+    aDialog.Init(msURL, msRange, mnLimit, msMove, mnSettings);
+    if (aDialog.Execute() == RET_OK)
+    {
+        bool bWasRunning = mbRunning;
+        Stop();
+        aDialog.StartStream(this);
+        if (bWasRunning)
+            Start();
+    }
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 1615735..b3547ca 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -32,8 +32,6 @@ typedef std::vector<OString> LinesList;
 class DataStream : boost::noncopyable, public sfx2::SvBaseLink
 {
     OString ConsumeLine();
-    void Decode(const OUString& rURL, const OUString& rRange, const sal_Int32 nLimit,
-            const OUString& rMove, const sal_uInt32 nSettings);
     void MoveData();
 
 public:
@@ -58,6 +56,8 @@ public:
     const sal_Int32& GetLimit() const { return mnLimit; }
     const OUString& GetMove() const { return msMove; }
     const sal_uInt32& GetSettings() const { return mnSettings; }
+    void Decode(const OUString& rURL, const OUString& rRange, const sal_Int32 nLimit,
+            const OUString& rMove, const sal_uInt32 nSettings);
     bool ImportData();
     void Start();
     void Stop();
diff --git a/sc/source/ui/inc/datastreamdlg.hxx b/sc/source/ui/inc/datastreamdlg.hxx
index cb469d7..5bb05f3 100644
--- a/sc/source/ui/inc/datastreamdlg.hxx
+++ b/sc/source/ui/inc/datastreamdlg.hxx
@@ -13,6 +13,7 @@
 #include <vcl/dialog.hxx>
 #include <vcl/layout.hxx>
 
+class DataStream;
 class ScDocShell;
 class SvtURLBox;
 
@@ -25,6 +26,7 @@ class DataStreamDlg : public ModalDialog
     RadioButton*    m_pRBScriptData;
     RadioButton*    m_pRBValuesInLine;
     RadioButton*    m_pRBAddressValue;
+    RadioButton*    m_pRBDataDown;
     RadioButton*    m_pRBRangeDown;
     RadioButton*    m_pRBNoMove;
     RadioButton*    m_pRBMaxLimit;
@@ -43,7 +45,9 @@ class DataStreamDlg : public ModalDialog
 public:
     DataStreamDlg(ScDocShell *pDocShell, Window* pParent);
     ~DataStreamDlg() {}
-    void StartStream();
+    void Init(const OUString& rURL, const OUString& rRange, const sal_Int32 nLimit,
+            const OUString& rMove, const sal_uInt32 nSettings);
+    void StartStream(DataStream *pStream = 0);
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index 95e07b9..6923df9 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -23,6 +23,7 @@ DataStreamDlg::DataStreamDlg(ScDocShell *pDocShell, Window* pParent)
     get(m_pRBScriptData, "scriptdata");
     get(m_pRBValuesInLine, "valuesinline");
     get(m_pRBAddressValue, "addressvalue");
+    get(m_pRBDataDown, "datadown");
     get(m_pRBRangeDown, "rangedown");
     get(m_pRBNoMove, "nomove");
     get(m_pRBMaxLimit, "maxlimit");
@@ -70,15 +71,35 @@ void DataStreamDlg::UpdateEnable()
     }
     else
     {
-        m_pVclFrameLimit->Show(true);
+        m_pVclFrameLimit->Show();
         m_pVclFrameMove->Show();
         m_pVclFrameRange->Show();
         bOk = bOk && !m_pEdRange->GetText().isEmpty();
     }
     m_pBtnOk->Enable(bOk);
+    setOptimalLayoutSize();
 }
 
-void DataStreamDlg::StartStream()
+void DataStreamDlg::Init(const OUString& rURL, const OUString& rRange, const sal_Int32 nLimit,
+        const OUString& rMove, const sal_uInt32 nSettings)
+{
+    m_pEdLimit->SetText(OUString::number(nLimit));
+    m_pCbUrl->SetText(rURL);
+    if (nSettings & DataStream::SCRIPT_STREAM)
+        m_pRBScriptData->Check();
+    if (!(nSettings & DataStream::VALUES_IN_LINE))
+        m_pRBAddressValue->Check();
+    m_pEdRange->SetText(rRange);
+    if (rMove == "NO_MOVE")
+        m_pRBNoMove->Check();
+    else if (rMove == "RANGE_DOWN")
+        m_pRBRangeDown->Check();
+    else if (rMove == "MOVE_DOWN")
+        m_pRBDataDown->Check();
+    UpdateEnable();
+}
+
+void DataStreamDlg::StartStream(DataStream *pStream)
 {
     sal_Int32 nLimit = 0;
     if (m_pRBMaxLimit->IsChecked())
@@ -89,6 +110,14 @@ void DataStreamDlg::StartStream()
        nSettings |= DataStream::SCRIPT_STREAM;
     if (m_pRBValuesInLine->IsChecked())
        nSettings |= DataStream::VALUES_IN_LINE;
+    if (pStream)
+    {
+        pStream->Decode(rURL, m_pEdRange->GetText(), nLimit,
+                m_pRBNoMove->IsChecked() ? OUString("NO_MOVE") : m_pRBRangeDown->IsChecked()
+                    ? OUString("RANGE_DOWN") : OUString("MOVE_DOWN"),
+                nSettings);
+        return;
+    }
     sfx2::SvBaseLink *pLink = DataStream::Set( mpDocShell,
             rURL,
             m_pEdRange->GetText(),
commit a51a356278a1860e2586ca748dd4f46d1f98d6ee
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Mon Nov 25 10:44:08 2013 +0100

    datastreams: do not hang when closing the link
    
    Change-Id: Ib38472849d7b56bf3013f65d84f1b4cfbd91b2d0

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 1529e78..68fb7cc 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -54,9 +54,9 @@ private:
             TimeValue const aTime = {0, 100000};
             maStart.wait();
             maStart.reset();
-            if (!mbTerminate)
-                while (mpDataStream->ImportData())
-                    wait(aTime);
+            while (!mbTerminate && mpDataStream->ImportData())
+                wait(aTime);
+            mpDataStream->maMakeSureTheThreadStopped.set();
         };
     }
 };
@@ -236,8 +236,7 @@ DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const OUString&
 
 DataStream::~DataStream()
 {
-    if (mbRunning)
-        Stop();
+    Stop();
     mxThread->mbTerminate = true;
     mxThread->maStart.set();
     mxThread->join();
@@ -314,6 +313,9 @@ void DataStream::Stop()
     if (!mbRunning)
         return;
     mbRunning = false;
+    SolarMutexReleaser aAllowTheThreadToStop;
+    maMakeSureTheThreadStopped.wait();
+    maMakeSureTheThreadStopped.reset();
     mpScDocument->EnableUndo(mbIsUndoEnabled);
 }
 
@@ -402,6 +404,12 @@ bool DataStream::ImportData()
     return mbRunning;
 }
 
+void DataStream::Closed()
+{
+    Stop();
+    SvBaseLink::Closed();
+}
+
 sfx2::SvBaseLink::UpdateResult DataStream::DataChanged(
         const OUString& , const css::uno::Any& )
 {
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 4189ba3..1615735 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -9,6 +9,7 @@
 
 #include <sal/config.h>
 
+#include <osl/conditn.hxx>
 #include <rtl/ref.hxx>
 #include <rtl/ustring.hxx>
 #include <sfx2/lnkbase.hxx>
@@ -38,6 +39,7 @@ class DataStream : boost::noncopyable, public sfx2::SvBaseLink
 public:
     enum MoveEnum { NO_MOVE, RANGE_DOWN, MOVE_DOWN, MOVE_UP };
     enum { SCRIPT_STREAM = 1, VALUES_IN_LINE = 2 };
+    osl::Condition maMakeSureTheThreadStopped;
 
     static void MakeToolbarVisible(ScDocShell *pShell);
     static sfx2::SvBaseLink* Set(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
@@ -46,6 +48,7 @@ public:
     DataStream(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
             sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings);
     virtual ~DataStream() SAL_OVERRIDE;
+    virtual void Closed() SAL_OVERRIDE;
     virtual sfx2::SvBaseLink::UpdateResult DataChanged(
             const OUString& , const css::uno::Any& ) SAL_OVERRIDE;
     virtual void Edit(Window* , const Link& ) SAL_OVERRIDE;
commit 40f29308226415d5d70b33fcf84dc80acaf428aa
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Fri Nov 22 16:14:11 2013 +0100

    export data streams; pretend to be an area link
    
    Fix ScXMLExport::GetAreaLinks to not use UNO, so we can hack DataStreams
    into ScMyAreaLinksContainer.
    We need to connect them to cells for export / import - that does not make
    sense for DataStream without any attached range. We use an arbitrary one.
    But you might remove it, if you create another ScAreaLink / DataStream
    with the same range, without knowing about it.
    
    Maybe it wouldn't be that bad to let DataStream inherit from ScAreaLink.
    
    Change-Id: I5b85a9329ba1ca46fb2893b54fe5161d2fb22f47

diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index 5ed08df..8fbeb8a 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -60,6 +60,8 @@
 #include "stylehelper.hxx"
 #include "edittextiterator.hxx"
 #include "editattributemap.hxx"
+#include <arealink.hxx>
+#include <datastream.hxx>
 
 #include <xmloff/xmltoken.hxx>
 #include <xmloff/xmlnmspe.hxx>
@@ -147,6 +149,7 @@
 
 #include "XMLCodeNameProvider.hxx"
 
+#include <sfx2/linkmgr.hxx>
 #include <sfx2/objsh.hxx>
 
 #include <vector>
@@ -814,37 +817,35 @@ table::CellRangeAddress ScXMLExport::GetEndAddress(const uno::Reference<sheet::X
     return aCellAddress;
 }
 
-void ScXMLExport::GetAreaLinks( uno::Reference< sheet::XSpreadsheetDocument>& xSpreadDoc,
-                                ScMyAreaLinksContainer& rAreaLinks )
+void ScXMLExport::GetAreaLinks( ScMyAreaLinksContainer& rAreaLinks )
 {
-    uno::Reference< beans::XPropertySet > xPropSet( xSpreadDoc, uno::UNO_QUERY );
-    if( !xPropSet.is() ) return;
-
-    uno::Reference< container::XIndexAccess > xLinksIAccess( xPropSet->getPropertyValue( OUString( SC_UNO_AREALINKS ) ), uno::UNO_QUERY);
-    if( xLinksIAccess.is() )
+    if (pDoc->GetLinkManager())
     {
-        const OUString sFilter( SC_UNONAME_FILTER );
-        const OUString sFilterOpt( SC_UNONAME_FILTOPT );
-        const OUString sURL( SC_UNONAME_LINKURL );
-        const OUString sRefresh( SC_UNONAME_REFDELAY );
-
-        sal_Int32 nCount(xLinksIAccess->getCount());
-        for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex )
+        const sfx2::SvBaseLinks& rLinks = pDoc->GetLinkManager()->GetLinks();
+        for (size_t i = 0; i < rLinks.size(); i++)
         {
-            uno::Reference< sheet::XAreaLink > xAreaLink(xLinksIAccess->getByIndex( nIndex ), uno::UNO_QUERY);
-            if( xAreaLink.is() )
+            ScAreaLink *pLink = dynamic_cast<ScAreaLink*>(&(*(*rLinks[i])));
+            if (pLink)
             {
                 ScMyAreaLink aAreaLink;
-                aAreaLink.aDestRange = xAreaLink->getDestArea();
-                aAreaLink.sSourceStr = xAreaLink->getSourceArea();
-                uno::Reference< beans::XPropertySet > xLinkProp( xAreaLink, uno::UNO_QUERY );
-                if( xLinkProp.is() )
-                {
-                    xLinkProp->getPropertyValue( sFilter ) >>= aAreaLink.sFilter;
-                    xLinkProp->getPropertyValue( sFilterOpt ) >>= aAreaLink.sFilterOptions;
-                    xLinkProp->getPropertyValue( sURL ) >>= aAreaLink.sURL;
-                    xLinkProp->getPropertyValue( sRefresh ) >>= aAreaLink.nRefresh;
-                }
+                ScUnoConversion::FillApiRange( aAreaLink.aDestRange, pLink->GetDestArea() );
+                aAreaLink.sSourceStr = pLink->GetSource();
+                aAreaLink.sFilter = pLink->GetFilter();
+                aAreaLink.sFilterOptions = pLink->GetOptions();
+                aAreaLink.sURL = pLink->GetFile();
+                aAreaLink.nRefresh = pLink->GetTimeout();
+                rAreaLinks.AddNewAreaLink( aAreaLink );
+            }
+            DataStream *pStream = dynamic_cast<DataStream*>(&(*(*rLinks[i])));
+            if (pStream)
+            {
+                ScMyAreaLink aAreaLink;
+                ScUnoConversion::FillApiRange( aAreaLink.aDestRange, pStream->GetRange() );
+                aAreaLink.sSourceStr = pStream->GetMove();
+                aAreaLink.sFilter = OUString::number(pStream->GetLimit());
+                aAreaLink.sFilterOptions = "DataStream";
+                aAreaLink.sURL = pStream->GetURL();
+                aAreaLink.nRefresh = pStream->GetSettings();
                 rAreaLinks.AddNewAreaLink( aAreaLink );
             }
         }
@@ -1904,7 +1905,7 @@ void ScXMLExport::_ExportContent()
         WriteCalculationSettings(xSpreadDoc);
         sal_Int32 nTableCount(xIndex->getCount());
         ScMyAreaLinksContainer aAreaLinks;
-        GetAreaLinks( xSpreadDoc, aAreaLinks );
+        GetAreaLinks( aAreaLinks );
         ScMyEmptyDatabaseRangesContainer aEmptyRanges(aExportDatabaseRanges.GetEmptyDatabaseRanges());
         ScMyDetectiveOpContainer aDetectiveOpContainer;
         GetDetectiveOpList( aDetectiveOpContainer );
diff --git a/sc/source/filter/xml/xmlexprt.hxx b/sc/source/filter/xml/xmlexprt.hxx
index cc649bd..4ece1d5 100644
--- a/sc/source/filter/xml/xmlexprt.hxx
+++ b/sc/source/filter/xml/xmlexprt.hxx
@@ -144,7 +144,7 @@ class ScXMLExport : public SvXMLExport
     com::sun::star::table::CellRangeAddress GetEndAddress(const com::sun::star::uno::Reference<com::sun::star::sheet::XSpreadsheet>& xTable,
                                                         const sal_Int32 nTable);
 //  ScMyEmptyDatabaseRangesContainer GetEmptyDatabaseRanges();
-    void GetAreaLinks( com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheetDocument>& xSpreadDoc, ScMyAreaLinksContainer& rAreaLinks );
+    void GetAreaLinks( ScMyAreaLinksContainer& rAreaLinks );
     void GetDetectiveOpList( ScMyDetectiveOpContainer& rDetOp );
     void WriteSingleColumn(const sal_Int32 nRepeatColumns, const sal_Int32 nStyleIndex,
         const sal_Int32 nIndex, const bool bIsAutoStyle, const bool bIsVisible);
diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index ba428f8..1529e78 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -16,6 +16,7 @@
 #include <salhelper/thread.hxx>
 #include <sfx2/linkmgr.hxx>
 #include <sfx2/viewfrm.hxx>
+#include <arealink.hxx>
 #include <asciiopt.hxx>
 #include <dbfunc.hxx>
 #include <docsh.hxx>
@@ -166,9 +167,44 @@ void DataStream::MakeToolbarVisible(ScDocShell *pShell)
 sfx2::SvBaseLink* DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
         sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings)
 {
+    // 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.
+    sfx2::LinkManager* pLinkManager = pShell->GetDocument()->GetLinkManager();
+    ScRange aDestArea;
+    aDestArea.Parse(rRange, pShell->GetDocument());
+    sal_uInt16 nLinkPos = 0;
+    while (nLinkPos < pLinkManager->GetLinks().size())
+    {
+        sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
+        if (rRange.isEmpty())
+        {
+            if ( (pBase->ISA(ScAreaLink) && dynamic_cast<ScAreaLink*>
+                        (&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
+                || (pBase->ISA(DataStream) && dynamic_cast<DataStream*>
+                        (&(*pBase))->GetRange().aStart == aDestArea.aStart) )
+            {
+                aDestArea.Move(0, 1, 0);
+                nLinkPos = 0;
+                continue;
+            }
+            else
+                ++nLinkPos;
+        }
+        else if ( (pBase->ISA(ScAreaLink) && dynamic_cast<ScAreaLink*>
+                    (&(*pBase))->GetDestArea().aStart == aDestArea.aStart)
+                || (pBase->ISA(DataStream) && dynamic_cast<DataStream*>
+                    (&(*pBase))->GetRange().aStart == aDestArea.aStart) )
+        {
+            pLinkManager->Remove( pBase );
+        }
+        else
+            ++nLinkPos;
+    }
+
     sfx2::SvBaseLink *pLink = 0;
     pLink = new DataStream( pShell, rURL, rRange, nLimit, rMove, nSettings );
-    sfx2::LinkManager* pLinkManager = pShell->GetDocument()->GetLinkManager();
     pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rURL, NULL, NULL );
     return pLink;
 }
@@ -181,20 +217,19 @@ DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const OUString&
     , mbRunning(false)
     , mpLines(0)
     , mnLinesCount(0)
-    , mpRange(new ScRange())
     , mpEndRange(NULL)
 {
     mxThread = new datastreams::CallerThread( this );
     mxThread->launch();
 
-    Decode(rURL, rRange, rMove, nSettings);
+    Decode(rURL, rRange, nLimit, rMove, nSettings);
 
-    mpStartRange.reset( new ScRange(*mpRange.get()) );
-    sal_Int32 nHeight = mpRange->aEnd.Row() - mpRange->aStart.Row() + 1;
+    maStartRange = maRange;
+    sal_Int32 nHeight = maRange.aEnd.Row() - maRange.aStart.Row() + 1;
     nLimit = nHeight * (nLimit / nHeight);
-    if (nLimit && mpRange->aStart.Row() + nLimit - 1 < MAXROW)
+    if (nLimit && maRange.aStart.Row() + nLimit - 1 < MAXROW)
     {
-        mpEndRange.reset( new ScRange(*mpRange) );
+        mpEndRange.reset( new ScRange(maRange) );
         mpEndRange->Move(0, nLimit - nHeight, 0);
     }
 }
@@ -235,28 +270,32 @@ OString DataStream::ConsumeLine()
     return mpLines->at(mnLinesCount++);
 }
 
-void DataStream::Decode( const OUString& rURL, const OUString& rRange,
-        const OUString& rMove, sal_uInt32 nSettings)
+void DataStream::Decode(const OUString& rURL, const OUString& rRange,
+        const sal_Int32 nLimit, const OUString& rMove, const sal_uInt32 nSettings)
 {
+    msURL = rURL;
+    msRange = rRange;
+    mnLimit = nLimit;
+    msMove = rMove;
+    mnSettings = nSettings;
+    maRange.Parse(msRange);
     SvStream *pStream = 0;
-    if (nSettings & SCRIPT_STREAM)
-        pStream = new SvScriptStream(rURL);
+    if (mnSettings & SCRIPT_STREAM)
+        pStream = new SvScriptStream(msURL);
     else
-        pStream = new SvFileStream(rURL, STREAM_READ);
+        pStream = new SvFileStream(msURL, STREAM_READ);
     mxReaderThread = new datastreams::ReaderThread( pStream );
     mxReaderThread->launch();
 
-    mbValuesInLine = nSettings & VALUES_IN_LINE;
+    mbValuesInLine = mnSettings & VALUES_IN_LINE;
     if (!mbValuesInLine)
         return;
 
-    mpRange->Parse(rRange, mpScDocument);
-    
-    if (rMove == "NO_MOVE")
+    if (msMove == "NO_MOVE")
         meMove = NO_MOVE;
-    else if (rMove == "RANGE_DOWN")
+    else if (msMove == "RANGE_DOWN")
         meMove = RANGE_DOWN;
-    else if (rMove == "MOVE_DOWN")
+    else if (msMove == "MOVE_DOWN")
         meMove = MOVE_DOWN;
 }
 
@@ -283,17 +322,17 @@ void DataStream::MoveData()
     switch (meMove)
     {
         case RANGE_DOWN:
-            if (mpRange->aStart == mpEndRange->aStart)
+            if (maRange.aStart == mpEndRange->aStart)
                 meMove = MOVE_UP;
             break;
         case MOVE_UP:
-            mpScDocument->DeleteRow(*mpStartRange);
+            mpScDocument->DeleteRow(maStartRange);
             mpScDocument->InsertRow(*mpEndRange);
             break;
         case MOVE_DOWN:
             if (mpEndRange.get())
                 mpScDocument->DeleteRow(*mpEndRange);
-            mpScDocument->InsertRow(*mpRange);
+            mpScDocument->InsertRow(maRange);
             break;
         case NO_MOVE:
             break;
@@ -306,7 +345,7 @@ bool DataStream::ImportData()
     MoveData();
     if (mbValuesInLine)
     {
-        SCROW nHeight = mpRange->aEnd.Row() - mpRange->aStart.Row() + 1;
+        SCROW nHeight = maRange.aEnd.Row() - maRange.aStart.Row() + 1;
         OStringBuffer aBuf;
         while (nHeight--)
         {
@@ -314,7 +353,7 @@ bool DataStream::ImportData()
             aBuf.append('\n');
         }
         SvMemoryStream aMemoryStream((void *)aBuf.getStr(), aBuf.getLength(), STREAM_READ);
-        ScImportExport aImport(mpScDocument, *mpRange);
+        ScImportExport aImport(mpScDocument, maRange);
         aImport.SetSeparator(',');
         aImport.ImportStream(aMemoryStream, OUString(), FORMAT_STRING);
     }
@@ -352,13 +391,13 @@ bool DataStream::ImportData()
 
     if (meMove == RANGE_DOWN)
     {
-        mpRange->Move(0, mpRange->aEnd.Row() - mpRange->aStart.Row() + 1, 0);
+        maRange.Move(0, maRange.aEnd.Row() - maRange.aStart.Row() + 1, 0);
         mpScDocShell->GetViewData()->GetView()->AlignToCursor(
-                mpRange->aStart.Col(), mpRange->aStart.Row(), SC_FOLLOW_JUMP);
+                maRange.aStart.Col(), maRange.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 );
+    mpScDocShell->PostPaint( ScRange( maStartRange.aStart, ScAddress( maRange.aEnd.Col(),
+                    aEndRow, maRange.aStart.Tab()) ), PAINT_GRID );
 
     return mbRunning;
 }
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 2731f24..4189ba3 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -12,6 +12,7 @@
 #include <rtl/ref.hxx>
 #include <rtl/ustring.hxx>
 #include <sfx2/lnkbase.hxx>
+#include <address.hxx>
 
 #include <boost/noncopyable.hpp>
 #include <boost/scoped_ptr.hpp>
@@ -23,7 +24,6 @@ namespace datastreams {
 }
 class ScDocShell;
 class ScDocument;
-class ScRange;
 class Window;
 
 typedef std::vector<OString> LinesList;
@@ -31,7 +31,8 @@ typedef std::vector<OString> LinesList;
 class DataStream : boost::noncopyable, public sfx2::SvBaseLink
 {
     OString ConsumeLine();
-    void Decode(const OUString& rURL, const OUString& rRange, const OUString& rMove, sal_uInt32 nSettings);
+    void Decode(const OUString& rURL, const OUString& rRange, const sal_Int32 nLimit,
+            const OUString& rMove, const sal_uInt32 nSettings);
     void MoveData();
 
 public:
@@ -49,6 +50,11 @@ public:
             const OUString& , const css::uno::Any& ) SAL_OVERRIDE;
     virtual void Edit(Window* , const Link& ) SAL_OVERRIDE;
 
+    const ScRange& GetRange() const { return maRange; }
+    const OUString& GetURL() const { return msURL; }
+    const sal_Int32& GetLimit() const { return mnLimit; }
+    const OUString& GetMove() const { return msMove; }
+    const sal_uInt32& GetSettings() const { return mnSettings; }
     bool ImportData();
     void Start();
     void Stop();
@@ -56,14 +62,19 @@ public:
 private:
     ScDocShell *mpScDocShell;
     ScDocument *mpScDocument;
+    OUString msURL;
+    OUString msRange;
+    OUString msMove;
+    sal_Int32 mnLimit;
+    sal_uInt32 mnSettings;
     MoveEnum meMove;
     bool mbRunning;
     bool mbIsUndoEnabled;
     bool mbValuesInLine;
     LinesList *mpLines;
     size_t mnLinesCount;
-    boost::scoped_ptr<ScRange> mpRange;
-    boost::scoped_ptr<ScRange> mpStartRange;
+    ScRange maRange;
+    ScRange maStartRange;
     boost::scoped_ptr<ScRange> mpEndRange;
     rtl::Reference<datastreams::CallerThread> mxThread;
     rtl::Reference<datastreams::ReaderThread> mxReaderThread;
diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index f1b2bae..95e07b9 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -66,6 +66,7 @@ void DataStreamDlg::UpdateEnable()
         m_pVclFrameLimit->Hide();
         m_pVclFrameMove->Hide();
         m_pVclFrameRange->Hide();
+        m_pEdRange->SetText("");
     }
     else
     {
commit ba7a46117272f4136690c5bfe0d970fa89b74966
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Thu Nov 21 21:20:17 2013 +0100

    Import data streams - reuse infrastructure for ScAreaLink.
    
    Change-Id: I18db991d2e8e665d5e4ca778344993e79772ccd5

diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx
index 47ad103..09bef92 100644
--- a/sc/source/core/data/documen8.cxx
+++ b/sc/source/core/data/documen8.cxx
@@ -86,6 +86,7 @@
 #include "columniterator.hxx"
 #include "globalnames.hxx"
 #include "stringutil.hxx"
+#include <datastream.hxx>
 
 #include <memory>
 #include <boost/scoped_ptr.hpp>
@@ -1193,7 +1194,7 @@ bool ScDocument::HasAreaLinks() const
         const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
         sal_uInt16 nCount = rLinks.size();
         for (sal_uInt16 i=0; i<nCount; i++)
-            if ((*rLinks[i])->ISA(ScAreaLink))
+            if ((*rLinks[i])->ISA(ScAreaLink) || (*rLinks[i])->ISA(DataStream))
                 return true;
     }
 
@@ -1208,7 +1209,7 @@ void ScDocument::UpdateAreaLinks()
         for (sal_uInt16 i=0; i<rLinks.size(); i++)
         {
             ::sfx2::SvBaseLink* pBase = *rLinks[i];
-            if (pBase->ISA(ScAreaLink))
+            if (pBase->ISA(ScAreaLink) || (*rLinks[i])->ISA(DataStream))
                 pBase->Update();
         }
     }
diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx
index e9f7d5b..5ca7129 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -52,6 +52,8 @@
 #include "tokenarray.hxx"
 #include "scmatrix.hxx"
 #include "documentimport.hxx"
+#include <datastream.hxx>
+#include <rangeutl.hxx>
 
 #include <xmloff/xmltkmap.hxx>
 #include <xmloff/xmltoken.hxx>
@@ -997,6 +999,19 @@ void ScXMLTableRowCellContext::SetCellRangeSource( const ScAddress& rPosition )
                 rPosition.Row() + static_cast<SCROW>(pCellRangeSource->nRows - 1), rPosition.Tab() );
             OUString sFilterName( pCellRangeSource->sFilterName );
             OUString sSourceStr( pCellRangeSource->sSourceStr );
+            OUString sRangeStr;
+            ScRangeStringConverter::GetStringFromRange( sRangeStr, aDestRange, pDoc, formula::FormulaGrammar::CONV_OOO );
+            if (pCellRangeSource->sFilterOptions == "DataStream")
+            {
+                DataStream::Set( dynamic_cast<ScDocShell*>(pDoc->GetDocumentShell())
+                        , pCellRangeSource->sURL // rURL
+                        , sRangeStr // rRange
+                        , sFilterName.toInt32() // nLimit
+                        , sSourceStr // rMove
+                        , pCellRangeSource->nRefresh // nSettings
+                        );
+                return;
+            }
             ScAreaLink* pLink = new ScAreaLink( pDoc->GetDocumentShell(), pCellRangeSource->sURL,
                 sFilterName, pCellRangeSource->sFilterOptions, sSourceStr, aDestRange, pCellRangeSource->nRefresh );
             sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index d58c72c..ba428f8 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -138,10 +138,10 @@ private:
 
 }
 
-static void lcl_MakeToolbarVisible(SfxViewFrame *pViewFrame)
+void DataStream::MakeToolbarVisible(ScDocShell *pShell)
 {
     css::uno::Reference< css::frame::XFrame > xFrame =
-        pViewFrame->GetFrame().GetFrameInterface();
+        pShell->GetViewData()->GetViewShell()->GetViewFrame()->GetFrame().GetFrameInterface();
     if (!xFrame.is())
         return;
 
@@ -163,18 +163,18 @@ static void lcl_MakeToolbarVisible(SfxViewFrame *pViewFrame)
     }
 }
 
-void DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUString& rRange, sal_Int32 nLimit, const OUString& rMove)
+sfx2::SvBaseLink* DataStream::Set(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
+        sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings)
 {
     sfx2::SvBaseLink *pLink = 0;
-    pLink = new DataStream( pShell, rURL, rRange, nLimit, rMove );
+    pLink = new DataStream( pShell, rURL, rRange, nLimit, rMove, nSettings );
     sfx2::LinkManager* pLinkManager = pShell->GetDocument()->GetLinkManager();
     pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rURL, NULL, NULL );
-
-    lcl_MakeToolbarVisible(pShell->GetViewData()->GetViewShell()->GetViewFrame());
+    return pLink;
 }
 
-DataStream::DataStream(ScDocShell *pShell, const OUString& rURL,
-        const OUString& rRange, sal_Int32 nLimit, const OUString& rMove)
+DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
+        sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings)
     : mpScDocShell(pShell)
     , mpScDocument(mpScDocShell->GetDocument())
     , meMove(NO_MOVE)
@@ -187,7 +187,7 @@ DataStream::DataStream(ScDocShell *pShell, const OUString& rURL,
     mxThread = new datastreams::CallerThread( this );
     mxThread->launch();
 
-    Decode(rURL, rRange, rMove);
+    Decode(rURL, rRange, rMove, nSettings);
 
     mpStartRange.reset( new ScRange(*mpRange.get()) );
     sal_Int32 nHeight = mpRange->aEnd.Row() - mpRange->aStart.Row() + 1;
@@ -215,6 +215,8 @@ OString DataStream::ConsumeLine()
     if (!mpLines || mnLinesCount >= mpLines->size())
     {
         mnLinesCount = 0;
+        if (mxReaderThread->mbTerminateReading)
+            return OString();
         osl::ResettableMutexGuard aGuard(mxReaderThread->maLinesProtector);
         if (mpLines)
             mxReaderThread->maUsedLines.push(mpLines);
@@ -233,18 +235,18 @@ OString DataStream::ConsumeLine()
     return mpLines->at(mnLinesCount++);
 }
 
-void DataStream::Decode( const OUString& rURL, const OUString& rRange, const OUString& rMove)
+void DataStream::Decode( const OUString& rURL, const OUString& rRange,
+        const OUString& rMove, sal_uInt32 nSettings)
 {
-    sal_Int32 nIndex = rURL.indexOf(sfx2::cTokenSeparator);
     SvStream *pStream = 0;
-    if (nIndex != -1)
-        pStream = new SvScriptStream(rURL.copy(0, nIndex));
+    if (nSettings & SCRIPT_STREAM)
+        pStream = new SvScriptStream(rURL);
     else
         pStream = new SvFileStream(rURL, STREAM_READ);
     mxReaderThread = new datastreams::ReaderThread( pStream );
     mxReaderThread->launch();
 
-    mbValuesInLine = !rRange.isEmpty();
+    mbValuesInLine = nSettings & VALUES_IN_LINE;
     if (!mbValuesInLine)
         return;
 
@@ -361,6 +363,14 @@ bool DataStream::ImportData()
     return mbRunning;
 }
 
+sfx2::SvBaseLink::UpdateResult DataStream::DataChanged(
+        const OUString& , const css::uno::Any& )
+{
+    MakeToolbarVisible(mpScDocShell);
+    Start();
+    return SUCCESS;
+}
+
 void DataStream::Edit(Window* , const Link& )
 {
 }
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 6da62c9..2731f24 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -31,18 +31,22 @@ typedef std::vector<OString> LinesList;
 class DataStream : boost::noncopyable, public sfx2::SvBaseLink
 {
     OString ConsumeLine();
-    void Decode(const OUString& rURL, const OUString& rRange, const OUString& rMove);
+    void Decode(const OUString& rURL, const OUString& rRange, const OUString& rMove, sal_uInt32 nSettings);
     void MoveData();
 
 public:
     enum MoveEnum { NO_MOVE, RANGE_DOWN, MOVE_DOWN, MOVE_UP };
+    enum { SCRIPT_STREAM = 1, VALUES_IN_LINE = 2 };
 
-    static void Set(ScDocShell *pShell, const OUString& rURL,
-            const OUString& rRange, sal_Int32 nLimit, const OUString& rMove);
+    static void MakeToolbarVisible(ScDocShell *pShell);
+    static sfx2::SvBaseLink* Set(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
+            sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings);
 
-    DataStream(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, sal_uInt32 nSettings);
     virtual ~DataStream() SAL_OVERRIDE;
+    virtual sfx2::SvBaseLink::UpdateResult DataChanged(
+            const OUString& , const css::uno::Any& ) SAL_OVERRIDE;
     virtual void Edit(Window* , const Link& ) SAL_OVERRIDE;
 
     bool ImportData();
diff --git a/sc/source/ui/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
index cd2d2c4..f1b2bae 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -10,7 +10,6 @@
 #include <datastreamdlg.hxx>
 
 #include <sfx2/filedlghelper.hxx>
-#include <sfx2/linkmgr.hxx>
 #include <svtools/inettbc.hxx>
 #include <vcl/layout.hxx>
 #include <datastream.hxx>
@@ -84,15 +83,20 @@ void DataStreamDlg::StartStream()
     if (m_pRBMaxLimit->IsChecked())
         nLimit = m_pEdLimit->GetText().toInt32();
     OUString rURL = m_pCbUrl->GetText();
+    sal_uInt32 nSettings = 0;
     if (m_pRBScriptData->IsChecked())
-       rURL += OUString(sfx2::cTokenSeparator);
-    DataStream::Set( mpDocShell,
+       nSettings |= DataStream::SCRIPT_STREAM;
+    if (m_pRBValuesInLine->IsChecked())
+       nSettings |= DataStream::VALUES_IN_LINE;
+    sfx2::SvBaseLink *pLink = DataStream::Set( mpDocShell,
             rURL,
             m_pEdRange->GetText(),
             nLimit,
             m_pRBNoMove->IsChecked() ? OUString("NO_MOVE") : m_pRBRangeDown->IsChecked()
                 ? OUString("RANGE_DOWN") : OUString("MOVE_DOWN")
+            , nSettings
             );
+    pLink->Update();
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit e50c08e914ffd58de9f0e60b3b118c0542d6f29a
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Thu Nov 21 15:23:09 2013 +0100

    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

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index c9f0b5f..95d971a 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -383,6 +383,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/ui/dialogs/searchresults \
     sc/source/ui/docshell/arealink \
     sc/source/ui/docshell/autostyl \
+    sc/source/ui/docshell/datastream \
     sc/source/ui/docshell/dbdocfun \
     sc/source/ui/docshell/dbdocimp \
     sc/source/ui/docshell/docfunc \
@@ -441,8 +442,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/ui/miscdlgs/autofmt \
     sc/source/ui/miscdlgs/conflictsdlg \
     sc/source/ui/miscdlgs/crnrdlg \
-    sc/source/ui/miscdlgs/datastreams \
-    sc/source/ui/miscdlgs/datastreamsdlg \
+    sc/source/ui/miscdlgs/datastreamdlg \
     sc/source/ui/miscdlgs/highred \
     sc/source/ui/miscdlgs/optsolver \
     sc/source/ui/miscdlgs/protectiondlg \
diff --git a/sc/source/ui/miscdlgs/datastreams.cxx b/sc/source/ui/docshell/datastream.cxx
similarity index 83%
rename from sc/source/ui/miscdlgs/datastreams.cxx
rename to sc/source/ui/docshell/datastream.cxx
index 59d3b39..d58c72c 100644
--- a/sc/source/ui/miscdlgs/datastreams.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -7,13 +7,14 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include <datastreams.hxx>
+#include <datastream.hxx>
 
 #include <com/sun/star/frame/XLayoutManager.hpp>
 #include <com/sun/star/ui/XUIElement.hpp>
 #include <osl/conditn.hxx>
 #include <rtl/strbuf.hxx>
 #include <salhelper/thread.hxx>
+#include <sfx2/linkmgr.hxx>
 #include <sfx2/viewfrm.hxx>
 #include <asciiopt.hxx>
 #include <dbfunc.hxx>
@@ -30,14 +31,14 @@ namespace datastreams {
 
 class CallerThread : public salhelper::Thread
 {
-    DataStreams *mpDataStreams;
+    DataStream *mpDataStream;
 public:
     osl::Condition maStart;
     bool mbTerminate;
 
-    CallerThread(DataStreams *pData):
+    CallerThread(DataStream *pData):
         Thread("CallerThread")
-        ,mpDataStreams(pData)
+        ,mpDataStream(pData)
         ,mbTerminate(false)
     {}
 
@@ -53,7 +54,7 @@ private:
             maStart.wait();
             maStart.reset();
             if (!mbTerminate)
-                while (mpDataStreams->ImportData())
+                while (mpDataStream->ImportData())
                     wait(aTime);
         };
     }
@@ -137,19 +138,68 @@ private:
 
 }
 
-DataStreams::DataStreams(ScDocShell *pScDocShell):
-    mpScDocShell(pScDocShell)
+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);
+    }
 }
 
-DataStreams::~DataStreams()
+DataStream::~DataStream()
 {
     if (mbRunning)
         Stop();
@@ -160,7 +210,7 @@ DataStreams::~DataStreams()
         mxReaderThread->endThread();
 }
 
-OString DataStreams::ConsumeLine()
+OString DataStream::ConsumeLine()
 {
     if (!mpLines || mnLinesCount >= mpLines->size())
     {
@@ -183,7 +233,32 @@ OString DataStreams::ConsumeLine()
     return mpLines->at(mnLinesCount++);
 }
 
-void DataStreams::Start()
+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;
@@ -191,30 +266,9 @@ void DataStreams::Start()
     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()
+void DataStream::Stop()
 {
     if (!mbRunning)
         return;
@@ -222,36 +276,7 @@ void DataStreams::Stop()
     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()
+void DataStream::MoveData()
 {
     switch (meMove)
     {
@@ -273,7 +298,7 @@ void DataStreams::MoveData()
     }
 }
 
-bool DataStreams::ImportData()
+bool DataStream::ImportData()
 {
     SolarMutexGuard aGuard;
     MoveData();
@@ -336,4 +361,8 @@ bool DataStreams::ImportData()
     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 d7be8ac..b44eb9f 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/datastreams.hxx b/sc/source/ui/inc/datastream.hxx
similarity index 71%
rename from sc/source/ui/inc/datastreams.hxx
rename to sc/source/ui/inc/datastream.hxx
index 93d1574..6da62c9 100644
--- a/sc/source/ui/inc/datastreams.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -11,6 +11,7 @@
 
 #include <rtl/ref.hxx>
 #include <rtl/ustring.hxx>
+#include <sfx2/lnkbase.hxx>
 
 #include <boost/noncopyable.hpp>
 #include <boost/scoped_ptr.hpp>
@@ -23,23 +24,28 @@ namespace datastreams {
 class ScDocShell;
 class ScDocument;
 class ScRange;
-class SvStream;
 class Window;
 
 typedef std::vector<OString> LinesList;
 
-class DataStreams : boost::noncopyable
+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 };
-    DataStreams(ScDocShell *pScDocShell);
-    ~DataStreams();
-    OString ConsumeLine();
+
+    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 MoveData();
-    void Set(SvStream *pStream, bool bValuesInLine,
-            const OUString& rRange, sal_Int32 nLimit, MoveEnum eMove);
-    void ShowDialog(Window *pParent);
     void Start();
     void Stop();
 
diff --git a/sc/source/ui/inc/datastreamdlg.hxx b/sc/source/ui/inc/datastreamdlg.hxx
new file mode 100644
index 0000000..cb469d7
--- /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 <sal/config.h>
+
+#include <rtl/ref.hxx>
+#include <vcl/dialog.hxx>
+#include <vcl/layout.hxx>
+
+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/miscdlgs/datastreamdlg.cxx b/sc/source/ui/miscdlgs/datastreamdlg.cxx
new file mode 100644
index 0000000..cd2d2c4
--- /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 <datastreamdlg.hxx>
+
+#include <sfx2/filedlghelper.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <svtools/inettbc.hxx>
+#include <vcl/layout.hxx>
+#include <datastream.hxx>
+
+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/datastreamsdlg.cxx b/sc/source/ui/miscdlgs/datastreamsdlg.cxx
deleted file mode 100644
index bacb67a..0000000
--- 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 <sfx2/filedlghelper.hxx>
-#include <svtools/inettbc.hxx>
-#include <vcl/dialog.hxx>
-#include <vcl/layout.hxx>
-#include <datastreams.hxx>
-
-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<SvStream*>( new SvScriptStream(m_pCbUrl->GetText()) ) :
-                dynamic_cast<SvStream*>( 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 943379f..e1ed032 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 4450bd9..aceb41c 100644
--- a/sc/source/ui/view/cellsh2.cxx
+++ b/sc/source/ui/view/cellsh2.cxx
@@ -20,6 +20,7 @@
 #include "scitems.hxx"
 #include <sfx2/viewfrm.hxx>
 #include <sfx2/app.hxx>
+#include <sfx2/linkmgr.hxx>
 #include <sfx2/request.hxx>
 #include <svl/aeitem.hxx>
 #include <basic/sbxcore.hxx>
@@ -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<DataStream*>(&(*(*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<DataStream*>(&(*(*rLinks[i]))))
+                            pStream->Stop();
+                }
+            }
             break;
         case SID_MANAGE_XML_SOURCE:
             ExecuteXMLSourceDialog();
diff --git a/sc/uiconfig/scalc/ui/datastreams.ui b/sc/uiconfig/scalc/ui/datastreams.ui
index 853840a..fc2dcea 100644
--- a/sc/uiconfig/scalc/ui/datastreams.ui
+++ b/sc/uiconfig/scalc/ui/datastreams.ui
@@ -2,7 +2,7 @@
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
   <!-- interface-requires LibreOffice 1.0 -->
-  <object class="GtkDialog" id="DataStreamsDialog">
+  <object class="GtkDialog" id="DataStreamDialog">
     <property name="can_focus">False</property>
     <property name="border_width">6</property>
     <property name="title" translatable="yes">Live Data Streams</property>
commit 7975e9dd3a55cde4ab54e05993b310ec24088283
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Mon Nov 25 13:51:52 2013 +0100

    Use better icons for data streams.
    
    Change-Id: I57064ff251a560b71aaf1846a9d7cd9105f938df

diff --git a/icon-themes/galaxy/links.txt b/icon-themes/galaxy/links.txt
index e55b9db..96ccd9b 100644
--- a/icon-themes/galaxy/links.txt
+++ b/icon-themes/galaxy/links.txt
@@ -1,4 +1,4 @@
-cmd/lc_datastreamsplay.png cmd/lc_runbasic.png
-cmd/sc_datastreamsplay.png cmd/sc_runbasic.png
-cmd/lc_datastreamsstop.png cmd/lc_basicstop.png
-cmd/sc_datastreamsstop.png cmd/sc_basicstop.png
+cmd/lc_datastreamsplay.png avmedia/res/avl02049.png
+cmd/sc_datastreamsplay.png avmedia/res/av02049.png
+cmd/lc_datastreamsstop.png avmedia/res/avl02051.png
+cmd/sc_datastreamsstop.png avmedia/res/av02051.png


More information about the Libreoffice-commits mailing list