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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC