From 4f3b163b3430b3bb99fe7db94d95fa106f8223bb Mon Sep 17 00:00:00 2001
From: shibakaneki <didier@sente.ch>
Date: Mon, 15 Aug 2011 11:10:24 +0200
Subject: [PATCH] Implemented the desktop mode for Linux

---
 src/board/UBBoardView.cpp                     | 1758 ++++++++---------
 src/desktop/UBDesktopAnnotationController.cpp |  107 +-
 src/desktop/UBDesktopAnnotationController.h   |    4 +
 src/desktop/UBDesktopPalette.cpp              |    9 +-
 src/desktop/UBDesktopPalette.h                |    1 +
 src/domain/UBGraphicsScene.cpp                |    4 +-
 src/gui/UBFloatingPalette.cpp                 |    1 +
 src/gui/UBFloatingPalette.h                   |    1 +
 src/gui/UBLibPalette.cpp                      |    3 +-
 src/gui/UBLibPalette.h                        |    3 +
 10 files changed, 1005 insertions(+), 886 deletions(-)

diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp
index 295858c7..7e9a256b 100644
--- a/src/board/UBBoardView.cpp
+++ b/src/board/UBBoardView.cpp
@@ -13,882 +13,882 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-
-#include "UBBoardView.h"
-
-#include <QtGui>
-
-#include "UBDrawingController.h"
-
-#include "frameworks/UBGeometryUtils.h"
-
-#include "core/UBSettings.h"
-#include "core/UBMimeData.h"
-#include "core/UBApplication.h"
-#include "core/UBSetting.h"
-#include "core/UBPersistenceManager.h"
-
-#include "network/UBHttpGet.h"
-
-#include "gui/UBStylusPalette.h"
-#include "gui/UBRubberBand.h"
-#include "gui/UBToolWidget.h"
-#include "gui/UBResources.h"
-#include "gui/UBMainWindow.h"
-
-#include "board/UBBoardController.h"
-
-#include "domain/UBGraphicsTextItem.h"
-#include "domain/UBGraphicsPixmapItem.h"
-#include "domain/UBGraphicsWidgetItem.h"
-#include "domain/UBItem.h"
-
-#include "document/UBDocumentProxy.h"
-#include "../gui/UBThumbnailWidget.h"
-
-#include "frameworks/UBPlatformUtils.h"
-
-#include "core/memcheck.h"
-
-UBBoardView::UBBoardView (UBBoardController* pController, QWidget* pParent)
-: QGraphicsView (pParent)
-, mController (pController)
-, mIsCreatingTextZone (false)
-, mIsCreatingSceneGrabZone (false)
-{
-  init ();
-
-  mFilterZIndex = false;
-}
-
-UBBoardView::UBBoardView (UBBoardController* pController, int pStartLayer, int pEndLayer, QWidget* pParent)
-: QGraphicsView (pParent)
-, mController (pController)
-{
-  init ();
-
-  mStartLayer = pStartLayer;
-  mEndLayer = pEndLayer;
-
-  mFilterZIndex = true;
-}
-
-UBBoardView::~UBBoardView () {
-  //NOOP
-}
-
-void
-UBBoardView::init ()
-{
-  connect (UBSettings::settings ()->boardPenPressureSensitive, SIGNAL (changed (QVariant)),
-           this, SLOT (settingChanged (QVariant)));
-
-  connect (UBSettings::settings ()->boardMarkerPressureSensitive, SIGNAL (changed (QVariant)),
-           this, SLOT (settingChanged (QVariant)));
-
-  connect (UBSettings::settings ()->boardUseHighResTabletEvent, SIGNAL (changed (QVariant)),
-           this, SLOT (settingChanged (QVariant)));
-
-  setWindowFlags (Qt::FramelessWindowHint);
-  setFrameStyle (QFrame::NoFrame);
-  setRenderHints (QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);
-  setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
-  setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
-  setAcceptDrops (true);
-
-  setOptimizationFlag (QGraphicsView::IndirectPainting); // enable UBBoardView::drawItems filter
-
-  mTabletStylusIsPressed = false;
-  mMouseButtonIsPressed = false;
-  mPendingStylusReleaseEvent = false;
-
-  setCacheMode (QGraphicsView::CacheBackground);
-
-  mUsingTabletEraser = false;
-  mIsCreatingTextZone = false;
-  mRubberBand = 0;
-
-  mVirtualKeyboardActive = false;
-
-  settingChanged (QVariant ());
-
-  unsetCursor();
-}
-
-UBGraphicsScene*
-UBBoardView::scene ()
-{
-  return qobject_cast<UBGraphicsScene*> (QGraphicsView::scene ());
-}
-
-void
-UBBoardView::hideEvent (QHideEvent * event)
-{
-  Q_UNUSED (event);
-  emit hidden ();
-}
-
-void
-UBBoardView::showEvent (QShowEvent * event)
-{
-  Q_UNUSED (event);
-  emit shown ();
-}
-
-void
-UBBoardView::keyPressEvent (QKeyEvent *event)
-{
-  // send to the scene anyway
-  QApplication::sendEvent (scene (), event);
-
-  if (!event->isAccepted ())
-    {
-      switch (event->key ())
-        {
-        case Qt::Key_Up:
-        case Qt::Key_PageUp:
-        case Qt::Key_Left:
-          {
-            mController->previousScene ();
-            break;
-          }
-
-        case Qt::Key_Down:
-        case Qt::Key_PageDown:
-        case Qt::Key_Right:
-        case Qt::Key_Space:
-          {
-            mController->nextScene ();
-            break;
-          }
-
-        case Qt::Key_Home:
-          {
-            mController->firstScene ();
-            break;
-          }
-        case Qt::Key_End:
-          {
-            mController->lastScene ();
-            break;
-          }
-        case Qt::Key_Insert:
-          {
-            mController->addScene ();
-            break;
-          }
-        }
-
-
-      if (event->modifiers () & Qt::ControlModifier) // keep only ctrl/cmd keys
-        {
-          switch (event->key ())
-            {
-            case Qt::Key_Plus:
-            case Qt::Key_I:
-              {
-                mController->zoomIn ();
-                event->accept ();
-                break;
-              }
-            case Qt::Key_Minus:
-            case Qt::Key_O:
-              {
-                mController->zoomOut ();
-                event->accept ();
-                break;
-              }
-            case Qt::Key_0:
-              {
-                mController->zoomRestore ();
-                event->accept ();
-                break;
-              }
-            case Qt::Key_Left:
-              {
-                mController->handScroll (-100, 0);
-                event->accept ();
-                break;
-              }
-            case Qt::Key_Right:
-              {
-                mController->handScroll (100, 0);
-                event->accept ();
-                break;
-              }
-            case Qt::Key_Up:
-              {
-                mController->handScroll (0, -100);
-                event->accept ();
-                break;
-              }
-            case Qt::Key_Down:
-              {
-                mController->handScroll (0, 100);
-                event->accept ();
-                break;
-              }
-            default:
-              {
-                // NOOP
-              }
-            }
-        }
-    }
-}
-
-bool
-UBBoardView::event (QEvent * e)
-{
-  if (e->type () == QEvent::Gesture)
-    {
-      QGestureEvent *gestureEvent = dynamic_cast<QGestureEvent *> (e);
-      if (gestureEvent)
-        {
-          QSwipeGesture* swipe = dynamic_cast<QSwipeGesture*> (gestureEvent->gesture (Qt::SwipeGesture));
-
-          if (swipe)
-            {
-              if (swipe->horizontalDirection () == QSwipeGesture::Left)
-                {
-                  mController->previousScene ();
-                  gestureEvent->setAccepted (swipe, true);
-                }
-
-              if (swipe->horizontalDirection () == QSwipeGesture::Right)
-                {
-                  mController->nextScene ();
-                  gestureEvent->setAccepted (swipe, true);
-                }
-            }
-        }
-    }
-
-  return QGraphicsView::event (e);
-}
-
-void
-UBBoardView::tabletEvent (QTabletEvent * event)
-{
-  if (!mUseHighResTabletEvent)
-    {
-      event->setAccepted (false);
-      return;
-    }
-
-  UBDrawingController *dc = UBDrawingController::drawingController ();
-
-  QPointF tabletPos = UBGeometryUtils::pointConstrainedInRect (event->hiResGlobalPos ()
-                                                               - mapToGlobal (QPoint (0, 0)), rect ());
-
-  UBStylusTool::Enum currentTool = (UBStylusTool::Enum)dc->stylusTool ();
-
-  if (event->type () == QEvent::TabletPress || event->type () == QEvent::TabletEnterProximity)
-    {
-      if (event->pointerType () == QTabletEvent::Eraser)
-        {
-          dc->setStylusTool (UBStylusTool::Eraser);
-          mUsingTabletEraser = true;
-        }
-      else
-        {
-          if (mUsingTabletEraser && currentTool == UBStylusTool::Eraser)
-            {
-              dc->setStylusTool (dc->latestDrawingTool ());
-            }
-
-          mUsingTabletEraser = false;
-        }
-    }
-
-  // if event are not Pen events, we drop the tablet stuff and route everything through mouse event
-  if (currentTool != UBStylusTool::Pen
-      && currentTool != UBStylusTool::Line
-      && currentTool != UBStylusTool::Marker
-      && !mMarkerPressureSensitive)
-    {
-      event->setAccepted (false);
-      return;
-    }
-
-  QPointF scenePos = viewportTransform ().inverted ().map (tabletPos);
-
-  qreal pressure = 1.0;
-  if (((currentTool == UBStylusTool::Pen || currentTool == UBStylusTool::Line)
-       && mPenPressureSensitive)
-      || (currentTool == UBStylusTool::Marker && mMarkerPressureSensitive))
-    {
-      pressure = event->pressure ();
-    }
-
-  bool acceptEvent = true;
-
-  switch (event->type ())
-    {
-    case QEvent::TabletPress:
-      {
-        mTabletStylusIsPressed = true;
-
-        scene ()->inputDevicePress (scenePos, pressure);
-
-        break;
-      }
-    case QEvent::TabletMove:
-      {
-        if (mTabletStylusIsPressed)
-          {
-            scene ()->inputDeviceMove (scenePos, pressure);
-          }
-
-        acceptEvent = false; // rerouted to mouse move
-
-        break;
-
-      }
-    case QEvent::TabletRelease:
-      {
-        UBStylusTool::Enum currentTool = (UBStylusTool::Enum)dc->stylusTool ();
-        scene ()->setToolCursor (currentTool);
-        setToolCursor (currentTool);
-
-        scene ()->inputDeviceRelease ();
-
-        mPendingStylusReleaseEvent = false;
-
-        mTabletStylusIsPressed = false;
-        mMouseButtonIsPressed = false;
-
-        break;
-      }
-    default:
-      {
-        //NOOP - avoid compiler warning
-      }
-    }
-
-  // ignore mouse press and mouse move tablet event so that it is rerouted to mouse events,
-  // documented in QTabletEvent Class Reference:
-  /* The event handler QWidget::tabletEvent() receives all three types of tablet events.
-     Qt will first send a tabletEvent then, if it is not accepted, it will send a mouse event. */
-  //
-  // This is a workaround to the fact that tablet event are not delivered to child widget (like palettes)
-  //
-
-  event->setAccepted (acceptEvent);
-
-}
-
-void
-UBBoardView::mousePressEvent (QMouseEvent *event)
-{
-  if (isAbsurdPoint (event->pos ()))
-    {
-      event->accept ();
-      return;
-    }
-
-  mMouseDownPos = event->pos ();
-
-  if (event->button () == Qt::LeftButton && isInteractive ())
-    {
-      UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController ()->stylusTool ();
-
-      if (!mTabletStylusIsPressed)
-        mMouseButtonIsPressed = true;
-
-      if (currentTool == UBStylusTool::ZoomIn)
-        {
-          mController->zoomIn (mapToScene (event->pos ()));
-          event->accept ();
-        }
-      else if (currentTool == UBStylusTool::ZoomOut)
-        {
-          mController->zoomOut (mapToScene (event->pos ()));
-          event->accept ();
-        }
-      else if (currentTool == UBStylusTool::Hand)
-        {
-          viewport ()->setCursor (QCursor (Qt::ClosedHandCursor));
-          mPreviousPoint = event->posF ();
-          event->accept ();
-        }
-      else if (currentTool == UBStylusTool::Selector)
-        {
-          QGraphicsView::mousePressEvent (event);
-        }
-      else if (currentTool == UBStylusTool::Text)
-        {
-          int frameWidth = UBSettings::settings ()->objectFrameWidth;
-          QRectF fuzzyRect (0, 0, frameWidth * 4, frameWidth * 4);
-          fuzzyRect.moveCenter (mapToScene (mMouseDownPos));
-
-          UBGraphicsTextItem* foundTextItem = 0;
-          QListIterator<QGraphicsItem *> it (scene ()->items (fuzzyRect));
-
-          while (it.hasNext () && !foundTextItem)
-            {
-              foundTextItem = qgraphicsitem_cast<UBGraphicsTextItem*>(it.next ());
-            }
-
-          if (foundTextItem)
-            {
-              mIsCreatingTextZone = false;
-              QGraphicsView::mousePressEvent (event);
-            }
-          else
-            {
-              scene ()->deselectAllItems ();
-
-              if (!mRubberBand)
-                mRubberBand = new UBRubberBand (QRubberBand::Rectangle, this);
-
-              mRubberBand->setGeometry (QRect (mMouseDownPos, QSize ()));
-              mRubberBand->show ();
-              mIsCreatingTextZone = true;
-
-              event->accept ();
-            }
-        }
-      else if (currentTool == UBStylusTool::Capture)
-        {
-          scene ()->deselectAllItems ();
-
-          if (!mRubberBand)
-            mRubberBand = new UBRubberBand (QRubberBand::Rectangle, this);
-
-          mRubberBand->setGeometry (QRect (mMouseDownPos, QSize ()));
-          mRubberBand->show ();
-          mIsCreatingSceneGrabZone = true;
-
-          event->accept ();
-        }
-		else
-		{
-			if(UBDrawingController::drawingController()->mActiveRuler==NULL)
-			{
-				viewport()->setCursor (QCursor (Qt::BlankCursor));			
-			}
-
-			if (scene () && !mTabletStylusIsPressed)
-			{
-				scene ()->inputDevicePress (mapToScene (UBGeometryUtils::pointConstrainedInRect (event->pos (), rect ())));
-			}
-			event->accept ();
-        }
-    }
-}
-
-void
-UBBoardView::mouseMoveEvent (QMouseEvent *event)
-{
-  UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController ()->stylusTool ();
-
-  if (isAbsurdPoint (event->pos ()))
-    {
-      event->accept ();
-      return;
-    }
-
-  if (currentTool == UBStylusTool::Hand && (mMouseButtonIsPressed || mTabletStylusIsPressed))
-    {
-      QPointF eventPosition = event->posF ();
-      qreal dx = eventPosition.x () - mPreviousPoint.x ();
-      qreal dy = eventPosition.y () - mPreviousPoint.y ();
-      mController->handScroll (dx, dy);
-      mPreviousPoint = eventPosition;
-      event->accept ();
-    }
-  else if (currentTool == UBStylusTool::Selector)
-    {
-      QGraphicsView::mouseMoveEvent (event);
-    }
-  else if ((UBDrawingController::drawingController()->isDrawingTool())
-  	&& !mMouseButtonIsPressed)
-  {
-	  QGraphicsView::mouseMoveEvent (event);
-  }
-  else if (currentTool == UBStylusTool::Text || currentTool == UBStylusTool::Capture)
-    {
-      if (mRubberBand && (mIsCreatingTextZone || mIsCreatingSceneGrabZone))
-        {
-          mRubberBand->setGeometry (QRect (mMouseDownPos, event->pos ()).normalized ());
-          event->accept ();
-        }
-      else
-        {
-          QGraphicsView::mouseMoveEvent (event);
-        }
-    }
-  else
-    {
-      if (!mTabletStylusIsPressed && scene ())
-      {
-          scene ()->inputDeviceMove (mapToScene (UBGeometryUtils::pointConstrainedInRect (event->pos (), rect ())), mMouseButtonIsPressed);
-      }
-      event->accept ();
-    }
-}
-
-void
-UBBoardView::mouseReleaseEvent (QMouseEvent *event)
-{
-  UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController ()->stylusTool ();
-
-  scene ()->setToolCursor (currentTool);
-  setToolCursor (currentTool);
-
-  // first propagate device release to the scene
-  if (scene ())
-    scene ()->inputDeviceRelease ();
-
-  if (currentTool == UBStylusTool::Selector)
-    {
-      QGraphicsView::mouseReleaseEvent (event);
-    }
-  else if (currentTool == UBStylusTool::Text)
-    {
-      if (mRubberBand)
-        mRubberBand->hide ();
-
-      if (scene () && mRubberBand && mIsCreatingTextZone)
-        {
-          QRect rubberRect = mRubberBand->geometry ();
-
-          UBGraphicsTextItem* textItem = scene ()->addText ("", mapToScene (rubberRect.topLeft ()));
-          event->accept ();
-
-          UBDrawingController::drawingController ()->setStylusTool (UBStylusTool::Selector);
-
-          textItem->setSelected (true);
-        }
-      else
-        {
-          QGraphicsView::mouseReleaseEvent (event);
-        }
-
-      mIsCreatingTextZone = false;
-    }
-  else if (currentTool == UBStylusTool::Capture)
-    {
-      if (mRubberBand)
-        mRubberBand->hide ();
-
-      if (scene () && mRubberBand && mIsCreatingSceneGrabZone && mRubberBand->geometry ().width () > 16)
-        {
-          QRect rect = mRubberBand->geometry ();
-          QPointF sceneTopLeft = mapToScene (rect.topLeft ());
-          QPointF sceneBottomRight = mapToScene (rect.bottomRight ());
-          QRectF sceneRect (sceneTopLeft, sceneBottomRight);
-
-          mController->grabScene (sceneRect);
-
-          event->accept ();
-        }
-      else
-        {
-          QGraphicsView::mouseReleaseEvent (event);
-        }
-
-      mIsCreatingSceneGrabZone = false;
-    }
-  else
-    {
-      if (mPendingStylusReleaseEvent || mMouseButtonIsPressed)
-        {
-          event->accept ();
-        }
-    }
-
-  mMouseButtonIsPressed = false;
-  mPendingStylusReleaseEvent = false;
-  mTabletStylusIsPressed = false;
-
-}
-
-void
-UBBoardView::forcedTabletRelease ()
-{
-
-  if (mMouseButtonIsPressed || mTabletStylusIsPressed || mPendingStylusReleaseEvent)
-    {
-      qWarning () << "dirty mouse/tablet state:";
-      qWarning () << "mMouseButtonIsPressed =" << mMouseButtonIsPressed;
-      qWarning () << "mTabletStylusIsPressed = " << mTabletStylusIsPressed;
-      qWarning () << "mPendingStylusReleaseEvent" << mPendingStylusReleaseEvent;
-      qWarning () << "forcing device release";
-
-      scene ()->inputDeviceRelease ();
-
-      mMouseButtonIsPressed = false;
-      mTabletStylusIsPressed = false;
-      mPendingStylusReleaseEvent = false;
-
-    }
-}
-
-void
-UBBoardView::mouseDoubleClickEvent (QMouseEvent *event)
-{
-  // We don't want a double click, we want two clicks
-  mousePressEvent (event);
-}
-
-void
-UBBoardView::wheelEvent (QWheelEvent *event)
-{
-  if (isInteractive () && event->orientation () == Qt::Vertical)
-    {
-      // Too many wheelEvent are sent, how should we handle them to "smoothly" zoom ?
-      // something like zoom( pow(zoomFactor, event->delta() / 120) )
-    }
-  event->accept ();
-}
-
-void
-UBBoardView::leaveEvent (QEvent * event)
-{
-  if (scene ())
-    scene ()->leaveEvent (event);
-
-  QGraphicsView::leaveEvent (event);
-}
-
-void
-UBBoardView::drawItems (QPainter *painter, int numItems,
-                        QGraphicsItem* items[],
-                        const QStyleOptionGraphicsItem options[])
-{
-  if (!mFilterZIndex)
-    {
-      QGraphicsView::drawItems (painter, numItems, items, options);
-    }
-  else
-    {
-      int count = 0;
-
-      QGraphicsItem** itemsFiltered = new QGraphicsItem*[numItems];
-      QStyleOptionGraphicsItem *optionsFiltered = new QStyleOptionGraphicsItem[numItems];
-
-      for (int i = 0; i < numItems; i++)
-        {
-          if (shouldDisplayItem (items[i]))
-            {
-              itemsFiltered[count] = items[i];
-              optionsFiltered[count] = options[i];
-              count++;
-            }
-        }
-
-      QGraphicsView::drawItems (painter, count, itemsFiltered, optionsFiltered);
-
-      delete[] optionsFiltered;
-      delete[] itemsFiltered;
-    }
-}
-
-void
-UBBoardView::dragEnterEvent (QDragEnterEvent *event)
-{
-  // TODO UB 4.x be smarter with drag accept code .... we cannot handle everything ...
-  event->acceptProposedAction ();
-}
-
-void
-UBBoardView::dragMoveEvent (QDragMoveEvent *event)
-{
-  event->acceptProposedAction ();
-}
-
-void
-UBBoardView::dropEvent (QDropEvent *event)
-{
-  if(!event->source() || dynamic_cast<UBThumbnailWidget *>(event->source()))
-  {
-        mController->processMimeData (event->mimeData (), mapToScene (event->pos ()));
-        event->acceptProposedAction ();
-  }
-}
-
-void
-UBBoardView::resizeEvent (QResizeEvent * event)
-{
-  const qreal maxWidth = width () * 10;
-  const qreal maxHeight = height () * 10;
-
-  setSceneRect (-(maxWidth / 2), -(maxHeight / 2), maxWidth, maxHeight);
-  centerOn (0, 0);
-
-  emit resized (event);
-}
-
-void
-UBBoardView::drawBackground (QPainter *painter, const QRectF &rect)
-{
-  if (testAttribute (Qt::WA_TranslucentBackground))
-    {
-      QGraphicsView::drawBackground (painter, rect);
-      return;
-    }
-
-  bool darkBackground = scene () && scene ()->isDarkBackground ();
-
-  if (darkBackground)
-    {
-      painter->fillRect (rect, QBrush (QColor (Qt::black)));
-    }
-  else
-    {
-      painter->fillRect (rect, QBrush (QColor (Qt::white)));
-    }
-
-  if (transform ().m11 () > 0.5)
-    {
-      QColor bgCrossColor;
-
-      if (darkBackground)
-        bgCrossColor = UBSettings::crossDarkBackground;
-      else
-        bgCrossColor = UBSettings::crossLightBackground;
-
-      if (transform ().m11 () < 1.0)
-        {
-          int alpha = 255 * transform ().m11 () / 2;
-          bgCrossColor.setAlpha (alpha); // fade the crossing on small zooms
-        }
-
-      painter->setPen (bgCrossColor);
-
-      if (scene () && scene ()->isCrossedBackground ())
-        {
-          qreal firstY = ((int) (rect.y () / UBSettings::crossSize)) * UBSettings::crossSize;
-
-          for (qreal yPos = firstY; yPos < rect.y () + rect.height (); yPos += UBSettings::crossSize)
-            {
-              painter->drawLine (rect.x (), yPos, rect.x () + rect.width (), yPos);
-            }
-
-          qreal firstX = ((int) (rect.x () / UBSettings::crossSize)) * UBSettings::crossSize;
-
-          for (qreal xPos = firstX; xPos < rect.x () + rect.width (); xPos += UBSettings::crossSize)
-            {
-              painter->drawLine (xPos, rect.y (), xPos, rect.y () + rect.height ());
-            }
-        }
-    }
-
-  if (!mFilterZIndex && scene ())
-    {
-      QSize pageNominalSize = scene ()->nominalSize ();
-
-      if (pageNominalSize.isValid ())
-        {
-          qreal penWidth = 8.0 / transform ().m11 ();
-
-          QRectF pageRect (pageNominalSize.width () / -2, pageNominalSize.height () / -2
-                           , pageNominalSize.width (), pageNominalSize.height ());
-
-          pageRect.adjust (-penWidth / 2, -penWidth / 2, penWidth / 2, penWidth / 2);
-
-          QColor docSizeColor;
-
-          if (darkBackground)
-            docSizeColor = UBSettings::documentSizeMarkColorDarkBackground;
-          else
-            docSizeColor = UBSettings::documentSizeMarkColorLightBackground;
-
-          QPen pen (docSizeColor);
-          pen.setWidth (penWidth);
-          painter->setPen (pen);
-          painter->drawRect (pageRect);
-        }
-    }
-}
-
-void
-UBBoardView::settingChanged (QVariant newValue)
-{
-  Q_UNUSED (newValue);
-
-  mPenPressureSensitive = UBSettings::settings ()->boardPenPressureSensitive->get ().toBool ();
-  mMarkerPressureSensitive = UBSettings::settings ()->boardMarkerPressureSensitive->get ().toBool ();
-  mUseHighResTabletEvent = UBSettings::settings ()->boardUseHighResTabletEvent->get ().toBool ();
-}
-
-void UBBoardView::virtualKeyboardActivated(bool b)
-{
-    UBPlatformUtils::setWindowNonActivableFlag(this, b);
-    mVirtualKeyboardActive = b;
-    setInteractive(!b);
-}
-
-
-// Apple remote desktop sends funny events when the transmission is bad
-
-bool
-UBBoardView::isAbsurdPoint (QPoint point)
-{
-    QDesktopWidget *desktop = qApp->desktop ();
-    bool isValidPoint = false;
-
-    for (int i = 0; i < desktop->numScreens (); i++)
-    {
-      QRect screenRect = desktop->screenGeometry (i);
-      isValidPoint = isValidPoint || screenRect.contains (point);
-    }
-
-    return !isValidPoint;
-}
-
-void
-UBBoardView::focusOutEvent (QFocusEvent * event)
-{
-  Q_UNUSED (event);
-}
-
-void
-UBBoardView::setToolCursor (int tool)
-{
-  QWidget *controlViewport = viewport ();
-  switch (tool)
-    {
-    case UBStylusTool::Pen:
-      controlViewport->setCursor (UBResources::resources ()->penCursor);
-      break;
-    case UBStylusTool::Eraser:
-      controlViewport->setCursor (UBResources::resources ()->eraserCursor);
-      break;
-    case UBStylusTool::Marker:
-      controlViewport->setCursor (UBResources::resources ()->markerCursor);
-      break;
-    case UBStylusTool::Pointer:
-      controlViewport->setCursor (UBResources::resources ()->pointerCursor);
-      break;
-    case UBStylusTool::Hand:
-      controlViewport->setCursor (UBResources::resources ()->handCursor);
-      break;
-    case UBStylusTool::ZoomIn:
-      controlViewport->setCursor (UBResources::resources ()->zoomInCursor);
-      break;
-    case UBStylusTool::ZoomOut:
-      controlViewport->setCursor (UBResources::resources ()->zoomOutCursor);
-      break;
-    case UBStylusTool::Selector:
-      controlViewport->setCursor (UBResources::resources ()->arrowCursor);
-      break;
-    case UBStylusTool::Line:
-      controlViewport->setCursor (UBResources::resources ()->penCursor);
-      break;
-    case UBStylusTool::Text:
-      controlViewport->setCursor (UBResources::resources ()->textCursor);
-      break;
-    case UBStylusTool::Capture:
-      controlViewport->setCursor (UBResources::resources ()->penCursor);
-      break;
-    default:
-      Q_ASSERT (false);
-      //failsafe
-      controlViewport->setCursor (UBResources::resources ()->penCursor);
-    }
-}
-
-
+
+#include "UBBoardView.h"
+
+#include <QtGui>
+
+#include "UBDrawingController.h"
+
+#include "frameworks/UBGeometryUtils.h"
+
+#include "core/UBSettings.h"
+#include "core/UBMimeData.h"
+#include "core/UBApplication.h"
+#include "core/UBSetting.h"
+#include "core/UBPersistenceManager.h"
+
+#include "network/UBHttpGet.h"
+
+#include "gui/UBStylusPalette.h"
+#include "gui/UBRubberBand.h"
+#include "gui/UBToolWidget.h"
+#include "gui/UBResources.h"
+#include "gui/UBMainWindow.h"
+
+#include "board/UBBoardController.h"
+
+#include "domain/UBGraphicsTextItem.h"
+#include "domain/UBGraphicsPixmapItem.h"
+#include "domain/UBGraphicsWidgetItem.h"
+#include "domain/UBItem.h"
+
+#include "document/UBDocumentProxy.h"
+#include "../gui/UBThumbnailWidget.h"
+
+#include "frameworks/UBPlatformUtils.h"
+
+#include "core/memcheck.h"
+
+UBBoardView::UBBoardView (UBBoardController* pController, QWidget* pParent)
+: QGraphicsView (pParent)
+, mController (pController)
+, mIsCreatingTextZone (false)
+, mIsCreatingSceneGrabZone (false)
+{
+  init ();
+
+  mFilterZIndex = false;
+}
+
+UBBoardView::UBBoardView (UBBoardController* pController, int pStartLayer, int pEndLayer, QWidget* pParent)
+: QGraphicsView (pParent)
+, mController (pController)
+{
+  init ();
+
+  mStartLayer = pStartLayer;
+  mEndLayer = pEndLayer;
+
+  mFilterZIndex = true;
+}
+
+UBBoardView::~UBBoardView () {
+  //NOOP
+}
+
+void
+UBBoardView::init ()
+{
+  connect (UBSettings::settings ()->boardPenPressureSensitive, SIGNAL (changed (QVariant)),
+           this, SLOT (settingChanged (QVariant)));
+
+  connect (UBSettings::settings ()->boardMarkerPressureSensitive, SIGNAL (changed (QVariant)),
+           this, SLOT (settingChanged (QVariant)));
+
+  connect (UBSettings::settings ()->boardUseHighResTabletEvent, SIGNAL (changed (QVariant)),
+           this, SLOT (settingChanged (QVariant)));
+
+  setWindowFlags (Qt::FramelessWindowHint);
+  setFrameStyle (QFrame::NoFrame);
+  setRenderHints (QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);
+  setVerticalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
+  setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
+  setAcceptDrops (true);
+
+  setOptimizationFlag (QGraphicsView::IndirectPainting); // enable UBBoardView::drawItems filter
+
+  mTabletStylusIsPressed = false;
+  mMouseButtonIsPressed = false;
+  mPendingStylusReleaseEvent = false;
+
+  setCacheMode (QGraphicsView::CacheBackground);
+
+  mUsingTabletEraser = false;
+  mIsCreatingTextZone = false;
+  mRubberBand = 0;
+
+  mVirtualKeyboardActive = false;
+
+  settingChanged (QVariant ());
+
+  unsetCursor();
+}
+
+UBGraphicsScene*
+UBBoardView::scene ()
+{
+  return qobject_cast<UBGraphicsScene*> (QGraphicsView::scene ());
+}
+
+void
+UBBoardView::hideEvent (QHideEvent * event)
+{
+  Q_UNUSED (event);
+  emit hidden ();
+}
+
+void
+UBBoardView::showEvent (QShowEvent * event)
+{
+  Q_UNUSED (event);
+  emit shown ();
+}
+
+void
+UBBoardView::keyPressEvent (QKeyEvent *event)
+{
+  // send to the scene anyway
+  QApplication::sendEvent (scene (), event);
+
+  if (!event->isAccepted ())
+    {
+      switch (event->key ())
+        {
+        case Qt::Key_Up:
+        case Qt::Key_PageUp:
+        case Qt::Key_Left:
+          {
+            mController->previousScene ();
+            break;
+          }
+
+        case Qt::Key_Down:
+        case Qt::Key_PageDown:
+        case Qt::Key_Right:
+        case Qt::Key_Space:
+          {
+            mController->nextScene ();
+            break;
+          }
+
+        case Qt::Key_Home:
+          {
+            mController->firstScene ();
+            break;
+          }
+        case Qt::Key_End:
+          {
+            mController->lastScene ();
+            break;
+          }
+        case Qt::Key_Insert:
+          {
+            mController->addScene ();
+            break;
+          }
+        }
+
+
+      if (event->modifiers () & Qt::ControlModifier) // keep only ctrl/cmd keys
+        {
+          switch (event->key ())
+            {
+            case Qt::Key_Plus:
+            case Qt::Key_I:
+              {
+                mController->zoomIn ();
+                event->accept ();
+                break;
+              }
+            case Qt::Key_Minus:
+            case Qt::Key_O:
+              {
+                mController->zoomOut ();
+                event->accept ();
+                break;
+              }
+            case Qt::Key_0:
+              {
+                mController->zoomRestore ();
+                event->accept ();
+                break;
+              }
+            case Qt::Key_Left:
+              {
+                mController->handScroll (-100, 0);
+                event->accept ();
+                break;
+              }
+            case Qt::Key_Right:
+              {
+                mController->handScroll (100, 0);
+                event->accept ();
+                break;
+              }
+            case Qt::Key_Up:
+              {
+                mController->handScroll (0, -100);
+                event->accept ();
+                break;
+              }
+            case Qt::Key_Down:
+              {
+                mController->handScroll (0, 100);
+                event->accept ();
+                break;
+              }
+            default:
+              {
+                // NOOP
+              }
+            }
+        }
+    }
+}
+
+bool
+UBBoardView::event (QEvent * e)
+{
+  if (e->type () == QEvent::Gesture)
+    {
+      QGestureEvent *gestureEvent = dynamic_cast<QGestureEvent *> (e);
+      if (gestureEvent)
+        {
+          QSwipeGesture* swipe = dynamic_cast<QSwipeGesture*> (gestureEvent->gesture (Qt::SwipeGesture));
+
+          if (swipe)
+            {
+              if (swipe->horizontalDirection () == QSwipeGesture::Left)
+                {
+                  mController->previousScene ();
+                  gestureEvent->setAccepted (swipe, true);
+                }
+
+              if (swipe->horizontalDirection () == QSwipeGesture::Right)
+                {
+                  mController->nextScene ();
+                  gestureEvent->setAccepted (swipe, true);
+                }
+            }
+        }
+    }
+
+  return QGraphicsView::event (e);
+}
+
+void
+UBBoardView::tabletEvent (QTabletEvent * event)
+{
+  if (!mUseHighResTabletEvent)
+    {
+      event->setAccepted (false);
+      return;
+    }
+
+  UBDrawingController *dc = UBDrawingController::drawingController ();
+
+  QPointF tabletPos = UBGeometryUtils::pointConstrainedInRect (event->hiResGlobalPos ()
+                                                               - mapToGlobal (QPoint (0, 0)), rect ());
+
+  UBStylusTool::Enum currentTool = (UBStylusTool::Enum)dc->stylusTool ();
+
+  if (event->type () == QEvent::TabletPress || event->type () == QEvent::TabletEnterProximity)
+    {
+      if (event->pointerType () == QTabletEvent::Eraser)
+        {
+          dc->setStylusTool (UBStylusTool::Eraser);
+          mUsingTabletEraser = true;
+        }
+      else
+        {
+          if (mUsingTabletEraser && currentTool == UBStylusTool::Eraser)
+            {
+              dc->setStylusTool (dc->latestDrawingTool ());
+            }
+
+          mUsingTabletEraser = false;
+        }
+    }
+
+  // if event are not Pen events, we drop the tablet stuff and route everything through mouse event
+  if (currentTool != UBStylusTool::Pen
+      && currentTool != UBStylusTool::Line
+      && currentTool != UBStylusTool::Marker
+      && !mMarkerPressureSensitive)
+    {
+      event->setAccepted (false);
+      return;
+    }
+
+  QPointF scenePos = viewportTransform ().inverted ().map (tabletPos);
+
+  qreal pressure = 1.0;
+  if (((currentTool == UBStylusTool::Pen || currentTool == UBStylusTool::Line)
+       && mPenPressureSensitive)
+      || (currentTool == UBStylusTool::Marker && mMarkerPressureSensitive))
+    {
+      pressure = event->pressure ();
+    }
+
+  bool acceptEvent = true;
+
+  switch (event->type ())
+    {
+    case QEvent::TabletPress:
+      {
+        mTabletStylusIsPressed = true;
+
+        scene ()->inputDevicePress (scenePos, pressure);
+
+        break;
+      }
+    case QEvent::TabletMove:
+      {
+        if (mTabletStylusIsPressed)
+          {
+            scene ()->inputDeviceMove (scenePos, pressure);
+          }
+
+        acceptEvent = false; // rerouted to mouse move
+
+        break;
+
+      }
+    case QEvent::TabletRelease:
+      {
+        UBStylusTool::Enum currentTool = (UBStylusTool::Enum)dc->stylusTool ();
+        scene ()->setToolCursor (currentTool);
+        setToolCursor (currentTool);
+
+        scene ()->inputDeviceRelease ();
+
+        mPendingStylusReleaseEvent = false;
+
+        mTabletStylusIsPressed = false;
+        mMouseButtonIsPressed = false;
+
+        break;
+      }
+    default:
+      {
+        //NOOP - avoid compiler warning
+      }
+    }
+
+  // ignore mouse press and mouse move tablet event so that it is rerouted to mouse events,
+  // documented in QTabletEvent Class Reference:
+  /* The event handler QWidget::tabletEvent() receives all three types of tablet events.
+     Qt will first send a tabletEvent then, if it is not accepted, it will send a mouse event. */
+  //
+  // This is a workaround to the fact that tablet event are not delivered to child widget (like palettes)
+  //
+
+  event->setAccepted (acceptEvent);
+
+}
+
+void
+UBBoardView::mousePressEvent (QMouseEvent *event)
+{
+  if (isAbsurdPoint (event->pos ()))
+    {
+      event->accept ();
+      return;
+    }
+
+  mMouseDownPos = event->pos ();
+
+  if (event->button () == Qt::LeftButton && isInteractive ())
+    {
+      UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController ()->stylusTool ();
+
+      if (!mTabletStylusIsPressed)
+        mMouseButtonIsPressed = true;
+
+      if (currentTool == UBStylusTool::ZoomIn)
+        {
+          mController->zoomIn (mapToScene (event->pos ()));
+          event->accept ();
+        }
+      else if (currentTool == UBStylusTool::ZoomOut)
+        {
+          mController->zoomOut (mapToScene (event->pos ()));
+          event->accept ();
+        }
+      else if (currentTool == UBStylusTool::Hand)
+        {
+          viewport ()->setCursor (QCursor (Qt::ClosedHandCursor));
+          mPreviousPoint = event->posF ();
+          event->accept ();
+        }
+      else if (currentTool == UBStylusTool::Selector)
+        {
+          QGraphicsView::mousePressEvent (event);
+        }
+      else if (currentTool == UBStylusTool::Text)
+        {
+          int frameWidth = UBSettings::settings ()->objectFrameWidth;
+          QRectF fuzzyRect (0, 0, frameWidth * 4, frameWidth * 4);
+          fuzzyRect.moveCenter (mapToScene (mMouseDownPos));
+
+          UBGraphicsTextItem* foundTextItem = 0;
+          QListIterator<QGraphicsItem *> it (scene ()->items (fuzzyRect));
+
+          while (it.hasNext () && !foundTextItem)
+            {
+              foundTextItem = qgraphicsitem_cast<UBGraphicsTextItem*>(it.next ());
+            }
+
+          if (foundTextItem)
+            {
+              mIsCreatingTextZone = false;
+              QGraphicsView::mousePressEvent (event);
+            }
+          else
+            {
+              scene ()->deselectAllItems ();
+
+              if (!mRubberBand)
+                mRubberBand = new UBRubberBand (QRubberBand::Rectangle, this);
+
+              mRubberBand->setGeometry (QRect (mMouseDownPos, QSize ()));
+              mRubberBand->show ();
+              mIsCreatingTextZone = true;
+
+              event->accept ();
+            }
+        }
+      else if (currentTool == UBStylusTool::Capture)
+        {
+          scene ()->deselectAllItems ();
+
+          if (!mRubberBand)
+            mRubberBand = new UBRubberBand (QRubberBand::Rectangle, this);
+
+          mRubberBand->setGeometry (QRect (mMouseDownPos, QSize ()));
+          mRubberBand->show ();
+          mIsCreatingSceneGrabZone = true;
+
+          event->accept ();
+        }
+            else
+            {
+                if(UBDrawingController::drawingController()->mActiveRuler==NULL)
+                {
+                        viewport()->setCursor (QCursor (Qt::BlankCursor));
+                }
+
+                if (scene () && !mTabletStylusIsPressed)
+                {
+                        scene ()->inputDevicePress (mapToScene (UBGeometryUtils::pointConstrainedInRect (event->pos (), rect ())));
+                }
+                event->accept ();
+        }
+    }
+}
+
+void
+UBBoardView::mouseMoveEvent (QMouseEvent *event)
+{
+  UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController ()->stylusTool ();
+
+  if (isAbsurdPoint (event->pos ()))
+    {
+      event->accept ();
+      return;
+    }
+
+  if (currentTool == UBStylusTool::Hand && (mMouseButtonIsPressed || mTabletStylusIsPressed))
+    {
+      QPointF eventPosition = event->posF ();
+      qreal dx = eventPosition.x () - mPreviousPoint.x ();
+      qreal dy = eventPosition.y () - mPreviousPoint.y ();
+      mController->handScroll (dx, dy);
+      mPreviousPoint = eventPosition;
+      event->accept ();
+    }
+  else if (currentTool == UBStylusTool::Selector)
+    {
+      QGraphicsView::mouseMoveEvent (event);
+    }
+  else if ((UBDrawingController::drawingController()->isDrawingTool())
+  	&& !mMouseButtonIsPressed)
+  {
+	  QGraphicsView::mouseMoveEvent (event);
+  }
+  else if (currentTool == UBStylusTool::Text || currentTool == UBStylusTool::Capture)
+    {
+      if (mRubberBand && (mIsCreatingTextZone || mIsCreatingSceneGrabZone))
+        {
+          mRubberBand->setGeometry (QRect (mMouseDownPos, event->pos ()).normalized ());
+          event->accept ();
+        }
+      else
+        {
+          QGraphicsView::mouseMoveEvent (event);
+        }
+    }
+  else
+    {
+      if (!mTabletStylusIsPressed && scene ())
+      {
+          scene ()->inputDeviceMove (mapToScene (UBGeometryUtils::pointConstrainedInRect (event->pos (), rect ())), mMouseButtonIsPressed);
+      }
+      event->accept ();
+    }
+}
+
+void
+UBBoardView::mouseReleaseEvent (QMouseEvent *event)
+{
+  UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController ()->stylusTool ();
+
+  scene ()->setToolCursor (currentTool);
+  setToolCursor (currentTool);
+
+  // first propagate device release to the scene
+  if (scene ())
+    scene ()->inputDeviceRelease ();
+
+  if (currentTool == UBStylusTool::Selector)
+    {
+      QGraphicsView::mouseReleaseEvent (event);
+    }
+  else if (currentTool == UBStylusTool::Text)
+    {
+      if (mRubberBand)
+        mRubberBand->hide ();
+
+      if (scene () && mRubberBand && mIsCreatingTextZone)
+        {
+          QRect rubberRect = mRubberBand->geometry ();
+
+          UBGraphicsTextItem* textItem = scene ()->addText ("", mapToScene (rubberRect.topLeft ()));
+          event->accept ();
+
+          UBDrawingController::drawingController ()->setStylusTool (UBStylusTool::Selector);
+
+          textItem->setSelected (true);
+        }
+      else
+        {
+          QGraphicsView::mouseReleaseEvent (event);
+        }
+
+      mIsCreatingTextZone = false;
+    }
+  else if (currentTool == UBStylusTool::Capture)
+    {
+      if (mRubberBand)
+        mRubberBand->hide ();
+
+      if (scene () && mRubberBand && mIsCreatingSceneGrabZone && mRubberBand->geometry ().width () > 16)
+        {
+          QRect rect = mRubberBand->geometry ();
+          QPointF sceneTopLeft = mapToScene (rect.topLeft ());
+          QPointF sceneBottomRight = mapToScene (rect.bottomRight ());
+          QRectF sceneRect (sceneTopLeft, sceneBottomRight);
+
+          mController->grabScene (sceneRect);
+
+          event->accept ();
+        }
+      else
+        {
+          QGraphicsView::mouseReleaseEvent (event);
+        }
+
+      mIsCreatingSceneGrabZone = false;
+    }
+  else
+    {
+      if (mPendingStylusReleaseEvent || mMouseButtonIsPressed)
+        {
+          event->accept ();
+        }
+    }
+
+  mMouseButtonIsPressed = false;
+  mPendingStylusReleaseEvent = false;
+  mTabletStylusIsPressed = false;
+
+}
+
+void
+UBBoardView::forcedTabletRelease ()
+{
+
+  if (mMouseButtonIsPressed || mTabletStylusIsPressed || mPendingStylusReleaseEvent)
+    {
+      qWarning () << "dirty mouse/tablet state:";
+      qWarning () << "mMouseButtonIsPressed =" << mMouseButtonIsPressed;
+      qWarning () << "mTabletStylusIsPressed = " << mTabletStylusIsPressed;
+      qWarning () << "mPendingStylusReleaseEvent" << mPendingStylusReleaseEvent;
+      qWarning () << "forcing device release";
+
+      scene ()->inputDeviceRelease ();
+
+      mMouseButtonIsPressed = false;
+      mTabletStylusIsPressed = false;
+      mPendingStylusReleaseEvent = false;
+
+    }
+}
+
+void
+UBBoardView::mouseDoubleClickEvent (QMouseEvent *event)
+{
+  // We don't want a double click, we want two clicks
+  mousePressEvent (event);
+}
+
+void
+UBBoardView::wheelEvent (QWheelEvent *event)
+{
+  if (isInteractive () && event->orientation () == Qt::Vertical)
+    {
+      // Too many wheelEvent are sent, how should we handle them to "smoothly" zoom ?
+      // something like zoom( pow(zoomFactor, event->delta() / 120) )
+    }
+  event->accept ();
+}
+
+void
+UBBoardView::leaveEvent (QEvent * event)
+{
+  if (scene ())
+    scene ()->leaveEvent (event);
+
+  QGraphicsView::leaveEvent (event);
+}
+
+void
+UBBoardView::drawItems (QPainter *painter, int numItems,
+                        QGraphicsItem* items[],
+                        const QStyleOptionGraphicsItem options[])
+{
+  if (!mFilterZIndex)
+    {
+      QGraphicsView::drawItems (painter, numItems, items, options);
+    }
+  else
+    {
+      int count = 0;
+
+      QGraphicsItem** itemsFiltered = new QGraphicsItem*[numItems];
+      QStyleOptionGraphicsItem *optionsFiltered = new QStyleOptionGraphicsItem[numItems];
+
+      for (int i = 0; i < numItems; i++)
+        {
+          if (shouldDisplayItem (items[i]))
+            {
+              itemsFiltered[count] = items[i];
+              optionsFiltered[count] = options[i];
+              count++;
+            }
+        }
+
+      QGraphicsView::drawItems (painter, count, itemsFiltered, optionsFiltered);
+
+      delete[] optionsFiltered;
+      delete[] itemsFiltered;
+    }
+}
+
+void
+UBBoardView::dragEnterEvent (QDragEnterEvent *event)
+{
+  // TODO UB 4.x be smarter with drag accept code .... we cannot handle everything ...
+  event->acceptProposedAction ();
+}
+
+void
+UBBoardView::dragMoveEvent (QDragMoveEvent *event)
+{
+  event->acceptProposedAction ();
+}
+
+void
+UBBoardView::dropEvent (QDropEvent *event)
+{
+  if(!event->source() || dynamic_cast<UBThumbnailWidget *>(event->source()))
+  {
+        mController->processMimeData (event->mimeData (), mapToScene (event->pos ()));
+        event->acceptProposedAction ();
+  }
+}
+
+void
+UBBoardView::resizeEvent (QResizeEvent * event)
+{
+  const qreal maxWidth = width () * 10;
+  const qreal maxHeight = height () * 10;
+
+  setSceneRect (-(maxWidth / 2), -(maxHeight / 2), maxWidth, maxHeight);
+  centerOn (0, 0);
+
+  emit resized (event);
+}
+
+void
+UBBoardView::drawBackground (QPainter *painter, const QRectF &rect)
+{
+  if (testAttribute (Qt::WA_TranslucentBackground))
+    {
+      QGraphicsView::drawBackground (painter, rect);
+      return;
+    }
+
+  bool darkBackground = scene () && scene ()->isDarkBackground ();
+
+  if (darkBackground)
+    {
+      painter->fillRect (rect, QBrush (QColor (Qt::black)));
+    }
+  else
+    {
+      painter->fillRect (rect, QBrush (QColor (Qt::white)));
+    }
+
+  if (transform ().m11 () > 0.5)
+    {
+      QColor bgCrossColor;
+
+      if (darkBackground)
+        bgCrossColor = UBSettings::crossDarkBackground;
+      else
+        bgCrossColor = UBSettings::crossLightBackground;
+
+      if (transform ().m11 () < 1.0)
+        {
+          int alpha = 255 * transform ().m11 () / 2;
+          bgCrossColor.setAlpha (alpha); // fade the crossing on small zooms
+        }
+
+      painter->setPen (bgCrossColor);
+
+      if (scene () && scene ()->isCrossedBackground ())
+        {
+          qreal firstY = ((int) (rect.y () / UBSettings::crossSize)) * UBSettings::crossSize;
+
+          for (qreal yPos = firstY; yPos < rect.y () + rect.height (); yPos += UBSettings::crossSize)
+            {
+              painter->drawLine (rect.x (), yPos, rect.x () + rect.width (), yPos);
+            }
+
+          qreal firstX = ((int) (rect.x () / UBSettings::crossSize)) * UBSettings::crossSize;
+
+          for (qreal xPos = firstX; xPos < rect.x () + rect.width (); xPos += UBSettings::crossSize)
+            {
+              painter->drawLine (xPos, rect.y (), xPos, rect.y () + rect.height ());
+            }
+        }
+    }
+
+  if (!mFilterZIndex && scene ())
+    {
+      QSize pageNominalSize = scene ()->nominalSize ();
+
+      if (pageNominalSize.isValid ())
+        {
+          qreal penWidth = 8.0 / transform ().m11 ();
+
+          QRectF pageRect (pageNominalSize.width () / -2, pageNominalSize.height () / -2
+                           , pageNominalSize.width (), pageNominalSize.height ());
+
+          pageRect.adjust (-penWidth / 2, -penWidth / 2, penWidth / 2, penWidth / 2);
+
+          QColor docSizeColor;
+
+          if (darkBackground)
+            docSizeColor = UBSettings::documentSizeMarkColorDarkBackground;
+          else
+            docSizeColor = UBSettings::documentSizeMarkColorLightBackground;
+
+          QPen pen (docSizeColor);
+          pen.setWidth (penWidth);
+          painter->setPen (pen);
+          painter->drawRect (pageRect);
+        }
+    }
+}
+
+void
+UBBoardView::settingChanged (QVariant newValue)
+{
+  Q_UNUSED (newValue);
+
+  mPenPressureSensitive = UBSettings::settings ()->boardPenPressureSensitive->get ().toBool ();
+  mMarkerPressureSensitive = UBSettings::settings ()->boardMarkerPressureSensitive->get ().toBool ();
+  mUseHighResTabletEvent = UBSettings::settings ()->boardUseHighResTabletEvent->get ().toBool ();
+}
+
+void UBBoardView::virtualKeyboardActivated(bool b)
+{
+    UBPlatformUtils::setWindowNonActivableFlag(this, b);
+    mVirtualKeyboardActive = b;
+    setInteractive(!b);
+}
+
+
+// Apple remote desktop sends funny events when the transmission is bad
+
+bool
+UBBoardView::isAbsurdPoint (QPoint point)
+{
+    QDesktopWidget *desktop = qApp->desktop ();
+    bool isValidPoint = false;
+
+    for (int i = 0; i < desktop->numScreens (); i++)
+    {
+      QRect screenRect = desktop->screenGeometry (i);
+      isValidPoint = isValidPoint || screenRect.contains (point);
+    }
+
+    return !isValidPoint;
+}
+
+void
+UBBoardView::focusOutEvent (QFocusEvent * event)
+{
+  Q_UNUSED (event);
+}
+
+void
+UBBoardView::setToolCursor (int tool)
+{
+  QWidget *controlViewport = viewport ();
+  switch (tool)
+    {
+    case UBStylusTool::Pen:
+      controlViewport->setCursor (UBResources::resources ()->penCursor);
+      break;
+    case UBStylusTool::Eraser:
+      controlViewport->setCursor (UBResources::resources ()->eraserCursor);
+      break;
+    case UBStylusTool::Marker:
+      controlViewport->setCursor (UBResources::resources ()->markerCursor);
+      break;
+    case UBStylusTool::Pointer:
+      controlViewport->setCursor (UBResources::resources ()->pointerCursor);
+      break;
+    case UBStylusTool::Hand:
+      controlViewport->setCursor (UBResources::resources ()->handCursor);
+      break;
+    case UBStylusTool::ZoomIn:
+      controlViewport->setCursor (UBResources::resources ()->zoomInCursor);
+      break;
+    case UBStylusTool::ZoomOut:
+      controlViewport->setCursor (UBResources::resources ()->zoomOutCursor);
+      break;
+    case UBStylusTool::Selector:
+      controlViewport->setCursor (UBResources::resources ()->arrowCursor);
+      break;
+    case UBStylusTool::Line:
+      controlViewport->setCursor (UBResources::resources ()->penCursor);
+      break;
+    case UBStylusTool::Text:
+      controlViewport->setCursor (UBResources::resources ()->textCursor);
+      break;
+    case UBStylusTool::Capture:
+      controlViewport->setCursor (UBResources::resources ()->penCursor);
+      break;
+    default:
+      Q_ASSERT (false);
+      //failsafe
+      controlViewport->setCursor (UBResources::resources ()->penCursor);
+    }
+}
+
+
diff --git a/src/desktop/UBDesktopAnnotationController.cpp b/src/desktop/UBDesktopAnnotationController.cpp
index d7a4a9cd..b78e767c 100644
--- a/src/desktop/UBDesktopAnnotationController.cpp
+++ b/src/desktop/UBDesktopAnnotationController.cpp
@@ -90,6 +90,7 @@ UBDesktopAnnotationController::UBDesktopAnnotationController(QObject *parent)
         mKeyboardPalette = UBKeyboardPalette::create(mTransparentDrawingView);
         mKeyboardPalette->setParent(mTransparentDrawingView);
         connect(mKeyboardPalette, SIGNAL(keyboardActivated(bool)), mTransparentDrawingView, SLOT(virtualKeyboardActivated(bool))); 
+        connect(mKeyboardPalette, SIGNAL(moved(QPoint)), this, SLOT(refreshMask()));
     }
 
     connect(mDesktopPalette, SIGNAL(uniboardClick()), this, SLOT(goToUniboard()));
@@ -143,12 +144,16 @@ UBDesktopAnnotationController::UBDesktopAnnotationController(QObject *parent)
     connect(&mHoldTimerMarker, SIGNAL(timeout()), this, SLOT(markerActionReleased()));
     connect(&mHoldTimerEraser, SIGNAL(timeout()), this, SLOT(eraserActionReleased()));
 
+    connect(mDesktopPalette, SIGNAL(moving()), this, SLOT(refreshMask()));
+    connect(mLibPalette, SIGNAL(resized()), this, SLOT(refreshMask()));
+
     onDesktopPaletteMaximized();
 }
 
 void UBDesktopAnnotationController::showKeyboard(bool show)
 {
     mKeyboardPalette->setVisible(show);
+    updateMask(true);
 
 //    mDesktopPalette->showVirtualKeyboard(show);
 }
@@ -332,6 +337,10 @@ void UBDesktopAnnotationController::showWindow()
     UBPlatformUtils::setDesktopMode(true);
 
     mDesktopPalette->appear();
+
+#ifdef Q_WS_X11
+    updateMask(true);
+#endif
 }
 
 
@@ -343,7 +352,15 @@ void UBDesktopAnnotationController::close()
 
 void UBDesktopAnnotationController::stylusToolChanged(int tool)
 {
-    Q_UNUSED(tool);
+    UBStylusTool::Enum eTool = (UBStylusTool::Enum)tool;
+    mDesktopPalette->notifySelectorSelection(UBStylusTool::Selector == eTool);
+
+    if(UBStylusTool::Selector != eTool)
+    {
+        UBApplication::mainWindow->actionVirtualKeyboard->setChecked(false);
+        mKeyboardPalette->setVisible(false);
+    }
+
     updateBackground();
 }
 
@@ -356,6 +373,9 @@ void UBDesktopAnnotationController::updateBackground()
             || UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Selector)
     {
         newBrush = QBrush(Qt::transparent);
+#ifdef Q_WS_X11
+        updateMask(true);
+#endif
     }
     else
     {
@@ -363,6 +383,9 @@ void UBDesktopAnnotationController::updateBackground()
         newBrush = QBrush(QColor(127, 127, 127, 15));
 #else
         newBrush = QBrush(QColor(127, 127, 127, 1));
+#endif
+#ifdef Q_WS_X11
+        updateMask(false);
 #endif
     }
 
@@ -389,6 +412,8 @@ void UBDesktopAnnotationController::goToUniboard()
 
     UBPlatformUtils::setDesktopMode(false);
 
+    UBApplication::mainWindow->actionVirtualKeyboard->setEnabled(true);
+
     emit restoreUniboard();
 }
 
@@ -751,3 +776,83 @@ void UBDesktopAnnotationController::onTransparentWidgetResized()
 //    qDebug() << "mLibPalette (" << mLibPalette->width() << "," << mLibPalette->height() << ")";
       mLibPalette->resize(mLibPalette->width(), mTransparentDrawingView->height());
 }
+
+void UBDesktopAnnotationController::updateMask(bool bTransparent)
+{
+    if(bTransparent)
+    {
+        // Here we have to generate a new mask. This method is certainly resource
+        // consuming but for the moment this is the only solution that I found.
+        mMask = QPixmap(mTransparentDrawingView->width(), mTransparentDrawingView->height());
+
+        QPainter p;
+
+        p.begin(&mMask);
+
+        p.setPen(Qt::red);
+        p.setBrush(QBrush(Qt::red));
+
+        // Here we draw the widget mask
+        if(mDesktopPalette->isVisible())
+        {
+            p.drawRect(mDesktopPalette->geometry().x(), mDesktopPalette->geometry().y(), mDesktopPalette->width(), mDesktopPalette->height());
+        }
+        if(mKeyboardPalette->isVisible())
+        {
+            p.drawRect(mKeyboardPalette->geometry().x(), mKeyboardPalette->geometry().y(), mKeyboardPalette->width(), mKeyboardPalette->height());
+        }
+        if(mLibPalette->isVisible())
+        {
+            p.drawRect(mLibPalette->geometry().x(), mLibPalette->geometry().y(), mLibPalette->width(), mLibPalette->height());
+        }
+
+        p.end();
+
+        // Then we add the annotations. We create another painter because we need to
+        // apply transformations on it for coordinates matching
+        QPainter annotationPainter;
+
+        QTransform trans;
+        trans.translate(mTransparentDrawingView->width()/2, mTransparentDrawingView->height()/2);
+
+        annotationPainter.begin(&mMask);
+        annotationPainter.setPen(Qt::red);
+        annotationPainter.setBrush(Qt::red);
+
+        annotationPainter.setTransform(trans);
+
+        QList<QGraphicsItem*> allItems = mTransparentDrawingScene->items();
+
+        for(int i = 0; i < allItems.size(); i++)
+        {
+            QGraphicsItem* pCrntItem = allItems.at(i);
+
+            if(pCrntItem->isVisible())
+            {
+                QPainterPath crntPath = pCrntItem->shape();
+                QRectF rect = crntPath.boundingRect();
+
+                annotationPainter.drawRect(rect);
+            }
+        }
+
+        annotationPainter.end();
+
+        mTransparentDrawingView->setMask(mMask.createMaskFromColor(Qt::black));
+    }
+    else
+    {
+        // Remove the mask
+        QPixmap noMask(mTransparentDrawingView->width(), mTransparentDrawingView->height());
+        mTransparentDrawingView->setMask(noMask.mask());
+    }
+}
+
+void UBDesktopAnnotationController::refreshMask()
+{
+    if(mIsFullyTransparent
+            || UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Selector)
+    {
+        updateMask(true);
+    }
+}
diff --git a/src/desktop/UBDesktopAnnotationController.h b/src/desktop/UBDesktopAnnotationController.h
index d595c04a..469296a7 100644
--- a/src/desktop/UBDesktopAnnotationController.h
+++ b/src/desktop/UBDesktopAnnotationController.h
@@ -94,10 +94,12 @@ class UBDesktopAnnotationController : public QObject
         void onDesktopPaletteMaximized();
         void onDesktopPaletteMinimize();
         void onTransparentWidgetResized();
+        void refreshMask();
 
     private:
         void setAssociatedPalettePosition(UBActionPalette* palette, const QString& actionName);
         void togglePropertyPalette(UBActionPalette* palette);
+        void updateMask(bool bTransparent);
 
         UBDesktopPalette *mDesktopPalette;
         UBKeyboardPalette *mKeyboardPalette;
@@ -126,6 +128,8 @@ class UBDesktopAnnotationController : public QObject
         int mBoardStylusTool;
         int mDesktopStylusTool;
 
+        QPixmap mMask;
+
 };
 
 #endif /* UBUNINOTESWINDOWCONTROLLER_H_ */
diff --git a/src/desktop/UBDesktopPalette.cpp b/src/desktop/UBDesktopPalette.cpp
index 6ec00c8a..f881f58a 100644
--- a/src/desktop/UBDesktopPalette.cpp
+++ b/src/desktop/UBDesktopPalette.cpp
@@ -36,9 +36,7 @@ UBDesktopPalette::UBDesktopPalette(QWidget *parent)
     actions << UBApplication::mainWindow->actionPen;
     actions << UBApplication::mainWindow->actionEraser;
     actions << UBApplication::mainWindow->actionMarker;
-#ifndef Q_WS_X11
     actions << UBApplication::mainWindow->actionSelector;
-#endif
     actions << UBApplication::mainWindow->actionPointer;
 
     if (UBPlatformUtils::hasVirtualKeyboard())
@@ -152,9 +150,7 @@ void UBDesktopPalette::maximizeMe()
     actions << UBApplication::mainWindow->actionPen;
     actions << UBApplication::mainWindow->actionEraser;
     actions << UBApplication::mainWindow->actionMarker;
-#ifndef Q_WS_X11
     actions << UBApplication::mainWindow->actionSelector;
-#endif
     actions << UBApplication::mainWindow->actionPointer;
     if (UBPlatformUtils::hasVirtualKeyboard())
         actions << UBApplication::mainWindow->actionVirtualKeyboard;
@@ -221,3 +217,8 @@ QPoint UBDesktopPalette::buttonPos(QAction *action)
 
     return p;
 }
+
+void UBDesktopPalette::notifySelectorSelection(bool selected)
+{
+    UBApplication::mainWindow->actionVirtualKeyboard->setEnabled(selected);
+}
diff --git a/src/desktop/UBDesktopPalette.h b/src/desktop/UBDesktopPalette.h
index 83c01eab..17168b85 100644
--- a/src/desktop/UBDesktopPalette.h
+++ b/src/desktop/UBDesktopPalette.h
@@ -27,6 +27,7 @@ class UBDesktopPalette : public UBActionPalette
         void disappearForCapture();
         void appear();
         QPoint buttonPos(QAction* action);
+        void notifySelectorSelection(bool selected);
 
     signals:
         void uniboardClick();
diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp
index 8a69e4e0..b66f4396 100644
--- a/src/domain/UBGraphicsScene.cpp
+++ b/src/domain/UBGraphicsScene.cpp
@@ -249,6 +249,8 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres
 			{
 	            if (currentTool == UBStylusTool::Line)
 		        {
+                            // TODO:    Verify this beautiful implementation and check if
+                            //          it is possible to optimize it
 			        QLineF radius(mPreviousPoint, position);
 				    qreal angle = radius.angle();
 					angle = qRound(angle / 45) * 45;
@@ -257,7 +259,7 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres
 			            mPreviousPoint.x() + radiusLength * cos((angle * PI) / 180),
 				        mPreviousPoint.y() - radiusLength * sin((angle * PI) / 180));
 					QLineF chord(position, newPosition);
-					if (chord.length() < qMin((int)16, (int)(radiusLength / 20)))
+                                        if (chord.length() < qMin((int)16, (int)(radiusLength / 20)))
 						position = newPosition;
 				}
 
diff --git a/src/gui/UBFloatingPalette.cpp b/src/gui/UBFloatingPalette.cpp
index 83a85261..6be7d5bc 100644
--- a/src/gui/UBFloatingPalette.cpp
+++ b/src/gui/UBFloatingPalette.cpp
@@ -106,6 +106,7 @@ void UBFloatingPalette::mouseMoveEvent(QMouseEvent *event)
     {
         moveInsideParent(event->globalPos() - mDragPosition);
         event->accept();
+        emit moving();
     }
     else
     {
diff --git a/src/gui/UBFloatingPalette.h b/src/gui/UBFloatingPalette.h
index a7e63125..0ddc6ade 100644
--- a/src/gui/UBFloatingPalette.h
+++ b/src/gui/UBFloatingPalette.h
@@ -78,6 +78,7 @@ class UBFloatingPalette : public QWidget
         void minimizeStart(eMinimizedLocation location);
         void maximizeStart();
         void maximized();
+        void moving();
 };
 
 
diff --git a/src/gui/UBLibPalette.cpp b/src/gui/UBLibPalette.cpp
index 656e2276..56ffeef2 100644
--- a/src/gui/UBLibPalette.cpp
+++ b/src/gui/UBLibPalette.cpp
@@ -34,7 +34,7 @@ UBLibPalette::UBLibPalette(QWidget *parent, const char *name):UBDockPalette(pare
     mIcon = QPixmap(":images/paletteLibrary.png");
     setAcceptDrops(true);
 
-    resize(UBSettings::settings()->libPaletteWidth->get().toInt(), height());
+    resize(UBSettings::settings()->libPaletteWidth->get().toInt(), parentWidget()->height());
     setContentsMargins(border(), 0, 0, 0);
     mCollapseWidth = 180;
     mLastWidth = 300;
@@ -201,6 +201,7 @@ void UBLibPalette::resizeEvent(QResizeEvent *event)
 {
     UBDockPalette::resizeEvent(event);
     UBSettings::settings()->libPaletteWidth->set(width());
+    emit resized();
 }
 
 // --------------------------------------------------------------------------
diff --git a/src/gui/UBLibPalette.h b/src/gui/UBLibPalette.h
index 3733610e..afbe8ff9 100644
--- a/src/gui/UBLibPalette.h
+++ b/src/gui/UBLibPalette.h
@@ -55,6 +55,9 @@ public:
 
     UBLibActionBar* actionBar(){return mActionBar;}
 
+signals:
+    void resized();
+
 protected:
     void updateMaxWidth();
     void dragEnterEvent(QDragEnterEvent* pEvent);