From 5b6b6c6eafe0d7545cfaced6ab715d740b8ea209 Mon Sep 17 00:00:00 2001 From: nowrep Date: Mon, 17 Mar 2014 10:43:18 +0100 Subject: [PATCH] [LoadingAnimation] New loading animation Instead of using QMovie with GIF, one PNG file with all frames is now animated. Fixes issue with bad transparent background of previous GIF animation. --- src/lib/data/icons.qrc | 2 +- src/lib/data/icons/other/loading.png | Bin 0 -> 4159 bytes src/lib/data/icons/other/progress.gif | Bin 2006 -> 0 bytes src/lib/lib.pro | 6 +- src/lib/webview/tabbedwebview.cpp | 20 ----- src/lib/webview/tabbedwebview.h | 1 - src/lib/webview/tabicon.cpp | 107 ++++++++++++++++++++++++++ src/lib/webview/tabicon.h | 60 +++++++++++++++ src/lib/webview/tabwidget.cpp | 68 ++++------------ src/lib/webview/tabwidget.h | 6 +- 10 files changed, 190 insertions(+), 80 deletions(-) create mode 100644 src/lib/data/icons/other/loading.png delete mode 100644 src/lib/data/icons/other/progress.gif create mode 100644 src/lib/webview/tabicon.cpp create mode 100644 src/lib/webview/tabicon.h diff --git a/src/lib/data/icons.qrc b/src/lib/data/icons.qrc index 7c3243a4b..274220c12 100644 --- a/src/lib/data/icons.qrc +++ b/src/lib/data/icons.qrc @@ -25,7 +25,6 @@ icons/menu/rss.png icons/other/about.png icons/other/feed.png - icons/other/progress.gif icons/other/bigstar.png icons/theme/unsortedbookmarks.png icons/locationbar/safe.png @@ -81,5 +80,6 @@ icons/theme/collapse.png icons/theme/speeddial.png icons/theme/view-restore.png + icons/other/loading.png diff --git a/src/lib/data/icons/other/loading.png b/src/lib/data/icons/other/loading.png new file mode 100644 index 0000000000000000000000000000000000000000..fa7f059fa99632fba5374dae721b1dca54ebd21c GIT binary patch literal 4159 zcmV-F5Ww$=P)E4$*2SgS}fwM5f|~tX!QCksL?hWB^p@~)@&3FArxyU zVi1Mw#u%bRG}ld7v!YE9F&YH?5hO;Dpka|v6PIP#yA(U2s40q_+CR>@zJ5*j>)Vq* zc2CvRd#}5{_jaFqe&5scF$yS(lQtj%I`wZSu+dr5UxXYP!uO4 zfv*7n13ciYIb0Dx7`Op2z!;zpxY1d&B@o{NTn=2M_*P&qunBnBS#ziaUjxold?(NX zd+i29(UICmf%}}OLYEDWc~L6zXG0e*0^SP z9b*C_JMF;92oGKW);nvCrmy{2*lp~Sb{7Xz_*+=^D5vk1%7}CZkkp*Ypw{upA9^QEPNh4;jFo_3I0r- ze_X*O`++&mn#T+9X93@Dg5L?;?yUJm0scJTd%#Hr_$|N;XU$s$_|F0VfCz6MZ3MpJ zta-lxe?736WBH%P-{P#a z{L>KrZP&jRU_5Z9jo({!%wh|xTR7{T*^ zyAXqVhqLC10=$3T18GAW#mQLU4&VYr{+{;df(%eq?D#2)N8y^Ku5i1Ti4}z-=+pQHW8vENjH0IGKq= zowJ=adot%b5W{*U5)pkqYeb?rxf;nd9?jFEC{8ZdXB>Lra zNcnJ=v*v-k>zYv%CsPsovD7>EN(Lx(qrU;-tPlj^YkCuRc~7RwyA1IV=LV!1*8`jV zLaFksOkJ|VSu?!}ehARwtT~{+F94pWF60N1Naz7)O<%w>bs;H|SKeOW2}B8Yl|_6S zvc67TQTG5p0p3MYuu~APeqWyVkK$w^@T%hbfz=3)_bIL$n3fuUsk7$J6#gv4YqkJA zh#`1c`OpDe3*4H*_ajQQM)Bt%A$AS;7hs-`5;SVP4p@Yw^dLs)vpy0~&;QSQd=BtP zI@O5cWDFwwU3#b&_)BNaEMn}BH3LY1vy`u=I%|6L+!Vyf-Pz0uM{%+UiLeeSezzVU zi)02(Q&f$Re~GN$>CT$%db|eIvQ9Y%--5{bBw%t;BvvxUb$~^T_}a<_NC){EFatQ* zS#wlxtUt6qqzbplS<|fx^9Sl-??ujhB%b*z-HvxkEs*rn*E%5db7h>bBgl+JtV^Tj(70)@*){toy~yYFtsAECXig&!?Oyb&>M1uV|26?vd4tphA0fPofFC<+zNp6+BdJM92JjLv6{!bZqsLClODhZT z3xIC|Yn(ME1e3u}1l~jffXP+yI>tMQ9G)^z1Jr>CO*i7T5+t-drzk(q8RI>~vyMYT zUJ%RvNgtV%;2%Ts^)X0+6eK)7#e2pQ{N;$kwId7#@l2obp0Nbqig^4^;2k~uHt<&= zQB!K1(+~py@Lgxk>`<)YCm{tw2r%9`__L{}DL$N z(Fc42G2C6wn(qYS7b20^5#Tr^!tAS{Hy0q$=275yL}!jxaQ+eS?}+T4P{y-@G2TI* z`@|4k%fa6Vd;>TmuU-*Cd-SslDJ~5`Jma(qW9&e7D^5=xTN7e@l-@;lYr0a$R#jj~ zkK)ft9eXIm_yDMp=>*PB9looI@ll$hpND|pf_I9h>gVRF#z*OV{d}}6YSYb!bAWq+ zYxJHNR3t(#URu{%k>bcRFGKL&=vN zS`kCk1w38>zezs_DV9*d%dNsZRiT{EJPmDyDY*4C0*@U(*HH4#b=1?u_No&!`LTe;@{U zZ3V-<4Va+cKZWdA{wxp+($e6m1KH*IK?VFDQ{UT>9iQNI8{w6wQ8XIVs`#SazB2M@ z>Ok>+t%eT}@9Fp&QuOOYB7qwMfnET5k@CLX{F9gGWSwO?MN7# z7X09FRBKnmbqs)gRXmYW8eh3>K*`S;8aWo>D~IArHQ>Vv24pF4J5ob@7*VLE^|lP9 z3#Bax->N+Ou*~nn74avgzWW}hDwJ+Z#Y%{L33j^Vrcy8kJVsQv>n7S#KGQirXH7SL#NZyVBlk z6yb_^2_k&nBaH}cC4i3_-i89d(?g>J=grc;>gNdq#DAclLz`YzOgky=8#;z`r{!V) zJBpL773WSXjSuC6Jh{qEI%VF2toINClrgF|IeOYf1>>m&>-6sI&H*^B8L98N{YWJ= zjXJ-#R|QAXXgMW~kK*JWy|2feHSC!@DGkhCjIF2AG&vVq3_)^{GFQZwAv00~oUU;qzz!JsDXrw9fHGKw;|9l|62HdFl zb;$h>K^m<>X&SPC>k$5(sXZe>qy`MdQ*rJz`LuD;0P!yXqXO40k5YeF@Yz7@mDJOQexx3>1{hmmZjV2Ntp8q>hfw@@{l1@iEhUJw*XK+6vj^GqsDkfA zbkF0rX3mdoCWC6ge~8qt_5p9GQC^5R&~NHCdo!AaL|_isP}9Bq^{ETKuMe7c0~3%P zj~3uTXHBmbebY@%PeyT)+X<_?5YOlhEO*xI)#BlDy`&BJk#4i+lJ)@Ij})ADYR$@f z)JfVCQb>`!D)CdK?$E3FNA>h9?WriEdw@+^0NjuC`~WOg1KX6er=-d*>j&0%LvUs)6r#YtNfCl4Xp-=3D0_1&cK zL$wFUQtwq;Tr_VKC&SW4F^ZExk@U*FPThbuY#L~5&2NDZqB!~6EI-wFJ&zRr0TwF% z`)G{BRz`7hcUFg^IH^T(@>Qgv65xJk%@Hqf(~+&*kw{(Tr%{|tN1~%WNZ-Q6NJH5m z#PTmpjXxVHES{ueyr~RZrT7uZcIjM1ake2lDW2{{!n$$#fUiVxGTWtI`H13VoL+aG zj+x%Bo{vNTe*9B9Nk|5cxcgde=3G z0c>m5LxjklSLz<5aj}$C=ANY9gb5P4ly%0BMdYd-iB4Nnr#AqP6ySVE`2HwPe0^#h z5}|uqOWo;vI#)jjBRXUr*lx{ZZ94!cM?}*}LEz)E42}G~` zD>fU@QqM7TbrHRWG|M$8iH3d&jj6ys{Tq%54oKQ! z+_CNIBNgxGKZvyR??noaT}YVNqxfwZ{Ai@n&etUg^mrhbOH0X`?Y-JkLhok)1S z1c}o2s5cr1+=7JQS7Z&8_P9Kc80!_l-1OFRs_xZ|yxP&5!B0h^%Y8_f`Z0z;)3))z z8`+|9B;C9gi3aCYZ70yEcO}w9xxVcB9DE02h~^DsH&Ep#as}^c{izhyn;7>2=WFB^ zf_o8hPM&rszN~36-Q1d{&4~QwZn#8o@}D#syDY5*uE`pDjh>&O_&qpJ&moPrS?4}U z@gs9ljq_jY*SMh(QA7J#h(~PC0JkGb^+c1ijZe=aWyJypqOB7&Hm zzXy5OYH5*j==`&gh$72~gNSl1Y7(8aAzo)D$L^N&As)2BFl6vU5YKok^%q+E5YKTG zvHA;KL6@@{(ItpC??-a<4-wBY9C;n#ktY1}-Od*xhJFL^Ur5pM<4BbBbd&WPq0c`B z5tLVS{x-e;o@Q+t%D=Axe}-(0ZwXB^6yK`%z8mSZ4#q0J1$m_)xQo2v_+yYAzu+iM z(~c!bop3oKKOrgK3pCdC4j}2vgUy~#oBY1cvF{}AMqYhkMp8$>=;c{m6-+f`laQ2b5Tb;^eL8B0rc(cR20h4&q(NJ*Y6$#J;Q_=DZLQetdKzLx zj{xsiX?9aZ9#8${$@fDWG!^eV#D^iga|4K|1_Or&uuJs+j#QU=U4{S9plkSLME|w{ z8$x-gj;sqY0=?+l^%dl&4UwM_hy&eGMSpeu#~||KNPq73aIhG19f0LQSm z)+&J#`~<-J_wQG&S~W5;??=1s>FEJ~N5U`RiU@Q_ z_%*d)VPl(bp>AbkTZ67-d2?-9qnFY(w6!gz^m;!!FKzT@d0Up~LBem5o&t83gDxw` z&N76JLG2lT;Qeu>K(=)qfLws*HAz!51z!Hil(Z~JQbs-^a`LC?dT2CQNlqdiuN6oP z+XKQPW7~l>&kDn%RK0{f4~`v&^#XGNlt$ydM%o5tF>$?Ez8T7;>Ry|}2^Go-@q#%$ zj^R`jb;%k7p)koUZvvANQe@L|v>6sfdt%vX@%^{VwwmkXr4sO81pZ4+`v*1Vu-S8> z=FQg#z%t>p$hnzSQx+ui?$TL>DvWhkr&R@9;bk3sHXk8P5}}bREH3W{6bZvitQQ#u zrp&n6kKs`5q5G-2JD^A@?`Q3UAWuDWlAxD3FT>pIoFWB9=?iK!qa2-Fkx?1%cGR*W zn_JY>rQ8989u7#xe5{yFAH*mkVjHE^84>|FWW~~$=y6d^e%@5QsG%Ik9Wxh4$+^UZ z9*fYBS*C$rWxWWLOXkCjSX;>5+yt`=4Iwrw6KZpa5IdCEG% zxu(a{tkGz|^f<}e9jT6d+HBXq78r%5^=IAqQ&EI$Gn5eN6 z#Swn5)o%72uZ}J%1In!vX}+8F4hk1 zUX2KR^Zd|eVng{&%VBN4F@(ny575IR9xd&c7($K})eu))6_>Y$L9#CI39p?yRl*T0 zMsVpVpGQXUBx9gpR&$#?)NCRQ*PnKC@c*-!!JeC%uA(sku(ZkRj+ZZsu<^L2#>J9U z;-rcSnj`Hty^x>dtAkcWx7adM1z9H{0-LPiQr}gkS_bjp(2NvlV2oGuOBO~(VAzr znG+2Hpjf9uLg$;x6L}KX;{-6`=F}p4z+j~WSG*gCMxskBuc!M+5jrz013aPi4F-rD zEtF1PMtl=v zq|v&statusBar(), SLOT(showMessage(QString))); } @@ -131,8 +130,6 @@ void TabbedWebView::userLoadAction(const QUrl &url) void TabbedWebView::slotLoadStarted() { - tabWidget()->startTabAnimation(tabIndex()); - if (title().isNull()) { tabWidget()->setTabText(tabIndex(), tr("Loading...")); } @@ -142,9 +139,6 @@ void TabbedWebView::slotLoadStarted() void TabbedWebView::slotLoadFinished() { - tabWidget()->stopTabAnimation(tabIndex()); - - showIcon(); QHostInfo::lookupHost(url().host(), this, SLOT(setIp(QHostInfo))); if (isCurrent()) { @@ -176,20 +170,6 @@ void TabbedWebView::titleChanged() tabWidget()->setTabText(tabIndex(), t); } -void TabbedWebView::showIcon() -{ - if (isLoading()) { - return; - } - - QIcon icon_ = icon(); - if (icon_.isNull()) { - icon_ = IconProvider::emptyWebIcon(); - } - - tabWidget()->setTabIcon(tabIndex(), icon_); -} - void TabbedWebView::linkHovered(const QString &link, const QString &title, const QString &content) { Q_UNUSED(title) diff --git a/src/lib/webview/tabbedwebview.h b/src/lib/webview/tabbedwebview.h index 218c8cfc3..ad8a9c975 100644 --- a/src/lib/webview/tabbedwebview.h +++ b/src/lib/webview/tabbedwebview.h @@ -60,7 +60,6 @@ public slots: void setAsCurrentTab(); void stop(); - void showIcon(); void slotLoadStarted(); void loadProgress(int prog); diff --git a/src/lib/webview/tabicon.cpp b/src/lib/webview/tabicon.cpp new file mode 100644 index 000000000..fc56cb45a --- /dev/null +++ b/src/lib/webview/tabicon.cpp @@ -0,0 +1,107 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2014 David Rosca +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* ============================================================ */ +#include "tabicon.h" +#include "webtab.h" +#include "tabbedwebview.h" + +#include + +#define ANIMATION_INTERVAL 70 + +TabIcon::TabIcon(QWidget* parent) + : QWidget(parent) + , m_tab(0) + , m_currentFrame(0) + , m_animationRunning(false) +{ + setObjectName(QSL("tab-icon")); + + m_animationImage = QImage(QSL(":icons/other/loading.png")); + m_framesCount = m_animationImage.width() / 16; + + m_updateTimer = new QTimer(this); + m_updateTimer->setInterval(ANIMATION_INTERVAL); + connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updateAnimationFrame())); + + resize(16, 16); +} + +void TabIcon::setWebTab(WebTab* tab) +{ + m_tab = tab; + + connect(m_tab->view(), SIGNAL(loadStarted()), this, SLOT(showLoadingAnimation())); + connect(m_tab->view(), SIGNAL(loadFinished(bool)), this, SLOT(hideLoadingAnimation())); + connect(m_tab->view(), SIGNAL(iconChanged()), this, SLOT(showIcon())); + + showIcon(); +} + +void TabIcon::setIcon(const QIcon &icon) +{ + m_siteImage = icon.pixmap(16).toImage(); + update(); +} + +void TabIcon::showLoadingAnimation() +{ + m_currentFrame = 0; + + // Start animation delayed with 100 ms + m_updateTimer->setInterval(100); + m_updateTimer->start(); +} + +void TabIcon::hideLoadingAnimation() +{ + m_animationRunning = false; + + m_updateTimer->stop(); + showIcon(); +} + +void TabIcon::showIcon() +{ + m_siteImage = m_tab->icon().pixmap(16).toImage(); + update(); +} + +void TabIcon::updateAnimationFrame() +{ + if (!m_animationRunning) { + m_animationRunning = true; + m_updateTimer->setInterval(ANIMATION_INTERVAL); + } + + update(); + m_currentFrame = (m_currentFrame + 1) % m_framesCount; +} + +void TabIcon::paintEvent(QPaintEvent* event) +{ + Q_UNUSED(event); + + QPainter p(this); + + if (m_animationRunning) { + p.drawImage(0, 0, m_animationImage, m_currentFrame * 16, 0, 16, 16); + } + else { + p.drawImage(0, 0, m_siteImage); + } +} diff --git a/src/lib/webview/tabicon.h b/src/lib/webview/tabicon.h new file mode 100644 index 000000000..b3eb8c745 --- /dev/null +++ b/src/lib/webview/tabicon.h @@ -0,0 +1,60 @@ +/* ============================================================ +* QupZilla - WebKit based browser +* Copyright (C) 2014 David Rosca +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* ============================================================ */ +#ifndef TABICON_H +#define TABICON_H + +#include +#include + +#include "qzcommon.h" + +class QTimer; + +class WebTab; + +class QUPZILLA_EXPORT TabIcon : public QWidget +{ + Q_OBJECT + +public: + explicit TabIcon(QWidget* parent = 0); + + void setWebTab(WebTab* tab); + void setIcon(const QIcon &icon); + +private slots: + void showIcon(); + void showLoadingAnimation(); + void hideLoadingAnimation(); + + void updateAnimationFrame(); + +private: + void paintEvent(QPaintEvent* event); + + WebTab* m_tab; + QTimer* m_updateTimer; + + QImage m_siteImage; + QImage m_animationImage; + int m_currentFrame; + int m_framesCount; + bool m_animationRunning; +}; + +#endif // TABICON_H diff --git a/src/lib/webview/tabwidget.cpp b/src/lib/webview/tabwidget.cpp index 4670449f6..f6d1c0f73 100644 --- a/src/lib/webview/tabwidget.cpp +++ b/src/lib/webview/tabwidget.cpp @@ -33,6 +33,7 @@ #include "datapaths.h" #include "qzsettings.h" #include "qtwin.h" +#include "tabicon.h" #include #include @@ -219,6 +220,19 @@ WebTab* TabWidget::weTab(int index) return qobject_cast(widget(index)); } +TabIcon* TabWidget::tabIcon(int index) +{ + TabIcon* icon = qobject_cast(m_tabBar->tabButton(index, m_tabBar->iconButtonPosition())); + + if (!icon) { + icon = new TabIcon(this); + icon->setWebTab(weTab(index)); + m_tabBar->setTabButton(index, m_tabBar->iconButtonPosition(), icon); + } + + return icon; +} + void TabWidget::showButtons() { m_buttonListTabs->show(); @@ -433,13 +447,6 @@ int TabWidget::addView(WebTab* tab) int index = addTab(tab, QString()); setTabText(index, tab->title()); - if (!tab->isLoading()) { - setTabIcon(index, tab->icon()); - } - else { - startTabAnimation(index); - } - connect(tab->view(), SIGNAL(wantsCloseTab(int)), this, SLOT(closeTab(int))); connect(tab->view(), SIGNAL(changed()), this, SIGNAL(changed())); connect(tab->view(), SIGNAL(ipChanged(QString)), m_window->ipLabel(), SLOT(setText(QString))); @@ -554,43 +561,6 @@ void TabWidget::tabMoved(int before, int after) m_lastTabIndex = before; } -void TabWidget::startTabAnimation(int index) -{ - if (!validIndex(index)) { - return; - } - - QLabel* label = qobject_cast(m_tabBar->tabButton(index, m_tabBar->iconButtonPosition())); - if (!label) { - label = new QLabel(); - label->setObjectName("tab-icon"); - m_tabBar->setTabButton(index, m_tabBar->iconButtonPosition(), label); - } - - if (label->movie()) { - label->movie()->start(); - return; - } - - QMovie* movie = new QMovie(":icons/other/progress.gif", QByteArray(), label); - movie->start(); - - label->setMovie(movie); -} - -void TabWidget::stopTabAnimation(int index) -{ - if (!validIndex(index)) { - return; - } - - QLabel* label = qobject_cast(m_tabBar->tabButton(index, m_tabBar->iconButtonPosition())); - - if (label && label->movie()) { - label->movie()->stop(); - } -} - void TabWidget::setCurrentIndex(int index) { m_lastTabIndex = currentIndex(); @@ -604,15 +574,7 @@ void TabWidget::setTabIcon(int index, const QIcon &icon) return; } - QLabel* label = qobject_cast(m_tabBar->tabButton(index, m_tabBar->iconButtonPosition())); - if (!label) { - label = new QLabel(); - label->setObjectName("tab-icon"); - label->resize(16, 16); - m_tabBar->setTabButton(index, m_tabBar->iconButtonPosition(), label); - } - - label->setPixmap(icon.pixmap(16, 16)); + tabIcon(index)->setIcon(icon); } void TabWidget::setTabText(int index, const QString &text) diff --git a/src/lib/webview/tabwidget.h b/src/lib/webview/tabwidget.h index 30ab412fb..c7d815b25 100644 --- a/src/lib/webview/tabwidget.h +++ b/src/lib/webview/tabwidget.h @@ -34,6 +34,7 @@ class QMenu; class BrowserWindow; class TabbedWebView; class TabBar; +class TabIcon; class TabWidget; class ClosedTabsManager; @@ -79,9 +80,6 @@ public: void savePinnedTabs(); void restorePinnedTabs(); - void startTabAnimation(int index); - void stopTabAnimation(int index); - void setCurrentIndex(int index); void setTabIcon(int index, const QIcon &icon); void setTabText(int index, const QString &text); @@ -145,6 +143,8 @@ private: WebTab* weTab(); WebTab* weTab(int index); + TabIcon* tabIcon(int index); + inline bool validIndex(int index) const { return index >= 0 && index < count(); } bool m_dontCloseWithOneTab;