ctkPopupWidget.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.commontk.org/LICENSE
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. // Qt includes
  15. #include <QApplication>
  16. #include <QDebug>
  17. #include <QDesktopWidget>
  18. #include <QDir>
  19. #include <QEvent>
  20. #include <QLabel>
  21. #include <QLayout>
  22. #include <QMouseEvent>
  23. #include <QPainter>
  24. #include <QPropertyAnimation>
  25. #include <QStyle>
  26. #include <QTimer>
  27. // CTK includes
  28. #include "ctkPopupWidget.h"
  29. #define LEAVE_CLOSING_DELAY 10
  30. #define ENTER_OPENING_DELAY 10
  31. #define DEFAULT_FADING_DURATION 333 // fast enough
  32. // -------------------------------------------------------------------------
  33. QGradient* duplicateGradient(const QGradient* gradient)
  34. {
  35. QGradient* newGradient = 0;
  36. switch (gradient->type())
  37. {
  38. case QGradient::LinearGradient:
  39. {
  40. const QLinearGradient* linearGradient = static_cast<const QLinearGradient*>(gradient);
  41. newGradient = new QLinearGradient(linearGradient->start(), linearGradient->finalStop());
  42. break;
  43. }
  44. case QGradient::RadialGradient:
  45. {
  46. const QRadialGradient* radialGradient = static_cast<const QRadialGradient*>(gradient);
  47. newGradient = new QRadialGradient(radialGradient->center(), radialGradient->radius());
  48. break;
  49. }
  50. case QGradient::ConicalGradient:
  51. {
  52. const QConicalGradient* conicalGradient = static_cast<const QConicalGradient*>(gradient);
  53. newGradient = new QConicalGradient(conicalGradient->center(), conicalGradient->angle());
  54. break;
  55. }
  56. default:
  57. break;
  58. }
  59. if (!newGradient)
  60. {
  61. Q_ASSERT(gradient->type() != QGradient::NoGradient);
  62. return newGradient;
  63. }
  64. newGradient->setCoordinateMode(gradient->coordinateMode());
  65. newGradient->setSpread(gradient->spread());
  66. newGradient->setStops(gradient->stops());
  67. return newGradient;
  68. }
  69. // -------------------------------------------------------------------------
  70. class ctkPopupWidgetPrivate
  71. {
  72. Q_DECLARE_PUBLIC(ctkPopupWidget);
  73. protected:
  74. ctkPopupWidget* const q_ptr;
  75. public:
  76. ctkPopupWidgetPrivate(ctkPopupWidget& object);
  77. ~ctkPopupWidgetPrivate();
  78. void init();
  79. bool fitBaseWidgetSize()const;
  80. Qt::Alignment pixmapAlignment()const;
  81. void setupPopupPixmapWidget();
  82. QRect closedGeometry()const;
  83. QRect openGeometry()const;
  84. QPropertyAnimation* currentAnimation()const;
  85. QWidget* BaseWidget;
  86. bool AutoHide;
  87. double WindowAlpha;
  88. ctkPopupWidget::AnimationEffect Effect;
  89. QPropertyAnimation* AlphaAnimation;
  90. bool ForcedTranslucent;
  91. QPropertyAnimation* ScrollAnimation;
  92. QLabel* PopupPixmapWidget;
  93. // Geometry attributes
  94. Qt::Alignment Alignment;
  95. Qt::Orientation Orientation;
  96. ctkPopupWidget::VerticalDirection VerticalDirection;
  97. Qt::LayoutDirection HorizontalDirection;
  98. };
  99. // -------------------------------------------------------------------------
  100. ctkPopupWidgetPrivate::ctkPopupWidgetPrivate(ctkPopupWidget& object)
  101. :q_ptr(&object)
  102. {
  103. this->BaseWidget = 0;
  104. this->AutoHide = true;
  105. this->Effect = ctkPopupWidget::ScrollEffect;
  106. this->WindowAlpha = 1.;
  107. this->AlphaAnimation = 0;
  108. this->ForcedTranslucent = false;
  109. this->ScrollAnimation = 0;
  110. this->PopupPixmapWidget = 0;
  111. // Geometry attributes
  112. this->Alignment = Qt::AlignJustify | Qt::AlignBottom;
  113. this->Orientation = Qt::Vertical;
  114. this->VerticalDirection = ctkPopupWidget::TopToBottom;
  115. this->HorizontalDirection = Qt::LeftToRight;
  116. }
  117. // -------------------------------------------------------------------------
  118. ctkPopupWidgetPrivate::~ctkPopupWidgetPrivate()
  119. {
  120. delete this->PopupPixmapWidget;
  121. }
  122. // -------------------------------------------------------------------------
  123. void ctkPopupWidgetPrivate::init()
  124. {
  125. Q_Q(ctkPopupWidget);
  126. this->AlphaAnimation = new QPropertyAnimation(q, "windowAlpha", q);
  127. this->AlphaAnimation->setDuration(DEFAULT_FADING_DURATION);
  128. this->AlphaAnimation->setStartValue(0.);
  129. this->AlphaAnimation->setEndValue(1.);
  130. QObject::connect(this->AlphaAnimation, SIGNAL(finished()),
  131. q, SLOT(onEffectFinished()));
  132. this->PopupPixmapWidget = new QLabel(0, Qt::ToolTip | Qt::FramelessWindowHint);
  133. this->ScrollAnimation = new QPropertyAnimation(q, "windowGeometry", q);
  134. this->ScrollAnimation->setDuration(DEFAULT_FADING_DURATION);
  135. QObject::connect(this->ScrollAnimation, SIGNAL(finished()),
  136. q, SLOT(onEffectFinished()));
  137. QObject::connect(this->ScrollAnimation, SIGNAL(finished()),
  138. this->PopupPixmapWidget, SLOT(hide()));
  139. q->setAnimationEffect(this->Effect);
  140. q->setEasingCurve(QEasingCurve::OutCubic);
  141. }
  142. // -------------------------------------------------------------------------
  143. QPropertyAnimation* ctkPopupWidgetPrivate::currentAnimation()const
  144. {
  145. return this->Effect == ctkPopupWidget::ScrollEffect ?
  146. this->ScrollAnimation : this->AlphaAnimation;
  147. }
  148. // -------------------------------------------------------------------------
  149. void ctkPopupWidgetPrivate::setupPopupPixmapWidget()
  150. {
  151. Q_Q(ctkPopupWidget);
  152. QPixmap pixmap;
  153. if (q->testAttribute(Qt::WA_TranslucentBackground))
  154. {
  155. this->PopupPixmapWidget->setAlignment(this->pixmapAlignment());
  156. // only QImage handle transparency correctly
  157. QImage image(this->openGeometry().size(), QImage::Format_ARGB32);
  158. image.fill(0);
  159. q->render(&image);
  160. pixmap = QPixmap::fromImage(image);
  161. }
  162. else
  163. {
  164. pixmap = QPixmap::grabWidget(q, QRect(QPoint(0,0), this->openGeometry().size()));
  165. }
  166. this->PopupPixmapWidget->setPixmap(pixmap);
  167. this->PopupPixmapWidget->setAttribute(
  168. Qt::WA_TranslucentBackground, q->testAttribute(Qt::WA_TranslucentBackground));
  169. this->PopupPixmapWidget->setWindowOpacity(q->windowOpacity());
  170. }
  171. // -------------------------------------------------------------------------
  172. Qt::Alignment ctkPopupWidgetPrivate::pixmapAlignment()const
  173. {
  174. Q_Q(const ctkPopupWidget);
  175. Qt::Alignment alignment;
  176. if (this->VerticalDirection == ctkPopupWidget::TopToBottom)
  177. {
  178. alignment |= Qt::AlignBottom;
  179. }
  180. else// if (this->VerticalDirection == ctkPopupWidget::BottomToTop)
  181. {
  182. alignment |= Qt::AlignTop;
  183. }
  184. if (this->HorizontalDirection == Qt::LeftToRight)
  185. {
  186. alignment |= Qt::AlignRight;
  187. }
  188. else// if (this->VerticalDirection == ctkPopupWidget::BottomToTop)
  189. {
  190. alignment |= Qt::AlignLeft;
  191. }
  192. return alignment;
  193. }
  194. // -------------------------------------------------------------------------
  195. QRect ctkPopupWidgetPrivate::closedGeometry()const
  196. {
  197. Q_Q(const ctkPopupWidget);
  198. /// TODO: it really doesn't handle many cases.
  199. /// It's a lot of parameters to think about.
  200. QRect openGeom = this->openGeometry();
  201. if (this->Orientation & Qt::Vertical)
  202. {
  203. if (this->VerticalDirection == ctkPopupWidget::BottomToTop)
  204. {
  205. openGeom.moveTop(openGeom.bottom());
  206. }
  207. openGeom.setHeight(0);
  208. }
  209. if (this->Orientation & Qt::Horizontal)
  210. {
  211. if (this->HorizontalDirection == Qt::LeftToRight)
  212. {
  213. openGeom.moveLeft(openGeom.right());
  214. }
  215. openGeom.setWidth(0);
  216. }
  217. return openGeom;
  218. }
  219. // -------------------------------------------------------------------------
  220. QRect ctkPopupWidgetPrivate::openGeometry()const
  221. {
  222. Q_Q(const ctkPopupWidget);
  223. QSize size = q->size();
  224. if (!q->testAttribute(Qt::WA_WState_Created))
  225. {
  226. size = q->sizeHint();
  227. }
  228. if (!this->BaseWidget)
  229. {
  230. return QRect(q->pos(), size);
  231. }
  232. QRect geometry;
  233. if (this->Alignment & Qt::AlignJustify)
  234. {
  235. if (this->Orientation & Qt::Vertical)
  236. {
  237. size.setWidth(this->BaseWidget->width());
  238. }
  239. }
  240. if (this->Alignment & Qt::AlignTop &&
  241. this->Alignment & Qt::AlignBottom)
  242. {
  243. size.setHeight(this->BaseWidget->height());
  244. }
  245. geometry.setSize(size);
  246. QPoint topLeft = QPoint(this->BaseWidget->geometry().left(), this->BaseWidget->geometry().top());
  247. QPoint bottomRight = QPoint(this->BaseWidget->geometry().right(), this->BaseWidget->geometry().bottom());
  248. topLeft = this->BaseWidget->parentWidget() ? this->BaseWidget->parentWidget()->mapToGlobal(topLeft) : topLeft;
  249. bottomRight = this->BaseWidget->parentWidget() ? this->BaseWidget->parentWidget()->mapToGlobal(bottomRight) : bottomRight;
  250. if (this->Alignment & Qt::AlignLeft)
  251. {
  252. if (this->HorizontalDirection == Qt::LeftToRight)
  253. {
  254. geometry.moveLeft(topLeft.x());
  255. }
  256. else
  257. {
  258. geometry.moveRight(topLeft.x());
  259. }
  260. }
  261. else if (this->Alignment & Qt::AlignRight)
  262. {
  263. if (this->HorizontalDirection == Qt::LeftToRight)
  264. {
  265. geometry.moveLeft(bottomRight.x());
  266. }
  267. else
  268. {
  269. geometry.moveRight(bottomRight.x());
  270. }
  271. }
  272. else if (this->Alignment & Qt::AlignHCenter)
  273. {
  274. if (this->HorizontalDirection == Qt::LeftToRight)
  275. {
  276. geometry.moveLeft((topLeft.x() + bottomRight.x()) / 2 - size.width() / 2);
  277. }
  278. else
  279. {
  280. geometry.moveRight((topLeft.x() + bottomRight.x()) / 2 + size.width() / 2);
  281. }
  282. }
  283. else if (this->Alignment & Qt::AlignJustify)
  284. {
  285. geometry.moveLeft(topLeft.x());
  286. }
  287. if (this->Alignment & Qt::AlignTop)
  288. {
  289. if (this->VerticalDirection == ctkPopupWidget::TopToBottom)
  290. {
  291. geometry.moveTop(topLeft.y());
  292. }
  293. else
  294. {
  295. geometry.moveBottom(topLeft.y());
  296. }
  297. }
  298. else if (this->Alignment & Qt::AlignBottom)
  299. {
  300. if (this->VerticalDirection == ctkPopupWidget::TopToBottom)
  301. {
  302. geometry.moveTop(bottomRight.y());
  303. }
  304. else
  305. {
  306. geometry.moveBottom(bottomRight.y());
  307. }
  308. }
  309. else if (this->Alignment & Qt::AlignVCenter)
  310. {
  311. if (this->VerticalDirection == ctkPopupWidget::TopToBottom)
  312. {
  313. geometry.moveTop((topLeft.y() + bottomRight.y()) / 2 + size.height() / 2);
  314. }
  315. else
  316. {
  317. geometry.moveBottom((topLeft.y() + bottomRight.y()) / 2 - size.height() / 2);
  318. }
  319. }
  320. return geometry;
  321. }
  322. // -------------------------------------------------------------------------
  323. // Qt::FramelessWindowHint is required on Windows for Translucent background
  324. // Qt::Toolip is preferred to Qt::Popup as it would close itself at the first
  325. // click outside the widget (typically a click in the BaseWidget)
  326. ctkPopupWidget::ctkPopupWidget(QWidget* parentWidget)
  327. : Superclass(parentWidget, Qt::ToolTip | Qt::FramelessWindowHint)
  328. , d_ptr(new ctkPopupWidgetPrivate(*this))
  329. {
  330. Q_D(ctkPopupWidget);
  331. d->init();
  332. }
  333. // -------------------------------------------------------------------------
  334. ctkPopupWidget::~ctkPopupWidget()
  335. {
  336. }
  337. // -------------------------------------------------------------------------
  338. QWidget* ctkPopupWidget::baseWidget()const
  339. {
  340. Q_D(const ctkPopupWidget);
  341. return d->BaseWidget;
  342. }
  343. // -------------------------------------------------------------------------
  344. void ctkPopupWidget::setBaseWidget(QWidget* widget)
  345. {
  346. Q_D(ctkPopupWidget);
  347. if (d->BaseWidget)
  348. {
  349. d->BaseWidget->removeEventFilter(this);
  350. }
  351. d->BaseWidget = widget;
  352. if (d->BaseWidget)
  353. {
  354. d->BaseWidget->installEventFilter(this);
  355. }
  356. QTimer::singleShot(ENTER_OPENING_DELAY, this, SLOT(updatePopup()));
  357. }
  358. // -------------------------------------------------------------------------
  359. bool ctkPopupWidget::autoHide()const
  360. {
  361. Q_D(const ctkPopupWidget);
  362. return d->AutoHide;
  363. }
  364. // -------------------------------------------------------------------------
  365. void ctkPopupWidget::setAutoHide(bool mode)
  366. {
  367. Q_D(ctkPopupWidget);
  368. d->AutoHide = mode;
  369. QTimer::singleShot(ENTER_OPENING_DELAY, this, SLOT(updatePopup()));
  370. }
  371. // -------------------------------------------------------------------------
  372. ctkPopupWidget::AnimationEffect ctkPopupWidget::animationEffect()const
  373. {
  374. Q_D(const ctkPopupWidget);
  375. return d->Effect;
  376. }
  377. // -------------------------------------------------------------------------
  378. void ctkPopupWidget::setAnimationEffect(ctkPopupWidget::AnimationEffect effect)
  379. {
  380. Q_D(ctkPopupWidget);
  381. /// TODO: handle the case where there is an animation running
  382. d->Effect = effect;
  383. }
  384. // -------------------------------------------------------------------------
  385. QEasingCurve::Type ctkPopupWidget::easingCurve()const
  386. {
  387. Q_D(const ctkPopupWidget);
  388. return d->AlphaAnimation->easingCurve().type();
  389. }
  390. // -------------------------------------------------------------------------
  391. void ctkPopupWidget::setEasingCurve(QEasingCurve::Type easingCurve)
  392. {
  393. Q_D(ctkPopupWidget);
  394. d->AlphaAnimation->setEasingCurve(easingCurve);
  395. d->ScrollAnimation->setEasingCurve(easingCurve);
  396. }
  397. // -------------------------------------------------------------------------
  398. Qt::Alignment ctkPopupWidget::alignment()const
  399. {
  400. Q_D(const ctkPopupWidget);
  401. return d->Alignment;
  402. }
  403. // -------------------------------------------------------------------------
  404. void ctkPopupWidget::setAlignment(Qt::Alignment alignment)
  405. {
  406. Q_D(ctkPopupWidget);
  407. d->Alignment = alignment;
  408. }
  409. // -------------------------------------------------------------------------
  410. Qt::Orientation ctkPopupWidget::orientation()const
  411. {
  412. Q_D(const ctkPopupWidget);
  413. return d->Orientation;
  414. }
  415. // -------------------------------------------------------------------------
  416. void ctkPopupWidget::setOrientation(Qt::Orientation orientation)
  417. {
  418. Q_D(ctkPopupWidget);
  419. d->Orientation = orientation;
  420. }
  421. // -------------------------------------------------------------------------
  422. ctkPopupWidget::VerticalDirection ctkPopupWidget::verticalDirection()const
  423. {
  424. Q_D(const ctkPopupWidget);
  425. return d->VerticalDirection;
  426. }
  427. // -------------------------------------------------------------------------
  428. void ctkPopupWidget::setVerticalDirection(ctkPopupWidget::VerticalDirection verticalDirection)
  429. {
  430. Q_D(ctkPopupWidget);
  431. d->VerticalDirection = verticalDirection;
  432. }
  433. // -------------------------------------------------------------------------
  434. Qt::LayoutDirection ctkPopupWidget::horizontalDirection()const
  435. {
  436. Q_D(const ctkPopupWidget);
  437. return d->HorizontalDirection;
  438. }
  439. // -------------------------------------------------------------------------
  440. void ctkPopupWidget::setHorizontalDirection(Qt::LayoutDirection horizontalDirection)
  441. {
  442. Q_D(ctkPopupWidget);
  443. d->HorizontalDirection = horizontalDirection;
  444. }
  445. // -------------------------------------------------------------------------
  446. void ctkPopupWidget::onEffectFinished()
  447. {
  448. Q_D(ctkPopupWidget);
  449. if (d->ForcedTranslucent)
  450. {
  451. d->ForcedTranslucent = false;
  452. this->setAttribute(Qt::WA_TranslucentBackground, false);
  453. }
  454. if (qobject_cast<QAbstractAnimation*>(this->sender())->direction() == QAbstractAnimation::Backward)
  455. {
  456. this->hide();
  457. }
  458. else
  459. {
  460. this->show();
  461. }
  462. }
  463. // -------------------------------------------------------------------------
  464. void ctkPopupWidget::paintEvent(QPaintEvent* event)
  465. {
  466. Q_D(ctkPopupWidget);
  467. Q_UNUSED(event);
  468. if (d->Effect == WindowOpacityFadeEffect)
  469. {
  470. int opacity = d->Alpha;
  471. if (d->AlphaAnimation->state() != QAbstractAnimation::Stopped)
  472. {
  473. stop.second.setAlpha(stop.second.alpha() * d->WindowAlpha);
  474. stops.push_back(stop);
  475. }
  476. QPainter painter(this);
  477. QBrush brush = this->palette().window();
  478. if (brush.style() == Qt::LinearGradientPattern ||
  479. brush.style() == Qt::ConicalGradientPattern ||
  480. brush.style() == Qt::RadialGradientPattern)
  481. {
  482. QGradient* newGradient = duplicateGradient(brush.gradient());
  483. QGradientStops stops;
  484. foreach(QGradientStop stop, newGradient->stops())
  485. {
  486. stop.second.setAlpha(opacity);
  487. stops.push_back(stop);
  488. }
  489. newGradient->setStops(stops);
  490. brush = QBrush(*newGradient);
  491. delete newGradient;
  492. }
  493. else
  494. {
  495. QColor color = brush.color();
  496. color.setAlpha(opacity);
  497. brush.setColor(color);
  498. }
  499. //QColor semiTransparentColor = this->palette().window().color();
  500. //semiTransparentColor.setAlpha(d->CurrentAlpha);
  501. painter.fillRect(this->rect(), brush);
  502. }
  503. else
  504. {
  505. QColor color = brush.color();
  506. color.setAlpha(color.alpha() * d->WindowAlpha);
  507. brush.setColor(color);
  508. }
  509. //QColor semiTransparentColor = this->palette().window().color();
  510. //semiTransparentColor.setAlpha(d->CurrentAlpha);
  511. painter.fillRect(this->rect(), brush);
  512. // Let the QFrame draw itself if needed
  513. this->Superclass::paintEvent(event);
  514. }
  515. // --------------------------------------------------------------------------
  516. void ctkPopupWidget::leaveEvent(QEvent* event)
  517. {
  518. QTimer::singleShot(LEAVE_CLOSING_DELAY, this, SLOT(updatePopup()));
  519. this->Superclass::leaveEvent(event);
  520. }
  521. // --------------------------------------------------------------------------
  522. void ctkPopupWidget::enterEvent(QEvent* event)
  523. {
  524. QTimer::singleShot(ENTER_OPENING_DELAY, this, SLOT(updatePopup()));
  525. this->Superclass::enterEvent(event);
  526. }
  527. // --------------------------------------------------------------------------
  528. bool ctkPopupWidget::eventFilter(QObject* obj, QEvent* event)
  529. {
  530. Q_D(ctkPopupWidget);
  531. if (obj == d->BaseWidget &&
  532. event->type() == QEvent::Enter)
  533. {
  534. QTimer::singleShot(ENTER_OPENING_DELAY, this, SLOT(updatePopup()));
  535. }
  536. else if (obj == d->BaseWidget &&
  537. event->type() == QEvent::Leave)
  538. {
  539. QTimer::singleShot(LEAVE_CLOSING_DELAY, this, SLOT(updatePopup()));
  540. }
  541. return this->QObject::eventFilter(obj, event);
  542. }
  543. // --------------------------------------------------------------------------
  544. void ctkPopupWidget::updatePopup()
  545. {
  546. Q_D(ctkPopupWidget);
  547. if (!d->AutoHide)
  548. {
  549. return;
  550. }
  551. if (this->underMouse() ||
  552. (d->BaseWidget && d->BaseWidget->underMouse()) ||
  553. (d->PopupPixmapWidget && d->PopupPixmapWidget->underMouse()))
  554. {
  555. this->showPopup();
  556. }
  557. else
  558. {
  559. this->hidePopup();
  560. }
  561. }
  562. // --------------------------------------------------------------------------
  563. void ctkPopupWidget::showPopup()
  564. {
  565. Q_D(ctkPopupWidget);
  566. if ((this->isVisible() &&
  567. d->currentAnimation()->state() == QAbstractAnimation::Stopped) ||
  568. (d->BaseWidget && !d->BaseWidget->isVisible()))
  569. {
  570. return;
  571. }
  572. if (d->BaseWidget)
  573. {
  574. /*
  575. QPoint bottomLeft = QPoint(d->BaseWidget->geometry().x(), d->BaseWidget->geometry().bottom());
  576. QPoint pos = d->BaseWidget->parentWidget() ? d->BaseWidget->parentWidget()->mapToGlobal(bottomLeft) : bottomLeft;
  577. this->move(pos);
  578. /// TODO: need some refinement
  579. if ((this->sizePolicy().horizontalPolicy() & QSizePolicy::GrowFlag &&
  580. this->width() < d->BaseWidget->width()) ||
  581. (this->sizePolicy().horizontalPolicy() & QSizePolicy::ShrinkFlag &&
  582. this->width() > d->BaseWidget->width()))
  583. {
  584. // Fit to BaseWidget size
  585. this->resize(d->BaseWidget->width(), this->sizeHint().height());
  586. }
  587. */
  588. }
  589. this->setGeometry(d->openGeometry());
  590. d->currentAnimation()->setDirection(QAbstractAnimation::Forward);
  591. switch(d->Effect)
  592. {
  593. case WindowOpacityFadeEffect:
  594. if (!this->testAttribute(Qt::WA_TranslucentBackground))
  595. {
  596. d->ForcedTranslucent = true;
  597. this->setAttribute(Qt::WA_TranslucentBackground, true);
  598. }
  599. this->show();
  600. break;
  601. case ScrollEffect:
  602. {
  603. QRect closedGeometry = d->closedGeometry();
  604. QRect openGeometry = d->openGeometry();
  605. d->PopupPixmapWidget->setGeometry(closedGeometry);
  606. d->ScrollAnimation->setStartValue(closedGeometry);
  607. d->ScrollAnimation->setEndValue(openGeometry);
  608. d->setupPopupPixmapWidget();
  609. d->PopupPixmapWidget->show();
  610. break;
  611. }
  612. default:
  613. break;
  614. }
  615. switch(d->currentAnimation()->state())
  616. {
  617. case QAbstractAnimation::Stopped:
  618. d->currentAnimation()->start();
  619. break;
  620. case QAbstractAnimation::Paused:
  621. d->currentAnimation()->resume();
  622. break;
  623. default:
  624. case QAbstractAnimation::Running:
  625. break;
  626. }
  627. }
  628. // --------------------------------------------------------------------------
  629. void ctkPopupWidget::hidePopup()
  630. {
  631. Q_D(ctkPopupWidget);
  632. if (!this->isVisible() &&
  633. d->currentAnimation()->state() == QAbstractAnimation::Stopped)
  634. {
  635. return;
  636. }
  637. d->currentAnimation()->setDirection(QAbstractAnimation::Backward);
  638. switch(d->Effect)
  639. {
  640. case WindowOpacityFadeEffect:
  641. if (!this->testAttribute(Qt::WA_TranslucentBackground))
  642. {
  643. d->ForcedTranslucent = true;
  644. this->setAttribute(Qt::WA_TranslucentBackground, true);
  645. }
  646. break;
  647. case ScrollEffect:
  648. {
  649. d->setupPopupPixmapWidget();
  650. d->PopupPixmapWidget->show();
  651. this->hide();
  652. break;
  653. }
  654. default:
  655. break;
  656. }
  657. switch(d->currentAnimation()->state())
  658. {
  659. case QAbstractAnimation::Stopped:
  660. d->currentAnimation()->start();
  661. break;
  662. case QAbstractAnimation::Paused:
  663. d->currentAnimation()->resume();
  664. break;
  665. default:
  666. case QAbstractAnimation::Running:
  667. break;
  668. }
  669. }
  670. // --------------------------------------------------------------------------
  671. double ctkPopupWidget::windowAlpha()const
  672. {
  673. Q_D(const ctkPopupWidget);
  674. return d->WindowAlpha;
  675. }
  676. // --------------------------------------------------------------------------
  677. void ctkPopupWidget::setWindowAlpha(double alpha)
  678. {
  679. Q_D(ctkPopupWidget);
  680. d->WindowAlpha = alpha;
  681. this->repaint();
  682. }
  683. // --------------------------------------------------------------------------
  684. QRect ctkPopupWidget::windowGeometry()const
  685. {
  686. Q_D(const ctkPopupWidget);
  687. return d->PopupPixmapWidget->geometry();
  688. }
  689. // --------------------------------------------------------------------------
  690. void ctkPopupWidget::setWindowGeometry(QRect newGeometry)
  691. {
  692. Q_D(ctkPopupWidget);
  693. d->PopupPixmapWidget->setGeometry(newGeometry);
  694. d->PopupPixmapWidget->repaint();
  695. }