mirror of
https://github.com/yann64/haikuports.git
synced 2026-03-19 01:46:00 +01:00
Advanced Docking System for Qt (ads), new recipe (#12805)
This commit is contained in:
80
dev-qt/ads/ads_qt6-4.4.0.recipe
Normal file
80
dev-qt/ads/ads_qt6-4.4.0.recipe
Normal file
@@ -0,0 +1,80 @@
|
||||
SUMMARY="Advanced Docking System for Qt"
|
||||
DESCRIPTION="Qt Advanced Docking System lets you create customizable layouts using a full \
|
||||
featured window docking system similar to what is found in many popular integrated development \
|
||||
environments (IDEs) such as Visual Studio."
|
||||
HOMEPAGE="https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System"
|
||||
COPYRIGHT="2014 Qt-Advanced-Docking-System authors"
|
||||
LICENSE="GNU LGPL v2.1"
|
||||
REVISION="1"
|
||||
SOURCE_URI="https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/archive/refs/tags/$portVersion.tar.gz"
|
||||
CHECKSUM_SHA256="ccd0aa64e5bcfdb58b7ad4dda06b656b90571cfc94cb556dafac4b283ac1bb55"
|
||||
SOURCE_DIR="Qt-Advanced-Docking-System-$portVersion"
|
||||
PATCHES="ads_qt6-$portVersion.patchset"
|
||||
|
||||
ARCHITECTURES="all !x86_gcc2"
|
||||
SECONDARY_ARCHITECTURES="x86"
|
||||
|
||||
libVersion="$portVersion"
|
||||
libVersionCompat="$libVersion compat >= ${libVersion%%.*}"
|
||||
|
||||
PROVIDES="
|
||||
ads_qt6$secondaryArchSuffix = $portVersion
|
||||
lib:libqtadvanceddocking_qt6$secondaryArchSuffix = $libVersionCompat
|
||||
"
|
||||
REQUIRES="
|
||||
haiku$secondaryArchSuffix
|
||||
lib:libGL$secondaryArchSuffix
|
||||
lib:libQt6Core$secondaryArchSuffix
|
||||
lib:libQt6Gui$secondaryArchSuffix
|
||||
lib:libQt6Widgets$secondaryArchSuffix
|
||||
"
|
||||
|
||||
PROVIDES_devel="
|
||||
ads_qt6${secondaryArchSuffix}_devel = $portVersion
|
||||
devel:libqtadvanceddocking_qt6$secondaryArchSuffix = $libVersionCompat
|
||||
"
|
||||
REQUIRES_devel="
|
||||
ads_qt6$secondaryArchSuffix == $portVersion base
|
||||
"
|
||||
|
||||
BUILD_REQUIRES="
|
||||
haiku${secondaryArchSuffix}_devel
|
||||
devel:libQt6Core$secondaryArchSuffix
|
||||
devel:libQt6Quick$secondaryArchSuffix
|
||||
"
|
||||
BUILD_PREREQUIRES="
|
||||
cmd:cmake
|
||||
cmd:gcc$secondaryArchSuffix
|
||||
cmd:ninja
|
||||
cmd:pkg_config$secondaryArchSuffix
|
||||
"
|
||||
|
||||
BUILD()
|
||||
{
|
||||
cmake -B build -S . -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
$cmakeDirArgs \
|
||||
-DADS_VERSION=$portVersion \
|
||||
-Wno-dev
|
||||
|
||||
ninja -v -C build $jobArgs
|
||||
}
|
||||
|
||||
INSTALL()
|
||||
{
|
||||
ninja -C build install
|
||||
|
||||
rm -rf $prefix/license
|
||||
|
||||
prepareInstalledDevelLib \
|
||||
libqtadvanceddocking-qt6
|
||||
|
||||
packageEntries devel \
|
||||
$developDir \
|
||||
$libDir/cmake
|
||||
}
|
||||
|
||||
TEST()
|
||||
{
|
||||
ctest --test-dir build --output-on-failure
|
||||
}
|
||||
325
dev-qt/ads/patches/ads_qt6-4.4.0.patchset
Normal file
325
dev-qt/ads/patches/ads_qt6-4.4.0.patchset
Normal file
@@ -0,0 +1,325 @@
|
||||
From 377503fb1e8d89cdd0df0db40efdbd746e12afbe Mon Sep 17 00:00:00 2001
|
||||
From: Luc Schrijvers <begasus@gmail.com>
|
||||
Date: Tue, 19 Aug 2025 16:01:48 +0200
|
||||
Subject: Disable xcb + fixes
|
||||
|
||||
|
||||
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
|
||||
index dbe3b7a..44b0280 100644
|
||||
--- a/src/CMakeLists.txt
|
||||
+++ b/src/CMakeLists.txt
|
||||
@@ -66,7 +66,7 @@ set(ads_HEADERS
|
||||
ResizeHandle.h
|
||||
)
|
||||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
|
||||
-if (UNIX AND NOT APPLE)
|
||||
+if (UNIX AND NOT APPLE AND NOT HAIKU)
|
||||
set(ads_SRCS linux/FloatingWidgetTitleBar.cpp ${ads_SRCS})
|
||||
set(ads_HEADERS linux/FloatingWidgetTitleBar.h ${ads_HEADERS})
|
||||
endif()
|
||||
@@ -85,7 +85,7 @@ add_library(ads::${library_name} ALIAS ${library_name})
|
||||
target_link_libraries(${library_name} PUBLIC Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Gui
|
||||
Qt${QT_VERSION_MAJOR}::Widgets)
|
||||
-if (UNIX AND NOT APPLE)
|
||||
+if (UNIX AND NOT APPLE AND NOT HAIKU)
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
find_package(X11 REQUIRED)
|
||||
target_link_libraries(${library_name} PUBLIC X11::xcb)
|
||||
diff --git a/src/DockFocusController.cpp b/src/DockFocusController.cpp
|
||||
index 27acc4a..b7a0539 100644
|
||||
--- a/src/DockFocusController.cpp
|
||||
+++ b/src/DockFocusController.cpp
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "DockManager.h"
|
||||
#include "DockAreaTitleBar.h"
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
#include "linux/FloatingWidgetTitleBar.h"
|
||||
#endif
|
||||
|
||||
@@ -44,7 +44,7 @@ struct DockFocusControllerPrivate
|
||||
QPointer<CDockWidget> FocusedDockWidget = nullptr;
|
||||
QPointer<CDockAreaWidget> FocusedArea = nullptr;
|
||||
QPointer<CDockWidget> OldFocusedDockWidget = nullptr;
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
QPointer<CFloatingDockContainer> FloatingWidget = nullptr;
|
||||
#endif
|
||||
CDockManager* DockManager;
|
||||
@@ -85,7 +85,7 @@ static void updateDockAreaFocusStyle(CDockAreaWidget* DockArea, bool Focused)
|
||||
|
||||
|
||||
//===========================================================================
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
static void updateFloatingWidgetFocusStyle(CFloatingDockContainer* FloatingWidget, bool Focused)
|
||||
{
|
||||
if (FloatingWidget->hasNativeTitleBar())
|
||||
@@ -170,7 +170,7 @@ void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget)
|
||||
}
|
||||
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
// This code is required for styling the floating widget titlebar for linux
|
||||
// depending on the current focus state
|
||||
if (FloatingWidget != NewFloatingWidget)
|
||||
@@ -289,7 +289,7 @@ void CDockFocusController::onApplicationFocusChanged(QWidget* focusedOld, QWidge
|
||||
DockWidget = internal::findParent<CDockWidget*>(focusedNow);
|
||||
}
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
if (!DockWidget)
|
||||
{
|
||||
return;
|
||||
diff --git a/src/DockManager.cpp b/src/DockManager.cpp
|
||||
index 99b432c..bb86a96 100644
|
||||
--- a/src/DockManager.cpp
|
||||
+++ b/src/DockManager.cpp
|
||||
@@ -63,7 +63,7 @@
|
||||
#include "DockComponentsFactory.h"
|
||||
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
#include "linux/FloatingWidgetTitleBar.h"
|
||||
#endif
|
||||
|
||||
@@ -207,7 +207,7 @@ void DockManagerPrivate::loadStylesheet()
|
||||
QString FileName = ":ads/stylesheets/";
|
||||
FileName += CDockManager::testConfigFlag(CDockManager::FocusHighlighting)
|
||||
? "focus_highlighting" : "default";
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
FileName += "_linux";
|
||||
#endif
|
||||
FileName += ".css";
|
||||
@@ -529,7 +529,7 @@ CDockManager::CDockManager(QWidget *parent) :
|
||||
|
||||
window()->installEventFilter(this);
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
connect(qApp, &QApplication::focusWindowChanged, [](QWindow* focusWindow)
|
||||
{
|
||||
// bring modal dialogs to foreground to ensure that they are in front of any
|
||||
@@ -614,7 +614,7 @@ void CDockManager::setComponentsFactory(QSharedPointer<ads::CDockComponentsFacto
|
||||
|
||||
|
||||
//============================================================================
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
bool CDockManager::eventFilter(QObject *obj, QEvent *e)
|
||||
{
|
||||
// Emulate Qt:Tool behaviour.
|
||||
diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp
|
||||
index 81a80fb..5aed9b9 100644
|
||||
--- a/src/FloatingDockContainer.cpp
|
||||
+++ b/src/FloatingDockContainer.cpp
|
||||
@@ -52,7 +52,7 @@
|
||||
#pragma comment(lib, "User32.lib")
|
||||
#endif
|
||||
#endif
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
#include "linux/FloatingWidgetTitleBar.h"
|
||||
#include <xcb/xcb.h>
|
||||
#endif
|
||||
@@ -374,7 +374,7 @@ struct FloatingDockContainerPrivate
|
||||
QPoint DragStartPos;
|
||||
bool Hiding = false;
|
||||
bool AutoHideChildren = true;
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
QWidget* MouseEventHandler = nullptr;
|
||||
CFloatingWidgetTitleBar* TitleBar = nullptr;
|
||||
bool IsResizing = false;
|
||||
@@ -425,7 +425,7 @@ struct FloatingDockContainerPrivate
|
||||
|
||||
void setWindowTitle(const QString &Text)
|
||||
{
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
if (TitleBar)
|
||||
{
|
||||
TitleBar->setTitle(Text);
|
||||
@@ -545,7 +545,7 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
|
||||
return;
|
||||
}
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
// Prevent display of drop overlays and docking as long as a model dialog
|
||||
// is active
|
||||
if (qApp->activeModalWidget())
|
||||
@@ -660,7 +660,7 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
|
||||
connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this,
|
||||
SLOT(onDockAreasAddedOrRemoved()));
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
QDockWidget::setWidget(d->DockContainer);
|
||||
QDockWidget::setFeatures(QDockWidget::DockWidgetClosable
|
||||
| QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
|
||||
@@ -820,7 +820,7 @@ void CFloatingDockContainer::changeEvent(QEvent *event)
|
||||
ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange ");
|
||||
d->zOrderIndex = ++zOrderCounterFloating;
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
if (d->DraggingState == DraggingFloatingWidget)
|
||||
{
|
||||
d->titleMouseReleaseEvent();
|
||||
@@ -994,7 +994,7 @@ void CFloatingDockContainer::hideEvent(QHideEvent *event)
|
||||
void CFloatingDockContainer::showEvent(QShowEvent *event)
|
||||
{
|
||||
Super::showEvent(event);
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
|
||||
{
|
||||
this->window()->activateWindow();
|
||||
@@ -1007,7 +1007,7 @@ void CFloatingDockContainer::showEvent(QShowEvent *event)
|
||||
void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos,
|
||||
const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)
|
||||
{
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
if (!isMaximized())
|
||||
{
|
||||
resize(Size);
|
||||
@@ -1054,7 +1054,7 @@ void CFloatingDockContainer::moveFloating()
|
||||
|
||||
case DraggingFloatingWidget:
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
-#ifdef Q_OS_MACOS
|
||||
+#if defined(Q_OS_MACOS)
|
||||
// In OSX when hiding the DockAreaOverlay the application would set
|
||||
// the main window as the active window for some reason. This fixes
|
||||
// that by resetting the active window to the floating widget after
|
||||
@@ -1144,7 +1144,7 @@ bool CFloatingDockContainer::restoreState(CDockingStateReader &Stream,
|
||||
return false;
|
||||
}
|
||||
onDockAreasAddedOrRemoved();
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
if(d->TitleBar)
|
||||
{
|
||||
d->TitleBar->setMaximizedIcon(windowState() == Qt::WindowMaximized);
|
||||
@@ -1198,7 +1198,7 @@ void CFloatingDockContainer::finishDropOperation()
|
||||
void CFloatingDockContainer::finishDragging()
|
||||
{
|
||||
ADS_PRINT("CFloatingDockContainer::finishDragging");
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
setWindowOpacity(1);
|
||||
activateWindow();
|
||||
if (d->MouseEventHandler)
|
||||
@@ -1210,7 +1210,7 @@ void CFloatingDockContainer::finishDragging()
|
||||
d->titleMouseReleaseEvent();
|
||||
}
|
||||
|
||||
-#ifdef Q_OS_MACOS
|
||||
+#if defined(Q_OS_MACOS) || defined(Q_OS_HAIKU)
|
||||
//============================================================================
|
||||
bool CFloatingDockContainer::event(QEvent *e)
|
||||
{
|
||||
@@ -1313,7 +1313,7 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event)
|
||||
#endif
|
||||
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
//============================================================================
|
||||
void CFloatingDockContainer::onMaximizeRequest()
|
||||
{
|
||||
diff --git a/src/FloatingDockContainer.h b/src/FloatingDockContainer.h
|
||||
index 2dd9d49..add1f0d 100644
|
||||
--- a/src/FloatingDockContainer.h
|
||||
+++ b/src/FloatingDockContainer.h
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include <QRubberBand>
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
#include <QDockWidget>
|
||||
#define tFloatingWidgetBase QDockWidget
|
||||
#else
|
||||
@@ -178,7 +178,7 @@ protected: // reimplements QWidget
|
||||
virtual void hideEvent(QHideEvent *event) override;
|
||||
virtual void showEvent(QShowEvent *event) override;
|
||||
|
||||
-#ifdef Q_OS_MACOS
|
||||
+#if defined(Q_OS_MACOS) || defined(Q_OS_HAIKU)
|
||||
virtual bool event(QEvent *e) override;
|
||||
virtual void moveEvent(QMoveEvent *event) override;
|
||||
#elif defined(Q_OS_UNIX)
|
||||
@@ -269,7 +269,7 @@ public:
|
||||
*/
|
||||
void finishDropOperation();
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
/**
|
||||
* This is a function that responds to FloatingWidgetTitleBar::maximizeRequest()
|
||||
* Maximize or normalize the container size.
|
||||
diff --git a/src/ads_globals.cpp b/src/ads_globals.cpp
|
||||
index b019318..0420f0f 100644
|
||||
--- a/src/ads_globals.cpp
|
||||
+++ b/src/ads_globals.cpp
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "IconProvider.h"
|
||||
#include "ads_globals.h"
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
#include <QSettings>
|
||||
#include <QFile>
|
||||
#include <QApplication>
|
||||
@@ -52,7 +52,7 @@ namespace internal
|
||||
{
|
||||
const int FloatingWidgetDragStartEvent = QEvent::registerEventType();
|
||||
const int DockedWidgetDragStartEvent = QEvent::registerEventType();
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
static QString _window_manager;
|
||||
static QHash<QString, xcb_atom_t> _xcb_atom_cache;
|
||||
|
||||
@@ -412,7 +412,7 @@ void setButtonIcon(QAbstractButton* Button, QStyle::StandardPixmap StandarPixmap
|
||||
return;
|
||||
}
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
Button->setIcon(Button->style()->standardIcon(StandarPixmap));
|
||||
#else
|
||||
// The standard icons does not look good on high DPI screens so we create
|
||||
diff --git a/src/ads_globals.h b/src/ads_globals.h
|
||||
index f7ccc8e..ddede0a 100644
|
||||
--- a/src/ads_globals.h
|
||||
+++ b/src/ads_globals.h
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
#include <xcb/xcb.h>
|
||||
#endif
|
||||
|
||||
@@ -171,7 +171,7 @@ static const char* const LocationProperty = "Location";
|
||||
extern const int FloatingWidgetDragStartEvent;
|
||||
extern const int DockedWidgetDragStartEvent;
|
||||
|
||||
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS) && !defined(Q_OS_HAIKU)
|
||||
// Utils to directly communicate with the X server
|
||||
/**
|
||||
* Get atom from cache or request it from the XServer.
|
||||
--
|
||||
2.50.1
|
||||
|
||||
Reference in New Issue
Block a user