File indexing completed on 2024-05-05 16:39:03
0001 /* This file is part of the KDE project 0002 Copyright (C) 2003,2009 Carsten Pfeiffer <pfeiffer@kde.org> 0003 0004 This program is free software; you can redistribute it and/or 0005 modify it under the terms of the GNU General Public 0006 License as published by the Free Software Foundation, version 2. 0007 0008 This program is distributed in the hope that it will be useful, 0009 but WITHOUT ANY WARRANTY; without even the implied warranty of 0010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0011 General Public License for more details. 0012 0013 You should have received a copy of the GNU General Public License 0014 along with this program; see the file COPYING. If not, write to 0015 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0016 Boston, MA 02110-1301, USA. 0017 */ 0018 0019 #include "kuickfile.h" 0020 #include "kuickshow_debug.h" 0021 0022 #include <KIO/FileCopyJob> 0023 #include <KIO/StatJob> 0024 #include <KLocalizedString> 0025 0026 #include <QFile> 0027 #include <QProgressDialog> 0028 #include <QScopedPointer> 0029 #include <QTemporaryFile> 0030 0031 #include "filecache.h" 0032 0033 0034 KuickFile::KuickFile(const QUrl& url) 0035 : QObject(), 0036 m_url( url ), 0037 m_job( 0L ), 0038 m_progress( 0L ), 0039 m_currentProgress( 0 ) 0040 { 0041 if ( m_url.isLocalFile()) 0042 m_localFile = m_url.path(); 0043 else { 0044 QUrl mostLocal; 0045 KIO::StatJob* job = KIO::mostLocalUrl(m_url); 0046 connect(job, &KIO::StatJob::result, [job, &mostLocal]() { 0047 if(!job->error()) mostLocal = job->mostLocalUrl(); 0048 }); 0049 job->exec(); 0050 0051 if ( mostLocal.isValid() && mostLocal.isLocalFile() ) 0052 m_localFile = mostLocal.path(); 0053 } 0054 } 0055 0056 KuickFile::~KuickFile() 0057 { 0058 delete m_job; 0059 0060 if ( hasDownloaded() ) 0061 QFile::remove( m_localFile ); 0062 } 0063 0064 QString KuickFile::localFile() const 0065 { 0066 // Note: never call isAvailable() from here, directly or indirectly 0067 0068 if ( isDownloading() ) 0069 return QString(); 0070 0071 return m_localFile; 0072 } 0073 0074 bool KuickFile::hasDownloaded() const 0075 { 0076 return !m_url.isLocalFile() && isAvailable() && m_job != 0L; 0077 } 0078 0079 // ### need an API for refreshing the file? 0080 bool KuickFile::download() 0081 { 0082 if ( m_url.isLocalFile() || isAvailable() ) 0083 return true; 0084 0085 if ( isDownloading() ) 0086 return true; 0087 0088 // reinitialize 0089 m_localFile.clear(); 0090 m_currentProgress = 0; 0091 0092 0093 QString ext; 0094 QString fileName = m_url.fileName(); 0095 int extIndex = fileName.lastIndexOf('.'); 0096 if ( extIndex > 0 ) 0097 ext = fileName.mid( extIndex ); 0098 0099 QScopedPointer<QTemporaryFile> tempFilePtr(FileCache::self()->createTempFile(ext)); 0100 if(tempFilePtr.isNull() || !tempFilePtr->open()) return false; 0101 0102 QUrl destURL = QUrl::fromLocalFile(tempFilePtr->fileName()); 0103 0104 // we don't need the actual temp file, just its unique name 0105 tempFilePtr.reset(); 0106 0107 m_job = KIO::file_copy( m_url, destURL, -1, KIO::HideProgressInfo | KIO::Overwrite ); // handling progress ourselves 0108 // m_job->setAutoErrorHandlingEnabled( true ); 0109 connect( m_job, SIGNAL( result( KJob * )), SLOT( slotResult( KJob * ) )); 0110 connect( m_job, SIGNAL( percent( KJob *, unsigned long )), SLOT( slotProgress( KJob *, unsigned long ) )); 0111 0112 // TODO: generify background/foreground downloading? 0113 0114 return m_job != 0L; 0115 } 0116 0117 KuickFile::DownloadStatus KuickFile::waitForDownload( QWidget *parent ) 0118 { 0119 if ( isAvailable() ) 0120 return OK; 0121 0122 if ( !isDownloading() ) { 0123 if ( !download() ) 0124 return ERROR; 0125 } 0126 0127 QProgressDialog *dialog = new QProgressDialog( parent ); 0128 dialog->setWindowTitle( i18n("Downloading %1...", m_url.fileName() ) ); 0129 dialog->setLabelText( i18n("Please wait while downloading\n%1", m_url.toDisplayString() )); 0130 dialog->setAutoClose( true ); 0131 0132 dialog->setMaximum( 100 ); // percent 0133 dialog->setValue( m_currentProgress ); 0134 0135 m_progress = dialog; 0136 dialog->exec(); 0137 m_progress = nullptr; 0138 0139 bool canceled = dialog->wasCanceled(); 0140 delete dialog; 0141 0142 if ( canceled && m_job ) { 0143 m_job->kill(); 0144 m_job = 0L; 0145 m_currentProgress = 0; 0146 } 0147 // ### when aborted, remove KuickImage from FileCache? 0148 0149 if ( canceled ) 0150 return CANCELED; 0151 0152 if ( !isAvailable() ) 0153 return ERROR; 0154 0155 // ### use custom progress dialog with OK, SKIP, CANCEL? 0156 return OK; 0157 } 0158 0159 void KuickFile::slotResult( KJob *job ) 0160 { 0161 if (job != m_job) { // huh? 0162 return; 0163 } 0164 0165 m_job = 0L; 0166 0167 if ( job->error() != 0 ) { 0168 m_currentProgress = 0; 0169 0170 if ( job->error() != KIO::ERR_USER_CANCELED ) 0171 qWarning("ERROR: KuickFile::slotResult: %s", qUtf8Printable(job->errorString())); 0172 0173 QString canceledFile = static_cast<KIO::FileCopyJob*>(job)->destUrl().path(); 0174 QFile::remove( canceledFile ); 0175 m_progress->hide(); 0176 } 0177 else { 0178 m_localFile = static_cast<KIO::FileCopyJob*>(job)->destUrl().path(); 0179 emit downloaded( this ); // before closing the progress dialog 0180 0181 if ( m_progress ) { 0182 m_progress->setValue( 100 ); 0183 } 0184 } 0185 } 0186 0187 void KuickFile::slotProgress( KJob *job, unsigned long percent ) 0188 { 0189 if (job != m_job) { // huh? 0190 return; 0191 } 0192 0193 m_currentProgress = percent; 0194 0195 if ( !m_progress ) 0196 return; 0197 0198 // only set 100% in slotResult. Otherwise, the progress dialog would be closed 0199 // before slotResult() is called. 0200 if ( percent >= 100 ) 0201 percent = 99; 0202 0203 m_progress->setValue( (int) percent ); 0204 } 0205 0206 bool operator==( const KuickFile& first, const KuickFile& second ) { 0207 return first.url() == second.url(); 0208 }