on xenial help sign in
Re-add original LightDM
commit83de736aa74f202698cfc5a1c1c4cc00b3f8fe22 authorJosh Arenson <joshua.arenson@canonical.com> dateThu 10 Sep 2015, 21:06 (11 years ago) parent3616f22
23 files changed+1952
plugins/IntegratedLightDM/CMakeLists.txt+40 plugins/IntegratedLightDM/DBusGreeter.cpp+49 plugins/IntegratedLightDM/DBusGreeter.h+52 plugins/IntegratedLightDM/DBusGreeterList.cpp+56 plugins/IntegratedLightDM/DBusGreeterList.h+57 plugins/IntegratedLightDM/Greeter.cpp+138 plugins/IntegratedLightDM/Greeter.h+82 plugins/IntegratedLightDM/GreeterPrivate.h+39 plugins/IntegratedLightDM/IntegratedLightDM.qmltypes+251 plugins/IntegratedLightDM/UsersModel.cpp+70 plugins/IntegratedLightDM/UsersModel.h+37 plugins/IntegratedLightDM/liblightdm/CMakeLists.txt+37 plugins/IntegratedLightDM/liblightdm/Greeter.cpp+184 plugins/IntegratedLightDM/liblightdm/Greeter.h+110 plugins/IntegratedLightDM/liblightdm/GreeterPrivate.cpp+305 plugins/IntegratedLightDM/liblightdm/GreeterPrivate.h+51 plugins/IntegratedLightDM/liblightdm/UsersModel.cpp+123 plugins/IntegratedLightDM/liblightdm/UsersModel.h+66 plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cpp+41 plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.h+59 plugins/IntegratedLightDM/plugin.cpp+69 plugins/IntegratedLightDM/plugin.h+33 plugins/IntegratedLightDM/qmldir+3
plugins/IntegratedLightDM/CMakeLists.txtnew file+40
@@ -0,0 +1,40 @@
1+pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
2+# TODO: Once we split out a separate greeter process, uncomment these lines
3+#pkg_check_modules(LIBLIGHTDM REQUIRED liblightdm-qt5-2)
4+
5+add_subdirectory(liblightdm)
6+
7+include_directories(
8+ ${CMAKE_CURRENT_SOURCE_DIR}
9+ ${CMAKE_CURRENT_BINARY_DIR}
10+ ${CMAKE_SOURCE_DIR}/plugins/Utils
11+ ${CMAKE_SOURCE_DIR}/tests/mocks/IntegratedLightDM
12+ #${LIBLIGHTDM_INCLUDE_DIRS}
13+ ${libunity8-private_SOURCE_DIR}
14+ ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
15+)
16+
17+set(QMLPLUGIN_SRC
18+ ../Utils/unitysortfilterproxymodelqml.cpp # FIXME evaluate a more generic approach for using other plugins
19+ DBusGreeter.cpp
20+ DBusGreeterList.cpp
21+ Greeter.cpp
22+ plugin.cpp
23+ UsersModel.cpp
24+ )
25+
26+add_library(IntegratedLightDM-qml MODULE
27+ ${QMLPLUGIN_SRC}
28+ )
29+
30+target_link_libraries(IntegratedLightDM-qml
31+ integratedLightDM
32+ unity8-private
33+# TODO: Once we split out a separate greeter process, uncomment these lines
34+# ${LIBLIGHTDM_LDFLAGS}
35+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
36+ )
37+
38+qt5_use_modules(IntegratedLightDM-qml DBus Gui Qml)
39+
40+add_unity8_plugin(IntegratedLightDM 0.1 IntegratedLightDM TARGETS IntegratedLightDM-qml)
plugins/IntegratedLightDM/DBusGreeter.cppnew file+49
@@ -0,0 +1,49 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "DBusGreeter.h"
18+#include "Greeter.h"
19+
20+#include <QDBusMessage>
21+#include <QStringList>
22+
23+DBusGreeter::DBusGreeter(Greeter *greeter, const QString &path)
24+ : UnityDBusObject(path, "com.canonical.UnityGreeter", true, greeter),
25+ m_greeter(greeter)
26+{
27+ connect(m_greeter, &Greeter::isActiveChanged, this, &DBusGreeter::isActiveChangedHandler);
28+}
29+
30+bool DBusGreeter::isActive() const
31+{
32+ return m_greeter->isActive();
33+}
34+
35+void DBusGreeter::ShowGreeter()
36+{
37+ return Q_EMIT m_greeter->showGreeter();
38+}
39+
40+void DBusGreeter::HideGreeter()
41+{
42+ return Q_EMIT m_greeter->hideGreeter();
43+}
44+
45+void DBusGreeter::isActiveChangedHandler()
46+{
47+ notifyPropertyChanged("IsActive", isActive());
48+ Q_EMIT isActiveChanged();
49+}
plugins/IntegratedLightDM/DBusGreeter.hnew file+52
@@ -0,0 +1,52 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef UNITY_DBUSGREETER_H
18+#define UNITY_DBUSGREETER_H
19+
20+#include "unitydbusobject.h"
21+#include <QDBusConnection>
22+
23+class Greeter;
24+
25+/** This is an internal class used to talk with the indicators.
26+ */
27+
28+class DBusGreeter : public UnityDBusObject
29+{
30+ Q_OBJECT
31+ Q_CLASSINFO("D-Bus Interface", "com.canonical.UnityGreeter")
32+
33+ Q_PROPERTY(bool IsActive READ isActive NOTIFY isActiveChanged) // since 14.10
34+
35+public:
36+ explicit DBusGreeter(Greeter *greeter, const QString &path);
37+
38+ bool isActive() const;
39+ Q_SCRIPTABLE void ShowGreeter(); // temporary, until we split the greeter again
40+ Q_SCRIPTABLE void HideGreeter(); // temporary, until we split the greeter again
41+
42+Q_SIGNALS:
43+ void isActiveChanged();
44+
45+private Q_SLOTS:
46+ void isActiveChangedHandler();
47+
48+private:
49+ Greeter *m_greeter;
50+};
51+
52+#endif
plugins/IntegratedLightDM/DBusGreeterList.cppnew file+56
@@ -0,0 +1,56 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#include "DBusGreeterList.h"
18+#include "Greeter.h"
19+
20+#include <QDBusMessage>
21+#include <QStringList>
22+
23+DBusGreeterList::DBusGreeterList(Greeter *greeter, const QString &path)
24+ : UnityDBusObject(path, "com.canonical.UnityGreeter", true, greeter),
25+ m_greeter(greeter)
26+{
27+ connect(m_greeter, &Greeter::authenticationUserChanged, this, &DBusGreeterList::authenticationUserChangedHandler);
28+ connect(m_greeter, &Greeter::promptlessChanged, this, &DBusGreeterList::promptlessChangedHandler);
29+}
30+
31+QString DBusGreeterList::GetActiveEntry() const
32+{
33+ return m_greeter->authenticationUser();
34+}
35+
36+void DBusGreeterList::SetActiveEntry(const QString &entry)
37+{
38+ Q_EMIT m_greeter->requestAuthenticationUser(entry);
39+}
40+
41+bool DBusGreeterList::entryIsLocked() const
42+{
43+ return !m_greeter->promptless();
44+}
45+
46+void DBusGreeterList::authenticationUserChangedHandler(const QString &user)
47+{
48+ notifyPropertyChanged("ActiveEntry", user);
49+ Q_EMIT EntrySelected(user);
50+}
51+
52+void DBusGreeterList::promptlessChangedHandler()
53+{
54+ notifyPropertyChanged("EntryIsLocked", entryIsLocked());
55+ Q_EMIT entryIsLockedChanged();
56+}
plugins/IntegratedLightDM/DBusGreeterList.hnew file+57
@@ -0,0 +1,57 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef UNITY_DBUSGREETERLIST_H
18+#define UNITY_DBUSGREETERLIST_H
19+
20+#include "unitydbusobject.h"
21+#include <QDBusConnection>
22+
23+class Greeter;
24+
25+/** This is an internal class used to talk with the indicators.
26+ */
27+
28+class DBusGreeterList : public UnityDBusObject
29+{
30+ Q_OBJECT
31+ Q_CLASSINFO("D-Bus Interface", "com.canonical.UnityGreeter.List")
32+
33+ Q_PROPERTY(QString ActiveEntry READ GetActiveEntry WRITE SetActiveEntry NOTIFY EntrySelected) // since 14.04
34+ Q_PROPERTY(bool EntryIsLocked READ entryIsLocked NOTIFY entryIsLockedChanged) // since 14.04
35+
36+public:
37+ explicit DBusGreeterList(Greeter *greeter, const QString &path);
38+
39+ Q_SCRIPTABLE void SetActiveEntry(const QString &entry); // since 13.04
40+ Q_SCRIPTABLE QString GetActiveEntry() const; // since 13.10
41+
42+ bool entryIsLocked() const;
43+
44+Q_SIGNALS:
45+ Q_SCRIPTABLE void EntrySelected(const QString &entry); // since 13.10
46+
47+ void entryIsLockedChanged();
48+
49+private Q_SLOTS:
50+ void authenticationUserChangedHandler(const QString &user);
51+ void promptlessChangedHandler();
52+
53+private:
54+ Greeter *m_greeter;
55+};
56+
57+#endif
plugins/IntegratedLightDM/Greeter.cppnew file+138
@@ -0,0 +1,138 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "Greeter.h"
20+#include "GreeterPrivate.h"
21+#include <libintl.h>
22+
23+GreeterPrivate::GreeterPrivate(Greeter* parent)
24+ : m_greeter(new QLightDM::Greeter(parent)),
25+ m_active(false),
26+ wasPrompted(false),
27+ promptless(false),
28+ q_ptr(parent)
29+{
30+}
31+
32+Greeter::Greeter(QObject* parent)
33+ : QObject(parent),
34+ d_ptr(new GreeterPrivate(this))
35+{
36+ Q_D(Greeter);
37+
38+ connect(d->m_greeter, &QLightDM::Greeter::showMessage,
39+ this, &Greeter::showMessageFilter);
40+ connect(d->m_greeter, &QLightDM::Greeter::showPrompt,
41+ this, &Greeter::showPromptFilter);
42+ connect(d->m_greeter, &QLightDM::Greeter::authenticationComplete,
43+ this, &Greeter::authenticationCompleteFilter);
44+
45+ d->m_greeter->connectSync();
46+}
47+
48+bool Greeter::isActive() const
49+{
50+ Q_D(const Greeter);
51+ return d->m_active;
52+}
53+
54+void Greeter::setIsActive(bool active)
55+{
56+ Q_D(Greeter);
57+ if (d->m_active != active) {
58+ d->m_active = active;
59+ Q_EMIT isActiveChanged();
60+ }
61+}
62+
63+bool Greeter::isAuthenticated() const
64+{
65+ Q_D(const Greeter);
66+ return d->m_greeter->isAuthenticated();
67+}
68+
69+QString Greeter::authenticationUser() const
70+{
71+ Q_D(const Greeter);
72+ return d->m_greeter->authenticationUser();
73+}
74+
75+bool Greeter::promptless() const
76+{
77+ Q_D(const Greeter);
78+ return d->promptless;
79+}
80+
81+void Greeter::authenticate(const QString &username)
82+{
83+ Q_D(Greeter);
84+ d->wasPrompted = false;
85+ if (d->promptless) {
86+ d->promptless = false;
87+ Q_EMIT promptlessChanged();
88+ }
89+
90+ d->m_greeter->authenticate(username);
91+ Q_EMIT isAuthenticatedChanged();
92+ Q_EMIT authenticationUserChanged(username);
93+}
94+
95+void Greeter::respond(const QString &response)
96+{
97+ Q_D(Greeter);
98+ d->m_greeter->respond(response);
99+}
100+
101+bool Greeter::startSessionSync(const QString &session)
102+{
103+ Q_D(Greeter);
104+ return d->m_greeter->startSessionSync(session);
105+}
106+
107+void Greeter::showPromptFilter(const QString &text, QLightDM::Greeter::PromptType type)
108+{
109+ Q_D(Greeter);
110+ d->wasPrompted = true;
111+
112+ bool isDefaultPrompt = (text == dgettext("Linux-PAM", "Password: "));
113+
114+ // Strip prompt of any colons at the end
115+ QString trimmedText = text.trimmed();
116+ if (trimmedText.endsWith(":") || trimmedText.endsWith(":")) {
117+ trimmedText.chop(1);
118+ }
119+
120+ Q_EMIT showPrompt(trimmedText, type == QLightDM::Greeter::PromptTypeSecret, isDefaultPrompt);
121+}
122+
123+void Greeter::showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type)
124+{
125+ Q_EMIT showMessage(text, type == QLightDM::Greeter::MessageTypeError);
126+}
127+
128+void Greeter::authenticationCompleteFilter()
129+{
130+ Q_D(Greeter);
131+ if (!d->wasPrompted) {
132+ d->promptless = true;
133+ Q_EMIT promptlessChanged();
134+ }
135+
136+ Q_EMIT isAuthenticatedChanged();
137+ Q_EMIT authenticationComplete();
138+}
plugins/IntegratedLightDM/Greeter.hnew file+82
@@ -0,0 +1,82 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+/* This class is a really tiny filter around QLightDM::Greeter. There are some
20+ operations that we want to edit a bit for the benefit of Qml. Specifically,
21+ we want to chop colons off of any password prompts. But there may be more
22+ such edits in the future, and by inserting ourselves here, we have more
23+ control. */
24+
25+#ifndef UNITY_GREETER_H
26+#define UNITY_GREETER_H
27+
28+#include <QLightDM/Greeter>
29+#include <QtCore/QObject>
30+
31+class GreeterPrivate;
32+
33+class Greeter : public QObject
34+{
35+ Q_OBJECT
36+
37+ Q_PROPERTY(bool active READ isActive WRITE setIsActive NOTIFY isActiveChanged)
38+ Q_PROPERTY(bool authenticated READ isAuthenticated NOTIFY isAuthenticatedChanged)
39+ Q_PROPERTY(QString authenticationUser READ authenticationUser NOTIFY authenticationUserChanged)
40+ Q_PROPERTY(bool promptless READ promptless NOTIFY promptlessChanged)
41+
42+public:
43+ explicit Greeter(QObject* parent=0);
44+
45+ bool isActive() const;
46+ bool isAuthenticated() const;
47+ QString authenticationUser() const;
48+ bool promptless() const;
49+
50+public Q_SLOTS:
51+ void authenticate(const QString &username=QString());
52+ void respond(const QString &response);
53+ bool startSessionSync(const QString &session=QString());
54+ void setIsActive(bool isActive);
55+
56+Q_SIGNALS:
57+ void showMessage(const QString &text, bool isError);
58+ void showPrompt(const QString &text, bool isSecret, bool isDefaultPrompt);
59+ void authenticationComplete();
60+ void authenticationUserChanged(const QString &user);
61+ void isActiveChanged();
62+ void isAuthenticatedChanged();
63+ void promptlessChanged();
64+ void showGreeter();
65+ void hideGreeter();
66+
67+ // This signal is emitted by external agents like indicators, and the UI
68+ // should switch to this user if possible.
69+ void requestAuthenticationUser(const QString &user);
70+
71+protected:
72+ GreeterPrivate * const d_ptr;
73+
74+ Q_DECLARE_PRIVATE(Greeter)
75+
76+private Q_SLOTS:
77+ void showMessageFilter(const QString &text, QLightDM::Greeter::MessageType type);
78+ void showPromptFilter(const QString &text, QLightDM::Greeter::PromptType type);
79+ void authenticationCompleteFilter();
80+};
81+
82+#endif
plugins/IntegratedLightDM/GreeterPrivate.hnew file+39
@@ -0,0 +1,39 @@
1+/*
2+ * Copyright (C) 2014 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+#ifndef UNITY_GREETER_PRIVATE_H
18+#define UNITY_GREETER_PRIVATE_H
19+
20+#include <QLightDM/Greeter>
21+
22+class GreeterPrivate
23+{
24+public:
25+ explicit GreeterPrivate(Greeter *parent);
26+
27+ QLightDM::Greeter *m_greeter;
28+ bool m_active;
29+ bool wasPrompted;
30+ bool promptless;
31+
32+protected:
33+ Greeter * const q_ptr;
34+
35+private:
36+ Q_DECLARE_PUBLIC(Greeter)
37+};
38+
39+#endif // UNITY_GREETER_PRIVATE_H
plugins/IntegratedLightDM/IntegratedLightDM.qmltypesnew file+251
@@ -0,0 +1,251 @@
1+import QtQuick.tooling 1.1
2+
3+// This file describes the plugin-supplied types contained in the library.
4+// It is used for QML tooling purposes only.
5+//
6+// This file was auto-generated by:
7+// 'qmlplugindump -notrelocatable LightDM 0.1 plugins'
8+
9+Module {
10+ Component {
11+ name: "Greeter"
12+ prototype: "QObject"
13+ exports: ["LightDM/Greeter 0.1"]
14+ isCreatable: false
15+ isSingleton: true
16+ exportMetaObjectRevisions: [0]
17+ Property { name: "active"; type: "bool" }
18+ Property { name: "authenticated"; type: "bool"; isReadonly: true }
19+ Property { name: "authenticationUser"; type: "string"; isReadonly: true }
20+ Property { name: "promptless"; type: "bool"; isReadonly: true }
21+ Signal {
22+ name: "showMessage"
23+ Parameter { name: "text"; type: "string" }
24+ Parameter { name: "isError"; type: "bool" }
25+ }
26+ Signal {
27+ name: "showPrompt"
28+ Parameter { name: "text"; type: "string" }
29+ Parameter { name: "isSecret"; type: "bool" }
30+ Parameter { name: "isDefaultPrompt"; type: "bool" }
31+ }
32+ Signal { name: "authenticationComplete" }
33+ Signal {
34+ name: "authenticationUserChanged"
35+ Parameter { name: "user"; type: "string" }
36+ }
37+ Signal { name: "isActiveChanged" }
38+ Signal { name: "isAuthenticatedChanged" }
39+ Signal { name: "showGreeter" }
40+ Signal { name: "hideGreeter" }
41+ Signal {
42+ name: "requestAuthenticationUser"
43+ Parameter { name: "user"; type: "string" }
44+ }
45+ Method {
46+ name: "authenticate"
47+ Parameter { name: "username"; type: "string" }
48+ }
49+ Method { name: "authenticate" }
50+ Method {
51+ name: "respond"
52+ Parameter { name: "response"; type: "string" }
53+ }
54+ Method {
55+ name: "startSessionSync"
56+ type: "bool"
57+ Parameter { name: "session"; type: "string" }
58+ }
59+ Method { name: "startSessionSync"; type: "bool" }
60+ Method {
61+ name: "setIsActive"
62+ Parameter { name: "isActive"; type: "bool" }
63+ }
64+ }
65+ Component {
66+ name: "QAbstractProxyModel"
67+ prototype: "QAbstractItemModel"
68+ Property { name: "sourceModel"; type: "QAbstractItemModel"; isPointer: true }
69+ }
70+ Component {
71+ name: "QLightDM::UsersModel"
72+ prototype: "QAbstractListModel"
73+ exports: ["LightDM/UserRoles 0.1"]
74+ isCreatable: false
75+ exportMetaObjectRevisions: [0]
76+ Enum {
77+ name: "UserModelRoles"
78+ values: {
79+ "NameRole": 256,
80+ "RealNameRole": 257,
81+ "LoggedInRole": 258,
82+ "BackgroundRole": 259,
83+ "SessionRole": 260,
84+ "HasMessagesRole": 261,
85+ "ImagePathRole": 262,
86+ "BackgroundPathRole": 263
87+ }
88+ }
89+ }
90+ Component {
91+ name: "QSortFilterProxyModel"
92+ prototype: "QAbstractProxyModel"
93+ Property { name: "filterRegExp"; type: "QRegExp" }
94+ Property { name: "filterKeyColumn"; type: "int" }
95+ Property { name: "dynamicSortFilter"; type: "bool" }
96+ Property { name: "filterCaseSensitivity"; type: "Qt::CaseSensitivity" }
97+ Property { name: "sortCaseSensitivity"; type: "Qt::CaseSensitivity" }
98+ Property { name: "isSortLocaleAware"; type: "bool" }
99+ Property { name: "sortRole"; type: "int" }
100+ Property { name: "filterRole"; type: "int" }
101+ Method {
102+ name: "setFilterRegExp"
103+ Parameter { name: "pattern"; type: "string" }
104+ }
105+ Method {
106+ name: "setFilterWildcard"
107+ Parameter { name: "pattern"; type: "string" }
108+ }
109+ Method {
110+ name: "setFilterFixedString"
111+ Parameter { name: "pattern"; type: "string" }
112+ }
113+ Method { name: "clear" }
114+ Method { name: "invalidate" }
115+ }
116+ Component {
117+ name: "UnitySortFilterProxyModelQML"
118+ prototype: "QSortFilterProxyModel"
119+ Property { name: "model"; type: "QAbstractItemModel"; isPointer: true }
120+ Property { name: "totalCount"; type: "int"; isReadonly: true }
121+ Property { name: "count"; type: "int"; isReadonly: true }
122+ Property { name: "invertMatch"; type: "bool" }
123+ Signal {
124+ name: "invertMatchChanged"
125+ Parameter { type: "bool" }
126+ }
127+ Method {
128+ name: "get"
129+ type: "QVariantMap"
130+ Parameter { name: "row"; type: "int" }
131+ }
132+ Method {
133+ name: "data"
134+ type: "QVariant"
135+ Parameter { name: "row"; type: "int" }
136+ Parameter { name: "role"; type: "int" }
137+ }
138+ Method { name: "count"; type: "int" }
139+ Method {
140+ name: "findFirst"
141+ type: "int"
142+ Parameter { name: "role"; type: "int" }
143+ Parameter { name: "value"; type: "QVariant" }
144+ }
145+ Method {
146+ name: "mapRowToSource"
147+ type: "int"
148+ Parameter { name: "row"; type: "int" }
149+ }
150+ Method {
151+ name: "mapFromSource"
152+ type: "int"
153+ Parameter { name: "row"; type: "int" }
154+ }
155+ Method {
156+ name: "mapToSource"
157+ type: "int"
158+ Parameter { name: "row"; type: "int" }
159+ }
160+ }
161+ Component {
162+ name: "UserMetricsOutput::ColorTheme"
163+ prototype: "QObject"
164+ Property { name: "start"; type: "QColor"; isReadonly: true }
165+ Property { name: "main"; type: "QColor"; isReadonly: true }
166+ Property { name: "end"; type: "QColor"; isReadonly: true }
167+ Signal {
168+ name: "startChanged"
169+ Parameter { name: "color"; type: "QColor" }
170+ }
171+ Signal {
172+ name: "mainChanged"
173+ Parameter { name: "color"; type: "QColor" }
174+ }
175+ Signal {
176+ name: "endChanged"
177+ Parameter { name: "color"; type: "QColor" }
178+ }
179+ }
180+ Component {
181+ name: "UserMetricsOutput::UserMetrics"
182+ prototype: "QObject"
183+ exports: ["LightDM/Infographic 0.1"]
184+ isCreatable: false
185+ isSingleton: true
186+ exportMetaObjectRevisions: [0]
187+ Property { name: "label"; type: "string"; isReadonly: true }
188+ Property { name: "username"; type: "string" }
189+ Property {
190+ name: "firstColor"
191+ type: "UserMetricsOutput::ColorTheme"
192+ isReadonly: true
193+ isPointer: true
194+ }
195+ Property {
196+ name: "secondColor"
197+ type: "UserMetricsOutput::ColorTheme"
198+ isReadonly: true
199+ isPointer: true
200+ }
201+ Property { name: "firstMonth"; type: "QAbstractItemModel"; isReadonly: true; isPointer: true }
202+ Property { name: "secondMonth"; type: "QAbstractItemModel"; isReadonly: true; isPointer: true }
203+ Property { name: "currentDay"; type: "int"; isReadonly: true }
204+ Signal {
205+ name: "labelChanged"
206+ Parameter { name: "label"; type: "string" }
207+ }
208+ Signal {
209+ name: "usernameChanged"
210+ Parameter { name: "username"; type: "string" }
211+ }
212+ Signal {
213+ name: "firstColorChanged"
214+ Parameter { name: "color"; type: "ColorTheme"; isPointer: true }
215+ }
216+ Signal {
217+ name: "firstMonthChanged"
218+ Parameter { name: "firstMonth"; type: "QAbstractItemModel"; isPointer: true }
219+ }
220+ Signal {
221+ name: "currentDayChanged"
222+ Parameter { name: "currentDay"; type: "int" }
223+ }
224+ Signal {
225+ name: "secondColorChanged"
226+ Parameter { name: "color"; type: "ColorTheme"; isPointer: true }
227+ }
228+ Signal {
229+ name: "secondMonthChanged"
230+ Parameter { name: "secondMonth"; type: "QAbstractItemModel"; isPointer: true }
231+ }
232+ Signal { name: "nextDataSource" }
233+ Signal { name: "readyForDataChange" }
234+ Signal { name: "dataAboutToAppear" }
235+ Signal { name: "dataAppeared" }
236+ Signal { name: "dataAboutToChange" }
237+ Signal { name: "dataChanged" }
238+ Signal { name: "dataAboutToDisappear" }
239+ Signal { name: "dataDisappeared" }
240+ Method { name: "nextDataSourceSlot" }
241+ Method { name: "readyForDataChangeSlot" }
242+ }
243+ Component {
244+ name: "UsersModel"
245+ prototype: "UnitySortFilterProxyModelQML"
246+ exports: ["LightDM/Users 0.1"]
247+ isCreatable: false
248+ isSingleton: true
249+ exportMetaObjectRevisions: [0]
250+ }
251+}
plugins/IntegratedLightDM/UsersModel.cppnew file+70
@@ -0,0 +1,70 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "UsersModel.h"
20+#include <QLightDM/UsersModel>
21+#include <QtCore/QSortFilterProxyModel>
22+
23+// First, we define an internal class that wraps LightDM's UsersModel. This
24+// class will modify some of the data coming from LightDM. For example, we
25+// modify any empty Real Names into just normal Names.
26+// (We can't modify the data directly in UsersModel below because it won't sort
27+// using the modified data.)
28+class MangleModel : public QSortFilterProxyModel
29+{
30+ Q_OBJECT
31+
32+public:
33+ explicit MangleModel(QObject* parent=0);
34+
35+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
36+};
37+
38+MangleModel::MangleModel(QObject* parent)
39+ : QSortFilterProxyModel(parent)
40+{
41+ setSourceModel(new QLightDM::UsersModel(this));
42+}
43+
44+QVariant MangleModel::data(const QModelIndex &index, int role) const
45+{
46+ QVariant data = QSortFilterProxyModel::data(index, role);
47+
48+ // If user's real name is empty, switch to unix name
49+ if (role == QLightDM::UsersModel::RealNameRole && data.toString().isEmpty()) {
50+ data = QSortFilterProxyModel::data(index, QLightDM::UsersModel::NameRole);
51+ } else if (role == QLightDM::UsersModel::BackgroundPathRole && data.toString().startsWith('#')) {
52+ data = "data:image/svg+xml,<svg><rect width='100%' height='100%' fill='" + data.toString() + "'/></svg>";
53+ }
54+
55+ return data;
56+}
57+
58+// **** Now we continue with actual UsersModel class ****
59+
60+UsersModel::UsersModel(QObject* parent)
61+ : UnitySortFilterProxyModelQML(parent)
62+{
63+ setModel(new MangleModel(this));
64+ setSortCaseSensitivity(Qt::CaseInsensitive);
65+ setSortLocaleAware(true);
66+ setSortRole(QLightDM::UsersModel::RealNameRole);
67+ sort(0);
68+}
69+
70+#include "UsersModel.moc"
plugins/IntegratedLightDM/UsersModel.hnew file+37
@@ -0,0 +1,37 @@
1+/*
2+ * Copyright (C) 2012,2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Authors: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+/* This class is a really tiny filter around QLightDM::UsersModel. There are
20+ some operations that we want to edit a bit for the benefit of Qml.
21+ Specifically, we want to sort users according to realName. */
22+
23+#ifndef UNITY_USERSMODEL_H
24+#define UNITY_USERSMODEL_H
25+
26+#include <unitysortfilterproxymodelqml.h>
27+#include <QtCore/QObject>
28+
29+class UsersModel : public UnitySortFilterProxyModelQML
30+{
31+ Q_OBJECT
32+
33+public:
34+ explicit UsersModel(QObject* parent=0);
35+};
36+
37+#endif
plugins/IntegratedLightDM/liblightdm/CMakeLists.txtnew file+37
@@ -0,0 +1,37 @@
1+pkg_check_modules(LIBUSERMETRICSOUTPUT REQUIRED libusermetricsoutput-1)
2+
3+set(LibLightDM_SOURCES
4+ Greeter.cpp
5+ UsersModel.cpp
6+ GreeterPrivate.cpp
7+ UsersModelPrivate.cpp
8+ ${CMAKE_SOURCE_DIR}/plugins/Utils/qvariantlistmodel.cpp
9+ )
10+
11+add_library(integratedLightDM STATIC ${LibLightDM_SOURCES})
12+add_library(MockLightDM-demo-shared SHARED ${LibLightDM_SOURCES})
13+
14+include_directories(
15+ ${CMAKE_CURRENT_BINARY_DIR}
16+ ${LIBUSERMETRICSOUTPUT_INCLUDE_DIRS}
17+)
18+
19+target_link_libraries(integratedLightDM
20+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
21+ -lpam
22+)
23+target_link_libraries(MockLightDM-demo-shared
24+ ${LIBUSERMETRICSOUTPUT_LDFLAGS}
25+ -lpam
26+)
27+
28+qt5_use_modules(integratedLightDM Concurrent Gui)
29+qt5_use_modules(MockLightDM-demo-shared Concurrent Gui)
30+
31+set_target_properties(integratedLightDM PROPERTIES COMPILE_FLAGS -fPIC)
32+set_target_properties(MockLightDM-demo-shared PROPERTIES
33+ OUTPUT_NAME lightdm-qt5-2)
34+
35+install(TARGETS MockLightDM-demo-shared
36+ DESTINATION ${SHELL_INSTALL_QML}/mocks/LightDM/demo
37+ )
plugins/IntegratedLightDM/liblightdm/Greeter.cppnew file+184
@@ -0,0 +1,184 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+
20+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
21+ * CHANGES MADE HERE MUST BE REFLECTED ON THE MOCK LIB
22+ * COUNTERPART IN tests/mocks/Lightdm/liblightdm
23+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
24+
25+
26+#include "Greeter.h"
27+#include "GreeterPrivate.h"
28+#include <QtCore/QCoreApplication>
29+#include <QTimer>
30+
31+namespace QLightDM
32+{
33+
34+Greeter::Greeter(QObject *parent)
35+ : QObject(parent),
36+ d_ptr(new GreeterPrivate(this))
37+{
38+}
39+
40+Greeter::~Greeter()
41+{
42+}
43+
44+QString Greeter::authenticationUser() const
45+{
46+ Q_D(const Greeter);
47+ return d->authenticationUser;
48+}
49+
50+bool Greeter::hasGuestAccountHint() const
51+{
52+ return true;
53+}
54+
55+QString Greeter::getHint(const QString &name) const
56+{
57+ Q_UNUSED(name)
58+ return "";
59+}
60+
61+QString Greeter::defaultSessionHint() const
62+{
63+ return "ubuntu";
64+}
65+
66+bool Greeter::hideUsersHint() const
67+{
68+ return false;
69+}
70+
71+bool Greeter::showManualLoginHint() const
72+{
73+ return true;
74+}
75+
76+bool Greeter::showRemoteLoginHint() const
77+{
78+ return true;
79+}
80+
81+bool Greeter::lockHint () const
82+{
83+ return false;
84+}
85+
86+QString Greeter::selectUserHint() const
87+{
88+ return "";
89+}
90+
91+bool Greeter::selectGuestHint() const
92+{
93+ return false;
94+}
95+
96+QString Greeter::autologinUserHint() const
97+{
98+ return "";
99+}
100+
101+bool Greeter::autologinGuestHint() const
102+{
103+ return false;
104+}
105+
106+int Greeter::autologinTimeoutHint() const
107+{
108+ return 0;
109+}
110+
111+bool Greeter::inAuthentication() const
112+{
113+ return false;
114+}
115+
116+QString Greeter::hostname() const
117+{
118+ return "hostname1";
119+}
120+
121+bool Greeter::isAuthenticated() const
122+{
123+ Q_D(const Greeter);
124+ return d->authenticated;
125+}
126+
127+bool Greeter::connectSync()
128+{
129+ return true;
130+}
131+
132+void Greeter::authenticate(const QString &username)
133+{
134+ Q_D(Greeter);
135+
136+ d->authenticated = false;
137+ d->authenticationUser = username;
138+ d->handleAuthenticate();
139+}
140+
141+void Greeter::authenticateAsGuest()
142+{}
143+
144+void Greeter::authenticateAutologin()
145+{}
146+
147+void Greeter::authenticateRemote(const QString &session, const QString &username)
148+{
149+ Q_UNUSED(session)
150+ Q_UNUSED(username)
151+}
152+
153+void Greeter::cancelAuthentication()
154+{}
155+
156+void Greeter::setLanguage (const QString &language)
157+{
158+ Q_UNUSED(language)
159+}
160+
161+bool Greeter::startSessionSync(const QString &session)
162+{
163+ Q_UNUSED(session)
164+ return true;
165+}
166+
167+void Greeter::respond(const QString &response)
168+{
169+ Q_D(Greeter);
170+
171+ d->handleRespond(response);
172+}
173+
174+void Greeter::sendAuthenticationComplete()
175+{
176+ if (qgetenv("UNITY_TESTING").isEmpty()) {
177+ // simulate PAM's delay
178+ QTimer::singleShot(1000, this, &Greeter::authenticationComplete);
179+ } else {
180+ Q_EMIT authenticationComplete();
181+ }
182+}
183+
184+}
plugins/IntegratedLightDM/liblightdm/Greeter.hnew file+110
@@ -0,0 +1,110 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ * Copyright (C) 2010-2011 David Edmundson.
4+ * Copyright (C) 2010-2011 Robert Ancell
5+ *
6+ * This program is free software; you can redistribute it and/or modify
7+ * it under the terms of the GNU General Public License as published by
8+ * the Free Software Foundation; version 3.
9+ *
10+ * This program is distributed in the hope that it will be useful,
11+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+ * GNU General Public License for more details.
14+ *
15+ * You should have received a copy of the GNU General Public License
16+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
17+ *
18+ * Author: David Edmundson <kde@davidedmundson.co.uk>
19+ */
20+
21+#ifndef UNITY_MOCK_GREETER_H
22+#define UNITY_MOCK_GREETER_H
23+
24+#include <QtCore/QObject>
25+#include <QtCore/QVariant>
26+
27+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
28+ * CHANGES MADE HERE MUST BE REFLECTED ON THE MOCK LIB
29+ * COUNTERPART IN tests/mocks/Lightdm/liblightdm
30+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
31+
32+namespace QLightDM
33+{
34+ class GreeterPrivate;
35+
36+class Q_DECL_EXPORT Greeter : public QObject
37+{
38+ Q_OBJECT
39+
40+ Q_PROPERTY(bool authenticated READ isAuthenticated ) //NOTFIY authenticationComplete
41+ Q_PROPERTY(QString authenticationUser READ authenticationUser )
42+ Q_PROPERTY(QString defaultSession READ defaultSessionHint CONSTANT)
43+ Q_PROPERTY(QString selectUser READ selectUserHint CONSTANT)
44+ Q_PROPERTY(bool selectGuest READ selectGuestHint CONSTANT)
45+
46+ Q_PROPERTY(QString hostname READ hostname CONSTANT)
47+ Q_PROPERTY(bool hasGuestAccount READ hasGuestAccountHint CONSTANT)
48+ Q_PROPERTY(bool locked READ lockHint CONSTANT)
49+
50+ Q_ENUMS(PromptType MessageType)
51+
52+public:
53+ enum PromptType {
54+ PromptTypeQuestion,
55+ PromptTypeSecret
56+ };
57+
58+ enum MessageType {
59+ MessageTypeInfo,
60+ MessageTypeError
61+ };
62+
63+ explicit Greeter(QObject* parent=0);
64+ virtual ~Greeter();
65+
66+ QString getHint(const QString &name) const;
67+ QString defaultSessionHint() const;
68+ bool hideUsersHint() const;
69+ bool showManualLoginHint() const;
70+ bool showRemoteLoginHint() const;
71+ bool lockHint () const;
72+ bool hasGuestAccountHint() const;
73+ QString selectUserHint() const;
74+ bool selectGuestHint() const;
75+ QString autologinUserHint() const;
76+ bool autologinGuestHint() const;
77+ int autologinTimeoutHint() const;
78+
79+ bool inAuthentication() const;
80+ bool isAuthenticated() const;
81+ QString authenticationUser() const;
82+ QString hostname() const;
83+
84+public Q_SLOTS:
85+ bool connectSync();
86+ void authenticate(const QString &username=QString());
87+ void authenticateAsGuest();
88+ void authenticateAutologin();
89+ void authenticateRemote(const QString &session=QString(), const QString &username=QString());
90+ void respond(const QString &response);
91+ void cancelAuthentication();
92+ void setLanguage (const QString &language);
93+ bool startSessionSync(const QString &session=QString());
94+
95+Q_SIGNALS:
96+ void showMessage(QString text, QLightDM::Greeter::MessageType type);
97+ void showPrompt(QString text, QLightDM::Greeter::PromptType type);
98+ void authenticationComplete();
99+ void autologinTimerExpired();
100+
101+protected:
102+ void sendAuthenticationComplete();
103+
104+private:
105+ GreeterPrivate *d_ptr;
106+ Q_DECLARE_PRIVATE(Greeter)
107+};
108+}
109+
110+#endif // UNITY_MOCK_GREETER_H
plugins/IntegratedLightDM/liblightdm/GreeterPrivate.cppnew file+305
@@ -0,0 +1,305 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "Greeter.h"
20+#include "GreeterPrivate.h"
21+#include <QFuture>
22+#include <QFutureInterface>
23+#include <QFutureWatcher>
24+#include <QQueue>
25+#include <QtConcurrent>
26+#include <QVector>
27+#include <security/pam_appl.h>
28+
29+namespace QLightDM
30+{
31+
32+class GreeterImpl : public QObject
33+{
34+ Q_OBJECT
35+
36+ struct AppData
37+ {
38+ GreeterImpl *impl;
39+ pam_handle *handle;
40+ };
41+
42+ typedef QFutureInterface<QString> ResponseFuture;
43+
44+public:
45+ explicit GreeterImpl(Greeter *parent, GreeterPrivate *greeterPrivate)
46+ : QObject(parent),
47+ greeter(parent),
48+ greeterPrivate(greeterPrivate),
49+ pamHandle(nullptr)
50+ {
51+ qRegisterMetaType<QLightDM::GreeterImpl::ResponseFuture>("QLightDM::GreeterImpl::ResponseFuture");
52+
53+ connect(&futureWatcher, &QFutureWatcher<int>::finished,
54+ this, &GreeterImpl::finishPam);
55+ connect(this, SIGNAL(showMessage(pam_handle *, QString, QLightDM::Greeter::MessageType)),
56+ this, SLOT(handleMessage(pam_handle *, QString, QLightDM::Greeter::MessageType)));
57+ // This next connect is how we pass ResponseFutures between threads
58+ connect(this, SIGNAL(showPrompt(pam_handle *, QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture)),
59+ this, SLOT(handlePrompt(pam_handle *, QString, QLightDM::Greeter::PromptType, QLightDM::GreeterImpl::ResponseFuture)),
60+ Qt::BlockingQueuedConnection);
61+ }
62+
63+ ~GreeterImpl()
64+ {
65+ cancelPam();
66+ }
67+
68+ void start(QString username)
69+ {
70+ // Clear out any existing PAM interactions first
71+ cancelPam();
72+ if (pamHandle != nullptr) {
73+ // While we were cancelling pam above, we processed Qt events.
74+ // Which may have allowed someone to call start() on us again.
75+ // In which case, we'll bail on our current start() call.
76+ // This isn't racy because it's all in the same thread.
77+ return;
78+ }
79+
80+ AppData *appData = new AppData();
81+ appData->impl = this;
82+
83+ // Now actually start a new conversation with PAM
84+ pam_conv conversation;
85+ conversation.conv = converseWithPam;
86+ conversation.appdata_ptr = static_cast<void*>(appData);
87+
88+ if (pam_start("lightdm", username.toUtf8(), &conversation, &pamHandle) == PAM_SUCCESS) {
89+ appData->handle = pamHandle;
90+ futureWatcher.setFuture(QtConcurrent::mapped(QList<pam_handle*>() << pamHandle, authenticateWithPam));
91+ } else {
92+ delete appData;
93+ greeterPrivate->authenticated = false;
94+ Q_EMIT greeter->showMessage("Internal error: could not start PAM authentication", QLightDM::Greeter::MessageTypeError);
95+ Q_EMIT greeter->authenticationComplete();
96+ }
97+ }
98+
99+ static int authenticateWithPam(pam_handle* const& pamHandle)
100+ {
101+ int pamStatus = pam_authenticate(pamHandle, 0);
102+ if (pamStatus == PAM_SUCCESS) {
103+ pamStatus = pam_acct_mgmt(pamHandle, 0);
104+ }
105+ if (pamStatus == PAM_NEW_AUTHTOK_REQD) {
106+ pamStatus = pam_chauthtok(pamHandle, PAM_CHANGE_EXPIRED_AUTHTOK);
107+ }
108+ if (pamStatus == PAM_SUCCESS) {
109+ pam_setcred(pamHandle, PAM_REINITIALIZE_CRED);
110+ }
111+ return pamStatus;
112+ }
113+
114+ static int converseWithPam(int num_msg, const pam_message** msg,
115+ pam_response** resp, void* appdata_ptr)
116+ {
117+ if (num_msg <= 0)
118+ return PAM_CONV_ERR;
119+
120+ auto* tmp_response = static_cast<pam_response*>(calloc(num_msg, sizeof(pam_response)));
121+ if (!tmp_response)
122+ return PAM_CONV_ERR;
123+
124+ AppData *appData = static_cast<AppData*>(appdata_ptr);
125+ GreeterImpl *impl = appData->impl;
126+ pam_handle *handle = appData->handle;
127+
128+ int count;
129+ QVector<ResponseFuture> responses;
130+
131+ for (count = 0; count < num_msg; ++count)
132+ {
133+ switch (msg[count]->msg_style)
134+ {
135+ case PAM_PROMPT_ECHO_ON:
136+ {
137+ QString message(msg[count]->msg);
138+ responses.append(ResponseFuture());
139+ responses.last().reportStarted();
140+ Q_EMIT impl->showPrompt(handle, message, Greeter::PromptTypeQuestion, responses.last());
141+ break;
142+ }
143+ case PAM_PROMPT_ECHO_OFF:
144+ {
145+ QString message(msg[count]->msg);
146+ responses.append(ResponseFuture());
147+ responses.last().reportStarted();
148+ Q_EMIT impl->showPrompt(handle, message, Greeter::PromptTypeSecret, responses.last());
149+ break;
150+ }
151+ case PAM_TEXT_INFO:
152+ {
153+ QString message(msg[count]->msg);
154+ Q_EMIT impl->showMessage(handle, message, Greeter::MessageTypeInfo);
155+ break;
156+ }
157+ default:
158+ {
159+ QString message(msg[count]->msg);
160+ Q_EMIT impl->showMessage(handle, message, Greeter::MessageTypeError);
161+ break;
162+ }
163+ }
164+ }
165+
166+ int i = 0;
167+ bool raise_error = false;
168+
169+ for (auto &response : responses)
170+ {
171+ pam_response* resp_item = &tmp_response[i++];
172+ resp_item->resp_retcode = 0;
173+ resp_item->resp = strdup(response.future().result().toUtf8());
174+
175+ if (!resp_item->resp)
176+ {
177+ raise_error = true;
178+ break;
179+ }
180+ }
181+
182+ delete appData;
183+
184+ if (raise_error)
185+ {
186+ for (int i = 0; i < count; ++i)
187+ free(tmp_response[i].resp);
188+
189+ free(tmp_response);
190+ return PAM_CONV_ERR;
191+ }
192+ else
193+ {
194+ *resp = tmp_response;
195+ return PAM_SUCCESS;
196+ }
197+ }
198+
199+public Q_SLOTS:
200+ bool respond(QString response)
201+ {
202+ if (!futures.isEmpty()) {
203+ futures.dequeue().reportFinished(&response);
204+ return true;
205+ } else {
206+ return false;
207+ }
208+ }
209+
210+Q_SIGNALS:
211+ void showMessage(pam_handle *handle, QString text, QLightDM::Greeter::MessageType type);
212+ void showPrompt(pam_handle *handle, QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture response);
213+
214+private Q_SLOTS:
215+ void finishPam()
216+ {
217+ if (pamHandle == nullptr) {
218+ return;
219+ }
220+
221+ int pamStatus = futureWatcher.result();
222+
223+ pam_end(pamHandle, pamStatus);
224+ pamHandle = nullptr;
225+
226+ greeterPrivate->authenticated = (pamStatus == PAM_SUCCESS);
227+ Q_EMIT greeter->authenticationComplete();
228+ }
229+
230+ void handleMessage(pam_handle *handle, QString text, QLightDM::Greeter::MessageType type)
231+ {
232+ if (handle != pamHandle)
233+ return;
234+
235+ Q_EMIT greeter->showMessage(text, type);
236+ }
237+
238+ void handlePrompt(pam_handle *handle, QString text, QLightDM::Greeter::PromptType type, QLightDM::GreeterImpl::ResponseFuture future)
239+ {
240+ if (handle != pamHandle) {
241+ future.reportResult(QString());
242+ future.reportFinished();
243+ return;
244+ }
245+
246+ futures.enqueue(future);
247+ Q_EMIT greeter->showPrompt(text, type);
248+ }
249+
250+private:
251+ void cancelPam()
252+ {
253+ if (pamHandle != nullptr) {
254+ QFuture<int> pamFuture = futureWatcher.future();
255+ pam_handle *handle = pamHandle;
256+ pamHandle = nullptr; // to disable normal finishPam() handling
257+ pamFuture.cancel();
258+
259+ // Note the empty loop, we just want to clear the futures queue.
260+ // Any further prompts from the pam thread will be immediately
261+ // responded to/dismissed in handlePrompt().
262+ while (respond(QString()));
263+
264+ // Now let signal/slot handling happen so the thread can finish
265+ while (!pamFuture.isFinished()) {
266+ QCoreApplication::processEvents();
267+ }
268+
269+ pam_end(handle, PAM_CONV_ERR);
270+ }
271+ }
272+
273+ Greeter *greeter;
274+ GreeterPrivate *greeterPrivate;
275+ pam_handle* pamHandle;
276+ QFutureWatcher<int> futureWatcher;
277+ QQueue<ResponseFuture> futures;
278+};
279+
280+GreeterPrivate::GreeterPrivate(Greeter* parent)
281+ : authenticated(false),
282+ authenticationUser(),
283+ m_impl(new GreeterImpl(parent, this)),
284+ q_ptr(parent)
285+{
286+}
287+
288+GreeterPrivate::~GreeterPrivate()
289+{
290+ delete m_impl;
291+}
292+
293+void GreeterPrivate::handleAuthenticate()
294+{
295+ m_impl->start(authenticationUser);
296+}
297+
298+void GreeterPrivate::handleRespond(const QString &response)
299+{
300+ m_impl->respond(response);
301+}
302+
303+}
304+
305+#include "GreeterPrivate.moc"
plugins/IntegratedLightDM/liblightdm/GreeterPrivate.hnew file+51
@@ -0,0 +1,51 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#ifndef UNITY_MOCK_GREETER_PRIVATE_H
20+#define UNITY_MOCK_GREETER_PRIVATE_H
21+
22+#include <QtCore/QObject>
23+
24+namespace QLightDM
25+{
26+class Greeter;
27+class GreeterImpl;
28+
29+class GreeterPrivate
30+{
31+public:
32+ explicit GreeterPrivate(Greeter* parent=0);
33+ virtual ~GreeterPrivate();
34+
35+ // These variables may not be used by all subclasses, that's no problem
36+ bool authenticated;
37+ QString authenticationUser;
38+
39+ void handleAuthenticate();
40+ void handleRespond(const QString &response);
41+
42+protected:
43+ GreeterImpl *m_impl; // if the backend needs more private data
44+ Greeter * const q_ptr;
45+
46+private:
47+ Q_DECLARE_PUBLIC(Greeter)
48+};
49+}
50+
51+#endif // UNITY_MOCK_GREETER_PRIVATE_H
plugins/IntegratedLightDM/liblightdm/UsersModel.cppnew file+123
@@ -0,0 +1,123 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+
20+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
21+ * CHANGES MADE HERE MUST BE REFLECTED ON THE MOCK LIB
22+ * COUNTERPART IN tests/mocks/Lightdm/liblightdm
23+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
24+
25+// LightDM currently is Qt4 compatible, and so doesn't define setRoleNames.
26+// To use the same method of setting role name that it does, we
27+// set our compatibility to Qt4 here too.
28+#define QT_DISABLE_DEPRECATED_BEFORE QT_VERSION_CHECK(4, 0, 0)
29+
30+#include "UsersModel.h"
31+#include "UsersModelPrivate.h"
32+#include <QtCore/QDir>
33+#include <QtCore/QString>
34+#include <QtGui/QIcon>
35+
36+namespace QLightDM
37+{
38+
39+UsersModel::UsersModel(QObject *parent) :
40+ QAbstractListModel(parent),
41+ d_ptr(new UsersModelPrivate(this))
42+{
43+ Q_D(UsersModel);
44+
45+ // Extend roleNames (we want to keep the "display" role)
46+ QHash<int, QByteArray> roles = roleNames();
47+ roles[NameRole] = "name";
48+ roles[RealNameRole] = "realName";
49+ roles[LoggedInRole] = "loggedIn";
50+ roles[BackgroundRole] = "background";
51+ roles[BackgroundPathRole] = "backgroundPath";
52+ roles[SessionRole] = "session";
53+ roles[HasMessagesRole] = "hasMessages";
54+ roles[ImagePathRole] = "imagePath";
55+ setRoleNames(roles);
56+
57+ // Now modify our mock user backgrounds
58+ QDir bgdir = QDir("/usr/share/demo-assets/shell/backgrounds/");
59+ QStringList backgrounds = bgdir.entryList(QDir::Files | QDir::NoDotAndDotDot);
60+
61+ for (int i = 0, j = 0; i < d->entries.size(); i++) {
62+ Entry &entry = d->entries[i];
63+ if (entry.background.isNull() && !backgrounds.isEmpty()) {
64+ entry.background = bgdir.filePath(backgrounds[j++]);
65+ if (j >= backgrounds.length()) {
66+ j = 0;
67+ }
68+ }
69+ }
70+}
71+
72+UsersModel::~UsersModel()
73+{
74+ delete d_ptr;
75+}
76+
77+int UsersModel::rowCount(const QModelIndex &parent) const
78+{
79+ Q_D(const UsersModel);
80+
81+ if (parent.isValid()) {
82+ return 0;
83+ } else { // parent is root
84+ return d->entries.size();
85+ }
86+}
87+
88+QVariant UsersModel::data(const QModelIndex &index, int role) const
89+{
90+ Q_D(const UsersModel);
91+
92+ if (!index.isValid()) {
93+ return QVariant();
94+ }
95+
96+ int row = index.row();
97+ switch (role) {
98+ case Qt::DisplayRole:
99+ return d->entries[row].real_name;
100+ case Qt::DecorationRole:
101+ return QIcon();
102+ case UsersModel::NameRole:
103+ return d->entries[row].username;
104+ case UsersModel::RealNameRole:
105+ return d->entries[row].real_name;
106+ case UsersModel::SessionRole:
107+ return d->entries[row].session;
108+ case UsersModel::LoggedInRole:
109+ return d->entries[row].is_active;
110+ case UsersModel::BackgroundRole:
111+ return QPixmap(d->entries[row].background);
112+ case UsersModel::BackgroundPathRole:
113+ return d->entries[row].background;
114+ case UsersModel::HasMessagesRole:
115+ return d->entries[row].has_messages;
116+ case UsersModel::ImagePathRole:
117+ return "";
118+ default:
119+ return QVariant();
120+ }
121+}
122+
123+}
plugins/IntegratedLightDM/liblightdm/UsersModel.hnew file+66
@@ -0,0 +1,66 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ * Copyright (C) 2010-2011 David Edmundson.
4+ *
5+ * This program is free software; you can redistribute it and/or modify
6+ * it under the terms of the GNU General Public License as published by
7+ * the Free Software Foundation; version 3.
8+ *
9+ * This program is distributed in the hope that it will be useful,
10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+ * GNU General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU General Public License
15+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16+ *
17+ * Author: David Edmundson <kde@davidedmundson.co.uk>
18+ */
19+
20+#ifndef UNITY_MOCK_USERSMODEL_H
21+#define UNITY_MOCK_USERSMODEL_H
22+
23+#include <QtCore/QString>
24+#include <QtCore/QSharedDataPointer>
25+#include <QAbstractListModel>
26+
27+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
28+ * CHANGES MADE HERE MUST BE REFLECTED ON THE MOCK LIB
29+ * COUNTERPART IN tests/mocks/Lightdm/liblightdm
30+ * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
31+
32+namespace QLightDM
33+{
34+class UsersModelPrivate;
35+
36+class Q_DECL_EXPORT UsersModel : public QAbstractListModel
37+{
38+ Q_OBJECT
39+
40+ Q_ENUMS(UserModelRoles)
41+
42+public:
43+ explicit UsersModel(QObject *parent = 0);
44+ virtual ~UsersModel();
45+
46+ enum UserModelRoles {NameRole = Qt::UserRole,
47+ RealNameRole,
48+ LoggedInRole,
49+ BackgroundRole,
50+ SessionRole,
51+ HasMessagesRole,
52+ ImagePathRole,
53+ BackgroundPathRole
54+ };
55+
56+ int rowCount(const QModelIndex &parent) const override;
57+ QVariant data(const QModelIndex &index, int role) const override;
58+
59+private:
60+ UsersModelPrivate * const d_ptr;
61+ Q_DECLARE_PRIVATE(UsersModel)
62+};
63+
64+}
65+
66+#endif // UNITY_MOCK_USERSMODEL_H
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.cppnew file+41
@@ -0,0 +1,41 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#include "UsersModelPrivate.h"
20+
21+#include <QDir>
22+#include <QSettings>
23+#include <QStringList>
24+
25+namespace QLightDM
26+{
27+
28+UsersModelPrivate::UsersModelPrivate(UsersModel* parent)
29+ : q_ptr(parent)
30+{
31+ QSettings settings(QDir::homePath() + "/.unity8-greeter-demo", QSettings::NativeFormat);
32+ QStringList users = settings.value("users", QStringList() << qgetenv("USER")).toStringList();
33+
34+ Q_FOREACH(const QString &user, users)
35+ {
36+ QString name = settings.value(user + "/name", user[0].toUpper() + user.mid(1)).toString();
37+ entries.append({user, name, 0, 0, false, false, 0, 0});
38+ }
39+}
40+
41+}
plugins/IntegratedLightDM/liblightdm/UsersModelPrivate.hnew file+59
@@ -0,0 +1,59 @@
1+/*
2+ * Copyright (C) 2013 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ * Author: Michael Terry <michael.terry@canonical.com>
17+ */
18+
19+#ifndef UNITY_MOCK_USERSMODEL_PRIVATE_H
20+#define UNITY_MOCK_USERSMODEL_PRIVATE_H
21+
22+#include <QtCore/QList>
23+#include <QtCore/QString>
24+
25+namespace QLightDM
26+{
27+class UsersModel;
28+
29+class Entry
30+{
31+public:
32+ QString username;
33+ QString real_name;
34+ QString background;
35+ QString layouts;
36+ bool is_active;
37+ bool has_messages;
38+ QString session;
39+ QString infographic;
40+};
41+
42+class UsersModelPrivate
43+{
44+public:
45+ explicit UsersModelPrivate(UsersModel *parent = 0);
46+ virtual ~UsersModelPrivate() = default;
47+
48+ QList<Entry> entries;
49+
50+protected:
51+ UsersModel * const q_ptr;
52+
53+private:
54+ Q_DECLARE_PUBLIC(UsersModel)
55+};
56+
57+}
58+
59+#endif // UNITY_MOCK_USERSMODEL_PRIVATE_H
plugins/IntegratedLightDM/plugin.cppnew file+69
@@ -0,0 +1,69 @@
1+/*
2+ * Copyright (C) 2012,2013, 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#include "plugin.h"
19+#include "DBusGreeter.h"
20+#include "DBusGreeterList.h"
21+#include "Greeter.h"
22+#include "UsersModel.h"
23+#include <libusermetricsoutput/ColorTheme.h>
24+#include <libusermetricsoutput/UserMetrics.h>
25+#include <QLightDM/UsersModel>
26+
27+#include <QAbstractItemModel>
28+#include <QDBusConnection>
29+#include <QtQml/qqml.h>
30+
31+static QObject *greeter_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
32+{
33+ Q_UNUSED(engine)
34+ Q_UNUSED(scriptEngine)
35+
36+ Greeter *greeter = new Greeter();
37+ new DBusGreeter(greeter, "/");
38+ new DBusGreeterList(greeter, "/list");
39+
40+ return greeter;
41+}
42+
43+static QObject *users_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
44+{
45+ Q_UNUSED(engine)
46+ Q_UNUSED(scriptEngine)
47+ return new UsersModel();
48+}
49+
50+static QObject *infographic_provider(QQmlEngine *engine, QJSEngine *scriptEngine)
51+{
52+ Q_UNUSED(engine)
53+ Q_UNUSED(scriptEngine)
54+ return UserMetricsOutput::UserMetrics::getInstance();
55+}
56+
57+void IntegratedLightDMPlugin::registerTypes(const char *uri)
58+{
59+ qmlRegisterType<QAbstractItemModel>();
60+ qmlRegisterType<UserMetricsOutput::ColorTheme>();
61+
62+ Q_ASSERT(uri == QLatin1String("IntegratedLightDM"));
63+ qRegisterMetaType<QLightDM::Greeter::MessageType>("QLightDM::Greeter::MessageType");
64+ qRegisterMetaType<QLightDM::Greeter::PromptType>("QLightDM::Greeter::PromptType");
65+ qmlRegisterSingletonType<Greeter>(uri, 0, 1, "Greeter", greeter_provider);
66+ qmlRegisterSingletonType<UsersModel>(uri, 0, 1, "Users", users_provider);
67+ qmlRegisterUncreatableType<QLightDM::UsersModel>(uri, 0, 1, "UserRoles", "Type is not instantiable");
68+ qmlRegisterSingletonType<UserMetricsOutput::UserMetrics>(uri, 0, 1, "Infographic", infographic_provider);
69+}
plugins/IntegratedLightDM/plugin.hnew file+33
@@ -0,0 +1,33 @@
1+/*
2+ * Copyright (C) 2012,2013, 2015 Canonical, Ltd.
3+ *
4+ * This program is free software; you can redistribute it and/or modify
5+ * it under the terms of the GNU General Public License as published by
6+ * the Free Software Foundation; version 3.
7+ *
8+ * This program is distributed in the hope that it will be useful,
9+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+ * GNU General Public License for more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ *
16+ */
17+
18+#ifndef INTEGRATED_LIGHTDM_PLUGIN_H
19+#define INTEGRATED_LIGHTDM_PLUGIN_H
20+
21+#include <QtQml/QQmlEngine>
22+#include <QtQml/QQmlExtensionPlugin>
23+
24+class IntegratedLightDMPlugin : public QQmlExtensionPlugin
25+{
26+ Q_OBJECT
27+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
28+
29+public:
30+ void registerTypes(const char *uri) override;
31+};
32+
33+#endif /* INTEGRATED_LIGHTDM_PLUGIN_H */
plugins/IntegratedLightDM/qmldirnew file+3
@@ -0,0 +1,3 @@
1+module IntegratedLightDM
2+plugin IntegratedLightDM-qml
3+typeinfo IntegratedLightDM.qmltypes