1 | /* This file is part of the KDE libraries |
2 | Copyright (c) 1999 Preston Brown <pbrown@kde.org> |
3 | Copyright (c) 2000-2001 Waldo Bastian <bastian@kde.org> |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Library General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2 of the License, or (at your option) any later version. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Library General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Library General Public License |
16 | along with this library; see the file COPYING.LIB. If not, write to |
17 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. |
19 | */ |
20 | |
21 | #ifndef KUNIQUEAPP_H |
22 | #define KUNIQUEAPP_H |
23 | |
24 | #include <kapplication.h> |
25 | |
26 | /** |
27 | * KUniqueApplication is a KApplication which only uses a single process. When |
28 | * a KUniqueApplication is started, it attempts to contact an existing copy |
29 | * of the application. If successful, the program asks the |
30 | * existing process to create a new instance by calling its newInstance() method |
31 | * and then exits. If there is no existing process then the program forks and |
32 | * calls the newInstance() method. When newInstance() is called, the application |
33 | * will typically create a new window or activate an existing one. |
34 | * |
35 | * Instances of KUniqueApplication can be made to behave like a normal application by passing |
36 | * the StartFlag::NonUniqueInstance flag to start(). |
37 | * |
38 | * Please note that this supports only one process per KDE session. If |
39 | * your application can only be opened once per user or once per host, you |
40 | * need to ensure this independently of KUniqueApplication. |
41 | * |
42 | * The .desktop file for the application should state X-DBUS-StartupType=Unique, |
43 | * see ktoolinvocation.h |
44 | * |
45 | * If you use command line options before start() is called, you MUST call addCmdLineOptions() |
46 | * so that the KUniqueApplication-specific command-line options can still work. |
47 | * |
48 | * If your application is used to open files, it should also support the --tempfile |
49 | * option (see KCmdLineArgs::addTempFileOption()), to delete tempfiles after use. |
50 | * Add X-KDE-HasTempFileOption=true to the .desktop file to indicate this. |
51 | * |
52 | * @see KApplication |
53 | * @author Preston Brown <pbrown@kde.org> |
54 | */ |
55 | class KDEUI_EXPORT KUniqueApplication : public KApplication |
56 | { |
57 | Q_OBJECT |
58 | public: |
59 | /** |
60 | * Constructor. Takes command line arguments from KCmdLineArgs |
61 | * |
62 | * @param GUIenabled Set to false to disable all GUI stuff. This implies |
63 | * no styles either. |
64 | * @param configUnique If true, the uniqueness of the application will |
65 | * depend on the value of the "MultipleInstances" |
66 | * key in the "KDE" group of the application config file. |
67 | */ |
68 | explicit KUniqueApplication( bool GUIenabled=true, |
69 | bool configUnique=false); |
70 | |
71 | #ifdef Q_WS_X11 |
72 | /** |
73 | * Constructor. Takes command line arguments from KCmdLineArgs |
74 | * |
75 | * @param display Will be passed to Qt as the X display. The display |
76 | * must be valid and already opened. |
77 | * |
78 | * @param visual Pointer to the X11 visual that should be used by the |
79 | * application. If NULL, the default visual will be used instead. |
80 | * |
81 | * @param colormap The colormap that should be used by the application. |
82 | * If 0, the default colormap will be used instead. |
83 | * |
84 | * @param configUnique If true, the uniqueness of the application will |
85 | * depend on the value of the "MultipleInstances" |
86 | * key in the "KDE" group of the application config file. |
87 | */ |
88 | explicit KUniqueApplication( Display *display, |
89 | Qt::HANDLE visual=0, |
90 | Qt::HANDLE colormap=0, |
91 | bool configUnique=false); |
92 | #endif |
93 | |
94 | /** |
95 | * Adds command line options specific for KUniqueApplication. |
96 | * |
97 | * Should be called before calling KUniqueApplication constructor |
98 | * and / or start(). |
99 | */ |
100 | static void addCmdLineOptions(); |
101 | |
102 | /** |
103 | * These flags can be used to specify how new instances of |
104 | * unique applications are created. |
105 | */ |
106 | enum StartFlag |
107 | { |
108 | /** |
109 | * Create a new instance of the application in a new process and |
110 | * do not attempt to re-use an existing process. |
111 | * |
112 | * With this flag set, the new instance of the application will |
113 | * behave as if it were a plain KApplication rather than a KUniqueApplication. |
114 | * |
115 | * This is useful if you have an application where all instances are typically run |
116 | * in a single process but under certain circumstances new instances may require |
117 | * their own process. |
118 | */ |
119 | NonUniqueInstance = 0x1 |
120 | }; |
121 | Q_DECLARE_FLAGS(StartFlags,StartFlag) |
122 | |
123 | /** |
124 | * Forks and registers with D-Bus. |
125 | * |
126 | * The command line arguments are being sent via D-Bus to newInstance() |
127 | * and will be received once the application enters the event loop. |
128 | * |
129 | * Typically this is used like: |
130 | * \code |
131 | * int main(int argc, char **argv) { |
132 | * KAboutData about("myappname", 0, ki18n("myAppName"), .....); |
133 | * KCmdLineArgs::init(argc, argv, &about); |
134 | * KCmdLineArgs::addCmdLineOptions( myCmdOptions ); |
135 | * KUniqueApplication::addCmdLineOptions(); |
136 | * |
137 | * if (!KUniqueApplication::start()) { |
138 | * fprintf(stderr, "myAppName is already running!\n"); |
139 | * return 0; |
140 | * } |
141 | * KUniqueApplication a; |
142 | * return a.exec(); |
143 | * } |
144 | * \endcode |
145 | * Note that it's not necessary to call start() explicitly. It will be |
146 | * called automatically before creating KUniqueApplication if it hasn't |
147 | * been called yet, without any performance impact. |
148 | * |
149 | * Also note that you MUST call KUniqueApplication::addCmdLineOptions(), |
150 | * if you use command line options before start() is called. |
151 | * |
152 | * @param flags Optional flags which control how a new instance |
153 | * of the application is started. |
154 | * @return true if registration is successful. |
155 | * false if another process was already running. |
156 | */ |
157 | static bool start(StartFlags flags); |
158 | // BIC: merge with start(StartFlags flags = StartFlags()) |
159 | static bool start(); |
160 | |
161 | /** |
162 | * Destructor |
163 | */ |
164 | virtual ~KUniqueApplication(); |
165 | |
166 | /** |
167 | * Creates a new "instance" of the application. |
168 | * |
169 | * Usually this will involve making some calls into the GUI portion of your |
170 | * application asking for a new window to be created, possibly with |
171 | * some data already loaded based on the arguments received. |
172 | * |
173 | * Command line arguments have been passed to KCmdLineArgs before this |
174 | * function is called and can be checked in the usual way. |
175 | * |
176 | * The default implementation ensures the mainwindow of the already |
177 | * running instance is shown and activated if necessary. If your |
178 | * application has only one mainwindow, you should call this default |
179 | * implementation and only add your special handling if needed. |
180 | * |
181 | * Note that newInstance() is called also in the first started |
182 | * application process. |
183 | * |
184 | * For applications that share one process for several mainwindows, |
185 | * the reimplementation could be: |
186 | * \code |
187 | int MyApp::newInstance() |
188 | { |
189 | KCmdLineArgs::setCwd(QDir::currentPath().toUtf8()); |
190 | KCmdLineArgs* args = KCmdLineArgs::parsedArgs(); |
191 | static bool first = true; |
192 | if (args->count() > 0) { |
193 | for (int i = 0; i < args->count(); ++i) { |
194 | openWindow(args->url(i)); |
195 | } |
196 | } else if( !first || !isSessionRestored()) { |
197 | openWindow(KUrl()); // create a new window |
198 | } |
199 | first = false; |
200 | args->clear(); |
201 | return 0; |
202 | } |
203 | * \endcode |
204 | * |
205 | * @return An exit value. The calling process will exit with this value. |
206 | */ |
207 | virtual int newInstance(); |
208 | |
209 | /** |
210 | * Returns whether newInstance() is being called while session |
211 | * restoration is in progress. |
212 | */ |
213 | bool restoringSession(); |
214 | |
215 | /** |
216 | * @internal |
217 | */ |
218 | #ifndef KDE_NO_DEPRECATED |
219 | KDE_DEPRECATED static void setHandleAutoStarted(); |
220 | #endif |
221 | |
222 | private: |
223 | friend class KUniqueApplicationAdaptor; |
224 | class Private; |
225 | Private * const d; |
226 | |
227 | Q_PRIVATE_SLOT(d, void _k_newInstanceNoFork()) |
228 | }; |
229 | Q_DECLARE_OPERATORS_FOR_FLAGS(KUniqueApplication::StartFlags) |
230 | |
231 | #endif |
232 | |