Icon.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. #include "Icon.h"
  2. #include "QFluentWidgets.h"
  3. #include <QPainter>
  4. #include <QSvgRenderer>
  5. #include <QDomDocument>
  6. #include <QHash>
  7. #include <QFile>
  8. static QString writeSvg(const QString &iconPath, const QVector<int> &indexes, const QHash<QString, QString> &attributes)
  9. {
  10. if (!iconPath.toLower().endsWith("svg")) {
  11. return "";
  12. }
  13. QFile f(iconPath);
  14. f.open(QIODevice::ReadOnly | QIODevice::Text);
  15. QDomDocument dom;
  16. dom.setContent(f.readAll());
  17. f.close();
  18. // change the color of each path
  19. QDomNodeList pathNodes = dom.elementsByTagName("path");
  20. QVector<int> _indexes = indexes;
  21. if (_indexes.isEmpty()) {
  22. for (int i = 0; i < pathNodes.length(); ++i) {
  23. _indexes.append(i);
  24. }
  25. }
  26. for (auto index : _indexes) {
  27. QDomElement element = pathNodes.at(index).toElement();
  28. QHashIterator<QString, QString> iter(attributes);
  29. while (iter.hasNext()) {
  30. iter.next();
  31. element.setAttribute(iter.key(), iter.value());
  32. }
  33. }
  34. return dom.toString();
  35. }
  36. IconEngine::IconEngine(const QString &path)
  37. : QIconEngine(), m_iconPath(path), m_indexes(QVector<int>()), m_attributes(QHash<QString, QString>())
  38. {
  39. m_isSvg = m_iconPath.toLower().endsWith("svg");
  40. }
  41. void IconEngine::setIndexes(const QVector<int> &indexes)
  42. {
  43. m_indexes = indexes;
  44. }
  45. void IconEngine::setAttributes(const QHash<QString, QString> &attributes)
  46. {
  47. m_attributes = attributes;
  48. }
  49. void IconEngine::setIconPath(const QString &iconPath)
  50. {
  51. m_iconPath = iconPath;
  52. m_isSvg = m_iconPath.toLower().endsWith("svg");
  53. }
  54. QString IconEngine::iconPath() const
  55. {
  56. return m_iconPath;
  57. }
  58. void IconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode /*mode*/, QIcon::State /*state*/)
  59. {
  60. if (m_iconPath.isEmpty()) {
  61. return;
  62. }
  63. painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
  64. if (m_isSvg) {
  65. if (m_attributes.isEmpty()) {
  66. QSvgRenderer svgRender(m_iconPath);
  67. svgRender.render(painter, QRectF(rect));
  68. } else {
  69. QString svg = writeSvg(m_iconPath, m_indexes, m_attributes);
  70. QSvgRenderer svgRender(svg.toUtf8());
  71. svgRender.render(painter, QRectF(rect));
  72. }
  73. } else {
  74. QPixmap pixmap = QIcon(m_iconPath).pixmap(rect.width(), rect.height());
  75. painter->drawPixmap(rect, pixmap);
  76. }
  77. }
  78. QPixmap IconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
  79. {
  80. QPixmap pixmap(size);
  81. pixmap.fill(Qt::transparent);
  82. QPainter painter(&pixmap);
  83. paint(&painter, QRect(QPoint(0, 0), size), mode, state);
  84. return pixmap;
  85. }
  86. QIconEngine *IconEngine::clone() const
  87. {
  88. return new IconEngine(m_iconPath);
  89. }
  90. MenuIconEngine::MenuIconEngine(const QIcon &icon) : m_icon(icon) { }
  91. void MenuIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode /*mode*/, QIcon::State state)
  92. {
  93. m_icon.paint(painter, rect, Qt::AlignHCenter, QIcon::Normal, state);
  94. }
  95. QIconEngine *MenuIconEngine::clone() const
  96. {
  97. return new MenuIconEngine(*this);
  98. }
  99. QString getIconColor()
  100. {
  101. if (QFWIns.isDarkTheme()) {
  102. return "white";
  103. } else {
  104. return "black";
  105. }
  106. }
  107. FluentIconBase::FluentIconBase(const QString &path) : iconEngine(new IconEngine(path)) { }
  108. FluentIconBase::~FluentIconBase() { }
  109. void FluentIconBase::render(QPainter *painter, const QRect &rect, const QVector<int> &indexes,
  110. const QHash<QString, QString> &attributes)
  111. {
  112. iconEngine->setIndexes(indexes);
  113. iconEngine->setAttributes(attributes);
  114. iconEngine->paint(painter, rect, QIcon::Normal, QIcon::On);
  115. }
  116. QString FluentIcon::iconName(FluentIcon::IconType type)
  117. {
  118. switch (type) {
  119. case UNKNOWN:
  120. return "Unknown";
  121. case ADD:
  122. return "Add";
  123. case CUT:
  124. return "Cut";
  125. case PIN:
  126. return "Pin";
  127. case TAG:
  128. return "Tag";
  129. case CHAT:
  130. return "Chat";
  131. case COPY:
  132. return "Copy";
  133. case CODE:
  134. return "Code";
  135. case EDIT:
  136. return "Edit";
  137. case FONT:
  138. return "Font";
  139. case HELP:
  140. return "Help";
  141. case HIDE:
  142. return "Hide";
  143. case HOME:
  144. return "Home";
  145. case INFO:
  146. return "Info";
  147. case LINK:
  148. return "Link";
  149. case MAIL:
  150. return "Mail";
  151. case MENU:
  152. return "Menu";
  153. case MORE:
  154. return "More";
  155. case SAVE:
  156. return "Save";
  157. case SEND:
  158. return "Send";
  159. case SYNC:
  160. return "Sync";
  161. case VIEW:
  162. return "View";
  163. case ZOOM:
  164. return "Zoom";
  165. case ALBUM:
  166. return "Album";
  167. case BRUSH:
  168. return "Brush";
  169. case CLOSE:
  170. return "Close";
  171. case EMBED:
  172. return "Embed";
  173. case GLOBE:
  174. return "Globe";
  175. case HEART:
  176. return "Heart";
  177. case MEDIA:
  178. return "Media";
  179. case MOVIE:
  180. return "Movie";
  181. case MUSIC:
  182. return "Music";
  183. case PASTE:
  184. return "Paste";
  185. case PHOTO:
  186. return "Photo";
  187. case PHONE:
  188. return "Phone";
  189. case PRINT:
  190. return "Print";
  191. case SHARE:
  192. return "Share";
  193. case UNPIN:
  194. return "Unpin";
  195. case VIDEO:
  196. return "Video";
  197. case ACCEPT:
  198. return "Accept";
  199. case CAMERA:
  200. return "Camera";
  201. case CANCEL:
  202. return "Cancel";
  203. case DELETE:
  204. return "Delete";
  205. case FOLDER:
  206. return "Folder";
  207. case SCROLL:
  208. return "Scroll";
  209. case LAYOUT:
  210. return "Layout";
  211. case GITHUB:
  212. return "GitHub";
  213. case UPDATE:
  214. return "Update";
  215. case RETURN:
  216. return "Return";
  217. case RINGER:
  218. return "Ringer";
  219. case SEARCH:
  220. return "Search";
  221. case SAVE_AS:
  222. return "SaveAs";
  223. case ZOOM_IN:
  224. return "ZoomIn";
  225. case HISTORY:
  226. return "History";
  227. case SETTING:
  228. return "Setting";
  229. case PALETTE:
  230. return "Palette";
  231. case MESSAGE:
  232. return "Message";
  233. case ZOOM_OUT:
  234. return "ZoomOut";
  235. case FEEDBACK:
  236. return "Feedback";
  237. case MINIMIZE:
  238. return "Minimize";
  239. case CHECKBOX:
  240. return "CheckBox";
  241. case DOCUMENT:
  242. return "Document";
  243. case LANGUAGE:
  244. return "Language";
  245. case DOWNLOAD:
  246. return "Download";
  247. case QUESTION:
  248. return "Question";
  249. case DATE_TIME:
  250. return "DateTime";
  251. case SEND_FILL:
  252. return "SendFill";
  253. case COMPLETED:
  254. return "Completed";
  255. case CONSTRACT:
  256. return "Constract";
  257. case ALIGNMENT:
  258. return "Alignment";
  259. case BOOK_SHELF:
  260. return "BookShelf";
  261. case HIGHTLIGHT:
  262. return "Highlight";
  263. case FOLDER_ADD:
  264. return "FolderAdd";
  265. case PENCIL_INK:
  266. return "PencilInk";
  267. case ZIP_FOLDER:
  268. return "ZipFolder";
  269. case MICROPHONE:
  270. return "Microphone";
  271. case ARROW_DOWN:
  272. return "ChevronDown";
  273. case TRANSPARENT:
  274. return "Transparent";
  275. case MUSIC_FOLDER:
  276. return "MusicFolder";
  277. case CHEVRON_RIGHT:
  278. return "ChevronRight";
  279. case BACKGROUND_FILL:
  280. return "BackgroundColor";
  281. }
  282. return "Unknown";
  283. }
  284. FluentIcon::FluentIcon(const QString &customPath)
  285. : FluentIconBase(customPath), m_theme(Qfw::Theme::AUTO), m_type(UNKNOWN)
  286. {
  287. }
  288. FluentIcon::FluentIcon(IconType type, Qfw::Theme t) : FluentIconBase(""), m_theme(t), m_type(type)
  289. {
  290. iconEngine->setIconPath(iconPath());
  291. }
  292. FluentIcon::~FluentIcon() { }
  293. QString FluentIcon::iconPath()
  294. {
  295. if (m_type == UNKNOWN) {
  296. return "";
  297. }
  298. QString c;
  299. if (m_theme == Qfw::Theme::AUTO) {
  300. c = getIconColor();
  301. } else if (m_theme == Qfw::Theme::DARK) {
  302. c = "black";
  303. } else {
  304. c = "white";
  305. }
  306. return QString(":/qfluentwidgets/images/icons/%1_%2.svg").arg(iconName(m_type)).arg(c);
  307. }
  308. QIcon FluentIcon::icon()
  309. {
  310. return QIcon(iconEngine->clone());
  311. }
  312. QString FluentIcon::typeName() const
  313. {
  314. return iconName(m_type);
  315. }
  316. QString FluentIcon::enumName() const
  317. {
  318. QMetaEnum metaEnum = QMetaEnum::fromType<IconType>();
  319. return metaEnum.valueToKey(m_type);
  320. }
  321. FluentIconBase *FluentIcon::clone()
  322. {
  323. if (m_type == UNKNOWN) {
  324. return new FluentIcon(iconEngine->iconPath());
  325. }
  326. return new FluentIcon(m_type, m_theme);
  327. }
  328. Qfw::Theme FluentIcon::theme() const
  329. {
  330. return m_theme;
  331. }
  332. void FluentIcon::setTheme(const Qfw::Theme &theme)
  333. {
  334. m_theme = theme;
  335. iconEngine->setIconPath(iconPath());
  336. }