Skip to content

Commit

Permalink
[nemo-systemsettings] Add watched property to UserInfo.
Browse files Browse the repository at this point in the history
Add watched property to UserInfo so that it's not necessary to watch for
changes in databases. Reduces some overhead. Note that this doesn't
allow disabling wathing. Once it is set to true it remains that way.
Separated the watching callback to its own method.

Signed-off-by: Tomi Leppänen <tomi.leppanen@jolla.com>
  • Loading branch information
Tomin1 committed Apr 28, 2020
1 parent f948fe2 commit 5638f15
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 24 deletions.
89 changes: 65 additions & 24 deletions src/userinfo.cpp
Expand Up @@ -91,6 +91,7 @@ UserInfoPrivate::UserInfoPrivate(struct passwd *pwd)

UserInfoPrivate::~UserInfoPrivate()
{
delete m_watcher;
}

QWeakPointer<UserInfoPrivate> UserInfoPrivate::s_current;
Expand Down Expand Up @@ -207,7 +208,6 @@ UserInfo::UserInfo()
UserInfoPrivate::s_current = d_ptr;
}
connectSignals();
watchForChanges();
}

UserInfo::UserInfo(const UserInfo &other)
Expand Down Expand Up @@ -389,6 +389,39 @@ bool UserInfo::alone()
return d->alone();
}

/**
* Returns true if object follows database changes, defaults to false
*
* Note that even if watched is false, the object can change and emit
* change signals.
*/
bool UserInfo::watched()
{
Q_D(const UserInfo);
return (bool)d->m_watcher;
}

/**
* If set true object starts to follow database changes.
* Setting to false is not allowed but it can change back to false
* if watching fails.
*
* Setting to false would be a bit difficult since if some data sharing
* object would like to stop watching it will end watching for all of
* them. Thus it's better if you never set this to false. In practice,
* it's not necessary to set this to false ever.
*/
void UserInfo::setWatched(bool watch)
{
Q_D(UserInfo);
// UserInfo objects with uid set to InvalidId can not be watched
if (d->m_uid != InvalidId && watch && !d->m_watcher) {
watchForChanges();
if (d_ptr->m_watcher)
emit d->watchedChanged();
}
}

/**
* Resets object reloading all information
*/
Expand Down Expand Up @@ -424,8 +457,13 @@ void UserInfo::replace(QSharedPointer<UserInfoPrivate> other)
if (old->m_loggedIn != d_ptr->m_loggedIn)
emit currentChanged();

if (old->m_watcher)
if (old->m_watcher && !d_ptr->m_watcher) {
watchForChanges();
if (!d_ptr->m_watcher)
emit watchedChanged();
} else if (!old->m_watcher && d_ptr->m_watcher) {
emit watchedChanged();
}

// If alone value was known, ensure that new d_ptr also knows it
if (old->m_alone != UserInfoPrivate::Unknown && old->alone() != d_ptr->alone())
Expand Down Expand Up @@ -465,13 +503,14 @@ void UserInfo::connectSignals()
connect(d_ptr.data(), &UserInfoPrivate::nameChanged, this, &UserInfo::nameChanged);
connect(d_ptr.data(), &UserInfoPrivate::uidChanged, this, &UserInfo::uidChanged);
connect(d_ptr.data(), &UserInfoPrivate::currentChanged, this, &UserInfo::currentChanged);
connect(d_ptr.data(), &UserInfoPrivate::watchedChanged, this, &UserInfo::watchedChanged);
connect(d_ptr.data(), &UserInfoPrivate::aloneChanged, this, &UserInfo::aloneChanged);
}

void UserInfo::watchForChanges()
{
Q_D(UserInfo);
d->m_watcher = new QFileSystemWatcher(this);
d->m_watcher = new QFileSystemWatcher(d);
QStringList missing = d->m_watcher->addPaths(QStringList() << UserDatabaseFile << GroupDatabaseFile);
if (missing.count() == 2) {
qCWarning(lcUsersLog) << "Could not watch for changes in user or group database";
Expand All @@ -480,27 +519,29 @@ void UserInfo::watchForChanges()
} else if (missing.count() > 0) {
qCWarning(lcUsersLog) << "Could not watch for changes in" << missing;
} else {
connect(d->m_watcher, &QFileSystemWatcher::fileChanged, this, [this] (const QString &path) {
Q_D(UserInfo);
if (QFile::exists(path)) {
if (path == UserDatabaseFile) {
// User database updated, reset model
qCDebug(lcUsersLog) << UserDatabaseFile << "changed, reseting model";
reset();
} else if (d->m_alone != UserInfoPrivate::Unknown) { // && path == GroupDatabaseFile
// Group database updated, update alone status
qCDebug(lcUsersLog) << GroupDatabaseFile << "changed, checking alone status again";
d->updateAlone();
}
}
if (!d->m_watcher->files().contains(path)) {
if (QFile::exists(path) && d->m_watcher->addPath(path)) {
qCDebug(lcUsersLog) << "Re-watching" << path << "for changes";
} else {
qCWarning(lcUsersLog) << "Stopped watching" << path << "for changes";
}
}
});
connect(d->m_watcher, &QFileSystemWatcher::fileChanged, d, &UserInfoPrivate::databaseChanged);
}
}

void UserInfoPrivate::databaseChanged(const QString &path)
{
if (QFile::exists(path)) {
if (path == UserDatabaseFile) {
// User database updated, reset model
qCDebug(lcUsersLog) << "User database changed, updating data";
set(getpwuid(m_uid));
} else if (m_alone != Unknown) { // && path == GroupDatabaseFile
// Group database updated, update alone status
qCDebug(lcUsersLog) << "Group database changed, checking alone status again";
updateAlone();
}
}
if (!m_watcher->files().contains(path)) {
if (QFile::exists(path) && m_watcher->addPath(path)) {
qCDebug(lcUsersLog) << "Re-watching" << path << "for changes";
} else {
qCWarning(lcUsersLog) << "Stopped watching" << path << "for changes";
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/userinfo.h
Expand Up @@ -53,6 +53,7 @@ class SYSTEMSETTINGS_EXPORT UserInfo: public QObject
Q_PROPERTY(int uid READ uid WRITE setUid NOTIFY uidChanged)
Q_PROPERTY(bool current READ current NOTIFY currentChanged)
Q_PROPERTY(bool alone READ alone NOTIFY aloneChanged)
Q_PROPERTY(bool watched READ watched WRITE setWatched NOTIFY watchedChanged)

friend class UserModel;

Expand All @@ -79,6 +80,8 @@ class SYSTEMSETTINGS_EXPORT UserInfo: public QObject
void setUid(int uid);
bool current() const;
bool alone();
bool watched();
void setWatched(bool watch);

Q_INVOKABLE void reset();

Expand All @@ -93,6 +96,7 @@ class SYSTEMSETTINGS_EXPORT UserInfo: public QObject
void uidChanged();
void currentChanged();
void aloneChanged();
void watchedChanged();

private:
explicit UserInfo(int uid);
Expand Down
4 changes: 4 additions & 0 deletions src/userinfo_p.h
Expand Up @@ -67,12 +67,16 @@ class UserInfoPrivate : public QObject
bool alone();
void updateAlone(bool force = false);

public slots:
void databaseChanged(const QString &path);

signals:
void displayNameChanged();
void usernameChanged();
void nameChanged();
void uidChanged();
void currentChanged();
void watchedChanged();
void aloneChanged();
};

Expand Down

0 comments on commit 5638f15

Please sign in to comment.