MythTV  master
logviewer.cpp
Go to the documentation of this file.
1 #include <unistd.h>
2 #include <iostream>
3 #include <cstdlib>
4 
5 // qt
6 #include <QKeyEvent>
7 #include <QFile>
8 #include <QTextStream>
9 #include <QCoreApplication>
10 
11 // mythtv
12 #include <mythcontext.h>
13 #include <mythdbcon.h>
14 #include <mythmainwindow.h>
15 #include <mythdialogbox.h>
16 #include <mythuibutton.h>
17 #include <mythuibuttonlist.h>
18 #include <mythuitext.h>
19 
20 // mytharchive
21 #include "archiveutil.h"
22 #include "logviewer.h"
23 
24 void showLogViewer(void)
25 {
27  QString logDir = getTempDirectory() + "logs";
28  QString progressLog;
29  QString fullLog;
30 
31  // wait for a log file to be available
32  int tries = 10;
33  while (tries--)
34  {
35  if (QFile::exists(logDir + "/progress.log"))
36  progressLog = logDir + "/progress.log";
37 
38  if (QFile::exists(logDir + "/mythburn.log"))
39  fullLog = logDir + "/mythburn.log";
40 
41  // we wait for both the progress.log and mythburn.log
42  if ((!progressLog.isEmpty()) && (!fullLog.isEmpty()))
43  break;
44 
45  // or we wait for a log from mytharchivehelper
46  if (progressLog.isEmpty() && fullLog.isEmpty())
47  {
48  QStringList logFiles;
49  QStringList filters;
50  filters << "*.log";
51 
52  QDir d(logDir);
53  logFiles = d.entryList(filters, QDir::Files | QDir::Readable, QDir::Time);
54 
55  if (!logFiles.isEmpty())
56  {
57  // the first log file should be the newest one available
58  progressLog = logDir + '/' + logFiles[0];
59  break;
60  }
61  }
62 
63  sleep(1);
64  }
65 
66  // do any logs exist?
67  if ((!progressLog.isEmpty()) || (!fullLog.isEmpty()))
68  {
69  auto *viewer = new LogViewer(mainStack);
70  viewer->setFilenames(progressLog, fullLog);
71  if (viewer->Create())
72  mainStack->AddScreen(viewer);
73  }
74  else
75  showWarningDialog(QCoreApplication::translate("LogViewer",
76  "Cannot find any logs to show!"));
77 }
78 
80  MythScreenType(parent, "logviewer")
81 {
83  "LogViewerUpdateTime", DEFAULT_UPDATE_TIME);
84  m_autoUpdate = gCoreContext->GetBoolSetting("LogViewerAutoUpdate", true);
85 }
86 
88 {
89  gCoreContext->SaveSetting("LogViewerUpdateTime", m_updateTime);
90  gCoreContext->SaveSetting("LogViewerAutoUpdate", m_autoUpdate ? "1" : "0");
91  delete m_updateTimer;
92 }
93 
95 {
96  // Load the theme for this screen
97  bool foundtheme = LoadWindowFromXML("mytharchive-ui.xml", "logviewer", this);
98  if (!foundtheme)
99  return false;
100 
101  bool err = false;
102  UIUtilE::Assign(this, m_logList, "loglist", &err);
103  UIUtilE::Assign(this, m_logText, "logitem_text", &err);
104  UIUtilE::Assign(this, m_cancelButton, "cancel_button", &err);
105  UIUtilE::Assign(this, m_updateButton, "update_button", &err);
106  UIUtilE::Assign(this, m_exitButton, "exit_button", &err);
107 
108  if (err)
109  {
110  LOG(VB_GENERAL, LOG_ERR, "Cannot load screen 'logviewer'");
111  return false;
112  }
113 
117 
119  this, &LogViewer::updateLogItem);
120 
121  m_updateTimer = nullptr;
122  m_updateTimer = new QTimer(this);
124 
125  BuildFocusList();
126 
128 
129  return true;
130 }
131 
132 void LogViewer::Init(void)
133 {
134  updateClicked();
135  if (m_logList->GetCount() > 0)
137 }
138 
139 bool LogViewer::keyPressEvent(QKeyEvent *event)
140 {
141  if (GetFocusWidget()->keyPressEvent(event))
142  return true;
143 
144  QStringList actions;
145  bool handled = GetMythMainWindow()->TranslateKeyPress("Global", event, actions);
146 
147  for (int i = 0; i < actions.size() && !handled; i++)
148  {
149  QString action = actions[i];
150  handled = true;
151 
152  if (action == "MENU")
153  ShowMenu();
154  else
155  handled = false;
156  }
157 
158  if (!handled && MythScreenType::keyPressEvent(event))
159  handled = true;
160 
161  return handled;
162 }
163 
165 {
166  updateClicked();
167 }
168 
170 {
172 
173  if (m_autoUpdate)
174  m_updateTimer->start(m_updateTime * 1000);
175  else
176  m_updateTimer->stop();
177 }
178 
180 {
181  if (item)
182  m_logText->SetText(item->GetText());
183 }
184 
186 {
187  QString tempDir = gCoreContext->GetSetting("MythArchiveTempDir", "");
188  QFile lockFile(tempDir + "/logs/mythburncancel.lck");
189 
190  if (!lockFile.open(QIODevice::WriteOnly | QIODevice::Truncate))
191  LOG(VB_GENERAL, LOG_ERR,
192  "LogViewer: Failed to create mythburncancel.lck file");
193 
194  lockFile.write("Cancel\n\r");
195  lockFile.close();
196 
197  ShowOkPopup(tr("Background creation has been asked to stop.\n"
198  "This may take a few minutes."));
199 }
200 
202 {
203  m_updateTimer->stop();
204 
205  QStringList list;
207 
208  if (!list.empty())
209  {
210  bool bUpdateCurrent =
211  (m_logList->GetCount() == m_logList->GetCurrentPos() + 1) ||
212  (m_logList->GetCurrentPos() == 0);
213 
214  for (int x = 0; x < list.size(); x++)
215  new MythUIButtonListItem(m_logList, list[x]);
216 
217  if (bUpdateCurrent)
219  }
220 
221  bool bRunning = (getSetting("MythArchiveLastRunStatus") == "Running");
222 
223  if (!bRunning)
224  {
225  m_cancelButton->SetEnabled(false);
226  m_updateButton->SetEnabled(false);
227  }
228 
229  if (m_autoUpdate)
230  {
231  if (m_logList->GetCount() > 0)
232  m_updateTimer->start(m_updateTime * 1000);
233  else
234  m_updateTimer->start(500);
235  }
236 }
237 
238 QString LogViewer::getSetting(const QString &key)
239 {
240  // read the setting direct from the DB rather than from the settings cache
241  // which isn't aware that the script may have changed something
243  if (query.isConnected())
244  {
245  query.prepare("SELECT data FROM settings WHERE value = :VALUE "
246  "AND hostname = :HOSTNAME ;");
247  query.bindValue(":VALUE", key);
248  query.bindValue(":HOSTNAME", gCoreContext->GetHostName());
249 
250  if (query.exec() && query.next())
251  {
252  return query.value(0).toString();
253  }
254  }
255  else
256  {
257  LOG(VB_GENERAL, LOG_ERR,
258  QString("Database not open while trying to load setting: %1")
259  .arg(key));
260  }
261 
262  return QString("");
263 }
264 
265 bool LogViewer::loadFile(const QString& filename, QStringList &list, int startline)
266 {
267  bool strip = !(filename.endsWith("progress.log") || filename.endsWith("mythburn.log"));
268 
269  list.clear();
270 
271  QFile file(filename);
272 
273  if (!file.exists())
274  return false;
275 
276  if (file.open( QIODevice::ReadOnly ))
277  {
278  QString s;
279  QTextStream stream(&file);
280 
281  // ignore the first startline lines
282  while ( !stream.atEnd() && startline > 0)
283  {
284  stream.readLine();
285  startline--;
286  }
287 
288  // read rest of file
289  while ( !stream.atEnd() )
290  {
291  s = stream.readLine();
292 
293  if (strip)
294  {
295  // the logging from mytharchivehelper contains a lot of junk
296  // we are not interested in so just strip it out
297  int pos = s.indexOf(" - ");
298  if (pos != -1)
299  s = s.mid(pos + 3);
300  }
301 
302  list.append(s);
303  }
304  file.close();
305  }
306  else
307  return false;
308 
309  return true;
310 }
311 
312 void LogViewer::setFilenames(const QString &progressLog, const QString &fullLog)
313 {
314  m_progressLog = progressLog;
315  m_fullLog = fullLog;
316  m_currentLog = progressLog;
317 }
318 
320 {
322  m_logList->Reset();
323  updateClicked();
324 }
325 
327 {
329  m_logList->Reset();
330  updateClicked();
331 }
332 
334 {
335  MythScreenStack *popupStack = GetMythMainWindow()->GetStack("popup stack");
336  auto *menuPopup = new MythDialogBox(tr("Menu"), popupStack, "actionmenu");
337 
338  if (menuPopup->Create())
339  popupStack->AddScreen(menuPopup);
340 
341  menuPopup->SetReturnEvent(this, "action");
342 
343  if (m_autoUpdate)
344  menuPopup->AddButton(tr("Don't Auto Update"), SLOT(toggleAutoUpdate()));
345  else
346  menuPopup->AddButton(tr("Auto Update"), SLOT(toggleAutoUpdate()));
347 
348  menuPopup->AddButton(tr("Show Progress Log"), SLOT(showProgressLog()));
349  menuPopup->AddButton(tr("Show Full Log"), SLOT(showFullLog()));
350 }
LogViewer::toggleAutoUpdate
void toggleAutoUpdate(void)
Definition: logviewer.cpp:169
MythUIButton::Clicked
void Clicked()
MSqlQuery::next
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
Definition: mythdbcon.cpp:783
LogViewer::~LogViewer
~LogViewer(void) override
Definition: logviewer.cpp:87
MSqlQuery
QSqlQuery wrapper that fetches a DB connection from the connection pool.
Definition: mythdbcon.h:126
MythMainWindow::GetMainStack
MythScreenStack * GetMainStack()
Definition: mythmainwindow.cpp:321
LogViewer::m_updateTime
int m_updateTime
Definition: logviewer.h:48
hardwareprofile.smolt.timeout
float timeout
Definition: smolt.py:103
LogViewer::setFilenames
void setFilenames(const QString &progressLog, const QString &fullLog)
Definition: logviewer.cpp:312
mythuitext.h
ShowOkPopup
MythConfirmationDialog * ShowOkPopup(const QString &message, QObject *parent, const char *slot, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
Definition: mythdialogbox.cpp:551
LogViewer::updateLogItem
void updateLogItem(MythUIButtonListItem *item)
Definition: logviewer.cpp:179
MythScreenType::Close
virtual void Close()
Definition: mythscreentype.cpp:402
MythMainWindow::TranslateKeyPress
bool TranslateKeyPress(const QString &context, QKeyEvent *e, QStringList &actions, bool allowJumps=true)
Get a list of actions for a keypress in the given context.
Definition: mythmainwindow.cpp:1139
MythUIButtonList::itemSelected
void itemSelected(MythUIButtonListItem *item)
mythdialogbox.h
MSqlQuery::value
QVariant value(int i) const
Definition: mythdbcon.h:198
MythScreenStack
Definition: mythscreenstack.h:16
arg
arg(title).arg(filename).arg(doDelete))
mythdbcon.h
MSqlQuery::exec
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
Definition: mythdbcon.cpp:603
logviewer.h
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythScreenType
Screen in which all other widgets are contained and rendered.
Definition: mythscreentype.h:45
build_compdb.file
file
Definition: build_compdb.py:55
LogViewer
Definition: logviewer.h:19
getTempDirectory
QString getTempDirectory(bool showError)
Definition: archiveutil.cpp:68
MythMainWindow::GetStack
MythScreenStack * GetStack(const QString &stackname)
Definition: mythmainwindow.cpp:326
mythuibuttonlist.h
LogViewer::cancelClicked
static void cancelClicked(void)
Definition: logviewer.cpp:185
MythUIButtonList::GetCount
int GetCount() const
Definition: mythuibuttonlist.cpp:1655
LogViewer::Create
bool Create(void) override
Definition: logviewer.cpp:94
MythScreenType::GetFocusWidget
MythUIType * GetFocusWidget(void) const
Definition: mythscreentype.cpp:112
showWarningDialog
void showWarningDialog(const QString &msg)
Definition: archiveutil.cpp:294
sleep
unsigned sleep(unsigned int x)
Definition: compat.h:160
MythUIButtonListItem
Definition: mythuibuttonlist.h:28
LogViewer::getSetting
static QString getSetting(const QString &key)
Definition: logviewer.cpp:238
DEFAULT_UPDATE_TIME
const int DEFAULT_UPDATE_TIME
Definition: logviewer.h:10
LogViewer::m_autoUpdate
bool m_autoUpdate
Definition: logviewer.h:47
LogViewer::m_exitButton
MythUIButton * m_exitButton
Definition: logviewer.h:58
LogViewer::m_updateButton
MythUIButton * m_updateButton
Definition: logviewer.h:60
MythUIButtonList::GetCurrentPos
int GetCurrentPos() const
Definition: mythuibuttonlist.h:190
archiveutil.h
MythScreenType::SetFocusWidget
bool SetFocusWidget(MythUIType *widget=nullptr)
Definition: mythscreentype.cpp:117
MythDialogBox
Basic menu dialog, message and a list of options.
Definition: mythdialogbox.h:138
LogViewer::m_updateTimer
QTimer * m_updateTimer
Definition: logviewer.h:49
LogViewer::ShowMenu
void ShowMenu(void) override
Definition: logviewer.cpp:333
MSqlQuery::InitCon
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
Definition: mythdbcon.cpp:535
MythScreenType::BuildFocusList
void BuildFocusList(void)
Definition: mythscreentype.cpp:222
LogViewer::m_logText
MythUIText * m_logText
Definition: logviewer.h:56
showLogViewer
void showLogViewer(void)
Definition: logviewer.cpp:24
LogViewer::Init
void Init(void) override
Used after calling Load() to assign data to widgets and other UI initilisation which is prohibited in...
Definition: logviewer.cpp:132
filename
QString filename
Definition: mythplugins/mytharchive/mytharchivehelper/main.cpp:637
MythUIType::SetEnabled
void SetEnabled(bool enable)
Definition: mythuitype.cpp:1108
LogViewer::m_cancelButton
MythUIButton * m_cancelButton
Definition: logviewer.h:59
MSqlQuery::isConnected
bool isConnected(void) const
Only updated once during object creation.
Definition: mythdbcon.h:135
gCoreContext
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
Definition: mythcorecontext.cpp:56
MythCoreContext::GetNumSetting
int GetNumSetting(const QString &key, int defaultval=0)
Definition: mythcorecontext.cpp:929
UIUtilDisp::Assign
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
Definition: mythuiutils.h:27
MythCoreContext::GetBoolSetting
bool GetBoolSetting(const QString &key, bool defaultval=false)
Definition: mythcorecontext.cpp:923
MythUIButtonListItem::GetText
QString GetText(const QString &name="") const
Definition: mythuibuttonlist.cpp:3305
LogViewer::showFullLog
void showFullLog(void)
Definition: logviewer.cpp:326
MythScreenType::keyPressEvent
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
Definition: mythscreentype.cpp:414
LogViewer::LogViewer
LogViewer(MythScreenStack *parent)
Definition: logviewer.cpp:79
XMLParseBase::LoadWindowFromXML
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
Definition: xmlparsebase.cpp:692
MSqlQuery::bindValue
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Definition: mythdbcon.cpp:864
LogViewer::showProgressLog
void showProgressLog(void)
Definition: logviewer.cpp:319
LogViewer::updateTimerTimeout
void updateTimerTimeout(void)
Definition: logviewer.cpp:164
MythUIText::SetText
virtual void SetText(const QString &text)
Definition: mythuitext.cpp:134
mythcontext.h
MythUIButtonList::Reset
void Reset() override
Reset the widget to it's original state, should not reset changes made by the theme.
Definition: mythuibuttonlist.cpp:114
GetMythMainWindow
MythMainWindow * GetMythMainWindow(void)
Definition: mythmainwindow.cpp:105
MythUIButtonList::SetItemCurrent
void SetItemCurrent(MythUIButtonListItem *item)
Definition: mythuibuttonlist.cpp:1557
build_compdb.action
action
Definition: build_compdb.py:9
mythuibutton.h
LogViewer::m_progressLog
QString m_progressLog
Definition: logviewer.h:52
LogViewer::loadFile
static bool loadFile(const QString &filename, QStringList &list, int startline)
Definition: logviewer.cpp:265
MythCoreContext::GetHostName
QString GetHostName(void)
Definition: mythcorecontext.cpp:855
LogViewer::updateClicked
void updateClicked(void)
Definition: logviewer.cpp:201
d
static const iso6937table * d
Definition: iso6937tables.cpp:1025
MythCoreContext::SaveSetting
void SaveSetting(const QString &key, int newValue)
Definition: mythcorecontext.cpp:898
LogViewer::m_logList
MythUIButtonList * m_logList
Definition: logviewer.h:55
mythmainwindow.h
LogViewer::m_currentLog
QString m_currentLog
Definition: logviewer.h:51
LogViewer::m_fullLog
QString m_fullLog
Definition: logviewer.h:53
MythScreenStack::AddScreen
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
Definition: mythscreenstack.cpp:49
query
MSqlQuery query(MSqlQuery::InitCon())
MythCoreContext::GetSetting
QString GetSetting(const QString &key, const QString &defaultval="")
Definition: mythcorecontext.cpp:915
LogViewer::keyPressEvent
bool keyPressEvent(QKeyEvent *e) override
Key event handler.
Definition: logviewer.cpp:139
MSqlQuery::prepare
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.
Definition: mythdbcon.cpp:808