00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <stdlib.h>
00020 #include <stdio.h>
00021 #include <ctype.h>
00022 #include <math.h>
00023
00024 #include <qpainter.h>
00025 #include <qdrawutil.h>
00026 #include <qkeycode.h>
00027 #include <qregexp.h>
00028 #include <qpoint.h>
00029 #include <qcursor.h>
00030 #include <qptrstack.h>
00031 #include <qbuffer.h>
00032 #include <qmessagebox.h>
00033 #include <qclipboard.h>
00034 #include <qpicture.h>
00035 #include <qdom.h>
00036 #include <qtextstream.h>
00037 #include <qdragobject.h>
00038 #include <qmime.h>
00039 #include <qsortedlist.h>
00040 #include <qvaluelist.h>
00041
00042 #include <kdebug.h>
00043 #include <klocale.h>
00044 #include <kglobal.h>
00045 #include <kmessagebox.h>
00046 #include <KoUnit.h>
00047 #include <KoPoint.h>
00048 #include <KoRect.h>
00049 #include <KoZoomHandler.h>
00050 #include <kapplication.h>
00051 #include <KoXmlWriter.h>
00052 #include <KoXmlNS.h>
00053 #include <KoDom.h>
00054 #include <KoStore.h>
00055 #include <KoOasisStyles.h>
00056 #include <KoGenStyles.h>
00057
00058 #include "kivio_page.h"
00059 #include "kivio_map.h"
00060 #include "kivio_doc.h"
00061 #include "kivio_canvas.h"
00062 #include "kivio_view.h"
00063 #include "kivio_config.h"
00064
00065 #include "kivio_common.h"
00066 #include "kivio_connector_point.h"
00067 #include "kivio_group_stencil.h"
00068 #include "kivio_intra_stencil_data.h"
00069 #include "kivio_layer.h"
00070 #include "kivio_painter.h"
00071 #include "kivio_stencil.h"
00072 #include "kivio_1d_stencil.h"
00073 #include "KIvioPageIface.h"
00074 #include "kivio_command.h"
00075 #include "kivioglobal.h"
00076 #include "kiviodragobject.h"
00077
00078 #include <fixx11h.h>
00079
00080 int KivioPage::s_id = 0L;
00081 QIntDict<KivioPage>* KivioPage::s_mapPages;
00082
00083 KivioPage::KivioPage( KivioMap *_map, const QString &pageName, const char *_name )
00084 : QObject( _map, _name ),
00085 m_pCurLayer(NULL)
00086 {
00087 if ( s_mapPages == 0L )
00088 s_mapPages = new QIntDict<KivioPage>;
00089 m_id = s_id++;
00090 s_mapPages->insert( m_id, this );
00091
00092 m_dcop = 0;
00093
00094 m_pMap = _map;
00095 m_pDoc = _map->doc();
00096
00097
00098 m_pCurLayer = new KivioLayer(this);
00099 m_pCurLayer->setName(i18n("Layer 1"));
00100 m_lstLayers.append( m_pCurLayer );
00101 m_lstLayers.setAutoDelete(true);
00102
00103 m_lstSelection.setAutoDelete(false);
00104
00105 m_strName = pageName;
00106
00107 setHidden(false);
00108
00109 if ( !_name ) {
00110 QCString s;
00111 s.sprintf("Page%i", s_id );
00112 setName( s.data() );
00113 }
00114
00115 m_pPageLayout = Kivio::Config::defaultPageLayout();
00116 }
00117
00118 DCOPObject* KivioPage::dcopObject()
00119 {
00120 if ( !m_dcop )
00121 m_dcop = new KIvioPageIface( this );
00122 return m_dcop;
00123 }
00124
00125
00126 KivioPage::~KivioPage()
00127 {
00128 kdDebug(43000)<<" KivioPage::~KivioPage()************ :"<<this<<endl;
00129 s_mapPages->remove(m_id);
00130 delete m_dcop;
00131 }
00132
00133 KivioPage* KivioPage::find( int _id )
00134 {
00135 if ( !s_mapPages )
00136 return 0L;
00137
00138 return (*s_mapPages)[ _id ];
00139 }
00140
00141 void KivioPage::print( QPainter &, KPrinter * )
00142 {
00143 }
00144
00145 void KivioPage::printPage( QPainter &, const QRect& , const QRect& )
00146 {
00147 }
00148
00149 QDomElement KivioPage::save( QDomDocument& doc )
00150 {
00151
00152 QDomElement page = doc.createElement( "KivioPage" );
00153 page.setAttribute( "name", m_strName );
00154 page.setAttribute( "hide", (int)m_bPageHide );
00155
00156
00157 QDomElement layoutE = saveLayout( doc );
00158 page.appendChild( layoutE );
00159
00160
00161 QDomElement guidesElement = doc.createElement("GuidesLayout");
00162 page.appendChild(guidesElement);
00163 saveGuideLines(guidesElement);
00164
00165
00166 KivioLayer *pLayer = m_lstLayers.first();
00167 while( pLayer )
00168 {
00169 QDomElement layerE = pLayer->saveXML(doc);
00170 if( layerE.isNull() )
00171 {
00172 kdDebug(43000) << "KivioPage::save() - Oh shit. KivioLayer::saveXML() returned a bad element!" << endl;
00173 }
00174 else
00175 {
00176 page.appendChild( layerE );
00177 }
00178
00179 pLayer = m_lstLayers.next();
00180 }
00181
00182 return page;
00183 }
00184
00185 void KivioPage::saveOasis(KoStore* , KoXmlWriter* docWriter, KoGenStyles* styles)
00186 {
00187 docWriter->startElement("draw:page");
00188 docWriter->addAttribute("draw:name", m_strName);
00189
00190 if(m_pPageLayout == Kivio::Config::defaultPageLayout()) {
00191 docWriter->addAttribute("draw:master-page-name", "Standard");
00192 } else {
00193 KoGenStyle pageLayout = m_pPageLayout.saveOasis();
00194 QString layoutName = styles->lookup(pageLayout, "PL");
00195
00196 KoGenStyle masterPage(KoGenStyle::STYLE_MASTER);
00197 masterPage.addAttribute("style:page-layout-name", layoutName);
00198 QString masterName = styles->lookup(masterPage, "MP");
00199
00200 docWriter->addAttribute("draw:master-page-name", masterName);
00201 }
00202
00203
00204
00205 QBuffer layerBuffer;
00206 layerBuffer.open(IO_WriteOnly);
00207 KoXmlWriter layerWriter(&layerBuffer);
00208 layerWriter.startElement("draw:layer-set");
00209
00210
00211 KivioLayer* layer = m_lstLayers.first();
00212
00213 while(layer) {
00214 layer->saveOasis(&layerWriter);
00215 layer = m_lstLayers.next();
00216 }
00217
00218 layerWriter.endElement();
00219 QString layerSet = QString::fromUtf8(layerBuffer.buffer(), layerBuffer.buffer().size());
00220 KoGenStyle pageStyle(Kivio::STYLE_PAGE, "drawing-page");
00221 pageStyle.addChildElement("draw:layer-set", layerSet);
00222 QString styleName = styles->lookup(pageStyle, "PS");
00223 docWriter->addAttribute("draw:style-name", styleName);
00224
00225 docWriter->endElement();
00226 }
00227
00228 QDomElement KivioPage::saveLayout( QDomDocument &doc )
00229 {
00230 QDomElement e = doc.createElement("PageLayout");
00231 Kivio::savePageLayout(e, m_pPageLayout);
00232
00233 return e;
00234 }
00235
00236 bool KivioPage::loadLayout( const QDomElement &e )
00237 {
00238 m_pPageLayout = Kivio::loadPageLayout(e);
00239 return true;
00240 }
00241
00242 bool KivioPage::isLoading()
00243 {
00244 return m_pDoc->isLoading();
00245 }
00246
00247 bool KivioPage::loadXML( const QDomElement& pageE )
00248 {
00249 m_strName = pageE.attribute("name");
00250 if (m_strName.isEmpty())
00251 return false;
00252
00253
00254 m_bPageHide = (int)pageE.attribute("hide").toInt();
00255
00256
00257 KivioLayer *pLayer;
00258 m_lstLayers.clear();
00259
00260 QDomNode node = pageE.firstChild();
00261 while( !node.isNull() )
00262 {
00263 if( node.nodeName() == "KivioLayer" )
00264 {
00265 pLayer = new KivioLayer(this);
00266 if( pLayer->loadXML( node.toElement() )==false )
00267 {
00268 delete pLayer;
00269 pLayer = NULL;
00270 }
00271 else
00272 {
00273 m_lstLayers.append( pLayer );
00274 pLayer = NULL;
00275 }
00276 }
00277 else if( node.nodeName() == "PageLayout" )
00278 {
00279 loadLayout( node.toElement() );
00280 }
00281 else if ( node.nodeName() == "GuidesLayout" ) {
00282 loadGuideLines(node.toElement());
00283 }
00284 else
00285 {
00286 kdDebug(43000) << "KivioLayer::loadXML() - unknown node found, " << node.nodeName() << endl;
00287 }
00288
00289 node = node.nextSibling();
00290 }
00291
00292 m_pCurLayer = m_lstLayers.first();
00293 if( !m_pCurLayer )
00294 {
00295 kdDebug(43000) << "KivioLayer::loadXML() - No layers loaded!! BIGGGGG PROBLEMS!" << endl;
00296 }
00297
00298
00299 KivioLayer *pLayerBak;
00300
00301 pLayer = m_lstLayers.first();
00302 while( pLayer )
00303 {
00304 pLayerBak = pLayer;
00305
00306 kdDebug(43000) << "KivioLayer::loadXML() - loading layer connections" << endl;
00307 pLayer->searchForConnections(this);
00308
00309 m_lstLayers.find( pLayerBak );
00310
00311 pLayer = m_lstLayers.next();
00312 }
00313
00314 return true;
00315 }
00316
00317 bool KivioPage::loadOasis(const QDomElement& page, KoOasisStyles& oasisStyles)
00318 {
00319 m_strName = page.attributeNS( KoXmlNS::draw, "name", QString::null);
00320 QDomElement* masterPage = oasisStyles.masterPages()[page.attributeNS( KoXmlNS::draw, "master-page-name", QString::null)];
00321
00322 if(!masterPage) {
00323 kdDebug(430000) << "Couldn't find the master page! " << page.attributeNS( KoXmlNS::draw, "master-page-name", QString::null) << endl;
00324 return false;
00325 }
00326
00327 const QDomElement *pageLayout = oasisStyles.findStyle(masterPage->attributeNS( KoXmlNS::style, "page-layout-name", QString::null ) );
00328
00329 if(!pageLayout) {
00330 kdDebug(430000) << "Couldn't find the pagelayout!" << endl;
00331 return false;
00332 }
00333
00334 m_pPageLayout.loadOasis(*pageLayout);
00335
00336 if(m_pPageLayout.ptWidth <= 1e-13 || m_pPageLayout.ptHeight <= 1e-13) {
00337 kdDebug(430000) << "Non valid pagelayout!" << endl;
00338 return false;
00339 }
00340
00341 const QDomElement* style = oasisStyles.findStyle(page.attributeNS( KoXmlNS::draw, "style-name", QString::null) );
00342
00343 if(!style) {
00344 return false;
00345 }
00346
00347 QDomNode styleNode = KoDom::namedItemNS( *style, KoXmlNS::style, "properties");
00348 styleNode = KoDom::namedItemNS( styleNode, KoXmlNS::draw, "layer-set");
00349 QDomNode currentNode = styleNode.firstChild();
00350
00351
00352 while(!currentNode.isNull()) {
00353 if(currentNode.nodeName() == "draw:layer") {
00354 KivioLayer* layer = new KivioLayer(this);
00355 layer->loadOasis(currentNode.toElement());
00356 m_lstLayers.append(layer);
00357 }
00358
00359 currentNode = currentNode.nextSibling();
00360 }
00361
00362 return true;
00363 }
00364
00365 void KivioPage::update()
00366 {
00367 }
00368
00369 KivioPage* KivioPage::findPage( const QString& name )
00370 {
00371 if (!m_pMap)
00372 return 0L;
00373
00374 return m_pMap->findPage(name);
00375 }
00376
00377 bool KivioPage::setPageName( const QString& name, bool init )
00378 {
00379 if ( map()->findPage( name ) )
00380 return false;
00381
00382 if ( m_strName == name )
00383 return true;
00384
00385 QString old_name = m_strName;
00386 m_strName = name;
00387
00388 if (init)
00389 return true;
00390
00391 emit m_pDoc->sig_pageNameChanged(this, old_name);
00392
00393 return true;
00394 }
00395
00402 void KivioPage::paintContent( KivioPainter& painter, const QRect& rect, bool transparent,
00403 QPoint p0, KoZoomHandler* zoom, bool drawConnectorTargets, bool drawSelection )
00404 {
00405 KivioLayer *pLayer = m_lstLayers.first();
00406 while( pLayer )
00407 {
00408 if( pLayer->visible() )
00409 {
00410 pLayer->paintContent( painter, rect, transparent, p0, zoom );
00411 }
00412
00413 pLayer = m_lstLayers.next();
00414 }
00415
00416
00417
00418 if(zoom->zoom() >= 50) {
00419 if(drawConnectorTargets) {
00420 m_pCurLayer->paintConnectorTargets( painter, rect, transparent, p0, zoom );
00421 pLayer = m_lstLayers.first();
00422
00423 while(pLayer) {
00424 if(pLayer->connectable() && (pLayer != m_pCurLayer)) {
00425 pLayer->paintConnectorTargets( painter, rect, transparent, p0, zoom );
00426 }
00427
00428 pLayer = m_lstLayers.next();
00429 }
00430 }
00431 }
00432
00433
00434 if(drawSelection) {
00435 m_pCurLayer->paintSelectionHandles( painter, rect, transparent, p0, zoom );
00436 }
00437 }
00438
00439 void KivioPage::printContent( KivioPainter& painter, int xdpi, int ydpi )
00440 {
00441 if(!xdpi) {
00442 xdpi = KoGlobal::dpiX();
00443 }
00444
00445 if(!ydpi) {
00446 ydpi = KoGlobal::dpiY();
00447 }
00448
00449 KivioLayer *pLayer = m_lstLayers.first();
00450
00451 while( pLayer )
00452 {
00453 if( pLayer->visible() )
00454 {
00455 pLayer->printContent( painter, xdpi, ydpi );
00456 }
00457
00458 pLayer = m_lstLayers.next();
00459 }
00460 }
00461
00462 void KivioPage::printContent(KivioPainter& painter, KoZoomHandler* zoomHandler)
00463 {
00464 KivioLayer *pLayer = m_lstLayers.first();
00465
00466 while( pLayer )
00467 {
00468 if(pLayer->visible())
00469 {
00470 pLayer->printContent(painter, zoomHandler);
00471 }
00472
00473 pLayer = m_lstLayers.next();
00474 }
00475 }
00476
00477 void KivioPage::printSelected( KivioPainter& painter, int xdpi, int ydpi )
00478 {
00479 if(!xdpi) {
00480 xdpi = KoGlobal::dpiX();
00481 }
00482
00483 if(!ydpi) {
00484 ydpi = KoGlobal::dpiY();
00485 }
00486
00487 KivioStencil *pStencil;
00488 KivioIntraStencilData data;
00489 KoZoomHandler zoomHandler;
00490 zoomHandler.setZoomAndResolution(100, xdpi, ydpi);
00491
00492 data.painter = &painter;
00493 data.zoomHandler = &zoomHandler;
00494 data.printing = true;
00495
00496 KivioLayer *pLayer = m_lstLayers.first();
00497
00498 while( pLayer )
00499 {
00500 if( pLayer->visible()==true )
00501 {
00502 pStencil = pLayer->firstStencil();
00503
00504 while( pStencil )
00505 {
00506 if(pStencil->isSelected())
00507 {
00508 pStencil->paint(&data);
00509 }
00510
00511 pStencil = pLayer->nextStencil();
00512 }
00513 }
00514
00515 pLayer = m_lstLayers.next();
00516 }
00517 }
00518
00519
00520 bool KivioPage::addStencil( KivioStencil *pStencil )
00521 {
00522 if(!pStencil) {
00523 kdDebug(43000) << "KivioPage::addStencil() - Null stencil passed" << endl;
00524 return false;
00525 }
00526
00527 if(!m_pCurLayer) {
00528 kdDebug(43000) << "KivioPage::addStencil() - NULL current layer" << endl;
00529 return false;
00530 }
00531
00532 KivioAddStencilCommand *cmd = new KivioAddStencilCommand(i18n("Add Stencil"), this, m_pCurLayer, pStencil );
00533 m_pDoc->addCommand(cmd);
00534
00535 return m_pCurLayer->addStencil( pStencil );
00536 }
00537
00538 void KivioPage::selectStencils( double x, double y, double w, double h )
00539 {
00540
00541 KivioStencil *pStencil = m_pCurLayer->stencilList()->first();
00542
00543 while(pStencil) {
00544
00545 if(pStencil->isInRect(KoRect(x, y, w, h))) {
00546 selectStencil( pStencil );
00547 }
00548
00549 pStencil = m_pCurLayer->stencilList()->next();
00550 }
00551
00552 m_pDoc->slotSelectionChanged();
00553 }
00554
00555 void KivioPage::selectStencil( KivioStencil *pStencil )
00556 {
00557 if(!pStencil) {
00558 kdDebug(43000) << "KivioPage::selectStencil - AHHHH! NULL STENCIL!" << endl;
00559 return;
00560 }
00561
00562
00563 if(m_lstSelection.findRef(pStencil) != -1) {
00564 return;
00565 }
00566
00567 kdDebug(43000) <<"KivioPage::selectStencil - Selecting stencil" << endl;
00568 pStencil->select();
00569 m_lstSelection.append(pStencil);
00570 m_pDoc->slotSelectionChanged();
00571 }
00572
00573 bool KivioPage::unselectStencil( KivioStencil *pStencil )
00574 {
00575 pStencil->unselect();
00576 m_pDoc->slotSelectionChanged();
00577 return m_lstSelection.removeRef( pStencil );
00578 }
00579
00580 void KivioPage::selectAllStencils()
00581 {
00582 unselectAllStencils();
00583 KivioStencil* pStencil = m_pCurLayer->stencilList()->first();
00584
00585 while(pStencil) {
00586 pStencil->select();
00587 m_lstSelection.append(pStencil);
00588 pStencil = m_pCurLayer->stencilList()->next();
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 m_pDoc->slotSelectionChanged();
00616 }
00617
00618 void KivioPage::unselectAllStencils()
00619 {
00620 KivioStencil* pStencil = m_lstSelection.first();
00621
00622 while(pStencil)
00623 {
00624 pStencil->unselect();
00625 pStencil = m_lstSelection.next();
00626 }
00627
00628 m_lstSelection.clear();
00629 m_pDoc->slotSelectionChanged();
00630 }
00631
00632 bool KivioPage::isStencilSelected(KivioStencil *pStencil)
00633 {
00634 return m_lstSelection.findRef( pStencil ) == -1;
00635 }
00636
00646 KivioStencil *KivioPage::checkForStencil( KoPoint *pPoint, int *collisionType, double threshold, bool selectedOnly )
00647 {
00648 KivioStencil *pStencil;
00649 int colType;
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 pStencil = m_pCurLayer->checkForStencil( pPoint, &colType, threshold, selectedOnly );
00673 if( pStencil )
00674 {
00675 *collisionType = colType;
00676 return pStencil;
00677 }
00678
00679
00680 *collisionType = kctNone;
00681 return NULL;
00682 }
00683
00684 void KivioPage::deleteSelectedStencils()
00685 {
00686
00687 KivioStencil* pStencil = m_lstSelection.first();
00688
00689 while(pStencil) {
00690 if(pStencil->protection()->at(kpDeletion)) {
00691 KMessageBox::information(NULL, i18n("One of the selected stencils has protection from deletion and cannot be deleted."),
00692 i18n("Protection From Deletion") );
00693 return;
00694 }
00695
00696 pStencil = m_lstSelection.next();
00697 }
00698
00699
00700 m_lstSelection.first();
00701 pStencil = m_lstSelection.take();
00702 KMacroCommand *macro = new KMacroCommand( i18n("Remove Stencil"));
00703 bool createMacro = false;
00704
00705 while(pStencil) {
00706 KivioRemoveStencilCommand *cmd =new KivioRemoveStencilCommand(i18n("Remove Stencil"), this, m_pCurLayer , pStencil );
00707 createMacro = true;
00708 macro->addCommand(cmd);
00709
00710 if(pStencil->type() == kstConnector) {
00711 static_cast<Kivio1DStencil*>(pStencil)->disconnectFromTargets();
00712 }
00713
00714 pStencil = m_lstSelection.take();
00715 }
00716
00717 if (createMacro) {
00718 macro->execute();
00719 m_pDoc->addCommand( macro );
00720 } else {
00721 delete macro;
00722 }
00723 }
00724
00725 void KivioPage::groupSelectedStencils()
00726 {
00727
00728 if(!m_pCurLayer || (m_lstSelection.count() <= 1)) {
00729 return;
00730 }
00731
00732 KivioGroupStencil* pGroup = new KivioGroupStencil();
00733
00734
00735
00736
00737 KivioStencil* pStencil = m_pCurLayer->firstStencil();
00738 KivioStencil* pTake = 0;
00739
00740 while(pStencil) {
00741 if(pStencil->isSelected()) {
00742
00743 pTake = m_pCurLayer->takeStencil(pStencil);
00744
00745 if(!pTake) {
00746 kdDebug(43000) << "KivioPage::groupSelectedStencil() - Failed to take() one of the selected stencils. CRAP!" << endl;
00747 } else {
00748
00749 pGroup->addToGroup(pTake);
00750 pStencil = m_pCurLayer->currentStencil();
00751 }
00752 } else {
00753 pStencil = m_pCurLayer->nextStencil();
00754 }
00755 }
00756
00757
00758 unselectAllStencils();
00759
00760
00761 m_pCurLayer->addStencil(pGroup);
00762
00763 selectStencil(pGroup);
00764
00765 KivioGroupCommand* cmd = new KivioGroupCommand(i18n("Group Selection"), this, m_pCurLayer, pGroup);
00766 doc()->addCommand(cmd);
00767 }
00768
00769 void KivioPage::ungroupSelectedStencils()
00770 {
00771 KivioStencil *pSelStencil, *pStencil;
00772 QPtrList<KivioStencil> *pList;
00773 QPtrList<KivioStencil> *pSelectThese = new QPtrList<KivioStencil>;
00774 KMacroCommand* macro = new KMacroCommand(i18n("Ungroup"));
00775 bool ungrouped = false;
00776
00777 pSelectThese->setAutoDelete(false);
00778
00779
00780 pSelStencil = m_lstSelection.first();
00781 while( pSelStencil )
00782 {
00783
00784 pList = pSelStencil->groupList();
00785 if(pList)
00786 {
00787 pList->first();
00788 pStencil = pList->first();
00789
00790 while( pStencil )
00791 {
00792 m_pCurLayer->addStencil( pStencil );
00793 pSelectThese->append( pStencil );
00794
00795 pStencil = pList->next();
00796 }
00797
00798
00799 m_lstSelection.take();
00800
00801
00802 if(!m_pCurLayer->takeStencil(pSelStencil))
00803 {
00804 kdDebug(43000) << "KivioPage::ungroupSelectedStencil() - Failed to locate the group shell for deletion"
00805 << endl;
00806 }
00807
00808 KivioUnGroupCommand* cmd = new KivioUnGroupCommand(i18n("Ungroup"), this, m_pCurLayer,
00809 static_cast<KivioGroupStencil*>(pSelStencil));
00810 macro->addCommand(cmd);
00811 ungrouped = true;
00812 }
00813
00814 pSelStencil = m_lstSelection.next();
00815 }
00816
00817
00818
00819 pStencil = pSelectThese->first();
00820 while( pStencil )
00821 {
00822 selectStencil( pStencil );
00823
00824 if(pStencil->type() == kstConnector) {
00825 pStencil->searchForConnections(this, 4.0);
00826 }
00827
00828 pStencil = pSelectThese->next();
00829 }
00830
00831 delete pSelectThese;
00832
00833 if(ungrouped) {
00834 doc()->addCommand(macro);
00835 } else {
00836 delete macro;
00837 }
00838 }
00839
00840 void KivioPage::bringToFront()
00841 {
00842 KivioStencil *pStencil, *pMove;
00843 KivioLayer *pLayer;
00844
00845 QPtrList <KivioStencil> newList;
00846
00847 pLayer = m_pCurLayer;
00848
00849 newList.setAutoDelete(false);
00850
00851
00852
00853
00854
00855 pStencil = pLayer->firstStencil();
00856 while( pStencil )
00857 {
00858 if( isStencilSelected( pStencil )==true )
00859 {
00860 pMove = pLayer->takeStencil();
00861 if( pMove )
00862 {
00863 newList.append(pMove);
00864 pStencil = pLayer->currentStencil();
00865 }
00866 else
00867 {
00868 pStencil = pLayer->nextStencil();
00869 }
00870 }
00871 else
00872 {
00873 pStencil = pLayer->nextStencil();
00874 }
00875 }
00876
00877
00878 pStencil = newList.last();
00879 while( pStencil )
00880 {
00881 pLayer->stencilList()->insert(0, pStencil);
00882
00883 pStencil = newList.prev();
00884 }
00885 }
00886
00887 void KivioPage::sendToBack()
00888 {
00889 KivioStencil *pStencil, *pMove;
00890 KivioLayer *pLayer;
00891
00892 QPtrList <KivioStencil> newList;
00893
00894 pLayer = m_pCurLayer;
00895
00896 newList.setAutoDelete(false);
00897
00898
00899
00900
00901
00902 pStencil = pLayer->firstStencil();
00903 while( pStencil )
00904 {
00905 if( isStencilSelected( pStencil )==true )
00906 {
00907 pMove = pLayer->takeStencil();
00908 if( pMove )
00909 {
00910 newList.append(pMove);
00911 pStencil = pLayer->currentStencil();
00912 }
00913 else
00914 {
00915 pStencil = pLayer->nextStencil();
00916 }
00917 }
00918 else
00919 {
00920 pStencil = pLayer->nextStencil();
00921 }
00922 }
00923
00924
00925 pStencil = newList.first();
00926 while( pStencil )
00927 {
00928 pLayer->stencilList()->append(pStencil);
00929
00930 pStencil = newList.next();
00931 }
00932 }
00933
00934 void KivioPage::copy()
00935 {
00936 if(m_lstSelection.count() <= 0) {
00937 return;
00938 }
00939
00940
00941 KivioDragObject* kdo = new KivioDragObject();
00942 kdo->setStencilList(m_lstSelection);
00943 kdo->setStencilRect(getRectForAllSelectedStencils());
00944 QApplication::clipboard()->setData(kdo, QClipboard::Clipboard);
00945 }
00946
00947 void KivioPage::cut()
00948 {
00949 KivioStencil *pStencil;
00950 KivioLayer *pLayer;
00951 bool safe=true;
00952
00953 if( m_lstSelection.count() <= 0 )
00954 return;
00955
00956 pLayer = m_pCurLayer;
00957
00958
00959 pStencil = pLayer->firstStencil();
00960 while( pStencil )
00961 {
00962 if( isStencilSelected( pStencil )==true )
00963 {
00964 if( pStencil->protection()->at(kpDeletion)==true )
00965 {
00966 safe=false;
00967 }
00968 }
00969
00970 pStencil = pLayer->nextStencil();
00971 }
00972
00973 if( safe==false )
00974 {
00975 KMessageBox::information(NULL, i18n("One of the stencils has protection from deletion. You cannot cut or delete this stencil."), i18n("Protection From Delete") );
00976
00977 return;
00978 }
00979
00980 copy();
00981 deleteSelectedStencils();
00982 }
00983
00984 void KivioPage::paste(KivioView* view)
00985 {
00986 QPtrList<KivioStencil> list;
00987 list.setAutoDelete(false);
00988 KivioDragObject kdo;
00989
00990 if(kdo.decode(QApplication::clipboard()->data(QClipboard::Clipboard), list, this)) {
00991 unselectAllStencils();
00992 KivioStencil* stencil = list.first();
00993
00994 while(stencil) {
00995 addStencil(stencil);
00996 selectStencil(stencil);
00997 stencil = list.next();
00998 }
00999
01000 view->canvasWidget()->startPasteMoving();
01001 }
01002 }
01003
01004 int KivioPage::generateStencilIds(int next)
01005 {
01006 KivioLayer *pLayer;
01007
01008 pLayer = m_lstLayers.first();
01009 while( pLayer )
01010 {
01011
01012 next = pLayer->generateStencilIds( next );
01013
01014 pLayer = m_lstLayers.next();
01015 }
01016
01017 return next;
01018 }
01019
01020 KivioLayer *KivioPage::firstLayer()
01021 {
01022 return m_lstLayers.first();
01023 }
01024
01025 KivioLayer *KivioPage::nextLayer()
01026 {
01027 return m_lstLayers.next();
01028 }
01029
01030 KivioLayer *KivioPage::prevLayer()
01031 {
01032 return m_lstLayers.prev();
01033 }
01034
01035 KivioLayer *KivioPage::lastLayer()
01036 {
01037 return m_lstLayers.last();
01038 }
01039
01040 bool KivioPage::removeCurrentLayer()
01041 {
01042 KivioLayer *pLayer;
01043
01044
01045 if( m_lstLayers.count() <= 1 )
01046 return false;
01047
01048 pLayer = m_lstLayers.first();
01049
01050 if( pLayer != m_pCurLayer )
01051 {
01052 if( m_lstLayers.find( m_pCurLayer )==false )
01053 {
01054 kdDebug(43000) << "KivioLayer::removeCurrentLayer() - Couldn't find current layer in the list. Bad!" << endl;
01055 return false;
01056 }
01057 }
01058
01059 pLayer = m_lstLayers.next();
01060 if( !pLayer )
01061 {
01062 (void)m_lstLayers.last();
01063 pLayer = m_lstLayers.prev();
01064 }
01065
01066 if( !pLayer )
01067 {
01068 kdDebug(43000) << "KivioLayer::removeCurrentLayer() - Couldn't find a next layer." << endl;
01069 return false;
01070 }
01071
01072 KivioRemoveLayerCommand * cmd = new KivioRemoveLayerCommand( i18n("Remove Layer"), this , m_pCurLayer , m_lstLayers.findRef(m_pCurLayer) );
01073 doc()->addCommand( cmd );
01074 takeLayer( m_pCurLayer );
01075
01076
01077
01078
01079
01080
01081
01082 m_pCurLayer = pLayer;
01083
01084
01085 return true;
01086 }
01087
01088 void KivioPage::takeLayer( KivioLayer *pLayer )
01089 {
01090 int pos=m_lstLayers.findRef(pLayer);
01091 m_lstLayers.take( pos );
01092 }
01093
01094 void KivioPage::addLayer( KivioLayer *pLayer )
01095 {
01096 m_lstLayers.append( pLayer );
01097 }
01098
01099 void KivioPage::insertLayer( int position, KivioLayer *pLayer )
01100 {
01101 m_lstLayers.insert( position, pLayer );
01102 }
01103
01104 KivioLayer *KivioPage::layerAt( int pos )
01105 {
01106 return m_lstLayers.at(pos);
01107 }
01108
01109 void KivioPage::alignStencils(AlignData d)
01110 {
01111 KivioStencil* pStencil = m_lstSelection.first();
01112
01113 if(!pStencil)
01114 return;
01115
01116 if (d.v != AlignData::None || d.h != AlignData::None) {
01117 KMacroCommand *macro = new KMacroCommand(i18n("Move Stencil"));
01118 double x = pStencil->x();
01119 double y = pStencil->y();
01120 double w = pStencil->w();
01121 double h = pStencil->h();
01122
01123 while( pStencil )
01124 {
01125 KoRect oldRect = pStencil->rect();
01126
01127 switch (d.v) {
01128 case AlignData::Top:
01129 pStencil->setY(y);
01130 break;
01131 case AlignData::Center:
01132 pStencil->setY(y+h/2-pStencil->h()/2);
01133 break;
01134 case AlignData::Bottom:
01135 pStencil->setY(y+h-pStencil->h());
01136 break;
01137 default:
01138 break;
01139 }
01140 switch (d.h) {
01141 case AlignData::Left:
01142 pStencil->setX(x);
01143 break;
01144 case AlignData::Center:
01145 pStencil->setX(x+w/2-pStencil->w()/2);
01146 break;
01147 case AlignData::Right:
01148 pStencil->setX(x+w-pStencil->w());
01149 break;
01150 default:
01151 break;
01152 }
01153
01154 KivioMoveStencilCommand * cmd = new KivioMoveStencilCommand( i18n("Move Stencil"),
01155 pStencil, oldRect, pStencil->rect(), this);
01156 macro->addCommand(cmd);
01157 pStencil = m_lstSelection.next();
01158 }
01159
01160 m_pDoc->addCommand(macro);
01161 }
01162
01163 if (d.centerOfPage) {
01164 KMacroCommand *macro = new KMacroCommand(i18n("Move Stencil"));
01165 double w = m_pPageLayout.ptWidth;
01166 double h = m_pPageLayout.ptHeight;
01167 KoRect r = getRectForAllSelectedStencils();
01168 double dx = ((w - r.width()) / 2.0) - r.x();
01169 double dy = ((h - r.height()) / 2.0) - r.y();
01170 pStencil = m_lstSelection.first();
01171
01172 while( pStencil )
01173 {
01174 KoRect oldRect = pStencil->rect();
01175 pStencil->setPosition(pStencil->x() + dx, pStencil->y() + dy);
01176 KivioMoveStencilCommand * cmd = new KivioMoveStencilCommand( i18n("Move Stencil"),
01177 pStencil, oldRect, pStencil->rect(), this);
01178 macro->addCommand(cmd);
01179 pStencil = m_lstSelection.next();
01180 }
01181
01182 m_pDoc->addCommand(macro);
01183 }
01184 }
01185
01186 class XYSortedStencilList : public QPtrList<KivioStencil>
01187 {
01188 public:
01189 XYSortedStencilList(bool sortX) :xsort(sortX) {};
01190
01191 protected:
01192 int compareItems(QPtrCollection::Item i1, QPtrCollection::Item i2)
01193 {
01194 KivioStencil* s1 = (KivioStencil*)i1;
01195 KivioStencil* s2 = (KivioStencil*)i2;
01196 if (xsort) {
01197 if (s1->x() > s2->x())
01198 return 1;
01199 if (s1->x() < s2->x())
01200 return -1;
01201 return 0;
01202 }
01203 if (s1->y() > s2->y())
01204 return 1;
01205 if (s1->y() < s2->y())
01206 return -1;
01207 return 0;
01208 }
01209
01210 private:
01211 bool xsort;
01212 };
01213
01214
01215 void KivioPage::distributeStencils(DistributeData d)
01216 {
01217 double x = 0.0;
01218 double y = 0.0;
01219 double x1 = 0.0;
01220 double y1 = 0.0;
01221
01222 KivioStencil* pStencil = m_lstSelection.first();
01223 if (!pStencil)
01224 return;
01225
01226 XYSortedStencilList xSortList(true);
01227 XYSortedStencilList ySortList(false);
01228 QValueList<KoRect> oldRects;
01229
01230 while( pStencil )
01231 {
01232 xSortList.append(pStencil);
01233 ySortList.append(pStencil);
01234 oldRects.append(pStencil->rect());
01235 pStencil = m_lstSelection.next();
01236 }
01237 xSortList.sort();
01238 ySortList.sort();
01239
01240 switch (d.extent) {
01241 case DistributeData::Page:
01242 x = m_pPageLayout.ptLeft;
01243 y = m_pPageLayout.ptTop;
01244 x1 = m_pPageLayout.ptWidth - m_pPageLayout.ptRight;
01245 y1 = m_pPageLayout.ptHeight - m_pPageLayout.ptBottom;
01246 break;
01247 case DistributeData::Selection:
01248 pStencil = m_lstSelection.first();
01249 x = pStencil->x();
01250 y = pStencil->x();
01251 x1 = x + pStencil->w();
01252 y1 = y + pStencil->h();
01253 while( pStencil )
01254 {
01255 x = QMIN(x,pStencil->x());
01256 y = QMIN(y,pStencil->y());
01257 x1 = QMAX(x1,pStencil->x() + pStencil->w());
01258 y1 = QMAX(y1,pStencil->y() + pStencil->h());
01259 pStencil = m_lstSelection.next();
01260 }
01261 break;
01262 default:
01263 break;
01264 }
01265
01266
01267 KivioStencil* firstx = xSortList.first();
01268 KivioStencil* lastx = xSortList.last();
01269 double countx = (double)(xSortList.count()-1);
01270 double distx = 0.0;
01271 switch (d.h) {
01272 case DistributeData::Left:
01273 x1 = x1 - lastx->w();
01274 distx = (x1 - x)/countx;
01275 break;
01276 case DistributeData::Center:
01277 x = x + firstx->w()/2;
01278 x1 = x1 - lastx->w()/2;
01279 distx = (x1 - x)/countx;
01280 break;
01281 case DistributeData::Spacing: {
01282 double allw = 0.0;
01283 pStencil = xSortList.first();
01284 while( pStencil )
01285 {
01286 allw = allw + pStencil->w();
01287 pStencil = xSortList.next();
01288 }
01289 distx = (x1-x-allw)/countx;
01290 break; }
01291 case DistributeData::Right:
01292 x = x + firstx->w();
01293 distx = (x1 - x)/countx;
01294 break;
01295 default:
01296 break;
01297 }
01298
01299 double xx = x;
01300 switch (d.h) {
01301 case DistributeData::Center:
01302 pStencil = xSortList.first();
01303 while( pStencil )
01304 {
01305 pStencil->setX(xx - pStencil->w()/2);
01306 xx = xx + distx;
01307 pStencil = xSortList.next();
01308 }
01309 break;
01310 case DistributeData::Right:
01311 pStencil = xSortList.first();
01312 while( pStencil )
01313 {
01314 pStencil->setX(xx - pStencil->w());
01315 xx = xx + distx;
01316 pStencil = xSortList.next();
01317 }
01318 break;
01319 case DistributeData::Left:
01320 pStencil = xSortList.first();
01321 while( pStencil )
01322 {
01323 pStencil->setX(xx);
01324 xx = xx + distx;
01325 pStencil = xSortList.next();
01326 }
01327 break;
01328 case DistributeData::Spacing:
01329 pStencil = xSortList.first();
01330 while( pStencil )
01331 {
01332 pStencil->setX(xx);
01333 xx = xx + pStencil->w() + distx;
01334 pStencil = xSortList.next();
01335 }
01336 break;
01337 default:
01338 break;
01339 }
01340
01341 KivioStencil* firsty = ySortList.first();
01342 KivioStencil* lasty = ySortList.last();
01343 double county = (double)(ySortList.count()-1);
01344 double disty = 0.0;
01345 switch (d.v) {
01346 case DistributeData::Top:
01347 y1 = y1 - lasty->h();
01348 disty = (y1 - y)/county;
01349 break;
01350 case DistributeData::Center:
01351 y = y + firsty->h()/2;
01352 y1 = y1 - lasty->h()/2;
01353 disty = (y1 - y)/countx;
01354 break;
01355 case DistributeData::Spacing: {
01356 double allh = 0.0;
01357 pStencil = ySortList.first();
01358 while( pStencil )
01359 {
01360 allh = allh + pStencil->h();
01361 pStencil = ySortList.next();
01362 }
01363 disty = (y1-y-allh)/county;
01364 break; }
01365 case DistributeData::Bottom:
01366 y = y + firsty->h();
01367 disty = (y1 - y)/county;
01368 break;
01369 default:
01370 break;
01371 }
01372
01373 double yy = y;
01374 switch (d.v) {
01375 case DistributeData::Center:
01376 pStencil = ySortList.first();
01377 while( pStencil )
01378 {
01379 pStencil->setY(yy - pStencil->h()/2);
01380 yy = yy + disty;
01381 pStencil = ySortList.next();
01382 }
01383 break;
01384 case DistributeData::Bottom:
01385 pStencil = ySortList.first();
01386 while( pStencil )
01387 {
01388 pStencil->setY(yy - pStencil->h());
01389 yy = yy + disty;
01390 pStencil = ySortList.next();
01391 }
01392 break;
01393 case DistributeData::Top:
01394 pStencil = ySortList.first();
01395 while( pStencil )
01396 {
01397 pStencil->setY(yy);
01398 yy = yy + disty;
01399 pStencil = ySortList.next();
01400 }
01401 break;
01402 case DistributeData::Spacing:
01403 pStencil = ySortList.first();
01404 while( pStencil )
01405 {
01406 pStencil->setY(yy);
01407 yy = yy + pStencil->h() + disty;
01408 pStencil = ySortList.next();
01409 }
01410 break;
01411 default:
01412 break;
01413 }
01414
01415 if(d.v != DistributeData::None || d.h != DistributeData::None) {
01416 KMacroCommand *macro = new KMacroCommand(i18n("Move Stencil"));
01417 QValueListIterator<KoRect> it;
01418 pStencil = m_lstSelection.first();
01419
01420 for(it = oldRects.begin(); it != oldRects.end(); ++it) {
01421 KivioMoveStencilCommand * cmd = new KivioMoveStencilCommand(i18n("Move Stencil"),
01422 pStencil, (*it), pStencil->rect(), this);
01423 macro->addCommand( cmd);
01424 pStencil = m_lstSelection.next();
01425 }
01426
01427 m_pDoc->addCommand( macro );
01428 }
01429 }
01430
01431
01435 KoRect KivioPage::getRectForAllSelectedStencils()
01436 {
01437 KoRect rTotal, r;
01438
01439 KivioStencil *pStencil = m_lstSelection.first();
01440
01441
01442 if( pStencil )
01443 {
01444 rTotal = pStencil->rect();
01445
01446 pStencil = m_lstSelection.next();
01447 }
01448
01449
01450 while( pStencil )
01451 {
01452 r = pStencil->rect();
01453
01454 rTotal = rTotal.unite( r );
01455
01456 pStencil = m_lstSelection.next();
01457 }
01458
01459 return rTotal;
01460 }
01461
01465 KoRect KivioPage::getRectForAllStencils()
01466 {
01467 KoRect rTotal, r;
01468
01469 bool firstTime = true;
01470
01471 KivioLayer *pLayer;
01472 KivioStencil *pStencil;
01473
01474 pLayer = m_lstLayers.first();
01475 while( pLayer )
01476 {
01477 pStencil = pLayer->firstStencil();
01478 while( pStencil )
01479 {
01480 if( firstTime==true )
01481 {
01482 rTotal = pStencil->rect();
01483 firstTime = false;
01484 }
01485 else
01486 {
01487 r = pStencil->rect();
01488 rTotal = rTotal.unite( r );
01489 }
01490
01491 pStencil = pLayer->nextStencil();
01492 }
01493
01494 pLayer = m_lstLayers.next();
01495 }
01496
01497
01498 return rTotal;
01499 }
01500
01501 void KivioPage::setPaperLayout(const KoPageLayout &l)
01502 {
01503 m_pPageLayout = l;
01504 doc()->updateView(this);
01505 emit sig_pageLayoutChanged(m_pPageLayout);
01506 }
01507
01508 KivioConnectorTarget *KivioPage::connectPointToTarget( KivioConnectorPoint *p, double )
01509 {
01510 double oldX, oldY;
01511 KivioLayer *pLayer, *pCurLayer;
01512 bool doneSearching = false;
01513 KivioConnectorTarget *pTarget;
01514
01515 if( !p )
01516 return NULL;
01517
01518 if( p->connectable()==false )
01519 return NULL;
01520
01521 oldX = p->x();
01522 oldY = p->y();
01523
01524 pCurLayer = curLayer();
01525 pLayer = firstLayer();
01526
01527 while( pLayer && doneSearching==false )
01528 {
01529 if( pLayer != pCurLayer )
01530 {
01531 if( pLayer->connectable()==false || pLayer->visible()==false )
01532 {
01533 pLayer = nextLayer();
01534 continue;
01535 }
01536 }
01537
01538 if( (pTarget=pLayer->connectPointToTarget(p, 8.0f )) )
01539 {
01540 return pTarget;
01541 }
01542
01543 pLayer = nextLayer();
01544 }
01545
01546 return NULL;
01547 }
01548
01549 KoPoint KivioPage::snapToTarget( const KoPoint& p, double thresh, bool& hit )
01550 {
01551 KivioLayer *pLayer, *pCurLayer;
01552 KoPoint retVal = p;
01553
01554 pCurLayer = curLayer();
01555 pLayer = firstLayer();
01556
01557 while( pLayer && !hit )
01558 {
01559 if( pLayer != pCurLayer )
01560 {
01561 if( pLayer->connectable()==false || pLayer->visible()==false )
01562 {
01563 pLayer = nextLayer();
01564 continue;
01565 }
01566 }
01567
01568 retVal = pLayer->snapToTarget(p, thresh, hit);
01569
01570 pLayer = nextLayer();
01571 }
01572
01573 return retVal;
01574 }
01575
01576 void KivioPage::setHidePage(bool _hide)
01577 {
01578 setHidden(_hide);
01579 if(_hide)
01580 emit sig_PageHidden(this);
01581 else
01582 emit sig_PageShown(this);
01583 }
01584
01585 void KivioPage::setPaintSelected(bool paint)
01586 {
01587 KivioStencil *pStencil = m_lstSelection.first();
01588
01589 while( pStencil )
01590 {
01591 pStencil->setHidden(!paint);
01592 pStencil = m_lstSelection.next();
01593 }
01594 }
01595
01596 bool KivioPage::checkForStencilTypeInSelection(KivioStencilType type)
01597 {
01598 KivioStencil *pStencil = m_lstSelection.first();
01599
01600 while( pStencil )
01601 {
01602 if(pStencil->type() == type) {
01603 return true;
01604 }
01605
01606 pStencil = m_lstSelection.next();
01607 }
01608
01609 return false;
01610 }
01611
01612 bool KivioPage::checkForTextBoxesInSelection()
01613 {
01614 KivioStencil *pStencil = m_lstSelection.first();
01615
01616 while(pStencil) {
01617 if(pStencil->hasTextBox()) {
01618 return true;
01619 }
01620
01621 pStencil = m_lstSelection.next();
01622 }
01623
01624 return false;
01625 }
01626
01627 void KivioPage::setGuideLines(const QValueList<double> hGuideLines, const QValueList<double> vGuideLines)
01628 {
01629 m_hGuideLines = hGuideLines;
01630 m_vGuideLines = vGuideLines;
01631 }
01632
01633 void KivioPage::saveGuideLines(QDomElement& element)
01634 {
01635 QValueList<double>::iterator it;
01636 QValueList<double>::iterator itEnd = m_hGuideLines.end();
01637
01638 for(it = m_hGuideLines.begin(); it != itEnd; ++it) {
01639 QDomElement e = element.ownerDocument().createElement("Guideline");
01640 element.appendChild(e);
01641 XmlWriteDouble(e, "pos", *it);
01642 XmlWriteInt(e, "orient", (int)Qt::Horizontal);
01643 }
01644
01645 itEnd = m_vGuideLines.end();
01646
01647 for(it = m_vGuideLines.begin(); it != itEnd; ++it) {
01648 QDomElement e = element.ownerDocument().createElement("Guideline");
01649 element.appendChild(e);
01650 XmlWriteDouble(e, "pos", *it);
01651 XmlWriteInt(e, "orient", (int)Qt::Vertical);
01652 }
01653 }
01654
01655 void KivioPage::loadGuideLines(const QDomElement& element)
01656 {
01657 m_hGuideLines.clear();
01658 m_vGuideLines.clear();
01659
01660 QDomElement e = element.firstChild().toElement();
01661
01662 for( ; !e.isNull(); e = e.nextSibling().toElement() )
01663 {
01664 double pos = XmlReadDouble(e, "pos", 0.0);
01665 Qt::Orientation orient = (Qt::Orientation)XmlReadInt(e, "orient", 0);
01666 addGuideLine(orient, pos);
01667 }
01668 }
01669
01670 void KivioPage::addGuideLine(Qt::Orientation orientation, double position)
01671 {
01672 if(orientation == Qt::Horizontal) {
01673 m_hGuideLines.append(position);
01674 } else {
01675 m_vGuideLines.append(position);
01676 }
01677 }
01678
01679 #include "kivio_page.moc"