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"
26 #include "kdenlivesettings.h"
28 #include <QPushButton>
30 #include <QListWidget>
35 #include <kdeversion.h>
36 #include <KGlobalSettings>
37 #include <KMessageBox>
38 #include <KFileDialog>
40 #include <KIO/NetAccess>
41 #include <Solid/Networking>
43 #include <KConfigGroup>
45 #if KDE_IS_VERSION(4,4,0)
46 #include <KPixmapSequence>
47 #include <KPixmapSequenceOverlayPainter>
52 #if KDE_IS_VERSION(4,6,0)
53 #include <Nepomuk/Variant>
54 #include <Nepomuk/Resource>
55 #include <Nepomuk/ResourceManager>
56 #include <Nepomuk/Vocabulary/NIE>
57 #include <Nepomuk/Vocabulary/NCO>
58 #include <Nepomuk/Vocabulary/NDO>
62 #ifdef USE_NEPOMUKCORE
63 #include <Nepomuk2/Variant>
64 #include <Nepomuk2/Resource>
65 #include <Nepomuk2/ResourceManager>
66 #include <Nepomuk2/Vocabulary/NIE>
67 #include <Nepomuk2/Vocabulary/NCO>
68 #include <Nepomuk2/Vocabulary/NDO>
71 ResourceWidget::ResourceWidget(const QString & folder, QWidget * parent) :
74 m_currentService(NULL)
76 setFont(KGlobalSettings::toolBarFont());
78 setAttribute(Qt::WA_DeleteOnClose);
80 service_list->addItem(i18n("Freesound Audio Library"), FREESOUND);
81 service_list->addItem(i18n("Archive.org Video Library"), ARCHIVEORG);
83 service_list->addItem(i18n("Open Clip Art Graphic Library"), OPENCLIPART);
84 setWindowTitle(i18n("Search Online Resources"));
85 info_browser->setStyleSheet(QString("QTextBrowser { background-color: transparent;}"));
86 connect(button_search, SIGNAL(clicked()), this, SLOT(slotStartSearch()));
87 connect(search_results, SIGNAL(currentRowChanged(int)), this, SLOT(slotUpdateCurrentSound()));
88 connect(button_preview, SIGNAL(clicked()), this, SLOT(slotPlaySound()));
89 connect(button_import, SIGNAL(clicked()), this, SLOT(slotSaveItem()));
90 connect(item_license, SIGNAL(leftClickedUrl(QString)), this, SLOT(slotOpenUrl(QString)));
91 connect(service_list, SIGNAL(currentIndexChanged(int)), this, SLOT(slotChangeService()));
92 if (Solid::Networking::status() == Solid::Networking::Unconnected) {
95 connect(Solid::Networking::notifier(), SIGNAL(shouldConnect()), this, SLOT(slotOnline()));
96 connect(Solid::Networking::notifier(), SIGNAL(shouldDisconnect()), this, SLOT(slotOffline()));
97 connect(page_next, SIGNAL(clicked()), this, SLOT(slotNextPage()));
98 connect(page_prev, SIGNAL(clicked()), this, SLOT(slotPreviousPage()));
99 connect(page_number, SIGNAL(valueChanged(int)), this, SLOT(slotStartSearch(int)));
100 connect(info_browser, SIGNAL(anchorClicked(QUrl)), this, SLOT(slotOpenLink(QUrl)));
102 m_autoPlay = new QAction(i18n("Auto Play"), this);
103 m_autoPlay->setCheckable(true);
104 QMenu *resourceMenu = new QMenu;
105 resourceMenu->addAction(m_autoPlay);
106 config_button->setMenu(resourceMenu);
107 config_button->setIcon(KIcon("configure"));
109 #if KDE_IS_VERSION(4,4,0)
110 m_busyWidget = new KPixmapSequenceOverlayPainter(this);
111 m_busyWidget->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
112 m_busyWidget->setWidget(search_results->viewport());
115 sound_box->setEnabled(false);
116 search_text->setFocus();
118 #if KDE_IS_VERSION(4,6,0)
119 Nepomuk::ResourceManager::instance()->init();
126 ResourceWidget::~ResourceWidget()
128 delete m_currentService;
129 KIO::NetAccess::removeTempFile(m_tmpThumbFile);
133 void ResourceWidget::loadConfig()
135 KSharedConfigPtr config = KGlobal::config();
136 KConfigGroup resourceConfig(config, "ResourceWidget");
139 splitter->setSizes(resourceConfig.readEntry( "mainSplitter", size));
142 void ResourceWidget::saveConfig()
144 KSharedConfigPtr config = KGlobal::config();
145 KConfigGroup resourceConfig(config, "ResourceWidget");
146 resourceConfig.writeEntry(QLatin1String("mainsplitter"), splitter->size());
150 void ResourceWidget::slotStartSearch(int page)
152 page_number->blockSignals(true);
153 page_number->setValue(page);
154 page_number->blockSignals(false);
155 #if KDE_IS_VERSION(4,4,0)
156 m_busyWidget->start();
158 m_currentService->slotStartSearch(search_text->text(), page);
161 void ResourceWidget::slotUpdateCurrentSound()
163 KIO::NetAccess::removeTempFile(m_tmpThumbFile);
164 if (!m_autoPlay->isChecked())
165 m_currentService->stopItemPreview(NULL);
166 item_license->clear();
171 QListWidgetItem *item = search_results->currentItem();
173 sound_box->setEnabled(false);
176 m_currentInfo = m_currentService->displayItemDetails(item);
178 if (m_autoPlay->isChecked() && m_currentService->hasPreview)
179 m_currentService->startItemPreview(item);
180 sound_box->setEnabled(true);
181 QString title = "<h3>" + m_currentInfo.itemName;
182 if (!m_currentInfo.infoUrl.isEmpty())
183 title += QString(" (<a href=\"%1\">%2</a>)").arg(m_currentInfo.infoUrl).arg(i18nc("the url link pointing to a web page", "link"));
184 title.append("</h3>");
186 if (!m_currentInfo.authorUrl.isEmpty()) {
187 title += QString("<a href=\"%1\">").arg(m_currentInfo.authorUrl);
188 if (!m_currentInfo.author.isEmpty())
189 title.append(m_currentInfo.author);
190 else title.append(i18n("Author"));
191 title.append("</a><br />");
193 else if (!m_currentInfo.author.isEmpty())
194 title.append(m_currentInfo.author + "<br />");
196 title.append("<br />");
199 if (!m_currentInfo.description.isEmpty()) slotSetDescription(m_currentInfo.description);
200 if (!m_currentInfo.license.isEmpty()) parseLicense(m_currentInfo.license);
204 void ResourceWidget::slotLoadThumb(const QString &url)
207 if (img.isEmpty()) return;
208 if (KIO::NetAccess::exists(img, KIO::NetAccess::SourceSide, this)) {
209 if (KIO::NetAccess::download(img, m_tmpThumbFile, this)) {
210 slotSetImage(m_tmpThumbFile);
211 /*QPixmap pix(tmpFile);
213 int newHeight = pix.height() * item_image->width() / pix.width();
214 if (newHeight > 200) {
215 item_image->setScaledContents(false);
216 //item_image->setFixedHeight(item_image->width());
219 item_image->setScaledContents(true);
220 item_image->setFixedHeight(newHeight);
222 item_image->setPixmap(pix);*/
228 void ResourceWidget::slotDisplayMetaInfo(const QMap<QString, QString> &metaInfo)
230 if (metaInfo.contains(QLatin1String("license"))) {
231 parseLicense(metaInfo.value(QLatin1String("license")));
233 if (metaInfo.contains(QLatin1String("description"))) {
234 slotSetDescription(metaInfo.value(QLatin1String("description")));
239 void ResourceWidget::slotPlaySound()
241 if (!m_currentService)
243 const bool started = m_currentService->startItemPreview(search_results->currentItem());
245 button_preview->setText(i18n("Preview"));
247 button_preview->setText(i18n("Stop"));
251 void ResourceWidget::slotSaveItem(const QString &originalUrl)
253 //if (m_currentUrl.isEmpty()) return;
254 QListWidgetItem *item = search_results->currentItem();
256 QString path = m_folder;
258 if (!path.endsWith('/')) path.append('/');
259 if (!originalUrl.isEmpty()) {
260 path.append(KUrl(originalUrl).fileName());
261 ext = "*." + KUrl(originalUrl).fileName().section('.', -1);
262 m_currentInfo.itemDownload = originalUrl;
265 path.append(m_currentService->getDefaultDownloadName(item));
266 ext = m_currentService->getExtension(search_results->currentItem());
268 QString saveUrl = KFileDialog::getSaveFileName(KUrl(path), ext);
270 KUrl srcUrl(m_currentInfo.itemDownload);
271 if (saveUrl.isEmpty() || !KIO::NetAccess::stat(srcUrl, entry, this))
273 KIO::FileCopyJob * getJob = KIO::file_copy(srcUrl, KUrl(saveUrl), -1, KIO::Overwrite);
275 KFileItem info(entry, srcUrl);
276 getJob->setSourceSize(info.size());
277 getJob->setProperty("license", item_license->text());
278 getJob->setProperty("licenseurl", item_license->url());
279 getJob->setProperty("originurl", m_currentInfo.itemDownload);
280 if (!m_currentInfo.authorUrl.isEmpty()) getJob->setProperty("author", m_currentInfo.authorUrl);
281 else if (!m_currentInfo.author.isEmpty()) getJob->setProperty("author", m_currentInfo.author);
282 connect(getJob, SIGNAL(result(KJob*)), this, SLOT(slotGotFile(KJob*)));
286 void ResourceWidget::slotGotFile(KJob *job)
288 if (job->error() != 0 ) return;
289 KIO::FileCopyJob* copyJob = static_cast<KIO::FileCopyJob*>( job );
290 const KUrl filePath = copyJob->destUrl();
292 #if KDE_IS_VERSION(4,6,0)
293 Nepomuk::Resource res( filePath );
294 res.setProperty( Nepomuk::Vocabulary::NIE::license(), (Nepomuk::Variant) job->property("license") );
295 res.setProperty( Nepomuk::Vocabulary::NIE::licenseType(), (Nepomuk::Variant) job->property("licenseurl") );
296 res.setProperty( Nepomuk::Vocabulary::NDO::copiedFrom(), (Nepomuk::Variant) job->property("originurl") );
297 res.setProperty( Nepomuk::Vocabulary::NCO::creator(), (Nepomuk::Variant) job->property("author") );
298 //res.setDescription(item_description->toPlainText());
299 //res.setProperty( Soprano::Vocabulary::NAO::description(),
303 #ifdef USE_NEPOMUKCORE
304 Nepomuk2::Resource res( filePath );
305 res.setProperty( Nepomuk2::Vocabulary::NIE::license(), (Nepomuk2::Variant) job->property("license") );
306 res.setProperty( Nepomuk2::Vocabulary::NIE::licenseType(), (Nepomuk2::Variant) job->property("licenseurl") );
307 res.setProperty( Nepomuk2::Vocabulary::NDO::copiedFrom(), (Nepomuk2::Variant) job->property("originurl") );
308 res.setProperty( Nepomuk2::Vocabulary::NCO::creator(), (Nepomuk2::Variant) job->property("author") );
309 //res.setDescription(item_description->toPlainText());
310 //res.setProperty( Soprano::Vocabulary::NAO::description(),
313 emit addClip(filePath, stringMap());
316 void ResourceWidget::slotOpenUrl(const QString &url)
318 new KRun(KUrl(url), this);
321 void ResourceWidget::slotChangeService()
323 delete m_currentService;
324 m_currentService = NULL;
325 SERVICETYPE service = (SERVICETYPE) service_list->itemData(service_list->currentIndex()).toInt();
326 if (service == FREESOUND) {
327 m_currentService = new FreeSound(search_results);
328 } else if (service == OPENCLIPART) {
329 m_currentService = new OpenClipArt(search_results);
330 } else if (service == ARCHIVEORG) {
331 m_currentService = new ArchiveOrg(search_results);
334 connect(m_currentService, SIGNAL(gotMetaInfo(QString)), this, SLOT(slotSetMetadata(QString)));
335 connect(m_currentService, SIGNAL(gotMetaInfo(QMap<QString,QString>)), this, SLOT(slotDisplayMetaInfo(QMap<QString,QString>)));
336 connect(m_currentService, SIGNAL(maxPages(int)), this, SLOT(slotSetMaximum(int)));
337 connect(m_currentService, SIGNAL(searchInfo(QString)), search_info, SLOT(setText(QString)));
338 connect(m_currentService, SIGNAL(gotThumb(QString)), this, SLOT(slotLoadThumb(QString)));
339 #if KDE_IS_VERSION(4,4,0)
340 connect(m_currentService, SIGNAL(searchDone()), m_busyWidget, SLOT(stop()));
343 button_preview->setVisible(m_currentService->hasPreview);
344 button_import->setVisible(!m_currentService->inlineDownload);
345 search_info->setText(QString());
346 if (!search_text->text().isEmpty())
350 void ResourceWidget::slotSetMaximum(int max)
352 page_number->setMaximum(max);
355 void ResourceWidget::slotOnline()
357 button_search->setEnabled(true);
358 search_info->setText(QString());
361 void ResourceWidget::slotOffline()
363 button_search->setEnabled(false);
364 search_info->setText(i18n("You need to be online\n for searching"));
367 void ResourceWidget::slotNextPage()
369 const int ix = page_number->value();
370 if (search_results->count() > 0)
371 page_number->setValue(ix + 1);
374 void ResourceWidget::slotPreviousPage()
376 const int ix = page_number->value();
378 page_number->setValue(ix - 1);
381 void ResourceWidget::parseLicense(const QString &licenseUrl)
384 if (licenseUrl.contains("/sampling+/"))
385 licenseName = "Sampling+";
386 else if (licenseUrl.contains("/by/"))
387 licenseName = "Attribution";
388 else if (licenseUrl.contains("/by-nd/"))
389 licenseName = "Attribution-NoDerivs";
390 else if (licenseUrl.contains("/by-nc-sa/"))
391 licenseName = "Attribution-NonCommercial-ShareAlike";
392 else if (licenseUrl.contains("/by-sa/"))
393 licenseName = "Attribution-ShareAlike";
394 else if (licenseUrl.contains("/by-nc/"))
395 licenseName = "Attribution-NonCommercial";
396 else if (licenseUrl.contains("/by-nc-nd/"))
397 licenseName = "Attribution-NonCommercial-NoDerivs";
398 else if (licenseUrl.contains("/publicdomain/zero/"))
399 licenseName = "Creative Commons 0";
400 else if (licenseUrl.endsWith("/publicdomain"))
401 licenseName = "Public Domain";
402 else licenseName = i18n("Unknown");
403 item_license->setText(licenseName);
404 item_license->setUrl(licenseUrl);
408 void ResourceWidget::slotOpenLink(const QUrl &url)
410 QString path = url.toEncoded();
411 if (path.endsWith("_import")) {
413 // import file in Kdenlive
421 void ResourceWidget::slotSetDescription(const QString &desc)
429 void ResourceWidget::slotSetMetadata(const QString &desc)
431 if (m_meta != desc) {
437 void ResourceWidget::slotSetImage(const QString &desc)
439 m_image = QString::fromLatin1("<img src=\"%1\" style=\"max-height:150px\" max-width=\"%2px\" />").arg(desc).arg((int) (info_browser->width() * 0.9));
443 void ResourceWidget::slotSetTitle(const QString &desc)
445 if (m_title != desc) {
451 void ResourceWidget::updateLayout()
453 QString content = m_title;
454 if (!m_image.isEmpty())
455 content.append(m_image + "<br clear=\"all\" />");
456 if (!m_desc.isEmpty())
457 content.append(m_desc);
458 if (!m_meta.isEmpty())
459 content.append(m_meta);
460 info_browser->setHtml(content);
464 #include "resourcewidget.moc"