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 = QStringList (QApplication::applicationDirPath () +
"/../Resources/share/");
108 #elif defined (Q_OS_WIN32)
109 QStringList prefixes = QStringList (QApplication::applicationDirPath () +
"/share/");
110 #elif defined (INSTALL_PREFIX)
111 QStringList prefixes = QStringList (INSTALL_PREFIX
"/share/leechcraft/");
113 QStringList prefixes = QStringList (
"/usr/local/share/leechcraft/")
114 <<
"/usr/share/leechcraft/";
116 bool hasBeenAdded =
false;
117 for (
const QString& prefix : prefixes)
119 GlobalPrefixesChain_ << prefix;
120 ScanPath (prefix + RelativePath_);
122 if (QFile::exists (prefix + RelativePath_))
124 Watcher_->addPath (prefix + RelativePath_);
130 qWarning () << Q_FUNC_INFO
131 <<
"no prefixes have been added:"
139 if (qApp->property (
"no-resource-caching").toBool ())
144 CacheFlushTimer_->stop ();
146 handleFlushCaches ();
151 CacheFlushTimer_->start (timeout);
153 CachePathContents_.setMaxCost (size * 1024);
154 CachePixmaps_.setMaxCost (size * 1024);
160 handleFlushCaches ();
164 const QStringList& nameFilters, QDir::Filters filters)
const
166 QSet<QString> alreadyListed;
167 QFileInfoList result;
168 for (
const auto& prefix : LocalPrefixesChain_ + GlobalPrefixesChain_)
170 const QString& path = prefix + RelativePath_ + option;
172 const QFileInfoList& list =
173 dir.entryInfoList (nameFilters, filters);
174 for (
const auto& info : list)
176 const QString& fname = info.fileName ();
177 if (alreadyListed.contains (fname))
180 alreadyListed << fname;
190 for (
const auto& prefix : LocalPrefixesChain_ + GlobalPrefixesChain_)
191 for (
const auto& path : pathVariants)
193 const QString& can = QFileInfo (prefix + RelativePath_ + path).absoluteFilePath ();
194 if (QFile::exists (can))
203 QStringList IconizeBasename (
const QString& basename)
205 QStringList variants;
206 variants << basename +
".svg"
209 << basename +
".gif";
216 return GetPath (IconizeBasename (basename));
221 QString path =
GetPath (pathVariants);
225 if (CachePathContents_.contains (path))
227 std::shared_ptr<QBuffer> result (
new QBuffer ());
228 result->setData (*CachePathContents_ [path]);
230 result->open (QIODevice::ReadOnly);
234 std::shared_ptr<QFile> result (
new QFile (path));
236 if (!result->isSequential () &&
237 result->size () < CachePathContents_.maxCost () / 2)
239 if (result->open (QIODevice::ReadOnly))
241 const QByteArray& data = result->readAll ();
242 CachePathContents_.insert (path,
new QByteArray (data), data.size ());
248 result->open (QIODevice::ReadOnly);
255 return Load (QStringList (pathVariant), open);
260 return Load (IconizeBasename (basename), open);
265 if (CachePixmaps_.contains (basename))
266 return *CachePixmaps_ [basename];
272 const auto& data = dev->readAll ();
275 result.loadFromData (data);
276 CachePixmaps_.insert (basename,
new QPixmap (result), data.size ());
287 AttrFilters_ = filters;
292 NameFilters_ = filters;
295 void ResourceLoader::ScanPath (
const QString& path)
297 for (
const auto& entry : QDir (path).entryList (NameFilters_, AttrFilters_))
299 Entry2Paths_ [entry] << path;
300 if (SubElemModel_->findItems (entry).size ())
303 SubElemModel_->appendRow (
new QStandardItem (entry));
307 void ResourceLoader::handleDirectoryChanged (
const QString& path)
311 for (
auto i = Entry2Paths_.begin (), end = Entry2Paths_.end (); i != end; ++i)
320 QStringList toRemove;
321 for (
auto i = Entry2Paths_.begin (), end = Entry2Paths_.end (); i != end; ++i)
323 toRemove << i.key ();
325 for (
const auto& entry : toRemove)
327 Entry2Paths_.remove (entry);
329 auto items = SubElemModel_->findItems (entry);
330 for (
auto item : SubElemModel_->findItems (entry))
331 SubElemModel_->removeRow (item->row ());
335 void ResourceLoader::handleFlushCaches ()
337 CachePathContents_.clear ();
338 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.