Skip to content

Commit

Permalink
If the library required is already loaded with some other version (#8764
Browse files Browse the repository at this point in the history
)

* If the library required is already loaded with some other version

Then allow the user to cancel the operation or unload everything and reload the class again.
Fixes #8183

* Updated the dialog Message

Handle the loadModel case.

* Info note

* Add convertPackageToLibrary to dictionary
  • Loading branch information
adeas31 committed Mar 29, 2022
1 parent 7262b33 commit a91b842
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 90 deletions.
3 changes: 2 additions & 1 deletion .openmodelica.aspell
@@ -1,4 +1,4 @@
personal_ws-1.1 en 75 UTF-8
personal_ws-1.1 en 79 UTF-8
subscripted
UTF
RML
Expand Down Expand Up @@ -76,3 +76,4 @@ URI
SHA
differentiable
evaluable
convertPackageToLibrary
3 changes: 2 additions & 1 deletion OMCompiler/Compiler/Util/Error.mo
Expand Up @@ -812,8 +812,9 @@ public constant ErrorTypes.Message DER_OF_NONDIFFERENTIABLE_EXP = ErrorTypes.MES
Gettext.gettext("Argument ‘%s‘ of der is not differentiable."));
public constant ErrorTypes.Message LOAD_MODEL_DIFFERENT_VERSIONS_WITHOUT_CONVERSION = ErrorTypes.MESSAGE(370, ErrorTypes.SCRIPTING(), ErrorTypes.NOTIFICATION(),
Gettext.gettext("%1 requested package %2 of version %3. %2 %4 is used instead which states that it is fully compatible without conversion script needed."));
// The following errors (371, 372, 373) are used by OMEdit. Do not change them.
public constant ErrorTypes.Message LOAD_MODEL_DIFFERENT_VERSIONS_WITH_CONVERSION = ErrorTypes.MESSAGE(371, ErrorTypes.SCRIPTING(), ErrorTypes.WARNING(),
Gettext.gettext("%1 requested package %2 of version %3. %2 %4 is used instead which states that it is only compatible with a conversion script. OpenModelica currently does not support conversion scripts and will proceed with potential issues as a result."));
Gettext.gettext("%1 requested package %2 of version %3. %2 %4 is used instead which states that it is only compatible with a conversion script. Use convertPackageToLibrary(%1, %2, \"%4\") to run the conversion script or proceed with potential issues as a result."));
public constant ErrorTypes.Message LOAD_MODEL_DIFFERENT_VERSIONS_OLDER = ErrorTypes.MESSAGE(372, ErrorTypes.SCRIPTING(), ErrorTypes.WARNING(),
Gettext.gettext("Requested package %1 of version %2, but this package was already loaded with version %3. There are no conversion annotations and %2 is older than %3, so the libraries are probably incompatible."));
public constant ErrorTypes.Message LOAD_MODEL_DIFFERENT_VERSIONS_NEWER = ErrorTypes.MESSAGE(373, ErrorTypes.SCRIPTING(), ErrorTypes.WARNING(),
Expand Down
62 changes: 3 additions & 59 deletions OMEdit/OMEditLIB/MainWindow.cpp
Expand Up @@ -1503,7 +1503,7 @@ void MainWindow::addSystemLibraries()
if (versions.isEmpty()) {
QAction *pAction = new QAction(library, this);
pAction->setData(QStringList() << library << "");
connect(pAction, SIGNAL(triggered()), SLOT(loadSystemLibrary()));
connect(pAction, SIGNAL(triggered()), mpLibraryWidget, SLOT(loadSystemLibrary()));
mpLibrariesMenu->addAction(pAction);
} else {
QMenu *pLibraryMenu = new QMenu(library);
Expand All @@ -1513,7 +1513,7 @@ void MainWindow::addSystemLibraries()
if ((library.compare(QStringLiteral("Modelica")) == 0) && (version.compare(QStringLiteral("4.0.0")) == 0)) {
pAction->setShortcut(QKeySequence("Ctrl+m"));
}
connect(pAction, SIGNAL(triggered()), SLOT(loadSystemLibrary()));
connect(pAction, SIGNAL(triggered()), mpLibraryWidget, SLOT(loadSystemLibrary()));
pLibraryMenu->addAction(pAction);
}
mpLibrariesMenu->addMenu(pLibraryMenu);
Expand Down Expand Up @@ -1856,70 +1856,14 @@ void MainWindow::openDirectory()
mpLibraryWidget->openFile(dir, Helper::utf8, true);
}

/*!
* \brief MainWindow::loadSystemLibrary
* Loads a system library.
*/
void MainWindow::loadSystemLibrary()
{
QAction *pAction = qobject_cast<QAction*>(sender());
if (pAction) {
QStringList actionData = pAction->data().toStringList();
if (actionData.size() > 1) {
loadSystemLibrary(actionData.at(0), actionData.at(1));
}
}
}

/*!
* \brief MainWindow::loadSystemLibrary
* Loads a system library.
* \param library
* \param version
*/
void MainWindow::loadSystemLibrary(const QString &library, QString version)
{
/* check if library is already loaded. */
LibraryTreeModel *pLibraryTreeModel = mpLibraryWidget->getLibraryTreeModel();
if (pLibraryTreeModel->findLibraryTreeItemOneLevel(library)) {
QMessageBox *pMessageBox = new QMessageBox(this);
pMessageBox->setWindowTitle(QString("%1 - %2").arg(Helper::applicationName, Helper::information));
pMessageBox->setIcon(QMessageBox::Information);
pMessageBox->setAttribute(Qt::WA_DeleteOnClose);
pMessageBox->setText(QString(GUIMessages::getMessage(GUIMessages::UNABLE_TO_LOAD_FILE).arg(library)));
pMessageBox->setInformativeText(QString(GUIMessages::getMessage(GUIMessages::REDEFINING_EXISTING_CLASSES)).arg(library).append("\n")
.append(GUIMessages::getMessage(GUIMessages::DELETE_AND_LOAD).arg(library)));
pMessageBox->setStandardButtons(QMessageBox::Ok);
pMessageBox->exec();
} else { /* if library is not loaded then load it. */
mpProgressBar->setRange(0, 0);
showProgressBar();
mpStatusBar->showMessage(QString(Helper::loading).append(": ").append(library));

if (version.isEmpty()) {
version = QString("default");
}

mpLibraryWidget->setLoadingLibraries(true);
if (mpOMCProxy->loadModel(library, version)) {
pLibraryTreeModel->createLibraryTreeItem(library, pLibraryTreeModel->getRootLibraryTreeItem(), true, true, true);
pLibraryTreeModel->checkIfAnyNonExistingClassLoaded();
}
mpLibraryWidget->setLoadingLibraries(false);
mpStatusBar->clearMessage();
hideProgressBar();
}
}

/*!
* \brief MainWindow::writeOutputFileData
* Writes the output data from stdout file and adds it to MessagesWidget.
* \param data
*/
void MainWindow::writeOutputFileData(QString data)
{
MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, data,
Helper::scriptingKind, Helper::notificationLevel));
MessagesWidget::instance()->addGUIMessage(MessageItem(MessageItem::Modelica, data, Helper::scriptingKind, Helper::notificationLevel));
}

/*!
Expand Down
2 changes: 0 additions & 2 deletions OMEdit/OMEditLIB/MainWindow.h
Expand Up @@ -486,8 +486,6 @@ public slots:
void openCompositeModelFile();
void loadExternalModels();
void openDirectory();
void loadSystemLibrary();
void loadSystemLibrary(const QString &library, QString version = QString("default"));
void writeOutputFileData(QString data);
void writeErrorFileData(QString data);
void openRecentFile();
Expand Down
157 changes: 143 additions & 14 deletions OMEdit/OMEditLIB/Modeling/LibraryTreeWidget.cpp
Expand Up @@ -4196,24 +4196,31 @@ void LibraryWidget::openModelicaFile(QString fileName, QString encoding, bool sh
pMessageBox->exec();
} else { // if no conflicting model found then just load the file simply
setLoadingLibraries(true);
QStringList classes = MainWindow::instance()->getOMCProxy()->getClassNames();
// load the file in OMC
if (MainWindow::instance()->getOMCProxy()->loadFile(fileName, encoding)) {
// create library tree nodes for loaded models
int progressvalue = 0;
if (showProgress) {
MainWindow::instance()->getProgressBar()->setRange(0, classesList.size());
MainWindow::instance()->showProgressBar();
}
foreach (QString model, classesList) {
mpLibraryTreeModel->createLibraryTreeItem(model, mpLibraryTreeModel->getRootLibraryTreeItem(), true, false, true, -1);
mpLibraryTreeModel->checkIfAnyNonExistingClassLoaded();
if (MainWindow::instance()->getOMCProxy()->isLoadModelError()) {
if (resolveConflictWithLoadedLibraries(classesList.join(","), classes)) {
openModelicaFile(fileName, encoding, showProgress);
}
} else {
// create library tree nodes for loaded models
int progressvalue = 0;
if (showProgress) {
MainWindow::instance()->getProgressBar()->setValue(++progressvalue);
MainWindow::instance()->getProgressBar()->setRange(0, classesList.size());
MainWindow::instance()->showProgressBar();
}
foreach (QString model, classesList) {
mpLibraryTreeModel->createLibraryTreeItem(model, mpLibraryTreeModel->getRootLibraryTreeItem(), true, false, true, -1);
mpLibraryTreeModel->checkIfAnyNonExistingClassLoaded();
if (showProgress) {
MainWindow::instance()->getProgressBar()->setValue(++progressvalue);
}
}
MainWindow::instance()->addRecentFile(fileName, encoding);
if (showProgress) {
MainWindow::instance()->hideProgressBar();
}
}
MainWindow::instance()->addRecentFile(fileName, encoding);
if (showProgress) {
MainWindow::instance()->hideProgressBar();
}
}
setLoadingLibraries(false);
Expand Down Expand Up @@ -5238,6 +5245,67 @@ void LibraryWidget::saveTotalLibraryTreeItemHelper(LibraryTreeItem *pLibraryTree
}
}

/*!
* \brief LibraryWidget::resolveConflictWithLoadedLibraries
* Check if the library loaded is compatiable with the already loaded libraries.
* \param library
* \param classes
* \return
*/
bool LibraryWidget::resolveConflictWithLoadedLibraries(const QString &library, const QStringList classes)
{
/* Issue #8183
* If the library required is already loaded with some other version.
* Then allow the user to cancel the operation or unload everything and reload the class again.
*/
QStringList classes1;
LibraryTreeItem *pLibraryTreeItem = 0;
// clear loadModelCallback classes
mAutoLoadedLibrariesList.clear();

QMessageBox *pMessageBox = new QMessageBox;
pMessageBox->setWindowTitle(QString("%1 - %2").arg(Helper::applicationName, Helper::error));
pMessageBox->setIcon(QMessageBox::Critical);
pMessageBox->setAttribute(Qt::WA_DeleteOnClose);
pMessageBox->setText(tr("The loaded class(es) <b>%1</b> uses versions of already loaded libraries which are not compatible with the required ones.<br /><br />"
"<b>Cancel Operation</b> does not load class <b>%1</b> and its dependencies.<br />"
"<b>Unload All & Reload %1</b> unloads all previously loaded classes and loads <b>%1</b> starting from a clean environment. "
"Make sure to save your work.").arg(library));
pMessageBox->addButton(tr("Cancel Operation"), QMessageBox::ActionRole);
pMessageBox->addButton(tr("Unload all && Reload %1").arg(library), QMessageBox::ActionRole);
int answer = pMessageBox->exec();
switch (answer) {
case 0: // cancel operation
default:
classes1 = MainWindow::instance()->getOMCProxy()->getClassNames();
if (classes1.size() > classes.size()) {
foreach (QString loadedClass, classes1) {
if (!classes.contains(loadedClass)) {
pLibraryTreeItem = MainWindow::instance()->getLibraryWidget()->getLibraryTreeModel()->findLibraryTreeItemOneLevel(loadedClass);
if (pLibraryTreeItem) {
MainWindow::instance()->getLibraryWidget()->getLibraryTreeModel()->unloadClass(pLibraryTreeItem, false, true);
} else {
MainWindow::instance()->getOMCProxy()->deleteClass(loadedClass);
}
}
}
}
return false;
case 1: // unload all and reload
classes1 = MainWindow::instance()->getOMCProxy()->getClassNames();
foreach (QString loadedClass, classes1) {
pLibraryTreeItem = MainWindow::instance()->getLibraryWidget()->getLibraryTreeModel()->findLibraryTreeItemOneLevel(loadedClass);
if (pLibraryTreeItem) {
MainWindow::instance()->getLibraryWidget()->getLibraryTreeModel()->unloadClass(pLibraryTreeItem, false, true);
} else {
MainWindow::instance()->getOMCProxy()->deleteClass(loadedClass);
}
}
// Just return true and the calling function will load the library.
return true;
}
}

/*!
* \brief LibraryWidget::handleAutoLoadedLibrary
* Slot activated when auto load library timer is timeout.
Expand All @@ -5252,6 +5320,67 @@ void LibraryWidget::handleAutoLoadedLibrary()
}
}

/*!
* \brief LibraryWidget::loadSystemLibrary
* Loads a system library.
*/
void LibraryWidget::loadSystemLibrary()
{
QAction *pAction = qobject_cast<QAction*>(sender());
if (pAction) {
QStringList actionData = pAction->data().toStringList();
if (actionData.size() > 1) {
loadSystemLibrary(actionData.at(0), actionData.at(1));
}
}
}

/*!
* \brief LibraryWidget::loadSystemLibrary
* Loads a system library.
* \param library
* \param version
*/
void LibraryWidget::loadSystemLibrary(const QString &library, QString version)
{
/* check if library is already loaded. */
if (mpLibraryTreeModel->findLibraryTreeItemOneLevel(library)) {
QMessageBox *pMessageBox = new QMessageBox(this);
pMessageBox->setWindowTitle(QString("%1 - %2").arg(Helper::applicationName, Helper::information));
pMessageBox->setIcon(QMessageBox::Information);
pMessageBox->setAttribute(Qt::WA_DeleteOnClose);
pMessageBox->setText(QString(GUIMessages::getMessage(GUIMessages::UNABLE_TO_LOAD_FILE).arg(library)));
pMessageBox->setInformativeText(QString(GUIMessages::getMessage(GUIMessages::REDEFINING_EXISTING_CLASSES)).arg(library).append("\n")
.append(GUIMessages::getMessage(GUIMessages::DELETE_AND_LOAD).arg(library)));
pMessageBox->setStandardButtons(QMessageBox::Ok);
pMessageBox->exec();
} else { /* if library is not loaded then load it. */
MainWindow::instance()->getProgressBar()->setRange(0, 0);
MainWindow::instance()->showProgressBar();
MainWindow::instance()->getStatusBar()->showMessage(QString(Helper::loading).append(": ").append(library));

if (version.isEmpty()) {
version = QString("default");
}

setLoadingLibraries(true);
QStringList classes = MainWindow::instance()->getOMCProxy()->getClassNames();
if (MainWindow::instance()->getOMCProxy()->loadModel(library, version)) {
if (MainWindow::instance()->getOMCProxy()->isLoadModelError()) {
if (resolveConflictWithLoadedLibraries(library, classes)) {
loadSystemLibrary(library, version);
}
} else {
mpLibraryTreeModel->createLibraryTreeItem(library, mpLibraryTreeModel->getRootLibraryTreeItem(), true, true, true);
mpLibraryTreeModel->checkIfAnyNonExistingClassLoaded();
}
}
setLoadingLibraries(false);
MainWindow::instance()->getStatusBar()->clearMessage();
MainWindow::instance()->hideProgressBar();
}
}

/*!
* \brief LibraryWidget::scrollToActiveLibraryTreeItem
* Makes sure that active LibraryTreeItem is visible. Scrolls to active LibraryTreeItem.
Expand Down
3 changes: 3 additions & 0 deletions OMEdit/OMEditLIB/Modeling/LibraryTreeWidget.h
Expand Up @@ -521,9 +521,12 @@ class LibraryWidget : public QWidget
bool saveAsOMSLibraryTreeItem(LibraryTreeItem *pLibraryTreeItem);
bool saveCompositeModelLibraryTreeItem(LibraryTreeItem *pLibraryTreeItem, QString fileName);
void saveTotalLibraryTreeItemHelper(LibraryTreeItem *pLibraryTreeItem);
bool resolveConflictWithLoadedLibraries(const QString &library, const QStringList classes);
private slots:
void handleAutoLoadedLibrary();
public slots:
void loadSystemLibrary();
void loadSystemLibrary(const QString &library, QString version = QString("default"));
void scrollToActiveLibraryTreeItem();
void searchClasses();
};
Expand Down
25 changes: 22 additions & 3 deletions OMEdit/OMEditLIB/OMC/OMCProxy.cpp
Expand Up @@ -133,6 +133,7 @@ OMCProxy::OMCProxy(threadData_t* threadData, QWidget *pParent)
mLibrariesBrowserDeletionCommandsList << "deleteClass"
<< "clear"
<< "clearProgram";
mLoadModelError = false;
//start the server
if(!initializeOMC(threadData)) { // if we are unable to start OMC. Exit the application.
MainWindow::instance()->setExitApplicationStatus(true);
Expand Down Expand Up @@ -573,9 +574,14 @@ bool OMCProxy::printMessagesStringInternal()
/* Loop in reverse order since getMessagesStringInternal returns error messages in reverse order. */
for (int i = errorsSize; i > 0 ; i--) {
setCurrentError(i);
MessageItem messageItem(MessageItem::Modelica, getErrorFileName(), getErrorReadOnly(), getErrorLineStart(), getErrorColumnStart(), getErrorLineEnd(),
getErrorColumnEnd(), getErrorMessage(), getErrorKind(), getErrorLevel());
MessagesWidget::instance()->addGUIMessage(messageItem);
const int errorId = getErrorId();
if (errorId == 371 || errorId == 372 || errorId == 373) {
mLoadModelError = true;
} else {
MessageItem messageItem(MessageItem::Modelica, getErrorFileName(), getErrorReadOnly(), getErrorLineStart(), getErrorColumnStart(), getErrorLineEnd(),
getErrorColumnEnd(), getErrorMessage(), getErrorKind(), getErrorLevel());
MessagesWidget::instance()->addGUIMessage(messageItem);
}
}
return returnValue;
}
Expand Down Expand Up @@ -701,6 +707,17 @@ QString OMCProxy::getErrorLevel()
return getResult();
}

/*!
* \brief OMCProxy::getErrorId
* Gets the current error id.
* \return
*/
int OMCProxy::getErrorId()
{
sendCommand("currentError.id");
return getResult().toInt();
}

/*!
Gets the OMC version. On Linux it also return the revision number as well.
\return the version
Expand Down Expand Up @@ -1584,6 +1601,7 @@ QString OMCProxy::changeDirectory(QString directory)
*/
bool OMCProxy::loadModel(QString className, QString priorityVersion, bool notify, QString languageStandard, bool requireExactVersion)
{
mLoadModelError = false;
bool result = false;
QList<QString> priorityVersionList;
priorityVersionList << priorityVersion;
Expand All @@ -1599,6 +1617,7 @@ bool OMCProxy::loadModel(QString className, QString priorityVersion, bool notify
*/
bool OMCProxy::loadFile(QString fileName, QString encoding, bool uses, bool notify, bool requireExactVersion)
{
mLoadModelError = false;
bool result = false;
fileName = fileName.replace('\\', '/');
result = mpOMCInterface->loadFile(fileName, encoding, uses, notify, requireExactVersion);
Expand Down
3 changes: 3 additions & 0 deletions OMEdit/OMEditLIB/OMC/OMCProxy.h
Expand Up @@ -82,6 +82,7 @@ class OMCProxy : public QObject
bool mIsLoggingEnabled;
QStringList mLibrariesBrowserAdditionCommandsList;
QStringList mLibrariesBrowserDeletionCommandsList;
bool mLoadModelError;
public:
OMCProxy(threadData_t *threadData, QWidget *pParent = 0);
~OMCProxy();
Expand All @@ -97,6 +98,7 @@ class OMCProxy : public QObject
void removeObjectRefFile();
void setLoggingEnabled(bool enable) {mIsLoggingEnabled = enable;}
bool isLoggingEnabled() {return mIsLoggingEnabled;}
bool isLoadModelError() const {return mLoadModelError;}
QString getErrorString(bool warningsAsErrors = false);
bool printMessagesStringInternal();
int getMessagesStringInternal();
Expand All @@ -110,6 +112,7 @@ class OMCProxy : public QObject
QString getErrorMessage();
QString getErrorKind();
QString getErrorLevel();
int getErrorId();
QString getVersion(QString className = QString("OpenModelica"));
void loadSystemLibraries();
void loadUserLibraries();
Expand Down

0 comments on commit a91b842

Please sign in to comment.