00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "QmitkPropertyListPopup.h"
00019 #include "QmitkMaterialEditor.h"
00020 #include "QmitkNumberPropertySlider.h"
00021
00022 #include "mitkRenderingManager.h"
00023 #include "mitkStringProperty.h"
00024 #include "mitkColorProperty.h"
00025
00026 #include <qinputdialog.h>
00027 #include <qcolordialog.h>
00028 #include <qmessagebox.h>
00029
00030 #include <qmenudata.h>
00031 #include <qpainter.h>
00032 #include <QWidgetAction>
00033
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00077
00078 QmitkPropertyListPopup::QmitkPropertyListPopup( mitk::PropertyList* list, QObject* parent, bool disableBoolProperties, bool fillMenuImmediatelty, const char* name )
00079 :QObject(parent, name),
00081
00082 m_PopupMenu( new QMenu( name, dynamic_cast<QWidget*>(parent) ) ),
00084 m_PropertyList(list),
00085 m_MaterialEditor(NULL),
00087 m_NameMenuAction(0),
00088 m_VisibleMenuAction(0),
00089 m_ColorMenuAction(0),
00090 m_MaterialMenuAction(0),
00091 m_OpacityMenuAction(0),
00092 m_AcceptOnHide(false),
00093 m_DisableBoolProperties(disableBoolProperties)
00095 {
00096 if (!parent)
00097 {
00098 std::cerr << "In " __FILE__ ", l." << __LINE__ << ": popup menu without parent. This tends to crash (click 'Choose color' in the material editor)." << std::endl;
00099 }
00100
00101 if (fillMenuImmediatelty)
00102 {
00103 fillPopup();
00104 }
00105
00106 connect( m_PopupMenu, SIGNAL(aboutToHide()), this, SLOT(popupAboutToHide()) );
00108
00109 connect( m_PopupMenu, SIGNAL(hovered(int)), this, SLOT(popupMenuItemHovered(int)) );
00111 }
00112
00114 QIcon QmitkPropertyListPopup::createColorIcon(QColor color)
00115 {
00116 QPixmap pixmap(20, 20);
00117 QPainter painter(&pixmap);
00118 painter.setPen(Qt::NoPen);
00119 painter.fillRect(QRect(0, 0, 20, 20), color);
00120
00121 return QIcon(pixmap);
00122 }
00124
00125 void QmitkPropertyListPopup::fillPopup()
00126 {
00127 if (m_PropertyList.IsNotNull())
00128 {
00130
00132
00133
00134 mitk::ColorProperty* colorProperty = dynamic_cast<mitk::ColorProperty*>( m_PropertyList->GetProperty("color"));
00135 if (colorProperty)
00136 {
00137 mitk::Color col = colorProperty->GetColor();
00138 QColor currentColor((int)(col.GetRed() * 255), (int)(col.GetGreen() * 255), (int)(col.GetBlue() * 255));
00139
00140 QFont normalFont;
00141 normalFont.setBold(true);
00143
00144
00145
00146 m_ColorMenuAction = new QAction(this->createColorIcon(currentColor), QString("Color..."), this);
00147 m_ColorMenuAction->setFont(normalFont);
00148 m_PopupMenu->addAction(m_ColorMenuAction);
00149 m_ColorMenuAction->setEnabled(true);
00150 connect( m_ColorMenuAction, SIGNAL(triggered()), this, SLOT(onColorClicked()) );
00152 }
00153 else
00154 {
00156
00157
00158 m_ColorMenuAction = new QAction(QString("Color..."), this);
00159 m_PopupMenu->addAction(m_ColorMenuAction);
00160 m_ColorMenuAction->setEnabled(true);
00162 }
00163
00164 if ( !AddMaterialPopup() )
00165 {
00167
00168
00169 m_MaterialMenuAction = new QAction(QString("Material"), this);
00170 m_PopupMenu->addAction(m_MaterialMenuAction);
00171 m_MaterialMenuAction->setEnabled(false);
00173 }
00174
00175
00176
00177 if ( mitk::FloatProperty* opacityProperty = dynamic_cast<mitk::FloatProperty*>( m_PropertyList->GetProperty("opacity")))
00178 {
00179 m_OriginalOpacity = mitk::FloatProperty::New( opacityProperty->GetValue() );
00181
00182 QMenu* opacityPopup = m_PopupMenu->addMenu("Opacity");
00184
00185 QmitkNumberPropertySlider* npe = new QmitkNumberPropertySlider( opacityProperty, opacityPopup );
00186 npe->setShowPercent(true);
00187 npe->setMinValue(0);
00188 npe->setMaxValue(1);
00190
00191
00192
00193
00194 QWidgetAction* opacityMenuAction = new QWidgetAction(opacityPopup);
00195 opacityMenuAction->setDefaultWidget(npe);
00196 m_OpacityMenuAction = opacityMenuAction;
00197 opacityPopup->addAction(m_OpacityMenuAction);
00198 m_OpacityMenuAction->setEnabled(true);
00200 }
00201 else
00202 {
00204
00205
00206 m_OpacityMenuAction = new QAction(QString("Opacity"), this);
00207 m_PopupMenu->addAction(m_OpacityMenuAction);
00208 m_OpacityMenuAction->setEnabled(true);
00210 }
00211
00212
00214
00215
00216
00217
00218
00219
00220
00221 m_NameMenuAction = new QAction(QString("Name..."), this);
00222 m_PopupMenu->addAction(m_NameMenuAction);
00223 mitk::StringProperty* nameProperty = dynamic_cast<mitk::StringProperty*>( m_PropertyList->GetProperty("name"));
00224 m_NameMenuAction->setEnabled(nameProperty != NULL);
00225 if (nameProperty)
00226 {
00227 connect( m_NameMenuAction, SIGNAL(triggered()), this, SLOT(onNameClicked()) );
00228 }
00230
00231
00232
00234
00235
00236
00237
00238
00239
00240
00241
00242 m_VisibleMenuAction = new QAction(QString("Visibility"), this);
00243 m_VisibleMenuAction->setCheckable(true);
00244 m_PopupMenu->addAction(m_VisibleMenuAction);
00245 mitk::BoolProperty* visibleProperty = dynamic_cast<mitk::BoolProperty*>( m_PropertyList->GetProperty("visible"));
00246 m_VisibleMenuAction->setEnabled( visibleProperty != NULL );
00247 if (visibleProperty)
00248 {
00249 m_VisibleMenuAction->setChecked( visibleProperty->GetValue() );
00250 connect( m_VisibleMenuAction, SIGNAL(triggered()), this, SLOT(onVisibleClicked()) );
00251 }
00253
00254
00255 const mitk::PropertyList::PropertyMap* map = m_PropertyList->GetMap();
00256 if (map)
00257 {
00258
00260
00261
00262
00263
00264
00265 m_InfoPopup = m_PopupMenu->addMenu("Information");
00266
00267
00268 m_PopupMenu->addSeparator();
00270
00271 QFont boldFont = m_PopupMenu->font();
00272 boldFont.setBold( true );
00273
00274
00275 for ( mitk::PropertyList::PropertyMap::const_iterator propertyIter = map->begin();
00276 propertyIter != map->end();
00277 ++propertyIter )
00278 {
00279 std::string name = propertyIter->first;
00280 if (name == "visible") continue;
00281
00282 if ( mitk::BoolProperty* boolProperty = dynamic_cast<mitk::BoolProperty*>(propertyIter->second.first.GetPointer()) )
00283 {
00284
00285 m_BoolProperties.push_back( boolProperty );
00286
00287 int newID = m_PopupMenu->insertItem( QString("%1").arg( name.c_str()) );
00288 m_PopupMenu->setItemChecked( newID, boolProperty->GetValue() );
00289 m_PopupMenu->setItemParameter( newID, m_BoolProperties.size() );
00290 m_PopupMenu->connectItem( newID, this, SLOT(onBoolPropertyClicked(int)) );
00291 if (m_DisableBoolProperties )
00292 {
00293 m_PopupMenu->setItemEnabled( newID, false );
00294 }
00295
00296 }
00297 }
00298
00299 boldFont = m_InfoPopup->font();
00300
00301
00302 for ( mitk::PropertyList::PropertyMap::const_iterator propertyIter = map->begin();
00303 propertyIter != map->end();
00304 ++propertyIter )
00305 {
00306 std::string name = propertyIter->first;
00307 if ( !dynamic_cast<mitk::BoolProperty*>(propertyIter->second.first.GetPointer()) )
00308 {
00309 std::string value("no value");
00310 mitk::BaseProperty::Pointer bp = propertyIter->second.first;
00311 if ( bp.IsNotNull() )
00312 {
00313 value = bp->GetValueAsString();
00314 }
00315 m_InfoPopup->insertItem( QString("%1: %2").arg( name.c_str()).arg(value.c_str()) );
00316 }
00317 }
00318 }
00319 }
00320 }
00321
00322 bool QmitkPropertyListPopup::AddMaterialPopup()
00323 {
00324
00325 if ( mitk::MaterialProperty* materialProperty = dynamic_cast<mitk::MaterialProperty*>( m_PropertyList->GetProperty("material")))
00326 {
00327 m_OriginalMaterial = mitk::MaterialProperty::New( *materialProperty );
00329
00330 QMenu* materialPopup = new QMenu( m_PopupMenu );
00332
00333 m_MaterialEditor = new QmitkMaterialEditor( m_PopupMenu );
00334 m_MaterialEditor->setInline(true);
00335 m_MaterialEditor->Initialize( materialProperty );
00337
00338
00339 QWidgetAction* materialEditorMenuItem = new QWidgetAction(materialPopup);
00340 materialEditorMenuItem->setDefaultWidget(m_MaterialEditor);
00341 materialPopup->addAction(materialEditorMenuItem);
00343 connect( m_MaterialEditor, SIGNAL(ChangesAccepted(QmitkMaterialEditor*)), this, SLOT(MaterialEditorChangesAccepted(QmitkMaterialEditor*)) );
00344
00346
00347
00348 m_MaterialMenuAction = new QAction(QString("Material"), materialPopup);
00349 materialPopup->addAction(m_OpacityMenuAction);
00350 m_OpacityMenuAction->setEnabled(true);
00352
00353 return true;
00354 }
00355
00356 return false;
00357 }
00358
00359 QmitkPropertyListPopup::~QmitkPropertyListPopup()
00360 {
00361 delete m_MaterialEditor;
00362 }
00363
00365
00366
00367
00368
00369 void QmitkPropertyListPopup::popup( const QPoint& pos, QAction* action )
00370 {
00371 m_PopupMenu->exec(pos, action);
00372 }
00374
00375 void QmitkPropertyListPopup::onNameClicked()
00376 {
00377 mitk::StringProperty* nameProperty = dynamic_cast<mitk::StringProperty*>( m_PropertyList->GetProperty("name"));
00378 if (nameProperty)
00379 {
00380 bool ok;
00381 QString newName = QInputDialog::getText( tr("Change object name"),
00382 QString(tr("Enter a new name for \"%1\"")).arg(nameProperty->GetValue()),
00383 QLineEdit::Normal,
00384 QString(nameProperty->GetValue()),
00385 &ok,
00386 m_PopupMenu );
00387 if ( ok && !newName.isEmpty() )
00388 {
00389
00390 nameProperty->SetValue( newName.ascii() );
00391 nameProperty->Modified();
00392 emit propertyListChangesDone();
00393 }
00394 else if (ok)
00395 {
00396
00397 if ( QMessageBox::question( m_PopupMenu,
00398 tr("Change object name"),
00399 tr("Do you really want to assign an empty name to '%1'?").arg( nameProperty->GetValue() ),
00400 QMessageBox::Yes,
00401 QMessageBox::No )
00402 == QMessageBox::Yes )
00403 {
00404
00405 nameProperty->SetValue( newName.ascii() );
00406 nameProperty->Modified();
00407 emit propertyListChangesDone();
00408 }
00409 }
00410 }
00411 }
00412
00413 void QmitkPropertyListPopup::onVisibleClicked()
00414 {
00416
00417 m_VisibleMenuAction->setChecked(m_VisibleMenuAction->isChecked());
00419 mitk::BoolProperty* visibleProperty = dynamic_cast<mitk::BoolProperty*>( m_PropertyList->GetProperty("visible"));
00420 if (visibleProperty)
00421 {
00423
00424 visibleProperty->SetValue( m_VisibleMenuAction->isChecked() );
00426 visibleProperty->Modified();
00427 mitk::RenderingManager::GetInstance()->RequestUpdateAll();
00428 emit propertyListChangesDone();
00429 }
00430 }
00431
00432 void QmitkPropertyListPopup::onColorClicked()
00433 {
00434 mitk::ColorProperty* colorProperty = dynamic_cast<mitk::ColorProperty*>( m_PropertyList->GetProperty("color"));
00435 if (colorProperty)
00436 {
00437 mitk::Color col = colorProperty->GetColor();
00438 QColor result = QColorDialog::getColor(QColor((int)(col.GetRed() * 255), (int)(col.GetGreen() * 255), (int)(col.GetBlue() * 255)));
00439 if (result.isValid())
00440 {
00441 col.SetRed(result.red() / 255.0);
00442 col.SetGreen(result.green() / 255.0);
00443 col.SetBlue(result.blue() / 255.0);
00444 colorProperty->SetColor(col);
00445 colorProperty->Modified();
00446 }
00447
00448 mitk::RenderingManager::GetInstance()->RequestUpdateAll();
00449 emit propertyListChangesDone();
00450 }
00451 }
00452
00453 void QmitkPropertyListPopup::onBoolPropertyClicked(int param)
00454 {
00455 int item = m_PopupMenu->idAt(param+6);
00456 bool on( !m_PopupMenu->isItemChecked(item) );
00457
00458 m_PopupMenu->setItemChecked( item, on );
00459
00460 try
00461 {
00462 mitk::BoolProperty* boolProperty = m_BoolProperties.at( param-1 );
00463 if (boolProperty)
00464 {
00465 boolProperty->SetValue( on );
00466 boolProperty->Modified();
00467 mitk::RenderingManager::GetInstance()->RequestUpdateAll();
00468 emit propertyListChangesDone();
00469 }
00470 }
00471 catch(...)
00472 {
00473
00474 }
00475 }
00476
00477 void QmitkPropertyListPopup::MaterialEditorChangesAccepted(QmitkMaterialEditor* )
00478 {
00479 }
00480
00481 void QmitkPropertyListPopup::popupAboutToHide()
00482 {
00483 if (!m_AcceptOnHide) return;
00484
00485 bool changes(false);
00486
00487 UpdateNodeMaterialOnPopupHiding( changes );
00488
00489 mitk::FloatProperty* opacity = dynamic_cast<mitk::FloatProperty*>( m_PropertyList->GetProperty("opacity"));
00490 if (opacity)
00491 {
00492 if ( !(*opacity == *m_OriginalOpacity) )
00493 {
00494 changes = true;
00495 }
00496 }
00497
00498 if (changes)
00499 {
00500 emit propertyListChangesDone();
00501 }
00502 }
00503
00505
00506 void QmitkPropertyListPopup::popupMenuItemHovered( QAction* action )
00507 {
00508 if ( action == m_OpacityMenuAction || action == m_MaterialMenuAction )
00509 {
00510 m_AcceptOnHide = true;
00511 }
00512 else
00513 {
00514 m_AcceptOnHide = false;
00515 }
00516 }
00517
00518 void QmitkPropertyListPopup::UpdateNodeMaterialOnPopupHiding( bool& changes )
00519 {
00520 mitk::MaterialProperty* material = dynamic_cast<mitk::MaterialProperty*>( m_PropertyList->GetProperty("material"));
00521 if (material)
00522 {
00523 mitk::DataNode* node = material->GetDataNode();
00524 material->SetDataNode(NULL);
00525 m_OriginalMaterial->SetDataNode(NULL);
00526 if ( !(*material == *m_OriginalMaterial) )
00527 {
00528 changes = true;
00529 }
00530 material->SetDataNode(node);
00531 }
00532 }
00533