TTKMusicPlayer  4.2.0.0
TTKMusicPlayer imitates Kugou UI, the music player uses of qmmp core library based on Qt for windows and linux
musicpluginwidget.cpp
Go to the documentation of this file.
1 #include "musicpluginwidget.h"
2 #include "ui_musicqmmppluginwidget.h"
3 #include "ui_musicserverpluginwidget.h"
4 #include "musicitemdelegate.h"
5 #include "musicsettingmanager.h"
6 #include "musicpluginproperty.h"
7 
8 #include "qjson/json.h"
9 
10 #include <qmmp/decoderfactory.h>
11 #include <qmmp/effectfactory.h>
12 #include <qmmp/visualfactory.h>
14 #include <qmmp/outputfactory.h>
15 #include <qmmp/decoder.h>
16 #include <qmmp/effect.h>
17 #include <qmmp/visual.h>
18 #include <qmmp/inputsource.h>
19 #include <qmmp/output.h>
20 
21 #include <QScrollBar>
22 
26 class MusicQmmpPluginItem : public QTreeWidgetItem
27 {
28 public:
29  MusicQmmpPluginItem(QTreeWidgetItem *parent, DecoderFactory *factory, const QString &path)
30  : QTreeWidgetItem(parent, PluginDecoder),
31  m_factory(factory)
32  {
33  MusicPluginProperty property;
34  property.m_name = factory->properties().name;
35  property.m_hasSettings = factory->properties().hasSettings;
36  property.m_description = factory->properties().description;
37  property.m_type = path;
38  initialize(Decoder::isEnabled(factory), true, property);
39  }
40 
41  MusicQmmpPluginItem(QTreeWidgetItem *parent, EffectFactory *factory, const QString &path)
42  : QTreeWidgetItem(parent, PluginEffect),
43  m_factory(factory)
44  {
45  MusicPluginProperty property;
46  property.m_name = factory->properties().name;
47  property.m_hasSettings = factory->properties().hasSettings;
48  property.m_type = path;
49  initialize(Effect::isEnabled(factory), false, property);
50  }
51 
52  MusicQmmpPluginItem(QTreeWidgetItem *parent, VisualFactory *factory, const QString &path)
53  : QTreeWidgetItem(parent, PluginVisual),
54  m_factory(factory)
55  {
56  MusicPluginProperty property;
57  property.m_name = factory->properties().name;
58  property.m_hasSettings = factory->properties().hasSettings;
59  property.m_type = path;
60  initialize(Visual::isEnabled(factory), false, property);
61  }
62 
63  MusicQmmpPluginItem(QTreeWidgetItem *parent, InputSourceFactory *factory, const QString &path)
64  : QTreeWidgetItem(parent, PluginTransports),
65  m_factory(factory)
66  {
67  MusicPluginProperty property;
68  property.m_name = factory->properties().name;
69  property.m_hasSettings = factory->properties().hasSettings;
70  property.m_type = path;
71  initialize(InputSource::isEnabled(factory), true, property);
72  }
73 
74  MusicQmmpPluginItem(QTreeWidgetItem *parent, OutputFactory *factory, const QString &path)
75  : QTreeWidgetItem(parent, PluginOutput),
76  m_factory(factory)
77  {
78  MusicPluginProperty property;
79  property.m_name = factory->properties().name;
80  property.m_hasSettings = factory->properties().hasSettings;
81  property.m_type = path;
82  initialize(Output::currentFactory() == factory, true, property);
83  }
84 
85  enum Module
86  {
87  PluginDecoder = QTreeWidgetItem::UserType,
92  };
93 
94  inline bool hasSettings() const
95  {
96  switch(type())
97  {
98  case PluginDecoder: return TTKStaticCast(DecoderFactory*, m_factory)->properties().hasSettings;
99  case PluginEffect: return false;
100  case PluginVisual: return false;
101  case PluginTransports: return TTKStaticCast(InputSourceFactory*, m_factory)->properties().hasSettings;
102  case PluginOutput: return TTKStaticCast(OutputFactory*, m_factory)->properties().hasSettings;
103  default: return false;
104  }
105  }
106 
107  inline void showSettingWidget() const
108  {
109  QDialog *dialog = nullptr;
110 
111  switch(type())
112  {
113  case PluginDecoder: dialog = TTKStaticCast(DecoderFactory*, m_factory)->createSettings(nullptr); break;
114  case PluginEffect: break;
115  case PluginVisual: break;
116  case PluginTransports: dialog = TTKStaticCast(InputSourceFactory*, m_factory)->createSettings(nullptr); break;
117  case PluginOutput: dialog = TTKStaticCast(OutputFactory*, m_factory)->createSettings(nullptr); break;
118  default: break;
119  }
120 
121  if(dialog)
122  {
123  dialog->exec();
124  dialog->deleteLater();
125  }
126  }
127 
128  inline void setEnabled(bool enabled)
129  {
130  switch(type())
131  {
133  case PluginEffect: break;
134  case PluginVisual: break;
136  case PluginOutput:
137  {
138  if(enabled)
139  {
141  }
142  break;
143  }
144  default: break;
145  }
146  }
147 
148  inline void initialize(bool state, bool enabled, const MusicPluginProperty &property)
149  {
150  setData(0, TTK_CHECKED_ROLE, state ? Qt::Checked : Qt::Unchecked);
151  setData(0, TTK_ENABLED_ROLE, enabled);
152  setData(1, TTK_DISPLAY_ROLE, property.m_name);
153  setData(2, TTK_DISPLAY_ROLE, property.m_type.section('/', -1));
154 
155  if(!property.m_description.isEmpty())
156  {
157  setToolTip(1, property.m_description);
158  setToolTip(2, property.m_description);
159  }
160 
161  if(property.m_hasSettings)
162  {
163  setIcon(3, QIcon(":/contextMenu/btn_setting"));
164  }
165 
166  const QColor &color = enabled ? (state ? QColor(0xE6, 0x73, 0x00) : QColor(0x00, 0x00, 0x00)) : QColor(0xBB, 0xBB, 0xBB);
167  setData(1, Qt::ForegroundRole, color);
168  setData(2, Qt::ForegroundRole, color);
169  }
170 
171 private:
172  void *m_factory;
173 
174 };
175 
176 
177 
179  : MusicAbstractMoveDialog(parent),
180  m_ui(new Ui::MusicQmmpPluginWidget)
181 {
182  m_ui->setupUi(this);
183  setFixedSize(size());
184  setBackgroundLabel(m_ui->background);
185 
186  m_ui->topTitleCloseButton->setIcon(QIcon(":/functions/btn_close_hover"));
187  m_ui->topTitleCloseButton->setStyleSheet(TTK::UI::ToolButtonStyle04);
188  m_ui->topTitleCloseButton->setCursor(QCursor(Qt::PointingHandCursor));
189  m_ui->topTitleCloseButton->setToolTip(tr("Close"));
190  connect(m_ui->topTitleCloseButton, SIGNAL(clicked()), SLOT(close()));
191 
192 #if TTK_QT_VERSION_CHECK(5,0,0)
193  m_ui->treeWidget->header()->setSectionsMovable(false);
194  m_ui->treeWidget->header()->setSectionResizeMode(0, QHeaderView::Fixed);
195 #else
196  m_ui->treeWidget->header()->setMovable(false);
197  m_ui->treeWidget->header()->setResizeMode(0, QHeaderView::Fixed);
198 #endif
199  m_ui->treeWidget->setHeaderLabels({{}, tr("Description"), tr("Name"), {}});
200 
201  TTKCheckBoxItemDelegate *delegateCheck = new TTKCheckBoxItemDelegate(this);
202  delegateCheck->setStyleSheet(TTK::UI::CheckBoxStyle01);
204  m_ui->treeWidget->setItemDelegateForColumn(0, delegateCheck);
205 
206  TTKLabelItemDelegate *delegateTitle = new TTKLabelItemDelegate(this);
208  delegateTitle->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
210  m_ui->treeWidget->setItemDelegateForColumn(1, delegateTitle);
211 
212  TTKLabelItemDelegate *delegateName = new TTKLabelItemDelegate(this);
214  delegateName->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
216  m_ui->treeWidget->setItemDelegateForColumn(2, delegateName);
217 
218  QItemDelegate *delegateSetting = new QItemDelegate(this);
219  m_ui->treeWidget->setItemDelegateForColumn(3, delegateSetting);
220 
221  m_ui->treeWidget->setColumnWidth(0, 65);
222  m_ui->treeWidget->setColumnWidth(1, 210);
223  m_ui->treeWidget->setColumnWidth(2, 120);
224  m_ui->treeWidget->setColumnWidth(3, 70);
225 
226  m_ui->settingButton->setStyleSheet(TTK::UI::PushButtonStyle03);
230  m_ui->treeWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
231  m_ui->treeWidget->verticalScrollBar()->setStyleSheet(TTK::UI::ScrollBarStyle03);
232  m_ui->treeWidget->setFocusPolicy(Qt::NoFocus);
233 
234  loadPluginsInfo();
235 
236  connect(m_ui->settingButton, SIGNAL(clicked()), SLOT(pluginButtonClicked()));
237  connect(m_ui->treeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), SLOT(pluginItemChanged(QTreeWidgetItem*,int)));
238 }
239 
240 void MusicQmmpPluginWidget::pluginItemChanged(QTreeWidgetItem *item, int column)
241 {
242  if(column == 0 && (item->type() == MusicQmmpPluginItem::PluginDecoder || item->type() == MusicQmmpPluginItem::PluginTransports || item->type() == MusicQmmpPluginItem::PluginOutput))
243  {
244  if(item->type() == MusicQmmpPluginItem::PluginOutput)
245  {
246  QTreeWidgetItem *parent = item->parent();
247  if(!parent)
248  {
249  return;
250  }
251 
252  for(int i = 0; i < parent->childCount(); ++i)
253  {
254  QTreeWidgetItem *it = parent->child(i);
255  it->setData(column, TTK_CHECKED_ROLE, Qt::Unchecked);
256  it->setData(1, Qt::ForegroundRole, QColor(0x00, 0x00, 0x00));
257  it->setData(2, Qt::ForegroundRole, QColor(0x00, 0x00, 0x00));
258  }
259  }
260 
261  const Qt::CheckState status = TTKStaticCast(Qt::CheckState, item->data(column, TTK_CHECKED_ROLE).toInt());
262  item->setData(column, TTK_CHECKED_ROLE, status == Qt::Checked ? Qt::Unchecked : Qt::Checked);
263  TTKDynamicCast(MusicQmmpPluginItem*, item)->setEnabled(status != Qt::Checked);
264 
265  const QColor &color = (status != Qt::Checked) ? QColor(0xE6, 0x73, 0x00) : QColor(0x00, 0x00, 0x00);
266  item->setData(1, Qt::ForegroundRole, color);
267  item->setData(2, Qt::ForegroundRole, color);
268  }
269 
271  m_ui->settingButton->setEnabled(it ? it->hasSettings() : false);
272 }
273 
275 {
276  MusicQmmpPluginItem *item = TTKDynamicCast(MusicQmmpPluginItem*, m_ui->treeWidget->currentItem());
277  if(item)
278  {
279  item->showSettingWidget();
280  }
281 }
282 
284 {
285  m_ui->treeWidget->blockSignals(true);
286 
287  QTreeWidgetItem *item = nullptr;
288  item = new QTreeWidgetItem(m_ui->treeWidget, {tr("Decoder")});
289  item->setFirstColumnSpanned(true);
290  item->setExpanded(true);
291  for(DecoderFactory *factory : Decoder::factories())
292  {
293  new MusicQmmpPluginItem(item, factory, Decoder::file(factory));
294  }
295  m_ui->treeWidget->addTopLevelItem(item);
296 
297  item = new QTreeWidgetItem(m_ui->treeWidget, {tr("Effect")});
298  item->setFirstColumnSpanned(true);
299  item->setExpanded(true);
300  for(EffectFactory *factory : Effect::factories())
301  {
302  new MusicQmmpPluginItem(item, factory, Effect::file(factory));
303  }
304  m_ui->treeWidget->addTopLevelItem(item);
305 
306  item = new QTreeWidgetItem(m_ui->treeWidget, {tr("Visualization")});
307  item->setFirstColumnSpanned(true);
308  item->setExpanded(true);
309  for(VisualFactory *factory : Visual::factories())
310  {
311  new MusicQmmpPluginItem(item, factory, Visual::file(factory));
312  }
313  m_ui->treeWidget->addTopLevelItem(item);
314 
315  item = new QTreeWidgetItem(m_ui->treeWidget, {tr("Transport")});
316  item->setFirstColumnSpanned(true);
317  item->setExpanded(true);
319  {
320  new MusicQmmpPluginItem(item, factory, InputSource::file(factory));
321  }
322  m_ui->treeWidget->addTopLevelItem(item);
323 
324  item = new QTreeWidgetItem(m_ui->treeWidget, {tr("Output")});
325  item->setFirstColumnSpanned(true);
326  item->setExpanded(true);
327  for(OutputFactory *factory : Output::factories())
328  {
329  new MusicQmmpPluginItem(item, factory, Output::file(factory));
330  }
331  m_ui->treeWidget->addTopLevelItem(item);
332 
333  m_ui->treeWidget->blockSignals(false);
334 }
335 
336 
337 static constexpr const char *QUERY_PLUGINS_URL = "resource/plugins";
338 
340  : MusicFillItemTableWidget(parent)
341 {
342  setAttribute(Qt::WA_TranslucentBackground, false);
343  setSelectionMode(QAbstractItemView::ExtendedSelection);
344  setColumnCount(2);
345 
346  QHeaderView *headerView = horizontalHeader();
347  headerView->resizeSection(0, 30);
348 #ifdef Q_OS_UNIX
349  headerView->resizeSection(1, 219);
350 #else
351  headerView->resizeSection(1, 222);
352 #endif
353  verticalScrollBar()->setStyleSheet(TTK::UI::ScrollBarStyle01);
354 
355  addCellItems();
356 }
357 
359 {
360  QByteArray bytes;
361  QFile file(APPCACHE_DIR_FULL + QUERY_PLUGINS_URL);
362  if(file.open(QIODevice::ReadOnly))
363  {
364  TTK_INFO_STREAM("Load server unity plugins ok");
365  bytes = file.readAll();
366  file.close();
367  }
368  else
369  {
370  TTK_ERROR_STREAM("Load server unity plugins failed");
371  return;
372  }
373 
374  QJsonParseError ok;
375  QJsonDocument json = QJsonDocument::fromJson(bytes, &ok);
377  {
378  QVariantList datas = json.toVariant().toList();
379  for(int i = 0; i < datas.count(); ++i)
380  {
381  QVariant &var = datas[i];
382  QTableWidgetItem *it = item(i, 0);
383 
384  if(var.isNull() || !it)
385  {
386  continue;
387  }
388 
389  QVariantMap value = var.toMap();
390  value["option"] = it->data(TTK_CHECKED_ROLE).toBool();
391  var = value;
392  }
393 
394  if(!file.open(QIODevice::WriteOnly))
395  {
396  TTK_ERROR_STREAM("Save server unity plugins failed");
397  return;
398  }
399 
400  json = QJsonDocument::fromVariant(datas);
401 #if TTK_QT_VERSION_CHECK(5,0,0) && !TTK_QT_VERSION_CHECK(5,1,0)
402  const qint64 ok = file.write(json.toJson());
403 #else
404  const qint64 ok = file.write(json.toJson(QJsonDocument::Indented));
405 #endif
406  file.close();
407  TTK_INFO_STREAM("Save server unity plugins" << (ok ? "ok" : "failed"));
408  }
409 }
410 
412 {
413  Q_UNUSED(column);
414  QTableWidgetItem *it = nullptr;
415 
416  it = item(row, 0);
417  const Qt::CheckState status = TTKStaticCast(Qt::CheckState, it->data(TTK_CHECKED_ROLE).toInt());
418  it->setData(TTK_CHECKED_ROLE, status == Qt::Checked ? Qt::Unchecked : Qt::Checked);
419 
420  it = item(row, 1);
421  it->setForeground(status == Qt::Checked ? Qt::gray : QColor(0xE6, 0x73, 0x00));
422 }
423 
425 {
427 
428  for(int i = 0; i < rowCount(); ++i)
429  {
430  item(i, 1)->setForeground(!checked ? Qt::gray : QColor(0xE6, 0x73, 0x00));
431  }
432 }
433 
435 {
436  QByteArray bytes;
437  QFile file(APPCACHE_DIR_FULL + QUERY_PLUGINS_URL);
438  if(file.open(QIODevice::ReadOnly))
439  {
440  TTK_INFO_STREAM("Load server unity plugins ok");
441  bytes = file.readAll();
442  file.close();
443  }
444  else
445  {
446  TTK_ERROR_STREAM("Load server unity plugins failed");
447  return;
448  }
449 
450  QJsonParseError ok;
451  const QJsonDocument &json = QJsonDocument::fromJson(bytes, &ok);
453  {
454  int index = 0;
455  const QVariantList &datas = json.toVariant().toList();
456  setRowCount(datas.count());
457 
458  for(const QVariant &var : qAsConst(datas))
459  {
460  if(var.isNull())
461  {
462  continue;
463  }
464 
465  const QVariantMap &value = var.toMap();
466  const bool option = value["option"].toBool();
467  const QString &name = value["name"].toString();
468  const QString &tips = value["description"].toString() + TTK_SPACE + value["version"].toString();
469 
470  QTableWidgetItem *item = new QTableWidgetItem;
471  item->setData(TTK_CHECKED_ROLE, option ? Qt::Checked : Qt::Unchecked);
472  setItem(index, 0, item);
473 
474  item = new QTableWidgetItem;
476  {
477  item->setToolTip(tips);
478  }
479  item->setText(name);
480  item->setForeground(option ? QColor(0xE6, 0x73, 0x00) : Qt::gray);
481  QtItemSetTextAlignment(item, Qt::AlignLeft | Qt::AlignVCenter);
482  setItem(index++, 1, item);
483  }
484  }
485 }
486 
487 
488 
490  : MusicAbstractMoveDialog(parent),
491  m_ui(new Ui::MusicServerPluginWidget)
492 {
493  m_ui->setupUi(this);
494  setFixedSize(size());
495  setBackgroundLabel(m_ui->background);
496 
497  m_ui->topTitleCloseButton->setIcon(QIcon(":/functions/btn_close_hover"));
498  m_ui->topTitleCloseButton->setStyleSheet(TTK::UI::ToolButtonStyle04);
499  m_ui->topTitleCloseButton->setCursor(QCursor(Qt::PointingHandCursor));
500  m_ui->topTitleCloseButton->setToolTip(tr("Close"));
501  connect(m_ui->topTitleCloseButton, SIGNAL(clicked()), SLOT(close()));
502 
503  m_ui->confirmButton->setStyleSheet(TTK::UI::PushButtonStyle04);
504  m_ui->selectAllCheckButton->setStyleSheet(TTK::UI::CheckBoxStyle01);
505 #ifdef Q_OS_UNIX
506  m_ui->confirmButton->setFocusPolicy(Qt::NoFocus);
507  m_ui->selectAllCheckButton->setFocusPolicy(Qt::NoFocus);
508 #endif
509 
510  connect(m_ui->confirmButton, SIGNAL(clicked()), SLOT(confirmButtonClicked()));
511  connect(m_ui->selectAllCheckButton, SIGNAL(clicked(bool)), m_ui->itemTableWidget, SLOT(checkedItemsStatus(bool)));
512 }
513 
515 {
516  m_ui->itemTableWidget->save();
517  accept();
518 }
static QJsonDocument fromVariant(const QVariant &variant)
void checkedItemsStatus(bool checked)
#define TTKStaticCast(x, y)
Definition: ttkglobal.h:231
Transport plugin interface.
static QList< VisualFactory * > factories()
virtual OutputProperties properties() const =0
The class of the label item delegate.
Ui::MusicServerPluginWidget * m_ui
#define TTK_DISPLAY_ROLE
static bool isEnabled(const InputSourceFactory *factory)
#define TTK_ENABLED_ROLE
The class of the qmmp plugin item widget.
QVariant toVariant() const
static QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error=0)
static QString file(const InputSourceFactory *factory)
MusicQmmpPluginItem(QTreeWidgetItem *parent, InputSourceFactory *factory, const QString &path)
static const QString CheckBoxStyle01
CheckBox.
static const QString SliderStyle06
voidpf void uLong size
Definition: ioapi.h:136
void setStyleSheet(const QString &style) const
static bool isEnabled(const DecoderFactory *factory)
static const QString PushButtonStyle12
MusicServerPluginWidget(QWidget *parent=nullptr)
virtual void itemCellClicked(int row, int column) override
void setEnabled(bool enabled)
virtual EffectProperties properties() const =0
#define QtItemSetTextAlignment(p, a)
Item text alignment.
Definition: ttkqtcompat.h:45
static void setCurrentFactory(const OutputFactory *factory)
static OutputFactory * currentFactory()
void setBackgroundLabel(QLabel *label) noexcept
The class of the fill item table widget.
Effect plugin interface (effect factory).
Definition: effectfactory.h:54
static QList< OutputFactory * > factories()
MusicQmmpPluginWidget(QWidget *parent=nullptr)
static QString file(const DecoderFactory *factory)
static bool isEnabled(const VisualFactory *factory)
void setAlignment(Qt::Alignment alignment) const
static const QString ScrollBarStyle03
ParseError error
The class of the server plugin manager widget.
#define APPCACHE_DIR_FULL
Definition: musicobject.h:135
#define qAsConst
Definition: ttkqtglobal.h:57
const char * name
Definition: http_parser.c:458
static const QString GroupBoxStyle01
GroupBox.
static const QString ScrollBarStyle01
ScrollBar.
virtual InputSourceProperties properties() const =0
static const QString PushButtonStyle03
Input plugin interface (decoder factory).
#define TTK_INFO_STREAM(msg)
Definition: ttklogger.h:74
void initialize(bool state, bool enabled, const MusicPluginProperty &property)
static const QString SpinBoxStyle01
SpinBox.
static bool isEnabled(const EffectFactory *factory)
virtual DecoderProperties properties() const =0
static const QString BackgroundStyle01
Background.
Definition: musicuiobject.h:77
void setModuleMode(TTKUInt8 mode) noexcept
static const QString PushButtonStyle04
MusicServerPluginTableWidget(QWidget *parent=nullptr)
MusicQmmpPluginItem(QTreeWidgetItem *parent, DecoderFactory *factory, const QString &path)
MusicQmmpPluginItem(QTreeWidgetItem *parent, EffectFactory *factory, const QString &path)
static QList< EffectFactory * > factories()
static void setEnabled(InputSourceFactory *factory, bool enable=true)
static QString file(const OutputFactory *factory)
The class of the moving dialog base.
The class of the qmmp plugin manager widget.
static QString file(const EffectFactory *factory)
static QList< InputSourceFactory * > factories()
static void setEnabled(DecoderFactory *factory, bool enable=true)
static const QString LineEditStyle01
LineEdit.
Visual plugin interface (visual factory).
Definition: visualfactory.h:42
static constexpr const char * QUERY_PLUGINS_URL
void pluginItemChanged(QTreeWidgetItem *item, int column)
static const QString ToolButtonStyle04
static const QString RadioButtonStyle01
RadioButton.
static QList< DecoderFactory * > factories()
virtual VisualProperties properties() const =0
The class of the checkbox item delegate.
static const QString ComboBoxStyle01
ComboBox.
Output plugin interface (output factory).
Definition: outputfactory.h:44
#define TTK_ERROR_STREAM(msg)
Definition: ttklogger.h:76
QByteArray toJson(JsonFormat format=Indented) const
static QString file(const VisualFactory *factory)
The class of the plugin property.
MusicQmmpPluginItem(QTreeWidgetItem *parent, VisualFactory *factory, const QString &path)
Ui::MusicQmmpPluginWidget * m_ui
#define TTK_SPACE
Definition: ttkglobal.h:268
#define TTK_CHECKED_ROLE
state
Definition: http_parser.c:279
#define TTKDynamicCast(x, y)
Definition: ttkglobal.h:219
#define G_SETTING_PTR
void showSettingWidget() const
MusicQmmpPluginItem(QTreeWidgetItem *parent, OutputFactory *factory, const QString &path)