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 {
93  if (!label.isEmpty())
94  {
95  MythUIButtonListItem *item = GetItemByData(value);
96  if (item)
97  {
98  item->SetText(label);
99  return;
100  }
101  }
102 
103  int insertPos=-1;
104 
105  for (int pos = 0; pos < m_itemList.size(); pos++)
106  {
107  MythUIButtonListItem *item = m_itemList.at(pos);
108  if (item->GetData().toInt() > value)
109  {
110  insertPos = pos;
111  break;
112  }
113  }
114 
115  new MythUIButtonListItem(this, label.isEmpty() ? QString(value) : label,
116  qVariantFromValue(value), insertPos);
117 }
118 
123  const QString &filename, QDomElement &element, bool showWarnings)
124 {
125  if (element.tagName() == "template")
126  {
127  QString format = parseText(element);
128 
129  if (element.attribute("type") == "negative")
130  m_negativeTemplate = format;
131  else if (element.attribute("type") == "zero")
132  m_zeroTemplate = format;
133  else
134  m_positiveTemplate = format;
135 
136  m_hasTemplate = true;
137  }
138  else
139  {
140  return MythUIButtonList::ParseElement(filename, element, showWarnings);
141  }
142 
143  return true;
144 }
145 
150 {
151  bool handled = false;
152 
153  if ((unit == MovePage) && m_moveAmount)
155  else
156  handled = MythUIButtonList::MoveDown(unit, amount);
157 
158  return handled;
159 }
160 
165 {
166  bool handled = false;
167 
168  if ((unit == MovePage) && m_moveAmount)
170  else
171  handled = MythUIButtonList::MoveUp(unit, amount);
172 
173  return handled;
174 }
175 
180 {
181  MythUISpinBox *spinbox = new MythUISpinBox(parent, objectName());
182  spinbox->CopyFrom(this);
183 }
184 
189 {
190  MythUISpinBox *spinbox = dynamic_cast<MythUISpinBox *>(base);
191 
192  if (!spinbox)
193  return;
194 
195  m_hasTemplate = spinbox->m_hasTemplate;
197  m_zeroTemplate = spinbox->m_zeroTemplate;
199 
201 }
202 
203 // Open the entry dialog on certain key presses. A select or search action will
204 // open the dialog. A number or minus sign will open the entry dialog with the
205 // given key as the first digit.
206 // If the spinbox uses a template, the entries are not just numbers
207 // but can be sentences. The whole sentence is put in the entry field,
208 // allowing the user to change the number part of it.
209 
210 bool MythUISpinBox::keyPressEvent(QKeyEvent *event)
211 {
212  QStringList actions;
213  bool handled = false;
214  handled = GetMythMainWindow()->TranslateKeyPress("Global", event, actions);
215  if (handled)
216  return true;
217 
219  if (item == nullptr)
220  return MythUIButtonList::keyPressEvent(event);
221 
222  QString initialEntry = item->GetText();
223  bool doEntry = false;
224 
225  // Only invoke the entry dialog if the entry is a number
226  bool isNumber = false;
227  (void)initialEntry.toLongLong(&isNumber,10);
228  if (!isNumber)
229  return MythUIButtonList::keyPressEvent(event);
230 
231  for (int i = 0; i < actions.size(); ++i)
232  {
233  if (actions[i] >= ACTION_0 && actions[i] <= ACTION_9)
234  {
235  if (!m_hasTemplate)
236  initialEntry = actions[i];
237  doEntry=true;
238  break;
239  }
240  if (actions[i] == ACTION_SELECT || actions[i] == "SEARCH")
241  {
242  doEntry=true;
243  break;
244  }
245  }
246  if (actions.empty() && event->text() == "-")
247  {
248  if (!m_hasTemplate)
249  initialEntry = "-";
250  doEntry=true;
251  }
252 
253  if (doEntry)
254  {
255  ShowEntryDialog(initialEntry);
256  handled = true;
257  }
258 
259  if (handled)
260  return true;
261  return MythUIButtonList::keyPressEvent(event);
262 }
263 
264 void MythUISpinBox::ShowEntryDialog(QString initialEntry)
265 {
266  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
267 
268  SpinBoxEntryDialog *dlg = new SpinBoxEntryDialog(popupStack, "SpinBoxEntryDialog",
269  this, std::move(initialEntry), m_low, m_high, m_step);
270 
271  if (dlg->Create())
272  popupStack->AddScreen(dlg);
273  else
274  delete dlg;
275 }
276 
277 // Convenience Dialog to allow entry of a Spinbox value
278 
280  MythUIButtonList *parentList, QString searchText,
281  int low, int high, int step)
282  : MythScreenType(parent, name, false),
283  m_parentList(parentList),
284  m_searchText(std::move(searchText)),
285  m_entryEdit(nullptr),
286  m_cancelButton(nullptr),
287  m_okButton(nullptr),
288  m_rulesText(nullptr),
289  m_okClicked(false),
290  m_low(low),
291  m_high(high),
292  m_step(step)
293 
294 {
295  m_selection = parentList->GetCurrentPos();
296 }
297 
298 
300 {
301  if (!CopyWindowFromBase("SpinBoxEntryDialog", this))
302  return false;
303 
304  bool err = false;
305  UIUtilE::Assign(this, m_entryEdit, "entry", &err);
306  UIUtilW::Assign(this, m_cancelButton,"cancel", &err);
307  UIUtilW::Assign(this, m_rulesText,"rules", &err);
308  UIUtilE::Assign(this, m_okButton, "ok", &err);
309 
310  if (err)
311  {
312  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'SpinBoxEntryDialog'");
313  return false;
314  }
315 
317  entryChanged();
318  if (m_rulesText)
319  {
320  InfoMap infoMap;
321  infoMap["low"] = QString::number(m_low);
322  infoMap["high"] = QString::number(m_high);
323  infoMap["step"] = QString::number(m_step);
324  m_rulesText->SetTextFromMap(infoMap);
325  }
326 
327  connect(m_entryEdit, SIGNAL(valueChanged()), SLOT(entryChanged()));
328  if (m_cancelButton)
329  connect(m_cancelButton, SIGNAL(Clicked()), SLOT(Close()));
330  connect(m_okButton, SIGNAL(Clicked()), SLOT(okClicked()));
331 
332  BuildFocusList();
333 
334  return true;
335 }
336 
338 {
339  int currPos = 0;
340  int count = m_parentList->GetCount();
341  QString searchText = m_entryEdit->GetText();
342  bool found = false;
343  for (currPos = 0; currPos < count; currPos++)
344  {
345  if (searchText.compare(m_parentList->GetItemAt(currPos)->GetText(),
346  Qt::CaseInsensitive) == 0)
347  {
348  found = true;
349  m_selection = currPos;
350  break;
351  }
352  }
353  m_okButton->SetEnabled(found);
354 }
355 
357 {
359  Close();
360 }
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:158
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