#
#
# add_file "res/forms/message.ui"
# content [f8208ef0a1ebfaeae1a2260410daa0f0f140a8c9]
#
# add_file "src/view/dialogs/Message.cpp"
# content [ac0fac32b19c603be4eac6af68230b5ed0ac2d18]
#
# add_file "src/view/dialogs/Message.h"
# content [d8ff01342e07e6c2162f3d28719cdc1b7998972a]
#
# patch "guitone.pro"
# from [bad165bd001ea9efdadeeb99cd5294c28eaaf1ae]
# to [55dc2152982160f09a70ff3916db59967ea5f418]
#
# patch "src/GuitoneDriver.cpp"
# from [65f257718ae2d0a79947d69043972a79ac34985a]
# to [4ba006ff7f2e467db5341dac631cf42bc9cec07d]
#
# patch "src/GuitoneDriver.h"
# from [b24931e08bf618708c41b9b55d6878de024f3f33]
# to [701a19b67cd5627f86143f5ecfb598747c24303b]
#
============================================================
--- res/forms/message.ui f8208ef0a1ebfaeae1a2260410daa0f0f140a8c9
+++ res/forms/message.ui f8208ef0a1ebfaeae1a2260410daa0f0f140a8c9
@@ -0,0 +1,90 @@
+
+
+ MessageDialog
+
+
+
+ 0
+ 0
+ 410
+ 299
+
+
+
+ Dialog
+
+
+ -
+
+
+
+ false
+ false
+ false
+
+
+
+ QPlainTextEdit::WidgetWidth
+
+
+ true
+
+
+
+
+
+ Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Close
+
+
+ true
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ MessageDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ MessageDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
============================================================
--- src/view/dialogs/Message.cpp ac0fac32b19c603be4eac6af68230b5ed0ac2d18
+++ src/view/dialogs/Message.cpp ac0fac32b19c603be4eac6af68230b5ed0ac2d18
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * Copyright (C) 2009 by Thomas Keller *
+ * address@hidden *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see . *
+ ***************************************************************************/
+
+#include "Message.h"
+
+#include
+
+Message::Message(QWidget * parent, const QString & title, const QString & msg) : Dialog(parent)
+{
+ setupUi(this);
+ Dialog::init();
+
+ setWindowTitle(title);
+
+ QFont f;
+ f.setStyleHint(QFont::Courier);
+ f.setFamily("Courier");
+ message->setFont(f);
+ message->setPlainText(msg);
+}
+
+Message::~Message() {}
+
============================================================
--- src/view/dialogs/Message.h d8ff01342e07e6c2162f3d28719cdc1b7998972a
+++ src/view/dialogs/Message.h d8ff01342e07e6c2162f3d28719cdc1b7998972a
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * Copyright (C) 2009 by Thomas Keller *
+ * address@hidden *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see . *
+ ***************************************************************************/
+
+#ifndef MESSAGE_H
+#define MESSAGE_H
+
+#include "ui_message.h"
+#include "Dialog.h"
+
+class Message : public Dialog, private Ui::MessageDialog
+{
+ Q_OBJECT
+public:
+ Message(QWidget *, const QString &, const QString &);
+ ~Message();
+};
+
+#endif
============================================================
--- guitone.pro bad165bd001ea9efdadeeb99cd5294c28eaaf1ae
+++ guitone.pro 55dc2152982160f09a70ff3916db59967ea5f418
@@ -61,6 +61,7 @@ HEADERS = src/view/TreeView.h \
src/view/dialogs/OpenPrompt.h \
src/view/dialogs/AddEditDatabaseVariable.h \
src/view/dialogs/CreateDatabase.h \
+ src/view/dialogs/Message.h \
src/view/panels/IconHelp.h \
src/view/panels/DatabaseVariables.h \
src/view/panels/NodeInfo.h \
@@ -143,6 +144,7 @@ SOURCES += src/view/TreeView.cpp \
src/view/dialogs/OpenPrompt.cpp \
src/view/dialogs/AddEditDatabaseVariable.cpp \
src/view/dialogs/CreateDatabase.cpp \
+ src/view/dialogs/Message.cpp \
src/view/panels/IconHelp.cpp \
src/view/panels/DatabaseVariables.cpp \
src/view/panels/NodeInfo.cpp \
@@ -212,7 +214,8 @@ FORMS += res/forms/select_revision.ui
res/forms/db_variables.ui \
res/forms/add_edit_variables.ui \
res/forms/nodeinfo.ui \
- res/forms/create_database.ui
+ res/forms/create_database.ui \
+ res/forms/message.ui
UI_DIR = tmp
OBJECTS_DIR = tmp
============================================================
--- src/GuitoneDriver.cpp 65f257718ae2d0a79947d69043972a79ac34985a
+++ src/GuitoneDriver.cpp 4ba006ff7f2e467db5341dac631cf42bc9cec07d
@@ -22,6 +22,7 @@
#include "DatabaseDialogManager.h"
#include "WorkspaceDialogManager.h"
+#include "Message.h"
#include
@@ -49,7 +50,7 @@ void GuitoneDriver::processCommands()
if (args.size() < 2)
{
- error("wrong number of arguments");
+ help();
return;
}
@@ -64,9 +65,11 @@ void GuitoneDriver::processCommands()
QFileInfo fileInfo(path);
if (!fileInfo.exists())
{
- error("non-existant path");
+ msg(QString("path '%1' does not exist").arg(path));
+ QCoreApplication::exit(1);
return;
}
+
path = fileInfo.absoluteFilePath();
if (fileInfo.isDir())
@@ -75,11 +78,12 @@ void GuitoneDriver::processCommands()
try
{
path = MonotoneManager::normalizeWorkspacePath(path);
- APP->manager()->getThreadForWorkspace(path);
+ APP->manager()->getThreadForWorkspace(path)->waitForStarted();
}
catch (GuitoneException e)
{
- error(e);
+ msg(QString("could not startup monotone: %1").arg(e));
+ QCoreApplication::exit(1);
return;
}
qobject_cast(dialogManager)->init(path);
@@ -89,18 +93,20 @@ void GuitoneDriver::processCommands()
dialogManager = new DatabaseDialogManager(NULL);
try
{
- APP->manager()->getThreadForDatabase(path);
+ APP->manager()->getThreadForDatabase(path)->waitForStarted();
}
catch (GuitoneException e)
{
- error(e);
+ msg(QString("could not startup monotone: %1").arg(e));
+ QCoreApplication::exit(1);
return;
}
qobject_cast(dialogManager)->init(path);
}
else
{
- error("file is neither a file nor a directory");
+ msg(QString("path '%1' is neither a file nor a directory").arg(path));
+ QCoreApplication::exit(1);
return;
}
}
@@ -111,70 +117,205 @@ void GuitoneDriver::processCommands()
APP, SLOT(quit())
);
+ // connect to all signals of the dialog manager
+ // FIXME: unfortunately our "general purpose" slots have no idea which
+ // signal they're responding to, since Qt has no API for that, obviously
+ // they store this information. It would be too cool if there would be
+ // a QObject::senderSignal() similar to QObject::sender() in the future...
+ const QMetaObject * metaObject = dialogManager->metaObject();
+ for (int i=0; imethodCount(); i++)
+ {
+ QMetaMethod m = metaObject->method(i);
+ if (m.methodType() != QMetaMethod::Signal) continue;
+
+ QByteArray sig = m.signature();
+ // ignore these signals from QObject
+ if (sig == "destroyed()" || sig == "destroyed(QObject*)")
+ continue;
+
+ D(QString("connecting to signal '%1'").arg(sig.constData()));
+
+ sig.prepend("2"); // see qobjectdefs.h
+ if (m.parameterTypes().size() == 0)
+ {
+ connect(
+ dialogManager, sig,
+ this, SLOT(signalWithNoArguments())
+ );
+ }
+ else
+ if (m.parameterTypes().size() == 1 && m.parameterTypes().at(0) == "QString")
+ {
+ connect(
+ dialogManager, sig,
+ this, SLOT(signalWithOneStringArgument(const QString &))
+ );
+ }
+ else
+ {
+ W(QString("could not connect to signal '%1'").arg(sig.constData()));
+ }
+ }
+
QString reqMethod = args.takeFirst();
const QMetaObject * obj = dialogManager->metaObject();
- QMetaMethod method;
- bool found = false;
+ QList methodCandidates;
for (int i=0; imethodCount(); i++)
{
- method = obj->method(i);
+ QMetaMethod method = obj->method(i);
QByteArray sig(method.signature());
sig = sig.left(sig.indexOf('('));
if (sig == reqMethod.toLatin1())
{
- found = true;
- break;
+ methodCandidates.push_back(method);
}
}
- if (!found)
+ if (methodCandidates.size() == 0)
{
- error("method signature not found");
+ msg(QString("method signature '%1' not found").arg(reqMethod));
+ QCoreApplication::exit(1);
return;
}
- QList methodArgs = method.parameterTypes();
+ // FIXME: for now we only compare the number of arguments of a function
+ // but not their argument type - which of course would make a valid
+ // overload as well. since this is not a problem in the current API
+ // we leave this task for later...
+ const QMetaMethod * chosenMethod = 0;
+ foreach (const QMetaMethod & m, methodCandidates)
+ {
+ if (m.parameterTypes().size() == args.size())
+ {
+ chosenMethod = &m;
+ }
+ }
- if (methodArgs.size() != args.size())
+ if (!chosenMethod)
{
- error("argument count doesn't match");
+ msg(QString("found %1 overloads for '%2', but none takes %3 arguments")
+ .arg(methodCandidates.size()).arg(reqMethod).arg(args.size()));
+ QCoreApplication::exit(1);
return;
}
if (args.size() > 10)
{
- error("cannot handle more than 10 function arguments");
+ msg("cannot handle more than 10 function arguments");
+ QCoreApplication::exit(1);
return;
}
QGenericArgument genArgs[10];
- for (int i=0; iparameterTypes().size(); i++)
{
- const char * typeName = methodArgs.at(i).constData();
+ const char * typeName = chosenMethod->parameterTypes().at(i).constData();
QVariant::Type type = QVariant::nameToType(typeName);
- // we currently only use / support strings
- switch (type)
+ // we currently only use / support strings and string lists
+ if (type == QVariant::String)
{
- case QVariant::String: genArgs[i] = Q_ARG(QString, args.at(i)); break;
- case QVariant::Invalid: I(false);
- default: error(QString("unrecognized type %1").arg(typeName)); return;
+ genArgs[i] = Q_ARG(QString, args.at(i));
}
+ else if (type == QVariant::StringList)
+ {
+ QString arg = args.at(i);
+ QRegExp rx("[^\\\\],");
+ int pos = 0;
+ while ((pos = rx.indexIn(arg)) != -1)
+ {
+ listElements << arg.left(pos + 1);
+ arg = arg.mid(pos + 2);
+ }
+ listElements << arg;
+
+ for (int j=0; j(reqMethod.toLatin1().data());
- QMetaObject::invokeMethod(dialogManager, methodName, Qt::DirectConnection,
- genArgs[0], genArgs[1], genArgs[2], genArgs[3],
- genArgs[4], genArgs[5], genArgs[6], genArgs[7],
- genArgs[8], genArgs[9]);
+ bool ok = QMetaObject::invokeMethod(dialogManager, methodName, Qt::QueuedConnection,
+ genArgs[0], genArgs[1], genArgs[2], genArgs[3],
+ genArgs[4], genArgs[5], genArgs[6], genArgs[7],
+ genArgs[8], genArgs[9]);
+ D(QString("execution successful: %1").arg(ok));
}
-void GuitoneDriver::error(const QString & msg)
+void GuitoneDriver::msg(const QString & message)
{
- C(msg);
- QMessageBox::critical(NULL, tr("Error"), msg, QMessageBox::Ok, 0, 0);
- quit();
+ Message msg(NULL, "guitone driver interface", message);
+ msg.exec();
}
+void GuitoneDriver::help()
+{
+ QList objs;
+ objs.append((new DialogManager(NULL))->metaObject());
+ objs.append((new DatabaseDialogManager(NULL))->metaObject());
+ objs.append((new WorkspaceDialogManager(NULL))->metaObject());
+
+ QStringList output;
+ output << "Usage: guitone exec [ ...]\n\n";
+ output << "Available functions:\n\n";
+
+ foreach (const QMetaObject * obj, objs)
+ {
+ output << obj->className() << ":\n";
+ for (int i=obj->methodOffset(); i < obj->methodCount(); i++)
+ {
+ QMetaMethod m = obj->method(i);
+ if (m.access() != QMetaMethod::Public ||
+ m.methodType() != QMetaMethod::Slot)
+ continue;
+
+ QByteArray sig(m.signature());
+ sig = sig.left(sig.indexOf('('));
+ QList names = m.parameterNames();
+ QList types = m.parameterTypes();
+
+ output << "\t" << sig;
+ for (int i=0; i 0)
+ output << ":" << names.at(i);
+ output << ">";
+ }
+ output << "\n";
+ }
+ }
+ output << "\n";
+ output << "The stringlist type has to be given as a single argument. "
+ "Elements are separated with a comma ','; any comma inside "
+ "a string element has to be escaped with a backslash '\\,'.";
+ msg(output.join(""));
+}
+
+void GuitoneDriver::signalWithNoArguments()
+{
+ L("signalled");
+}
+
+void GuitoneDriver::signalWithOneStringArgument(const QString & arg)
+{
+ L(QString("signalled, value: %1").arg(arg));
+}
+
============================================================
--- src/GuitoneDriver.h b24931e08bf618708c41b9b55d6878de024f3f33
+++ src/GuitoneDriver.h 701a19b67cd5627f86143f5ecfb598747c24303b
@@ -33,9 +33,12 @@ private slots:
private slots:
void processCommands();
+ void signalWithNoArguments();
+ void signalWithOneStringArgument(const QString &);
private:
- void error(const QString &);
+ void msg(const QString &);
+ void help();
DialogManager * dialogManager;
};