PageRenderTime 39ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/src/gui/widgets/overridecursor.cpp

http://github.com/FellowTraveler/Moneychanger
C++ | 182 lines | 90 code | 16 blank | 76 comment | 9 complexity | ac864f5e055b4dbb8dbc7889afd29b0e MD5 | raw file
Possible License(s): LGPL-2.1
  1. #ifndef __STABLE_HPP__
  2. #include <core/stable.hpp>
  3. #endif
  4. #include <QApplication>
  5. #include <QEvent>
  6. #include <gui/widgets/overridecursor.hpp>
  7. // -----------------------------------
  8. MTSpinner::MTSpinner()
  9. : m_pCursor(MTOverrideCursor::It())
  10. { // Note: MTOverrideCursor::It() returns NULL if one is already instantiated.
  11. // Therefore, m_pCursor MIGHT contain a pointer, or MIGHT contain NULL.
  12. // This way, only the outermost-spinner ever actually does something.
  13. // The outermost one instantiates, and sets the pointer into MTSpinner.
  14. // Then when the MTSpinner destructs, the pointer is set, so it deletes it,
  15. // and the MTOverrideCursor being deleted sets the static pointer back to NULL
  16. // in its destructor.
  17. // (This way, the next run it will be instantiated again and work properly.)
  18. // Whereas any INNER MTSpinners will do nothing, since a NULL pointer will be
  19. // set here, and thus the inner MTSpinner's destructor will do nothing, and the
  20. // static MTOverrideCursor pointer will remain valid until the outermost one destroys it.
  21. // Easy, right? :-)
  22. }
  23. // Note:
  24. MTSpinner::~MTSpinner()
  25. {
  26. if (NULL != m_pCursor)
  27. delete m_pCursor;
  28. m_pCursor = NULL;
  29. }
  30. // --------------------------------------------
  31. //static
  32. MTOverrideCursor * MTOverrideCursor::Exists()
  33. {
  34. // This version is used by the password dialog, which temporarily
  35. // deactivates the override cursor until it's finished collecting
  36. // the password. (Only IF the override cursor is set...)
  37. //
  38. return MTOverrideCursor::s_pCursor;
  39. }
  40. // --------------------------------------------
  41. //static
  42. MTOverrideCursor * MTOverrideCursor::s_pCursor = NULL;
  43. // --------------------------------------------
  44. //static
  45. MTOverrideCursor * MTOverrideCursor::It()
  46. {
  47. // Use: opentxs::OTCleanup<MTOverrideCursor> theCursorAngel(MTOverrideCursor::It());
  48. //
  49. // Oooo even better, use: MTSpinner theSpinner;
  50. // ----------------------------
  51. // How does this work?
  52. //
  53. // MTOverrideCursor::s_pCursor is instantiated, if NULL, and a pointer returned.
  54. //
  55. // If it's returned, it should be stored in an opentxs::OTCleanup instance, which will destroy
  56. // it when it goes out of scope.
  57. //
  58. // Meanwhile our destructor, ~MTOverrideCursor, sets MTOverrideCursor::s_pCursor back
  59. // to NULL again, so that future calls will correctly instantiate it again, instead of
  60. // returning a bad pointer.
  61. //
  62. // One more thing: if MTOverrideCursor::s_pCursor is NOT NULL when calling It(), then
  63. // we return NULL. This is because It() must have been called twice. For example, if you
  64. // call function A, which sets the override spinner, and then it calls function B, which
  65. // calls function C, which ALSO sets the override spinner, then a few things are clear:
  66. //
  67. // 1. Function C might legitimately activate the spinner, but in the case where it's called by
  68. // function A, we do NOT want to activate the spinner, since it's ALREADY ACTIVE (from A.)
  69. //
  70. // 2. Function A in this case is ALREADY going to clean up the spinner at the right time, and thus
  71. // there's no need to Function C to clean it up as well.
  72. //
  73. // 3. Even if Function C was allowed to clean it up, we'd have to make sure it was a different one
  74. // than the one Function A is going to clean up, to prevent a double delete. By returning a NULL
  75. // pointer to function C, we know it will clean up nothing, which is proper. (And in cases where a
  76. // pointer IS returned to function C, we know it will clean up something, as is also proper.)
  77. //
  78. // 4. Even if functions A and C were cleaning up their own copies of the object, which they are not since
  79. // we're now using a singleton, we would STILL have to deal with the fact that both of them are setting
  80. // and removing the override cursor on the QApplication. But our use of a singleton saves us from that problem.
  81. //
  82. // By returning NULL in cases where the pointer is already set, we insure that only the OUTERMOST USE of
  83. // the override cursor will actually do anything, and we also insure that a pointer to that use is available
  84. // for strange cases like if we are in the password dialog and we need to temporarily suspend the override
  85. // cursor until the password dialog is finished.
  86. //
  87. if (NULL != MTOverrideCursor::s_pCursor)
  88. return NULL;
  89. // ------------------------------------------------
  90. // Else s_pCursor is definitely NULL, so we can go ahead and instantiate it.
  91. //
  92. MTOverrideCursor::s_pCursor = new MTOverrideCursor;
  93. return MTOverrideCursor::s_pCursor;
  94. }
  95. // ------------------------------------------------
  96. void MTOverrideCursor::Pause()
  97. {
  98. if (!m_bPaused)
  99. {
  100. m_bPaused = true;
  101. this->SpinnerDeactivate();
  102. }
  103. }
  104. // ------------------------------------------------
  105. void MTOverrideCursor::Unpause()
  106. {
  107. if (m_bPaused)
  108. {
  109. m_bPaused = false;
  110. this->SpinnerActivate();
  111. }
  112. }
  113. // ------------------------------------------------
  114. void MTOverrideCursor::SpinnerActivate()
  115. {
  116. if (!m_bActive)
  117. {
  118. m_bActive = true;
  119. QApplication::setOverrideCursor(Qt::WaitCursor);
  120. QCoreApplication * pCore = QCoreApplication::instance();
  121. pCore->installEventFilter(this);
  122. }
  123. }
  124. // ------------------------------------------------
  125. void MTOverrideCursor::SpinnerDeactivate()
  126. {
  127. if (m_bActive)
  128. {
  129. m_bActive = false;
  130. QApplication::restoreOverrideCursor();
  131. QCoreApplication * pCore = QCoreApplication::instance();
  132. pCore->removeEventFilter(this);
  133. }
  134. }
  135. // ------------------------------------------------
  136. MTOverrideCursor::MTOverrideCursor(QObject *parent) :
  137. QObject(NULL), // notice we pass NULL here instead of parent.
  138. m_bActive(false),
  139. m_bPaused(false)
  140. {
  141. this->SpinnerActivate();
  142. }
  143. // ------------------------------------------------
  144. MTOverrideCursor::~MTOverrideCursor()
  145. {
  146. MTOverrideCursor::s_pCursor = NULL;
  147. // ----------------------------------------
  148. this->SpinnerDeactivate();
  149. }
  150. bool MTOverrideCursor::eventFilter(QObject *obj, QEvent *event)
  151. {
  152. switch ( event->type())
  153. {
  154. //list event you want to prevent here ...
  155. case QEvent::KeyPress:
  156. case QEvent::KeyRelease:
  157. case QEvent::MouseButtonRelease:
  158. case QEvent::MouseButtonPress:
  159. case QEvent::MouseButtonDblClick:
  160. //...
  161. return true;
  162. default: break;
  163. }
  164. return QObject::eventFilter( obj, event );
  165. }
  166. // -----------------------------------------------------