[Uml-devel] KDE/kdesdk/umbrello/umbrello/codeimpwizard

Ralf Habacker ralf.habacker at gmail.com
Mon Dec 26 10:03:19 UTC 2011


SVN commit 1270601 by habacker:

refactored import processing to a signal/slot based approach

There is also an additional try to implement threading support, which
do not work because there are runtime errors reporting that objects
derived from QObject could not be called in a different thread.

No idea how to solve.

 M  +74 -19    codeimpstatuspage.cpp  
 M  +11 -3     codeimpstatuspage.h  
 M  +3 -1      codeimpthread.cpp  
 M  +4 -1      codeimpthread.h  


--- trunk/KDE/kdesdk/umbrello/umbrello/codeimpwizard/codeimpstatuspage.cpp #1270600:1270601
@@ -17,6 +17,10 @@
     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
+
+// do not work because there are runtime errors reporting that
+// objects derived from QObject could not be called in a different thread
+// #define ENABLE_IMPORT_THREAD
 #include "codeimpstatuspage.h"
 
 // app includes
@@ -40,7 +44,8 @@
  */
 CodeImpStatusPage::CodeImpStatusPage(QWidget *parent)
   : QWizardPage(parent),
-    m_workDone(false)
+    m_workDone(false),
+    m_index(0)
 {
     setTitle(i18n("Status of Code Importing Progress"));
     setSubTitle(i18n("Press the button 'Start import' to start the code import.\nCheck the success state for every class."));
@@ -63,6 +68,9 @@
  */
 CodeImpStatusPage::~CodeImpStatusPage()
 {
+#ifdef ENABLE_IMPORT_THREAD
+    delete m_thread;
+#endif
 }
 
 /**
@@ -113,31 +121,58 @@
     setCommitPage(true);  //:TODO: disable back and cancel button ?
 
     UMLDoc* doc = UMLApp::app()->document();
+    doc->setLoading(true);
 
     ui_textEditLogger->setHtml(i18n("<b>Code import of %1 files:</b><br>", m_files.size()));
+    m_index = 0;
+    m_workDone = false;
+#ifdef ENABLE_IMPORT_THREAD
+    m_thread = new QThread;
+    //connect(thread, SIGNAL(started()), this, SLOT(importCodeFile()));
+    connect(m_thread, SIGNAL(finished()), this, SLOT(importCodeFile()));
+    connect(m_thread, SIGNAL(terminated()), this, SLOT(importCodeStop()));
+#endif
+    importCodeFile();
+}
 
-    foreach (const QFileInfo& file, m_files) {
-        messageToLog(file.fileName(), i18n("importing file ..."));
-        CodeImpThread* worker = new CodeImpThread(file);
+void CodeImpStatusPage::importCodeFile()
+{
+    // all files done
+    if (m_index >= m_files.size()) {
+        messageToLog(m_file.fileName(), i18n("importing file ... DONE<br>"));
+        updateStatus(m_file.fileName(), i18n("Import Done"));
+        importCodeFinish();
+        return;
+    }
+    // at least one file done
+    else if (m_index > 0) {
+        messageToLog(m_file.fileName(), i18n("importing file ... DONE<br>"));
+        updateStatus(m_file.fileName(), i18n("Import Done"));
+    }
+
+    m_file = m_files.at(m_index++);
+    messageToLog(m_file.fileName(), i18n("importing file ..."));
+    CodeImpThread* worker = new CodeImpThread(m_file);
         connect(worker, SIGNAL(messageToWiz(QString,QString)), this, SLOT(updateStatus(QString,QString)));
         connect(worker, SIGNAL(messageToLog(QString,QString)), this, SLOT(messageToLog(QString,QString)));
         connect(worker, SIGNAL(messageToApp(QString)), this, SLOT(messageToApp(QString)));
-#if 0
-        worker->start();
-uDebug() << "****** starting task for " << file.fileName();
-        worker->wait();  //:TODO: better solution - not blocking
-uDebug() << "****** task done for " << file.fileName();
+#ifndef ENABLE_IMPORT_THREAD
+    connect(worker, SIGNAL(finished()), this, SLOT(importCodeFile()));
+    connect(worker, SIGNAL(aborted()), this, SLOT(importCodeStop()));
+    worker->run();
+    worker->deleteLater();
 #else
-        ClassImport *classImporter = ClassImport::createImporterByFileExt(file.fileName(), worker);
-        QString fileName = file.absoluteFilePath();
-        if (classImporter) {
-            classImporter->importFile(fileName);
-            delete classImporter;
-        }
+    worker->moveToThread(m_thread);
+    m_thread->start();
+    QMetaObject::invokeMethod(worker, "run", Qt::QueuedConnection);
+    // FIXME: when to delete worker and m_thread
 #endif
-        messageToLog(file.fileName(), i18n("importing file ... DONE<br>"));
-        updateStatus(file.fileName(), i18n("Import Done"));
+    uDebug() << "****** starting task for " << m_file.fileName();
     }
+
+void CodeImpStatusPage::importCodeFinish()
+{
+    UMLDoc* doc = UMLApp::app()->document();
     doc->setLoading(false);
     // Modification is set after the import is made, because the file was modified when adding the classes.
     // Allowing undo of the whole class importing. I think it eats a lot of memory.
@@ -147,6 +182,10 @@
     m_workDone = true;
     setFinalPage(true);
     emit completeChanged();
+#ifdef ENABLE_IMPORT_THREAD
+    delete m_thread;
+    m_thread = 0;
+#endif
 }
 
 /**
@@ -162,9 +201,25 @@
 /**
  * Slot for the stop button. Stops the code import.
  */
-void CodeImpStatusPage::importStop()
+void CodeImpStatusPage::importCodeStop()
 {
-    uDebug() << "TODO: Not yet implemented!";
+    messageToLog(m_file.fileName(), i18n("importing file ... stopped<br>"));
+    updateStatus(m_file.fileName(), i18n("Import stopped"));
+
+    UMLDoc* doc = UMLApp::app()->document();
+    doc->setLoading(false);
+    // Modification is set after the import is made, because the file was modified when adding the classes.
+    // Allowing undo of the whole class importing. I think it eats a lot of memory.
+    // Setting the modification, but without allowing undo.
+    doc->setModified(true);
+
+    m_workDone = true;
+    setFinalPage(true);
+    emit completeChanged();
+#ifdef ENABLE_IMPORT_THREAD
+    delete m_thread;
+    m_thread = 0;
+#endif
 }
 
 /**
--- trunk/KDE/kdesdk/umbrello/umbrello/codeimpwizard/codeimpstatuspage.h #1270600:1270601
@@ -33,6 +33,7 @@
 #include <QtGui/QHBoxLayout>
 #include <QtCore/QFileInfo>
 
+class QThread;
 /**
  * This class is used in the code importing wizard.
  * It represents the second page where files are listed and imported by parsing.
@@ -50,12 +51,19 @@
     bool isComplete() const;
 
 private:
-    QList<QFileInfo> m_files;
+    QList<QFileInfo> m_files; ///< list of files to import
     bool             m_workDone;
+    int              m_index; ///< index in m_files
+    QFileInfo        m_file; ///< current file
+#ifdef ENABLE_IMPORT_THREAD
+    QThread         *m_thread;
+#endif
 
 protected slots:
-    void importCode();
-    void importStop();
+    void importCode(); ///< start importing
+    void importCodeFile(); ///< import single file
+    void importCodeFinish(); ///< finish importing
+    void importCodeStop(); ///< cancel importing
     void updateStatus(const QString& file, const QString& text);
     void messageToLog(const QString& file, const QString& text);
     void messageToApp(const QString& text);
--- trunk/KDE/kdesdk/umbrello/umbrello/codeimpwizard/codeimpthread.cpp #1270600:1270601
@@ -30,7 +30,7 @@
  * @param fileNames   name of imported files
  */
 CodeImpThread::CodeImpThread(QFileInfo file, QObject* parent)
-  : //QThread(parent),
+  : QObject(parent),
     m_file(file)
 {
     connect(this, SIGNAL(askQuestion(QString,QMessageBox::StandardButton*)),
@@ -60,10 +60,12 @@
         emit messageToApp(i18nc("show Ready on status bar", "Ready."));
         emit messageToWiz(m_file.fileName(), "finished");
         emit messageToLog(m_file.fileName(), "...stop import");
+        emit finished();
     }
     else {
         emit messageToWiz(m_file.fileName(), "aborted");
         emit messageToApp(i18n("No code importer for file: %1", fileName));
+        emit aborted();
     }
 }
 
--- trunk/KDE/kdesdk/umbrello/umbrello/codeimpwizard/codeimpthread.h #1270600:1270601
@@ -33,13 +33,14 @@
  * TODO: For a start it is only a QObject and is used to signals messages.
  * @author Andi Fischer
  */
-class CodeImpThread : public QObject //QThread
+class CodeImpThread : public QObject
 {
     Q_OBJECT
 public:
     explicit CodeImpThread(QFileInfo file, QObject* parent = 0);
     virtual ~CodeImpThread();
 
+public slots:
     virtual void run();
 
     int emitAskQuestion(const QString& question);
@@ -50,6 +51,8 @@
     void messageToWiz(const QString& file, const QString& text);
     void messageToLog(const QString& file, const QString& text);
     void messageToApp(const QString& text);
+    void finished();
+    void aborted();
 
 private slots:
     void questionAsked(const QString& question, QMessageBox::StandardButton* answer);




More information about the umbrello-devel mailing list