31 #include <QApplication>
34 #include <QStandardItemModel>
35 #include <QSortFilterProxyModel>
36 #include <QFileSystemWatcher>
47 , RelativePath_ (relPath)
48 , SubElemModel_ (new QStandardItemModel (this))
49 , AttrFilters_ (QDir::Dirs | QDir::NoDotAndDotDot | QDir::Readable)
50 , SortModel_ (new QSortFilterProxyModel (this))
51 , Watcher_ (new QFileSystemWatcher (this))
52 , CacheFlushTimer_ (new QTimer (this))
53 , CachePathContents_ (0)
56 if (RelativePath_.startsWith (
'/'))
57 RelativePath_ = RelativePath_.mid (1);
58 if (!RelativePath_.endsWith (
'/'))
59 RelativePath_.append (
'/');
61 SortModel_->setDynamicSortFilter (
true);
62 SortModel_->setSourceModel (SubElemModel_);
66 SIGNAL (directoryChanged (
const QString&)),
68 SLOT (handleDirectoryChanged (
const QString&)));
70 connect (CacheFlushTimer_,
73 SLOT (handleFlushCaches ()));
78 if (!prefix.isEmpty () &&
79 !prefix.endsWith (
'/'))
81 QString result = QDir::homePath () +
"/.leechcraft/data/" + prefix;
82 LocalPrefixesChain_ << result;
84 QDir testDir = QDir::home ();
85 if (!testDir.exists (
".leechcraft/data/" + prefix + RelativePath_))
87 qDebug () << Q_FUNC_INFO
88 <<
".leechcraft/data/" + prefix + RelativePath_
89 <<
"doesn't exist, trying to create it...";
91 if (!testDir.mkpath (
".leechcraft/data/" + prefix + RelativePath_))
93 qWarning () << Q_FUNC_INFO
95 <<
".leechcraft/data/" + prefix + RelativePath_;
99 ScanPath (result + RelativePath_);
101 Watcher_->addPath (result + RelativePath_);
107 QStringList prefixes = QApplication::arguments ().contains (
"-nobundle") ?
108 QStringList (
"/usr/local/share/leechcraft/") :
109 QStringList (QApplication::applicationDirPath () +
"/../Resources/share/");
110 #elif defined (Q_OS_WIN32)
111 QStringList prefixes = QStringList (QApplication::applicationDirPath () +
"/share/");
112 #elif defined (INSTALL_PREFIX)
113 QStringList prefixes = QStringList (INSTALL_PREFIX
"/share/leechcraft/");
115 QStringList prefixes = QStringList (
"/usr/local/share/leechcraft/")
116 <<
"/usr/share/leechcraft/";
118 bool hasBeenAdded =
false;
119 for (
const QString& prefix : prefixes)
121 GlobalPrefixesChain_ << prefix;
122 ScanPath (prefix + RelativePath_);
124 if (QFile::exists (prefix + RelativePath_))
126 Watcher_->addPath (prefix + RelativePath_);
132 qWarning () << Q_FUNC_INFO
133 <<
"no prefixes have been added:"
141 if (qApp->property (
"no-resource-caching").toBool ())
146 CacheFlushTimer_->stop ();
148 handleFlushCaches ();
153 CacheFlushTimer_->start (timeout);
155 CachePathContents_.setMaxCost (size * 1024);
156 CachePixmaps_.setMaxCost (size * 1024);
162 handleFlushCaches ();
166 const QStringList& nameFilters, QDir::Filters filters)
const
169 QFileInfoList result;
170 for (
const auto& prefix : LocalPrefixesChain_ + GlobalPrefixesChain_)
172 const QString& path = prefix + RelativePath_ + option;
174 const QFileInfoList& list =
175 dir.entryInfoList (nameFilters, filters);
176 for (
const auto& info : list)
178 const QString& fname = info.fileName ();
179 if (alreadyListed.contains (fname))
182 alreadyListed << fname;
192 for (
const auto& prefix : LocalPrefixesChain_ + GlobalPrefixesChain_)
193 for (
const auto& path : pathVariants)
195 const QString& can = QFileInfo (prefix + RelativePath_ + path).absoluteFilePath ();
196 if (QFile::exists (can))
205 QStringList IconizeBasename (
const QString& basename)
207 QStringList variants;
208 variants << basename +
".svg"
211 << basename +
".gif";
218 return GetPath (IconizeBasename (basename));
223 QString path =
GetPath (pathVariants);
227 if (CachePathContents_.contains (path))
229 std::shared_ptr<QBuffer> result (
new QBuffer ());
230 result->setData (*CachePathContents_ [path]);
232 result->open (QIODevice::ReadOnly);
236 std::shared_ptr<QFile> result (
new QFile (path));
238 if (!result->isSequential () &&
239 result->size () < CachePathContents_.maxCost () / 2)
241 if (result->open (QIODevice::ReadOnly))
243 const QByteArray& data = result->readAll ();
244 CachePathContents_.insert (path,
new QByteArray (data), data.size ());
250 result->open (QIODevice::ReadOnly);
257 return Load (QStringList (pathVariant), open);
262 return Load (IconizeBasename (basename), open);
267 if (CachePixmaps_.contains (basename))
268 return *CachePixmaps_ [basename];
274 const auto& data = dev->readAll ();
277 result.loadFromData (data);
278 CachePixmaps_.insert (basename,
new QPixmap (result), data.size ());
289 AttrFilters_ = filters;
294 NameFilters_ = filters;
297 void ResourceLoader::ScanPath (
const QString& path)
299 for (
const auto& entry : QDir (path).entryList (NameFilters_, AttrFilters_))
301 Entry2Paths_ [entry] << path;
302 if (SubElemModel_->findItems (entry).size ())
305 SubElemModel_->appendRow (
new QStandardItem (entry));
309 void ResourceLoader::handleDirectoryChanged (
const QString& path)
313 for (
auto i = Entry2Paths_.begin (), end = Entry2Paths_.end (); i != end; ++i)
322 QStringList toRemove;
323 for (
auto i = Entry2Paths_.begin (), end = Entry2Paths_.end (); i != end; ++i)
325 toRemove << i.key ();
327 for (
const auto& entry : toRemove)
329 Entry2Paths_.remove (entry);
331 auto items = SubElemModel_->findItems (entry);
332 for (
auto item : SubElemModel_->findItems (entry))
333 SubElemModel_->removeRow (item->row ());
337 void ResourceLoader::handleFlushCaches ()
339 CachePathContents_.clear ();
340 CachePixmaps_.clear ();
QPixmap LoadPixmap(const QString &basename) const
Returns the pixmap for the given basename.
QFileInfoList List(const QString &option, const QStringList &names=QStringList(), QDir::Filters filters=QDir::NoFilter) const
Lists the available files for the given option.
void watchedDirectoriesChanged()
void SetAttrFilters(QDir::Filters)
Sets the attribute filters for the subelement model.
void AddLocalPrefix(QString prefix=QString())
Registers a local search prefix.
QAbstractItemModel * GetSubElemModel() const
Returns the subelement model with the contents of registered paths.
void SetNameFilters(const QStringList &)
Sets the name filters for the subelement model.
void SetCacheParams(int size, int timeout)
Sets the caching parameters of this loader.
void AddGlobalPrefix()
Registers global OS-dependent prefixes.
void FlushCache()
Forcefully flushes the cache.
QString GetPath(const QStringList &pathVariants) const
Returns the first found path for the list of variants.
QString GetIconPath(const QString &basename) const
Calls GetPath() with standard variants for the icon extensions.
ResourceLoader(const QString &relPath, QObject *obj=0)
Initializes the loader with the given path.
std::shared_ptr< QIODevice > QIODevice_ptr
QIODevice_ptr GetIconDevice(const QString &basename, bool open=false) const
Returns the QIODevice for the corresponding icon.
QIODevice_ptr Load(const QStringList &pathVariants, bool open=false) const
Returns the QIODevice for the corresponding resource.