--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/vsexplorer/vsexplorer.cpp Wed Aug 25 15:49:42 2010 +0300
@@ -0,0 +1,835 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QObject>
+#include <QTextStream>
+#include <QFile>
+#include <QSocketNotifier>
+#include <cstdio>
+#include <cstdlib>
+#include <QMap>
+#include <QDir>
+#include <QStringList>
+#include <QSet>
+
+#include <qvaluespace.h>
+#include <qvaluespacesubscriber.h>
+#include <qvaluespacepublisher.h>
+
+#ifdef USE_READLINE
+#include <stdio.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <QThread>
+#include <QMutex>
+#include <QEvent>
+#include <QWaitCondition>
+#include <pthread.h>
+#endif
+
+#ifdef Q_OS_WIN
+#include <QThread>
+#endif
+
+QTM_USE_NAMESPACE
+
+static bool terminateRequested = false;
+
+class VSExplorer : public QObject
+{
+Q_OBJECT
+public:
+ VSExplorer();
+
+ void printError();
+ void printHelp();
+ void ls();
+ void dump();
+ void pwdCmd();
+ void ls(const QString &abs, bool);
+ void subscribe();
+ void unsubscribe();
+ void quit();
+ void suppress();
+ void listwatchers();
+ void watch(const QString &);
+ void unwatch(const QString &);
+ void set(const QString &, const QString &);
+ void clear(const QString &);
+ void subscriptions();
+
+ QString path() const
+ {
+ return pwd.path();
+ }
+
+public slots:
+ void processLine(const QString &);
+
+private slots:
+ void contentsChanged();
+ void interestChanged(const QString &attribute, bool interested);
+
+private:
+ void lsPath(QValueSpaceSubscriber *, int = 0, bool = false);
+
+ bool isSuppress;
+ QValueSpaceSubscriber pwd;
+ QValueSpacePublisher prov;
+ QSet<QValueSpaceSubscriber *> subs;
+ QSet<QValueSpacePublisher *> watchers;
+};
+static VSExplorer * vse = 0;
+
+class LineInput :
+#if defined(USE_READLINE) || defined(Q_OS_WIN)
+ public QThread
+#else
+ public QObject
+#endif
+{
+ Q_OBJECT
+
+public:
+ LineInput();
+
+signals:
+ void line(const QString &);
+
+#if defined(USE_READLINE)
+protected:
+ virtual bool event(QEvent *);
+ virtual void run();
+
+private:
+ QMutex mutex;
+ QWaitCondition wait;
+#elif defined(Q_OS_WIN)
+protected:
+ void run();
+
+private:
+ QFile ts;
+#else
+private slots:
+ void readyRead();
+
+private:
+ QFile ts;
+ QSocketNotifier *sock;
+#endif
+};
+
+VSExplorer::VSExplorer()
+: isSuppress(false), pwd(QLatin1String("/")), prov(QLatin1String("/"))
+{
+}
+
+void VSExplorer::interestChanged(const QString &attribute, bool interested)
+{
+ Q_ASSERT(sender());
+
+ if (!isSuppress) {
+ QValueSpacePublisher *obj = static_cast<QValueSpacePublisher *>(sender());
+ fprintf(stdout, "\nInterest Changed: %s ... %s %d\n",
+ qPrintable(obj->path()), qPrintable(attribute), interested);
+ }
+}
+
+static QString variantToString( const QVariant& var )
+{
+ if ( var.type() == QVariant::StringList )
+ return var.toStringList().join(QLatin1String(", "));
+ else
+ return var.toString();
+}
+
+void VSExplorer::contentsChanged()
+{
+ Q_ASSERT(sender());
+
+ if(!isSuppress) {
+ QValueSpaceSubscriber *subscriber = static_cast<QValueSpaceSubscriber *>(sender());
+ fprintf(stdout, "\nChanged: %s\n", subscriber->path().toAscii().constData());
+ }
+}
+
+void VSExplorer::printError()
+{
+ fprintf(stdout, "Come again?\n");
+ fflush(stdout);
+}
+
+void VSExplorer::printHelp()
+{
+ fprintf(stdout, "help/?: Print this message\n");
+ fprintf(stdout, "quit: Exit VSExplorer\n");
+ fprintf(stdout, "ls: List contents of path\n");
+ fprintf(stdout, "pwd: Print current working directory\n");
+ fprintf(stdout, "subscribe: Subscribe to path\n");
+ fprintf(stdout, "unsubscribe: Unsubscribe from path\n");
+ fprintf(stdout, "suppress: Toggle suppression of publish messages\n");
+ fprintf(stdout, "subscriptions: List current subscriptions\n");
+ fprintf(stdout, "set <key> <value>: Set app layer<key> to <value>\n");
+ fprintf(stdout, "clear <key>: Clear app layer <key>\n");
+ fprintf(stdout, "cd <path>: Change working path\n");
+ fprintf(stdout, "watch <path>: Add a watch for the path\n");
+ fprintf(stdout, "unwatch <path>: Remove a watch for the path\n");
+ fprintf(stdout, "watchers: List paths for which a watch is active\n");
+ fflush(stdout);
+}
+
+void VSExplorer::ls()
+{
+ lsPath(&pwd);
+ fflush(stdout);
+}
+
+void VSExplorer::ls(const QString &abs, bool all)
+{
+ QValueSpaceSubscriber subscriber(abs);
+ lsPath(&subscriber, 0, all);
+ fflush(stdout);
+}
+
+
+void VSExplorer::lsPath(QValueSpaceSubscriber * p, int indent, bool showHidden)
+{
+ QVariant var = p->value();
+ bool spaceRequired = false;
+ if(!var.isNull()) {
+ fprintf(stdout, "Value: '%s' (%s)\n",
+ variantToString(var).toAscii().constData(), var.typeName());
+ spaceRequired = true;
+ }
+
+ foreach (const QString &path, p->subPaths()) {
+ if (!showHidden && path.startsWith(QLatin1Char('.')))
+ continue;
+
+ if(spaceRequired) {
+ fprintf(stdout, "\n");
+ spaceRequired = false;
+ }
+ for(int ii = 0; ii < indent; ++ii) fprintf(stdout, "\t");
+ fprintf(stdout, "%s/", path.toAscii().constData());
+ QVariant value = p->value(path);
+ if(!value.isNull()) {
+ if(path.length() < 30) {
+ for(int ii = 0; ii < 30 - path.length(); ++ii)
+ fprintf(stdout, " ");
+ } else {
+ fprintf(stdout, " ");
+ }
+
+ fprintf(stdout, " '%s' (%s)",
+ variantToString(value).toAscii().constData(), value.typeName());
+ }
+ fprintf(stdout, "\n");
+ }
+}
+
+void VSExplorer::listwatchers()
+{
+ if(watchers.isEmpty()) {
+ fprintf(stdout, "No watchers.\n");
+ } else {
+ fprintf(stdout, "Current watchers:\n");
+ foreach (QValueSpacePublisher *obj, watchers)
+ fprintf(stdout, "\t%s\n", obj->path().toAscii().constData());
+ }
+
+ fflush(stdout);
+}
+
+void VSExplorer::subscriptions()
+{
+ if(subs.isEmpty()) {
+ fprintf(stdout, "No subscriptions.\n");
+ } else {
+ fprintf(stdout, "Current subscriptions:\n");
+
+ foreach (QValueSpaceSubscriber *subscriber, subs)
+ fprintf(stdout, "\t%s\n", subscriber->path().toAscii().constData());
+ }
+
+ fflush(stdout);
+}
+
+void VSExplorer::subscribe()
+{
+ QValueSpaceSubscriber *subscriber = new QValueSpaceSubscriber;
+ subscriber->setPath(&pwd);
+ QObject::connect(subscriber, SIGNAL(contentsChanged()),
+ this, SLOT(contentsChanged()));
+ subs.insert(subscriber);
+
+ fprintf(stdout, "OK\n");
+ fflush(stdout);
+}
+
+void VSExplorer::unsubscribe()
+{
+ foreach (QValueSpaceSubscriber *subscriber, subs) {
+ if (subscriber->path() == pwd.path()) {
+ subs.remove(subscriber);
+ delete subscriber;
+ fprintf(stdout, "OK\n");
+ fflush(stdout);
+ return;
+ }
+ }
+
+ fprintf(stdout, "No subscription.\n");
+ fflush(stdout);
+}
+
+void VSExplorer::quit()
+{
+ fprintf(stdout, "Bye, bye.\n");
+ fflush(stdout);
+ terminateRequested = true;
+}
+
+void VSExplorer::watch(const QString &path)
+{
+ foreach (QValueSpacePublisher *obj, watchers) {
+ if (obj->path() == path)
+ return;
+ }
+
+ QValueSpacePublisher * newObject = new QValueSpacePublisher(path);
+ watchers.insert(newObject);
+ QObject::connect(newObject, SIGNAL(interestChanged(QString,bool)),
+ this, SLOT(interestChanged(QString,bool)));
+}
+
+void VSExplorer::unwatch(const QString &path)
+{
+ foreach (QValueSpacePublisher *obj, watchers) {
+ if (obj->path() == path) {
+ watchers.remove(obj);
+ delete obj;
+ return;
+ }
+ }
+}
+
+void VSExplorer::suppress()
+{
+ if (isSuppress) {
+ isSuppress = false;
+ fprintf(stdout, "Suppression off.\n");
+ } else {
+ isSuppress = true;
+ fprintf(stdout, "Suppression on.\n");
+ }
+ fflush(stdout);
+}
+
+void VSExplorer::set(const QString &name, const QString &value)
+{
+ if (name.startsWith(QLatin1Char('/')))
+ prov.setValue(name, value);
+ else if (pwd.path().endsWith(QLatin1Char('/')))
+ prov.setValue(pwd.path() + name, value);
+ else
+ prov.setValue(pwd.path() + QLatin1Char('/') + name, value);
+}
+
+void VSExplorer::clear(const QString &name)
+{
+ if (name.startsWith(QLatin1Char('/')))
+ prov.resetValue(name);
+ else if (pwd.path().endsWith(QLatin1Char('/')))
+ prov.resetValue(pwd.path() + name);
+ else
+ prov.resetValue(pwd.path() + QLatin1Char('/') + name);
+}
+
+void VSExplorer::processLine(const QString &line)
+{
+ QStringList cmds = line.trimmed().split(QLatin1Char(' '));
+
+ if(cmds.isEmpty()) {
+ return;
+ }
+
+ const QString & cmd = cmds.at(0);
+ if (cmd.isEmpty()) {
+
+ } else if (cmd == QLatin1String("ls") && 1 == cmds.count()) {
+ ls();
+ } else if (cmd == QLatin1String("dump")) {
+ dump();
+ } else if (cmd == QLatin1String("pwd")) {
+ pwdCmd();
+ } else if (cmd == QLatin1String("ls") && 2 <= cmds.count()) {
+ QStringList newCmds = cmds;
+ newCmds.removeFirst();
+ bool lsAll = false;
+ if (newCmds.first() == QLatin1String("-a")) {
+ lsAll = true;
+ newCmds.removeFirst();
+ }
+ QString newPath = newCmds.join(QLatin1String(" "));
+ if (newPath.startsWith(QLatin1Char('"')) && newPath.endsWith(QLatin1Char('"'))) {
+ newPath = newPath.mid(1);
+ newPath = newPath.left(newPath.length() - 1);
+ }
+ if(newPath.isEmpty()) {
+ ls(pwd.path(), lsAll);
+ } else if (newPath.startsWith(QLatin1Char('/'))) {
+ ls(newPath, lsAll);
+ } else {
+ QString oldPath = pwd.path();
+ if (!oldPath.endsWith(QLatin1Char('/')))
+ oldPath.append(QLatin1Char('/'));
+ oldPath.append(newPath);
+ oldPath = QDir::cleanPath(oldPath);
+ ls(oldPath, lsAll);
+ }
+
+ } else if (cmd == QLatin1String("cd") && 2 <= cmds.count()) {
+ QStringList newCmds = cmds;
+ newCmds.removeFirst();
+ QString newPath = newCmds.join(QLatin1String(" "));
+ if (newPath.startsWith(QLatin1Char('"')) && newPath.endsWith(QLatin1Char('"'))) {
+ newPath = newPath.mid(1);
+ newPath = newPath.left(newPath.length() - 1);
+ }
+ if (newPath.startsWith(QLatin1Char('/'))) {
+ pwd.setPath(newPath);
+ } else {
+ QString oldPath = pwd.path();
+ if (!oldPath.endsWith(QLatin1Char('/')))
+ oldPath.append(QLatin1Char('/'));
+ oldPath.append(newPath);
+ oldPath = QDir::cleanPath(oldPath);
+ pwd.setPath(oldPath);
+ }
+ } else if (cmd == QLatin1String("unwatch") && 2 <= cmds.count()) {
+ QStringList newCmds = cmds;
+ newCmds.removeFirst();
+ QString newPath = newCmds.join(QLatin1String(" "));
+ QString finalPath;
+ if (newPath.startsWith(QLatin1Char('"')) && newPath.endsWith(QLatin1Char('"'))) {
+ newPath = newPath.mid(1);
+ newPath = newPath.left(newPath.length() - 1);
+ }
+ if (newPath.startsWith(QLatin1Char('/'))) {
+ finalPath = QValueSpaceSubscriber(newPath).path();
+ } else {
+ QString oldPath = pwd.path();
+ if (!oldPath.endsWith(QLatin1Char('/')))
+ oldPath.append(QLatin1Char('/'));
+ oldPath.append(newPath);
+ oldPath = QDir::cleanPath(oldPath);
+ finalPath = QValueSpaceSubscriber(oldPath).path();
+ }
+ unwatch(finalPath);
+ } else if (cmd == QLatin1String("watch") && 2 <= cmds.count()) {
+ QStringList newCmds = cmds;
+ newCmds.removeFirst();
+ QString newPath = newCmds.join(QLatin1String(" "));
+ QString finalPath;
+ if (newPath.startsWith(QLatin1Char('"')) && newPath.endsWith(QLatin1Char('"'))) {
+ newPath = newPath.mid(1);
+ newPath = newPath.left(newPath.length() - 1);
+ }
+ if (newPath.startsWith(QLatin1Char('/'))) {
+ finalPath = QValueSpaceSubscriber(newPath).path();
+ } else {
+ QString oldPath = pwd.path();
+ if (!oldPath.endsWith(QLatin1Char('/')))
+ oldPath.append(QLatin1Char('/'));
+ oldPath.append(newPath);
+ oldPath = QDir::cleanPath(oldPath);
+ finalPath = QValueSpaceSubscriber(oldPath).path();
+ }
+ watch(finalPath);
+ } else if (cmd == QLatin1String("set") && 3 == cmds.count()) {
+ set(cmds.at(1).trimmed(), cmds.at(2).trimmed());
+ } else if (cmd == QLatin1String("clear") && 2 == cmds.count()) {
+ clear(cmds.at(1).trimmed());
+ } else if ((cmd == QLatin1String("subscribe") || cmd == QLatin1String("sub")) &&
+ 1 == cmds.count()) {
+ subscribe();
+ } else if ((cmd == QLatin1String("unsubscribe") || cmd == QLatin1String("unsub")) &&
+ 1 == cmds.count()) {
+ unsubscribe();
+ } else if ((cmd == QLatin1String("?") || cmd == QLatin1String("help")) && 1 == cmds.count()) {
+ printHelp();
+ } else if ((cmd == QLatin1String("quit") || cmd == QLatin1String("exit")) &&
+ 1 == cmds.count()) {
+ quit();
+ } else if (cmd == QLatin1String("suppress") && 1 == cmds.count()) {
+ suppress();
+ } else if (cmd == QLatin1String("watchers") && 1 == cmds.count()) {
+ listwatchers();
+ } else if (cmd == QLatin1String("subscriptions") && 1 == cmds.count()) {
+ subscriptions();
+ } else {
+ printError();
+ }
+}
+
+#ifdef USE_READLINE
+extern "C" {
+ char * item_generator(const char * text, int num);
+ char * command_generator(const char * text, int num);
+ char ** item_completion(const char * text, int start, int end);
+}
+#endif
+
+LineInput::LineInput()
+{
+#if defined(USE_READLINE)
+ rl_completion_append_character = '\0';
+ rl_attempted_completion_function = item_completion;
+ rl_completer_quote_characters = "\"";
+ rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&(";
+ rl_filename_quote_characters = " ";
+ QObject::connect(this, SIGNAL(finished()), qApp, SLOT(quit()));
+ QObject::connect(this, SIGNAL(terminated()), qApp, SLOT(quit()));
+ start();
+#elif defined(Q_OS_WIN)
+ ts.open(stdin, QIODevice::ReadOnly);
+ QObject::connect(this, SIGNAL(finished()), qApp, SLOT(quit()));
+ QObject::connect(this, SIGNAL(terminated()), qApp, SLOT(quit()));
+ start();
+
+ fprintf(stdout, "%s > ", vse->path().constData());
+ fflush(stdout);
+#else
+ ts.open(stdin, QIODevice::ReadOnly);
+ sock = new QSocketNotifier(ts.handle(), QSocketNotifier::Read, this);
+ QObject::connect(sock, SIGNAL(activated(int)), this, SLOT(readyRead()));
+
+ fprintf(stdout, "%s > ", qPrintable(vse->path()));
+ fflush(stdout);
+#endif
+}
+
+#if !defined(USE_READLINE) && !defined(Q_OS_WIN)
+void LineInput::readyRead()
+{
+ QByteArray line = ts.readLine();
+
+ emit this->line(QString::fromLocal8Bit(line));
+
+ if(terminateRequested)
+ exit(0);
+
+ fprintf(stdout, "%s > ", qPrintable(vse->path()));
+ fflush(stdout);
+}
+#endif
+
+#ifdef USE_READLINE
+#define TEXTEVENTTYPE (QEvent::User + 10)
+struct TextEvent : public QEvent
+{
+ TextEvent(char *line)
+ : QEvent((QEvent::Type)TEXTEVENTTYPE), data(line) {}
+
+ char * data;
+};
+
+bool LineInput::event(QEvent *e)
+{
+ if(e->type() == TEXTEVENTTYPE) {
+ TextEvent * te = static_cast<TextEvent *>(e);
+ emit line(te->data);
+ free(te->data);
+
+ mutex.lock();
+ wait.wakeAll();
+ mutex.unlock();
+
+ return true;
+ } else {
+ return QThread::event(e);
+ }
+}
+
+char ** item_completion(const char * text, int start, int end)
+{
+ char ** matches = (char **)NULL;
+ const char * non_space = text;
+ while(*non_space == ' ') ++non_space;
+
+
+ if(start == non_space - text)
+ matches = rl_completion_matches(text, command_generator);
+ else
+ matches = rl_completion_matches(text, item_generator);
+
+ rl_attempted_completion_over = 1;
+ return (matches);
+}
+
+char * command_generator(const char * t, int num)
+{
+ static QList<QByteArray> children;
+
+ if(0 == num) {
+ children.clear();
+
+ // Command
+ static const char * commands[] = { "help ",
+ "quit ",
+ "pwd ",
+ "ls ",
+ "subscribe ",
+ "unsubscribe ",
+ "suppress ",
+ "subscriptions ",
+ "set ",
+ "clear ",
+ "cd " };
+
+ for(unsigned int ii = 0; ii < sizeof(commands) / sizeof(char *); ++ii)
+ if(0 == ::strncmp(commands[ii], t, strlen(t)))
+ children.append(commands[ii]);
+ }
+
+ if(children.isEmpty())
+ return 0;
+
+ char * rv = (char *)malloc(children.at(0).length() + 1);
+ ::memcpy(rv, children.at(0).constData(), children.at(0).length() + 1);
+ children.removeFirst();
+
+ return rv;
+}
+
+char * item_generator(const char * t, int num)
+{
+ static QStringList children;
+
+ rl_filename_completion_desired = 1;
+ rl_filename_quoting_desired = 1;
+ if(0 == num) {
+
+ children.clear();
+
+ // Path
+ QString text = QString::fromLocal8Bit(t);
+ QString textExt;
+ QString textBase;
+
+ int last = text.lastIndexOf('/');
+ if(-1 == last) {
+ textExt = text;
+ } else {
+ textBase = text.left(last);
+ textExt = text.mid(last + 1);
+ }
+
+ QString vsBase;
+
+ if (!textBase.startsWith(QLatin1Char('/'))) {
+ QString in = vse->path();
+ if (!in.endsWith(QLatin1Char('/')))
+ vsBase = in + QLatin1Char('/') + textBase;
+ else
+ vsBase = in + textBase;
+ } else {
+ vsBase = textBase;
+ }
+
+ QValueSpaceSubscriber subscriber(vsBase);
+
+ QStringList schildren = subscriber.subPaths();
+
+ foreach(QString child, schildren) {
+ if(child.startsWith(textExt)) {
+ QString completion;
+ completion.append(textBase);
+ if(!completion.isEmpty())
+ completion.append(QLatin1Char('/'));
+ completion.append(child.toAscii());
+ completion.append(QLatin1Char('/'));
+ children.append(completion);
+ }
+ }
+ }
+
+ if(children.isEmpty())
+ return 0;
+
+ QByteArray child = children.takeFirst().toLocal8Bit();
+ char *rv = (char *)malloc(child.length() + 1);
+ ::memcpy(rv, child.constData(), child.length() + 1);
+
+ return rv;
+}
+
+
+void LineInput::run()
+{
+ while(true) {
+ /* Get a line from the user. */
+ mutex.lock();
+ QString prompt = vse->path();
+ prompt.append(" > ");
+ mutex.unlock();
+ char *line_read = readline (prompt.toLocal8Bit().constData());
+
+ /* If the line has any text in it,
+ save it on the history. */
+ if (line_read && *line_read)
+ add_history (line_read);
+
+ mutex.lock();
+ TextEvent * e = new TextEvent(line_read);
+ QApplication::postEvent(this, e);
+ wait.wait(&mutex);
+ if(terminateRequested) {
+ mutex.unlock();
+ return;
+ } else {
+ mutex.unlock();
+ }
+ }
+}
+#endif
+
+#ifdef Q_OS_WIN
+void LineInput::run()
+{
+ while (!terminateRequested) {
+ fprintf(stdout, "%s > ", vse->path().constData());
+ fflush(stdout);
+
+ QByteArray l = ts.readLine();
+ emit line(QString::fromLocal8Bit(l.constData(), l.length()));
+ }
+}
+
+#endif
+
+void usage(char * app)
+{
+ fprintf(stderr, "Usage: %s [-s] [-d]\n", app);
+ fprintf(stderr, " -s a valuespace manager instance is created\n");
+ fprintf(stderr, " -d the tree content is dumped to command line\n");
+ exit(-1);
+}
+
+void dodump(QValueSpaceSubscriber *subscriber)
+{
+ foreach (const QString &child, subscriber->subPaths()) {
+ if (child.isEmpty())
+ continue;
+
+ QValueSpaceSubscriber subItem;
+ subItem.setPath(subscriber);
+ subItem.cd(child);
+ dodump(&subItem);
+ }
+
+ QVariant var = subscriber->value();
+ fprintf(stdout, "%s '%s' %s\n",
+ subscriber->path().toAscii().constData(),
+ variantToString(var).toAscii().constData(),
+ var.typeName());
+}
+
+void VSExplorer::dump()
+{
+ QValueSpaceSubscriber subscriber;
+ subscriber.setPath(&pwd);
+ dodump(&subscriber);
+ fflush(stdout);
+}
+
+void VSExplorer::pwdCmd()
+{
+ fprintf(stdout, "Working directory: %s\n", pwd.path().toLatin1().constData());
+ fflush(stdout);
+}
+
+
+int main(int argc, char ** argv)
+{
+ QApplication app(argc, argv, true);
+
+ bool manager = false;
+ bool dump = false;
+ for(int ii = 1; ii < argc; ++ii) {
+ if(0 == ::strcmp(argv[ii], "-s"))
+ manager = true;
+ else if(0 == ::strcmp(argv[ii], "-d"))
+ dump = true;
+ else
+ usage(argv[0]);
+ }
+
+ if(manager)
+ QValueSpace::initValueSpaceServer();
+
+ if(dump) {
+ QValueSpaceSubscriber subscriber(QLatin1String("/"));
+ dodump(&subscriber);
+ return 0;
+ } else {
+ vse = new VSExplorer;
+ LineInput li;
+
+
+#ifdef Q_OS_WIN
+ QObject::connect(&li, SIGNAL(line(QString)),
+ vse, SLOT(processLine(QString)), Qt::BlockingQueuedConnection);
+#else
+ QObject::connect(&li, SIGNAL(line(QString)),
+ vse, SLOT(processLine(QString)));
+#endif
+
+ int rv = app.exec();
+ delete vse;
+ return rv;
+ }
+}
+
+#include "vsexplorer.moc"