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);