File indexing completed on 2023-12-10 04:47:38
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: