From d0feccc7ed4025f6348644b3a91be757e10ced77 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Peter=20K=C3=BCmmel?= Date: Sat, 23 Oct 2010 10:49:45 +0000 Subject: [PATCH] switch mouse to busy symbol every 3 seconds and then back to show the user something is done in the background git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@35795 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/frontends/qt4/GuiClipboard.cpp | 1 + src/frontends/qt4/GuiView.cpp | 102 +++++++++++++++++++++++++---- src/frontends/qt4/GuiView.h | 11 +++- src/frontends/qt4/GuiWorkArea.cpp | 36 +++++++--- src/frontends/qt4/GuiWorkArea.h | 4 ++ src/support/bind.h | 8 +-- 6 files changed, 130 insertions(+), 32 deletions(-) diff --git a/src/frontends/qt4/GuiClipboard.cpp b/src/frontends/qt4/GuiClipboard.cpp index 76fcd2d884..297b828948 100644 --- a/src/frontends/qt4/GuiClipboard.cpp +++ b/src/frontends/qt4/GuiClipboard.cpp @@ -47,6 +47,7 @@ #include #include +#include using namespace std; using namespace lyx::support; diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp index efcbdd86b0..99962e2a36 100644 --- a/src/frontends/qt4/GuiView.cpp +++ b/src/frontends/qt4/GuiView.cpp @@ -26,6 +26,7 @@ #include "GuiToc.h" #include "GuiToolbar.h" #include "GuiWorkArea.h" +#include "GuiProgress.h" #include "LayoutBox.h" #include "Menus.h" #include "TocModel.h" @@ -79,7 +80,6 @@ #include "support/Systemcall.h" #include "support/Timeout.h" #include "support/ProgressInterface.h" -#include "GuiProgress.h" #include #include @@ -283,6 +283,11 @@ struct GuiView::GuiViewPrivate bg_widget_->setFocus(); } + int tabWorkAreaCount() + { + return splitter_->count(); + } + TabWorkArea * tabWorkArea(int i) { return dynamic_cast(splitter_->widget(i)); @@ -290,11 +295,12 @@ struct GuiView::GuiViewPrivate TabWorkArea * currentTabWorkArea() { - if (splitter_->count() == 1) + int areas = tabWorkAreaCount(); + if (areas == 1) // The first TabWorkArea is always the first one, if any. return tabWorkArea(0); - for (int i = 0; i != splitter_->count(); ++i) { + for (int i = 0; i != areas; ++i) { TabWorkArea * twa = tabWorkArea(i); if (current_main_work_area_ == twa->currentWorkArea()) return twa; @@ -307,12 +313,12 @@ struct GuiView::GuiViewPrivate #if (QT_VERSION >= 0x040400) void setPreviewFuture(QFuture const & f) { - if (preview_watcher_.isRunning()) { + if (processing_thread_watcher_.isRunning()) { // we prefer to cancel this preview in order to keep a snappy // interface. return; } - preview_watcher_.setFuture(f); + processing_thread_watcher_.setFuture(f); } #endif @@ -356,12 +362,12 @@ public: #if (QT_VERSION >= 0x040400) /// QFutureWatcher autosave_watcher_; - QFutureWatcher preview_watcher_; + QFutureWatcher processing_thread_watcher_; /// string last_export_format; #else struct DummyWatcher { bool isRunning(){return false;} }; - DummyWatcher preview_watcher_; + DummyWatcher processing_thread_watcher_; #endif static QSet busyBuffers; @@ -381,7 +387,10 @@ public: bool (Buffer::*syncFunc)(string const &, bool, bool) const, bool (Buffer::*previewFunc)(string const &, bool) const); - + QTimer processing_cursor_timer_; + bool indicates_processing_; + QMap orig_cursors_; + QVector guiWorkAreas(); }; QSet GuiView::GuiViewPrivate::busyBuffers; @@ -436,9 +445,13 @@ GuiView::GuiView(int id) #if (QT_VERSION >= 0x040400) connect(&d.autosave_watcher_, SIGNAL(finished()), this, - SLOT(threadFinished())); - connect(&d.preview_watcher_, SIGNAL(finished()), this, - SLOT(threadFinished())); + SLOT(processingThreadFinished())); + connect(&d.processing_thread_watcher_, SIGNAL(finished()), this, + SLOT(processingThreadFinished())); + + d.processing_cursor_timer_.setInterval(1000 * 3); + connect(&d.processing_cursor_timer_, SIGNAL(timeout()), this, + SLOT(indicateProcessing())); #endif connect(this, SIGNAL(triggerShowDialog(QString const &, QString const &, Inset *)), @@ -470,7 +483,64 @@ GuiView::~GuiView() } -void GuiView::threadFinished() +QVector GuiView::GuiViewPrivate::guiWorkAreas() +{ + QVector areas; + for (int i = 0; i < tabWorkAreaCount(); i++) { + TabWorkArea* ta = tabWorkArea(i); + for (int u = 0; u < ta->count(); u++) { + areas << ta->workArea(u); + } + } + return areas; +} + +void GuiView::setCursorShapes(Qt::CursorShape shape) +{ + QVector areas = d.guiWorkAreas(); + Q_FOREACH(GuiWorkArea* wa, areas) { + wa->setCursorShape(shape); + } +} + +void GuiView::restoreCursorShapes() +{ + QVector areas = d.guiWorkAreas(); + Q_FOREACH(GuiWorkArea* wa, areas) { + if (d.orig_cursors_.contains(wa)) { + wa->setCursorShape(d.orig_cursors_[wa]); + } + } +} + +void GuiView::saveCursorShapes() +{ + d.orig_cursors_.clear(); + QVector areas = d.guiWorkAreas(); + Q_FOREACH(GuiWorkArea* wa, areas) { + d.orig_cursors_[wa] = wa->cursorShape(); + } +} + +void GuiView::indicateProcessing() +{ + if (d.indicates_processing_) { + restoreCursorShapes(); + } else { + setCursorShapes(Qt::BusyCursor); + } + d.indicates_processing_ = !d.indicates_processing_; +} + +void GuiView::processingThreadStarted() +{ + saveCursorShapes(); + d.indicates_processing_ = false; + indicateProcessing(); + d.processing_cursor_timer_.start(); +} + +void GuiView::processingThreadFinished() { #if (QT_VERSION >= 0x040400) QFutureWatcher const * watcher = @@ -478,6 +548,9 @@ void GuiView::threadFinished() message(watcher->result()); updateToolbars(); errors(d.last_export_format); + d.processing_cursor_timer_.stop(); + restoreCursorShapes(); + d.indicates_processing_ = false; #endif } @@ -1444,12 +1517,12 @@ bool GuiView::getStatus(FuncRequest const & cmd, FuncStatus & flag) case LFUN_MASTER_BUFFER_UPDATE: case LFUN_MASTER_BUFFER_VIEW: enable = doc_buffer && doc_buffer->parent() != 0 - && !d.preview_watcher_.isRunning(); + && !d.processing_thread_watcher_.isRunning(); break; case LFUN_BUFFER_UPDATE: case LFUN_BUFFER_VIEW: { - if (!doc_buffer || d.preview_watcher_.isRunning()) { + if (!doc_buffer || d.processing_thread_watcher_.isRunning()) { enable = false; break; } @@ -2865,6 +2938,7 @@ bool GuiView::GuiViewPrivate::asyncBufferProcessing( if (!used_buffer) { return false; } + gv_->processingThreadStarted(); string format = argument; if (format.empty()) { format = used_buffer->getDefaultOutputFormat(); diff --git a/src/frontends/qt4/GuiView.h b/src/frontends/qt4/GuiView.h index deb1e24a72..80bfc6d057 100644 --- a/src/frontends/qt4/GuiView.h +++ b/src/frontends/qt4/GuiView.h @@ -82,6 +82,10 @@ public: /// are we busy ? bool busy() const; + void saveCursorShapes(); + void restoreCursorShapes(); + void setCursorShapes(Qt::CursorShape shape); + /// \name Generic accessor functions //@{ /// The current BufferView refers to the BufferView that has the focus, @@ -224,8 +228,10 @@ private Q_SLOTS: void normalSizedIcons(); void bigSizedIcons(); - /// For completion of autosave or exporrt threads. - void threadFinished(); + /// For completion of autosave or export threads. + void processingThreadStarted(); + void processingThreadFinished(); + void indicateProcessing(); /// must be called in GUI thread void doShowDialog(QString const & qname, QString const & qdata, @@ -411,6 +417,7 @@ private: bool closing_; /// if the view is busy the cursor shouldn't blink for instance. bool busy_; + }; } // namespace frontend diff --git a/src/frontends/qt4/GuiWorkArea.cpp b/src/frontends/qt4/GuiWorkArea.cpp index cc1c8091dc..0c1eeed670 100644 --- a/src/frontends/qt4/GuiWorkArea.cpp +++ b/src/frontends/qt4/GuiWorkArea.cpp @@ -288,7 +288,7 @@ void GuiWorkArea::init() setFocusPolicy(Qt::StrongFocus); - viewport()->setCursor(Qt::IBeamCursor); + setCursorShape(Qt::IBeamCursor); synthetic_mouse_event_.timeout.timeout.connect( bind(&GuiWorkArea::generateSyntheticMouseEvent, @@ -320,6 +320,16 @@ GuiWorkArea::~GuiWorkArea() } +Qt::CursorShape GuiWorkArea::cursorShape() const +{ + return viewport()->cursor().shape(); +} + +void GuiWorkArea::setCursorShape(Qt::CursorShape shape) +{ + viewport()->setCursor(shape); +} + void GuiWorkArea::setGuiView(GuiView & gv) { lyx_view_ = &gv; @@ -1465,7 +1475,7 @@ void TabWorkArea::mouseDoubleClickEvent(QMouseEvent * event) void TabWorkArea::setFullScreen(bool full_screen) { for (int i = 0; i != count(); ++i) { - if (GuiWorkArea * wa = dynamic_cast(widget(i))) + if (GuiWorkArea * wa = workArea(i)) wa->setFullScreen(full_screen); } @@ -1496,12 +1506,18 @@ GuiWorkArea * TabWorkArea::currentWorkArea() } +GuiWorkArea * TabWorkArea::workArea(int index) +{ + return dynamic_cast(widget(index)); +} + + GuiWorkArea * TabWorkArea::workArea(Buffer & buffer) { // FIXME: this method doesn't work if we have more than work area // showing the same buffer. for (int i = 0; i != count(); ++i) { - GuiWorkArea * wa = dynamic_cast(widget(i)); + GuiWorkArea * wa = workArea(i); LASSERT(wa, return 0); if (&wa->bufferView().buffer() == &buffer) return wa; @@ -1513,7 +1529,7 @@ GuiWorkArea * TabWorkArea::workArea(Buffer & buffer) void TabWorkArea::closeAll() { while (count()) { - GuiWorkArea * wa = dynamic_cast(widget(0)); + GuiWorkArea * wa = workArea(0); LASSERT(wa, /**/); removeTab(0); delete wa; @@ -1596,7 +1612,7 @@ void TabWorkArea::on_currentTabChanged(int i) // returns e.g. on application destruction if (i == -1) return; - GuiWorkArea * wa = dynamic_cast(widget(i)); + GuiWorkArea * wa = workArea(i); LASSERT(wa, return); wa->setUpdatesEnabled(true); wa->redraw(true); @@ -1615,7 +1631,7 @@ void TabWorkArea::closeCurrentBuffer() if (clicked_tab_ == -1) wa = currentWorkArea(); else { - wa = dynamic_cast(widget(clicked_tab_)); + wa = workArea(clicked_tab_); LASSERT(wa, /**/); } wa->view().closeWorkArea(wa); @@ -1628,7 +1644,7 @@ void TabWorkArea::hideCurrentTab() if (clicked_tab_ == -1) wa = currentWorkArea(); else { - wa = dynamic_cast(widget(clicked_tab_)); + wa = workArea(clicked_tab_); LASSERT(wa, /**/); } wa->view().hideWorkArea(wa); @@ -1642,7 +1658,7 @@ void TabWorkArea::closeTab(int index) if (index == -1) wa = currentWorkArea(); else { - wa = dynamic_cast(widget(index)); + wa = workArea(index); LASSERT(wa, /**/); } wa->view().closeWorkArea(wa); @@ -1753,7 +1769,7 @@ void TabWorkArea::updateTabTexts() // collect full names first: path into postfix, empty prefix and // filename without extension for (size_t i = 0; i < n; ++i) { - GuiWorkArea * i_wa = dynamic_cast(widget(i)); + GuiWorkArea * i_wa = workArea(i); FileName const fn = i_wa->bufferView().buffer().fileName(); paths.push_back(DisplayPath(i, fn)); } @@ -1837,7 +1853,7 @@ void TabWorkArea::updateTabTexts() // set new tab titles for (It it = paths.begin(); it != paths.end(); ++it) { - GuiWorkArea * i_wa = dynamic_cast(widget(it->tab())); + GuiWorkArea * i_wa = workArea(it->tab()); Buffer & buf = i_wa->bufferView().buffer(); if (!buf.fileName().empty() && !buf.isClean()) setTabText(it->tab(), it->displayString() + "*"); diff --git a/src/frontends/qt4/GuiWorkArea.h b/src/frontends/qt4/GuiWorkArea.h index 0858521a9a..a0fcf73786 100644 --- a/src/frontends/qt4/GuiWorkArea.h +++ b/src/frontends/qt4/GuiWorkArea.h @@ -139,6 +139,9 @@ public: /// GuiCompleter & completer() { return *completer_; } + Qt::CursorShape cursorShape() const; + void setCursorShape(Qt::CursorShape shape); + /// Return the GuiView this workArea belongs to GuiView const & view() const { return *lyx_view_; } @@ -309,6 +312,7 @@ public: bool removeWorkArea(GuiWorkArea *); GuiWorkArea * currentWorkArea(); GuiWorkArea * workArea(Buffer & buffer); + GuiWorkArea * workArea(int index); Q_SIGNALS: /// diff --git a/src/support/bind.h b/src/support/bind.h index 4d2968048d..efd3267de5 100644 --- a/src/support/bind.h +++ b/src/support/bind.h @@ -12,13 +12,9 @@ #ifndef LYX_BIND_H #define LYX_BIND_H -#ifdef LYX_USE_TR1 - -#include +#include "support/functional.h" -#ifdef __GNUC__ -#include -#endif +#ifdef LYX_USE_TR1 namespace lyx { -- 2.39.5