File indexing completed on 2023-05-30 11:30:46

0001 /**
0002  * Copyright (C) 2004 Scott Wheeler <wheeler@kde.org>
0003  * Copyright (C) 2017 Michael Pyne  <mpyne@kde.org>
0004  *
0005  * This program is free software; you can redistribute it and/or modify it under
0006  * the terms of the GNU General Public License as published by the Free Software
0007  * Foundation; either version 2 of the License, or (at your option) any later
0008  * version.
0009  *
0010  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0012  * PARTICULAR PURPOSE. See the GNU General Public License for more details.
0013  *
0014  * You should have received a copy of the GNU General Public License along with
0015  * this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 #include "filehandle.h"
0019 
0020 #include <QFileInfo>
0021 #include <QSharedData>
0022 #include <QScopedPointer>
0023 
0024 #include "filehandleproperties.h"
0025 #include "juktag.h"
0026 #include "cache.h"
0027 #include "coverinfo.h"
0028 #include "juk_debug.h"
0029 
0030 AddProperty(Title, tag()->title())
0031 AddProperty(Artist, tag()->artist())
0032 AddProperty(Album, tag()->album())
0033 AddProperty(Genre, tag()->genre())
0034 AddNumberProperty(Track, tag()->track())
0035 AddNumberProperty(Year, tag()->year())
0036 AddProperty(Comment, tag()->comment())
0037 AddNumberProperty(Seconds, tag()->seconds())
0038 AddNumberProperty(Bitrate, tag()->bitrate())
0039 AddProperty(Path, absFilePath())
0040 AddNumberProperty(Size, fileInfo().size())
0041 AddProperty(Extension, fileInfo().suffix())
0042 
0043 class FileHandle::FileHandlePrivate : public QSharedData
0044 {
0045 public:
0046     FileHandlePrivate(QFileInfo fInfo)
0047         : tag(nullptr)
0048         , coverInfo(nullptr)
0049         , fileInfo(fInfo)
0050         , absFilePath(fInfo.canonicalFilePath())
0051     {
0052         baseModificationTime = fileInfo.lastModified();
0053     }
0054 
0055     mutable QScopedPointer<Tag> tag;
0056     mutable QScopedPointer<CoverInfo> coverInfo;
0057     QFileInfo fileInfo;
0058     QString absFilePath;
0059     QDateTime baseModificationTime;
0060     mutable QDateTime lastModified;
0061 };
0062 
0063 ////////////////////////////////////////////////////////////////////////////////
0064 // public methods
0065 ////////////////////////////////////////////////////////////////////////////////
0066 
0067 FileHandle::FileHandle(const FileHandle &f) :
0068     d(f.d)
0069 {
0070 }
0071 
0072 FileHandle::FileHandle(const QFileInfo &info) :
0073     d(new FileHandlePrivate(info))
0074 {
0075 }
0076 
0077 FileHandle::FileHandle()
0078     : FileHandle(QFileInfo()) // delegating ctor
0079 {
0080 }
0081 
0082 FileHandle::FileHandle(const QString &path)
0083     : FileHandle(QFileInfo(path)) // delegating ctor
0084 {
0085 }
0086 
0087 FileHandle::FileHandle(const QString &path, CacheDataStream &s)
0088     : FileHandle(QFileInfo(path)) // delegating ctor
0089 {
0090     if(d->fileInfo.exists())
0091         read(s);
0092 }
0093 
0094 FileHandle::~FileHandle() = default;
0095 
0096 void FileHandle::refresh()
0097 {
0098     d->fileInfo.refresh();
0099     d->tag.reset(new Tag(d->absFilePath));
0100 }
0101 
0102 void FileHandle::setFile(const QString &path)
0103 {
0104     if(path.isEmpty()) {
0105         qCCritical(JUK_LOG) << "trying to set an empty path";
0106         return;
0107     }
0108 
0109     if(!QFile::exists(path)) {
0110         qCCritical(JUK_LOG) << "trying to set non-existent file: " << path;
0111         return;
0112     }
0113 
0114     d = new FileHandlePrivate(QFileInfo(path));
0115 }
0116 
0117 Tag *FileHandle::tag() const
0118 {
0119     if(Q_UNLIKELY(!d->tag)) {
0120         d->tag.reset(new Tag(d->absFilePath));
0121     }
0122 
0123     return d->tag.data();
0124 }
0125 
0126 CoverInfo *FileHandle::coverInfo() const
0127 {
0128     if(Q_UNLIKELY(!d->coverInfo))
0129         d->coverInfo.reset(new CoverInfo(*this));
0130 
0131     return d->coverInfo.data();
0132 }
0133 
0134 QString FileHandle::absFilePath() const
0135 {
0136     return d->absFilePath;
0137 }
0138 
0139 const QFileInfo &FileHandle::fileInfo() const
0140 {
0141     return d->fileInfo;
0142 }
0143 
0144 bool FileHandle::isNull() const
0145 {
0146     return d->absFilePath.isEmpty();
0147 }
0148 
0149 bool FileHandle::current() const
0150 {
0151     return (d->baseModificationTime.isValid() &&
0152             lastModified().isValid() &&
0153             d->baseModificationTime >= lastModified());
0154 }
0155 
0156 const QDateTime &FileHandle::lastModified() const
0157 {
0158     if(d->lastModified.isNull())
0159         d->lastModified = d->fileInfo.lastModified();
0160 
0161     return d->lastModified;
0162 }
0163 
0164 void FileHandle::read(CacheDataStream &s)
0165 {
0166     switch(s.cacheVersion()) {
0167     case 1:
0168     default:
0169         if(d->tag) {
0170             qCWarning(JUK_LOG) << "We already read in tag for d->absFilePath!";
0171         }
0172 
0173         if(!d->tag)
0174             d->tag.reset(new Tag(d->absFilePath, true));
0175 
0176         s >> *(d->tag);
0177         s >> d->baseModificationTime;
0178         break;
0179     }
0180 }
0181 
0182 FileHandle &FileHandle::operator=(const FileHandle &f)
0183 {
0184     if(&f != this)
0185         d = f.d;
0186 
0187     return *this;
0188 }
0189 
0190 bool FileHandle::operator==(const FileHandle &f) const
0191 {
0192     return d == f.d;
0193 }
0194 
0195 bool FileHandle::operator!=(const FileHandle &f) const
0196 {
0197     return d != f.d;
0198 }
0199 
0200 QStringList FileHandle::properties() // static
0201 {
0202     return FileHandleProperties::properties();
0203 }
0204 
0205 QString FileHandle::property(const QString &name) const
0206 {
0207     return FileHandleProperties::property(*this, name.toUtf8());
0208 }
0209 
0210 ////////////////////////////////////////////////////////////////////////////////
0211 // related functions
0212 ////////////////////////////////////////////////////////////////////////////////
0213 
0214 QDataStream &operator<<(QDataStream &s, const FileHandle &f)
0215 {
0216     s << *(f.tag())
0217       << f.lastModified();
0218 
0219     return s;
0220 }
0221 
0222 CacheDataStream &operator>>(CacheDataStream &s, FileHandle &f)
0223 {
0224     f.read(s);
0225     return s;
0226 }
0227 
0228 // vim: set et sw=4 tw=0 sta: