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

Annotation of /qsampler/trunk/src/qsampler.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2181 - (hide annotations) (download)
Sun Jun 5 10:21:53 2011 UTC (12 years, 10 months ago) by capela
File size: 10247 byte(s)
* Debugging stacktrace now applies to all working threads.
1 capela 2074 // 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 persson 2144 #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 capela 2074 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 persson 2144 #if WIN32
89     }
90     #endif
91 capela 2074 }
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 persson 2144 #if WIN32
99     sLocPath = QApplication::applicationDirPath() + "/share/locale";
100     #else
101 capela 2074 sLocPath = CONFIG_PREFIX "/share/locale";
102 persson 2144 #endif
103 capela 2074 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 capela 2181 static const char *format = "gdb -q --batch --pid=%d"
274     " --eval-command='thread apply all bt'";
275 capela 2074
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