--- qsampler/trunk/src/qsampler.cpp 2010/10/06 18:49:54 2144 +++ qsampler/trunk/src/qsampler.cpp 2015/08/25 18:36:55 2839 @@ -1,7 +1,7 @@ // qsampler.cpp // /**************************************************************************** - Copyright (C) 2004-2010, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2004-2015, rncbc aka Rui Nuno Capela. All rights reserved. Copyright (C) 2007, 2008 Christian Schoenebeck This program is free software; you can redistribute it and/or @@ -28,13 +28,24 @@ #include #include #include + #if defined(__APPLE__) // Toshi Nagata 20080105 #include #endif -#if QT_VERSION < 0x040300 -#define lighter(x) light(x) -#define darker(x) dark(x) +#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" +#endif + +#if WIN32 +#define RELATIVE_LOCALE_DIR "/share/locale" +#elif defined(__APPLE__) +#define RELATIVE_LOCALE_DIR "/../Resources" #endif @@ -42,24 +53,66 @@ // Singleton application instance stuff (Qt/X11 only atm.) // +#if QT_VERSION < 0x050000 #if defined(Q_WS_X11) +#define CONFIG_X11 +#endif +#else +#if defined(QT_X11EXTRAS_LIB) +#define CONFIG_X11 +#endif +#endif + + +#ifdef CONFIG_X11 +#ifdef CONFIG_XUNIQUE #include #include #include -#define QSAMPLER_XUNIQUE "qsamplerMainForm_xunique" +#define QSAMPLER_XUNIQUE "qsamplerApplication" + +#if QT_VERSION >= 0x050100 + +#include +#include + +#include + +class qsamplerApplication; + +class qsamplerXcbEventFilter : public QAbstractNativeEventFilter +{ +public: + + // Constructor. + qsamplerXcbEventFilter(qsamplerApplication *pApp) + : QAbstractNativeEventFilter(), m_pApp(pApp) {} + + // XCB event filter (virtual processor). + bool nativeEventFilter(const QByteArray& eventType, void *message, long *); + +private: + + // Instance variable. + qsamplerApplication *m_pApp; +}; #endif +#endif // CONFIG_XUNIQUE +#endif // CONFIG_X11 + + class qsamplerApplication : public QApplication { public: // Constructor. qsamplerApplication(int& argc, char **argv) : QApplication(argc, argv), - m_pQtTranslator(0), m_pMyTranslator(0), m_pWidget(0) + m_pQtTranslator(0), m_pMyTranslator(0), m_pWidget(0) { // Load translation support. QLocale loc; @@ -71,23 +124,23 @@ if (m_pQtTranslator->load(sLocName, sLocPath)) { QApplication::installTranslator(m_pQtTranslator); } else { - #if WIN32 - sLocPath = QApplication::applicationDirPath() + "/share/locale"; + #ifdef RELATIVE_LOCALE_DIR + sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR; if (m_pQtTranslator->load(sLocName, sLocPath)) { QApplication::installTranslator(m_pQtTranslator); } else { - #endif + #endif delete m_pQtTranslator; m_pQtTranslator = 0; - #ifdef CONFIG_DEBUG + #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 WIN32 + #endif + #ifdef RELATIVE_LOCALE_DIR } - #endif + #endif } // Try own application translation... m_pMyTranslator = new QTranslator(this); @@ -95,37 +148,52 @@ if (m_pMyTranslator->load(sLocName, sLocPath)) { QApplication::installTranslator(m_pMyTranslator); } else { - #if WIN32 - sLocPath = QApplication::applicationDirPath() + "/share/locale"; - #else - sLocPath = CONFIG_PREFIX "/share/locale"; - #endif + #ifdef RELATIVE_LOCALE_DIR + sLocPath = QApplication::applicationDirPath() + RELATIVE_LOCALE_DIR; + #else + 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 + #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 + #endif } } } - #if defined(Q_WS_X11) + #ifdef CONFIG_X11 + #ifdef CONFIG_XUNIQUE + // Instance uniqueness initialization... 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); + #if QT_VERSION >= 0x050100 + m_pXcbEventFilter = new qsamplerXcbEventFilter(this); + installNativeEventFilter(m_pXcbEventFilter); #endif + #endif // CONFIG_XUNIQUE + #endif // CONFIG_X11 } // Destructor. ~qsamplerApplication() { + #ifdef CONFIG_X11 + #ifdef CONFIG_XUNIQUE + #if QT_VERSION >= 0x050100 + removeNativeEventFilter(m_pXcbEventFilter); + delete m_pXcbEventFilter; + #endif + #endif // CONFIG_XUNIQUE + #endif // CONFIG_X11 if (m_pMyTranslator) delete m_pMyTranslator; if (m_pQtTranslator) delete m_pQtTranslator; } @@ -134,12 +202,14 @@ void setMainWidget(QWidget *pWidget) { m_pWidget = pWidget; - #if defined(Q_WS_X11) + #ifdef CONFIG_X11 + #ifdef CONFIG_XUNIQUE XGrabServer(m_pDisplay); m_wOwner = m_pWidget->winId(); XSetSelectionOwner(m_pDisplay, m_aUnique, m_wOwner, CurrentTime); XUngrabServer(m_pDisplay); - #endif + #endif // CONFIG_XUNIQUE + #endif // CONFIG_X11 } QWidget *mainWidget() const { return m_pWidget; } @@ -148,7 +218,8 @@ // and raise its proper main widget... bool setup() { - #if defined(Q_WS_X11) + #ifdef CONFIG_X11 + #ifdef CONFIG_XUNIQUE if (m_wOwner != None) { // First, notify any freedesktop.org WM // that we're about to show the main widget... @@ -172,8 +243,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, @@ -185,17 +256,16 @@ // Done. return true; } - #endif + #endif // CONFIG_XUNIQUE + #endif // CONFIG_X11 return false; } -#if defined(Q_WS_X11) - bool x11EventFilter(XEvent *pEv) +#ifdef CONFIG_X11 +#ifdef CONFIG_XUNIQUE + void x11PropertyNotify(Window w) { - if (m_pWidget && m_wOwner != None - && pEv->type == PropertyNotify - && pEv->xproperty.window == m_wOwner - && pEv->xproperty.state == PropertyNewValue) { + if (m_pWidget && m_wOwner == w) { // Always check whether our property-flag is still around... Atom aType; int iFormat = 0; @@ -226,9 +296,18 @@ if (iItems > 0 && pData) XFree(pData); } + } +#if QT_VERSION < 0x050000 + bool x11EventFilter(XEvent *pEv) + { + if (pEv->type == PropertyNotify + && pEv->xproperty.state == PropertyNewValue) + x11PropertyNotify(pEv->xproperty.window); return QApplication::x11EventFilter(pEv); } #endif +#endif // CONFIG_XUNIQUE +#endif // CONFIG_X11 private: @@ -239,14 +318,40 @@ // Instance variables. QWidget *m_pWidget; -#if defined(Q_WS_X11) +#ifdef CONFIG_X11 +#ifdef CONFIG_XUNIQUE Display *m_pDisplay; Atom m_aUnique; Window m_wOwner; +#if QT_VERSION >= 0x050100 + qsamplerXcbEventFilter *m_pXcbEventFilter; #endif +#endif // CONFIG_XUNIQUE +#endif // CONFIG_X11 }; +#ifdef CONFIG_X11 +#ifdef CONFIG_XUNIQUE +#if QT_VERSION >= 0x050100 +// XCB Event filter (virtual processor). +bool qsamplerXcbEventFilter::nativeEventFilter ( + const QByteArray& eventType, void *message, long * ) +{ + if (eventType == "xcb_generic_event_t") { + xcb_property_notify_event_t *pEv + = static_cast (message); + if ((pEv->response_type & ~0x80) == XCB_PROPERTY_NOTIFY + && pEv->state == XCB_PROPERTY_NEW_VALUE) + m_pApp->x11PropertyNotify(pEv->window); + } + return false; +} +#endif +#endif // CONFIG_XUNIQUE +#endif // CONFIG_X11 + + //------------------------------------------------------------------------- // stacktrace - Signal crash handler. // @@ -257,6 +362,7 @@ #include #include #include +#include #include void stacktrace ( int signo ) @@ -270,7 +376,8 @@ signal(signo, SIG_DFL); static const char *shell = "/bin/sh"; - static const char *format = "gdb -q --batch --pid=%d --eval-command=bt"; + static const char *format = "gdb -q --batch --pid=%d" + " --eval-command='thread apply all bt'"; snprintf(cmd, sizeof(cmd), format, (int) getpid()); @@ -353,6 +460,19 @@ // Dark themes grayed/disabled color group fix... QPalette pal(app.palette()); if (pal.base().color().value() < 0x7f) { + #if QT_VERSION >= 0x050000 + const QColor& color = pal.window().color(); + const int iGroups = int(QPalette::Active | QPalette::Inactive) + 1; + for (int i = 0; i < iGroups; ++i) { + const QPalette::ColorGroup group = QPalette::ColorGroup(i); + pal.setBrush(group, QPalette::Light, color.lighter(150)); + pal.setBrush(group, QPalette::Midlight, color.lighter(120)); + pal.setBrush(group, QPalette::Dark, color.darker(150)); + pal.setBrush(group, QPalette::Mid, color.darker(120)); + pal.setBrush(group, QPalette::Shadow, color.darker(200)); + } + // pal.setColor(QPalette::Disabled, QPalette::ButtonText, pal.mid().color()); + #endif pal.setColorGroup(QPalette::Disabled, pal.windowText().color().darker(), pal.button(), @@ -367,10 +487,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;