/*************************************************************************** * Copyright (C) 2004 by Johan Maes - ON4QZ * * on4qz@telenet.be * * http://users.telenet.be/on4qz * * * * 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. * * * * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "mcanvas.h" #include "qsstvglobal.h" #include #include #include "configdialog.h" #include "effects.h" #include #include "galerymainwindow.h" /*! \fn mcanvas::mcanvas(int w,int h) \brief mcanvas constructor Constructs a mcanvas with a given width \a w and a given height \a h \param w width \param h height \sa resize */ mcanvas::mcanvas(int w,int h) : QCanvas(w,h) { currentObject=NULL; depth=0; } /*! \fn mcanvas::~mcanvas() \brief mcanvas destructor */ mcanvas::~mcanvas() {} /*! \fn mcanvas::resize(int w,int h) \brief resize the canvas Resize mcanvas to a given width \a w and a given height \a h \param w width \param h height */ void mcanvas::resize(int w,int h) { QCanvas::resize(w,h); } /*! \fn mcanvas::createItem(int itemType) \brief create an object on the canvas Create an object of type \a itemType on the canvas \param itemType is one of
  • ellipseRTTI
  • rectangleRTTI
  • textRTTI
  • imageRTTI
  • lineRTTI
*/ canvasItemBase *mcanvas::createItem(int itemType) { switch(itemType) { case -1: return NULL; break; case ellipseRTTI: { currentObject=new ellipse(this); } break; case rectangleRTTI: { currentObject=new rectangle(this); } break; case imageRTTI: { currentObject=new imageItem(this); } break; case textRTTI: { currentObject=new textItem(this); } break; default: { QMessageBox::critical( 0,"Editor","Error creating object" ); return NULL; } } currentObject->setZ(++depth); currentObject->setShear(0.); currentObject->setRotate(0); return currentObject; } /*! \fn mcanvas::load(QFile &f) \brief load \a a file \a into the canvas This function loads a file into the canvas. The currentObject is set to the newly created image \param f file (template or valid image file) \return TRUE if successful, else FALSE */ bool mcanvas::load(QFile &f) { int depthBase=depth; Q_UINT32 mn=0; Q_UINT16 at=0; QImage ima; QColor c; if(!f.open( IO_ReadOnly )) return FALSE; resetSelected(); //clearAll(); QDataStream stream( &f); // first check if we see the magic number; stream >> mn; if(mn==MAGICNUMBER) { imageType=TEMPLATE; // we have a template file stream >> c; // the backgroundcolor setBackgroundColor(c); int w,h; stream >> w >> h; //debug("canvas width=%d height=%d",w,h); resize(w,h); while(!stream.atEnd()) { stream >> at; if(createItem(at)==NULL) return FALSE; currentObject->load(stream); currentObject->setZ(currentObject->z()+depthBase); if((int)currentObject->z()>depth) depth=(int)currentObject->z(); } setChanged(QRect(0,0,w,h)); update(); f.close(); } else { imageType=FLATIMAGE; f.close(); if(!ima.load(f.name())) return FALSE; setImage(&ima,0,0); // will also update the canvas } return TRUE; } /*! \fn mcanvas::save(QFile &f,bool asTemplate) \brief save \a a file \a into the canvas This function saves the canvas to a file. \param f the file to save \param asTemplate
  • FALSE save as image file
  • TRUE save as template file
\return TRUE if successful, else FALSE */ bool mcanvas::save(QFile &f,bool asTemplate) { resetSelected(); optimizeDepth(); QCanvasItemList l=allItems(); if(!f.open( IO_WriteOnly )) return FALSE; QDataStream stream( &f); if(asTemplate) { stream << (Q_UINT32) MAGICNUMBER; stream << backgroundColor(); stream << width() << height(); for(QCanvasItemList::Iterator it=l.begin();it!=l.end();++it) { currentObject = (canvasItemBase *)*it; currentObject->save(stream); } f.close(); } else { QFileInfo fi(f); flattenImage(); if(fi.extension().isEmpty()) { im.save(f.name(),defaultImageFormat.upper()); } else { // check if the format is supported QStringList list = im.outputFormatList(); QStringList::Iterator it = list.begin(); bool success=FALSE; while( it != list.end() ) { QString tmp(*it); if(fi.extension().lower()==tmp.lower()) { success=TRUE; break; } ++it; } if (success) { im.save(f.name(),fi.extension(FALSE).upper()); } else { QMessageBox::information(0,"Editor", "The format " + fi.extension(FALSE).upper() + " is not supported.\n Saving in as " + defaultImageFormat.upper() + " format." ,QMessageBox::Ok); f.setName(fi.baseName()+"."+defaultImageFormat); im.save(f.name(),defaultImageFormat.upper()); } } f.close(); } return TRUE; } /*! \fn mcanvas::getImage(QSize size) \brief import image from mcanvas The image returned will be the scaled version of the entire canvas. If the \a size=(0,0), then the image will have the size of the canvas. If there is only one object and it is an image object, then the original image will be returned if \a size=(0,0) else a scaled version of the image will be returned.
example: \code yourImage=yourcanvas->getImage(size)->copy() \endcode \code yourImage=yourcanvas->getImag(QSize(0,0))->copy() \endcode \param size size of the scaled image \return QImage * - pointer to the converted image */ QImage *mcanvas::getImage(QSize size) { if(count()==1) { selectFront(); if(currentObject->rtti()==imageRTTI) { if(size==QSize(0,0)) { im=currentObject->getFullImage(); return (&im); } im=currentObject->getFullImage().smoothScale(size); return &im; } } else { flattenImage(); } if(size==QSize(0,0)) return &im; // just return the im=im.smoothScale(size); return (&im); } /*! \fn mcanvas::optimizeDepth() \brief optimize the depth of all items This function will walk through all canvas items,start with a depth of 1, incrementing the depth by 1 for every item found. */ void mcanvas::optimizeDepth() { canvasItemBase *cur; QCanvasItemList::Iterator it; QCanvasItemList l=collisions(QRect(0,0,width(),height())); if(l.isEmpty()) return; depth=l.count(); int dp=depth; for ( it = l.begin(); it != l.end(); ++it ) { cur=(canvasItemBase *)*it; // debug("org depth %d",(int) cur->z()); cur->setZ(dp--); } } /*! \fn mcanvas::bringToFront() \brief brings object to the front Brings the currently selected object to the front */ void mcanvas::bringToFront() { if(!checkSelected()) return; optimizeDepth(); currentObject->setZ(++depth); setChanged(currentObject->rect()); update(); } /*! \fn mcanvas::sendToBack() \brief Send object to the back Send the currently selected object to the back */ void mcanvas::sendToBack() { if(!checkSelected()) return; optimizeDepth(); currentObject->setZ(0.5); setChanged(currentObject->rect()); update(); } /*! \fn mcanvas::forward() \brief Brings object one step closer to the front Brings the currently selected object one step closer to the front */ void mcanvas::forward() { if(!checkSelected()) return; optimizeDepth(); double d=currentObject->z(); d+=1.5; currentObject->setZ(d); setChanged(currentObject->rect()); update(); } /*! \fn mcanvas::backward() \brief Send object one step toward the back Send the currently selected object one step toward the back */ void mcanvas::backward() { if(!checkSelected()) return; optimizeDepth(); double d=currentObject->z(); d-=1.5; currentObject->setZ(d); setChanged(currentObject->rect()); update(); } /*! \fn mcanvas::flattenImage() \brief flatten the objects on the canvas Create an image with all ojects flattened, preserving transparency */ void mcanvas::flattenImage() { QCanvasItemList::Iterator it; canvasItemBase *cur; im.create(width(),height(),32); // create an empty image im.setAlphaBuffer(FALSE); im.fill(0x0); im.setAlphaBuffer(TRUE); QCanvasItemList l=collisions(QRect(0,0,width(),height())); if(l.isEmpty()) return; it=l.end(); do { --it; cur=(canvasItemBase *)*it; cur->updateActiveImage(); blendImage(im,cur->startPoint(),cur->getActiveImage()); } while (it!=l.begin()); return; } /*! \fn mcanvas::clearAll() \brief clear the canvas, delete all objects */ void mcanvas::clearAll() { QCanvasItemList list = allItems(); QCanvasItemList::Iterator it = list.begin(); for (; it != list.end(); ++it) { if ( *it ) delete *it; } currentObject=NULL; update(); } /*! \fn mcanvas::checkSelected() \brief check if the currentObject is selected \return TRUE if object exists and is selected, else FALSE; */ bool mcanvas::checkSelected() { if(!currentObject) return FALSE; return currentObject->isSelected(); } /*! \fn mcanvas::resetSelected() \brief reset the selection of the current object */ void mcanvas::resetSelected() { if (checkSelected()) { currentObject->setSelected(FALSE); update(); } } /*! \fn mcanvas::setSelected() \brief set the current object to selected */ void mcanvas::setSelected() { if(currentObject) currentObject->setSelected(TRUE); } /*! \fn mcanvas::overlay(QImage *ima,int templateIndex) \brief apply an overlay to an image \param ima the base image \param templateIndex */ QImage *mcanvas::overlay(QImage *ima,int templateIndex) { QString tmp; tmp=galMW->getTemplateFileName(templateIndex); return(overlay(ima,tmp)); } /*! \fn mcanvas::overlay(QImage *ima,int templateIndex) \brief apply an overlay to an image \param ima the base image \param fn : the filename */ QImage *mcanvas::overlay(QImage *ima,QString fn) { QFile f(fn); load(f); if(ima) setImage(ima); setSelected(); sendToBack(); current()->setGeometry(rect().topLeft(),rect().bottomRight()); flattenImage(); return &im; } /*! \fn mcanvas::current() \return pointer to the current object */ canvasItemBase * mcanvas::current() { return currentObject; } /*! \fn mcanvas::copy() \brief copy object Makes a copy of the currently selected object */ void mcanvas::copy() { if(checkSelected()) currentObject->getParam(copyParam); } /*! \fn mcanvas::paste() */ void mcanvas::paste() { resetSelected(); if(createItem(copyParam.type)==NULL) { debug("paste error"); return; } currentObject->setParam(copyParam,++depth); currentObject->moveBy(10,10); currentObject->show(); currentObject->setFinal(TRUE); update(); } /*! \fn mcanvas::setImage(QImage ima,int w,int h) \brief copy an image to this canvas Copy an image to the canvas. This image object becomes the currentObject. \param ima the image to copy \param w the width of the image on the canvas, if w=0 then the image will have the width of the canvas. (default=0) \param h the height of the image on the canvas if h=0 then the image will have the height of the canvas (default=0) */ void mcanvas::setImage(QImage *ima,int w,int h) { //debug("imagesize =%d,%d",ima.width(),ima.height()); // resizeContents(ima.width(),ima.height()); if(createItem(imageRTTI)==NULL) { debug("error creating ima"); return; } int wd,ht; if(w==0) wd=width()-1; else wd=w-1; if(h==0) ht=height()-1; else ht=h-1; currentObject->create(QPoint(0,0),QPoint(wd,ht)); currentObject->setImage(ima); currentObject->setFinal(TRUE); currentObject->setZ(++depth); setChanged(QRect(0,0,width(),height())); update(); } /*! \fn mcanvas::deleteObject() \brief delete object Delete the current selected object */ void mcanvas::deleteObject() { if(!checkSelected()) return; delete currentObject; currentObject=NULL; } /*! \fn mcanvas::selectFront() \brief select the front object The currentObject is set to the front object and it is selected. */ void mcanvas::selectFront() { resetSelected(); QCanvasItemList::Iterator it; QCanvasItemList l=collisions(QRect(0,0,width(),height())); if(l.isEmpty()) return; it = l.begin(); currentObject=(canvasItemBase *)*it; currentObject->setSelected(TRUE); } /*! \fn mcanvas::makeSelection(QPoint cl, bool selecObject) \brief select object at point \a cl \param cl selection point, objects will be searched from front to back \param selectObject if TRUE then object will be set to selected (default=TRUE) \return pointer to currentObject */ canvasItemBase * mcanvas::makeSelection(QPoint cl, bool selectObject) { QCanvasItemList l=collisions(cl); //debug("x=%d,y=%d",clickPoint.x(),clickPoint.y()); if(l.isEmpty()) return NULL; QCanvasItemList::Iterator it=l.begin(); if(*it) { resetSelected(); currentObject=(canvasItemBase *)*it; if(selectObject) currentObject->setSelected(TRUE); return currentObject; } return NULL; } /*! \fn mcanvas::count() \brief returns the number of objects on the canvas */ int mcanvas::count() { /// @todo implement me QCanvasItemList l=allItems(); return l.count(); }