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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2987 - (hide annotations) (download)
Fri Sep 23 11:42:50 2016 UTC (7 years, 6 months ago) by capela
File size: 13108 byte(s)
- Almost complete overhaul on the configure script command
  line options, wrt. installation directories specification,
  eg. --prefix, --bindir, --libdir, --datadir and --mandir.
  (EXPERIMENTAL)
1 capela 2074 // qsampler.cpp
2     //
3     /****************************************************************************
4 capela 2987 Copyright (C) 2004-2016, rncbc aka Rui Nuno Capela. All rights reserved.
5 capela 2074 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 capela 2459
32 capela 2074 #if defined(__APPLE__) // Toshi Nagata 20080105
33     #include <QDir>
34     #endif
35    
36 persson 2210 #if WIN32
37     #define RELATIVE_LOCALE_DIR "/share/locale"
38     #elif defined(__APPLE__)
39     #define RELATIVE_LOCALE_DIR "/../Resources"
40     #endif
41 capela 2074
42 persson 2210
43 capela 2074 //-------------------------------------------------------------------------
44     // Singleton application instance stuff (Qt/X11 only atm.)
45     //
46    
47 capela 2839 #if QT_VERSION < 0x050000
48 capela 2074 #if defined(Q_WS_X11)
49 capela 2839 #define CONFIG_X11
50     #endif
51     #else
52     #if defined(QT_X11EXTRAS_LIB)
53     #define CONFIG_X11
54     #endif
55     #endif
56 capela 2074
57 capela 2839
58     #ifdef CONFIG_X11
59     #ifdef CONFIG_XUNIQUE
60    
61 capela 2074 #include <QX11Info>
62    
63     #include <X11/Xatom.h>
64     #include <X11/Xlib.h>
65    
66 capela 2839 #define QSAMPLER_XUNIQUE "qsamplerApplication"
67 capela 2074
68 capela 2839 #if QT_VERSION >= 0x050100
69    
70     #include <xcb/xcb.h>
71     #include <xcb/xproto.h>
72    
73     #include <QAbstractNativeEventFilter>
74    
75     class qsamplerApplication;
76    
77     class qsamplerXcbEventFilter : public QAbstractNativeEventFilter
78     {
79     public:
80    
81     // Constructor.
82     qsamplerXcbEventFilter(qsamplerApplication *pApp)
83     : QAbstractNativeEventFilter(), m_pApp(pApp) {}
84    
85     // XCB event filter (virtual processor).
86     bool nativeEventFilter(const QByteArray& eventType, void *message, long *);
87    
88     private:
89    
90     // Instance variable.
91     qsamplerApplication *m_pApp;
92     };
93    
94 capela 2074 #endif
95    
96 capela 2839 #endif // CONFIG_XUNIQUE
97     #endif // CONFIG_X11
98    
99    
100 capela 2074 class qsamplerApplication : public QApplication
101     {
102     public:
103    
104     // Constructor.
105     qsamplerApplication(int& argc, char **argv) : QApplication(argc, argv),
106 capela 2839 m_pQtTranslator(0), m_pMyTranslator(0), m_pWidget(0)
107 capela 2074 {
108     // Load translation support.
109     QLocale loc;
110     if (loc.language() != QLocale::C) {
111     // Try own Qt translation...
112     m_pQtTranslator = new QTranslator(this);
113     QString sLocName = "qt_" + loc.name();
114     QString sLocPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
115     if (m_pQtTranslator->load(sLocName, sLocPath)) {
116     QApplication::installTranslator(m_pQtTranslator);
117     } else {
118 capela 2631 #ifdef RELATIVE_LOCALE_DIR
119 persson 2210 sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR;
120 persson 2144 if (m_pQtTranslator->load(sLocName, sLocPath)) {
121     QApplication::installTranslator(m_pQtTranslator);
122     } else {
123 capela 2631 #endif
124 capela 2074 delete m_pQtTranslator;
125     m_pQtTranslator = 0;
126 capela 2631 #ifdef CONFIG_DEBUG
127 capela 2074 qWarning("Warning: no translation found for '%s' locale: %s/%s.qm",
128     loc.name().toUtf8().constData(),
129     sLocPath.toUtf8().constData(),
130     sLocName.toUtf8().constData());
131 capela 2631 #endif
132     #ifdef RELATIVE_LOCALE_DIR
133 persson 2144 }
134 capela 2631 #endif
135 capela 2074 }
136     // Try own application translation...
137     m_pMyTranslator = new QTranslator(this);
138     sLocName = "qsampler_" + loc.name();
139     if (m_pMyTranslator->load(sLocName, sLocPath)) {
140     QApplication::installTranslator(m_pMyTranslator);
141     } else {
142 capela 2631 #ifdef RELATIVE_LOCALE_DIR
143 persson 2210 sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR;
144 capela 2631 #else
145     sLocPath = CONFIG_DATADIR "/qsampler/translations";
146     #endif
147 capela 2074 if (m_pMyTranslator->load(sLocName, sLocPath)) {
148     QApplication::installTranslator(m_pMyTranslator);
149     } else {
150     delete m_pMyTranslator;
151     m_pMyTranslator = 0;
152 capela 2631 #ifdef CONFIG_DEBUG
153 capela 2074 qWarning("Warning: no translation found for '%s' locale: %s/%s.qm",
154     loc.name().toUtf8().constData(),
155     sLocPath.toUtf8().constData(),
156     sLocName.toUtf8().constData());
157 capela 2631 #endif
158 capela 2074 }
159     }
160     }
161 capela 2839 #ifdef CONFIG_X11
162     #ifdef CONFIG_XUNIQUE
163     // Instance uniqueness initialization...
164 capela 2074 m_pDisplay = QX11Info::display();
165     m_aUnique = XInternAtom(m_pDisplay, QSAMPLER_XUNIQUE, false);
166     XGrabServer(m_pDisplay);
167     m_wOwner = XGetSelectionOwner(m_pDisplay, m_aUnique);
168     XUngrabServer(m_pDisplay);
169 capela 2839 #if QT_VERSION >= 0x050100
170     m_pXcbEventFilter = new qsamplerXcbEventFilter(this);
171     installNativeEventFilter(m_pXcbEventFilter);
172 capela 2074 #endif
173 capela 2839 #endif // CONFIG_XUNIQUE
174     #endif // CONFIG_X11
175 capela 2074 }
176    
177     // Destructor.
178     ~qsamplerApplication()
179     {
180 capela 2839 #ifdef CONFIG_X11
181     #ifdef CONFIG_XUNIQUE
182     #if QT_VERSION >= 0x050100
183     removeNativeEventFilter(m_pXcbEventFilter);
184     delete m_pXcbEventFilter;
185     #endif
186     #endif // CONFIG_XUNIQUE
187     #endif // CONFIG_X11
188 capela 2074 if (m_pMyTranslator) delete m_pMyTranslator;
189     if (m_pQtTranslator) delete m_pQtTranslator;
190     }
191    
192     // Main application widget accessors.
193     void setMainWidget(QWidget *pWidget)
194     {
195     m_pWidget = pWidget;
196 capela 2839 #ifdef CONFIG_X11
197     #ifdef CONFIG_XUNIQUE
198 capela 2074 XGrabServer(m_pDisplay);
199     m_wOwner = m_pWidget->winId();
200     XSetSelectionOwner(m_pDisplay, m_aUnique, m_wOwner, CurrentTime);
201     XUngrabServer(m_pDisplay);
202 capela 2839 #endif // CONFIG_XUNIQUE
203     #endif // CONFIG_X11
204 capela 2074 }
205    
206     QWidget *mainWidget() const { return m_pWidget; }
207    
208     // Check if another instance is running,
209     // and raise its proper main widget...
210     bool setup()
211     {
212 capela 2839 #ifdef CONFIG_X11
213     #ifdef CONFIG_XUNIQUE
214 capela 2074 if (m_wOwner != None) {
215     // First, notify any freedesktop.org WM
216     // that we're about to show the main widget...
217     Screen *pScreen = XDefaultScreenOfDisplay(m_pDisplay);
218     int iScreen = XScreenNumberOfScreen(pScreen);
219     XEvent ev;
220     memset(&ev, 0, sizeof(ev));
221     ev.xclient.type = ClientMessage;
222     ev.xclient.display = m_pDisplay;
223     ev.xclient.window = m_wOwner;
224     ev.xclient.message_type = XInternAtom(m_pDisplay, "_NET_ACTIVE_WINDOW", false);
225     ev.xclient.format = 32;
226     ev.xclient.data.l[0] = 0; // Source indication.
227     ev.xclient.data.l[1] = 0; // Timestamp.
228     ev.xclient.data.l[2] = 0; // Requestor's currently active window (none)
229     ev.xclient.data.l[3] = 0;
230     ev.xclient.data.l[4] = 0;
231     XSelectInput(m_pDisplay, m_wOwner, StructureNotifyMask);
232     XSendEvent(m_pDisplay, RootWindow(m_pDisplay, iScreen), false,
233     (SubstructureNotifyMask | SubstructureRedirectMask), &ev);
234     XSync(m_pDisplay, false);
235     XRaiseWindow(m_pDisplay, m_wOwner);
236     // And then, let it get caught on destination
237 capela 2839 // by QApplication::native/x11EventFilter...
238     const QByteArray value = QSAMPLER_XUNIQUE;
239 capela 2074 XChangeProperty(
240     m_pDisplay,
241     m_wOwner,
242     m_aUnique,
243     m_aUnique, 8,
244     PropModeReplace,
245     (unsigned char *) value.data(),
246     value.length());
247     // Done.
248     return true;
249     }
250 capela 2839 #endif // CONFIG_XUNIQUE
251     #endif // CONFIG_X11
252 capela 2074 return false;
253     }
254    
255 capela 2839 #ifdef CONFIG_X11
256     #ifdef CONFIG_XUNIQUE
257     void x11PropertyNotify(Window w)
258 capela 2074 {
259 capela 2839 if (m_pWidget && m_wOwner == w) {
260 capela 2074 // Always check whether our property-flag is still around...
261     Atom aType;
262     int iFormat = 0;
263     unsigned long iItems = 0;
264     unsigned long iAfter = 0;
265     unsigned char *pData = 0;
266     if (XGetWindowProperty(
267     m_pDisplay,
268     m_wOwner,
269     m_aUnique,
270     0, 1024,
271     false,
272     m_aUnique,
273     &aType,
274     &iFormat,
275     &iItems,
276     &iAfter,
277     &pData) == Success
278     && aType == m_aUnique && iItems > 0 && iAfter == 0) {
279     // Avoid repeating it-self...
280     XDeleteProperty(m_pDisplay, m_wOwner, m_aUnique);
281     // Just make it always shows up fine...
282     m_pWidget->show();
283     m_pWidget->raise();
284     m_pWidget->activateWindow();
285     }
286     // Free any left-overs...
287     if (iItems > 0 && pData)
288     XFree(pData);
289     }
290 capela 2839 }
291     #if QT_VERSION < 0x050000
292     bool x11EventFilter(XEvent *pEv)
293     {
294     if (pEv->type == PropertyNotify
295     && pEv->xproperty.state == PropertyNewValue)
296     x11PropertyNotify(pEv->xproperty.window);
297 capela 2074 return QApplication::x11EventFilter(pEv);
298     }
299     #endif
300 capela 2839 #endif // CONFIG_XUNIQUE
301     #endif // CONFIG_X11
302 capela 2074
303     private:
304    
305     // Translation support.
306     QTranslator *m_pQtTranslator;
307     QTranslator *m_pMyTranslator;
308    
309     // Instance variables.
310     QWidget *m_pWidget;
311    
312 capela 2839 #ifdef CONFIG_X11
313     #ifdef CONFIG_XUNIQUE
314 capela 2074 Display *m_pDisplay;
315     Atom m_aUnique;
316     Window m_wOwner;
317 capela 2839 #if QT_VERSION >= 0x050100
318     qsamplerXcbEventFilter *m_pXcbEventFilter;
319 capela 2074 #endif
320 capela 2839 #endif // CONFIG_XUNIQUE
321     #endif // CONFIG_X11
322 capela 2074 };
323    
324    
325 capela 2839 #ifdef CONFIG_X11
326     #ifdef CONFIG_XUNIQUE
327     #if QT_VERSION >= 0x050100
328     // XCB Event filter (virtual processor).
329     bool qsamplerXcbEventFilter::nativeEventFilter (
330     const QByteArray& eventType, void *message, long * )
331     {
332     if (eventType == "xcb_generic_event_t") {
333     xcb_property_notify_event_t *pEv
334     = static_cast<xcb_property_notify_event_t *> (message);
335     if ((pEv->response_type & ~0x80) == XCB_PROPERTY_NOTIFY
336     && pEv->state == XCB_PROPERTY_NEW_VALUE)
337     m_pApp->x11PropertyNotify(pEv->window);
338     }
339     return false;
340     }
341     #endif
342     #endif // CONFIG_XUNIQUE
343     #endif // CONFIG_X11
344    
345    
346 capela 2074 //-------------------------------------------------------------------------
347     // stacktrace - Signal crash handler.
348     //
349    
350     #ifdef CONFIG_STACKTRACE
351     #if defined(__GNUC__) && defined(Q_OS_LINUX)
352    
353     #include <stdio.h>
354     #include <errno.h>
355     #include <signal.h>
356 capela 2341 #include <unistd.h>
357 capela 2074 #include <sys/wait.h>
358    
359     void stacktrace ( int signo )
360     {
361     pid_t pid;
362     int rc;
363     int status = 0;
364     char cmd[80];
365    
366     // Reinstall default handler; prevent race conditions...
367     signal(signo, SIG_DFL);
368    
369     static const char *shell = "/bin/sh";
370 capela 2181 static const char *format = "gdb -q --batch --pid=%d"
371     " --eval-command='thread apply all bt'";
372 capela 2074
373     snprintf(cmd, sizeof(cmd), format, (int) getpid());
374    
375     pid = fork();
376    
377     // Fork failure!
378     if (pid < 0)
379     return;
380    
381     // Fork child...
382     if (pid == 0) {
383     execl(shell, shell, "-c", cmd, NULL);
384     _exit(1);
385     return;
386     }
387    
388     // Parent here: wait for child to terminate...
389     do { rc = waitpid(pid, &status, 0); }
390     while ((rc < 0) && (errno == EINTR));
391    
392     // Dispatch any logging, if any...
393     QApplication::processEvents(QEventLoop::AllEvents, 3000);
394    
395     // Make sure everyone terminates...
396     kill(pid, SIGTERM);
397     _exit(1);
398     }
399    
400     #endif
401     #endif
402    
403    
404     //-------------------------------------------------------------------------
405     // main - The main program trunk.
406     //
407    
408     int main ( int argc, char **argv )
409     {
410     Q_INIT_RESOURCE(qsampler);
411     #ifdef CONFIG_STACKTRACE
412     #if defined(__GNUC__) && defined(Q_OS_LINUX)
413     signal(SIGILL, stacktrace);
414     signal(SIGFPE, stacktrace);
415     signal(SIGSEGV, stacktrace);
416     signal(SIGABRT, stacktrace);
417     signal(SIGBUS, stacktrace);
418     #endif
419     #endif
420     qsamplerApplication app(argc, argv);
421    
422     #if defined(__APPLE__) // Toshi Nagata 20080105
423     {
424     // Set the plugin path to @exetutable_path/../plugins
425     QDir dir(QApplication::applicationDirPath());
426     dir.cdUp(); // "Contents" directory
427     QApplication::setLibraryPaths(QStringList(dir.absolutePath() + "/plugins"));
428    
429     // Set the PATH environment variable to include @executable_path/../../..
430     dir.cdUp();
431     dir.cdUp();
432     QString path(getenv("PATH"));
433     path = dir.absolutePath() + ":" + path;
434     setenv("PATH", path.toUtf8().constData(), 1);
435     }
436     #endif
437    
438     // Construct default settings; override with command line arguments.
439     QSampler::Options options;
440     if (!options.parse_args(app.arguments())) {
441     app.quit();
442     return 1;
443     }
444    
445     // Have another instance running?
446     if (app.setup()) {
447     app.quit();
448     return 2;
449     }
450    
451     // Dark themes grayed/disabled color group fix...
452     QPalette pal(app.palette());
453     if (pal.base().color().value() < 0x7f) {
454 capela 2415 #if QT_VERSION >= 0x050000
455     const QColor& color = pal.window().color();
456     const int iGroups = int(QPalette::Active | QPalette::Inactive) + 1;
457     for (int i = 0; i < iGroups; ++i) {
458     const QPalette::ColorGroup group = QPalette::ColorGroup(i);
459     pal.setBrush(group, QPalette::Light, color.lighter(150));
460     pal.setBrush(group, QPalette::Midlight, color.lighter(120));
461     pal.setBrush(group, QPalette::Dark, color.darker(150));
462     pal.setBrush(group, QPalette::Mid, color.darker(120));
463     pal.setBrush(group, QPalette::Shadow, color.darker(200));
464     }
465     // pal.setColor(QPalette::Disabled, QPalette::ButtonText, pal.mid().color());
466     #endif
467 capela 2074 pal.setColorGroup(QPalette::Disabled,
468     pal.windowText().color().darker(),
469     pal.button(),
470     pal.light(),
471     pal.dark(),
472     pal.mid(),
473     pal.text().color().darker(),
474     pal.text().color().lighter(),
475     pal.base(),
476     pal.window());
477     app.setPalette(pal);
478     }
479    
480     // Set default base font...
481     if (options.iBaseFontSize > 0)
482 capela 2677 app.setFont(QFont(app.font().family(), options.iBaseFontSize));
483 capela 2074
484     // Construct, setup and show the main form.
485     QSampler::MainForm w;
486     w.setup(&options);
487     w.show();
488    
489     // Settle this one as application main widget...
490     app.setMainWidget(&w);
491    
492     // Register the quit signal/slot.
493     // app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
494    
495     return app.exec();
496     }
497    
498    
499     // end of qsampler.cpp

  ViewVC Help
Powered by ViewVC