Hi, all,

Back to trying to get some way of canceling background export reliably. I'm playing with patches Peter attached earlier, but am also working on a different sort of solution. The attached is some playing, but it won't compile. I keep getting an "undeclared reference to vtable" error. Any help?

Richard

>From 2985d49036f35685e34b46fdcc813a463eaaeb0d Mon Sep 17 00:00:00 2001
From: Richard Heck <rgh...@lyx.org>
Date: Tue, 22 May 2012 15:26:29 -0400
Subject: [PATCH] Basic code to try throwing exceptions in the export thread.

---
 lib/ui/stdmenus.inc           |    1 +
 lib/ui/stdtoolbars.inc        |    1 +
 src/FuncCode.h                |    1 +
 src/LyXAction.cpp             |    9 ++++++
 src/frontends/qt4/GuiView.cpp |   56 +++++++++++++++++++++++++++++-----------
 src/frontends/qt4/GuiView.h   |    3 ++
 6 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/lib/ui/stdmenus.inc b/lib/ui/stdmenus.inc
index b7e1f03..7e2fad2 100644
--- a/lib/ui/stdmenus.inc
+++ b/lib/ui/stdmenus.inc
@@ -327,6 +327,7 @@ Menuset
 		UpdateFormats
 		OptItem "View Master Document|M" "master-buffer-view"
 		OptItem "Update Master Document|a" "master-buffer-update"
+		OptItem "Cancel Export Process" "export-cancel"
 		Separator
 		Item "Split View Into Left and Right Half|i" "split-view horizontal"
 		Item "Split View Into Upper and Lower Half|e" "split-view vertical"
diff --git a/lib/ui/stdtoolbars.inc b/lib/ui/stdtoolbars.inc
index 4190760..cc29079 100644
--- a/lib/ui/stdtoolbars.inc
+++ b/lib/ui/stdtoolbars.inc
@@ -102,6 +102,7 @@ ToolbarSet
 		Item "Update" "buffer-update"
 		Item "View master document" "master-buffer-view"
 		Item "Update master document" "master-buffer-update"
+#		Item "Cancel export" "export-cancel"
 		Item "Enable Forward/Reverse Search" "buffer-toggle-output-sync"
 		Separator
 		StickyPopupMenu "view-others" "View other formats"
diff --git a/src/FuncCode.h b/src/FuncCode.h
index 9a7b06e..c1c8249 100644
--- a/src/FuncCode.h
+++ b/src/FuncCode.h
@@ -452,6 +452,7 @@ enum FuncCode
 	// 350
 	LFUN_CLIPBOARD_PASTE_SIMPLE,	// tommaso, 20111028
 	LFUN_IPA_INSERT,                // spitz, 20120305
+	LFUN_EXPORT_CANCEL,             // rgh, 20111102
 
 	LFUN_LASTACTION                 // end of the table
 };
diff --git a/src/LyXAction.cpp b/src/LyXAction.cpp
index 39018ce..d1ac1de 100644
--- a/src/LyXAction.cpp
+++ b/src/LyXAction.cpp
@@ -3005,6 +3005,15 @@ void LyXAction::init()
  */
 		{ LFUN_BUFFER_EXPORT_AS, "buffer-export-as", ReadOnly, Buffer },
 /*!
+ * \var lyx::FuncCode lyx::LFUN_EXPORT_CANCEL
+ * \li Action: Cancels a background export process
+ * \li Syntax: export-cancel
+ * \li Origin: rgh, 2 November 2011
+ * \endvar
+ */
+		{ LFUN_EXPORT_CANCEL, "export-cancel", ReadOnly, Buffer },
+
+/*!
  * \var lyx::FuncCode lyx::LFUN_BUFFER_PRINT
  * \li Action: Prints the current document.
  * \li Notion: Many settings can be given via the preferences dialog.
diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
index f6c6a93..261575d 100644
--- a/src/frontends/qt4/GuiView.cpp
+++ b/src/frontends/qt4/GuiView.cpp
@@ -392,19 +392,19 @@ public:
 #endif
 
 	static QSet<Buffer const *> busyBuffers;
-	static Buffer::ExportStatus previewAndDestroy(Buffer const * orig, Buffer * buffer, string const & format);
-	static Buffer::ExportStatus exportAndDestroy(Buffer const * orig, Buffer * buffer, string const & format);
-	static Buffer::ExportStatus compileAndDestroy(Buffer const * orig, Buffer * buffer, string const & format);
+	static Buffer::ExportStatus previewAndDestroy(GuiView * gv, Buffer const * orig, Buffer * buffer, string const & format);
+	static Buffer::ExportStatus exportAndDestroy(GuiView * gv, Buffer const * orig, Buffer * buffer, string const & format);
+	static Buffer::ExportStatus compileAndDestroy(GuiView * gv, Buffer const * orig, Buffer * buffer, string const & format);
 	static docstring autosaveAndDestroy(Buffer const * orig, Buffer * buffer);
 
 	template<class T>
-	static Buffer::ExportStatus runAndDestroy(const T& func, Buffer const * orig, Buffer * buffer, string const & format);
+	static Buffer::ExportStatus runAndDestroy(GuiView * gv, const T& func, Buffer const * orig, Buffer * buffer, string const & format);
 
 	// TODO syncFunc/previewFunc: use bind
 	bool asyncBufferProcessing(string const & argument,
 				   Buffer const * used_buffer,
 				   docstring const & msg,
-				   Buffer::ExportStatus (*asyncFunc)(Buffer const *, Buffer *, string const &),
+				   Buffer::ExportStatus (*asyncFunc)(GuiView *, Buffer const *, Buffer *, string const &),
 				   Buffer::ExportStatus (Buffer::*syncFunc)(string const &, bool) const,
 				   Buffer::ExportStatus (Buffer::*previewFunc)(string const &) const);
 
@@ -1684,6 +1684,10 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag)
 		enable = doc_buffer;
 		break;
 
+	case LFUN_EXPORT_CANCEL:
+		enable = d.processing_thread_watcher_.isRunning();
+		break;
+
 	case LFUN_BUFFER_CLOSE:
 		enable = doc_buffer;
 		break;
@@ -3031,9 +3035,22 @@ bool GuiView::goToFileRow(string const & argument)
 
 
 #if (QT_VERSION >= 0x040400)
+
+class CancelException : public std::exception {};
+
+class Canceler : public QObject
+{
+	Q_OBJECT
+public Q_SLOTS:
+	void cancel() { throw CancelException(); }
+};
+
+
 template<class T>
-Buffer::ExportStatus GuiView::GuiViewPrivate::runAndDestroy(const T& func, Buffer const * orig, Buffer * clone, string const & format)
+Buffer::ExportStatus GuiView::GuiViewPrivate::runAndDestroy(GuiView * gv, const T& func, Buffer const * orig, Buffer * clone, string const & format)
 {
+	Canceler canceler;
+	connect(gv, SIGNAL(cancelBackgroundProcessing()), &canceler, SLOT(cancel()));
 	Buffer::ExportStatus const status = func(format);
 
 	// the cloning operation will have produced a clone of the entire set of
@@ -3045,24 +3062,24 @@ Buffer::ExportStatus GuiView::GuiViewPrivate::runAndDestroy(const T& func, Buffe
 }
 
 
-Buffer::ExportStatus GuiView::GuiViewPrivate::compileAndDestroy(Buffer const * orig, Buffer * clone, string const & format)
+Buffer::ExportStatus GuiView::GuiViewPrivate::compileAndDestroy(GuiView * gv, Buffer const * orig, Buffer * clone, string const & format)
 {
 	Buffer::ExportStatus (Buffer::* mem_func)(std::string const &, bool) const = &Buffer::doExport;
-	return runAndDestroy(bind(mem_func, clone, _1, true), orig, clone, format);
+	return runAndDestroy(gv, bind(mem_func, clone, _1, true), orig, clone, format);
 }
 
 
-Buffer::ExportStatus GuiView::GuiViewPrivate::exportAndDestroy(Buffer const * orig, Buffer * clone, string const & format)
+Buffer::ExportStatus GuiView::GuiViewPrivate::exportAndDestroy(GuiView * gv, Buffer const * orig, Buffer * clone, string const & format)
 {
 	Buffer::ExportStatus (Buffer::* mem_func)(std::string const &, bool) const = &Buffer::doExport;
-	return runAndDestroy(bind(mem_func, clone, _1, false), orig, clone, format);
+	return runAndDestroy(gv, bind(mem_func, clone, _1, false), orig, clone, format);
 }
 
 
-Buffer::ExportStatus GuiView::GuiViewPrivate::previewAndDestroy(Buffer const * orig, Buffer * clone, string const & format)
+Buffer::ExportStatus GuiView::GuiViewPrivate::previewAndDestroy(GuiView * gv, Buffer const * orig, Buffer * clone, string const & format)
 {
 	Buffer::ExportStatus (Buffer::* mem_func)(std::string const &) const = &Buffer::preview;
-	return runAndDestroy(bind(mem_func, clone, _1), orig, clone, format);
+	return runAndDestroy(gv, bind(mem_func, clone, _1), orig, clone, format);
 }
 
 #else
@@ -3070,21 +3087,21 @@ Buffer::ExportStatus GuiView::GuiViewPrivate::previewAndDestroy(Buffer const * o
 // not used, but the linker needs them
 
 Buffer::ExportStatus GuiView::GuiViewPrivate::compileAndDestroy(
-		Buffer const *, Buffer *, string const &)
+		GuiView *, Buffer const *, Buffer *, string const &)
 {
 	return Buffer::ExportSuccess;
 }
 
 
 Buffer::ExportStatus GuiView::GuiViewPrivate::exportAndDestroy(
-		Buffer const *, Buffer *, string const &)
+		GuiView *, Buffer const *, Buffer *, string const &)
 {
 	return Buffer::ExportSuccess;
 }
 
 
 Buffer::ExportStatus GuiView::GuiViewPrivate::previewAndDestroy(
-		Buffer const *, Buffer *, string const &)
+		GuiView *, Buffer const *, Buffer *, string const &)
 {
 	return Buffer::ExportSuccess;
 }
@@ -3096,7 +3113,7 @@ bool GuiView::GuiViewPrivate::asyncBufferProcessing(
 			   string const & argument,
 			   Buffer const * used_buffer,
 			   docstring const & msg,
-			   Buffer::ExportStatus (*asyncFunc)(Buffer const *, Buffer *, string const &),
+			   Buffer::ExportStatus (*asyncFunc)(GuiView *, Buffer const *, Buffer *, string const &),
 			   Buffer::ExportStatus (Buffer::*syncFunc)(string const &, bool) const,
 			   Buffer::ExportStatus (Buffer::*previewFunc)(string const &) const)
 {
@@ -3121,6 +3138,7 @@ bool GuiView::GuiViewPrivate::asyncBufferProcessing(
 	}
 	QFuture<Buffer::ExportStatus> f = QtConcurrent::run(
 				asyncFunc,
+	      gv_,
 				used_buffer,
 				cloned_buffer,
 				format);
@@ -3281,6 +3299,12 @@ void GuiView::dispatch(FuncRequest const & cmd, DispatchResult & dr)
 						0, &Buffer::preview);
 			break;
 		}
+		case LFUN_EXPORT_CANCEL: {
+#if QT_VERSION >= 0x040400
+			cancelBackgroundProcessing();
+#endif
+			break;
+		}
 		case LFUN_BUFFER_SWITCH: {
 			string const file_name = to_utf8(cmd.argument());
 			if (!FileName::isAbsolute(file_name)) {
diff --git a/src/frontends/qt4/GuiView.h b/src/frontends/qt4/GuiView.h
index bc7b9ec..7603074 100644
--- a/src/frontends/qt4/GuiView.h
+++ b/src/frontends/qt4/GuiView.h
@@ -203,6 +203,9 @@ public:
 Q_SIGNALS:
 	void closing(int);
 	void triggerShowDialog(QString const & qname, QString const & qdata, Inset * inset);
+#if QT_VERSION >= 0x040400
+	void cancelBackgroundProcessing();
+#endif
 
 public Q_SLOTS:
 	///
-- 
1.7.7.6

Reply via email to