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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC