diff --git a/src/lib/tabwidget/tabbar.cpp b/src/lib/tabwidget/tabbar.cpp index 89b6bf124..58d66a399 100644 --- a/src/lib/tabwidget/tabbar.cpp +++ b/src/lib/tabwidget/tabbar.cpp @@ -1,6 +1,6 @@ /* ============================================================ * Falkon - Qt web browser -* Copyright (C) 2010-2017 David Rosca +* Copyright (C) 2010-2018 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,7 +28,6 @@ #include "tabcontextmenu.h" #include "searchenginesmanager.h" -#include #include #include #include @@ -38,6 +37,9 @@ #include #include #include +#include + +#define MIMETYPE QSL("application/qupzilla.tabbar.tab") TabBar::TabBar(BrowserWindow* window, TabWidget* tabWidget) : ComboTabBar() @@ -454,9 +456,8 @@ void TabBar::mousePressEvent(QMouseEvent* event) } if (event->buttons() == Qt::LeftButton && !emptyArea(event->pos())) { - m_dragStartPosition = mapFromGlobal(event->globalPos()); - } - else { + m_dragStartPosition = event->pos(); + } else { m_dragStartPosition = QPoint(); } @@ -469,10 +470,36 @@ void TabBar::mouseMoveEvent(QMouseEvent* event) return; } - if (!m_dragStartPosition.isNull() && m_tabWidget->buttonAddTab()->isVisible()) { - int manhattanLength = (event->pos() - m_dragStartPosition).manhattanLength(); - if (manhattanLength > QApplication::startDragDistance()) { - m_tabWidget->buttonAddTab()->hide(); + if (!m_dragStartPosition.isNull()) { + if (m_tabWidget->buttonAddTab()->isVisible()) { + int manhattanLength = (event->pos() - m_dragStartPosition).manhattanLength(); + if (manhattanLength > QApplication::startDragDistance()) { + m_tabWidget->buttonAddTab()->hide(); + } + } + int offset = 0; + const int eventY = event->pos().y(); + if (eventY < 0) { + offset = qAbs(eventY); + } else if (eventY > height()) { + offset = eventY - height(); + } + if (count() > 1 && offset > QApplication::startDragDistance()) { + const QPoint global = mapToGlobal(m_dragStartPosition); + QWidget *w = QApplication::widgetAt(global); + if (w) { + QMouseEvent mouse(QEvent::MouseButtonRelease, w->mapFromGlobal(global), Qt::LeftButton, Qt::LeftButton, event->modifiers()); + QApplication::sendEvent(w, &mouse); + } + QDrag *drag = new QDrag(this); + QMimeData *mime = new QMimeData; + mime->setData(MIMETYPE, QByteArray()); + drag->setMimeData(mime); + drag->setPixmap(tabPixmap(currentIndex())); + if (drag->exec() == Qt::IgnoreAction) { + m_tabWidget->detachTab(currentIndex()); + } + return; } } @@ -528,7 +555,7 @@ enum TabDropAction { AppendTab }; -static TabDropAction tabDropAction(const QPoint &pos, const QRect &tabRect) +static TabDropAction tabDropAction(const QPoint &pos, const QRect &tabRect, bool allowSelect) { if (!tabRect.contains(pos)) { return NoAction; @@ -538,7 +565,7 @@ static TabDropAction tabDropAction(const QPoint &pos, const QRect &tabRect) const QSize csize = QSize(tabRect.width() * 0.7, tabRect.height() * 0.7); const QRect center(c.x() - csize.width() / 2, c.y() - csize.height() / 2, csize.width(), csize.height()); - if (center.contains(pos)) { + if (allowSelect && center.contains(pos)) { return SelectTab; } else if (pos.x() < c.x()) { return PrependTab; @@ -551,7 +578,7 @@ void TabBar::dragEnterEvent(QDragEnterEvent* event) { const QMimeData* mime = event->mimeData(); - if (mime->hasText() || mime->hasUrls()) { + if (mime->hasText() || mime->hasUrls() || mime->hasFormat(MIMETYPE)) { event->acceptProposedAction(); return; } @@ -559,22 +586,17 @@ void TabBar::dragEnterEvent(QDragEnterEvent* event) ComboTabBar::dragEnterEvent(event); } -void TabBar::dragLeaveEvent(QDragLeaveEvent *event) -{ - clearDropIndicator(); - - ComboTabBar::dragLeaveEvent(event); -} - void TabBar::dragMoveEvent(QDragMoveEvent *event) { const int index = tabAt(event->pos()); - if (index == -1) { + const QMimeData* mime = event->mimeData(); + + if (index == -1 || (mime->hasFormat(MIMETYPE) && event->source() == this)) { ComboTabBar::dragMoveEvent(event); return; } - switch (tabDropAction(event->pos(), tabRect(index))) { + switch (tabDropAction(event->pos(), tabRect(index), !mime->hasFormat(MIMETYPE))) { case PrependTab: showDropIndicator(index, BeforeTab); break; @@ -587,17 +609,32 @@ void TabBar::dragMoveEvent(QDragMoveEvent *event) } } +void TabBar::dragLeaveEvent(QDragLeaveEvent *event) +{ + clearDropIndicator(); + + ComboTabBar::dragLeaveEvent(event); +} + void TabBar::dropEvent(QDropEvent* event) { clearDropIndicator(); const QMimeData* mime = event->mimeData(); - if (!mime->hasText() && !mime->hasUrls()) { + if (!mime->hasText() && !mime->hasUrls() && !mime->hasFormat(MIMETYPE)) { ComboTabBar::dropEvent(event); return; } + event->acceptProposedAction(); + + if (mime->hasFormat(MIMETYPE) && event->source() == this) { + return; + } + + TabBar *sourceTabBar = qobject_cast(event->source()); + int index = tabAt(event->pos()); if (index == -1) { if (mime->hasUrls()) { @@ -606,24 +643,39 @@ void TabBar::dropEvent(QDropEvent* event) } } else if (mime->hasText()) { m_tabWidget->addView(mApp->searchEnginesManager()->searchResult(mime->text()), Qz::NT_SelectedNewEmptyTab); + } else if (mime->hasFormat(MIMETYPE) && sourceTabBar) { + WebTab *tab = sourceTabBar->webTab(); + if (tab) { + sourceTabBar->m_tabWidget->detachTab(tab); + tab->setPinned(false); + m_tabWidget->addView(tab, Qz::NT_SelectedTab); + } } - } - else { + } else { LoadRequest req; WebTab* tab = m_window->weView(index)->webTab(); - TabDropAction action = tabDropAction(event->pos(), tabRect(index)); + TabDropAction action = tabDropAction(event->pos(), tabRect(index), !mime->hasFormat(MIMETYPE)); if (mime->hasUrls()) { req = mime->urls().at(0); } else if (mime->hasText()) { req = mApp->searchEnginesManager()->searchResult(mime->text()); } if (action == SelectTab) { - if (tab->isRestored()) { + if (tab->isRestored() && !req.isEmpty()) { tab->webView()->load(req); } } else if (action == PrependTab || action == AppendTab) { const int newIndex = action == PrependTab ? index : index + 1; - m_tabWidget->addView(req, QString(), Qz::NT_SelectedNewEmptyTab, false, newIndex, index <= pinnedTabsCount()); + if (!req.isEmpty()) { + m_tabWidget->addView(req, QString(), Qz::NT_SelectedNewEmptyTab, false, newIndex, index < pinnedTabsCount()); + } else if (mime->hasFormat(MIMETYPE) && sourceTabBar) { + WebTab *tab = sourceTabBar->webTab(); + if (tab) { + sourceTabBar->m_tabWidget->detachTab(tab); + tab->setPinned(index < pinnedTabsCount()); + m_tabWidget->insertView(newIndex, tab, Qz::NT_SelectedTab); + } + } } } } diff --git a/src/lib/tabwidget/tabbar.h b/src/lib/tabwidget/tabbar.h index 5dcd235cf..9501a0d12 100644 --- a/src/lib/tabwidget/tabbar.h +++ b/src/lib/tabwidget/tabbar.h @@ -1,6 +1,6 @@ /* ============================================================ * Falkon - Qt web browser -* Copyright (C) 2010-2017 David Rosca +* Copyright (C) 2010-2018 David Rosca * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -70,8 +70,8 @@ private: void mouseReleaseEvent(QMouseEvent* event); void dragEnterEvent(QDragEnterEvent* event); - void dragLeaveEvent(QDragLeaveEvent *event); void dragMoveEvent(QDragMoveEvent *event); + void dragLeaveEvent(QDragLeaveEvent *event); void dropEvent(QDropEvent* event); QSize tabSizeHint(int index, bool fast) const; diff --git a/src/lib/tabwidget/tabwidget.cpp b/src/lib/tabwidget/tabwidget.cpp index 9decc10bc..661949469 100644 --- a/src/lib/tabwidget/tabwidget.cpp +++ b/src/lib/tabwidget/tabwidget.cpp @@ -386,7 +386,7 @@ int TabWidget::addView(WebTab *tab, const Qz::NewTabPositionFlags &openFlags) int TabWidget::insertView(int index, WebTab *tab, const Qz::NewTabPositionFlags &openFlags) { m_locationBars->addWidget(tab->locationBar()); - int newIndex = insertTab(index, tab, QString()); + int newIndex = insertTab(index, tab, QString(), tab->isPinned()); tab->attach(m_window); if (openFlags.testFlag(Qz::NT_SelectedTab)) { @@ -661,11 +661,12 @@ void TabWidget::detachTab(int index) { WebTab* tab = weTab(index); - if (tab->isPinned() || count() == 1) { + if (count() < 2) { return; } detachTab(tab); + tab->setPinned(false); BrowserWindow* window = mApp->createWindow(Qz::BW_NewWindow); window->setStartTab(tab);