Go to the documentation of this file.
8 #include <QCoreApplication>
11 #include <QRegularExpression>
34 #define LOC QString("MythNews: ")
35 #define LOC_WARN QString("MythNews, Warning: ")
36 #define LOC_ERR QString("MythNews, Error: ")
44 m_retrieveTimer(new QTimer(this)),
45 m_updateFreq(
gCoreContext->GetDurSetting<
std::chrono::minutes>(
"NewsUpdateFrequency", 30min)),
46 m_zoom(
gCoreContext->GetSetting(
"WebBrowserZoomLevel",
"1.0")),
47 m_browser(
gCoreContext->GetSetting(
"WebBrowserCommand",
""))
55 dir.mkdir(fileprefix);
56 fileprefix +=
"/MythNews";
57 dir.setPath(fileprefix);;
59 dir.mkdir(fileprefix);
71 QMutexLocker locker(&
m_lock);
76 QMutexLocker locker(&
m_lock);
99 LOG(VB_GENERAL, LOG_ERR,
"Cannot load screen 'news'");
154 QMutexLocker locker(&
m_lock);
160 "SELECT name, url, ico, updated, podcast "
172 QString name = query.
value(0).toString();
173 QString url = query.
value(1).toString();
176 bool podcast = query.
value(4).toBool();
184 item->SetData(QVariant::fromValue(site));
203 QMutexLocker locker(&
m_lock);
226 if (!article.
title().isEmpty())
254 if (site && !site->
imageURL().isEmpty())
342 QString text(tr(
"Updated") +
" - ");
344 if (updated.isValid()) {
349 text += tr(
"Unknown");
363 for (
int i = 0; i < actions.size() && !handled; i++)
365 QString
action = actions[i];
368 if (
action ==
"RETRIEVENEWS")
370 else if (
action ==
"CANCEL")
372 else if (
action ==
"MENU")
374 else if (
action ==
"EDIT")
376 else if (
action ==
"DELETE")
390 QMutexLocker locker(&
m_lock);
412 qint64 updated = site->
lastUpdated().toSecsSinceEpoch();
415 query.
prepare(
"UPDATE newssites SET updated = :UPDATED "
416 "WHERE name = :NAME ;");
427 QMutexLocker locker(&
m_lock);
438 QMutexLocker locker(&
m_lock);
459 for (
auto & article : articles)
472 QMutexLocker locker(&
m_lock);
474 if (!item || item->
GetData().isNull())
485 for (
auto & article : articles)
496 QMutexLocker locker(&
m_lock);
498 QMap<MythUIButtonListItem*,NewsArticle>::const_iterator it =
515 ShowOkPopup(tr(
"No browser command set! MythNews needs MythBrowser to be installed."));
527 cmd.replace(
"%ZOOM%",
m_zoom);
528 cmd.replace(
"%URL%", cmdUrl);
529 cmd.replace(
'\'',
"%27");
530 cmd.replace(
"&",
"\\&");
531 cmd.replace(
";",
"\\;");
544 QMutexLocker locker(&
m_lock);
552 if (!siteListItem || siteListItem->
GetData().isNull())
563 if (mythnewseditor->Create())
569 delete mythnewseditor;
576 auto *mythnewsconfig =
new MythNewsConfig(mainStack,
"mythnewsconfig");
578 if (mythnewsconfig->Create())
584 delete mythnewsconfig;
589 QMutexLocker locker(&
m_lock);
591 QString label = tr(
"Options");
621 QMutexLocker locker(&
m_lock);
625 if (siteUIItem && !siteUIItem->
GetData().isNull())
652 QString resultid = dce->
GetId();
653 int buttonnum = dce->GetResult();
655 if (resultid ==
"options")
659 else if (buttonnum == 1)
661 else if (buttonnum == 2)
663 else if (buttonnum == 3)
673 QString result = text;
676 result.replace(
"
",
"");
677 result.replace(
"
",
"");
678 result.replace(
"£", u8
"\u00A3");
679 result.replace(
"­",
"");
680 result.replace(
"–",
"-");
681 result.replace(
"“",
"""");
682 result.replace(
"”",
"""");
683 result.replace(
"‘",
"'");
684 result.replace(
"’",
"'");
685 result.replace(
"'",
"'");
688 static const QRegularExpression kHtmlParaStartRE
689 {
"<p>", QRegularExpression::CaseInsensitiveOption };
690 static const QRegularExpression kHtmlParaEndRE
691 {
"</p>", QRegularExpression::CaseInsensitiveOption };
692 static const QRegularExpression kHtmlBreak1RE
693 {
"<(br|)>", QRegularExpression::CaseInsensitiveOption };
694 static const QRegularExpression kHtmlBreak2RE
695 {
"<(br|)/>", QRegularExpression::CaseInsensitiveOption };
696 if( result.contains(kHtmlParaEndRE) )
698 result.replace( kHtmlParaStartRE,
"");
699 result.replace( kHtmlParaEndRE,
"\n\n");
703 result.replace( kHtmlParaStartRE,
"\n\n");
704 result.replace( kHtmlParaEndRE,
"");
706 result.replace( kHtmlBreak2RE,
"\n");
707 result.replace( kHtmlBreak1RE,
"\n");
711 static const QRegularExpression kTabRE {
"\t" };
712 result.replace( kTabRE,
"");
714 static const QRegularExpression kTwoSpaceRE {
" " };
715 result.replace( kTwoSpaceRE,
"");
717 static const QRegularExpression kStartingSpaceRE {
"\n " };
718 result.replace( kStartingSpaceRE,
"\n");
720 static const QRegularExpression kRemoveHtmlRE(QRegularExpression(
"</?.+>"));
721 result.remove((
const QRegularExpression&) kRemoveHtmlRE);
722 result = result.trimmed();
void ShowMenu(void) override
bool isActive(void) const
bool next(void)
Wrap QSqlQuery::next() so we can display the query results.
QSqlQuery wrapper that fetches a DB connection from the connection pool.
MythScreenStack * GetMainStack()
QString imageURL(void) const
void SetReturnEvent(QObject *retobject, const QString &resultid)
MythUIText * m_updatedText
QString toString(const QDateTime &raw_dt, uint format)
Returns formatted string representing the time.
NewsSite::List m_newsSites
QString articleURL(void) const
static QString cleanText(const QString &text)
MythUIText * m_nositesText
void Reset(void) override
Reset the widget to it's original state, should not reset changes made by the theme.
void slotNewsRetrieved(NewsSite *site)
QString title(void) const
MythDialogBox * m_menuPopup
void processAndShowNews(NewsSite *site)
QString thumbnail(void) const
bool Load(bool allowLoadInBackground=true, bool forceStat=false)
Load the image(s), wraps ImageLoader::LoadImage()
void slotRetrieveNews(void)
void customEvent(QEvent *event) override
void finished(NewsSite *item)
QVariant value(int i) const
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
bool exec(void)
Wrap QSqlQuery::exec() so we can display SQL.
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Screen in which all other widgets are contained and rendered.
QString description(void) const
QMap< MythUIButtonListItem *, NewsArticle > m_articles
uint myth_system(const QString &command, uint flags, std::chrono::seconds timeout)
void slotViewArticle(MythUIButtonListItem *articlesListItem)
bool HandleMedia(const QString &Handler, const QString &Mrl, const QString &Plot="", const QString &Title="", const QString &Subtitle="", const QString &Director="", int Season=0, int Episode=0, const QString &Inetref="", std::chrono::minutes LenMins=2h, const QString &Year="1895", const QString &Id="", bool UseBookmarks=false)
static bool sortByName(NewsSite *a, NewsSite *b)
MythNews(MythScreenStack *parent, const QString &name)
Creates a new MythNews Screen.
MythUIType * GetFocusWidget(void) const
MBASE_PUBLIC QDateTime fromSecsSinceEpoch(int64_t seconds)
This function takes the number of seconds since the start of the epoch and returns a QDateTime with t...
MythUIImage * m_downloadImage
void ShowFeedManager() const
bool TranslateKeyPress(const QString &Context, QKeyEvent *Event, QStringList &Actions, bool AllowJumps=true)
Get a list of actions for a keypress in the given context.
bool SetFocusWidget(MythUIType *widget=nullptr)
void AddButton(const QString &title)
Basic menu dialog, message and a list of options.
bool removeFromDB(RSSSite *site)
static MSqlQueryInfo InitCon(ConnectionReuse _reuse=kNormalConnection)
Only use this in combination with MSqlQuery constructor.
static void playVideo(const NewsArticle &article)
bool Create(void) override
static void DBError(const QString &where, const MSqlQuery &query)
void BuildFocusList(void)
QDateTime lastUpdated(void) const
void deleteNewsSite(void)
NewsArticle::List GetArticleList(void) const
void updateInfoView(void)
void cancelRetrieve(void)
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
MythUIImage * m_podcastImage
static bool Assign(ContainerType *container, UIType *&item, const QString &name, bool *err=nullptr)
MythUIButtonList * m_articlesList
QString description(void) const
void slotSiteSelected(MythUIButtonListItem *item)
@ kSimplify
Do Today/Yesterday/Tomorrow transform.
void ShowEditDialog(bool edit)
std::vector< NewsArticle > List
bool keyPressEvent(QKeyEvent *event) override
Key event handler.
static bool LoadWindowFromXML(const QString &xmlfile, const QString &windowname, MythUIType *parent)
void bindValue(const QString &placeholder, const QVariant &val)
Add a single binding.
Event dispatched from MythUI modal dialogs to a listening class containing a result of some form.
MythUIImage * m_thumbnailImage
virtual void SetText(const QString &text)
static const Type kEventType
MythMainWindow * GetMythMainWindow(void)
bool Create(void) override
std::chrono::minutes m_updateFreq
MythScreenStack * GetStack(const QString &Stackname)
QString enclosure(void) const
std::chrono::minutes m_timerTimeout
@ kDateTimeFull
Default local time.
MythUIButtonList * m_sitesList
@ kMSDontDisableDrawing
avoid disabling UI drawing
void AllowInput(bool Allow)
void SetFilename(const QString &filename)
Must be followed by a call to Load() to load the image.
virtual void AddScreen(MythScreenType *screen, bool allowFade=true)
MythConfirmationDialog * ShowOkPopup(const QString &message, bool showCancel)
Non-blocking version of MythPopupBox::showOkPopup()
bool IsVisible(bool recurse=false) const
MythUIImage * m_enclosureImage
bool prepare(const QString &query)
QSqlQuery::prepare() is not thread safe in Qt <= 3.3.2.