MythTV  master
mythuispinbox.cpp
Go to the documentation of this file.
1 
2 #include "mythmainwindow.h"
3 #include "mythuispinbox.h"
4 #include "mythlogging.h"
5 #include "mythuibutton.h"
6 #include "mythuitextedit.h"
7 #include "mythuitext.h"
8 
9 // QT headers
10 #include <QCoreApplication>
11 #include <QDomDocument>
12 #include <utility>
13 
25 void MythUISpinBox::SetRange(int low, int high, int step, uint pageMultiple)
26 {
27  if ((high == low) || step == 0)
28  return;
29 
30  m_low = low;
31  m_high = high;
32  m_step = step;
33 
34  m_moveAmount = pageMultiple;
35 
36  bool reverse = false;
37  int value = low;
38 
39  if (low > high)
40  reverse = true;
41 
42  Reset();
43 
44  while ((reverse && (value >= high)) ||
45  (!reverse && (value <= high)))
46  {
47  QString text;
48 
49  if (m_hasTemplate)
50  {
51  QString temp;
52 
53  if (value < 0 && !m_negativeTemplate.isEmpty())
54  temp = m_negativeTemplate;
55  else if (value == 0 && !m_zeroTemplate.isEmpty())
56  temp = m_zeroTemplate;
57  else if (!m_positiveTemplate.isEmpty())
58  temp = m_positiveTemplate;
59 
60  if (!temp.isEmpty())
61  {
62  if (temp.contains("%n"))
63  text = qApp->translate("ThemeUI", temp.toUtf8(), nullptr,
64  qAbs(value));
65  else
66  text = qApp->translate("ThemeUI", temp.toUtf8());
67  }
68  }
69 
70  if (text.isEmpty())
71  text = QString::number(value);
72 
73  new MythUIButtonListItem(this, text, qVariantFromValue(value));
74 
75  if (reverse)
76  value = value - step;
77  else
78  value = value + step;
79  }
80 
82 }
83 
84 
91 void MythUISpinBox::AddSelection(int value, const QString &label)
92 {
94  if (!label.isEmpty())
95  {
96  item = GetItemByData(value);
97  if (item)
98  {
99  item->SetText(label);
100  return;
101  }
102  }
103 
104  int insertPos=-1;
105 
106  for (int pos = 0; pos < m_itemList.size(); pos++)
107  {
108  item = m_itemList.at(pos);
109  if (item->GetData().toInt() > value)
110  {
111  insertPos = pos;
112  break;
113  }
114  }
115 
116  new MythUIButtonListItem(this, label.isEmpty() ? QString(value) : label,
117  qVariantFromValue(value), insertPos);
118 }
119 
124  const QString &filename, QDomElement &element, bool showWarnings)
125 {
126  if (element.tagName() == "template")
127  {
128  QString format = parseText(element);
129 
130  if (element.attribute("type") == "negative")
131  m_negativeTemplate = format;
132  else if (element.attribute("type") == "zero")
133  m_zeroTemplate = format;
134  else
135  m_positiveTemplate = format;
136 
137  m_hasTemplate = true;
138  }
139  else
140  {
141  return MythUIButtonList::ParseElement(filename, element, showWarnings);
142  }
143 
144  return true;
145 }
146 
151 {
152  bool handled = false;
153 
154  if ((unit == MovePage) && m_moveAmount)
156  else
157  handled = MythUIButtonList::MoveDown(unit, amount);
158 
159  return handled;
160 }
161 
166 {
167  bool handled = false;
168 
169  if ((unit == MovePage) && m_moveAmount)
171  else
172  handled = MythUIButtonList::MoveUp(unit, amount);
173 
174  return handled;
175 }
176 
181 {
182  MythUISpinBox *spinbox = new MythUISpinBox(parent, objectName());
183  spinbox->CopyFrom(this);
184 }
185 
190 {
191  MythUISpinBox *spinbox = dynamic_cast<MythUISpinBox *>(base);
192 
193  if (!spinbox)
194  return;
195 
196  m_hasTemplate = spinbox->m_hasTemplate;
198  m_zeroTemplate = spinbox->m_zeroTemplate;
200 
202 }
203 
204 // Open the entry dialog on certain key presses. A select or search action will
205 // open the dialog. A number or minus sign will open the entry dialog with the
206 // given key as the first digit.
207 // If the spinbox uses a template, the entries are not just numbers
208 // but can be sentences. The whole sentence is put in the entry field,
209 // allowing the user to change the number part of it.
210 
211 bool MythUISpinBox::keyPressEvent(QKeyEvent *event)
212 {
213  QStringList actions;
214  bool handled = false;
215  handled = GetMythMainWindow()->TranslateKeyPress("Global", event, actions);
216  if (handled)
217  return true;
218 
220  if (item == nullptr)
221  return MythUIButtonList::keyPressEvent(event);
222 
223  QString initialEntry = item->GetText();
224  bool doEntry = false;
225 
226  // Only invoke the entry dialog if the entry is a number
227  bool isNumber = false;
228  (void)initialEntry.toLongLong(&isNumber,10);
229  if (!isNumber)
230  return MythUIButtonList::keyPressEvent(event);
231 
232  for (int i = 0; i < actions.size(); ++i)
233  {
234  if (actions[i] >= ACTION_0 && actions[i] <= ACTION_9)
235  {
236  if (!m_hasTemplate)
237  initialEntry = actions[i];
238  doEntry=true;
239  break;
240  }
241  if (actions[i] == ACTION_SELECT || actions[i] == "SEARCH")
242  {
243  doEntry=true;
244  break;
245  }
246  }
247  if (actions.empty() && event->text() == "-")
248  {
249  if (!m_hasTemplate)
250  initialEntry = "-";
251  doEntry=true;
252  }
253 
254  if (doEntry)
255  {
256  ShowEntryDialog(initialEntry);
257  handled = true;
258  }
259 
260  if (handled)
261  return true;
262  return MythUIButtonList::keyPressEvent(event);
263 }
264 
265 void MythUISpinBox::ShowEntryDialog(QString initialEntry)
266 {
267  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
268 
269  SpinBoxEntryDialog *dlg = new SpinBoxEntryDialog(popupStack, "SpinBoxEntryDialog",
270  this, std::move(initialEntry), m_low, m_high, m_step);
271 
272  if (dlg->Create())
273  popupStack->AddScreen(dlg);
274  else
275  delete dlg;
276 }
277 
278 // Convenience Dialog to allow entry of a Spinbox value
279 
281  MythUIButtonList *parentList, QString searchText,
282  int low, int high, int step)
283  : MythScreenType(parent, name, false),
284  m_parentList(parentList),
285  m_searchText(std::move(searchText)),
286  m_entryEdit(nullptr),
287  m_cancelButton(nullptr),
288  m_okButton(nullptr),
289  m_rulesText(nullptr),
290  m_okClicked(false),
291  m_low(low),
292  m_high(high),
293  m_step(step)
294 
295 {
296  m_selection = parentList->GetCurrentPos();
297 }
298 
299 
301 {
302  if (!CopyWindowFromBase("SpinBoxEntryDialog", this))
303  return false;
304 
305  bool err = false;
306  UIUtilE::Assign(this, m_entryEdit, "entry", &err);
307  UIUtilW::Assign(this, m_cancelButton,"cancel", &err);
308  UIUtilW::Assign(this, m_rulesText,"rules", &err);
309  UIUtilE::Assign(this, m_okButton, "ok", &err);
310 
311  if (err)
312  {
313  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'SpinBoxEntryDialog'");
314  return false;
315  }
316 
318  entryChanged();
319  if (m_rulesText)
320  {
321  InfoMap infoMap;
322  infoMap["low"] = QString::number(m_low);
323  infoMap["high"] = QString::number(m_high);
324  infoMap["step"] = QString::number(m_step);
325  m_rulesText->SetTextFromMap(infoMap);
326  }
327 
328  connect(m_entryEdit, SIGNAL(valueChanged()), SLOT(entryChanged()));
329  if (m_cancelButton)
330  connect(m_cancelButton, SIGNAL(Clicked()), SLOT(Close()));
331  connect(m_okButton, SIGNAL(Clicked()), SLOT(okClicked()));
332 
333  BuildFocusList();
334 
335  return true;
336 }
337 
339 {
340  int currPos = 0;
341  int count = m_parentList->GetCount();
342  QString searchText = m_entryEdit->GetText();
343  bool found = false;
344  for (currPos = 0; currPos < count; currPos++)
345  {
346  if (searchText.compare(m_parentList->GetItemAt(currPos)->GetText(),
347  Qt::CaseInsensitive) == 0)
348  {
349  found = true;
350  m_selection = currPos;
351  break;
352  }
353  }
354  m_okButton->SetEnabled(found);
355 }
356 
358 {
360  Close();
361 }
MythUIText * m_rulesText
Definition: mythuispinbox.h:81
void AddSelection(int value, const QString &label="")
Add a special label for a value of the spinbox, it does not need to be in the range.
MythUIButton * m_cancelButton
Definition: mythuispinbox.h:79
void CopyFrom(MythUIType *base) override
Copy this widgets state from another.
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
void SetEnabled(bool enable)
MythUIButtonList * m_parentList
Definition: mythuispinbox.h:76
A widget for offering a range of numerical values where only the the bounding values and interval are...
Definition: mythuispinbox.h:16
QString m_positiveTemplate
Definition: mythuispinbox.h:50
void CalculateArrowStates(void)
#define ACTION_0
Definition: mythuiactions.h:4
bool MoveDown(MovementUnit unit=MoveItem, uint amount=0) override
virtual bool MoveDown(MovementUnit unit=MoveItem, uint amount=0)
MythUIButton * m_okButton
Definition: mythuispinbox.h:80
void SetTextFromMap(const InfoMap &map)
Definition: mythuitext.cpp:159
friend class MythUIButtonListItem
MythScreenStack * GetStack(const QString &stackname)
unsigned int uint
Definition: compat.h:140
MythUIButtonListItem * GetItemAt(int pos) const
QString m_zeroTemplate
Definition: mythuispinbox.h:49
The base class on which all widgets and screens are based.
Definition: mythuitype.h:63
void BuildFocusList(void)
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
#define ACTION_SELECT
Definition: mythuiactions.h:15
virtual void Close()
virtual bool MoveUp(MovementUnit unit=MoveItem, uint amount=0)
MythUIButtonListItem * GetItemByData(const QVariant &data)
void SetRange(int low, int high, int step, uint pageMultiple=5)
Set the lower and upper bounds of the spinbox, the interval and page amount.
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
QString m_negativeTemplate
Definition: mythuispinbox.h:48
QHash< QString, QString > InfoMap
Definition: mythtypes.h:15
static bool CopyWindowFromBase(const QString &windowname, MythScreenType *win)
bool ParseElement(const QString &filename, QDomElement &element, bool showWarnings) override
Parse the xml definition of this widget setting the state of the object accordingly.
bool ParseElement(const QString &filename, QDomElement &element, bool showWarnings) override
Parse the xml definition of this widget setting the state of the object accordingly.
MythUISpinBox(MythUIType *parent, const QString &name)
Definition: mythuispinbox.h:20
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
void SetText(const QString &text, const QString &name="", const QString &state="")
void CreateCopy(MythUIType *parent) override
Copy the state of this widget to the one given, it must be of the same type.
const char * name
Definition: ParseText.cpp:328
bool Create(void) override
List widget, displays list items in a variety of themeable arrangements and can trigger signals when ...
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
void SetText(const QString &text, bool moveCursor=true)
static QString parseText(QDomElement &element)
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
MythMainWindow * GetMythMainWindow(void)
QString GetText(const QString &name="") const
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
#define ACTION_9
Definition: mythuiactions.h:13
bool MoveUp(MovementUnit unit=MoveItem, uint amount=0) override
MythUITextEdit * m_entryEdit
Definition: mythuispinbox.h:78
void ShowEntryDialog(QString initialEntry)
void SetItemCurrent(MythUIButtonListItem *item)
void CopyFrom(MythUIType *base) override
Copy this widgets state from another.
SpinBoxEntryDialog(MythScreenStack *parent, const char *name, MythUIButtonList *parentList, QString searchText, int low, int high, int step)
Screen in which all other widgets are contained and rendered.
int GetCurrentPos() const
QList< MythUIButtonListItem * > m_itemList
QString GetText(void) const
MythUIButtonListItem * GetItemCurrent() const