]> git.sesse.net Git - kdenlive/blob - src/utils/resourcewidget.cpp
Initial support for project metadata (that can be embedded in rendered files)
[kdenlive] / src / utils / resourcewidget.cpp
1 /***************************************************************************
2  *   Copyright (C) 2011 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
3  *                                                                         *
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 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.                          *
14  *                                                                         *
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  ***************************************************************************/
20
21
22 #include "resourcewidget.h"
23 #include "freesound.h"
24 #include "openclipart.h"
25
26 #include <QPushButton>
27 #include <QSpinBox>
28 #include <QListWidget>
29 #include <QDomDocument>
30
31 #include <KDebug>
32 #include <kdeversion.h>
33 #include "kdenlivesettings.h"
34 #include <KGlobalSettings>
35 #include <KMessageBox>
36 #include <KFileDialog>
37 #include <kio/job.h>
38 #include <KIO/NetAccess>
39 #include <Solid/Networking>
40 #include <KRun>
41
42 #ifdef USE_NEPOMUK
43 #if KDE_IS_VERSION(4,6,0)
44 #include <Nepomuk/Variant>
45 #include <Nepomuk/Resource>
46 #include <Nepomuk/ResourceManager>
47 #include <Soprano/Vocabulary/NAO>
48 #include <Nepomuk/Vocabulary/NIE>
49 #include <Nepomuk/Vocabulary/NDO>
50 #endif
51 #endif
52
53 ResourceWidget::ResourceWidget(const QString & folder, QWidget * parent) :
54         QDialog(parent),
55         m_folder(folder),
56         m_currentService(NULL)
57 {
58     setFont(KGlobalSettings::toolBarFont());
59     setupUi(this);
60     setAttribute(Qt::WA_DeleteOnClose);
61 #ifdef USE_QJSON
62     service_list->addItem(i18n("Freesound Audio Library"), FREESOUND);
63 #endif
64     service_list->addItem(i18n("Open Clip Art Graphic Library"), OPENCLIPART);
65     setWindowTitle(i18n("Search Online Resources"));
66     info_widget->setStyleSheet(QString("QTreeWidget { background-color: transparent;}"));
67     item_description->setStyleSheet(QString("KTextBrowser { background-color: transparent;}"));
68     connect(button_search, SIGNAL(clicked()), this, SLOT(slotStartSearch()));
69     connect(search_results, SIGNAL(currentRowChanged(int)), this, SLOT(slotUpdateCurrentSound()));
70     connect(button_preview, SIGNAL(clicked()), this, SLOT(slotPlaySound()));
71     connect(button_import, SIGNAL(clicked()), this, SLOT(slotSaveSound()));
72     connect(sound_author, SIGNAL(leftClickedUrl(const QString &)), this, SLOT(slotOpenUrl(const QString &)));
73     connect(item_license, SIGNAL(leftClickedUrl(const QString &)), this, SLOT(slotOpenUrl(const QString &)));
74     connect(sound_name, SIGNAL(leftClickedUrl(const QString &)), this, SLOT(slotOpenUrl(const QString &)));
75     connect(service_list, SIGNAL(currentIndexChanged(int)), this, SLOT(slotChangeService()));
76     sound_image->setFixedWidth(180);
77     if (Solid::Networking::status() == Solid::Networking::Unconnected) {
78         slotOffline();
79     }
80     connect(Solid::Networking::notifier(), SIGNAL(shouldConnect()), this, SLOT(slotOnline()));
81     connect(Solid::Networking::notifier(), SIGNAL(shouldDisconnect()), this, SLOT(slotOffline()));
82     connect(page_next, SIGNAL(clicked()), this, SLOT(slotNextPage()));
83     connect(page_prev, SIGNAL(clicked()), this, SLOT(slotPreviousPage()));
84     connect(page_number, SIGNAL(valueChanged(int)), this, SLOT(slotStartSearch(int)));
85     sound_box->setEnabled(false);
86     search_text->setFocus();
87 #ifdef USE_NEPOMUK
88 #if KDE_IS_VERSION(4,6,0)    
89     Nepomuk::ResourceManager::instance()->init();
90 #endif
91 #endif
92     slotChangeService();
93 }
94
95 ResourceWidget::~ResourceWidget()
96 {
97     if (m_currentService) delete m_currentService;
98 }
99
100 void ResourceWidget::slotStartSearch(int page)
101 {
102     page_number->blockSignals(true);
103     page_number->setValue(page);
104     page_number->blockSignals(false);
105     m_currentService->slotStartSearch(search_text->text(), page);
106 }
107
108 void ResourceWidget::slotUpdateCurrentSound()
109 {
110     if (!sound_autoplay->isChecked()) m_currentService->stopItemPreview(NULL);
111     info_widget->clear();
112     item_description->clear();
113     item_license->clear();
114     QListWidgetItem *item = search_results->currentItem();
115     if (!item) {
116         sound_box->setEnabled(false);
117         return;
118     }
119     m_currentInfo = m_currentService->displayItemDetails(item);
120     
121     if (sound_autoplay->isChecked()) m_currentService->startItemPreview(item);
122     sound_box->setEnabled(true);
123     sound_name->setText(item->text());
124     sound_name->setUrl(m_currentInfo.infoUrl);
125     sound_author->setText(m_currentInfo.author);
126     sound_author->setUrl(m_currentInfo.authorUrl);
127     item_description->setHtml(m_currentInfo.description);
128     
129
130     KUrl img(m_currentInfo.imagePreview);
131     if (img.isEmpty()) return;
132     if (KIO::NetAccess::exists(img, KIO::NetAccess::SourceSide, this)) {
133         QString tmpFile;
134         if (KIO::NetAccess::download(img, tmpFile, this)) {
135             QPixmap pix(tmpFile);
136             int newHeight = pix.height() * sound_image->width() / pix.width();
137             if (newHeight > 200) {
138                 sound_image->setScaledContents(false);
139                 //sound_image->setFixedHeight(sound_image->width());
140             }
141             else {
142                 sound_image->setScaledContents(true);
143                 sound_image->setFixedHeight(newHeight);
144             }
145             sound_image->setPixmap(pix);
146             KIO::NetAccess::removeTempFile(tmpFile);
147         }
148     }
149 }
150
151
152 void ResourceWidget::slotDisplayMetaInfo(QMap <QString, QString> metaInfo)
153 {
154     if (metaInfo.contains("description")) {
155         item_description->setHtml(metaInfo.value("description"));
156         metaInfo.remove("description");
157     }
158     if (metaInfo.contains("license")) {
159         parseLicense(metaInfo.value("license"));
160         metaInfo.remove("license");
161     }
162     QMap<QString, QString>::const_iterator i = metaInfo.constBegin();
163     while (i != metaInfo.constEnd()) {
164         new QTreeWidgetItem(info_widget, QStringList() << i.key() << i.value());
165         ++i;
166     }
167     info_widget->resizeColumnToContents(0);
168     info_widget->resizeColumnToContents(1);
169 }
170
171
172 void ResourceWidget::slotPlaySound()
173 {
174     if (!m_currentService) return;
175     bool started = m_currentService->startItemPreview(search_results->currentItem());
176     if (started) button_preview->setText(i18n("Preview"));
177     else button_preview->setText(i18n("Stop"));
178 }
179
180
181 void ResourceWidget::slotForcePlaySound(bool play)
182 {
183     /*
184     if (m_service != FREESOUND) return;
185     m_previewProcess->close();
186     if (m_currentPreview.isEmpty()) return;
187     if (play)
188         m_previewProcess->start("ffplay", QStringList() << m_currentPreview << "-nodisp");
189     */
190 }
191
192 void ResourceWidget::slotPreviewStatusChanged(QProcess::ProcessState state)
193 {
194     /*if (state == QProcess::NotRunning)
195         button_preview->setText(i18n("Preview"));
196     else 
197         button_preview->setText(i18n("Stop"));*/
198 }
199
200 void ResourceWidget::slotSaveSound()
201 {
202     //if (m_currentUrl.isEmpty()) return;
203     QListWidgetItem *item = search_results->currentItem();
204     if (!item) return;
205     QString path = m_folder;
206     if (!path.endsWith('/')) path.append('/');
207     path.append(m_currentService->getDefaultDownloadName(item));
208     QString ext = m_currentService->getExtension(search_results->currentItem());
209     QString saveUrl = KFileDialog::getSaveFileName(KUrl(path), ext);
210     if (saveUrl.isEmpty()) return;
211     if (KIO::NetAccess::download(KUrl(m_currentInfo.itemDownload), saveUrl, this)) {
212         const KUrl filePath = KUrl(saveUrl);
213 #ifdef USE_NEPOMUK
214 #if KDE_IS_VERSION(4,6,0)
215         Nepomuk::Resource res( filePath );
216         res.setProperty( Nepomuk::Vocabulary::NIE::license(), (Nepomuk::Variant) item_license->text() );
217         res.setProperty( Nepomuk::Vocabulary::NIE::licenseType(), (Nepomuk::Variant) item_license->url() );
218         res.setProperty( Nepomuk::Vocabulary::NDO::copiedFrom(), sound_name->url() );
219         //res.setDescription(item_description->toPlainText());
220         //res.setProperty( Soprano::Vocabulary::NAO::description(), 
221 #endif
222 #endif
223         emit addClip(KUrl(saveUrl), QString());//, sound_name->url());
224     }
225 }
226
227 void ResourceWidget::slotOpenUrl(const QString &url)
228 {
229     new KRun(KUrl(url), this);
230 }
231
232 void ResourceWidget::slotChangeService()
233 {
234     if (m_currentService) {
235         delete m_currentService;
236         m_currentService = NULL;
237     }
238     SERVICETYPE service = (SERVICETYPE) service_list->itemData(service_list->currentIndex()).toInt();
239     if (service == FREESOUND) {
240         m_currentService = new FreeSound(search_results);
241     }
242     else if (service == OPENCLIPART) {
243         m_currentService = new OpenClipArt(search_results);
244     }
245     connect(m_currentService, SIGNAL(gotMetaInfo(QMap <QString, QString>)), this, SLOT(slotDisplayMetaInfo(QMap <QString, QString>)));
246     connect(m_currentService, SIGNAL(maxPages(int)), page_number, SLOT(setMaximum(int)));
247     connect(m_currentService, SIGNAL(searchInfo(QString)), search_info, SLOT(setText(QString)));
248     
249     button_preview->setVisible(m_currentService->hasPreview);
250     sound_autoplay->setVisible(m_currentService->hasPreview);
251     search_info->setText(QString());
252     info_widget->setVisible(m_currentService->hasMetadata);
253     if (!search_text->text().isEmpty()) slotStartSearch();
254 }
255
256 void ResourceWidget::slotOnline()
257 {
258     button_search->setEnabled(true);
259     search_info->setText(QString());
260 }
261
262 void ResourceWidget::slotOffline()
263 {
264     button_search->setEnabled(false);
265     search_info->setText(i18n("You need to be online\n for searching"));
266 }
267
268 void ResourceWidget::slotNextPage()
269 {
270     int ix = page_number->value();
271     if (search_results->count() > 0) page_number->setValue(ix + 1);
272 }
273
274 void ResourceWidget::slotPreviousPage()
275 {
276     int ix = page_number->value();
277     if (ix > 1) page_number->setValue(ix - 1);
278 }
279
280 void ResourceWidget::parseLicense(const QString &licenseUrl)
281 {
282     QString licenseName;
283     if (licenseUrl.contains("/sampling+/"))
284         licenseName = "Sampling+";
285     else if (licenseUrl.contains("/by/"))
286         licenseName = "Attribution";
287     else if (licenseUrl.contains("/by-nd/"))
288         licenseName = "Attribution-NoDerivs";
289     else if (licenseUrl.contains("/by-nc-sa/"))
290         licenseName = "Attribution-NonCommercial-ShareAlike";
291     else if (licenseUrl.contains("/by-sa/"))
292         licenseName = "Attribution-ShareAlike";
293     else if (licenseUrl.contains("/by-nc/"))
294         licenseName = "Attribution-NonCommercial";
295     else if (licenseUrl.contains("/by-nc-nd/"))
296         licenseName = "Attribution-NonCommercial-NoDerivs";
297     else if (licenseUrl.contains("/publicdomain/zero/"))
298         licenseName = "Creative Commons 0";
299     else if (licenseUrl.endsWith("/publicdomain"))
300         licenseName = "Public Domain";
301     else licenseName = i18n("Unknown");
302     item_license->setText(licenseName);
303     item_license->setUrl(licenseUrl);
304 }
305