diff --git a/Modules/QtWidgets/CMakeLists.txt b/Modules/QtWidgets/CMakeLists.txt index 94b31c19d1..881d6b9344 100644 --- a/Modules/QtWidgets/CMakeLists.txt +++ b/Modules/QtWidgets/CMakeLists.txt @@ -1,8 +1,8 @@ MITK_CREATE_MODULE( INCLUDE_DIRS PRIVATE resource # for xpm includes DEPENDS MitkPlanarFigure MitkOverlays - PACKAGE_DEPENDS PUBLIC VTK|vtkGUISupportQt+vtkGUISupportQtOpenGL Qt4|QtGui+QtOpenGL Qt5|Widgets+OpenGL + PACKAGE_DEPENDS PUBLIC VTK|vtkGUISupportQt+vtkGUISupportQtOpenGL Qt4|QtGui+QtOpenGL Qt5|Widgets+OpenGL+Core SUBPROJECTS MITK-CoreUI ) add_subdirectory(test) diff --git a/Modules/QtWidgets/src/QmitkMimeTypes.cpp b/Modules/QtWidgets/src/QmitkMimeTypes.cpp index e1411f576c..9674fcbe3f 100644 --- a/Modules/QtWidgets/src/QmitkMimeTypes.cpp +++ b/Modules/QtWidgets/src/QmitkMimeTypes.cpp @@ -1,44 +1,46 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkMimeTypes.h" const QString QmitkMimeTypes::DataNodePtrs = "application/x-qmitk-datanode-ptrs"; const QString QmitkMimeTypes::DataStorageTreeItemPtrs = "application/x-qmitk-datastorage-treeitem-ptrs"; #include +#include + QList QmitkMimeTypes::ToDataNodePtrList(const QByteArray &ba) { QDataStream ds(ba); QList result; while(!ds.atEnd()) { quintptr dataNodePtr; ds >> dataNodePtr; result.push_back(reinterpret_cast(dataNodePtr)); } return result; } QList QmitkMimeTypes::ToDataNodePtrList(const QMimeData *mimeData) { if (mimeData == nullptr || !mimeData->hasFormat(QmitkMimeTypes::DataNodePtrs)) { return QList(); } return ToDataNodePtrList(mimeData->data(QmitkMimeTypes::DataNodePtrs)); } diff --git a/Utilities/qtsingleapplication/qthandlenewappinstance.cpp b/Utilities/qtsingleapplication/qthandlenewappinstance.cpp index b01e755d12..cd9e4d0826 100644 --- a/Utilities/qtsingleapplication/qthandlenewappinstance.cpp +++ b/Utilities/qtsingleapplication/qthandlenewappinstance.cpp @@ -1,147 +1,149 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "qthandlenewappinstance.h" #include "qtsingleapplication.h" +#include + #if QT_VERSION < 0x050000 #include #include // mkdtemp #ifdef Q_OS_UNIX #include #endif #ifdef Q_OS_WIN #include //#include #endif bool createTemporaryDir(QString& path) { QString baseName = QCoreApplication::applicationName(); if (baseName.isEmpty()) { baseName = QLatin1String("mitk_temp"); } QString templateName = QDir::tempPath() + QLatin1Char('/') + baseName + QLatin1String("-XXXXXX"); bool success = false; #ifdef Q_OS_WIN QString buffer = templateName; // Windows' mktemp believes 26 temp files per process ought to be enough for everyone (!) // Let's add a few random chars then, before the XXXXXX template. for (int i = 0 ; i < 4 ; ++i) buffer += QChar((qrand() & 0xffff) % (26) + 'A'); if (!buffer.endsWith(QLatin1String("XXXXXX"))) buffer += QLatin1String("XXXXXX"); //QFileSystemEntry baseEntry(buffer); //QFileSystemEntry::NativePath basePath = baseEntry.nativeFilePath(); QString basePath = QDir::toNativeSeparators(buffer); wchar_t* array = (wchar_t*)basePath.utf16(); if (_wmktemp(array) && ::CreateDirectoryW(array, 0)) { success = true; //QFileSystemEntry entry(QString::fromWCharArray(array), QFileSystemEntry::FromNativePath()); //path = entry.filePath(); path = QDir::fromNativeSeparators(QString::fromUtf16((const ushort*)array)); } #else QByteArray buffer = QFile::encodeName(templateName); if (!buffer.endsWith("XXXXXX")) buffer += "XXXXXX"; if (mkdtemp(buffer.data())) { // modifies buffer success = true; path = QFile::decodeName(buffer.constData()); } #endif return success; } #else #include bool createTemporaryDir(QString& path) { QString baseName = QCoreApplication::applicationName(); if (baseName.isEmpty()) { baseName = QLatin1String("mitk_temp"); } QString templateName = QDir::tempPath() + QLatin1Char('/') + baseName + QLatin1String("-XXXXXX"); QTemporaryDir tmpDir(templateName); tmpDir.setAutoRemove(false); if (tmpDir.isValid()) { path = tmpDir.path(); return true; } return false; } #endif QString handleNewAppInstance(QtSingleApplication* singleApp, int argc, char** argv, const QString& newInstanceArg) { if (singleApp->isRunning()) { QStringList args; bool newInstance = false; for (int i = 0; i < argc; ++i) { args << argv[i]; if (args.back().endsWith(newInstanceArg)) { newInstance = true; } } if (newInstance) { QString path; if (!createTemporaryDir(path)) { qCritical("Could not create temporary storage path for new application instance."); exit(EXIT_FAILURE); } qWarning("Forcing new application instance. The application data will be written to a temporary directory."); return path; } else { QByteArray ba; QDataStream msg(&ba, QIODevice::WriteOnly); msg << QString("$cmdLineArgs"); // This message contains command line arguments msg << args; if(singleApp->sendMessage(ba)) { exit(EXIT_SUCCESS); } else { qCritical("The running application seems to be frozen."); exit(EXIT_FAILURE); } } } return QString(); } diff --git a/Utilities/qtsingleapplication/qtlocalpeer.cpp b/Utilities/qtsingleapplication/qtlocalpeer.cpp index 7b3e5c666f..b55a53d8e0 100644 --- a/Utilities/qtsingleapplication/qtlocalpeer.cpp +++ b/Utilities/qtsingleapplication/qtlocalpeer.cpp @@ -1,201 +1,202 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Solutions component. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names ** of its contributors may be used to endorse or promote products derived ** from this software without specific prior written permission. ** ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qtlocalpeer.h" #include +#include #include #if defined(Q_OS_WIN) #include #include typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*); static PProcessIdToSessionId pProcessIdToSessionId = 0; #endif #if defined(Q_OS_UNIX) #include #include #include #endif namespace QtLP_Private { #include "qtlockedfile.cpp" #if defined(Q_OS_WIN) #include "qtlockedfile_win.cpp" #else #include "qtlockedfile_unix.cpp" #endif } const char* QtLocalPeer::ack = "ack"; QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId) : QObject(parent), id(appId) { QString prefix = id; if (id.isEmpty()) { id = QCoreApplication::applicationFilePath(); #if defined(Q_OS_WIN) id = id.toLower(); #endif prefix = id.section(QLatin1Char('/'), -1); } prefix.remove(QRegExp("[^a-zA-Z]")); prefix.truncate(6); QByteArray idc = id.toUtf8(); quint16 idNum = qChecksum(idc.constData(), idc.size()); socketName = QLatin1String("qtsingleapp-") + prefix + QLatin1Char('-') + QString::number(idNum, 16); #if defined(Q_OS_WIN) if (!pProcessIdToSessionId) { QLibrary lib("kernel32"); pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); } if (pProcessIdToSessionId) { DWORD sessionId = 0; pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); socketName += QLatin1Char('-') + QString::number(sessionId, 16); } #else socketName += QLatin1Char('-') + QString::number(::getuid(), 16); #endif server = new QLocalServer(this); QString lockName = QDir(QDir::tempPath()).absolutePath() + QLatin1Char('/') + socketName + QLatin1String("-lockfile"); lockFile.setFileName(lockName); lockFile.open(QIODevice::ReadWrite); } bool QtLocalPeer::isClient() { if (lockFile.isLocked()) return false; if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false)) return true; bool res = server->listen(socketName); #if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0)) // ### Workaround if (!res && server->serverError() == QAbstractSocket::AddressInUseError) { QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName); res = server->listen(socketName); } #endif if (!res) qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString())); QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection())); return false; } bool QtLocalPeer::sendMessage(const QByteArray &message, int timeout) { if (!isClient()) return false; QLocalSocket socket; bool connOk = false; for(int i = 0; i < 2; i++) { // Try twice, in case the other instance is just starting up socket.connectToServer(socketName); connOk = socket.waitForConnected(timeout/2); if (connOk || i) break; int ms = 250; #if defined(Q_OS_WIN) Sleep(DWORD(ms)); #else struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; nanosleep(&ts, nullptr); #endif } if (!connOk) return false; QDataStream ds(&socket); ds.writeBytes(message.constData(), message.size()); bool res = socket.waitForBytesWritten(timeout); if (res) { res &= socket.waitForReadyRead(timeout); // wait for ack if (res) res &= (socket.read(qstrlen(ack)) == ack); } return res; } void QtLocalPeer::receiveConnection() { QLocalSocket* socket = server->nextPendingConnection(); if (!socket) return; while (socket->bytesAvailable() < (int)sizeof(quint32)) socket->waitForReadyRead(); QDataStream ds(socket); QByteArray uMsg; quint32 remaining; ds >> remaining; uMsg.resize(remaining); int got = 0; char* uMsgBuf = uMsg.data(); do { got = ds.readRawData(uMsgBuf, remaining); remaining -= got; uMsgBuf += got; } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); if (got < 0) { qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData()); delete socket; return; } socket->write(ack, qstrlen(ack)); socket->waitForBytesWritten(1000); socket->waitForDisconnected(1000); // make sure client reads ack delete socket; emit messageReceived(uMsg); //### (might take a long time to return) }