Added fading animation to Play/Pause Button.
[bangarang:bangarang-kde-mirror.git] / src / app / common / sensiblewidgets.cpp
1 /* BANGARANG MEDIA PLAYER
2 * Copyright (C) 2009 Andrew Lake (jamboarder@yahoo.com)
3 * <http://gitorious.org/bangarang>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "sensiblewidgets.h"
20 #include "ratingdelegate.h"
21 #include "starrating.h"
22 #include "timercounter.h"
23
24 #include <KIcon>
25 #include <KFileDialog>
26 #include <QStylePainter>
27 #include <QPaintEvent>
28
29 SToolButton::SToolButton(QWidget * parent):QToolButton (parent) 
30 {
31     m_hoverDelay = 0;
32     m_holdEnabled = true;
33     m_timer = new QTimer(this);
34     m_holdIcon = NULL;
35     m_animateHold = false;
36     m_animationTimer = new TimerCounter(0, 50, false);
37     connect(m_animationTimer, SIGNAL(timeout()), this, SLOT(repaint()));
38     connect(this, SIGNAL(pressed()), this, SLOT(pressedEvent()));
39     connect(this, SIGNAL(released()), this, SLOT(releasedEvent()));
40 }
41 SToolButton::~SToolButton() 
42 {
43     delete m_timer;
44 }
45 void SToolButton::setHoverDelay(int i)
46 {
47     m_hoverDelay = i;
48 }
49 int SToolButton::hoverDelay()
50 {
51     return m_hoverDelay;
52 }
53 void SToolButton::enterEvent(QEvent *event)
54 {
55     Q_UNUSED(event);
56     m_hovered = true;
57     if (m_hoverDelay > 0) {
58         QTimer::singleShot(m_hoverDelay, this, SLOT(hoverTimeout()));
59     } else {   
60         emit this->entered(); 
61     }
62 }
63 void SToolButton::leaveEvent(QEvent *event)
64 {
65     Q_UNUSED(event);
66     m_hovered = false;
67     emit this->exited(); 
68 }
69 void SToolButton::hoverTimeout()
70 {
71     if (m_hovered) {
72         emit this->entered();
73     }
74 }
75 void SToolButton::setHoldDelay(int i)
76 {
77     m_holdDelay = i;
78     m_animationTimer->setMax(i/m_animationTimer->interval());
79 }
80 int SToolButton::holdDelay()
81 {
82     return m_holdDelay;
83 }
84 void SToolButton::setHoldIcon(KIcon icon, bool animation)
85 {
86     delete m_holdIcon;
87     m_holdIcon = new KIcon(icon); //copy it
88     m_animateHold = animation;
89 }
90 void SToolButton::enableHold(bool enable)
91 {
92     m_holdEnabled = enable; //no animation if no icon was set
93 }
94 void SToolButton::disableHold()
95 {
96     m_holdEnabled = false;
97 }
98 void SToolButton::pressedEvent()
99 {
100     m_pressed = true;
101     if (m_holdDelay <= 0 || !m_holdEnabled) { //nothing else to do
102         return;
103     }
104     if (m_animateHold) {
105         m_animationTimer->reset();
106     }
107  
108     //start timer when hold timeout exceeds
109     m_timer->singleShot(m_holdDelay, this, SLOT(holdTimeout()));
110 }
111 void SToolButton::holdTimeout()
112 {
113     if (m_animateHold || m_animationTimer->isActive() ){
114         m_animationTimer->stop();
115     }
116     if (!m_pressed) {
117         return; //not pressed anymore, no actions required
118     }
119     if (m_holdIcon) {
120         setIcon(*m_holdIcon);
121     }
122     emit this->held();
123 }
124 void SToolButton::releasedEvent()
125 {
126     m_pressed = false;
127     m_timer->stop();
128 }
129 void SToolButton::paintEvent(QPaintEvent* event)
130 {
131     QToolButton::paintEvent(event);
132     if (m_animateHold && m_pressed && m_holdEnabled) {
133         qreal progress = (qreal) m_animationTimer->getValue() / (qreal) m_animationTimer->max();
134         //progress *= progress;
135         const QPixmap &pxm = m_holdIcon->pixmap(iconSize());
136         QRect pmRect = pxm.rect();
137         pmRect.moveCenter(rect().center());
138         if (pmRect.intersects(event->rect())) {
139             QPainter painter(this);
140             painter.setOpacity(progress);
141             painter.drawPixmap(pmRect.left(), pmRect.top(), pxm);
142         }
143     }
144 }
145
146
147 SFrame::SFrame(QWidget * parent):QFrame (parent) 
148 {
149     m_hoverDelay = 0;
150 }
151 SFrame::~SFrame() 
152 {
153 }
154 void SFrame::setHoverDelay(int i)
155 {
156     m_hoverDelay = i;
157 }
158 int SFrame::hoverDelay()
159 {
160     return m_hoverDelay;
161 }
162 void SFrame::enterEvent(QEvent *event)
163 {
164     Q_UNUSED(event);
165     m_hovered = true;
166     if (m_hoverDelay > 0) {
167         QTimer::singleShot(m_hoverDelay, this, SLOT(hoverTimeout()));
168     } else {   
169         emit this->entered(); 
170     }
171 }
172 void SFrame::leaveEvent(QEvent *event)
173 {
174     Q_UNUSED(event);
175     m_hovered = false;
176     emit this->exited(); 
177 }
178 void SFrame::mouseMoveEvent(QMouseEvent *event)
179 {
180     emit mouseMoved();
181     Q_UNUSED(event);
182 }
183 void SFrame::resizeEvent(QResizeEvent *)
184 {
185     emit resized();
186 }
187 void SFrame::hoverTimeout()
188 {
189     if (m_hovered) {
190         emit this->entered();
191     }
192 }
193
194 SLabel::SLabel(QWidget * parent):QLabel (parent) 
195 {
196     m_hoverPixmap = new QPixmap();
197     m_mousePressed = false;
198 }
199 SLabel::~SLabel() 
200 {
201 }
202 void SLabel::setHoverPixmap(QPixmap * pixmap)
203 {
204     m_hoverPixmap = pixmap;
205 }
206 void SLabel::enterEvent(QEvent *event)
207 {
208     Q_UNUSED(event);
209     if (!m_hoverPixmap->isNull()) {
210         m_pixmap = *this->pixmap();
211         this->setPixmap(*m_hoverPixmap);
212     }
213     emit this->entered(); 
214 }
215 void SLabel::leaveEvent(QEvent *event)
216 {
217     Q_UNUSED(event);
218    if (!m_hoverPixmap->isNull()) {
219         this->setPixmap(m_pixmap);
220     }
221     emit this->exited(); 
222 }
223
224 SListWidget::SListWidget(QWidget * parent):QListWidget (parent) 
225 {
226     connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(compareSelectionChanges()));
227 }
228 SListWidget::~SListWidget() 
229 {
230 }
231 void SListWidget::compareSelectionChanges()
232 {
233     QList<QListWidgetItem *> currentSelectedItems = this->selectedItems();
234     for (int i = 0; i < currentSelectedItems.count(); ++i) {
235         if (lastSelectedItems.indexOf(currentSelectedItems.at(i)) == -1) {
236             emit selected(currentSelectedItems.at(i));
237         }
238     }
239     for (int i = 0; i < lastSelectedItems.count(); ++i) {
240         if (currentSelectedItems.indexOf(lastSelectedItems.at(i)) == -1) {
241             emit unSelected(lastSelectedItems.at(i));
242         }
243     }
244     lastSelectedItems = currentSelectedItems;
245 }
246
247 void SListWidget::selectorEntered()
248 {
249     this->setSelectionMode(QAbstractItemView::MultiSelection);
250 }
251
252 void SListWidget::selectorExited()
253 {
254     this->setSelectionMode(QAbstractItemView::ExtendedSelection);
255 }
256
257 SRatingCombo::SRatingCombo(QWidget * parent) : QComboBox(parent)
258 {
259     this->setItemDelegate(new RatingDelegate(this));
260 }
261
262 void SRatingCombo::paintEvent (QPaintEvent * e)
263 {
264     QVariant ratingData = this->itemData(this->currentIndex(),Qt::UserRole).toInt();
265     if (ratingData.isValid()) {
266         QStylePainter p(this);
267         QStyleOptionComboBox option;
268         option.initFrom(this);
269
270         p.drawComplexControl(QStyle::CC_ComboBox, option);
271
272         QRect subRect = p.style()->subElementRect(QStyle::SE_ComboBoxFocusRect, &option);
273         const int left = subRect.left();
274         const int top = subRect.top();
275         const int height = subRect.height();
276
277         int rating = ratingData.toInt();
278         StarRating starRating = StarRating(rating, StarRating::Medium);
279         starRating.setRating(rating);
280         QSize ratingSize = starRating.sizeHint();
281         int ratingLeft = left + 2;
282         int ratingTop = top + (height - ratingSize.height())/2;
283         QRect ratingRect = QRect(QPoint(ratingLeft, ratingTop), ratingSize);
284         starRating.setPoint(ratingRect.topLeft());
285         if (!this->isEnabled()) {
286             starRating.setHoverAtPosition(ratingRect.topLeft());
287         }
288         starRating.paint(&p);
289     } else {
290         QComboBox::paintEvent(e);
291     }
292
293 }
294
295 #include "sensiblewidgets.moc"