diff options
Diffstat (limited to 'src/iteminterface.cpp')
-rw-r--r-- | src/iteminterface.cpp | 601 |
1 files changed, 601 insertions, 0 deletions
diff --git a/src/iteminterface.cpp b/src/iteminterface.cpp new file mode 100644 index 0000000..6b9c1af --- /dev/null +++ b/src/iteminterface.cpp @@ -0,0 +1,601 @@ +/*************************************************************************** + * 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 "circuitview.h" +#include "colorcombo.h" +#include "contexthelp.h" +#include "cnitem.h" +#include "cnitemgroup.h" +#include "doublespinbox.h" +#include "itemdocument.h" +#include "itemeditor.h" +#include "iteminterface.h" +#include "itemview.h" +#include "ktechlab.h" + +#include <kcombobox.h> +#include <kdebug.h> +#include <klineedit.h> +#include <knuminput.h> +#include <kurlrequester.h> +#include <ktoolbar.h> +#include <qapplication.h> +#include <qlabel.h> +#include <qcheckbox.h> + +#include <assert.h> + +ItemInterface * ItemInterface::m_pSelf = 0l; + +ItemInterface * ItemInterface::self( KTechlab * ktechlab ) +{ + if ( !m_pSelf ) + { + assert(ktechlab); + m_pSelf = new ItemInterface(ktechlab); + } + return m_pSelf; +} + + +ItemInterface::ItemInterface( KTechlab * ktechlab ) + : QObject(ktechlab), + p_ktechlab(ktechlab) +{ + m_pActiveItemEditorToolBar = 0; + p_cvb = 0l; + p_itemGroup = 0l; + p_lastItem = 0l; + m_currentActionTicket = -1; + m_toolBarWidgetID = -1; +} + + +ItemInterface::~ItemInterface() +{ +} + + +void ItemInterface::slotGetActionTicket() +{ + m_currentActionTicket = p_cvb ? p_cvb->getActionTicket() : -1; +} + + +void ItemInterface::slotItemDocumentChanged( ItemDocument * doc ) +{ + slotClearAll(); + if ( ItemDocument * itemDocument = dynamic_cast<ItemDocument*>((Document*)p_cvb) ) + { + disconnect( itemDocument, SIGNAL(itemSelected(Item*)), this, SLOT(slotUpdateItemInterface()) ); + disconnect( itemDocument, SIGNAL(itemUnselected(Item*)), this, SLOT(slotUpdateItemInterface()) ); + } + + p_itemGroup = 0l; + p_cvb = doc; + + slotGetActionTicket(); + + if (!p_cvb) + return; + + connect( p_cvb, SIGNAL(itemSelected(Item*)), this, SLOT(slotUpdateItemInterface()) ); + connect( p_cvb, SIGNAL(itemUnselected(Item*)), this, SLOT(slotUpdateItemInterface()) ); + + p_itemGroup = p_cvb->selectList(); + + slotUpdateItemInterface(); +} + + +void ItemInterface::clearItemEditorToolBar() +{ + if ( m_pActiveItemEditorToolBar && m_toolBarWidgetID != -1 ) + m_pActiveItemEditorToolBar->removeItem(m_toolBarWidgetID); + m_toolBarWidgetID = -1; + itemEditTBCleared(); +} + + +void ItemInterface::slotClearAll() +{ + ContextHelp::self()->slotClear(); + ItemEditor::self()->slotClear(); + clearItemEditorToolBar(); + p_lastItem = 0l; +} + + +void ItemInterface::slotMultipleSelected() +{ + ContextHelp::self()->slotMultipleSelected(); + ItemEditor::self()->slotMultipleSelected(); + clearItemEditorToolBar(); + p_lastItem = 0l; +} + + +void ItemInterface::slotUpdateItemInterface() +{ + if (!p_itemGroup) + return; + + slotGetActionTicket(); + updateItemActions(); + + if (!p_itemGroup->itemsAreSameType() ) + { + slotMultipleSelected(); + return; + } + if ( p_lastItem && p_itemGroup->activeItem() ) + { + ItemEditor::self()->updateMergeDefaults(p_itemGroup); + return; + } + + p_lastItem = p_itemGroup->activeItem(); + if (!p_lastItem) + { + slotClearAll(); + return; + } + + ContextHelp::self()->slotUpdate(p_lastItem); + ItemEditor::self()->slotUpdate(p_itemGroup); + if ( CNItem * cnItem = dynamic_cast<CNItem*>((Item*)p_lastItem) ) + ItemEditor::self()->slotUpdate(cnItem); + + // Update item editor toolbar + if ( ItemView * itemView = dynamic_cast<ItemView*>(p_cvb->activeView()) ) + { + if ( m_pActiveItemEditorToolBar = dynamic_cast<KToolBar*>(p_ktechlab->factory()->container("itemEditorTB",itemView)) ) + { + m_pActiveItemEditorToolBar->setFullSize( true ); + QWidget * widget = configWidget(); + m_toolBarWidgetID = 1; + m_pActiveItemEditorToolBar->insertWidget( m_toolBarWidgetID, 0, widget ); + } + } +} + + +void ItemInterface::updateItemActions() +{ + ItemView * itemView = ((ItemDocument*)p_cvb) ? dynamic_cast<ItemView*>(p_cvb->activeView()) : 0l; + if ( !itemView ) + return; + + bool itemsSelected = p_itemGroup && p_itemGroup->itemCount(); + + itemView->action("edit_raise")->setEnabled(itemsSelected); + itemView->action("edit_lower")->setEnabled(itemsSelected); + p_ktechlab->action("edit_cut")->setEnabled(itemsSelected); + p_ktechlab->action("edit_copy")->setEnabled(itemsSelected); + + CNItemGroup * cnItemGroup = dynamic_cast<CNItemGroup*>((ItemGroup*)p_itemGroup); + CircuitView * circuitView = dynamic_cast<CircuitView*>(itemView); + + if ( cnItemGroup && circuitView ) + { + circuitView->action("edit_flip")->setEnabled(cnItemGroup->canFlip()); + bool canRotate = cnItemGroup->canRotate(); + circuitView->action("edit_rotate_ccw")->setEnabled(canRotate); + circuitView->action("edit_rotate_cw")->setEnabled(canRotate); + } +} + + +void ItemInterface::setFlowPartOrientation( unsigned orientation ) +{ + CNItemGroup *cnItemGroup = dynamic_cast<CNItemGroup*>((ItemGroup*)p_itemGroup); + if (!cnItemGroup) + return; + + cnItemGroup->setFlowPartOrientation( orientation ); +} + + +void ItemInterface::setComponentOrientation( int angleDegrees, bool flipped ) +{ + CNItemGroup *cnItemGroup = dynamic_cast<CNItemGroup*>((ItemGroup*)p_itemGroup); + if (!cnItemGroup) + return; + + cnItemGroup->setComponentOrientation( angleDegrees, flipped ); +} + + +void ItemInterface::itemEditTBCleared() +{ + m_stringLineEditMap.clear(); + m_stringComboBoxMap.clear(); + m_stringURLReqMap.clear(); + m_intSpinBoxMap.clear(); + m_doubleSpinBoxMap.clear(); + m_colorComboMap.clear(); + m_boolCheckMap.clear(); +} + + +// The bool specifies whether advanced data should be shown +QWidget * ItemInterface::configWidget() +{ + if ( !p_itemGroup || !p_itemGroup->activeItem() || !m_pActiveItemEditorToolBar ) + return 0l; + + VariantDataMap *variantMap = p_itemGroup->activeItem()->variantMap(); + + QWidget * parent = m_pActiveItemEditorToolBar; + + // Create new widget with the toolbar or dialog as the parent + QWidget * configWidget = new QWidget( parent, "tbConfigWidget" ); + configWidget->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding, 1, 1 ) ); + + QHBoxLayout * configLayout = new QHBoxLayout( configWidget ); +// configLayout->setAutoAdd( true ); + configLayout->setSpacing( 6 ); + +// configLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + + const VariantDataMap::iterator vaEnd = variantMap->end(); + for ( VariantDataMap::iterator vait = variantMap->begin(); vait != vaEnd; ++vait ) + { + if ( vait.data()->isHidden() || vait.data()->isAdvanced() ) + continue; + + const Variant::Type::Value type = vait.data()->type(); + + // common to all types apart from bool + QString toolbarCaption = vait.data()->toolbarCaption(); + if ( type != Variant::Type::Bool && !toolbarCaption.isEmpty() ) + configLayout->addWidget( new QLabel( toolbarCaption, configWidget ) ); + + QWidget * editWidget = 0l; // Should be set to the created widget + + switch( type ) + { + case Variant::Type::Port: + case Variant::Type::Pin: + case Variant::Type::VarName: + case Variant::Type::Combo: + case Variant::Type::Select: + case Variant::Type::KeyPad: + case Variant::Type::SevenSegment: + { + QString value = vait.data()->value().toString(); + if ( !value.isEmpty() && !vait.data()->allowed().contains(value) ) + vait.data()->appendAllowed(value); + + const QStringList allowed = vait.data()->allowed(); + + KComboBox * box = new KComboBox(configWidget); + + box->insertStringList(allowed); + box->setCurrentItem(value); + + if ( type == Variant::Type::VarName || type == Variant::Type::Combo ) + box->setEditable( true ); + + m_stringComboBoxMap[vait.key()] = box; + connectMapWidget( box, SIGNAL(textChanged(const QString &))); + connectMapWidget( box, SIGNAL(activated(const QString &))); + + editWidget = box; + break; + } + case Variant::Type::FileName: + { + QString value = vait.data()->value().toString(); + if ( !vait.data()->allowed().contains(value) ) + vait.data()->appendAllowed(value); + + const QStringList allowed = vait.data()->allowed(); + + KURLComboRequester * urlreq = new KURLComboRequester( configWidget ); + urlreq->setFilter( vait.data()->filter() ); + connectMapWidget( urlreq, SIGNAL(urlSelected(const QString &)) ); + m_stringURLReqMap[vait.key()] = urlreq; + + KComboBox * box = urlreq->comboBox(); + box->insertStringList(allowed); + box->setEditable( true ); + + // Note this has to be called after inserting the allowed list + urlreq->setURL( vait.data()->value().toString() ); + + // Generally we only want a file name once the user has finished typing out the full file name. + connectMapWidget( box, SIGNAL(returnPressed(const QString &))); + connectMapWidget( box, SIGNAL(activated(const QString &))); + + editWidget = urlreq; + break; + } + case Variant::Type::String: + { + KLineEdit * edit = new KLineEdit( configWidget ); + + edit->setText( vait.data()->value().toString() ); + connectMapWidget(edit,SIGNAL(textChanged(const QString &))); + m_stringLineEditMap[vait.key()] = edit; + editWidget = edit; + break; + } + case Variant::Type::Int: + { + KIntSpinBox *spin = new KIntSpinBox( (int)vait.data()->minValue(), (int)vait.data()->maxValue(), 1, vait.data()->value().toInt(), 10, configWidget ); + + connectMapWidget( spin, SIGNAL(valueChanged(int)) ); + m_intSpinBoxMap[vait.key()] = spin; + editWidget = spin; + break; + } + case Variant::Type::Double: + { + DoubleSpinBox *spin = new DoubleSpinBox( vait.data()->minValue(), vait.data()->maxValue(), vait.data()->minAbsValue(), vait.data()->value().toDouble(), vait.data()->unit(), configWidget ); + + connectMapWidget( spin, SIGNAL(valueChanged(double))); + m_doubleSpinBoxMap[vait.key()] = spin; + editWidget = spin; + break; + } + case Variant::Type::Color: + { + QColor value = vait.data()->value().toColor(); + + ColorCombo * colorBox = new ColorCombo( (ColorCombo::ColorScheme)vait.data()->colorScheme(), configWidget ); + + colorBox->setColor( value ); + connectMapWidget( colorBox, SIGNAL(activated(const QColor &))); + m_colorComboMap[vait.key()] = colorBox; + + editWidget = colorBox; + break; + } + case Variant::Type::Bool: + { + const bool value = vait.data()->value().toBool(); + QCheckBox * box = new QCheckBox( vait.data()->toolbarCaption(), configWidget ); + + box->setChecked(value); + connectMapWidget( box, SIGNAL(toggled(bool))); + m_boolCheckMap[vait.key()] = box; + editWidget = box; + break; + } + case Variant::Type::Raw: + case Variant::Type::PenStyle: + case Variant::Type::PenCapStyle: + case Variant::Type::Multiline: + case Variant::Type::None: + { + // Do nothing, as these data types are not handled in the toolbar + break; + } + } + + if ( !editWidget ) + continue; + + // In the case of the toolbar, we don't want it too high + if ( editWidget->height() > parent->height()-2 ) + editWidget->setMaximumHeight( parent->height()-2 ); + + switch ( type ) + { + case Variant::Type::VarName: + case Variant::Type::Combo: + case Variant::Type::String: + { + QSizePolicy p( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed, 1, 1 ); + + editWidget->setSizePolicy( p ); + editWidget->setMaximumWidth( 250 ); + break; + } + + case Variant::Type::FileName: + case Variant::Type::Port: + case Variant::Type::Pin: + case Variant::Type::Select: + case Variant::Type::KeyPad: + case Variant::Type::SevenSegment: + case Variant::Type::Int: + case Variant::Type::Double: + case Variant::Type::Color: + case Variant::Type::Bool: + case Variant::Type::Raw: + case Variant::Type::PenStyle: + case Variant::Type::PenCapStyle: + case Variant::Type::Multiline: + case Variant::Type::None: + break; + } + + configLayout->addWidget( editWidget ); + } + + configLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Fixed ) ); + + return configWidget; +} + + +void ItemInterface::connectMapWidget( QWidget *widget, const char *_signal ) +{ + connect( widget, _signal, this, SLOT(tbDataChanged()) ); +} + + +void ItemInterface::tbDataChanged() +{ + // Manual string values + const KLineEditMap::iterator m_stringLineEditMapEnd = m_stringLineEditMap.end(); + for ( KLineEditMap::iterator leit = m_stringLineEditMap.begin(); leit != m_stringLineEditMapEnd; ++leit ) + { + slotSetData( leit.key(), leit.data()->text() ); + } + + // String values from comboboxes + const KComboBoxMap::iterator m_stringComboBoxMapEnd = m_stringComboBoxMap.end(); + for ( KComboBoxMap::iterator cmit = m_stringComboBoxMap.begin(); cmit != m_stringComboBoxMapEnd; ++cmit ) + { + slotSetData( cmit.key(), cmit.data()->currentText() ); + } + + // Colors values from colorcombos + const ColorComboMap::iterator m_colorComboMapEnd = m_colorComboMap.end(); + for ( ColorComboMap::iterator ccit = m_colorComboMap.begin(); ccit != m_colorComboMapEnd; ++ccit ) + { + slotSetData( ccit.key(), ccit.data()->color() ); + } + + // Bool values from checkboxes + const QCheckBoxMap::iterator m_boolCheckMapEnd = m_boolCheckMap.end(); + for ( QCheckBoxMap::iterator chit = m_boolCheckMap.begin(); chit != m_boolCheckMapEnd; ++chit ) + { + slotSetData( chit.key(), chit.data()->isChecked() ); + } + + const IntSpinBoxMap::iterator m_intSpinBoxMapEnd = m_intSpinBoxMap.end(); + for ( IntSpinBoxMap::iterator it = m_intSpinBoxMap.begin(); it != m_intSpinBoxMapEnd; ++it ) + { + slotSetData( it.key(), it.data()->value() ); + } + + // (?) Combined values from spin boxes and combo boxes + // (?) Get values from all spin boxes + + const DoubleSpinBoxMap::iterator m_doubleSpinBoxMapEnd = m_doubleSpinBoxMap.end(); + for ( DoubleSpinBoxMap::iterator sbit = m_doubleSpinBoxMap.begin(); sbit != m_doubleSpinBoxMapEnd; ++sbit ) + { +// VariantDataMap::iterator vait = variantData.find(sbit.key()); + slotSetData( sbit.key(), sbit.data()->value() ); + } + + // Filenames from KURLRequesters + const KURLReqMap::iterator m_stringURLReqMapEnd = m_stringURLReqMap.end(); + for ( KURLReqMap::iterator urlit = m_stringURLReqMap.begin(); urlit != m_stringURLReqMapEnd; ++urlit ) + { + slotSetData( urlit.key(), urlit.data()->url() ); + } + + if (p_cvb) + p_cvb->setModified(true); +} + + + + +void ItemInterface::slotSetData( const QString &id, QVariant value ) +{ + if ( !p_itemGroup || (p_itemGroup->itemCount() == 0) ) + return; + + if ( !p_itemGroup->itemsAreSameType() ) + { + kdDebug() << k_funcinfo << "Items are not the same type!"<<endl; + return; + } + + const ItemList itemList = p_itemGroup->items(true); + const ItemList::const_iterator end = itemList.end(); + for ( ItemList::const_iterator it = itemList.begin(); it != end; ++it ) + { + if (*it) + (*it)->property(id)->setValue(value); + } + if (p_cvb) + p_cvb->setModified(true); + + + VariantDataMap * variantMap = (*itemList.begin())->variantMap(); + VariantDataMap::iterator it = variantMap->find(id); + if ( it == variantMap->end() ) + return; + + + // setData might have been called from the PropertiesListView, so want + // to see if the toolbar widgets want setting + + switch( it.data()->type() ) + { + case Variant::Type::String: + { + KLineEditMap::iterator mit = m_stringLineEditMap.find(id); + if ( mit != m_stringLineEditMap.end() ) mit.data()->setText( it.data()->value().toString() ); + break; + } + case Variant::Type::FileName: + { + KURLReqMap::iterator mit = m_stringURLReqMap.find(id); + if ( mit != m_stringURLReqMap.end() ) mit.data()->setURL( it.data()->value().toString() ); + break; + } + case Variant::Type::PenCapStyle: + case Variant::Type::PenStyle: + case Variant::Type::Port: + case Variant::Type::Pin: + case Variant::Type::VarName: + case Variant::Type::Combo: + case Variant::Type::Select: + case Variant::Type::SevenSegment: + case Variant::Type::KeyPad: + { + KComboBoxMap::iterator mit = m_stringComboBoxMap.find(id); + if ( mit != m_stringComboBoxMap.end() ) mit.data()->setCurrentItem( it.data()->value().toString() ); + break; + } + case Variant::Type::Int: + { + IntSpinBoxMap::iterator mit = m_intSpinBoxMap.find(id); + if ( mit != m_intSpinBoxMap.end() ) { + KIntSpinBox *sb = mit.data(); + sb->setValue( it.data()->value().toInt() ); + } + break; + } + case Variant::Type::Double: + { + DoubleSpinBoxMap::iterator mit = m_doubleSpinBoxMap.find(id); + if ( mit != m_doubleSpinBoxMap.end() ) { + DoubleSpinBox *sb = mit.data(); + sb->setValue( it.data()->value().toDouble() ); + } + break; + } + case Variant::Type::Color: + { + ColorComboMap::iterator mit = m_colorComboMap.find(id); + if ( mit != m_colorComboMap.end() ) mit.data()->setColor( it.data()->value().toColor() ); + break; + } + case Variant::Type::Bool: + { + QCheckBoxMap::iterator mit = m_boolCheckMap.find(id); + if ( mit != m_boolCheckMap.end() ) mit.data()->setChecked( it.data()->value().toBool() ); + break; + } + case Variant::Type::Raw: + case Variant::Type::Multiline: + case Variant::Type::None: + { + // This data will never be handled in the toolbar/PLV, so no need to worry about it + break; + } + } + + ItemEditor::self()->updateMergeDefaults(p_itemGroup); + + if (p_cvb) + p_cvb->requestStateSave(m_currentActionTicket); +} + +#include "iteminterface.moc" |