diff options
Diffstat (limited to 'src/modules/dcc/canvaswidget.cpp')
-rw-r--r-- | src/modules/dcc/canvaswidget.cpp | 1601 |
1 files changed, 1601 insertions, 0 deletions
diff --git a/src/modules/dcc/canvaswidget.cpp b/src/modules/dcc/canvaswidget.cpp new file mode 100644 index 00000000..203e0b36 --- /dev/null +++ b/src/modules/dcc/canvaswidget.cpp @@ -0,0 +1,1601 @@ +// +// File : canvaswidget.cpp +// Creation date : Mon Jul 30 07 2001 04:50:50 by Szymon Stefanek +// +// This file is part of the KVirc irc client distribution +// Copyright (C) 2001 Szymon Stefanek (pragma at kvirc dot net) +// +// 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 opinion) any later version. +// +// 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. +// + +#include "canvaswidget.h" + +#ifdef COMPILE_DCC_CANVAS + + +#include <qcursor.h> +#include <qpainter.h> +#include <qsimplerichtext.h> +#include <qlineedit.h> +#include <qcombobox.h> +#include <qvalidator.h> +#include <stdlib.h> + +#include "kvi_string.h" + +#include "kvi_locale.h" +#include "kvi_tal_popupmenu.h" + +#include <math.h> + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviCanvasRectangleItem +// + +KviCanvasRectangleItem::KviCanvasRectangleItem(QCanvas * c,int x,int y,int w,int h) +: QCanvasRectangle(x,y,w,h,c) +{ +} + +KviCanvasRectangleItem::~KviCanvasRectangleItem() +{ +} + +void KviCanvasRectangleItem::drawSelection(QPainter &p) +{ + p.setRasterOp(NotROP); + p.fillRect((int)x() + 1,(int)y() + 1,width() - 2,height() - 2,QBrush(Dense6Pattern)); + p.setPen(QPen(DotLine)); + p.drawRect((int)x(),(int)y(),width(),height()); + p.setRasterOp(CopyROP); +} + + +void KviCanvasRectangleItem::setProperty(const QString &property,const QVariant &val) +{ + if(m_properties[property].isValid()) + { + m_properties.replace(property,val); + hide(); + show(); + } +} + + + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviCanvasPolygon +// + + +KviCanvasPolygon::KviCanvasPolygon(QCanvas * c,int x,int y,QPointArray &pnts,double dScaleFactor) +: QCanvasPolygon(c) +{ + m_properties.insert("clrForeground",QVariant(QColor(0,0,0))); + m_properties.insert("uLineWidth",QVariant((unsigned int)0)); + + m_properties.insert("clrBackground",QVariant(QColor(0,0,0))); + m_properties.insert("bHasBackground",QVariant(false,1)); + + m_dScaleFactor = dScaleFactor; + m_points = pnts; + + resetPoints(); + move(x,y); +} + + +KviCanvasPolygon::~KviCanvasPolygon() +{ +} + +void KviCanvasPolygon::setScaleFactor(double dScaleFactor) +{ + m_dScaleFactor = dScaleFactor; + resetPoints(); +} + +void KviCanvasPolygon::setInternalPoints(const QPointArray &pnts) +{ + m_points = pnts; + resetPoints(); + +} + +void KviCanvasPolygon::resetPoints() +{ + QPointArray scaled(m_points.size()); + for(unsigned int i=0;i<m_points.size();i++) + { + int px; + int py; + m_points.point(i,&px,&py); + px = (int)(px * m_dScaleFactor); + py = (int)(py * m_dScaleFactor); + scaled.setPoint(i,px,py); + } + setPoints(scaled); +} + +int KviCanvasPolygon::rtti() const +{ + return KVI_CANVAS_RTTI_POLYGON; +} + +void KviCanvasPolygon::setProperty(const QString &property,const QVariant &val) +{ + if(m_properties[property].isValid()) + { + m_properties.replace(property,val); + if((property == "clrForeground") || (property == "uLineWidth")) + { + setPen(QPen(m_properties["clrForeground"].asColor(),m_properties["uLineWidth"].toInt())); + } else if((property == "clrBackground") || (property == "bHasBackground")) + { + if(m_properties["bHasBackground"].asBool()) + setBrush(QBrush(m_properties["clrBackground"].asColor())); + else + setBrush(QBrush()); + } else { + hide(); show(); + } + } +} + +void KviCanvasPolygon::draw(QPainter &p) +{ +#if QT_VERSION >= 300 + if(isEnabled()) +#else + if(enabled()) +#endif + { + p.setBrush(brush()); + p.setPen(pen()); + p.drawPolygon(areaPoints()); + } + +#if QT_VERSION >=300 + if(isSelected()) +#else + if(selected()) +#endif + { + p.setRasterOp(NotROP); + p.setPen(QPen(DotLine)); + p.drawPolygon(areaPoints()); + p.setBrush(QBrush()); + double dVal = 10; + p.drawEllipse((int)(x() - dVal),(int)(y() - dVal),(int)(dVal * 2),(int)(dVal * 2)); + p.drawLine((int)(x() - (dVal * 2)),(int)y(),(int)(x() + (dVal * 2)),(int)y()); + p.drawLine((int)x(),(int)(y() - (dVal * 2)),(int)x(),(int)(y() + (dVal * 2))); + p.setRasterOp(CopyROP); + canvas()->setChanged(QRect((int)(x() - dVal),(int)(y() - dVal),(int)(dVal * 4),(int)(dVal * 4))); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviCanvasEllipticItem +// + +KviCanvasEllipticItem::KviCanvasEllipticItem(QCanvas * c,int x,int y,int w,int h) +: KviCanvasRectangleItem(c,x,y,w,h) +{ + m_properties.insert("clrForeground",QVariant(QColor(0,0,0))); + m_properties.insert("uLineWidth",QVariant((unsigned int)0)); + + m_properties.insert("clrBackground",QVariant(QColor(0,0,0))); + m_properties.insert("bHasBackground",QVariant(false,1)); + +// m_properties.insert("iStartAngle",QVariant(0)); +// m_properties.insert("iEndAngle",QVariant(360)); +} + +KviCanvasEllipticItem::~KviCanvasEllipticItem() +{ +} + +void KviCanvasEllipticItem::draw(QPainter &p) +{ +#if QT_VERSION >= 300 + if(isEnabled()) +#else + if(enabled()) +#endif + { + QBrush b = p.brush(); + if(m_properties["bHasBackground"].asBool())p.setBrush(m_properties["clrBackground"].asColor()); + else p.setBrush(QBrush()); + p.setPen(pen()); + drawContent(p); + p.setBrush(b); + } + +#if QT_VERSION >= 300 + if(isSelected())drawSelection(p); +#else + if(selected())drawSelection(p); +#endif +} + +void KviCanvasEllipticItem::drawContent(QPainter &p) +{ +} + + +void KviCanvasEllipticItem::setProperty(const QString & property,const QVariant &val) +{ + if(m_properties[property].isValid()) + { + m_properties.replace(property,val); + if((property == "clrForeground") || (property == "uLineWidth")) + { + setPen(QPen(m_properties["clrForeground"].asColor(),m_properties["uLineWidth"].toInt())); + } else { + hide(); show(); + } + } +} + +int KviCanvasEllipticItem::rtti() const +{ + return KVI_CANVAS_RTTI_ELLIPSE; +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviCanvasEllipse +// + + +KviCanvasEllipse::KviCanvasEllipse(QCanvas * c,int x,int y,int w,int h) +: KviCanvasEllipticItem(c,x,y,w,h) +{ +} + +KviCanvasEllipse::~KviCanvasEllipse() +{ +} + +int KviCanvasEllipse::rtti() const +{ + return KVI_CANVAS_RTTI_ELLIPSE; +} + +void KviCanvasEllipse::drawContent(QPainter &p) +{ + p.drawEllipse((int)x(),(int)y(),width(),height()); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviCanvasPie +// + + +KviCanvasPie::KviCanvasPie(QCanvas * c,int x,int y,int w,int h) +: KviCanvasEllipticItem(c,x,y,w,h) +{ + m_properties.insert("iStartAngle",QVariant((int)0)); + m_properties.insert("iExtensionAngle",QVariant((int)360)); +} + +KviCanvasPie::~KviCanvasPie() +{ +} + +int KviCanvasPie::rtti() const +{ + return KVI_CANVAS_RTTI_PIE; +} + +void KviCanvasPie::drawContent(QPainter &p) +{ + int iStartAngle = m_properties["iStartAngle"].asInt() * 16; + int iEndAngle = m_properties["iExtensionAngle"].asInt() * 16; + p.drawPie((int)x(),(int)y(),width(),height(),iStartAngle,iEndAngle); +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviCanvasChord +// + + +KviCanvasChord::KviCanvasChord(QCanvas * c,int x,int y,int w,int h) +: KviCanvasEllipticItem(c,x,y,w,h) +{ + m_properties.insert("iStartAngle",QVariant((int)0)); + m_properties.insert("iExtensionAngle",QVariant((int)360)); +} + +KviCanvasChord::~KviCanvasChord() +{ +} + +int KviCanvasChord::rtti() const +{ + return KVI_CANVAS_RTTI_CHORD; +} + +void KviCanvasChord::drawContent(QPainter &p) +{ + int iStartAngle = m_properties["iStartAngle"].asInt() * 16; + int iEndAngle = m_properties["iExtensionAngle"].asInt() * 16; + p.drawChord((int)x(),(int)y(),width(),height(),iStartAngle,iEndAngle); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviCanvasRectangle +// + +KviCanvasRectangle::KviCanvasRectangle(QCanvas * c,int x,int y,int w,int h) +: KviCanvasRectangleItem(c,x,y,w,h) +{ + m_properties.insert("clrForeground",QVariant(QColor(0,0,0))); + m_properties.insert("uLineWidth",QVariant((unsigned int)0)); + + m_properties.insert("clrBackground",QVariant(QColor(0,0,0))); + m_properties.insert("bHasBackground",QVariant(false,1)); +} + +KviCanvasRectangle::~KviCanvasRectangle() +{ +} + +int KviCanvasRectangle::rtti() const +{ + return KVI_CANVAS_RTTI_RECTANGLE; +} + + +void KviCanvasRectangle::setProperty(const QString &property,const QVariant &val) +{ + if(m_properties[property].isValid()) + { + m_properties.replace(property,val); + if((property == "clrForeground") || (property == "uLineWidth")) + { + setPen(QPen(m_properties["clrForeground"].asColor(),m_properties["uLineWidth"].toInt())); + } else { + hide(); show(); + } + } +} + +void KviCanvasRectangle::draw(QPainter & p) +{ +#if QT_VERSION >= 300 + if(isEnabled()) +#else + if(enabled()) +#endif + { + if(m_properties["bHasBackground"].asBool()) + { + p.fillRect((int)x() + 1,(int)y() + 1,width() - 2,height() - 2,m_properties["clrBackground"].asColor()); + } + p.setPen(pen()); + p.drawRect((int)x(),(int)y(),width(),height()); + } +#if QT_VERSION >= 300 + if(isSelected())drawSelection(p); +#else + if(selected())drawSelection(p); +#endif +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviCanvasRichText +// + +KviCanvasRichText::KviCanvasRichText(QCanvas * c,int x,int y,int w,int h) +: KviCanvasRectangleItem(c,x,y,w,h) +{ + QFont f = QFont(); + f.setStyleHint(QFont::SansSerif); + f.setPointSize(12); + m_properties.insert("szText",QVariant(QString("<center>Insert here your <font color=\"#FF0000\"><b>RICH TEXT</b></font></center>"))); + m_properties.insert("fntDefault",QVariant(f)); +} + +KviCanvasRichText::~KviCanvasRichText() +{ +} + +int KviCanvasRichText::rtti() const +{ + return KVI_CANVAS_RTTI_RICHTEXT; +} + +void KviCanvasRichText::draw(QPainter & p) +{ +#if QT_VERSION >= 300 + if(isEnabled()) +#else + if(enabled()) +#endif + { + QString szText = m_properties["szText"].asString(); + QSimpleRichText text(szText,m_properties["fntDefault"].asFont()); + text.setWidth(width()); +#if QT_VERSION >= 300 + text.draw(&p,(int)x() + 1,(int)y() + 1,QRegion(QRect((int)x() + 1,(int)y() + 1,width(),height())),QColorGroup()); +#else + text.draw(&p,(int)x() + 1,(int)y() + 1,QRegion(QRect((int)x() + 1,(int)y() + 1,width(),height())),QPalette()); +#endif + } +#if QT_VERSION >= 300 + if(isSelected())drawSelection(p); +#else + if(selected())drawSelection(p); +#endif +} + + + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviCanvasLine +// + + +KviCanvasLine::KviCanvasLine(QCanvas * c,int x1,int y1,int x2,int y2) +: QCanvasLine(c) +{ + setPoints(x1,y1,x2,y2); + m_properties.insert("uLineWidth",QVariant((unsigned int)0)); + m_properties.insert("clrForeground",QVariant(QColor())); +} + +KviCanvasLine::~KviCanvasLine() +{ +} + +void KviCanvasLine::setProperty(const QString &property,const QVariant &val) +{ + m_properties.replace(property,val); + if((property == "uLineWidth") || (property == "clrForeground")) + { + setPen(QPen(m_properties["clrForeground"].asColor(),m_properties["uLineWidth"].toInt())); + } +} + +int KviCanvasLine::rtti() const +{ + return KVI_CANVAS_RTTI_LINE; +} + +void KviCanvasLine::draw(QPainter &p) +{ +#if QT_VERSION >= 300 + if(isEnabled()) +#else + if(enabled()) +#endif + { + p.setPen(pen()); + p.drawLine(startPoint(),endPoint()); + } + +#if QT_VERSION >= 300 + if(isSelected()) +#else + if(selected()) +#endif + { + p.setRasterOp(NotROP); + p.setPen(QPen(DotLine)); + p.drawLine(startPoint(),endPoint()); + p.setRasterOp(CopyROP); + } +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviCanvasView +// + +KviCanvasView::KviCanvasView(QCanvas * c,KviCanvasWidget * cw,QWidget * par) +: QCanvasView(c,par) +{ + m_pCanvasWidget = cw; + m_state = Idle; + m_dragMode = None; + m_pSelectedItem = 0; + viewport()->setMouseTracking(true); +} + + +KviCanvasView::~KviCanvasView() +{ +} + + +void KviCanvasView::insertRectangle() +{ + m_state = SelectOrigin; + setCursor(crossCursor); + m_objectToInsert = Rectangle; +} + +void KviCanvasView::insertRichText() +{ + m_state = SelectOrigin; + setCursor(crossCursor); + m_objectToInsert = RichText; +} + +void KviCanvasView::insertLine() +{ + m_state = SelectOrigin; + setCursor(crossCursor); + m_objectToInsert = Line; +} + +void KviCanvasView::insertEllipse() +{ + m_state = SelectOrigin; + setCursor(crossCursor); + m_objectToInsert = Ellipse; +} + +void KviCanvasView::insertPie() +{ + m_state = SelectOrigin; + setCursor(crossCursor); + m_objectToInsert = Pie; +} + +void KviCanvasView::insertChord() +{ + m_state = SelectOrigin; + setCursor(crossCursor); + m_objectToInsert = Chord; +} + + +void KviCanvasView::insertPolygonTriangle() +{ + m_state = SelectOrigin; + setCursor(crossCursor); + m_objectToInsert = PolygonTriangle; +} + + +void KviCanvasView::insertPolygonRectangle() +{ + m_state = SelectOrigin; + setCursor(crossCursor); + m_objectToInsert = PolygonRectangle; +} + + +void KviCanvasView::insertPolygonPentagon() +{ + m_state = SelectOrigin; + setCursor(crossCursor); + m_objectToInsert = PolygonPentagon; +} + +void KviCanvasView::insertPolygonHexagon() +{ + m_state = SelectOrigin; + setCursor(crossCursor); + m_objectToInsert = PolygonPentagon; +} + +#ifndef M_PI + #define M_PI 3.14159265358979323846 +#endif + +static void calcPolygonPoints(QPointArray &pnts,unsigned int nVertices) +{ + double dDelta = (2 * M_PI) / nVertices; + for(unsigned int i=0;i<nVertices;i++) + { + double dAng = dDelta * i; + double theX = 300 * sin(dAng); + double theY = 300 * cos(dAng); + pnts.setPoint(i,(int)theX,(int)theY); + } +} + +void KviCanvasView::insertObjectAt(const QPoint & pnt,ObjectType o) +{ + QCanvasItem * r = 0; + + switch(o) + { + case Rectangle: + r = new KviCanvasRectangle(canvas(),pnt.x(),pnt.y(),0,0); + break; + case RichText: + r = new KviCanvasRichText(canvas(),pnt.x(),pnt.y(),0,0); + break; + case Line: + r = new KviCanvasLine(canvas(),pnt.x(),pnt.y(),pnt.x(),pnt.y()); + break; + case Ellipse: + r = new KviCanvasEllipse(canvas(),pnt.x(),pnt.y(),0,0); + break; + case Pie: + r = new KviCanvasPie(canvas(),pnt.x(),pnt.y(),0,0); + break; + case Chord: + r = new KviCanvasChord(canvas(),pnt.x(),pnt.y(),0,0); + break; + case PolygonTriangle: + { + QPointArray pa(3); + pa.setPoint(0,0,-500); + pa.setPoint(1,-450,220); + pa.setPoint(2,450,220); + r = new KviCanvasPolygon(canvas(),pnt.x(),pnt.y(),pa,0.1); + } + break; + case PolygonRectangle: + { + QPointArray pa(4); + pa.setPoint(0,-350,-350); + pa.setPoint(1,350,-350); + pa.setPoint(2,350,350); + pa.setPoint(3,-350,350); + r = new KviCanvasPolygon(canvas(),pnt.x(),pnt.y(),pa,0.1); + } + break; + case PolygonPentagon: + { + QPointArray pa(5); + calcPolygonPoints(pa,5); + r = new KviCanvasPolygon(canvas(),pnt.x(),pnt.y(),pa,0.1); + } + break; + case PolygonHexagon: + { + QPointArray pa(6); + calcPolygonPoints(pa,6); + r = new KviCanvasPolygon(canvas(),pnt.x(),pnt.y(),pa,0.1); + } + break; + } + + if(r) + { + setItemSelected(r); + r->setEnabled(true); + r->show(); + } + + switch(KVI_CANVAS_RTTI_CONTROL_TYPE(r)) + { + case KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE: + beginDragRectangle((KviCanvasRectangleItem *)r,pnt,true); + break; + case KVI_CANVAS_RTTI_CONTROL_TYPE_LINE: + beginDragLine((KviCanvasLine *)r,pnt,true); + break; +// case KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON: +// beginDragPolygon((KviCanvasPolygon *)r,pnt,true); +// break; + } + +// canvas()->update(); +} + +void KviCanvasView::setItemSelected(QCanvasItem * it) +{ + clearSelection(); + it->setSelected(true); + m_pSelectedItem = it; + m_pCanvasWidget->m_pPropertiesWidget->editItem(it); + +} + +void KviCanvasView::clearSelection() +{ + if(!m_pSelectedItem)return; + m_pSelectedItem->setSelected(false); + m_pSelectedItem = 0; + m_pCanvasWidget->m_pPropertiesWidget->editItem(0); +} + + + +void KviCanvasView::beginDragLine(KviCanvasLine * it,const QPoint &p,bool bInitial) +{ + QPoint sp = it->startPoint(); + + m_dragBegin = p - sp; + + if(bInitial) + { + m_dragMode = Bottom; + setCursor(sizeAllCursor); + return; + } + + if((abs(p.x() - sp.x()) < 3) && (abs(p.y() - sp.y()) < 3)) + { + m_dragMode = Top; + setCursor(sizeAllCursor); + return; + } + + sp = it->endPoint(); + if((abs(p.x() - sp.x()) < 3) && (abs(p.y() - sp.y()) < 3)) + { + m_dragMode = Bottom; + setCursor(sizeAllCursor); + return; + } + + m_dragMode = All; + setCursor(pointingHandCursor); +} + +void KviCanvasView::dragLine(KviCanvasLine * it,const QPoint &p) +{ + switch(m_dragMode) + { + case Bottom: + { + QPoint sp = it->startPoint(); + it->setPoints(sp.x(),sp.y(),p.x(),p.y()); + } + break; + case Top: + { + QPoint ep = it->endPoint(); + it->setPoints(p.x(),p.y(),ep.x(),ep.y()); + } + break; + case All: + { + QPoint sp = p - m_dragBegin; + QPoint ep = sp + (it->endPoint() - it->startPoint()); + it->setPoints(sp.x(),sp.y(),ep.x(),ep.y()); + } + break; + default: /* make gcc happy */ + break; + } + canvas()->update(); +} + + +static double ssm_2d_rotationAngleFromXAxis(double dx,double dy) +{ + // + // v1 . v2 dx * 1 + dy * 0 dx + //acos(---------) = acos(-----------------) = acos(---------) + // |v1||v2| |(dx,dy)| * 1 |(dx,dy)| + // + + //double dVal = hypot(dx,dy); + double dVal = sqrt((dx * dx) + (dy * dy)); + + if(dVal == 0.0)return 0; // ??? + + dVal = acos(dx / dVal); + + return (dy > 0.0) ? dVal : -dVal; +} + +static double ssm_2d_rotationAngle(double drefx,double drefy,double drotatedx,double drotatedy) +{ + double dRefAngle = ssm_2d_rotationAngleFromXAxis(drefx,drefy); + double dRotAngle = ssm_2d_rotationAngleFromXAxis(drotatedx,drotatedy); + return dRotAngle - dRefAngle; +} + +static void ssm_2d_rotate(double &dx,double &dy,double dAngle) +{ + // Rotation matrix: + // + // | cos(x) sin(x) | + // | | + // | -sin(x) cos(x) | + + double s = sin(dAngle); + double c = cos(dAngle); + + double tmpX = (dx * c) - (dy * s); + double tmpY = (dx * s) + (dy * c); + + dx = tmpX; + dy = tmpY; +} + +static double ssm_hypot(double a,double b) +{ + return sqrt((a * a) + (b * b)); +} + +void KviCanvasView::beginDragPolygon(KviCanvasPolygon * it,const QPoint &p,bool bShift,bool bCtrl) +{ + m_dragBegin = QPoint((int)(p.x() - it->x()),(int)(p.y() - it->y())); + + QPointArray pa = it->areaPoints(); + + for(unsigned int i=0;i<pa.size();i++) + { + QPoint pnt = pa.point(i); + double dX = pnt.x() - p.x(); + double dY = pnt.y() - p.y(); + double dHypot = sqrt((dX * dX) + (dY * dY)); + if(dHypot < 3.0) + { + // We're dragging a point + m_dragMode = SinglePoint; + m_dragPointIndex = i; + setCursor(crossCursor); + return; + } + } + + if(bShift) + { + m_dragMode = Scale; + m_dragScaleFactor = it->scaleFactor(); + setCursor(sizeAllCursor); + return; + } + + if(bCtrl) + { + m_dragMode = Rotate; + m_dragPointArray = it->internalPoints(); +// debug("Here"); + setCursor(sizeHorCursor); + return; + } + + m_dragMode = All; + setCursor(pointingHandCursor); +} + +void KviCanvasView::dragPolygon(KviCanvasPolygon * it,const QPoint &p) +{ + switch(m_dragMode) + { + case All: + it->move(p.x() - m_dragBegin.x(),p.y() - m_dragBegin.y()); + break; + case SinglePoint: + { + QPointArray pnt = it->internalPoints(); + pnt.setPoint(m_dragPointIndex,(int)((p.x() - it->x()) / it->scaleFactor()),(int)((p.y() - it->y()) / it->scaleFactor())); + it->setInternalPoints(pnt); + } + break; + case Scale: + { + double dDistance = ssm_hypot(p.x() - it->x(),p.y() - it->y()); + double dOriginal = ssm_hypot(m_dragBegin.x(),m_dragBegin.y()); + if(dOriginal < 1)dOriginal = 1; + if(dDistance < 0.1)dDistance = 0.1; + it->setScaleFactor(m_dragScaleFactor * dDistance / dOriginal); + } + break; + case Rotate: + { + QPoint act((int)(p.x() - it->x()),(int)(p.y() - it->y())); + double dAngle = ssm_2d_rotationAngle(m_dragBegin.x(),m_dragBegin.y(),act.x(),act.y()); +// debug("%d,%d %d,%d %f",m_dragBegin.x(),m_dragBegin.y(),act.x(),act.y(),dAngle); + QPointArray thePoints = m_dragPointArray.copy(); + for(unsigned int i=0;i<thePoints.size();i++) + { + QPoint tmp = thePoints.point(i); + double dx = tmp.x(); + double dy = tmp.y(); + ssm_2d_rotate(dx,dy,dAngle); + thePoints.setPoint(i,(int)dx,(int)dy); + } + it->setInternalPoints(thePoints); + } + break; + default: + break; + } + canvas()->update(); +} + +void KviCanvasView::beginDragRectangle(KviCanvasRectangleItem * it,const QPoint & p,bool bInitial) +{ + m_dragBegin = QPoint((int)(p.x() - it->x()),(int)(p.y() - it->y())); + + if(bInitial) + { + // Right bottom + m_dragMode = RightBottom; + setCursor(sizeFDiagCursor); + return; + } + + if(p.x() < (((int)it->x()) + 2)) + { + // Left edge + if(p.y() < (((int)it->y()) + 2)) + { + // Left top + m_dragMode = LeftTop; + setCursor(sizeFDiagCursor); + return; + } + if(p.y() > ( it->bottom() - 2)) + { + // Left bottom + m_dragMode = LeftBottom; + setCursor(sizeBDiagCursor); + return; + } + m_dragMode = Left; + setCursor(sizeHorCursor); + return; + } + + if(p.x() > (it->right() - 2)) + { + // Right edge + if(p.y() < (((int)it->y()) + 2)) + { + // Right top + m_dragMode = RightTop; + setCursor(sizeBDiagCursor); + return; + } + if(p.y() > ( it->bottom() - 2)) + { + // Right bottom + m_dragMode = RightBottom; + setCursor(sizeFDiagCursor); + return; + } + m_dragMode = Right; + setCursor(sizeHorCursor); + return; + } + + // Somewhere in the middle + if(p.y() < (((int)it->y()) + 2)) + { + // Top + m_dragMode = Top; + setCursor(sizeVerCursor); + return; + } + if(p.y() > ( it->bottom() - 2)) + { + // Bottom + m_dragMode = Bottom; + setCursor(sizeVerCursor); + return; + } + + m_dragMode = All; + setCursor(pointingHandCursor); +} + +void KviCanvasView::dragRectangle(KviCanvasRectangleItem * it,const QPoint & p) +{ + + int aux1,aux2,aux3,aux4; + + switch(m_dragMode) + { + case All: + it->move(p.x() - m_dragBegin.x(),p.y() - m_dragBegin.y()); + break; + case Left: + aux1 = it->width() + (int)(it->x() - p.x()); + aux2 = p.x(); + if(aux1 < 1) + { + aux2 += (aux1 - 1); + aux1 = 1; + } + it->move(aux2,it->y()); + it->setSize(aux1,it->height()); + break; + case Right: + aux1 = it->width() + (p.x() - it->right()); + if(aux1 < 1)aux1 = 1; + it->setSize(aux1,it->height()); + break; + case Top: + aux1 = it->height() + (int)(it->y() - p.y()); + aux2 = p.y(); + if(aux1 < 1) + { + aux2 += (aux1 - 1); + aux1 = 1; + } + it->move(it->x(),aux2); + it->setSize(it->width(),aux1); + break; + case Bottom: + aux1 = (int)it->height() + (p.y() - it->bottom()); + if(aux1 < 1)aux1 = 1; + it->setSize(it->width(),aux1); + break; + case LeftTop: + aux1 = it->width() + (int)(it->x() - p.x()); + aux3 = p.x(); + if(aux1 < 1) + { + aux3 += (aux1 - 1); + aux1 = 1; + } + aux2 = it->height() + (int)(it->y() - p.y()); + aux4 = p.y(); + if(aux2 < 1) + { + aux4 += (aux2 - 1); + aux2 = 1; + } + it->setSize(aux1,aux2); + it->move(aux3,aux4); + break; + case RightTop: + aux1 = it->width() + (int)(p.x() - it->right()); + if(aux1 < 1)aux1 = 1; + aux2 = it->height() + (int)(it->y() - p.y()); + aux4 = p.y(); + if(aux2 < 1) + { + aux4 += (aux2 - 1); + aux2 = 1; + } + it->setSize(aux1,aux2); + it->move(it->x(),aux4); + break; + case LeftBottom: + aux1 = it->width() + (int)(it->x() - p.x()); + aux3 = p.x(); + if(aux1 < 1) + { + aux3 += (aux1 - 1); + aux1 = 1; + } + aux2 = it->height() + (int)(p.y() - it->bottom()); + if(aux2 < 1)aux2 = 1; + it->setSize(aux1,aux2); + it->move(aux3,it->y()); + break; + case RightBottom: + aux1 = it->width() + (int)(p.x() - it->right()); + if(aux1 < 1)aux1 = 1; + aux2 = it->height() + (int)(p.y() - it->bottom()); + if(aux2 < 1)aux2 = 1; + it->setSize(aux1,aux2); + break; + default: + break; + } + + canvas()->update(); +} + +void KviCanvasView::contentsMouseMoveEvent(QMouseEvent *e) +{ +// QPoint p = inverseWorldMatrix().map(e->pos()); + QPoint p = e->pos(); + if(e->state() & Qt::LeftButton) + { + if((m_dragMode != None) && (m_pSelectedItem)) + { +#if QT_VERSION >= 300 + if(m_pSelectedItem->isEnabled())m_pSelectedItem->setEnabled(false); +#else + if(m_pSelectedItem->enabled())m_pSelectedItem->setEnabled(false); +#endif + switch(KVI_CANVAS_RTTI_CONTROL_TYPE(m_pSelectedItem)) + { + case KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE: + dragRectangle((KviCanvasRectangleItem *)m_pSelectedItem,p); + break; + case KVI_CANVAS_RTTI_CONTROL_TYPE_LINE: + dragLine((KviCanvasLine *)m_pSelectedItem,p); + break; + case KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON: + dragPolygon((KviCanvasPolygon *)m_pSelectedItem,p); + break; + } + } + } else { + // Without buttons + if(m_state == Idle) + { + QCanvasItemList l = canvas()->collisions(p); + QCanvasItemList::Iterator it = l.begin(); + + if(it != l.end()) + { + // Got an item + QCanvasItem * hit = (QCanvasItem *)*it; + // Now find the point on that we have clicked it + if(hit == m_pSelectedItem) + { + switch(KVI_CANVAS_RTTI_CONTROL_TYPE(m_pSelectedItem)) + { + case KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE: + beginDragRectangle((KviCanvasRectangleItem *)m_pSelectedItem,p); + break; + case KVI_CANVAS_RTTI_CONTROL_TYPE_LINE: + beginDragLine((KviCanvasLine *)m_pSelectedItem,p); + break; + case KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON: + beginDragPolygon((KviCanvasPolygon *)m_pSelectedItem,p); + break; + } + } + else if(m_dragMode != None)setCursor(arrowCursor); + } else { + if(m_dragMode != None)setCursor(arrowCursor); + } + } + } +} + +void KviCanvasView::contentsMouseReleaseEvent(QMouseEvent *e) +{ + if(m_dragMode != None) + { + // Was just dragging a rectangle + m_dragMode = None; + setCursor(arrowCursor); + if(m_pSelectedItem) + { + m_pSelectedItem->setEnabled(true); + canvas()->update(); + } + } +} + +void KviCanvasView::contentsMousePressEvent(QMouseEvent *e) +{ + if(e->button() & Qt::LeftButton) + { +// QPoint p = inverseWorldMatrix().map(e->pos()); + QPoint p = e->pos(); + + switch(m_state) + { + case SelectOrigin: + clearSelection(); + setCursor(arrowCursor); + m_state = Idle; + insertObjectAt(p,m_objectToInsert); + canvas()->update(); + break; + + case Idle: + { + QCanvasItemList l = canvas()->collisions(p); + QCanvasItemList::Iterator it = l.begin(); + + if(it != l.end()) + { + // Got an item + QCanvasItem * hit = *it; + if(hit != m_pSelectedItem) + { + // Was not selected yet + setItemSelected(hit); + canvas()->update(); + } + // Now find the point on that we have clicked it + switch(KVI_CANVAS_RTTI_CONTROL_TYPE(hit)) + { + case KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE: + beginDragRectangle(((KviCanvasRectangleItem *)hit),p); + break; + case KVI_CANVAS_RTTI_CONTROL_TYPE_LINE: + beginDragLine(((KviCanvasLine *)hit),p); + break; + case KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON: + beginDragPolygon(((KviCanvasPolygon *)hit),p,e->state() & Qt::ShiftButton,e->state() & Qt::ControlButton); + break; + } + } else { + // No item + clearSelection(); + canvas()->update(); + } + } + break; + } + } +} + + +void KviCanvasView::propertyChanged(const QString &s,const QVariant &v) +{ + if(!m_pSelectedItem)return; + + + switch(KVI_CANVAS_RTTI_CONTROL_TYPE(m_pSelectedItem)) + { + case KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE: + ((KviCanvasRectangleItem *)m_pSelectedItem)->setProperty(s,v); + break; + case KVI_CANVAS_RTTI_CONTROL_TYPE_LINE: + ((KviCanvasLine *)m_pSelectedItem)->setProperty(s,v); + break; + case KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON: + ((KviCanvasPolygon *)m_pSelectedItem)->setProperty(s,v); + break; + } + + canvas()->update(); +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviVariantTableItem +// + + + +KviVariantTableItem::KviVariantTableItem(QTable * t,const QVariant & property) +: QTableItem(t,QTableItem::WhenCurrent,QString::null) +{ + m_property = property; +} + +KviVariantTableItem::~KviVariantTableItem() +{ +} + + +QWidget * KviVariantTableItem::createEditor() const +{ + switch(m_property.type()) + { + case QVariant::String: + { + QLineEdit * e = new QLineEdit(table()->viewport()); + e->setText(m_property.toString()); + return e; + } + break; + case QVariant::Int: + { + QLineEdit * e = new QLineEdit(table()->viewport()); + QString sz; + sz.setNum(m_property.toInt()); + e->setText(sz); + e->setValidator(new QIntValidator(e)); + return e; + } + break; + case QVariant::UInt: + { + QLineEdit * e = new QLineEdit(table()->viewport()); + QString sz; + sz.setNum(m_property.toInt()); + e->setText(sz); + QIntValidator * i = new QIntValidator(e); + i->setBottom(0); + e->setValidator(i); + return e; + } + break; + case QVariant::Bool: + { + QComboBox * b = new QComboBox(false,table()->viewport()); + b->insertItem("FALSE"); + b->insertItem("TRUE"); + b->setCurrentItem(m_property.toBool() ? 1 : 0); + return b; + } + break; + case QVariant::Color: + { + QLineEdit * e = new QLineEdit(table()->viewport()); + e->setText(m_property.toColor().name()); + return e; + } + break; + case QVariant::Font: + { + QComboBox * b = new QComboBox(true,table()->viewport()); + + QString tmp; + QString tmpDefault; + QFont f = QFont(); + f.setStyleHint(QFont::SansSerif); + tmpDefault = f.family(); + f.setStyleHint(QFont::TypeWriter); + tmp.setNum(m_property.toFont().pointSize()); + tmp.prepend(", "); + tmp.prepend(m_property.toFont().family()); + b->insertItem(tmp); + b->insertItem(tmpDefault + ", 8"); + b->insertItem(tmpDefault + ", 10"); + b->insertItem(tmpDefault + ", 12"); + b->insertItem(tmpDefault + ", 14"); + b->insertItem(tmpDefault + ", 16"); + b->insertItem(tmpDefault + ", 18"); + b->insertItem(tmpDefault + ", 20"); + b->insertItem(tmpDefault + ", 24"); + b->insertItem(tmpDefault + ", 28"); + b->insertItem(tmpDefault + ", 32"); + b->insertItem(tmpDefault + ", 40"); + b->insertItem(tmpDefault + ", 48"); + b->insertItem(f.family() + ", 12"); + b->setCurrentItem(0); + + b->setCurrentItem(m_property.toBool() ? 1 : 0); + return b; + } + break; + default: + break; + } + return 0; +} + +void KviVariantTableItem::setContentFromEditor(QWidget * w) +{ + switch(m_property.type()) + { + case QVariant::String: + m_property = QVariant(((QLineEdit *)w)->text()); + break; + case QVariant::Int: + m_property = QVariant(((QLineEdit *)w)->text().toInt()); + break; + case QVariant::UInt: + m_property = QVariant(((QLineEdit *)w)->text().toUInt()); + break; + case QVariant::Bool: + m_property = QVariant(((QComboBox *)w)->currentItem(),1); + break; + case QVariant::Color: + m_property.asColor().setNamedColor(((QLineEdit *)w)->text()); + break; + case QVariant::Font: + { + KviStr txt = ((QComboBox *)w)->currentText(); + if(txt.hasData()) + { + KviStr fam = txt; + fam.cutFromFirst(',',true); + fam.stripWhiteSpace(); + KviStr psz = txt; + psz.cutToFirst(',',true); + psz.stripWhiteSpace(); + bool bOk; + unsigned int uSize = psz.toUInt(&bOk); + if(!bOk)uSize = 12; + m_property = QVariant(QFont(fam.ptr(),uSize)); + } + + } + break; + default: + break; + } +} + + +void KviVariantTableItem::paint(QPainter *p,const QColorGroup &cg,const QRect &cr,bool) +{ + p->fillRect(0,0,cr.width(),cr.height(),cg.base()); + + if(m_property.type() == QVariant::Color) + { + p->fillRect(3,3,cr.width() - 6,cr.height() - 6,m_property.asColor()); + } else { + QString sz; + switch(m_property.type()) + { + case QVariant::String: + sz = m_property.toString(); + break; + case QVariant::Bool: + sz = m_property.toBool() ? "TRUE" : "FALSE"; + break; + case QVariant::Font: + sz.setNum(m_property.toFont().pointSize()); + sz.prepend(", "); + sz.prepend(m_property.toFont().family()); + break; + case QVariant::Int: + sz.setNum(m_property.toInt()); + break; + case QVariant::UInt: + sz.setNum(m_property.toUInt()); + break; + default: + break; + } + p->setPen(cg.text()); + p->drawText(0,0,cr.width(),cr.height(),Qt::AlignLeft | Qt::AlignTop,sz); + } +} + + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviCanvasItemPropertiesWidget +// + + +KviCanvasItemPropertiesWidget::KviCanvasItemPropertiesWidget(QWidget * par) +: QTable(par) +{ + setSelectionMode(QTable::NoSelection); + setColumnMovingEnabled(false); + setRowMovingEnabled(false); + setShowGrid(true); + setNumCols(2); + setSorting(false); + setLeftMargin(0); + verticalHeader()->hide(); + connect(this,SIGNAL(valueChanged(int,int)),this,SLOT(cellEdited(int,int))); +} + +KviCanvasItemPropertiesWidget::~KviCanvasItemPropertiesWidget() +{ +} + +void KviCanvasItemPropertiesWidget::cellEdited(int row,int) +{ + QTableItem * it = item(row,0); + if(!it)return; + QString szName = it->text(); + it = item(row,1); + if(!it)return; + emit propertyChanged(szName,((KviVariantTableItem *)it)->property()); +} + +void KviCanvasItemPropertiesWidget::editItem(QCanvasItem * it) +{ + if(!it) + { + for(int i=0;i<numRows();i++) + { + clearCell(i,0); + clearCell(i,1); + clearCellWidget(i,1); + } + setNumRows(0); + return; + } + + QMap<QString,QVariant> * m = 0; + + switch(KVI_CANVAS_RTTI_CONTROL_TYPE(it)) + { + case KVI_CANVAS_RTTI_CONTROL_TYPE_RECTANGLE: + m = ((KviCanvasRectangleItem *)it)->properties(); + break; + case KVI_CANVAS_RTTI_CONTROL_TYPE_LINE: + m = ((KviCanvasLine *)it)->properties(); + break; + case KVI_CANVAS_RTTI_CONTROL_TYPE_POLYGON: + m = ((KviCanvasPolygon *)it)->properties(); + break; + } + + if(!m) + { + editItem(0); + return; + } + + for(int i=0;i<numRows();i++) + { + clearCell(i,0); + clearCell(i,1); + clearCellWidget(i,1); + } + + setNumRows(m->count()); + + QTableItem * item; + + int idx = 0; + + for(QMap<QString,QVariant>::ConstIterator iter = m->begin();iter != m->end();++iter) + { + item = new QTableItem(this,QTableItem::Never,iter.key().utf8().data()); + setItem(idx,0,item); + item = new KviVariantTableItem(this,iter.data()); + setItem(idx,1,item); + idx++; + } + +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// KviCanvasWidget +// + +KviCanvasWidget::KviCanvasWidget(QWidget * par) +: QWidget(par,"canvas_widget") +{ + m_pCanvas = new QCanvas(this); +//#warning "Make this size as parameter of Dcc ?" + m_pCanvas->resize(648,480); + m_pMenuBar = new QMenuBar(this); + m_pSplitter = new QSplitter(QSplitter::Horizontal,this); + m_pCanvasView = new KviCanvasView(m_pCanvas,this,m_pSplitter); + m_pStatusLabel = new QLabel(this); + m_pPropertiesWidget = new KviCanvasItemPropertiesWidget(m_pSplitter); + QValueList<int> l; + l.append(80); + l.append(20); + m_pSplitter->setSizes(l); + + connect(m_pPropertiesWidget,SIGNAL(propertyChanged(const QString &,const QVariant &)),m_pCanvasView,SLOT(propertyChanged(const QString &,const QVariant &))); + + KviTalPopupMenu * add = new KviTalPopupMenu(m_pMenuBar); + KviTalPopupMenu * shapes = new KviTalPopupMenu(add); + KviTalPopupMenu * polygons = new KviTalPopupMenu(add); + KviTalPopupMenu * items = new KviTalPopupMenu(add); + shapes->insertItem(__tr2qs_ctx("&Line","dcc"),m_pCanvasView,SLOT(insertLine())); + shapes->insertItem(__tr2qs_ctx("&Rectangle","dcc"),m_pCanvasView,SLOT(insertRectangle())); + shapes->insertItem(__tr2qs_ctx("&Ellipse","dcc"),m_pCanvasView,SLOT(insertEllipse())); + shapes->insertItem(__tr2qs_ctx("&Pie","dcc"),m_pCanvasView,SLOT(insertPie())); + shapes->insertItem(__tr2qs_ctx("&Chord","dcc"),m_pCanvasView,SLOT(insertChord())); + + items->insertItem(__tr2qs_ctx("&Rich text (html)","dcc"),m_pCanvasView,SLOT(insertRichText())); + + polygons->insertItem(__tr2qs_ctx("&Triangle","dcc"),m_pCanvasView,SLOT(insertPolygonTriangle())); + polygons->insertItem(__tr2qs_ctx("&Rectangle","dcc"),m_pCanvasView,SLOT(insertPolygonRectangle())); + polygons->insertItem(__tr2qs_ctx("&Pentagon","dcc"),m_pCanvasView,SLOT(insertPolygonPentagon())); + polygons->insertItem(__tr2qs_ctx("&Hexagon","dcc"),m_pCanvasView,SLOT(insertPolygonHexagon())); + + add->insertItem(__tr2qs_ctx("&Shape","dcc"),shapes); + add->insertItem(__tr2qs_ctx("&Item","dcc"),items); + add->insertItem(__tr2qs_ctx("&Polygons","dcc"),polygons); + + m_pMenuBar->insertItem(__tr2qs_ctx("&Insert","dcc"),add); +} + +KviCanvasWidget::~KviCanvasWidget() +{ +} + + + +void KviCanvasWidget::resizeEvent(QResizeEvent *) +{ + int h = m_pMenuBar->sizeHint().height(); + m_pMenuBar->setGeometry(0,0,width(),h); + int h2 = m_pStatusLabel->sizeHint().height(); + m_pStatusLabel->setGeometry(0,height() - h2,width(),h2); + m_pSplitter->setGeometry(0,h,width(),height() - (h + h2)); +} + + +#include "m_canvaswidget.moc" + +#endif |