/[svn]/qsampler/trunk/src/main.cpp
ViewVC logotype

Contents of /qsampler/trunk/src/main.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2065 - (show annotations) (download)
Sat Mar 13 12:44:15 2010 UTC (10 years ago) by capela
File size: 9879 byte(s)
* Automatic crash-dump reports, debugger stack-traces (gdb), back-
  traces, whatever, are being introduced as a brand new configure
  option (--enable-stacktrace) and default enabled on debug build
  targets (--enable-debug).

1 // main.cpp
2 //
3 /****************************************************************************
4 Copyright (C) 2004-2010, rncbc aka Rui Nuno Capela. All rights reserved.
5 Copyright (C) 2007, 2008 Christian Schoenebeck
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 *****************************************************************************/
22
23 #include "qsamplerAbout.h"
24 #include "qsamplerOptions.h"
25 #include "qsamplerMainForm.h"
26
27 #include <QApplication>
28 #include <QLibraryInfo>
29 #include <QTranslator>
30 #include <QLocale>
31 #if defined(__APPLE__) // Toshi Nagata 20080105
32 #include <QDir>
33 #endif
34
35 #if QT_VERSION < 0x040300
36 #define lighter(x) light(x)
37 #define darker(x) dark(x)
38 #endif
39
40
41 //-------------------------------------------------------------------------
42 // Singleton application instance stuff (Qt/X11 only atm.)
43 //
44
45 #if defined(Q_WS_X11)
46
47 #include <QX11Info>
48
49 #include <X11/Xatom.h>
50 #include <X11/Xlib.h>
51
52 #define QSAMPLER_XUNIQUE "qsamplerMainForm_xunique"
53
54 #endif
55
56 class qsamplerApplication : public QApplication
57 {
58 public:
59
60 // Constructor.
61 qsamplerApplication(int& argc, char **argv) : QApplication(argc, argv),
62 m_pQtTranslator(0), m_pMyTranslator(0), m_pWidget(0)
63 {
64 // Load translation support.
65 QLocale loc;
66 if (loc.language() != QLocale::C) {
67 // Try own Qt translation...
68 m_pQtTranslator = new QTranslator(this);
69 QString sLocName = "qt_" + loc.name();
70 QString sLocPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
71 if (m_pQtTranslator->load(sLocName, sLocPath)) {
72 QApplication::installTranslator(m_pQtTranslator);
73 } else {
74 delete m_pQtTranslator;
75 m_pQtTranslator = 0;
76 #ifdef CONFIG_DEBUG
77 qWarning("Warning: no translation found for '%s' locale: %s/%s.qm",
78 loc.name().toUtf8().constData(),
79 sLocPath.toUtf8().constData(),
80 sLocName.toUtf8().constData());
81 #endif
82 }
83 // Try own application translation...
84 m_pMyTranslator = new QTranslator(this);
85 sLocName = "qsampler_" + loc.name();
86 if (m_pMyTranslator->load(sLocName, sLocPath)) {
87 QApplication::installTranslator(m_pMyTranslator);
88 } else {
89 sLocPath = CONFIG_PREFIX "/share/locale";
90 if (m_pMyTranslator->load(sLocName, sLocPath)) {
91 QApplication::installTranslator(m_pMyTranslator);
92 } else {
93 delete m_pMyTranslator;
94 m_pMyTranslator = 0;
95 #ifdef CONFIG_DEBUG
96 qWarning("Warning: no translation found for '%s' locale: %s/%s.qm",
97 loc.name().toUtf8().constData(),
98 sLocPath.toUtf8().constData(),
99 sLocName.toUtf8().constData());
100 #endif
101 }
102 }
103 }
104 #if defined(Q_WS_X11)
105 m_pDisplay = QX11Info::display();
106 m_aUnique = XInternAtom(m_pDisplay, QSAMPLER_XUNIQUE, false);
107 XGrabServer(m_pDisplay);
108 m_wOwner = XGetSelectionOwner(m_pDisplay, m_aUnique);
109 XUngrabServer(m_pDisplay);
110 #endif
111 }
112
113 // Destructor.
114 ~qsamplerApplication()
115 {
116 if (m_pMyTranslator) delete m_pMyTranslator;
117 if (m_pQtTranslator) delete m_pQtTranslator;
118 }
119
120 // Main application widget accessors.
121 void setMainWidget(QWidget *pWidget)
122 {
123 m_pWidget = pWidget;
124 #if defined(Q_WS_X11)
125 XGrabServer(m_pDisplay);
126 m_wOwner = m_pWidget->winId();
127 XSetSelectionOwner(m_pDisplay, m_aUnique, m_wOwner, CurrentTime);
128 XUngrabServer(m_pDisplay);
129 #endif
130 }
131
132 QWidget *mainWidget() const { return m_pWidget; }
133
134 // Check if another instance is running,
135 // and raise its proper main widget...
136 bool setup()
137 {
138 #if defined(Q_WS_X11)
139 if (m_wOwner != None) {
140 // First, notify any freedesktop.org WM
141 // that we're about to show the main widget...
142 Screen *pScreen = XDefaultScreenOfDisplay(m_pDisplay);
143 int iScreen = XScreenNumberOfScreen(pScreen);
144 XEvent ev;
145 memset(&ev, 0, sizeof(ev));
146 ev.xclient.type = ClientMessage;
147 ev.xclient.display = m_pDisplay;
148 ev.xclient.window = m_wOwner;
149 ev.xclient.message_type = XInternAtom(m_pDisplay, "_NET_ACTIVE_WINDOW", false);
150 ev.xclient.format = 32;
151 ev.xclient.data.l[0] = 0; // Source indication.
152 ev.xclient.data.l[1] = 0; // Timestamp.
153 ev.xclient.data.l[2] = 0; // Requestor's currently active window (none)
154 ev.xclient.data.l[3] = 0;
155 ev.xclient.data.l[4] = 0;
156 XSelectInput(m_pDisplay, m_wOwner, StructureNotifyMask);
157 XSendEvent(m_pDisplay, RootWindow(m_pDisplay, iScreen), false,
158 (SubstructureNotifyMask | SubstructureRedirectMask), &ev);
159 XSync(m_pDisplay, false);
160 XRaiseWindow(m_pDisplay, m_wOwner);
161 // And then, let it get caught on destination
162 // by QApplication::x11EventFilter...
163 QByteArray value = QSAMPLER_XUNIQUE;
164 XChangeProperty(
165 m_pDisplay,
166 m_wOwner,
167 m_aUnique,
168 m_aUnique, 8,
169 PropModeReplace,
170 (unsigned char *) value.data(),
171 value.length());
172 // Done.
173 return true;
174 }
175 #endif
176 return false;
177 }
178
179 #if defined(Q_WS_X11)
180 bool x11EventFilter(XEvent *pEv)
181 {
182 if (m_pWidget && m_wOwner != None
183 && pEv->type == PropertyNotify
184 && pEv->xproperty.window == m_wOwner
185 && pEv->xproperty.state == PropertyNewValue) {
186 // Always check whether our property-flag is still around...
187 Atom aType;
188 int iFormat = 0;
189 unsigned long iItems = 0;
190 unsigned long iAfter = 0;
191 unsigned char *pData = 0;
192 if (XGetWindowProperty(
193 m_pDisplay,
194 m_wOwner,
195 m_aUnique,
196 0, 1024,
197 false,
198 m_aUnique,
199 &aType,
200 &iFormat,
201 &iItems,
202 &iAfter,
203 &pData) == Success
204 && aType == m_aUnique && iItems > 0 && iAfter == 0) {
205 // Avoid repeating it-self...
206 XDeleteProperty(m_pDisplay, m_wOwner, m_aUnique);
207 // Just make it always shows up fine...
208 m_pWidget->show();
209 m_pWidget->raise();
210 m_pWidget->activateWindow();
211 }
212 // Free any left-overs...
213 if (iItems > 0 && pData)
214 XFree(pData);
215 }
216 return QApplication::x11EventFilter(pEv);
217 }
218 #endif
219
220 private:
221
222 // Translation support.
223 QTranslator *m_pQtTranslator;
224 QTranslator *m_pMyTranslator;
225
226 // Instance variables.
227 QWidget *m_pWidget;
228
229 #if defined(Q_WS_X11)
230 Display *m_pDisplay;
231 Atom m_aUnique;
232 Window m_wOwner;
233 #endif
234 };
235
236
237 //-------------------------------------------------------------------------
238 // stacktrace - Signal crash handler.
239 //
240
241 #ifdef CONFIG_STACKTRACE
242 #if defined(__GNUC__) && defined(Q_OS_LINUX)
243
244 #include <stdio.h>
245 #include <errno.h>
246 #include <signal.h>
247 #include <sys/wait.h>
248
249 void stacktrace ( int signo )
250 {
251 pid_t pid;
252 int rc;
253 int status = 0;
254 char cmd[80];
255
256 // Reinstall default handler; prevent race conditions...
257 signal(signo, SIG_DFL);
258
259 static const char *shell = "/bin/sh";
260 static const char *format = "gdb -q --batch --pid=%d --eval-command=bt";
261
262 snprintf(cmd, sizeof(cmd), format, (int) getpid());
263
264 pid = fork();
265
266 // Fork failure!
267 if (pid < 0)
268 return;
269
270 // Fork child...
271 if (pid == 0) {
272 execl(shell, shell, "-c", cmd, NULL);
273 _exit(1);
274 return;
275 }
276
277 // Parent here: wait for child to terminate...
278 do { rc = waitpid(pid, &status, 0); }
279 while ((rc < 0) && (errno == EINTR));
280
281 // Dispatch any logging, if any...
282 QApplication::processEvents(QEventLoop::AllEvents, 3000);
283
284 // Make sure everyone terminates...
285 kill(pid, SIGTERM);
286 _exit(1);
287 }
288
289 #endif
290 #endif
291
292
293 //-------------------------------------------------------------------------
294 // main - The main program trunk.
295 //
296
297 int main ( int argc, char **argv )
298 {
299 Q_INIT_RESOURCE(qsampler);
300 #ifdef CONFIG_STACKTRACE
301 #if defined(__GNUC__) && defined(Q_OS_LINUX)
302 signal(SIGILL, stacktrace);
303 signal(SIGFPE, stacktrace);
304 signal(SIGSEGV, stacktrace);
305 signal(SIGABRT, stacktrace);
306 signal(SIGBUS, stacktrace);
307 #endif
308 #endif
309 qsamplerApplication app(argc, argv);
310
311 #if defined(__APPLE__) // Toshi Nagata 20080105
312 {
313 // Set the plugin path to @exetutable_path/../plugins
314 QDir dir(QApplication::applicationDirPath());
315 dir.cdUp(); // "Contents" directory
316 QApplication::setLibraryPaths(QStringList(dir.absolutePath() + "/plugins"));
317
318 // Set the PATH environment variable to include @executable_path/../../..
319 dir.cdUp();
320 dir.cdUp();
321 QString path(getenv("PATH"));
322 path = dir.absolutePath() + ":" + path;
323 setenv("PATH", path.toUtf8().constData(), 1);
324 }
325 #endif
326
327 // Construct default settings; override with command line arguments.
328 QSampler::Options options;
329 if (!options.parse_args(app.arguments())) {
330 app.quit();
331 return 1;
332 }
333
334 // Have another instance running?
335 if (app.setup()) {
336 app.quit();
337 return 2;
338 }
339
340 // Dark themes grayed/disabled color group fix...
341 QPalette pal(app.palette());
342 if (pal.base().color().value() < 0x7f) {
343 pal.setColorGroup(QPalette::Disabled,
344 pal.windowText().color().darker(),
345 pal.button(),
346 pal.light(),
347 pal.dark(),
348 pal.mid(),
349 pal.text().color().darker(),
350 pal.text().color().lighter(),
351 pal.base(),
352 pal.window());
353 app.setPalette(pal);
354 }
355
356 // Set default base font...
357 int iBaseFontSize = app.font().pointSize();
358 if (options.iBaseFontSize > 0)
359 iBaseFontSize = options.iBaseFontSize;
360 app.setFont(QFont(app.font().family(), iBaseFontSize));
361
362 // Construct, setup and show the main form.
363 QSampler::MainForm w;
364 w.setup(&options);
365 w.show();
366
367 // Settle this one as application main widget...
368 app.setMainWidget(&w);
369
370 // Register the quit signal/slot.
371 // app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
372
373 return app.exec();
374 }
375
376
377 // end of main.cpp

  ViewVC Help
Powered by ViewVC