MythTV master
mythuithemehelper.cpp
Go to the documentation of this file.
1// Qt
2#include <QDir>
3
4// MythTV
9
10#include "mythuithemehelper.h"
11
12#define LOC QString("ThemeHelper: ")
13
15{
16 StorageGroup sgroup("Themes", gCoreContext->GetHostName());
17 m_userThemeDir = sgroup.GetFirstDir(true);
18
19 QString themename = gCoreContext->GetSetting("Theme", DEFAULT_UI_THEME);
20 QString themedir = FindThemeDir(themename);
21
22 ThemeInfo themeinfo(themedir);
23 m_isWide = themeinfo.IsWide();
24 m_baseSize = themeinfo.GetBaseRes();
25 m_themename = themeinfo.GetName();
26 LOG(VB_GUI, LOG_INFO, LOC + QString("Using theme base resolution of %1x%2")
27 .arg(m_baseSize.width()).arg(m_baseSize.height()));
28
30 m_searchPaths.clear();
31
32 themename = gCoreContext->GetSetting("MenuTheme", "defaultmenu");
33 if (themename == "default")
34 themename = "defaultmenu";
36}
37
48QString MythUIThemeHelper::FindThemeDir(const QString& ThemeName, bool Fallback)
49{
50 QString testdir;
51 QDir dir;
52
53 if (!ThemeName.isEmpty())
54 {
55 testdir = m_userThemeDir + ThemeName;
56 dir.setPath(testdir);
57 if (dir.exists())
58 return testdir;
59
60 testdir = GetThemesParentDir() + ThemeName;
61 dir.setPath(testdir);
62 if (dir.exists())
63 return testdir;
64
65 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("No theme dir: '%1'").arg(dir.absolutePath()));
66 }
67
68 if (!Fallback)
69 return {};
70
72 dir.setPath(testdir);
73 if (dir.exists())
74 {
75 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Could not find theme: %1 - Switching to %2")
76 .arg(ThemeName, DEFAULT_UI_THEME));
78 return testdir;
79 }
80
81 LOG(VB_GENERAL, LOG_WARNING, LOC + QString("No default theme dir: '%1'")
82 .arg(dir.absolutePath()));
83
85 dir.setPath(testdir);
86 if (dir.exists())
87 {
88 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Could not find theme: %1 - Switching to %2")
89 .arg(ThemeName, FALLBACK_UI_THEME));
91 return testdir;
92 }
93
94 LOG(VB_GENERAL, LOG_ERR, LOC + QString("No fallback GUI theme dir: '%1'").arg(dir.absolutePath()));
95 return {};
96}
97
106QString MythUIThemeHelper::FindMenuThemeDir(const QString& MenuName)
107{
108 QString testdir;
109 QDir dir;
110
111 testdir = m_userThemeDir + MenuName;
112 dir.setPath(testdir);
113 if (dir.exists())
114 return testdir;
115
116 testdir = GetThemesParentDir() + MenuName;
117 dir.setPath(testdir);
118 if (dir.exists())
119 return testdir;
120
121 testdir = GetShareDir();
122 dir.setPath(testdir);
123 if (dir.exists())
124 {
125 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Could not find menu theme: %1 - Switching to default")
126 .arg(MenuName));
127 gCoreContext->SaveSetting("MenuTheme", "default");
128 return testdir;
129 }
130
131 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Could not find menu theme: %1 - Fallback to default failed.")
132 .arg(MenuName));
133 return {};
134}
135
137{
138 return m_menuthemepathname;
139}
140
142{
143 return m_themepathname;
144}
145
147{
148 return m_themename;
149}
150
152{
153 if (!m_searchPaths.isEmpty())
154 return m_searchPaths;
155
156 // traverse up the theme inheritance list adding their location to the search path
157 QList<ThemeInfo> themeList = GetThemes(THEME_UI);
158 bool found = true;
159 QString themeName = m_themename;
160 QString baseName;
161 QString dirName;
162
163 while (found && !themeName.isEmpty())
164 {
165 // find the ThemeInfo for this theme
166 found = false;
167 baseName = "";
168 dirName = "";
169
170 for (int x = 0; x < themeList.count(); x++)
171 {
172 if (themeList.at(x).GetName() == themeName)
173 {
174 found = true;
175 baseName = themeList.at(x).GetBaseTheme();
176 dirName = themeList.at(x).GetDirectoryName();
177 break;
178 }
179 }
180
181 // try to find where the theme is installed
182 if (found)
183 {
184 QString themedir = FindThemeDir(dirName, false);
185 if (!themedir.isEmpty())
186 {
187 LOG(VB_GUI, LOG_INFO, LOC + QString("Adding path '%1' to theme search paths").arg(themedir));
188 m_searchPaths.append(themedir + '/');
189 }
190 else
191 {
192 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Could not find ui theme location: %1").arg(themedir));
193 }
194 }
195 else
196 {
197 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Could not find inherited theme: %1").arg(themeName));
198 }
199
200 themeName = baseName;
201 }
202
203 if (m_isWide)
204 m_searchPaths.append(GetThemesParentDir() + "default-wide/");
205
206 m_searchPaths.append(GetThemesParentDir() + "default/");
207 m_searchPaths.append("/tmp/");
208 return m_searchPaths;
209}
210
212{
213 QDir themeDirs(GetThemesParentDir());
214 themeDirs.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
215 themeDirs.setSorting(QDir::Name | QDir::IgnoreCase);
216 QFileInfoList fileList { themeDirs.entryInfoList() };
217 themeDirs.setPath(m_userThemeDir);
218 fileList.append(themeDirs.entryInfoList());
219
220 QList<ThemeInfo> themeList;
221 for (const auto & theme : std::as_const(fileList))
222 {
223 if (theme.baseName() == "default" || theme.baseName() == "default-wide" ||
224 theme.baseName() == "Slave")
225 {
226 continue;
227 }
228
229 ThemeInfo themeInfo(theme.absoluteFilePath());
230
231 if (themeInfo.GetType() & Type)
232 themeList.append(themeInfo);
233 }
234
235 return themeList;
236}
237
239{
240 QFileInfo fi(Path);
241
242 if (fi.isAbsolute() && fi.exists())
243 return true;
244#ifdef Q_OS_ANDROID
245 if (Path.startsWith("assets:/") && fi.exists())
246 return true;
247#endif
248
249 QString file;
250 bool foundit = false;
251 const QStringList searchpath = GetThemeSearchPath();
252
253 for (const auto & ii : std::as_const(searchpath))
254 {
255 if (fi.isRelative())
256 file = ii + fi.filePath();
257 else if (fi.isAbsolute() && !fi.isRoot())
258 file = ii + fi.fileName();
259
260 if (QFile::exists(file))
261 {
262 Path = file;
263 foundit = true;
264 break;
265 }
266 }
267
268 return foundit;
269}
270
272{
273 return m_baseSize;
274}
275
276
QString GetHostName(void)
void SaveSetting(const QString &key, int newValue)
QString GetSetting(const QString &key, const QString &defaultval="")
void OverrideSettingForSession(const QString &key, const QString &value)
bool FindThemeFile(QString &Path)
QList< ThemeInfo > GetThemes(ThemeType Type)
QStringList GetThemeSearchPath()
QString FindThemeDir(const QString &ThemeName, bool Fallback=true)
Returns the full path to the theme denoted by themename.
QStringList m_searchPaths
QString FindMenuThemeDir(const QString &MenuName)
Returns the full path to the menu theme denoted by menuname.
QSize GetBaseSize() const
QString GetFirstDir(bool appendSlash=false) const
QSize GetBaseRes() const
Definition: themeinfo.h:28
QString GetName() const
Definition: themeinfo.h:29
bool IsWide() const
Definition: themeinfo.cpp:247
int GetType() const
Definition: themeinfo.h:34
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
QString GetShareDir(void)
Definition: mythdirs.cpp:261
QString GetThemesParentDir(void)
Definition: mythdirs.cpp:264
static QString themedir
Definition: mythdirs.cpp:23
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
#define LOC
static constexpr const char * FALLBACK_UI_THEME
static constexpr const char * DEFAULT_UI_THEME
string themeName
Definition: mythburn.py:217
bool exists(str path)
Definition: xbmcvfs.py:51
ThemeType
Definition: themeinfo.h:13
@ THEME_UI
Definition: themeinfo.h:15