Made database scan work, added immediate scan option
This commit is contained in:
@@ -30,6 +30,6 @@
|
|||||||
<message id="msg-error-not-a-directory">Not a directory</message>
|
<message id="msg-error-not-a-directory">Not a directory</message>
|
||||||
<message id="msg-btn-apply">Apply</message>
|
<message id="msg-btn-apply">Apply</message>
|
||||||
<message id="msg-btn-discard">Discard</message>
|
<message id="msg-btn-discard">Discard</message>
|
||||||
|
<message id="msg-btn-immediate-scan">Scan now!</message>
|
||||||
|
|
||||||
</messages>
|
</messages>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
${apply-btn class="btn-primary"} ${discard-btn}
|
${apply-btn class="btn-primary"} ${discard-btn} ${immediate-scan-btn class="btn-info"}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -295,12 +295,12 @@ Cluster::pointer
|
|||||||
ClusterType::getCluster(std::string name) const
|
ClusterType::getCluster(std::string name) const
|
||||||
{
|
{
|
||||||
assert(self());
|
assert(self());
|
||||||
assert(self()->id() != Wt::Dbo::dbo_traits<Release>::invalidId() );
|
assert(self()->id() != Wt::Dbo::dbo_traits<ClusterType>::invalidId() );
|
||||||
assert(session());
|
assert(session());
|
||||||
|
|
||||||
return session()->find<Cluster>()
|
return session()->find<Cluster>()
|
||||||
.where("name = ?").bind(name)
|
.where("name = ?").bind(name)
|
||||||
.where("cluster_type_id = ").bind(self()->id());
|
.where("cluster_type_id = ?").bind(self()->id());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Cluster::pointer>
|
std::vector<Cluster::pointer>
|
||||||
@@ -311,7 +311,7 @@ ClusterType::getClusters() const
|
|||||||
assert(session());
|
assert(session());
|
||||||
|
|
||||||
Wt::Dbo::collection<Cluster::pointer> res = session()->find<Cluster>()
|
Wt::Dbo::collection<Cluster::pointer> res = session()->find<Cluster>()
|
||||||
.where("cluster_type_id = ").bind(self()->id())
|
.where("cluster_type_id = ?").bind(self()->id())
|
||||||
.orderBy("name");
|
.orderBy("name");
|
||||||
|
|
||||||
return std::vector<Cluster::pointer>(res.begin(), res.end());
|
return std::vector<Cluster::pointer>(res.begin(), res.end());
|
||||||
|
|||||||
+2
-1
@@ -129,7 +129,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
// bind entry point
|
// bind entry point
|
||||||
server.addEntryPoint(Wt::Application, boost::bind(UserInterface::LmsApplication::create,
|
server.addEntryPoint(Wt::Application, boost::bind(UserInterface::LmsApplication::create,
|
||||||
_1, boost::ref(*connectionPool)));
|
_1, boost::ref(*connectionPool), boost::ref(scanner)));
|
||||||
|
|
||||||
// Start
|
// Start
|
||||||
LMS_LOG(MAIN, INFO) << "Starting Media scanner...";
|
LMS_LOG(MAIN, INFO) << "Starting Media scanner...";
|
||||||
@@ -149,6 +149,7 @@ int main(int argc, char* argv[])
|
|||||||
LMS_LOG(MAIN, INFO) << "Stopping database updater...";
|
LMS_LOG(MAIN, INFO) << "Stopping database updater...";
|
||||||
scanner.stop();
|
scanner.stop();
|
||||||
|
|
||||||
|
LMS_LOG(MAIN, INFO) << "Clean stop!";
|
||||||
res = EXIT_SUCCESS;
|
res = EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
catch( libconfig::FileIOException& e)
|
catch( libconfig::FileIOException& e)
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ MediaScanner::start(void)
|
|||||||
_running = true;
|
_running = true;
|
||||||
|
|
||||||
// post some jobs in the io_service
|
// post some jobs in the io_service
|
||||||
processNextJob();
|
scheduleScan();
|
||||||
|
|
||||||
_ioService.start();
|
_ioService.start();
|
||||||
}
|
}
|
||||||
@@ -171,50 +171,63 @@ MediaScanner::stop(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MediaScanner::processNextJob(void)
|
MediaScanner::scheduleImmediateScan()
|
||||||
{
|
{
|
||||||
if (Setting::getBool(_db.getSession(), "manual_scan_requested", false))
|
_ioService.post([=]()
|
||||||
{
|
{
|
||||||
LMS_LOG(DBUPDATER, INFO) << "Manual scan requested!";
|
LMS_LOG(DBUPDATER, INFO) << "Schedule immediate scan";
|
||||||
scheduleScan( boost::posix_time::seconds(0) );
|
scheduleScan( boost::posix_time::seconds(0) );
|
||||||
}
|
});
|
||||||
else
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaScanner::reschedule()
|
||||||
|
{
|
||||||
|
_ioService.post([=]()
|
||||||
{
|
{
|
||||||
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
|
LMS_LOG(DBUPDATER, INFO) << "Rescheduling scan";
|
||||||
boost::posix_time::time_duration startTime = getUpdateStartTime(_db.getSession());
|
scheduleScan();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
boost::gregorian::date nextScanDate;
|
void
|
||||||
|
MediaScanner::scheduleScan()
|
||||||
|
{
|
||||||
|
boost::posix_time::ptime now = boost::posix_time::second_clock::local_time();
|
||||||
|
boost::posix_time::time_duration startTime = getUpdateStartTime(_db.getSession());
|
||||||
|
|
||||||
switch ( getUpdatePeriod(_db.getSession()) )
|
boost::gregorian::date nextScanDate;
|
||||||
{
|
|
||||||
case UpdatePeriod::Daily:
|
|
||||||
if (now.time_of_day() < startTime)
|
|
||||||
nextScanDate = now.date();
|
|
||||||
else
|
|
||||||
nextScanDate = getNextDay(now.date());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UpdatePeriod::Weekly:
|
switch ( getUpdatePeriod(_db.getSession()) )
|
||||||
if (now.time_of_day() < startTime && now.date().day_of_week() == 1)
|
{
|
||||||
nextScanDate = now.date();
|
case UpdatePeriod::Daily:
|
||||||
else
|
if (now.time_of_day() < startTime)
|
||||||
nextScanDate = getNextMonday(now.date());
|
nextScanDate = now.date();
|
||||||
break;
|
else
|
||||||
|
nextScanDate = getNextDay(now.date());
|
||||||
|
break;
|
||||||
|
|
||||||
case UpdatePeriod::Monthly:
|
case UpdatePeriod::Weekly:
|
||||||
if (now.time_of_day() < startTime && now.date().day() == 1)
|
if (now.time_of_day() < startTime && now.date().day_of_week() == 1)
|
||||||
nextScanDate = now.date();
|
nextScanDate = now.date();
|
||||||
else
|
else
|
||||||
nextScanDate = getNextFirstOfMonth(now.date());
|
nextScanDate = getNextMonday(now.date());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UpdatePeriod::Never:
|
case UpdatePeriod::Monthly:
|
||||||
break;
|
if (now.time_of_day() < startTime && now.date().day() == 1)
|
||||||
}
|
nextScanDate = now.date();
|
||||||
|
else
|
||||||
|
nextScanDate = getNextFirstOfMonth(now.date());
|
||||||
|
break;
|
||||||
|
|
||||||
if (!nextScanDate.is_special())
|
case UpdatePeriod::Never:
|
||||||
scheduleScan( boost::posix_time::ptime (nextScanDate, startTime) );
|
LMS_LOG(DBUPDATER, INFO) << "Auto scan disabled!";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!nextScanDate.is_special())
|
||||||
|
scheduleScan( boost::posix_time::ptime (nextScanDate, startTime) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -222,7 +235,7 @@ MediaScanner::scheduleScan( boost::posix_time::time_duration duration)
|
|||||||
{
|
{
|
||||||
LMS_LOG(DBUPDATER, INFO) << "Scheduling next scan in " << duration;
|
LMS_LOG(DBUPDATER, INFO) << "Scheduling next scan in " << duration;
|
||||||
_scheduleTimer.expires_from_now(duration);
|
_scheduleTimer.expires_from_now(duration);
|
||||||
_scheduleTimer.async_wait( boost::bind( &MediaScanner::process, this, boost::asio::placeholders::error) );
|
_scheduleTimer.async_wait( boost::bind( &MediaScanner::scan, this, boost::asio::placeholders::error) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -230,11 +243,11 @@ MediaScanner::scheduleScan( boost::posix_time::ptime time)
|
|||||||
{
|
{
|
||||||
LMS_LOG(DBUPDATER, INFO) << "Scheduling next scan at " << time;
|
LMS_LOG(DBUPDATER, INFO) << "Scheduling next scan at " << time;
|
||||||
_scheduleTimer.expires_at(time);
|
_scheduleTimer.expires_at(time);
|
||||||
_scheduleTimer.async_wait( boost::bind( &MediaScanner::process, this, boost::asio::placeholders::error) );
|
_scheduleTimer.async_wait( boost::bind( &MediaScanner::scan, this, boost::asio::placeholders::error) );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MediaScanner::process(boost::system::error_code err)
|
MediaScanner::scan(boost::system::error_code err)
|
||||||
{
|
{
|
||||||
if (err)
|
if (err)
|
||||||
return;
|
return;
|
||||||
@@ -250,9 +263,9 @@ MediaScanner::process(boost::system::error_code err)
|
|||||||
if (!_running)
|
if (!_running)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
LMS_LOG(DBUPDATER, INFO) << "Processing root directory '" << rootDirectory << "'...";
|
LMS_LOG(DBUPDATER, INFO) << "scaning root directory '" << rootDirectory << "'...";
|
||||||
processRootDirectory(rootDirectory, stats);
|
scanRootDirectory(rootDirectory, stats);
|
||||||
LMS_LOG(DBUPDATER, INFO) << "Processing root directory '" << rootDirectory << "' DONE";
|
LMS_LOG(DBUPDATER, INFO) << "scaning root directory '" << rootDirectory << "' DONE";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_running)
|
if (_running)
|
||||||
@@ -269,9 +282,8 @@ MediaScanner::process(boost::system::error_code err)
|
|||||||
if (_running)
|
if (_running)
|
||||||
{
|
{
|
||||||
Setting::setTime(_db.getSession(), "last_scan", now);
|
Setting::setTime(_db.getSession(), "last_scan", now);
|
||||||
Setting::setBool(_db.getSession(), "manual_scan_requested", false);
|
|
||||||
|
|
||||||
processNextJob();
|
scheduleScan();
|
||||||
|
|
||||||
scanComplete().emit(stats);
|
scanComplete().emit(stats);
|
||||||
}
|
}
|
||||||
@@ -373,12 +385,19 @@ MediaScanner::getClusters( const MetaData::Clusters& clustersNames)
|
|||||||
for (auto clusterNames : clustersNames)
|
for (auto clusterNames : clustersNames)
|
||||||
{
|
{
|
||||||
ClusterType::pointer clusterType = ClusterType::getByName(_db.getSession(), clusterNames.first);
|
ClusterType::pointer clusterType = ClusterType::getByName(_db.getSession(), clusterNames.first);
|
||||||
|
bool newType = !clusterType;
|
||||||
|
|
||||||
if (!clusterType)
|
if (!clusterType)
|
||||||
clusterType = ClusterType::create(_db.getSession(), clusterNames.first);
|
clusterType = ClusterType::create(_db.getSession(), clusterNames.first);
|
||||||
|
|
||||||
|
std::cout << "Cluster type = " << clusterType.id() << "\n";
|
||||||
for (auto clusterName : clusterNames.second)
|
for (auto clusterName : clusterNames.second)
|
||||||
{
|
{
|
||||||
Cluster::pointer cluster = clusterType->getCluster(clusterName);
|
Cluster::pointer cluster;
|
||||||
|
|
||||||
|
if (!newType)
|
||||||
|
cluster = clusterType->getCluster(clusterName);
|
||||||
|
|
||||||
if (!cluster)
|
if (!cluster)
|
||||||
cluster = Cluster::create(_db.getSession(), clusterType, clusterName);
|
cluster = Cluster::create(_db.getSession(), clusterType, clusterName);
|
||||||
|
|
||||||
@@ -390,7 +409,7 @@ MediaScanner::getClusters( const MetaData::Clusters& clustersNames)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MediaScanner::processAudioFile( const boost::filesystem::path& file, Stats& stats)
|
MediaScanner::scanAudioFile( const boost::filesystem::path& file, Stats& stats)
|
||||||
{
|
{
|
||||||
boost::posix_time::ptime lastWriteTime (boost::posix_time::from_time_t( boost::filesystem::last_write_time( file ) ) );
|
boost::posix_time::ptime lastWriteTime (boost::posix_time::from_time_t( boost::filesystem::last_write_time( file ) ) );
|
||||||
|
|
||||||
@@ -601,7 +620,7 @@ MediaScanner::processAudioFile( const boost::filesystem::path& file, Stats& stat
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MediaScanner::processRootDirectory(boost::filesystem::path rootDirectory, Stats& stats)
|
MediaScanner::scanRootDirectory(boost::filesystem::path rootDirectory, Stats& stats)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
@@ -619,7 +638,7 @@ MediaScanner::processRootDirectory(boost::filesystem::path rootDirectory, Stats&
|
|||||||
if (boost::filesystem::is_regular(path))
|
if (boost::filesystem::is_regular(path))
|
||||||
{
|
{
|
||||||
if (isFileSupported(path, _fileExtensions))
|
if (isFileSupported(path, _fileExtensions))
|
||||||
processAudioFile(path, stats );
|
scanAudioFile(path, stats );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ class MediaScanner
|
|||||||
void stop();
|
void stop();
|
||||||
void restart();
|
void restart();
|
||||||
|
|
||||||
|
void scheduleImmediateScan();
|
||||||
|
void reschedule();
|
||||||
|
|
||||||
struct Stats
|
struct Stats
|
||||||
{
|
{
|
||||||
std::size_t nbNoChange = 0; // no change since last scan
|
std::size_t nbNoChange = 0; // no change since last scan
|
||||||
@@ -82,14 +85,14 @@ class MediaScanner
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
// Job handling
|
// Job handling
|
||||||
void processNextJob();
|
void scheduleScan();
|
||||||
void scheduleScan(boost::posix_time::time_duration duration);
|
void scheduleScan(boost::posix_time::time_duration duration);
|
||||||
void scheduleScan(boost::posix_time::ptime time);
|
void scheduleScan(boost::posix_time::ptime time);
|
||||||
|
|
||||||
// Update database (scheduled callback)
|
// Update database (scheduled callback)
|
||||||
void process(boost::system::error_code ec);
|
void scan(boost::system::error_code ec);
|
||||||
|
|
||||||
void processRootDirectory( boost::filesystem::path rootDirectory, Stats& stats);
|
void scanRootDirectory( boost::filesystem::path rootDirectory, Stats& stats);
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
Database::Artist::pointer getArtist( const boost::filesystem::path& file, const std::string& name, const std::string& MBID);
|
Database::Artist::pointer getArtist( const boost::filesystem::path& file, const std::string& name, const std::string& MBID);
|
||||||
@@ -100,11 +103,7 @@ class MediaScanner
|
|||||||
// Audio
|
// Audio
|
||||||
void checkAudioFiles( Stats& stats );
|
void checkAudioFiles( Stats& stats );
|
||||||
void checkDuplicatedAudioFiles( Stats& stats );
|
void checkDuplicatedAudioFiles( Stats& stats );
|
||||||
void processAudioFile( const boost::filesystem::path& file, Stats& stats);
|
void scanAudioFile( const boost::filesystem::path& file, Stats& stats);
|
||||||
|
|
||||||
// Video
|
|
||||||
void checkVideoFiles( Stats& stats );
|
|
||||||
void processVideoFile( const boost::filesystem::path& file, Stats& stats);
|
|
||||||
|
|
||||||
bool _running;
|
bool _running;
|
||||||
Wt::WIOService _ioService;
|
Wt::WIOService _ioService;
|
||||||
|
|||||||
@@ -46,13 +46,13 @@ namespace skeletons {
|
|||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
Wt::WApplication*
|
Wt::WApplication*
|
||||||
LmsApplication::create(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool)
|
LmsApplication::create(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* You could read information from the environment to decide whether
|
* You could read information from the environment to decide whether
|
||||||
* the user has permission to start a new application
|
* the user has permission to start a new application
|
||||||
*/
|
*/
|
||||||
return new LmsApplication(env, connectionPool);
|
return new LmsApplication(env, connectionPool, scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
LmsApplication*
|
LmsApplication*
|
||||||
@@ -67,9 +67,10 @@ LmsApplication::instance()
|
|||||||
* constructor so it is typically also an argument for your custom
|
* constructor so it is typically also an argument for your custom
|
||||||
* application constructor.
|
* application constructor.
|
||||||
*/
|
*/
|
||||||
LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool)
|
LmsApplication::LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner)
|
||||||
: Wt::WApplication(env),
|
: Wt::WApplication(env),
|
||||||
_db(connectionPool),
|
_db(connectionPool),
|
||||||
|
_scanner(scanner),
|
||||||
_imageResource(nullptr),
|
_imageResource(nullptr),
|
||||||
_transcodeResource(nullptr)
|
_transcodeResource(nullptr)
|
||||||
{
|
{
|
||||||
@@ -141,6 +142,11 @@ TranscodeResource* SessionTranscodeResource()
|
|||||||
return LmsApplication::instance()->getTranscodeResource();
|
return LmsApplication::instance()->getTranscodeResource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scanner::MediaScanner& MediaScanner()
|
||||||
|
{
|
||||||
|
return LmsApplication::instance()->getMediaScanner();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LmsApplication::goHome()
|
LmsApplication::goHome()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,8 @@
|
|||||||
#include <Wt/Dbo/SqlConnectionPool>
|
#include <Wt/Dbo/SqlConnectionPool>
|
||||||
|
|
||||||
#include "database/DatabaseHandler.hpp"
|
#include "database/DatabaseHandler.hpp"
|
||||||
|
#include "scanner/MediaScanner.hpp"
|
||||||
|
|
||||||
#include "resource/ImageResource.hpp"
|
#include "resource/ImageResource.hpp"
|
||||||
#include "resource/TranscodeResource.hpp"
|
#include "resource/TranscodeResource.hpp"
|
||||||
|
|
||||||
@@ -34,26 +36,29 @@ namespace UserInterface {
|
|||||||
class LmsApplication : public Wt::WApplication
|
class LmsApplication : public Wt::WApplication
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static Wt::WApplication *create(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool);
|
static Wt::WApplication *create(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner);
|
||||||
static LmsApplication* instance();
|
static LmsApplication* instance();
|
||||||
|
|
||||||
LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool);
|
|
||||||
|
|
||||||
// Session application data
|
// Session application data
|
||||||
ImageResource* getImageResource() { return _imageResource; }
|
ImageResource* getImageResource() { return _imageResource; }
|
||||||
TranscodeResource* getTranscodeResource() { return _transcodeResource; }
|
TranscodeResource* getTranscodeResource() { return _transcodeResource; }
|
||||||
Database::Handler& getDbHandler() { return _db;}
|
Database::Handler& getDbHandler() { return _db;}
|
||||||
|
|
||||||
|
Scanner::MediaScanner& getMediaScanner() { return _scanner; }
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
void goHome();
|
void goHome();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
LmsApplication(const Wt::WEnvironment& env, Wt::Dbo::SqlConnectionPool& connectionPool, Scanner::MediaScanner& scanner);
|
||||||
|
|
||||||
void handleAuthEvent(void);
|
void handleAuthEvent(void);
|
||||||
void createFirstConnectionUI();
|
void createFirstConnectionUI();
|
||||||
void createLmsUI();
|
void createLmsUI();
|
||||||
|
|
||||||
Database::Handler _db;
|
Database::Handler _db;
|
||||||
|
Scanner::MediaScanner& _scanner;
|
||||||
ImageResource* _imageResource;
|
ImageResource* _imageResource;
|
||||||
TranscodeResource* _transcodeResource;
|
TranscodeResource* _transcodeResource;
|
||||||
};
|
};
|
||||||
@@ -70,6 +75,7 @@ Database::User::pointer CurrentUser();
|
|||||||
ImageResource *SessionImageResource();
|
ImageResource *SessionImageResource();
|
||||||
TranscodeResource *SessionTranscodeResource();
|
TranscodeResource *SessionTranscodeResource();
|
||||||
|
|
||||||
|
Scanner::MediaScanner& MediaScanner();
|
||||||
|
|
||||||
} // namespace UserInterface
|
} // namespace UserInterface
|
||||||
|
|
||||||
|
|||||||
@@ -258,13 +258,19 @@ DatabaseView::DatabaseView(Wt::WContainerWidget *parent)
|
|||||||
|
|
||||||
Wt::WPushButton *saveBtn = new Wt::WPushButton(Wt::WString::tr("msg-btn-apply"));
|
Wt::WPushButton *saveBtn = new Wt::WPushButton(Wt::WString::tr("msg-btn-apply"));
|
||||||
bindWidget("apply-btn", saveBtn);
|
bindWidget("apply-btn", saveBtn);
|
||||||
saveBtn->setStyleClass("btn-primary");
|
|
||||||
|
|
||||||
Wt::WPushButton *discardBtn = new Wt::WPushButton(Wt::WString::tr("msg-btn-discard"));
|
Wt::WPushButton *discardBtn = new Wt::WPushButton(Wt::WString::tr("msg-btn-discard"));
|
||||||
bindWidget("discard-btn", discardBtn);
|
bindWidget("discard-btn", discardBtn);
|
||||||
|
|
||||||
|
Wt::WPushButton *immScanBtn = new Wt::WPushButton(Wt::WString::tr("msg-btn-immediate-scan"));
|
||||||
|
bindWidget("immediate-scan-btn", immScanBtn);
|
||||||
|
|
||||||
saveBtn->clicked().connect(this, &DatabaseView::processSave);
|
saveBtn->clicked().connect(this, &DatabaseView::processSave);
|
||||||
discardBtn->clicked().connect(this, &DatabaseView::processDiscard);
|
discardBtn->clicked().connect(this, &DatabaseView::processDiscard);
|
||||||
|
immScanBtn->clicked().connect(std::bind([=] ()
|
||||||
|
{
|
||||||
|
MediaScanner().scheduleImmediateScan();
|
||||||
|
}));
|
||||||
|
|
||||||
updateView(_model);
|
updateView(_model);
|
||||||
}
|
}
|
||||||
@@ -285,7 +291,7 @@ DatabaseView::processSave()
|
|||||||
if (_model->validate()) {
|
if (_model->validate()) {
|
||||||
_model->saveData();
|
_model->saveData();
|
||||||
|
|
||||||
// _sigChanged.emit();
|
MediaScanner().reschedule();
|
||||||
}
|
}
|
||||||
// Udate the view: Delete any validation message in the view, etc.
|
// Udate the view: Delete any validation message in the view, etc.
|
||||||
updateView(_model);
|
updateView(_model);
|
||||||
|
|||||||
Reference in New Issue
Block a user