Skip to content

Commit

Permalink
Merge pull request #1830 from ghutchis/cache-scripts
Browse files Browse the repository at this point in the history
When possible, load script names from cache
  • Loading branch information
ghutchis authored Nov 30, 2024
2 parents fedca00 + 6f2dfec commit 141c595
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 24 deletions.
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

0 comments on commit 141c595

Please sign in to comment.