StickerPanel.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #include "StickerPanel.h"
  2. #include "StickerCache.h"
  3. #include <QColor>
  4. #include <QFrame>
  5. #include <QGraphicsDropShadowEffect>
  6. #include <QGridLayout>
  7. #include <QIcon>
  8. #include <QLabel>
  9. #include <QPushButton>
  10. #include <QScrollArea>
  11. #include <QShowEvent>
  12. #include <QStackedWidget>
  13. #include <QTabBar>
  14. #include <QVBoxLayout>
  15. StickerPanel::StickerPanel(QWidget *parent)
  16. : QWidget(parent)
  17. {
  18. setAttribute(Qt::WA_TranslucentBackground, true);
  19. setAutoFillBackground(false);
  20. setFixedSize(376, 276);
  21. auto *outer = new QVBoxLayout(this);
  22. outer->setContentsMargins(8, 8, 8, 8);
  23. outer->setSpacing(0);
  24. auto *card = new QFrame(this);
  25. card->setObjectName(QStringLiteral("stickerCard"));
  26. card->setAttribute(Qt::WA_StyledBackground, true);
  27. card->setStyleSheet(QStringLiteral(
  28. "#stickerCard { background:#FFFFFF; border:1px solid #E8E8E8; border-radius:4px; }"));
  29. auto *shadow = new QGraphicsDropShadowEffect(card);
  30. shadow->setBlurRadius(22);
  31. shadow->setOffset(0, 3);
  32. shadow->setColor(QColor(0, 0, 0, 50));
  33. card->setGraphicsEffect(shadow);
  34. auto *lay = new QVBoxLayout(card);
  35. lay->setContentsMargins(0, 0, 0, 0);
  36. lay->setSpacing(0);
  37. m_tabs = new QTabBar(card);
  38. m_tabs->setDrawBase(false);
  39. m_tabs->setExpanding(false);
  40. m_tabs->setStyleSheet(QStringLiteral(
  41. "QTabBar { background:#FFFFFF; }"
  42. "QTabBar::tab { height:32px; padding:0 12px; color:#666; background:#FFFFFF; border:none; }"
  43. "QTabBar::tab:selected { color:#07C160; background:#FFFFFF; }"));
  44. m_pages = new QStackedWidget(card);
  45. m_pages->setStyleSheet(QStringLiteral("QStackedWidget { background:#FFFFFF; border:none; }"));
  46. lay->addWidget(m_tabs);
  47. lay->addWidget(m_pages, 1);
  48. outer->addWidget(card);
  49. connect(m_tabs, &QTabBar::currentChanged, m_pages, &QStackedWidget::setCurrentIndex);
  50. connect(&StickerCache::instance(), &StickerCache::ready, this, &StickerPanel::rebuild);
  51. connect(&StickerCache::instance(), &StickerCache::stickerReady, this, [this](qint64, const QString &) {
  52. rebuild();
  53. });
  54. }
  55. void StickerPanel::showEvent(QShowEvent *event)
  56. {
  57. QWidget::showEvent(event);
  58. reload();
  59. }
  60. void StickerPanel::reload()
  61. {
  62. if (StickerCache::instance().packs().isEmpty())
  63. StickerCache::instance().sync();
  64. else
  65. rebuild();
  66. }
  67. void StickerPanel::rebuild()
  68. {
  69. const int keep = m_tabs->currentIndex();
  70. while (m_tabs->count() > 0)
  71. m_tabs->removeTab(0);
  72. while (m_pages->count() > 0)
  73. {
  74. QWidget *w = m_pages->widget(0);
  75. m_pages->removeWidget(w);
  76. w->deleteLater();
  77. }
  78. const auto packs = StickerCache::instance().packs();
  79. for (int i = 0; i < packs.size(); ++i)
  80. {
  81. m_tabs->addTab(packs[i].name);
  82. m_pages->addWidget(buildPackPage(i));
  83. }
  84. if (packs.isEmpty())
  85. {
  86. auto *empty = new QLabel(QStringLiteral("表情包加载中…"), m_pages);
  87. empty->setAlignment(Qt::AlignCenter);
  88. empty->setStyleSheet(QStringLiteral("color:#B0B0B0; background:#FFFFFF;"));
  89. m_pages->addWidget(empty);
  90. }
  91. if (keep >= 0 && keep < m_tabs->count())
  92. m_tabs->setCurrentIndex(keep);
  93. }
  94. QWidget *StickerPanel::buildPackPage(int packIndex)
  95. {
  96. const auto packs = StickerCache::instance().packs();
  97. auto *page = new QWidget(m_pages);
  98. page->setStyleSheet(QStringLiteral("background:#FFFFFF;"));
  99. auto *outer = new QVBoxLayout(page);
  100. outer->setContentsMargins(0, 0, 0, 0);
  101. auto *scroll = new QScrollArea(page);
  102. scroll->setWidgetResizable(true);
  103. scroll->setFrameShape(QFrame::NoFrame);
  104. scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  105. scroll->setStyleSheet(QStringLiteral(
  106. "QScrollArea { background:#FFFFFF; border:none; }"
  107. "QScrollBar:vertical { background:#FFFFFF; width:8px; }"
  108. "QScrollBar::handle:vertical { background:#D0D0D0; border-radius:4px; }"
  109. "QScrollBar:horizontal { height:0px; }"));
  110. auto *host = new QWidget(scroll);
  111. host->setStyleSheet(QStringLiteral("background:#FFFFFF;"));
  112. auto *grid = new QGridLayout(host);
  113. grid->setContentsMargins(8, 8, 8, 8);
  114. grid->setSpacing(4);
  115. if (packIndex >= 0 && packIndex < packs.size())
  116. {
  117. const auto &pack = packs[packIndex];
  118. int col = 0;
  119. int row = 0;
  120. for (const auto &s : pack.stickers)
  121. {
  122. auto *btn = new QPushButton(host);
  123. btn->setFlat(true);
  124. btn->setCursor(Qt::PointingHandCursor);
  125. btn->setFixedSize(50, 50);
  126. btn->setStyleSheet(QStringLiteral(
  127. "QPushButton { background:#FFFFFF; border:none; border-radius:4px; }"
  128. "QPushButton:hover { background:#F5F5F5; }"));
  129. const QPixmap pm = StickerCache::instance().pixmap(pack.id, s.code, 44);
  130. if (!pm.isNull())
  131. btn->setIcon(QIcon(pm));
  132. btn->setIconSize(QSize(44, 44));
  133. const qint64 packId = pack.id;
  134. const QString code = s.code;
  135. connect(btn, &QPushButton::clicked, this, [this, packId, code]() {
  136. emit stickerPicked(packId, code);
  137. });
  138. grid->addWidget(btn, row, col);
  139. if (++col >= 6)
  140. {
  141. col = 0;
  142. ++row;
  143. }
  144. }
  145. }
  146. scroll->setWidget(host);
  147. outer->addWidget(scroll);
  148. return page;
  149. }