folgendes nochmal zum hintergrund:
es handelt sich bei der datei um eine text datei (logfile) was mehrere 100mb gross sein kann. das einlesen geschieht wie gesagt in einem thread. hierbei habe ich bereits folgende ansaetze probiert, die NICHT zufriedenstellend waren:
1. bei jedem einlese-schritt per signal slot das aktuelle einlese-datum (eine zeile der datei) an main-gui geschickt und ins QTextEdit gepastet
2. es wird erst ein signal an die main-gui gesendet, wenn alles eingelesen ist und der gesamte lese-inhalt (QString) übersendet.
nachteile beider ansaetze:
1. die gui friert ein, da sie alle naselang ein signal abarbeiten muss (es wird halt recht schnell eingelesen, selbst bei groesseren chunks (mehrere 100 oder 1000 zeilen) bekomme ich beim einfuegen in das QTextEdit ein problem (crasht mir aufgrund der imensen string-laenge).
2. aehnlich wie bei 1. ist der uebermittelte (riesige) QString schlecht einzufuegen (anwendung crasht bei insertPlainText(..)
Folgender (aktuellster) Ansatz wurde mir nahegelegt, jedoch fuehrt dieser wie gesagt auch zu einem crash:
Es wird beim einlesen im worker-thread ein QTextDocument befuellt. Dieses muss nun in den main-thread (an die gui) uebermittelt werden.
das einfuegen/einlesen klappt problemlos. jedoch crasht meine anwendung wenn ich in der main-gui das vom worker-thread modifizierte QTextDocument als aktuelles dokument setzen moechte.
Die QObject::moveToThread(..) methode ist in diesem kontext wichtig, bin mir aber nicht sicher ob ich sie richtig verwende.
Hier mein Code zu meiner fileloader klasse (die CLogfile Klasse kann ignoriert werden. die GetNextLines(lines, x) methode liefert aus einer textdatei die naechsten x zeilen und speichert sie in lines):
Code: Alles auswählen
// //////////////////////////////////////////
class FileLoader : public QThread
// //////////////////////////////////////////
{
Q_OBJECT
// //////////////////////////////
public:
// //////////////////////////////
FileLoader();
~FileLoader();
void Abort(){abort=true;}
signals:
void Progress(double);
void WorkDone(QTextDocument *);
protected:
void run();
// //////////////////////////////
private:
// //////////////////////////////
CLogFile logfile;
QTextDocument *doc;
bool abort;
};
Code: Alles auswählen
//// //////////////////////////////////
FileLoader::FileLoader()
// //////////////////////////////////
{
doc = new QTextDocument();
}
//// //////////////////////////////////
FileLoader::~FileLoader()
// //////////////////////////////////
{
}
// //////////////////////////////////
void FileLoader::run()
// //////////////////////////////////
{
abort = false;
logfile.Open("big.log");
if( !logfile.IsOpen() )
return;
doc->moveToThread(this);
QTextCursor cursor(doc);
double rate = 0 ;
ulong filesize = logfile.GetFileSize();
string content ;
while(logfile.GetNextLines(content, 1000))
{
cursor.movePosition(QTextCursor::End);
cursor.insertText(content.c_str());
content.clear();
if(abort)
break;
ulong gc = logfile.GCount();
rate = (double)gc/(double)filesize;
rate *= 100;
emit Progress(rate);
}
emit WorkDone(doc);
logfile.Close();
}
meine main-gui sieht so aus:
Code: Alles auswählen
// //////////////////////////////////////////
class MainWindow : public QMainWindow
// //////////////////////////////////////////
{
Q_OBJECT
// //////////////////////
public:
// //////////////////////
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void UpdateFileLoadProgress(double);
void PutDoc(QTextDocument *);
// //////////////////////
private:
// //////////////////////
Ui::MainWindow *ui;
FileLoader fileloader;
QProgressBar progressbar;
// //////////////////////
private slots:
// //////////////////////
void on_pushButton_2_clicked();
void on_pushButton_clicked();
};
und inhalt der entsprechenden cpp-datei:
Code: Alles auswählen
// //////////////////////////////////
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
// //////////////////////////////////
{
ui->setupUi(this);
QObject::connect(&fileloader, SIGNAL(Progress(double)), this, SLOT(UpdateFileLoadProgress(double)));
QObject::connect(&fileloader, SIGNAL(WorkDone(QTextDocument *)),this, SLOT(PutDoc(QTextDocument *)));
statusBar()->addPermanentWidget(&progressbar);
progressbar.setVisible(false);
progressbar.setRange(0,100);
}
// //////////////////////////////////
MainWindow::~MainWindow()
// //////////////////////////////////
{
delete ui;
}
// //////////////////////////////////
void MainWindow::PutDoc(QTextDocument *doc)
// //////////////////////////////////
{
if(!doc)
return;
doc->moveToThread(QApplication::instance()->thread());
ui->textEdit->setDocument(doc);
progressbar.setVisible(false);
}
// //////////////////////////////////
void MainWindow::UpdateFileLoadProgress(double rate)
// //////////////////////////////////
{
progressbar.setValue((ulong)rate);
}
// //////////////////////////////////
void MainWindow::on_pushButton_clicked()
// //////////////////////////////////
{
ui->textEdit->clear();
progressbar.setVisible(true);
fileloader.start();
}
// //////////////////////////////////
void MainWindow::on_pushButton_2_clicked()
// //////////////////////////////////
{
fileloader.Abort();
}
crashen tut es in der slot-methode PutDoc(..) in der zeile
den trace habe ich als anhang (gif-bild) eingefuegt.