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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC