TTKMusicPlayer  4.3.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
musicspectrumwidget.cpp
Go to the documentation of this file.
1 #include "musicspectrumwidget.h"
2 #include "ui_musicspectrumwidget.h"
3 #include "musicqmmputils.h"
4 #include "musicformats.h"
5 #include "musictoastlabel.h"
6 #include "musicwidgetheaders.h"
7 #include "musictopareawidget.h"
8 #include "musicfileutils.h"
9 
10 #include <QPluginLoader>
11 
12 #include <qmmp/florid.h>
13 #include <qmmp/visualfactory.h>
14 #include <qmmp/lightfactory.h>
15 #include <qmmp/soundcore.h>
16 
17 static constexpr const char *LIGHT_WAVEFORM_MODULE = "lightwaveform";
18 static constexpr const char *LIGHT_SPECTROGRAM_MODULE = "lightspectrogram";
19 
22  m_ui(new Ui::MusicSpectrumWidget),
23  m_spectrumLayout(nullptr)
24 {
25  m_ui->setupUi(this);
26  setMinimumSize(750, 650);
27  setAttribute(Qt::WA_DeleteOnClose);
28  setBackgroundLabel(m_ui->background);
29 
30  setStyleSheet(TTK::UI::MenuStyle02);
31 
32  m_ui->topTitleCloseButton->setIcon(QIcon(":/functions/btn_close_hover"));
33  m_ui->topTitleCloseButton->setStyleSheet(TTK::UI::ToolButtonStyle04);
34  m_ui->topTitleCloseButton->setCursor(QCursor(Qt::PointingHandCursor));
35  m_ui->topTitleCloseButton->setToolTip(tr("Close"));
36  connect(m_ui->topTitleCloseButton, SIGNAL(clicked()), SLOT(close()));
37 
38  m_ui->mainViewWidget->setStyleSheet(TTK::UI::TabWidgetStyle01);
39 
40  m_ui->localFileButton->setStyleSheet(TTK::UI::PushButtonStyle04);
41  m_ui->localFileButton->setCursor(QCursor(Qt::PointingHandCursor));
42  m_ui->openFileButton->setStyleSheet(TTK::UI::PushButtonStyle04);
43  m_ui->openFileButton->setCursor(QCursor(Qt::PointingHandCursor));
44 
45  m_ui->spectrumNormalLayoutButton->setStyleSheet(TTK::UI::ToolButtonStyle05);
46  m_ui->spectrumPlusLayoutButton->setStyleSheet(TTK::UI::ToolButtonStyle05);
47  m_ui->spectrumWaveLayoutButton->setStyleSheet(TTK::UI::ToolButtonStyle05);
48  m_ui->spectrumFlowLayoutButton->setStyleSheet(TTK::UI::ToolButtonStyle05);
49  m_ui->spectrumFloridLayoutButton->setStyleSheet(TTK::UI::ToolButtonStyle05);
50 
51 #ifdef Q_OS_UNIX
52  m_ui->spectrumNormalLayoutButton->setFocusPolicy(Qt::NoFocus);
53  m_ui->spectrumPlusLayoutButton->setFocusPolicy(Qt::NoFocus);
54  m_ui->spectrumWaveLayoutButton->setFocusPolicy(Qt::NoFocus);
55  m_ui->spectrumFlowLayoutButton->setFocusPolicy(Qt::NoFocus);
56  m_ui->spectrumFloridLayoutButton->setFocusPolicy(Qt::NoFocus);
57  m_ui->localFileButton->setFocusPolicy(Qt::NoFocus);
58  m_ui->openFileButton->setFocusPolicy(Qt::NoFocus);
59 #endif
60  // Objects Mouse tracking
61  setObjectsTracking({m_ui->background});
62 
63  connect(m_ui->localFileButton, SIGNAL(clicked()), SLOT(localFileButtonClicked()));
64  connect(m_ui->openFileButton, SIGNAL(clicked()), SLOT(openFileButtonClicked()));
65  connect(m_ui->spectrumNormalLayoutButton, SIGNAL(stateChanged(bool&,QString)), SLOT(spectrumNormalTypeChanged(bool&,QString)));
66  connect(m_ui->spectrumPlusLayoutButton, SIGNAL(stateChanged(bool&,QString)), SLOT(spectrumPlusTypeChanged(bool&,QString)));
67  connect(m_ui->spectrumWaveLayoutButton, SIGNAL(stateChanged(bool&,QString)), SLOT(spectrumWaveTypeChanged(bool&,QString)));
68  connect(m_ui->spectrumFlowLayoutButton, SIGNAL(stateChanged(bool&,QString)), SLOT(spectrumFlowTypeChanged(bool&,QString)));
69  connect(m_ui->spectrumFloridLayoutButton, SIGNAL(stateChanged(bool&,QString)), SLOT(spectrumFloridTypeChanged(bool&,QString)));
70 }
71 
73 {
75  for(const Data &data : qAsConst(m_spectrums))
76  {
77  TTK::TTKQmmp::setVisualEnabled(data.m_module, false, this);
78  }
79  delete m_ui;
80 }
81 
83 {
84  createSpectrumWidget(Data::Module::Normal, state, name, m_ui->spectrumNormalAreaLayout);
85 }
86 
88 {
89  createSpectrumWidget(Data::Module::Plus, state, name, m_ui->spectrumPlusAreaLayout);
90 }
91 
93 {
94  if(name == LIGHT_WAVEFORM_MODULE)
95  {
96  createLightWidget(Data::Module::Light, state, name, m_ui->spectrumWaveAreaLayout);
97  }
98  else
99  {
100  createSpectrumWidget(Data::Module::Wave, state, name, m_ui->spectrumWaveAreaLayout);
101  }
102 }
103 
105 {
106  createFlowWidget(Data::Module::Flow, state, name, m_ui->spectrumFlowAreaLayout);
107 }
108 
110 {
111  createFloridWidget(Data::Module::Florid, state, name, m_ui->spectrumFloridAreaLayout);
112 }
113 
115 {
116  bool state = true;
117  createLightWidget(Data::Module::Light, state, LIGHT_SPECTROGRAM_MODULE, m_ui->spectrumLightAreaLayout);
118 }
119 
121 {
123  if(!path.isEmpty())
124  {
125  bool state = true;
126  createLightWidget(Data::Module::Light, state, LIGHT_SPECTROGRAM_MODULE, m_ui->spectrumLightAreaLayout, path);
127  }
128 }
129 
130 void MusicSpectrumWidget::fullscreenByUser(QWidget *widget, bool state)
131 {
132  if(state)
133  {
134  QWidget *parent = TTKObjectCast(QWidget*, widget->parent());
135  if(parent)
136  {
137  m_spectrumLayout = parent->layout();
138  widget->setParent(nullptr);
139  widget->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
140  widget->showFullScreen();
141  }
142  }
143  else
144  {
145  if(m_spectrumLayout)
146  {
147 #ifdef Q_OS_WIN
148  widget->showNormal();
149  widget->setWindowFlags(Qt::Window);
150  m_spectrumLayout->addWidget(widget);
151 #else
152  Data spem;
153  for(int i = 0; i < m_spectrums.count(); ++i)
154  {
155  if(m_spectrums[i].m_object == widget)
156  {
157  spem = m_spectrums.takeAt(i);
158  break;
159  }
160  }
161 
162  if(spem.m_module.isEmpty())
163  {
164  return;
165  }
166 
167  TTK::TTKQmmp::setVisualEnabled(spem.m_module, false, this);
168 
169  bool state = true;
170  switch(spem.m_type)
171  {
173  {
175  break;
176  }
177  case Data::Module::Plus:
178  {
180  break;
181  }
182  case Data::Module::Wave:
183  {
185  break;
186  }
187  case Data::Module::Flow:
188  {
189  m_lastFlowName.clear();
191  break;
192  }
194  {
195  m_lastFloridName.clear();
197  break;
198  }
199  case Data::Module::Light:
200  {
202  break;
203  }
204  default: break;
205  }
206 #endif
207  }
208  }
209 }
210 
212 {
213  MusicAbstractMoveResizePlainWidget::mouseDoubleClickEvent(event);
214  if(event->buttons() == Qt::LeftButton)
215  {
216  isMaximized() ? showNormal() : showMaximized();
217  }
218 }
219 
220 void MusicSpectrumWidget::createSpectrumWidget(Data::Module spectrum, bool &state, const QString &name, QLayout *layout)
221 {
222  if(state)
223  {
224  const int before = Visual::visuals()->count();
225  TTK::TTKQmmp::setVisualEnabled(name, true, this);
226  const QList<Visual*> *vs = Visual::visuals();
227  if(before == vs->count())
228  {
230  state = false;
231  return;
232  }
233 
234  if(!vs->isEmpty())
235  {
236  Data spem;
237  spem.m_module = name;
238  spem.m_object = vs->last();
239  spem.m_type = spectrum;
240  m_spectrums << spem;
241  layout->addWidget(spem.m_object);
242  spem.m_object->setStyleSheet(TTK::UI::MenuStyle02);
243 
244  connect(spem.m_object, SIGNAL(fullscreenByUser(QWidget*,bool)), SLOT(fullscreenByUser(QWidget*,bool)));
245  }
246  else
247  {
249  state = false;
250  }
251  }
252  else
253  {
254  const int index = findSpectrumWidget(name);
255  if(index != -1)
256  {
257  const Data &data = m_spectrums.takeAt(index);
258  layout->removeWidget(data.m_object);
259  TTK::TTKQmmp::setVisualEnabled(name, false, this);
260  }
261  }
262 }
263 
264 void MusicSpectrumWidget::createFlowWidget(Data::Module spectrum, bool &state, const QString &name, QLayout *layout)
265 {
266  createModuleWidget(spectrum, state, name, layout, false);
267 }
268 
269 void MusicSpectrumWidget::createFloridWidget(Data::Module spectrum, bool &state, const QString &name, QLayout *layout)
270 {
271  createModuleWidget(spectrum, state, name, layout, true);
272 }
273 
274 void MusicSpectrumWidget::createModuleWidget(Data::Module spectrum, bool &state, const QString &name, QLayout *layout, bool florid)
275 {
276  QString *module = florid ? &m_lastFloridName : &m_lastFlowName;
277  if(*module == name)
278  {
279  state = true;
280  return;
281  }
282 
283  const int index = findSpectrumWidget(*module);
284  if(index != -1)
285  {
286  const Data &data = m_spectrums.takeAt(index);
287  layout->removeWidget(data.m_object);
288  TTK::TTKQmmp::setVisualEnabled(*module, false, this);
289  }
290 
291  if(!state)
292  {
293  module->clear();
294  return;
295  }
296 
297  const int before = Visual::visuals()->count();
298  TTK::TTKQmmp::setVisualEnabled(name, true, this);
299  const QList<Visual*> *vs = Visual::visuals();
300  if(before == vs->count())
301  {
303  state = false;
304  return;
305  }
306 
307  if(!vs->isEmpty())
308  {
309  *module = name;
310  Data spem;
311  spem.m_module = name;
312  spem.m_object = vs->last();
313  spem.m_type = spectrum;
314  m_spectrums << spem;
315  layout->addWidget(spem.m_object);
316  spem.m_object->setStyleSheet(TTK::UI::MenuStyle02);
317 
318  if(florid)
319  {
320  TTKObjectCast(Florid*, spem.m_object)->setImage(MusicTopAreaWidget::instance()->originImage());
321  connect(MusicTopAreaWidget::instance(), SIGNAL(originImageChanged(QImage)), spem.m_object, SLOT(setImage(QImage)));
322  }
323  connect(spem.m_object, SIGNAL(fullscreenByUser(QWidget*,bool)), SLOT(fullscreenByUser(QWidget*,bool)));
324  }
325  else
326  {
328  state = false;
329  }
330 }
331 
332 void MusicSpectrumWidget::createLightWidget(Data::Module spectrum, bool &state, const QString &name, QLayout *layout, const QString &url)
333 {
334  if(state)
335  {
336  if(findSpectrumWidget(name) == -1)
337  {
338  QPluginLoader loader;
339  loader.setFileName(TTK::TTKQmmp::pluginPath("Light", name));
340  QObject *obj = loader.instance();
341  LightFactory *factory = nullptr;
342  if(obj && (factory = TTKObjectCast(LightFactory*, obj)))
343  {
344  Data spem;
345  spem.m_module = name;
346  spem.m_object = factory->create(this);
347  spem.m_type = spectrum;
348  m_spectrums << spem;
349  layout->addWidget(spem.m_object);
350  }
351  }
352 
353  const int index = findSpectrumWidget(name);
354  if(index == -1)
355  {
356  return;
357  }
358 
359  Light *light = TTKObjectCast(Light*, m_spectrums[index].m_object);
360  if(!light)
361  {
362  return;
363  }
364 
365  const QString &path = url.isEmpty() ? SoundCore::instance()->path() : url;
366  if(LIGHT_WAVEFORM_MODULE == name)
367  {
368  light->open(path);
369  }
370  else if(LIGHT_SPECTROGRAM_MODULE == name)
371  {
372  const QString &suffix = TTK_FILE_SUFFIX(QFileInfo(path));
373  for(QString &filter : MusicFormats::supportSpekInputFilterFormats())
374  {
375  if(filter.remove(0, 2) == suffix) // remove *.
376  {
377  light->open(path);
378  return;
379  }
380  }
381 
382  MusicToastLabel::popup(tr("Unsupported file format"));
383  }
384  }
385  else
386  {
387  const int index = findSpectrumWidget(name);
388  if(index != -1)
389  {
390  const Data &data = m_spectrums.takeAt(index);
391  layout->removeWidget(data.m_object);
392  delete data.m_object;
393  }
394  }
395 }
396 
398 {
399  if(name.isEmpty())
400  {
401  return -1;
402  }
403 
404  for(int i = 0; i < m_spectrums.count(); ++i)
405  {
406  if(m_spectrums[i].m_module.contains(name))
407  {
408  return i;
409  }
410  }
411 
412  return -1;
413 }
414 
416 {
417  MusicToastLabel::popup(tr("Spectrum init error"));
418 }
void spectrumPlusTypeChanged(bool &state, const QString &name)
MusicSpectrumWidget(QWidget *parent=nullptr)
static const QString ToolButtonStyle05
void createFlowWidget(Data::Module spectrum, bool &state, const QString &name, QLayout *layout)
The class of the moving resize widget with plain.
void spectrumNormalTypeChanged(bool &state, const QString &name)
static SoundCore * instance()
int findSpectrumWidget(const QString &name)
Light plugin interface (Light factory).
Definition: lightfactory.h:76
Helper class to light widget.
Definition: lightfactory.h:28
void createLightWidget(Data::Module spectrum, bool &state, const QString &name, QLayout *layout, const QString &url={})
void setObjectsTracking(const QWidgetList &objects)
void fullscreenByUser(QWidget *widget, bool state)
TTK_MODULE_EXPORT QString getOpenFileName(QWidget *parent, const QString &filter="Image Files (*.png *.bmp *.jpg)")
void setBackgroundLabel(QLabel *label) noexcept
static constexpr const char * LIGHT_SPECTROGRAM_MODULE
virtual void open(const QString &path)=0
virtual Light * create(QWidget *parent)=0
static void popup(const QString &text)
void spectrumWaveTypeChanged(bool &state, const QString &name)
The class of the music spectrum widget all.
#define qAsConst
Definition: ttkqtglobal.h:57
QString path() const
const char * name
Definition: http_parser.c:458
TTK_MODULE_EXPORT QString suffix(const QString &name)
static QStringList supportSpekInputFilterFormats() noexcept
void createModuleWidget(Data::Module spectrum, bool &state, const QString &name, QLayout *layout, bool florid)
void createSpectrumWidget(Data::Module spectrum, bool &state, const QString &name, QLayout *layout)
static const QString PushButtonStyle04
#define TTK_REMOVE_SINGLE_WIDGET(object)
Ui::MusicSpectrumWidget * m_ui
virtual void mouseDoubleClickEvent(QMouseEvent *event) overridefinal
TTK_MODULE_EXPORT void setVisualEnabled(const QString &name, bool enabled, QWidget *parent)
static const QString MenuStyle02
TTK_MODULE_EXPORT QString pluginPath(const QString &module, const QString &format)
void spectrumFloridTypeChanged(bool &state, const QString &name)
static const QString TabWidgetStyle01
TabWidget.
static const QString ToolButtonStyle04
static QString supportSpekInputFormats() noexcept
#define TTK_FILE_SUFFIX(fin)
Definition: ttkqtglobal.h:185
static QList< Visual * > * visuals()
Helper class to florid widget.
Definition: florid.h:77
void createFloridWidget(Data::Module spectrum, bool &state, const QString &name, QLayout *layout)
static MusicTopAreaWidget * instance()
state
Definition: http_parser.c:279
void spectrumFlowTypeChanged(bool &state, const QString &name)
#define TTKObjectCast(x, y)
Definition: ttkqtglobal.h:82
static constexpr const char * LIGHT_WAVEFORM_MODULE