[Libreoffice-commits] core.git: 11 commits - icon-themes/galaxy sc/Library_sc.mk sc/sdi sc/source sc/uiconfig sc/UIConfig_scalc.mk

Matúš Kukan matus.kukan at collabora.com
Thu Nov 28 11:46:01 PST 2013


 icon-themes/galaxy/links.txt                       |    8 
 sc/Library_sc.mk                                   |    4 
 sc/UIConfig_scalc.mk                               |    1 
 sc/sdi/cellsh.sdi                                  |    6 
 sc/source/core/data/documen8.cxx                   |    5 
 sc/source/filter/xml/xmlcelli.cxx                  |   17 
 sc/source/filter/xml/xmlexprt.cxx                  |   55 +-
 sc/source/filter/xml/xmlexprt.hxx                  |    2 
 sc/source/ui/docshell/datastream.cxx               |  474 +++++++++++++++++++++
 sc/source/ui/inc/cellsh.hxx                        |    3 
 sc/source/ui/inc/datastream.hxx                    |   84 +++
 sc/source/ui/inc/datastreamdlg.hxx                 |   53 ++
 sc/source/ui/inc/datastreams.hxx                   |   62 --
 sc/source/ui/miscdlgs/datastreamdlg.cxx            |  134 +++++
 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                      |   47 +-
 sc/uiconfig/scalc/ui/datastreams.ui                |    2 
 sc/uiconfig/scalc/ui/queryrunstreamscriptdialog.ui |   33 +
 20 files changed, 876 insertions(+), 590 deletions(-)

New commits:
commit edc484d92e3d8c154f72231cde049269c5b6c217
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Thu Nov 28 20:33:37 2013 +0100

    make data streams an experimental feature
    
    Change-Id: I674b86a6e1c1c0b162c159747b6900ce438ab095

diff --git a/sc/sdi/cellsh.sdi b/sc/sdi/cellsh.sdi
index 470e319..2fe1237 100644
--- a/sc/sdi/cellsh.sdi
+++ b/sc/sdi/cellsh.sdi
@@ -51,9 +51,9 @@ interface CellSelection
     SID_REFRESH_DBAREA      [ ExecMethod = ExecuteDB; StateMethod = GetDBState; ]
     SID_SBA_BRW_INSERT      [ ExecMethod = ExecuteDB; StateMethod = GetDBState; ]
     SID_SELECT_DB           [ ExecMethod = ExecuteDB; StateMethod = GetDBState; ]
-    SID_DATA_STREAMS        [ ExecMethod = ExecuteDB; ]
-    SID_DATA_STREAMS_PLAY   [ ExecMethod = ExecuteDB; ]
-    SID_DATA_STREAMS_STOP   [ ExecMethod = ExecuteDB; ]
+    SID_DATA_STREAMS        [ ExecMethod = ExecuteDB; StateMethod = GetDBState; ]
+    SID_DATA_STREAMS_PLAY   [ ExecMethod = ExecuteDB; StateMethod = GetDBState; ]
+    SID_DATA_STREAMS_STOP   [ ExecMethod = ExecuteDB; StateMethod = GetDBState; ]
     SID_MANAGE_XML_SOURCE   [ ExecMethod = ExecuteDB; StateMethod = GetDBState; ]
     SID_SORT                [ ExecMethod = ExecuteDB; StateMethod = GetDBState; ]
     SID_DATA_FORM           [ ExecMethod = ExecuteDB; StateMethod = GetDBState; ]
diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx
index 5ca7129..1875afa 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -86,6 +86,7 @@
 #include "editeng/langitem.hxx"
 #include <svx/unoapi.hxx>
 #include <svl/languageoptions.hxx>
+#include <svtools/miscopt.hxx>
 #include <sax/tools/converter.hxx>
 
 #include <com/sun/star/frame/XModel.hpp>
@@ -1001,7 +1002,8 @@ void ScXMLTableRowCellContext::SetCellRangeSource( const ScAddress& rPosition )
             OUString sSourceStr( pCellRangeSource->sSourceStr );
             OUString sRangeStr;
             ScRangeStringConverter::GetStringFromRange( sRangeStr, aDestRange, pDoc, formula::FormulaGrammar::CONV_OOO );
-            if (pCellRangeSource->sFilterOptions == "DataStream")
+            SvtMiscOptions aMiscOptions;
+            if (aMiscOptions.IsExperimentalMode() && pCellRangeSource->sFilterOptions == "DataStream")
             {
                 DataStream::Set( dynamic_cast<ScDocShell*>(pDoc->GetDocumentShell())
                         , pCellRangeSource->sURL // rURL
diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx
index a8d301e..71c9282 100644
--- a/sc/source/ui/view/cellsh2.cxx
+++ b/sc/source/ui/view/cellsh2.cxx
@@ -29,6 +29,7 @@
 #include <vcl/msgbox.hxx>
 #include <svl/stritem.hxx>
 #include <svl/visitem.hxx>
+#include <svtools/miscopt.hxx>
 #include <unotools/moduleoptions.hxx>
 
 #include <com/sun/star/frame/FrameSearchFlag.hpp>
@@ -1167,7 +1168,15 @@ void ScCellShell::GetDBState( SfxItemSet& rSet )
                     }
                 }
                 break;
-
+            case SID_DATA_STREAMS:
+            case SID_DATA_STREAMS_PLAY:
+            case SID_DATA_STREAMS_STOP:
+                {
+                    SvtMiscOptions aMiscOptions;
+                    if ( !aMiscOptions.IsExperimentalMode() )
+                        rSet.DisableItem( nWhich );
+                }
+                break;
             case SID_TEXT_TO_COLUMNS:
                 {
                     ScRange aRange;
commit 39bc5e1155d928b89d5e35822170b0b368bb7e50
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Thu Nov 28 10:47:15 2013 +0100

    fix memory leak
    
    Change-Id: Ic84ace8ac3aa52009f43aafe78283730f97881f2

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index bb85b3a..44c8b39 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -201,6 +201,7 @@ DataStream::~DataStream()
         StopImport();
     if (mxReaderThread.is())
         mxReaderThread->endThread();
+    delete mpLines;
 }
 
 OString DataStream::ConsumeLine()
commit 75997ec53cab1f41337b9cf9d2b7648ae707b97b
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Thu Nov 28 10:44:42 2013 +0100

    datastreams: No need to disable undo. We do not add undo actions.
    
    Also fixes memory leak, because EnableUndo()
    was called from Document's destructor.
    
    Change-Id: I637ff62bde6f8c3238238323e6e4a5a5d2b81881

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index 30e59f6..bb85b3a 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -262,8 +262,6 @@ void DataStream::StartImport()
 {
     if (mbRunning)
         return;
-    mbIsUndoEnabled = mpScDocument->IsUndoEnabled();
-    mpScDocument->EnableUndo(false);
     if (!mxReaderThread.is())
     {
         SvStream *pStream = 0;
@@ -284,7 +282,6 @@ void DataStream::StopImport()
         return;
     mbRunning = false;
     AutoTimer::Stop();
-    mpScDocument->EnableUndo(mbIsUndoEnabled);
 }
 
 void DataStream::MoveData()
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 57e094b..c329a3d 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -72,7 +72,6 @@ private:
     sal_uInt32 mnSettings;
     MoveEnum meMove;
     bool mbRunning;
-    bool mbIsUndoEnabled;
     bool mbValuesInLine;
     LinesList *mpLines;
     size_t mnLinesCount;
commit 2f4a1487512276901229acb1775181c9fbc5ed18
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Wed Nov 27 18:00:42 2013 +0100

    datastreams: Simplify code for importing CSV data.
    
    The code is copied and simplified from sc/source/ui/docshell/impex.cxx.
    
    Change-Id: I15a426a16c4f2ba659af86492c1b2e4ba879d8b6

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index ed9227e..30e59f6 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -315,22 +315,87 @@ IMPL_LINK_NOARG(DataStream, RefreshHdl)
     return 0;
 }
 
+//  lcl_ScanString and Text2Doc is simplified version
+//  of code from sc/source/ui/docshell/impex.cxx
+const sal_Unicode* lcl_ScanString( const sal_Unicode* p, OUString& rString, sal_Unicode cStr)
+{
+    const sal_Unicode* p0 = p;
+    for( ;; )
+    {
+        if (!*p)
+            break;
+        if (*p == cStr)
+        {
+            if (*++p != cStr)
+                break;
+            p++;
+        }
+        else
+            p++;
+    }
+    if (p0 < p)
+        if (rString.getLength() + (p - p0) <= STRING_MAXLEN)
+            rString += OUString( p0, sal::static_int_cast<sal_Int32>( p - p0 ) );
+    return p;
+}
+
+void DataStream::Text2Doc()
+{
+    sal_Unicode cSep(',');
+    sal_Unicode cStr('"');
+    SCCOL nStartCol = maRange.aStart.Col();
+    SCROW nStartRow = maRange.aStart.Row();
+    SCCOL nEndCol = maRange.aEnd.Col();
+    SCROW nEndRow = maRange.aEnd.Row();
+    OUString aCell;
+    SCROW nRow = nStartRow;
+    ScDocumentImport aDocImport(*mpScDocument);
+    while (nRow <= nEndRow)
+    {
+        SCCOL nCol = nStartCol;
+        OUString sLine( OStringToOUString(ConsumeLine(), RTL_TEXTENCODING_UTF8) );
+        const sal_Unicode* p = sLine.getStr();
+        while (*p)
+        {
+            aCell = "";
+            const sal_Unicode* q = p;
+            while (*p && *p != cSep)
+            {
+                // Always look for a pairing quote and ignore separator in between.
+                while (*p && *p == cStr)
+                    q = p = lcl_ScanString(p, aCell, cStr);
+                // All until next separator or quote.
+                while (*p && *p != cSep && *p != cStr)
+                    ++p;
+                if (aCell.getLength() + (p - q) <= STRING_MAXLEN)
+                    aCell += OUString( q, sal::static_int_cast<sal_Int32>( p - q ) );
+                q = p;
+            }
+            if (*p)
+                ++p;
+            if (nCol <= nEndCol && nRow <= nEndRow)
+            {
+                ScAddress aAddress(nCol, nRow, maRange.aStart.Tab());
+                if (aCell == "0" || ( aCell.indexOf(':') == -1 && aCell.toDouble() ))
+                    aDocImport.setNumericCell(aAddress, aCell.toDouble());
+                else
+                    aDocImport.setStringCell(aAddress, aCell);
+            }
+            ++nCol;
+        }
+        ++nRow;
+    }
+    aDocImport.finalize();
+    mpScDocShell->PostPaint( maRange, PAINT_GRID );
+}
+
 bool DataStream::ImportData()
 {
     MoveData();
     if (mbValuesInLine)
     {
-        SCROW nHeight = maRange.aEnd.Row() - maRange.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, maRange);
-        aImport.SetSeparator(',');
-        aImport.ImportStream(aMemoryStream, OUString(), FORMAT_STRING);
+        // do CSV import
+        Text2Doc();
     }
     else
     {
@@ -359,8 +424,6 @@ bool DataStream::ImportData()
         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;
 
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 092539b..57e094b 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -32,6 +32,7 @@ class DataStream : boost::noncopyable, public sfx2::SvBaseLink, ScRefreshTimer
 {
     OString ConsumeLine();
     void MoveData();
+    void Text2Doc();
     DECL_LINK( RefreshHdl, void* );
 
 public:
commit 1e7196461e9fa247d658338241be2392aefdcd12
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Wed Nov 27 15:48:32 2013 +0100

    datastreams: for security, ask before executing a script when importing
    
    Change-Id: I76a11dae2569eb7e0c791c9f1fb20626c4ff7528

diff --git a/sc/UIConfig_scalc.mk b/sc/UIConfig_scalc.mk
index 2d8859b..e87e0eb 100644
--- a/sc/UIConfig_scalc.mk
+++ b/sc/UIConfig_scalc.mk
@@ -110,6 +110,7 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/scalc,\
 	sc/uiconfig/scalc/ui/printareasdialog \
 	sc/uiconfig/scalc/ui/printeroptions \
 	sc/uiconfig/scalc/ui/protectsheetdlg \
+	sc/uiconfig/scalc/ui/queryrunstreamscriptdialog \
 	sc/uiconfig/scalc/ui/randomnumbergenerator \
 	sc/uiconfig/scalc/ui/rightfooterdialog \
 	sc/uiconfig/scalc/ui/rightheaderdialog \
diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index fff0bbd..ed9227e 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -11,6 +11,7 @@
 
 #include <com/sun/star/frame/XLayoutManager.hpp>
 #include <com/sun/star/ui/XUIElement.hpp>
+#include <officecfg/Office/Common.hxx>
 #include <osl/conditn.hxx>
 #include <rtl/strbuf.hxx>
 #include <salhelper/thread.hxx>
@@ -237,14 +238,6 @@ void DataStream::Decode(const OUString& rURL, const OUString& rRange,
     mnSettings = nSettings;
     mpEndRange.reset( NULL );
 
-    SvStream *pStream = 0;
-    if (mnSettings & SCRIPT_STREAM)
-        pStream = new SvScriptStream(msURL);
-    else
-        pStream = new SvFileStream(msURL, STREAM_READ);
-    mxReaderThread = new datastreams::ReaderThread( pStream );
-    mxReaderThread->launch();
-
     mbValuesInLine = mnSettings & VALUES_IN_LINE;
 
     if (msMove == "NO_MOVE")
@@ -271,6 +264,16 @@ void DataStream::StartImport()
         return;
     mbIsUndoEnabled = mpScDocument->IsUndoEnabled();
     mpScDocument->EnableUndo(false);
+    if (!mxReaderThread.is())
+    {
+        SvStream *pStream = 0;
+        if (mnSettings & SCRIPT_STREAM)
+            pStream = new SvScriptStream(msURL);
+        else
+            pStream = new SvFileStream(msURL, STREAM_READ);
+        mxReaderThread = new datastreams::ReaderThread( pStream );
+        mxReaderThread->launch();
+    }
     mbRunning = true;
     AutoTimer::Start();
 }
@@ -378,7 +381,18 @@ sfx2::SvBaseLink::UpdateResult DataStream::DataChanged(
         const OUString& , const css::uno::Any& )
 {
     MakeToolbarVisible(mpScDocShell);
-    StartImport();
+    StopImport();
+    bool bStart = true;
+    if (mnSettings & SCRIPT_STREAM && !mxReaderThread.is() &&
+        officecfg::Office::Common::Security::Scripting::MacroSecurityLevel::get() >= 1)
+    {
+        MessageDialog aQBox( NULL, "QueryRunStreamScriptDialog", "modules/scalc/ui/queryrunstreamscriptdialog.ui");
+        aQBox.set_primary_text( aQBox.get_primary_text().replaceFirst("%URL", msURL) );
+        if (RET_YES != aQBox.Execute())
+            bStart = false;
+    }
+    if (bStart)
+        StartImport();
     return SUCCESS;
 }
 
diff --git a/sc/uiconfig/scalc/ui/queryrunstreamscriptdialog.ui b/sc/uiconfig/scalc/ui/queryrunstreamscriptdialog.ui
new file mode 100644
index 0000000..ca7fbe6
--- /dev/null
+++ b/sc/uiconfig/scalc/ui/queryrunstreamscriptdialog.ui
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 3.0 -->
+  <object class="GtkMessageDialog" id="QueryRunStreamScriptDialog">
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <property name="resizable">False</property>
+    <property name="type_hint">dialog</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="message_type">question</property>
+    <property name="buttons">yes-no</property>
+    <property name="text" translatable="yes">This data stream is generated by a script. Do you want to execute %URL?</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="messagedialog-vbox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">24</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="messagedialog-action_area">
+            <property name="can_focus">False</property>
+            <property name="layout_style">center</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
commit d925f6072914c66816b9c69c47141053282f9960
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Wed Nov 27 12:42:59 2013 +0100

    Let's use ScRefreshTimer for data streams instead of our own thread.
    
    As was the original idea, for some reason abandoned, and as ScAreaLink does.
    
    The main advantage is that ImportData() is not called anymore with
    invalid mpScDocument (when we close it).
    There is surely something going on with SolarMutex and it just works better.
    We do not need to use our own SolarMutexGuard.
    
    Change-Id: I09256a18ffa14606fc8e06b968016bbc0562a6fa

diff --git a/sc/source/ui/docshell/datastream.cxx b/sc/source/ui/docshell/datastream.cxx
index ff095f5..fff0bbd 100644
--- a/sc/source/ui/docshell/datastream.cxx
+++ b/sc/source/ui/docshell/datastream.cxx
@@ -31,37 +31,6 @@
 
 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;
@@ -219,19 +188,16 @@ DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const OUString&
     , mpLines(0)
     , mnLinesCount(0)
 {
-    mxThread = new datastreams::CallerThread( this );
-    mxThread->launch();
-
+    SetRefreshHandler(LINK( this, DataStream, RefreshHdl ));
+    SetRefreshControl(mpScDocument->GetRefreshTimerControlAddress());
+    SetTimeout( 1 );
     Decode(rURL, rRange, nLimit, rMove, nSettings);
 }
 
 DataStream::~DataStream()
 {
     if (mbRunning)
-        Stop();
-    mxThread->mbTerminate = true;
-    mxThread->maStart.set();
-    mxThread->join();
+        StopImport();
     if (mxReaderThread.is())
         mxReaderThread->endThread();
 }
@@ -299,21 +265,22 @@ void DataStream::Decode(const OUString& rURL, const OUString& rRange,
     }
 }
 
-void DataStream::Start()
+void DataStream::StartImport()
 {
     if (mbRunning)
         return;
     mbIsUndoEnabled = mpScDocument->IsUndoEnabled();
     mpScDocument->EnableUndo(false);
     mbRunning = true;
-    mxThread->maStart.set();
+    AutoTimer::Start();
 }
 
-void DataStream::Stop()
+void DataStream::StopImport()
 {
     if (!mbRunning)
         return;
     mbRunning = false;
+    AutoTimer::Stop();
     mpScDocument->EnableUndo(mbIsUndoEnabled);
 }
 
@@ -339,9 +306,14 @@ void DataStream::MoveData()
     }
 }
 
+IMPL_LINK_NOARG(DataStream, RefreshHdl)
+{
+    ImportData();
+    return 0;
+}
+
 bool DataStream::ImportData()
 {
-    SolarMutexGuard aGuard;
     MoveData();
     if (mbValuesInLine)
     {
@@ -406,7 +378,7 @@ sfx2::SvBaseLink::UpdateResult DataStream::DataChanged(
         const OUString& , const css::uno::Any& )
 {
     MakeToolbarVisible(mpScDocShell);
-    Start();
+    StartImport();
     return SUCCESS;
 }
 
@@ -417,10 +389,10 @@ void DataStream::Edit(Window* pWindow, const Link& )
     if (aDialog.Execute() == RET_OK)
     {
         bool bWasRunning = mbRunning;
-        Stop();
+        StopImport();
         aDialog.StartStream(this);
         if (bWasRunning)
-            Start();
+            StartImport();
     }
 }
 
diff --git a/sc/source/ui/inc/datastream.hxx b/sc/source/ui/inc/datastream.hxx
index 91dda2e..092539b 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -13,13 +13,13 @@
 #include <rtl/ustring.hxx>
 #include <sfx2/lnkbase.hxx>
 #include <address.hxx>
+#include <refreshtimer.hxx>
 
 #include <boost/noncopyable.hpp>
 #include <boost/scoped_ptr.hpp>
 #include <vector>
 
 namespace datastreams {
-    class CallerThread;
     class ReaderThread;
 }
 class ScDocShell;
@@ -28,10 +28,11 @@ class Window;
 
 typedef std::vector<OString> LinesList;
 
-class DataStream : boost::noncopyable, public sfx2::SvBaseLink
+class DataStream : boost::noncopyable, public sfx2::SvBaseLink, ScRefreshTimer
 {
     OString ConsumeLine();
     void MoveData();
+    DECL_LINK( RefreshHdl, void* );
 
 public:
     enum MoveEnum { NO_MOVE, RANGE_DOWN, MOVE_DOWN, MOVE_UP };
@@ -44,6 +45,7 @@ public:
     DataStream(ScDocShell *pShell, const OUString& rURL, const OUString& rRange,
             sal_Int32 nLimit, const OUString& rMove, sal_uInt32 nSettings);
     virtual ~DataStream() SAL_OVERRIDE;
+    // sfx2::SvBaseLink
     virtual sfx2::SvBaseLink::UpdateResult DataChanged(
             const OUString& , const css::uno::Any& ) SAL_OVERRIDE;
     virtual void Edit(Window* , const Link& ) SAL_OVERRIDE;
@@ -56,8 +58,8 @@ public:
     void Decode(const OUString& rURL, const OUString& rRange, sal_Int32 nLimit,
             const OUString& rMove, const sal_uInt32 nSettings);
     bool ImportData();
-    void Start();
-    void Stop();
+    void StartImport();
+    void StopImport();
 
 private:
     ScDocShell *mpScDocShell;
@@ -76,7 +78,6 @@ private:
     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 e56cc03..cbfd46b 100644
--- a/sc/source/ui/miscdlgs/datastreamdlg.cxx
+++ b/sc/source/ui/miscdlgs/datastreamdlg.cxx
@@ -128,7 +128,7 @@ void DataStreamDlg::StartStream(DataStream *pStream)
             , nSettings
             );
     DataStream::MakeToolbarVisible( mpDocShell );
-    pStream->Start();
+    pStream->StartImport();
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx
index aceb41c..a8d301e 100644
--- a/sc/source/ui/view/cellsh2.cxx
+++ b/sc/source/ui/view/cellsh2.cxx
@@ -750,7 +750,7 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
                     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();
+                            pStream->StartImport();
                 }
             }
             break;
@@ -762,7 +762,7 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq )
                     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();
+                            pStream->StopImport();
                 }
             }
             break;
commit 6ce9618ef9ebe58bc6f3ced34c465bbeb5df5b23
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 aef6c3b..ff095f5 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>
@@ -217,21 +218,11 @@ DataStream::DataStream(ScDocShell *pShell, const OUString& rURL, const OUString&
     , mbRunning(false)
     , mpLines(0)
     , mnLinesCount(0)
-    , mpEndRange(NULL)
 {
     mxThread = new datastreams::CallerThread( this );
     mxThread->launch();
 
     Decode(rURL, rRange, nLimit, rMove, nSettings);
-
-    maStartRange = maRange;
-    sal_Int32 nHeight = maRange.aEnd.Row() - maRange.aStart.Row() + 1;
-    nLimit = nHeight * (nLimit / nHeight);
-    if (nLimit && maRange.aStart.Row() + nLimit - 1 < MAXROW)
-    {
-        mpEndRange.reset( new ScRange(maRange) );
-        mpEndRange->Move(0, nLimit - nHeight, 0);
-    }
 }
 
 DataStream::~DataStream()
@@ -271,14 +262,15 @@ OString DataStream::ConsumeLine()
 }
 
 void DataStream::Decode(const OUString& rURL, const OUString& rRange,
-        const sal_Int32 nLimit, const OUString& rMove, const sal_uInt32 nSettings)
+        sal_Int32 nLimit, const OUString& rMove, const sal_uInt32 nSettings)
 {
     msURL = rURL;
     msRange = rRange;
     mnLimit = nLimit;
     msMove = rMove;
     mnSettings = nSettings;
-    maRange.Parse(msRange);
+    mpEndRange.reset( NULL );
+
     SvStream *pStream = 0;
     if (mnSettings & SCRIPT_STREAM)
         pStream = new SvScriptStream(msURL);
@@ -288,8 +280,6 @@ void DataStream::Decode(const OUString& rURL, const OUString& rRange,
     mxReaderThread->launch();
 
     mbValuesInLine = mnSettings & VALUES_IN_LINE;
-    if (!mbValuesInLine)
-        return;
 
     if (msMove == "NO_MOVE")
         meMove = NO_MOVE;
@@ -297,6 +287,16 @@ void DataStream::Decode(const OUString& rURL, const OUString& rRange,
         meMove = RANGE_DOWN;
     else if (msMove == "MOVE_DOWN")
         meMove = MOVE_DOWN;
+
+    maRange.Parse(msRange);
+    maStartRange = maRange;
+    sal_Int32 nHeight = maRange.aEnd.Row() - maRange.aStart.Row() + 1;
+    nLimit = nHeight * (nLimit / nHeight);
+    if (nLimit && maRange.aStart.Row() + nLimit - 1 < MAXROW)
+    {
+        mpEndRange.reset( new ScRange(maRange) );
+        mpEndRange->Move(0, nLimit - nHeight, 0);
+    }
 }
 
 void DataStream::Start()
@@ -410,8 +410,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 b60a988..91dda2e 100644
--- a/sc/source/ui/inc/datastream.hxx
+++ b/sc/source/ui/inc/datastream.hxx
@@ -31,8 +31,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:
@@ -55,6 +53,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, 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 b266687..e56cc03 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");
@@ -63,6 +64,7 @@ void DataStreamDlg::UpdateEnable()
     bool bOk = !m_pCbUrl->GetURL().isEmpty();
     if (m_pRBAddressValue->IsChecked())
     {
+        m_pRBNoMove->Check();
         m_pVclFrameLimit->Hide();
         m_pVclFrameMove->Hide();
         m_pVclFrameRange->Hide();
@@ -70,15 +72,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,7 +111,15 @@ void DataStreamDlg::StartStream()
        nSettings |= DataStream::SCRIPT_STREAM;
     if (m_pRBValuesInLine->IsChecked())
        nSettings |= DataStream::VALUES_IN_LINE;
-    DataStream *pStream = DataStream::Set( mpDocShell,
+    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;
+    }
+    pStream = DataStream::Set( mpDocShell,
             rURL,
             m_pEdRange->GetText(),
             nLimit,
commit fa0fe19e89ba68a6b02cbdd5eff6bc161024c53d
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 a57512c..aef6c3b 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)
 DataStream* 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 dynamic_cast<DataStream*>(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 00c000f..b60a988 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 92b3290..b266687 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 55d6fdaf453062994d5f361621f4945f7b0e93dc
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..a57512c 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)
+DataStream* 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 dynamic_cast<DataStream*>(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..00c000f 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 DataStream* 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..92b3290 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,21 @@ 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;
+    DataStream *pStream = DataStream::Set( mpDocShell,
             rURL,
             m_pEdRange->GetText(),
             nLimit,
             m_pRBNoMove->IsChecked() ? OUString("NO_MOVE") : m_pRBRangeDown->IsChecked()
                 ? OUString("RANGE_DOWN") : OUString("MOVE_DOWN")
+            , nSettings
             );
+    DataStream::MakeToolbarVisible( mpDocShell );
+    pStream->Start();
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 47bc56725a37834888680986844b5d7630a6581d
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 aa7099c..fe2ddf8 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -385,6 +385,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 \
@@ -443,8 +444,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 ec69f05..cf9d13b 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 4cbc3d855529737bf8ce37a3c98dbbcc6b17f09e
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