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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC