ResultItemDelegate.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include "ResultItemDelegate.hpp"
  2. #include "ResultListModel.hpp"
  3. #include <QAbstractItemView>
  4. #include <QApplication>
  5. #include <QFileInfo>
  6. #include <QMouseEvent>
  7. #include <QPainter>
  8. #include <QToolTip>
  9. #include <cstddef>
  10. ResultItemDelegate::ResultItemDelegate(QObject *parent)
  11. : QStyledItemDelegate(parent) {}
  12. void ResultItemDelegate::paint(QPainter *painter,
  13. const QStyleOptionViewItem &option,
  14. const QModelIndex &index) const {
  15. const auto *model = qobject_cast<const ResultListModel *>(index.model());
  16. if (!model)
  17. return;
  18. painter->save();
  19. const auto &item = model->getItem(index.row());
  20. if (item.type == ResultListItem::Header) {
  21. QRect r = option.rect;
  22. r.adjust(0, 5, 0, -5);
  23. painter->setRenderHint(QPainter::Antialiasing);
  24. painter->setBrush(QColor("#f0f0f0"));
  25. painter->setPen(Qt::NoPen);
  26. painter->drawRoundedRect(r, 4, 4);
  27. QFont font = painter->font();
  28. font.setBold(true);
  29. painter->setFont(font);
  30. painter->setPen(Qt::black);
  31. painter->drawText(r.adjusted(5, 0, -5, 0), Qt::AlignVCenter | Qt::AlignLeft,
  32. item.headerText);
  33. } else {
  34. int cardWidth = option.rect.width() / 4;
  35. for (int i = 0; i < static_cast<int>(item.images.size()); ++i) {
  36. const auto &imgData = item.images[i];
  37. QRect cardRect(option.rect.x() + i * cardWidth, option.rect.y(),
  38. cardWidth, option.rect.height());
  39. // Thumbnail
  40. QRect thumbRect(cardRect.x() + (cardWidth - 150) / 2, cardRect.y() + 5,
  41. 150, 150);
  42. QPixmap pix = model->getThumbnail(imgData.path);
  43. if (pix.isNull()) {
  44. painter->setPen(Qt::black);
  45. painter->drawText(thumbRect, Qt::AlignCenter, "Loading...");
  46. } else {
  47. // center pixmap
  48. QPoint topLeft(thumbRect.center().x() - pix.width() / 2,
  49. thumbRect.center().y() - pix.height() / 2);
  50. painter->drawPixmap(topLeft, pix);
  51. }
  52. // Checkbox
  53. QRect cbRect(cardRect.x() + 5, thumbRect.bottom() + 5, cardWidth - 10,
  54. 20);
  55. QStyleOptionButton cbOpt;
  56. cbOpt.rect = cbRect;
  57. cbOpt.text = "Delete candidate";
  58. cbOpt.state = QStyle::State_Enabled;
  59. if (model->isChecked(imgData.path)) {
  60. cbOpt.state |= QStyle::State_On;
  61. } else {
  62. cbOpt.state |= QStyle::State_Off;
  63. }
  64. QApplication::style()->drawControl(QStyle::CE_CheckBox, &cbOpt, painter);
  65. // Info text
  66. QRect textRect(cardRect.x() + 5, cbRect.bottom() + 2, cardWidth - 10,
  67. cardRect.bottom() - cbRect.bottom() - 2);
  68. QString info = QString("%1 KB\n%2")
  69. .arg(imgData.file_size / 1024)
  70. .arg(QString::fromStdString(imgData.path));
  71. QFont font = painter->font();
  72. font.setPixelSize(10);
  73. painter->setFont(font);
  74. painter->setPen(QColor("#666666"));
  75. painter->drawText(textRect,
  76. Qt::AlignTop | Qt::AlignLeft | Qt::TextWordWrap, info);
  77. }
  78. }
  79. painter->restore();
  80. }
  81. QSize ResultItemDelegate::sizeHint(const QStyleOptionViewItem &option,
  82. const QModelIndex &index) const {
  83. const auto *model = qobject_cast<const ResultListModel *>(index.model());
  84. if (!model)
  85. return QSize(0, 0);
  86. const auto &item = model->getItem(index.row());
  87. if (item.type == ResultListItem::Header) {
  88. return QSize(option.rect.width(), 40);
  89. } else {
  90. return QSize(option.rect.width(), 220);
  91. }
  92. }
  93. bool ResultItemDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
  94. const QStyleOptionViewItem &option,
  95. const QModelIndex &index) {
  96. if (!event)
  97. return false;
  98. auto *listModel = qobject_cast<ResultListModel *>(model);
  99. if (!listModel)
  100. return false;
  101. const auto &item = listModel->getItem(index.row());
  102. if (item.type != ResultListItem::ImageRow)
  103. return false;
  104. if (event->type() == QEvent::MouseButtonRelease) {
  105. QMouseEvent *me = static_cast<QMouseEvent *>(event);
  106. int cardWidth = option.rect.width() / 4;
  107. for (int i = 0; i < static_cast<int>(item.images.size()); ++i) {
  108. const auto &imgData = item.images[i];
  109. QRect cardRect(option.rect.x() + i * cardWidth, option.rect.y(),
  110. cardWidth, option.rect.height());
  111. if (cardRect.contains(me->pos())) {
  112. if (me->button() == Qt::RightButton) {
  113. emit contextMenuRequested(imgData.path, item.groupId,
  114. me->globalPosition().toPoint());
  115. return true;
  116. } else if (me->button() == Qt::LeftButton) {
  117. QRect thumbRect(cardRect.x() + (cardWidth - 150) / 2,
  118. cardRect.y() + 5, 150, 150);
  119. QRect cbRect(cardRect.x() + 5, thumbRect.bottom() + 5, cardWidth - 10,
  120. 20);
  121. if (cbRect.contains(me->pos())) {
  122. bool currentState = listModel->isChecked(imgData.path);
  123. listModel->setChecked(imgData.path, !currentState);
  124. return true;
  125. }
  126. }
  127. }
  128. }
  129. } else if (event->type() == QEvent::MouseButtonDblClick) {
  130. QMouseEvent *me = static_cast<QMouseEvent *>(event);
  131. int cardWidth = option.rect.width() / 4;
  132. for (int i = 0; i < static_cast<int>(item.images.size()); ++i) {
  133. const auto &imgData = item.images[i];
  134. QRect cardRect(option.rect.x() + i * cardWidth, option.rect.y(),
  135. cardWidth, option.rect.height());
  136. if (cardRect.contains(me->pos())) {
  137. emit fileDoubleClicked(imgData.path);
  138. return true;
  139. }
  140. }
  141. }
  142. return QStyledItemDelegate::editorEvent(event, model, option, index);
  143. }
  144. bool ResultItemDelegate::helpEvent(QHelpEvent *event, QAbstractItemView *view,
  145. const QStyleOptionViewItem &option,
  146. const QModelIndex &index) {
  147. if (!event || !view || !index.isValid())
  148. return false;
  149. if (event->type() == QEvent::ToolTip) {
  150. const auto *listModel =
  151. qobject_cast<const ResultListModel *>(index.model());
  152. if (!listModel)
  153. return false;
  154. const auto &item = listModel->getItem(index.row());
  155. if (item.type != ResultListItem::ImageRow)
  156. return false;
  157. int cardWidth = option.rect.width() / 4;
  158. for (int i = 0; i < static_cast<int>(item.images.size()); ++i) {
  159. const auto &imgData = item.images[i];
  160. QRect cardRect(option.rect.x() + i * cardWidth, option.rect.y(),
  161. cardWidth, option.rect.height());
  162. if (cardRect.contains(event->pos())) {
  163. QFileInfo fileInfo(QString::fromStdString(imgData.path));
  164. QString toolTip = fileInfo.fileName();
  165. QToolTip::showText(event->globalPos(), toolTip, view, cardRect);
  166. return true;
  167. }
  168. }
  169. }
  170. return QStyledItemDelegate::helpEvent(event, view, option, index);
  171. }