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"
26 #include <QPushButton>
28 #include <QListWidget>
29 #include <QDomDocument>
32 #include "kdenlivesettings.h"
33 #include <KGlobalSettings>
34 #include <KMessageBox>
35 #include <KFileDialog>
37 #include <KIO/NetAccess>
38 #include <Solid/Networking>
41 #ifdef USE_NEPOMUK AND KDE_IS_VERSION(4,6,0)
42 #include <Nepomuk/Variant>
43 #include <Nepomuk/Resource>
44 #include <Nepomuk/ResourceManager>
45 #include <Soprano/Vocabulary/NAO>
46 #include <Nepomuk/Vocabulary/NIE>
47 #include <Nepomuk/Vocabulary/NDO>
50 ResourceWidget::ResourceWidget(const QString & folder, QWidget * parent) :
53 m_currentService(NULL)
55 setFont(KGlobalSettings::toolBarFont());
57 setAttribute(Qt::WA_DeleteOnClose);
59 service_list->addItem(i18n("Freesound Audio Library"), FREESOUND);
61 service_list->addItem(i18n("Open Clip Art Graphic Library"), OPENCLIPART);
62 setWindowTitle(i18n("Search Online Resources"));
63 info_widget->setStyleSheet(QString("QTreeWidget { background-color: transparent;}"));
64 item_description->setStyleSheet(QString("KTextBrowser { background-color: transparent;}"));
65 connect(button_search, SIGNAL(clicked()), this, SLOT(slotStartSearch()));
66 connect(search_results, SIGNAL(currentRowChanged(int)), this, SLOT(slotUpdateCurrentSound()));
67 connect(button_preview, SIGNAL(clicked()), this, SLOT(slotPlaySound()));
68 connect(button_import, SIGNAL(clicked()), this, SLOT(slotSaveSound()));
69 connect(sound_author, SIGNAL(leftClickedUrl(const QString &)), this, SLOT(slotOpenUrl(const QString &)));
70 connect(item_license, SIGNAL(leftClickedUrl(const QString &)), this, SLOT(slotOpenUrl(const QString &)));
71 connect(sound_name, SIGNAL(leftClickedUrl(const QString &)), this, SLOT(slotOpenUrl(const QString &)));
72 connect(service_list, SIGNAL(currentIndexChanged(int)), this, SLOT(slotChangeService()));
73 sound_image->setFixedWidth(180);
74 if (Solid::Networking::status() == Solid::Networking::Unconnected) {
77 connect(Solid::Networking::notifier(), SIGNAL(shouldConnect()), this, SLOT(slotOnline()));
78 connect(Solid::Networking::notifier(), SIGNAL(shouldDisconnect()), this, SLOT(slotOffline()));
79 connect(page_next, SIGNAL(clicked()), this, SLOT(slotNextPage()));
80 connect(page_prev, SIGNAL(clicked()), this, SLOT(slotPreviousPage()));
81 connect(page_number, SIGNAL(valueChanged(int)), this, SLOT(slotStartSearch(int)));
82 sound_box->setEnabled(false);
83 search_text->setFocus();
84 #ifdef USE_NEPOMUK AND KDE_IS_VERSION(4,6,0)
85 Nepomuk::ResourceManager::instance()->init();
90 ResourceWidget::~ResourceWidget()
92 if (m_currentService) delete m_currentService;
95 void ResourceWidget::slotStartSearch(int page)
97 /*m_currentPreview.clear();
98 m_currentUrl.clear();*/
99 page_number->blockSignals(true);
100 page_number->setValue(page);
101 page_number->blockSignals(false);
102 m_currentService->slotStartSearch(search_text->text(), page);
104 if (m_service == FREESOUND) {
105 uri = "http://www.freesound.org/api/sounds/search/?q=";
106 uri.append(search_text->text());
107 if (page > 1) uri.append("&p=" + QString::number(page));
108 uri.append("&api_key=a1772c8236e945a4bee30a64058dabf8");
110 else if (m_service == OPENCLIPART) {
111 uri = "http://openclipart.org/api/search/?query=";
112 uri.append(search_text->text());
113 if (page > 1) uri.append("&page=" + QString::number(page));
117 void ResourceWidget::slotUpdateCurrentSound()
119 if (!sound_autoplay->isChecked()) m_currentService->stopItemPreview(NULL);
120 info_widget->clear();
121 item_description->clear();
122 item_license->clear();
123 QListWidgetItem *item = search_results->currentItem();
125 sound_box->setEnabled(false);
128 m_currentInfo = m_currentService->displayItemDetails(item);
129 /*m_currentPreview = item->data(previewRole).toString();
130 m_currentUrl = item->data(downloadRole).toString();
131 m_currentId = item->data(idRole).toInt();*/
133 if (sound_autoplay->isChecked()) m_currentService->startItemPreview(item);
134 sound_box->setEnabled(true);
135 sound_name->setText(item->text());
136 sound_name->setUrl(m_currentInfo.infoUrl);
137 sound_author->setText(m_currentInfo.author);
138 sound_author->setUrl(m_currentInfo.authorUrl);
139 item_description->setHtml(m_currentInfo.description);
142 KUrl img(m_currentInfo.imagePreview);
143 if (img.isEmpty()) return;
144 if (KIO::NetAccess::exists(img, KIO::NetAccess::SourceSide, this)) {
146 if (KIO::NetAccess::download(img, tmpFile, this)) {
147 QPixmap pix(tmpFile);
148 int newHeight = pix.height() * sound_image->width() / pix.width();
149 if (newHeight > 200) {
150 sound_image->setScaledContents(false);
151 //sound_image->setFixedHeight(sound_image->width());
154 sound_image->setScaledContents(true);
155 sound_image->setFixedHeight(newHeight);
157 sound_image->setPixmap(pix);
158 KIO::NetAccess::removeTempFile(tmpFile);
164 void ResourceWidget::slotDisplayMetaInfo(QMap <QString, QString> metaInfo)
166 if (metaInfo.contains("description")) {
167 item_description->setHtml(metaInfo.value("description"));
168 metaInfo.remove("description");
170 if (metaInfo.contains("license")) {
171 parseLicense(metaInfo.value("license"));
172 metaInfo.remove("license");
174 QMap<QString, QString>::const_iterator i = metaInfo.constBegin();
175 while (i != metaInfo.constEnd()) {
176 new QTreeWidgetItem(info_widget, QStringList() << i.key() << i.value());
179 info_widget->resizeColumnToContents(0);
180 info_widget->resizeColumnToContents(1);
184 void ResourceWidget::slotPlaySound()
186 if (!m_currentService) return;
187 bool started = m_currentService->startItemPreview(search_results->currentItem());
188 if (started) button_preview->setText(i18n("Preview"));
189 else button_preview->setText(i18n("Stop"));
193 void ResourceWidget::slotForcePlaySound(bool play)
196 if (m_service != FREESOUND) return;
197 m_previewProcess->close();
198 if (m_currentPreview.isEmpty()) return;
200 m_previewProcess->start("ffplay", QStringList() << m_currentPreview << "-nodisp");
204 void ResourceWidget::slotPreviewStatusChanged(QProcess::ProcessState state)
206 /*if (state == QProcess::NotRunning)
207 button_preview->setText(i18n("Preview"));
209 button_preview->setText(i18n("Stop"));*/
212 void ResourceWidget::slotSaveSound()
214 //if (m_currentUrl.isEmpty()) return;
215 QListWidgetItem *item = search_results->currentItem();
217 QString path = m_folder;
218 if (!path.endsWith('/')) path.append('/');
219 path.append(m_currentService->getDefaultDownloadName(item));
220 QString ext = m_currentService->getExtension(search_results->currentItem());
221 QString saveUrl = KFileDialog::getSaveFileName(KUrl(path), ext);
222 if (saveUrl.isEmpty()) return;
223 if (KIO::NetAccess::download(KUrl(m_currentInfo.itemDownload), saveUrl, this)) {
224 const KUrl filePath = KUrl(saveUrl);
225 #ifdef USE_NEPOMUK AND KDE_IS_VERSION(4,6,0)
226 Nepomuk::Resource res( filePath );
227 res.setProperty( Nepomuk::Vocabulary::NIE::license(), (Nepomuk::Variant) item_license->text() );
228 res.setProperty( Nepomuk::Vocabulary::NIE::licenseType(), (Nepomuk::Variant) item_license->url() );
229 res.setProperty( Nepomuk::Vocabulary::NDO::copiedFrom(), sound_name->url() );
230 //res.setDescription(item_description->toPlainText());
231 //res.setProperty( Soprano::Vocabulary::NAO::description(),
233 emit addClip(KUrl(saveUrl), QString());//, sound_name->url());
237 void ResourceWidget::slotOpenUrl(const QString &url)
239 new KRun(KUrl(url), this);
242 void ResourceWidget::slotChangeService()
244 if (m_currentService) {
245 delete m_currentService;
246 m_currentService = NULL;
248 SERVICETYPE service = (SERVICETYPE) service_list->itemData(service_list->currentIndex()).toInt();
249 if (service == FREESOUND) {
250 m_currentService = new FreeSound(search_results);
252 else if (service == OPENCLIPART) {
253 m_currentService = new OpenClipArt(search_results);
255 connect(m_currentService, SIGNAL(gotMetaInfo(QMap <QString, QString>)), this, SLOT(slotDisplayMetaInfo(QMap <QString, QString>)));
256 connect(m_currentService, SIGNAL(maxPages(int)), page_number, SLOT(setMaximum(int)));
257 connect(m_currentService, SIGNAL(searchInfo(QString)), search_info, SLOT(setText(QString)));
259 button_preview->setVisible(m_currentService->hasPreview);
260 sound_autoplay->setVisible(m_currentService->hasPreview);
261 search_info->setText(QString());
262 info_widget->setVisible(m_currentService->hasMetadata);
263 if (!search_text->text().isEmpty()) slotStartSearch();
266 void ResourceWidget::slotOnline()
268 button_search->setEnabled(true);
269 search_info->setText(QString());
272 void ResourceWidget::slotOffline()
274 button_search->setEnabled(false);
275 search_info->setText(i18n("You need to be online\n for searching"));
278 void ResourceWidget::slotNextPage()
280 int ix = page_number->value();
281 if (search_results->count() > 0) page_number->setValue(ix + 1);
284 void ResourceWidget::slotPreviousPage()
286 int ix = page_number->value();
287 if (ix > 1) page_number->setValue(ix - 1);
290 void ResourceWidget::parseLicense(const QString &licenseUrl)
293 if (licenseUrl.contains("/sampling+/"))
294 licenseName = "Sampling+";
295 else if (licenseUrl.contains("/by/"))
296 licenseName = "Attribution";
297 else if (licenseUrl.contains("/by-nd/"))
298 licenseName = "Attribution-NoDerivs";
299 else if (licenseUrl.contains("/by-nc-sa/"))
300 licenseName = "Attribution-NonCommercial-ShareAlike";
301 else if (licenseUrl.contains("/by-sa/"))
302 licenseName = "Attribution-ShareAlike";
303 else if (licenseUrl.contains("/by-nc/"))
304 licenseName = "Attribution-NonCommercial";
305 else if (licenseUrl.contains("/by-nc-nd/"))
306 licenseName = "Attribution-NonCommercial-NoDerivs";
307 else if (licenseUrl.contains("/publicdomain/zero/"))
308 licenseName = "Creative Commons 0";
309 else if (licenseUrl.endsWith("/publicdomain"))
310 licenseName = "Public Domain";
311 item_license->setText(i18n("License: %1", licenseName));
312 item_license->setUrl(licenseUrl);