1 /***************************************************************************
2 * Copyright (C) 2011 by Jean-Baptiste Mardelle (jb@kdenlive.org) *
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. *
10 * This program 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, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
19 ***************************************************************************/
22 #include "resourcewidget.h"
23 #include "freesound.h"
24 #include "openclipart.h"
25 #include "archiveorg.h"
27 #include <QPushButton>
29 #include <QListWidget>
30 #include <QDomDocument>
33 #include <kdeversion.h>
34 #include "kdenlivesettings.h"
35 #include <KGlobalSettings>
36 #include <KMessageBox>
37 #include <KFileDialog>
39 #include <KIO/NetAccess>
40 #include <Solid/Networking>
44 #if KDE_IS_VERSION(4,6,0)
45 #include <Nepomuk/Variant>
46 #include <Nepomuk/Resource>
47 #include <Nepomuk/ResourceManager>
48 #include <Soprano/Vocabulary/NAO>
49 #include <Nepomuk/Vocabulary/NIE>
50 #include <Nepomuk/Vocabulary/NDO>
51 #include <kfileitem.h>
55 ResourceWidget::ResourceWidget(const QString & folder, QWidget * parent) :
58 m_currentService(NULL)
60 setFont(KGlobalSettings::toolBarFont());
62 setAttribute(Qt::WA_DeleteOnClose);
64 service_list->addItem(i18n("Freesound Audio Library"), FREESOUND);
65 service_list->addItem(i18n("Archive.org Video Library"), ARCHIVEORG);
67 service_list->addItem(i18n("Open Clip Art Graphic Library"), OPENCLIPART);
68 setWindowTitle(i18n("Search Online Resources"));
69 info_browser->setStyleSheet(QString("QTextBrowser { background-color: transparent;}"));
70 connect(button_search, SIGNAL(clicked()), this, SLOT(slotStartSearch()));
71 connect(search_results, SIGNAL(currentRowChanged(int)), this, SLOT(slotUpdateCurrentSound()));
72 connect(button_preview, SIGNAL(clicked()), this, SLOT(slotPlaySound()));
73 connect(button_import, SIGNAL(clicked()), this, SLOT(slotSaveItem()));
74 connect(sound_author, SIGNAL(leftClickedUrl(const QString &)), this, SLOT(slotOpenUrl(const QString &)));
75 connect(item_license, SIGNAL(leftClickedUrl(const QString &)), this, SLOT(slotOpenUrl(const QString &)));
76 connect(sound_name, SIGNAL(leftClickedUrl(const QString &)), this, SLOT(slotOpenUrl(const QString &)));
77 connect(service_list, SIGNAL(currentIndexChanged(int)), this, SLOT(slotChangeService()));
78 item_image->setFixedWidth(180);
79 if (Solid::Networking::status() == Solid::Networking::Unconnected) {
82 connect(Solid::Networking::notifier(), SIGNAL(shouldConnect()), this, SLOT(slotOnline()));
83 connect(Solid::Networking::notifier(), SIGNAL(shouldDisconnect()), this, SLOT(slotOffline()));
84 connect(page_next, SIGNAL(clicked()), this, SLOT(slotNextPage()));
85 connect(page_prev, SIGNAL(clicked()), this, SLOT(slotPreviousPage()));
86 connect(page_number, SIGNAL(valueChanged(int)), this, SLOT(slotStartSearch(int)));
87 connect(info_browser, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(slotOpenLink(const QUrl &)));
89 sound_box->setEnabled(false);
90 search_text->setFocus();
92 #if KDE_IS_VERSION(4,6,0)
93 Nepomuk::ResourceManager::instance()->init();
99 ResourceWidget::~ResourceWidget()
101 if (m_currentService) delete m_currentService;
104 void ResourceWidget::slotStartSearch(int page)
106 page_number->blockSignals(true);
107 page_number->setValue(page);
108 page_number->blockSignals(false);
109 m_currentService->slotStartSearch(search_text->text(), page);
112 void ResourceWidget::slotUpdateCurrentSound()
114 item_image->setEnabled(false);
115 if (!sound_autoplay->isChecked()) m_currentService->stopItemPreview(NULL);
116 info_browser->clear();
117 item_license->clear();
118 QListWidgetItem *item = search_results->currentItem();
120 sound_box->setEnabled(false);
123 m_currentInfo = m_currentService->displayItemDetails(item);
125 if (sound_autoplay->isChecked()) m_currentService->startItemPreview(item);
126 sound_box->setEnabled(true);
127 sound_name->setText(item->text());
128 sound_name->setUrl(m_currentInfo.infoUrl);
129 sound_author->setText(m_currentInfo.author);
130 sound_author->setUrl(m_currentInfo.authorUrl);
131 if (!m_currentInfo.description.isEmpty()) info_browser->setHtml("<em>" + m_currentInfo.description + "</em>");
132 if (!m_currentInfo.license.isEmpty()) parseLicense(m_currentInfo.license);
136 void ResourceWidget::slotLoadThumb(const QString url)
139 if (img.isEmpty()) return;
140 if (KIO::NetAccess::exists(img, KIO::NetAccess::SourceSide, this)) {
142 if (KIO::NetAccess::download(img, tmpFile, this)) {
143 QPixmap pix(tmpFile);
144 int newHeight = pix.height() * item_image->width() / pix.width();
145 if (newHeight > 200) {
146 item_image->setScaledContents(false);
147 //item_image->setFixedHeight(item_image->width());
150 item_image->setScaledContents(true);
151 item_image->setFixedHeight(newHeight);
153 item_image->setPixmap(pix);
154 KIO::NetAccess::removeTempFile(tmpFile);
157 item_image->setEnabled(true);
161 void ResourceWidget::slotDisplayMetaInfo(QMap <QString, QString> metaInfo)
163 if (metaInfo.contains("license")) {
164 parseLicense(metaInfo.value("license"));
169 void ResourceWidget::slotPlaySound()
171 if (!m_currentService) return;
172 bool started = m_currentService->startItemPreview(search_results->currentItem());
173 if (started) button_preview->setText(i18n("Preview"));
174 else button_preview->setText(i18n("Stop"));
178 void ResourceWidget::slotForcePlaySound(bool play)
181 if (m_service != FREESOUND) return;
182 m_previewProcess->close();
183 if (m_currentPreview.isEmpty()) return;
185 m_previewProcess->start("ffplay", QStringList() << m_currentPreview << "-nodisp");
189 void ResourceWidget::slotPreviewStatusChanged(QProcess::ProcessState state)
191 /*if (state == QProcess::NotRunning)
192 button_preview->setText(i18n("Preview"));
194 button_preview->setText(i18n("Stop"));*/
197 void ResourceWidget::slotSaveItem(const QString originalUrl)
199 //if (m_currentUrl.isEmpty()) return;
200 QListWidgetItem *item = search_results->currentItem();
202 QString path = m_folder;
204 if (!path.endsWith('/')) path.append('/');
205 if (!originalUrl.isEmpty()) {
206 path.append(KUrl(originalUrl).fileName());
207 ext = "*." + KUrl(originalUrl).fileName().section(".", -1);
208 m_currentInfo.itemDownload = originalUrl;
211 path.append(m_currentService->getDefaultDownloadName(item));
212 ext = m_currentService->getExtension(search_results->currentItem());
214 QString saveUrl = KFileDialog::getSaveFileName(KUrl(path), ext);
216 KUrl srcUrl(m_currentInfo.itemDownload);
217 if (saveUrl.isEmpty() || !KIO::NetAccess::stat(srcUrl, entry, this)) return;
218 KIO::FileCopyJob * getJob = KIO::file_copy(srcUrl, KUrl(saveUrl), -1, KIO::Overwrite);
220 KFileItem info(entry, srcUrl);
221 getJob->setSourceSize(info.size());
222 connect(getJob, SIGNAL(result(KJob*)), this, SLOT(slotGotFile(KJob*)));
226 void ResourceWidget::slotGotFile(KJob *job)
228 if (job->error() != 0 ) return;
229 KIO::FileCopyJob* copyJob = static_cast<KIO::FileCopyJob*>( job );
230 const KUrl filePath = copyJob->destUrl();
232 #if KDE_IS_VERSION(4,6,0)
233 Nepomuk::Resource res( filePath );
234 res.setProperty( Nepomuk::Vocabulary::NIE::license(), (Nepomuk::Variant) item_license->text() );
235 res.setProperty( Nepomuk::Vocabulary::NIE::licenseType(), (Nepomuk::Variant) item_license->url() );
236 res.setProperty( Nepomuk::Vocabulary::NDO::copiedFrom(), sound_name->url() );
237 //res.setDescription(item_description->toPlainText());
238 //res.setProperty( Soprano::Vocabulary::NAO::description(),
241 emit addClip(filePath, QString());//, sound_name->url());
244 void ResourceWidget::slotOpenUrl(const QString &url)
246 new KRun(KUrl(url), this);
249 void ResourceWidget::slotChangeService()
251 if (m_currentService) {
252 delete m_currentService;
253 m_currentService = NULL;
255 SERVICETYPE service = (SERVICETYPE) service_list->itemData(service_list->currentIndex()).toInt();
256 if (service == FREESOUND) {
257 m_currentService = new FreeSound(search_results);
259 else if (service == OPENCLIPART) {
260 m_currentService = new OpenClipArt(search_results);
262 else if (service == ARCHIVEORG) {
263 m_currentService = new ArchiveOrg(search_results);
266 connect(m_currentService, SIGNAL(gotMetaInfo(const QString)), this, SLOT(slotGotMetaInfo(const QString)));
267 connect(m_currentService, SIGNAL(gotMetaInfo(QMap <QString, QString>)), this, SLOT(slotDisplayMetaInfo(QMap <QString, QString>)));
268 connect(m_currentService, SIGNAL(maxPages(int)), page_number, SLOT(setMaximum(int)));
269 connect(m_currentService, SIGNAL(searchInfo(QString)), search_info, SLOT(setText(QString)));
270 connect(m_currentService, SIGNAL(gotThumb(const QString)), this, SLOT(slotLoadThumb(const QString)));
272 button_preview->setVisible(m_currentService->hasPreview);
273 button_import->setVisible(!m_currentService->inlineDownload);
274 sound_autoplay->setVisible(m_currentService->hasPreview);
275 search_info->setText(QString());
276 info_browser->setVisible(m_currentService->hasMetadata);
277 if (!search_text->text().isEmpty()) slotStartSearch();
280 void ResourceWidget::slotOnline()
282 button_search->setEnabled(true);
283 search_info->setText(QString());
286 void ResourceWidget::slotOffline()
288 button_search->setEnabled(false);
289 search_info->setText(i18n("You need to be online\n for searching"));
292 void ResourceWidget::slotNextPage()
294 int ix = page_number->value();
295 if (search_results->count() > 0) page_number->setValue(ix + 1);
298 void ResourceWidget::slotPreviousPage()
300 int ix = page_number->value();
301 if (ix > 1) page_number->setValue(ix - 1);
304 void ResourceWidget::parseLicense(const QString &licenseUrl)
307 if (licenseUrl.contains("/sampling+/"))
308 licenseName = "Sampling+";
309 else if (licenseUrl.contains("/by/"))
310 licenseName = "Attribution";
311 else if (licenseUrl.contains("/by-nd/"))
312 licenseName = "Attribution-NoDerivs";
313 else if (licenseUrl.contains("/by-nc-sa/"))
314 licenseName = "Attribution-NonCommercial-ShareAlike";
315 else if (licenseUrl.contains("/by-sa/"))
316 licenseName = "Attribution-ShareAlike";
317 else if (licenseUrl.contains("/by-nc/"))
318 licenseName = "Attribution-NonCommercial";
319 else if (licenseUrl.contains("/by-nc-nd/"))
320 licenseName = "Attribution-NonCommercial-NoDerivs";
321 else if (licenseUrl.contains("/publicdomain/zero/"))
322 licenseName = "Creative Commons 0";
323 else if (licenseUrl.endsWith("/publicdomain"))
324 licenseName = "Public Domain";
325 else licenseName = i18n("Unknown");
326 item_license->setText(licenseName);
327 item_license->setUrl(licenseUrl);
330 void ResourceWidget::slotGotMetaInfo(const QString info)
332 info_browser->setHtml(info_browser->toHtml() + info);
336 void ResourceWidget::slotOpenLink(const QUrl &url)
338 QString path = url.toEncoded();
339 if (path.endsWith("_preview")) {
344 // import file in Kdenlive