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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2210 - (hide annotations) (download)
Mon Jul 18 08:18:36 2011 UTC (12 years, 9 months ago) by persson
File size: 10437 byte(s)
* Made lookup of translation files work inside a Mac OS X bundle
* Minor Mac OS X compilation error fix

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

  ViewVC Help
Powered by ViewVC