Index: kdecore/CMakeLists.txt
===================================================================
--- kdecore/CMakeLists.txt	(revision 891265)
+++ kdecore/CMakeLists.txt	(working copy)
@@ -142,6 +142,7 @@
    io/kdebugdbusiface.cpp
    io/kmessage.cpp
    io/kprocess.cpp
+   io/klinebasedreader.cpp
    io/ksavefile.cpp
    io/ktempdir.cpp
    io/ktemporaryfile.cpp
@@ -372,6 +373,7 @@
    io/kdebug.h
    io/kmessage.h
    io/kprocess.h
+   io/klinebasedreader.h
    io/klockfile.h
    io/ksavefile.h
    io/ktempdir.h
Index: kdecore/io/klinebasedreader.cpp
===================================================================
--- kdecore/io/klinebasedreader.cpp	(revision 0)
+++ kdecore/io/klinebasedreader.cpp	(revision 0)
@@ -0,0 +1,71 @@
+/*
+    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 "klinebasedreader.h"
+
+#include <QtDebug>
+#include <QObject>
+#include <QIODevice>
+
+KLineBasedReader::KLineBasedReader(QIODevice *p)
+{
+    m_p = p;
+    connect(p,SIGNAL(readyRead()),this,SLOT(slotReadyRead()));
+}
+
+KLineBasedReader::~KLineBasedReader()
+{
+    disconnect(m_p,SIGNAL(readyRead()),this,SLOT(slotReadyRead()));
+}
+
+void KLineBasedReader::slotReadyRead()
+{
+    if (m_p->canReadLine())
+        emit readyReadLine();
+}
+ 
+qint64 KLineBasedReader::readLine(char * data, qint64 maxSize)
+{
+    qint64 ret = m_p->readLine(data, maxSize);
+    if (ret <= 0)
+        return ret;
+    if (data[strlen(data)-2] == '\x0d' && data[strlen(data)-1] == '\x0a')
+        data[strlen(data)-2] = '\0';
+    else if (data[strlen(data)-1] == '\x0a')
+        data[strlen(data)-1] = '\0';
+    return ret;
+}
+
+QString KLineBasedReader::readLine (qint64 maxSize)
+{
+    QString data = m_p->readLine(maxSize);
+    if (data.size() == 0)
+        return data;
+    if (data.endsWith("\x0d\x0a"))
+        return data.left(data.size()-2);
+    else if (data.endsWith("\x0a"))
+        return data.left(data.size()-1);
+    else
+        return data;
+}
+
+#include "klinebasedreader.moc"
+ 
\ No newline at end of file
Index: kdecore/io/klinebasedreader.h
===================================================================
--- kdecore/io/klinebasedreader.h	(revision 0)
+++ kdecore/io/klinebasedreader.h	(revision 0)
@@ -0,0 +1,51 @@
+/*
+    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.
+*/
+
+#ifndef KLINE_BASED_READER_H
+#define KLINE_BASED_READER_H
+
+#include <kdecore_export.h>
+
+#include <QObject>
+class QIODevice;
+
+class KDECORE_EXPORT KLineBasedReader : public QObject {
+    Q_OBJECT
+
+public:
+    KLineBasedReader(QIODevice *p);
+    ~KLineBasedReader();
+    qint64 readLine(char * data, qint64 maxSize);
+    QString readLine(qint64 maxSize = 0);
+
+Q_SIGNALS:
+    void readyReadLine(); 
+    
+private Q_SLOTS:
+    void slotReadyRead(); 
+
+private: 
+    QIODevice *m_p;
+};
+    
+    
+    
+#endif
Index: kdecore/tests/CMakeLists.txt
===================================================================
--- kdecore/tests/CMakeLists.txt	(revision 891265)
+++ 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 891265)
+++ 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
@@ -20,20 +21,54 @@
 */
 
 #include <kprocess.h>
+#include <klinebasedreader.h>
 #include <qtest_kde.h>
 
 #include <stdio.h>
 #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_linebasedreader();
+
+    void slotPrintOutput();
+    void slotPrintError();
+    void slotFinished(int exitCode, QProcess::ExitStatus exitStatus);
+
+    void slotPrintLineChar();
+    void slotPrintLineError();
+    void slotPrintLineQString();
+    void slotFinishedLines(int exitCode, QProcess::ExitStatus exitStatus);
+
+    void cleanup(); 
+    
+private:
+    QEventLoop loop;
+    QStringList outData;
 };
 
+KLineBasedReader *reader;
+KProcess *process;
+
 // IOCCC nomination pending
 
 static char **gargv;
@@ -60,6 +95,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 +129,109 @@
 #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)
+{
+    qDebug() << __FUNCTION__;
+    loop.exit();
+    disconnect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(slotPrintOutput()));
+    disconnect(process,SIGNAL(readyReadStandardError()),this,SLOT(slotPrintError()));
+    disconnect(process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotFinished(int,QProcess::ExitStatus)));
+
+    QVERIFY(outData.size() == 1);
+    QString a = QLatin1String("line1" NL "line2" NL "line3");
+    QCOMPARE(outData.at(0),a);
+}
+
+void KProcessTest::test_signals()
+{
+    qDebug() << __FUNCTION__;
+    outData.clear();
+    process = new KProcess;
+    process->setOutputChannelMode(KProcess::SeparateChannels);
+    connect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(slotPrintOutput()));
+    connect(process,SIGNAL(readyReadStandardError()),this,SLOT(slotPrintError()));
+    connect(process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotFinished(int,QProcess::ExitStatus)));
+    process->setProgram("kprocesstesthelper", QStringList() << "--partial-line" << "--stdout");
+    process->start();   
+    loop.exec();
+}
+
+void KProcessTest::slotPrintLineChar()
+{
+    qDebug() << __FUNCTION__;
+    char data[1024];
+    while(reader->readLine(data,sizeof(data)-1) > 0) {
+        qDebug() << "data" << data;
+        outData << data;
+    }
+}
+
+void KProcessTest::slotPrintLineError()
+{
+    KProcess *p = static_cast<KProcess*>(sender());
+    qDebug() << p->readAllStandardError();
+}
+
+void KProcessTest::slotPrintLineQString()
+{
+    qDebug() << __FUNCTION__;
+    while(1) {
+        QString data = reader->readLine();
+        if (data.size() == 0)
+            break;
+        qDebug() << data;
+        outData << data;
+    }
+}
+
+void KProcessTest::slotFinishedLines (int exitCode, QProcess::ExitStatus exitStatus)
+{
+    qDebug() << __FUNCTION__;
+    loop.exit();
+    disconnect(reader,SIGNAL(readyReadLine()),this,SLOT(slotPrintLineChar()));
+    disconnect(process,SIGNAL(readyReadStandardError()),this,SLOT(slotPrintLineError()));
+    disconnect(process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotFinishedLines(int,QProcess::ExitStatus)));
+    
+    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_linebasedreader()
+{
+    outData.clear();
+    process = new KProcess;
+    reader = new KLineBasedReader(process); 
+    process->setOutputChannelMode(KProcess::SeparateChannels);
+    connect(reader,SIGNAL(readyReadLine()),this,SLOT(slotPrintLineChar()));
+    connect(process,SIGNAL(readyReadStandardError()),this,SLOT(slotPrintLineError()));
+    connect(process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(slotFinishedLines(int,QProcess::ExitStatus)));
+    process->setProgram("kprocesstesthelper", QStringList() << "--partial-line" << "--stdout");
+    process->start();
+    loop.exec();
+}
+
+void KProcessTest::cleanup()
+{
+  //delete process;
+  loop.exit();
+  process->deleteLater();
+  reader->deleteLater();
+}
+
 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;
+}
