#include "yacreader_table_view.h" #include "yacreader_global.h" #include "yacreader_global_gui.h" #include #include #include #include #include #include #include #include #include "QsLog.h" #include "comic_item.h" #include "comic_model.h" YACReaderTableView::YACReaderTableView(QWidget *parent) : QTableView(parent), editing(false), myeditor(0) { setAlternatingRowColors(true); verticalHeader()->setAlternatingRowColors(true); setContextMenuPolicy(Qt::ActionsContextMenu); setShowGrid(false); verticalHeader()->setSectionResizeMode(QHeaderView::Fixed); // comicView->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); horizontalHeader()->setStretchLastSection(true); horizontalHeader()->setSectionsClickable(false); // comicView->verticalHeader()->setResizeMode(QHeaderView::ResizeToContents); verticalHeader()->setDefaultSectionSize(24); verticalHeader()->setSectionsClickable(false); // TODO comportamiento anĂ³malo setCornerButtonEnabled(false); setSelectionBehavior(QAbstractItemView::SelectRows); setSelectionMode(QAbstractItemView::ExtendedSelection); setItemDelegateForColumn(ComicModel::Rating, new YACReaderRatingDelegate(this)); setEditTriggers(QAbstractItemView::NoEditTriggers); setMouseTracking(true); // drag: if the default drag is enabled there is no way for setting a custom image // TODO report bug/suggestion // setDragEnabled(true); // setDragDropMode(QAbstractItemView::DragDrop); setAcceptDrops(true); initTheme(this); } void YACReaderTableView::applyTheme(const Theme &theme) { setStyleSheet(theme.tableView.tableViewQSS); } void YACReaderTableView::mouseMoveEvent(QMouseEvent *event) { QModelIndex mi = indexAt(event->pos()); if (mi.isValid()) { QList selectedIndexes = this->selectedIndexes(); if (selectedIndexes.contains(mi)) { if (mi.column() == ComicModel::Rating) { if (!editing) { editing = true; currentIndexEditing = mi; edit(mi); myeditor = indexWidget(mi); } else if (mi.row() != currentIndexEditing.row()) closeRatingEditor(); } else closeRatingEditor(); } else closeRatingEditor(); } else closeRatingEditor(); // are we in a drag action?? if (event->buttons() & Qt::LeftButton) { int distance = (event->pos() - startDragPos).manhattanLength(); if (distance >= QApplication::startDragDistance()) performDrag(); } // disabled mouseMoveEvent in the parent class } void YACReaderTableView::mousePressEvent(QMouseEvent *event) { QTableView::mousePressEvent(event); QModelIndex mi = indexAt(event->pos()); if (mi.isValid()) { QList selectedIndexes = this->selectedIndexes(); if (selectedIndexes.contains(mi)) { if (mi.column() == ComicModel::Rating) { if (!editing) { editing = true; currentIndexEditing = mi; edit(mi); myeditor = indexWidget(mi); } return; } } } // this could be the origin of a new drag acction if (event->button() == Qt::LeftButton) { startDragPos = event->pos(); } } void YACReaderTableView::leaveEvent(QEvent *event) { closeRatingEditor(); event->accept(); } void YACReaderTableView::performDrag() { QLOG_DEBUG() << "performDrag"; QDrag *drag = new QDrag(this); drag->setMimeData(model()->mimeData(selectionModel()->selectedRows())); drag->setPixmap(YACReader::hdpiPixmap(":/images/comics_view_toolbar/openInYACReader.svg", QSize(18, 18))); // TODO add better image /*Qt::DropAction dropAction =*/drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction); } void YACReaderTableView::dragEnterEvent(QDragEnterEvent *event) { QTableView::dragEnterEvent(event); if (model()->canDropMimeData(event->mimeData(), event->proposedAction(), 0, 0, QModelIndex())) event->acceptProposedAction(); QLOG_DEBUG() << "drag enter table"; } void YACReaderTableView::dragMoveEvent(QDragMoveEvent *event) { QTableView::dragMoveEvent(event); if (model()->canDropMimeData(event->mimeData(), event->proposedAction(), 0, 0, QModelIndex())) event->acceptProposedAction(); QLOG_DEBUG() << "dragMoveEvent table"; } void YACReaderTableView::dropEvent(QDropEvent *event) { QTableView::dropEvent(event); if (model()->canDropMimeData(event->mimeData(), event->proposedAction(), 0, 0, QModelIndex())) event->acceptProposedAction(); QLOG_DEBUG() << "drop on table"; } void YACReaderTableView::closeRatingEditor() { editing = false; if (myeditor != 0) closeEditor(myeditor, QAbstractItemDelegate::NoHint); myeditor = 0; } void YACReaderTableView::closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint) { editing = false; myeditor = 0; QTableView::closeEditor(editor, hint); } void YACReaderTableView::commitData(QWidget *editor) { // TODO StarEditor *starEditor = qobject_cast(editor); if (starEditor->getShouldCommitData()) emit comicRated(((StarEditor *)editor)->starRating().starCount(), currentIndexEditing); } void YACReaderTableView::resizeEvent(QResizeEvent *event) { QTableView::resizeEvent(event); } //------------------------------------------------------------------------------ // YACReaderRatingDelegate------------------------------------------------------- //------------------------------------------------------------------------------ void YACReaderRatingDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { int rating = ((ComicItem *)index.internalPointer())->data(ComicModel::Rating).toInt(); StarRating starRating(rating); // Get colors from parent table view QColor ratingColor(0xE9BE0F); QColor ratingSelectedColor(Qt::white); if (auto tableView = qobject_cast(parent())) { ratingColor = tableView->starRatingColor(); ratingSelectedColor = tableView->starRatingSelectedColor(); } QStyledItemDelegate::paint(painter, option, index); if (!(option.state & QStyle::State_Editing)) { if (option.state & QStyle::State_Selected) starRating.paintSelected(painter, option.rect, option.palette, StarRating::ReadOnly, ratingSelectedColor); else starRating.paint(painter, option.rect, option.palette, StarRating::ReadOnly, ratingColor); } } QSize YACReaderRatingDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(option) int rating = ((ComicItem *)index.internalPointer())->data(ComicModel::Rating).toInt(); StarRating starRating(rating); return starRating.sizeHint(); } QWidget *YACReaderRatingDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_UNUSED(option) Q_UNUSED(index) StarEditor *editor = new StarEditor(parent); connect(editor, &StarEditor::editingFinished, this, &YACReaderRatingDelegate::sendCloseEditor); connect(editor, &StarEditor::commitData, this, &YACReaderRatingDelegate::sendCommitData); return editor; } void YACReaderRatingDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { int rating = ((ComicItem *)index.internalPointer())->data(ComicModel::Rating).toInt(); StarRating starRating(rating); StarEditor *starEditor = qobject_cast(editor); starEditor->setStarRating(starRating); } void YACReaderRatingDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QStyledItemDelegate::setModelData(editor, model, index); } void YACReaderRatingDelegate::sendCommitData() { StarEditor *editor = qobject_cast(sender()); emit commitData(editor); } void YACReaderRatingDelegate::sendCloseEditor() { StarEditor *editor = qobject_cast(sender()); emit closeEditor(editor); } //------------------------------------------------------------------------------- // StarRating--------------------------------------------------------------------- //------------------------------------------------------------------------------- const int PaintingScaleFactor = 20; StarRating::StarRating(int starCount, int maxStarCount) { myStarCount = starCount; myMaxStarCount = maxStarCount; int numVertex = 5; double pi = 3.14159265359; double angle = 3.14159265359 / numVertex; float rOuter = 0.3f; float rInner = 0.15f; for (int i = 0; i < 2 * numVertex; i++) { double r = (i & 1) == 0 ? rOuter : rInner; starPolygon << QPointF(0.5 + cos((i * angle) - pi / 2) * r, 0.5 + sin((i * angle) - pi / 2) * r); } diamondPolygon << QPointF(0.4, 0.5) << QPointF(0.5, 0.4) << QPointF(0.6, 0.5) << QPointF(0.5, 0.6) << QPointF(0.4, 0.5); } QSize StarRating::sizeHint() const { return PaintingScaleFactor * QSize(myMaxStarCount, 1); } void StarRating::paint(QPainter *painter, const QRect &rect, const QPalette &palette, EditMode mode) const { paint(painter, rect, palette, mode, QColor("#e9be0f")); } void StarRating::paint(QPainter *painter, const QRect &rect, const QPalette &palette, EditMode mode, QColor color) const { Q_UNUSED(palette) painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); painter->setPen(Qt::NoPen); QBrush brush(color); painter->setBrush(brush); int yOffset = (rect.height() - PaintingScaleFactor) / 2; painter->translate(rect.x(), rect.y() + yOffset); painter->scale(PaintingScaleFactor, PaintingScaleFactor); for (int i = 0; i < myMaxStarCount; ++i) { if (i < myStarCount) { painter->drawPolygon(starPolygon, Qt::WindingFill); } else if (mode == Editable) { painter->drawEllipse(QPointF(0.5, 0.5), 0.08, 0.08); } painter->translate(1.0, 0.0); } painter->restore(); } void StarRating::paintSelected(QPainter *painter, const QRect &rect, const QPalette &palette, EditMode mode, QColor color) const { Q_UNUSED(palette) Q_UNUSED(mode) painter->save(); painter->setRenderHint(QPainter::Antialiasing, true); painter->setPen(Qt::NoPen); QBrush star(color); QBrush dot(QColor("#ffffff")); int yOffset = (rect.height() - PaintingScaleFactor) / 2; painter->translate(rect.x(), rect.y() + yOffset); painter->scale(PaintingScaleFactor, PaintingScaleFactor); for (int i = 0; i < myMaxStarCount; ++i) { if (i < myStarCount) { painter->setBrush(star); painter->drawPolygon(starPolygon, Qt::WindingFill); } else { painter->setBrush(dot); painter->drawEllipse(QPointF(0.5, 0.5), 0.08, 0.08); } painter->translate(1.0, 0.0); } painter->restore(); } void StarRating::paintSelected(QPainter *painter, const QRect &rect, const QPalette &palette, EditMode mode) const { paintSelected(painter, rect, palette, mode, QColor("#ffffff")); } //------------------------------------------------------------------------------- // StarEditor--------------------------------------------------------------------- //------------------------------------------------------------------------------- StarEditor::StarEditor(QWidget *parent) : QWidget(parent), shouldCommitData(false) { // setMouseTracking(true); // setAutoFillBackground(true); } QSize StarEditor::sizeHint() const { return myStarRating.sizeHint(); } void StarEditor::paintEvent(QPaintEvent *) { /* QPainter painter(this); myStarRating.paintSelected(&painter, rect(), this->palette(), StarRating::Editable,QColor("#615f59"));*/ } void StarEditor::mouseMoveEvent(QMouseEvent *event) { Q_UNUSED(event) /*int star = starAtPosition(event->x()); if (star != myStarRating.starCount() && star != -1) { myStarRating.setStarCount(star); update(); }*/ } void StarEditor::leaveEvent(QEvent *event) { emit editingFinished(); QWidget::leaveEvent(event); } void StarEditor::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { int star = starAtPosition(event->x()); if (star != myStarRating.starCount() && star != -1) { myStarRating.setStarCount(star); shouldCommitData = true; emit commitData(); } } } int StarEditor::starAtPosition(int x) { int star = (x / (myStarRating.sizeHint().width() / myStarRating.maxStarCount())) + 1; if (star <= 0 || star > myStarRating.maxStarCount()) return -1; return star; }