1 /*****************************************************************************
2 ** QNapi
3 ** Copyright (C) 2008-2017 Piotr Krzemiński <pio.krzeminski@gmail.com>
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12 **
13 *****************************************************************************/
14
15 #include "subtitlepostprocessor.h"
16
17 #include <QFile>
18 #include <QFileInfo>
19 #include <QTextCodec>
20 #include <QTextStream>
21
SubtitlePostProcessor(const PostProcessingConfig & ppConfig,const QSharedPointer<const SubtitleConverter> & subtitleConverter)22 SubtitlePostProcessor::SubtitlePostProcessor(
23 const PostProcessingConfig& ppConfig,
24 const QSharedPointer<const SubtitleConverter>& subtitleConverter)
25 : ppConfig(ppConfig), subtitleConverter(subtitleConverter) {}
26
perform(const QString & movieFilePath,const QString & subtitleFilePath) const27 void SubtitlePostProcessor::perform(const QString& movieFilePath,
28 const QString& subtitleFilePath) const {
29 if (ppConfig.removeWordsEnabled()) {
30 ppRemoveLinesContainingWords(subtitleFilePath, ppConfig.removeWords());
31 }
32
33 switch (ppConfig.encodingChangeMethod()) {
34 case ECM_REPLACE_DIACRITICS:
35 ppReplaceDiacriticsWithASCII(subtitleFilePath);
36 break;
37 case ECM_CHANGE:
38 if (!ppConfig.encodingAutoDetectFrom() ||
39 !ppChangeSubtitlesEncoding(subtitleFilePath, ppConfig.encodingTo())) {
40 ppChangeSubtitlesEncoding(subtitleFilePath, ppConfig.encodingFrom(),
41 ppConfig.encodingTo());
42 }
43 break;
44 case ECM_ORIGINAL:
45 // Nie ruszaj pobranych napisów!
46 break;
47 }
48
49 if (!ppConfig.subFormat().isEmpty()) {
50 QString targetFormat = ppConfig.subFormat();
51 subtitleConverter->convertSubtitles(subtitleFilePath, targetFormat,
52 subtitleFilePath, movieFilePath);
53 }
54 }
55
ppReplaceDiacriticsWithASCII(const QString & subtitleFilePath) const56 bool SubtitlePostProcessor::ppReplaceDiacriticsWithASCII(
57 const QString& subtitleFilePath) const {
58 if (!QFileInfo(subtitleFilePath).exists()) return false;
59
60 QString from = encodingUtils.detectFileEncoding(subtitleFilePath);
61
62 if (from.isEmpty()) return false;
63
64 QFile f(subtitleFilePath);
65 if (!f.open(QIODevice::ReadOnly)) return false;
66
67 QByteArray fileContent = f.readAll();
68
69 QString contentStr =
70 QTextCodec::codecForName(qPrintable(from))->toUnicode(fileContent);
71 f.close();
72
73 fileContent.clear();
74 fileContent.append(encodingUtils.replaceDiacriticsWithASCII(contentStr));
75
76 if (!f.open(QIODevice::WriteOnly)) return false;
77
78 f.write(fileContent);
79 f.close();
80
81 return true;
82 }
83
ppChangeSubtitlesEncoding(const QString & subtitleFilePath,const QString & from,const QString & to) const84 bool SubtitlePostProcessor::ppChangeSubtitlesEncoding(
85 const QString& subtitleFilePath, const QString& from,
86 const QString& to) const {
87 QFile f(subtitleFilePath);
88 if (!f.open(QIODevice::ReadOnly)) return false;
89
90 QByteArray fileContent = f.readAll();
91
92 QString contentStr =
93 QTextCodec::codecForName(qPrintable(from))->toUnicode(fileContent);
94 f.close();
95
96 if (to.compare("UTF-8", Qt::CaseInsensitive) != 0) {
97 fileContent = QTextCodec::codecForName(qPrintable(to))
98 ->fromUnicode(contentStr.constData(), contentStr.size());
99 } else {
100 fileContent.clear();
101 fileContent.append(contentStr);
102 }
103
104 if (!f.open(QIODevice::WriteOnly)) return false;
105
106 f.write(fileContent);
107 f.close();
108
109 return true;
110 }
111
ppChangeSubtitlesEncoding(const QString & subtitleFilePath,const QString & to) const112 bool SubtitlePostProcessor::ppChangeSubtitlesEncoding(
113 const QString& subtitleFilePath, const QString& to) const {
114 if (!QFileInfo(subtitleFilePath).exists()) return false;
115
116 QString from = encodingUtils.detectFileEncoding(subtitleFilePath);
117
118 if (from.isEmpty()) return false;
119
120 return ppChangeSubtitlesEncoding(from, to);
121 }
122
ppRemoveLinesContainingWords(const QString & subtitleFilePath,QStringList wordList) const123 bool SubtitlePostProcessor::ppRemoveLinesContainingWords(
124 const QString& subtitleFilePath, QStringList wordList) const {
125 if (!QFileInfo(subtitleFilePath).exists()) return false;
126
127 wordList = wordList.filter(QRegExp("^(.+)$"));
128
129 QString fromCodec = encodingUtils.detectFileEncoding(subtitleFilePath);
130
131 if (fromCodec.isEmpty()) fromCodec = ppConfig.encodingFrom();
132
133 QFile f(subtitleFilePath);
134 if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) return false;
135
136 QList<QByteArray> lines = f.readAll().split('\n');
137 QList<QByteArray> out;
138
139 foreach (QByteArray line, lines) {
140 int i;
141 while ((i = line.indexOf('\r')) >= 0) line.remove(i, 1);
142
143 QTextStream ts(line);
144 ts.setCodec(qPrintable(fromCodec));
145 QString encLine = ts.readAll();
146
147 if (encLine.isEmpty()) {
148 out << line;
149 continue;
150 }
151
152 bool found = false;
153 foreach (QString word, wordList) {
154 if (encLine.contains(word, Qt::CaseInsensitive)) {
155 found = true;
156 break;
157 }
158 }
159 if (found) continue;
160
161 out << line;
162 }
163
164 f.close();
165
166 if (!f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
167 return false;
168
169 foreach (QByteArray line, out) {
170 f.write(line);
171 f.write("\n", 1);
172 }
173 f.close();
174
175 return true;
176 }
177