diff --git a/src/lib/bookmarks/bookmarksmodel.h b/src/lib/bookmarks/bookmarksmodel.h --- a/src/lib/bookmarks/bookmarksmodel.h +++ b/src/lib/bookmarks/bookmarksmodel.h @@ -20,6 +20,7 @@ #include #include +#include #include "qzcommon.h" @@ -99,4 +100,23 @@ QTimer* m_filterTimer; }; +class FALKON_EXPORT BookmarksButtonMimeData : public QMimeData +{ + Q_OBJECT + +public: + explicit BookmarksButtonMimeData(); + + BookmarkItem *item() const; + void setBookmarkItem(BookmarkItem *item); + + bool hasFormat(const QString &format) const override; + QStringList formats() const override; + + static QString mimeType(); + +private: + BookmarkItem* m_item; +}; + #endif // BOOKMARKSMODEL_H diff --git a/src/lib/bookmarks/bookmarksmodel.cpp b/src/lib/bookmarks/bookmarksmodel.cpp --- a/src/lib/bookmarks/bookmarksmodel.cpp +++ b/src/lib/bookmarks/bookmarksmodel.cpp @@ -349,3 +349,33 @@ { QSortFilterProxyModel::setFilterFixedString(m_pattern); } + +BookmarksButtonMimeData::BookmarksButtonMimeData() + : QMimeData() +{ +} + +BookmarkItem *BookmarksButtonMimeData::item() const +{ + return m_item; +} + +void BookmarksButtonMimeData::setBookmarkItem(BookmarkItem *item) +{ + m_item = item; +} + +bool BookmarksButtonMimeData::hasFormat(const QString &format) const +{ + return mimeType() == format; +} + +QStringList BookmarksButtonMimeData::formats() const +{ + return {mimeType()}; +} + +QString BookmarksButtonMimeData::mimeType() +{ + return QSL("application/falkon.bookmarktoolbutton.bookmarkitem"); +} diff --git a/src/lib/bookmarks/bookmarkstoolbar.h b/src/lib/bookmarks/bookmarkstoolbar.h --- a/src/lib/bookmarks/bookmarkstoolbar.h +++ b/src/lib/bookmarks/bookmarkstoolbar.h @@ -59,14 +59,21 @@ void dropEvent(QDropEvent* e); void dragEnterEvent(QDragEnterEvent* e); + void dragMoveEvent(QDragMoveEvent* e); + void dragLeaveEvent(QDragLeaveEvent* e); + void paintEvent(QPaintEvent* p); BrowserWindow* m_window; Bookmarks* m_bookmarks; BookmarkItem* m_clickedBookmark; QHBoxLayout* m_layout; QTimer* m_updateTimer; QAction* m_actShowOnlyIcons = nullptr; QAction* m_actShowOnlyText = nullptr; + + int m_dropRow; + QPoint m_dropPos; + void clearDropIndicator(); }; #endif // BOOKMARKSTOOLBAR_H diff --git a/src/lib/bookmarks/bookmarkstoolbar.cpp b/src/lib/bookmarks/bookmarkstoolbar.cpp --- a/src/lib/bookmarks/bookmarkstoolbar.cpp +++ b/src/lib/bookmarks/bookmarkstoolbar.cpp @@ -18,10 +18,12 @@ #include "bookmarkstoolbar.h" #include "bookmarkstoolbarbutton.h" #include "bookmarkstools.h" +#include "bookmarksmodel.h" #include "bookmarkitem.h" #include "bookmarks.h" #include "mainapplication.h" #include "iconprovider.h" +#include "qztools.h" #include #include @@ -34,6 +36,7 @@ , m_window(window) , m_bookmarks(mApp->bookmarks()) , m_clickedBookmark(0) + , m_dropRow(-1) { setObjectName("bookmarksbar"); setAcceptDrops(true); @@ -226,36 +229,104 @@ void BookmarksToolbar::dropEvent(QDropEvent* e) { + int row = m_dropRow; + clearDropIndicator(); + const QMimeData* mime = e->mimeData(); - if (!mime->hasUrls()) { + if (!mime->hasUrls() && !mime->hasFormat(BookmarksButtonMimeData::mimeType())) { QWidget::dropEvent(e); return; } - QUrl url = mime->urls().at(0); - QString title = mime->hasText() ? mime->text() : url.toEncoded(QUrl::RemoveScheme); - BookmarkItem* parent = m_bookmarks->toolbarFolder(); - BookmarksToolbarButton* button = buttonAt(e->pos()); - if (button && button->bookmark()->isFolder()) { - parent = button->bookmark(); + BookmarkItem* bookmark = nullptr; + + if (mime->hasFormat(BookmarksButtonMimeData::mimeType())) { + const BookmarksButtonMimeData* bookmarkMime = static_cast(mime); + bookmark = bookmarkMime->item(); + const int initialIndex = bookmark->parent()->children().indexOf(bookmark); + BookmarksToolbarButton* current = buttonAt(m_dropPos); + if (initialIndex < m_layout->indexOf(current)) { + row -= 1; + } + } else { + const QUrl url = mime->urls().at(0); + const QString title = mime->hasText() ? mime->text() : url.toEncoded(QUrl::RemoveScheme); + + bookmark = new BookmarkItem(BookmarkItem::Url); + bookmark->setTitle(title); + bookmark->setUrl(url); } - BookmarkItem* bookmark = new BookmarkItem(BookmarkItem::Url); - bookmark->setTitle(title); - bookmark->setUrl(url); - m_bookmarks->addBookmark(parent, bookmark); + if (row >= 0) { + m_bookmarks->insertBookmark(parent, row, bookmark); + } else { + m_bookmarks->addBookmark(parent, bookmark); + } } void BookmarksToolbar::dragEnterEvent(QDragEnterEvent* e) { const QMimeData* mime = e->mimeData(); - if (mime->hasUrls() && mime->hasText()) { + if ((mime->hasUrls() && mime->hasText()) || mime->hasFormat(BookmarksButtonMimeData::mimeType())) { e->acceptProposedAction(); return; } QWidget::dragEnterEvent(e); } + +void BookmarksToolbar::dragMoveEvent(QDragMoveEvent *e) +{ + int eventX = e->pos().x(); + BookmarksToolbarButton* button = buttonAt(e->pos()); + m_dropPos = e->pos(); + m_dropRow = m_layout->indexOf(button); + if (button) { + bool res = eventX - button->x() < button->x() + button->width() -eventX; + m_dropRow = res ? m_dropRow : m_dropRow + 1; + } else { + m_dropRow = -1; + } + + update(); +} + +void BookmarksToolbar::dragLeaveEvent(QDragLeaveEvent *e) +{ + Q_UNUSED(e); + clearDropIndicator(); +} + +void BookmarksToolbar::clearDropIndicator() +{ + m_dropRow = -1; + update(); +} + +void BookmarksToolbar::paintEvent(QPaintEvent *p) +{ + QWidget::paintEvent(p); + + // Draw drop indicator + if (m_dropRow != -1) { + BookmarksToolbarButton* button = buttonAt(m_dropPos); + if (button) { + if (button->bookmark()->isFolder()) { + return; + } + const QRect tr = QRect(button->x(), 0, button->width(), height()); + QRect r; + + if (m_dropRow == m_layout->indexOf(button)) { + r = QRect(qMax(0, tr.left() - 2), tr.top(), 3, tr.height()); + } else { + r = QRect(tr.right() + 0, tr.top(), 3, tr.height()); + } + + QzTools::paintDropIndicator(this, r); + } + } +} diff --git a/src/lib/bookmarks/bookmarkstoolbarbutton.h b/src/lib/bookmarks/bookmarkstoolbarbutton.h --- a/src/lib/bookmarks/bookmarkstoolbarbutton.h +++ b/src/lib/bookmarks/bookmarkstoolbarbutton.h @@ -67,13 +67,19 @@ void leaveEvent(QEvent* event) override; void mousePressEvent(QMouseEvent* event) override; void mouseReleaseEvent(QMouseEvent* event) override; + void mouseMoveEvent(QMouseEvent *event) override; void paintEvent(QPaintEvent* event) override; + void dragEnterEvent(QDragEnterEvent *event) override; + void dragLeaveEvent(QDragLeaveEvent *event) override; + void dropEvent(QDropEvent *event) override; + BookmarkItem* m_bookmark; BrowserWindow* m_window; bool m_showOnlyIcon; bool m_showOnlyText; + QPoint m_dragStartPosition; }; #endif // BOOKMARKSTOOLBARBUTTON_H diff --git a/src/lib/bookmarks/bookmarkstoolbarbutton.cpp b/src/lib/bookmarks/bookmarkstoolbarbutton.cpp --- a/src/lib/bookmarks/bookmarkstoolbarbutton.cpp +++ b/src/lib/bookmarks/bookmarkstoolbarbutton.cpp @@ -17,6 +17,7 @@ * ============================================================ */ #include "bookmarkstoolbarbutton.h" #include "bookmarkstools.h" +#include "bookmarksmodel.h" #include "bookmarkitem.h" #include "bookmarks.h" #include "mainapplication.h" @@ -26,6 +27,8 @@ #include #include #include +#include +#include #define MAX_WIDTH 150 #define SEPARATOR_WIDTH 8 @@ -38,6 +41,10 @@ , m_showOnlyIcon(false) { init(); + + if (m_bookmark->isFolder()) { + setAcceptDrops(true); + } } BookmarkItem* BookmarksToolbarButton::bookmark() const @@ -266,6 +273,8 @@ } } + m_dragStartPosition = event->pos(); + QPushButton::mousePressEvent(event); } @@ -294,6 +303,23 @@ QPushButton::mouseReleaseEvent(event); } +void BookmarksToolbarButton::mouseMoveEvent(QMouseEvent *event) +{ + if ((event->pos() - m_dragStartPosition).manhattanLength() < QApplication::startDragDistance()) { + QPushButton::mouseMoveEvent(event); + return; + } + + setDown(false); + + QDrag *drag = new QDrag(this); + BookmarksButtonMimeData* mime = new BookmarksButtonMimeData; + mime->setBookmarkItem(m_bookmark); + drag->setMimeData(mime); + drag->setPixmap(grab()); + drag->exec(); +} + void BookmarksToolbarButton::paintEvent(QPaintEvent* event) { Q_UNUSED(event) @@ -362,3 +388,48 @@ Qt::TextSingleLine | Qt::AlignCenter, option.palette, true, txt); } } + +void BookmarksToolbarButton::dragEnterEvent(QDragEnterEvent *event) +{ + const QMimeData* mime = event->mimeData(); + if ((mime->hasUrls() && mime->hasText()) || mime->hasFormat(BookmarksButtonMimeData::mimeType())) { + event->acceptProposedAction(); + setDown(true); + return; + } + + QPushButton::dragEnterEvent(event); +} + +void BookmarksToolbarButton::dragLeaveEvent(QDragLeaveEvent *event) +{ + Q_UNUSED(event); + setDown(false); +} + +void BookmarksToolbarButton::dropEvent(QDropEvent *event) +{ + setDown(false); + + const QMimeData* mime = event->mimeData(); + if (!mime->hasUrls() && !mime->hasFormat(BookmarksButtonMimeData::mimeType())) { + QPushButton::dropEvent(event); + return; + } + + BookmarkItem* bookmark = nullptr; + + if (mime->hasFormat(BookmarksButtonMimeData::mimeType())) { + const BookmarksButtonMimeData* bookmarkMime = static_cast(mime); + bookmark = bookmarkMime->item(); + } else { + const QUrl url = mime->urls().at(0); + const QString title = mime->hasText() ? mime->text() : url.toEncoded(QUrl::RemoveScheme); + + bookmark = new BookmarkItem(BookmarkItem::Url); + bookmark->setTitle(title); + bookmark->setUrl(url); + } + + mApp->bookmarks()->addBookmark(m_bookmark, bookmark); +} diff --git a/src/lib/tabwidget/combotabbar.cpp b/src/lib/tabwidget/combotabbar.cpp --- a/src/lib/tabwidget/combotabbar.cpp +++ b/src/lib/tabwidget/combotabbar.cpp @@ -22,6 +22,7 @@ #include "mainapplication.h" #include "proxystyle.h" #include "qzsettings.h" +#include "qztools.h" #include #include @@ -1379,19 +1380,7 @@ const int rightOffset = m_dropIndicatorIndex == count() - 1 ? -2 : 0; r = QRect(tr.right() + rightOffset, tr.top(), 3, tr.height()); } - // Modified code from KFilePlacesView - QColor color = palette().brush(QPalette::Normal, QPalette::Highlight).color(); - const int x = (r.left() + r.right()) / 2; - const int thickness = qRound(r.width() / 2.0); - int alpha = 255; - const int alphaDec = alpha / (thickness + 1); - for (int i = 0; i < thickness; i++) { - color.setAlpha(alpha); - alpha -= alphaDec; - p.setPen(color); - p.drawLine(x - i, r.top(), x - i, r.bottom()); - p.drawLine(x + i, r.top(), x + i, r.bottom()); - } + QzTools::paintDropIndicator(this, r); } } diff --git a/src/lib/tools/qztools.h b/src/lib/tools/qztools.h --- a/src/lib/tools/qztools.h +++ b/src/lib/tools/qztools.h @@ -19,6 +19,7 @@ #define QZTOOLS_H #include +#include #include "qzcommon.h" @@ -95,6 +96,8 @@ { return (index >= 0 && container.count() > index); } + + static void paintDropIndicator(QWidget *widget, const QRect &r); }; #endif // QZTOOLS_H diff --git a/src/lib/tools/qztools.cpp b/src/lib/tools/qztools.cpp --- a/src/lib/tools/qztools.cpp +++ b/src/lib/tools/qztools.cpp @@ -1001,3 +1001,20 @@ return QzTools::operatingSystem() + QSL(" ") + arch; } +void QzTools::paintDropIndicator(QWidget *widget, const QRect &r) +{ + // Modified code from KFilePlacesView + QColor color = widget->palette().brush(QPalette::Normal, QPalette::Highlight).color(); + const int x = (r.left() + r.right()) / 2; + const int thickness = qRound(r.width() / 2.0); + int alpha = 255; + const int alphaDec = alpha / (thickness + 1); + QStylePainter p(widget); + for (int i = 0; i < thickness; i++) { + color.setAlpha(alpha); + alpha -= alphaDec; + p.setPen(color); + p.drawLine(x - i, r.top(), x - i, r.bottom()); + p.drawLine(x + i, r.top(), x + i, r.bottom()); + } +}