Author: tommaso
Date: Wed Mar  7 00:21:12 2012
New Revision: 40877
URL: http://www.lyx.org/trac/changeset/40877

Log:
Now ESC cancels long Advanced Find and Replace operations.
(see #7217 and #7965 for related issues and discussion)

Modified:
   lyx-devel/trunk/src/frontends/Application.h
   lyx-devel/trunk/src/frontends/qt4/FindAndReplace.cpp
   lyx-devel/trunk/src/frontends/qt4/GuiApplication.cpp
   lyx-devel/trunk/src/frontends/qt4/GuiApplication.h
   lyx-devel/trunk/src/lyxfind.cpp

Modified: lyx-devel/trunk/src/frontends/Application.h
==============================================================================
--- lyx-devel/trunk/src/frontends/Application.h Wed Mar  7 00:12:36 2012        
(r40876)
+++ lyx-devel/trunk/src/frontends/Application.h Wed Mar  7 00:21:12 2012        
(r40877)
@@ -239,6 +239,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.

Modified: lyx-devel/trunk/src/frontends/qt4/FindAndReplace.cpp
==============================================================================
--- lyx-devel/trunk/src/frontends/qt4/FindAndReplace.cpp        Wed Mar  7 
00:12:36 2012        (r40876)
+++ lyx-devel/trunk/src/frontends/qt4/FindAndReplace.cpp        Wed Mar  7 
00:21:12 2012        (r40877)
@@ -294,6 +294,8 @@
        oss << opt;
        FuncRequest cmd(LFUN_WORD_FINDADV, from_utf8(oss.str()));
 
+       view_.message(_("Advanced search started: please wait . . ."));
+       theApp()->startLongOperation();
        view_.setBusy(true);
        if (opt.scope == FindAndReplaceOptions::S_ALL_MANUALS) {
                vector<string> const & v = allManualsFiles();
@@ -301,7 +303,9 @@
                        FileName const & fname = FileName(*v.begin());
                        if (!theBufferList().exists(fname)) {
                                guiApp->currentView()->setBusy(false);
+                               theApp()->stopLongOperation();
                                guiApp->currentView()->loadDocument(fname, 
false);
+                               theApp()->startLongOperation();
                                guiApp->currentView()->setBusy(true);
                        }
                        buf = theBufferList().getBuffer(fname);
@@ -327,10 +331,19 @@
                        if (replace_all)
                                continue;
                        view_.setBusy(false);
+                       theApp()->stopLongOperation();
                        return true;
                } else if (replace_all)
                        bv->clearSelection();
 
+               if (theApp()->longOperationCancelled()) {
+                       // Search aborted by user
+                       view_.message(_("Advanced search cancelled by user"));
+                       view_.setBusy(false);
+                       theApp()->stopLongOperation();
+                       return false;
+               }
+
                // No match found in current buffer (however old selection 
might have been replaced)
                // select next buffer in scope, if any
                bool const prompt = nextPrevBuffer(buf, opt);
@@ -341,9 +354,11 @@
                                break;
                        docstring q = getQuestionString(opt);
                        view_.setBusy(false);
+                       theApp()->stopLongOperation();
                        wrap_answer = frontend::Alert::prompt(
                                _("Wrap search?"), q,
                                0, 1, _("&Yes"), _("&No"));
+                       theApp()->startLongOperation();
                        view_.setBusy(true);
                        if (wrap_answer == 1)
                                break;
@@ -373,6 +388,7 @@
                cur_orig.pos() = cur_orig.lastpos();
        bv->cursor().setCursor(cur_orig);
        view_.setBusy(false);
+       theApp()->stopLongOperation();
        return false;
 }
 

Modified: lyx-devel/trunk/src/frontends/qt4/GuiApplication.cpp
==============================================================================
--- lyx-devel/trunk/src/frontends/qt4/GuiApplication.cpp        Wed Mar  7 
00:12:36 2012        (r40876)
+++ lyx-devel/trunk/src/frontends/qt4/GuiApplication.cpp        Wed Mar  7 
00:21:12 2012        (r40877)
@@ -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_;
 };
 
 
@@ -2529,6 +2572,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...

Modified: lyx-devel/trunk/src/frontends/qt4/GuiApplication.h
==============================================================================
--- lyx-devel/trunk/src/frontends/qt4/GuiApplication.h  Wed Mar  7 00:12:36 
2012        (r40876)
+++ lyx-devel/trunk/src/frontends/qt4/GuiApplication.h  Wed Mar  7 00:21:12 
2012        (r40877)
@@ -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();

Modified: lyx-devel/trunk/src/lyxfind.cpp
==============================================================================
--- lyx-devel/trunk/src/lyxfind.cpp     Wed Mar  7 00:12:36 2012        (r40876)
+++ lyx-devel/trunk/src/lyxfind.cpp     Wed Mar  7 00:21:12 2012        (r40877)
@@ -1133,12 +1133,12 @@
 {
        if (!cur)
                return 0;
-       while (cur) {
+       while (!theApp()->longOperationCancelled() && cur) {
                LYXERR(Debug::FIND, "findForwardAdv() cur: " << cur);
                int match_len = match(cur, -1, false);
                LYXERR(Debug::FIND, "match_len: " << match_len);
                if (match_len) {
-                       for (; cur; cur.forwardPos()) {
+                       for (; !theApp()->longOperationCancelled() && cur; 
cur.forwardPos()) {
                                LYXERR(Debug::FIND, "Advancing cur: " << cur);
                                int match_len = match(cur);
                                LYXERR(Debug::FIND, "match_len: " << match_len);
@@ -1235,7 +1235,7 @@
                else
                        cur.backwardPos();
                pit_changed = true;
-       } while (true);
+       } while (!theApp()->longOperationCancelled());
        return 0;
 }
 

Reply via email to