[Libreoffice-commits] core.git: Branch 'feature/datastreams' - 6 commits - sc/source sc/uiconfig sc/UIConfig_scalc.mk

Matúš Kukan matus.kukan at collabora.com
Thu Nov 28 03:13:39 PST 2013


Rebased ref, commits from common ancestor:
commit 6e377fd0ea1737df71cc69ce1be8cb3cc8ad0970
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 503449dcd0af4f410ccade34bd432eeb84210e5e
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 5a0517251dcd7729299612eb0e7ceb41751238f9
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 d9d123cea43dcfcb4afde0ff5c6fd18563037d56
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 23c4972..8f28b61 100644
--- a/sc/UIConfig_scalc.mk
+++ b/sc/UIConfig_scalc.mk
@@ -109,6 +109,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 478f43a101ade97b98b49543423727ea1ea0d9c7
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 09373772fab4b63bf09497ce3ddd23bf28564850
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,


More information about the Libreoffice-commits mailing list