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_);
106 #if defined (Q_OS_MAC) && !defined (USE_UNIX_LAYOUT) 107 const QStringList prefixes { QApplication::applicationDirPath () +
"/../Resources/share/" };
108 #elif defined (Q_OS_WIN32) 109 const QStringList prefixes { QApplication::applicationDirPath () +
"/share/" };
110 #elif defined (INSTALL_PREFIX) 111 const QStringList prefixes { INSTALL_PREFIX
"/share/leechcraft/" };
113 const QStringList prefixes
115 "/usr/local/share/leechcraft/",
116 "/usr/share/leechcraft/" 119 bool hasBeenAdded =
false;
120 for (
const auto& prefix : prefixes)
122 GlobalPrefixesChain_ << prefix;
123 ScanPath (prefix + RelativePath_);
125 if (QFile::exists (prefix + RelativePath_))
127 Watcher_->addPath (prefix + RelativePath_);
133 qWarning () << Q_FUNC_INFO
134 <<
"no prefixes have been added:" 142 if (qApp->property (
"no-resource-caching").toBool ())
147 CacheFlushTimer_->stop ();
149 handleFlushCaches ();
154 CacheFlushTimer_->start (timeout);
156 CachePathContents_.setMaxCost (size * 1024);
157 CachePixmaps_.setMaxCost (size * 1024);
163 handleFlushCaches ();
167 const QStringList& nameFilters, QDir::Filters filters)
const 169 QSet<QString> alreadyListed;
170 QFileInfoList result;
171 for (
const auto& prefix : LocalPrefixesChain_ + GlobalPrefixesChain_)
173 const QString& path = prefix + RelativePath_ + option;
175 const QFileInfoList& list =
176 dir.entryInfoList (nameFilters, filters);
177 for (
const auto& info : list)
179 const QString& fname = info.fileName ();
180 if (alreadyListed.contains (fname))
183 alreadyListed << fname;
193 for (
const auto& prefix : LocalPrefixesChain_ + GlobalPrefixesChain_)
194 for (
const auto& path : pathVariants)
196 const QString& can = QFileInfo (prefix + RelativePath_ + path).absoluteFilePath ();
197 if (QFile::exists (can))
206 QStringList IconizeBasename (
const QString& basename)
208 QStringList variants;
209 variants << basename +
".svg" 212 << basename +
".gif";
219 return GetPath (IconizeBasename (basename));
224 QString path =
GetPath (pathVariants);
228 if (CachePathContents_.contains (path))
230 std::shared_ptr<QBuffer> result (
new QBuffer ());
231 result->setData (*CachePathContents_ [path]);
233 result->open (QIODevice::ReadOnly);
237 std::shared_ptr<QFile> result (
new QFile (path));
239 if (!result->isSequential () &&
240 result->size () < CachePathContents_.maxCost () / 2)
242 if (result->open (QIODevice::ReadOnly))
244 const QByteArray& data = result->readAll ();
245 CachePathContents_.insert (path,
new QByteArray (data), data.size ());
251 result->open (QIODevice::ReadOnly);
258 return Load (QStringList (pathVariant), open);
263 return Load (IconizeBasename (basename), open);
268 if (CachePixmaps_.contains (basename))
269 return *CachePixmaps_ [basename];
275 const auto& data = dev->readAll ();
278 result.loadFromData (data);
279 CachePixmaps_.insert (basename,
new QPixmap (result), data.size ());
290 AttrFilters_ = filters;
295 NameFilters_ = filters;
298 void ResourceLoader::ScanPath (
const QString& path)
300 for (
const auto& entry : QDir (path).entryList (NameFilters_, AttrFilters_))
302 Entry2Paths_ [entry] << path;
303 if (SubElemModel_->findItems (entry).size ())
306 SubElemModel_->appendRow (
new QStandardItem (entry));
310 void ResourceLoader::handleDirectoryChanged (
const QString& path)
314 for (
auto i = Entry2Paths_.begin (), end = Entry2Paths_.end (); i != end; ++i)
323 QStringList toRemove;
324 for (
auto i = Entry2Paths_.begin (), end = Entry2Paths_.end (); i != end; ++i)
326 toRemove << i.key ();
328 for (
const auto& entry : toRemove)
330 Entry2Paths_.remove (entry);
332 auto items = SubElemModel_->findItems (entry);
333 for (
auto item : SubElemModel_->findItems (entry))
334 SubElemModel_->removeRow (item->row ());
338 void ResourceLoader::handleFlushCaches ()
340 CachePathContents_.clear ();
341 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.