Index: kdecore/io/kprocess.cpp
===================================================================
--- kdecore/io/kprocess.cpp	(revision 890832)
+++ kdecore/io/kprocess.cpp	(working copy)
@@ -41,6 +41,15 @@
 # define STD_ERROR_HANDLE 2
 #endif
 
+KProcessPrivate::KProcessPrivate() : openMode(QIODevice::ReadWrite), outputLineMode(false)
+{
+#ifdef Q_OS_WIN32    
+    outputDelimiter = "\r\n";
+#else
+    outputDelimiter = "\n";
+#endif
+}
+
 void KProcessPrivate::writeAll(const QByteArray &buf, int fd)
 {
 #ifdef Q_OS_WIN
@@ -83,6 +92,67 @@
     forwardStd(KProcess::StandardError, STD_ERROR_HANDLE);
 }
 
+void KProcessPrivate::_k_receivedStdout()
+{
+    if (!outputLineMode)
+        return; 
+
+    Q_Q(KProcess);
+    QByteArray ndata = q->readAllStandardOutput();
+    int oldBufferSize = stdoutBuffer.size();
+    stdoutBuffer.append(ndata);
+    if (newlineInStdout < 0) {
+        newlineInStdout = ndata.indexOf(outputDelimiter);
+        if (newlineInStdout >= 0) {
+            newlineInStdout += oldBufferSize;
+            emit q->readyReadLineStandardOutput();
+        }
+    }
+}
+
+void KProcessPrivate::_k_receivedStderr()
+{
+    if (!outputLineMode)
+        return; 
+
+    Q_Q(KProcess);    
+    QByteArray ndata = q->readAllStandardError();
+    int oldBufferSize = stderrBuffer.size();
+    stderrBuffer.append(ndata);
+    if (newlineInStderr < 0) {
+        newlineInStderr = ndata.indexOf(outputDelimiter);
+        if (newlineInStderr >= 0) {
+            newlineInStderr += oldBufferSize;
+            emit q->readyReadLineStandardError();
+        }
+    }
+}
+
+void KProcessPrivate::_k_finished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+    if (!outputLineMode)
+        return; 
+
+    // check if there is unprocessed data in output channel 
+    Q_Q(KProcess);    
+
+    QByteArray ndata = q->readAllStandardOutput();
+    stdoutBuffer.append(ndata);
+    if (stdoutBuffer.size() > 0) {
+        stdoutBuffer.append(outputDelimiter);
+        newlineInStdout = stdoutBuffer.indexOf(outputDelimiter);
+        emit q->readyReadLineStandardOutput();
+    }
+    ndata = q->readAllStandardError();
+    stderrBuffer.append(ndata);
+    if (stderrBuffer.size() > 0) {
+        stderrBuffer.append(outputDelimiter);
+        newlineInStderr = stderrBuffer.indexOf(outputDelimiter);
+        emit q->readyReadLineStandardError();
+    }
+}
+
+
 /////////////////////////////
 // public member functions //
 /////////////////////////////
@@ -115,18 +185,36 @@
     d->outputChannelMode = mode;
     disconnect(this, SIGNAL(readyReadStandardOutput()));
     disconnect(this, SIGNAL(readyReadStandardError()));
+    disconnect(this, SIGNAL(finished(int,QProcess::ExitStatus)));
     switch (mode) {
     case OnlyStdoutChannel:
         connect(this, SIGNAL(readyReadStandardError()), SLOT(_k_forwardStderr()));
+        QProcess::setProcessChannelMode(QProcess::SeparateChannels);
         break;
     case OnlyStderrChannel:
         connect(this, SIGNAL(readyReadStandardOutput()), SLOT(_k_forwardStdout()));
+        QProcess::setProcessChannelMode(QProcess::SeparateChannels);
         break;
+    case MergedChannels:
+        if (d->outputLineMode) {
+            connect(this, SIGNAL(readyReadStandardOutput()), SLOT(_k_receivedStdout()));
+            connect(this, SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(_k_finished(int,QProcess::ExitStatus)));
+        }
+        QProcess::setProcessChannelMode(QProcess::MergedChannels);
+        break;
+        
+    case SeparateChannels:
+        if (d->outputLineMode) {
+            connect(this, SIGNAL(readyReadStandardOutput()), SLOT(_k_receivedStdout()));
+            connect(this, SIGNAL(readyReadStandardError()), SLOT(_k_receivedStderr()));
+            connect(this, SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(_k_finished(int,QProcess::ExitStatus)));
+        }
+        QProcess::setProcessChannelMode(QProcess::SeparateChannels);
+        break;
     default:
         QProcess::setProcessChannelMode((ProcessChannelMode)mode);
-        return;
+        break;
     }
-    QProcess::setProcessChannelMode(QProcess::SeparateChannels);
 }
 
 KProcess::OutputChannelMode KProcess::outputChannelMode() const
@@ -136,6 +224,68 @@
     return d->outputChannelMode;
 }
 
+void KProcess::setOutputLineMode(bool mode)
+{
+    Q_D(KProcess);
+
+    d->outputLineMode = mode;
+    // make sure slots are setup right
+    setOutputChannelMode(d->outputChannelMode);
+}
+
+bool KProcess::outputLineMode() const
+{
+    Q_D(const KProcess);
+
+    return d->outputLineMode;
+}
+
+void KProcess::setOutputLineDelimiter(QString &delim)
+{
+    Q_D(KProcess);
+
+    d->outputDelimiter = delim.toAscii();
+}
+
+QString KProcess::outputLineDelimiter() const
+{
+    Q_D(const KProcess);
+
+    return d->outputDelimiter;
+}
+
+QStringList &KProcess::readLinesStandardOutput(QStringList &out)
+{
+    Q_D(KProcess);
+
+    if (d->newlineInStdout < 0)
+        return out;
+
+    while (d->newlineInStdout > -1) {
+        out << d->stdoutBuffer.left(d->newlineInStdout);
+        d->stdoutBuffer.remove(0, d->newlineInStdout + d->outputDelimiter.size());
+        d->newlineInStdout = d->stdoutBuffer.indexOf(d->outputDelimiter);
+    }
+
+    return out;
+}
+
+QStringList &KProcess::readLinesStandardError(QStringList &out)
+{
+    Q_D(KProcess);
+
+    if (d->newlineInStderr < 0)
+        return out;
+
+    while (d->newlineInStderr > -1) {
+        out << d->stdoutBuffer.left(d->newlineInStderr);
+        d->stderrBuffer.remove(0, d->newlineInStderr + d->outputDelimiter.size());
+        d->newlineInStderr = d->stderrBuffer.indexOf(d->outputDelimiter);
+    }
+
+    return out;
+}
+
 void KProcess::setNextOpenMode(QIODevice::OpenMode mode)
 {
     Q_D(KProcess);
Index: kdecore/io/kprocess.h
===================================================================
--- kdecore/io/kprocess.h	(revision 890832)
+++ kdecore/io/kprocess.h	(working copy)
@@ -97,6 +97,50 @@
     OutputChannelMode outputChannelMode() const;
 
     /**
+     * set the output line mode. When activated output data from the process is returned  as complete 
+     * lines. The line data can be retrieved by calling @ref readLinesStandardOutput()  for stdout and 
+     * @ref readLinesStandardError()  for stderr. 
+     * 
+     * Available line data is indicated by the signal @ref readReadLineStandardOutput() for stdout 
+     * and @ref readReadLineStandardError()  for stderr . 
+     *
+     * As line delimiter the operating systems default line delimiter is used (\\r\\n on win32, \\n on unix, ?? on mac). 
+     * Non standard line delimiters could be set with @ref setOutputLineDelimiter().
+     *
+     * The output line mode is disabled by default. 
+     
+     * @note When using output line mode, the readAllStandardOutput() and readAllStandardError() methods should not 
+     * be used, otherwise there will be no line output. 
+     * 
+     * @param mode of the output line mode
+     */
+    void setOutputLineMode(bool mode);
+
+    /**
+     * Query the state of the output line mode. See @ref setOutputLineMode() for more details for the output line mode.
+     *
+     * @return the state of the output line  mode
+    */    
+    bool outputLineMode() const;
+
+    /**
+     * Set  non standard line delimiter for output data in case the default line delimiter (\\r\\n on win32, \\n on unix, ?? on mac) 
+     * is not appliable. 
+     *
+     * This function must be called before starting the process.
+     *
+     * @param string with line delimiter
+     */
+    void setOutputLineDelimiter(QString &delim=QString());
+
+    /**
+     * Query the currently used output delimiter 
+     *
+     * @return the output line delimiter
+     */
+    QString outputLineDelimiter() const;
+
+    /**
      * Set the QIODevice open mode the process will be opened in.
      *
      * This function must be called before starting the process, obviously.
@@ -315,6 +359,38 @@
      */
     int pid() const;
 
+    /**
+    * When a line delimiter is set with setOutputLineDelimiter(), this function returns 
+    * all data lines available from the standard output of the process as a QStringList, 
+    * regardless of the current read channel,
+    * 
+    * Available data lines are indicated by the readyReadLineStandardOutput() signal. 
+    */
+    QStringList &readLinesStandardOutput(QStringList &out=QStringList());
+
+    /**
+    * When a line delimiter is set with setOutputLineDelimiter(), this function returns 
+    * all data lines available from the standard error of the process as a QStringList, 
+    * regardless of the current read channel,
+    * 
+    * Available data lines are indicated by the readyReadLineStandardOutput() signal. 
+    */
+    QStringList &readLinesStandardError(QStringList &out=QStringList());
+    
+signals:
+    /**
+    * This signal is emitted when an output delimiter is set with setOutputLineDelimiter() and 
+    * the process has made new data lines available through its standard output channel (stdout).
+    * It is emitted regardless of the current read channel.
+    */
+    void readyReadLineStandardOutput();
+    /**
+    * This signal is emitted when an output delimiter is set with setOutputLineDelimiter() and 
+    * the process has made new data lines available through its standard error channel (stderr).
+    * It is emitted regardless of the current read channel.
+    */
+    void readyReadLineStandardError();
+    
 protected:
     /**
      * @internal
@@ -335,6 +411,9 @@
 
     Q_PRIVATE_SLOT(d_func(), void _k_forwardStdout())
     Q_PRIVATE_SLOT(d_func(), void _k_forwardStderr())
+    Q_PRIVATE_SLOT(d_func(), void _k_receivedStdout())
+    Q_PRIVATE_SLOT(d_func(), void _k_receivedStderr())
+    Q_PRIVATE_SLOT(d_func(), void _k_finished(int, QProcess::ExitStatus))
 };
 
 #endif
Index: kdecore/io/kprocess_p.h
===================================================================
--- kdecore/io/kprocess_p.h	(revision 890832)
+++ kdecore/io/kprocess_p.h	(working copy)
@@ -27,21 +27,28 @@
 class KProcessPrivate {
     Q_DECLARE_PUBLIC(KProcess)
 protected:
-    KProcessPrivate() :
-        openMode(QIODevice::ReadWrite)
-    {
-    }
+    KProcessPrivate();
     void writeAll(const QByteArray &buf, int fd);
     void forwardStd(KProcess::ProcessChannel good, int fd);
     void _k_forwardStdout();
     void _k_forwardStderr();
+    void _k_receivedStdout();
+    void _k_receivedStderr();
+    void _k_finished(int, QProcess::ExitStatus);
 
     QString prog;
     QStringList args;
     KProcess::OutputChannelMode outputChannelMode;
     QIODevice::OpenMode openMode;
+    KProcess *q_ptr;
 
-    KProcess *q_ptr;
+    
+    bool outputLineMode;
+    QByteArray outputDelimiter; 
+    QByteArray stdoutBuffer; 
+    QByteArray stderrBuffer; 
+    int newlineInStdout;
+    int newlineInStderr;
 };
 
 
Index: kdecore/tests/CMakeLists.txt
===================================================================
--- kdecore/tests/CMakeLists.txt	(revision 890832)
+++ kdecore/tests/CMakeLists.txt	(working copy)
@@ -105,3 +105,10 @@
 set_target_properties(klibloadertestmodule4 PROPERTIES SKIP_BUILD_RPATH FALSE BUILD_WITH_INSTALL_RPATH FALSE)
 
 endif (NOT WIN32)
+
+########### next target ###############
+
+kde4_add_executable(kprocesstesthelper NOGUI kprocesstesthelper.cpp)
+target_link_libraries(kprocesstesthelper ${KDE4_KDECORE_LIBS})
+
+add_dependencies(kprocesstest kprocesstesthelper)
Index: kdecore/tests/kprocesstest.cpp
===================================================================
--- kdecore/tests/kprocesstest.cpp	(revision 890832)
+++ kdecore/tests/kprocesstest.cpp	(working copy)
@@ -2,6 +2,7 @@
     This file is part of the KDE libraries
 
     Copyright (C) 2007 Oswald Buddenhagen <ossi@kde.org>
+    Copyright (C) 2008 Ralf Habacker <ralf.habacker@freenet.de>
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Library General Public
@@ -26,12 +27,40 @@
 #include <stdlib.h>
 #include <signal.h>
 
+#ifdef Q_OS_WIN32
+#define NL "\r\n"
+#else
+#ifdef Q_OS_UNIX
+#define NL "\n"
+#else
+# warning define NL for this os
+#endif
+#endif
+
 class KProcessTest : public QObject {
     Q_OBJECT
 
+public: 
+    KProcessTest();    
+    
 private Q_SLOTS:
     void test_channels();
     void test_setShellCommand();
+    void test_signals();
+    void test_outputLineMode();
+
+    void slotPrintError();
+    void slotPrintOutput();
+    void slotFinished(int exitCode, QProcess::ExitStatus exitStatus);
+
+    void slotOutputLines();
+    void slotOutputLinesFinished(int exitCode, QProcess::ExitStatus exitStatus);
+
+    void cleanup(); 
+    
+private:
+    QEventLoop loop;
+    QStringList outData;
 };
 
 // IOCCC nomination pending
@@ -60,6 +89,11 @@
     a = "mode: " ms "\n" + recurse(KProcess::me); \
     QCOMPARE(a, e)
 
+    
+KProcessTest::KProcessTest() : loop( this )
+{
+}
+    
 void KProcessTest::test_channels()
 {
 #ifdef Q_OS_UNIX
@@ -89,6 +123,73 @@
 #endif
 }
 
+void KProcessTest::slotPrintOutput()
+{
+    KProcess *p = static_cast<KProcess*>(sender());
+    outData << p->readAllStandardOutput();
+}
+
+void KProcessTest::slotPrintError()
+{
+    KProcess *p = static_cast<KProcess*>(sender());
+    qDebug() << p->readAllStandardError();
+}
+
+void KProcessTest::slotFinished (int exitCode, QProcess::ExitStatus exitStatus)
+{
+    loop.exit();
+    QVERIFY(outData.size() == 1);
+    QString a = QLatin1String("line1" NL "line2" NL "line3");
+    QCOMPARE(outData.at(0),a);
+}
+
+void KProcessTest::test_signals()
+{
+    outData.clear();
+    KProcess *p = new KProcess;
+    p->setOutputChannelMode(KProcess::SeparateChannels);
+    connect(p,SIGNAL(readyReadStandardOutput()),this,SLOT(slotPrintOutput()));
+    connect(p,SIGNAL(readyReadStandardError()),this,SLOT(slotPrintError()));
+    connect(p,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotFinished(int,QProcess::ExitStatus)));
+    p->setProgram("kprocesstesthelper", QStringList() << "--partial-line" << "--stdout");
+    p->start();   
+    loop.exec();
+}
+
+void KProcessTest::slotOutputLines()
+{
+    KProcess *p = static_cast<KProcess*>(sender());
+    p->readLinesStandardOutput(outData);
+}
+
+void KProcessTest::slotOutputLinesFinished (int exitCode, QProcess::ExitStatus exitStatus)
+{
+    loop.exit();
+    QVERIFY(outData.size() == 3);
+    QCOMPARE(outData.at(0), QLatin1String("line1"));
+    QCOMPARE(outData.at(1), QLatin1String("line2"));
+    QCOMPARE(outData.at(2), QLatin1String("line3"));
+}
+
+void KProcessTest::test_outputLineMode()
+{
+    outData.clear();
+    KProcess *p = new KProcess;
+    p->setOutputLineMode(true);
+    p->setOutputChannelMode(KProcess::SeparateChannels);
+    connect(p,SIGNAL(readyReadLineStandardOutput()),this,SLOT(slotOutputLines()));
+    connect(p,SIGNAL(readyReadStandardError()),this,SLOT(slotPrintError()));
+    connect(p,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotOutputLinesFinished(int,QProcess::ExitStatus)));
+    p->setProgram("kprocesstesthelper", QStringList() << "--partial-line" << "--stdout");
+    p->start();
+    loop.exec();
+}
+
+void KProcessTest::cleanup()
+{
+    loop.exit();
+}
+
 static void recursor(char **argv)
 {
     if (argv[1]) {
Index: kdecore/tests/kprocesstesthelper.cpp
===================================================================
--- kdecore/tests/kprocesstesthelper.cpp	(revision 0)
+++ kdecore/tests/kprocesstesthelper.cpp	(revision 0)
@@ -0,0 +1,50 @@
+/*
+    This file is part of the KDE libraries
+
+    Copyright (C) 2008 Ralf Habacker <ralf.habacker@freenet.de>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include <stdio.h>
+#include <QCoreApplication>
+#include <QStringList>
+
+int main( int argc, char **argv )
+{
+    QCoreApplication app(argc, argv);
+    bool partialLine = false; 
+    FILE *out = stderr; 
+
+    QStringList args = QCoreApplication::arguments();
+    args.removeFirst();
+    Q_FOREACH(QString arg, args) {
+        if (arg == "--partial-line")
+            partialLine = true;
+        else if (arg == "--stdout")
+            out = stdout; 
+        else if (arg == "--stderr")
+            out = stderr; 
+    }
+    if (partialLine) 
+        fprintf(out, "line1\nline2\nline3");
+    else
+        fprintf(out, "line1\nline2\nline3\n");
+
+    fflush(out);
+
+    return 0;
+}
