2 * abby Copyright (C) 2009 Toni Gundogdu.
3 * This file is part of abby.
5 * abby 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 3 of the License, or
8 * (at your option) any later version.
10 * abby is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include <QMessageBox>
27 ScanDialog::ScanDialog(QWidget
*parent
)
28 : QDialog(parent
), mgr(0), titleMode(false),
29 scannedPages(0), expectedScans(0)
35 mgr
= createManager();
37 itemsTree
->setColumnHidden(1, true);
41 enable_widgets(ScanDialog
*d
, const bool state
=true) {
42 d
->linkEdit
->setEnabled (state
);
43 d
->scanButton
->setEnabled (state
);
44 d
->titlesBox
->setEnabled (state
);
45 d
->selectallButton
->setEnabled(state
);
46 d
->invertButton
->setEnabled(state
);
47 d
->buttonBox
->setEnabled (state
);
51 ScanDialog::onScan() {
53 QString lnk
= linkEdit
->text();
60 if (!lnk
.startsWith("http://", Qt::CaseInsensitive
))
61 lnk
.insert(0,"http://");
70 enable_widgets(this, false);
72 Util::appendLog(logEdit
, QString(tr("Scan ... %1")).arg(lnk
));
74 mgr
->get( QNetworkRequest(lnk
) );
78 ScanDialog::replyFinished(QNetworkReply
* reply
) {
80 if (reply
->error() == QNetworkReply::NoError
) {
82 handleRedirect(reply
);
84 if (!redirectedToURL
.isEmpty()) {
87 QString(tr("Fetch ... %1"))
88 .arg(redirectedToURL
.toString())
90 mgr
->get( QNetworkRequest(redirectedToURL
) );
94 Util::appendLog(logEdit
, tr("Scan contents for video links."));
100 QString(tr("Parse video title ... %1 [%2/%3]"))
101 .arg(reply
->url().toString())
105 parseHtmlTitle(reply
);
106 if (scannedPages
== expectedScans
)
109 redirectedToURL
.clear();
113 Util::appendLog(logEdit
, tr("Error occurred."));
114 QMessageBox::critical(this, QCoreApplication::applicationName(),
115 QString(tr("Network error: %1")).arg(reply
->errorString()));
120 linkEdit
->setEnabled (state
);
121 scanButton
->setEnabled (state
);
122 titlesBox
->setEnabled (state
);
123 buttonBox
->setEnabled (state
);
124 selectallButton
->setEnabled(state
);
125 invertButton
->setEnabled(state
);
129 reply
->deleteLater();
133 matchScanContent (const QStringList
& lst
, QRegExp
& re
, const QString
& content
) {
135 re
.setCaseSensitivity(Qt::CaseInsensitive
);
141 while ((pos
= re
.indexIn(content
, pos
)) != -1) {
142 const QString cap
= re
.cap(1).simplified();
143 if (!matches
.contains(cap
)
144 && !lst
.contains(cap
)
149 pos
+= re
.matchedLength();
154 typedef unsigned int _uint
;
158 dumpScanMatches (const QStringList
& lst
) {
159 const register _uint size
= lst
.size();
160 for (register _uint i
=0; i
<size
; ++i
)
162 qDebug() << "total: " << lst
.size();
167 scanYoutubeEmbed(QStringList
& lst
, const QString
& content
) {
168 QRegExp
re("\\/v\\/(.*)[\"&\n<]");
169 QStringList matches
= matchScanContent(lst
, re
, content
);
170 //dumpScanMatches(matches);
175 scanYoutubeRegular(QStringList
& lst
, const QString
& content
) {
176 QRegExp
re("\\/watch\\?v=(.*)[\"&\n<]");
177 QStringList matches
= matchScanContent(lst
, re
, content
);
178 //dumpScanMatches(matches);
183 ScanDialog::scanContent(QNetworkReply
*reply
) {
185 const QString content
= QString::fromLocal8Bit(reply
->readAll());
187 QStringList IDs
, links
;
189 scanYoutubeEmbed (IDs
, content
);
190 scanYoutubeRegular (IDs
, content
);
192 const register _uint ids_size
= IDs
.size();
195 for (i
=0; i
<ids_size
; ++i
)
196 links
<< "http://www.youtube.com/watch?v="+IDs
[i
];
198 const register _uint links_size
= links
.size();
202 QString(tr("Found %1 video links.")).arg(links_size
)
205 if (titlesBox
->checkState()) {
207 for (i
=0, expectedScans
=links_size
; i
<links_size
; ++i
)
208 mgr
->get( QNetworkRequest(links
[i
]) );
212 for (i
=0; i
<links_size
; ++i
) {
213 QTreeWidgetItem
*item
= new QTreeWidgetItem
;
214 item
->setCheckState(0, Qt::Unchecked
);
215 item
->setText(0, links
[i
]);
216 item
->setText(1, links
[i
]);
217 itemsTree
->addTopLevelItem(item
);
225 ScanDialog::parseHtmlTitle(QNetworkReply
*reply
) {
227 const QString content
= QString::fromLocal8Bit(reply
->readAll());
228 const QString link
= reply
->url().toString();
230 QRegExp
re("<title>(.*)<"); // TODO: improve.
231 re
.setCaseSensitivity(Qt::CaseInsensitive
);
235 QTreeWidgetItem
*item
= new QTreeWidgetItem
;
236 item
->setCheckState(0, Qt::Unchecked
);
237 item
->setText(0, re
.cap(1).simplified());
238 item
->setText(1, link
);
239 itemsTree
->addTopLevelItem(item
);
242 QNetworkAccessManager
*
243 ScanDialog::createManager() {
244 QNetworkAccessManager
*p
= new QNetworkAccessManager(this);
246 connect(p
, SIGNAL(finished(QNetworkReply
*)),
247 this, SLOT(replyFinished(QNetworkReply
*)));
253 ScanDialog::handleRedirect(const QNetworkReply
*reply
) {
256 // reply->header(QNetworkRequest::LocationHeader).toUrl();
259 reply
->attribute(QNetworkRequest::RedirectionTargetAttribute
).toUrl();
261 if (!location
.isEmpty() && location
!= redirectedToURL
)
262 redirectedToURL
= location
;
264 redirectedToURL
.clear();
268 ScanDialog::writeSettings() {
270 s
.beginGroup("ScanDialog");
271 s
.setValue("size", size());
276 ScanDialog::readSettings() {
278 s
.beginGroup("ScanDialog");
279 resize( s
.value("size", QSize(514,295)).toSize() );
284 ScanDialog::onSelectAll() {
285 Util::checkAllItems(itemsTree
, Qt::Checked
);
289 ScanDialog::onInvert() {
290 Util::invertAllCheckableItems(itemsTree
);
294 ScanDialog::scanComplete() {
295 enable_widgets(this);
296 Util::appendLog(logEdit
, tr("Scan complete."));