diff --git a/Application/Ui/CMakeLists.txt b/Application/Ui/CMakeLists.txt index 0e7133f6fb84b3ca48a0271719bf80e60533af97..8b9bf61514e442a967fbff755de28126f10e2cd7 100644 --- a/Application/Ui/CMakeLists.txt +++ b/Application/Ui/CMakeLists.txt @@ -19,8 +19,8 @@ add_library(ApplicationUi Widgets/vvSelectFramesDialog.ui Widgets/images/resources.qrc - pqLidarViewManager.cxx - pqLidarViewManager.h + lqLidarViewManager.cxx + lqLidarViewManager.h lqOpenPcapReaction.cxx lqOpenPcapReaction.h lqOpenRecentFilesReaction.cxx @@ -29,7 +29,7 @@ add_library(ApplicationUi lqOpenSensorReaction.h lqUpdateCalibrationReaction.cxx lqUpdateCalibrationReaction.h - vvPythonQtDecorators.h + lqPythonQtLidarView.h # LV Specific PythonQt Decorators ) target_link_libraries(ApplicationUi PUBLIC ParaView::pqCore diff --git a/Application/Ui/lqLidarViewManager.cxx b/Application/Ui/lqLidarViewManager.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ecec2918465de989686a35782c650def6d63bd3c --- /dev/null +++ b/Application/Ui/lqLidarViewManager.cxx @@ -0,0 +1,73 @@ +/*========================================================================= + + Program: LidarView + Module: lqLidarViewManager.cxx + + Copyright (c) Kitware Inc. + All rights reserved. + + LidarView is a free software; you can redistribute it and/or modify it + under the terms of the LidarView license. + + See LICENSE for the full LidarView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +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 AUTHORS 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. + +========================================================================*/ +#include "lqLidarViewManager.h" + +#include "lqPythonQtLidarView.h" +#include "lqOpenPcapReaction.h" + +#include <QFileInfo> + +//----------------------------------------------------------------------------- +lqLidarViewManager::lqLidarViewManager(QObject* parent /*=nullptr*/) + : Superclass(parent) +{ + +} + +//----------------------------------------------------------------------------- +lqLidarViewManager::~lqLidarViewManager() +{ + +} +//----------------------------------------------------------------------------- +void lqLidarViewManager::pythonStartup() +{ + // Register LidarView specific decorators first + PythonQt::self()->addDecorators(new lqPythonQtLidarView(this)); + + Superclass::pythonStartup(); +} + + +//----------------------------------------------------------------------------- +void lqLidarViewManager::openData(const QString& filename) +{ + if (QFileInfo(filename).suffix() == "pcap") + { + lqOpenPcapReaction::createSourceFromFile(filename); + } + else + { + this->runPython(QString("lv.openData('%1')\n").arg(filename)); + } +} + diff --git a/Application/Ui/lqLidarViewManager.h b/Application/Ui/lqLidarViewManager.h new file mode 100644 index 0000000000000000000000000000000000000000..a6d78380c41f4951c1c1fe284439f9386f0566dd --- /dev/null +++ b/Application/Ui/lqLidarViewManager.h @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: LidarView + Module: lqLidarViewManager.h + + Copyright (c) Kitware Inc. + All rights reserved. + + LidarView is a free software; you can redistribute it and/or modify it + under the terms of the LidarView license. + + See LICENSE for the full LidarView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +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 AUTHORS 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. + +========================================================================*/ +#ifndef LQLIDARVIEWMANAGER_H +#define LQLIDARVIEWMANAGER_H + +#include <lqLidarCoreManager.h> + +#include "applicationui_export.h" + +class APPLICATIONUI_EXPORT lqLidarViewManager : public lqLidarCoreManager +{ + + Q_OBJECT + typedef lqLidarCoreManager Superclass; + +public: + + lqLidarViewManager(QObject* parent = nullptr); + ~lqLidarViewManager() override; + + /** + * Returns the pqPVApplicationCore instance. If no pqPVApplicationCore has been + * created then return nullptr. + */ + static lqLidarViewManager* instance() + { + return qobject_cast<lqLidarViewManager*>(Superclass::instance()); + } + + // LidarView specific + void pythonStartup() override; + + void openData(const QString& filename); +}; + +#endif // LQLIDARVIEWMANAGER_H diff --git a/Application/Ui/lqOpenPcapReaction.cxx b/Application/Ui/lqOpenPcapReaction.cxx index 9ad219eaffdd9f99f49f0fa427463c4e8a7d7dd9..b2672a463b1375832757f503bfd25bb398fe3a1e 100644 --- a/Application/Ui/lqOpenPcapReaction.cxx +++ b/Application/Ui/lqOpenPcapReaction.cxx @@ -17,7 +17,7 @@ #include "lqHelper.h" #include "lqUpdateCalibrationReaction.h" -#include "pqLidarViewManager.h" +#include "lqLidarViewManager.h" #include "vvCalibrationDialog.h" #include "lqSensorListWidget.h" @@ -94,7 +94,7 @@ void lqOpenPcapReaction::createSourceFromFile(QString fileName) // Launch the calibration Dialog before creating the Source to allow to cancel the action // (with the "cancel" button in the dialog) - vvCalibrationDialog dialog(pqLidarViewManager::instance()->getMainWindow()); + vvCalibrationDialog dialog(lqLidarViewManager::instance()->getMainWindow()); //DisplayDialogOnActiveWindow(dialog); if (!dialog.exec()) { @@ -102,7 +102,7 @@ void lqOpenPcapReaction::createSourceFromFile(QString fileName) } // Create a progress bar so the user see that VeloView is running - QProgressDialog progress("Reading pcap", "", 0, 0, pqLidarViewManager::getMainWindow()); + QProgressDialog progress("Reading pcap", "", 0, 0, lqLidarViewManager::getMainWindow()); progress.setCancelButton(nullptr); progress.setModal(true); progress.show(); @@ -143,6 +143,7 @@ void lqOpenPcapReaction::createSourceFromFile(QString fileName) // To get the pqPipelineSource modified with the new property, you have to connect to the signal // "dataUpdated" of the pqServerManagerModel pqPipelineSource* lidarSource = builder->createSource("sources", "LidarReader", server); + lidarSource->setModifiedState(pqProxy::UNMODIFIED); vtkSMPropertyHelper(lidarSource->getProxy(), "FileName").Set(fileName.toStdString().c_str()); lidarSource->getProxy()->UpdateProperty("FileName"); QString lidarName = lidarSource->getSMName(); @@ -167,6 +168,7 @@ void lqOpenPcapReaction::createSourceFromFile(QString fileName) inputs.push_back(lidarSource->getOutputPort(0)); namedInputs["Input"] = inputs; pqPipelineSource* trailingFrameFilter = builder->createFilter("filters", "TrailingFrame", namedInputs, server); + trailingFrameFilter->setModifiedState(pqProxy::UNMODIFIED); QString trailingFrameName = trailingFrameFilter->getSMName(); // Set the trailing frame associated to the sensor Widget @@ -174,7 +176,7 @@ void lqOpenPcapReaction::createSourceFromFile(QString fileName) listSensor->setSourceToDisplayToLidarSourceWidget(lidarSource, trailingFrameFilter); //Update applogic to be able to use function only define in applogic. - pqLidarViewManager::instance()->runPython(QString("lv.UpdateApplogicReader('%1', '%2', '%3')\n").arg(lidarName, posOrName, trailingFrameName)); + lqLidarViewManager::instance()->runPython(QString("lv.UpdateApplogicReader('%1', '%2', '%3')\n").arg(lidarName, posOrName, trailingFrameName)); // Show the trailing frame controller->Show(trailingFrameFilter->getSourceProxy(), 0, view->getViewProxy()); diff --git a/Application/Ui/lqOpenSensorReaction.cxx b/Application/Ui/lqOpenSensorReaction.cxx index c1508fc279af05ffc17597ca8cb99b0971d266c9..0ef852a5ade5c5ce29a3bacd5a83da16dc08f450 100644 --- a/Application/Ui/lqOpenSensorReaction.cxx +++ b/Application/Ui/lqOpenSensorReaction.cxx @@ -17,7 +17,7 @@ #include "lqHelper.h" #include "lqUpdateCalibrationReaction.h" -#include "pqLidarViewManager.h" +#include "lqLidarViewManager.h" #include "vvCalibrationDialog.h" #include "lqSensorListWidget.h" @@ -41,7 +41,7 @@ void lqOpenSensorReaction::onTriggered() // Launch the calibration Dialog before creating the Source to allow to cancel the action // (with the "cancel" button in the dialog) - vvCalibrationDialog dialog(pqLidarViewManager::instance()->getMainWindow()); + vvCalibrationDialog dialog(lqLidarViewManager::instance()->getMainWindow()); DisplayDialogOnActiveWindow(dialog); if (!dialog.exec()) { @@ -69,6 +69,7 @@ void lqOpenSensorReaction::onTriggered() // To get the pqPipelineSource modified with the new property, you have to connect to the signal // "dataUpdated" of the pqServerManagerModel pqPipelineSource* lidarSource = builder->createSource("sources", "LidarStream", server); + lidarSource->setModifiedState(pqProxy::UNMODIFIED); QString lidarName = lidarSource->getSMName(); controller->Show(lidarSource->getSourceProxy(), 0, view->getViewProxy()); @@ -91,5 +92,5 @@ void lqOpenSensorReaction::onTriggered() lidarSource->getProxy()->InvokeCommand("Start"); //Update applogic to be able to use function only define in applogic. - pqLidarViewManager::instance()->runPython(QString("lv.UpdateApplogicLidar('%1', '%2')\n").arg(lidarName, posOrName)); + lqLidarViewManager::instance()->runPython(QString("lv.UpdateApplogicLidar('%1', '%2')\n").arg(lidarName, posOrName)); } diff --git a/Application/Ui/lqPythonQtLidarView.h b/Application/Ui/lqPythonQtLidarView.h new file mode 100644 index 0000000000000000000000000000000000000000..182b27d06ac73f849b7db6d46a0023baba8c97b8 --- /dev/null +++ b/Application/Ui/lqPythonQtLidarView.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: LidarView + Module: lqPythonQtLidarView.h + + Copyright (c) Kitware Inc. + All rights reserved. + + LidarView is a free software; you can redistribute it and/or modify it + under the terms of the LidarView license. + + See LICENSE for the full LidarView license. + A copy of this license can be obtained by contacting + Kitware Inc. + 28 Corporate Drive + Clifton Park, NY 12065 + USA + +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 AUTHORS 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. + +========================================================================*/ +#ifndef lqPythonQtLidarView_h +#define lqPythonQtLidarView_h + +#include <PythonQt.h> +#include <QObject> + +#include "Widgets/vvCropReturnsDialog.h" +#include "Widgets/vvSelectFramesDialog.h" + +//WIP Could thinks about subclassing and rework how manager add it +class lqPythonQtLidarView : public QObject +{ + Q_OBJECT + +public: + lqPythonQtLidarView(QObject* parent = 0) + : QObject(parent) + { + this->registerClassForPythonQt(&vvCropReturnsDialog::staticMetaObject); + this->registerClassForPythonQt(&vvSelectFramesDialog::staticMetaObject); + } + + inline void registerClassForPythonQt(const QMetaObject* metaobject) + { + PythonQt::self()->registerClass(metaobject, "paraview"); + } + +public slots: + + vvCropReturnsDialog* new_vvCropReturnsDialog(QWidget* arg0) + { + return new vvCropReturnsDialog(arg0); + } + + vvSelectFramesDialog* new_vvSelectFramesDialog(QWidget* arg0) + { + return new vvSelectFramesDialog(arg0); + } +}; + +#endif //lqPythonQtLidarView_h diff --git a/Application/Ui/lqUpdateCalibrationReaction.cxx b/Application/Ui/lqUpdateCalibrationReaction.cxx index 9bfee62a5742b341cb55528683cde91c3e196b9b..ae6000b80e3f810047b12144c74f1013ba9d88e7 100644 --- a/Application/Ui/lqUpdateCalibrationReaction.cxx +++ b/Application/Ui/lqUpdateCalibrationReaction.cxx @@ -18,7 +18,7 @@ #include "lqHelper.h" #include "lqSensorListWidget.h" -#include "pqLidarViewManager.h" +#include "lqLidarViewManager.h" #include "vvCalibrationDialog.h" #include <cctype> @@ -185,6 +185,7 @@ void lqUpdateCalibrationReaction::UpdateCalibration(pqPipelineSource* & lidarSou { // If the Lidar Source is a stream, we created a Position Orientation Stream posOrSource = builder->createSource("sources", "PositionOrientationStream", server); + posOrSource->setModifiedState(pqProxy::UNMODIFIED); posOrProxy = posOrSource->getProxy(); posOrSource->getProxy()->InvokeCommand("Start"); } @@ -193,6 +194,7 @@ void lqUpdateCalibrationReaction::UpdateCalibration(pqPipelineSource* & lidarSou // If the Lidar Source is a Lidar Reader we created a Position Orientation Reader // And we set the filename to interpret to the same as the Lidar one. posOrSource = builder->createSource("sources", "PositionOrientationReader", server); + posOrSource->setModifiedState(pqProxy::UNMODIFIED); vtkSMProperty * lidarFileNameProperty = lidarProxy->GetProperty("FileName"); std::string pcapFileName = vtkSMPropertyHelper(lidarFileNameProperty).GetAsString(); vtkSMPropertyHelper(posOrSource->getProxy(), "FileName").Set(pcapFileName.c_str()); @@ -241,7 +243,7 @@ void lqUpdateCalibrationReaction::UpdateExistingSource(pqPipelineSource* & lidar // Create the dialog with the proxy so the dialog has the proxy information vvCalibrationDialog dialog(lidarSource->getProxy(), posOrProxy, - pqLidarViewManager::instance()->getMainWindow()); + lqLidarViewManager::instance()->getMainWindow()); DisplayDialogOnActiveWindow(dialog); // Launch the calibration Dialog diff --git a/Application/Ui/pqLidarViewManager.cxx b/Application/Ui/pqLidarViewManager.cxx deleted file mode 100644 index 7b3a6531466ea10c6a8bb29a73f400b627f09f6c..0000000000000000000000000000000000000000 --- a/Application/Ui/pqLidarViewManager.cxx +++ /dev/null @@ -1,406 +0,0 @@ -// Copyright 2013 Velodyne Acoustics, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include "pqLidarViewManager.h" - -#include "LASFileWriter.h" -#include "vtkPVConfig.h" // needed for PARAVIEW_VERSION -#include "vtkLidarReader.h" -#include "vvPythonQtDecorators.h" -#include "lqOpenPcapReaction.h" - -#include <pqActiveObjects.h> -#include <pqApplicationCore.h> -#include <pqDataRepresentation.h> -#include <pqPVApplicationCore.h> -#include <pqPersistentMainWindowStateBehavior.h> -#include <pqPipelineSource.h> -#include <pqPythonShell.h> -#include <pqPythonManager.h> -#include <pqRenderView.h> -#include <pqServer.h> -#include <pqServerManagerModel.h> -#include <pqSettings.h> -#include <pqView.h> - -#include <vtkSMPropertyHelper.h> -#include <vtkSMSourceProxy.h> -#include <vtkSMViewProxy.h> - -#include <vtkFieldData.h> -#include <vtkPointData.h> -#include <vtkPythonInterpreter.h> -#include <vtkTimerLog.h> - -#include <QApplication> -#include <QDir> -#include <QFileInfo> -#include <QLabel> -#include <QMainWindow> -#include <QMessageBox> -#include <QProcess> -#include <QProgressDialog> -#include <QTimer> - -#include <sstream> - -// Use LV_PYTHON_VERSION supplied at build time -#ifndef LV_PYTHON_VERSION - #error "LV_PYTHON_VERSION not defined" -#endif -static_assert( LV_PYTHON_VERSION, "LV_PYTHON_VERSION is not defined" ); // For good measure - -//----------------------------------------------------------------------------- -class pqLidarViewManager::pqInternal -{ -}; - -//----------------------------------------------------------------------------- -QPointer<pqLidarViewManager> pqLidarViewManagerInstance = NULL; - -//----------------------------------------------------------------------------- -pqLidarViewManager* pqLidarViewManager::instance() -{ - if (!pqLidarViewManagerInstance) - { - pqLidarViewManagerInstance = new pqLidarViewManager(pqApplicationCore::instance()); - } - - return pqLidarViewManagerInstance; -} - -//----------------------------------------------------------------------------- -pqLidarViewManager::pqLidarViewManager(QObject* p) - : QObject(p) -{ - this->Internal = new pqInternal; -} - -//----------------------------------------------------------------------------- -pqLidarViewManager::~pqLidarViewManager() -{ - delete this->Internal; -} - -//----------------------------------------------------------------------------- -void pqLidarViewManager::pythonStartup() -{ - QStringList pythonDirs; - pythonDirs << QCoreApplication::applicationDirPath() - << QCoreApplication::applicationDirPath() + "/../Libraries" // use lidarpluginpython module from packaging MacOS - << QCoreApplication::applicationDirPath() + "/../Python/" // use lidarview module from install MacOS - << QCoreApplication::applicationDirPath() + "/../lib/pythonLV_PYTHON_VERSION/site-packages/" // use lidarview module from install Linux - << QCoreApplication::applicationDirPath() + "/Lib/site-packages/"; // use lidarview module from install Windows - - foreach (const QString& dirname, pythonDirs) - { - if (QDir(dirname).exists()) - { - vtkPythonInterpreter::PrependPythonPath(dirname.toUtf8().data()); - } - } - - PythonQt::self()->addDecorators(new vvPythonQtDecorators()); - - this->runPython(QString( - "import PythonQt\n" - "QtGui = PythonQt.QtGui\n" - "QtCore = PythonQt.QtCore\n" - "import lidarview.applogic as lv\n" - "lv.start()\n")); - - pqSettings* const settings = pqApplicationCore::instance()->settings(); - const QVariant& gridVisible = - settings->value("LidarPlugin/MeasurementGrid/Visibility", true); - - // Save the current main window state as its original state. This happens in - // two cases: The first time launching the application or when launching it - // with older/wrong settings which were cleared right before. - bool shouldSave = true; - - QStringList keys = settings->allKeys(); - for (int keyIndex = 0; keyIndex < keys.size(); ++keyIndex) - { - if (keys[keyIndex].contains("OriginalMainWindow")) - { - shouldSave = false; - break; - } - } - - if (shouldSave) - { - std::cout << "First time launching the application, " - "saving current state as original state..." - << std::endl; - - QMainWindow* mainWindow = qobject_cast<QMainWindow*>(getMainWindow()); - - settings->saveState(*mainWindow, "OriginalMainWindow"); - - // Saving an OriginalMainWondow state means that wasn't created beforehand. - new pqPersistentMainWindowStateBehavior(mainWindow); - } - - this->onMeasurementGrid(gridVisible.toBool()); -} - -//----------------------------------------------------------------------------- -void pqLidarViewManager::runPython(const QString& statements) -{ - if(this->pythonShell) - { - this->pythonShell->executeScript(statements); - } -} - -//----------------------------------------------------------------------------- -void pqLidarViewManager::onEnableCrashAnalysis(bool crashAnalysisEnabled) -{ - pqSettings* const Settings = pqApplicationCore::instance()->settings(); - Settings->setValue("LidarPlugin/MainWindow/EnableCrashAnalysis", crashAnalysisEnabled); -} - -//----------------------------------------------------------------------------- -void pqLidarViewManager::onResetDefaultSettings() -{ - QMessageBox messageBox; - messageBox.setIcon(QMessageBox::Warning); - std::stringstream ss; - ss << "This action will reset " << SOFTWARE_NAME << " settings. " - << "Some settings will need " << SOFTWARE_NAME << " to restart to be completly reset. " - << "Every unsaved change will be lost. Are you sure you want to reset " << SOFTWARE_NAME << " settings?"; - messageBox.setText(ss.str().c_str()); - messageBox.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok); - - if (messageBox.exec() == QMessageBox::Ok) - { - pqApplicationCore* const app = pqApplicationCore::instance(); - pqSettings* const settings = app->settings(); - QMainWindow* const mainWindow = qobject_cast<QMainWindow*>(getMainWindow()); - - // Restore the original main window state before clearing settings, as clearing - // settings doesn't update the UI. - settings->restoreState("OriginalMainWindow", *mainWindow); - - settings->clear(); - - // Resave the current main window state as the original main window state in - // the settings - settings->saveState(*mainWindow, "OriginalMainWindow"); - - // Quit the current application instance and restart a new one. - qApp->quit(); - QProcess::startDetached(qApp->arguments()[0]); - } -} - -//----------------------------------------------------------------------------- -void pqLidarViewManager::saveFramesToPCAP( - vtkSMSourceProxy* proxy, int startFrame, int endFrame, const QString& filename) -{ - if (!proxy) - { - return; - } - - vtkLidarReader* reader = vtkLidarReader::SafeDownCast(proxy->GetClientSideObject()); - if (!reader) - { - return; - } - - reader->Open(); - reader->SaveFrame(startFrame, endFrame, filename.toUtf8().data()); - reader->Close(); -} - -//----------------------------------------------------------------------------- -void pqLidarViewManager::saveFramesToLAS(vtkLidarReader* reader, vtkPolyData* position, - int startFrame, int endFrame, const QString& filename, int positionMode) -{ - if (!reader || (positionMode > 0 && !position)) - { - return; - } - - // initialize origin point - double northing, easting, height; - easting = northing = height = 0; - - // projection transform parameters - int gcs, in, out, utmZone; - gcs = in = out = utmZone = 0; - - // data accuracy - double neTol, hTol; - hTol = neTol = 1e-3; - - bool isLatLon = false; - - LASFileWriter writer; - writer.Open(qPrintable(filename)); - - // not sensor relative; it can be - // relative registered data or - // georeferenced data - if (positionMode > 0) - { - - // Georeferenced data - if (positionMode > 1) - { - // Since the data are georeferenced here, we must - // check that a position reader is provided - if (position) - { - vtkDataArray* const zoneData = position->GetFieldData()->GetArray("zone"); - vtkDataArray* const eastingData = position->GetPointData()->GetArray("easting"); - vtkDataArray* const northingData = position->GetPointData()->GetArray("northing"); - vtkDataArray* const heightData = position->GetPointData()->GetArray("height"); - - if (zoneData && zoneData->GetNumberOfTuples() && eastingData && - eastingData->GetNumberOfTuples() && northingData && northingData->GetNumberOfTuples() && - heightData && heightData->GetNumberOfTuples()) - { - // We assume that eastingData, norhtingData and heightData are in system reference - // coordinates (srs) of UTM zoneData - utmZone = static_cast<int>(zoneData->GetComponent(0, 0)); - - // should in some cases use 32700? 32600 is for northern UTM zone, 32700 for southern UTM zone - gcs = 32600 + utmZone; - - out = gcs; - if (positionMode == 3) // Absolute lat/lon - { - in = gcs; // ...or 32700? - out = 4326; // lat/lon (espg id code for lat-long-alt coordinates) - neTol = 1e-8; // about 1mm; - isLatLon = true; - } - - northing = northingData->GetComponent(0, 0); - easting = eastingData->GetComponent(0, 0); - height = heightData->GetComponent(0, 0); - } - } - } - } - - std::cout << "origin : [" << northing << ";" << easting << ";" << height << "]" << std::endl; - std::cout << "gcs : " << gcs << std::endl; - - writer.SetPrecision(neTol, hTol); - writer.SetGeoConversionUTM(utmZone, isLatLon); - writer.SetOrigin(easting, northing, height); - - QProgressDialog progress("Exporting LAS...", "Abort Export", startFrame, - startFrame + (endFrame - startFrame) * 2, getMainWindow()); - progress.setWindowModality(Qt::WindowModal); - - reader->Open(); - for (int frame = startFrame; frame <= endFrame; ++frame) - { - progress.setValue(frame); - - if (progress.wasCanceled()) - { - reader->Close(); - return; - } - - const vtkSmartPointer<vtkPolyData>& data = reader->GetFrame(frame); - writer.UpdateMetaData(data.GetPointer()); - } - - writer.FlushMetaData(); - - for (int frame = startFrame; frame <= endFrame; ++frame) - { - progress.setValue(endFrame + (frame - startFrame)); - - if (progress.wasCanceled()) - { - reader->Close(); - return; - } - - const vtkSmartPointer<vtkPolyData>& data = reader->GetFrame(frame); - writer.WriteFrame(data.GetPointer()); - } - - reader->Close(); -} - -//----------------------------------------------------------------------------- -void pqLidarViewManager::setup() -{ - QTimer::singleShot(0, this, SLOT(pythonStartup())); -} - -//----------------------------------------------------------------------------- -void pqLidarViewManager::setPythonShell(pqPythonShell* shell) -{ - this->pythonShell = shell; -} - -//----------------------------------------------------------------------------- -void pqLidarViewManager::openData(const QString& filename) -{ - if (QFileInfo(filename).suffix() == "pcap") - { - lqOpenPcapReaction::createSourceFromFile(filename); - } - else - { - this->runPython(QString("lv.openData('%1')\n").arg(filename)); - } -} - -//----------------------------------------------------------------------------- -void pqLidarViewManager::onMeasurementGrid(bool gridVisible) -{ - pqSettings* settings = pqApplicationCore::instance()->settings(); - settings->setValue("LidarPlugin/MeasurementGrid/Visibility", gridVisible); - - if (gridVisible) - { - this->runPython("lv.showMeasurementGrid()\n"); - } - else - { - this->runPython("lv.hideMeasurementGrid()\n"); - } -} - -//----------------------------------------------------------------------------- -pqServer* pqLidarViewManager::getActiveServer() -{ - pqApplicationCore* app = pqApplicationCore::instance(); - pqServerManagerModel* smModel = app->getServerManagerModel(); - pqServer* server = smModel->getItemAtIndex<pqServer*>(0); - return server; -} - -//----------------------------------------------------------------------------- -QWidget* pqLidarViewManager::getMainWindow() -{ - foreach (QWidget* topWidget, QApplication::topLevelWidgets()) - { - if (qobject_cast<QMainWindow*>(topWidget)) - { - return topWidget; - } - } - return NULL; -} diff --git a/Application/Ui/pqLidarViewManager.h b/Application/Ui/pqLidarViewManager.h deleted file mode 100644 index b4950cf0847194004975fee60632b67e200f5245..0000000000000000000000000000000000000000 --- a/Application/Ui/pqLidarViewManager.h +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2013 Velodyne Acoustics, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef __pqLidarViewManager_h -#define __pqLidarViewManager_h - -#include <QObject> -#include "applicationui_export.h" - -class vtkLidarReader; -class vvAppLogic; - -class pqPipelineSource; -class pqServer; -class pqView; -class pqPythonShell; - -class vtkSMSourceProxy; - -class vtkPolyData; - -class QAction; -class QLabel; -class QWidget; - -class APPLICATIONUI_EXPORT pqLidarViewManager : public QObject -{ - - Q_OBJECT - -public: - static pqLidarViewManager* instance(); - - virtual ~pqLidarViewManager(); - - /// Convenience function for getting the current server. - static pqServer* getActiveServer(); - - /// Convenience function for getting the main window. - static QWidget* getMainWindow(); - - /// Convenience function for destroying a pipeline object and all of its - /// consumers. - // static void destroyPipelineSourceAndConsumers(pqPipelineSource *source); - - /// Finds a pipeline source with the given SM XML name. If there is more than - /// one, the first is returned. - // static pqPipelineSource *findPipelineSource(const char *SMName); - - void setSource(pqPipelineSource* source); - pqPipelineSource* source(); - - void setup(); - void setPythonShell(pqPythonShell* pythonShell); - - void openData(const QString& filename); - - void runPython(const QString& statements); - - static void saveFramesToPCAP( - vtkSMSourceProxy* proxy, int startFrame, int endFrame, const QString& filename); - - static void saveFramesToLAS(vtkLidarReader* reader, vtkPolyData* position, int startFrame, - int endFrame, const QString& filename, int positionMode); - -public slots: - - void pythonStartup(); - - void onMeasurementGrid(bool gridVisible); - void onEnableCrashAnalysis(bool crashAnalysisEnabled); - void onResetDefaultSettings(); - -signals: - - void sourceCreated(); - -private: - pqLidarViewManager(QObject* p); - - class pqInternal; - pqInternal* Internal; - pqPythonShell* pythonShell; - - Q_DISABLE_COPY(pqLidarViewManager); -}; - -#endif diff --git a/Application/Ui/python/lidarview/applogic.py b/Application/Ui/python/lidarview/applogic.py index 6a15fcaccb7c8d063c85cabcf58f00ed7bfe8c52..82cf70dc8057451581c779543b63261529a5955b 100644 --- a/Application/Ui/python/lidarview/applogic.py +++ b/Application/Ui/python/lidarview/applogic.py @@ -16,7 +16,6 @@ import os import csv import datetime import math -import sys import paraview.simple as smp from paraview import servermanager from paraview import vtk @@ -35,38 +34,15 @@ from PythonQt.paraview import vvCropReturnsDialog, vvSelectFramesDialog # import the vtk wrapping of the Lidar Plugin # this enable to get the specific vtkObject behind a proxy via GetClientSideObject() # without this plugin, GetClientSideObject(), would return the first mother class known by paraview -import LidarPlugin.LidarCore +import LidarPlugin.LidarCore # NOQA import lidarview.planefit as planefit -_repCache = {} - -SAMPLE_PROCESSING_MODE = False - -def vtkGetFileNameFromPluginName(pluginName): - import os - if os.name == "nt": - return pluginName + ".dll"; - elif sys.platform == "darwin": - return "lib" + pluginName + ".dylib"; - else: - return "lib" + pluginName + ".so"; - -def cachedGetRepresentation(src, view): - try: - return _repCache[(src, view)] - except KeyError: - rep = smp.GetRepresentation(src, view) - _repCache[(src, view)] = rep - return rep - class AppLogic(object): def __init__(self): self.createStatusBarWidgets() - self.mousePressed = False - mainView = smp.GetActiveView() self.mainView = mainView @@ -80,11 +56,6 @@ class AppLogic(object): self.gridProperties = None - #Not plugins anymore, kept for future reference - #smp.LoadPlugin(vtkGetFileNameFromPluginName('PointCloudPlugin')) - #smp.LoadPlugin(vtkGetFileNameFromPluginName('EyeDomeLightingView')) - - def createStatusBarWidgets(self): self.logoLabel = QtGui.QLabel() @@ -96,7 +67,6 @@ class AppLogic(object): self.sensorInformationLabel = QtGui.QLabel() self.positionPacketInfoLabel = QtGui.QLabel() - class GridProperties: def __init__(self): @@ -108,8 +78,7 @@ class GridProperties: self.Color = [0, 0, 0] self.Persist = False - - +# Array Helper def hasArrayName(sourceProxy, arrayName): ''' Returns True if the data has non-zero points and has a point data @@ -129,10 +98,10 @@ def hasArrayName(sourceProxy, arrayName): return True return False - +# Used by lqLidarViewManager def openData(filename): - close() + onClose() reader = smp.OpenDataFile(filename, guiName='Data') @@ -155,7 +124,7 @@ def openData(filename): app.actions['actionCropReturns'].setEnabled(False) app.actions['actionShowRPM'].enabled = True - +# Action Related Logic def planeFit(): planefit.fitPlane(app.actions['actionSpreadsheet']) @@ -259,17 +228,6 @@ def setDefaultLookupTables(sourceProxy): +1.0, 1.0, 0.9, 0.4], Annotations=['-1', 'low', '0', 'dual', '1', 'high']) - # LUT for 'laser_id'. This LUT is extracted from the XML calibration file - # which doesn't exist in live stream mode - if False and getReader() is not None: - rgbRaw = [0] * 256 - sourceProxy.GetClientSideObject().GetXMLColorTable(rgbRaw) - - smp.GetLookupTableForArray( - 'laser_id', 1, - ScalarRangeInitialized=1.0, - ColorSpace='RGB', - RGBPoints=rgbRaw) def getTimeStamp(): format = '%Y-%m-%d-%H-%M-%S' @@ -281,9 +239,6 @@ def getReaderFileName(): return filename[0] if isinstance(filename, servermanager.FileNameProperty) else filename -def setDefaultSaveName(defaultSaveName): - app.DefaultSaveName = defaultSaveName - def getDefaultSaveFileName(extension, suffix='', appendFrameNumber=False): sensor = getSensor() @@ -304,21 +259,16 @@ def getDefaultSaveFileName(extension, suffix='', appendFrameNumber=False): suffix = '%s (Frame %04d)' % (suffix, int(app.scene.AnimationTime)) return '%s%s.%s' % (basename, suffix, extension) +# Used by Ui/lqOpenPcapReaction Ui/lqOpenSensorReaction def UpdateApplogicLidar(lidarProxyName, gpsProxyName): sensor = smp.FindSource(lidarProxyName) - if not app.grid : - app.grid = createGrid() - sensor.UpdatePipeline() if gpsProxyName: app.position = smp.FindSource(gpsProxyName) - if SAMPLE_PROCESSING_MODE: - processor = smp.ProcessingSample(sensor) - smp.GetActiveView().ViewTime = 0.0 app.sensor = sensor @@ -332,14 +282,6 @@ def UpdateApplogicLidar(lidarProxyName, gpsProxyName): onCropReturns(False) # Dont show the dialog just restore settings -# rep = smp.Show(sensor) -# rep.InterpolateScalarsBeforeMapping = 0 -# if app.sensor.GetClientSideObject().GetNumberOfChannels() == 128: -# rep.Representation = 'Point Cloud' -# rep.ColorArrayName = 'intensity' - - if SAMPLE_PROCESSING_MODE: - smp.Show(processor) smp.Render() showSourceInSpreadSheet(sensor) @@ -348,12 +290,12 @@ def UpdateApplogicLidar(lidarProxyName, gpsProxyName): #Auto adjustment of the grid size with the distance resolution app.DistanceResolutionM = sensor.Interpreter.GetClientSideObject().GetDistanceResolutionM() - app.actions['actionMeasurement_Grid'].setChecked(True) showMeasurementGrid() + setDefaultLookupTables(sensor) updateUIwithNewLidar() - +# Used by Ui/lqOpenPcapReaction def UpdateApplogicReader(lidarName, posOrName, trailingFrameName): reader = smp.FindSource(lidarName) @@ -361,12 +303,6 @@ def UpdateApplogicReader(lidarName, posOrName, trailingFrameName): if not reader : return - # We create a grid only if there is not a previous one - # This avoid creating a grid for every open sensor - # In long term this should be moved to the reaction - if not app.grid : - app.grid = createGrid() - reader.UpdatePipelineInformation() app.reader = reader app.trailingFramesSpinBox.enabled = True @@ -385,14 +321,8 @@ def UpdateApplogicReader(lidarName, posOrName, trailingFrameName): app.positionPacketInfoLabel.setText('') # will be updated later if possible onCropReturns(False) # Dont show the dialog just restore settings - if SAMPLE_PROCESSING_MODE: - processor = smp.ProcessingSample(reader) - - smp.GetActiveView().ViewTime = 0.0 - if SAMPLE_PROCESSING_MODE: - smp.Show(processor) app.scene.UpdateAnimationUsingDataTimeSteps() posreader = smp.FindSource(posOrName) @@ -427,14 +357,12 @@ def UpdateApplogicReader(lidarName, posOrName, trailingFrameName): #Auto adjustment of the grid size with the distance resolution app.DistanceResolutionM = reader.Interpreter.GetClientSideObject().GetDistanceResolutionM() - app.actions['actionMeasurement_Grid'].setChecked(True) showMeasurementGrid() setDefaultLookupTables(current_trailingFrame) app.trailingFrame.append(current_trailingFrame) updateUIwithNewLidar() - def hideMeasurementGrid(): rep = smp.GetDisplayProperties(app.grid) rep.Visibility = 0 @@ -446,100 +374,6 @@ def showMeasurementGrid(): rep.Visibility = 1 smp.Render() - -# Start Functions related to ruler - - -def createRuler(): - pxm = servermanager.ProxyManager() - distancerep = pxm.NewProxy('representations', 'DistanceWidgetRepresentation') - distancerepeasy = servermanager._getPyProxy(distancerep) - smp.GetActiveView().Representations.append(distancerepeasy) - distancerepeasy.Visibility = False - smp.Render() - - return distancerepeasy - - -def hideRuler(): - app.ruler.Visibility = False - smp.Render() - - -def showRuler(): - app.ruler.Visibility = True - smp.Render() - -def getPointFromCoordinate(coord, midPlaneDistance = 0.5): - assert len(coord) == 2 - - windowHeight = smp.GetActiveView().ViewSize[1] - - displayPoint = [coord[0], windowHeight - coord[1], midPlaneDistance] - renderer = smp.GetActiveView().GetRenderer() - renderer.SetDisplayPoint(displayPoint) - renderer.DisplayToWorld() - world1 = renderer.GetWorldPoint() - - return world1[:3] - -def toggleRulerContext(): - - measurmentState = app.actions['actionMeasure'].isChecked() - - mW = getMainWindow() - vtkW = mW.findChild('pqQVTKWidget') - - if measurmentState == True: - vtkW.connect('mouseEvent(QMouseEvent*)', setRulerCoordinates) - - elif measurmentState == False: - vtkW.disconnect('mouseEvent(QMouseEvent*)', setRulerCoordinates) - - app.mousePressed = False - hideRuler() - - -def setRulerCoordinates(mouseEvent): - - pqView = smp.GetActiveView() - rW = pqView.GetRenderWindow() - windowInteractor = rW.GetInteractor() - currentMouseState = mouseEvent.buttons() - currentKeyboardState = mouseEvent.modifiers() - - if currentMouseState == 1: #Left button pressed - - if app.mousePressed == False: #For the first time - - if currentKeyboardState == 67108864: #Control key pressed - - app.mousePressed = True - app.ruler.Point1WorldPosition = getPointFromCoordinate([mouseEvent.x(),mouseEvent.y()]) - - windowInteractor.Disable() - - elif app.mousePressed == True: #Not for the first time - - app.ruler.Point2WorldPosition = getPointFromCoordinate([mouseEvent.x(),mouseEvent.y()]) - showRuler() - smp.Render() - - elif currentMouseState == 0: #Left button released - - windowInteractor.Enable() - - if app.mousePressed == True: #For the first time - - app.mousePressed = False - app.ruler.Point2WorldPosition = getPointFromCoordinate([mouseEvent.x(),mouseEvent.y()]) - showRuler() - smp.Render() - - -# End Functions related to ruler - - def rotateCSVFile(filename): # read the csv file, move the last 3 columns to the @@ -594,11 +428,11 @@ def saveLASFrames(filename, first, last, transform = 0): if getPosition() is not None: position = getPosition().GetClientSideObject().GetOutput() - PythonQt.paraview.pqLidarViewManager.saveFramesToLAS( + PythonQt.paraview.lqLidarViewManager.saveFramesToLAS( reader, position, first, last, filename, transform) else: - PythonQt.paraview.pqLidarViewManager.saveFramesToLAS( + PythonQt.paraview.lqLidarViewManager.saveFramesToLAS( reader, None, first, last, filename, transform) @@ -692,7 +526,7 @@ def restoreNativeFileDialogsAction(): settings = getPVSettings() app.actions['actionNative_File_Dialogs'].setChecked(int(settings.value('LidarPlugin/NativeFileDialogs', 1))) - +# Action related Logic def onNativeFileDialogsAction(): settings = getPVSettings() settings.setValue('LidarPlugin/NativeFileDialogs', int(app.actions['actionNative_File_Dialogs'].isChecked())) @@ -853,7 +687,7 @@ def onSavePCAP(): if not fileName: return - PythonQt.paraview.pqLidarViewManager.saveFramesToPCAP(getReader().SMProxy, frameOptions.start, frameOptions.stop, fileName) + PythonQt.paraview.lqLidarViewManager.saveFramesToPCAP(getReader().SMProxy, frameOptions.start, frameOptions.stop, fileName) def onSaveScreenshot(): @@ -929,15 +763,7 @@ def exportToDirectory(outDir, timesteps): return filenames -def getVersionString(): - return " ".join(getMainWindow().windowTitle.split(" ")[1:]) - - -def onAbout(): - aboutDialog.showDialog(getMainWindow()) - - -def close(): +def onClose(): # Save grid properties for this session app.gridProperties.Normal = app.grid.Normal app.gridProperties.Origin = app.grid.Origin @@ -947,13 +773,11 @@ def close(): app.gridProperties.Color = app.grid.Color smp.GetAnimationScene().Stop() - hideRuler() unloadData() app.scene.AnimationTime = 0 app.reader = None app.sensor = None app.trailingFrame = [] - smp.Delete(app.grid) smp.HideUnusedScalarBars() @@ -963,6 +787,7 @@ def close(): disableSaveActions() +# Generic Helpers def _setSaveActionsEnabled(enabled): for action in ('SavePCAP', 'Export_To_KiwiViewer', 'Close', 'CropReturns'): @@ -981,40 +806,7 @@ def disableSaveActions(): app.actions['actionSavePositionCSV'].setEnabled(False) -def startStream(): - - sensor = getSensor() - if sensor: - sensor.Start() - - -def stopStream(): - sensor = getSensor() - if sensor: - sensor.Stop() - - -def getPointCloudData(attribute=None): - - if attribute is not None: - data = getPointCloudData() - if data: - if attribute == 'points': - return data.GetPoints().GetData() - else: - return data.GetPointData().GetArray(attribute) - else: - source = getSensor() or getReader() - if source: - return source.GetClientSideObject().GetOutput() - - -def getNumberOfTimesteps(): - return getTimeKeeper().getNumberOfTimeStepValues() - - def unloadData(): - _repCache.clear() for k, src in smp.GetSources().items(): if src != app.grid and src != smp.FindSource("RPM"): @@ -1089,16 +881,6 @@ def onCropReturns(show = True): smp.Render() -def resetCameraToBirdsEyeView(view=None): - - view = view or smp.GetActiveView() - view.CameraFocalPoint = [0, 0, 0] - view.CameraViewUp = [0, 1, 0] - view.CameraPosition = [0, 0, 40] - view.CenterOfRotation = [0, 0, 0] - smp.Render(view) - - def resetCameraToForwardView(view=None): view = view or smp.GetActiveView() @@ -1148,14 +930,10 @@ def showSourceInSpreadSheet(source): smp.Hide(source, spreadSheetView) smp.Show(source, spreadSheetView) - -def createGrid(view=None): - - view = view or smp.GetActiveView() - grid = smp.GridSource(guiName='Measurement Grid') - +def createGrid(): + app.grid = smp.GridSource(guiName='Measurement Grid') if app.gridProperties.Persist == False: - grid.GridNbTicks = (int(math.ceil(50000 * app.DistanceResolutionM/ grid.Scale ))) + app.grid.GridNbTicks = (int(math.ceil(50000 * app.DistanceResolutionM/ app.grid.Scale ))) else: # Restore grid properties grid.Normal = app.gridProperties.Normal @@ -1165,14 +943,16 @@ def createGrid(view=None): grid.LineWidth = app.gridProperties.LineWidth grid.Color = app.gridProperties.Color - rep = smp.Show(grid, view) - rep.LineWidth = grid.LineWidth - rep.DiffuseColor = grid.Color + rep = smp.Show(app.grid) + rep.LineWidth = app.grid.LineWidth + rep.DiffuseColor = app.grid.Color rep.Pickable = 0 rep.Visibility = 0 smp.SetActiveSource(None) - return grid + app.grid.UpdatePipeline() + smp.Show(app.grid) + return app.grid def hideGrid(): smp.GetDisplayProperties(app.grid).Hide() @@ -1181,7 +961,6 @@ def hideGrid(): def showGrid(): smp.GetDisplayProperties(app.grid).Show() - def getAnimationScene(): '''This function is a workaround because paraview.simple.GetAnimationScene() has an issue where the returned proxy might not have its Cues property initialized''' @@ -1195,7 +974,6 @@ def start(): global app app = AppLogic() app.scene = getAnimationScene() - app.gridProperties = GridProperties() view = smp.GetActiveView() view.Background = [0.0, 0.0, 0.0] @@ -1203,20 +981,20 @@ def start(): view.UseGradientBackground = True smp._DisableFirstRenderCameraReset() smp.GetActiveView().LODThreshold = 1e100 - app.DistanceResolutionM = 0.002 - app.grid = createGrid() - app.ruler = createRuler() resetCameraToForwardView() setupActions() disableSaveActions() - app.actions['actionMeasure'].setEnabled(view.CameraParallelProjection) setupStatusBar() hideColorByComponent() restoreNativeFileDialogsAction() createRPMBehaviour() - + + # Create Grid #WIP not perfect requires loaded plugin + app.DistanceResolutionM = 0.002 + app.gridProperties = GridProperties() # Reset Grid Properties + createGrid() def findQObjectByName(widgets, name): for w in widgets: @@ -1240,22 +1018,11 @@ def getTimeKeeper(): return getPVApplicationCore().getActiveServer().getTimeKeeper() -def quit(): - PythonQt.QtGui.QApplication.instance().quit() -exit = quit - - -def addShortcuts(keySequenceStr, function): - shortcut = PythonQt.QtGui.QShortcut(PythonQt.QtGui.QKeySequence(keySequenceStr), getMainWindow()) - shortcut.connect("activated()", function) - - def onTrailingFramesChanged(numFrames): for tr in app.trailingFrame : tr.NumberOfTrailingFrames = numFrames smp.Render() - def setupStatusBar(): # by using a QScrollArea inside the statusBar it should be possible # to reduce the minimum main window's width @@ -1267,20 +1034,18 @@ def setupStatusBar(): statusBar.addWidget(app.sensorInformationLabel) statusBar.addWidget(app.positionPacketInfoLabel) - def onGridProperties(): + if not app.grid: + createGrid() if gridAdjustmentDialog.showDialog(getMainWindow(), app.grid, app.gridProperties): - rep = smp.Show(app.grid, None) - rep.LineWidth = app.grid.LineWidth + rep = smp.Show(app.grid) + rep.LineWidth = app.grid.LineWidth rep.DiffuseColor = app.grid.Color - app.actions['actionMeasurement_Grid'].setChecked(True) smp.Render() - def hideColorByComponent(): getMainWindow().findChild('lqColorToolbar').findChild('pqDisplayColorWidget').findChildren('QComboBox')[1].hide() - def adjustScalarBarRangeLabelFormat(): if not app.actions['actionScalarBarVisibility'].isChecked(): return @@ -1291,21 +1056,6 @@ def adjustScalarBarRangeLabelFormat(): sb.RangeLabelFormat = '%g' smp.Render() -def toggleProjectionType(): - - view = smp.GetActiveView() - - view.CameraParallelProjection = not view.CameraParallelProjection - if app.actions['actionMeasure'].isChecked(): - app.actions['actionMeasure'].trigger() - app.actions['actionMeasure'].toggle() - - app.actions['actionMeasure'].setEnabled(view.CameraParallelProjection) - if not view.CameraParallelProjection: - app.actions['actionMeasure'].setChecked(False) - - smp.Render() - def toggleRPM(): rpm = smp.FindSource("RPM") if rpm: @@ -1315,11 +1065,6 @@ def toggleRPM(): smp.Hide(rpm) smp.Render() - -def toggleCrashAnalysis(): - app.EnableCrashAnalysis = app.actions['actionEnableCrashAnalysis'].isChecked() - - def transformMode(): reader = getReader() if not reader: @@ -1391,7 +1136,7 @@ def setupActions(): app.actions['actionPlaneFit'].connect('triggered()', planeFit) - app.actions['actionClose'].connect('triggered()', close) + app.actions['actionClose'].connect('triggered()', onClose) app.actions['actionSavePositionCSV'].connect('triggered()', onSavePosition) app.actions['actionSavePCAP'].connect('triggered()', onSavePCAP) app.actions['actionSaveScreenshot'].connect('triggered()', onSaveScreenshot) @@ -1399,10 +1144,8 @@ def setupActions(): app.actions['actionGrid_Properties'].connect('triggered()', onGridProperties) app.actions['actionCropReturns'].connect('triggered()', onCropReturns) app.actions['actionNative_File_Dialogs'].connect('triggered()', onNativeFileDialogsAction) - app.actions['actionAbout_LidarView'].connect('triggered()', onAbout) - - app.actions['actionToggleProjection'].connect('triggered()', toggleProjectionType) - app.actions['actionMeasure'].connect('triggered()', toggleRulerContext) + app.actions['actionAbout_LidarView'].connect('triggered()', lambda : aboutDialog.showDialog(getMainWindow()) ) + app.actions['actionShowPosition'].connect('triggered()', ShowPosition) app.actions['actionShowRPM'].connect('triggered()', toggleRPM) @@ -1410,7 +1153,6 @@ def setupActions(): # Restore action states from settings settings = getPVSettings() - advanceMode = int(settings.value("LidarPlugin/AdvanceFeature/Enable", 0)) if not advanceMode: app.actions['actionAdvanceFeature'].checked = False @@ -1441,15 +1183,8 @@ def setupActions(): # Set default toolbar visibility geolocationToolBar.visible = False - app.geolocationToolBar = geolocationToolBar - - # Setup and add the playback speed control toolbar - timeToolBar = mW.findChild('QToolBar','Player Control') - - spinBoxLabel = QtGui.QLabel('TF:') - spinBoxLabel.toolTip = "Number of trailing frames" - timeToolBar.addWidget(spinBoxLabel) + # Trailing Frame Spinbox spinBox = QtGui.QSpinBox() spinBox.toolTip = "Number of trailing frames" spinBox.setMinimum(0) @@ -1457,18 +1192,10 @@ def setupActions(): spinBox.connect('valueChanged(int)', onTrailingFramesChanged) app.trailingFramesSpinBox = spinBox - app.actions['actionTrailingFramesSelector'] = timeToolBar.addWidget(spinBox) - app.actions['actionTrailingFramesSelector'].setVisible(True) - displayWidget = getMainWindow().findChild('lqColorToolbar').findChild('pqDisplayColorWidget') displayWidget.connect('arraySelectionChanged ()',adjustScalarBarRangeLabelFormat) app.actions['actionScalarBarVisibility'].connect('triggered()',adjustScalarBarRangeLabelFormat) - app.MainToolbar = getMainWindow().findChild('QToolBar','toolBar') - app.ColorToolbar = getMainWindow().findChild('QToolBar','colorToolBar') - app.PlaybackToolbar = timeToolBar - app.GeolocationToolbar = getMainWindow().findChild('QToolBar','geolocationToolbar') - def createRPMBehaviour(): # create and customize a label to display the rpm diff --git a/Application/Ui/vvPythonQtDecorators.h b/Application/Ui/vvPythonQtDecorators.h deleted file mode 100644 index 98e78723cd35465352407712a21fe55266225398..0000000000000000000000000000000000000000 --- a/Application/Ui/vvPythonQtDecorators.h +++ /dev/null @@ -1,62 +0,0 @@ - -#ifndef __vvPythonQtDecorators_h -#define __vvPythonQtDecorators_h - -#include <PythonQt.h> -#include <QObject> - -#include "pqLidarViewManager.h" -#include "Widgets/vvCropReturnsDialog.h" -#include "Widgets/vvSelectFramesDialog.h" -#include <pqActiveObjects.h> - -class vvPythonQtDecorators : public QObject -{ - Q_OBJECT - -public: - vvPythonQtDecorators(QObject* parent = 0) - : QObject(parent) - { - this->registerClassForPythonQt(&pqLidarViewManager::staticMetaObject); - this->registerClassForPythonQt(&vvCropReturnsDialog::staticMetaObject); - this->registerClassForPythonQt(&vvSelectFramesDialog::staticMetaObject); - this->registerClassForPythonQt(&pqActiveObjects::staticMetaObject); - } - - inline void registerClassForPythonQt(const QMetaObject* metaobject) - { - PythonQt::self()->registerClass(metaobject, "paraview"); - } - -public slots: - - vvCropReturnsDialog* new_vvCropReturnsDialog(QWidget* arg0) - { - return new vvCropReturnsDialog(arg0); - } - - vvSelectFramesDialog* new_vvSelectFramesDialog(QWidget* arg0) - { - return new vvSelectFramesDialog(arg0); - } - - pqActiveObjects* new_pqActiveObjects() - { - return pqActiveObjects::instancePtr(); - } - - void static_pqLidarViewManager_saveFramesToPCAP( - vtkSMSourceProxy* arg0, int arg1, int arg2, const QString& arg3) - { - pqLidarViewManager::saveFramesToPCAP(arg0, arg1, arg2, arg3); - } - - void static_pqLidarViewManager_saveFramesToLAS(vtkLidarReader* arg0, vtkPolyData* arg1, - int arg2, int arg3, const QString& arg4, int arg5) - { - pqLidarViewManager::saveFramesToLAS(arg0, arg1, arg2, arg3, arg4, arg5); - } -}; - -#endif diff --git a/Application/branding.cmake b/Application/branding.cmake index f1b439f3de69e4ac6c7f81918e34eba298e153e9..a682649ffbf54963dfbb0857ad19f5133f39b5a1 100644 --- a/Application/branding.cmake +++ b/Application/branding.cmake @@ -2,7 +2,7 @@ # Software Name / Vendor set(SOFTWARE_NAME "LidarView") -set(SOFTWARE_VENDOR "Kitware, Inc.") +set(SOFTWARE_VENDOR "Kitware") # Software LOGO / ICON # Must be absolute to be used by packaging set(SOFTWARE_ICON_PATH "${CMAKE_CURRENT_LIST_DIR}/SoftwareInformation/logo.ico") diff --git a/Application/vvFilters.xml b/Application/vvFilters.xml index 29395f940f0ca7e45e88bf4ec49aa56c92628d74..982d2fc59434b2f779c51d7587e4eec69db2d980 100644 --- a/Application/vvFilters.xml +++ b/Application/vvFilters.xml @@ -1,7 +1,7 @@ <!-- list of filters copy pasted from paraview --> +<!-- Removed some show_in_toolbar="1" properties --> <ParaViewFilters> - <Category name="Common" menu_label="&Common" preserve_order="1" - show_in_toolbar="1"> + <Category name="Common" menu_label="&Common" preserve_order="1"> <Proxy group="filters" name="Calculator" icon=":/pqWidgets/Icons/pqCalculator.svg"/> <Proxy group="filters" name="Contour" icon=":/pqWidgets/Icons/pqIsosurface.svg"/> <Proxy group="filters" name="Clip" icon=":/pqWidgets/Icons/pqClip.svg"/> @@ -21,18 +21,18 @@ icon=":/pqWidgets/Icons/pqExtractSelection.svg" /> <Proxy group="filters" name="ExtractSelectionOverTime" icon=":/pqWidgets/Icons/pqPlotCellOverTime24.png" /> - <Proxy group="filters" name="ExtractHistogram" + <Proxy group="filters" name="ExtractHistogram" icon=":/pqWidgets/Icons/pqHistogram24.png"/> <Proxy group="filters" name="IntegrateAttributes" /> <Proxy group="filters" name="ExtractFieldDataOverTime" /> - <Proxy group="filters" name="ProbeLine" + <Proxy group="filters" name="ProbeLine" icon=":/pqWidgets/Icons/pqPlotLineOverTime24.png" /> - <Proxy group="filters" name="ProbePoint" + <Proxy group="filters" name="ProbePoint" icon=":/pqWidgets/Icons/pqProbeLocation.svg" /> <Proxy group="filters" name="PlotAttributes" /> <Proxy group="filters" name="PlotOnSortedLines" /> <Proxy group="filters" name="PlotOnIntersectionCurves" /> - <Proxy group="filters" name="ProgrammableFilter" + <Proxy group="filters" name="ProgrammableFilter" icon=":/pqWidgets/Icons/pqProgrammableFilter.svg"/> </Category> @@ -44,15 +44,15 @@ <Proxy group="filters" name="PCAStatistics"/> </Category> - <Category name="Temporal" menu_label="&Temporal"> - <Proxy group="filters" name="ParticleTracer" /> + <Category name="Temporal" menu_label="&Temporal"> + <Proxy group="filters" name="ParticleTracer" /> <Proxy group="filters" name="ParticlePathLines" /> - <Proxy group="filters" name="TemporalCache" /> - <Proxy group="filters" name="TemporalInterpolator" /> - <Proxy group="filters" name="TemporalSnapToTimeStep" /> - <Proxy group="filters" name="TemporalShiftScale" /> + <Proxy group="filters" name="TemporalCache" /> + <Proxy group="filters" name="TemporalInterpolator" /> + <Proxy group="filters" name="TemporalSnapToTimeStep" /> + <Proxy group="filters" name="TemporalShiftScale" /> <Proxy group="filters" name="TemporalStatistics" /> - <Proxy group="filters" name="TimeToTextConvertor" /> + <Proxy group="filters" name="TimeToTextConvertor" /> </Category> <Proxy group="filters" name="Append" /> @@ -140,7 +140,7 @@ <Proxy group="filters" name="SurfaceVectors" /> <Proxy group="filters" name="TemporalCache" /> <Proxy group="filters" name="TemporalInterpolator" /> - <Proxy group="filters" name="TemporalSnapToTimeStep" /> + <Proxy group="filters" name="TemporalSnapToTimeStep" /> <Proxy group="filters" name="TemporalShiftScale" /> <Proxy group="filters" name="TemporalStatistics" /> <Proxy group="filters" name="TessellatorFilter" /> diff --git a/Application/vvMainWindow.cxx b/Application/vvMainWindow.cxx index 391beb29554e46cb467b0fa7221140e235b54ab4..ddaccd26659b8ca9807192779ce02c8ac5cbb9c7 100644 --- a/Application/vvMainWindow.cxx +++ b/Application/vvMainWindow.cxx @@ -27,47 +27,54 @@ #include "vvMainWindow.h" #include "ui_vvMainWindow.h" + #include "lqDockableSpreadSheetReaction.h" -#include "lqSaveLidarStateReaction.h" -#include "lqLoadLidarStateReaction.h" #include "lqEnableAdvancedArraysReaction.h" -#include "lqOpenSensorReaction.h" +#include "lqLoadLidarStateReaction.h" #include "lqOpenPcapReaction.h" #include "lqOpenRecentFilesReaction.h" -#include "lqUpdateCalibrationReaction.h" -#include "lqSaveLidarFrameReaction.h" +#include "lqOpenSensorReaction.h" #include "lqSaveLASReaction.h" - -#include <vtkSMProxyManager.h> -#include <vtkSMSessionProxyManager.h> +#include "lqSaveLidarFrameReaction.h" +#include "lqSaveLidarStateReaction.h" +#include "lqUpdateCalibrationReaction.h" +#include <lqLidarViewManager.h> +#include <lqSensorListWidget.h> +#include <lqCameraParallelProjectionReaction.h> #include <pqActiveObjects.h> #include <pqApplicationCore.h> +#include <pqAxesToolbar.h> +#include <pqCameraToolbar.h> +#include <pqDataRepresentation.h> +#include <pqDeleteReaction.h> +#include <pqDesktopServicesReaction.h> +#include <pqHelpReaction.h> #include <pqInterfaceTracker.h> +#include <pqLoadDataReaction.h> +#include <pqMainWindowEventManager.h> #include <pqObjectBuilder.h> #include <pqOutputWidget.h> +#include <pqParaViewBehaviors.h> +#include <pqParaViewMenuBuilders.h> +#include <pqPythonManager.h> #include <pqRenderView.h> #include <pqRenderViewSelectionReaction.h> -#include <pqDeleteReaction.h> -#include <pqHelpReaction.h> -#include <pqDesktopServicesReaction.h> #include <pqServer.h> +#include <pqSetName.h> #include <pqSettings.h> -#include <pqLidarViewManager.h> -#include <pqParaViewMenuBuilders.h> -#include <pqPythonManager.h> #include <pqTabbedMultiViewWidget.h> -#include <pqSetName.h> -#include <vtkSMPropertyHelper.h> -#include "pqAxesToolbar.h" -#include "pqCameraToolbar.h" -#include <pqParaViewBehaviors.h> -#include <pqDataRepresentation.h> + +#include <vtksys/SystemTools.hxx> + +// LidarView is always Python Enabled +#include <pvpythonmodules.h> #include <pqPythonShell.h> -#include <pqLoadDataReaction.h> +#include <pqPythonDebugLeaksView.h> +typedef pqPythonDebugLeaksView DebugLeaksViewType; + #include <QToolBar> -#include <QShortcut> #include <QMenu> #include <QMessageBox> #include <QMimeData> @@ -80,357 +87,403 @@ #include <sstream> #include "lqPlayerControlsToolbar.h" +#include "lqViewFrameActions.h" -// Declare the plugin to load. +// Declare static plugin to load. #define PARAVIEW_BUILDING_PLUGIN #include "vtkPVPlugin.h" -PV_PLUGIN_IMPORT_INIT(PythonQtPlugin); //could link it dynamically actually wip ? +PV_PLUGIN_IMPORT_INIT(PythonQtPlugin); // WIP could be Dynamically loaded -class vvMainWindow::pqInternals +//----------------------------------------------------------------------------- +class vvMainWindow::pqInternals : public Ui::vvMainWindow { public: - pqInternals(vvMainWindow* window) - : Ui() - , MainView(0) + pqInternals(): + Ui::vvMainWindow() { - this->Ui.setupUi(window); - this->paraviewInit(window); - this->setupUi(); - - window->show(); - window->raise(); - window->activateWindow(); } - Ui::vvMainWindow Ui; - pqRenderView* MainView = nullptr; - pqServer* Server = nullptr; - pqObjectBuilder* Builder = nullptr; +}; -private: - void paraviewInit(vvMainWindow* window) +//----------------------------------------------------------------------------- +vvMainWindow::vvMainWindow() +{ + // ParaView Init Start + // DebugLeaksView MUST be instantiated first + DebugLeaksViewType* leaksView = nullptr; + if (vtksys::SystemTools::GetEnv("PV_DEBUG_LEAKS_VIEW")) { - pqApplicationCore* core = pqApplicationCore::instance(); - - // need to be created before the first scene - QToolBar* vcrToolbar = new lqPlayerControlsToolbar(window) - << pqSetName("Player Control"); - window->addToolBar(Qt::TopToolBarArea, vcrToolbar); - - QToolBar* cameraToolbar = new pqCameraToolbar(window) - << pqSetName("cameraToolbar"); - window->addToolBar(Qt::TopToolBarArea, cameraToolbar); - - QToolBar* axesToolbar = new pqAxesToolbar(window) - << pqSetName("axesToolbar"); - window->addToolBar(Qt::TopToolBarArea, axesToolbar); - - // create pythonshell - pqPythonShell* shell = new pqPythonShell(window); - shell->setObjectName("pythonShell"); - shell->setFontSize(8); - this->Ui.pythonShellDock->setWidget(shell); - pqLidarViewManager::instance()->setPythonShell(shell); - - // Give the macros menu to the pqPythonMacroSupervisor - pqPythonManager* manager = - qobject_cast<pqPythonManager*>(pqApplicationCore::instance()->manager("PYTHON_MANAGER")); - if (manager) - { - QToolBar* macrosToolbar = new QToolBar("Macros Toolbars", window) - << pqSetName("MacrosToolbar"); - manager->addWidgetForRunMacros(macrosToolbar); - window->addToolBar(Qt::TopToolBarArea, macrosToolbar); - } + leaksView = new DebugLeaksViewType(this); + leaksView->setWindowFlags(Qt::Window); + leaksView->show(); + } - // Define application behaviors. - pqParaViewBehaviors::enableQuickLaunchShortcuts(); - pqParaViewBehaviors::enableSpreadSheetVisibilityBehavior(); - pqParaViewBehaviors::enableObjectPickingBehavior(); - pqParaViewBehaviors::enableCrashRecoveryBehavior(); - pqParaViewBehaviors::enableAutoLoadPluginXMLBehavior(); - pqParaViewBehaviors::enableDataTimeStepBehavior(); - pqParaViewBehaviors::enableCommandLineOptionsBehavior(); - pqParaViewBehaviors::enableLiveSourceBehavior(); - pqParaViewBehaviors::enableApplyBehavior(); - pqParaViewBehaviors::enableStandardViewFrameActions(); - pqParaViewBehaviors::enableStandardPropertyWidgets(); - pqParaViewBehaviors::setEnableDefaultViewBehavior(false); - - // Check if the settings are well formed i.e. if an OriginalMainWindow - // state was previously saved. If not, we don't want to automatically - // restore the settings state nor save it on quitting LidarView. - // An OriginalMainWindow state will be force saved once the UI is completly - // set up. - pqSettings* const settings = pqApplicationCore::instance()->settings(); - bool shouldClearSettings = false; - QStringList keys = settings->allKeys(); - - if (keys.size() == 0) - { - // There were no settings before, let's save the current state as - // OriginalMainWindow state - shouldClearSettings = true; - } - else - { - // Checks if the existing settings are well formed and if not, clear them. - // An original MainWindow state will be force saved later once the UI is - // entirely set up - for (int keyIndex = 0; keyIndex < keys.size(); ++keyIndex) - { - if (keys[keyIndex].contains("OriginalMainWindow")) - { - shouldClearSettings = true; - break; - } - } - } + // Connect to builtin server. + pqServer* server = pqApplicationCore::instance()->getObjectBuilder()->createServer(pqServerResource("builtin:")); + pqActiveObjects::instance().setActiveServer(server); - if (shouldClearSettings) - { - pqParaViewBehaviors::enablePersistentMainWindowStateBehavior(); - } - else - { - if (keys.size() > 0) - { - vtkGenericWarningMacro("Settings weren't set correctly. Clearing settings."); - } - - // As pqPersistentMainWindowStateBehavior is not created right now, - // we can clear the settings as the current bad state won't be saved on - // closing LidarView - settings->clear(); - } + // PVPython + pvpythonmodules_load(); - // the paraview behaviors, which will in our case instantiate the enableStandardViewFrameActions - // must be created before creating the first renderview, otherwise this view won't have the default - // view toolbar buttons/actions - new pqParaViewBehaviors(window, window); - - // Connect to builtin server. - this->Builder = core->getObjectBuilder(); - this->Server = this->Builder->createServer(pqServerResource("builtin:")); - pqActiveObjects::instance().setActiveServer(this->Server); - - // Set default render view settings - vtkSMSessionProxyManager* pxm = - vtkSMProxyManager::GetProxyManager()->GetActiveSessionProxyManager(); - vtkSMProxy* renderviewsettings = pxm->GetProxy("RenderViewSettings"); - assert(renderviewsettings); - - vtkSMPropertyHelper(renderviewsettings, "ResolveCoincidentTopology").Set(0); - - // Set the central widget - pqTabbedMultiViewWidget* mv = new pqTabbedMultiViewWidget; - mv->setTabVisibility(false); - window->setCentralWidget(mv); - - new lqDockableSpreadSheetReaction(this->Ui.actionSpreadsheet, window); - - this->MainView = - qobject_cast<pqRenderView*>(this->Builder->createView(pqRenderView::renderViewType(), this->Server)); - assert(this->MainView); - - // Add view to layout - this->Builder->addToLayout(this->MainView); - - vtkSMPropertyHelper(this->MainView->getProxy(), "CenterAxesVisibility").Set(0); - double bgcolor[3] = { 0, 0, 0 }; - vtkSMPropertyHelper(this->MainView->getProxy(), "Background").Set(bgcolor, 3); - // MultiSamples doesn't work, we need to set that up before registering the proxy. - // vtkSMPropertyHelper(view->getProxy(),"MultiSamples").Set(1); - this->MainView->getProxy()->UpdateVTKObjects(); - - // Add save/load lidar state action - new lqSaveLidarStateReaction(this->Ui.actionSaveLidarState); - new lqLoadLidarStateReaction(this->Ui.actionLoadLidarState); - - // Change calibration reaction - new lqUpdateCalibrationReaction(this->Ui.actionChoose_Calibration_File); - - // Specify each Properties Panel as we do want to present one panel per dock - this->Ui.propertiesPanel->setPanelMode(pqPropertiesPanel::SOURCE_PROPERTIES); - this->Ui.viewPropertiesPanel->setPanelMode(pqPropertiesPanel::VIEW_PROPERTIES); - this->Ui.displayPropertiesPanel->setPanelMode(pqPropertiesPanel::DISPLAY_PROPERTIES); - - // Enable help from the properties panel. - QObject::connect(this->Ui.propertiesPanel, - SIGNAL(helpRequested(const QString&, const QString&)), - window, SLOT(showHelpForProxy(const QString&, const QString&))); - - /// hook delete to pqDeleteReaction. - QAction* tempDeleteAction = new QAction(window); - pqDeleteReaction* handler = new pqDeleteReaction(tempDeleteAction); - handler->connect(this->Ui.propertiesPanel, - SIGNAL(deleteRequested(pqProxy*)), - SLOT(deleteSource(pqProxy*))); - - // specify how corner are occupied by the dockable widget - window->setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); - window->setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea); - window->setCorner(Qt::TopRightCorner, Qt::RightDockWidgetArea); - window->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); - - // organize dockable widget in tab - window->setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North); - window->tabifyDockWidget(this->Ui.propertiesDock, this->Ui.colorMapEditorDock); - window->tabifyDockWidget(this->Ui.viewPropertiesDock, this->Ui.colorMapEditorDock); - window->tabifyDockWidget(this->Ui.displayPropertiesDock, this->Ui.colorMapEditorDock); - window->tabifyDockWidget(this->Ui.informationDock, this->Ui.memoryInspectorDock); - window->tabifyDockWidget(this->Ui.informationDock, this->Ui.viewAnimationDock); - window->tabifyDockWidget(this->Ui.informationDock, this->Ui.outputWidgetDock); - window->tabifyDockWidget(this->Ui.informationDock, this->Ui.pythonShellDock); - - // hide docker by default - this->Ui.pipelineBrowserDock->hide(); - this->Ui.propertiesDock->hide(); - this->Ui.viewPropertiesDock->hide(); - this->Ui.displayPropertiesDock->hide(); - this->Ui.colorMapEditorDock->hide(); - this->Ui.informationDock->hide(); - this->Ui.memoryInspectorDock->hide(); - this->Ui.viewAnimationDock->hide(); - this->Ui.outputWidgetDock->hide(); - this->Ui.pythonShellDock->hide(); - this->Ui.sensorListDock->hide(); - - // Setup the View menu. This must be setup after all toolbars and dockwidgets - // have been created. - pqParaViewMenuBuilders::buildViewMenu(*this->Ui.menuViews, *window); - - /// If you want to automatically add a menu for sources as requested in the - /// configuration pass in a non-null main window. - pqParaViewMenuBuilders::buildSourcesMenu(*this->Ui.menuSources, nullptr); - - /// If you want to automatically add a menu for filters as requested in the - /// configuration pass in a non-null main window. - pqParaViewMenuBuilders::buildFiltersMenu(*this->Ui.menuFilters, nullptr); - - // setup the context menu for the pipeline browser. - pqParaViewMenuBuilders::buildPipelineBrowserContextMenu(*this->Ui.pipelineBrowser->contextMenu()); - - // build Paraview file menu - QMenu *paraviewFileMenu = this->Ui.menuAdvance->addMenu("File (Paraview)"); - pqParaViewMenuBuilders::buildFileMenu(*paraviewFileMenu); - // for some reason the menu builder rename the QMenu... - paraviewFileMenu->setTitle("File (Paraview)"); - - // build Paraview edit menu - QMenu *paraviewEditMenu = this->Ui.menuAdvance->addMenu("Edit (Paraview)"); - // for some reason the menu builder rename the QMenu... - pqParaViewMenuBuilders::buildEditMenu(*paraviewEditMenu); - paraviewEditMenu->setTitle("Edit (Paraview)"); - - // build Paraview tools menu - QMenu *paraviewToolsMenu = this->Ui.menuAdvance->addMenu("Tools (Paraview)"); - pqParaViewMenuBuilders::buildToolsMenu(*paraviewToolsMenu); - - // build Paraview macro menu - QMenu *paraviewMacroMenu = this->Ui.menuAdvance->addMenu("Macro (Paraview)"); - pqParaViewMenuBuilders::buildMacrosMenu(*paraviewMacroMenu); - - // Add Professional Support / How to SLAM Menu Actions - new pqDesktopServicesReaction(QUrl("https://www.kitware.com/what-we-offer"), - (this->Ui.actionHelpSupport )); - - new pqDesktopServicesReaction(QUrl("https://gitlab.kitware.com/keu-computervision/slam/-/blob/master/paraview_wrapping/doc/How_to_SLAM_with_LidarView.md"), - (this->Ui.actionHelpSlam )); - - pqActiveObjects::instance().setActiveView(this->MainView); - } + // Internals + this->Internals = new pqInternals(); + this->Internals->setupUi(this); + //this->Internals->outputWidgetDock->hide(); // This is default ParaView, we give the App choice first + //this->Internals->pythonShellDock->hide(); // Kept for reference + //this->Internals->materialEditorDock->hide(); - //----------------------------------------------------------------------------- - void setupUi() - { - new pqRenderViewSelectionReaction(this->Ui.actionSelect_Visible_Points, this->MainView, - pqRenderViewSelectionReaction::SELECT_SURFACE_POINTS); - new pqRenderViewSelectionReaction(this->Ui.actionSelect_All_Points, this->MainView, - pqRenderViewSelectionReaction::SELECT_FRUSTUM_POINTS); + // Load Plugins + PV_PLUGIN_IMPORT(PythonQtPlugin); + + // LidarView Specific Manager + new lqLidarViewManager(this); - pqLidarViewManager::instance()->setup(); + // Create pythonshell + pqPythonShell* shell = new pqPythonShell(this); + shell->setObjectName("pythonShell"); + shell->setFontSize(8); + lqLidarViewManager::instance()->setPythonShell(shell); + if (leaksView) + { + leaksView->setShell(shell); + } + // ParaView Init END - pqSettings* const settings = pqApplicationCore::instance()->settings(); - const QVariant& gridVisible = - settings->value("LidarPlugin/MeasurementGrid/Visibility", true); - this->Ui.actionMeasurement_Grid->setChecked(gridVisible.toBool()); + // Persistent Settings Restore // WIP TO rework is this verbatim PV ? + // Better instantiated before any widget instantiation / outputWidget connection + lqLidarViewManager::instance()->persistentSettingsRestore(); - new lqOpenSensorReaction(this->Ui.actionOpen_Sensor_Stream); - new lqOpenPcapReaction(this->Ui.actionOpenPcap); + // Setup ParaView Base GUI + this->setupPVGUI(); - new lqOpenRecentFilesReaction(this->Ui.menuRecent_Files, this->Ui.actionClear_Menu); + // Setup LidarView Base GUI + this->setupLVGUI(); - lqSensorListWidget * listSensor = lqSensorListWidget::instance(); - listSensor->setCalibrationFunction(&lqUpdateCalibrationReaction::UpdateExistingSource); + // LidarView custom GUI + this->setupGUICustom(); - new lqSaveLidarFrameReaction(this->Ui.actionSavePCD, "PCDWriter", "pcd", false, false, true, true); - new lqSaveLidarFrameReaction(this->Ui.actionSaveCSV, "DataSetCSVWriter", "csv", false, false, true, true); - new lqSaveLidarFrameReaction(this->Ui.actionSavePLY, "PPLYWriter", "ply", false, false, true, true); - new lqSaveLASReaction(this->Ui.actionSaveLAS, false, false, true, true); + // LidarView Branding + this->setBranding(); - connect(this->Ui.actionMeasurement_Grid, SIGNAL(toggled(bool)), pqLidarViewManager::instance(), - SLOT(onMeasurementGrid(bool))); + // Create Main Render View + lqLidarViewManager::instance()->createMainRenderView(); - connect(this->Ui.actionResetDefaultSettings, SIGNAL(triggered()), - pqLidarViewManager::instance(), SLOT(onResetDefaultSettings())); + // Schedule Python Init late otherwise startup is slow, WIP to investigate (related to window creation timing) + lqLidarViewManager::instance()->schedulePythonStartup(); - connect(this->Ui.actionShowErrorDialog, SIGNAL(triggered()), this->Ui.outputWidgetDock, - SLOT(show())); + // Save Original State if first time or invalid and discarded + lqLidarViewManager::instance()->persistentSettingsSaveOriginal(); - connect(this->Ui.actionPython_Console, SIGNAL(triggered()), this->Ui.pythonShellDock, - SLOT(show())); + // Force Show App + this->show(); + this->raise(); + this->activateWindow(); +} - // Add save/load lidar state action - new lqEnableAdvancedArraysReaction(this->Ui.actionEnableAdvancedArrays); - } -}; +//----------------------------------------------------------------------------- +vvMainWindow::~vvMainWindow() +{ + delete this->Internals; + this->Internals = NULL; +} //----------------------------------------------------------------------------- -vvMainWindow::vvMainWindow() - : Internals(new vvMainWindow::pqInternals(this)) +void vvMainWindow::setupPVGUI() { - pqApplicationCore::instance()->registerManager( - "COLOR_EDITOR_PANEL", this->Internals->Ui.colorMapEditorDock); - this->Internals->Ui.colorMapEditorDock->hide(); + // Common Parts of the ParaViewMainWindow.cxx + // Easily updatable and referenceable + // Common elements to all LidarView-based Apps + + // PARAVIEW_USE_MATERIALEDITOR // Not used // show output widget if we received an error message. - this->connect(this->Internals->Ui.outputWidget, SIGNAL(messageDisplayed(const QString&, int)), + this->connect(this->Internals->outputWidget, SIGNAL(messageDisplayed(const QString&, int)), SLOT(handleMessage(const QString&, int))); - PV_PLUGIN_IMPORT(PythonQtPlugin); + // Setup default GUI layout. + this->setTabPosition(Qt::LeftDockWidgetArea, QTabWidget::North); + + // Set up the dock window corners to give the vertical docks more room. + this->setCorner(Qt::TopLeftCorner , Qt::LeftDockWidgetArea); + this->setCorner(Qt::BottomLeftCorner , Qt::LeftDockWidgetArea); + this->setCorner(Qt::TopRightCorner , Qt::RightDockWidgetArea); + this->setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea); + + // CUSTOMIZED tabifyDockWidget() / hide() section + // Easier to understand what is being used + + // Memory Inspector Dock + this->tabifyDockWidget(this->Internals->informationDock , this->Internals->memoryInspectorDock); + this->Internals->memoryInspectorDock->hide(); + + // View Animation Dock + this->tabifyDockWidget(this->Internals->informationDock , this->Internals->viewAnimationDock); + this->Internals->viewAnimationDock->hide(); + + // Hide Various Other Docks + this->Internals->colorMapEditorDock->hide(); + this->Internals->pipelineBrowserDock->hide(); + this->Internals->propertiesDock->hide(); + this->Internals->viewPropertiesDock->hide(); + this->Internals->displayPropertiesDock->hide(); + this->Internals->informationDock->hide(); + + // CUSTOMIZED PropertiesPanelMode + this->Internals->propertiesPanel ->setPanelMode(pqPropertiesPanel::SOURCE_PROPERTIES); + this->Internals->viewPropertiesPanel ->setPanelMode(pqPropertiesPanel::VIEW_PROPERTIES); + this->Internals->displayPropertiesPanel->setPanelMode(pqPropertiesPanel::DISPLAY_PROPERTIES); + + // TODO update UI when font size changes. + + // TODO Enable help from the properties panel. + + /// hook delete to pqDeleteReaction. + QAction* tempDeleteAction = new QAction(this); + pqDeleteReaction* handler = new pqDeleteReaction(tempDeleteAction); + handler->connect(this->Internals->propertiesPanel, SIGNAL(deleteRequested(pqProxy*)), + SLOT(deleteSource(pqProxy*))); + + // setup color editor + /// Provide access to the color-editor panel for the application. + pqApplicationCore::instance()->registerManager( + "COLOR_EDITOR_PANEL", this->Internals->colorMapEditorDock); + + // Provide access to the find data panel for the application. + //pqApplicationCore::instance()->registerManager("FIND_DATA_PANEL", this->Internals->findDataDock); // Unused + + // Populate application menus with actions. + //pqParaViewMenuBuilders::buildFileMenu(*this->Internals->menu_File); // Advanced Menu + //pqParaViewMenuBuilders::buildEditMenu(*this->Internals->menu_Edit, this->Internals->propertiesPanel); // Advanced Menu + + // Populate sources menu. + pqParaViewMenuBuilders::buildSourcesMenu(*this->Internals->menuSources, this); + + // Populate filters menu. + pqParaViewMenuBuilders::buildFiltersMenu(*this->Internals->menuFilters, this); + + // Populate extractors menu. + //pqParaViewMenuBuilders::buildExtractorsMenu(*this->Internals->menuExtractors, this); // Unused + + // Populate Tools menu. + //pqParaViewMenuBuilders::buildToolsMenu(*this->Internals->menuTools); // Advanced Menu + + // Populate Catalyst menu. + //pqParaViewMenuBuilders::buildCatalystMenu(*this->Internals->menu_Catalyst); // Unused + + // setup the context menu for the pipeline browser. + pqParaViewMenuBuilders::buildPipelineBrowserContextMenu(*this->Internals->pipelineBrowser->contextMenu()); + + // CUSTOMIZED Toolbars + //pqParaViewMenuBuilders::buildToolbars(*this); + this->pqbuildToolbars(); + + // Setup the View menu. This must be setup after all toolbars and dockwidgets + // have been created. + pqParaViewMenuBuilders::buildViewMenu(*this->Internals->menuViews, *this); + + // Setup the menu to show macros. + //pqParaViewMenuBuilders::buildMacrosMenu(*this->Internals->menu_Macros); // Advanced Menu + + // Setup the help menu. + //pqParaViewMenuBuilders::buildHelpMenu(*this->Internals->menu_Help); // Custom + + // CUSTOMIZED Paraview behaviors + pqParaViewBehaviors::enableApplyBehavior(); + pqParaViewBehaviors::enableAutoLoadPluginXMLBehavior(); + pqParaViewBehaviors::enableCommandLineOptionsBehavior(); + pqParaViewBehaviors::enableCrashRecoveryBehavior(); + pqParaViewBehaviors::enableDataTimeStepBehavior(); + pqParaViewBehaviors::enableLiveSourceBehavior(); + pqParaViewBehaviors::enableObjectPickingBehavior(); + pqParaViewBehaviors::enableQuickLaunchShortcuts(); + pqParaViewBehaviors::enableSpreadSheetVisibilityBehavior(); + pqParaViewBehaviors::enableStandardPropertyWidgets(); + pqParaViewBehaviors::setEnableStandardViewFrameActions(false); + pqParaViewBehaviors::setEnableDefaultViewBehavior(false); + + pqParaViewBehaviors::setEnableUsageLoggingBehavior(true); + new pqParaViewBehaviors(this, this); // MUST be created before renderView +} + +//----------------------------------------------------------------------------- +void vvMainWindow::pqbuildToolbars() +{ + // Rework of pqParaViewMenuBuilders::buildToolbars + // Removed pqMainControlsToolbar, pqVCRToolbar, pqAnimationTimeToolbar, + // pqCustomViewpointsToolbar, pqColorToolbar, pqRepresentationToolbar + QToolBar* cameraToolbar = new pqCameraToolbar(this) + << pqSetName("cameraToolbar"); + this->addToolBar(Qt::TopToolBarArea, cameraToolbar); + + QToolBar* axesToolbar = new pqAxesToolbar(this) + << pqSetName("axesToolbar"); + this->addToolBar(Qt::TopToolBarArea, axesToolbar); + + // Give the macros menu to the pqPythonMacroSupervisor + pqPythonManager* manager = + qobject_cast<pqPythonManager*>(pqApplicationCore::instance()->manager("PYTHON_MANAGER")); + if (manager) + { + QToolBar* macrosToolbar = new QToolBar("Macros Toolbars", this) + << pqSetName("MacrosToolbar"); + manager->addWidgetForRunMacros(macrosToolbar); + this->addToolBar(Qt::TopToolBarArea, macrosToolbar); + } +} + +//----------------------------------------------------------------------------- +void vvMainWindow::setupLVGUI() +{ + // Add generally common elements to all LidarView-based apps + // Not necessarilly verbatim Paraview + // Feel Free to modify this in your LidarView-based app if you really do not like the look + + // Set the central widget + pqTabbedMultiViewWidget* mv = new pqTabbedMultiViewWidget; + mv->setTabVisibility(false); + this->setCentralWidget(mv); + + // Output Window Dock + this->Internals->outputWidgetDock->setWidget(this->Internals->outputWidget); + this->tabifyDockWidget(this->Internals->informationDock , this->Internals->outputWidgetDock); + connect(this->Internals->actionShowErrorDialog, SIGNAL(triggered()), this->Internals->outputWidgetDock, SLOT(show())); + this->Internals->outputWidgetDock->hide(); + + // Python Shell Dock + this->Internals->pythonShellDock->setWidget(lqLidarViewManager::instance()->getPythonShell()); + this->tabifyDockWidget(this->Internals->informationDock , this->Internals->pythonShellDock); + connect(this->Internals->actionPython_Console , SIGNAL(triggered()), this->Internals->pythonShellDock , SLOT(show())); + this->Internals->pythonShellDock->hide(); + + // Sensor List Dock //wipwip not a core LV element, could also be added in the .ui in internals, like python shell + QDockWidget* sensorListDock = new QDockWidget("Sensor List", this); + sensorListDock->setObjectName("sensorListDock"); + sensorListDock->hide(); + sensorListDock->setWidget(lqSensorListWidget::instance()); + this->addDockWidget(Qt::RightDockWidgetArea, sensorListDock); +} + +//----------------------------------------------------------------------------- +void vvMainWindow::setupGUICustom() +{ + // LidarView Specific UI elements + + // WIP TODO actionResetDefaultSettings needs rework + connect(this->Internals->actionResetDefaultSettings, SIGNAL(triggered()), + lqLidarViewManager::instance(), SLOT(onResetDefaultSettings())); + + // Add Professional Support menu action + new pqDesktopServicesReaction(QUrl("https://www.kitware.com/what-we-offer"), + (this->Internals->actionHelpSupport )); + // How to SLAM menu action + new pqDesktopServicesReaction(QUrl("https://gitlab.kitware.com/keu-computervision/slam/-/blob/master/paraview_wrapping/doc/How_to_SLAM_with_LidarView.md"), + (this->Internals->actionHelpSlam )); + + // Enable help from the properties panel. + QObject::connect(this->Internals->propertiesPanel, + SIGNAL(helpRequested(const QString&, const QString&)), + this, SLOT(showHelpForProxy(const QString&, const QString&))); + + // LidarView-specific Toolbars + QToolBar* vcrToolbar = new lqPlayerControlsToolbar(this) + << pqSetName("Player Control"); + this->addToolBar(Qt::TopToolBarArea, vcrToolbar); + + pqInterfaceTracker* pgm = pqApplicationCore::instance()->interfaceTracker(); + pgm->addInterface(new lqViewFrameActions); + + // Create RenderView dependant reactions + new lqCameraParallelProjectionReaction(this->Internals->actionToggleProjection); + //new pqRenderViewSelectionReaction(this->Internals->actionSelect_Visible_Points, nullptr, // WIP + // pqRenderViewSelectionReaction::SELECT_SURFACE_POINTS); + new pqRenderViewSelectionReaction(this->Internals->actionSelect_Points, nullptr, + pqRenderViewSelectionReaction::SELECT_FRUSTUM_POINTS); + + // LV Reactions + new lqDockableSpreadSheetReaction(this->Internals->actionSpreadsheet, this); + + //WIP SETTINGS GRID + pqSettings* const settings = pqApplicationCore::instance()->settings(); + const QVariant& gridVisible = settings->value("LidarPlugin/MeasurementGrid/Visibility", true); + this->Internals->actionMeasurement_Grid->setChecked(gridVisible.toBool()); + connect(this->Internals->actionMeasurement_Grid, SIGNAL(toggled(bool)), lqLidarViewManager::instance(), + SLOT(onMeasurementGrid(bool))); + + new lqOpenSensorReaction(this->Internals->actionOpen_Sensor_Stream); + new lqOpenPcapReaction(this->Internals->actionOpenPcap); + + new lqUpdateCalibrationReaction(this->Internals->actionChoose_Calibration_File); // Requires lqSensorListWidget init + // Following is required if intend to use the lqSensorListWidget + lqSensorListWidget::instance()->setCalibrationFunction(&lqUpdateCalibrationReaction::UpdateExistingSource); + + new lqSaveLidarStateReaction(this->Internals->actionSaveLidarState); + new lqLoadLidarStateReaction(this->Internals->actionLoadLidarState); + + new lqOpenRecentFilesReaction(this->Internals->menuRecent_Files, this->Internals->actionClear_Menu); + + new lqSaveLidarFrameReaction(this->Internals->actionSavePCD, "PCDWriter" , "pcd", false, false, true, true); + new lqSaveLidarFrameReaction(this->Internals->actionSaveCSV, "DataSetCSVWriter", "csv", false, false, true, true); + new lqSaveLidarFrameReaction(this->Internals->actionSavePLY, "PPLYWriter" , "ply", false, false, true, true); + new lqSaveLASReaction(this->Internals->actionSaveLAS, false, false, true, true); + + // Add save/load lidar state action + new lqEnableAdvancedArraysReaction(this->Internals->actionEnableAdvancedArrays); + + + // Advanced Menu + // build Paraview file menu + QMenu *paraviewFileMenu = this->Internals->menuAdvance->addMenu("File (Paraview)"); + pqParaViewMenuBuilders::buildFileMenu(*paraviewFileMenu); + paraviewFileMenu->setTitle("File (Paraview)"); // for some reason the menu builder rename the QMenu... + + // build Paraview edit menu + QMenu *paraviewEditMenu = this->Internals->menuAdvance->addMenu("Edit (Paraview)"); + pqParaViewMenuBuilders::buildEditMenu(*paraviewEditMenu); + paraviewEditMenu->setTitle("Edit (Paraview)"); // for some reason the menu builder rename the QMenu... + + // build Paraview macro menu + QMenu *paraviewMacroMenu = this->Internals->menuAdvance->addMenu("Macro (Paraview)"); + pqParaViewMenuBuilders::buildMacrosMenu(*paraviewMacroMenu); + + // build Paraview tools menu + // MUST BE ISNTANTIATED LAST for qtTesting + requires pqTabbedMultiViewWidget + QMenu *paraviewToolsMenu = this->Internals->menuAdvance->addMenu("Tools (Paraview)"); + pqParaViewMenuBuilders::buildToolsMenu(*paraviewToolsMenu); + // DO NOT ADD ANYTHING BELOW +} + +//----------------------------------------------------------------------------- +void vvMainWindow::setBranding() +{ + // For good measure + #ifndef SOFTWARE_NAME + #error "SOFTWARE_NAME not defined" + #endif + static_assert( SOFTWARE_NAME, "SOFTWARE_NAME is not defined" ); - // Branding std::stringstream ss; ss << "Reset " << SOFTWARE_NAME << " settings"; QString text = QString(ss.str().c_str()); - this->Internals->Ui.actionResetDefaultSettings->setText(text); + this->Internals->actionResetDefaultSettings->setText(text); ss.str(""); ss.clear(); ss << "This will reset all " << SOFTWARE_NAME << " settings by default"; text = QString(ss.str().c_str()); - this->Internals->Ui.actionResetDefaultSettings->setIconText(text); + this->Internals->actionResetDefaultSettings->setIconText(text); ss.str(""); ss.clear(); ss << "About " << SOFTWARE_NAME; text = QString(ss.str().c_str()); - this->Internals->Ui.actionAbout_LidarView->setText(text); + this->Internals->actionAbout_LidarView->setText(text); ss.str(""); ss.clear(); } -//----------------------------------------------------------------------------- -vvMainWindow::~vvMainWindow() -{ - delete this->Internals; - this->Internals = NULL; -} - //----------------------------------------------------------------------------- void vvMainWindow::dragEnterEvent(QDragEnterEvent* evt) { - evt->acceptProposedAction(); + pqApplicationCore::instance()->getMainWindowEventManager()->dragEnterEvent(evt); } //----------------------------------------------------------------------------- @@ -473,6 +526,20 @@ void vvMainWindow::dropEvent(QDropEvent* evt) } } +//----------------------------------------------------------------------------- +void vvMainWindow::showEvent(QShowEvent* evt) +{ + // TODO PV uses it to show Welcome Message once + // could also be used for the "first startup" stuff + static_cast<void>(evt); +} + +//----------------------------------------------------------------------------- +void vvMainWindow::closeEvent(QCloseEvent* evt) +{ + pqApplicationCore::instance()->getMainWindowEventManager()->closeEvent(evt); +} + //----------------------------------------------------------------------------- void vvMainWindow::showHelpForProxy(const QString& groupname, const QString& proxyname) @@ -480,12 +547,16 @@ void vvMainWindow::showHelpForProxy(const QString& groupname, const pqHelpReaction::showProxyHelp(groupname, proxyname); } +//----------------------------------------------------------------------------- void vvMainWindow::handleMessage(const QString &, int type) { - QDockWidget* dock = this->Internals->Ui.outputWidgetDock; + QDockWidget* dock = this->Internals->outputWidgetDock; if (!dock) + { + std::cout << "Error: NO DOCK for handleMessage()" << std::endl; return; - + } + if (!dock->isVisible() && (type == QtCriticalMsg || type == QtFatalMsg || type == QtWarningMsg)) { // if dock is not visible, we always pop it up as a floating dialog. This diff --git a/Application/vvMainWindow.h b/Application/vvMainWindow.h index 0a96e3e9d16f248ef40b3ea199720a14de075844..05431ea405e6cf9f9e6348c28d3782ac03436f5c 100644 --- a/Application/vvMainWindow.h +++ b/Application/vvMainWindow.h @@ -25,22 +25,35 @@ class vvMainWindow : public QMainWindow public: vvMainWindow(); - virtual ~vvMainWindow(); + virtual ~vvMainWindow() override; protected: void dragEnterEvent(QDragEnterEvent* evt) override; void dropEvent(QDropEvent* evt) override; + void showEvent(QShowEvent* evt) override; + void closeEvent(QCloseEvent* evt) override; -protected slots: +protected Q_SLOTS: void showHelpForProxy(const QString& proxyname, const QString& groupname); - void handleMessage(const QString &, int type); + void handleMessage(const QString&, int); + //void showWelcomeDialog(); + //void updateFontSize(); private: Q_DISABLE_COPY(vvMainWindow); class pqInternals; pqInternals* Internals; - friend class pqInternals; + + // Following Methods should be the same accross LidarView-based Apps + // Exact elements shared accross apps has not been decided yet, + // coherence has been improved, but code-duplication remains for more freedom. + void setupPVGUI(); // Common Parts of the ParaViewMainWindow.cxx + void pqbuildToolbars(); // Reworked pqParaViewMenuBuilders::buildToolbars helper + void setupLVGUI(); // Add generally common elements to all LidarView-based apps + + void setupGUICustom(); // LidarView Specific UI elements + void setBranding(); // LidarView Specific Branding }; #endif diff --git a/Application/vvMainWindow.ui b/Application/vvMainWindow.ui index 19ffa99647378ab0e2848d5cf736745bdd7a8a51..feb76a8d90d50810057e91c71092e899cdc3d646 100644 --- a/Application/vvMainWindow.ui +++ b/Application/vvMainWindow.ui @@ -167,7 +167,7 @@ <addaction name="actionChoose_Calibration_File"/> <addaction name="actionCropReturns"/> <addaction name="separator"/> - <addaction name="actionSelect_All_Points"/> + <addaction name="actionSelect_Points"/> <addaction name="actionSpreadsheet"/> <addaction name="actionPython_Console"/> <addaction name="actionShowErrorDialog"/> @@ -195,7 +195,6 @@ <bool>true</bool> </attribute> <addaction name="actionToggleProjection"/> - <addaction name="actionMeasure"/> <addaction name="actionPlaneFit"/> <addaction name="separator"/> </widget> @@ -342,15 +341,6 @@ </layout> </widget> </widget> - <widget class="QDockWidget" name="sensorListDock"> - <property name="windowTitle"> - <string>Sensors List</string> - </property> - <attribute name="dockWidgetArea"> - <number>2</number> - </attribute> - <widget class="lqSensorListWidget" name="sensorListPanel"/> - </widget> <action name="actionE_xit"> <property name="text"> <string>E&xit</string> @@ -364,7 +354,7 @@ </action> <action name="actionOpenPcap"> <property name="icon"> - <iconset resource="../Plugins/VelodyneUIPlugin/Ui/images/resources.qrc"> + <iconset resource="vvResources.qrc"> <normaloff>:/LidarViewPlugin/WiresharkDoc-128.png</normaloff>:/LidarViewPlugin/WiresharkDoc-128.png</iconset> </property> <property name="text"> @@ -380,19 +370,7 @@ <string>Ctrl+O</string> </property> </action> - <action name="actionSelect_Visible_Points"> - <property name="icon"> - <iconset resource="vvResources.qrc"> - <normaloff>:/vvResources/Icons/pqSurfaceSelectionPoint24.png</normaloff>:/vvResources/Icons/pqSurfaceSelectionPoint24.png</iconset> - </property> - <property name="text"> - <string>Select Visible Points</string> - </property> - <property name="toolTip"> - <string>Select Visible Points (s)</string> - </property> - </action> - <action name="actionSelect_All_Points"> + <action name="actionSelect_Points"> <property name="checkable"> <bool>true</bool> </property> @@ -401,10 +379,10 @@ <normaloff>:/vvResources/Icons/pqFrustumSelectionPoint24.png</normaloff>:/vvResources/Icons/pqFrustumSelectionPoint24.png</iconset> </property> <property name="text"> - <string>Select All Points</string> + <string>Select Points</string> </property> <property name="toolTip"> - <string>Select All Points</string> + <string>Select Points</string> </property> </action> <action name="actionSpreadsheet"> @@ -427,7 +405,7 @@ </action> <action name="actionOpen_Sensor_Stream"> <property name="icon"> - <iconset resource="../Plugins/VelodyneUIPlugin/Ui/images/resources.qrc"> + <iconset resource="vvResources.qrc"> <normaloff>:/LidarViewPlugin/lidar.png</normaloff>:/LidarViewPlugin/lidar.png</iconset> </property> <property name="text"> @@ -454,7 +432,7 @@ </action> <action name="actionChoose_Calibration_File"> <property name="icon"> - <iconset resource="../Plugins/VelodyneUIPlugin/Ui/images/resources.qrc"> + <iconset resource="vvResources.qrc"> <normaloff>:/LidarViewPlugin/calibrate.png</normaloff>:/LidarViewPlugin/calibrate.png</iconset> </property> <property name="text"> @@ -517,7 +495,7 @@ </action> <action name="actionSaveCSV"> <property name="icon"> - <iconset resource="../Plugins/VelodyneUIPlugin/Ui/images/resources.qrc"> + <iconset resource="vvResources.qrc"> <normaloff>:/LidarViewPlugin/csv.png</normaloff>:/LidarViewPlugin/csv.png</iconset> </property> <property name="text"> @@ -526,7 +504,7 @@ </action> <action name="actionExport_To_KiwiViewer"> <property name="icon"> - <iconset resource="../Plugins/VelodyneUIPlugin/Ui/images/resources.qrc"> + <iconset resource="vvResources.qrc"> <normaloff>:/LidarViewPlugin/kiwi_200.png</normaloff>:/LidarViewPlugin/kiwi_200.png</iconset> </property> <property name="text"> @@ -543,7 +521,7 @@ </action> <action name="actionSavePCAP"> <property name="icon"> - <iconset resource="../Plugins/VelodyneUIPlugin/Ui/images/resources.qrc"> + <iconset resource="vvResources.qrc"> <normaloff>:/LidarViewPlugin/WiresharkDoc-128.png</normaloff>:/LidarViewPlugin/WiresharkDoc-128.png</iconset> </property> <property name="text"> @@ -661,21 +639,6 @@ <string>Toggle between projective and orthogonal view</string> </property> </action> - <action name="actionMeasure"> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="icon"> - <iconset resource="vvResources.qrc"> - <normaloff>:/vvResources/Icons/Measurements.png</normaloff>:/vvResources/Icons/Measurements.png</iconset> - </property> - <property name="text"> - <string>Measure</string> - </property> - <property name="toolTip"> - <string>Measure the distance (in meters) between two screen points.<br/>To draw a ruler line, click this button, then hold down the <b>Ctrl key</b> and the <b>left button</b> of your mouse. <br/><u>This feature is only available in orthogonal projection.</u></string> - </property> - </action> <action name="actionPlaneFit"> <property name="icon"> <iconset resource="vvResources.qrc"> @@ -729,7 +692,7 @@ </action> <action name="actionSaveLAS"> <property name="icon"> - <iconset resource="../Plugins/VelodyneUIPlugin/Ui/images/resources.qrc"> + <iconset resource="vvResources.qrc"> <normaloff>:/LidarViewPlugin/las.png</normaloff>:/LidarViewPlugin/las.png</iconset> </property> <property name="text"> @@ -741,7 +704,7 @@ </action> <action name="actionCropReturns"> <property name="icon"> - <iconset resource="../Plugins/VelodyneUIPlugin/Ui/images/resources.qrc"> + <iconset resource="vvResources.qrc"> <normaloff>:/LidarViewPlugin/crop.png</normaloff>:/LidarViewPlugin/crop.png</iconset> </property> <property name="text"> @@ -871,15 +834,8 @@ <extends>QWidget</extends> <header>pqOutputWidget.h</header> </customwidget> - <customwidget> - <class>lqSensorListWidget</class> - <extends>QWidget</extends> - <header>lqSensorListWidget.h</header> - <container>1</container> - </customwidget> </customwidgets> <resources> - <include location="../Plugins/VelodyneUIPlugin/Ui/images/resources.qrc"/> <include location="vvResources.qrc"/> <include location="../LVCore/ApplicationComponents/lqResources.qrc"/> </resources> diff --git a/LVCore b/LVCore index 9784fbe61795430093183022f3717613a8c4e555..9399696dfa00d03145af65e8427fa8082191f5e7 160000 --- a/LVCore +++ b/LVCore @@ -1 +1 @@ -Subproject commit 9784fbe61795430093183022f3717613a8c4e555 +Subproject commit 9399696dfa00d03145af65e8427fa8082191f5e7 diff --git a/Superbuild/lidarview-superbuild b/Superbuild/lidarview-superbuild index e69e8617f6aadb0fe00447fba5b58ad073642b38..c5368f1758255b882326a4dd590268491e184899 160000 --- a/Superbuild/lidarview-superbuild +++ b/Superbuild/lidarview-superbuild @@ -1 +1 @@ -Subproject commit e69e8617f6aadb0fe00447fba5b58ad073642b38 +Subproject commit c5368f1758255b882326a4dd590268491e184899