00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "propertywidgetcontainer.h"
00018 #include "propertywidgetitem.h"
00019 #include "core/gluonobject.h"
00020
00021 #include <QtGui/QGridLayout>
00022 #include <QtGui/QBoxLayout>
00023 #include <QtGui/QToolButton>
00024 #include <QtGui/QCheckBox>
00025 #include <QtGui/QMenu>
00026 #include <QtCore/QHash>
00027 #include <QtCore/QMetaProperty>
00028 #include <QtCore/QStringBuilder>
00029 #include <KIcon>
00030 #include <KLocalizedString>
00031 #include <KMessageBox>
00032 #include <ksqueezedtextlabel.h>
00033 #include <selectionmanager.h>
00034
00035 namespace GluonCreator
00036 {
00037 class PropertyWidgetContainer::PropertyWidgetContainerPrivate
00038 {
00039 public:
00040 PropertyWidgetContainerPrivate( PropertyWidgetContainer* parent )
00041 : expanded( true )
00042 , enabled( true )
00043 , containerWidget( 0 )
00044 , containerLayout( 0 )
00045 , expander( 0 )
00046 , enabler( 0 )
00047 , menuButton( 0 )
00048 {
00049 this->parent = parent;
00050 menu = new QMenu( parent );
00051
00052
00053 QFrame* titleWidget = new QFrame( parent );
00054 titleWidget->setFrameShape( QFrame::StyledPanel );
00055 titleWidget->setFrameShadow( QFrame::Raised );
00056 parent->layout()->addWidget( titleWidget );
00057
00058 QHBoxLayout* titleLayout = new QHBoxLayout();
00059 titleLayout->setSpacing( 0 );
00060 titleLayout->setContentsMargins( 0, 0, 0, 0 );
00061 titleWidget->setLayout( titleLayout );
00062
00063 expander = new QToolButton( titleWidget );
00064 expander->setAutoRaise( true );
00065 expander->setArrowType( Qt::DownArrow );
00066 connect( expander, SIGNAL( clicked( bool ) ), parent, SLOT( toggleExpanded() ) );
00067 titleLayout->addWidget( expander );
00068
00069 enabler = new QCheckBox( titleWidget );
00070 enabler->setText( title );
00071 enabler->setChecked( enabled );
00072 connect( enabler, SIGNAL( toggled( bool ) ), parent, SLOT( setEnabled( bool ) ) );
00073 titleLayout->addWidget( enabler );
00074
00075 menuButton = new QToolButton( titleWidget );
00076 menuButton->setIcon( KIcon( "preferences-other" ) );
00077 menuButton->setAutoRaise( true );
00078 menuButton->setPopupMode( QToolButton::InstantPopup );
00079 menuButton->setMenu( menu );
00080 titleLayout->addWidget( menuButton );
00081
00082
00083 containerWidget = new QWidget( parent );
00084 containerLayout = new QGridLayout();
00085 containerLayout->setSpacing( 0 );
00086 containerLayout->setContentsMargins( 2, 0, 0, 0 );
00087 containerWidget->setLayout( containerLayout );
00088 containerLayout->setColumnStretch( 0, 1 );
00089 containerLayout->setColumnStretch( 1, 3 );
00090 parent->layout()->addWidget( containerWidget );
00091 }
00092 ~PropertyWidgetContainerPrivate()
00093 {
00094 }
00095
00104 QString humanifyString( QString fixThis );
00105
00106 PropertyWidgetContainer* parent;
00107 GluonCore::GluonObject* object;
00108 void appendMetaObject( QObject* object );
00109 void addPropertyItem( QString name, PropertyWidgetItem* item );
00110
00111 bool expanded;
00112 bool enabled;
00113 QString title;
00114
00115 QWidget* containerWidget;
00116 QGridLayout* containerLayout;
00117 QHash<QString, QWidget*> items;
00118
00119 QToolButton* expander;
00120 QCheckBox* enabler;
00121 QToolButton* menuButton;
00122
00123 QMenu* menu;
00124 };
00125 }
00126
00127 using namespace GluonCreator;
00128
00129 PropertyWidgetContainer::PropertyWidgetContainer( GluonCore::GluonObject* theObject, QWidget* parent, Qt::WindowFlags f )
00130 : QWidget( parent, f )
00131 {
00132
00133 QVBoxLayout* layout = new QVBoxLayout( this );
00134 layout->setSpacing( 0 );
00135 layout->setContentsMargins( 0, 0, 0, 0 );
00136 setLayout( layout );
00137
00138 d = new PropertyWidgetContainerPrivate( this );
00139 setObject( theObject );
00140 }
00141
00142 PropertyWidgetContainer::~PropertyWidgetContainer()
00143 {
00144 delete d;
00145 }
00146
00147 void PropertyWidgetContainer::setObject( GluonCore::GluonObject* theObject )
00148 {
00149 d->object = theObject;
00150
00151 QString classname( theObject->metaObject()->className() );
00152 classname = classname.right( classname.length() - classname.lastIndexOf( ':' ) - 1 );
00153 setTitle( d->humanifyString( classname ) );
00154
00155 if( !theObject->property( "enabled" ).isNull() )
00156 setEnabled( theObject->property( "enabled" ).value<bool>() );
00157 if( !theObject->property( "expanded" ).isNull() )
00158 setExpanded( theObject->property( "expanded" ).value<bool>() );
00159 connect( this, SIGNAL( propertyChanged( QObject*, QString, QVariant, QVariant ) ), parentWidget(), SIGNAL( propertyChanged( QObject*, QString, QVariant, QVariant ) ) );
00160
00161
00162 PropertyWidgetItem* nameWidget = PropertyWidgetItemFactory::instance()->create( theObject, "QString", parentWidget() );
00163 nameWidget->setEditObject( theObject );
00164 nameWidget->setEditProperty( "name" );
00165 d->addPropertyItem( "name", nameWidget );
00166
00167 PropertyWidgetItem* descriptionWidget = PropertyWidgetItemFactory::instance()->create( theObject, "QString", parentWidget() );
00168 descriptionWidget->setEditObject( theObject );
00169 descriptionWidget->setEditProperty( "description" );
00170 d->addPropertyItem( "description", descriptionWidget );
00171
00172 QFrame* separator = new QFrame( this );
00173 separator->setFrameShape( QFrame::HLine );
00174 d->containerLayout->addWidget( separator, d->containerLayout->rowCount(), 0, 1, 2 );
00175
00176
00177 if( classname != QString( "GameObject" ) )
00178 {
00179
00180 QAction* upAction = new QAction( this );
00181 upAction->setText( i18n( "Move Up" ) );
00182 connect( upAction, SIGNAL( triggered( bool ) ), this, SLOT( upTriggered() ) );
00183 d->menu->addAction( upAction );
00184 QAction* downAction = new QAction( this );
00185 downAction->setText( i18n( "Move Down" ) );
00186 connect( downAction, SIGNAL( triggered( bool ) ), this, SLOT( downTriggered() ) );
00187 d->menu->addAction( downAction );
00188 QAction* sepAction = new QAction( this );
00189 sepAction->setSeparator( true );
00190 d->menu->addAction( sepAction );
00191 }
00192 if( classname != QString( "GameProject" ) )
00193 {
00194 QAction* delAction = new QAction( this );
00195 delAction->setText( i18n( "Delete" ) );
00196 connect( delAction, SIGNAL( triggered( bool ) ), this, SLOT( delTriggered() ) );
00197 d->menu->addAction( delAction );
00198 }
00199
00200 d->appendMetaObject( theObject );
00201 }
00202
00203 void
00204 PropertyWidgetContainer::upTriggered()
00205 {
00206
00207 }
00208
00209 void
00210 PropertyWidgetContainer::downTriggered()
00211 {
00212
00213 }
00214
00215 void
00216 PropertyWidgetContainer::delTriggered()
00217 {
00218 if( KMessageBox::questionYesNo( this, i18n( "Are you sure you wish to delete the item %1?" ).arg( d->object->fullyQualifiedName() ), i18n( "Delete Item?" ) ) == KMessageBox::Yes )
00219 {
00220 GluonCore::GluonObject* theParent = qobject_cast<GluonCore::GluonObject*>( d->object->parent() );
00221 if( theParent )
00222 theParent->removeChild( d->object );
00223 d->object->deleteLater();
00224
00225
00226 SelectionManager::SelectionList list;
00227 list.append( theParent );
00228 SelectionManager::instance()->setSelection( list );
00229 }
00230 }
00231
00232 bool
00233 PropertyWidgetContainer::expanded() const
00234 {
00235 return d->expanded;
00236 }
00237
00238 void
00239 PropertyWidgetContainer::setExpanded( const bool& newExpanded )
00240 {
00241 bool oldExpanded = d->expanded;
00242 d->expanded = newExpanded;
00243
00244
00245 if( !newExpanded )
00246 d->object->setProperty( "expanded", false );
00247 else
00248 d->object->setProperty( "expanded", QVariant() );
00249
00250 if( newExpanded )
00251 {
00252 d->expander->setArrowType( Qt::DownArrow );
00253 }
00254 else
00255 {
00256 d->expander->setArrowType( Qt::RightArrow );
00257 }
00258
00259 d->containerWidget->setVisible( newExpanded );
00260
00261 emit propertyChanged( d->object, "expanded", oldExpanded, newExpanded );
00262 }
00263
00264 void
00265 PropertyWidgetContainer::toggleExpanded()
00266 {
00267 setExpanded( !expanded() );
00268 }
00269
00270 bool
00271 PropertyWidgetContainer::enabled() const
00272 {
00273 return d->enabled;
00274 }
00275
00276 void
00277 PropertyWidgetContainer::setEnabled( const bool& newEnabled )
00278 {
00279 bool oldEnabled = d->enabled;
00280 d->enabled = newEnabled;
00281 if( d->enabled != d->object->property( "enabled" ).value<bool>() )
00282 d->object->setProperty( "enabled", newEnabled );
00283 if( d->enabler->isChecked() != newEnabled )
00284 d->enabler->setChecked( newEnabled );
00285 emit propertyChanged( d->object, "expanded", oldEnabled, newEnabled );
00286 }
00287
00288 QString
00289 PropertyWidgetContainer::title() const
00290 {
00291 return d->title;
00292 }
00293
00294 void
00295 PropertyWidgetContainer::setTitle( const QString& newTitle )
00296 {
00297 d->title = newTitle;
00298 d->enabler->setText( newTitle );
00299 }
00300
00301 void
00302 PropertyWidgetContainer::addDefaultMenuItems()
00303 {
00304 }
00305
00306 void
00307 PropertyWidgetContainer::addMenuItem( QAction* menuItem )
00308 {
00309 d->menu->addAction( menuItem );
00310 }
00311
00312 void
00313 PropertyWidgetContainer::removeMenuItem( QAction* menuItem )
00314 {
00315 if( d->menu->actions().contains( menuItem ) )
00316 d->menu->removeAction( menuItem );
00317 }
00318
00319 void
00320 PropertyWidgetContainer::PropertyWidgetContainerPrivate::appendMetaObject( QObject* object )
00321 {
00322 QString propertyName, propertyDescription;
00323 QVariant propertyValue;
00324
00325 const QMetaObject* metaObject = object->metaObject();
00326 QMetaProperty metaProperty;
00327
00328 int count = metaObject->propertyCount();
00329 for( int i = 0; i < count; ++i )
00330 {
00331 metaProperty = metaObject->property( i );
00332
00333
00334
00335
00336 propertyName = QString( metaProperty.name() );
00337 if( propertyName == QString( "objectName" ) || propertyName == QString( "name" ) || propertyName == QString( "description" ) || propertyName == QString( "expanded" ) || propertyName == QString( "enabled" ) )
00338 continue;
00339
00340 PropertyWidgetItem* editWidget = PropertyWidgetItemFactory::instance()->create( object, metaProperty.typeName(), parent->parentWidget() );
00341 editWidget->setEditObject( object );
00342 editWidget->setEditProperty( metaProperty.name() );
00343
00344 addPropertyItem( metaProperty.name(), editWidget );
00345 }
00346
00347 foreach( const QByteArray & propName, object->dynamicPropertyNames() )
00348 {
00349 QString thePropName( propName );
00350
00351
00352 if( thePropName == QString( "description" ) || thePropName == QString( "expanded" ) || thePropName == QString( "enabled" ) )
00353 continue;
00354
00355 PropertyWidgetItem* editWidget = PropertyWidgetItemFactory::instance()->create( object, object->property( propName ).typeName(), parent->parentWidget() );
00356 editWidget->setEditObject( object );
00357 editWidget->setEditProperty( thePropName );
00358
00359 addPropertyItem( thePropName, editWidget );
00360 }
00361 }
00362
00363 void
00364 PropertyWidgetContainer::PropertyWidgetContainerPrivate::addPropertyItem( QString name, PropertyWidgetItem* item )
00365 {
00366
00367 KSqueezedTextLabel* nameLabel = new KSqueezedTextLabel( parent );
00368 nameLabel->setAlignment( Qt::AlignLeft | Qt::AlignTop );
00369 nameLabel->setTextElideMode( Qt::ElideRight );
00370 nameLabel->setText( humanifyString( name ) );
00371 nameLabel->setToolTip( nameLabel->fullText() );
00372
00373 item->setMinimumWidth( 150 );
00374 item->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Fixed );
00375
00376 connect( item, SIGNAL( propertyChanged( QObject*, QString, QVariant, QVariant ) ), parent, SIGNAL( propertyChanged( QObject*, QString, QVariant, QVariant ) ) );
00377
00378 int row = containerLayout->rowCount();
00379 containerLayout->addWidget( nameLabel, row, 0 );
00380 containerLayout->addWidget( item, row, 1 );
00381
00382 items.insert( name, item );
00383 }
00384
00385 QString
00386 PropertyWidgetContainer::PropertyWidgetContainerPrivate::humanifyString( QString fixThis )
00387 {
00388 QString fixedString;
00389 const int length = fixThis.size();
00390 for( int i = 0; i < length; ++i )
00391 {
00392 const QChar current = fixThis.at( i );
00393 if( i == 0 )
00394 {
00395
00396 fixedString = current.toUpper();
00397 }
00398 else
00399 {
00400 if( current.isUpper() )
00401 {
00402 fixedString = fixedString % ' ' % current;
00403 }
00404 else
00405 {
00406 fixedString = fixedString % current;
00407 }
00408 }
00409 }
00410 return fixedString;
00411 }
00412
00413