Logo Search packages:      
Sourcecode: kbarcode version File versions  Download package

mycanvasview.cpp

/***************************************************************************
                          mycanvasview.cpp  -  description
                             -------------------
    begin                : Die Apr 23 2002
    copyright            : (C) 2002 by Dominik Seichter
    email                : domseichter@web.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "mycanvasview.h"
#include "commands.h"
#include "definition.h"
#include "measurements.h"
#include "kbarcodesettings.h"

// Qt includes
#include <qcursor.h>
#include <qpainter.h>
#include <qpaintdevicemetrics.h>

// KDE includes
#include <kruler.h>
#include <kstatusbar.h>

MyCanvas::MyCanvas( QObject* parent, const char* name )
    : QCanvas( parent, name )
{
    m_grid = false;

    setBackgroundColor( Qt::lightGray );
    
    resize( 0, 0 );
}

MyCanvas::~MyCanvas()
{
}

void MyCanvas::drawBackground( QPainter & painter, const QRect & clip )
{
    QCanvas::drawBackground( painter, clip );

    QRect shadow1( int(m_rect.x() + m_rect.width()), m_rect.y() + 5, 5, m_rect.height() );
    QRect shadow2( m_rect.x()+ 5, int(m_rect.y() + m_rect.height()), m_rect.width(), 5 );

    // draw background shadow
    if( clip.intersects( shadow1 ) )
        painter.fillRect( shadow1, Qt::black );

    if( clip.intersects( shadow2 ) )
        painter.fillRect( shadow2, Qt::black );

    if( clip.intersects( m_rect ) ) {
        painter.fillRect( m_rect, Qt::white );

        if( m_grid ) {
            painter.translate( m_rect.x(), m_rect.y() );

            painter.setPen( QPen( KBarcodeSettings::getInstance()->gridColor(), 0 ) );
            for( int x = 0; x <= m_rect.width(); x += KBarcodeSettings::getInstance()->gridSize() )
                for( int y = 0; y <= m_rect.height(); y += KBarcodeSettings::getInstance()->gridSize() ) {
//                    if( clip.x() < x && clip.x() + clip.height() > x )
                        painter.drawLine( x, 0, x, m_rect.height() );

//                    if( clip.y() < y && clip.y() + clip.width() > y )
                        painter.drawLine( 0, y, m_rect.width(), y );
                }
            painter.translate( -m_rect.x(), -m_rect.y() );
        }
    }
}

MyCanvasView::MyCanvasView( Definition* d, MyCanvas* c, QWidget* parent, const char* name, WFlags f)
    : QCanvasView(c,parent,name,f)
{
    statusbar = 0;
    m_commov = 0;
    canv = c;

    rulerv = new KRuler( Qt::Vertical, this );
    rulerh = new KRuler( Qt::Horizontal, this );
    if( Measurements::measurementSystem() == Measurements::Metric ) {
        rulerv->setRulerMetricStyle( KRuler::Millimetres );
        rulerh->setRulerMetricStyle( KRuler::Millimetres );
    } else {
        rulerv->setRulerMetricStyle( KRuler::Inch );
        rulerh->setRulerMetricStyle( KRuler::Inch );
    }
    rulerv->setMaxValue( 0 );
    rulerh->setMaxValue( 0 );

    viewport()->setMouseTracking( true );
    setDefinition( d );
}

MyCanvasView::~MyCanvasView()
{
}

void MyCanvasView::snapPoint(QPoint * point)
{
    // move item to next grid position
    // TODO: align the top left to the grid not the current mouse position!
    point->setX(point->x() + KBarcodeSettings::getInstance()->gridSize()/2);
    point->setY(point->y() + KBarcodeSettings::getInstance()->gridSize()/2);
    point->setX(point->x() - point->x() % KBarcodeSettings::getInstance()->gridSize());
    point->setY(point->y() - point->y() % KBarcodeSettings::getInstance()->gridSize());
}

void MyCanvasView::contentsMouseMoveEvent(QMouseEvent* e)
{
    rulerh->slotNewValue( e->x() );
    rulerv->slotNewValue( e->y() );

    if( statusbar ) {
        LabelUtils l;
        int x = (int)l.pixelToMm( e->x(), this, LabelUtils::DpiX );
        int y = (int)l.pixelToMm( e->y(), this, LabelUtils::DpiY );
        statusbar->changeItem( i18n("Position: ") +
                        QString( "%1%2 x %3%4" ).arg( x )
                        .arg( Measurements::system() ).arg( y ).arg( Measurements::system()), mouseid );
    }

    updateCursor( e->pos() );

    // if no mouse button is pressed bail out now
    if( !(e->state() & Qt::LeftButton ) ) {
        (void)updateCursor( e->pos(), true );
        return;
    }

    bool shift_pressed = e->state() & Qt::ShiftButton;

    MyCanvasRectangle* moving = getActive();
    if( moving ) {
        QPoint p = inverseWorldMatrix().map(e->pos());

        if( m_mode == Barcode || m_mode == Inside ) {
            QCanvasItemList list = getSelected();
            for( unsigned int i = 0; i < list.count(); i++ ) {
                MyCanvasRectangle* moving = (MyCanvasRectangle*)list[i];
                QPoint new_pt =QPoint(p.x() - delta_pt.x(),p.y() - delta_pt.y());
                if( canv->grid() ) {
                    snapPoint(&new_pt) ;
                }
                // Move the item
                MoveCommand* mv = new MoveCommand( new_pt.x() - (int) moving->x(),
                                                   new_pt.y() - (int) moving->y(), moving );
                mv->execute();
                getMoveCommand()->addCommand( mv );
            }
        } else if( m_mode == LineLeft || m_mode == LineRight ) {
            QPoint a, b;
            MyCanvasLine* line = (MyCanvasLine*)moving;

            if( canv->grid() ) {
                snapPoint(&p) ;
            }
            
            a = m_mode == LineLeft ? p : line->startPoint();
            b = m_mode == LineRight ? p : line->endPoint();

            LineMoveCommand* lmc = new LineMoveCommand( a, b, line );
            lmc->execute();

            getMoveCommand()->addCommand( lmc );
            repaintContents( line->boundingRect() );
        } else {
            
            if( canv->grid() ) {
                snapPoint(&p) ;
            }
            
            ResizeCommand* mv = new ResizeCommand( moving, shift_pressed );
            
            switch( m_mode ) {
                case RightMiddle:
                    mv->setRect( (int) moving->x(), (int) moving->y(), p.x() - (int) moving->x(), moving->height() );
                    break;
                case LeftMiddle:
                    mv->setRect( p.x(), (int) moving->y(), (int) moving->width()+ ((int) moving->x() - p.x()), (int) moving->height() );
                    break;
                case BottomMiddle:
                    mv->setRect( (int) moving->x(), (int) moving->y(), (int) moving->width(), p.y() - (int) moving->y());
                    break;
                case TopMiddle:
                    mv->setRect( (int) moving->x(), p.y(), (int) moving->width(), (int) moving->height()+ ((int) moving->y() - p.y()));
                    break;
                case BottomLeft:
                    mv->setRect( p.x(), (int) moving->y(), (int) moving->width()+ ((int) moving->x() - p.x()), p.y() - (int) moving->y() );
                    break;
                case BottomRight:
                    mv->setRect( (int) moving->x(), (int) moving->y(), p.x() - (int) moving->x(), p.y() - (int) moving->y() );
                    break;
                case TopLeft:
                    mv->setRect( p.x(), p.y(), (int) moving->width()+ ((int) moving->x() - p.x()), (int) moving->height()+ ((int) moving->y() - p.y()));
                    break;
                case TopRight:
                    mv->setRect( (int) moving->x(), p.y(), p.x() - (int) moving->x(),(int) moving->height()+ ((int) moving->y() - p.y()) );
                    break;
                default:
                    break;
            }
            mv->execute();
            getMoveCommand()->addCommand( mv );
        }
        
        moving_start = p;

        emit movedSomething();
    }
}

void MyCanvasView::contentsMousePressEvent(QMouseEvent* e)
{
    setActive( 0, e->state() & Qt::ControlButton  );

    QCanvasItemList list = canvas()->allItems();
    for( int z = MyCanvasView::getLowestZ( list ); z <= MyCanvasView::getHighestZ( list ); z++ )
        for( unsigned int i = 0; i < list.count(); i++ )
            if( list[i]->z() == z && isInside( e->pos(), list[i] ) )
                setActive( (MyCanvasRectangle*)list[i], (e->state() & Qt::ControlButton) );

    if( getActive() ) {
        moving_start = inverseWorldMatrix().map(e->pos());
        m_mode = updateCursor( e->pos() );
        old = getActive()->boundingRect();
        delta_pt=QPoint(e->x() - old.x(),e->y() - old.y());
    }

    if( e->button() == Qt::RightButton && getActive() )
        emit showContextMenu( getActive(), e->globalPos() );
}

void MyCanvasView::contentsMouseReleaseEvent(QMouseEvent* e)
{
    if( e->button() != Qt::LeftButton || getSelected().isEmpty() )
        return;

    if( m_commov ) {
        history->addCommand( getMoveCommand(), false );
        m_commov = 0;
    }

    // TODO: check: is this needed
    if( m_mode == LineLeft || m_mode == LineRight )
        repaintContents();

    updateCursor( e->pos() );
}

KMacroCommand* MyCanvasView::getMoveCommand()
{
    if( !m_commov )
        m_commov = new KMacroCommand( i18n("Item Moved") );

    return m_commov;
}

void MyCanvasView::contentsMouseDoubleClickEvent(QMouseEvent* e)
{
    setActive( 0 );
    QCanvasItemList list = canvas()->allItems();
    for( int z = MyCanvasView::getHighestZ( list ); z >= MyCanvasView::getLowestZ( list ); z-- )    
        for( unsigned int i = 0; i < list.count(); i++ )
            if( list[i]->z() == z && isInside( e->pos(), list[i] ) ) {
                setActive( (MyCanvasRectangle*)list[i] );
                emit doubleClickedItem( getActive() );
                return;
            }
}

bool MyCanvasView::isInside( QPoint p, QCanvasItem* item )
{
    if( !item->isVisible() )
        return false;

    return item->boundingRect().contains( p );
}

int MyCanvasView::isEdge( QPoint p, QCanvasItem* item )
{
    if( !isInside( p, item ) )
        return Outside;

    if( item->rtti() == LINE_RTTI ) {
        MyCanvasLine* line = (MyCanvasLine*)item;

        QRect start( line->startPoint(), QSize( SPOTSIZE, SPOTSIZE ) );
        QRect end( line->endPoint(), QSize( SPOTSIZE, SPOTSIZE ) );

        if( start.contains( p ) )
            return LineLeft;

        if( end.contains( p ) )
            return LineRight;

        return Inside;
    }

    QRect r = item->boundingRect();
    
    int rh = r.y() + r.height();
    int rw = r.x() + r.width();
    if( p.x() > r.x() && p.x() < r.x() + SPOTSIZE ) {
        // Left
        if( p.y() > r.y() && p.y() < r.y() + SPOTSIZE )
            return TopLeft;

        if( p.y() >  rh - SPOTSIZE && p.y() < rh )
            return BottomLeft;

        if( (r.height() - 2 * SPOTSIZE ) / 2 > SPOTSIZE ) {
            // Middle
            int start = ( r.y() + (r.height() - SPOTSIZE)/2 );
            if( p.y() >  start && p.y() < start + SPOTSIZE )
                return LeftMiddle;
        }

    }

    if( p.y() > r.y() && p.y() < r.y() + SPOTSIZE ) {
        // Top
        if( (r.width() - 2 * SPOTSIZE ) / 2 > SPOTSIZE ) {
            // Middle
            int start = ( r.x() + (r.width() - SPOTSIZE)/2 );
            if( p.x() >  start && p.x() < start + SPOTSIZE )
                return TopMiddle;
        }
    }

    if( p.y() > rh - SPOTSIZE && p.y() < rh ) {
        // Bottom
        if( (r.width() - 2 * SPOTSIZE ) / 2 > SPOTSIZE ) {
            // Middle
            int start = ( r.x() + (r.width() - SPOTSIZE)/2 );
            if( p.x() >  start && p.x() < start + SPOTSIZE )
                return BottomMiddle;
        }
    }

    if( p.x() > rw - SPOTSIZE && p.x() < rw ) {
        // Right
        if( p.y() > r.y() && p.y() < r.y() + SPOTSIZE )
            return TopRight;

        if( p.y() >  rh - SPOTSIZE && p.y() < rh )
            return BottomRight;

        if( (r.height() - 2 * SPOTSIZE ) / 2 > SPOTSIZE ) {
            // Middle
            int start = ( r.y() + (r.height() - SPOTSIZE)/2 );
            if( p.y() >  start && p.y() < start + SPOTSIZE )
                return RightMiddle;
        }
    }

    return Inside;
}

void MyCanvasView::deleteCurrent()
{
    if( getActive() ) {
        KMacroCommand* mc = new KMacroCommand( i18n("Delete") );

        QCanvasItemList list = getSelected();
        for( unsigned int i = 0; i < list.count(); i++ ) {
            DeleteCommand* dc = new DeleteCommand( list[i] );
            dc->execute();
            mc->addCommand( dc );
        }
        
        history->addCommand( mc, false );
        setActive( 0 );
        canvas()->update();
    }
}

void MyCanvasView::setCurrent( QCanvasItem* item )
{
    setSelected( item );
    setActive( item );
}

void MyCanvasView::updateRuler()
{
    rulerh->setGeometry( 20, 0, width() - 20, 20 );
    rulerv->setGeometry( 0, 20, 20, height() - 20 );

    if( def ) {
        Measurements* m = def->getMeasurements();
        canv->setRect( QRect( translation.x(), translation.y(), (int)m->width( this ), (int)m->height( this )) );

        rulerv->setMaxValue( height() );
        rulerh->setMaxValue( width() );


        QPaintDeviceMetrics pdm( this );
        if( Measurements::measurementSystem() == Measurements::Metric ) {
            rulerh->setPixelPerMark( (1/ 25.4)* pdm.logicalDpiX() );
            rulerv->setPixelPerMark( (1/25.4)* pdm.logicalDpiY() );
        } 
    }

}

void MyCanvasView::resizeEvent( QResizeEvent * r )
{
    setUpdatesEnabled( false );
    QPoint old = translation;

    Measurements* measure = def->getMeasurements();
    // make sure that there is some space around the label, therefore at 60 pixel
    int w = ( this->width() - 2 > measure->width( this ) ? this->width() - 2 : int(measure->width( this ) + 60) );
    int h = ( this->height() - 2 > measure->height( this ) ? this->height() - 2 : int(measure->height( this ) + 60) );

    canvas()->resize( w, h );
    QCanvasView::resizeEvent( r );

    reposition();
    updateRuler();

    repaintContents();

    old = translation - old;
    QCanvasItemList list = canvas()->allItems();
    for( unsigned int i = 0; i < list.count(); i++ )
        list[i]->moveBy( old.x(), old.y() );

    setUpdatesEnabled( true );
}

void MyCanvasView::reposition()
{
    /*
     * it is difficult to handle the repositioning
     * when a new scaling factor has been set.
     * Therefore we divide by the old factor
     * and multiply with the new one.
     * As a result we have the correct width.
     */

    Measurements* measure = def->getMeasurements();
    int x = int((width() - (measure->width( this ))  ) / 2);
    int y = int((height() - (measure->height( this )) ) / 2);

    // move label 30 pixels away from top/left if necessary
    x = x > 0 ? x : 30;
    y = y > 0 ? y : 30;

    translation = QPoint( x, y );
}

void MyCanvasView::setDefinition( Definition* d )
{
    def = d;
    reposition();
    updateRuler();
    repaintContents( true );
}


int MyCanvasView::getLowestZ( QCanvasItemList list )
{
    int v = 0;
    for( unsigned int i = 0; i < list.count(); i++ )
        if( list[i]->z() < v )
            v = (int)list[i]->z();

    return v;
}

int MyCanvasView::getHighestZ( QCanvasItemList list )
{
    int v = 0;
    for( unsigned int i = 0; i < list.count(); i++ )
        if( list[i]->z() > v )
            v = (int)list[i]->z();

    return v;
}

MyCanvasRectangle* MyCanvasView::getActive()
{
    QCanvasItemList list = canvas()->allItems();
    for( unsigned int i = 0; i < list.count(); i++ )
        if( list[i]->isActive() )
            return (MyCanvasRectangle*)list[i];

    return 0;
}

void MyCanvasView::setActive( QCanvasItem* item, bool control )
{
    emit selectionChanged();
    QCanvasItemList list = canvas()->allItems();
    for( unsigned int i = 0; i < list.count(); i++ )
        list[i]->setActive( false );

    if( item )
        item->setActive( true );

    setSelected( item, control );
}

QCanvasItemList MyCanvasView::getSelected()
{
    QCanvasItemList l;
    QCanvasItemList list = canvas()->allItems();
    for( unsigned int i = 0; i < list.count(); i++ )
        if( list[i]->isSelected() )
            l.append( list[i] );

    return l;
}

void MyCanvasView::setSelected( QCanvasItem* item, bool control )
{
    if( !control ) {
        QCanvasItemList list = canvas()->allItems();
        for( unsigned int i = 0; i < list.count(); i++ )
            list[i]->setSelected( false );
    }

    if( item )
        item->setSelected( true );
}

int MyCanvasView::updateCursor( QPoint pos, bool pressed )
{
    if( !getActive() ) {
        this->setCursor( QCursor::ArrowCursor );
        return -1;
    }

    int mode = isEdge( pos, getActive() );
    if( getActive()->rtti() == BARCODE_RTTI ) {
        pressed && mode != Outside ? setCursor( QCursor::SizeAllCursor ) : setCursor( QCursor::ArrowCursor );
        mode = Barcode;
        return mode;
    }

    switch( mode ) {
        case TopLeft:
        case BottomRight:
            this->setCursor( QCursor::SizeFDiagCursor );
            break;
        case TopMiddle:
        case BottomMiddle:
            this->setCursor( QCursor::SizeVerCursor );
            break;
        case TopRight:
        case BottomLeft:
            this->setCursor( QCursor::SizeBDiagCursor );
            break;
        case LineLeft:
        case LineRight:
        case RightMiddle:
        case LeftMiddle:
            this->setCursor( QCursor::SizeHorCursor );
            break;
        case Inside:
            pressed ? setCursor( QCursor::SizeAllCursor ) : setCursor( QCursor::ArrowCursor );
            break;
        case Outside:
        default:
            this->setCursor( QCursor::ArrowCursor );
            break;
    };

    return mode;
}


Generated by  Doxygen 1.6.0   Back to index