+QString ClipManager::projectFolder() const
+{
+ return m_doc->projectFolder().path();
+}
+
+void ClipManager::addFolder(const QString &id, const QString &name)
+{
+ m_folderList.insert(id, name);
+}
+
+void ClipManager::deleteFolder(const QString &id)
+{
+ m_folderList.remove(id);
+}
+
+AbstractGroupItem *ClipManager::createGroup()
+{
+ AbstractGroupItem *group = new AbstractGroupItem(m_doc->fps());
+ m_groupsList.append(group);
+ return group;
+}
+
+void ClipManager::removeGroup(AbstractGroupItem *group)
+{
+ m_groupsList.removeAll(group);
+}
+
+QDomElement ClipManager::groupsXml() const
+{
+ QDomDocument doc;
+ QDomElement groups = doc.createElement("groups");
+ doc.appendChild(groups);
+ for (int i = 0; i < m_groupsList.count(); ++i) {
+ QDomElement group = doc.createElement("group");
+ groups.appendChild(group);
+ QList <QGraphicsItem *> children = m_groupsList.at(i)->childItems();
+ for (int j = 0; j < children.count(); j++) {
+ if (children.at(j)->type() == AVWidget || children.at(j)->type() == TransitionWidget) {
+ AbstractClipItem *item = static_cast <AbstractClipItem *>(children.at(j));
+ ItemInfo info = item->info();
+ if (item->type() == AVWidget) {
+ QDomElement clip = doc.createElement("clipitem");
+ clip.setAttribute("track", info.track);
+ clip.setAttribute("position", info.startPos.frames(m_doc->fps()));
+ group.appendChild(clip);
+ } else if (item->type() == TransitionWidget) {
+ QDomElement clip = doc.createElement("transitionitem");
+ clip.setAttribute("track", info.track);
+ clip.setAttribute("position", info.startPos.frames(m_doc->fps()));
+ group.appendChild(clip);
+ }
+ }
+ }
+ }
+ return doc.documentElement();
+}
+
+
+void ClipManager::slotClipModified(const QString &path)
+{
+ //kDebug() << "// CLIP: " << path << " WAS MODIFIED";
+ const QList <DocClipBase *> list = getClipByResource(path);
+ for (int i = 0; i < list.count(); ++i) {
+ DocClipBase *clip = list.at(i);
+ if (clip != NULL) {
+ QString id = clip->getId();
+ if (!m_modifiedClips.contains(id))
+ emit modifiedClip(id);
+ m_modifiedClips[id] = QTime::currentTime();
+ }
+ }
+ if (!m_modifiedTimer.isActive()) m_modifiedTimer.start();
+}
+
+void ClipManager::slotProcessModifiedClips()
+{
+ if (!m_modifiedClips.isEmpty()) {
+ QMapIterator<QString, QTime> i(m_modifiedClips);
+ while (i.hasNext()) {
+ i.next();
+ if (QTime::currentTime().msecsTo(i.value()) <= -1500) {
+ emit reloadClip(i.key());
+ m_modifiedClips.remove(i.key());
+ break;
+ }
+ }
+ }
+ if (m_modifiedClips.isEmpty()) m_modifiedTimer.stop();
+}
+
+void ClipManager::slotClipMissing(const QString &path)
+{
+ // kDebug() << "// CLIP: " << path << " WAS MISSING";
+ const QList <DocClipBase *> list = getClipByResource(path);
+ for (int i = 0; i < list.count(); ++i) {
+ DocClipBase *clip = list.at(i);
+ if (clip != NULL) emit missingClip(clip->getId());
+ }
+}
+
+void ClipManager::slotClipAvailable(const QString &path)
+{
+ // kDebug() << "// CLIP: " << path << " WAS ADDED";
+ const QList <DocClipBase *> list = getClipByResource(path);
+ for (int i = 0; i < list.count(); ++i) {
+ DocClipBase *clip = list.at(i);
+ if (clip != NULL) emit availableClip(clip->getId());
+ }
+}
+
+int ClipManager::clipsCount() const
+{
+ return m_clipList.count();
+}
+
+
+void ClipManager::listRemovableVolumes()
+{
+ QList<SolidVolumeInfo> volumes;
+ m_removableVolumes.clear();
+
+ QList<Solid::Device> devices = Solid::Device::listFromType(Solid::DeviceInterface::StorageAccess);
+
+ foreach(const Solid::Device &accessDevice, devices)
+ {
+ // check for StorageAccess
+ if (!accessDevice.is<Solid::StorageAccess>())
+ continue;
+
+ const Solid::StorageAccess *access = accessDevice.as<Solid::StorageAccess>();
+
+ if (!access->isAccessible())
+ continue;
+
+ // check for StorageDrive
+ Solid::Device driveDevice;
+ for (Solid::Device currentDevice = accessDevice; currentDevice.isValid(); currentDevice = currentDevice.parent())
+ {
+ if (currentDevice.is<Solid::StorageDrive>())
+ {
+ driveDevice = currentDevice;
+ break;
+ }
+ }
+ if (!driveDevice.isValid())
+ continue;
+
+ Solid::StorageDrive *drive = driveDevice.as<Solid::StorageDrive>();
+ if (!drive->isRemovable()) continue;
+
+ // check for StorageVolume
+ Solid::Device volumeDevice;
+ for (Solid::Device currentDevice = accessDevice; currentDevice.isValid(); currentDevice = currentDevice.parent())
+ {
+ if (currentDevice.is<Solid::StorageVolume>())
+ {
+ volumeDevice = currentDevice;
+ break;
+ }
+ }
+ if (!volumeDevice.isValid())
+ continue;
+
+ Solid::StorageVolume *volume = volumeDevice.as<Solid::StorageVolume>();
+
+ 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;
+}
+
+void ClipManager::projectTreeThumbReady(const QString &id, int frame, const QImage &img, int type)
+{
+ switch (type) {
+ case 2:
+ emit gotClipPropertyThumbnail(id, img);
+ break;
+ default:
+ emit thumbReady(id, frame, img);
+ }
+}
+