Il 05/11/2011 08:12, Vincent van Ravesteijn ha scritto:
My feeling says we should acquire all information about which files we need to convert. Then we convert them one by one (or make it parallel) and then after each processed file, we should check whether the thread has been cancelled by the UI or not. If not, we continue. This would also allow us to return progress information to the UI.

I know you're discussing about aborting threads, however this may be related...

In my old patch for aborting a long Find Advanced operation in response to the user pressing [ESC], I had added a couple of methods to Application.h and GuiApplication.{h,cpp}, as in the attached patch (updated to trunk).

I was thinking to recover this functionality for some upcoming release (2.0.x or 2.1.0svn), so I'd like to check whether the GUI interaction model might be (made) compatible with the one of cancelling a background export or not.

AFAIU, the background export goes on in the background, while the user may still work with LyX and modify things, right ? (btw, what happens if the user modifies and saves while it is exporting in the background ?) In the advanced find case, instead, the user is not supposed to keep editing while LyX is searching ... unless you can suggest me a way to avoid crashes due to the cursor jumping suddenly to non-existing locations & the like... perhaps we could have Cursor::fixIfBroken() continuously called...

    T.
Index: src/frontends/Application.h
===================================================================
--- src/frontends/Application.h	(revisione 40132)
+++ src/frontends/Application.h	(copia locale)
@@ -17,6 +17,7 @@
 #include "KeyModifier.h"
 
 #include "support/strfwd.h"
+#include "support/shared_ptr.h"
 
 #include <boost/function.hpp>
 
@@ -239,6 +240,14 @@
 	/// Handle a accented char key sequence
 	/// FIXME: this is only needed for LFUN_ACCENT_* in Text::dispatch()
 	virtual void handleKeyFunc(FuncCode action) = 0;
+
+	/// Start a long operation with some cancel possibility (button or ESC)
+	virtual void startLongOperation() = 0;
+	/// This needs to be periodically called to avoid freezing the GUI
+	virtual bool longOperationCancelled() = 0;
+	/// Stop the long operation mode (i.e., release the GUI)
+	virtual void stopLongOperation() = 0;
+
 };
 
 /// Return the list of loadable formats.
Index: src/frontends/qt4/GuiApplication.h
===================================================================
--- src/frontends/qt4/GuiApplication.h	(revisione 40132)
+++ src/frontends/qt4/GuiApplication.h	(copia locale)
@@ -169,6 +169,13 @@
 	///		not the current buffer
 	void gotoBookmark(unsigned int idx, bool openFile, bool switchToBuffer);
 
+	/// Start a long operation with some cancel possibility (button or ESC)
+	void startLongOperation();
+	/// This needs to be periodically called to avoid freezing the GUI
+	bool longOperationCancelled();
+	/// Stop the long operation mode (i.e., release the GUI)
+	void stopLongOperation();
+
 private Q_SLOTS:
 	///
 	void execBatchCommands();
Index: src/frontends/qt4/GuiApplication.cpp
===================================================================
--- src/frontends/qt4/GuiApplication.cpp	(revisione 40132)
+++ src/frontends/qt4/GuiApplication.cpp	(copia locale)
@@ -80,12 +80,14 @@
 #include <QClipboard>
 #include <QDateTime>
 #include <QDir>
+#include <QEvent>
 #include <QEventLoop>
 #include <QFileOpenEvent>
 #include <QFileInfo>
 #include <QHash>
 #include <QIcon>
 #include <QImageReader>
+#include <QKeyEvent>
 #include <QLocale>
 #include <QLibraryInfo>
 #include <QList>
@@ -98,6 +100,7 @@
 #include <QRegExp>
 #include <QSessionManager>
 #include <QSettings>
+#include <QShowEvent>
 #include <QSocketNotifier>
 #include <QSortFilterProxyModel>
 #include <QStandardItemModel>
@@ -675,6 +678,43 @@
 
 #endif // Q_WS_WIN
 
+
+/// Allows to check whether ESC was pressed during a long operation
+class KeyChecker : public QObject {
+private:
+	bool pressed_;
+public:
+	KeyChecker() {
+		pressed_ = false;
+	}
+	void start() {
+		QCoreApplication::instance()->installEventFilter(this);
+		pressed_ = false;
+	}
+	void stop() {
+		QCoreApplication::instance()->removeEventFilter(this);
+	}
+	bool pressed() {
+		QCoreApplication::processEvents();
+		return pressed_;
+	}
+	bool eventFilter(QObject *obj, QEvent *event) {
+		LYXERR(Debug::ACTION, "Event Type: " << event->type());
+		switch (event->type()) {
+		case QEvent::Show:
+		case QEvent::Hide:
+		case QEvent::Resize:
+			return QObject::eventFilter(obj, event);
+		default:
+			QKeyEvent *keyEvent = dynamic_cast<QKeyEvent*>(event);
+			if (keyEvent && keyEvent->key() == Qt::Key_Escape)
+				pressed_ = true;
+			return true;
+		}
+	}
+};
+
+
 ////////////////////////////////////////////////////////////////////////
 // GuiApplication::Private definition and implementation.
 ////////////////////////////////////////////////////////////////////////
@@ -752,6 +792,9 @@
 	/// WMF Mime handler for Windows clipboard.
 	QWindowsMimeMetafile * wmf_mime_;
 #endif
+
+	/// Allows to check whether ESC was pressed during a long operation
+	KeyChecker key_checker_;
 };
 
 
@@ -762,6 +805,13 @@
 #ifdef Q_WS_MACX
 	closeAllLinkBackLinks();
 #endif
+	delete d->language_model_;
+	QHash<int, SocketNotifier *>::const_iterator it = d->socket_notifiers_.begin();
+	for (; it != d->socket_notifiers_.end(); ++it) {
+		unregisterSocketCallback(it.key());
+		delete it.value();
+	}
+	delete d->global_menubar_;
 	delete d;
 }
 
@@ -2529,6 +2579,21 @@
 }
 
 
+void GuiApplication::startLongOperation() {
+	d->key_checker_.start();
+}
+
+
+bool GuiApplication::longOperationCancelled() {
+	return d->key_checker_.pressed();
+}
+
+
+void GuiApplication::stopLongOperation() {
+	d->key_checker_.stop();
+}
+
+
 ////////////////////////////////////////////////////////////////////////
 //
 // X11 specific stuff goes here...

Reply via email to