]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/metadatawidget.cpp
- Fix crash found while investigating https://bugs.kde.org/show_bug.cgi?id=170927
[dolphin.git] / src / metadatawidget.cpp
index 4859a893c8acee43716a85ab45b970dfa3834e1b..218a6d1ce4e53de20ee2003a846499b5e5a4b227 100644 (file)
  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
  ***************************************************************************/
 
-#include <config-kmetadata.h>
-
 #include "metadatawidget.h"
 
+#include "commentwidget.h"
+
+#include <config-nepomuk.h>
+
 #include <klocale.h>
+#include <KDebug>
+#include <KMessageBox>
 
-#include <QLabel>
-#include <QGridLayout>
-#include <QTextEdit>
-
-#ifdef HAVE_KMETADATA
-#include <kmetadata/kmetadatatagwidget.h>
-#include <kmetadata/resourcemanager.h>
-#include <kmetadata/resource.h>
-#include <kmetadata/variant.h>
-#include <kmetadata/kratingwidget.h>
-#include <kmetadata/kmetadatatagwidget.h>
-#endif
+#include <QtCore/QEvent>
+#include <QtCore/QMutex>
+#include <QtCore/QMutexLocker>
+#include <QtCore/QThread>
+#include <QtGui/QLabel>
+#include <QtGui/QGridLayout>
+#include <QtGui/QTextEdit>
 
-// FIXME: these should be replaced by using KMetaData::File once it is available again
-static const char* s_nfoFile = "http://ont.semanticdesktop.org/2007/03/22/nfo#File";
-static const char* s_nfoFileUrl = "http://ont.semanticdesktop.org/2007/03/22/nfo#fileUrl";
+#ifdef HAVE_NEPOMUK
+#include "nepomukmassupdatejob.h"
+#include <nepomuk/kmetadatatagwidget.h>
+#include <nepomuk/resourcemanager.h>
+#include <nepomuk/resource.h>
+#include <nepomuk/variant.h>
+#include <nepomuk/kratingwidget.h>
+#include <Soprano/Vocabulary/Xesam>
+#include "tagcloud/resourcetaggingwidget.h"
+#endif
 
 
 bool MetaDataWidget::metaDataAvailable()
 {
-#ifdef HAVE_KMETADATA
-    return !Nepomuk::KMetaData::ResourceManager::instance()->init();
+#ifdef HAVE_NEPOMUK
+    return !Nepomuk::ResourceManager::instance()->init();
 #else
     return false;
 #endif
@@ -54,57 +60,130 @@ bool MetaDataWidget::metaDataAvailable()
 class MetaDataWidget::Private
 {
 public:
-#ifdef HAVE_KMETADATA
-    void loadComment(const QString& comment)
-    {
-        editComment->blockSignals(true);
-        if (comment.isEmpty()) {
-            editComment->setFontItalic(true);
-            editComment->setText(i18n("Click to add comment..."));
-        } else {
-            editComment->setFontItalic(false);
-            editComment->setText(comment);
-        }
-        editComment->blockSignals(false);
-    }
-
-    KUrl fileUrl;
-
-    Nepomuk::KMetaData::Resource file;
+#ifdef HAVE_NEPOMUK
+    void loadComment(const QString& comment);
 
-    QTextEdit* editComment;
+    CommentWidget* editComment;
     KRatingWidget* ratingWidget;
-    Nepomuk::KMetaData::TagWidget* tagWidget;
+    Nepomuk::ResourceTaggingWidget* tagWidget;
+    
+    // shared data between the GUI-thread and
+    // the loader-thread (see LoadFilesThread):
+    QMutex mutex;
+    struct SharedData
+    {
+        int rating;
+        QString comment;
+        QList<Nepomuk::Resource> fileRes;
+        QMap<KUrl, Nepomuk::Resource> files;
+    } sharedData;
+    
+    /**
+     * Loads the meta data of files and writes
+     * the result into a shared data pool that
+     * can be used by the widgets in the GUI thread.
+     */
+    class LoadFilesThread : public QThread
+    {
+    public:
+        LoadFilesThread(SharedData* sharedData, QMutex* mutex);
+        void setFiles(const KUrl::List& urls);
+        virtual void run();
+        
+    private:
+        SharedData* m_sharedData;
+        QMutex* m_mutex;
+        KUrl::List m_urls;
+    };
+    
+    LoadFilesThread* loadFilesThread;
 #endif
 };
 
+#ifdef HAVE_NEPOMUK
+void MetaDataWidget::Private::loadComment(const QString& comment)
+{
+    editComment->setComment( comment );
+}
+
+MetaDataWidget::Private::LoadFilesThread::LoadFilesThread(
+    MetaDataWidget::Private::SharedData* sharedData,
+    QMutex* mutex) :
+    m_sharedData(sharedData),
+    m_mutex(mutex),
+    m_urls()
+{
+}
+
+void MetaDataWidget::Private::LoadFilesThread::setFiles(const KUrl::List& urls)
+{
+    QMutexLocker locker( m_mutex );
+    m_urls = urls;
+}
 
-MetaDataWidget::MetaDataWidget(QWidget* parent)
-        : QWidget(parent)
+void MetaDataWidget::Private::LoadFilesThread::run()
 {
-#ifdef HAVE_KMETADATA
+    QMutexLocker locker( m_mutex );
+    const KUrl::List urls = m_urls;
+    locker.unlock();
+    
+    bool first = true;
+    QList<Nepomuk::Resource> fileRes;
+    QMap<KUrl, Nepomuk::Resource> files;
+    unsigned int rating = 0;
+    QString comment;
+    Q_FOREACH( const KUrl &url, urls ) {
+        Nepomuk::Resource file( url, Soprano::Vocabulary::Xesam::File() );
+        files.insert( url, file );
+        fileRes.append( file );
+
+        if ( !first && rating != file.rating() ) {
+            rating = 0; // reset rating
+        }
+        else if ( first ) {
+            rating = file.rating();
+        }
+
+        if ( !first && comment != file.description() ) {
+            comment.clear();
+        }
+        else if ( first ) {
+            comment = file.description();
+        }
+        first = false;
+    }
+    
+    locker.relock();
+    m_sharedData->rating = rating;
+    m_sharedData->comment = comment;
+    m_sharedData->fileRes = fileRes;
+    m_sharedData->files = files;
+}
+#endif
+
+MetaDataWidget::MetaDataWidget(QWidget* parent) :
+    QWidget(parent)
+{
+#ifdef HAVE_NEPOMUK
     d = new Private;
-    d->editComment = new QTextEdit(this);
-    d->tagWidget = new Nepomuk::KMetaData::TagWidget(this);
+    d->editComment = new CommentWidget(this);
+    d->editComment->setFocusPolicy(Qt::ClickFocus);
     d->ratingWidget = new KRatingWidget(this);
-    connect(d->ratingWidget, SIGNAL(ratingChanged(int)), this, SLOT(slotRatingChanged(int)));
-    connect(d->editComment, SIGNAL(textChanged()), this, SLOT(slotCommentChanged()));
+    d->ratingWidget->setAlignment( Qt::AlignCenter );
+    d->tagWidget = new Nepomuk::ResourceTaggingWidget(this);
+    connect(d->ratingWidget, SIGNAL(ratingChanged(unsigned int)), this, SLOT(slotRatingChanged(unsigned int)));
+    connect(d->editComment, SIGNAL(commentChanged(const QString&)), this, SLOT(slotCommentChanged(const QString&)));
+    connect( d->tagWidget, SIGNAL( tagClicked( const Nepomuk::Tag& ) ), this, SLOT( slotTagClicked( const Nepomuk::Tag& ) ) );
+    
+    d->sharedData.rating = 0;
+    d->loadFilesThread = new Private::LoadFilesThread(&d->sharedData, &d->mutex);
+    connect(d->loadFilesThread, SIGNAL(finished()), this, SLOT(slotLoadingFinished()));
 
     QVBoxLayout* lay = new QVBoxLayout(this);
     lay->setMargin(0);
-    QHBoxLayout* hbox = new QHBoxLayout;
-    hbox->addWidget(new QLabel(i18n("Rating:"), this));
-    hbox->addStretch(1);
-    hbox->addWidget(d->ratingWidget);
-    lay->addLayout(hbox);
+    lay->addWidget(d->ratingWidget);
     lay->addWidget(d->editComment);
-    hbox = new QHBoxLayout;
-    hbox->addWidget(new QLabel(i18n("Tags:"), this));
-    hbox->addWidget(d->tagWidget, 1);
-    lay->addLayout(hbox);
-
-    d->editComment->installEventFilter(this);
-    d->editComment->viewport()->installEventFilter(this);
+    lay->addWidget( d->tagWidget );
 #else
     d = 0;
 #endif
@@ -113,67 +192,90 @@ MetaDataWidget::MetaDataWidget(QWidget* parent)
 
 MetaDataWidget::~MetaDataWidget()
 {
+#ifdef HAVE_NEPOMUK
+    delete d->loadFilesThread;
+#endif
     delete d;
 }
 
 
 void MetaDataWidget::setFile(const KUrl& url)
 {
-#ifdef HAVE_KMETADATA
-    // FIXME: replace with KMetaData::File once we have it again
-    d->fileUrl = url;
-    d->file = Nepomuk::KMetaData::Resource(url.url(), s_nfoFile);
-//    d->file.setLocation(url.url());
-    d->file.setProperty( s_nfoFileUrl, url.url() );
-    d->ratingWidget->setRating(d->file.rating());
-    d->tagWidget->setTaggedResource(d->file);
-    d->loadComment(d->file.description());
+    kDebug() << url;
+    KUrl::List urls;
+    urls.append( url );
+    setFiles( urls );
+}
+
+void MetaDataWidget::setFiles(const KUrl::List& urls)
+{
+#ifdef HAVE_NEPOMUK
+    d->loadFilesThread->setFiles( urls );
+    d->loadFilesThread->start();
+#else
+    Q_UNUSED( urls );
 #endif
 }
 
 
-void MetaDataWidget::setFiles(const KUrl::List urls)
+void MetaDataWidget::slotCommentChanged( const QString& s )
 {
-#ifdef HAVE_KMETADATA
-    // FIXME: support multiple files
-    setFile(urls.first());
+#ifdef HAVE_NEPOMUK
+    QMutexLocker locker( &d->mutex );
+    Nepomuk::MassUpdateJob* job = Nepomuk::MassUpdateJob::commentResources( d->sharedData.files.values(), s );
+    connect( job, SIGNAL( result( KJob* ) ),
+             this, SLOT( metadataUpdateDone() ) );
+    setEnabled( false ); // no updates during execution
+    job->start();
+#else
+    Q_UNUSED( s );
 #endif
 }
 
 
-void MetaDataWidget::slotCommentChanged()
+void MetaDataWidget::slotRatingChanged(unsigned int rating)
 {
-#ifdef HAVE_KMETADATA
-    d->file.setDescription(d->editComment->toPlainText());
+#ifdef HAVE_NEPOMUK
+    QMutexLocker locker( &d->mutex );
+    Nepomuk::MassUpdateJob* job = Nepomuk::MassUpdateJob::rateResources( d->sharedData.files.values(), rating );
+    connect( job, SIGNAL( result( KJob* ) ),
+             this, SLOT( metadataUpdateDone() ) );
+    setEnabled( false ); // no updates during execution
+    job->start();
+#else
+    Q_UNUSED( rating );
 #endif
 }
 
 
-void MetaDataWidget::slotRatingChanged(int r)
+void MetaDataWidget::metadataUpdateDone()
 {
-#ifdef HAVE_KMETADATA
-    d->file.setRating(r);
-#endif
+    setEnabled( true );
 }
 
 
 bool MetaDataWidget::eventFilter(QObject* obj, QEvent* event)
 {
-#ifdef HAVE_KMETADATA
-    if (obj == d->editComment->viewport()
-            || obj == d->editComment) {
-        if (event->type() == QEvent::FocusOut) {
-            // make sure the info text is displayed again
-            d->loadComment(d->editComment->toPlainText());
-        } else if (event->type() == QEvent::FocusIn) {
-            d->editComment->setFontItalic(false);
-            if (d->file.description().isEmpty())
-                d->editComment->setText(QString());
-        }
-    }
+    return QWidget::eventFilter(obj, event);
+}
+
+
+void MetaDataWidget::slotTagClicked( const Nepomuk::Tag& tag )
+{
+    Q_UNUSED( tag );
+#ifdef HAVE_NEPOMUK
+    d->tagWidget->showTagPopup( QCursor::pos() );
 #endif
+}
 
-    return QWidget::eventFilter(obj, event);
+void MetaDataWidget::slotLoadingFinished()
+{
+#ifdef HAVE_NEPOMUK
+    QMutexLocker locker( &d->mutex );
+    d->ratingWidget->setRating( d->sharedData.rating );
+    d->loadComment( d->sharedData.comment );
+    d->tagWidget->setResources( d->sharedData.fileRes );
+#endif
 }
 
 #include "metadatawidget.moc"