forked from qt-creator/qt-creator
Client: Block until editor is closed
Change-Id: I06bd4425008103be3a4c8f64b6dff8f7df30c552 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@digia.com> Reviewed-by: Eike Ziller <eike.ziller@digia.com>
This commit is contained in:
committed by
Orgad Shaneh
parent
225c21a0f2
commit
14e35b5dc4
+10
-4
@@ -71,7 +71,8 @@ static const char fixedOptionsC[] =
|
||||
" -version Display program version\n"
|
||||
" -client Attempt to connect to already running first instance\n"
|
||||
" -settingspath <path> Override the default path where user settings are stored\n"
|
||||
" -pid <pid> Attempt to connect to instance given by pid\n";
|
||||
" -pid <pid> Attempt to connect to instance given by pid\n"
|
||||
" -block Block until editor is closed\n";
|
||||
|
||||
|
||||
static const char HELP_OPTION1[] = "-h";
|
||||
@@ -82,6 +83,7 @@ static const char VERSION_OPTION[] = "-version";
|
||||
static const char CLIENT_OPTION[] = "-client";
|
||||
static const char SETTINGS_OPTION[] = "-settingspath";
|
||||
static const char PID_OPTION[] = "-pid";
|
||||
static const char BLOCK_OPTION[] = "-block";
|
||||
|
||||
typedef QList<PluginSpec *> PluginSpecSet;
|
||||
|
||||
@@ -409,6 +411,7 @@ int main(int argc, char **argv)
|
||||
appOptions.insert(QLatin1String(VERSION_OPTION), false);
|
||||
appOptions.insert(QLatin1String(CLIENT_OPTION), false);
|
||||
appOptions.insert(QLatin1String(PID_OPTION), true);
|
||||
appOptions.insert(QLatin1String(BLOCK_OPTION), false);
|
||||
QString errorMessage;
|
||||
if (!PluginManager::parseOptions(arguments, appOptions, &foundAppOptions, &errorMessage)) {
|
||||
displayError(errorMessage);
|
||||
@@ -456,7 +459,10 @@ int main(int argc, char **argv)
|
||||
pid = tmpPid;
|
||||
}
|
||||
|
||||
if (app.isRunning() && (pid != -1 || foundAppOptions.contains(QLatin1String(CLIENT_OPTION)))) {
|
||||
bool isBlock = foundAppOptions.contains(QLatin1String(BLOCK_OPTION));
|
||||
if (app.isRunning() && (pid != -1 || isBlock
|
||||
|| foundAppOptions.contains(QLatin1String(CLIENT_OPTION)))) {
|
||||
app.setBlock(isBlock);
|
||||
if (app.sendMessage(PluginManager::serializedArguments(), 5000 /*timeout*/, pid))
|
||||
return 0;
|
||||
|
||||
@@ -489,8 +495,8 @@ int main(int argc, char **argv)
|
||||
|
||||
// Set up lock and remote arguments.
|
||||
app.initialize();
|
||||
QObject::connect(&app, SIGNAL(messageReceived(QString)),
|
||||
&pluginManager, SLOT(remoteArguments(QString)));
|
||||
QObject::connect(&app, SIGNAL(messageReceived(QString,QObject*)),
|
||||
&pluginManager, SLOT(remoteArguments(QString,QObject*)));
|
||||
|
||||
QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), coreplugin->plugin(),
|
||||
SLOT(fileOpenRequest(QString)));
|
||||
|
||||
@@ -157,6 +157,19 @@
|
||||
\sa asynchronousShutdownFinished()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QObject *IPlugin::remoteCommand(const QStringList &options, const QStringList &arguments)
|
||||
\brief When \QC is executed with the -client argument while already another instance of \QC
|
||||
is running, this method of plugins is called in the running instance.
|
||||
|
||||
Plugin-specific arguments are passed in \a options, while the rest of the
|
||||
arguments are passed in \a arguments.
|
||||
|
||||
\returns a QObject that blocks the command until it is destroyed, if -block is used.
|
||||
|
||||
\sa PluginManager::serializedArguments()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void IPlugin::asynchronousShutdownFinished()
|
||||
Sent by the plugin implementation after a asynchronous shutdown
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
virtual void extensionsInitialized() = 0;
|
||||
virtual bool delayedInitialize() { return false; }
|
||||
virtual ShutdownFlag aboutToShutdown() { return SynchronousShutdown; }
|
||||
virtual void remoteCommand(const QStringList & /* options */, const QStringList & /* arguments */) { }
|
||||
virtual QObject *remoteCommand(const QStringList & /* options */, const QStringList & /* arguments */) { return 0; }
|
||||
|
||||
PluginSpec *pluginSpec() const;
|
||||
|
||||
|
||||
@@ -532,13 +532,16 @@ static QStringList subList(const QStringList &in, const QString &key)
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn PluginManager::remoteArguments(const QString &argument)
|
||||
\fn PluginManager::remoteArguments(const QString &argument, QObject *socket)
|
||||
|
||||
Parses the options encoded by serializedArguments() const
|
||||
and passes them on to the respective plugins along with the arguments.
|
||||
|
||||
\a socket is passed for disconnecting the peer when the operation is done (for example,
|
||||
document is closed) for supporting the -block flag.
|
||||
*/
|
||||
|
||||
void PluginManager::remoteArguments(const QString &serializedArgument)
|
||||
void PluginManager::remoteArguments(const QString &serializedArgument, QObject *socket)
|
||||
{
|
||||
if (serializedArgument.isEmpty())
|
||||
return;
|
||||
@@ -547,9 +550,15 @@ void PluginManager::remoteArguments(const QString &serializedArgument)
|
||||
foreach (const PluginSpec *ps, plugins()) {
|
||||
if (ps->state() == PluginSpec::Running) {
|
||||
const QStringList pluginOptions = subList(serializedArguments, QLatin1Char(':') + ps->name());
|
||||
ps->plugin()->remoteCommand(pluginOptions, arguments);
|
||||
QObject *socketParent = ps->plugin()->remoteCommand(pluginOptions, arguments);
|
||||
if (socketParent && socket) {
|
||||
socket->setParent(socketParent);
|
||||
socket = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (socket)
|
||||
delete socket;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -137,7 +137,7 @@ signals:
|
||||
void initializationDone();
|
||||
|
||||
public slots:
|
||||
void remoteArguments(const QString &serializedArguments);
|
||||
void remoteArguments(const QString &serializedArguments, QObject *socket);
|
||||
void shutdown();
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -119,10 +119,12 @@ bool CorePlugin::delayedInitialize()
|
||||
return true;
|
||||
}
|
||||
|
||||
void CorePlugin::remoteCommand(const QStringList & /* options */, const QStringList &args)
|
||||
QObject *CorePlugin::remoteCommand(const QStringList & /* options */, const QStringList &args)
|
||||
{
|
||||
m_mainWindow->openFiles(args, Core::ICore::OpenFilesFlags(ICore::SwitchMode | ICore::CanContainLineNumbers));
|
||||
IDocument *res = m_mainWindow->openFiles(
|
||||
args, ICore::OpenFilesFlags(ICore::SwitchMode | ICore::CanContainLineNumbers));
|
||||
m_mainWindow->activateWindow();
|
||||
return res;
|
||||
}
|
||||
|
||||
void CorePlugin::fileOpenRequest(const QString &f)
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
void extensionsInitialized();
|
||||
bool delayedInitialize();
|
||||
ShutdownFlag aboutToShutdown();
|
||||
void remoteCommand(const QStringList & /* options */, const QStringList &args);
|
||||
QObject *remoteCommand(const QStringList & /* options */, const QStringList &args);
|
||||
|
||||
public slots:
|
||||
void fileOpenRequest(const QString&);
|
||||
|
||||
@@ -831,31 +831,51 @@ static IDocumentFactory *findDocumentFactory(const QList<IDocumentFactory*> &fil
|
||||
return 0;
|
||||
}
|
||||
|
||||
// opens either an editor or loads a project
|
||||
void MainWindow::openFiles(const QStringList &fileNames, ICore::OpenFilesFlags flags)
|
||||
/*! Either opens \a fileNames with editors or loads a project.
|
||||
*
|
||||
* \a flags can be used to stop on first failure, indicate that a file name
|
||||
* might include line numbers and/or switch mode to edit mode.
|
||||
*
|
||||
* \returns the first opened document. Required to support the -block flag
|
||||
* for client mode.
|
||||
*
|
||||
* \sa IPlugin::remoteArguments()
|
||||
*/
|
||||
IDocument *MainWindow::openFiles(const QStringList &fileNames, ICore::OpenFilesFlags flags)
|
||||
{
|
||||
QList<IDocumentFactory*> nonEditorFileFactories = getNonEditorDocumentFactories();
|
||||
IDocument *res = 0;
|
||||
|
||||
foreach (const QString &fileName, fileNames) {
|
||||
const QFileInfo fi(fileName);
|
||||
const QString absoluteFilePath = fi.absoluteFilePath();
|
||||
if (IDocumentFactory *documentFactory = findDocumentFactory(nonEditorFileFactories, mimeDatabase(), fi)) {
|
||||
Core::IDocument *document = documentFactory->open(absoluteFilePath);
|
||||
if (!document && (flags & ICore::StopOnLoadFail))
|
||||
return;
|
||||
if (document && (flags & ICore::SwitchMode))
|
||||
ModeManager::activateMode(Id(Core::Constants::MODE_EDIT));
|
||||
IDocument *document = documentFactory->open(absoluteFilePath);
|
||||
if (!document) {
|
||||
if (flags & ICore::StopOnLoadFail)
|
||||
return res;
|
||||
} else {
|
||||
if (!res)
|
||||
res = document;
|
||||
if (flags & ICore::SwitchMode)
|
||||
ModeManager::activateMode(Id(Core::Constants::MODE_EDIT));
|
||||
}
|
||||
} else {
|
||||
QFlags<EditorManager::OpenEditorFlag> emFlags;
|
||||
if (flags & ICore::SwitchMode)
|
||||
emFlags = EditorManager::ModeSwitch;
|
||||
if (flags & ICore::CanContainLineNumbers)
|
||||
emFlags |= EditorManager::CanContainLineNumber;
|
||||
Core::IEditor *editor = EditorManager::openEditor(absoluteFilePath, Id(), emFlags);
|
||||
if (!editor && (flags & ICore::StopOnLoadFail))
|
||||
return;
|
||||
IEditor *editor = EditorManager::openEditor(absoluteFilePath, Id(), emFlags);
|
||||
if (!editor) {
|
||||
if (flags & ICore::StopOnLoadFail)
|
||||
return res;
|
||||
} else if (!res) {
|
||||
res = editor->document();
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void MainWindow::setFocusToEditor()
|
||||
|
||||
@@ -53,6 +53,7 @@ class EditorManager;
|
||||
class ExternalToolManager;
|
||||
class DocumentManager;
|
||||
class HelpManager;
|
||||
class IDocument;
|
||||
class IWizard;
|
||||
class MessageManager;
|
||||
class MimeDatabase;
|
||||
@@ -95,7 +96,7 @@ public:
|
||||
void removeContextObject(IContext *contex);
|
||||
void resetContext();
|
||||
|
||||
void openFiles(const QStringList &fileNames, ICore::OpenFilesFlags flags);
|
||||
Core::IDocument *openFiles(const QStringList &fileNames, ICore::OpenFilesFlags flags);
|
||||
|
||||
Core::ActionManager *actionManager() const;
|
||||
Core::MessageManager *messageManager() const;
|
||||
|
||||
@@ -3441,10 +3441,11 @@ IPlugin::ShutdownFlag DebuggerPlugin::aboutToShutdown()
|
||||
return SynchronousShutdown;
|
||||
}
|
||||
|
||||
void DebuggerPlugin::remoteCommand(const QStringList &options,
|
||||
QObject *DebuggerPlugin::remoteCommand(const QStringList &options,
|
||||
const QStringList &list)
|
||||
{
|
||||
theDebuggerCore->remoteCommand(options, list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DebuggerRunControl *DebuggerPlugin::createDebugger
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
private:
|
||||
// IPlugin implementation.
|
||||
bool initialize(const QStringList &arguments, QString *errorMessage);
|
||||
void remoteCommand(const QStringList &options, const QStringList &arguments);
|
||||
QObject *remoteCommand(const QStringList &options, const QStringList &arguments);
|
||||
ShutdownFlag aboutToShutdown();
|
||||
void extensionsInitialized();
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ bool QtLocalPeer::isClient()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QtLocalPeer::sendMessage(const QString &message, int timeout)
|
||||
bool QtLocalPeer::sendMessage(const QString &message, int timeout, bool block)
|
||||
{
|
||||
if (!isClient())
|
||||
return false;
|
||||
@@ -129,6 +129,8 @@ bool QtLocalPeer::sendMessage(const QString &message, int timeout)
|
||||
bool res = socket.waitForBytesWritten(timeout);
|
||||
res &= socket.waitForReadyRead(timeout); // wait for ack
|
||||
res &= (socket.read(qstrlen(ack)) == ack);
|
||||
if (block) // block until peer disconnects
|
||||
socket.waitForDisconnected(-1);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -168,8 +170,7 @@ void QtLocalPeer::receiveConnection()
|
||||
QString message = QString::fromUtf8(uMsg.constData(), uMsg.size());
|
||||
socket->write(ack, qstrlen(ack));
|
||||
socket->waitForBytesWritten(1000);
|
||||
delete socket;
|
||||
emit messageReceived(message); // ##(might take a long time to return)
|
||||
emit messageReceived(message, socket); // ##(might take a long time to return)
|
||||
}
|
||||
|
||||
} // namespace SharedTools
|
||||
|
||||
@@ -42,12 +42,12 @@ class QtLocalPeer : public QObject
|
||||
public:
|
||||
explicit QtLocalPeer(QObject *parent = 0, const QString &appId = QString());
|
||||
bool isClient();
|
||||
bool sendMessage(const QString &message, int timeout);
|
||||
bool sendMessage(const QString &message, int timeout, bool block);
|
||||
QString applicationId() const
|
||||
{ return id; }
|
||||
|
||||
Q_SIGNALS:
|
||||
void messageReceived(const QString &message);
|
||||
void messageReceived(const QString &message, QObject *socket);
|
||||
|
||||
protected Q_SLOTS:
|
||||
void receiveConnection();
|
||||
|
||||
@@ -38,10 +38,11 @@ namespace SharedTools {
|
||||
void QtSingleApplication::sysInit(const QString &appId)
|
||||
{
|
||||
actWin = 0;
|
||||
block = false;
|
||||
firstPeer = new QtLocalPeer(this, appId);
|
||||
connect(firstPeer, SIGNAL(messageReceived(QString)), SIGNAL(messageReceived(QString)));
|
||||
connect(firstPeer, SIGNAL(messageReceived(QString,QObject*)), SIGNAL(messageReceived(QString,QObject*)));
|
||||
pidPeer = new QtLocalPeer(this, appId + QLatin1Char('-') + QString::number(QCoreApplication::applicationPid(), 10));
|
||||
connect(pidPeer, SIGNAL(messageReceived(QString)), SIGNAL(messageReceived(QString)));
|
||||
connect(pidPeer, SIGNAL(messageReceived(QString,QObject*)), SIGNAL(messageReceived(QString,QObject*)));
|
||||
}
|
||||
|
||||
|
||||
@@ -87,10 +88,10 @@ void QtSingleApplication::initialize(bool)
|
||||
bool QtSingleApplication::sendMessage(const QString &message, int timeout, qint64 pid)
|
||||
{
|
||||
if (pid == -1)
|
||||
return firstPeer->sendMessage(message, timeout);
|
||||
return firstPeer->sendMessage(message, timeout, block);
|
||||
|
||||
QtLocalPeer peer(this, appId + QLatin1Char('-') + QString::number(pid, 10));
|
||||
return peer.sendMessage(message, timeout);
|
||||
return peer.sendMessage(message, timeout, block);
|
||||
}
|
||||
|
||||
QString QtSingleApplication::id() const
|
||||
@@ -103,15 +104,20 @@ QString QtSingleApplication::applicationId() const
|
||||
return appId;
|
||||
}
|
||||
|
||||
void QtSingleApplication::setBlock(bool value)
|
||||
{
|
||||
block = value;
|
||||
}
|
||||
|
||||
void QtSingleApplication::setActivationWindow(QWidget *aw, bool activateOnMessage)
|
||||
{
|
||||
actWin = aw;
|
||||
if (activateOnMessage) {
|
||||
connect(firstPeer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow()));
|
||||
connect(pidPeer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow()));
|
||||
connect(firstPeer, SIGNAL(messageReceived(QString,QObject*)), this, SLOT(activateWindow()));
|
||||
connect(pidPeer, SIGNAL(messageReceived(QString,QObject*)), this, SLOT(activateWindow()));
|
||||
} else {
|
||||
disconnect(firstPeer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow()));
|
||||
disconnect(pidPeer, SIGNAL(messageReceived(QString)), this, SLOT(activateWindow()));
|
||||
disconnect(firstPeer, SIGNAL(messageReceived(QString,QObject*)), this, SLOT(activateWindow()));
|
||||
disconnect(pidPeer, SIGNAL(messageReceived(QString,QObject*)), this, SLOT(activateWindow()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
bool event(QEvent *event);
|
||||
|
||||
QString applicationId() const;
|
||||
void setBlock(bool value);
|
||||
|
||||
public Q_SLOTS:
|
||||
bool sendMessage(const QString &message, int timeout = 5000, qint64 pid = -1);
|
||||
@@ -61,7 +62,7 @@ public:
|
||||
// end obsolete methods
|
||||
|
||||
Q_SIGNALS:
|
||||
void messageReceived(const QString &message);
|
||||
void messageReceived(const QString &message, QObject *socket);
|
||||
void fileOpenRequest(const QString &file);
|
||||
|
||||
private:
|
||||
@@ -70,6 +71,7 @@ private:
|
||||
QtLocalPeer *pidPeer;
|
||||
QWidget *actWin;
|
||||
QString appId;
|
||||
bool block;
|
||||
};
|
||||
|
||||
} // namespace SharedTools
|
||||
|
||||
Reference in New Issue
Block a user