diff --git a/src/part/dotgraphview.h b/src/part/dotgraphview.h --- a/src/part/dotgraphview.h +++ b/src/part/dotgraphview.h @@ -83,6 +83,7 @@ bool KGRAPHVIEWER_EXPORT loadDot(const QString& dotFileName); bool KGRAPHVIEWER_EXPORT loadLibrary(const QString& dotFileName); + bool KGRAPHVIEWER_EXPORT loadLibrarySync(const QString& dotFileName); bool loadLibrary(graph_t* graph, const QString& layoutCommand = "dot"); void readViewConfig(); diff --git a/src/part/dotgraphview.cpp b/src/part/dotgraphview.cpp --- a/src/part/dotgraphview.cpp +++ b/src/part/dotgraphview.cpp @@ -896,6 +896,43 @@ return true; } +bool DotGraphView::loadLibrarySync(const QString& dotFileName) +{ + qCDebug(KGRAPHVIEWERLIB_LOG) << "loading sync: '" << dotFileName << "'"; + Q_D(DotGraphView); + if (d->m_canvas) + d->m_canvas->clear(); + QGraphicsSimpleTextItem* loadingLabel = d->m_canvas->addSimpleText(i18n("graph %1 is getting loaded...", dotFileName)); + loadingLabel->setZValue(100); + centerOn(loadingLabel); + + qCDebug(KGRAPHVIEWERLIB_LOG) << dotFileName; + FILE* fp = fopen(dotFileName.toUtf8().data(), "r"); + if (!fp) { + qCWarning(KGRAPHVIEWERLIB_LOG) << "Failed to open file " << dotFileName; + return false; + } + graph_t* graph = agread(fp, nullptr); + if (!graph) { + qCWarning(KGRAPHVIEWERLIB_LOG) << "Failed to read file, retrying to work around graphviz bug(?)"; + rewind(fp); + graph = agread(fp, nullptr); + } + fclose(fp); + if (!graph) { + qCWarning(KGRAPHVIEWERLIB_LOG) << "Failed to read file " << dotFileName; + return false; + } + + QString layoutCommand = (d->m_graph ? d->m_graph->layoutCommand() : QString()); + if (layoutCommand.isEmpty()) { + layoutCommand = d->m_graph ? d->m_graph->chooseLayoutProgramForFile(dotFileName) : "dot"; + } + d->m_layoutThread.layoutGraph(graph, layoutCommand); + + return true; +} + bool DotGraphView::loadLibrary(const QString& dotFileName) { qCDebug(KGRAPHVIEWERLIB_LOG) << "'" << dotFileName << "'"; diff --git a/src/part/kgraphviewer_part.cpp b/src/part/kgraphviewer_part.cpp --- a/src/part/kgraphviewer_part.cpp +++ b/src/part/kgraphviewer_part.cpp @@ -192,7 +192,8 @@ return false; break; case InternalLibrary: - if (!d->m_widget->loadLibrary(localFilePath())) + // kpart expects loading to be done sync in this method + if (!d->m_widget->loadLibrarySync(localFilePath())) return false; break; default: diff --git a/src/part/loadagraphthread.cpp b/src/part/loadagraphthread.cpp --- a/src/part/loadagraphthread.cpp +++ b/src/part/loadagraphthread.cpp @@ -47,6 +47,17 @@ void LoadAGraphThread::loadFile(const QString& dotFileName) { + // FIXME: deadlock possible + // if thread is still running or queued finished signal of the thread has not + // yet been delivered so its handler who would release the semaphore, + // then the semaphore can not be acquired and this will block the (main) thread + // which called LoadAGraphThread::loadFile(). + // That one though very much might have also been the one which before invoked this + // method and thus the still running thread or yet-to-be delivered finished signal. + // But being blocked now, it will not reach its event loop where the queued finished + // signal of the thread would be processed and delivered, so in the further processing + // by the signal handler this semaphore would be released + // -> blocked ourselves without any escape sem.acquire(); m_dotFileName = dotFileName; m_g = nullptr;