Mercurial > hg > svgui
comparison widgets/PropertyBox.cpp @ 1204:d421df27e184 3.0-integration
Further PropertyBox layout overhaul: avoid crash (/ assertion failure) when property type changes from e.g. colour to colourmap, by replacing the existing widget within the layout rather than trying to repopulate it
author | Chris Cannam |
---|---|
date | Tue, 20 Dec 2016 10:49:24 +0000 |
parents | 73d43e410a6b |
children | 312f99a9f2aa |
comparison
equal
deleted
inserted
replaced
1203:ff042979331b | 1204:d421df27e184 |
---|---|
254 cerr << "::updatePropertyEditor(\"" << name << "\"):"; | 254 cerr << "::updatePropertyEditor(\"" << name << "\"):"; |
255 cerr << " value " << value << ", have " << have << ", group \"" | 255 cerr << " value " << value << ", have " << have << ", group \"" |
256 << groupName << "\"" << endl; | 256 << groupName << "\"" << endl; |
257 #endif | 257 #endif |
258 | 258 |
259 QString groupLabel = groupName; | |
260 if (groupName == QString()) { | |
261 groupName = "ungrouped: " + name; // not tr(), this is internal id | |
262 groupLabel = propertyLabel; | |
263 } | |
264 | |
259 if (!have) { | 265 if (!have) { |
260 | 266 if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) { |
261 QLabel *labelWidget = 0; | 267 QWidget *labelWidget = new QLabel(groupLabel, m_mainWidget); |
262 | |
263 if (groupName != QString()) { | |
264 if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) { | |
265 labelWidget = new QLabel(groupName, m_mainWidget); | |
266 } | |
267 } else { | |
268 groupName = "ungrouped: " + propertyLabel; | |
269 if (m_groupLayouts.find(groupName) == m_groupLayouts.end()) { | |
270 labelWidget = new QLabel(propertyLabel, m_mainWidget); | |
271 } | |
272 } | |
273 | |
274 if (labelWidget) { | |
275 m_layout->addWidget(labelWidget, row, 0); | 268 m_layout->addWidget(labelWidget, row, 0); |
276 QWidget *frame = new QWidget(m_mainWidget); | 269 QWidget *frame = new QWidget(m_mainWidget); |
277 frame->setMinimumSize(WidgetScale::scaleQSize(QSize(1, 24))); | 270 frame->setMinimumSize(WidgetScale::scaleQSize(QSize(1, 24))); |
278 m_groupLayouts[groupName] = new QGridLayout; | 271 m_groupLayouts[groupName] = new QGridLayout; |
279 #ifdef Q_OS_MAC | 272 #ifdef Q_OS_MAC |
288 m_layout->addWidget(frame, row, 1, 1, 2); | 281 m_layout->addWidget(frame, row, 1, 1, 2); |
289 m_layout->setColumnStretch(1, 10); | 282 m_layout->setColumnStretch(1, 10); |
290 } | 283 } |
291 } | 284 } |
292 | 285 |
286 QGridLayout *groupLayout = m_groupLayouts[groupName]; | |
287 | |
288 #ifdef DEBUG_PROPERTY_BOX | |
289 cerr << "groupName becomes \"" << groupName << "\", groupLabel = \"" | |
290 << groupLabel << "\", groupLayout = " << groupLayout << endl; | |
291 #endif | |
292 | |
293 assert(groupLayout); | |
294 | |
295 QWidget *existing = m_propertyControllers[name]; | |
296 | |
293 switch (type) { | 297 switch (type) { |
294 | 298 |
295 case PropertyContainer::ToggleProperty: | 299 case PropertyContainer::ToggleProperty: |
296 { | 300 { |
297 QAbstractButton *button = 0; | 301 QAbstractButton *button; |
298 | 302 |
299 if (have) { | 303 if (!(button = qobject_cast<QAbstractButton *>(existing))) { |
300 button = qobject_cast<QAbstractButton *>(m_propertyControllers[name]); | |
301 assert(button); | |
302 } else { | |
303 #ifdef DEBUG_PROPERTY_BOX | 304 #ifdef DEBUG_PROPERTY_BOX |
304 cerr << "PropertyBox: creating new checkbox" << endl; | 305 cerr << "PropertyBox: creating new checkbox" << endl; |
305 #endif | 306 #endif |
306 if (iconName != "") { | 307 if (iconName != "") { |
307 button = new NotifyingPushButton(); | 308 button = new NotifyingPushButton(); |
319 connect(button, SIGNAL(mouseEntered()), | 320 connect(button, SIGNAL(mouseEntered()), |
320 this, SLOT(mouseEnteredWidget())); | 321 this, SLOT(mouseEnteredWidget())); |
321 connect(button, SIGNAL(mouseLeft()), | 322 connect(button, SIGNAL(mouseLeft()), |
322 this, SLOT(mouseLeftWidget())); | 323 this, SLOT(mouseLeftWidget())); |
323 button->setToolTip(propertyLabel); | 324 button->setToolTip(propertyLabel); |
324 m_groupLayouts[groupName]->addWidget | 325 |
325 (button, 0, m_groupLayouts[groupName]->columnCount()); | 326 if (existing) { |
327 groupLayout->replaceWidget(existing, button); | |
328 delete existing; | |
329 } else { | |
330 groupLayout->addWidget(button, 0, groupLayout->columnCount()); | |
331 } | |
332 | |
326 m_propertyControllers[name] = button; | 333 m_propertyControllers[name] = button; |
327 } | 334 } |
328 | 335 |
329 if (button->isChecked() != (value > 0)) { | 336 if (button->isChecked() != (value > 0)) { |
330 button->blockSignals(true); | 337 button->blockSignals(true); |
336 | 343 |
337 case PropertyContainer::RangeProperty: | 344 case PropertyContainer::RangeProperty: |
338 { | 345 { |
339 AudioDial *dial; | 346 AudioDial *dial; |
340 | 347 |
341 if (have) { | 348 if ((dial = qobject_cast<AudioDial *>(existing))) { |
342 dial = qobject_cast<AudioDial *>(m_propertyControllers[name]); | |
343 assert(dial); | |
344 if (rangeChanged) { | 349 if (rangeChanged) { |
345 dial->blockSignals(true); | 350 dial->blockSignals(true); |
346 dial->setMinimum(min); | 351 dial->setMinimum(min); |
347 dial->setMaximum(max); | 352 dial->setMaximum(max); |
348 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name)); | 353 dial->setRangeMapper(m_container->getNewPropertyRangeMapper(name)); |
349 dial->blockSignals(false); | 354 dial->blockSignals(false); |
350 } | 355 } |
351 | 356 } else { |
352 } else { | |
353 #ifdef DEBUG_PROPERTY_BOX | 357 #ifdef DEBUG_PROPERTY_BOX |
354 cerr << "PropertyBox: creating new dial" << endl; | 358 cerr << "PropertyBox: creating new dial" << endl; |
355 #endif | 359 #endif |
356 dial = new AudioDial(); | 360 dial = new AudioDial(); |
357 dial->setObjectName(name); | 361 dial->setObjectName(name); |
371 connect(dial, SIGNAL(mouseLeft()), | 375 connect(dial, SIGNAL(mouseLeft()), |
372 this, SLOT(mouseLeftWidget())); | 376 this, SLOT(mouseLeftWidget())); |
373 | 377 |
374 dial->setFixedWidth(WidgetScale::scalePixelSize(24)); | 378 dial->setFixedWidth(WidgetScale::scalePixelSize(24)); |
375 dial->setFixedHeight(WidgetScale::scalePixelSize(24)); | 379 dial->setFixedHeight(WidgetScale::scalePixelSize(24)); |
376 m_groupLayouts[groupName]->addWidget | 380 |
377 (dial, 0, m_groupLayouts[groupName]->columnCount()); | 381 if (existing) { |
382 groupLayout->replaceWidget(existing, dial); | |
383 delete existing; | |
384 } else { | |
385 groupLayout->addWidget(dial, 0, groupLayout->columnCount()); | |
386 } | |
378 | 387 |
379 m_propertyControllers[name] = dial; | 388 m_propertyControllers[name] = dial; |
380 } | 389 } |
381 | 390 |
382 if (dial->value() != value) { | 391 if (dial->value() != value) { |
389 | 398 |
390 case PropertyContainer::ColourProperty: | 399 case PropertyContainer::ColourProperty: |
391 { | 400 { |
392 ColourComboBox *cb; | 401 ColourComboBox *cb; |
393 | 402 |
394 if (have) { | 403 if (!(cb = qobject_cast<ColourComboBox *>(existing))) { |
395 cb = qobject_cast<ColourComboBox *>(m_propertyControllers[name]); | 404 |
396 assert(cb); | |
397 } else { | |
398 #ifdef DEBUG_PROPERTY_BOX | 405 #ifdef DEBUG_PROPERTY_BOX |
399 cerr << "PropertyBox: creating new colour combobox" << endl; | 406 cerr << "PropertyBox: creating new colour combobox" << endl; |
400 #endif | 407 #endif |
401 cb = new ColourComboBox(true); | 408 cb = new ColourComboBox(true); |
402 cb->setObjectName(name); | 409 cb->setObjectName(name); |
407 this, SLOT(mouseEnteredWidget())); | 414 this, SLOT(mouseEnteredWidget())); |
408 connect(cb, SIGNAL(mouseLeft()), | 415 connect(cb, SIGNAL(mouseLeft()), |
409 this, SLOT(mouseLeftWidget())); | 416 this, SLOT(mouseLeftWidget())); |
410 | 417 |
411 cb->setToolTip(propertyLabel); | 418 cb->setToolTip(propertyLabel); |
412 m_groupLayouts[groupName]->addWidget | 419 |
413 (cb, 0, m_groupLayouts[groupName]->columnCount()); | 420 if (existing) { |
421 groupLayout->replaceWidget(existing, cb); | |
422 delete existing; | |
423 } else { | |
424 groupLayout->addWidget(cb, 0, groupLayout->columnCount()); | |
425 } | |
426 | |
414 m_propertyControllers[name] = cb; | 427 m_propertyControllers[name] = cb; |
415 } | 428 } |
416 | 429 |
417 if (cb->currentIndex() != value) { | 430 if (cb->currentIndex() != value) { |
418 cb->blockSignals(true); | 431 cb->blockSignals(true); |
424 } | 437 } |
425 | 438 |
426 case PropertyContainer::ColourMapProperty: | 439 case PropertyContainer::ColourMapProperty: |
427 { | 440 { |
428 ColourMapComboBox *cb; | 441 ColourMapComboBox *cb; |
429 | 442 |
430 if (have) { | 443 if (!(cb = qobject_cast<ColourMapComboBox *>(existing))) { |
431 cb = qobject_cast<ColourMapComboBox *>(m_propertyControllers[name]); | |
432 assert(cb); | |
433 } else { | |
434 #ifdef DEBUG_PROPERTY_BOX | 444 #ifdef DEBUG_PROPERTY_BOX |
435 cerr << "PropertyBox: creating new colourmap combobox" << endl; | 445 cerr << "PropertyBox: creating new colourmap combobox" << endl; |
436 #endif | 446 #endif |
437 cb = new ColourMapComboBox(false); | 447 cb = new ColourMapComboBox(false); |
438 cb->setObjectName(name); | 448 cb->setObjectName(name); |
441 this, SLOT(propertyControllerChanged(int))); | 451 this, SLOT(propertyControllerChanged(int))); |
442 connect(cb, SIGNAL(mouseEntered()), | 452 connect(cb, SIGNAL(mouseEntered()), |
443 this, SLOT(mouseEnteredWidget())); | 453 this, SLOT(mouseEnteredWidget())); |
444 connect(cb, SIGNAL(mouseLeft()), | 454 connect(cb, SIGNAL(mouseLeft()), |
445 this, SLOT(mouseLeftWidget())); | 455 this, SLOT(mouseLeftWidget())); |
446 | 456 |
447 cb->setToolTip(propertyLabel); | 457 cb->setToolTip(propertyLabel); |
448 m_groupLayouts[groupName]->addWidget | 458 |
449 (cb, 0, m_groupLayouts[groupName]->columnCount()); | 459 if (existing) { |
460 groupLayout->replaceWidget(existing, cb); | |
461 delete existing; | |
462 } else { | |
463 groupLayout->addWidget(cb, 0, groupLayout->columnCount()); | |
464 } | |
465 | |
450 m_propertyControllers[name] = cb; | 466 m_propertyControllers[name] = cb; |
451 } | 467 } |
452 | 468 |
453 if (cb->currentIndex() != value) { | 469 if (cb->currentIndex() != value) { |
454 cb->blockSignals(true); | 470 cb->blockSignals(true); |
462 case PropertyContainer::ValueProperty: | 478 case PropertyContainer::ValueProperty: |
463 case PropertyContainer::UnitsProperty: | 479 case PropertyContainer::UnitsProperty: |
464 { | 480 { |
465 NotifyingComboBox *cb; | 481 NotifyingComboBox *cb; |
466 | 482 |
467 if (have) { | 483 if (!(cb = qobject_cast<NotifyingComboBox *>(existing))) { |
468 cb = qobject_cast<NotifyingComboBox *>(m_propertyControllers[name]); | |
469 assert(cb); | |
470 } else { | |
471 #ifdef DEBUG_PROPERTY_BOX | 484 #ifdef DEBUG_PROPERTY_BOX |
472 cerr << "PropertyBox: creating new combobox" << endl; | 485 cerr << "PropertyBox: creating new combobox" << endl; |
473 #endif | 486 #endif |
474 | |
475 cb = new NotifyingComboBox(); | 487 cb = new NotifyingComboBox(); |
476 cb->setObjectName(name); | 488 cb->setObjectName(name); |
477 cb->setDuplicatesEnabled(false); | 489 cb->setDuplicatesEnabled(false); |
478 } | 490 } |
479 | 491 |
516 this, SLOT(mouseEnteredWidget())); | 528 this, SLOT(mouseEnteredWidget())); |
517 connect(cb, SIGNAL(mouseLeft()), | 529 connect(cb, SIGNAL(mouseLeft()), |
518 this, SLOT(mouseLeftWidget())); | 530 this, SLOT(mouseLeftWidget())); |
519 | 531 |
520 cb->setToolTip(propertyLabel); | 532 cb->setToolTip(propertyLabel); |
521 m_groupLayouts[groupName]->addWidget | 533 groupLayout->addWidget(cb, 0, groupLayout->columnCount()); |
522 (cb, 0, m_groupLayouts[groupName]->columnCount()); | |
523 m_propertyControllers[name] = cb; | 534 m_propertyControllers[name] = cb; |
524 } | 535 } else if (existing != cb) { |
536 groupLayout->replaceWidget(existing, cb); | |
537 delete existing; | |
538 } | |
525 | 539 |
526 cb->blockSignals(true); | 540 cb->blockSignals(true); |
527 if (type == PropertyContainer::ValueProperty) { | 541 if (type == PropertyContainer::ValueProperty) { |
528 if (cb->currentIndex() != value) { | 542 if (cb->currentIndex() != value) { |
529 cb->setCurrentIndex(value); | 543 cb->setCurrentIndex(value); |