#include "lts_drag_icon.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace LtsWidgets { class LtsToolButton : public QToolButton { Q_OBJECT public: explicit LtsToolButton(QWidget *parent) : QToolButton(parent) , m_sameWidgetDrop(false) , m_isDraggable(true) , m_startPos(QPoint()) { setAutoFillBackground(false); setToolButtonStyle(Qt::ToolButtonTextUnderIcon); } virtual ~LtsToolButton() = default; void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void dragEnterEvent(QDragEnterEvent *event) override; void setSameWidgetDrop(bool drop) { m_sameWidgetDrop = drop; } bool sameWidgetDrop() const { return m_sameWidgetDrop; } void setDraggable(bool isDraggable) { m_isDraggable = isDraggable; } void dropEvent(QDropEvent *event) override { emit newDropEvent(event); QToolButton::dropEvent(event); } void addMimeData(const QString &mimeType, const QByteArray &data); bool removeMimeData(const QString &mimeType); void removeAllMimeData() { m_mimeData.clear(); } protected: void initButton(); signals: void newDropEvent(QDropEvent *e); void dropSuc(); private: void performDrag(QMouseEvent *event); bool m_sameWidgetDrop; bool m_isDraggable; QPoint m_startPos; QMap m_mimeData; }; LtsDragIcon::LtsDragIcon(QWidget *parent) : QWidget(parent) , m_lay(nullptr) , m_toolButton(nullptr) , m_icon() , m_dragLabel(new QLabel(this)) , m_text() , m_style(ButtonStyle::eAll) , m_forceFixedSize(false) , m_isDraggable(true) , m_dropHandlerKey(0L) , m_buttonSize(ButtonSize::eDefault) , m_showDragIcon(true) { setAutoFillBackground(false); initButton(); } void LtsDragIcon::setStyleToButton() { if (nullptr == m_toolButton) return; switch (m_style) { case ButtonStyle::eIconOnly: { setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); m_toolButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); setFixedSize(QSize(static_cast(m_buttonSize), static_cast(m_buttonSize))); m_toolButton->setToolButtonStyle(Qt::ToolButtonIconOnly); } break; case ButtonStyle::eTextOnly: { setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); m_toolButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); setFixedSize( QSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX) ); m_toolButton->setToolButtonStyle(Qt::ToolButtonTextOnly); layout()->setSizeConstraint( QLayout::SetDefaultConstraint ); } break; case ButtonStyle::eTextNextToIcon: { setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); m_toolButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); setFixedSize( QSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX) ); m_toolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); layout()->setSizeConstraint( QLayout::SetDefaultConstraint ); } break; default: break; } } void LtsDragIcon::initButton() { setMinimumSize(static_cast(m_buttonSize), static_cast(m_buttonSize)); delete m_toolButton; delete m_lay; delete layout(); m_toolButton = new LtsToolButton(this); m_toolButton->setDraggable(m_isDraggable); connect(m_toolButton, &LtsToolButton::clicked, this, &LtsDragIcon::clicked); connect(m_toolButton, &LtsToolButton::toggled, this, &LtsDragIcon::toggled); connect(m_toolButton, &LtsToolButton::newDropEvent, this, &LtsDragIcon::newDropEvent); connect(m_toolButton, &LtsToolButton::dropSuc, this, &LtsDragIcon::dropSuc); m_toolButton->setIcon(modifyIcon(m_icon)); m_toolButton->setText(m_text); generateToolTip(); m_toolButton->setIconSize(QSize(static_cast(m_buttonSize), static_cast(m_buttonSize))); QVBoxLayout *box = new QVBoxLayout(this); box->setMargin(0); box->setSpacing(0); box->addWidget(m_toolButton); this->setLayout(box); m_toolButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); if (m_forceFixedSize) { m_toolButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); setFixedSize(QSize(static_cast(m_buttonSize), static_cast(m_buttonSize))); } else { m_toolButton->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Minimum); } setStyleToButton(); } void LtsDragIcon::addToButtonGroup(QButtonGroup *btnGrp, int btnGrpId) { btnGrp->addButton(m_toolButton, btnGrpId); } void LtsDragIcon::setIcon(const QIcon &icon) { m_icon = icon; (m_toolButton) ? m_toolButton->setIcon(modifyIcon(m_icon)) : initButton(); } void LtsDragIcon::setMenu(QMenu *menu) { if (nullptr == m_toolButton) initButton(); m_toolButton->setMenu(menu); } QMenu *LtsDragIcon::menu() const { if (nullptr == m_toolButton) return nullptr; return m_toolButton->menu(); } void LtsDragIcon::setText(const QString &text) { m_text = text; (m_toolButton) ? generateToolTip() : initButton(); } void LtsDragIcon::setContext(const QString &context) { m_context = context; generateToolTip(); } void LtsDragIcon::generateToolTip() { if (!m_toolButton || m_text.isEmpty()) return; QString text(m_text); if (!m_context.isEmpty()) text.prepend(m_context + QLatin1String(" - ")); m_toolButton->setText(m_text); m_toolButton->setToolTip(text); } bool LtsDragIcon::isCheckable() { return (m_toolButton) ? m_toolButton->isCheckable() : false; } void LtsDragIcon::setDraggable(bool draggable) { m_isDraggable = draggable; m_toolButton->setDraggable(m_isDraggable); } void LtsDragIcon::setCheckable(bool checkable) { m_toolButton->setCheckable(checkable); } bool LtsDragIcon::isChecked() const { return (m_toolButton) ? m_toolButton->isChecked() : false; } void LtsDragIcon::setChecked(bool checked) { if (nullptr == m_toolButton) initButton(); m_toolButton->setChecked(checked); } void LtsDragIcon::setSameWidgetDrop(bool drop) { if (nullptr == m_toolButton) initButton(); m_toolButton->setSameWidgetDrop(drop); } bool LtsDragIcon::sameWidgetDrop() const { if (nullptr == m_toolButton) return false; return m_toolButton->sameWidgetDrop(); } void LtsDragIcon::addMimeData(const QString &mimeType, const QByteArray &data) { if (nullptr == m_toolButton) initButton(); m_toolButton->addMimeData(mimeType, data); } bool LtsDragIcon::removeMimeData(const QString &mimeType) { if (nullptr == m_toolButton) initButton(); return m_toolButton->removeMimeData(mimeType); } void LtsDragIcon::removeAllMimeData() { if (nullptr == m_toolButton) initButton(); m_toolButton->removeAllMimeData(); } void LtsDragIcon::setAcceptDrops(bool on) { if (nullptr == m_toolButton) initButton(); m_toolButton->setAcceptDrops(on); } void LtsDragIcon::dragEnterEvent(QDragEnterEvent *e) { if (m_toolButton) m_toolButton->dragEnterEvent(e); } void LtsDragIcon::dropEvent(QDropEvent *e) { QWidget::dropEvent(e); } void LtsDragIcon::setButtonStyle(ButtonStyle style) { m_style = style; setStyleToButton(); } void LtsDragIcon::setIconSize(ButtonSize buttonSize) { m_buttonSize = buttonSize; (m_toolButton) ? m_toolButton->setIconSize(QSize(static_cast(m_buttonSize), static_cast(m_buttonSize))) : initButton(); } void LtsDragIcon::setForceFixedSize(bool force) { m_forceFixedSize = force; initButton(); } void LtsDragIcon::setButtonVisible(bool visible) { if (nullptr == m_toolButton) initButton(); m_toolButton->setVisible(visible); } bool LtsDragIcon::buttonVisible() const { if (nullptr == m_toolButton) return false; return m_toolButton->isVisible(); } void LtsDragIcon::setAction(QAction *action) { QIcon icon = action->icon(); if(!icon.isNull()) m_icon = icon; m_toolButton->setDefaultAction(action); this->setObjectName(action->objectName()); } void LtsDragIcon::changeEvent(QEvent *event) { if (event->type() == QEvent::EnabledChange) emit enabledChanged(isEnabled()); } void LtsToolButton::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) m_startPos = event->pos(); QToolButton::mousePressEvent(event); } void LtsToolButton::mouseReleaseEvent(QMouseEvent *event) { QToolButton::mouseReleaseEvent(event); } void LtsToolButton::mouseMoveEvent(QMouseEvent *event) { if (!m_isDraggable) return; if (event->buttons() & Qt::LeftButton) { int distance = (event->pos() - m_startPos).manhattanLength(); if (distance >= 5) { this->setDown(false); performDrag(event); return; } } QToolButton::mouseMoveEvent(event); } void LtsToolButton::performDrag(QMouseEvent *) { QWidget *item = this; if (item) { LtsDragIcon *dragIcon = nullptr; QString name; while (dragIcon == nullptr) { if ((!item->objectName().isEmpty()) && (name.isNull())) { name = item->objectName(); } item = item->parentWidget(); if (nullptr == item) return; dragIcon = dynamic_cast(item); } QMimeData *mimeData = new QMimeData(); mimeData->setText(name); for(auto it = m_mimeData.cbegin(); it != m_mimeData.cend(); ++it) mimeData->setData(it.key(), it.value()); if (dragIcon->dropHandlerKey() != 0L) { QByteArray data = QByteArray(QByteArray::number(dragIcon->dropHandlerKey())); mimeData->setData(QLatin1String("DropHandlerPtr"),data); } QDrag *drag = new QDrag(item); drag->setMimeData(mimeData); QAction *action = defaultAction(); if ((action) && (dragIcon->showDragIcon())) { drag->setPixmap(action->icon().pixmap(16,16) ); } else { drag->setPixmap(dragIcon->icon().pixmap(16, 16)); } Qt::DropAction drop = drag->exec(Qt::CopyAction | Qt::MoveAction); if (drop == Qt::MoveAction || drop == Qt::CopyAction ) emit dropSuc(); } } void LtsToolButton::dragEnterEvent(QDragEnterEvent *event) { QWidget *source = qobject_cast(event->source()); if (source && source != this) { event->setDropAction(Qt::MoveAction); event->accept(); } QWidget::dragEnterEvent(event); } void LtsToolButton::addMimeData(const QString &mimeType, const QByteArray &data) { m_mimeData.insert(mimeType,data); } bool LtsToolButton::removeMimeData(const QString &mimeType) { return (m_mimeData.remove(mimeType) > 0); } #define SIZE 40 QIcon LtsDragIcon::modifyIcon(const QIcon &icon) { if (m_modification.isEmpty()) return icon; QPixmap iconImage(icon.pixmap(SIZE*0.8, SIZE*0.8)); QPainter painter(&iconImage); painter.save(); painter.setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing | QPainter::HighQualityAntialiasing | QPainter::SmoothPixmapTransform); painter.setBrush(QColor("red")); painter.setPen(QPen(QColor("red"), 3)); QFont f; f.setFamily(QStringLiteral("Monospace")); f.setPointSize(12); f.setBold(true); painter.setFont(f); painter.drawText(QRect(0, 0, 28, 28), m_modification); painter.restore(); return iconImage; } } #include "lts_drag_icon.moc"