1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #pragma once
27 
28 #include <coreplugin/editormanager/iexternaleditor.h>
29 
30 #include <QStringList>
31 #include <QMap>
32 
33 #include <functional>
34 
35 QT_BEGIN_NAMESPACE
36 class QTcpSocket;
37 QT_END_NAMESPACE
38 
39 namespace QtSupport { class BaseQtVersion; }
40 
41 namespace QmakeProjectManager {
42 namespace Internal {
43 
44 /* Convenience parametrizable base class for Qt editors/binaries
45  * Provides convenience functions that
46  * try to retrieve the binary of the editor from the Qt version
47  * of the project the file belongs to, falling back to path search
48  * if none is found. On Mac, the "open" mechanism can be optionally be used. */
49 
50 class ExternalQtEditor : public Core::IExternalEditor
51 {
52     Q_OBJECT
53 
54 public:
55     // Member function pointer for a QtVersion function return a string (command)
56     using CommandForQtVersion = std::function<QString(const QtSupport::BaseQtVersion *)>;
57 
58     static ExternalQtEditor *createLinguistEditor();
59     static ExternalQtEditor *createDesignerEditor();
60 
61     QStringList mimeTypes() const override;
62     Utils::Id id() const override;
63     QString displayName() const override;
64 
65     bool startEditor(const Utils::FilePath &filePath, QString *errorMessage) override;
66 
67     // Data required to launch the editor
68     struct LaunchData {
69         QString binary;
70         QStringList arguments;
71         QString workingDirectory;
72     };
73 
74 protected:
75     ExternalQtEditor(Utils::Id id,
76                      const QString &displayName,
77                      const QString &mimetype,
78                      const CommandForQtVersion &commandForQtVersion);
79 
80     // Try to retrieve the binary of the editor from the Qt version,
81     // prepare arguments accordingly (Mac "open" if desired)
82     bool getEditorLaunchData(const Utils::FilePath &filePath,
83                              LaunchData *data,
84                              QString *errorMessage) const;
85 
86     // Create and start a detached GUI process executing in the background.
87     // Set the project environment if there is one.
88     bool startEditorProcess(const LaunchData &data, QString *errorMessage);
89 
90 private:
91     const QStringList m_mimeTypes;
92     const Utils::Id m_id;
93     const QString m_displayName;
94     const CommandForQtVersion m_commandForQtVersion;
95 };
96 
97 /* Qt Designer on the remaining platforms: Uses Designer's own
98  * Tcp-based communication mechanism to ensure all files are opened
99  * in one instance (per version). */
100 
101 class DesignerExternalEditor : public ExternalQtEditor
102 {
103     Q_OBJECT
104 public:
105     DesignerExternalEditor();
106 
107     bool startEditor(const Utils::FilePath &filePath, QString *errorMessage) override;
108 
109 private:
110     void processTerminated(const QString &binary);
111 
112     // A per-binary entry containing the socket
113     using ProcessCache = QMap<QString, QTcpSocket*>;
114 
115     ProcessCache m_processCache;
116 };
117 
118 } // namespace Internal
119 } // namespace QmakeProjectManager
120