Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When possible, load script names from cache #1830

Merged
merged 3 commits into from
Nov 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions avogadro/qtgui/scriptloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <QtCore/QDir>
#include <QtCore/QJsonArray>
#include <QtCore/QJsonDocument>
#include <QtCore/QSettings>
#include <QtCore/QStandardPaths>

namespace Avogadro::QtGui {
Expand Down Expand Up @@ -42,6 +43,14 @@ QMultiMap<QString, QString> ScriptLoader::scriptList(const QString& type)
QStringList dirs;
QMultiMap<QString, QString> scriptList;

QSettings settings; // to cache the names of scripts
QStringList scriptFiles = settings.value("scripts/" + type).toStringList();
QStringList scriptNames =
settings.value("scripts/" + type + "/names").toStringList();
// hash from the last modified time and size of the scripts
QStringList scriptHashes =
settings.value("scripts/" + type + "/hashes").toStringList();

// add the default paths
QStringList stdPaths =
QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation);
Expand All @@ -56,7 +65,9 @@ QMultiMap<QString, QString> ScriptLoader::scriptList(const QString& type)
// build up a list of possible files, then we check if they're real scripts
QStringList fileList;
foreach (const QString& dirStr, dirs) {
#ifndef NDEBUG
qDebug() << tr("Checking for %1 scripts in path %2").arg(type).arg(dirStr);
#endif
QDir dir(dirStr);
if (dir.exists() && dir.isReadable()) {
foreach (
Expand Down Expand Up @@ -118,6 +129,21 @@ QMultiMap<QString, QString> ScriptLoader::scriptList(const QString& type)

// go through the list of files to see if they're actually scripts
foreach (const QString& filePath, fileList) {
QFileInfo file(filePath);
// check if we have this from the last time
if (scriptFiles.contains(filePath)) {
int index = scriptFiles.indexOf(filePath);
if (index != -1) {
QString hash = scriptHashes.at(index);
// got a match?
if (hash ==
QString::number(file.size()) + file.lastModified().toString()) {
scriptList.insert(scriptNames.at(index), filePath);
continue;
}
}
}

QString displayName;
if (queryProgramName(filePath, displayName)) {
if (displayName.isEmpty())
Expand All @@ -126,14 +152,27 @@ QMultiMap<QString, QString> ScriptLoader::scriptList(const QString& type)
// Might be another script with the same name
if (scriptList.contains(displayName)) {
// check the last-modified-time of the existing case
QFileInfo file(filePath);
QFileInfo existingFile(scriptList.value(displayName));
if (file.lastModified() > existingFile.lastModified()) {
// replace existing with this new entry
scriptList.replace(displayName, filePath);
// update the cache
int index = scriptFiles.indexOf(filePath);
if (index != -1) {
scriptFiles.replace(index, filePath);
scriptNames.replace(index, displayName);
scriptHashes.replace(index, QString::number(file.size()) +
file.lastModified().toString());
}
}
} else // new entry
} else { // new entry
scriptList.insert(displayName, filePath);
// update the cache
scriptFiles << filePath;
scriptNames << displayName;
scriptHashes << QString::number(file.size()) +
file.lastModified().toString();
}
} // run queryProgramName
} // foreach files

Expand Down
16 changes: 15 additions & 1 deletion avogadro/qtplugins/commandscripts/command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ QStringList Command::menuPath(QAction* action) const
return path;
}

// cache the menu paths
QSettings settings;
QFileInfo info(scriptFileName); // check if the script matches the hash
QString hash =
settings.value("scripts/" + scriptFileName + "/hash").toString();
if (hash == QString::number(info.size()) + info.lastModified().toString()) {
path = settings.value("scripts/" + scriptFileName + "/menu").toStringList();
if (!path.isEmpty())
return path;
}

// otherwise, we have a script name, so ask it
InterfaceScript gen(scriptFileName);
path = gen.menuPath().split('|');
Expand Down Expand Up @@ -93,12 +104,15 @@ QStringList Command::menuPath(QAction* action) const
// add it back to the path
path << lastPart;

// cache the path
settings.setValue("scripts/" + scriptFileName + "/menu", path);

if (priority != 0) {
action->setProperty("menu priority", priority);
}

// try to translate each part of the path
// not ideal, but menus should already be in the translation file
// not ideal, but most menus should already be in the translation file
QStringList translatedPath;
foreach (QString part, path)
translatedPath << tr(part.toUtf8());
Expand Down
5 changes: 3 additions & 2 deletions avogadro/qtplugins/forcefield/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,6 @@ if (NOT BUILD_GPL_PLUGINS)
)
endif()

install(PROGRAMS ${forcefields}
DESTINATION "${INSTALL_LIBRARY_DIR}/avogadro2/scripts/energy/")
# Don't install the scripts - we'll use these as plugins
# install(PROGRAMS ${forcefields}
# DESTINATION "${INSTALL_LIBRARY_DIR}/avogadro2/scripts/energy/")
44 changes: 26 additions & 18 deletions avogadro/qtplugins/forcefield/forcefield.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include <QtCore/QDebug>
#include <QtCore/QSettings>
#include <QtCore/QTimer>

#include <QAction>
#include <QtWidgets/QMessageBox>
Expand Down Expand Up @@ -65,24 +66,6 @@ Forcefield::Forcefield(QObject* parent_)
m_gradientTolerance = settings.value("gradientTolerance", 1.0e-4).toDouble();
settings.endGroup();

// prefer to use Python interface scripts if available
refreshScripts();

// add the openbabel calculators in case they don't exist
#ifdef BUILD_GPL_PLUGINS
// These directly use Open Babel and are fast
qDebug() << " registering GPL plugins";
Calc::EnergyManager::registerModel(new OBEnergy("MMFF94"));
Calc::EnergyManager::registerModel(new OBEnergy("UFF"));
Calc::EnergyManager::registerModel(new OBEnergy("GAFF"));
#else
// These call obmm and can be slower
qDebug() << " registering obmm plugins";
Calc::EnergyManager::registerModel(new OBMMEnergy("MMFF94"));
Calc::EnergyManager::registerModel(new OBMMEnergy("UFF"));
Calc::EnergyManager::registerModel(new OBMMEnergy("GAFF"));
#endif

QAction* action = new QAction(this);
action->setEnabled(true);
action->setText(tr("Optimize Geometry"));
Expand Down Expand Up @@ -133,6 +116,9 @@ Forcefield::Forcefield(QObject* parent_)
action->setData(unfreezeAction);
connect(action, SIGNAL(triggered()), SLOT(unfreezeSelected()));
m_actions.push_back(action);

// single-shot timer to allow the GUI to start up
QTimer::singleShot(500, this, SLOT(deferredStart()));
}

Forcefield::~Forcefield() {}
Expand All @@ -142,6 +128,28 @@ QList<QAction*> Forcefield::actions() const
return m_actions;
}

void Forcefield::deferredStart()
{

// prefer to use Python interface scripts if available
refreshScripts();

// add the openbabel calculators in case they don't exist
#ifdef BUILD_GPL_PLUGINS
// These directly use Open Babel and are fast
qDebug() << " registering GPL plugins";
Calc::EnergyManager::registerModel(new OBEnergy("MMFF94"));
Calc::EnergyManager::registerModel(new OBEnergy("UFF"));
Calc::EnergyManager::registerModel(new OBEnergy("GAFF"));
#else
// These call obmm and can be slower
qDebug() << " registering obmm plugins";
Calc::EnergyManager::registerModel(new OBMMEnergy("MMFF94"));
Calc::EnergyManager::registerModel(new OBMMEnergy("UFF"));
Calc::EnergyManager::registerModel(new OBMMEnergy("GAFF"));
#endif
}

QStringList Forcefield::menuPath(QAction* action) const
{
QStringList path;
Expand Down
2 changes: 2 additions & 0 deletions avogadro/qtplugins/forcefield/forcefield.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ private slots:
void freezeSelected();
void unfreezeSelected();

void deferredStart();

private:
QList<QAction*> m_actions;
QtGui::Molecule* m_molecule = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion avogadro/qtplugins/quantuminput/quantuminput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ void QuantumInput::updateActions()
// Include the full path if there are multiple generators with the same
// name.
QString label = programName;
if (!label.endsWith("…") && !label.endsWith(""))
if (!label.endsWith("…") && !label.endsWith("..."))
label.append("…");

if (scripts.size() == 1) {
Expand Down
Loading