From: Jean-Baptiste Mardelle Date: Tue, 12 Jun 2012 13:14:12 +0000 (+0200) Subject: Warn user when adding a clip from a removable drive, and propose to copy clip to... X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=c4aeddbf6aa3f4aa787afda183046fc06cf41cd1;p=kdenlive Warn user when adding a clip from a removable drive, and propose to copy clip to project folder --- diff --git a/src/clipmanager.cpp b/src/clipmanager.cpp index ed7cbb0f..edd2ddfb 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(), @@ -464,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"); @@ -791,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; +} + + + diff --git a/src/clipmanager.h b/src/clipmanager.h index ce508927..624bb9b5 100644 --- a/src/clipmanager.h +++ b/src/clipmanager.h @@ -38,6 +38,7 @@ #include #include #include +#include #if KDE_IS_VERSION(4,5,0) #include @@ -52,6 +53,21 @@ class KdenliveDoc; class DocClipBase; class AbstractGroupItem; + +class SolidVolumeInfo +{ + +public: + + QString path; // mount path of volume, with trailing slash + QString uuid; // UUID as from Solid + QString label; // volume label (think of CDs) + bool isRemovable; // may be removed + bool isMounted; + + bool isNull() const { return path.isNull(); } +}; + namespace Mlt { class Producer; @@ -125,6 +141,8 @@ private slots: void slotProcessModifiedClips(); void slotGetThumbs(); void slotGetAudioThumbs(); + /** @brief Clip has been copied, add it now. */ + void slotAddClip(KIO::Job *job, const KUrl &, const KUrl &dst); private: // Private attributes /** the list of clips in the document */ @@ -157,6 +175,13 @@ private: // Private attributes bool m_abortAudioThumb; /** @brief The id of currently processed clip for audio thumbs creation. */ QString m_processingAudioThumbId; + /** @brief The list of removable drives. */ + QList m_removableVolumes; + + /** @brief Get a list of drives, to check if we have files on removable media. */ + void listRemovableVolumes(); + /** @brief Check if added file is on a removable drive. */ + bool isOnRemovableDevice(const KUrl &url); signals: void reloadClip(const QString &);