File indexing completed on 2024-04-14 15:51:32

0001 /***************************************************************************
0002                           krenamefile.cpp  -  description
0003                              -------------------
0004     begin                : Wed Apr 18 2007
0005     copyright            : (C) 2007 by Dominik Seichter
0006     email                : domseichter@web.de
0007  ***************************************************************************/
0008 
0009 /***************************************************************************
0010  *                                                                         *
0011  *   This program is free software; you can redistribute it and/or modify  *
0012  *   it under the terms of the GNU General Public License as published by  *
0013  *   the Free Software Foundation; either version 2 of the License, or     *
0014  *   (at your option) any later version.                                   *
0015  *                                                                         *
0016  ***************************************************************************/
0017 
0018 #include "krenamefile.h"
0019 
0020 #include <kio/previewjob.h>
0021 #include <KJobWidgets>
0022 
0023 /** A singleton class that loads icons for urls in a synchronous way
0024  */
0025 class KRenamePreviewProvider
0026 {
0027 
0028 public:
0029     /** Get the KRenamePreviewProvider instance. This is a singleton
0030      *  as only one KRenamePreviewProvider may exist for one application.
0031      */
0032     static KRenamePreviewProvider *Instance()
0033     {
0034         if (!s_instance) {
0035             s_instance = new KRenamePreviewProvider();
0036         }
0037 
0038         return s_instance;
0039     }
0040 
0041     QPixmap loadIcon(const QUrl &url)
0042     {
0043         return KIO::pixmapForUrl(url);
0044     }
0045 
0046 private:
0047     /** Create a KRenamePreviewProvider
0048      */
0049     KRenamePreviewProvider()
0050     {
0051     }
0052 
0053     ~KRenamePreviewProvider()
0054     {
0055     }
0056 
0057 private:
0058     static KRenamePreviewProvider *s_instance;
0059 };
0060 
0061 KRenamePreviewProvider *KRenamePreviewProvider::s_instance = nullptr;
0062 
0063 const int KRenameFile::DEFAULT_ICON_SIZE = 64;
0064 int KRenameFile::m_iconSize = 0; // read from config file
0065 const char *KRenameFile::EXTRA_DATA_KEY = "KRenameFile::EXTRA_DATA_KEY";
0066 
0067 KRenameFile::KRenameFile(const QUrl &src, ESplitMode eSplitMode, unsigned int dot)
0068     : m_bValid(false), m_error(0), m_manualMode(eManualChangeMode_None)
0069 {
0070     KIO::StatJob *statJob = KIO::stat(src, KIO::StatJob::DestinationSide, 2);
0071     statJob->exec();
0072     if (statJob->error()) {
0073         return;
0074     }
0075 
0076     KFileItem file(statJob->statResult(), src);
0077 
0078     m_bValid     = file.isReadable();
0079     m_bDirectory = file.isDir();
0080 
0081     m_fileItem = file;
0082     initFileDescription(m_src, src, eSplitMode, dot);
0083 }
0084 
0085 KRenameFile::KRenameFile(const QUrl &src, bool directory, ESplitMode eSplitMode, unsigned int dot)
0086     : m_bDirectory(directory), m_bValid(true), m_error(0), m_manualMode(eManualChangeMode_None)
0087 {
0088     initFileDescription(m_src, src, eSplitMode, dot);
0089 }
0090 
0091 KRenameFile::KRenameFile(const KFileItem &item, ESplitMode eSplitMode, unsigned int dot)
0092     : m_bDirectory(item.isDir()), m_bValid(item.isReadable()), m_error(0), m_manualMode(eManualChangeMode_None)
0093 {
0094     m_fileItem = item;
0095 
0096     initFileDescription(m_src, item.url(), eSplitMode, dot);
0097 }
0098 
0099 KRenameFile::KRenameFile(const KRenameFile &rhs)
0100 {
0101     this->operator=(rhs);
0102 }
0103 
0104 const KRenameFile &KRenameFile::operator=(const KRenameFile &rhs)
0105 {
0106     m_bDirectory = rhs.m_bDirectory;
0107     m_src        = rhs.m_src;
0108     m_dst        = rhs.m_dst;
0109 
0110     m_bValid     = rhs.m_bValid;
0111     m_icon       = rhs.m_icon;
0112     m_error      = rhs.m_error;
0113     m_manual     = rhs.m_manual;
0114     m_manualMode = rhs.m_manualMode;
0115 
0116     return *this;
0117 }
0118 
0119 bool KRenameFile::operator==(const KFileItem &item) const
0120 {
0121     return this->fileItem() == item;
0122 }
0123 
0124 void KRenameFile::setIconSize(int size)
0125 {
0126     m_iconSize = size;
0127 }
0128 
0129 int KRenameFile::iconSize()
0130 {
0131     return m_iconSize;
0132 }
0133 
0134 int KRenameFile::getDefaultIconSize()
0135 {
0136     return DEFAULT_ICON_SIZE;
0137 }
0138 
0139 void KRenameFile::setCurrentSplitMode(ESplitMode eSplitMode, unsigned int dot)
0140 {
0141     QUrl    url      = m_src.url;
0142     QString filename = m_src.filename;
0143     if (!m_src.extension.isEmpty()) {
0144         filename = filename + '.' + m_src.extension;
0145     }
0146 
0147     url.setPath(m_src.directory + '/' + filename);
0148 
0149     this->initFileDescription(m_src, url, eSplitMode, dot);
0150 }
0151 
0152 void KRenameFile::initFileDescription(TFileDescription &rDescription, const QUrl &url,
0153                                       ESplitMode eSplitMode, unsigned int dot) const
0154 {
0155     int splitPos = -1;
0156     QString path = url.path();
0157     QString file;
0158 
0159     if (!m_bValid) {
0160         return;
0161     }
0162 
0163     rDescription.url       = url;
0164     rDescription.directory = path;
0165 
0166     if (!m_bDirectory) {
0167         // split directory/filename
0168         splitPos = path.lastIndexOf('/');
0169         if (splitPos == -1) {
0170             // only a filename?? can this happen?
0171             file = path;
0172             path.clear();
0173         } else {
0174             file = path.right(path.length() - splitPos - 1);
0175             path = path.left(splitPos);
0176         }
0177 
0178         // split filename.extension
0179         splitPos = -1;
0180         if (eSplitMode == eSplitMode_FirstDot) {
0181             splitPos = file.indexOf('.');
0182         } else if (eSplitMode == eSplitMode_LastDot) {
0183             splitPos = file.lastIndexOf('.');
0184         } else if (eSplitMode == eSplitMode_NoExtension) {
0185             splitPos = file.length();
0186         } else {
0187             if (dot) {
0188                 int i = 0;
0189                 splitPos = 0;
0190                 do {
0191                     splitPos = file.indexOf('.', splitPos + 1);
0192                     ++i;
0193                 } while (i < static_cast<int>(dot) && splitPos != -1);
0194             } else
0195                 // if dot == 0, do not take an extension
0196             {
0197                 splitPos = file.length();
0198             }
0199         }
0200 
0201         if (splitPos == -1) {
0202             splitPos = file.length();
0203         }
0204 
0205         rDescription.filename  = file.left(splitPos);
0206         rDescription.extension = "";
0207         if (splitPos != file.length()) {
0208             rDescription.extension = file.right(file.length() - splitPos - 1);
0209         }
0210         rDescription.directory = path;
0211     } else {
0212         if (rDescription.directory.endsWith('/')) {
0213             rDescription.directory = rDescription.directory.left(rDescription.directory.length() - 1);
0214         }
0215 
0216         int lastSlash = rDescription.directory.lastIndexOf('/');
0217         rDescription.filename  = rDescription.directory.right(rDescription.directory.length() - lastSlash - 1);
0218         rDescription.directory = rDescription.directory.left(lastSlash);
0219         rDescription.extension = "";
0220     }
0221 
0222     /*
0223     qDebug("URL : %s", url.toDisplayString().toLatin1().data() );
0224     qDebug("Path: %s", rDescription.directory.toLatin1().data());
0225     qDebug("File: %s", rDescription.filename.toLatin1().data());
0226     qDebug("Ext : %s", rDescription.extension.toLatin1().data());
0227     qDebug("Split %i", splitPos );
0228     qDebug("Dot   %i", dot );
0229     qDebug("=====");
0230     */
0231 }
0232 
0233 void KRenameFile::loadPreviewIcon()
0234 {
0235     m_icon = KRenamePreviewProvider::Instance()->loadIcon(m_src.url);
0236 }
0237 
0238 int KRenameFile::dots() const
0239 {
0240     int dots = 0;
0241 
0242     dots += m_src.filename.count('.');
0243     dots += m_src.extension.count('.');
0244 
0245     if (!m_src.extension.isEmpty()) {
0246         ++dots;
0247     }
0248 
0249     return dots;
0250 }
0251 
0252 const QUrl KRenameFile::srcUrl() const
0253 {
0254     if (m_overrideDir.isNull()) {
0255         return m_src.url;
0256     } else {
0257         QUrl changed = m_src.url;
0258         QString filename = m_src.filename;
0259         if (!m_src.extension.isEmpty()) {
0260             filename += '.';
0261             filename += m_src.extension;
0262         }
0263 
0264         changed.setPath(m_overrideDir + '/' +  filename);
0265         return changed;
0266     }
0267 }
0268 
0269 const KFileItem &KRenameFile::fileItem() const
0270 {
0271     if (m_fileItem.isNull()) {
0272         // No file item has been constructed
0273         // create one first.
0274         KIO::StatJob *statJob = KIO::stat(m_src.url, KIO::StatJob::DestinationSide, 2);
0275         statJob->exec();
0276         if (!statJob->error()) {
0277             KFileItem file(statJob->statResult(), m_src.url);
0278             const_cast<KRenameFile *>(this)->m_fileItem = file;
0279         }
0280     }
0281 
0282     /*
0283     // Update extra as often as possible
0284     // As the address is changed through sorting and moving files
0285     // It is only valid if no moving of data has happened!
0286     const_cast<KRenameFile*>(this)->m_fileItem.setExtraData( KRenameFile::EXTRA_DATA_KEY,
0287                                                              const_cast<KRenameFile*>(this) );
0288     */
0289     return m_fileItem;
0290 }