PageRenderTime 55ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/mediaCenterPlugins/XbmcXml.cpp

https://github.com/zabinko/MediaElch
C++ | 1951 lines | 1524 code | 190 blank | 237 comment | 362 complexity | 5039a23fe7903bb37b94871978fd39c0 MD5 | raw file
Possible License(s): GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. #include "XbmcXml.h"
  2. #include <QApplication>
  3. #include <QDebug>
  4. #include <QDir>
  5. #include <QFileInfo>
  6. #include <QXmlStreamWriter>
  7. #include "globals/Globals.h"
  8. #include "globals/Helper.h"
  9. #include "globals/Manager.h"
  10. #include "settings/Settings.h"
  11. /**
  12. * @brief XbmcXml::XbmcXml
  13. * @param parent
  14. */
  15. XbmcXml::XbmcXml(QObject *parent)
  16. {
  17. setParent(parent);
  18. }
  19. /**
  20. * @brief XbmcXml::~XbmcXml
  21. */
  22. XbmcXml::~XbmcXml()
  23. {
  24. }
  25. /**
  26. * @brief Checks if our MediaCenterPlugin supports a feature
  27. * @param feature Feature to check
  28. * @return Feature is supported or not
  29. */
  30. bool XbmcXml::hasFeature(int feature)
  31. {
  32. if (feature == MediaCenterFeatures::HandleMovieSetImages)
  33. return false;
  34. return true;
  35. }
  36. /**
  37. * @brief Writes movie elements to an xml stream
  38. * @param xml XML stream
  39. * @param movie Movie to save
  40. */
  41. void XbmcXml::writeMovieXml(QXmlStreamWriter &xml, Movie *movie)
  42. {
  43. qDebug() << "Entered, movie=" << movie->name();
  44. xml.writeStartElement("movie");
  45. xml.writeTextElement("title", movie->name());
  46. xml.writeTextElement("originaltitle", movie->originalName());
  47. xml.writeTextElement("rating", QString("%1").arg(movie->rating()));
  48. xml.writeTextElement("votes", QString::number(movie->votes()));
  49. xml.writeTextElement("top250", QString::number(movie->top250()));
  50. xml.writeTextElement("year", movie->released().toString("yyyy"));
  51. xml.writeTextElement("plot", movie->overview());
  52. xml.writeTextElement("outline", movie->outline());
  53. xml.writeTextElement("tagline", movie->tagline());
  54. if (movie->runtime() > 0)
  55. xml.writeTextElement("runtime", QString("%1").arg(movie->runtime()));
  56. xml.writeTextElement("mpaa", movie->certification());
  57. xml.writeTextElement("credits", movie->writer());
  58. xml.writeTextElement("director", movie->director());
  59. xml.writeTextElement("playcount", QString("%1").arg(movie->playcount()));
  60. xml.writeTextElement("lastplayed", movie->lastPlayed().toString("yyyy-MM-dd HH:mm:ss"));
  61. xml.writeTextElement("id", movie->id());
  62. xml.writeTextElement("tmdbid", movie->tmdbId());
  63. xml.writeTextElement("set", movie->set());
  64. xml.writeTextElement("sorttitle", movie->sortTitle());
  65. xml.writeTextElement("trailer", Helper::formatTrailerUrl(movie->trailer().toString()));
  66. xml.writeTextElement("watched", (movie->watched()) ? "true" : "false");
  67. foreach (const QString &studio, movie->studios())
  68. xml.writeTextElement("studio", studio);
  69. foreach (const QString &genre, movie->genres())
  70. xml.writeTextElement("genre", genre);
  71. foreach (const QString &country, movie->countries())
  72. xml.writeTextElement("country", country);
  73. foreach (const QString &tag, movie->tags())
  74. xml.writeTextElement("tag", tag);
  75. foreach (const Actor &actor, movie->actors()) {
  76. xml.writeStartElement("actor");
  77. xml.writeTextElement("name", actor.name);
  78. xml.writeTextElement("role", actor.role);
  79. xml.writeTextElement("thumb", actor.thumb);
  80. xml.writeEndElement();
  81. }
  82. foreach (const Poster &poster, movie->posters()) {
  83. xml.writeStartElement("thumb");
  84. xml.writeAttribute("preview", poster.thumbUrl.toString());
  85. xml.writeCharacters(poster.originalUrl.toString());
  86. xml.writeEndElement();
  87. }
  88. xml.writeStartElement("fanart");
  89. foreach (const Poster &poster, movie->backdrops()) {
  90. xml.writeStartElement("thumb");
  91. xml.writeAttribute("preview", poster.thumbUrl.toString());
  92. xml.writeCharacters(poster.originalUrl.toString());
  93. xml.writeEndElement();
  94. }
  95. xml.writeEndElement();
  96. xml.writeStartElement("fileinfo");
  97. writeStreamDetails(xml, movie->streamDetails());
  98. xml.writeEndElement();
  99. xml.writeEndElement();
  100. }
  101. /**
  102. * @brief Saves a movie (including images)
  103. * @param movie Movie to save
  104. * @return Saving success
  105. * @see XbmcXml::writeMovieXml
  106. */
  107. bool XbmcXml::saveMovie(Movie *movie)
  108. {
  109. qDebug() << "Entered, movie=" << movie->name();
  110. QByteArray xmlContent;
  111. QXmlStreamWriter xml(&xmlContent);
  112. xml.setAutoFormatting(true);
  113. xml.writeStartDocument("1.0", true);
  114. writeMovieXml(xml, movie);
  115. xml.writeEndDocument();
  116. if (movie->files().size() == 0) {
  117. qWarning() << "Movie has no files";
  118. return false;
  119. }
  120. movie->setNfoContent(xmlContent);
  121. Manager::instance()->database()->update(movie);
  122. bool saved = false;
  123. QFileInfo fi(movie->files().at(0));
  124. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::MovieNfo)) {
  125. QString saveFileName = dataFile.saveFileName(fi.fileName());
  126. QFile file(fi.absolutePath() + QDir::separator() + saveFileName);
  127. qDebug() << "Saving to" << file.fileName();
  128. if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
  129. qWarning() << "File could not be openend";
  130. } else {
  131. file.write(xmlContent);
  132. file.close();
  133. saved = true;
  134. }
  135. }
  136. if (!saved)
  137. return false;
  138. if (movie->posterImageChanged() && !movie->posterImage()->isNull()) {
  139. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::MoviePoster)) {
  140. QString saveFileName = dataFile.saveFileName(fi.fileName(), -1, movie->files().count() > 1);
  141. qDebug() << "Saving poster to" << fi.absolutePath() + QDir::separator() + saveFileName;
  142. movie->posterImage()->save(fi.absolutePath() + QDir::separator() + saveFileName, "jpg", 100);
  143. }
  144. }
  145. if (movie->backdropImageChanged() && !movie->backdropImage()->isNull()) {
  146. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::MovieBackdrop)) {
  147. QString saveFileName = dataFile.saveFileName(fi.fileName(), -1, movie->files().count() > 1);
  148. qDebug() << "Saving fanart to" << fi.absolutePath() + QDir::separator() + saveFileName;
  149. movie->backdropImage()->save(fi.absolutePath() + QDir::separator() + saveFileName, "jpg", 100);
  150. }
  151. }
  152. saveAdditionalImages(movie);
  153. foreach (const Actor &actor, movie->actors()) {
  154. if (!actor.image.isNull()) {
  155. QDir dir;
  156. dir.mkdir(fi.absolutePath() + QDir::separator() + ".actors");
  157. QString actorName = actor.name;
  158. actorName = actorName.replace(" ", "_");
  159. actor.image.save(fi.absolutePath() + QDir::separator() + ".actors" + QDir::separator() + actorName + ".tbn", "jpg", 100);
  160. }
  161. }
  162. return true;
  163. }
  164. /**
  165. * @brief Saves additional movie images (logo, clear art, cd art)
  166. * @param movie Movie object
  167. */
  168. void XbmcXml::saveAdditionalImages(Movie *movie)
  169. {
  170. QFileInfo fi(movie->files().at(0));
  171. if (movie->logoImageChanged() && !movie->logoImage()->isNull()) {
  172. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::MovieLogo)) {
  173. QString saveFileName = dataFile.saveFileName(fi.fileName());
  174. qDebug() << "Saving logo to" << fi.absolutePath() + QDir::separator() + saveFileName;
  175. movie->logoImage()->save(fi.absolutePath() + QDir::separator() + saveFileName, "png", 100);
  176. }
  177. }
  178. if (movie->clearArtImageChanged() && !movie->clearArtImage()->isNull()) {
  179. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::MovieClearArt)) {
  180. QString saveFileName = dataFile.saveFileName(fi.fileName());
  181. qDebug() << "Saving clear art to" << fi.absolutePath() + QDir::separator() + saveFileName;
  182. movie->clearArtImage()->save(fi.absolutePath() + QDir::separator() + saveFileName, "png", 100);
  183. }
  184. }
  185. if (movie->cdArtImageChanged() && !movie->cdArtImage()->isNull()) {
  186. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::MovieCdArt)) {
  187. QString saveFileName = dataFile.saveFileName(fi.fileName());
  188. qDebug() << "Saving cd art to" << fi.absolutePath() + QDir::separator() + saveFileName;
  189. movie->cdArtImage()->save(fi.absolutePath() + QDir::separator() + saveFileName, "png", 100);
  190. }
  191. }
  192. if (movie->inSeparateFolder() && !movie->files().isEmpty()) {
  193. foreach (const QString &file, movie->extraFanartsToRemove())
  194. QFile::remove(file);
  195. QDir dir(QFileInfo(movie->files().first()).absolutePath() + "/extrafanart");
  196. if (!dir.exists() && !movie->extraFanartImagesToAdd().isEmpty())
  197. QDir(QFileInfo(movie->files().first()).absolutePath()).mkdir("extrafanart");
  198. foreach (QImage img, movie->extraFanartImagesToAdd()) {
  199. int num = 1;
  200. while (QFileInfo(dir.absolutePath() + "/" + QString("fanart%1.jpg").arg(num)).exists())
  201. ++num;
  202. img.save(dir.absolutePath() + "/" + QString("fanart%1.jpg").arg(num), "jpg", 100);
  203. }
  204. }
  205. }
  206. /**
  207. * @brief Tries to find an nfo file for the movie
  208. * @param movie Movie
  209. * @return Path to nfo file, if none found returns an empty string
  210. */
  211. QString XbmcXml::nfoFilePath(Movie *movie)
  212. {
  213. QString nfoFile;
  214. if (movie->files().size() == 0) {
  215. qWarning() << "Movie has no files";
  216. return nfoFile;
  217. }
  218. QFileInfo fi(movie->files().at(0));
  219. if (!fi.isFile() ) {
  220. qWarning() << "First file of the movie is not readable" << movie->files().at(0);
  221. return nfoFile;
  222. }
  223. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::MovieNfo)) {
  224. QString file = dataFile.saveFileName(fi.fileName());
  225. QFileInfo nfoFi(fi.absolutePath() + QDir::separator() + file);
  226. if (nfoFi.exists()) {
  227. nfoFile = fi.absolutePath() + QDir::separator() + file;
  228. break;
  229. }
  230. }
  231. return nfoFile;
  232. }
  233. QString XbmcXml::nfoFilePath(TvShowEpisode *episode)
  234. {
  235. QString nfoFile;
  236. if (episode->files().size() == 0) {
  237. qWarning() << "Episode has no files";
  238. return nfoFile;
  239. }
  240. QFileInfo fi(episode->files().at(0));
  241. if (!fi.isFile() ) {
  242. qWarning() << "First file of the episode is not readable" << episode->files().at(0);
  243. return nfoFile;
  244. }
  245. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::TvShowEpisodeNfo)) {
  246. QString file = dataFile.saveFileName(fi.fileName());
  247. QFileInfo nfoFi(fi.absolutePath() + QDir::separator() + file);
  248. if (nfoFi.exists()) {
  249. nfoFile = fi.absolutePath() + QDir::separator() + file;
  250. break;
  251. }
  252. }
  253. return nfoFile;
  254. }
  255. /**
  256. * @brief Tries to find an nfo file for the concert
  257. * @param concert Concert
  258. * @return Path to nfo file, if none found returns an empty string
  259. */
  260. QString XbmcXml::nfoFilePath(Concert *concert)
  261. {
  262. QString nfoFile;
  263. if (concert->files().size() == 0) {
  264. qWarning() << "Concert has no files";
  265. return nfoFile;
  266. }
  267. QFileInfo fi(concert->files().at(0));
  268. if (!fi.isFile() ) {
  269. qWarning() << "First file of the concert is not readable" << concert->files().at(0);
  270. return nfoFile;
  271. }
  272. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::ConcertNfo)) {
  273. QString file = dataFile.saveFileName(fi.fileName());
  274. QFileInfo nfoFi(fi.absolutePath() + QDir::separator() + file);
  275. if (nfoFi.exists()) {
  276. nfoFile = fi.absolutePath() + QDir::separator() + file;
  277. break;
  278. }
  279. }
  280. return nfoFile;
  281. }
  282. /**
  283. * @brief Loads movie infos (except images)
  284. * @param movie Movie to load
  285. * @return Loading success
  286. */
  287. bool XbmcXml::loadMovie(Movie *movie, QString initialNfoContent)
  288. {
  289. movie->clear();
  290. movie->setChanged(false);
  291. QString nfoContent;
  292. if (initialNfoContent.isEmpty()) {
  293. QString nfoFile = nfoFilePath(movie);
  294. if (nfoFile.isEmpty())
  295. return false;
  296. QFile file(nfoFile);
  297. if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
  298. qWarning() << "File" << nfoFile << "could not be opened for reading";
  299. return false;
  300. }
  301. nfoContent = QString::fromUtf8(file.readAll());
  302. movie->setNfoContent(nfoContent);
  303. file.close();
  304. } else {
  305. nfoContent = initialNfoContent;
  306. }
  307. QDomDocument domDoc;
  308. domDoc.setContent(nfoContent);
  309. if (!domDoc.elementsByTagName("title").isEmpty() )
  310. movie->setName(domDoc.elementsByTagName("title").at(0).toElement().text());
  311. if (!domDoc.elementsByTagName("originaltitle").isEmpty())
  312. movie->setOriginalName(domDoc.elementsByTagName("originaltitle").at(0).toElement().text());
  313. if (!domDoc.elementsByTagName("rating").isEmpty())
  314. movie->setRating(domDoc.elementsByTagName("rating").at(0).toElement().text().toFloat());
  315. if (!domDoc.elementsByTagName("votes").isEmpty())
  316. movie->setVotes(domDoc.elementsByTagName("votes").at(0).toElement().text().toInt());
  317. if (!domDoc.elementsByTagName("top250").isEmpty())
  318. movie->setTop250(domDoc.elementsByTagName("top250").at(0).toElement().text().toInt());
  319. if (!domDoc.elementsByTagName("year").isEmpty())
  320. movie->setReleased(QDate::fromString(domDoc.elementsByTagName("year").at(0).toElement().text(), "yyyy"));
  321. if (!domDoc.elementsByTagName("plot").isEmpty())
  322. movie->setOverview(domDoc.elementsByTagName("plot").at(0).toElement().text());
  323. if (!domDoc.elementsByTagName("outline").isEmpty())
  324. movie->setOutline(domDoc.elementsByTagName("outline").at(0).toElement().text());
  325. if (!domDoc.elementsByTagName("tagline").isEmpty())
  326. movie->setTagline(domDoc.elementsByTagName("tagline").at(0).toElement().text());
  327. if (!domDoc.elementsByTagName("runtime").isEmpty())
  328. movie->setRuntime(domDoc.elementsByTagName("runtime").at(0).toElement().text().toInt());
  329. if (!domDoc.elementsByTagName("mpaa").isEmpty())
  330. movie->setCertification(domDoc.elementsByTagName("mpaa").at(0).toElement().text());
  331. if (!domDoc.elementsByTagName("credits").isEmpty())
  332. movie->setWriter(domDoc.elementsByTagName("credits").at(0).toElement().text());
  333. if (!domDoc.elementsByTagName("director").isEmpty())
  334. movie->setDirector(domDoc.elementsByTagName("director").at(0).toElement().text());
  335. if (!domDoc.elementsByTagName("playcount").isEmpty())
  336. movie->setPlayCount(domDoc.elementsByTagName("playcount").at(0).toElement().text().toInt());
  337. if (!domDoc.elementsByTagName("lastplayed").isEmpty())
  338. movie->setLastPlayed(QDateTime::fromString(domDoc.elementsByTagName("lastplayed").at(0).toElement().text(), "yyyy-MM-dd HH:mm:ss"));
  339. if (!domDoc.elementsByTagName("id").isEmpty())
  340. movie->setId(domDoc.elementsByTagName("id").at(0).toElement().text());
  341. if (!domDoc.elementsByTagName("tmdbid").isEmpty())
  342. movie->setTmdbId(domDoc.elementsByTagName("tmdbid").at(0).toElement().text());
  343. if (!domDoc.elementsByTagName("set").isEmpty())
  344. movie->setSet(domDoc.elementsByTagName("set").at(0).toElement().text());
  345. if (!domDoc.elementsByTagName("sorttitle").isEmpty())
  346. movie->setSortTitle(domDoc.elementsByTagName("sorttitle").at(0).toElement().text());
  347. if (!domDoc.elementsByTagName("trailer").isEmpty())
  348. movie->setTrailer(QUrl(domDoc.elementsByTagName("trailer").at(0).toElement().text()));
  349. if (!domDoc.elementsByTagName("watched").isEmpty())
  350. movie->setWatched(domDoc.elementsByTagName("watched").at(0).toElement().text() == "true" ? true : false);
  351. for (int i=0, n=domDoc.elementsByTagName("studio").size() ; i<n ; i++)
  352. movie->addStudio(domDoc.elementsByTagName("studio").at(i).toElement().text());
  353. for (int i=0, n=domDoc.elementsByTagName("genre").size() ; i<n ; i++)
  354. movie->addGenre(domDoc.elementsByTagName("genre").at(i).toElement().text());
  355. for (int i=0, n=domDoc.elementsByTagName("country").size() ; i<n ; i++)
  356. movie->addCountry(domDoc.elementsByTagName("country").at(i).toElement().text());
  357. for (int i=0, n=domDoc.elementsByTagName("tag").size() ; i<n ; i++)
  358. movie->addTag(domDoc.elementsByTagName("tag").at(i).toElement().text());
  359. for (int i=0, n=domDoc.elementsByTagName("actor").size() ; i<n ; i++) {
  360. Actor a;
  361. a.imageHasChanged = false;
  362. if (!domDoc.elementsByTagName("actor").at(i).toElement().elementsByTagName("name").isEmpty())
  363. a.name = domDoc.elementsByTagName("actor").at(i).toElement().elementsByTagName("name").at(0).toElement().text();
  364. if (!domDoc.elementsByTagName("actor").at(i).toElement().elementsByTagName("role").isEmpty())
  365. a.role = domDoc.elementsByTagName("actor").at(i).toElement().elementsByTagName("role").at(0).toElement().text();
  366. if (!domDoc.elementsByTagName("actor").at(i).toElement().elementsByTagName("thumb").isEmpty())
  367. a.thumb = domDoc.elementsByTagName("actor").at(i).toElement().elementsByTagName("thumb").at(0).toElement().text();
  368. movie->addActor(a);
  369. }
  370. for (int i=0, n=domDoc.elementsByTagName("thumb").size() ; i<n ; i++) {
  371. QString parentTag = domDoc.elementsByTagName("thumb").at(i).parentNode().toElement().tagName();
  372. if (parentTag == "movie") {
  373. Poster p;
  374. p.originalUrl = QUrl(domDoc.elementsByTagName("thumb").at(i).toElement().text());
  375. p.thumbUrl = QUrl(domDoc.elementsByTagName("thumb").at(i).toElement().attribute("preview"));
  376. movie->addPoster(p);
  377. } else if (parentTag == "fanart") {
  378. Poster p;
  379. p.originalUrl = QUrl(domDoc.elementsByTagName("thumb").at(i).toElement().text());
  380. p.thumbUrl = QUrl(domDoc.elementsByTagName("thumb").at(i).toElement().attribute("preview"));
  381. movie->addBackdrop(p);
  382. }
  383. }
  384. movie->setStreamDetailsLoaded(loadStreamDetails(movie->streamDetails(), domDoc));
  385. // Existence of images
  386. if (initialNfoContent.isEmpty()) {
  387. movie->setHasPoster(!posterImageName(movie).isEmpty());
  388. movie->setHasBackdrop(!backdropImageName(movie).isEmpty());
  389. movie->setHasLogo(!logoImageName(movie).isEmpty());
  390. movie->setHasClearArt(!clearArtImageName(movie).isEmpty());
  391. movie->setHasCdArt(!cdArtImageName(movie).isEmpty());
  392. }
  393. return true;
  394. }
  395. /**
  396. * @brief Loads the stream details from the dom document
  397. * @param streamDetails StreamDetails object
  398. * @param domDoc Nfo document
  399. * @return Infos loaded
  400. */
  401. bool XbmcXml::loadStreamDetails(StreamDetails* streamDetails, QDomDocument domDoc)
  402. {
  403. streamDetails->clear();
  404. if (!domDoc.elementsByTagName("streamdetails").isEmpty()) {
  405. QDomElement elem = domDoc.elementsByTagName("streamdetails").at(0).toElement();
  406. if (!elem.elementsByTagName("video").isEmpty()) {
  407. QDomElement videoElem = elem.elementsByTagName("video").at(0).toElement();
  408. QStringList details = (QStringList() << "codec" << "aspect" << "width" << "height" << "durationinseconds" << "scantype");
  409. foreach (const QString &detail, details) {
  410. if (!videoElem.elementsByTagName(detail).isEmpty())
  411. streamDetails->setVideoDetail(detail, videoElem.elementsByTagName(detail).at(0).toElement().text());
  412. }
  413. }
  414. if (!elem.elementsByTagName("audio").isEmpty()) {
  415. for (int i=0, n=elem.elementsByTagName("audio").count() ; i<n ; ++i) {
  416. QStringList details = QStringList() << "codec" << "language" << "channels";
  417. QDomElement audioElem = elem.elementsByTagName("audio").at(i).toElement();
  418. foreach (const QString &detail, details) {
  419. if (!audioElem.elementsByTagName(detail).isEmpty())
  420. streamDetails->setAudioDetail(i, detail, audioElem.elementsByTagName(detail).at(0).toElement().text());
  421. }
  422. }
  423. }
  424. if (!elem.elementsByTagName("subtitle").isEmpty()) {
  425. for (int i=0, n=elem.elementsByTagName("subtitle").count() ; i<n ; ++i) {
  426. QStringList details = QStringList() << "language";
  427. QDomElement subtitleElem = elem.elementsByTagName("subtitle").at(i).toElement();
  428. foreach (const QString &detail, details) {
  429. if (!subtitleElem.elementsByTagName(detail).isEmpty())
  430. streamDetails->setSubtitleDetail(i, detail, subtitleElem.elementsByTagName(detail).at(0).toElement().text());
  431. }
  432. }
  433. }
  434. return true;
  435. }
  436. return false;
  437. }
  438. /**
  439. * @brief Writes streamdetails to xml stream
  440. * @param xml XML Stream
  441. * @param streamDetails Stream Details object
  442. */
  443. void XbmcXml::writeStreamDetails(QXmlStreamWriter &xml, StreamDetails *streamDetails)
  444. {
  445. xml.writeStartElement("streamdetails");
  446. xml.writeStartElement("video");
  447. QMapIterator<QString, QString> itVideo(streamDetails->videoDetails());
  448. while (itVideo.hasNext()) {
  449. itVideo.next();
  450. if (itVideo.key() == "width" && itVideo.value().toInt() == 0)
  451. continue;
  452. if (itVideo.key() == "height" && itVideo.value().toInt() == 0)
  453. continue;
  454. if (itVideo.key() == "durationinseconds" && itVideo.value().toInt() == 0)
  455. continue;
  456. if (itVideo.value() == "")
  457. continue;
  458. xml.writeTextElement(itVideo.key(), itVideo.value());
  459. }
  460. xml.writeEndElement();
  461. for (int i=0, n=streamDetails->audioDetails().count() ; i<n ; ++i) {
  462. xml.writeStartElement("audio");
  463. QMapIterator<QString, QString> itAudio(streamDetails->audioDetails().at(i));
  464. while (itAudio.hasNext()) {
  465. itAudio.next();
  466. if (itAudio.value() == "")
  467. continue;
  468. xml.writeTextElement(itAudio.key(), itAudio.value());
  469. }
  470. xml.writeEndElement();
  471. }
  472. for (int i=0, n=streamDetails->subtitleDetails().count() ; i<n ; ++i) {
  473. xml.writeStartElement("subtitle");
  474. QMapIterator<QString, QString> itSubtitle(streamDetails->subtitleDetails().at(i));
  475. while (itSubtitle.hasNext()) {
  476. itSubtitle.next();
  477. if (itSubtitle.value() == "")
  478. continue;
  479. xml.writeTextElement(itSubtitle.key(), itSubtitle.value());
  480. }
  481. xml.writeEndElement();
  482. }
  483. xml.writeEndElement();
  484. }
  485. /**
  486. * @brief Get the path to the actor image
  487. * @param movie
  488. * @param actor Actor
  489. * @return Path to actor image
  490. */
  491. QString XbmcXml::actorImageName(Movie *movie, Actor actor)
  492. {
  493. if (movie->files().isEmpty())
  494. return QString();
  495. QFileInfo fi(movie->files().at(0));
  496. QString actorName = actor.name;
  497. actorName = actorName.replace(" ", "_");
  498. QString path = fi.absolutePath() + QDir::separator() + ".actors" + QDir::separator() + actorName + ".tbn";
  499. fi.setFile(path);
  500. if (fi.isFile())
  501. return path;
  502. return QString();
  503. }
  504. /**
  505. * @brief Get the path to the movie poster
  506. * @param movie Movie object
  507. * @return Path to poster image
  508. */
  509. QString XbmcXml::posterImageName(Movie *movie, QList<DataFile> dataFiles, bool constructName)
  510. {
  511. QString posterFileName;
  512. if (movie->files().size() == 0) {
  513. qWarning() << "Movie has no files";
  514. return posterFileName;
  515. }
  516. QFileInfo fi(movie->files().at(0));
  517. if (!constructName)
  518. dataFiles = Settings::instance()->dataFiles(DataFileType::MoviePoster);
  519. foreach (DataFile dataFile, dataFiles) {
  520. QString file = dataFile.saveFileName(fi.fileName(), -1, movie->files().count() > 1);
  521. QFileInfo pFi(fi.absolutePath() + QDir::separator() + file);
  522. if (pFi.isFile() || constructName) {
  523. posterFileName = fi.absolutePath() + QDir::separator() + file;
  524. break;
  525. }
  526. }
  527. return posterFileName;
  528. }
  529. /**
  530. * @brief Get the path to the movie backdrop
  531. * @param movie Movie object
  532. * @return Path to backdrop image
  533. */
  534. QString XbmcXml::backdropImageName(Movie *movie, QList<DataFile> dataFiles, bool constructName)
  535. {
  536. QString fanartFileName;
  537. if (movie->files().size() == 0) {
  538. qWarning() << "Movie has no files";
  539. return fanartFileName;
  540. }
  541. QFileInfo fi(movie->files().at(0));
  542. if (!constructName)
  543. dataFiles = Settings::instance()->dataFiles(DataFileType::MovieBackdrop);
  544. foreach (DataFile dataFile, dataFiles) {
  545. QString file = dataFile.saveFileName(fi.fileName(), -1, movie->files().count() > 1);
  546. QFileInfo bFi(fi.absolutePath() + QDir::separator() + file);
  547. if (bFi.isFile() || constructName) {
  548. fanartFileName = fi.absolutePath() + QDir::separator() + file;
  549. break;
  550. }
  551. }
  552. return fanartFileName;
  553. }
  554. /**
  555. * @brief Get the path to the movie logo
  556. * @param movie Movie object
  557. * @return Path to logo image
  558. */
  559. QString XbmcXml::logoImageName(Movie *movie, QList<DataFile> dataFiles, bool constructName)
  560. {
  561. QString logoFileName;
  562. if (movie->files().size() == 0) {
  563. qWarning() << "Movie has no files";
  564. return logoFileName;
  565. }
  566. QFileInfo fi(movie->files().at(0));
  567. if (!constructName)
  568. dataFiles = Settings::instance()->dataFiles(DataFileType::MovieLogo);
  569. foreach (DataFile dataFile, dataFiles) {
  570. QString file = dataFile.saveFileName(fi.fileName());
  571. QFileInfo bFi(fi.absolutePath() + QDir::separator() + file);
  572. if (bFi.isFile() || constructName) {
  573. logoFileName = fi.absolutePath() + QDir::separator() + file;
  574. break;
  575. }
  576. }
  577. return logoFileName;
  578. }
  579. /**
  580. * @brief Get the path to the movie clear art
  581. * @param movie Movie object
  582. * @return Path to clear art image
  583. */
  584. QString XbmcXml::clearArtImageName(Movie *movie, QList<DataFile> dataFiles, bool constructName)
  585. {
  586. QString clearArtFileName;
  587. if (movie->files().size() == 0) {
  588. qWarning() << "Movie has no files";
  589. return clearArtFileName;
  590. }
  591. QFileInfo fi(movie->files().at(0));
  592. if (!constructName)
  593. dataFiles = Settings::instance()->dataFiles(DataFileType::MovieClearArt);
  594. foreach (DataFile dataFile, dataFiles) {
  595. QString file = dataFile.saveFileName(fi.fileName());
  596. QFileInfo bFi(fi.absolutePath() + QDir::separator() + file);
  597. if (bFi.isFile() || constructName) {
  598. clearArtFileName = fi.absolutePath() + QDir::separator() + file;
  599. break;
  600. }
  601. }
  602. return clearArtFileName;
  603. }
  604. /**
  605. * @brief Get the path to the movie cd art
  606. * @param movie Movie object
  607. * @return Path to cd art image
  608. */
  609. QString XbmcXml::cdArtImageName(Movie *movie, QList<DataFile> dataFiles, bool constructName)
  610. {
  611. QString cdArtFileName;
  612. if (movie->files().size() == 0) {
  613. qWarning() << "Movie has no files";
  614. return cdArtFileName;
  615. }
  616. QFileInfo fi(movie->files().at(0));
  617. if (!constructName)
  618. dataFiles = Settings::instance()->dataFiles(DataFileType::MovieCdArt);
  619. foreach (DataFile dataFile, dataFiles) {
  620. QString file = dataFile.saveFileName(fi.fileName());
  621. QFileInfo bFi(fi.absolutePath() + QDir::separator() + file);
  622. if (bFi.isFile() || constructName) {
  623. cdArtFileName = fi.absolutePath() + QDir::separator() + file;
  624. break;
  625. }
  626. }
  627. return cdArtFileName;
  628. }
  629. /**
  630. * @brief Writes concert elements to an xml stream
  631. * @param xml XML stream
  632. * @param concert Concert to save
  633. */
  634. void XbmcXml::writeConcertXml(QXmlStreamWriter &xml, Concert *concert)
  635. {
  636. qDebug() << "Entered, concert=" << concert->name();
  637. xml.writeStartElement("musicvideo");
  638. xml.writeTextElement("title", concert->name());
  639. xml.writeTextElement("artist", concert->artist());
  640. xml.writeTextElement("album", concert->album());
  641. xml.writeTextElement("id", concert->id());
  642. xml.writeTextElement("tmdbid", concert->tmdbId());
  643. xml.writeTextElement("rating", QString("%1").arg(concert->rating()));
  644. xml.writeTextElement("year", concert->released().toString("yyyy"));
  645. xml.writeTextElement("plot", concert->overview());
  646. xml.writeTextElement("outline", concert->overview());
  647. xml.writeTextElement("tagline", concert->tagline());
  648. if (concert->runtime() > 0)
  649. xml.writeTextElement("runtime", QString("%1").arg(concert->runtime()));
  650. xml.writeTextElement("mpaa", concert->certification());
  651. xml.writeTextElement("playcount", QString("%1").arg(concert->playcount()));
  652. xml.writeTextElement("lastplayed", concert->lastPlayed().toString("yyyy-MM-dd HH:mm:ss"));
  653. xml.writeTextElement("trailer", Helper::formatTrailerUrl(concert->trailer().toString()));
  654. xml.writeTextElement("watched", (concert->watched()) ? "true" : "false");
  655. foreach (const QString &genre, concert->genres())
  656. xml.writeTextElement("genre", genre);
  657. foreach (const QString &tag, concert->tags())
  658. xml.writeTextElement("tag", tag);
  659. foreach (const Poster &poster, concert->posters()) {
  660. xml.writeStartElement("thumb");
  661. xml.writeAttribute("preview", poster.thumbUrl.toString());
  662. xml.writeCharacters(poster.originalUrl.toString());
  663. xml.writeEndElement();
  664. }
  665. xml.writeStartElement("fanart");
  666. foreach (const Poster &poster, concert->backdrops()) {
  667. xml.writeStartElement("thumb");
  668. xml.writeAttribute("preview", poster.thumbUrl.toString());
  669. xml.writeCharacters(poster.originalUrl.toString());
  670. xml.writeEndElement();
  671. }
  672. xml.writeEndElement();
  673. xml.writeStartElement("fileinfo");
  674. writeStreamDetails(xml, concert->streamDetails());
  675. xml.writeEndElement();
  676. xml.writeEndElement();
  677. }
  678. /**
  679. * @brief Saves a concert (including images)
  680. * @param concert Concert to save
  681. * @return Saving success
  682. * @see XbmcXml::writeConcertXml
  683. */
  684. bool XbmcXml::saveConcert(Concert *concert)
  685. {
  686. qDebug() << "Entered, movie=" << concert->name();
  687. QByteArray xmlContent;
  688. QXmlStreamWriter xml(&xmlContent);
  689. xml.setAutoFormatting(true);
  690. xml.writeStartDocument("1.0", true);
  691. writeConcertXml(xml, concert);
  692. xml.writeEndDocument();
  693. if (concert->files().size() == 0) {
  694. qWarning() << "Movie has no files";
  695. return false;
  696. }
  697. concert->setNfoContent(xmlContent);
  698. Manager::instance()->database()->update(concert);
  699. bool saved = false;
  700. QFileInfo fi(concert->files().at(0));
  701. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::ConcertNfo)) {
  702. QString saveFileName = dataFile.saveFileName(fi.fileName());
  703. QFile file(fi.absolutePath() + QDir::separator() + saveFileName);
  704. qDebug() << "Saving to" << file.fileName();
  705. if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
  706. qWarning() << "File could not be openend";
  707. } else {
  708. file.write(xmlContent);
  709. file.close();
  710. saved = true;
  711. }
  712. }
  713. if (!saved)
  714. return false;
  715. if (concert->posterImageChanged() && !concert->posterImage()->isNull()) {
  716. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::ConcertPoster)) {
  717. QString saveFileName = dataFile.saveFileName(fi.fileName());
  718. qDebug() << "Saving poster to" << fi.absolutePath() + QDir::separator() + saveFileName;
  719. concert->posterImage()->save(fi.absolutePath() + QDir::separator() + saveFileName, "jpg", 100);
  720. }
  721. }
  722. if (concert->backdropImageChanged() && !concert->backdropImage()->isNull()) {
  723. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::ConcertBackdrop)) {
  724. QString saveFileName = dataFile.saveFileName(fi.fileName());
  725. qDebug() << "Saving fanart to" << fi.absolutePath() + QDir::separator() + saveFileName;
  726. concert->backdropImage()->save(fi.absolutePath() + QDir::separator() + saveFileName, "jpg", 100);
  727. }
  728. }
  729. saveAdditionalImages(concert);
  730. return true;
  731. }
  732. /**
  733. * @brief Saves additional concert images (logo, clear art, cd art)
  734. * @param concert Concert object
  735. */
  736. void XbmcXml::saveAdditionalImages(Concert *concert)
  737. {
  738. QFileInfo fi(concert->files().at(0));
  739. if (concert->logoImageChanged() && !concert->logoImage()->isNull()) {
  740. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::ConcertLogo)) {
  741. QString saveFileName = dataFile.saveFileName(fi.fileName());
  742. qDebug() << "Saving logo to" << fi.absolutePath() + QDir::separator() + saveFileName;
  743. concert->logoImage()->save(fi.absolutePath() + QDir::separator() + saveFileName, "png", 100);
  744. }
  745. }
  746. if (concert->clearArtImageChanged() && !concert->clearArtImage()->isNull()) {
  747. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::ConcertClearArt)) {
  748. QString saveFileName = dataFile.saveFileName(fi.fileName());
  749. qDebug() << "Saving clear art to" << fi.absolutePath() + QDir::separator() + saveFileName;
  750. concert->clearArtImage()->save(fi.absolutePath() + QDir::separator() + saveFileName, "png", 100);
  751. }
  752. }
  753. if (concert->cdArtImageChanged() && !concert->cdArtImage()->isNull()) {
  754. foreach (DataFile dataFile, Settings::instance()->dataFiles(DataFileType::ConcertCdArt)) {
  755. QString saveFileName = dataFile.saveFileName(fi.fileName());
  756. qDebug() << "Saving cd art to" << fi.absolutePath() + QDir::separator() + saveFileName;
  757. concert->cdArtImage()->save(fi.absolutePath() + QDir::separator() + saveFileName, "png", 100);
  758. }
  759. }
  760. if (concert->inSeparateFolder() && !concert->files().isEmpty()) {
  761. foreach (const QString &file, concert->extraFanartsToRemove())
  762. QFile::remove(file);
  763. QDir dir(QFileInfo(concert->files().first()).absolutePath() + "/extrafanart");
  764. if (!dir.exists() && !concert->extraFanartImagesToAdd().isEmpty())
  765. QDir(QFileInfo(concert->files().first()).absolutePath()).mkdir("extrafanart");
  766. foreach (QImage img, concert->extraFanartImagesToAdd()) {
  767. int num = 1;
  768. while (QFileInfo(dir.absolutePath() + "/" + QString("fanart%1.jpg").arg(num)).exists())
  769. ++num;
  770. img.save(dir.absolutePath() + "/" + QString("fanart%1.jpg").arg(num), "jpg", 100);
  771. }
  772. }
  773. }
  774. /**
  775. * @brief Loads concert infos (except images)
  776. * @param concert Concert to load
  777. * @return Loading success
  778. */
  779. bool XbmcXml::loadConcert(Concert *concert, QString initialNfoContent)
  780. {
  781. concert->clear();
  782. concert->setChanged(false);
  783. QString nfoContent;
  784. if (initialNfoContent.isEmpty()) {
  785. QString nfoFile = nfoFilePath(concert);
  786. if (nfoFile.isEmpty())
  787. return false;
  788. QFile file(nfoFile);
  789. if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
  790. qWarning() << "File" << nfoFile << "could not be opened for reading";
  791. return false;
  792. }
  793. nfoContent = QString::fromUtf8(file.readAll());
  794. concert->setNfoContent(nfoContent);
  795. file.close();
  796. } else {
  797. nfoContent = initialNfoContent;
  798. }
  799. QDomDocument domDoc;
  800. domDoc.setContent(nfoContent);
  801. if (!domDoc.elementsByTagName("id").isEmpty() )
  802. concert->setId(domDoc.elementsByTagName("id").at(0).toElement().text());
  803. if (!domDoc.elementsByTagName("tmdbid").isEmpty() )
  804. concert->setTmdbId(domDoc.elementsByTagName("tmdbid").at(0).toElement().text());
  805. if (!domDoc.elementsByTagName("title").isEmpty() )
  806. concert->setName(domDoc.elementsByTagName("title").at(0).toElement().text());
  807. if (!domDoc.elementsByTagName("artist").isEmpty() )
  808. concert->setArtist(domDoc.elementsByTagName("artist").at(0).toElement().text());
  809. if (!domDoc.elementsByTagName("album").isEmpty() )
  810. concert->setAlbum(domDoc.elementsByTagName("album").at(0).toElement().text());
  811. if (!domDoc.elementsByTagName("rating").isEmpty())
  812. concert->setRating(domDoc.elementsByTagName("rating").at(0).toElement().text().toFloat());
  813. if (!domDoc.elementsByTagName("year").isEmpty())
  814. concert->setReleased(QDate::fromString(domDoc.elementsByTagName("year").at(0).toElement().text(), "yyyy"));
  815. if (!domDoc.elementsByTagName("plot").isEmpty())
  816. concert->setOverview(domDoc.elementsByTagName("plot").at(0).toElement().text());
  817. if (!domDoc.elementsByTagName("tagline").isEmpty())
  818. concert->setTagline(domDoc.elementsByTagName("tagline").at(0).toElement().text());
  819. if (!domDoc.elementsByTagName("runtime").isEmpty())
  820. concert->setRuntime(domDoc.elementsByTagName("runtime").at(0).toElement().text().toInt());
  821. if (!domDoc.elementsByTagName("mpaa").isEmpty())
  822. concert->setCertification(domDoc.elementsByTagName("mpaa").at(0).toElement().text());
  823. if (!domDoc.elementsByTagName("playcount").isEmpty())
  824. concert->setPlayCount(domDoc.elementsByTagName("playcount").at(0).toElement().text().toInt());
  825. if (!domDoc.elementsByTagName("lastplayed").isEmpty())
  826. concert->setLastPlayed(QDateTime::fromString(domDoc.elementsByTagName("lastplayed").at(0).toElement().text(), "yyyy-MM-dd HH:mm:ss"));
  827. if (!domDoc.elementsByTagName("trailer").isEmpty())
  828. concert->setTrailer(QUrl(domDoc.elementsByTagName("trailer").at(0).toElement().text()));
  829. if (!domDoc.elementsByTagName("watched").isEmpty())
  830. concert->setWatched(domDoc.elementsByTagName("watched").at(0).toElement().text() == "true" ? true : false);
  831. for (int i=0, n=domDoc.elementsByTagName("genre").size() ; i<n ; i++)
  832. concert->addGenre(domDoc.elementsByTagName("genre").at(i).toElement().text());
  833. for (int i=0, n=domDoc.elementsByTagName("tag").size() ; i<n ; i++)
  834. concert->addTag(domDoc.elementsByTagName("tag").at(i).toElement().text());
  835. for (int i=0, n=domDoc.elementsByTagName("thumb").size() ; i<n ; i++) {
  836. QString parentTag = domDoc.elementsByTagName("thumb").at(i).parentNode().toElement().tagName();
  837. if (parentTag == "movie") {
  838. Poster p;
  839. p.originalUrl = QUrl(domDoc.elementsByTagName("thumb").at(i).toElement().text());
  840. p.thumbUrl = QUrl(domDoc.elementsByTagName("thumb").at(i).toElement().attribute("preview"));
  841. concert->addPoster(p);
  842. } else if (parentTag == "fanart") {
  843. Poster p;
  844. p.originalUrl = QUrl(domDoc.elementsByTagName("thumb").at(i).toElement().text());
  845. p.thumbUrl = QUrl(domDoc.elementsByTagName("thumb").at(i).toElement().attribute("preview"));
  846. concert->addBackdrop(p);
  847. }
  848. }
  849. concert->setStreamDetailsLoaded(loadStreamDetails(concert->streamDetails(), domDoc));
  850. return true;
  851. }
  852. /**
  853. * @brief Get the path to the concert poster
  854. * @param concert Concert object
  855. * @return Path to poster image
  856. */
  857. QString XbmcXml::posterImageName(Concert *concert, QList<DataFile> dataFiles, bool constructName)
  858. {
  859. if (concert->files().count() == 0)
  860. return QString();
  861. if (!constructName)
  862. dataFiles = Settings::instance()->dataFiles(DataFileType::ConcertPoster);
  863. QFileInfo fi(concert->files().at(0));
  864. QString posterFileName;
  865. foreach (DataFile dataFile, dataFiles) {
  866. QString file = dataFile.saveFileName(fi.fileName());
  867. QFileInfo pFi(fi.absolutePath() + QDir::separator() + file);
  868. if (pFi.isFile() || constructName) {
  869. posterFileName = fi.absolutePath() + QDir::separator() + file;
  870. break;
  871. }
  872. }
  873. fi.setFile(posterFileName);
  874. if (fi.isFile())
  875. return posterFileName;
  876. return QString();
  877. }
  878. /**
  879. * @brief Get the path to the concert backdrop
  880. * @param concert Concert object
  881. * @return Path to backdrop image
  882. */
  883. QString XbmcXml::backdropImageName(Concert *concert, QList<DataFile> dataFiles, bool constructName)
  884. {
  885. if (concert->files().count() == 0)
  886. return QString();
  887. if (!constructName)
  888. dataFiles = Settings::instance()->dataFiles(DataFileType::ConcertBackdrop);
  889. QFileInfo fi(concert->files().at(0));
  890. QString fanartFileName;
  891. foreach (DataFile dataFile, dataFiles) {
  892. QString file = dataFile.saveFileName(fi.fileName());
  893. QFileInfo bFi(fi.absolutePath() + QDir::separator() + file);
  894. if (bFi.isFile() || constructName) {
  895. fanartFileName = fi.absolutePath() + QDir::separator() + file;
  896. break;
  897. }
  898. }
  899. fi.setFile(fanartFileName);
  900. if (fi.isFile())
  901. return fanartFileName;
  902. return QString();
  903. }
  904. /**
  905. * @brief Get the path to the concert logo
  906. * @param concert Concert object
  907. * @return Path to logo image
  908. */
  909. QString XbmcXml::logoImageName(Concert *concert, QList<DataFile> dataFiles, bool constructName)
  910. {
  911. QString logoFileName;
  912. if (concert->files().size() == 0) {
  913. qWarning() << "Concert has no files";
  914. return logoFileName;
  915. }
  916. QFileInfo fi(concert->files().at(0));
  917. if (!constructName)
  918. dataFiles = Settings::instance()->dataFiles(DataFileType::ConcertLogo);
  919. foreach (DataFile dataFile, dataFiles) {
  920. QString file = dataFile.saveFileName(fi.fileName());
  921. QFileInfo bFi(fi.absolutePath() + QDir::separator() + file);
  922. if (bFi.isFile() || constructName) {
  923. logoFileName = fi.absolutePath() + QDir::separator() + file;
  924. break;
  925. }
  926. }
  927. return logoFileName;
  928. }
  929. /**
  930. * @brief Get the path to the concert clear art
  931. * @param concert Concert object
  932. * @return Path to clear art image
  933. */
  934. QString XbmcXml::clearArtImageName(Concert *concert, QList<DataFile> dataFiles, bool constructName)
  935. {
  936. QString clearArtFileName;
  937. if (concert->files().size() == 0) {
  938. qWarning() << "Concert has no files";
  939. return clearArtFileName;
  940. }
  941. QFileInfo fi(concert->files().at(0));
  942. if (!constructName)
  943. dataFiles = Settings::instance()->dataFiles(DataFileType::ConcertClearArt);
  944. foreach (DataFile dataFile, dataFiles) {
  945. QString file = dataFile.saveFileName(fi.fileName());
  946. QFileInfo bFi(fi.absolutePath() + QDir::separator() + file);
  947. if (bFi.isFile() || constructName) {
  948. clearArtFileName = fi.absolutePath() + QDir::separator() + file;
  949. break;
  950. }
  951. }
  952. return clearArtFileName;
  953. }
  954. /**
  955. * @brief Get the path to the concert cd art
  956. * @param concert Concert object
  957. * @return Path to cd art image
  958. */
  959. QString XbmcXml::cdArtImageName(Concert *concert, QList<DataFile> dataFiles, bool constructName)
  960. {
  961. QString cdArtFileName;
  962. if (concert->files().size() == 0) {
  963. qWarning() << "Concert has no files";
  964. return cdArtFileName;
  965. }
  966. QFileInfo fi(concert->files().at(0));
  967. if (!constructName)
  968. dataFiles = Settings::instance()->dataFiles(DataFileType::ConcertCdArt);
  969. foreach (DataFile dataFile, dataFiles) {
  970. QString file = dataFile.saveFileName(fi.fileName());
  971. QFileInfo bFi(fi.absolutePath() + QDir::separator() + file);
  972. if (bFi.isFile() || constructName) {
  973. cdArtFileName = fi.absolutePath() + QDir::separator() + file;
  974. break;
  975. }
  976. }
  977. return cdArtFileName;
  978. }
  979. /**
  980. * @brief Get path to poster image
  981. * @param show
  982. * @return
  983. */
  984. QString XbmcXml::posterImageName(TvShow *show, QList<DataFile> dataFiles, bool constructName)
  985. {
  986. if (show->dir().isEmpty())
  987. return QString();
  988. if (!constructName)
  989. dataFiles = Settings::instance()->dataFiles(DataFileType::TvShowPoster);
  990. QString posterFileName;
  991. foreach (DataFile dataFile, dataFiles) {
  992. QString loadFileName = dataFile.saveFileName("");
  993. QFileInfo posterFi(show->dir() + QDir::separator() + loadFileName);
  994. if (posterFi.isFile() || constructName) {
  995. posterFileName = show->dir() + QDir::separator() + loadFileName;
  996. break;
  997. }
  998. }
  999. QFileInfo fi(posterFileName);
  1000. if (fi.isFile())
  1001. return posterFileName;
  1002. return QString();
  1003. }
  1004. /**
  1005. * @brief Gets path to backdrop image
  1006. * @param show
  1007. * @return
  1008. */
  1009. QString XbmcXml::backdropImageName(TvShow *show, QList<DataFile> dataFiles, bool constructName)
  1010. {
  1011. if (show->dir().isEmpty())
  1012. return QString();
  1013. if (!constructName)
  1014. dataFiles = Settings::instance()->dataFiles(DataFileType::TvShowBackdrop);
  1015. QString posterFileName;
  1016. foreach (DataFile dataFile, dataFiles) {
  1017. QString loadFileName = dataFile.saveFileName("");
  1018. QFileInfo posterFi(show->dir() + QDir::separator() + loadFileName);
  1019. if (posterFi.isFile() || constructName) {
  1020. posterFileName = show->dir() + QDir::separator() + loadFileName;
  1021. break;
  1022. }
  1023. }
  1024. QFileInfo fi(posterFileName);
  1025. if (fi.isFile())
  1026. return posterFileName;
  1027. return QString();
  1028. }
  1029. /**
  1030. * @brief Get path to banner image
  1031. * @param show
  1032. * @return
  1033. */
  1034. QString XbmcXml::bannerImageName(TvShow *show, QList<DataFile> dataFiles, bool constructName)
  1035. {
  1036. if (show->dir().isEmpty())
  1037. return QString();
  1038. if (!constructName)
  1039. dataFiles = Settings::instance()->dataFiles(DataFileType::TvShowBanner);
  1040. QString bannerFileName;
  1041. foreach (DataFile dataFile, dataFiles) {
  1042. QString loadFileName = dataFile.saveFileName("");
  1043. QFileInfo bannerFi(show->dir() + QDir::separator() + loadFileName);
  1044. if (bannerFi.isFile() || constructName) {
  1045. bannerFileName = show->dir() + QDir::separator() + loadFileName;
  1046. break;
  1047. }
  1048. }
  1049. QFileInfo fi(bannerFileName);
  1050. if (fi.isFile())
  1051. return bannerFileName;
  1052. return QString();
  1053. }
  1054. /**
  1055. * @brief Get the path to the tv show logo
  1056. * @param show TV Show object
  1057. * @return Path to logo image
  1058. */
  1059. QString XbmcXml::logoImageName(TvShow *show, QList<DataFile> dataFiles, bool constructName)
  1060. {
  1061. QString logoFileName;
  1062. if (show->dir().isEmpty())
  1063. return logoFileName;
  1064. if (!constructName)
  1065. dataFiles = Settings::instance()->dataFiles(DataFileType::TvShowLogo);
  1066. foreach (DataFile dataFile, dataFiles) {
  1067. QString file = dataFile.saveFileName("");
  1068. QFileInfo fi(show->dir() + QDir::separator() + file);
  1069. if (fi.isFile() || constructName) {
  1070. logoFileName = show->dir() + QDir::separator() + file;
  1071. break;
  1072. }
  1073. }
  1074. return logoFileName;
  1075. }
  1076. /**
  1077. * @brief Get the path to the tv show clear art
  1078. * @param show TV Show object
  1079. * @return Path to clear art image
  1080. */
  1081. QString XbmcXml::clearArtImageName(TvShow *show, QList<DataFile> dataFiles, bool constructName)
  1082. {
  1083. QString clearArtFileName;
  1084. if (show->dir().isEmpty())
  1085. return clearArtFileName;
  1086. if (!constructName)
  1087. dataFiles = Settings::instance()->dataFiles(DataFileType::TvShowClearArt);
  1088. foreach (DataFile dataFile, dataFiles) {
  1089. QString file = dataFile.saveFileName("");
  1090. QFileInfo fi(show->dir() + QDir::separator() + file);
  1091. if (fi.isFile() || constructName) {
  1092. clearArtFileName = show->dir() + QDir::separator() + file;
  1093. break;
  1094. }
  1095. }
  1096. return clearArtFileName;
  1097. }
  1098. /**
  1099. * @brief Get the path to the tv show character art
  1100. * @param show TV Show object
  1101. * @return Path to character art image
  1102. */
  1103. QString XbmcXml::characterArtImageName(TvShow *show, QList<DataFile> dataFiles, bool constructName)
  1104. {
  1105. QString characterArtFileName;
  1106. if (show->dir().isEmpty())
  1107. return characterArtFileName;
  1108. if (!constructName)
  1109. dataFiles = Settings::instance()->dataFiles(DataFileType::TvShowCharacterArt);
  1110. foreach (DataFile dataFile, dataFiles) {
  1111. QString file = dataFile.saveFileName("");
  1112. QFileInfo fi(show->dir() + QDir::separator() + file);
  1113. if (fi.isFile() || constructName) {
  1114. characterArtFileName = show->dir() + QDir::separator() + file;
  1115. break;
  1116. }
  1117. }
  1118. return characterArtFileName;
  1119. }
  1120. /**
  1121. * @brief Get path to season poster
  1122. * @param show
  1123. * @param season
  1124. * @return
  1125. */
  1126. QString XbmcXml::seasonPosterImageName(TvShow *show, int season, QList<DataFile> dataFiles, bool constructName)
  1127. {
  1128. QString fileName;
  1129. if (show->dir().isEmpty())
  1130. return fileName;
  1131. if (!constructName)
  1132. dataFiles = Settings::instance()->dataFiles(DataFileType::TvShowSeasonPoster);
  1133. foreach (DataFile dataFile, dataFiles) {
  1134. QString file = dataFile.saveFileName("", season);
  1135. QFileInfo fi(show->dir() + QDir::separator() + file);
  1136. if (fi.isFile() || constructName) {
  1137. fileName = show->dir() + QDir::separator() + file;
  1138. break;
  1139. }
  1140. }
  1141. return fileName;
  1142. }
  1143. QString XbmcXml::seasonBackdropImageName(TvShow *show, int season, QList<DataFile> dataFiles, bool constructName)
  1144. {
  1145. QString fileName;
  1146. if (show->dir().isEmpty())
  1147. return fileName;
  1148. if (!constructName)
  1149. dataFiles = Settings::instance()->dataFiles(DataFileType::TvShowSeasonBackdrop);
  1150. foreach (DataFile dataFile, dataFiles) {
  1151. QString file = dataFile.saveFileName("", season);
  1152. QFileInfo fi(show->dir() + QDir::separator() + file);
  1153. if (fi.isFile() || constructName) {
  1154. fileName = show->dir() + QDir::separator() + file;
  1155. break;
  1156. }
  1157. }
  1158. return fileName;
  1159. }
  1160. QString XbmcXml::seasonBannerImageName(TvShow *show, int season, QList<DataFile> dataFiles, bool constructName)
  1161. {
  1162. QString fileName;
  1163. if (show->dir().isEmpty())
  1164. return fileName;
  1165. if (!constructName)
  1166. dataFiles = Settings::instance()->dataFiles(DataFileType::TvShowSeasonBanner);
  1167. foreach (DataFile dataFile, dataFiles) {
  1168. QString file = dataFile.saveFileName("", season);
  1169. QFileInfo fi(show->dir() + QDir::separator() + file);
  1170. if (fi.isFile() || constructName) {
  1171. fileName = show->dir() + QDir::separator() + file;
  1172. break;
  1173. }
  1174. }
  1175. return fileName;
  1176. }
  1177. /**
  1178. * @brief Get path to actor image
  1179. * @param show
  1180. * @param actor
  1181. * @return Path to actor image
  1182. */
  1183. QString XbmcXml::actorImageName(TvShow *show, Actor actor)
  1184. {
  1185. if (show->dir().isEmpty(

Large files files are truncated, but you can click here to view the full file