/*************************************************************************** * Copyright (C) 2004-2005 by David Saxton * * david@bluehaze.org * * * * 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 "itemdocument.h" #include "itemdocumentdata.h" #include "core/ktlconfig.h" #include #include #include #include #include #include #include const int minPrefixExp = -24; const int maxPrefixExp = 24; const int numPrefix = int((maxPrefixExp-minPrefixExp)/3)+1; const TQString SIprefix[] = {"y","z","a","f","p","n",TQChar(0xB5),"m","","k","M","G","T","P","E","Z","Y"}; Item::Item( ItemDocument *itemDocument, bool newItem, const TQString &id ) : TQObject(), TQCanvasPolygon( itemDocument->canvas() ) { m_bDynamicContent = false; m_bIsRaised = false; m_bDoneCreation = false; p_parentItem = 0l; b_deleted = false; p_itemDocument = itemDocument; m_baseZ = -1; if ( TQFontInfo(m_font).pixelSize() > 11 ) // It has to be > 11, not > 12, as (I think) pixelSize() rounds off the actual size m_font.setPixelSize(12); if (newItem) m_id = p_itemDocument->generateUID(id); else { m_id = id; p_itemDocument->registerUID(id); } } Item::~Item() { p_itemDocument->requestEvent( ItemDocument::ItemDocumentEvent::ResizeCanvasToItems ); p_itemDocument->unregisterUID( id() ); TQCanvasPolygon::hide(); const VariantDataMap::iterator variantDataEnd = m_variantData.end(); for ( VariantDataMap::iterator it = m_variantData.begin(); it != variantDataEnd; ++it ) delete it.data(); m_variantData.clear(); } void Item::removeItem() { if (b_deleted) return; b_deleted = true; hide(); setCanvas(0l); emit removed(this); p_itemDocument->appendDeleteList(this); } void Item::moveBy( double dx, double dy ) { TQCanvasPolygon::moveBy(dx,dy); emit movedBy( dx, dy ); } void Item::setChanged() { if (b_deleted) return; if (canvas()) canvas()->setChanged(boundingRect()); } void Item::setItemPoints( const TQPointArray & pa, bool setSizeFromPoints ) { m_itemPoints = pa; if (setSizeFromPoints) setSize( m_itemPoints.boundingRect() ); itemPointsChanged(); } void Item::itemPointsChanged() { setPoints(m_itemPoints); } void Item::setSize( TQRect sizeRect, bool forceItemPoints ) { if ( m_sizeRect == sizeRect && !forceItemPoints ) return; if ( !preResize(sizeRect) ) return; canvas()->setChanged(areaPoints().boundingRect()); m_sizeRect = sizeRect; if ( m_itemPoints.isEmpty() || forceItemPoints ) { setItemPoints( TQPointArray( m_sizeRect ), false ); } canvas()->setChanged(areaPoints().boundingRect()); postResize(); emit resized(); } ItemData Item::itemData() const { ItemData itemData; itemData.type = m_type; itemData.x = x(); itemData.y = y(); if ( !parentItem() ) itemData.z = m_baseZ; itemData.size = m_sizeRect; itemData.setSize = canResize(); if (p_parentItem) itemData.parentId = p_parentItem->id(); const VariantDataMap::const_iterator end = m_variantData.end(); for ( VariantDataMap::const_iterator it = m_variantData.begin(); it != end; ++it ) { switch( it.data()->type() ) { case Variant::Type::String: case Variant::Type::FileName: case Variant::Type::Port: case Variant::Type::Pin: case Variant::Type::VarName: case Variant::Type::Combo: case Variant::Type::Select: case Variant::Type::Multiline: case Variant::Type::SevenSegment: case Variant::Type::KeyPad: { itemData.dataString[it.key()] = it.data()->value().toString(); break; } case Variant::Type::Int: case Variant::Type::Double: { itemData.dataNumber[it.key()] = it.data()->value().toDouble(); break; } case Variant::Type::Color: { itemData.dataColor[it.key()] = it.data()->value().toColor(); break; } case Variant::Type::Bool: { itemData.dataBool[it.key()] = it.data()->value().toBool(); break; } case Variant::Type::Raw: { itemData.dataRaw[it.key()] = it.data()->value().toBitArray(); break; } case Variant::Type::PenStyle: case Variant::Type::PenCapStyle: { // These types are only created from DrawPart, and that class // deals with these, so we can ignore them break; } case Variant::Type::None: { // ? Maybe obsoleted data... break; } } } return itemData; } void Item::restoreFromItemData( const ItemData &itemData ) { move( itemData.x, itemData.y ); if ( canResize() ) setSize( itemData.size ); Item *parentItem = p_itemDocument->itemWithID( itemData.parentId ); if (parentItem) setParentItem(parentItem); else m_baseZ = itemData.z; //BEGIN Restore data const TQStringMap::const_iterator stringEnd = itemData.dataString.end(); for ( TQStringMap::const_iterator it = itemData.dataString.begin(); it != stringEnd; ++it ) { if ( hasProperty(it.key()) ) property( it.key() )->setValue( it.data() ); } const DoubleMap::const_iterator numberEnd = itemData.dataNumber.end(); for ( DoubleMap::const_iterator it = itemData.dataNumber.begin(); it != numberEnd; ++it ) { if ( hasProperty(it.key()) ) property( it.key() )->setValue( it.data() ); } const TQColorMap::const_iterator colorEnd = itemData.dataColor.end(); for ( TQColorMap::const_iterator it = itemData.dataColor.begin(); it != colorEnd; ++it ) { if ( hasProperty(it.key()) ) property( it.key() )->setValue( it.data() ); } const BoolMap::const_iterator boolEnd = itemData.dataBool.end(); for ( BoolMap::const_iterator it = itemData.dataBool.begin(); it != boolEnd; ++it ) { if ( hasProperty(it.key()) ) property( it.key() )->setValue( TQVariant( it.data() ) ); } const TQBitArrayMap::const_iterator rawEnd = itemData.dataRaw.end(); for ( TQBitArrayMap::const_iterator it = itemData.dataRaw.begin(); it != rawEnd; ++it ) { if ( hasProperty(it.key()) ) property( it.key() )->setValue( it.data() ); } //END Restore Data } bool Item::mousePressEvent( const EventInfo &eventInfo ) { Q_UNUSED(eventInfo); return false; } bool Item::mouseReleaseEvent( const EventInfo &eventInfo ) { Q_UNUSED(eventInfo); return false; } bool Item::mouseMoveEvent( const EventInfo &eventInfo ) { Q_UNUSED(eventInfo); return false; } bool Item::wheelEvent( const EventInfo &eventInfo ) { Q_UNUSED(eventInfo); return false; } void Item::enterEvent() { } void Item::leaveEvent() { } bool Item::mouseDoubleClickEvent( const EventInfo &eventInfo ) { Q_UNUSED(eventInfo); typedef TQValueList VarPtrLst; VarPtrLst list; const VariantDataMap::iterator variantDataEnd = m_variantData.end(); for ( VariantDataMap::iterator it = m_variantData.begin(); it != variantDataEnd; ++it ) { if ( it.data()->type() == Variant::Type::Multiline ) { list.append(it.data()); } } if ( list.count() > 1 ) { kdWarning() << "Item::mouseDoubleClickEvent: Can't handle more than one multiline data"<caption(), "", v->getValue(), ok ); KDialogBase *dlg = new KDialogBase( 0l, "", true, v->editorCaption(), KDialogBase::Ok|KDialogBase::Cancel|KDialogBase::User1, KDialogBase::Ok, false, KStdGuiItem::clear() ); TQFrame *frame = dlg->makeMainWidget(); TQVBoxLayout *layout = new TQVBoxLayout( frame, 0, dlg->spacingHint() ); KTextEdit *textEdit = new KTextEdit( frame ); textEdit->setTextFormat( PlainText ); textEdit->setText( v->value().toString() ); layout->addWidget( textEdit, 10 ); textEdit->setFocus(); connect( dlg, TQT_SIGNAL( user1Clicked() ), textEdit, TQT_SLOT( clear() ) ); dlg->setMinimumWidth( 600 ); if ( dlg->exec() == KDialogBase::Accepted ) { v->setValue( textEdit->text() ); dataChanged(); p_itemDocument->setModified(true); } delete dlg; return true; } void Item::setSelected( bool yes ) { if ( isSelected() == yes ) { return; } TQCanvasPolygon::setSelected(yes); yes ? (emit selected(this)) : (emit unselected(this)); } void Item::setParentItem( Item *newParentItem ) { // kdDebug() << k_funcinfo << "this = "<addChild(this); } } p_parentItem = newParentItem; (void)level(); reparented( oldParentItem, newParentItem ); p_itemDocument->slotUpdateZOrdering(); } int Item::level() const { return p_parentItem ? p_parentItem->level()+1 : 0; } ItemList Item::children( bool includeGrandChildren ) const { if (!includeGrandChildren) return m_children; ItemList children = m_children; ItemList::const_iterator end = m_children.end(); for ( ItemList::const_iterator it = m_children.begin(); it != end; ++it ) { if (!*it) continue; children += (*it)->children(true); } return children; } void Item::addChild( Item *child ) { if ( !child ) return; if ( child->contains(this) ) { // kdError() << k_funcinfo << "Attempting to add a child to this item that is already a parent of this item. Incest results in stack overflow." << endl; return; } if ( contains( child, true ) ) { // kdError() << k_funcinfo << "Already have child " << child << endl; return; } m_children.append(child); connect( child, TQT_SIGNAL(removed(Item* )), this, TQT_SLOT(removeChild(Item* )) ); child->setParentItem(this); childAdded(child); p_itemDocument->slotUpdateZOrdering(); } void Item::removeChild( Item *child ) { if ( !child || !m_children.contains(child) ) return; m_children.remove(child); disconnect( child, TQT_SIGNAL(removed(Item* )), this, TQT_SLOT(removeChild(Item* )) ); childRemoved(child); p_itemDocument->slotUpdateZOrdering(); } bool Item::contains( Item *item, bool direct ) const { const ItemList::const_iterator end = m_children.end(); for ( ItemList::const_iterator it = m_children.begin(); it != end; ++it ) { if ( (Item*)*it == item || ( !direct && (*it)->contains( item, false ) ) ) return true; } return false; } void Item::setRaised( bool isRaised ) { m_bIsRaised = isRaised; // We'll get called later to update our Z } void Item::updateZ( int baseZ ) { m_baseZ = baseZ; double z = ItemDocument::Z::Item + (ItemDocument::Z::DeltaItem)*baseZ; if ( isRaised() ) z += ItemDocument::Z::RaisedItem - ItemDocument::Z::Item; setZ(z); const ItemList::const_iterator end = m_children.end(); for ( ItemList::const_iterator it = m_children.begin(); it != end; ++it ) { if (*it) (*it)->updateZ(baseZ+1); } } int Item::getNumberPre( double num ) { return (int)(num/getMultiplier(num)); } TQString Item::getNumberMag( double num ) { if ( num == 0. ) return ""; const double exp_n = std::log10(std::abs(num)); if ( exp_n < minPrefixExp+3 ) return SIprefix[0]; else if ( exp_n >= maxPrefixExp ) return SIprefix[numPrefix-1]; else return SIprefix[(int)std::floor((double)(exp_n/3))-(int)floor(double(minPrefixExp/3))]; } double Item::getMultiplier( double num ) { if ( num == 0. ) return 1.; else return std::pow( 10, 3*std::floor(std::log10(std::abs(num))/3) ); } double Item::getMultiplier( const TQString &_mag ) { TQString mag; // Allow the user to enter in "u" instead of mu, as unfortunately many keyboards don't have the mu key if ( _mag == "u" ) mag = TQChar(0xB5); else mag = _mag; for ( int i=0; ivalue().toDouble() : 0.0; } int Item::dataInt( const TQString & id ) const { Variant * variant = property(id); return variant ? variant->value().toInt() : 0; } bool Item::dataBool( const TQString & id ) const { Variant * variant = property(id); return variant ? variant->value().toBool() : false; } TQString Item::dataString( const TQString & id ) const { Variant * variant = property(id); return variant ? variant->value().toString() : TQString(); } TQColor Item::dataColor( const TQString & id ) const { Variant * variant = property(id); return variant ? variant->value().toColor() : TQt::black; } Variant * Item::createProperty( const TQString & id, Variant::Type::Value type ) { if ( !m_variantData.contains(id) ) { m_variantData[id] = new Variant(type); if (m_bDoneCreation) connect( m_variantData[id], TQT_SIGNAL(valueChanged(TQVariant,TQVariant)), this, TQT_SLOT(dataChanged()) ); } return m_variantData[id]; } Variant * Item::property( const TQString & id ) const { if ( m_variantData.contains(id) ) return m_variantData[id]; kdError() << k_funcinfo << " No such property with id " << id << endl; return 0l; } bool Item::hasProperty( const TQString & id ) const { return m_variantData.contains(id); } void Item::finishedCreation( ) { m_bDoneCreation = true; const VariantDataMap::iterator end = m_variantData.end(); for ( VariantDataMap::iterator it = m_variantData.begin(); it != end; ++it ) connect( it.data(), TQT_SIGNAL(valueChanged(TQVariant,TQVariant)), this, TQT_SLOT(dataChanged()) ); dataChanged(); } //END Data stuff #include "item.moc"