File indexing completed on 2024-05-12 05:09:50
0001 /*************************************************************************** 0002 Copyright (C) 2009 Robby Stephenson <robby@periapsis.org> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 #include "imagedirectory.h" 0026 #include "image.h" 0027 #include "../core/filehandler.h" 0028 #include "../tellico_debug.h" 0029 0030 #include <KZip> 0031 0032 #include <QFile> 0033 #include <QDir> 0034 #include <QUrl> 0035 #include <QTemporaryDir> 0036 0037 using namespace Tellico; 0038 using Tellico::ImageStorage; 0039 using Tellico::ImageDirectory; 0040 using Tellico::TemporaryImageDirectory; 0041 using Tellico::ImageZipArchive; 0042 0043 ImageDirectory::ImageDirectory() : ImageStorage(), m_pathExists(false), m_dir(nullptr) { 0044 } 0045 0046 ImageDirectory::ImageDirectory(const QString& path_) : ImageStorage() , m_dir(nullptr) { 0047 setPath(path_); 0048 } 0049 0050 ImageDirectory::~ImageDirectory() { 0051 delete m_dir; 0052 m_dir = nullptr; 0053 } 0054 0055 QString ImageDirectory::path() { 0056 return m_path; 0057 } 0058 0059 void ImageDirectory::setPath(const QString& path_) { 0060 m_path = path_; 0061 QDir dir(m_path); 0062 m_pathExists = dir.exists(); 0063 } 0064 0065 bool ImageDirectory::hasImage(const QString& id_) { 0066 return m_pathExists && QFile::exists(path() + id_); 0067 } 0068 0069 Tellico::Data::Image* ImageDirectory::imageById(const QString& id_) { 0070 if(!hasImage(id_)) { 0071 return nullptr; 0072 } 0073 0074 Data::Image* img = new Data::Image(path() + id_, id_); 0075 if(img->isNull()) { 0076 myLog() << "image found but null:" << (path() + id_); 0077 delete img; 0078 return nullptr; 0079 } 0080 return img; 0081 } 0082 0083 bool ImageDirectory::writeImage(const Data::Image& img_) { 0084 const QString path = this->path(); // virtual function, so don't assume m_path is correct 0085 if(!m_pathExists) { 0086 if(path.isEmpty()) { 0087 // an empty path means the file hasn't been saved yet 0088 if(!m_dir) { 0089 m_dir = new QTemporaryDir(); // default is to auto-delete, aka autoRemove() 0090 // in KDE4, the way this worked included the final slash. 0091 ImageDirectory::setPath(m_dir->path() + QLatin1Char('/')); 0092 } 0093 return writeImage(img_); 0094 } 0095 QDir dir(path); 0096 if(dir.mkdir(path)) { 0097 // myLog() << "created" << path; 0098 } else { 0099 myWarning() << "unable to create dir:" << path; 0100 } 0101 m_pathExists = true; 0102 } 0103 QUrl target = QUrl::fromLocalFile(path); 0104 target.setPath(target.path() + img_.id()); 0105 return FileHandler::writeDataURL(target, img_.byteArray(), true /* force */); 0106 } 0107 0108 bool ImageDirectory::removeImage(const QString& id_) { 0109 return m_pathExists && QFile::remove(path() + id_); 0110 } 0111 0112 TemporaryImageDirectory::TemporaryImageDirectory() : ImageDirectory(), m_dir(nullptr) { 0113 } 0114 0115 TemporaryImageDirectory::~TemporaryImageDirectory() { 0116 purge(); 0117 } 0118 0119 void TemporaryImageDirectory::purge() { 0120 delete m_dir; 0121 m_dir = nullptr; 0122 } 0123 0124 QString TemporaryImageDirectory::path() { 0125 if(!m_dir) { 0126 m_dir = new QTemporaryDir(); // default is to auto-delete, aka autoRemove() 0127 // in KDE4, the way this worked included the final slash. 0128 ImageDirectory::setPath(m_dir->path() + QLatin1Char('/')); 0129 } 0130 return ImageDirectory::path(); 0131 } 0132 0133 void TemporaryImageDirectory::setPath(const QString& path) { 0134 Q_UNUSED(path); 0135 Q_ASSERT(path.isEmpty()); // should never be called, that's why it's private 0136 } 0137 0138 ImageZipArchive::ImageZipArchive() : ImageStorage(), m_imgDir(nullptr) { 0139 } 0140 0141 ImageZipArchive::~ImageZipArchive() { 0142 } 0143 0144 void ImageZipArchive::setZip(std::unique_ptr<KZip> zip_) { 0145 m_images.clear(); 0146 m_zip = std::move(zip_); 0147 m_imgDir = nullptr; 0148 0149 const KArchiveDirectory* dir = m_zip->directory(); 0150 if(!dir) { 0151 m_zip.reset(); 0152 return; 0153 } 0154 const KArchiveEntry* imgDirEntry = dir->entry(QStringLiteral("images")); 0155 if(!imgDirEntry || !imgDirEntry->isDirectory()) { 0156 m_zip.reset(); 0157 return; 0158 } 0159 m_imgDir = static_cast<const KArchiveDirectory*>(imgDirEntry); 0160 m_images.add(m_imgDir->entries()); 0161 } 0162 0163 bool ImageZipArchive::hasImage(const QString& id_) { 0164 return m_images.has(id_); 0165 } 0166 0167 Tellico::Data::Image* ImageZipArchive::imageById(const QString& id_) { 0168 if(!hasImage(id_)) { 0169 return nullptr; 0170 } 0171 Data::Image* img = nullptr; 0172 const KArchiveEntry* file = m_imgDir->entry(id_); 0173 if(file && file->isFile()) { 0174 img = new Data::Image(static_cast<const KArchiveFile*>(file)->data(), 0175 id_.section(QLatin1Char('.'), -1).toUpper(), id_); 0176 } 0177 // might be unexpected behavior, but in order to delete the zip object after 0178 // all images are read, we need to consider the image gone now 0179 m_images.remove(id_); 0180 if(m_images.isEmpty()) { 0181 m_zip.reset(); 0182 m_imgDir = nullptr; 0183 } 0184 if(!img) { 0185 myLog() << "image not found:" << id_; 0186 return nullptr; 0187 } 0188 if(img->isNull()) { 0189 myLog() << "image found but null:" << id_; 0190 delete img; 0191 return nullptr; 0192 } 0193 return img; 0194 }