1 /* This file is part of Clementine.
2    Copyright 2010, David Sansome <me@davidsansome.com>
3 
4    Clementine is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8 
9    Clementine is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with Clementine.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include "config.h"
19 #include "trackslider.h"
20 #include "ui_trackslider.h"
21 #include "core/timeconstants.h"
22 #include "core/utilities.h"
23 
24 #include <QSettings>
25 
26 #ifdef HAVE_MOODBAR
27 #include "moodbar/moodbarproxystyle.h"
28 #endif
29 
30 const char* TrackSlider::kSettingsGroup = "MainWindow";
31 
TrackSlider(QWidget * parent)32 TrackSlider::TrackSlider(QWidget* parent)
33     : QWidget(parent),
34       ui_(new Ui_TrackSlider),
35       moodbar_style_(nullptr),
36       setting_value_(false),
37       show_remaining_time_(true),
38       slider_maximum_value_(0) {
39   ui_->setupUi(this);
40 
41   UpdateLabelWidth();
42 
43   // Load settings
44   QSettings s;
45   s.beginGroup(kSettingsGroup);
46   show_remaining_time_ = s.value("show_remaining_time").toBool();
47 
48   connect(ui_->slider, SIGNAL(sliderMoved(int)), SIGNAL(ValueChanged(int)));
49   connect(ui_->slider, SIGNAL(valueChanged(int)), SLOT(ValueMaybeChanged(int)));
50   connect(ui_->slider, SIGNAL(SeekForward()), SIGNAL(SeekForward()));
51   connect(ui_->slider, SIGNAL(SeekBackward()), SIGNAL(SeekBackward()));
52   connect(ui_->slider, SIGNAL(Previous()), SIGNAL(Previous()));
53   connect(ui_->slider, SIGNAL(Next()), SIGNAL(Next()));
54   connect(ui_->remaining, SIGNAL(Clicked()), SLOT(ToggleTimeDisplay()));
55 }
56 
~TrackSlider()57 TrackSlider::~TrackSlider() { delete ui_; }
58 
SetApplication(Application * app)59 void TrackSlider::SetApplication(Application* app) {
60 #ifdef HAVE_MOODBAR
61   moodbar_style_ = new MoodbarProxyStyle(app, ui_->slider);
62 #endif
63 }
64 
UpdateLabelWidth()65 void TrackSlider::UpdateLabelWidth() {
66   // We set the label's minimum size so it won't resize itself when the user
67   // is dragging the slider.
68   UpdateLabelWidth(ui_->elapsed, "0:00:00");
69   UpdateLabelWidth(ui_->remaining, "-0:00:00");
70 }
71 
UpdateLabelWidth(QLabel * label,const QString & text)72 void TrackSlider::UpdateLabelWidth(QLabel* label, const QString& text) {
73   QString old_text = label->text();
74   label->setText(text);
75   label->setMinimumWidth(0);
76   int width = label->sizeHint().width();
77   label->setText(old_text);
78 
79   label->setMinimumWidth(width);
80 }
81 
sizeHint() const82 QSize TrackSlider::sizeHint() const {
83   int width = 500;
84   width += ui_->elapsed->sizeHint().width();
85   width += ui_->remaining->sizeHint().width();
86 
87   int height =
88       qMax(ui_->slider->sizeHint().height(), ui_->elapsed->sizeHint().height());
89 
90   return QSize(width, height);
91 }
92 
SetValue(int elapsed,int total)93 void TrackSlider::SetValue(int elapsed, int total) {
94   setting_value_ =
95       true;  // This is so we don't emit from QAbstractSlider::valueChanged
96 
97   ui_->slider->setMaximum(total);
98   if (!ui_->slider->isSliderDown()) {
99     ui_->slider->setValue(elapsed);
100   }
101 
102   setting_value_ = false;
103 
104   UpdateTimes(elapsed / kMsecPerSec);
105 }
106 
UpdateTimes(int elapsed)107 void TrackSlider::UpdateTimes(int elapsed) {
108   ui_->elapsed->setText(Utilities::PrettyTime(elapsed));
109   // update normally if showing remaining time
110   if (show_remaining_time_) {
111     ui_->remaining->setText(
112         "-" + Utilities::PrettyTime((ui_->slider->maximum() / kMsecPerSec) -
113                                     elapsed));
114   } else {
115     // check if slider maximum value is changed before updating
116     if (slider_maximum_value_ != ui_->slider->maximum() ||
117         !ui_->slider->isEnabled()) {
118       slider_maximum_value_ = ui_->slider->maximum();
119       ui_->remaining->setText(
120           Utilities::PrettyTime((ui_->slider->maximum() / kMsecPerSec)));
121     }
122   }
123   setEnabled(true);
124 }
125 
SetStopped()126 void TrackSlider::SetStopped() {
127   setEnabled(false);
128   ui_->elapsed->setText("0:00:00");
129   ui_->remaining->setText("0:00:00");
130 
131   setting_value_ = true;
132   ui_->slider->setValue(0);
133   slider_maximum_value_ = 0;
134   setting_value_ = false;
135 }
136 
SetCanSeek(bool can_seek)137 void TrackSlider::SetCanSeek(bool can_seek) {
138   ui_->slider->setEnabled(can_seek);
139 }
140 
Seek(int gap)141 void TrackSlider::Seek(int gap) {
142   if (ui_->slider->isEnabled())
143     ui_->slider->setValue(ui_->slider->value() + gap * kMsecPerSec);
144 }
145 
ValueMaybeChanged(int value)146 void TrackSlider::ValueMaybeChanged(int value) {
147   if (setting_value_) return;
148 
149   UpdateTimes(value / kMsecPerSec);
150   emit ValueChangedSeconds(value / kMsecPerSec);
151 }
152 
event(QEvent * e)153 bool TrackSlider::event(QEvent* e) {
154   switch (e->type()) {
155     case QEvent::ApplicationFontChange:
156     case QEvent::StyleChange:
157       UpdateLabelWidth();
158       break;
159     default:
160       break;
161   }
162   return false;
163 }
164 
ToggleTimeDisplay()165 void TrackSlider::ToggleTimeDisplay() {
166   show_remaining_time_ = !show_remaining_time_;
167   if (!show_remaining_time_) {
168     // we set the value to -1 because the label must be updated
169     slider_maximum_value_ = -1;
170   }
171   UpdateTimes(ui_->slider->value() / kMsecPerSec);
172 
173   // save this setting
174   QSettings s;
175   s.beginGroup(kSettingsGroup);
176   s.setValue("show_remaining_time", show_remaining_time_);
177 }
178