Skip to content

Commit

Permalink
Resources|Home|libdoomsday: Identify data files asynchronously
Browse files Browse the repository at this point in the history
A background task is used for identifying all the found data bundles.
Notifications are used for informing about the completion of the
operation.
  • Loading branch information
skyjake committed Jun 25, 2016
1 parent ba48bfe commit a2b3e52
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 43 deletions.
15 changes: 14 additions & 1 deletion doomsday/apps/client/src/ui/home/packagescolumnwidget.cpp
Expand Up @@ -25,10 +25,12 @@
#include <de/CallbackAction>
#include <de/Config>
#include <de/DirectoryListDialog>
#include <de/Loop>
#include <de/ui/ActionItem>
#include <de/ui/SubwidgetItem>

#include <doomsday/DoomsdayApp>
#include <doomsday/Games>

using namespace de;

Expand All @@ -52,10 +54,12 @@ static PopupWidget *makePackageFoldersDialog()
}

DENG_GUI_PIMPL(PackagesColumnWidget)
, DENG2_OBSERVES(Games, Readiness)
{
PackagesWidget *packages;
LabelWidget *countLabel;
ui::ListData actions;
LoopCallback mainCall;

Instance(Public *i) : Base(i)
{
Expand Down Expand Up @@ -105,6 +109,14 @@ DENG_GUI_PIMPL(PackagesColumnWidget)
return menu;
}, ui::Down);
}

void gameReadinessUpdated() override
{
if (mainCall.isEmpty())
{
mainCall.enqueue([this] () { packages->refreshPackages(); });
}
}
};

PackagesColumnWidget::PackagesColumnWidget()
Expand All @@ -130,7 +142,8 @@ PackagesColumnWidget::PackagesColumnWidget()
d->packages->rule().height());

d->packages->setFilterEditorMinimumY(scrollArea().margins().top());
d->packages->refreshPackages();

DoomsdayApp::games().audienceForReadiness() += d;
}

String PackagesColumnWidget::tabHeading() const
Expand Down
18 changes: 10 additions & 8 deletions doomsday/apps/client/src/ui/widgets/packageswidget.cpp
Expand Up @@ -59,7 +59,7 @@ static PackageLoadStatus isPackageLoaded;
PackagesWidget::IPackageStatus::~IPackageStatus() {}

DENG_GUI_PIMPL(PackagesWidget)
, DENG2_OBSERVES(res::Bundles, Refresh)
, DENG2_OBSERVES(res::Bundles, Identify)
, public ChildWidgetOrganizer::IFilter
, public ChildWidgetOrganizer::IWidgetFactory
{
Expand Down Expand Up @@ -484,14 +484,16 @@ DENG_GUI_PIMPL(PackagesWidget)
}
}

void dataBundlesRefreshed()
void dataBundlesIdentified(bool) override
{
// After bundles have been refreshed, make sure the list items are up to date.
mainCall.enqueue([this] ()
if (mainCall.isEmpty())
{
App::fileSystem().refresh();
self.populate();
});
mainCall.enqueue([this] ()
{
self.populate();
});
}
}

//- ChildWidgetOrganizer::IFilter ---------------------------------------------
Expand Down Expand Up @@ -551,7 +553,7 @@ PackagesWidget::PackagesWidget(String const &name)
{
rule().setInput(Rule::Height, d->search->rule().height() + d->menu->rule().height());

DoomsdayApp::bundles().audienceForRefresh() += d;
DoomsdayApp::bundles().audienceForIdentify() += d;
}

void PackagesWidget::setFilterEditorMinimumY(Rule const &minY)
Expand Down Expand Up @@ -710,5 +712,5 @@ void PackagesWidget::operator << (PersistentState const &fromState)
void PackagesWidget::refreshPackages()
{
App::fileSystem().refresh();
d->tasks.start([] () { DoomsdayApp::bundles().identify(); });
DoomsdayApp::bundles().identify();
}
10 changes: 6 additions & 4 deletions doomsday/apps/libdoomsday/include/doomsday/resource/bundles.h
Expand Up @@ -41,7 +41,7 @@ class LIBDOOMSDAY_PUBLIC Bundles
typedef QList<de::Info::BlockElement const *> BlockElements;

/// Notified when a data bundle refresh/identification has been made.
DENG2_DEFINE_AUDIENCE2(Refresh, void dataBundlesRefreshed())
DENG2_DEFINE_AUDIENCE2(Identify, void dataBundlesIdentified(bool wereIdentified))

DENG2_ERROR(InvalidError);

Expand Down Expand Up @@ -71,11 +71,13 @@ class LIBDOOMSDAY_PUBLIC Bundles
* previous call of this method. Recognized data files are linked as
* packages under the /sys/bundles folder.
*
* @see res::DataBundle::identifyPackages()
* Calling this starts a background task where the identification is performed.
* The method returns immediately. The Identify audience is notified once the
* task is finished.
*
* @return @c true, if one or more bundles were identified.
* @see res::DataBundle::identifyPackages()
*/
bool identify();
void identify();

/**
* Finds a matching entry in the registry for a given data bundle.
Expand Down
21 changes: 1 addition & 20 deletions doomsday/apps/libdoomsday/src/doomsdayapp.cpp
Expand Up @@ -308,16 +308,9 @@ DENG2_PIMPL(DoomsdayApp)
packs.populate();
}

void folderPopulated(Folder &)
void folderPopulated(Folder &) // "/local/packs" or "/local/wads"
{
dataBundles.identify();
mainCall.enqueue([this] ()
{
if (initialized)
{
games.checkReadiness();
}
});
}

#ifdef UNIX
Expand Down Expand Up @@ -404,23 +397,11 @@ void DoomsdayApp::initialize()
void DoomsdayApp::initWadFolders()
{
d->initWadFolders();
/*d->dataBundles.identify();
if (d->initialized)
{
games().checkReadiness();
}*/
}

void DoomsdayApp::initPackageFolders()
{
d->initPackageFolders();
/*d->dataBundles.identify();
if (d->initialized)
{
games().checkReadiness();
}*/
}

void DoomsdayApp::determineGlobalPaths()
Expand Down
13 changes: 13 additions & 0 deletions doomsday/apps/libdoomsday/src/games.cpp
Expand Up @@ -24,18 +24,21 @@
#include <doomsday/console/cmd.h>
#include <doomsday/filesys/fs_main.h>
#include <doomsday/resource/manifest.h>
#include <doomsday/resource/bundles.h>

#include <de/App>
#include <de/ScriptSystem>
#include <de/ArrayValue>
#include <de/DictionaryValue>
#include <de/Log>
#include <de/Loop>
#include <de/charsymbols.h>
#include <QtAlgorithms>

using namespace de;

DENG2_PIMPL(Games)
, DENG2_OBSERVES(res::Bundles, Identify)
{
/// The actual collection.
All games;
Expand All @@ -45,6 +48,8 @@ DENG2_PIMPL(Games)

QHash<String, Game *> idLookup; // not owned, lower case

LoopCallback mainCall;

/**
* Delegates game addition notifications to scripts.
*/
Expand Down Expand Up @@ -114,6 +119,14 @@ DENG2_PIMPL(Games)
return nullptr;
}

void dataBundlesIdentified(bool wereIdentified)
{
if (wereIdentified && mainCall.isEmpty())
{
mainCall.enqueue([this] () { self.checkReadiness(); });
}
}

DENG2_PIMPL_AUDIENCE(Addition)
DENG2_PIMPL_AUDIENCE(Readiness)
DENG2_PIMPL_AUDIENCE(Progress)
Expand Down
24 changes: 14 additions & 10 deletions doomsday/apps/libdoomsday/src/resource/bundles.cpp
Expand Up @@ -24,6 +24,7 @@
#include <de/PackageLoader>
#include <de/LinkFile>
#include <de/Loop>
#include <de/TaskPool>

#include <QList>
#include <QSet>
Expand All @@ -43,6 +44,7 @@ DENG2_PIMPL(Bundles)
QSet<DataBundle const *> bundlesToIdentify; // lock for access
LoopCallback mainCall;
QHash<DataBundle::Format, BlockElements> formatEntries;
TaskPool tasks;

Instance(Public *i) : Base(i)
{
Expand Down Expand Up @@ -149,10 +151,10 @@ DENG2_PIMPL(Bundles)
}
}

DENG2_PIMPL_AUDIENCE(Refresh)
DENG2_PIMPL_AUDIENCE(Identify)
};

DENG2_AUDIENCE_METHOD(Bundles, Refresh)
DENG2_AUDIENCE_METHOD(Bundles, Identify)

Bundles::Bundles()
: d(new Instance(this))
Expand All @@ -170,14 +172,16 @@ Bundles::BlockElements Bundles::formatEntries(DataBundle::Format format) const
return d->formatEntries[format];
}

bool Bundles::identify()
void Bundles::identify()
{
bool const identified = d->identifyAddedDataBundles();
DENG2_FOR_AUDIENCE2(Refresh, i)
d->tasks.start([this] ()
{
i->dataBundlesRefreshed();
}
return identified;
bool const identified = d->identifyAddedDataBundles();
DENG2_FOR_AUDIENCE2(Identify, i)
{
i->dataBundlesIdentified(identified);
}
});
}

Bundles::MatchResult Bundles::match(DataBundle const &bundle) const
Expand Down Expand Up @@ -221,7 +225,7 @@ Bundles::MatchResult Bundles::match(DataBundle const &bundle) const
String fileType = def->keyValue(QStringLiteral("fileType"));
if (fileType.isEmpty()) fileType = "file"; // prefer files by default
if ((!fileType.compareWithoutCase(QStringLiteral("file")) && source.status().type() == File::Status::FILE) ||
(!fileType.compareWithoutCase(QStringLiteral("folder")) && source.status().type() == File::Status::FOLDER))
(!fileType.compareWithoutCase(QStringLiteral("folder")) && source.status().type() == File::Status::FOLDER))
{
++score;
}
Expand Down Expand Up @@ -281,7 +285,7 @@ Bundles::MatchResult Bundles::match(DataBundle const &bundle) const
}

if (requiredSize >= 0 &&
bundle.lumpDirectory()->lumpSize(lumpName) != duint32(requiredSize))
bundle.lumpDirectory()->lumpSize(lumpName) != duint32(requiredSize))
{
--score;
break;
Expand Down

0 comments on commit a2b3e52

Please sign in to comment.