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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2181 - (show annotations) (download)
Sun Jun 5 10:21:53 2011 UTC (10 years, 1 month ago) by capela
File size: 10247 byte(s)
* Debugging stacktrace now applies to all working threads.
1 // qsampler.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 #if WIN32
75 sLocPath = QApplication::applicationDirPath() + "/share/locale";
76 if (m_pQtTranslator->load(sLocName, sLocPath)) {
77 QApplication::installTranslator(m_pQtTranslator);
78 } else {
79 #endif
80 delete m_pQtTranslator;
81 m_pQtTranslator = 0;
82 #ifdef CONFIG_DEBUG
83 qWarning("Warning: no translation found for '%s' locale: %s/%s.qm",
84 loc.name().toUtf8().constData(),
85 sLocPath.toUtf8().constData(),
86 sLocName.toUtf8().constData());
87 #endif
88 #if WIN32
89 }
90 #endif
91 }
92 // Try own application translation...
93 m_pMyTranslator = new QTranslator(this);
94 sLocName = "qsampler_" + loc.name();
95 if (m_pMyTranslator->load(sLocName, sLocPath)) {
96 QApplication::installTranslator(m_pMyTranslator);
97 } else {
98 #if WIN32
99 sLocPath = QApplication::applicationDirPath() + "/share/locale";
100 #else
101 sLocPath = CONFIG_PREFIX "/share/locale";
102 #endif
103 if (m_pMyTranslator->load(sLocName, sLocPath)) {
104 QApplication::installTranslator(m_pMyTranslator);
105 } else {
106 delete m_pMyTranslator;
107 m_pMyTranslator = 0;
108 #ifdef CONFIG_DEBUG
109 qWarning("Warning: no translation found for '%s' locale: %s/%s.qm",
110 loc.name().toUtf8().constData(),
111 sLocPath.toUtf8().constData(),
112 sLocName.toUtf8().constData());
113 #endif
114 }
115 }
116 }
117 #if defined(Q_WS_X11)
118 m_pDisplay = QX11Info::display();
119 m_aUnique = XInternAtom(m_pDisplay, QSAMPLER_XUNIQUE, false);
120 XGrabServer(m_pDisplay);
121 m_wOwner = XGetSelectionOwner(m_pDisplay, m_aUnique);
122 XUngrabServer(m_pDisplay);
123 #endif
124 }
125
126 // Destructor.
127 ~qsamplerApplication()
128 {
129 if (m_pMyTranslator) delete m_pMyTranslator;
130 if (m_pQtTranslator) delete m_pQtTranslator;
131 }
132
133 // Main application widget accessors.
134 void setMainWidget(QWidget *pWidget)
135 {
136 m_pWidget = pWidget;
137 #if defined(Q_WS_X11)
138 XGrabServer(m_pDisplay);
139 m_wOwner = m_pWidget->winId();
140 XSetSelectionOwner(m_pDisplay, m_aUnique, m_wOwner, CurrentTime);
141 XUngrabServer(m_pDisplay);
142 #endif
143 }
144
145 QWidget *mainWidget() const { return m_pWidget; }
146
147 // Check if another instance is running,
148 // and raise its proper main widget...
149 bool setup()
150 {
151 #if defined(Q_WS_X11)
152 if (m_wOwner != None) {
153 // First, notify any freedesktop.org WM
154 // that we're about to show the main widget...
155 Screen *pScreen = XDefaultScreenOfDisplay(m_pDisplay);
156 int iScreen = XScreenNumberOfScreen(pScreen);
157 XEvent ev;
158 memset(&ev, 0, sizeof(ev));
159 ev.xclient.type = ClientMessage;
160 ev.xclient.display = m_pDisplay;
161 ev.xclient.window = m_wOwner;
162 ev.xclient.message_type = XInternAtom(m_pDisplay, "_NET_ACTIVE_WINDOW", false);
163 ev.xclient.format = 32;
164 ev.xclient.data.l[0] = 0; // Source indication.
165 ev.xclient.data.l[1] = 0; // Timestamp.
166 ev.xclient.data.l[2] = 0; // Requestor's currently active window (none)
167 ev.xclient.data.l[3] = 0;
168 ev.xclient.data.l[4] = 0;
169 XSelectInput(m_pDisplay, m_wOwner, StructureNotifyMask);
170 XSendEvent(m_pDisplay, RootWindow(m_pDisplay, iScreen), false,
171 (SubstructureNotifyMask | SubstructureRedirectMask), &ev);
172 XSync(m_pDisplay, false);
173 XRaiseWindow(m_pDisplay, m_wOwner);
174 // And then, let it get caught on destination
175 // by QApplication::x11EventFilter...
176 QByteArray value = QSAMPLER_XUNIQUE;
177 XChangeProperty(
178 m_pDisplay,
179 m_wOwner,
180 m_aUnique,
181 m_aUnique, 8,
182 PropModeReplace,
183 (unsigned char *) value.data(),
184 value.length());
185 // Done.
186 return true;
187 }
188 #endif
189 return false;
190 }
191
192 #if defined(Q_WS_X11)
193 bool x11EventFilter(XEvent *pEv)
194 {
195 if (m_pWidget && m_wOwner != None
196 && pEv->type == PropertyNotify
197 && pEv->xproperty.window == m_wOwner
198 && pEv->xproperty.state == PropertyNewValue) {
199 // Always check whether our property-flag is still around...
200 Atom aType;
201 int iFormat = 0;
202 unsigned long iItems = 0;
203 unsigned long iAfter = 0;
204 unsigned char *pData = 0;
205 if (XGetWindowProperty(
206 m_pDisplay,
207 m_wOwner,
208 m_aUnique,
209 0, 1024,
210 false,
211 m_aUnique,
212 &aType,
213 &iFormat,
214 &iItems,
215 &iAfter,
216 &pData) == Success
217 && aType == m_aUnique && iItems > 0 && iAfter == 0) {
218 // Avoid repeating it-self...
219 XDeleteProperty(m_pDisplay, m_wOwner, m_aUnique);
220 // Just make it always shows up fine...
221 m_pWidget->show();
222 m_pWidget->raise();
223 m_pWidget->activateWindow();
224 }
225 // Free any left-overs...
226 if (iItems > 0 && pData)
227 XFree(pData);
228 }
229 return QApplication::x11EventFilter(pEv);
230 }
231 #endif
232
233 private:
234
235 // Translation support.
236 QTranslator *m_pQtTranslator;
237 QTranslator *m_pMyTranslator;
238
239 // Instance variables.
240 QWidget *m_pWidget;
241
242 #if defined(Q_WS_X11)
243 Display *m_pDisplay;
244 Atom m_aUnique;
245 Window m_wOwner;
246 #endif
247 };
248
249
250 //-------------------------------------------------------------------------
251 // stacktrace - Signal crash handler.
252 //
253
254 #ifdef CONFIG_STACKTRACE
255 #if defined(__GNUC__) && defined(Q_OS_LINUX)
256
257 #include <stdio.h>
258 #include <errno.h>
259 #include <signal.h>
260 #include <sys/wait.h>
261
262 void stacktrace ( int signo )
263 {
264 pid_t pid;
265 int rc;
266 int status = 0;
267 char cmd[80];
268
269 // Reinstall default handler; prevent race conditions...
270 signal(signo, SIG_DFL);
271
272 static const char *shell = "/bin/sh";
273 static const char *format = "gdb -q --batch --pid=%d"
274 " --eval-command='thread apply all bt'";
275
276 snprintf(cmd, sizeof(cmd), format, (int) getpid());
277
278 pid = fork();
279
280 // Fork failure!
281 if (pid < 0)
282 return;
283
284 // Fork child...
285 if (pid == 0) {
286 execl(shell, shell, "-c", cmd, NULL);
287 _exit(1);
288 return;
289 }
290
291 // Parent here: wait for child to terminate...
292 do { rc = waitpid(pid, &status, 0); }
293 while ((rc < 0) && (errno == EINTR));
294
295 // Dispatch any logging, if any...
296 QApplication::processEvents(QEventLoop::AllEvents, 3000);
297
298 // Make sure everyone terminates...
299 kill(pid, SIGTERM);
300 _exit(1);
301 }
302
303 #endif
304 #endif
305
306
307 //-------------------------------------------------------------------------
308 // main - The main program trunk.
309 //
310
311 int main ( int argc, char **argv )
312 {
313 Q_INIT_RESOURCE(qsampler);
314 #ifdef CONFIG_STACKTRACE
315 #if defined(__GNUC__) && defined(Q_OS_LINUX)
316 signal(SIGILL, stacktrace);
317 signal(SIGFPE, stacktrace);
318 signal(SIGSEGV, stacktrace);
319 signal(SIGABRT, stacktrace);
320 signal(SIGBUS, stacktrace);
321 #endif
322 #endif
323 qsamplerApplication app(argc, argv);
324
325 #if defined(__APPLE__) // Toshi Nagata 20080105
326 {
327 // Set the plugin path to @exetutable_path/../plugins
328 QDir dir(QApplication::applicationDirPath());
329 dir.cdUp(); // "Contents" directory
330 QApplication::setLibraryPaths(QStringList(dir.absolutePath() + "/plugins"));
331
332 // Set the PATH environment variable to include @executable_path/../../..
333 dir.cdUp();
334 dir.cdUp();
335 QString path(getenv("PATH"));
336 path = dir.absolutePath() + ":" + path;
337 setenv("PATH", path.toUtf8().constData(), 1);
338 }
339 #endif
340
341 // Construct default settings; override with command line arguments.
342 QSampler::Options options;
343 if (!options.parse_args(app.arguments())) {
344 app.quit();
345 return 1;
346 }
347
348 // Have another instance running?
349 if (app.setup()) {
350 app.quit();
351 return 2;
352 }
353
354 // Dark themes grayed/disabled color group fix...
355 QPalette pal(app.palette());
356 if (pal.base().color().value() < 0x7f) {
357 pal.setColorGroup(QPalette::Disabled,
358 pal.windowText().color().darker(),
359 pal.button(),
360 pal.light(),
361 pal.dark(),
362 pal.mid(),
363 pal.text().color().darker(),
364 pal.text().color().lighter(),
365 pal.base(),
366 pal.window());
367 app.setPalette(pal);
368 }
369
370 // Set default base font...
371 int iBaseFontSize = app.font().pointSize();
372 if (options.iBaseFontSize > 0)
373 iBaseFontSize = options.iBaseFontSize;
374 app.setFont(QFont(app.font().family(), iBaseFontSize));
375
376 // Construct, setup and show the main form.
377 QSampler::MainForm w;
378 w.setup(&options);
379 w.show();
380
381 // Settle this one as application main widget...
382 app.setMainWidget(&w);
383
384 // Register the quit signal/slot.
385 // app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
386
387 return app.exec();
388 }
389
390
391 // end of qsampler.cpp

  ViewVC Help
Powered by ViewVC