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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2210 - (show 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 // 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 #if WIN32
41 #define RELATIVE_LOCALE_DIR "/share/locale"
42 #elif defined(__APPLE__)
43 #define RELATIVE_LOCALE_DIR "/../Resources"
44 #endif
45
46
47 //-------------------------------------------------------------------------
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 #ifdef RELATIVE_LOCALE_DIR
81 sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR;
82 if (m_pQtTranslator->load(sLocName, sLocPath)) {
83 QApplication::installTranslator(m_pQtTranslator);
84 } else {
85 #endif
86 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 #ifdef RELATIVE_LOCALE_DIR
95 }
96 #endif
97 }
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 #ifdef RELATIVE_LOCALE_DIR
105 sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR;
106 #else
107 sLocPath = CONFIG_PREFIX "/share/locale";
108 #endif
109 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 static const char *format = "gdb -q --batch --pid=%d"
280 " --eval-command='thread apply all bt'";
281
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