/* This file is part of the KDE project Copyright (C) 2006 Sebastian Sauer This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "keximacroproperty.h" #include #include #include #include #include #include #include #include #include #include "../lib/variable.h" #include "../lib/macroitem.h" #define KEXIMACRO_PROPERTYEDITORTYPE 5682 /************************************************************* * KexiMacroProperty */ /** * @internal d-pointer class to be more flexible on future extension of the * functionality without to much risk to break the binary compatibility. */ class KexiMacroProperty::Private { public: /** The @a KoMacro::MacroItem the custom property uses internal. Together with the name we are able to identify the used variable at runtime. */ KSharedPtr macroitem; /** The name the variable @a KoMacro::Variable is known as in the @a KoMacro::MacroItem defined above. */ TQString name; }; KexiMacroProperty::KexiMacroProperty(KoProperty::Property* parent, KSharedPtr macroitem, const TQString& name) : KoProperty::CustomProperty(parent) , d( new Private() ) { d->macroitem = macroitem; d->name = name; init(); } KexiMacroProperty::~KexiMacroProperty() { delete d; } void KexiMacroProperty::init() { Q_ASSERT( d->macroitem != 0 ); //kdDebug() << "--------- KexiMacroProperty::set() macroitem=" << d->macroitem->name() << " name=" << d->name << endl; KSharedPtr action = d->macroitem->action(); KSharedPtr actionvariable = action->variable(d->name); if(! actionvariable.data()) { kdDebug() << "KexiMacroProperty::createProperty() Skipped cause there exists no such action=" << d->name << endl; return; } KSharedPtr variable = d->macroitem->variable(d->name, true/*checkaction*/); if(! variable.data()) { kdDebug() << "KexiMacroProperty::createProperty() Skipped cause there exists no such variable=" << d->name << endl; return; } //TESTCASE!!!!!!!!!!!!!!!!!!!!!! //if(! variable->isEnabled()) qFatal( TQString("############## VARIABLE=%1").tqarg(variable->name()).latin1() ); Q_ASSERT(! d->name.isNull()); m_property->setName( d->name.latin1() ); m_property->setCaption( actionvariable->text() ); m_property->setDescription( action->comment() ); m_property->setValue( variable->variant(), true ); m_property->setType( KEXIMACRO_PROPERTYEDITORTYPE ); // use our own propertytype } KoProperty::Property* KexiMacroProperty::parentProperty() const { return m_property; } void KexiMacroProperty::setValue(const TQVariant &value, bool rememberOldValue) { Q_UNUSED(rememberOldValue); kdDebug()<<"KexiMacroProperty::setValue name="<name<<" value="<setValue() does check if the value changed by using // this-value() and cause we already set it above, m_property->setValue() // will be aborted. Well, we don't touch the properties value and handle // it all via our CustomProperty class anyway. So, just ignore the property. //m_property->setValue(this->value(), rememberOldValue, false/*useCustomProperty*/); emit valueChanged(); } TQVariant KexiMacroProperty::value() const { KSharedPtr variable = d->macroitem->variable(d->name, true); Q_ASSERT( variable.data() != 0 ); return variable.data() ? variable->variant() : TQVariant(); } bool KexiMacroProperty::handleValue() const { return true; // we handle getting and setting of values and don't need KoProperty::Property for it. } KSharedPtr KexiMacroProperty::macroItem() const { return d->macroitem; } TQString KexiMacroProperty::name() const { return d->name; } KSharedPtr KexiMacroProperty::variable() const { return d->macroitem->variable(d->name, true/*checkaction*/); } KoProperty::Property* KexiMacroProperty::createProperty(KSharedPtr macroitem, const TQString& name) { KoProperty::Property* property = new KoProperty::Property(); KexiMacroProperty* customproperty = new KexiMacroProperty(property, macroitem, name); if(! customproperty->variable().data()) { kdWarning() << "KexiMacroProperty::createProperty() No such variable" << endl; delete customproperty; customproperty = 0; delete property; property = 0; return 0; } property->setCustomProperty(customproperty); return property; } /************************************************************* * KexiMacroPropertyFactory */ KexiMacroPropertyFactory::KexiMacroPropertyFactory(TQObject* parent) : KoProperty::CustomPropertyFactory(parent) { } KexiMacroPropertyFactory::~KexiMacroPropertyFactory() { } KoProperty::CustomProperty* KexiMacroPropertyFactory::createCustomProperty(KoProperty::Property* parent) { kdDebug()<<"KexiMacroPropertyFactory::createCustomProperty parent="<name()<customProperty(); KexiMacroProperty* parentcustomproperty = dynamic_cast(customproperty); if(! parentcustomproperty) { kdWarning() << "KexiMacroPropertyFactory::createCustomProperty() parent=" << parent->name() << " has an invalid customproperty." << endl; return 0; } KSharedPtr macroitem = parentcustomproperty->macroItem(); Q_ASSERT( macroitem.data() != 0 ); const TQString name = parentcustomproperty->name(); Q_ASSERT(! name.isEmpty()); KexiMacroProperty* macroproperty = new KexiMacroProperty(parent, macroitem, name); if(! macroproperty->variable().data()) { delete macroproperty; macroproperty = 0; return 0; } return macroproperty; } KoProperty::Widget* KexiMacroPropertyFactory::createCustomWidget(KoProperty::Property* property) { kdDebug()<<"KexiMacroPropertyFactory::createCustomWidget property="<name()<factoryForEditorType(KEXIMACRO_PROPERTYEDITORTYPE); if(! factory) { factory = new KexiMacroPropertyFactory( KoProperty::FactoryManager::self() ); KoProperty::FactoryManager::self()->registerFactoryForEditor(KEXIMACRO_PROPERTYEDITORTYPE, factory); } } /************************************************************* * KexiMacroPropertyWidget */ /** * @internal implementation of a TQListBoxItem to display the items of the * combobox used within @a KexiMacroPropertyWidget to handle variables * within a @a ListBox instance. */ class ListBoxItem : public TQListBoxText { public: ListBoxItem(TQListBox* listbox) : TQListBoxText(listbox), m_enabled(true) {} ListBoxItem(TQListBox* listbox, const TQString& text, TQListBoxItem* after) : TQListBoxText(listbox, text, after), m_enabled(true) {} virtual ~ListBoxItem() {} void setEnabled(bool enabled) { m_enabled = enabled; } virtual int width(const TQListBox* lb) const { Q_ASSERT( dynamic_cast( lb->parent() ) ); return static_cast( lb->parent() )->lineEdit()->width() + 2; } virtual int height(const TQListBox* lb) const { Q_ASSERT( dynamic_cast( lb->parent() ) ); return m_enabled ? static_cast( lb->parent() )->height() + 2 : 0; } private: bool m_enabled; }; /** * @internal implementation of a @a ListBoxItem to provide an editable * @a KoProperty::Widget as TQListBoxItem in a @a ListBox instance. */ class EditListBoxItem : public ListBoxItem { public: EditListBoxItem(TQListBox* listbox, KexiMacroProperty* macroproperty) : ListBoxItem(listbox) , m_macroproperty(macroproperty) , m_prop(0) , m_widget(0) { init(); } virtual ~EditListBoxItem() { delete m_widget; delete m_prop; } virtual TQString text() const { KSharedPtr variable = m_macroproperty->variable(); Q_ASSERT( variable.data() ); //kdDebug()<<"EditListBoxItem::text() text="<toString()<toString() != TQString() ); return variable->toString(); } KoProperty::Widget* widget() const { return m_widget; } KSharedPtr macroItem() const { return m_macroproperty->macroItem(); } KSharedPtr variable() const { return m_macroproperty->variable(); } KSharedPtr action() const { return m_macroproperty->macroItem()->action(); } protected: virtual void paint(TQPainter* p) { if(! m_widget) return; Q_ASSERT( dynamic_cast( listBox()->parent() ) ); const int w = width(listBox()); const int h = height(listBox()); m_widget->setFixedSize(w - 2, h - 2); p->drawPixmap(0, 0, TQPixmap::grabWidget(m_widget), 1, 1, w - 1, h - 1); } private: void init() { KSharedPtr macroitem = m_macroproperty->macroItem(); Q_ASSERT( macroitem.data() ); KSharedPtr action = m_macroproperty->macroItem()->action(); if(! action.data()) { kdWarning() << "EditListBoxItem::EditListBoxItem() Skipped cause there exists no action for macroproperty=" << m_macroproperty->name() << endl; return; } KoProperty::Property* parentproperty = m_macroproperty->parentProperty(); if(! parentproperty) { kdWarning() << "EditListBoxItem::EditListBoxItem() No parentproperty defined" << endl; return; } KSharedPtr variable = m_macroproperty->variable(); if(! variable.data()) { kdWarning() << "EditListBoxItem::EditListBoxItem() No variable defined for property=" << parentproperty->name() << endl; return; } TQVariant variant = variable->variant(); KSharedPtr actionvariable = action->variable(m_macroproperty->name()); if(actionvariable.data()) { TQVariant actionvariant = actionvariable->variant(); Q_ASSERT( ! actionvariant.isNull() ); Q_ASSERT( variant.canCast(actionvariant.type()) ); variant.cast( actionvariant.type() ); //preserve type. } int type = KoProperty::Auto; switch(variant.type()) { case TQVariant::UInt: case TQVariant::Int: { type = KoProperty::Integer; } break; case TQVariant::CString: case TQVariant::String: { type = KoProperty::String; } break; default: { kdWarning() << "EditListBoxItem::EditListBoxItem() name=" << variable->name() << " type=" << TQVariant::typeToName(variant.type()) << endl; } break; } TQString name = variable->name(); Q_ASSERT(! name.isNull()); //if(name.isNull()) name = "aaaaaaaaaaaaaaaaa";//TESTCASE m_prop = new KoProperty::Property( name.latin1(), // name variant, // value variable->text(), // caption TQString(), // description type, // type 0 //parentproperty // parent ); m_widget = KoProperty::FactoryManager::self()->createWidgetForProperty(m_prop); Q_ASSERT( m_widget != 0 ); //m_widget->reparent(listBox()->viewport(), 0, TQPoint(0,0)); m_widget->reparent(listBox(), 0, TQPoint(1,1)); //tqlayout->addWidget(m_widget, 1); m_widget->setMinimumHeight(5); m_widget->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding); } private: KexiMacroProperty* m_macroproperty; KoProperty::Property* m_prop; KoProperty::Widget* m_widget; }; /** * @internal implementation of a @a TQListBox for the combobox used within * @a KexiMacroPropertyWidget to handle different variable-states. */ class ListBox : public TQListBox { public: ListBox(KComboBox* parent, KexiMacroProperty* macroproperty) : TQListBox(parent) , m_macroproperty(macroproperty) , m_edititem(0) { viewport()->setBackgroundMode(PaletteBackground); setVariableHeight(true); update(); } virtual ~ListBox() {} void update() { m_items.clear(); delete m_edititem; m_edititem = 0; clear(); m_edititem = new EditListBoxItem(this, m_macroproperty); Q_ASSERT( m_edititem->widget() != 0 ); const TQString name = m_macroproperty->name(); KoMacro::Variable::List tqchildren; { KoMacro::Variable::List actiontqchildren; KSharedPtr itemvar = m_macroproperty->macroItem()->variable(name,false); //kdDebug() << "KexiMacroProperty::ListBox::update() itemvar="<<(itemvar.data() ? "name:"+itemvar->name()+" value:"+itemvar->toString() : "NULL")<tqchildren(); KSharedPtr action = m_edititem->action(); KSharedPtr actionvar = action.data() ? action->variable(name) : KSharedPtr(); //kdDebug() << "KexiMacroProperty::ListBox::update() actionvar="<<(actionvar.data() ? "name:"+actionvar->name()+" value:"+actionvar->toString() : "NULL")<tqchildren(); KoMacro::Variable::List::ConstIterator it(actiontqchildren.constBegin()), end(actiontqchildren.constEnd()); for(; it != end; ++it) { if(name == (*it)->name()) { KoMacro::Variable::List list = (*it)->tqchildren(); KoMacro::Variable::List::ConstIterator listit(list.constBegin()), listend(list.constEnd()); for(; listit != listend; ++listit) tqchildren.append( *listit ); } } if(tqchildren.count() <= 0) tqchildren = actiontqchildren; } /* kdDebug() << "KexiMacroProperty::ListBox::update() name="<variant(); //kdDebug() << " child name=" << n << " value=" << v << endl; switch( v.type() ) { /* case TQVariant::Map: { const TQMap map = v.toMap(); for(TQMap::ConstIterator it = map.constBegin(); it != map.constEnd(); ++it) m_items.append(it.key()); } break; */ case TQVariant::List: { const TQValueList list = v.toList(); for(TQValueList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it) { const TQString s = (*it).toString().stripWhiteSpace(); if(! s.isEmpty()) m_items.append(s); } } break; case TQVariant::StringList: { const TQStringList list = v.toStringList(); for(TQStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it) if(! (*it).isEmpty()) m_items.append(*it); } break; default: { const TQString s = v.toString().stripWhiteSpace(); if(! s.isEmpty()) m_items.append(s); } break; } } } TQListBoxItem* item = m_edititem; const uint count = m_items.count(); for(uint i = 0; i < count; i++) item = new ListBoxItem(this, m_items[i], item); } EditListBoxItem* editItem() const { return m_edititem; } TQStringList items() const { return m_items; } virtual void hide () { TQListBox::hide(); for(uint i = 0; i < count(); i++) static_cast( item(i) )->setEnabled(false); } virtual void show() { update(); adjustSize(); TQListBox::show(); } private: KexiMacroProperty* m_macroproperty; EditListBoxItem* m_edititem; TQStringList m_items; }; /** * @internal d-pointer class to be more flexible on future extension of the * functionality without to much risk to break the binary compatibility. */ class KexiMacroPropertyWidget::Private { public: KexiMacroProperty* macroproperty; KComboBox* combobox; ListBox* listbox; }; KexiMacroPropertyWidget::KexiMacroPropertyWidget(KoProperty::Property* property, TQWidget* parent) : KoProperty::Widget(property, parent) , d( new Private() ) { kdDebug() << "KexiMacroPropertyWidget::KexiMacroPropertyWidget() Ctor" << endl; TQHBoxLayout* tqlayout = new TQHBoxLayout(this, 0, 0); d->macroproperty = dynamic_cast( property->customProperty() ); if(! d->macroproperty) { kdWarning() << "KexiMacroPropertyWidget::KexiMacroPropertyWidget() Missing macroproperty for property=" << property->name() << endl; return; } d->combobox = new KComboBox(this); tqlayout->addWidget(d->combobox); d->listbox = new ListBox(d->combobox, d->macroproperty); d->combobox->setEditable(true); d->combobox->setListBox(d->listbox); d->combobox->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding); d->combobox->setMinimumHeight(5); d->combobox->setInsertionPolicy(TQComboBox::NoInsertion); d->combobox->setMinimumSize(10, 0); // to allow the combo to be resized to a small size d->combobox->setAutoCompletion(false); d->combobox->setContextMenuEnabled(false); TQVariant value = d->macroproperty->value(); int index = d->listbox->items().findIndex( value.toString() ); if(index >= 0) { d->combobox->setCurrentItem(index + 1); d->listbox->setCurrentItem(index + 1); } else { Q_ASSERT( d->listbox->editItem()->widget() != 0 ); d->listbox->editItem()->widget()->setValue( d->macroproperty->value(), true ); //d->combobox->setCurrentItem(0); } kdDebug() << ">>> KexiMacroPropertyWidget::KexiMacroPropertyWidget() CurrentItem=" << d->combobox->currentItem() << endl; d->combobox->setFocusProxy( d->listbox->editItem()->widget() ); setFocusWidget( d->combobox->lineEdit() ); connect(d->combobox, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(slotComboBoxChanged())); connect(d->combobox, TQT_SIGNAL(activated(int)), this, TQT_SLOT(slotComboBoxActivated())); connect(d->listbox->editItem()->widget(), TQT_SIGNAL(valueChanged(Widget*)), this, TQT_SLOT(slotWidgetValueChanged())); connect(d->macroproperty, TQT_SIGNAL(valueChanged()), this, TQT_SLOT(slotPropertyValueChanged())); } KexiMacroPropertyWidget::~KexiMacroPropertyWidget() { kdDebug() << "KexiMacroPropertyWidget::~KexiMacroPropertyWidget() Dtor" << endl; delete d; } TQVariant KexiMacroPropertyWidget::value() const { kdDebug()<<"KexiMacroPropertyWidget::value() value="<macroproperty->value()<macroproperty->value(); /* TQVariant value = d->combobox->currentText(); value.cast( d->macroproperty->value().type() ); return value; */ } void KexiMacroPropertyWidget::setValue(const TQVariant& value, bool emitChange) { kdDebug()<<"KexiMacroPropertyWidget::setValue() value="<combobox->blockSignals(false); } void KexiMacroPropertyWidget::setReadOnlyInternal(bool readOnly) { Q_UNUSED(readOnly); //kdDebug()<<"KexiMacroPropertyWidget::setReadOnlyInternal() readOnly="<combobox->currentText(); d->macroproperty->setValue(v, true); //emit valueChanged(this); } void KexiMacroPropertyWidget::slotComboBoxActivated() { Q_ASSERT( d->listbox->editItem()->widget() ); const int index = d->combobox->currentItem(); TQString text = (index == 0) ? d->listbox->editItem()->widget()->value().toString() : d->combobox->text(index); kdDebug()<<"KexiMacroPropertyWidget::slotComboBoxActivated() index="<