--- qsampler/trunk/src/qsampler.cpp 2013/07/08 10:06:57 2459 +++ qsampler/trunk/src/qsampler.cpp 2019/03/10 11:06:53 3496 @@ -1,8 +1,8 @@ // qsampler.cpp // /**************************************************************************** - Copyright (C) 2004-2013, rncbc aka Rui Nuno Capela. All rights reserved. - Copyright (C) 2007, 2008 Christian Schoenebeck + Copyright (C) 2004-2019, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2007,2008,2015 Christian Schoenebeck This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -20,11 +20,11 @@ *****************************************************************************/ -#include "qsamplerAbout.h" +#include "qsampler.h" + #include "qsamplerOptions.h" #include "qsamplerMainForm.h" -#include #include #include #include @@ -33,22 +33,15 @@ #include #endif -#define CONFIG_QUOTE1(x) #x -#define CONFIG_QUOTED(x) CONFIG_QUOTE1(x) - -#if defined(DATADIR) -#define CONFIG_DATADIR CONFIG_QUOTED(DATADIR) -#else -#define CONFIG_DATADIR CONFIG_PREFIX "/share" +#ifndef CONFIG_PREFIX +#define CONFIG_PREFIX "/usr/local" #endif -#if defined(LOCALEDIR) -#define CONFIG_LOCALEDIR CONFIG_QUOTED(LOCALEDIR) -#else -#define CONFIG_LOCALEDIR CONFIG_DATADIR "/locale" +#ifndef CONFIG_DATADIR +#define CONFIG_DATADIR CONFIG_PREFIX "/share" #endif -#if WIN32 +#if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) #define RELATIVE_LOCALE_DIR "/share/locale" #elif defined(__APPLE__) #define RELATIVE_LOCALE_DIR "/../Resources" @@ -59,113 +52,161 @@ // Singleton application instance stuff (Qt/X11 only atm.) // -#if defined(Q_WS_X11) +#ifdef CONFIG_XUNIQUE + +#define QSAMPLER_XUNIQUE "qsamplerApplication" + +#if QT_VERSION < 0x050000 +#ifdef CONFIG_X11 -#include +#include /* for gethostname() */ #include #include -#define QSAMPLER_XUNIQUE "qsamplerMainForm_xunique" - +#endif // CONFIG_X11 +#else +#include +#include +#include +#include #endif -class qsamplerApplication : public QApplication -{ -public: +#endif // CONFIG_XUNIQUE - // Constructor. - qsamplerApplication(int& argc, char **argv) : QApplication(argc, argv), - m_pQtTranslator(0), m_pMyTranslator(0), m_pWidget(0) - { - // Load translation support. - QLocale loc; - if (loc.language() != QLocale::C) { - // Try own Qt translation... - m_pQtTranslator = new QTranslator(this); - QString sLocName = "qt_" + loc.name(); - QString sLocPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); + +// Constructor. +qsamplerApplication::qsamplerApplication ( int& argc, char **argv ) + : QApplication(argc, argv), + m_pQtTranslator(NULL), m_pMyTranslator(NULL), m_pWidget(NULL) +{ + // Load translation support. + QLocale loc; + if (loc.language() != QLocale::C) { + // Try own Qt translation... + m_pQtTranslator = new QTranslator(this); + QString sLocName = "qt_" + loc.name(); + QString sLocPath = QLibraryInfo::location(QLibraryInfo::TranslationsPath); + if (m_pQtTranslator->load(sLocName, sLocPath)) { + QApplication::installTranslator(m_pQtTranslator); + } else { + #ifdef RELATIVE_LOCALE_DIR + sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR; if (m_pQtTranslator->load(sLocName, sLocPath)) { QApplication::installTranslator(m_pQtTranslator); } else { - #ifdef RELATIVE_LOCALE_DIR - sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR; - if (m_pQtTranslator->load(sLocName, sLocPath)) { - QApplication::installTranslator(m_pQtTranslator); - } else { #endif - delete m_pQtTranslator; - m_pQtTranslator = 0; + delete m_pQtTranslator; + m_pQtTranslator = 0; #ifdef CONFIG_DEBUG - qWarning("Warning: no translation found for '%s' locale: %s/%s.qm", - loc.name().toUtf8().constData(), - sLocPath.toUtf8().constData(), - sLocName.toUtf8().constData()); + qWarning("Warning: no translation found for '%s' locale: %s/%s.qm", + loc.name().toUtf8().constData(), + sLocPath.toUtf8().constData(), + sLocName.toUtf8().constData()); #endif #ifdef RELATIVE_LOCALE_DIR - } - #endif } - // Try own application translation... - m_pMyTranslator = new QTranslator(this); - sLocName = "qsampler_" + loc.name(); - if (m_pMyTranslator->load(sLocName, sLocPath)) { - QApplication::installTranslator(m_pMyTranslator); - } else { + #endif + } + // Try own application translation... + m_pMyTranslator = new QTranslator(this); + sLocName = "qsampler_" + loc.name(); + if (m_pMyTranslator->load(sLocName, sLocPath)) { + QApplication::installTranslator(m_pMyTranslator); + } else { #ifdef RELATIVE_LOCALE_DIR - sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR; + sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR; #else - sLocPath = CONFIG_LOCALEDIR; + sLocPath = CONFIG_DATADIR "/qsampler/translations"; #endif - if (m_pMyTranslator->load(sLocName, sLocPath)) { - QApplication::installTranslator(m_pMyTranslator); - } else { - delete m_pMyTranslator; - m_pMyTranslator = 0; - #ifdef CONFIG_DEBUG - qWarning("Warning: no translation found for '%s' locale: %s/%s.qm", - loc.name().toUtf8().constData(), - sLocPath.toUtf8().constData(), - sLocName.toUtf8().constData()); - #endif - } + if (m_pMyTranslator->load(sLocName, sLocPath)) { + QApplication::installTranslator(m_pMyTranslator); + } else { + delete m_pMyTranslator; + m_pMyTranslator = 0; + #ifdef CONFIG_DEBUG + qWarning("Warning: no translation found for '%s' locale: %s/%s.qm", + loc.name().toUtf8().constData(), + sLocPath.toUtf8().constData(), + sLocName.toUtf8().constData()); + #endif } } - #if defined(Q_WS_X11) - m_pDisplay = QX11Info::display(); - m_aUnique = XInternAtom(m_pDisplay, QSAMPLER_XUNIQUE, false); - XGrabServer(m_pDisplay); - m_wOwner = XGetSelectionOwner(m_pDisplay, m_aUnique); - XUngrabServer(m_pDisplay); - #endif } +#ifdef CONFIG_XUNIQUE +#if QT_VERSION < 0x050000 +#ifdef CONFIG_X11 + m_pDisplay = NULL; + m_aUnique = 0; + m_wOwner = 0; +#endif // CONFIG_X11 +#else + m_pMemory = NULL; + m_pServer = NULL; +#endif +#endif // CONFIG_XUNIQUE +} - // Destructor. - ~qsamplerApplication() - { - if (m_pMyTranslator) delete m_pMyTranslator; - if (m_pQtTranslator) delete m_pQtTranslator; + +// Destructor. +qsamplerApplication::~qsamplerApplication (void) +{ +#ifdef CONFIG_XUNIQUE +#if QT_VERSION >= 0x050000 + if (m_pServer) { + m_pServer->close(); + delete m_pServer; + m_pServer = NULL; } + if (m_pMemory) { + delete m_pMemory; + m_pMemory = NULL; +} +#endif +#endif // CONFIG_XUNIQUE + if (m_pMyTranslator) delete m_pMyTranslator; + if (m_pQtTranslator) delete m_pQtTranslator; +} - // Main application widget accessors. - void setMainWidget(QWidget *pWidget) - { - m_pWidget = pWidget; - #if defined(Q_WS_X11) + +// Main application widget accessors. +void qsamplerApplication::setMainWidget ( QWidget *pWidget ) +{ + m_pWidget = pWidget; +#ifdef CONFIG_XUNIQUE +#if QT_VERSION < 0x050000 +#ifdef CONFIG_X11 + m_wOwner = m_pWidget->winId(); + if (m_pDisplay && m_wOwner) { XGrabServer(m_pDisplay); - m_wOwner = m_pWidget->winId(); XSetSelectionOwner(m_pDisplay, m_aUnique, m_wOwner, CurrentTime); XUngrabServer(m_pDisplay); - #endif } +#endif // CONFIG_X11 +#endif +#endif // CONFIG_XUNIQUE +} - QWidget *mainWidget() const { return m_pWidget; } - // Check if another instance is running, - // and raise its proper main widget... - bool setup() - { - #if defined(Q_WS_X11) +// Check if another instance is running, +// and raise its proper main widget... +bool qsamplerApplication::setup (void) +{ +#ifdef CONFIG_XUNIQUE +#if QT_VERSION < 0x050000 +#ifdef CONFIG_X11 + m_pDisplay = QX11Info::display(); + if (m_pDisplay) { + QString sUnique = QSAMPLER_XUNIQUE; + char szHostName[255]; + if (::gethostname(szHostName, sizeof(szHostName)) == 0) { + sUnique += '@'; + sUnique += szHostName; + } + m_aUnique = XInternAtom(m_pDisplay, sUnique.toUtf8().constData(), false); + XGrabServer(m_pDisplay); + m_wOwner = XGetSelectionOwner(m_pDisplay, m_aUnique); + XUngrabServer(m_pDisplay); if (m_wOwner != None) { // First, notify any freedesktop.org WM // that we're about to show the main widget... @@ -189,8 +230,8 @@ XSync(m_pDisplay, false); XRaiseWindow(m_pDisplay, m_wOwner); // And then, let it get caught on destination - // by QApplication::x11EventFilter... - QByteArray value = QSAMPLER_XUNIQUE; + // by QApplication::native/x11EventFilter... + const QByteArray value = QSAMPLER_XUNIQUE; XChangeProperty( m_pDisplay, m_wOwner, @@ -202,66 +243,145 @@ // Done. return true; } - #endif - return false; } - -#if defined(Q_WS_X11) - bool x11EventFilter(XEvent *pEv) - { - if (m_pWidget && m_wOwner != None - && pEv->type == PropertyNotify - && pEv->xproperty.window == m_wOwner - && pEv->xproperty.state == PropertyNewValue) { - // Always check whether our property-flag is still around... - Atom aType; - int iFormat = 0; - unsigned long iItems = 0; - unsigned long iAfter = 0; - unsigned char *pData = 0; - if (XGetWindowProperty( - m_pDisplay, - m_wOwner, - m_aUnique, - 0, 1024, - false, - m_aUnique, - &aType, - &iFormat, - &iItems, - &iAfter, - &pData) == Success - && aType == m_aUnique && iItems > 0 && iAfter == 0) { - // Avoid repeating it-self... - XDeleteProperty(m_pDisplay, m_wOwner, m_aUnique); - // Just make it always shows up fine... - m_pWidget->show(); - m_pWidget->raise(); - m_pWidget->activateWindow(); - } - // Free any left-overs... - if (iItems > 0 && pData) - XFree(pData); +#endif // CONFIG_X11 + return false; +#else + m_sUnique = QCoreApplication::applicationName(); + m_sUnique += '@'; + m_sUnique += QHostInfo::localHostName(); +#ifdef Q_OS_UNIX + m_pMemory = new QSharedMemory(m_sUnique); + m_pMemory->attach(); + delete m_pMemory; +#endif + m_pMemory = new QSharedMemory(m_sUnique); + bool bServer = false; + const qint64 pid = QCoreApplication::applicationPid(); + struct Data { qint64 pid; }; + if (m_pMemory->create(sizeof(Data))) { + m_pMemory->lock(); + Data *pData = static_cast (m_pMemory->data()); + if (pData) { + pData->pid = pid; + bServer = true; + } + m_pMemory->unlock(); + } + else + if (m_pMemory->attach()) { + m_pMemory->lock(); // maybe not necessary? + Data *pData = static_cast (m_pMemory->data()); + if (pData) + bServer = (pData->pid == pid); + m_pMemory->unlock(); + } + if (bServer) { + QLocalServer::removeServer(m_sUnique); + m_pServer = new QLocalServer(); + m_pServer->setSocketOptions(QLocalServer::UserAccessOption); + m_pServer->listen(m_sUnique); + QObject::connect(m_pServer, + SIGNAL(newConnection()), + SLOT(newConnectionSlot())); + } else { + QLocalSocket socket; + socket.connectToServer(m_sUnique); + if (socket.state() == QLocalSocket::ConnectingState) + socket.waitForConnected(200); + if (socket.state() == QLocalSocket::ConnectedState) { + socket.write(QCoreApplication::arguments().join(' ').toUtf8()); + socket.flush(); + socket.waitForBytesWritten(200); } - return QApplication::x11EventFilter(pEv); } + return !bServer; #endif - -private: +#else + return false; +#endif // !CONFIG_XUNIQUE +} - // Translation support. - QTranslator *m_pQtTranslator; - QTranslator *m_pMyTranslator; - // Instance variables. - QWidget *m_pWidget; +#ifdef CONFIG_XUNIQUE +#if QT_VERSION < 0x050000 +#ifdef CONFIG_X11 + +void qsamplerApplication::x11PropertyNotify ( Window w ) +{ + if (m_pDisplay && m_pWidget && m_wOwner == w) { + // Always check whether our property-flag is still around... + Atom aType; + int iFormat = 0; + unsigned long iItems = 0; + unsigned long iAfter = 0; + unsigned char *pData = 0; + if (XGetWindowProperty( + m_pDisplay, + m_wOwner, + m_aUnique, + 0, 1024, + false, + m_aUnique, + &aType, + &iFormat, + &iItems, + &iAfter, + &pData) == Success + && aType == m_aUnique && iItems > 0 && iAfter == 0) { + // Avoid repeating it-self... + XDeleteProperty(m_pDisplay, m_wOwner, m_aUnique); + // Just make it always shows up fine... + m_pWidget->show(); + m_pWidget->raise(); + m_pWidget->activateWindow(); + } + // Free any left-overs... + if (iItems > 0 && pData) + XFree(pData); + } +} + + +bool qsamplerApplication::x11EventFilter ( XEvent *pEv ) +{ + if (pEv->type == PropertyNotify + && pEv->xproperty.state == PropertyNewValue) + x11PropertyNotify(pEv->xproperty.window); + return QApplication::x11EventFilter(pEv); +} + +#endif // CONFIG_X11 +#else + +// Local server conection slot. +void qsamplerApplication::newConnectionSlot (void) +{ + QLocalSocket *pSocket = m_pServer->nextPendingConnection(); + QObject::connect(pSocket, + SIGNAL(readyRead()), + SLOT(readyReadSlot())); +} + +// Local server data-ready slot. +void qsamplerApplication::readyReadSlot (void) +{ + QLocalSocket *pSocket = qobject_cast (sender()); + if (pSocket) { + const qint64 nread = pSocket->bytesAvailable(); + if (nread > 0) { + QByteArray data = pSocket->read(nread); + // Just make it always shows up fine... + m_pWidget->hide(); + m_pWidget->show(); + m_pWidget->raise(); + m_pWidget->activateWindow(); + } + } +} -#if defined(Q_WS_X11) - Display *m_pDisplay; - Atom m_aUnique; - Window m_wOwner; #endif -}; +#endif // CONFIG_XUNIQUE //------------------------------------------------------------------------- @@ -339,7 +459,9 @@ #endif #endif qsamplerApplication app(argc, argv); - +#if QT_VERSION >= 0x050600 + app.setAttribute(Qt::AA_EnableHighDpiScaling); +#endif #if defined(__APPLE__) // Toshi Nagata 20080105 { // Set the plugin path to @exetutable_path/../plugins @@ -399,10 +521,8 @@ } // Set default base font... - int iBaseFontSize = app.font().pointSize(); if (options.iBaseFontSize > 0) - iBaseFontSize = options.iBaseFontSize; - app.setFont(QFont(app.font().family(), iBaseFontSize)); + app.setFont(QFont(app.font().family(), options.iBaseFontSize)); // Construct, setup and show the main form. QSampler::MainForm w; @@ -420,3 +540,4 @@ // end of qsampler.cpp +