Skip to content

Commit

Permalink
Use relative paths for shortcuts inside drive_c
Browse files Browse the repository at this point in the history
This allows apps inside the prefix to be implicitly portable with regards to the prefix folder, so long as the app itself isn't moved within the prefix.
Apps that don't exist will now simply popup an error message explaining as such.
Also some other misc tweaks.
  • Loading branch information
SeongGino committed Dec 26, 2024
1 parent 8d2090b commit e8cb9ed
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 56 deletions.
76 changes: 43 additions & 33 deletions src/neromanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ void NeroManagerWindow::RenderPrefixList()
prefixShortcutPlayButton.at(i)->setToolTip("Start " + sortedShortcuts.at(i));
prefixShortcutPlayButton.at(i)->setIconSize(QSize(16, 16));
prefixShortcutPlayButton.at(i)->setProperty("slot", i);
prefixShortcutPlayButton.at(i)->setProperty("hash", hashMap[sortedShortcuts.at(i)]);

prefixShortcutEditButton << new QPushButton(QIcon::fromTheme("document-properties"), "");
prefixShortcutEditButton.at(i)->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
Expand Down Expand Up @@ -504,6 +505,7 @@ void NeroManagerWindow::on_addButton_clicked()
prefixShortcutPlayButton.last()->setIconSize(QSize(16, 16));
prefixShortcutPlayButton.last()->setToolTip("Start " + shortcutAdd.shortcutName);
prefixShortcutPlayButton.last()->setProperty("slot", pos);
prefixShortcutPlayButton.last()->setProperty("hash", hashName);

prefixShortcutEditButton << new QPushButton(QIcon::fromTheme("document-properties"), "");
prefixShortcutEditButton.last()->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
Expand Down Expand Up @@ -630,50 +632,58 @@ void NeroManagerWindow::prefixShortcutPlayButtons_clicked()

umuController.at(prefixShortcutPlayButton.at(slot)->property("thread").toInt())->Stop();
} else {
ui->prefixSettingsBtn->setEnabled(false);
ui->prefixTricksBtn->setEnabled(false);

prefixShortcutPlayButton.at(slot)->setIcon(QIcon::fromTheme("media-playback-stop"));
prefixShortcutPlayButton.at(slot)->setToolTip("Stop " + prefixShortcutLabel.at(slot)->text());
ui->backButton->setIcon(QIcon::fromTheme("media-playback-stop"));
ui->backButton->setToolTip("Shut down all running programs in this prefix.");
sysTray->setIcon(QIcon(":/ico/systrayPhiPlaying"));
threadsCount += 1;
currentlyRunning.append(slot);
if(currentlyRunning.count() > 1)
sysTray->setToolTip("Nero Manager (" + NeroFS::GetCurrentPrefix() + " is running " + QString::number(currentlyRunning.count()) + " apps)");
else sysTray->setToolTip("Nero Manager (" + NeroFS::GetCurrentPrefix() + " is running " + prefixShortcutLabel.at(slot)->text() + ')');
QMap<QString, QVariant> shortcutSettings = NeroFS::GetShortcutSettings(sender()->property("hash").toString());

// in case the directory has a Windows drive letter prefix,
// which should be harmless in the context of what Windows allows files/dirs to be named anyways.
if(QFileInfo::exists(shortcutSettings.value("Path").toString().replace("C:/",
NeroFS::GetPrefixesPath().canonicalPath()+'/'+NeroFS::GetCurrentPrefix()+"/drive_c/"))) {
ui->prefixSettingsBtn->setEnabled(false);
ui->prefixTricksBtn->setEnabled(false);

prefixShortcutPlayButton.at(slot)->setIcon(QIcon::fromTheme("media-playback-stop"));
prefixShortcutPlayButton.at(slot)->setToolTip("Stop " + prefixShortcutLabel.at(slot)->text());
ui->backButton->setIcon(QIcon::fromTheme("media-playback-stop"));
ui->backButton->setToolTip("Shut down all running programs in this prefix.");
sysTray->setIcon(QIcon(":/ico/systrayPhiPlaying"));
threadsCount += 1;
currentlyRunning.append(slot);
if(currentlyRunning.count() > 1)
sysTray->setToolTip("Nero Manager (" + NeroFS::GetCurrentPrefix() + " is running " + QString::number(currentlyRunning.count()) + " apps)");
else sysTray->setToolTip("Nero Manager (" + NeroFS::GetCurrentPrefix() + " is running " + prefixShortcutLabel.at(slot)->text() + ')');

QMap<QString, QString> settings = NeroFS::GetCurrentShortcutsMap();
if(managerCfg->value("ShortcutHidesManager").toBool())
this->hide();

if(managerCfg->value("ShortcutHidesManager").toBool())
this->hide();
if(runnerWindow == nullptr) {
runnerWindow = new NeroRunnerDialog(this);
runnerWindow->SetupWindow(true, prefixShortcutLabel.at(slot)->text(), prefixShortcutIco.at(slot));
runnerWindow->show();
}

if(runnerWindow == nullptr) {
runnerWindow = new NeroRunnerDialog(this);
runnerWindow->SetupWindow(true, prefixShortcutLabel.at(slot)->text(), prefixShortcutIco.at(slot));
runnerWindow->show();
if(currentlyRunning.count() > 1)
umuController << new NeroThreadController(slot, sender()->property("hash").toString(), true);
else umuController << new NeroThreadController(slot, sender()->property("hash").toString());

umuController.last()->setProperty("slot", threadsCount-1);
prefixShortcutPlayButton.at(slot)->setProperty("thread", threadsCount-1);
connect(umuController.last(), &NeroThreadController::passUmuResults, this, &NeroManagerWindow::handleUmuResults);
connect(&umuController.last()->umuWorker->Runner, &NeroRunner::StatusUpdate, this, &NeroManagerWindow::handleUmuSignal);
emit umuController.last()->operate();
} else {
QMessageBox::critical(this,
"Executable could not be found!",
"The executable that this shortcut links to currently doesn't exist.\n"
"Check that the application path is correct, or change it in this shortcut's settings.");
}

if(currentlyRunning.count() > 1)
umuController << new NeroThreadController(slot, settings.value(prefixShortcutLabel.at(slot)->text()), true);
else umuController << new NeroThreadController(slot, settings.value(prefixShortcutLabel.at(slot)->text()));

umuController.last()->setProperty("slot", threadsCount-1);
prefixShortcutPlayButton.at(slot)->setProperty("thread", threadsCount-1);
connect(umuController.last(), &NeroThreadController::passUmuResults, this, &NeroManagerWindow::handleUmuResults);
connect(&umuController.last()->umuWorker->Runner, &NeroRunner::StatusUpdate, this, &NeroManagerWindow::handleUmuSignal);
emit umuController.last()->operate();
}
}

void NeroManagerWindow::prefixShortcutEditButtons_clicked()
{
int slot = sender()->property("slot").toInt();

QMap<QString, QString> settings = NeroFS::GetCurrentShortcutsMap();

prefixSettings = new NeroPrefixSettingsWindow(this, settings.value(prefixShortcutLabel.at(slot)->text()));
prefixSettings = new NeroPrefixSettingsWindow(this, prefixShortcutPlayButton.at(slot)->property("hash").toString());
prefixSettings->setProperty("slot", slot);
connect(prefixSettings, &NeroPrefixSettingsWindow::finished, this, &NeroManagerWindow::prefixSettings_result);
if(currentlyRunning.count())
Expand Down
2 changes: 1 addition & 1 deletion src/neroprefixsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ void NeroPrefixSettingsWindow::on_shortcutPathBtn_clicked()
nullptr,
QFileDialog::DontResolveSymlinks);
if(!newApp.isEmpty()) {
ui->shortcutPath->setText(newApp);
ui->shortcutPath->setText(newApp.replace(NeroFS::GetPrefixesPath().path()+'/'+NeroFS::GetCurrentPrefix()+"/drive_c", "C:"));
if(newApp != settings.value("Path").toString())
ui->shortcutPath->setFont(boldFont);
else ui->shortcutPath->setFont(QFont());
Expand Down
2 changes: 1 addition & 1 deletion src/neroprefixsettings.ui
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@
<bool>true</bool>
</property>
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The current path for this shortcut.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The current path for this shortcut.&lt;/p&gt;&lt;p&gt;If the path is within the prefix's &lt;span style=&quot; font-style:italic;&quot;&gt;drive_c&lt;/span&gt; folder (or in other words, within the virtual Windows' &lt;span style=&quot; font-style:italic;&quot;&gt;C:/&lt;/span&gt; drive), this shortcut will always be run relative to the path of this current prefix - so if the current prefix changes name or location, but not the application itself, then this shortcut will still work until the application path itself changes.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="accessibleName">
<string>Executable Path</string>
Expand Down
23 changes: 8 additions & 15 deletions src/nerorunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@
#include <QApplication>
#include <QProcess>
#include <QDir>
#include <QDebug>

int NeroRunner::StartShortcut(const QString &hash, const bool &prefixAlreadyRunning)
{
QSettings *settings = NeroFS::GetCurrentPrefixCfg();
QFileInfo fileToRun(settings->value("Shortcuts--"+hash+"/Path").toString());

if(fileToRun.exists()) {
if(settings->value("Shortcuts--"+hash+"/Path").toString().startsWith("C:/") || fileToRun.exists()) {
QProcess runner;

if(!settings->value("Shortcuts--"+hash+"/PreRunScript").toString().isEmpty()) {
Expand Down Expand Up @@ -141,19 +142,7 @@ int NeroRunner::StartShortcut(const QString &hash, const bool &prefixAlreadyRunn
QStringList arguments;
arguments.append("umu-run");

// set path to be relative to an existing drive, as some apps seems to rely on this behavior:
QString app = settings->value("Shortcuts--"+hash+"/Path").toString();
QDir dosdevicesPath(NeroFS::GetPrefixesPath().path() + '/' + NeroFS::GetCurrentPrefix() + "/dosdevices");
QFileInfoList dosdevices(dosdevicesPath.entryInfoList(QDir::NoDotAndDotDot | QDir::Dirs, QDir::Name));
for(auto const device : dosdevices) {
if(app.contains(device.symLinkTarget())) {
app.remove(device.symLinkTarget());
app.prepend(device.baseName().toUpper());
break;
}
}

arguments.append(app);
arguments.append(settings->value("Shortcuts--"+hash+"/Path").toString());

if(!settings->value("Shortcuts--"+hash+"/Args").toString().isEmpty())
arguments.append(settings->value("Shortcuts--"+hash+"/Args").toStringList());
Expand Down Expand Up @@ -364,7 +353,11 @@ int NeroRunner::StartShortcut(const QString &hash, const bool &prefixAlreadyRunn
}

runner.setProcessEnvironment(env);
runner.setWorkingDirectory(settings->value("Shortcuts--"+hash+"/Path").toString().left(settings->value("Shortcuts--"+hash+"/Path").toString().lastIndexOf("/")));
// some apps requires working directory to be in the right location
// (corrected if path starts with Windows drive letter prefix)
runner.setWorkingDirectory(settings->value("Shortcuts--"+hash+"/Path")
.toString().left(settings->value("Shortcuts--"+hash+"/Path").toString().lastIndexOf("/"))
.replace("C:/", NeroFS::GetPrefixesPath().path()+'/'+NeroFS::GetCurrentPrefix()+"/drive_c/"));
QString command = arguments.takeFirst();

QDir logsDir(NeroFS::GetPrefixesPath().path()+'/'+NeroFS::GetCurrentPrefix());
Expand Down
17 changes: 11 additions & 6 deletions src/neroshortcut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ NeroShortcutWizard::NeroShortcutWizard(QWidget *parent, QString newAppPath)
, ui(new Ui::NeroShortcutWizard)
{
ui->setupUi(this);
ui->appPath->setText(newAppPath);
ui->nameMatchWarning->setVisible(false);

NeroIcoExtractor::CheckIcoCache(QDir(QString("%1/%2").arg(NeroFS::GetPrefixesPath().path(), NeroFS::GetCurrentPrefix())));
// if exe is inside of prefix, convert path to Windows path inside C:/
ui->appPath->setText(newAppPath.replace(NeroFS::GetPrefixesPath().path()+'/'+NeroFS::GetCurrentPrefix()+"/drive_c", "C:"));

NeroIcoExtractor::CheckIcoCache(QDir(NeroFS::GetPrefixesPath().path()+'/'+NeroFS::GetCurrentPrefix()));

QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
appIcon = NeroIcoExtractor::GetIcon(newAppPath);
Expand All @@ -51,7 +53,7 @@ NeroShortcutWizard::NeroShortcutWizard(QWidget *parent, QString newAppPath)

NeroShortcutWizard::~NeroShortcutWizard()
{
QDir tempDir(QString("%1/nero-manager").arg(QDir::tempPath()));
QDir tempDir(QDir::tempPath()+"/nero-manager");
tempDir.removeRecursively();

delete ui;
Expand Down Expand Up @@ -79,7 +81,6 @@ void NeroShortcutWizard::on_shortcutName_textEdited(const QString &arg1)

void NeroShortcutWizard::on_selectBox_clicked()
{
// TODO: filemanager prompt. If path returned is empty, don't change anything.
QString newApp = QFileDialog::getOpenFileName(this,
"Select a Windows Executable",
qEnvironmentVariable("HOME"),
Expand All @@ -88,8 +89,6 @@ void NeroShortcutWizard::on_selectBox_clicked()
QFileDialog::DontResolveSymlinks);

if(!newApp.isEmpty()) {
ui->appPath->setText(newApp);

QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
appIcon = NeroIcoExtractor::GetIcon(newApp);
QGuiApplication::restoreOverrideCursor();
Expand All @@ -99,6 +98,12 @@ void NeroShortcutWizard::on_selectBox_clicked()
ui->appIcon->setIcon(QPixmap(appIcon).scaled(48,48,Qt::KeepAspectRatio,Qt::SmoothTransformation));
else ui->appIcon->setIcon(QPixmap(appIcon));
} else ui->appIcon->setIcon(QIcon::fromTheme("application-x-executable"));

// if exe is inside of prefix, convert path to Windows path inside C:/
if(newApp.startsWith(NeroFS::GetPrefixesPath().canonicalPath()+'/'+NeroFS::GetCurrentPrefix()+"/drive_c"))
newApp = newApp.replace(NeroFS::GetPrefixesPath().canonicalPath()+'/'+NeroFS::GetCurrentPrefix()+"/drive_c", "C:");

ui->appPath->setText(newApp);
}
}

Expand Down

0 comments on commit e8cb9ed

Please sign in to comment.