/****************************************************************************
**
** This file is part of the LibreCAD project, a 2D CAD program
**
** Copyright (C) 2010-2011 R. van Twisk (librecad@rvt.dds.nl)
** Copyright (C) 2001-2003 RibbonSoft. All rights reserved.
**
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file gpl-2.0.txt included in the
** packaging of this file.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
** This copyright notice MUST APPEAR in all copies of the script!
**
**********************************************************************/

#include "qg_graphicview.h"

#include <QGridLayout>
#include <QLabel>
#include <QDebug>
#if QT_VERSION >= 0x050200
#include <QNativeGestureEvent>
#endif

#include "rs_actionzoomin.h"
#include "rs_actionzoompan.h"
#include "rs_actionzoomscroll.h"
#include "rs_actionzoomauto.h"
#include "rs_actionmodifydelete.h"
#include "rs_actionselectsingle.h"
#include "rs_settings.h"
#include "rs_painterqt.h"
#include "qg_cadtoolbar.h"
#include "rs_dialogfactory.h"
#include "qg_dialogfactory.h"


#include "qg_scrollbar.h"

#define QG_SCROLLMARGIN 400


/**
 * Constructor.
 */
QG_GraphicView::QG_GraphicView(QWidget* parent, const char* name, Qt::WindowFlags f)
        : QWidget(parent, f), RS_GraphicView() {

    setObjectName(name);
    setBackground(background);

    redrawMethod=RS2::RedrawAll;
    isSmoothScrolling = false;

    PixmapLayer1=PixmapLayer2=PixmapLayer3=NULL;

    layout = new QGridLayout(this);
    layout->setMargin(0);
    layout->setSpacing(0);
    layout->setColumnStretch(0, 1);
    layout->setColumnStretch(1, 0);
    layout->setColumnStretch(2, 0);
    layout->setRowStretch(0, 1);
    layout->setRowStretch(1, 0);

    hScrollBar = new QG_ScrollBar(Qt::Horizontal, this);
    hScrollBar->setSingleStep(50);
    hScrollBar->setCursor(Qt::ArrowCursor);
    layout->addWidget(hScrollBar, 1, 0);
    layout->addItem(new QSpacerItem(0, hScrollBar->sizeHint().height()), 1, 0);
    connect(hScrollBar, SIGNAL(valueChanged(int)),
            this, SLOT(slotHScrolled(int)));

    vScrollBar = new QG_ScrollBar(Qt::Vertical, this);
    vScrollBar->setSingleStep(50);
    vScrollBar->setCursor(Qt::ArrowCursor);
    layout->addWidget(vScrollBar, 0, 2);
    layout->addItem(new QSpacerItem(vScrollBar->sizeHint().width(), 0), 0, 2);
    connect(vScrollBar, SIGNAL(valueChanged(int)),
            this, SLOT(slotVScrolled(int)));

    // Mouse Cursors:
    QPixmap cur1(":ui/cur_cad_bmp.png");
    QPixmap cur2(":ui/cur_glass_bmp.png");
    QPixmap cur3(":ui/cur_del_bmp.png");
    QPixmap cur4(":ui/cur_select_bmp.png");
    QPixmap cur5(":ui/cur_hand_bmp.png");
#ifdef Q_OS_WIN32
    curCad = new QCursor(cur1, 16, 16);
    curMagnifier = new QCursor(cur2, 12, 12);
    curDel = new QCursor(cur3, 16, 16);
    curSelect = new QCursor(cur4, 16, 16);
    curHand = new QCursor(cur5, 15, 15);
#else
    curCad = new QCursor(cur1, 15, 15);
    curMagnifier = new QCursor(cur2, 12, 12);
    curDel = new QCursor(cur3, 15, 15);
    curSelect = new QCursor(cur4, 15, 15);
    curHand = new QCursor(cur5, 15, 15);
#endif

    // Dummy widgets for scrollbar corners:
    //layout->addWidget(new QWidget(this), 1, 1);
    //QWidget* w = new QWidget(this);
    //w->setEraseColor(QColor(255,0,0));
    gridStatus = new QLabel("-", this);
    gridStatus->setAlignment(Qt::AlignRight);
    layout->addWidget(gridStatus, 1, 1, 1, 2);
    layout->addItem(new QSpacerItem(50, 0), 0, 1);

    setMouseTracking(true);
        // flickering under win:
    //setFocusPolicy(WheelFocus);

    setFocusPolicy(Qt::NoFocus);

    // See https://sourceforge.net/tracker/?func=detail&aid=3289298&group_id=342582&atid=1433844 (Left-mouse drag shrinks window)
    setAttribute(Qt::WA_NoMousePropagation);

    //update entities to selected entities to the current active layer
    RS_SETTINGS->beginGroup("/Modify");
    m_bUpdateLayer=(RS_SETTINGS->readEntry("/ModifyEntitiesToActiveLayer", "0")=="1");
    RS_SETTINGS->writeEntry("/ModifyEntitiesToActiveLayer", m_bUpdateLayer?1:0);
    RS_SETTINGS->endGroup();
}



/**
 * Destructor
 */
QG_GraphicView::~QG_GraphicView() {
    cleanUp();
        delete PixmapLayer1;
        delete PixmapLayer2;
        delete PixmapLayer3;
}



/**
 * @return width of widget.
 */
int QG_GraphicView::getWidth() {
    return width() - vScrollBar->sizeHint().width();
}



/**
 * @return height of widget.
 */
int QG_GraphicView::getHeight() {
    return height() - hScrollBar->sizeHint().height();
}


/**
 * Changes the current background color of this view.
 */
void QG_GraphicView::setBackground(const RS_Color& bg) {
    RS_GraphicView::setBackground(bg);

    QPalette palette;
    palette.setColor(backgroundRole(), bg);
    setPalette(palette);
}



/**
 * Sets the mouse cursor to the given type.
 */
void QG_GraphicView::setMouseCursor(RS2::CursorType c) {

    switch (c) {
    default:
    case RS2::ArrowCursor:
        setCursor(Qt::ArrowCursor);
        break;
    case RS2::UpArrowCursor:
        setCursor(Qt::UpArrowCursor);
        break;
    case RS2::CrossCursor:
        setCursor(Qt::CrossCursor);
        break;
    case RS2::WaitCursor:
        setCursor(Qt::WaitCursor);
        break;
    case RS2::IbeamCursor:
        setCursor(Qt::IBeamCursor);
        break;
    case RS2::SizeVerCursor:
        setCursor(Qt::SizeVerCursor);
        break;
    case RS2::SizeHorCursor:
        setCursor(Qt::SizeHorCursor);
        break;
    case RS2::SizeBDiagCursor:
        setCursor(Qt::SizeBDiagCursor);
        break;
    case RS2::SizeFDiagCursor:
        setCursor(Qt::SizeFDiagCursor);
        break;
    case RS2::SizeAllCursor:
        setCursor(Qt::SizeAllCursor);
        break;
    case RS2::BlankCursor:
        setCursor(Qt::BlankCursor);
        break;
    case RS2::SplitVCursor:
        setCursor(Qt::SplitVCursor);
        break;
    case RS2::SplitHCursor:
        setCursor(Qt::SplitHCursor);
        break;
    case RS2::PointingHandCursor:
        setCursor(Qt::PointingHandCursor);
        break;
    case RS2::ForbiddenCursor:
        setCursor(Qt::ForbiddenCursor);
        break;
    case RS2::WhatsThisCursor:
        setCursor(Qt::WhatsThisCursor);
        break;
    case RS2::OpenHandCursor:
        setCursor(Qt::OpenHandCursor);
        break;
    case RS2::ClosedHandCursor:
        setCursor(Qt::ClosedHandCursor);
        break;
    case RS2::CadCursor:
        setCursor(*curCad);
        break;
    case RS2::DelCursor:
        setCursor(*curDel);
        break;
    case RS2::SelectCursor:
        setCursor(*curSelect);
        break;
    case RS2::MagnifierCursor:
        setCursor(*curMagnifier);
        break;
    case RS2::MovingHandCursor:
        setCursor(*curHand);
        break;

    }

}



/**
 * Sets the text for the grid status widget in the left bottom corner.
 */
void QG_GraphicView::updateGridStatusWidget(const QString& text) {
    gridStatus->setText(text);
}



/**
 * Redraws the widget.
 */
void QG_GraphicView::redraw(RS2::RedrawMethod method) {
        redrawMethod=(RS2::RedrawMethod ) (redrawMethod | method);
        update(); // Paint when reeady to pain
//	repaint(); //Paint immediate
}



void QG_GraphicView::resizeEvent(QResizeEvent* /*e*/) {
    RS_DEBUG->print("QG_GraphicView::resizeEvent begin");
    adjustOffsetControls();
    adjustZoomControls();
//     updateGrid();
        // Small hack, delete teh snapper during resizes
        getOverlayContainer(RS2::Snapper)->clear();
        redraw();
    RS_DEBUG->print("QG_GraphicView::resizeEvent end");
}



void QG_GraphicView::emulateMouseMoveEvent() {
    QMouseEvent e(QEvent::MouseMove, QPoint(mx, my),
                    Qt::NoButton, Qt::NoButton, Qt::NoModifier);//RLZ
    //mouseMoveEvent(&e);
}



void QG_GraphicView::mousePressEvent(QMouseEvent* e) {
    // pan zoom with middle mouse button
#if QT_VERSION < 0x040700
    if (e->button()==Qt::MidButton /*|| (e->state()==Qt::LeftButton|Qt::AltButton)*/) {
#else
    if (e->button()==Qt::MiddleButton /*|| (e->state()==Qt::LeftButton|Qt::AltButton)*/) {
#endif
        setCurrentAction(new RS_ActionZoomPan(*container, *this));
    }

    RS_GraphicView::mousePressEvent(e);
    QWidget::mousePressEvent(e);
}

void QG_GraphicView::mouseDoubleClickEvent(QMouseEvent* e) {
    // zoom auto with double click middle mouse button
#if QT_VERSION < 0x040700
    if (e->button()==Qt::MidButton) {
#else
    if (e->button()==Qt::MiddleButton) {
#endif
        setCurrentAction(new RS_ActionZoomAuto(*container, *this));
        e->accept();
    }
}


void QG_GraphicView::mouseReleaseEvent(QMouseEvent* e) {
        RS_DEBUG->print("QG_GraphicView::mouseReleaseEvent");
    RS_GraphicView::mouseReleaseEvent(e);
    //QWidget::mouseReleaseEvent(e);

    if (!e->isAccepted()) {
        if (QG_DIALOGFACTORY!=NULL && QG_DIALOGFACTORY->getCadToolBar()!=NULL) {
                        RS_DEBUG->print("QG_GraphicView::mouseReleaseEvent: "
                                "fwd to cadtoolbar");
            QG_DIALOGFACTORY->getCadToolBar()->mouseReleaseEvent(e);
        }
    }
        RS_DEBUG->print("QG_GraphicView::mouseReleaseEvent: OK");
}


void QG_GraphicView::mouseMoveEvent(QMouseEvent* e) {
    //RS_DEBUG->print("QG_GraphicView::mouseMoveEvent begin");
    //QMouseEvent rsm = QG_Qt2Rs::mouseEvent(e);

    RS_GraphicView::mouseMoveEvent(e);
    QWidget::mouseMoveEvent(e);

#ifdef Q_OS_WIN32
        // make sure that we can still use hotkeys and the mouse wheel
        if (parent()!=NULL) {
                ((QWidget*)parent())->setFocus();
        }
#endif

    //RS_DEBUG->print("QG_GraphicView::mouseMoveEvent end");
}

bool QG_GraphicView::event(QEvent *event) {
#if QT_VERSION >= 0x050200
    if (event->type() == QEvent::NativeGesture) {
        QNativeGestureEvent *nge = static_cast<QNativeGestureEvent *>(event);

        if (nge->gestureType() == Qt::ZoomNativeGesture) {
            double v = nge->value();
            RS2::ZoomDirection direction;
            double factor;

            if (v < 0) {
                direction = RS2::Out;
                factor = 1-v;
            } else {
                direction = RS2::In;
                factor = 1+v;
            }

            // It seems the NativeGestureEvent::pos() incorrectly reports global coordinates
            QPoint g = mapFromGlobal(nge->globalPos());
            RS_Vector mouse = toGraph(RS_Vector(g.x(), g.y()));
            setCurrentAction(new RS_ActionZoomIn(*container, *this, direction,
                                                 RS2::Both, mouse, factor));
        }

        return true;
    }
#endif
	return QWidget::event(event);
}

/**
 * support for the wacom graphic tablet.
 */
void QG_GraphicView::tabletEvent(QTabletEvent* e) {
    if (testAttribute(Qt::WA_UnderMouse)) {
        switch (e->device()) {
        case QTabletEvent::Eraser:
            if (e->type()==QEvent::TabletRelease) {
                if (container!=NULL) {

                    RS_ActionSelectSingle* a =
                        new RS_ActionSelectSingle(*container, *this);
                    setCurrentAction(a);
                    QMouseEvent ev(QEvent::MouseButtonRelease, e->pos(),
                                   Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);//RLZ
                    mouseReleaseEvent(&ev);
                    a->finish();

                    if (container->countSelected()>0) {
                        setCurrentAction(
                            new RS_ActionModifyDelete(*container, *this));
                    }
                }
            }
            break;

        case QTabletEvent::Stylus:
        case QTabletEvent::Puck:
            if (e->type()==QEvent::TabletPress) {
                QMouseEvent ev(QEvent::MouseButtonPress, e->pos(),
                               Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);//RLZ
                mousePressEvent(&ev);
            } else if (e->type()==QEvent::TabletRelease) {
                QMouseEvent ev(QEvent::MouseButtonRelease, e->pos(),
                               Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);//RLZ
                mouseReleaseEvent(&ev);
            } else if (e->type()==QEvent::TabletMove) {
                QMouseEvent ev(QEvent::MouseMove, e->pos(),
                               Qt::NoButton, 0, Qt::NoModifier);//RLZ
                mouseMoveEvent(&ev);
            }
            break;

        default:
            break;
        }
    }

    // a 'mouse' click:
    /*if (e->pressure()>10 && lastPressure<10) {
        QMouseEvent e(QEvent::MouseButtonPress, e->pos(),
           Qt::LeftButton, Qt::LeftButton);
        mousePressEvent(&e);
}
    else if (e->pressure()<10 && lastPressure>10) {
        QMouseEvent e(QEvent::MouseButtonRelease, e->pos(),
           Qt::LeftButton, Qt::LeftButton);
        mouseReleaseEvent(&e);
}	else if (lastPos!=e->pos()) {
        QMouseEvent e(QEvent::MouseMove, e->pos(),
           Qt::NoButton, 0);
        mouseMoveEvent(&e);
}

    lastPressure = e->pressure();
    lastPos = e->pos();
    */
}

void QG_GraphicView::leaveEvent(QEvent* e) {
    RS_GraphicView::mouseLeaveEvent();
    QWidget::leaveEvent(e);
}


void QG_GraphicView::enterEvent(QEvent* e) {
    RS_GraphicView::mouseEnterEvent();
    QWidget::enterEvent(e);
}


void QG_GraphicView::focusOutEvent(QFocusEvent* e) {
    QWidget::focusOutEvent(e);
}


void QG_GraphicView::focusInEvent(QFocusEvent* e) {
    RS_GraphicView::mouseEnterEvent();
    QWidget::focusInEvent(e);
}


/**
 * mouse wheel event. zooms in/out or scrolls when
 * shift or ctrl is pressed.
 */
void QG_GraphicView::wheelEvent(QWheelEvent *e) {
    //RS_DEBUG->print("wheel: %d", e->delta());

    //printf("state: %d\n", e->state());
    //printf("ctrl: %d\n", Qt::ControlButton);

    if (container==NULL) {
        return;
    }

    RS_Vector mouse = toGraph(RS_Vector(e->x(), e->y()));

#if QT_VERSION >= 0x050200
    QPoint numPixels = e->pixelDelta();

    // high-resolution scrolling triggers Pan instead of Zoom logic
    isSmoothScrolling |= !numPixels.isNull();

    if (isSmoothScrolling) {
        if (e->phase() == Qt::ScrollEnd) isSmoothScrolling = false;

        if (!numPixels.isNull()) {
            if (e->modifiers()==Qt::ControlModifier) {
                // Hold ctrl to zoom. 1 % per pixel
                double v = -numPixels.y() / 100.;
                RS2::ZoomDirection direction;
                double factor;

                if (v < 0) {
                    direction = RS2::Out; factor = 1-v;
                } else {
                    direction = RS2::In;  factor = 1+v;
                }

                setCurrentAction(new RS_ActionZoomIn(*container, *this, direction,
                                                     RS2::Both, mouse, factor));
            } else {
                // otherwise, scroll
                setCurrentAction(new RS_ActionZoomScroll(numPixels.x(), numPixels.y(),
                                                         *container, *this));
            }
            redraw();
        }
        e->accept();
        return;
    }
#endif

    if (e->delta() == 0) {
        // A zero delta event occurs when smooth scrolling is ended. Ignore this
        e->accept();
        return;
    }

    bool scroll = false;
    RS2::Direction direction = RS2::Up;

    // scroll up / down:
    if (e->modifiers()==Qt::ControlModifier) {
        scroll = true;
        switch(e->orientation()){
        case Qt::Horizontal:
            direction=(e->delta()>0)?RS2::Left:RS2::Right;
            break;
        default:
        case Qt::Vertical:
            direction=(e->delta()>0)?RS2::Up:RS2::Down;
        }
    }

    // scroll left / right:
    else if	(e->modifiers()==Qt::ShiftModifier) {
        scroll = true;
        switch(e->orientation()){
        case Qt::Horizontal:
            direction=(e->delta()>0)?RS2::Up:RS2::Down;
            break;
        default:
        case Qt::Vertical:
            direction=(e->delta()>0)?RS2::Left:RS2::Right;
        }
    }

    if (scroll) {
        setCurrentAction(new RS_ActionZoomScroll(direction,
                         *container, *this));
    }

    // zoom in / out:
    else if (e->modifiers()==0) {
        if (e->delta()>0) {
            setCurrentAction(new RS_ActionZoomIn(*container, *this,
                                                 RS2::In, RS2::Both,
                                                                                                 mouse));
        } else {
            setCurrentAction(new RS_ActionZoomIn(*container, *this,
                                                 RS2::Out, RS2::Both,
                                                                                                 mouse));
        }
    }

        redraw();

    e->accept();
}


void QG_GraphicView::keyPressEvent(QKeyEvent* e) {
    //if (e->key()==Qt::Key_Control) {
    //	setCtrlPressed(true);
    //}


    if (container==NULL) {
        return;
    }

    bool scroll = false;
    RS2::Direction direction = RS2::Up;

    switch (e->key()) {
    case Qt::Key_Left:
        scroll = true;
        direction = RS2::Right;
        break;
    case Qt::Key_Right:
        scroll = true;
        direction = RS2::Left;
        break;
    case Qt::Key_Up:
        scroll = true;
        direction = RS2::Up;
        break;
    case Qt::Key_Down:
        scroll = true;
        direction = RS2::Down;
        break;
    default:
        scroll = false;
        break;
    }

    if (scroll) {
        setCurrentAction(new RS_ActionZoomScroll(direction,
                         *container, *this));
    }

    RS_GraphicView::keyPressEvent(e);
}


void QG_GraphicView::keyReleaseEvent(QKeyEvent* e) {
    //if (e->key()==Qt::Key_Control) {
    //	setCtrlPressed(false);
    //}
    RS_GraphicView::keyReleaseEvent(e);
}


/**
 * Called whenever the graphic view has changed.
 * Adjusts the scrollbar ranges / steps.
 */
void QG_GraphicView::adjustOffsetControls() {
        static bool running = false;

        if (running) {
                return;
        }

        running = true;

    RS_DEBUG->print("QG_GraphicView::adjustOffsetControls() begin");

    if (container==NULL || hScrollBar==NULL || vScrollBar==NULL) {
        return;
    }

    int ox = getOffsetX();
    int oy = getOffsetY();

    RS_Vector min = container->getMin();
    RS_Vector max = container->getMax();

    // no drawing yet - still allow to scroll
    if (max.x < min.x+1.0e-6 ||
            max.y < min.y+1.0e-6 ||
                max.x > RS_MAXDOUBLE ||
                max.x < RS_MINDOUBLE ||
                min.x > RS_MAXDOUBLE ||
                min.x < RS_MINDOUBLE ||
                max.y > RS_MAXDOUBLE ||
                max.y < RS_MINDOUBLE ||
                min.y > RS_MAXDOUBLE ||
                min.y < RS_MINDOUBLE ) {
        min = RS_Vector(-10,-10);
        max = RS_Vector(100,100);
    }

        int minVal = (int)(-ox-toGuiDX(getWidth())*0.5
                        - QG_SCROLLMARGIN - getBorderLeft());
        int maxVal = (int)(-ox+toGuiDX(getWidth())*0.5
                        + QG_SCROLLMARGIN + getBorderRight());

        hScrollBar->setValue(0);
        if (minVal<=maxVal) {
                hScrollBar->setRange(minVal, maxVal);
        }
    //hScrollBar->setMinValue(minVal);

        //hScrollBar->setMaxValue(maxVal);

        minVal = (int)(oy-toGuiDY(getHeight())*0.5
                        - QG_SCROLLMARGIN - getBorderTop());
        maxVal = (int)(oy+toGuiDY(getHeight())*0.5
                       +QG_SCROLLMARGIN + getBorderBottom());

        if (minVal<=maxVal) {
                vScrollBar->setRange(minVal, maxVal);
        }
    //vScrollBar->setMaxValue((int)(QG_SCROLLMARGIN + getBorderBottom()
     //                             - (min.y * getFactor().y)));


    //vScrollBar->setMinValue((int)(getHeight() -
     //                             max.y * getFactor().y
     //                             - QG_SCROLLMARGIN - getBorderTop()));


    hScrollBar->setPageStep((int)(getWidth()));
    vScrollBar->setPageStep((int)(getHeight()));

    hScrollBar->setValue(-ox);
    vScrollBar->setValue(oy);


    slotHScrolled(-ox);
    slotVScrolled(oy);


    RS_DEBUG->print("H min: %d / max: %d / step: %d / value: %d\n",
                    hScrollBar->minimum(), hScrollBar->maximum(),
                    hScrollBar->pageStep(), ox);
//    DEBUG_HEADER();
    RS_DEBUG->print(/*RS_Debug::D_WARNING, */"V min: %d / max: %d / step: %d / value: %d\n",
                    vScrollBar->minimum(), vScrollBar->maximum(),
                    vScrollBar->pageStep(), oy);

    RS_DEBUG->print("QG_GraphicView::adjustOffsetControls() end");

        running = false;
}


/**
 * override this to adjust controls and widgets that
 * control the zoom factor of the graphic.
 */
void QG_GraphicView::adjustZoomControls() {}


/**
 * Slot for horizontal scroll events.
 */
void QG_GraphicView::slotHScrolled(int value) {
    // Scrollbar behaviour tends to change with every Qt version..
    // so let's keep old code in here for now

    //static int running = false;
    //if (!running) {
    //running = true;
    ////RS_DEBUG->print("value x: %d\n", value);
    if (hScrollBar->maximum()==hScrollBar->minimum()) {
        centerOffsetX();
    } else {
        setOffsetX(-value);
    }
    //if (isUpdateEnabled()) {
//         updateGrid();
    redraw();
}


/**
 * Slot for vertical scroll events.
 */
void QG_GraphicView::slotVScrolled(int value) {
    // Scrollbar behaviour tends to change with every Qt version..
    // so let's keep old code in here for now

    //static int running = false;
    //if (!running) {
    //running = true;
//    DEBUG_HEADER();
    RS_DEBUG->print(/*RS_Debug::D_WARNING,*/ "%s %s(): set vertical offset from %d to %d\n", __FILE__, __FUNCTION__, getOffsetY(), value);
    if (vScrollBar->maximum()==vScrollBar->minimum()) {
        centerOffsetY();
    } else {
        setOffsetY(value);
    }
    //if (isUpdateEnabled()) {
  //  updateGrid();
    redraw();
}
/**
 * @brief setOffset
 * @param ox, offset X
 * @param oy, offset Y
 */
void QG_GraphicView::setOffset(int ox, int oy) {
//    DEBUG_HEADER();
//    qDebug()<<"adjusting offset from ("<<getOffsetX()<<","<<getOffsetY()<<") to ("<<ox<<" , "<<oy<<")";
    RS_GraphicView::setOffset(ox, oy);
    // need to adjust offset control for scrollbars when setting graphicview offset
    adjustOffsetControls();
}

QPixmap* QG_GraphicView::getPixmapForView(QPixmap *pm)
{

        if (pm==NULL) {
                return new QPixmap(getWidth(), getHeight());
        } else if (pm->width()!=getWidth() || pm->height()!=getHeight()) {
                delete pm;
                return new QPixmap(getWidth(), getHeight());
        } else {
                return pm;
        }
}

void QG_GraphicView::layerActivated(RS_Layer *layer) {
    if(m_bUpdateLayer==false) return;
    RS_EntityContainer *container = this->getContainer();
    RS_Entity *entity = container->firstEntity();

    while (entity != NULL) {
        if (entity->isSelected()) {
            entity->setLayer(layer);
        }

        entity = container->nextEntity();
    }

    container->setSelected(false);
    redraw(RS2::RedrawDrawing);
}


/**
 * Handles paint events by redrawing the graphic in this view.
 * usually that's very fast since we only paint the buffer we
 * have from the last call..
 */
void QG_GraphicView::paintEvent(QPaintEvent *) {
    RS_DEBUG->print("QG_GraphicView::paintEvent begin");

        RS_SETTINGS->beginGroup("/Appearance");
    bool draftMode = (bool)RS_SETTINGS->readNumEntry("/DraftMode", 0);
    RS_SETTINGS->endGroup();


        // Re-Create or get the layering pixmaps
        PixmapLayer1=getPixmapForView(PixmapLayer1);
        PixmapLayer2=getPixmapForView(PixmapLayer2);
        PixmapLayer3=getPixmapForView(PixmapLayer3);

    // Draw Layer 1
        if (redrawMethod & RS2::RedrawGrid) {
                PixmapLayer1->fill(background);
                RS_PainterQt painter1(PixmapLayer1);
                //painter1->setBackgroundMode(Qt::OpaqueMode);
                //painter1->setBackgroundColor(background);
                //painter1->eraseRect(0,0,getWidth(), getHeight());
                drawLayer1((RS_Painter*)&painter1);
                painter1.end();
        }


        if (redrawMethod & RS2::RedrawDrawing) {
                // DRaw layer 2
                PixmapLayer2->fill(Qt::transparent);
                RS_PainterQt painter2(PixmapLayer2);
                painter2.setDrawingMode(drawingMode);
                setDraftMode(draftMode);
        painter2.setDrawSelectedOnly(false);
        drawLayer2((RS_Painter*)&painter2);
        painter2.setDrawSelectedOnly(true);
        drawLayer2((RS_Painter*)&painter2);
        //removed to solve bug #3470573
//        setDraftMode(false);
                painter2.end();
        }

    if (redrawMethod & RS2::RedrawOverlay) {
        PixmapLayer3->fill(Qt::transparent);
        RS_PainterQt painter3(PixmapLayer3);
        drawLayer3((RS_Painter*)&painter3);
        painter3.end();
    }

        // Finally paint the layers back on the screen, bitblk to the rescue!
        RS_PainterQt wPainter(this);
        //wPainter.setCompositionMode(QPainter::CompositionMode_Screen);
        wPainter.drawPixmap(0,0,*PixmapLayer1);
        wPainter.drawPixmap(0,0,*PixmapLayer2);
        wPainter.drawPixmap(0,0,*PixmapLayer3);
        wPainter.end();

        redrawMethod=RS2::RedrawNone;
    RS_DEBUG->print("QG_GraphicView::paintEvent end");
}

