Commit 9296370f authored by John Tourtellott's avatar John Tourtellott

Merge branch 'cubit-integration'

Adds toolbar with button to launch CUBIT executable
* cubit-integration:
  Add icon for the cubit-launch action
  Add logic to get working directory, plus some refactoring
  Add code to launch the executable using QProcess
  Add logic get path to CUBIT from user
  Add Cubit toolbar with simple "launch" button
  Add paraview setting for the path to the CUBIT executable
parents 78078ea4 2aea6bec
<ServerManagerConfiguration>
<ProxyGroup name="settings">
<SettingsProxy name="ACE3PSettings" label="ACE3P"
processes="client|dataserver|renderserver">
<Documentation>
Settings for the ACE3P Plugin
</Documentation>
<StringVectorProperty
name="CubitPath"
label="CUBIT"
number_of_elements="1"
default_values=""
panel_visibility="default">
<Documentation>
The path to the CUBIT executable.
</Documentation>
<FileListDomain name="files" />
</StringVectorProperty>
<Hints>
<UseDocumentationForLabels />
</Hints>
</SettingsProxy>
</ProxyGroup>
</ServerManagerConfiguration>
set(PluginHdrs
set(client_headers
pqCubitToolBar.h
pqCumulusJobsPanel.h
)
)
set(PluginSrcs
pqCumulusJobsPanel.cxx
)
set(client_sources
pqCubitToolBar.cxx
pqCumulusJobsPanel.cxx
)
set(CMAKE_AUTOMOC 1)
......@@ -16,14 +18,28 @@ paraview_plugin_add_dock_window(
SOURCES dock_sources
)
paraview_plugin_add_toolbar(
CLASS_NAME pqCubitToolBar
INTERFACES toolbar_interfaces
SOURCES toolbar_sources
)
# Specify the plugin
paraview_add_plugin(smtkACE3PPlugin
VERSION "1.0"
UI_INTERFACES ${dock_interfaces}
UI_INTERFACES
${dock_interfaces}
${toolbar_interfaces}
SOURCES
${PluginHdrs}
${PluginSrcs}
${client_headers}
${client_sources}
${dock_sources}
${toolbar_sources}
UI_RESOURCES
icons.qrc
SERVER_MANAGER_XML
ACE3PSettings.xml
XML_DOCUMENTATION OFF
)
target_link_libraries(smtkACE3PPlugin
......
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><title>CUBIT_SVG</title><path d="M26.71,59.14a.5.5,0,0,1-.31-.1L5.22,43.65A.53.53,0,0,1,5,43.22V10.13a.53.53,0,0,1,.41-.52L33.58,3a.54.54,0,0,1,.28,0l24.77,8.18a.53.53,0,0,1,.37.5V44.8a.53.53,0,0,1-.32.49L26.92,59.1A.49.49,0,0,1,26.71,59.14Z" style="fill:#c9c9c9"/><polygon points="58.44 22.22 37.25 29.91 37.4 41.47 58.53 33.04 58.44 22.22" style="fill:#fff"/><polygon points="58.44 11.83 58.44 22.22 37.4 29.88 37.27 42.05 58.38 33.57 58.38 45.09 26.81 58.52 26.81 21.22 58.44 11.83" style="fill:#009a00"/><polygon points="48.85 8.7 19.41 16.76 18.4 17.69 18.49 53.35 26.48 58.52 26.74 21.09 58.18 11.63 48.85 8.7" style="fill:#004d00"/><path d="M11.26,48.61a.54.54,0,0,1-.54-.54V13.77a.54.54,0,0,1,1.08,0v34.3A.54.54,0,0,1,11.26,48.61Z" style="fill:#787878"/><path d="M18.38,53.67a.54.54,0,0,1-.54-.54V17.34a.54.54,0,0,1,1.08,0V53.13A.54.54,0,0,1,18.38,53.67Z" style="fill:#787878"/><path d="M37.23,55.06a.54.54,0,0,1-.54-.54V18.17a.54.54,0,0,1,.54-.54.54.54,0,0,1,.54.54V54.52A.54.54,0,0,1,37.23,55.06Z" style="fill:#787878"/><path d="M47.93,50.41a.55.55,0,0,1-.54-.54V15a.54.54,0,0,1,.54-.54.54.54,0,0,1,.54.54v34.9A.54.54,0,0,1,47.93,50.41Z" style="fill:#787878"/><path d="M26.53,34.74a.54.54,0,0,1-.18-1.05l32.1-11.83a.55.55,0,0,1,.69.33.54.54,0,0,1-.32.69L26.72,34.71A.63.63,0,0,1,26.53,34.74Z" style="fill:#787878"/><path d="M26.41,46.88a.54.54,0,0,1-.2-1L58.43,33a.55.55,0,0,1,.71.3.54.54,0,0,1-.31.7L26.61,46.84A.48.48,0,0,1,26.41,46.88Z" style="fill:#787878"/><path d="M26.53,21.92a.59.59,0,0,1-.25-.07L4.87,10.64a.55.55,0,0,1-.28-.55A.56.56,0,0,1,5,9.63L33.47,3a.48.48,0,0,1,.29,0l25,8.27a.52.52,0,0,1,.37.52.53.53,0,0,1-.38.51l-32.1,9.61A.45.45,0,0,1,26.53,21.92ZM6.66,10.35,26.59,20.79l30.25-9L33.57,4.05Z" style="fill:#787878"/><path d="M26.53,59.71a.55.55,0,0,1-.32-.1L4.81,44.05a.55.55,0,0,1-.23-.44V10.16A.56.56,0,0,1,5,9.63L33.47,3a.48.48,0,0,1,.29,0l25,8.27a.52.52,0,0,1,.37.51V45.21a.54.54,0,0,1-.32.5l-32.1,14A.54.54,0,0,1,26.53,59.71ZM5.66,43.34,26.6,58.55,58.09,44.86V12.15L33.57,4.05,5.66,10.59Z" style="fill:#787878"/><path d="M26.53,59.71a.54.54,0,0,1-.54-.54V21.38a.54.54,0,1,1,1.08,0V59.17A.54.54,0,0,1,26.53,59.71Z" style="fill:#787878"/><path d="M11.7,13.83a.53.53,0,0,1-.52-.41.55.55,0,0,1,.39-.66L40.74,5.37a.54.54,0,1,1,.26,1L11.84,13.81Z" style="fill:#787878"/><path d="M18.67,17.54a.56.56,0,0,1-.53-.4.54.54,0,0,1,.38-.66l30.4-8.4a.53.53,0,0,1,.66.38.54.54,0,0,1-.37.66l-30.4,8.4Z" style="fill:#787878"/><path d="M37.23,18.71a.68.68,0,0,1-.23-.05L15.19,8.23a.54.54,0,0,1,.47-1L37.47,17.68a.54.54,0,0,1-.24,1Z" style="fill:#787878"/><path d="M47.93,15.51a.54.54,0,0,1-.21,0L25.19,5.91a.54.54,0,1,1,.42-1l22.53,9.55a.53.53,0,0,1,.29.71A.56.56,0,0,1,47.93,15.51Z" style="fill:#787878"/><path d="M26.33,34.63a.55.55,0,0,1-.28-.07l-21.21-13a.55.55,0,0,1-.18-.74.54.54,0,0,1,.75-.18l21.2,12.94a.54.54,0,0,1-.28,1Z" style="fill:#787878"/><path d="M26.41,46.88a.52.52,0,0,1-.29-.09L4.83,33.1a.54.54,0,1,1,.59-.9L26.7,45.88a.55.55,0,0,1,.16.75A.53.53,0,0,1,26.41,46.88Z" style="fill:#787878"/></svg>
\ No newline at end of file
<RCC>
<qresource prefix="/icons/toolbar">
<file alias = "cubit02.svg">CUBIT_SVG-02.svg</file>
</qresource>
</RCC>
//=========================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#include "pqCubitToolBar.h"
// Client side
#include "pqActiveObjects.h"
#include "pqCoreUtilities.h"
#include "pqServer.h"
#include "vtkSMProperty.h"
#include "vtkSMProxy.h"
#include "vtkSMSessionProxyManager.h"
#include "vtkSMStringVectorProperty.h"
// Qt
#include <QAction>
#include <QDebug>
#include <QDir>
#include <QFileDialog>
#include <QFileInfo>
#include <QIcon>
#include <QMessageBox>
#include <QProcess>
#include <QStringList>
#include <QWidget>
pqCubitToolBar::pqCubitToolBar(QWidget* parent)
: Superclass("CUBIT Application", parent)
, m_cubitPID(0)
{
this->setObjectName("CUBIT Executable");
QAction* launchAction = this->addAction(QIcon(":/icons/toolbar/cubit02.svg"), "Launch CUBIT",
this, &pqCubitToolBar::onLaunch);
}
pqCubitToolBar::~pqCubitToolBar() = default;
void pqCubitToolBar::onLaunch()
{
QWidget* mainWidget = pqCoreUtilities::mainWidget();
// Have we been here before?
if (m_cubitPID != 0)
{
QString text = "You have already started CUBIT from modelbuilder before."
" Do you want to continue anyway?";
int choice = QMessageBox::question(mainWidget, "CUBIT Already Running?", text);
if (choice != QMessageBox::Yes)
{
return;
}
}
QString cubitPath;
if (!this->getCubitPath(cubitPath))
{
return;
}
QString workspacePath;
if (!this->getWorkspacePath(workspacePath))
{
return;
}
// Make sure workspace/cubit folder exists
QDir workspaceDir(workspacePath);
QDir workingDir(workspaceDir);
if (!workingDir.cd("cubit"))
{
if (!workspaceDir.mkdir("cubit"))
{
QMessageBox::warning(mainWidget, "Cannot Create working Directory",
"Error creating working directory " + workingDir.canonicalPath());
return;
}
workingDir.setPath(workspaceDir.path());
workingDir.cd("cubit");
}
// Start cubit as a detached process
bool success = this->runCubit(cubitPath, workingDir.canonicalPath());
if (!success)
{
QMessageBox::warning(mainWidget, "CUBIT LAUNCH FAILED", "The system was unable to launch CUBIT.");
return;
}
}
void pqCubitToolBar::askUserForPath(const QString& headline, const QString& details, QString& result) const
{
QWidget* mainWidget = pqCoreUtilities::mainWidget();
QMessageBox msgBox(mainWidget);
msgBox.setText(headline);
msgBox.setInformativeText(details);
msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
msgBox.setDefaultButton(QMessageBox::Yes);
int msgRet = msgBox.exec();
if (msgRet != QMessageBox::Yes)
{
result.clear();
return;
}
QFileDialog fileDialog(mainWidget, "CUBIT executable");
fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
fileDialog.setFileMode(QFileDialog::ExistingFile);
bool fileRet = fileDialog.exec();
if (fileRet != QDialog::Accepted)
{
result.clear();
}
else
{
result = fileDialog.selectedFiles().at(0);
}
}
bool pqCubitToolBar::checkCubitPath(const QString& path, QString& reason) const
{
QFileInfo fileInfo(path);
if (!fileInfo.exists())
{
reason = "File was not found at " + path + ".";
return false;
}
if (!fileInfo.isExecutable())
{
reason = "The file is not executable: " + path + ".";
return false;
}
if (!fileInfo.permission(QFileDevice::ExeUser))
{
reason = "The current user does not have permission to run " + path + ".";
return false;
}
return true;
}
bool pqCubitToolBar::getCubitPath(QString& usePath) const
{
// Get the CUBIT path from application settings
QWidget* mainWidget = pqCoreUtilities::mainWidget();
pqServer* server = pqActiveObjects::instance().activeServer();
vtkSMProxy* proxy = server->proxyManager()->GetProxy("settings", "ACE3PSettings");
if (!proxy)
{
QMessageBox::warning(
mainWidget, "Internal Error", "Internal Error: Settings proxy for ACE3P not found.");
return false;
}
vtkSMProperty* cubitProp = proxy->GetProperty("CubitPath");
auto* cubitStringProp = vtkSMStringVectorProperty::SafeDownCast(cubitProp);
if (!cubitStringProp)
{
QMessageBox::critical(
mainWidget, "Internal Error", "Internal Error: CubitPath not found in ACE3P settings.");
return false;
}
std::string cubitPath = cubitStringProp->GetElement(0);
// Make sure the path is set to a valid executable
bool done = false;
QString path = QString::fromStdString(cubitPath);
int ret;
while (!done)
{
QString headline;
QString details;
if (path.isEmpty())
{
headline = "The application does not know where CUBIT is on your system.";
details = "Do you want to set it now?";
this->askUserForPath(headline, details, path);
if (path.isEmpty())
{
break;
}
} // if (path empty)
// Check path
QString reason;
if (this->checkCubitPath(path, reason))
{
done = true;
break;
}
// (else)
this->askUserForPath(reason, "Do you want to try again?", path);
if (path.isEmpty())
{
break;
}
} // while
if (path.isEmpty())
{
return false;
}
// (else)
usePath = path;
cubitPath = path.toStdString();
// Update settings
cubitStringProp->SetElement(0, cubitPath.c_str());
proxy->UpdateVTKObjects();
return true;
}
bool pqCubitToolBar::getWorkspacePath(QString& usePath) const
{
// Get the Workspace path from application settings
QWidget* mainWidget = pqCoreUtilities::mainWidget();
pqServer* server = pqActiveObjects::instance().activeServer();
vtkSMProxy* proxy = server->proxyManager()->GetProxy("settings", "SMTKSettings");
if (!proxy)
{
QMessageBox::critical(
mainWidget, "Internal Error", "Internal Error: Settings proxy for SMTK not found.");
return false;
}
vtkSMProperty* folderProp = proxy->GetProperty("ProjectsRootFolder");
auto* folderStringProp = vtkSMStringVectorProperty::SafeDownCast(folderProp);
if (!folderStringProp)
{
QMessageBox::critical(
mainWidget, "Internal Error", "Internal Error: ProjectsRootFolder not found in SMTK settings.");
return false;
}
std::string folderPath = folderStringProp->GetElement(0);
QString path = QString::fromStdString(folderPath);
if (path.isEmpty())
{
QString headline = "The projects workspace folder has not been specified.";
QString details = "This setting is required before you can run CUBIT."
" Do you want to set it now?";
this->askUserForPath(headline, details, path);
if (path.isEmpty())
{
return false;
}
} // if (path empty)
// Check that path exists
QDir projectsFolder(path);
if (!projectsFolder.exists() && !projectsFolder.mkpath(path))
{
QString details = "The system could not create a folder at " + path;
QMessageBox::warning(mainWidget, "Unable to create projects folder", details);
return false;
}
// (else)
usePath = path;
// Update settings
folderStringProp->SetElement(0, path.toStdString().c_str());
proxy->UpdateVTKObjects();
return true;
}
bool pqCubitToolBar::runCubit(const QString& path, const QString& workingDir)
{
QProcess process;
process.setProgram(path);
QStringList args;
args << "-workingdir" << workingDir;
process.setArguments(args);
process.setWorkingDirectory(workingDir); // backup
qint64 pid;
qInfo() << "Starting" << path;
bool success = process.startDetached(&pid);
if (success)
{
qInfo() << "Started" << path << "as process" << pid;
qInfo() << "Working directory" << workingDir;
m_cubitPID = pid;
}
return success;
}
//=========================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#ifndef ace3p_extension_plugin_pqCubitToolBar_h
#define ace3p_extension_plugin_pqCubitToolBar_h
#include "smtk/PublicPointerDefs.h"
#include <QString>
#include <QtGlobal> // qint64
#include <QToolBar>
class pqCubitToolBar : public QToolBar
{
Q_OBJECT
using Superclass = QToolBar;
public:
pqCubitToolBar(QWidget* parent = nullptr);
~pqCubitToolBar() override;
protected slots:
void onLaunch();
protected:
void askUserForPath(const QString& headline, const QString& details, QString& result) const;
bool checkCubitPath(const QString& path, QString& reason) const;
bool getCubitPath(QString& path) const;
bool getWorkspacePath(QString& path) const;
bool runCubit(const QString& path, const QString& workingDir);
// Remember if we already started CUBIT before
qint64 m_cubitPID;
private:
Q_DISABLE_COPY(pqCubitToolBar);
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment