mirror of
https://invent.kde.org/network/falkon.git
synced 2024-11-13 10:32:11 +01:00
Add support for Drag (on) and Drop (off) the bookmark toolbar
Differential Revision: https://phabricator.kde.org/D11664
This commit is contained in:
parent
b1dc68d09e
commit
fb95cc81d6
|
@ -349,3 +349,33 @@ void BookmarksFilterModel::startFiltering()
|
||||||
{
|
{
|
||||||
QSortFilterProxyModel::setFilterFixedString(m_pattern);
|
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");
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QMimeData>
|
||||||
|
|
||||||
#include "qzcommon.h"
|
#include "qzcommon.h"
|
||||||
|
|
||||||
|
@ -99,4 +100,23 @@ private:
|
||||||
QTimer* m_filterTimer;
|
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
|
#endif // BOOKMARKSMODEL_H
|
||||||
|
|
|
@ -18,10 +18,12 @@
|
||||||
#include "bookmarkstoolbar.h"
|
#include "bookmarkstoolbar.h"
|
||||||
#include "bookmarkstoolbarbutton.h"
|
#include "bookmarkstoolbarbutton.h"
|
||||||
#include "bookmarkstools.h"
|
#include "bookmarkstools.h"
|
||||||
|
#include "bookmarksmodel.h"
|
||||||
#include "bookmarkitem.h"
|
#include "bookmarkitem.h"
|
||||||
#include "bookmarks.h"
|
#include "bookmarks.h"
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
#include "iconprovider.h"
|
#include "iconprovider.h"
|
||||||
|
#include "qztools.h"
|
||||||
|
|
||||||
#include <QDragEnterEvent>
|
#include <QDragEnterEvent>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
@ -34,6 +36,7 @@ BookmarksToolbar::BookmarksToolbar(BrowserWindow* window, QWidget* parent)
|
||||||
, m_window(window)
|
, m_window(window)
|
||||||
, m_bookmarks(mApp->bookmarks())
|
, m_bookmarks(mApp->bookmarks())
|
||||||
, m_clickedBookmark(0)
|
, m_clickedBookmark(0)
|
||||||
|
, m_dropRow(-1)
|
||||||
{
|
{
|
||||||
setObjectName("bookmarksbar");
|
setObjectName("bookmarksbar");
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
|
@ -226,36 +229,104 @@ QSize BookmarksToolbar::minimumSizeHint() const
|
||||||
|
|
||||||
void BookmarksToolbar::dropEvent(QDropEvent* e)
|
void BookmarksToolbar::dropEvent(QDropEvent* e)
|
||||||
{
|
{
|
||||||
|
int row = m_dropRow;
|
||||||
|
clearDropIndicator();
|
||||||
|
|
||||||
const QMimeData* mime = e->mimeData();
|
const QMimeData* mime = e->mimeData();
|
||||||
|
|
||||||
if (!mime->hasUrls()) {
|
if (!mime->hasUrls() && !mime->hasFormat(BookmarksButtonMimeData::mimeType())) {
|
||||||
QWidget::dropEvent(e);
|
QWidget::dropEvent(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl url = mime->urls().at(0);
|
|
||||||
QString title = mime->hasText() ? mime->text() : url.toEncoded(QUrl::RemoveScheme);
|
|
||||||
|
|
||||||
BookmarkItem* parent = m_bookmarks->toolbarFolder();
|
BookmarkItem* parent = m_bookmarks->toolbarFolder();
|
||||||
BookmarksToolbarButton* button = buttonAt(e->pos());
|
BookmarkItem* bookmark = nullptr;
|
||||||
if (button && button->bookmark()->isFolder()) {
|
|
||||||
parent = button->bookmark();
|
|
||||||
}
|
|
||||||
|
|
||||||
BookmarkItem* bookmark = new BookmarkItem(BookmarkItem::Url);
|
if (mime->hasFormat(BookmarksButtonMimeData::mimeType())) {
|
||||||
|
const BookmarksButtonMimeData* bookmarkMime = static_cast<const BookmarksButtonMimeData*>(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->setTitle(title);
|
||||||
bookmark->setUrl(url);
|
bookmark->setUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row >= 0) {
|
||||||
|
m_bookmarks->insertBookmark(parent, row, bookmark);
|
||||||
|
} else {
|
||||||
m_bookmarks->addBookmark(parent, bookmark);
|
m_bookmarks->addBookmark(parent, bookmark);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BookmarksToolbar::dragEnterEvent(QDragEnterEvent* e)
|
void BookmarksToolbar::dragEnterEvent(QDragEnterEvent* e)
|
||||||
{
|
{
|
||||||
const QMimeData* mime = e->mimeData();
|
const QMimeData* mime = e->mimeData();
|
||||||
|
|
||||||
if (mime->hasUrls() && mime->hasText()) {
|
if ((mime->hasUrls() && mime->hasText()) || mime->hasFormat(BookmarksButtonMimeData::mimeType())) {
|
||||||
e->acceptProposedAction();
|
e->acceptProposedAction();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget::dragEnterEvent(e);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -59,6 +59,9 @@ private:
|
||||||
|
|
||||||
void dropEvent(QDropEvent* e);
|
void dropEvent(QDropEvent* e);
|
||||||
void dragEnterEvent(QDragEnterEvent* e);
|
void dragEnterEvent(QDragEnterEvent* e);
|
||||||
|
void dragMoveEvent(QDragMoveEvent* e);
|
||||||
|
void dragLeaveEvent(QDragLeaveEvent* e);
|
||||||
|
void paintEvent(QPaintEvent* p);
|
||||||
|
|
||||||
BrowserWindow* m_window;
|
BrowserWindow* m_window;
|
||||||
Bookmarks* m_bookmarks;
|
Bookmarks* m_bookmarks;
|
||||||
|
@ -67,6 +70,10 @@ private:
|
||||||
QTimer* m_updateTimer;
|
QTimer* m_updateTimer;
|
||||||
QAction* m_actShowOnlyIcons = nullptr;
|
QAction* m_actShowOnlyIcons = nullptr;
|
||||||
QAction* m_actShowOnlyText = nullptr;
|
QAction* m_actShowOnlyText = nullptr;
|
||||||
|
|
||||||
|
int m_dropRow;
|
||||||
|
QPoint m_dropPos;
|
||||||
|
void clearDropIndicator();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BOOKMARKSTOOLBAR_H
|
#endif // BOOKMARKSTOOLBAR_H
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
#include "bookmarkstoolbarbutton.h"
|
#include "bookmarkstoolbarbutton.h"
|
||||||
#include "bookmarkstools.h"
|
#include "bookmarkstools.h"
|
||||||
|
#include "bookmarksmodel.h"
|
||||||
#include "bookmarkitem.h"
|
#include "bookmarkitem.h"
|
||||||
#include "bookmarks.h"
|
#include "bookmarks.h"
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
|
@ -26,6 +27,8 @@
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QStyleOptionButton>
|
#include <QStyleOptionButton>
|
||||||
|
#include <QDrag>
|
||||||
|
#include <QMimeData>
|
||||||
|
|
||||||
#define MAX_WIDTH 150
|
#define MAX_WIDTH 150
|
||||||
#define SEPARATOR_WIDTH 8
|
#define SEPARATOR_WIDTH 8
|
||||||
|
@ -38,6 +41,10 @@ BookmarksToolbarButton::BookmarksToolbarButton(BookmarkItem* bookmark, QWidget*
|
||||||
, m_showOnlyIcon(false)
|
, m_showOnlyIcon(false)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
|
if (m_bookmark->isFolder()) {
|
||||||
|
setAcceptDrops(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BookmarkItem* BookmarksToolbarButton::bookmark() const
|
BookmarkItem* BookmarksToolbarButton::bookmark() const
|
||||||
|
@ -266,6 +273,8 @@ void BookmarksToolbarButton::mousePressEvent(QMouseEvent* event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_dragStartPosition = event->pos();
|
||||||
|
|
||||||
QPushButton::mousePressEvent(event);
|
QPushButton::mousePressEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,6 +303,23 @@ void BookmarksToolbarButton::mouseReleaseEvent(QMouseEvent* event)
|
||||||
QPushButton::mouseReleaseEvent(event);
|
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)
|
void BookmarksToolbarButton::paintEvent(QPaintEvent* event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event)
|
Q_UNUSED(event)
|
||||||
|
@ -362,3 +388,48 @@ void BookmarksToolbarButton::paintEvent(QPaintEvent* event)
|
||||||
Qt::TextSingleLine | Qt::AlignCenter, option.palette, true, txt);
|
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<const BookmarksButtonMimeData*>(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);
|
||||||
|
}
|
||||||
|
|
|
@ -67,13 +67,19 @@ private:
|
||||||
void leaveEvent(QEvent* event) override;
|
void leaveEvent(QEvent* event) override;
|
||||||
void mousePressEvent(QMouseEvent* event) override;
|
void mousePressEvent(QMouseEvent* event) override;
|
||||||
void mouseReleaseEvent(QMouseEvent* event) override;
|
void mouseReleaseEvent(QMouseEvent* event) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent *event) override;
|
||||||
void paintEvent(QPaintEvent* 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;
|
BookmarkItem* m_bookmark;
|
||||||
BrowserWindow* m_window;
|
BrowserWindow* m_window;
|
||||||
|
|
||||||
bool m_showOnlyIcon;
|
bool m_showOnlyIcon;
|
||||||
bool m_showOnlyText;
|
bool m_showOnlyText;
|
||||||
|
QPoint m_dragStartPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BOOKMARKSTOOLBARBUTTON_H
|
#endif // BOOKMARKSTOOLBARBUTTON_H
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "mainapplication.h"
|
#include "mainapplication.h"
|
||||||
#include "proxystyle.h"
|
#include "proxystyle.h"
|
||||||
#include "qzsettings.h"
|
#include "qzsettings.h"
|
||||||
|
#include "qztools.h"
|
||||||
|
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
|
@ -1379,19 +1380,7 @@ void TabBarHelper::paintEvent(QPaintEvent *)
|
||||||
const int rightOffset = m_dropIndicatorIndex == count() - 1 ? -2 : 0;
|
const int rightOffset = m_dropIndicatorIndex == count() - 1 ? -2 : 0;
|
||||||
r = QRect(tr.right() + rightOffset, tr.top(), 3, tr.height());
|
r = QRect(tr.right() + rightOffset, tr.top(), 3, tr.height());
|
||||||
}
|
}
|
||||||
// Modified code from KFilePlacesView
|
QzTools::paintDropIndicator(this, r);
|
||||||
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());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1001,3 +1001,20 @@ QString QzTools::operatingSystemLong()
|
||||||
return QzTools::operatingSystem() + QSL(" ") + arch;
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#define QZTOOLS_H
|
#define QZTOOLS_H
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QStylePainter>
|
||||||
|
|
||||||
#include "qzcommon.h"
|
#include "qzcommon.h"
|
||||||
|
|
||||||
|
@ -95,6 +96,8 @@ public:
|
||||||
{
|
{
|
||||||
return (index >= 0 && container.count() > index);
|
return (index >= 0 && container.count() > index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void paintDropIndicator(QWidget *widget, const QRect &r);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QZTOOLS_H
|
#endif // QZTOOLS_H
|
||||||
|
|
Loading…
Reference in New Issue
Block a user