X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fclipmanager.cpp;h=13f4e5cf00d3332186ef08aac9a33d32e98ce366;hb=f41770656c58ffc541441d04a3845cd1005fcdcf;hp=af4522a6cdeb76c9dfc48d460195e920ee85a7ea;hpb=d18eaa998a96b0f8d9dd43e5b7dd2fb9574e71a1;p=kdenlive diff --git a/src/clipmanager.cpp b/src/clipmanager.cpp index af4522a6..13f4e5cf 100644 --- a/src/clipmanager.cpp +++ b/src/clipmanager.cpp @@ -35,12 +35,19 @@ #include #include #include +#include + +#include +#include +#include +#include #include #include #include + ClipManager::ClipManager(KdenliveDoc *doc) : QObject(), m_audioThumbsQueue(), @@ -54,7 +61,9 @@ ClipManager::ClipManager(KdenliveDoc *doc) : m_modifiedTimer.setInterval(1500); connect(&m_fileWatcher, SIGNAL(dirty(const QString &)), this, SLOT(slotClipModified(const QString &))); connect(&m_fileWatcher, SIGNAL(deleted(const QString &)), this, SLOT(slotClipMissing(const QString &))); - connect(&m_fileWatcher, SIGNAL(created(const QString &)), this, SLOT(slotClipAvailable(const QString &))); + + // Seems like a dirty signal is emitted anyways when a watched file is created, so don't react twice. + //connect(&m_fileWatcher, SIGNAL(created(const QString &)), this, SLOT(slotClipAvailable(const QString &))); connect(&m_modifiedTimer, SIGNAL(timeout()), this, SLOT(slotProcessModifiedClips())); #if KDE_IS_VERSION(4,5,0) @@ -305,7 +314,7 @@ void ClipManager::slotGetAudioThumbs() producer.seek(z); mlt_frame = producer.get_frame(); if (mlt_frame && mlt_frame->is_valid()) { - int samples = mlt_sample_calculator(framesPerSecond, frequency, mlt_frame_get_position(mlt_frame->get_frame())); + int samples = mlt_sample_calculator(framesPerSecond, frequency, mlt_frame->get_position()); qint16* pcm = static_cast(mlt_frame->get_audio(audioFormat, frequency, channels, samples)); for (int c = 0; c < channels; c++) { QByteArray audioArray; @@ -462,15 +471,43 @@ void ClipManager::resetProducersList(const QList prods, bool d emit checkAllClips(displayRatioChanged, fpsChanged, brokenClips); } +void ClipManager::slotAddClip(KIO::Job *job, const KUrl &, const KUrl &dst) +{ + KIO::MetaData meta = job->metaData(); + kDebug()<<"Finished copying: "<activeWindow(), i18n("Clip %1
already exists in project, what do you want to do?", file.path()), i18n("Clip already exists")) == KMessageBox::Cancel) continue; } + if (isOnRemovableDevice(file)) { + int answer = KMessageBox::warningYesNoCancel(kapp->activeWindow(), i18n("Clip %1
is on a removable device, will not be available when device is unplugged", file.path()), i18n("File on a Removable Device"), KGuiItem(i18n("Copy file to project folder")), KGuiItem(i18n("Continue")), KStandardGuiItem::cancel(), QString("copyFilesToProjectFolder")); + if (answer == KMessageBox::Cancel) continue; + else if (answer == KMessageBox::Yes) { + // Copy files to project folder + QString sourcesFolder = m_doc->projectFolder().path(KUrl::AddTrailingSlash) + "clips/"; + KIO::NetAccess::mkdir(sourcesFolder, kapp->activeWindow()); + //KIO::filesize_t m_requestedSize; + KIO::CopyJob *copyjob = KIO::copy (file, KUrl(sourcesFolder)); + //TODO: for some reason, passing metadata does not work... + copyjob->addMetaData("group", group); + copyjob->addMetaData("groupId", groupId); + copyjob->addMetaData("comment", comment); + copyjob->ui()->setWindow(kapp->activeWindow()); + connect(copyjob, SIGNAL(copyingDone(KIO::Job *, const KUrl &, const KUrl &, time_t, bool, bool)), this, SLOT(slotAddClip(KIO::Job *, const KUrl &, const KUrl &))); + continue; + } + } kDebug() << "Adding clip: " << file.path(); QDomDocument doc; QDomElement prod = doc.createElement("producer"); @@ -494,7 +531,7 @@ void ClipManager::slotAddClipList(const KUrl::List urls, const QString &group, c KFileMetaInfo metaInfo(file.path(), QString("image/jpeg"), KFileMetaInfo::TechnicalInfo); const QHash metaInfoItems = metaInfo.items(); foreach(const KFileMetaInfoItem & metaInfoItem, metaInfoItems) { - prod.setAttribute("meta.attr." + metaInfoItem.name().section("#", 1), metaInfoItem.value().toString()); + prod.setAttribute("meta.attr." + metaInfoItem.name().section('#', 1), metaInfoItem.value().toString()); } } } else if (type->is("application/x-kdenlivetitle")) { @@ -789,3 +826,90 @@ int ClipManager::clipsCount() const } +void ClipManager::listRemovableVolumes() +{ + QList volumes; + m_removableVolumes.clear(); + + QList devices = Solid::Device::listFromType(Solid::DeviceInterface::StorageAccess); + + foreach(const Solid::Device &accessDevice, devices) + { + // check for StorageAccess + if (!accessDevice.is()) + continue; + + const Solid::StorageAccess *access = accessDevice.as(); + + if (!access->isAccessible()) + continue; + + // check for StorageDrive + Solid::Device driveDevice; + for (Solid::Device currentDevice = accessDevice; currentDevice.isValid(); currentDevice = currentDevice.parent()) + { + if (currentDevice.is()) + { + driveDevice = currentDevice; + break; + } + } + if (!driveDevice.isValid()) + continue; + + Solid::StorageDrive *drive = driveDevice.as(); + if (!drive->isRemovable()) continue; + + // check for StorageVolume + Solid::Device volumeDevice; + for (Solid::Device currentDevice = accessDevice; currentDevice.isValid(); currentDevice = currentDevice.parent()) + { + if (currentDevice.is()) + { + volumeDevice = currentDevice; + break; + } + } + if (!volumeDevice.isValid()) + continue; + + Solid::StorageVolume *volume = volumeDevice.as(); + + SolidVolumeInfo info; + info.path = access->filePath(); + info.isMounted = access->isAccessible(); + if (!info.path.isEmpty() && !info.path.endsWith('/')) + info.path += '/'; + info.uuid = volume->uuid(); + info.label = volume->label(); + info.isRemovable = drive->isRemovable(); + m_removableVolumes << info; + } +} + +bool ClipManager::isOnRemovableDevice(const KUrl &url) +{ + SolidVolumeInfo volume; + QString path = url.path(KUrl::RemoveTrailingSlash); + int volumeMatch = 0; + + //FIXME: Network shares! Here we get only the volume of the mount path... + // This is probably not really clean. But Solid does not help us. + foreach (const SolidVolumeInfo &v, m_removableVolumes) + { + if (v.isMounted && !v.path.isEmpty() && path.startsWith(v.path)) + { + int length = v.path.length(); + if (length > volumeMatch) + { + volumeMatch = v.path.length(); + volume = v; + } + } + } + + return volumeMatch; +} + + +