Browse Source

Add database notification support.

Neal Wilson 7 years ago
parent
commit
fc6e8d077b
1 changed files with 104 additions and 3 deletions
  1. 104
    3
      src/typica.w

+ 104
- 3
src/typica.w View File

@@ -12887,6 +12887,7 @@ define a macro that returns the |Application| instance.
12887 12887
 
12888 12888
 class NodeInserter;
12889 12889
 class DeviceTreeModel;
12890
+class DatabaseNotification;
12890 12891
 class Application : public QApplication@/
12891 12892
 {@/
12892 12893
     @[Q_OBJECT@]@;
@@ -12900,10 +12901,12 @@ class Application : public QApplication@/
12900 12901
         Q_INVOKABLE bool login(const QString &user, const QString &password);
12901 12902
         Q_INVOKABLE bool autoLogin();
12902 12903
         QScriptEngine *engine;
12903
-        QNetworkAccessManager *network;@/
12904
+        QNetworkAccessManager *network;
12905
+        DatabaseNotification *subscribe(const QString &notification);@/
12904 12906
     @[public slots@]:@/
12905 12907
 	    void setDatabaseConnected(bool status);
12906 12908
 	    void setCurrentTypicaUser(const QString &user);
12909
+	    void notify(const QString &notification);
12907 12910
         @<Extended Application slots@>@;
12908 12911
     @[signals@]:@/
12909 12912
 	    void userChanged(const QString &user);
@@ -12912,6 +12915,8 @@ class Application : public QApplication@/
12912 12915
         QDomDocument conf;
12913 12916
         bool connectionStatus;
12914 12917
         QString currentUser;
12918
+        QMap<QString, DatabaseNotification*> notifiers;
12919
+        QSqlDriver *notificationDriver;
12915 12920
 };
12916 12921
 
12917 12922
 @ The constructor for this class handles a few things that had previously been
@@ -12956,11 +12961,11 @@ if(app->load(QString("%1_%2").arg("Typica").arg(QLocale::system().name()), QStri
12956 12961
 }
12957 12962
 
12958 12963
 @ We also want to be able to access the application instance from within the
12959
-scripting engine. We don'@q'@>t need to be able to create new instances, just access
12960
-the one that already exists.
12964
+scripting engine. We don'@q'@>t need to be able to create new instances, just access the one that already exists.
12961 12965
 
12962 12966
 @<Set up the scripting engine@>=
12963 12967
 value = engine->newQObject(AppInstance);
12968
+value.setProperty("subscribe", engine->newFunction(Application_subscribe));
12964 12969
 engine->globalObject().setProperty("Application", value);
12965 12970
 
12966 12971
 @ The |configuration()| method provides access to an XML document containing the
@@ -13002,6 +13007,102 @@ bool Application::databaseConnected()
13002 13007
 	return connectionStatus;
13003 13008
 }
13004 13009
 
13010
+@ Database notifications allow various parts of Typica to be aware when data in
13011
+the database may have been changed by another instance of Typica running on a
13012
+different computer or by another program that uses the same database. To pass
13013
+notifications to the various places that may be interested in these and not
13014
+bother notification aware controls that are uninterested in unrelated
13015
+notifications, a notification object is created for each notification.
13016
+
13017
+@<Application Implementation@>=
13018
+DatabaseNotification* Application::subscribe(const QString &notification)
13019
+{
13020
+    DatabaseNotification *retval;
13021
+    if(notifiers.contains(notification))
13022
+    {
13023
+        retval = notifiers.value(notification);
13024
+    }
13025
+    else
13026
+    {
13027
+        if(notifiers.size() == 0)
13028
+        {
13029
+            notificationDriver = QSqlDatabase::database().driver();
13030
+            connect(notificationDriver, SIGNAL(notification(QString)), this, SLOT(notify(QString)));
13031
+        }
13032
+        retval = new DatabaseNotification;
13033
+        connect(this, SIGNAL(aboutToQuit()), retval, SLOT(deleteLater()));
13034
+        if(notifiers.size() !=
13035
+            notificationDriver->subscribedToNotifications().size())
13036
+        {
13037
+            for(int i = 0; i < notifiers.size(); i++)
13038
+            {
13039
+                notificationDriver->subscribeToNotification(notifiers.keys().at(i));
13040
+            }
13041
+        }
13042
+        notifiers.insert(notification, retval);
13043
+        notificationDriver->subscribeToNotification(notification);
13044
+    }
13045
+    return retval;
13046
+}
13047
+
13048
+@ As the various parts of \pn{} operate mostly indepent of each other and
13049
+notifications from the current instance may not be immediately returned, it is
13050
+generally a good idea for operations that would generate a notification to also
13051
+signal that notification within the application.
13052
+
13053
+@<Application Implementation@>=
13054
+void Application::notify(const QString &notification)
13055
+{
13056
+    if(notifiers.contains(notification))
13057
+    {
13058
+        DatabaseNotification *notifier = notifiers.value(notification);
13059
+        notifier->forwardNotification(notification);
13060
+    }
13061
+}
13062
+
13063
+@ A function is provided to allow subscribing to notifications from scripts.
13064
+@<Function prototypes for scripting@>=
13065
+QScriptValue Application_subscribe(QScriptContext *context,
13066
+                                   QScriptEngine *engine);
13067
+
13068
+@ The implementation is trivial.
13069
+
13070
+@<Functions for scripting@>=
13071
+QScriptValue Application_subscribe(QScriptContext *context,
13072
+                                   QScriptEngine *engine)
13073
+{
13074
+    return engine->newQObject(
13075
+        AppInstance->subscribe(argument<QString>(0, context)));
13076
+}
13077
+
13078
+@ The DatabaseNotification object just needs a signal that interested objects
13079
+can connect to.
13080
+
13081
+@<Class declarations@>=
13082
+class DatabaseNotification : public QObject
13083
+{
13084
+    Q_OBJECT
13085
+    public:
13086
+        DatabaseNotification();
13087
+    public slots:
13088
+        void forwardNotification(const QString &notification);
13089
+    signals:
13090
+        void notify(const QString &notification);
13091
+};
13092
+
13093
+@ The implementation is trivial.
13094
+
13095
+@<Class declarations@>=
13096
+DatabaseNotification::DatabaseNotification() : QObject(NULL)
13097
+{
13098
+    /* Nothing needs to be done here. */
13099
+}
13100
+
13101
+void DatabaseNotification::forwardNotification(const QString &notification)
13102
+{
13103
+    emit notify(notification);
13104
+}
13105
+
13005 13106
 @** Table editor for ordered arrays with SQL relations.
13006 13107
 
13007 13108
 \noindent A database in use at Wilson's Coffee \char'046~Tea stores information

Loading…
Cancel
Save