annotate data/fileio/FileSource.h @ 360:ac300d385ab2

* Various fixes to object lifetime management, particularly in the spectrum layer and for notification of main model deletion. The main purpose of this is to improve the behaviour of the spectrum, but I think it may also help with #1840922 Various crashes in Layer Summary window.
author Chris Cannam
date Wed, 23 Jan 2008 15:43:27 +0000
parents b92513201610
children 183ee2a55fc7
rev   line source
Chris@208 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@208 2
Chris@208 3 /*
Chris@208 4 Sonic Visualiser
Chris@208 5 An audio file viewer and annotation editor.
Chris@208 6 Centre for Digital Music, Queen Mary, University of London.
Chris@208 7 This file copyright 2007 QMUL.
Chris@208 8
Chris@208 9 This program is free software; you can redistribute it and/or
Chris@208 10 modify it under the terms of the GNU General Public License as
Chris@208 11 published by the Free Software Foundation; either version 2 of the
Chris@208 12 License, or (at your option) any later version. See the file
Chris@208 13 COPYING included with this distribution for more information.
Chris@208 14 */
Chris@208 15
Chris@208 16 #ifndef _REMOTE_FILE_H_
Chris@208 17 #define _REMOTE_FILE_H_
Chris@208 18
Chris@208 19 #include <QUrl>
Chris@208 20 #include <QMutex>
Chris@208 21 #include <QString>
Chris@210 22 #include <QTimer>
Chris@208 23
Chris@304 24 #include <map>
Chris@304 25
Chris@208 26 class QFtp;
Chris@208 27 class QHttp;
Chris@208 28 class QFile;
Chris@208 29 class QProgressDialog;
Chris@210 30 class QHttpResponseHeader;
Chris@357 31 class ProgressPrinter;
Chris@208 32
Chris@325 33 /**
Chris@325 34 * FileSource is a class used to refer to the contents of a file that
Chris@325 35 * may be either local or at a remote location such as a HTTP URL.
Chris@325 36 *
Chris@325 37 * When a FileSource object is constructed, the file or URL passed to
Chris@325 38 * its constructor is tested for validity, and if it refers to a
Chris@325 39 * remote HTTP or FTP location it is retrieved asynchronously (the Qt
Chris@325 40 * event loop must be running) and cached locally. You can then query
Chris@325 41 * a local path for the file and refer to that as a normal filename.
Chris@325 42 *
Chris@325 43 * Use isAvailable() to test whether the file or remote URL exists,
Chris@325 44 * and isOK() to test for internal validity or transmission errors.
Chris@325 45 * Call waitForStatus() to block until the availability and validity
Chris@325 46 * of the URL have been established so that isAvailable may be called,
Chris@325 47 * and waitForData() to block until the entire file has been cached.
Chris@325 48 *
Chris@325 49 * FileSource handles reference counting for cache files. You can
Chris@325 50 * construct many FileSource objects with the same URL and you will
Chris@325 51 * receive the same cached file for each; it is also reasonable to
Chris@325 52 * pass FileSource objects by value. FileSource only makes sense for
Chris@325 53 * stateless URLs that result in the same data on each request.
Chris@325 54 *
Chris@325 55 * Cached files share a lifetime with their "owning" FileSource
Chris@325 56 * objects; when the last FileSource referring to a given URL is
Chris@325 57 * deleted or goes out of scope, its cached file (if any) is also
Chris@325 58 * removed.
Chris@325 59 */
Chris@317 60 class FileSource : public QObject
Chris@208 61 {
Chris@208 62 Q_OBJECT
Chris@208 63
Chris@208 64 public:
Chris@325 65
Chris@357 66 enum ShowProgressType {
Chris@357 67 ProgressNone,
Chris@357 68 ProgressDialog,
Chris@357 69 ProgressToConsole
Chris@357 70 };
Chris@357 71
Chris@325 72 /**
Chris@325 73 * Construct a FileSource using the given local file path or URL.
Chris@357 74 * The URL may be raw or encoded.
Chris@357 75 *
Chris@357 76 * If progressType is ProgressDialog, a progress dialog will be
Chris@357 77 * shown for any network transfers; if it is ProgressToConsole, a
Chris@357 78 * progress indication will be sent to the console.
Chris@357 79 * Note that the progress() signal will also be emitted regularly
Chris@357 80 * during retrieval, even if progressType is ProgressNone.
Chris@325 81 */
Chris@357 82 FileSource(QString fileOrUrl,
Chris@357 83 ShowProgressType progressType = ProgressNone);
Chris@325 84
Chris@325 85 /**
Chris@357 86 * Construct a FileSource using the given remote URL.
Chris@357 87 *
Chris@357 88 * If progressType is ProgressDialog, a progress dialog will be
Chris@357 89 * shown for any network transfers; if it is ProgressToConsole, a
Chris@357 90 * progress indication will be sent to the console.
Chris@357 91 * Note that the progress() signal also will be emitted regularly
Chris@357 92 * during retrieval, even if progressType is ProgressNone.
Chris@325 93 */
Chris@357 94 FileSource(QUrl url,
Chris@357 95 ShowProgressType progressType = ProgressNone);
Chris@325 96
Chris@317 97 FileSource(const FileSource &);
Chris@316 98
Chris@317 99 virtual ~FileSource();
Chris@208 100
Chris@325 101 /**
Chris@325 102 * Block on a sub-event-loop until the availability of the file or
Chris@325 103 * remote URL is known.
Chris@325 104 */
Chris@325 105 void waitForStatus();
Chris@325 106
Chris@325 107 /**
Chris@325 108 * Block on a sub-event-loop until the whole of the data has been
Chris@325 109 * retrieved (if it is remote).
Chris@325 110 */
Chris@325 111 void waitForData();
Chris@325 112
Chris@325 113 /**
Chris@325 114 * Return true if the FileSource object is valid and no error
Chris@325 115 * occurred in looking up the file or remote URL. Non-existence
Chris@325 116 * of the file or URL is not an error -- call isAvailable() to
Chris@325 117 * test for that.
Chris@325 118 */
Chris@325 119 bool isOK() const;
Chris@325 120
Chris@325 121 /**
Chris@325 122 * Return true if the file or remote URL exists. This may block
Chris@325 123 * on a sub-event-loop (calling waitForStatus) if the status is
Chris@325 124 * not yet available.
Chris@325 125 */
Chris@210 126 bool isAvailable();
Chris@210 127
Chris@325 128 /**
Chris@325 129 * Return true if the entire file has been retrieved and is
Chris@325 130 * available.
Chris@325 131 */
Chris@325 132 bool isDone() const;
Chris@316 133
Chris@325 134 /**
Chris@325 135 * Return true if this FileSource is referring to a remote URL.
Chris@325 136 */
Chris@325 137 bool isRemote() const;
Chris@325 138
Chris@325 139 /**
Chris@325 140 * Return the location filename or URL as passed to the
Chris@325 141 * constructor.
Chris@325 142 */
Chris@325 143 QString getLocation() const;
Chris@325 144
Chris@325 145 /**
Chris@325 146 * Return the name of the local file this FileSource refers to.
Chris@325 147 * This is the filename that should be used when reading normally
Chris@325 148 * from the FileSource. If the filename passed to the constructor
Chris@325 149 * was a local file, this will return the same filename; otherwise
Chris@325 150 * this will be the name of the temporary cache file owned by the
Chris@325 151 * FileSource.
Chris@325 152 */
Chris@325 153 QString getLocalFilename() const;
Chris@325 154
Chris@325 155 /**
Chris@325 156 * Return the MIME content type of this file, if known.
Chris@325 157 */
Chris@325 158 QString getContentType() const;
Chris@325 159
Chris@325 160 /**
Chris@325 161 * Return the file extension for this file, if any.
Chris@325 162 */
Chris@325 163 QString getExtension() const;
Chris@325 164
Chris@325 165 /**
Chris@325 166 * Return an error message, if isOK() is false.
Chris@325 167 */
Chris@325 168 QString getErrorString() const;
Chris@325 169
Chris@325 170 /**
Chris@325 171 * Specify whether any local, cached file should remain on disc
Chris@325 172 * after this FileSource has been destroyed. The default is false
Chris@325 173 * (cached files share their FileSource owners' lifespans).
Chris@325 174 */
Chris@316 175 void setLeaveLocalFile(bool leave);
Chris@208 176
Chris@325 177 /**
Chris@325 178 * Return true if the given filename or URL refers to a remote
Chris@325 179 * URL.
Chris@325 180 */
Chris@325 181 static bool isRemote(QString fileOrUrl);
Chris@210 182
Chris@325 183 /**
Chris@325 184 * Return true if FileSource can handle the retrieval scheme for
Chris@325 185 * the given URL (or if the URL is for a local file).
Chris@325 186 */
Chris@208 187 static bool canHandleScheme(QUrl url);
Chris@208 188
Chris@208 189 signals:
Chris@325 190 /**
Chris@325 191 * Emitted during URL retrieval, when the retrieval progress
Chris@325 192 * notches up to a new percentage.
Chris@325 193 */
Chris@208 194 void progress(int percent);
Chris@325 195
Chris@325 196 /**
Chris@325 197 * Emitted when the file's existence has been tested and/or
Chris@325 198 * response header received. Calls to isAvailable() after this
Chris@325 199 * has been emitted will not block.
Chris@325 200 */
Chris@325 201 void statusAvailable();
Chris@325 202
Chris@325 203 /**
Chris@325 204 * Emitted when the entire file data has been retrieved and the
Chris@325 205 * local file is complete (if no error has occurred).
Chris@325 206 */
Chris@208 207 void ready();
Chris@208 208
Chris@208 209 protected slots:
Chris@208 210 void dataReadProgress(int done, int total);
Chris@214 211 void httpResponseHeaderReceived(const QHttpResponseHeader &resp);
Chris@214 212 void ftpCommandFinished(int, bool);
Chris@208 213 void dataTransferProgress(qint64 done, qint64 total);
Chris@208 214 void done(bool error);
Chris@210 215 void showProgressDialog();
Chris@210 216 void cancelled();
Chris@208 217
Chris@208 218 protected:
Chris@317 219 FileSource &operator=(const FileSource &); // not provided
Chris@316 220
Chris@304 221 QUrl m_url;
Chris@208 222 QFtp *m_ftp;
Chris@208 223 QHttp *m_http;
Chris@208 224 QFile *m_localFile;
Chris@208 225 QString m_localFilename;
Chris@208 226 QString m_errorString;
Chris@315 227 QString m_contentType;
Chris@208 228 bool m_ok;
Chris@210 229 int m_lastStatus;
Chris@316 230 bool m_remote;
Chris@208 231 bool m_done;
Chris@316 232 bool m_leaveLocalFile;
Chris@357 233 ShowProgressType m_progressType;
Chris@357 234 ProgressPrinter *m_progressPrinter;
Chris@208 235 QProgressDialog *m_progressDialog;
Chris@210 236 QTimer m_progressShowTimer;
Chris@208 237
Chris@304 238 typedef std::map<QUrl, int> RemoteRefCountMap;
Chris@304 239 typedef std::map<QUrl, QString> RemoteLocalMap;
Chris@304 240 static RemoteRefCountMap m_refCountMap;
Chris@304 241 static RemoteLocalMap m_remoteLocalMap;
Chris@304 242 static QMutex m_mapMutex;
Chris@316 243 bool m_refCounted;
Chris@316 244
Chris@357 245 void init();
Chris@316 246 void initHttp();
Chris@316 247 void initFtp();
Chris@304 248
Chris@211 249 void cleanup();
Chris@211 250
Chris@316 251 // Create a local file for m_url. If it already existed, return true.
Chris@316 252 // The local filename is stored in m_localFilename.
Chris@316 253 bool createCacheFile();
Chris@316 254 void deleteCacheFile();
Chris@208 255
Chris@208 256 static QMutex m_fileCreationMutex;
Chris@208 257 static int m_count;
Chris@208 258 };
Chris@208 259
Chris@208 260 #endif