00001 #include <qapplication.h>
00002 #include <qpainter.h>
00003 #include <qpixmap.h>
00004
00005 #include <cassert>
00006
00007 #include "mythcontext.h"
00008 #include "mythlistbutton.h"
00009 #include "mythmainwindow.h"
00010 #include "mythcontext.h"
00011 #include "mythfontproperties.h"
00012 #include "mythuistatetype.h"
00013 #include "mythuibutton.h"
00014
00015 MythListButton::MythListButton(MythUIType *parent, const char *name)
00016 : MythUIType(parent, name)
00017 {
00018 m_showArrow = true;
00019 m_showScrollArrows = false;
00020
00021 Const();
00022 }
00023
00024 MythListButton::MythListButton(MythUIType *parent, const char *name,
00025 const QRect& area, bool showArrow,
00026 bool showScrollArrows)
00027 : MythUIType(parent, name)
00028 {
00029 m_Area = area;
00030
00031 m_showArrow = showArrow;
00032 m_showScrollArrows = showScrollArrows;
00033
00034 Const();
00035 }
00036
00037 void MythListButton::Const(void)
00038 {
00039 m_layout = LayoutVertical;
00040
00041 m_active = false;
00042 m_drawFromBottom = false;
00043
00044 m_itemList.setAutoDelete(false);
00045 m_topItem = 0;
00046 m_selItem = 0;
00047 m_selIterator = new QPtrListIterator<MythListButtonItem>(m_itemList);
00048 m_topIterator = new QPtrListIterator<MythListButtonItem>(m_itemList);
00049 m_selPosition = 0;
00050 m_topPosition = 0;
00051 m_itemCount = 0;
00052
00053 m_initialized = false;
00054 m_clearing = false;
00055 m_itemHorizSpacing = 0;
00056 m_itemVertSpacing = 0;
00057 m_itemMargin = 0;
00058 m_itemHeight = 0;
00059 m_itemsVisible = 0;
00060 m_columns = 0;
00061 m_rows = 0;
00062
00063 m_upArrow = m_downArrow = NULL;
00064
00065 m_textFlags = Qt::AlignLeft | Qt::AlignVCenter;
00066
00067 m_fontActive = new MythFontProperties();
00068 m_fontInactive = new MythFontProperties();
00069
00070 arrowPix = checkNonePix = checkHalfPix = checkFullPix = NULL;
00071 itemRegPix = itemSelActPix = itemSelInactPix = NULL;
00072
00073 SetCanTakeFocus(true);
00074
00075 connect(this, SIGNAL(TakingFocus()), this, SLOT(Select()));
00076 connect(this, SIGNAL(LosingFocus()), this, SLOT(Deselect()));
00077 }
00078
00079 MythListButton::~MythListButton()
00080 {
00081 m_clearing = true;
00082 MythListButtonItem* item = 0;
00083 for (item = m_itemList.first(); item; item = m_itemList.next())
00084 delete item;
00085 m_itemList.clear();
00086
00087 delete m_topIterator;
00088 delete m_selIterator;
00089
00090 if (m_fontActive)
00091 delete m_fontActive;
00092 if (m_fontInactive)
00093 delete m_fontInactive;
00094
00095 if (itemRegPix)
00096 itemRegPix->DownRef();
00097 if (itemSelActPix)
00098 itemSelActPix->DownRef();
00099 if (itemSelInactPix)
00100 itemSelInactPix->DownRef();
00101 if (arrowPix)
00102 arrowPix->DownRef();
00103 if (checkNonePix)
00104 checkNonePix->DownRef();
00105 if (checkHalfPix)
00106 checkHalfPix->DownRef();
00107 if (checkFullPix)
00108 checkFullPix->DownRef();
00109 }
00110
00111 void MythListButton::SetFontActive(const MythFontProperties &font)
00112 {
00113 *m_fontActive = font;
00114 }
00115
00116 void MythListButton::SetFontInactive(const MythFontProperties &font)
00117 {
00118 *m_fontInactive = font;
00119 }
00120
00121 void MythListButton::SetSpacing(int spacing)
00122 {
00123 m_itemHorizSpacing = NormX(spacing);
00124 m_itemVertSpacing = NormY(spacing);
00125 }
00126
00127 void MythListButton::SetMargin(int margin)
00128 {
00129 m_itemMargin = margin;
00130 }
00131
00132 void MythListButton::SetDrawFromBottom(bool draw)
00133 {
00134 m_drawFromBottom = draw;
00135 }
00136
00137 void MythListButton::SetTextFlags(int flags)
00138 {
00139 m_textFlags = flags;
00140 }
00141
00142 void MythListButton::SetActive(bool active)
00143 {
00144 m_active = active;
00145 if (m_initialized)
00146 SetPositionArrowStates();
00147 }
00148
00149 void MythListButton::Reset()
00150 {
00151 m_clearing = true;
00152
00153 MythListButtonItem* item = 0;
00154 for (item = m_itemList.first(); item; item = m_itemList.next())
00155 delete item;
00156
00157 m_clearing = false;
00158 m_itemList.clear();
00159
00160 m_topItem = 0;
00161 m_selItem = 0;
00162 m_selPosition = 0;
00163 m_topPosition = 0;
00164 m_itemCount = 0;
00165 m_selIterator->toFirst();
00166 m_topIterator->toFirst();
00167
00168 SetPositionArrowStates();
00169 }
00170
00171 void MythListButton::SetPositionArrowStates(void)
00172 {
00173 if (!m_initialized)
00174 Init();
00175
00176 if (m_ButtonList.size() > 0)
00177 {
00178 int button = 0;
00179
00180 if (m_drawFromBottom && m_itemCount < (int)m_itemsVisible)
00181 button = m_itemsVisible - m_itemCount;
00182
00183 for (int i = 0; i < button; i++)
00184 m_ButtonList[i]->SetVisible(false);
00185
00186 QPtrListIterator<MythListButtonItem> it = (*m_topIterator);
00187 while (it.current() && button < (int)m_itemsVisible)
00188 {
00189 MythUIButton *realButton = m_ButtonList[button];
00190 MythListButtonItem *buttonItem = it.current();
00191
00192 buttonItem->SetToRealButton(realButton, true);
00193 realButton->SetVisible(true);
00194
00195 button++;
00196 ++it;
00197 }
00198
00199 for (; button < (int)m_itemsVisible; button++)
00200 m_ButtonList[button]->SetVisible(false);
00201 }
00202
00203 if (!m_showScrollArrows || !m_downArrow || !m_upArrow)
00204 return;
00205
00206 if (m_itemCount == 0)
00207 {
00208 m_downArrow->DisplayState(MythUIStateType::Off);
00209 m_upArrow->DisplayState(MythUIStateType::Off);
00210 }
00211 else
00212 {
00213 if (m_topItem != m_itemList.first())
00214 m_upArrow->DisplayState(MythUIStateType::Full);
00215 else
00216 m_upArrow->DisplayState(MythUIStateType::Off);
00217
00218 if (m_topPosition + (int)m_itemsVisible < m_itemCount)
00219 m_downArrow->DisplayState(MythUIStateType::Full);
00220 else
00221 m_downArrow->DisplayState(MythUIStateType::Off);
00222 }
00223 }
00224
00225 void MythListButton::InsertItem(MythListButtonItem *item)
00226 {
00227 MythListButtonItem* lastItem = m_itemList.last();
00228 m_itemList.append(item);
00229
00230 m_itemCount++;
00231
00232 if (!lastItem)
00233 {
00234 m_topItem = item;
00235 m_selItem = item;
00236 m_selIterator->toFirst();
00237 m_topIterator->toFirst();
00238 m_selPosition = m_topPosition = 0;
00239 emit itemSelected(item);
00240 }
00241
00242 SetPositionArrowStates();
00243 }
00244
00245 void MythListButton::RemoveItem(MythListButtonItem *item)
00246 {
00247 if (m_clearing)
00248 return;
00249
00250 if (m_itemList.findRef(item) == -1)
00251 return;
00252
00253 if (item == m_topItem)
00254 {
00255 if (m_topItem != m_itemList.last())
00256 {
00257 ++(*m_topIterator);
00258 ++m_topPosition;
00259 m_topItem = m_topIterator->current();
00260 }
00261 else if (m_topItem != m_itemList.first())
00262 {
00263 --(*m_topIterator);
00264 --m_topPosition;
00265 m_topItem = m_topIterator->current();
00266 }
00267 else
00268 {
00269 m_topItem = NULL;
00270 m_topPosition = 0;
00271 m_topIterator->toFirst();
00272 }
00273 }
00274
00275 if (item == m_selItem)
00276 {
00277 if (m_selItem != m_itemList.last())
00278 {
00279 ++(*m_selIterator);
00280 ++m_selPosition;
00281 m_selItem = m_selIterator->current();
00282 }
00283 else if (m_selItem != m_itemList.first())
00284 {
00285 --(*m_selIterator);
00286 --m_selPosition;
00287 m_selItem = m_selIterator->current();
00288 }
00289 else
00290 {
00291 m_selItem = NULL;
00292 m_selPosition = 0;
00293 m_selIterator->toFirst();
00294 }
00295 }
00296
00297 m_itemList.remove(item);
00298 m_itemCount--;
00299
00300 SetPositionArrowStates();
00301
00302 if (m_selItem)
00303 emit itemSelected(m_selItem);
00304 }
00305
00306 void MythListButton::SetItemCurrent(MythListButtonItem* item)
00307 {
00308 m_selIterator->toFirst();
00309 MythListButtonItem *cur;
00310 bool found = false;
00311 m_selPosition = 0;
00312 while ((cur = m_selIterator->current()) != 0)
00313 {
00314 if (cur == item)
00315 {
00316 found = true;
00317 break;
00318 }
00319
00320 ++(*m_selIterator);
00321 ++m_selPosition;
00322 }
00323
00324 if (!found)
00325 {
00326 m_selIterator->toFirst();
00327 m_selPosition = 0;
00328 }
00329
00330 m_itemCount = m_selPosition;
00331 m_topItem = item;
00332 m_selItem = item;
00333 (*m_topIterator) = (*m_selIterator);
00334
00335 SetPositionArrowStates();
00336
00337 emit itemSelected(m_selItem);
00338 }
00339
00340 void MythListButton::SetItemCurrent(int current)
00341 {
00342 MythListButtonItem* item = m_itemList.at(current);
00343 if (!item)
00344 item = m_itemList.first();
00345
00346 SetItemCurrent(item);
00347 }
00348
00349 MythListButtonItem* MythListButton::GetItemCurrent()
00350 {
00351 return m_selItem;
00352 }
00353
00354 MythListButtonItem* MythListButton::GetItemFirst()
00355 {
00356 return m_itemList.first();
00357 }
00358
00359 MythListButtonItem* MythListButton::GetItemNext(MythListButtonItem *item)
00360 {
00361 if (m_itemList.findRef(item) == -1)
00362 return 0;
00363
00364 return m_itemList.next();
00365 }
00366
00367 int MythListButton::GetCount()
00368 {
00369 return m_itemCount;
00370 }
00371
00372 bool MythListButton::IsEmpty()
00373 {
00374 if (m_itemCount > 0)
00375 return false;
00376 else
00377 return true;
00378 }
00379
00380 QPtrListIterator<MythListButtonItem> MythListButton::GetIterator(void)
00381 {
00382 return QPtrListIterator<MythListButtonItem>(m_itemList);
00383 }
00384
00385 MythListButtonItem* MythListButton::GetItemAt(int pos)
00386 {
00387 return m_itemList.at(pos);
00388 }
00389
00390 int MythListButton::GetItemPos(MythListButtonItem* item)
00391 {
00392 if (!item)
00393 return -1;
00394 return m_itemList.findRef(item);
00395 }
00396
00397 void MythListButton::MoveUp(MovementUnit unit)
00398 {
00399 int pos = m_selPosition;
00400 if (pos == -1)
00401 return;
00402
00403 switch (unit)
00404 {
00405 case MoveItem:
00406 if (!m_selIterator->atFirst())
00407 {
00408 --(*m_selIterator);
00409 --m_selPosition;
00410 }
00411 break;
00412 case MoveColumn:
00413 if ((pos+1) - (((pos+1)/m_columns)*m_columns) != 1)
00414 {
00415 --(*m_selIterator);
00416 --m_selPosition;
00417 }
00418 break;
00419 case MoveRow:
00420 if ((pos - m_columns) >= 0)
00421 {
00422 for (int i = 0; i < m_columns; i++)
00423 {
00424 --(*m_selIterator);
00425 --m_selPosition;
00426 }
00427 }
00428 break;
00429 case MovePage:
00430 if (pos > (int)m_itemsVisible)
00431 {
00432 for (int i = 0; i < (int)m_itemsVisible; i++)
00433 {
00434 --(*m_selIterator);
00435 --m_selPosition;
00436 }
00437 break;
00438 }
00439
00440 case MoveMax:
00441 m_selIterator->toFirst();
00442 m_selPosition = 0;
00443 break;
00444 }
00445
00446 if (!m_selIterator->current())
00447 return;
00448
00449 m_selItem = m_selIterator->current();
00450
00451 if (m_selPosition <= m_topPosition)
00452 {
00453 m_topItem = m_selItem;
00454 (*m_topIterator) = (*m_selIterator);
00455 m_topPosition = m_selPosition;
00456 }
00457
00458 SetPositionArrowStates();
00459
00460 emit itemSelected(m_selItem);
00461 }
00462
00463 void MythListButton::MoveDown(MovementUnit unit)
00464 {
00465 int pos = m_selPosition;
00466 if (pos == -1)
00467 return;
00468
00469 switch (unit)
00470 {
00471 case MoveItem:
00472 if (!m_selIterator->atLast())
00473 {
00474 ++(*m_selIterator);
00475 ++m_selPosition;
00476 }
00477 break;
00478 case MoveColumn:
00479 if ((pos+1) - (((pos+1)/m_columns)*m_columns) > 0)
00480 {
00481 ++(*m_selIterator);
00482 ++m_selPosition;
00483 }
00484 break;
00485 case MoveRow:
00486 if ((pos + m_columns) < m_itemCount)
00487 {
00488 for (int i = 0; i < m_columns; i++)
00489 {
00490 ++(*m_selIterator);
00491 ++m_selPosition;
00492 }
00493 }
00494 break;
00495 case MovePage:
00496
00497 if ((pos + (int)m_itemsVisible) <= m_itemCount - 1)
00498 {
00499 for (int i = 0; i < (int)m_itemsVisible; i++)
00500 {
00501 ++(*m_selIterator);
00502 ++m_selPosition;
00503 }
00504 break;
00505 }
00506 break;
00507 case MoveMax:
00508 m_selIterator->toLast();
00509 m_selPosition = m_itemCount - 1;
00510 break;
00511 }
00512
00513 if (!m_selIterator->current())
00514 {
00515 VERBOSE(VB_IMPORTANT, "m_selIterator has left the building.");
00516 return;
00517 }
00518
00519 m_selItem = m_selIterator->current();
00520
00521
00522 while (m_topPosition + (int)m_itemsVisible < m_selPosition + 1)
00523 {
00524 ++(*m_topIterator);
00525 ++m_topPosition;
00526 }
00527
00528 m_topItem = m_topIterator->current();
00529
00530 SetPositionArrowStates();
00531
00532 emit itemSelected(m_selItem);
00533 }
00534
00535 bool MythListButton::MoveToNamedPosition(const QString &position_name)
00536 {
00537 if (m_selPosition < 0)
00538 {
00539 return false;
00540 }
00541
00542 if (!m_selIterator->toFirst())
00543 {
00544 return false;
00545 }
00546 m_selPosition = 0;
00547
00548 bool found_it = false;
00549 while(m_selIterator->current())
00550 {
00551 if (m_selIterator->current()->text() == position_name)
00552 {
00553 found_it = true;
00554 break;
00555 }
00556 ++(*m_selIterator);
00557 ++m_selPosition;
00558 }
00559
00560 if (!found_it)
00561 {
00562 m_selPosition = -1;
00563 return false;
00564 }
00565
00566 m_selItem = m_selIterator->current();
00567
00568 while (m_topPosition + (int)m_itemsVisible < m_selPosition + 1)
00569 {
00570 ++(*m_topIterator);
00571 ++m_topPosition;
00572 }
00573
00574 m_topItem = m_topIterator->current();
00575
00576 SetPositionArrowStates();
00577
00578 emit itemSelected(m_selItem);
00579
00580 return true;
00581 }
00582
00583 bool MythListButton::MoveItemUpDown(MythListButtonItem *item, bool flag)
00584 {
00585 if (item != m_selItem)
00586 {
00587 cerr << "Can't move non-selected item\n";
00588 return false;
00589 }
00590
00591 if (item == m_itemList.getFirst() && flag)
00592 return false;
00593 if (item == m_itemList.getLast() && !flag)
00594 return false;
00595
00596 int oldpos = m_selPosition;
00597 int insertat = 0;
00598 bool dolast = false;
00599
00600 if (flag)
00601 {
00602 insertat = m_selPosition - 1;
00603 if (item == m_itemList.getLast())
00604 dolast = true;
00605 else
00606 ++m_selPosition;
00607
00608 if (item == m_topItem)
00609 ++m_topPosition;
00610 }
00611 else
00612 insertat = m_selPosition + 1;
00613
00614 if (m_itemList.current() == item)
00615 {
00616 m_itemList.take();
00617
00618 }
00619 else
00620 m_itemList.take(oldpos);
00621
00622 m_itemList.insert(insertat, item);
00623
00624 if (flag)
00625 {
00626 MoveUp();
00627 if (!dolast)
00628 MoveUp();
00629 }
00630 else
00631 MoveDown();
00632
00633 return true;
00634 }
00635
00636 void MythListButton::Init()
00637 {
00638 if (m_initialized)
00639 return;
00640
00641 m_initialized = true;
00642
00643 QRect arrowsRect;
00644 if (m_showScrollArrows && m_upArrow)
00645 arrowsRect = PlaceArrows(m_upArrow->GetArea().size());
00646 else
00647 arrowsRect = QRect(0, 0, 0, 0);
00648
00649 if (m_upArrow)
00650 m_upArrow->SetVisible(m_showScrollArrows);
00651 if (m_downArrow)
00652 m_downArrow->SetVisible(m_showScrollArrows);
00653
00654 m_contentsRect = CalculateContentsRect(arrowsRect);
00655
00656 QFontMetrics fm(m_fontActive->face());
00657 QSize sz1 = fm.size(Qt::SingleLine, "XXXXX");
00658 fm = QFontMetrics(m_fontInactive->face());
00659 QSize sz2 = fm.size(Qt::SingleLine, "XXXXX");
00660 m_itemHeight = QMAX(sz1.height(), sz2.height()) + (int)(2 * m_itemMargin);
00661 m_itemWidth = m_contentsRect.width();
00662
00663
00664
00665 if (itemRegPix && (itemRegPix->height() > 10))
00666 m_itemHeight = itemRegPix->height();
00667 if (itemRegPix && (itemRegPix->width() > 10))
00668 m_itemWidth = itemRegPix->width();
00669
00670 CalculateVisibleItems();
00671
00672 if (itemRegPix)
00673 itemRegPix->Resize(QSize(ItemWidth(), m_itemHeight));
00674 if (itemSelActPix)
00675 itemSelActPix->Resize(QSize(ItemWidth(), m_itemHeight));
00676 if (itemSelInactPix)
00677 itemSelInactPix->Resize(QSize(ItemWidth(), m_itemHeight));
00678
00679 int col = 1;
00680 int row = 1;
00681
00682 for (int i = 0; i < (int)m_itemsVisible; i++)
00683 {
00684 QString name = QString("buttonlist button %1").arg(i);
00685 MythUIButton *button = new MythUIButton(this, name);
00686 if (itemRegPix)
00687 {
00688 button->SetBackgroundImage(MythUIButton::Normal, itemRegPix);
00689 button->SetBackgroundImage(MythUIButton::Active, itemRegPix);
00690 }
00691
00692 if (itemSelInactPix)
00693 button->SetBackgroundImage(MythUIButton::SelectedInactive,
00694 itemSelInactPix);
00695
00696 if (itemSelActPix)
00697 button->SetBackgroundImage(MythUIButton::Selected, itemSelActPix);
00698
00699 button->SetPaddingMargin(m_itemMargin);
00700
00701 if (checkNonePix)
00702 {
00703 button->SetCheckImage(MythUIStateType::Off, checkNonePix);
00704 button->SetCheckImage(MythUIStateType::Half, checkHalfPix);
00705 button->SetCheckImage(MythUIStateType::Full, checkFullPix);
00706 }
00707
00708 if (arrowPix)
00709 button->SetRightArrowImage(arrowPix);
00710
00711 button->SetFont(MythUIButton::Normal, *m_fontActive);
00712 button->SetFont(MythUIButton::Disabled, *m_fontInactive);
00713
00714 if (col > m_columns)
00715 {
00716 col = 1;
00717 row++;
00718 }
00719
00720 button->SetPosition(GetButtonPosition(col, row));
00721
00722 col++;
00723
00724 m_ButtonList.push_back(button);
00725 }
00726
00727 SetPositionArrowStates();
00728 }
00729
00730 bool MythListButton::keyPressEvent(QKeyEvent *e)
00731 {
00732 QStringList actions;
00733 bool handled = false;
00734 GetMythMainWindow()->TranslateKeyPress("Global", e, actions);
00735
00736 for (unsigned int i = 0; i < actions.size() && !handled; i++)
00737 {
00738 QString action = actions[i];
00739 handled = true;
00740
00741 if (action == "UP")
00742 {
00743 if ((m_layout == LayoutVertical) || (m_layout == LayoutGrid))
00744 MoveUp(MoveRow);
00745 else
00746 handled = false;
00747 }
00748 else if (action == "DOWN")
00749 {
00750 if ((m_layout == LayoutVertical) || (m_layout == LayoutGrid))
00751 MoveDown(MoveRow);
00752 else
00753 handled = false;
00754 }
00755 else if (action == "RIGHT")
00756 {
00757 if (m_layout == LayoutHorizontal)
00758 MoveDown(MoveItem);
00759 else if (m_layout == LayoutGrid)
00760 MoveDown(MoveColumn);
00761 else
00762 handled = false;
00763 }
00764 else if (action == "LEFT")
00765 {
00766 if (m_layout == LayoutHorizontal)
00767 MoveUp(MoveItem);
00768 else if (m_layout == LayoutGrid)
00769 MoveUp(MoveColumn);
00770 else
00771 handled = false;
00772 }
00773 else if (action == "PAGEUP")
00774 {
00775 MoveUp(MovePage);
00776 }
00777 else if (action == "PAGEDOWN")
00778 {
00779 MoveDown(MovePage);
00780 }
00781 else if (action == "SELECT")
00782 {
00783 emit itemSelected(GetItemCurrent());
00784 emit itemClicked(GetItemCurrent());
00785 }
00786 else
00787 handled = false;
00788 }
00789
00790 return handled;
00791 }
00792
00799 void MythListButton::gestureEvent(MythUIType *uitype, MythGestureEvent *event)
00800 {
00801 if (event->gesture() == MythGestureEvent::Click)
00802 {
00803 MoveToNamedPosition(dynamic_cast<MythUIButton *>(uitype)->GetText());
00804 emit itemClicked(GetItemCurrent());
00805 }
00806 }
00807
00815 MythUIType *MythListButton::GetChildAt(const QPoint &p)
00816 {
00817 if (GetArea().contains(p))
00818 {
00819
00820
00821
00822
00823 if (m_ChildrenList.isEmpty())
00824 return NULL;
00825
00826
00827 QValueVector<MythUIType*>::iterator it;
00828 for (it = m_ChildrenList.end()-1; it != m_ChildrenList.begin()-1; it--)
00829 {
00830 MythUIType *child = (*it)->GetChildAt(p - GetArea().topLeft());
00831 if (child != NULL)
00832 {
00833 return child;
00834 }
00835 }
00836 }
00837 return NULL;
00838 }
00839
00840 QPoint MythListButton::GetButtonPosition(int column, int row) const
00841 {
00842 QPoint position;
00843
00844 if (m_layout == LayoutHorizontal)
00845 {
00846 position = QPoint((column - 1) * (ItemWidth() + m_itemHorizSpacing),
00847 GetArea().height() / 2 - m_itemHeight / 2);
00848 }
00849 else if (m_layout == LayoutVertical)
00850 {
00851 position = QPoint(0, (row - 1) * (m_itemHeight + m_itemVertSpacing));
00852 }
00853 else if (m_layout == LayoutGrid)
00854 {
00855 position = QPoint((column - 1) * (ItemWidth() + m_itemHorizSpacing),
00856 (row - 1) * (m_itemHeight + m_itemVertSpacing));
00857 }
00858
00859 return position;
00860 }
00861
00862 void MythListButton::LoadPixmap(MythImage **pix, QDomElement &element)
00863 {
00864 if (*pix)
00865 (*pix)->DownRef();
00866 *pix = NULL;
00867
00868 QString filename = element.attribute("filename");
00869 if (!filename.isEmpty())
00870 {
00871 QImage *p = gContext->LoadScaleImage(filename);
00872 *pix = MythImage::FromQImage(&p);
00873 return;
00874 }
00875
00876 QColor startcol = QColor(element.attribute("gradientstart", "#505050"));
00877 QColor endcol = QColor(element.attribute("gradientend", "#000000"));
00878 int alpha = element.attribute("gradientalpha", "100").toInt();
00879
00880 *pix = MythImage::Gradient(QSize(10, 10), startcol, endcol, alpha);
00881 }
00882
00883 const QRect MythListButton::PlaceArrows(const QSize &arrowSize)
00884 {
00885 if (m_layout == LayoutHorizontal)
00886 {
00887 int x = GetArea().width() - arrowSize.width() - 1;
00888 int ytop = GetArea().height() / 2 - m_itemMargin / 2 - arrowSize.height();
00889 int ybottom = GetArea().height() / 2 + m_itemMargin / 2;
00890
00891 m_upArrow->SetPosition(QPoint(x, ybottom));
00892 m_downArrow->SetPosition(QPoint(x, ytop));
00893
00894
00895 QRect arrowsRect(x, 0, arrowSize.width() + 1, m_Area.height());
00896
00897 return QRect(x, 0, arrowSize.width() + 1, m_Area.height());
00898 }
00899
00900 int y = m_Area.height() - arrowSize.height() - 1;
00901 m_upArrow->SetPosition(QPoint(0, y));
00902 m_downArrow->SetPosition(QPoint(arrowSize.width() + m_itemMargin, y));
00903
00904 return QRect(0, y, m_Area.width(), arrowSize.height());
00905 }
00906
00907 QRect MythListButton::CalculateContentsRect(const QRect &arrowsRect) const
00908 {
00909 QRect contectRect;
00910
00911 if (m_layout == LayoutHorizontal)
00912 {
00913 contectRect = QRect(0, 0,
00914 GetArea().width() - arrowsRect.width() - 2 * m_itemMargin,
00915 GetArea().height());
00916 }
00917 else if ((m_layout == LayoutVertical) || (m_layout == LayoutGrid))
00918 {
00919 contectRect = QRect(0, 0, GetArea().width(), GetArea().height() -
00920 arrowsRect.height() - 2 * m_itemMargin);
00921 }
00922
00923 return contectRect;
00924 }
00925
00926 void MythListButton::CalculateVisibleItems(void)
00927 {
00928 int y = 0;
00929 int x = 0;
00930 m_itemsVisible = 0;
00931 m_rows = 0;
00932 m_columns = 0;
00933
00934 if ((m_layout == LayoutHorizontal) || (m_layout == LayoutGrid))
00935 {
00936 while (x <= m_contentsRect.width() - m_itemWidth)
00937 {
00938 x += m_itemWidth + m_itemHorizSpacing;
00939 m_columns++;
00940 }
00941 }
00942
00943 if ((m_layout == LayoutVertical) || (m_layout == LayoutGrid))
00944 {
00945 while (y <= m_contentsRect.height() - m_itemHeight)
00946 {
00947 y += m_itemHeight + m_itemVertSpacing;
00948 m_rows++;
00949 }
00950 }
00951
00952 if (m_rows == 0)
00953 m_rows = 1;
00954
00955 if (m_columns == 0)
00956 m_columns = 1;
00957
00958 m_itemsVisible = m_columns * m_rows;
00959 }
00960
00961 bool MythListButton::ParseElement(QDomElement &element)
00962 {
00963 if (element.tagName() == "area")
00964 m_Area = parseRect(element);
00965 else if (element.tagName() == "layout")
00966 {
00967 QString layout = getFirstText(element).lower();
00968
00969 if (layout == "grid")
00970 m_layout = LayoutGrid;
00971 else if (layout == "horizontal")
00972 m_layout = LayoutHorizontal;
00973 else
00974 m_layout = LayoutVertical;
00975 }
00976 else if (element.tagName() == "inactivefont")
00977 {
00978 QString fontname = getFirstText(element);
00979 MythFontProperties *fp = GetFont(fontname);
00980 if (!fp)
00981 fp = GetGlobalFontMap()->GetFont(fontname);
00982 if (fp)
00983 *m_fontInactive = *fp;
00984 }
00985 else if (element.tagName() == "activefont")
00986 {
00987 QString fontname = getFirstText(element);
00988 MythFontProperties *fp = GetFont(fontname);
00989 if (!fp)
00990 fp = GetGlobalFontMap()->GetFont(fontname);
00991 if (fp)
00992 *m_fontActive = *fp;
00993 }
00994 else if (element.tagName() == "scrollarrows")
00995 {
00996 m_showScrollArrows = parseBool(element.attribute("show", ""));
00997 if (m_showScrollArrows)
00998 {
00999 if (m_upArrow)
01000 delete m_upArrow;
01001 if (m_downArrow)
01002 delete m_downArrow;
01003 ParseChildren(element, this);
01004 m_upArrow = dynamic_cast<MythUIStateType *>(GetChild("upscrollarrow"));
01005 m_downArrow = dynamic_cast<MythUIStateType *>(GetChild("downscrollarrow"));
01006 }
01007 }
01008 else if (element.tagName() == "showarrow")
01009 m_showArrow = parseBool(element);
01010 else if (element.tagName() == "arrow")
01011 LoadPixmap(&arrowPix, element);
01012 else if (element.tagName() == "check-empty")
01013 LoadPixmap(&checkNonePix, element);
01014 else if (element.tagName() == "check-half")
01015 LoadPixmap(&checkHalfPix, element);
01016 else if (element.tagName() == "check-full")
01017 LoadPixmap(&checkFullPix, element);
01018 else if (element.tagName() == "regular-background")
01019 LoadPixmap(&itemRegPix, element);
01020 else if (element.tagName() == "selected-background")
01021 LoadPixmap(&itemSelActPix, element);
01022 else if (element.tagName() == "inactive-background")
01023 LoadPixmap(&itemSelInactPix, element);
01024 else if (element.tagName() == "spacing")
01025 {
01026 m_itemHorizSpacing = NormX(getFirstText(element).toInt());
01027 m_itemVertSpacing = NormY(getFirstText(element).toInt());
01028 }
01029 else if (element.tagName() == "margin")
01030 m_itemMargin = NormX(getFirstText(element).toInt());
01031 else if (element.tagName() == "drawfrombottom")
01032 m_drawFromBottom = parseBool(element);
01033 else if (element.tagName() == "multiline")
01034 {
01035 if (parseBool(element))
01036 m_textFlags |= Qt::WordBreak;
01037 else
01038 m_textFlags &= ~Qt::WordBreak;
01039 }
01040 else if (element.tagName() == "textflags")
01041 {
01042 QString align = getFirstText(element).lower();
01043
01044 m_textFlags = m_textFlags & Qt::WordBreak;
01045
01046 if (align == "center")
01047 m_textFlags |= Qt::AlignCenter;
01048 else if (align == "right")
01049 m_textFlags |= Qt::AlignRight;
01050 else if (align == "left")
01051 m_textFlags |= Qt::AlignLeft;
01052 else if (align == "allcenter")
01053 m_textFlags |= Qt::AlignHCenter | Qt::AlignVCenter;
01054 else if (align == "vcenter")
01055 m_textFlags |= Qt::AlignVCenter;
01056 else if (align == "hcenter")
01057 m_textFlags |= Qt::AlignHCenter;
01058 }
01059 else
01060 return MythUIType::ParseElement(element);
01061
01062 return true;
01063 }
01064
01065 void MythListButton::CreateCopy(MythUIType *parent)
01066 {
01067 MythListButton *lb = new MythListButton(parent, name());
01068 lb->CopyFrom(this);
01069 }
01070
01071 void MythListButton::CopyFrom(MythUIType *base)
01072 {
01073 MythListButton *lb = dynamic_cast<MythListButton *>(base);
01074 if (!lb)
01075 {
01076 VERBOSE(VB_IMPORTANT, QString("MythListButton CopyFrom ERR: "
01077 "Copy Failed "
01078 "base '%1' is not a mythlistbutton")
01079 .arg(base->name()));
01080 return;
01081 }
01082
01083 m_layout = lb->m_layout;
01084 m_order = lb->m_order;
01085 m_rect = lb->m_rect;
01086 m_contentsRect = lb->m_contentsRect;
01087
01088 m_itemHeight = lb->m_itemHeight;
01089 m_itemHorizSpacing = lb->m_itemHorizSpacing;
01090 m_itemVertSpacing = lb->m_itemVertSpacing;
01091 m_itemMargin = lb->m_itemMargin;
01092 m_itemsVisible = lb->m_itemsVisible;
01093 m_itemWidth = lb->m_itemWidth;
01094
01095 arrowPix = lb->arrowPix;
01096 checkNonePix = lb->checkNonePix;
01097 checkHalfPix = lb->checkHalfPix;
01098 checkFullPix = lb->checkFullPix;
01099 itemRegPix = lb->itemRegPix;
01100 itemSelActPix = lb->itemSelActPix;
01101 itemSelInactPix = lb->itemSelInactPix;
01102
01103 if (itemRegPix)
01104 itemRegPix->UpRef();
01105 if (itemSelActPix)
01106 itemSelActPix->UpRef();
01107 if (itemSelInactPix)
01108 itemSelInactPix->UpRef();
01109 if (arrowPix)
01110 arrowPix->UpRef();
01111 if (checkNonePix)
01112 checkNonePix->UpRef();
01113 if (checkHalfPix)
01114 checkHalfPix->UpRef();
01115 if (checkFullPix)
01116 checkFullPix->UpRef();
01117
01118 m_active = lb->m_active;
01119 m_showScrollArrows = lb->m_showScrollArrows;
01120 m_showArrow = lb->m_showArrow;
01121
01122 *m_fontActive = *lb->m_fontActive;
01123 *m_fontInactive = *lb->m_fontInactive;
01124
01125 m_drawoffset = lb->m_drawoffset;
01126 m_drawFromBottom = lb->m_drawFromBottom;
01127
01128 m_textFlags = lb->m_textFlags;
01129
01130 m_clearing = false;
01131 m_topItem = m_selItem = NULL;
01132
01133 m_selPosition = m_topPosition = m_itemCount = 0;
01134
01135 MythUIType::CopyFrom(base);
01136
01137 m_upArrow = dynamic_cast<MythUIStateType *>(GetChild("upscrollarrow"));
01138 m_downArrow = dynamic_cast<MythUIStateType *>(GetChild("downscrollarrow"));
01139
01140 for (int i = 0; i < (int)m_itemsVisible; i++)
01141 {
01142 MythUIType *deltype;
01143 QString name = QString("buttonlist button %1").arg(i);
01144 if ((deltype = GetChild(name)))
01145 delete deltype;
01146 }
01147
01148 m_ButtonList.clear();
01149
01150 m_initialized = false;
01151 }
01152
01153 void MythListButton::Finalize(void)
01154 {
01155 MythUIType::Finalize();
01156 }
01157
01159
01160 MythListButtonItem::MythListButtonItem(MythListButton* lbtype,
01161 const QString& text,
01162 MythImage *image, bool checkable,
01163 CheckState state, bool showArrow)
01164 {
01165 assert(lbtype);
01166
01167 m_parent = lbtype;
01168 m_text = text;
01169 m_image = image;
01170 m_checkable = checkable;
01171 m_state = state;
01172 m_showArrow = showArrow;
01173 m_data = 0;
01174 m_overrideInactive = false;
01175
01176 if (state >= NotChecked)
01177 m_checkable = true;
01178
01179 m_parent->InsertItem(this);
01180 }
01181
01182 MythListButtonItem::~MythListButtonItem()
01183 {
01184 if (m_parent)
01185 m_parent->RemoveItem(this);
01186 }
01187
01188 QString MythListButtonItem::text() const
01189 {
01190 return m_text;
01191 }
01192
01193 void MythListButtonItem::setText(const QString &text)
01194 {
01195 m_text = text;
01196 }
01197
01198 const MythImage* MythListButtonItem::image() const
01199 {
01200 return m_image;
01201 }
01202
01203 void MythListButtonItem::setImage(MythImage *image)
01204 {
01205 m_image = image;
01206 }
01207
01208 bool MythListButtonItem::checkable() const
01209 {
01210 return m_checkable;
01211 }
01212
01213 MythListButtonItem::CheckState MythListButtonItem::state() const
01214 {
01215 return m_state;
01216 }
01217
01218 MythListButton* MythListButtonItem::parent() const
01219 {
01220 return m_parent;
01221 }
01222
01223 void MythListButtonItem::setChecked(MythListButtonItem::CheckState state)
01224 {
01225 if (!m_checkable)
01226 return;
01227 m_state = state;
01228 }
01229
01230 void MythListButtonItem::setCheckable(bool flag)
01231 {
01232 m_checkable = flag;
01233 }
01234
01235 void MythListButtonItem::setDrawArrow(bool flag)
01236 {
01237 m_showArrow = flag;
01238 }
01239
01240 void MythListButtonItem::setData(void *data)
01241 {
01242 m_data = data;
01243 }
01244
01245 void *MythListButtonItem::getData()
01246 {
01247 return m_data;
01248 }
01249
01250 void MythListButtonItem::setOverrideInactive(bool flag)
01251 {
01252 m_overrideInactive = flag;
01253 }
01254
01255 bool MythListButtonItem::getOverrideInactive(void)
01256 {
01257 return m_overrideInactive;
01258 }
01259
01260 bool MythListButtonItem::moveUpDown(bool flag)
01261 {
01262 return m_parent->MoveItemUpDown(this, flag);
01263 }
01264
01265 void MythListButtonItem::SetToRealButton(MythUIButton *button, bool active_on)
01266 {
01267 button->SetText(m_text, m_parent->m_textFlags);
01268 button->SetButtonImage(m_image);
01269
01270 if (m_state == NotChecked)
01271 button->SetCheckState(MythUIStateType::Off);
01272 else if (m_state == HalfChecked)
01273 button->SetCheckState(MythUIStateType::Half);
01274 else
01275 button->SetCheckState(MythUIStateType::Full);
01276
01277 button->EnableCheck(m_checkable);
01278
01279 if (this == m_parent->m_selItem)
01280 {
01281 if (m_parent->m_active && !m_overrideInactive && active_on)
01282 button->SelectState(MythUIButton::Selected);
01283 else
01284 {
01285 if (active_on)
01286 button->SelectState(MythUIButton::SelectedInactive);
01287 else
01288 button->SelectState(MythUIButton::Active);
01289 }
01290
01291 button->EnableRightArrow(m_parent->m_showArrow || m_showArrow);
01292 }
01293 else
01294 {
01295 button->SelectState(MythUIButton::Normal);
01296 button->EnableRightArrow(false);
01297 }
01298 }
01299