00001 #include <algorithm>
00002
00003 #include <QGroupBox>
00004 #include <QStackedWidget>
00005
00006 #include "mythconfiggroups.h"
00007 #include "mythcontext.h"
00008 #include "mythlogging.h"
00009 #include "mythuihelper.h"
00010
00011 static void clear_widgets(vector<Configurable*> &children,
00012 vector<QWidget*> &childwidget)
00013 {
00014 for (uint i = 0; (i < childwidget.size()) && (i < children.size()); i++)
00015 {
00016 if (children[i] && childwidget[i])
00017 children[i]->widgetInvalid(childwidget[i]);
00018 }
00019 childwidget.clear();
00020 }
00021
00022 ConfigurationGroup::ConfigurationGroup(bool luselabel, bool luseframe,
00023 bool lzeroMargin, bool lzeroSpace) :
00024 Setting(this),
00025 uselabel(luselabel), useframe(luseframe),
00026 zeroMargin(lzeroMargin), zeroSpace(lzeroSpace)
00027 {
00028
00029
00030 if (lzeroMargin)
00031 margin = 2;
00032 else
00033 {
00034 float wmult = 0, hmult = 0;
00035
00036 GetMythUI()->GetScreenSettings(wmult, hmult);
00037
00038 if (luselabel)
00039 margin = (int)(28 * hmult * 0.5);
00040 else
00041 margin = (int)(10 * hmult * 0.5);
00042 }
00043
00044 space = (lzeroSpace) ? 2 : -1;
00045 }
00046
00047 ConfigurationGroup::~ConfigurationGroup()
00048 {
00049 childList::iterator it = children.begin();
00050 for (; it != children.end() ; ++it)
00051 {
00052 if (*it)
00053 {
00054 (*it)->disconnect();
00055 (*it)->deleteLater();
00056 }
00057 }
00058 children.clear();
00059 }
00060
00061 void ConfigurationGroup::deleteLater(void)
00062 {
00063 childList::iterator it = children.begin();
00064 for (; it != children.end() ; ++it)
00065 {
00066 if (*it)
00067 (*it)->disconnect();
00068 }
00069 Setting::deleteLater();
00070 }
00071
00072 Setting *ConfigurationGroup::byName(const QString &name)
00073 {
00074 Setting *tmp = NULL;
00075
00076 childList::iterator it = children.begin();
00077 for (; !tmp && (it != children.end()); ++it)
00078 {
00079 if (*it)
00080 tmp = (*it)->byName(name);
00081 }
00082
00083 return tmp;
00084 }
00085
00086 void ConfigurationGroup::Load(void)
00087 {
00088 childList::iterator it = children.begin();
00089 for (; it != children.end() ; ++it)
00090 if (*it && (*it)->GetStorage())
00091 (*it)->GetStorage()->Load();
00092 }
00093
00094 void ConfigurationGroup::Save(void)
00095 {
00096 childList::iterator it = children.begin();
00097 for (; it != children.end() ; ++it)
00098 if (*it && (*it)->GetStorage())
00099 (*it)->GetStorage()->Save();
00100 }
00101
00102 void ConfigurationGroup::Save(QString destination)
00103 {
00104 childList::iterator it = children.begin();
00105 for (; it != children.end() ; ++it)
00106 if (*it && (*it)->GetStorage())
00107 (*it)->GetStorage()->Save(destination);
00108 }
00109
00110 void ConfigurationGroup::SetSaveRequired(void)
00111 {
00112 childList::iterator it = children.begin();
00113 for (; it != children.end() ; ++it)
00114 if (*it && (*it)->GetStorage())
00115 (*it)->GetStorage()->SetSaveRequired();
00116 }
00117
00118 QWidget *VerticalConfigurationGroup::configWidget(
00119 ConfigurationGroup *cg,
00120 QWidget *parent,
00121 const char *widgetName)
00122 {
00123 layout = new QVBoxLayout();
00124 layout->setMargin(margin);
00125 layout->setSpacing((space<0) ? margin : space);
00126
00127 childwidget.resize(children.size());
00128 for (uint i = 0; i < children.size(); i++)
00129 {
00130 if (children[i] && children[i]->isVisible())
00131 {
00132 childwidget[i] = children[i]->configWidget(cg, NULL, NULL);
00133 layout->addWidget(childwidget[i]);
00134 children[i]->setEnabled(children[i]->isEnabled());
00135 }
00136 }
00137
00138 if (cg)
00139 {
00140 connect(this, SIGNAL(changeHelpText(QString)),
00141 cg, SIGNAL(changeHelpText(QString)));
00142 confgrp = cg;
00143 }
00144
00145 QWidget *widget = NULL;
00146 if (uselabel)
00147 {
00148 QGroupBox *groupbox = new QGroupBox(parent);
00149 groupbox->setObjectName(QString("VCG(%1)_groupbox").arg(widgetName));
00150 groupbox->setTitle(getLabel());
00151 widget = groupbox;
00152 }
00153 else if (useframe)
00154 {
00155 QFrame *frame = new QFrame(parent);
00156 frame->setFrameStyle(QFrame::Box);
00157 frame->setObjectName(QString("VCG(%1)_frame").arg(widgetName));
00158 widget = frame;
00159 }
00160 else
00161 {
00162 widget = new QWidget(parent);
00163 widget->setObjectName(QString("VCG(%1)_widget").arg(widgetName));
00164 }
00165
00166 widget->setLayout(layout);
00167 connect(widget, SIGNAL(destroyed(QObject*)),
00168 this, SLOT(widgetDeleted(QObject*)));
00169 return widget;
00170 }
00171
00172 void VerticalConfigurationGroup::widgetInvalid(QObject *obj)
00173 {
00174 widget = (widget == obj) ? NULL : widget;
00175 }
00176
00177 void VerticalConfigurationGroup::deleteLater(void)
00178 {
00179 clear_widgets(children, childwidget);
00180 ConfigurationGroup::deleteLater();
00181 }
00182
00183 bool VerticalConfigurationGroup::replaceChild(
00184 Configurable *old_child, Configurable *new_child)
00185 {
00186 childList::iterator it = children.begin();
00187 for (uint i = 0; it != children.end(); ++it, ++i)
00188 {
00189 if (*it != old_child)
00190 continue;
00191
00192 *it = new_child;
00193
00194 if (!widget)
00195 {
00196 old_child->deleteLater();
00197 return true;
00198 }
00199
00200 if (childwidget[i])
00201 {
00202 old_child->widgetInvalid(childwidget[i]);
00203 layout->removeWidget(childwidget[i]);
00204 childwidget[i]->deleteLater();
00205 childwidget[i] = NULL;
00206 }
00207
00208 bool was_visible = old_child->isVisible();
00209 bool was_enabled = old_child->isEnabled();
00210
00211 old_child->deleteLater();
00212
00213 if (was_visible)
00214 {
00215 childwidget[i] = new_child->configWidget(confgrp, widget, NULL);
00216 layout->addWidget(childwidget[i]);
00217 new_child->setEnabled(was_enabled);
00218 childwidget[i]->resize(1,1);
00219 childwidget[i]->show();
00220 }
00221
00222 return true;
00223 }
00224
00225 return false;
00226 }
00227
00228 void VerticalConfigurationGroup::repaint(void)
00229 {
00230 if (widget)
00231 widget->repaint();
00232 }
00233
00234 QWidget *HorizontalConfigurationGroup::configWidget(
00235 ConfigurationGroup *cg,
00236 QWidget *parent,
00237 const char *widgetName)
00238 {
00239 QHBoxLayout *layout = new QHBoxLayout();
00240 layout->setMargin(margin);
00241 layout->setSpacing((space<0) ? margin : space);
00242
00243 for (uint i = 0 ; i < children.size() ; ++i)
00244 {
00245 if (children[i] && children[i]->isVisible())
00246 {
00247 QWidget *child = children[i]->configWidget(cg, NULL, NULL);
00248 layout->addWidget(child);
00249 children[i]->setEnabled(children[i]->isEnabled());
00250 }
00251 }
00252
00253 if (cg)
00254 {
00255 connect(this, SIGNAL(changeHelpText(QString)),
00256 cg, SIGNAL(changeHelpText(QString)));
00257 }
00258
00259 QWidget *widget = NULL;
00260 if (uselabel)
00261 {
00262 QGroupBox *groupbox = new QGroupBox(parent);
00263 groupbox->setObjectName(QString("HCG(%1)_groupbox").arg(widgetName));
00264 groupbox->setTitle(getLabel());
00265 widget = groupbox;
00266 }
00267 else if (useframe)
00268 {
00269 QFrame *frame = new QFrame(parent);
00270 frame->setFrameStyle(QFrame::Box);
00271 frame->setObjectName(QString("HCG(%1)_frame").arg(widgetName));
00272 widget = frame;
00273 }
00274 else
00275 {
00276 widget = new QWidget(parent);
00277 widget->setObjectName(QString("HCG(%1)_widget").arg(widgetName));
00278 }
00279
00280 widget->setLayout(layout);
00281 return widget;
00282 }
00283
00284 QWidget* GridConfigurationGroup::configWidget(
00285 ConfigurationGroup *cg,
00286 QWidget *parent,
00287 const char *widgetName)
00288 {
00289 QGridLayout *layout = new QGridLayout();
00290 layout->setMargin(margin);
00291 layout->setSpacing(space < 0 ? margin : space);
00292
00293 for (uint i = 0; i < children.size(); i++)
00294 {
00295 if (children[i] && children[i]->isVisible())
00296 {
00297 QWidget *child = children[i]->configWidget(cg, NULL, NULL);
00298 layout->addWidget(child, i / columns, i % columns);
00299 children[i]->setEnabled(children[i]->isEnabled());
00300 }
00301 }
00302
00303 if (cg)
00304 {
00305 connect(this, SIGNAL(changeHelpText(QString)),
00306 cg, SIGNAL(changeHelpText(QString)));
00307 }
00308
00309 QWidget *widget = NULL;
00310 if (uselabel)
00311 {
00312 QGroupBox *groupbox = new QGroupBox(parent);
00313 groupbox->setObjectName(QString("GCG(%1)_groupbox").arg(widgetName));
00314 groupbox->setTitle(getLabel());
00315 widget = groupbox;
00316 }
00317 else if (useframe)
00318 {
00319 QFrame *frame = new QFrame(parent);
00320 frame->setFrameStyle(QFrame::Box);
00321 frame->setObjectName(QString("GCG(%1)_frame").arg(widgetName));
00322 widget = frame;
00323 }
00324 else
00325 {
00326 widget = new QWidget(parent);
00327 widget->setObjectName(QString("GCG(%1)_widget").arg(widgetName));
00328 }
00329
00330 widget->setLayout(layout);
00331
00332 return widget;
00333 }
00334
00335 StackedConfigurationGroup::~StackedConfigurationGroup()
00336 {
00337 clear_widgets(children, childwidget);
00338 ConfigurationGroup::deleteLater();
00339 }
00340
00341 void StackedConfigurationGroup::deleteLater(void)
00342 {
00343 clear_widgets(children, childwidget);
00344 ConfigurationGroup::deleteLater();
00345 }
00346
00347 QWidget* StackedConfigurationGroup::configWidget(ConfigurationGroup *cg,
00348 QWidget* parent,
00349 const char* widgetName)
00350 {
00351 widget = new QStackedWidget(parent);
00352 widget->setObjectName(widgetName);
00353
00354 connect(widget, SIGNAL(destroyed(QObject*)),
00355 this, SLOT( widgetDeleted(QObject*)));
00356
00357 for (uint i = 0 ; i < children.size() ; ++i)
00358 {
00359 if (!children[i]->isVisible())
00360 continue;
00361
00362 childwidget[i] = children[i]->configWidget(cg, widget, NULL);
00363 if (!childwidget[i])
00364 continue;
00365
00366 connect(childwidget[i], SIGNAL(destroyed( QObject*)),
00367 this, SLOT( widgetInvalid(QObject*)));
00368 widget->addWidget(childwidget[i]);
00369 children[i]->setEnabled(children[i]->isEnabled());
00370 }
00371
00372 if (childwidget[top])
00373 widget->setCurrentWidget(childwidget[top]);
00374
00375 if (cg)
00376 {
00377 connect(this, SIGNAL(changeHelpText(QString)), cg,
00378 SIGNAL(changeHelpText(QString)));
00379 }
00380 confgrp = cg;
00381
00382 return widget;
00383 }
00384
00385 void StackedConfigurationGroup::widgetInvalid(QObject *obj)
00386 {
00387 widget = (widget == obj) ? NULL : widget;
00388 for (uint i = 0; i < childwidget.size(); i++)
00389 {
00390 if ((QObject*)childwidget[i] == obj)
00391 childwidget[i] = NULL;
00392 }
00393 }
00394
00395 void StackedConfigurationGroup::addChild(Configurable *child)
00396 {
00397 ConfigurationGroup::addChild(child);
00398 childwidget.resize(childwidget.size() + 1);
00399 if (!widget)
00400 return;
00401
00402 uint i = children.size() - 1;
00403 if ((i < children.size()) && children[i]->isVisible())
00404 {
00405 childwidget[i] = children[i]->configWidget(confgrp, widget, NULL);
00406 widget->addWidget(childwidget[i]);
00407 childwidget[i]->resize(1,1);
00408 childwidget[i]->show();
00409 }
00410 }
00411
00412 void StackedConfigurationGroup::removeChild(Configurable *child)
00413 {
00414 childList::iterator it = find(children.begin(), children.end(), child);
00415 if (it == children.end())
00416 return;
00417
00418 uint i = it - children.begin();
00419 if ((i >= children.size()) || (i >= childwidget.size()))
00420 return;
00421
00422 children.erase(it);
00423
00424 vector<QWidget*>::iterator cit = childwidget.begin() + i;
00425 QWidget *cw = *cit;
00426 childwidget.erase(cit);
00427
00428 if (widget && cw)
00429 {
00430 child->widgetInvalid(cw);
00431 widget->removeWidget(cw);
00432 }
00433 }
00434
00435 void StackedConfigurationGroup::raise(Configurable* child)
00436 {
00437 for (uint i = 0 ; i < children.size() ; i++)
00438 {
00439 if (children[i] == child)
00440 {
00441 top = i;
00442 if (widget && childwidget[top])
00443 widget->setCurrentWidget(childwidget[top]);
00444 return;
00445 }
00446 }
00447
00448 LOG(VB_GENERAL, LOG_ALERT,
00449 QString("BUG: StackedConfigurationGroup::raise(): "
00450 "unrecognized child 0x%1 on setting %2/%3")
00451 .arg((uint64_t)child,0,16).arg(getName()).arg(getLabel()));
00452 }
00453
00454 void StackedConfigurationGroup::Save(void)
00455 {
00456 if (saveAll)
00457 ConfigurationGroup::Save();
00458 else if (top < children.size())
00459 children[top]->GetStorage()->Save();
00460 }
00461
00462 void StackedConfigurationGroup::Save(QString destination)
00463 {
00464 if (saveAll)
00465 ConfigurationGroup::Save(destination);
00466 else if (top < children.size())
00467 children[top]->GetStorage()->Save(destination);
00468 }
00469
00470 void TriggeredConfigurationGroup::addChild(Configurable* child)
00471 {
00472 VerifyLayout();
00473 configLayout->addChild(child);
00474 }
00475
00476 void TriggeredConfigurationGroup::addTarget(QString triggerValue,
00477 Configurable *target)
00478 {
00479 VerifyLayout();
00480 triggerMap[triggerValue] = target;
00481
00482 if (!configStack)
00483 {
00484 configStack = new StackedConfigurationGroup(
00485 stackUseLabel, stackUseFrame, stackZeroMargin, stackZeroSpace);
00486 configStack->setSaveAll(isSaveAll);
00487 }
00488
00489 configStack->addChild(target);
00490 }
00491
00492 Setting *TriggeredConfigurationGroup::byName(const QString &settingName)
00493 {
00494 VerifyLayout();
00495 Setting *setting = ConfigurationGroup::byName(settingName);
00496
00497 if (!setting)
00498 setting = configLayout->byName(settingName);
00499
00500 if (!setting && !widget)
00501 setting = configStack->byName(settingName);
00502
00503 return setting;
00504 }
00505
00506 void TriggeredConfigurationGroup::Load(void)
00507 {
00508 VerifyLayout();
00509
00510 configLayout->Load();
00511
00512 if (!widget && configStack)
00513 configStack->Load();
00514 }
00515
00516 void TriggeredConfigurationGroup::Save(void)
00517 {
00518 VerifyLayout();
00519
00520 configLayout->Save();
00521
00522 if (!widget)
00523 configStack->Save();
00524 }
00525
00526 void TriggeredConfigurationGroup::Save(QString destination)
00527 {
00528 VerifyLayout();
00529
00530 configLayout->Save(destination);
00531
00532 if (!widget)
00533 configStack->Save(destination);
00534 }
00535
00536 void TriggeredConfigurationGroup::repaint(void)
00537 {
00538 VerifyLayout();
00539
00540 if (widget)
00541 widget->repaint();
00542 }
00543
00544 void TriggeredConfigurationGroup::setTrigger(Configurable *_trigger)
00545 {
00546 if (trigger)
00547 {
00548 trigger->disconnect();
00549 }
00550
00551 trigger = _trigger;
00552
00553 if (trigger)
00554 {
00555 connect(trigger, SIGNAL(valueChanged( const QString&)),
00556 this, SLOT( triggerChanged(const QString&)));
00557 }
00558 }
00559
00560 void TriggeredConfigurationGroup::triggerChanged(const QString &value)
00561 {
00562 if (!configStack)
00563 return;
00564
00565 QMap<QString,Configurable*>::iterator it = triggerMap.find(value);
00566
00567 if (it == triggerMap.end())
00568 {
00569 LOG(VB_GENERAL, LOG_ALERT,
00570 "TriggeredConfigurationGroup::" +
00571 QString("triggerChanged(%1) Error:").arg(value) +
00572 "Failed to locate value in triggerMap");
00573 }
00574 else
00575 {
00576 configStack->raise(*it);
00577 }
00578 }
00579
00586 void TriggeredConfigurationGroup::SetVertical(bool vert)
00587 {
00588 if (configLayout)
00589 {
00590 LOG(VB_GENERAL, LOG_ALERT,
00591 "TriggeredConfigurationGroup::setVertical(): "
00592 "Sorry, this must be called before any children are added "
00593 "to the group.");
00594 return;
00595 }
00596
00597 isVertical = vert;
00598 }
00599
00600 void TriggeredConfigurationGroup::removeTarget(QString triggerValue)
00601 {
00602 ComboBoxSetting *combobox = dynamic_cast<ComboBoxSetting*>(trigger);
00603 if (!combobox)
00604 {
00605 LOG(VB_GENERAL, LOG_ALERT,
00606 "TriggeredConfigurationGroup::removeTarget(): "
00607 "Failed to cast trigger to ComboBoxSetting -- aborting");
00608 return;
00609 }
00610
00611 QMap<QString,Configurable*>::iterator cit = triggerMap.find(triggerValue);
00612 if (cit == triggerMap.end())
00613 {
00614 LOG(VB_GENERAL, LOG_ALERT,
00615 QString("TriggeredConfigurationGroup::removeTarget(): "
00616 "Failed to find desired value(%1) -- aborting")
00617 .arg(triggerValue));
00618 return;
00619 }
00620
00621
00622 bool ok = false;
00623 for (uint i = 0; i < combobox->size(); i++)
00624 {
00625 if (combobox->GetValue(i) == triggerValue)
00626 {
00627 ok = combobox->removeSelection(
00628 combobox->GetLabel(i), combobox->GetValue(i));
00629 break;
00630 }
00631 }
00632
00633 if (!ok)
00634 {
00635 LOG(VB_GENERAL, LOG_ALERT,
00636 QString("TriggeredConfigurationGroup::removeTarget(): "
00637 "Failed to remove '%1' from combobox -- aborting")
00638 .arg(triggerValue));
00639 return;
00640 }
00641
00642
00643 configStack->removeChild(*cit);
00644 triggerMap.erase(cit);
00645 }
00646
00647 void TriggeredConfigurationGroup::VerifyLayout(void)
00648 {
00649 if (configLayout)
00650 return;
00651
00652 if (isVertical)
00653 {
00654 configLayout = new VerticalConfigurationGroup(
00655 uselabel, useframe, zeroMargin, zeroSpace);
00656 }
00657 else
00658 {
00659 configLayout = new HorizontalConfigurationGroup(
00660 uselabel, useframe, zeroMargin, zeroSpace);
00661 }
00662
00663 ConfigurationGroup::addChild(configLayout);
00664 }
00665
00666 QWidget *TriggeredConfigurationGroup::configWidget(
00667 ConfigurationGroup *cg, QWidget *parent, const char *widgetName)
00668 {
00669 VerifyLayout();
00670
00671 configLayout->addChild(configStack);
00672
00673 widget = configLayout->configWidget(cg, parent, widgetName);
00674 connect(widget, SIGNAL(destroyed(QObject*)),
00675 this, SLOT(widgetDeleted(QObject*)));
00676
00677 return widget;
00678 }
00679
00680 void TriggeredConfigurationGroup::widgetInvalid(QObject *obj)
00681 {
00682 widget = (widget == obj) ? NULL : widget;
00683 }
00684
00685 JumpPane::JumpPane(const QStringList &labels, const QStringList &helptext) :
00686 VerticalConfigurationGroup(true, false, true, true)
00687 {
00688
00689 for (int i = 0; i < labels.size(); i++)
00690 {
00691 TransButtonSetting *button =
00692 new TransButtonSetting(QString::number(i));
00693 button->setLabel(labels[i]);
00694 button->setHelpText(helptext[i]);
00695 connect(button, SIGNAL(pressed(QString)),
00696 this, SIGNAL(pressed(QString)));
00697 addChild(button);
00698 }
00699 }