Skip to content

Commit

Permalink
Merge branch 'jb45380_textswitch' into 'master'
Browse files Browse the repository at this point in the history
Support VPN ordering by connected status

See merge request mer-core/nemo-qml-plugin-systemsettings!106
  • Loading branch information
llewelld committed Jun 4, 2019
2 parents 72f3ec0 + aff8fe1 commit 5ea9986
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 16 deletions.
76 changes: 60 additions & 16 deletions src/vpnmodel.cpp
Expand Up @@ -320,6 +320,7 @@ VpnModel::VpnModel(QObject *parent)
, provisioningOutputPath_(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/system/privileged/vpn-provisioning"))
, bestState_(VpnModel::Idle)
, autoConnect_(false)
, orderByConnected_(false)
{
qDBusRegisterMetaType<PathProperties>();
qDBusRegisterMetaType<PathPropertiesArray>();
Expand Down Expand Up @@ -400,6 +401,30 @@ bool VpnModel::autoConnect() const
return autoConnect_;
}

bool VpnModel::orderByConnected() const
{
return orderByConnected_;
}

void VpnModel::setOrderByConnected(bool orderByConnected)
{
if (orderByConnected != orderByConnected_) {
orderByConnected_ = orderByConnected;

// Update the ordering; only the connected connections need to move
// In practice only one VPN can be connected, so full sort is overkill
const int itemCount(count());
for (int index = 0; index < itemCount; ++index) {
VpnConnection *conn = get<VpnConnection>(index);
if (conn->connected()) {
reorderConnection(conn);
}
}

emit orderByConnectedChanged();
}
}

void VpnModel::createConnection(const QVariantMap &createProperties)
{
const QString path(createProperties.value(QString("path")).toString());
Expand Down Expand Up @@ -851,6 +876,7 @@ void VpnModel::updateConnection(VpnConnection *conn, const QVariantMap &updatePr
}

int oldState(conn->state());
bool connectionChanged = false;

if (updateItem(conn, properties)) {
itemChanged(conn);
Expand All @@ -859,6 +885,10 @@ void VpnModel::updateConnection(VpnConnection *conn, const QVariantMap &updatePr

if (conn->state() != oldState) {
emit connectionStateChanged(conn->path(), static_cast<int>(conn->state()));
if ((conn->state() == VpnModel::Ready) != (oldState == VpnModel::Ready)) {
emit conn->connectedChanged();
connectionChanged = true;
}

// Check to see if the best state has changed
ConnectionState maxState = Idle;
Expand All @@ -874,23 +904,14 @@ void VpnModel::updateConnection(VpnConnection *conn, const QVariantMap &updatePr
}
}


// Keep the items sorted by name. So sort only when updateProperties map contains
// a name e.i. not when "autoConnect" changes. In practice this means that sorting
// is only allowed when a VPN is created. When modifying name of a VPN, the VPN
// Keep the items sorted by name and possibly connected status. So sort
// only when the connection status has changed, or the updateProperties
// map contains a name i.e. not when "autoConnect" changes. In practice
// this means that if orderByConnected_ is false then sorting is only
// allowed when a VPN is created. When modifying name of a VPN, the VPN
// will be first removed and then recreated.
if (itemCount > 1 && updateProperties.contains(QStringLiteral("name"))) {
int index = 0;
for ( ; index < itemCount; ++index) {
const VpnConnection *existing = get<VpnConnection>(index);
if (existing->name() > conn->name()) {
break;
}
}
const int currentIndex = indexOf(conn);
if (index != currentIndex && (index - 1) != currentIndex) {
moveItem(currentIndex, (currentIndex < index ? (index - 1) : index));
}
if (updateProperties.contains(QStringLiteral("name")) || (orderByConnected_ && connectionChanged)) {
reorderConnection(conn);
}
}

Expand All @@ -905,6 +926,29 @@ void VpnModel::updateConnection(VpnConnection *conn, const QVariantMap &updatePr
}
}

void VpnModel::reorderConnection(VpnConnection * conn)
{
const int itemCount(count());

if (itemCount > 1) {
int index = 0;
for ( ; index < itemCount; ++index) {
const VpnConnection *existing = get<VpnConnection>(index);
// Scenario 1 orderByConnected == true: order first by connected, second by name
// Scenario 2 orderByConnected == false: order only by name
if ((orderByConnected_ && (existing->connected() < conn->connected()))
|| ((!orderByConnected_ || (existing->connected() == conn->connected()))
&& (existing->name() > conn->name()))) {
break;
}
}
const int currentIndex = indexOf(conn);
if (index != currentIndex && (index - 1) != currentIndex) {
moveItem(currentIndex, (currentIndex < index ? (index - 1) : index));
}
}
}

QVariantMap VpnModel::processOpenVpnProvisioningFile(QFile &provisioningFile)
{
QVariantMap rv;
Expand Down
11 changes: 11 additions & 0 deletions src/vpnmodel.h
Expand Up @@ -52,6 +52,7 @@ class SYSTEMSETTINGS_EXPORT VpnModel : public ObjectListModel

Q_PROPERTY(int bestState READ bestState NOTIFY bestStateChanged)
Q_PROPERTY(bool autoConnect READ autoConnect NOTIFY autoConnectChanged)
Q_PROPERTY(bool orderByConnected READ orderByConnected WRITE setOrderByConnected NOTIFY orderByConnectedChanged)

public:
enum ConnectionState {
Expand All @@ -69,6 +70,9 @@ class SYSTEMSETTINGS_EXPORT VpnModel : public ObjectListModel
int bestState() const;
bool autoConnect() const;

bool orderByConnected() const;
void setOrderByConnected(bool orderByConnected);

Q_INVOKABLE void createConnection(const QVariantMap &properties);
Q_INVOKABLE void modifyConnection(const QString &path, const QVariantMap &properties);
Q_INVOKABLE void deleteConnection(const QString &path);
Expand All @@ -92,6 +96,7 @@ class SYSTEMSETTINGS_EXPORT VpnModel : public ObjectListModel
void bestStateChanged();
void autoConnectChanged();
void connectionStateChanged(const QString &path, int state);
void orderByConnectedChanged();

private:
void fetchVpnList();
Expand All @@ -104,6 +109,7 @@ class SYSTEMSETTINGS_EXPORT VpnModel : public ObjectListModel
bool domainInUse(const QString &domain) const;
QString createDefaultDomain() const;
bool isDefaultDomain(const QString &domain) const;
void reorderConnection(VpnConnection * conn);

class CredentialsRepository
{
Expand Down Expand Up @@ -135,6 +141,7 @@ class SYSTEMSETTINGS_EXPORT VpnModel : public ObjectListModel
ConnectionState bestState_;
// True if there's one VPN that has autoConnect true
bool autoConnect_;
bool orderByConnected_;
};

class SYSTEMSETTINGS_EXPORT VpnConnection : public QObject
Expand All @@ -157,6 +164,7 @@ class SYSTEMSETTINGS_EXPORT VpnConnection : public QObject
Q_PROPERTY(QVariantList userRoutes READ userRoutes WRITE setUserRoutes NOTIFY userRoutesChanged)
Q_PROPERTY(QVariantList serverRoutes READ serverRoutes WRITE setServerRoutes NOTIFY serverRoutesChanged)
Q_PROPERTY(QVariantMap providerProperties READ providerProperties WRITE setProviderProperties NOTIFY providerPropertiesChanged)
Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)

public:
VpnConnection(const QString &path);
Expand Down Expand Up @@ -211,6 +219,8 @@ class SYSTEMSETTINGS_EXPORT VpnConnection : public QObject
QVariantMap providerProperties() const { return providerProperties_; }
void setProviderProperties(const QVariantMap providerProperties) { updateMember(&VpnConnection::providerProperties_, providerProperties, &VpnConnection::providerPropertiesChanged); }

int connected() const { return state_ == VpnModel::Ready; }

signals:
void nameChanged();
void stateChanged();
Expand All @@ -228,6 +238,7 @@ class SYSTEMSETTINGS_EXPORT VpnConnection : public QObject
void userRoutesChanged();
void serverRoutesChanged();
void providerPropertiesChanged();
void connectedChanged();

private:
template<typename T, typename V>
Expand Down

0 comments on commit 5ea9986

Please sign in to comment.