WARNING: USE THIS SOFTWARE AT YOUR OWN RISK! THIS IS EXPERIMENTAL SOFTWARE NOT INTENDED FOR PRODUCTION USE! Zuble is currently an early stage prototype. As such Zuble is minimally tested and inherently unstable. It is provided for experimental, development, and demonstration purposes only. Zuble QML Types   |  Zuble C++ Classes   |  Zuble Overview
Zuble  0.1
Zuble Framework C++/QML extension API
ZblApp.cpp
Go to the documentation of this file.
1 /*
2  * Zuble - A run-time system for QML/Javascript applications
3  * Copyright (C) 2013, 2014 Bob Dinitto
4  *
5  * ZblApp.cpp
6  *
7  * Created on: Feb 3, 2013
8  * Author: Bob Dinitto bob@ninzo.com
9  *
10  * Zuble is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24 */
25 
26 #include "ZblApp.h"
27 #include "ZblException.h"
28 #include "ZApplication.h"
29 #include "ZblThreadErr.h"
30 #include "ZScriptThread.h"
31 #include "zglobal.h"
32 #include "ZDir.h"
33 #include "ZFile.h"
34 #include "ZByteArray.h"
35 #include "ZTextStream.h"
36 #include "ZDataStream.h"
37 #include "ZSchemaValidator.h"
38 #include "ZTableModel.h"
39 #include "ZblCog.h"
40 #include "ZblFactory.h"
41 #include "ZblLogManager.h"
42 #include "ZSettings.h"
43 #include "ZFileSystemWatcher.h"
44 #include "ZMessageQueue.h"
45 #include "ZMailslot.h"
46 #include "ZMailbox.h"
47 #include "ZMap.h"
48 #include "ZScopedMap.h"
49 #include "ZLogReader.h"
50 #include "ZxQuery.h"
51 #include "ZProcess.h"
52 #include <QtQml>
53 #include <QVariant>
54 
55 namespace Zbl
56 {
57 
59 
60 QVariant ZblApp::m_tags;
61 QReadWriteLock ZblApp::m_lock(QReadWriteLock::Recursive); // TBD: need this?
62 
63 QThreadStorage<ZblApp::AppPtr*> ZblApp::m_zApp;
64 
65 ZblApp::ZblApp(QJSEngine* scriptEngine,
66  ZScriptThread *container,
67  QObject* parent)
68  : QObject(parent), m_engine(scriptEngine), m_container(container)
69 {
70 
71  //ZBL_REGISTER_LOGGED_OBJECT
72  zDebug() << "ZblApp::ZblApp";
73 
74  m_zApp.setLocalData(new AppPtr(this));
75 
76  createTags();
77 
78  connect( &zApp.zStatus(), SIGNAL(dataReady(const QString&)),
79  SIGNAL(statusAvailable(QString)));
80 
81  connect( this, SIGNAL(destroyed(QObject*)),
82  SLOT(onDestroyed(QObject*)));
83 
84  connect( this, SIGNAL(exit(int)),
85  this, SLOT(exitApp(int)), Qt::QueuedConnection);
86 
87 }
88 
90 {
91  zDebug() << "ZblApp::~ZblApp";
92 
93  stopAllTimers();
94 }
95 
97 {
98  if(!m_zApp.hasLocalData())
99  throw ZblException("ZblApp::zInstance - a ZblApp object hasn't been "
100  "constructed for the current thread.");
101 
102  return *m_zApp.localData()->m_app;
103 }
104 
106 {
107  if(!m_tags.isNull())
108  return;
109 
110  QVariantMap map;
111 
112  map.insert("appDirPath", ZApplication::appDirPath);
113  map.insert("appFilePath", ZApplication::appFilePath);
114  map.insert("appName", ZApplication::appName);
115  map.insert("appPid", ZApplication::appPid);
116  map.insert("appVersion", ZApplication::appVersion);
117  map.insert("appArguments", ZApplication::appArguments);
118  map.insert("appLibraryPath", ZApplication::appLibraryPath);
119 
120  map.insert("LogFieldRecordNum", ZblLogManager::LogFieldRecordNum);
121  map.insert("LogFieldCategory", ZblLogManager::LogFieldCategory);
122  map.insert("LogFieldSource", ZblLogManager::LogFieldSource);
123  map.insert("LogFieldMessage", ZblLogManager::LogFieldMessage);
124  map.insert("LogFieldFunction", ZblLogManager::LogFieldFunction);
125  map.insert("LogFieldLine", ZblLogManager::LogFieldLine);
126  map.insert("LogFieldFile", ZblLogManager::LogFieldFile);
127 
128  map.insert("LogFieldSeekIndex", ZblLogManager::LogFieldFile);
129  map.insert("LogFieldByteCount", ZblLogManager::LogFieldFile);
130  map.insert("LogFieldBookmarks", ZblLogManager::LogFieldFile);
131 
132  map.insert("LogRuleCategory", ZblLogManager::RuleCategory);
133  map.insert("LogRuleRegistered", ZblLogManager::RuleRegistered);
134  map.insert("LogRuleSaved", ZblLogManager::RuleSaved);
135  map.insert("LogRuleEnabled", ZblLogManager::RuleEnabled);
136  map.insert("LogRuleWarning", ZblLogManager::RuleWarning);
137  map.insert("LogRuleCritical", ZblLogManager::RuleCritical);
138  map.insert("LogRuleDebug", ZblLogManager::RuleDebug);
139 
140  map.insert("SettingsUserScope", QSettings::UserScope);
141  map.insert("SettingsSystemScope", QSettings::SystemScope);
142 
143 
144  QVariantMap testMap;
145 
146  testMap.insert("VALUE_ONE", 1);
147  testMap.insert("VALUE_TWO", 2);
148 
149 
150  map.insert("Test", QVariant::fromValue(testMap));
151 
152 
153  m_tags = QVariant::fromValue(map);
154 }
155 
157 {
158  return m_tags;
159 }
160 
162  QQmlEngine *engine, QJSEngine *scriptEngine)
163 {
164  Q_UNUSED(engine)
165 
166  zDebug() << "ZblApp::getSingletonType";
167 
168  ZblApp* newApp = new ZblApp(scriptEngine);
169 
170  return newApp;
171 
172 }
173 
175 {
177 
178  zDebug() << "ZblApp::registerSingletonType";
179 
180 
181  //m_log().setEnabled(QtDebugMsg, true);
182  //m_log().setEnabled(QtWarningMsg, true);
183  //m_log().setEnabled(QtCriticalMsg, true);
184 
185 
186  return qmlRegisterSingletonType<ZblApp>(
187  "org.zuble.qml",
188  1,
189  0,
190  "Zbl",
192 
193 }
194 
196 {
198 }
199 
201 {
203 }
204 
205 QString ZblApp::errorMessage()
206 {
207  return zThreadErr.getErrorMessage();
208 }
209 
211 {
212  throw Zbl::ZblException("top level exception");
213 }
214 
216 {
218 
219  throwException();
220 
221  ZBL_SLOT_END_VOID(myfacility,mycode,exception in throwDeeperException)
222 }
223 
225 {
226  try
227  {
228  throwException();
229  }
230  catch(Zbl::ZblException zblEx)
231  {
232  zDebug() << "ZblException exception caught: " << zblEx.what();
233  }
234  catch(...)
235  {
236  zDebug() << "unknown exception caught";
237  }
238 }
239 
240 
242 {
243  throw Zbl::ZblException("second level exception");
244 }
245 
246 #if 0
247 QJSValue ZblApp::returnAnException()
248 {
249  //QString name("message");
250  //m_errorObject.setProperty(name, QJSValue("returning error message ok"));
251 
252  setError(QJSValue("returnExceptionError"));
253 
254  return m_errorObject;
255 }
256 #else
257 
259 {
260  //QString name("message");
261  //m_errorObject.setProperty(name, QJSValue("returning error message ok"));
262 
263  setError(QJSValue("returnExceptionError"));
264 
265  return error().toVariant();
266 }
267 #endif
268 
269 void ZblApp::setError(QJSValue errValue)
270 {
271  QWriteLocker lock(&m_lock);
272 
273  if(errValue.isError())
274  {
275  zThreadErr.raiseError(
276  errValue.property(QStringLiteral("name")).toString(),
277  QStringLiteral(""),
278  errValue.property(QStringLiteral("message")).toString());
279  }
280  else
281  {
282  zThreadErr.raiseError(
283  QStringLiteral("Error"),
284  QStringLiteral(""),
285  errValue.toString());
286  }
287 
288 
289 }
290 
292 {
293  QReadLocker lock(&m_lock);
294 
295  return zThreadErr.error().isError();
296 }
297 
299 {
300  QWriteLocker lock(&m_lock);
301  //qDebug("ZblApp::clearError");
302 
303  zThreadErr.clearError();
304 }
305 
306 QJSValue ZblApp::error()
307 {
308  QJSValue err(m_engine->evaluate("new Error();"));
309  err.setProperty(QStringLiteral("facility"), QJSValue(zThreadErr.error().facility()));
310  err.setProperty(QStringLiteral("code"), QJSValue(zThreadErr.error().code()));
311  err.setProperty(QStringLiteral("message"), QJSValue(zThreadErr.error().message()));
312  err.setProperty(QStringLiteral("description"), QJSValue(zThreadErr.error().description()));
313  err.setProperty(QStringLiteral("isError"), QJSValue(zThreadErr.error().isError()));
314  return err;
315 }
316 
317 QJSValue ZblApp::convertEvaluateError(const QJSValue& evaluateError)
318 {
319  QString msg(evaluateError.toString());
320  QString desc("ZBL:0:%1");
321 
322  QJSValue err(m_engine->evaluate("new Error();"));
323  err.setProperty(QStringLiteral("facility"), QJSValue("ZBL"));
324  err.setProperty(QStringLiteral("code"), QJSValue(0));
325  err.setProperty(QStringLiteral("message"), QJSValue(msg));
326  err.setProperty(QStringLiteral("description"), QJSValue(desc.arg(msg)));
327  err.setProperty(QStringLiteral("isError"), true);
328  return err;
329 }
330 
331 QVariant ZblApp::include(const QString& fileUrl)
332 {
333  QString filePath = resolveAppPath(fileUrl,false);
334  QString script;
335  QJSValue result;
337 
338  QFile file(filePath);
339 
340  status(QString("zInclude: %1").arg(filePath));
341 
342  if(!file.exists())
343  {
344  QString msg("zInclude -- Non-existent file: %1");
345  throw ZblException(msg.arg(filePath));
346  }
347  else if(!file.open(QIODevice::ReadOnly))
348  {
349  QString msg("zInclude -- Can't open file for reading: %1");
350  throw ZblException(msg.arg(filePath));
351  }
352 
353  QTextStream stream(&file);
354 
355  script = stream.readAll();
356 
357  if(!script.isEmpty())
358  result = m_engine->evaluate(script, fileUrl, 1);
359 
360  if(result.isError())
361  {
362  // evaluation error
363  result = convertEvaluateError(result);
364  }
365 
366  if(isError())
367  {
368  // Zuble custom QObject exception error
369  result = error();
370  }
371 
372  }
373  catch(ZblException ex)
374  {
375  // normal exception error
376 
377  result = error();
378  }
379 
380  return result.toVariant();
381 }
382 
383 
384 
385 void ZblApp::status(const QString& text)
386 {
387  qDebug() << "z@ " << text;
388 
389  ZTextFeed& feed(zApp.zStatus());
390 
391  feed.send(text);
392 
393  feed.flush();
394 }
395 
396 
397 
398 
399 QVariant ZblApp::getAppData(int dataKey)
400 {
401  //qDebug() << "ZblApp::getAppData in some thread";
402 
403  if(isInMainThread())
404  {
405  //qDebug() << "ZblApp::getAppData in main thread ";
406 
407  return zApp.getAppData(dataKey);
408  }
409  else
410  {
411  //qDebug() << "ZblApp::getAppData in background thread";
412 
413  //ZApplication::appDataKey key(static_cast<ZApplication::appDataKey>(dataKey));
414 
415  QVariant retValue;
416 
417  QMetaObject::invokeMethod(&zApp,"getAppData",
418  Qt::BlockingQueuedConnection,
419  Q_RETURN_ARG( QVariant, retValue),
420  Q_ARG(int, dataKey));
421 
422  //qDebug() << "ZblApp::getAppData: " << retValue;
423 
424  return retValue;
425  }
426 }
427 
429 {
430  if(isInMainThread())
431  {
432  return zApp.getAppName();
433  }
434  else
435  {
436  //qDebug() << "ZblApp::getAppData in background thread";
437 
438  //ZApplication::appDataKey key(static_cast<ZApplication::appDataKey>(dataKey));
439 
440  QVariant retValue;
441 
442  QMetaObject::invokeMethod(&zApp,"getAppName",
443  Qt::BlockingQueuedConnection,
444  Q_RETURN_ARG(QVariant, retValue));
445  return retValue;
446  }
447 }
448 
449 
451 {
452  return QThread::currentThread() == qApp->thread();
453 }
454 
455 QObject* ZblApp::newDir()
456 {
458  ZBL_SLOT_END_RETURN(new ZDir(), NULL,
459  Z_FAC_JS, ZblApp::newDir, newDir failed)
460 }
461 
462 QObject* ZblApp::newFile()
463 {
465  ZBL_SLOT_END_RETURN(new ZFile(), NULL,
467 }
468 
470 {
472  ZBL_SLOT_END_RETURN(new ZByteArray(), NULL,
474 }
475 
476 QObject* ZblApp::newTextStream(const QString& text)
477 {
478  ZqStringPtr stringPtr = ZqStringPtr::create();
480  *stringPtr = text;
481  ZBL_SLOT_END_RETURN(new ZTextStream(stringPtr), NULL,
483 }
484 
486 {
488  QTextStream instream(stdin);
489  QString text = instream.readLine(0);
490  ZBL_SLOT_END_RETURN(text, QString(),
492 }
493 
494 void ZblApp::print(const QString& text, bool newLine)
495 {
497  QTextStream outstream(stdout, QIODevice::WriteOnly | QIODevice::Text);
498  outstream << text;
499  if(newLine)
500  outstream << endl;
502 }
503 
504 void ZblApp::printErr(const QString& text, bool newLine)
505 {
507  QTextStream errstream(stderr, QIODevice::WriteOnly | QIODevice::Text);
508  errstream << text;
509  if(newLine)
510  errstream << endl;
512 }
513 
514 
515 QObject* ZblApp::newDataStream(QObject* byteArray)
516 {
518  ZByteArray* pByteArray = qobject_cast<ZByteArray*>(byteArray);
519  if(!pByteArray)
520  throw ZblException(
521  "Programming error - object passed is not a Zbl::ZByteArray");
522  ZBL_SLOT_END_RETURN(new ZDataStream(pByteArray->qByteArray()), NULL,
524 }
525 
527 {
531 }
532 
533 
535 {
537  ZBL_SLOT_END_RETURN(new ZTableModel(), NULL,
539 }
540 
542 {
546 }
547 
549 {
551  ZBL_SLOT_END_RETURN(new ZMailslot(), NULL,
553 }
554 
556 {
558  ZBL_SLOT_END_RETURN(new ZProcess(), NULL,
560 }
561 
563 {
565  ZBL_SLOT_END_RETURN(new ZMailbox(), NULL,
567 }
568 
569 QObject* ZblApp::newMap()
570 {
572  ZBL_SLOT_END_RETURN(new ZMap(), NULL,
573  Z_FAC_JS, ZblApp::newMap, newMap failed)
574 }
575 
577 {
579  ZBL_SLOT_END_RETURN(new ZScopedMap(), NULL,
581 }
582 
584 {
586  ZBL_SLOT_END_RETURN(new ZLogReader(), NULL,
588 }
589 
590 
592 {
596 }
597 
598 QObject* ZblApp::newAppSettings(int scope,
599  const QString& application,
600  const QString& organization)
601 {
602  ZSettings* settings = NULL;
603 
605  settings = new ZSettings();
606 
607  bool ok = settings->open(scope, application, organization);
608  if(!ok)
609  {
610  delete settings;
611  throw ZblException(QString("ZblApp::newAppSettings - can't open app settings "
612  "for scope: %1, application: %2, organization: %3")
613  .arg(scope).arg(application, organization));
614  }
615  ZBL_SLOT_END_RETURN(settings, NULL,
617 }
618 
619 QObject* ZblApp::newSettingsFile(const QString& filePath)
620 {
621  ZSettings* settings = nullptr;
622 
624  settings = new ZSettings();
625 
626  bool ok = settings->open(filePath);
627  if(!ok)
628  {
629  delete settings;
630  throw ZblException(QString("ZblApp::newSettingsFile - can't open settings "
631  "file: %1").arg(filePath));
632  }
633  ZBL_SLOT_END_RETURN(settings, NULL,
635 }
636 
638 {
640  ZBL_SLOT_END_RETURN(new ZxQuery(), NULL,
642 }
643 
645 {
649 }
650 
651 QObject* ZblApp::bundleSettings(const QString& bundleID)
652 {
653  QObject* settings = nullptr;
655  settings = ZSettings::getBundleSettings(bundleID);
656  ZBL_SLOT_END_RETURN(settings, NULL,
658 }
659 
661  const QString& sprocketUri, const QString& objectName)
662 {
663  QObject* ob = nullptr;
664 
666 
667  ZblFactory* factory = m_factories.value(sprocketUri, nullptr);
668 
669  if(!factory)
670  throw ZblException(QString(
671  "No Sprocket plugin has been imported for uri: %1").arg(sprocketUri));
672 
673  // new Sprocket object will automatically receive Javascript ownership
674 
675  ob = factory->createObject(cStr(objectName));
676 
677  ZBL_SLOT_END_RETURN(ob, NULL,
679 }
680 
681 
683  const QString& sprocketUri, int versionMajor, int versionMinor)
684 {
686 
687  if(m_factories.contains(sprocketUri))
688  throw ZblException(QString(
689  "Sprocket already imported: %1").arg(sprocketUri));
690 
691  ZblFactory* factory = zCog.createFactory(cStr(sprocketUri), versionMajor, versionMinor);
692 
693  if(!factory)
694  throw ZblException(QString(
695  "Can't import Sprocket: %1").arg(sprocketUri));
696 
697  factory->setParent(this);
698 
699  m_factories.insert(sprocketUri, factory);
700 
701  ZBL_SLOT_END_RETURN(true, false,
702  Z_FAC_JS, ZblApp::import, import failed)
703 
704 }
705 
707  const QString& uri,
708  int versionMajor,
709  int versionMinor,
710  const QString& fileName)
711 {
714  zCog.mapResource(uri.toUtf8(),
715  versionMajor, versionMinor, fileName.toUtf8()),
716  false, Z_FAC_JS, ZblApp::mapResource, mapResource failed)
717 }
718 
720  const QString& uri, int versionMajor, int versionMinor)
721 {
724  zCog.registerResource(uri.toUtf8(), versionMajor, versionMinor),
726 }
727 
728 
729 bool ZblApp::mapPluginResources(const QString& fileName, bool qmlregister)
730 {
733  zCog.mapPluginResources(fileName.toUtf8(), qmlregister),
735 }
736 
737 
739 {
741  ZBL_SLOT_END_RETURN(QCoreApplication::arguments(), QStringList(),
743 }
744 
746 {
749  QProcessEnvironment::systemEnvironment().toStringList(),
750  QStringList(),
752 }
753 
755 {
756  QThread* thread = QThread::currentThread();
757 
758  if(thread == qApp->thread())
759  return false;
760  else
761  return thread->isInterruptionRequested();
762 }
763 
764 
766 {
769  QString("<Thread ID Error>"),
771 }
772 
773 
774 QString ZblApp::getObjectThreadAddress(QObject* object)
775 {
778  QString("<Thread ID Error>"),
780 }
781 
782 void ZblApp::addLibraryPath(const QString& path)
783 {
784  if(!isInMainThread())
785  {
786 #if 0
787  //TBD: THIS CAN'T WORK! no addLibraryPath method in ZApplication
788 
789  QMetaObject::invokeMethod(&zApp,"addLibraryPath",
790  Qt::BlockingQueuedConnection,
791  Q_ARG(const QString&, path));
792 #else
793 
794  zWarning() << "Zuble programming ERROR: addLibaryPath not supported for background threads.";
795 
796 #endif
797  }
798  else
799  {
800  qApp->addLibraryPath(path);
801  }
802 }
803 
804 
805 QString ZblApp::resolveAppPath(const QString& path, bool includeUrlScheme)
806 {
808  ZApplication::getRootPath(), path, includeUrlScheme);
809 }
810 
811 QString ZblApp::resolveHomePath(const QString& path, bool includeUrlScheme)
812 {
813  QString homePath(QDir::homePath() + "/");
815  homePath, path, includeUrlScheme);
816 }
817 
818 QString ZblApp::resolvePath(const QString& path, bool includeUrlScheme)
819 {
820  return ZApplication::resolvePath( path, includeUrlScheme);
821 }
822 
824 {
825  return ZApplication::getRootPath();
826 }
827 
829 {
831 }
832 
833 bool ZblApp::isResourcePath(const QString& path)
834 {
835  QString scheme = ZApplication::getPathScheme(path);
836 
837  if(scheme == "qrc:/" || scheme == ":/")
838  return true;
839 
840  return false;
841 }
842 
843 QString ZblApp::bundleMetapath(const QString& bundleID)
844 {
846 
849 }
850 
851 QString ZblApp::bundleMetadata(const QString& bundleID)
852 {
854 
857 }
858 
859 
861  QJSValue timerFunction,
862  QJSValue timerArgument,
863  int milliseconds)
864 {
865  int timerID = 0;
866 
868 
869  timerID = startTimer(milliseconds);
870 
871  if(timerID == 0)
872  throw ZblException("QObject::startTimer failed");
873 
874  if(m_scriptTimers.contains(timerID))
875  zWarning() << "ZblApp::startTimerInterval - warning: script timer ID reused";
876 
877  m_scriptTimers.insert(
878  timerID,TimerMethodCall(timerFunction, timerArgument));
879 
880  ZBL_SLOT_END_RETURN(timerID, timerID,
882 
883  //return 0;
884 
885 }
886 
887 void ZblApp::stopTimerInterval(int timerID)
888 {
890  if(timerID == 0)
891  return;
892  killTimer(timerID);
893  m_scriptTimers.remove(timerID);
896 }
897 
898 void ZblApp::timerEvent(QTimerEvent * event)
899 {
901  const int timerID = event->timerId();
902 
903  //qDebug("ZblApp::timerEvent -- %u", timerID);
904 
905  if(m_scriptTimers.contains(timerID))
906  {
907  TimerMethodCall call(m_scriptTimers.value(timerID));
908  QJSValueList timerArgs;
909  timerArgs.append(call.timerArg);
910  call.timerFunc.callWithInstance(m_engine->globalObject(),timerArgs);
911  }
914 
915 }
916 
918 {
920 
921  if(!m_scriptTimers.isEmpty())
922  {
923  timerKeys timers(m_scriptTimers.keys());
924 
925  timerKeys::iterator it(timers.begin());
926 
927  while(it != timers.end())
928  killTimer(*it++);
929 
930  m_scriptTimers.clear();
931  }
932 
935 
936 }
937 
938 void ZblApp::sleep(unsigned long milliseconds)
939 {
941 
942  QThread::msleep(milliseconds);
943 
945 }
946 
947 void ZblApp::sleepEvents(unsigned long milliseconds)
948 {
950 
951  unsigned long waitTime = 25;
952  unsigned long count = milliseconds / waitTime;
953  QAbstractEventDispatcher* d = QThread::currentThread()->eventDispatcher();
954 
955 
956  if(count < 1)
957  count = 1;
958 
959  zDebug() << "Waiting: " << count << " * " << waitTime << " milliseconds.";
960 
961  for(unsigned long i=0; i < count; i++)
962  {
963  QThread::msleep(waitTime);
964 
965  d->processEvents(QEventLoop::AllEvents);
966 
967  //QCoreApplication::processEvents(QEventLoop::AllEvents);
968  collectGarbage(); // TBD: need this?
969 
970  }
971  zDebug() << "Done Waiting: " << count << " * " << waitTime << " milliseconds.";
972 
973 
975 }
976 
977 
979 {
981  m_engine->collectGarbage();
984 }
985 
986 void ZblApp::alert(const QString signalID, QVariant payload, bool wait)
987 {
989 
990  if(isInMainThread())
991  return;
992  // pass int as int
993  // pass string as string with JSONflag = false
994  // pass QJSValues as JSON strings with JSONflag = true
995 
996 
997  if(!m_container)
998  {
999  zWarning() << "ZblApp::alert - Programming error! Background ZblApp "
1000  "expects it's container to be a ZScriptThread object.";
1001 
1002  return;
1003  }
1004 
1005  zDebug() << "SENDING ALERT id=" << signalID << ", wait = " << wait << ", payload=" << payload;
1006 
1007  //QVariant vPayload(payload);
1008 
1009  QString strPayload;
1011  QJsonDocument doc;
1012 
1013  int metatype = int(payload.type());
1014 
1015  zDebug() << "metatype = " << metatype;
1016 
1017  switch(metatype)
1018  {
1019 
1020  case QMetaType::Int:
1021 
1022  zDebug() << "QMetaType = Int";
1023 
1024  strPayload = payload.toString();
1025  conversion = ZScriptThread::INTEGER;
1026 
1027  break;
1028 
1029  case QMetaType::Double:
1030 
1031  zDebug() << "QMetaType = Double";
1032 
1033  strPayload = payload.toString();
1034  conversion = ZScriptThread::DOUBLE;
1035 
1036  break;
1037 
1038  case QMetaType::QString:
1039 
1040  zDebug() << "QMetaType = QString";
1041 
1042  strPayload = payload.toString();
1043  conversion = ZScriptThread::STRING;
1044 
1045  break;
1046 
1047  case QMetaType::User:
1048 
1049  zDebug() << "QMetaType = User";
1050 
1051  static const int qjstype = QVariant::fromValue(QJSValue()).userType();
1052 
1053  if(payload.userType() == qjstype)
1054  {
1055  zDebug() << "QMetaType = QJSValue";
1056 
1057  QVariant var = payload.value<QJSValue>().toVariant();
1058 
1059  strPayload = ZScriptThread::variantToJson(var);
1060  conversion = ZScriptThread::JSON;
1061 
1062  zDebug() << "Stringified payload=" << strPayload;
1063  }
1064  else
1065  {
1066  QString msg("ZblApp::alert received unrecognized QVariant type: %1");
1067  throw ZblException(msg.arg(metatype));
1068  }
1069  break;
1070 
1071  default:
1072 
1073  QString msg("ZblApp::alert received unrecognized QVariant type: %1");
1074  msg = msg.arg(metatype);
1075 
1076  zWarning() << msg;
1077 
1078  throw ZblException(msg);
1079  }
1080 
1081 
1082  Qt::ConnectionType connection = wait ? Qt::BlockingQueuedConnection
1083  : Qt::QueuedConnection;
1084 
1085  QMetaObject::invokeMethod(m_container,"onThreadAlert",
1086  connection,
1087  Q_ARG(QString, signalID),
1088  Q_ARG(QString, strPayload),
1089  Q_ARG(int, static_cast<int>(conversion)));
1090 
1091  zDebug() << "SENT ALERT id=" << signalID << ", payload=" << payload;
1092 
1094 }
1095 
1097 {
1099 
1100  if(isInMainThread())
1101  {
1102  zDebug() << "ZblApp calling QCoreApplication::quit()...";
1103 
1104  QMetaObject::invokeMethod(m_engine,"quit",
1105  Qt::QueuedConnection);
1106 
1107  m_engine->deleteLater();
1108 
1109  return;
1110  }
1111 
1112  if(!m_container)
1113  {
1114  zWarning() << "ZblApp::quit - Programming error! Background ZblApp "
1115  "expects it's container to be a ZScriptThread object.";
1116 
1117  return;
1118  }
1119 
1120  zDebug() << "ZblApp quitting thread: " << getCurrentThreadAddress();
1121 
1122  QMetaObject::invokeMethod(m_container,"quit",
1123  Qt::QueuedConnection);
1124 
1126 }
1127 
1128 
1129 void ZblApp::exitApp(int returnCode)
1130 {
1132 
1133  if(isInMainThread())
1134  {
1135  zDebug() << "ZblApp calling QCoreApplication::exit()...";
1136 
1137  m_engine->deleteLater();
1138 
1139  QCoreApplication::exit(returnCode);
1140  }
1141  else
1142  {
1143  zWarning() << "ZblApp::exit - Programming ERROR: exit() method must be called from main thread.";
1144  }
1145 
1147 }
1148 
1149 
1150 void ZblApp::onDestroyed(QObject* obj)
1151 {
1152  zDebug() << "ZblApp::onDestroyed";
1153 }
1154 
1155 } // Zbl
Q_INVOKABLE QObject * newTextStream(const QString &text)
Returns a new ZTextStream object for reading and writing text in strings.
Definition: ZblApp.cpp:476
void stopAllTimers()
Stops all existing timers that were started with ZblApp::startTimerInterval() and destroys them...
Definition: ZblApp.cpp:917
Q_INVOKABLE QObject * newMessageQueue()
Returns a new ZMessageQueue object for passing messages between components.
Definition: ZblApp.cpp:541
This class supports streaming of text and binary data.
Definition: ZByteArray.h:41
Q_INVOKABLE QVariant getAppData(int dataKey)
Allows background threads to obtain application object data.
Definition: ZblApp.cpp:399
int startTimerInterval(QJSValue timerFunction, QJSValue timerArgument, int milliseconds)
Calls the specified javascript function periodically at the specified interval.
Definition: ZblApp.cpp:860
This class wraps QFileSystemWatcher and adds path reference counting.
Q_INVOKABLE void status(const QString &text)
Sends status information to Zuble&#39;s main status text feed.
Definition: ZblApp.cpp:385
QML/Javascript wrapper for the QProcess class, allows QML programs to spawn and communicate with a ba...
Definition: ZProcess.h:20
A Javascript dictionary object.
Definition: ZMap.h:40
Q_INVOKABLE QObject * newSettingsFile(const QString &filePath)
Returns a new ZSettings object representing a JSON file in the specified file location.
Definition: ZblApp.cpp:619
Q_INVOKABLE QObject * newThread()
Returns a new ZScriptThread object.
Definition: ZblApp.cpp:644
static QObject * getSingletonType(QQmlEngine *engine, QJSEngine *scriptEngine)
Obtains an new instance of this class. This is called by the QML engine to create the ZblApp object f...
Definition: ZblApp.cpp:161
static QThreadStorage< AppPtr * > m_zApp
ZblApp is a thread singleton - ie one ZblApp object exists per Zuble thread. This variable holds a po...
Definition: ZblApp.h:1263
Q_INVOKABLE QVariant getAppName()
Obtains Zuble application name.
Definition: ZblApp.cpp:428
Q_INVOKABLE QObject * newProcess()
Returns a new ZProcess object for creating an operating system process.
Definition: ZblApp.cpp:555
static QString getPathScheme(const QString &path)
Obtains the scheme part of a URL path.
Q_INVOKABLE QStringList getApplicationArguments()
obtain a string array containing arguments passed on the command line
Definition: ZblApp.cpp:738
static ZblApp & zInstance()
Obtains a reference to the ZblApp object for the current thread.
Definition: ZblApp.cpp:96
Q_INVOKABLE QObject * newSchemaValidator()
Returns a new ZSchemaValidator object for validating XML documents against XML schemas.
Definition: ZblApp.cpp:591
#define zApp
Definition: ZApplication.h:37
Access and manipulate file directories. This class is a Javascript wrapper for QDir objects...
Definition: ZDir.h:42
Q_INVOKABLE QObject * getLogBuffer()
Obtain the log buffer data model.
Q_INVOKABLE QString resolveAppPath(const QString &path, bool includeUrlScheme=true)
Converts Zuble application paths into canonical file paths. Zuble applicaiton paths are prefixed with...
Definition: ZblApp.cpp:805
void setError(QJSValue theObject)
Sets the internal Javascript Error object.
Definition: ZblApp.cpp:269
QVariant returnAnException()
test method to return a javascript Error object
Definition: ZblApp.cpp:258
A mechanism for safely holding a ZblApp object pointer in thread local storage.
Definition: ZblApp.h:118
A QML type that manages reading JSON formatted Zuble log files. QML programs create using Zbl...
Definition: ZLogReader.h:62
void printErr(const QString &text, bool newLine=true)
Writes text to stderr.
Definition: ZblApp.cpp:504
Q_INVOKABLE bool isResourcePath(const QString &path)
Determine if the specified path refers to a an object inside a Qt binary resource.
Definition: ZblApp.cpp:833
virtual ~ZblApp()
Definition: ZblApp.cpp:89
void throwAnException()
test method to throw a ZblException
Definition: ZblApp.cpp:210
void throwDeeperException()
test method to throw a ZblException
Definition: ZblApp.cpp:215
#define Z_FAC_JS
Definition: zglobal.h:123
QJSEngine * m_engine
The QJSEngine that owns the javascript context for this ZblApp object.
Definition: ZblApp.h:1275
void collectGarbage()
Instructs the javascript engine to garbage collect memory as soon as possible.
Definition: ZblApp.cpp:978
Q_INVOKABLE QObject * newMailslot()
Returns a new ZMailslot object for passing messages between components.
Definition: ZblApp.cpp:548
This class provides a means of directing a text stream to listeners.
Definition: ZTextFeed.h:50
enum Zbl::ZScriptThread::alertConversion AlertConversion
Q_INVOKABLE QString resolveHomePath(const QString &path, bool includeUrlScheme=true)
Converts Zuble home paths into canonical file paths. Zuble home paths are prefixed with "home://" and...
Definition: ZblApp.cpp:811
QString getRootPath()
Obtains the canonical path to the Zuble application&#39;s root directory.
Definition: ZblApp.cpp:823
#define zCog
Definition: ZblCog.h:34
Q_INVOKABLE void addLibraryPath(const QString &path)
Add the specified path to the beginning of the library search path.
Definition: ZblApp.cpp:782
Q_INVOKABLE bool isInterruptRequested()
Calls QThread::isInterruptRequested() on the current thread. Does nothing and returns false if curren...
Definition: ZblApp.cpp:754
Q_INVOKABLE QObject * getLogBuffer()
Obtain Zuble&#39;s log buffer data model.
Definition: ZblApp.cpp:195
Q_INVOKABLE QString bundleMetadata(const QString &bundleID)
Returns the Zuble settings metadata text for the specified settings bundle ID.
Definition: ZblApp.cpp:851
#define ZBL_REGISTER_LOGGED_OBJECT
Definition: zglobal.h:104
Q_INVOKABLE QObject * newTableModel()
Returns a new ZTableModel object for passing variant data to QML views.
Definition: ZblApp.cpp:534
QJSEngine & engine()
Returns the QJSEngine object associated with this object.
Definition: ZblApp.h:1312
Q_INVOKABLE bool isInMainThread()
Determine if the caller is currently executing in the Qt&#39;s main GUI thread.
Definition: ZblApp.cpp:450
Q_INVOKABLE bool mapPluginResources(const QString &fileName, bool qmlregister=false)
Make a plugin&#39;s binary resource files known to Zuble so they can be loaded into QML by calling Zbl...
Definition: ZblApp.cpp:729
Q_INVOKABLE bool mapResource(const QString &uri, int versionMajor, int versionMinor, const QString &fileName)
Called by Javascript programs to make binary resource files known to Zuble so they can be loaded into...
Definition: ZblApp.cpp:706
void send(const QString &text)
Definition: ZTextFeed.cpp:46
Q_INVOKABLE QObject * newScopedMap()
Returns a new ZScopedMap object for mapping arbitrary strings to javascript values.
Definition: ZblApp.cpp:576
Q_INVOKABLE bool registerResource(const QString &uri, int versionMajor, int versionMinor)
Makes a Zuble resource file known to QML and background javascript programs.
Definition: ZblApp.cpp:719
static const QString m_appPathPrefix
URL scheme used to specify Zuble app directory location: "zbl://".
Definition: ZApplication.h:340
Q_INVOKABLE QObject * newDir()
Returns a new ZDir object for reading and manipulating file directories.
Definition: ZblApp.cpp:455
QSharedPointer< QString > ZqStringPtr
Definition: zglobal.h:165
A message queue that decouples sending and processing of messages.
Definition: ZMessageQueue.h:54
A thread class to support Zuble&#39;s background Javascript processing.
Definition: ZScriptThread.h:62
bool isError()
Determines if an error state exists for this thread.
Definition: ZblApp.cpp:291
ZblApp(QJSEngine *scriptEngine, ZScriptThread *container=nullptr, QObject *parent=nullptr)
Definition: ZblApp.cpp:65
factoryMap m_factories
Maps sprocket plugin uri&#39;s to ZblFactory objects.
Definition: ZblApp.h:1307
Q_INVOKABLE QObject * bundleSettings(const QString &bundleID)
Returns a new ZSettings object representing a JSON file in the location specified by the settings bun...
Definition: ZblApp.cpp:651
A two-way messaging communication channel that supports buffered message streams to multiple end poin...
Definition: ZMailbox.h:52
A javascript wrapper for QFile.
Definition: ZFile.h:53
static QString getMainQmlPath()
Obtains the canonical path to the Zuble application&#39;s main QML file.
QString errorMessage()
Returns a formatted error message from this thread&#39;s ZblThreadErr object.
static QVariant m_tags
A QVariantMap used to pass ZApplication enumeration values to Javascript programs.
Definition: ZblApp.h:1293
static QString variantToJson(QVariant &var)
Converts QVariant to json string.
static const QString m_homePathPrefix
URL scheme used to specify user&#39;s home directory location: "home://".
Definition: ZApplication.h:346
static QReadWriteLock m_lock
A lock for multi-threaded data access.
Definition: ZblApp.h:1268
Q_INVOKABLE QObject * newMap()
Returns a new ZMap object for mapping arbitrary strings to javascript values.
Definition: ZblApp.cpp:569
QString readLine()
Reads a line of text from stdin.
Definition: ZblApp.cpp:485
timerHash m_scriptTimers
A hash of javascript function/argument pairs keyed by timer ID.
Definition: ZblApp.h:1300
Q_INVOKABLE QStringList getSystemEnvironment()
obtain a string array containing the process system environment
Definition: ZblApp.cpp:745
Q_INVOKABLE QObject * newMailbox()
Returns a new ZMailbox object for passing messages between components.
Definition: ZblApp.cpp:562
Q_INVOKABLE QObject * newObject(const QString &sprocketUri, const QString &objectName)
Returns a new Zuble sprocket object from the specified sprocket extension plugin. ...
Definition: ZblApp.cpp:660
Definition: ZAndGate.cpp:6
static ZblLogManager & zInstance()
Obtain a reference to Zuble&#39;s log manager object.
static int versionMinor
Definition: main.cpp:60
Q_INVOKABLE QObject * newLogReader()
Returns a new ZLogReader object for reading Zuble log files.
Definition: ZblApp.cpp:583
QVariant getAppTags()
Obtains a javascript dictionary object that maps application data item names to integer values...
Definition: ZblApp.cpp:156
#define ZBL_SLOT_BEGIN_TRY
Definition: zglobal.h:128
void clearError()
Clears an existing error condition for this thread.
Definition: ZblApp.cpp:298
Q_INVOKABLE void sleep(unsigned long milliseconds)
Blocks the current thread for the specified number of milliseconds.
Definition: ZblApp.cpp:938
#define ZBL_DEFINE_LOGGED_OBJECT(class_name)
Definition: zglobal.h:99
void stopTimerInterval(int timerID)
Stops the specified timer.
Definition: ZblApp.cpp:887
Q_INVOKABLE QObject * newFile()
Returns a new ZFile object for reading, writing and manipulating files.
Definition: ZblApp.cpp:462
static int versionMajor
Definition: main.cpp:59
#define zWarning()
Definition: zglobal.h:111
#define zThreadErr
where does this show up?
Definition: ZblThreadErr.h:39
This two dimensional table model is used to store and manipulate data.
Definition: ZTableModel.h:96
Q_INVOKABLE QObject * newXmlQuery()
Returns a new ZxQuery object.
Definition: ZblApp.cpp:637
Q_INVOKABLE QObject * newAppSettings(int scope, const QString &application, const QString &organization)
Returns a new ZSettings object representing a JSON file in the platform-specific configuration file l...
Definition: ZblApp.cpp:598
#define ZBL_SLOT_END_VOID(facility, code, error_message)
Definition: zglobal.h:134
The primary QML API to the Zuble plugin library. Zuble applications access this object through the ja...
Definition: ZblApp.h:81
Q_INVOKABLE QObject * getLogRules()
Obtain Zuble&#39;s log category rules data model.
Definition: ZblApp.cpp:200
ZScriptThread * m_container
The ZScriptThread object that represents the thread in which ZblApp is running.
Definition: ZblApp.h:1286
Q_INVOKABLE QString bundleMetapath(const QString &bundleID)
Returns the path to the Zuble settings metadata file for the specified settings bundle ID...
Definition: ZblApp.cpp:843
void statusAvailable(const QString &text)
Sent when text for the main applicaiton status is available. Connect to this signal to display status...
#define zDebug()
Definition: zglobal.h:113
Q_INVOKABLE void sleepEvents(unsigned long milliseconds)
Blocks the current thread for the specified number of milliseconds while processing events...
Definition: ZblApp.cpp:947
Wraps the QSettings class and implements a JSON-based backend for storing the settings data...
Definition: ZSettings.h:44
A two-way buffered message stream with attached user-defined data cache.
Definition: ZMailslot.h:50
QJSValue error()
returns the internal Error object for this thread saved in thread local storage.
Definition: ZblApp.cpp:306
static QString getObjectThreadAddress(QObject *object)
Returns the human-readable memory address of the specified object&#39;s thread.
const char * what() const
static int registerSingletonType()
Registers this object with QML as a singleton type.
Definition: ZblApp.cpp:174
QJSValue convertEvaluateError(const QJSValue &evaluateError)
Javascript syntax errors appear to be passing back a string object with the QJSValue error bit set...
Definition: ZblApp.cpp:317
void catchDeeperException()
test method to throw and then catch a ZblException
Definition: ZblApp.cpp:224
void createTags()
Create the m_tag object that presents a Javascript interface to ZApplication enumeration values...
Definition: ZblApp.cpp:105
static QString resolvePath(const QString &path, bool includeUrlScheme=true)
Converts relative file paths into canonical file paths. Paths prefixed with prefix are mapped relativ...
#define cStr(qStr)
Definition: zglobal.h:49
static QString getBundleMetadata(const QString &id)
Definition: ZSettings.cpp:721
void onDestroyed(QObject *obj)
Experimental, may be deprecated.
Definition: ZblApp.cpp:1150
Q_INVOKABLE QObject * newByteArray()
Returns a new ZByteArray object for reading and writing byte arrays.
Definition: ZblApp.cpp:469
This inner class allows ZblApp to store javascript function pointers that are used to provide timer s...
Definition: ZblApp.h:91
Q_INVOKABLE QString getCurrentThreadAddress()
Returns the human-readable memory address of the current thread.
Definition: ZblApp.cpp:765
virtual ZBL_DECLARE_LOGGED_OBJECT void timerEvent(QTimerEvent *event)
Overloaded timer function to implement startTimerInterval. This method calls the specified timer&#39;s ja...
Definition: ZblApp.cpp:898
Q_INVOKABLE QObject * newFileSystemWatcher()
Returns a new ZFileSystemWatcher object for detecting changes in files and directories.
Definition: ZblApp.cpp:526
Zuble&#39;s Qt Exception Object.
Definition: ZblException.h:45
static QString getCurrentThreadAddress()
Returns the human-readable memory address of the current thread.
A hierarchical map object for creating scopes.
Definition: ZScopedMap.h:36
An object factory that creates new instances of objects defined by a Zuble sprocket. Used primarily to construct sprocket objects in Zuble background threads.
Definition: ZblFactory.h:54
QString getMainQmlPath()
Obtains the canonical path to the Zuble application&#39;s main QML file.
Definition: ZblApp.cpp:828
static QString getRootPath()
Obtains the canonical path to the Zuble application&#39;s root directory.
static ZSettings * getBundleSettings(const QString &id)
Returns the ZSettings object for the specified settings bundle ID. Caller takes ownership of the ZSet...
Definition: ZSettings.cpp:645
This class provides access to the QXMLQuery class from Javascript.
Definition: ZxQuery.h:48
Q_INVOKABLE QString getObjectThreadAddress(QObject *object)
Returns the human-readable memory address of the specified object&#39;s thread.
Definition: ZblApp.cpp:774
static QString getBundleMetapath(const QString &id)
Definition: ZSettings.cpp:713
void throwException()
test method to throw an exception
Definition: ZblApp.cpp:241
QList< int > timerKeys
Definition: ZblApp.h:106
Q_INVOKABLE QString resolvePath(const QString &path, bool includeUrlScheme=true)
Converts Zuble paths into canonical file paths. Zuble home paths are prefixed with "home://" and are ...
Definition: ZblApp.cpp:818
void quit()
Calls quit() on the owning ZScriptThread object.
Definition: ZblApp.cpp:1096
This class wraps the QXmlSchemaValidator and QXmlSchema classes.
Q_INVOKABLE bool import(const QString &sprocketUri, int versionMajor, int versionMinor)
Makes a Zuble sprocket extension plugin available to background javascript threads.
Definition: ZblApp.cpp:682
Q_INVOKABLE QObject * newDataStream(QObject *byteArray)
Returns a new ZDataStream object for reading and writing data in byte arrays.
Definition: ZblApp.cpp:515
return result toVariant()
void print(const QString &text, bool newLine=true)
Writes text to stdout.
Definition: ZblApp.cpp:494
#define ZBL_SLOT_END_RETURN(return_success, return_failed, facility, code, error_message)
Definition: zglobal.h:141
void alert(const QString signalID, QVariant payload, bool wait=false)
Call this method to send an alert signal to the owning ZScriptThread object.
Definition: ZblApp.cpp:986
void exit(int returnCode)
Exits the thread. When called by the main thread exits the application.
void exitApp(int returnCode=0)
Calls exit() on ??? the owning ZScriptThread object.
Definition: ZblApp.cpp:1129
QVariant include(const QString &fileUrl)
Loads the specified javascript file and executes it in the current javascript context.
Definition: ZblApp.cpp:331
Q_INVOKABLE QObject * getLogRules()
Obtain the logging rules data model.