Skip to content

Commit 7115aa1

Browse files
authored
Various minor enhancements, fixes and doc updates (#204)
* Various minor enhancements, fixes and doc updates * Fix logic error in screenshot scrape of TGDB * Update Screenscraper thread count messages and general numeric options range checks * Enable Skyscraper unit tests in CI workflow and fix unittest for test/settings * Documentation addition when using folder options (input, gamelist, media folder) in frontend INI section. * Path outputs with ~ instead verbatim home path * Ensure Python3 is present when using update_skyscraper script
1 parent 02fad25 commit 7115aa1

19 files changed

Lines changed: 771 additions & 709 deletions

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,19 @@ The scriptmodule will also automagically install programmable completion for the
8989

9090
_Qt5 is end-of-life by end of May 2025_: You can still use and compile Skyscraper with Qt5 with no restrictions, when your setup does not provide Qt6. However, if you have the option to use Qt6 I strongly recommend it, Skyscraper works well with Qt6. Use Qt6 especially when you use Skyscraper on a recent Linux distribution, macOS or Windows. In some cases you may have to use `qmake6` instead of `qmake`. If you find a mismatch in the build scripts, please file an issue.
9191

92+
In general you should have these packages installed:
93+
94+
```
95+
$ sudo apt install \
96+
make \
97+
g++ \
98+
gcc \
99+
git \
100+
python3
101+
```
102+
103+
Python3 is needed for the `update_skyscraper.sh` script and if you want to use the Python scripts in the supplementary/ folder.
104+
92105
#### Linux <img src="docs/resources/os/Tux.svg" width="20px">
93106
_For Qt6_:
94107
```bash
@@ -100,8 +113,6 @@ _For Qt5 (these are legacy installation prerequisites!)_: Skyscraper needs Qt5.1
100113
```bash
101114
$ sudo apt update
102115
$ sudo apt install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5sql5-sqlite p7zip-full
103-
# You may need these too, if they are not installed already
104-
$ sudo apt install make g++ gcc git
105116
```
106117
To install Qt5 (disencouraged) or Qt6 (preferred) on other Linux distributions, please refer to their documentation.
107118

docs/CLIHELP.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,13 @@ Skyscraper -p snes -s import
191191

192192
Read more about [each scraping module](SCRAPINGMODULES.md).
193193

194-
### -t &lt;1-8&gt;
194+
### -t &lt;1-...&gt;
195195

196-
Sets the desired number of parallel threads to be run when scraping. By default it is set to 4.
196+
Sets the desired number of parallel threads to be run when scraping. By default it is set to 4. You can not set this higher than the [ideal thread count](https://doc.qt.io/qt-6/qthread.html#idealThreadCount), which is usually the output of `nproc` on your system.
197197

198198
!!! note
199199

200-
Some modules have maximum allowed threads. If you set this higher than the allowed value, it will be auto-adjusted.
200+
Some scraping modules have maximum allowed threads. If you set this higher than the allowed value, it will be auto-adjusted. For gamelist creation runs you may set it to the maximum.
201201

202202
**Example(s)**
203203

docs/CONFIGINI.md

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ This is an alphabetical index of all configuration options their usage level and
149149

150150
Sets the rom input folder. By default Skyscraper will look for roms in the `/home/<USER>/RetroPie/roms/<PLATFORM>` folder. If your roms are located in a non-default location, you can set the input path using this option.
151151

152-
!!! note
152+
!!! note "Path Appended With `<PLATFORM>`"
153153

154154
If this is set in the `[main]` or `[<FRONTEND>]` section it will automatically add `/<PLATFORM>` to the end of the path. If you want better control consider adding it to a `[<PLATFORM>]` section instead where it will be used as is.
155155

@@ -158,13 +158,20 @@ Allowed in sections: `[main]`, `[<PLATFORM>]`, `[<FRONTEND>]`
158158

159159
The default is valid for the most frontends, very few [frontends](FRONTENDS.md) do use a different default value.
160160

161+
!!! tip "Usage in `[<FRONTEND>]` Section"
162+
163+
When you use this option in a `[<FRONTEND>]` section other than
164+
the default `emulationstation`, then it is only evaluated when you provide
165+
either `-f` command line parameter or have set the [`frontend`](#frontend)
166+
option during a scraping run.
167+
161168
---
162169

163170
#### gameListFolder
164171

165172
Sets the game list export folder. By default Skyscraper exports the game list to the same directory as the rom input folder. This enables you to change that to a non-default location.
166173

167-
!!! note
174+
!!! note "Path Appended With `<PLATFORM>`"
168175

169176
If this is set in the `[main]` or `[<FRONTEND>]` section it will automatically add `/<PLATFORM>` to the end of the path. If you want better control consider adding it to a `[<PLATFORM>]` section instead where it will be used as is.
170177

@@ -173,6 +180,13 @@ Allowed in sections: `[main]`, `[<PLATFORM>]`, `[<FRONTEND>]`
173180

174181
The default is valid for the most frontends, very few [frontends](FRONTENDS.md) do use a different default value.
175182

183+
!!! tip "Usage in `[<FRONTEND>]` Section"
184+
185+
When you use this option in a `[<FRONTEND>]` section other than
186+
the default `emulationstation`, then it is only evaluated when you provide
187+
either `-f` command line parameter or have set the [`frontend`](#frontend)
188+
option during a scraping run.
189+
176190
---
177191

178192
#### gameListFilename
@@ -199,7 +213,7 @@ Sets the artwork / media output folder. By default (ie. if the option `mediaFold
199213

200214
Read more about the [artwork compositing](ARTWORK.md).
201215

202-
!!! note
216+
!!! note "Path Appended With `<PLATFORM>`"
203217

204218
If this is set in the `[main]` or `[<FRONTEND>]` section it will automatically add `/<PLATFORM>` to the end of the path. If you want better control consider adding it to a `[<PLATFORM>]` section instead where it will be used as is.
205219

@@ -208,6 +222,13 @@ Allowed in sections: `[main]`, `[<PLATFORM>]`, `[<FRONTEND>]`
208222

209223
The default is valid for the most frontends, very few [frontends](FRONTENDS.md) do use a different default value.
210224

225+
!!! tip "Usage in `[<FRONTEND>]` Section"
226+
227+
When you use this option in a `[<FRONTEND>]` section other than
228+
the default `emulationstation`, then it is only evaluated when you provide
229+
either `-f` command line parameter or have set the [`frontend`](#frontend)
230+
option during a scraping run.
231+
211232
---
212233

213234
#### mediaFolderHidden
@@ -635,7 +656,7 @@ Allowed in sections: `[main]`, `[<PLATFORM>]`, `[<SCRAPER>]`
635656

636657
#### threads
637658

638-
Sets the desired number of parallel threads to be run when scraping. Some modules have maximum allowed threads. If you set this higher than the allowed value, it will be auto-adjusted. By default it is set to 4.
659+
Sets the desired number of parallel threads to be run when scraping or creating the gamelist. Some modules have maximum allowed threads. If you set this higher than the allowed value, it will be auto-adjusted. By default it is set to 4. You can not set this higher than the [ideal thread count](https://doc.qt.io/qt-6/qthread.html#idealThreadCount), which is usually the output of `nproc` on your Linux system.
639660

640661
Default value: `4`
641662
Allowed in sections: `[main]`, `[<PLATFORM>]`, `[<SCRAPER>]`

src/cache.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,12 +1179,15 @@ void Cache::assembleReport(const Settings &config, const QString filter) {
11791179

11801180
QString dateTime = QDateTime::currentDateTime().toString("yyyyMMdd");
11811181
for (const auto &resType : resTypeList) {
1182-
QFile reportFile(reportsDir.absolutePath() + "/report-" +
1183-
config.platform + "-missing_" + resType + "-" +
1184-
dateTime + ".txt");
1182+
QString rFn = QString("{1}/report-{2}-missing_{3}-{4}.txt")
1183+
.arg(reportsDir.absolutePath())
1184+
.arg(config.platform)
1185+
.arg(resType)
1186+
.arg(dateTime);
1187+
QFile reportFile(rFn);
11851188
printf("Report filename: '\033[1;32m%s\033[0m'\nAssembling report, "
11861189
"please wait...",
1187-
reportFile.fileName().toStdString().c_str());
1190+
Config::pathToCStr(rFn));
11881191
if (reportFile.open(QIODevice::WriteOnly)) {
11891192
int missing = 0;
11901193
int dots = 0;

src/config.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,4 +383,12 @@ QString &Config::expandHomePath(QString &path) {
383383
// "~account/folder" not supported
384384
}
385385
return path;
386+
}
387+
388+
const char *Config::pathToCStr(QString &in) {
389+
QString ret = in;
390+
#ifndef Q_OS_WIN
391+
ret = ret.replace(QDir::homePath(), "~");
392+
#endif
393+
return ret.toUtf8().constData();
386394
}

src/config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ namespace Config {
4646
QString lexicallyRelativePath(const QString &base, const QString &other);
4747
QString lexicallyNormalPath(const QString &pathWithDots);
4848
QString &expandHomePath(QString &path);
49+
const char *pathToCStr(QString &in);
4950
} // namespace Config
5051

5152
#endif // CONFIG_H

src/screenscraper.cpp

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,9 @@ void ScreenScraper::getSearchResults(QList<GameEntry> &gameEntries,
169169
"191;167;200;198;192;228;169;156"),
170170
"****");
171171
data.replace(config->password.toUtf8(), "****");
172-
QFile errorResponse(
173-
Config::getSkyFolder(Config::SkyFolderType::LOG) +
174-
"/screenscraper_error.txt");
172+
QString errFile = Config::getSkyFolder(Config::SkyFolderType::LOG) %
173+
"/screenscraper_error.txt";
174+
QFile errorResponse(errFile);
175175
if (errorResponse.open(QIODevice::WriteOnly)) {
176176
if (data.length() > 64) {
177177
if (data.startsWith("****I****l**** "
@@ -182,16 +182,12 @@ void ScreenScraper::getSearchResults(QList<GameEntry> &gameEntries,
182182
"\nEN: Mandatory fields are missing in the URL.\n");
183183
}
184184
errorResponse.write(data);
185-
printf("The erroneous answer was written to "
186-
"'%s'. "
187-
"If this file contains game data, please consider "
188-
"filing a bug report at "
185+
printf("The erroneous answer was written to '%s'. If you "
186+
"expected to scrape game data and this error "
187+
"persists, please consider filing a bug report at "
189188
"'https://github.com/Gemba/skyscraper/issues' and "
190189
"attach that file.\n",
191-
QFileInfo(errorResponse)
192-
.absoluteFilePath()
193-
.toStdString()
194-
.c_str());
190+
Config::pathToCStr(errFile));
195191
}
196192
errorResponse.close();
197193
}

src/settings.cpp

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <QDebug>
2828
#include <QFileInfo>
2929
#include <QStringBuilder>
30+
#include <QThread>
3031
#include <filesystem>
3132

3233
static inline bool isArcadePlatform(const QString &platform) {
@@ -146,7 +147,7 @@ void RuntimeCfg::applyConfigIni(CfgType type, QSettings *settings,
146147
default:;
147148
}
148149
qInfo() << "Section type" << type << "[" << section << "]"
149-
<< "has surplus key(s) (=ignored): " << invalid;
150+
<< "has surplus key(s), which will be ignored: " << invalid;
150151
}
151152

152153
for (auto k : retained) {
@@ -495,19 +496,17 @@ void RuntimeCfg::applyConfigIni(CfgType type, QSettings *settings,
495496
bool intOk;
496497
int v = ss.toInt(&intOk);
497498
if (!intOk) {
498-
printf("\033[1;31mConversion of %s to integer failed for key "
499-
"%s. Please fix in config.ini.\n\033[0m",
500-
ss.toString().toUtf8().constData(),
501-
k.toUtf8().constData());
499+
printf(
500+
"\033[1;31mConversion of %s to integer failed for option "
501+
"%s. Please fix in config.ini.\n\033[0m",
502+
ss.toString().toUtf8().constData(), k.toUtf8().constData());
502503
exit(1);
503504
}
504505
if (k == "jpgQuality") {
505506
if (0 < v && v <= 100) {
506507
config->jpgQuality = v;
507508
} else {
508-
printf("\033[1;33mValue of %d is out of range and is "
509-
"ignored! Consult the documentation.\n\033[0m",
510-
v);
509+
outOfRange(k, v);
511510
}
512511
continue;
513512
}
@@ -519,9 +518,7 @@ void RuntimeCfg::applyConfigIni(CfgType type, QSettings *settings,
519518
if (0 < v && v <= 200) {
520519
config->maxFails = v;
521520
} else {
522-
printf("\033[1;33mValue of %d is out of range and is "
523-
"ignored! Consult the documentation.\n\033[0m",
524-
v);
521+
outOfRange(k, v);
525522
}
526523
continue;
527524
}
@@ -532,24 +529,24 @@ void RuntimeCfg::applyConfigIni(CfgType type, QSettings *settings,
532529
config->minMatch = v;
533530
config->minMatchSet = true;
534531
} else {
535-
printf("\033[1;33mValue of %d is out of range and is "
536-
"ignored! Consult the documentation.\n\033[0m",
537-
v);
532+
outOfRange(k, v);
538533
}
539534
continue;
540535
}
541536
if (k == "threads") {
542-
config->threads = v;
543-
config->threadsSet = true;
537+
if (v > 0 && v <= QThread::idealThreadCount()) {
538+
config->threads = v;
539+
config->threadsSet = true;
540+
} else {
541+
outOfRange(k, v);
542+
}
544543
continue;
545544
}
546545
if (k == "verbosity") {
547546
if (0 < v && v <= 3) {
548547
config->verbosity = v;
549548
} else {
550-
printf("\033[1;33mValue of %d is out of range and is "
551-
"ignored! Consult the documentation.\n\033[0m",
552-
v);
549+
outOfRange(k, v);
553550
}
554551
continue;
555552
}
@@ -567,7 +564,8 @@ void RuntimeCfg::applyCli(bool &inputFolderSet, bool &gameListFolderSet,
567564
parser->value("l").toInt() <= 10000) {
568565
config->maxLength = parser->value("l").toInt();
569566
}
570-
if (parser->isSet("t") && parser->value("t").toInt() <= 8) {
567+
if (parser->isSet("t") && parser->value("t").toInt() > 0 &&
568+
parser->value("t").toInt() <= QThread::idealThreadCount()) {
571569
config->threads = parser->value("t").toInt();
572570
config->threadsSet = true;
573571
}
@@ -913,4 +911,10 @@ QString RuntimeCfg::getAllExtensionsOfPlatform() {
913911
return Platform::get()
914912
.getFormats(config->platform, config->extensions, config->addExtensions)
915913
.remove('*');
914+
}
915+
916+
void RuntimeCfg::outOfRange(QString &k, int v) {
917+
printf("\033[1;33mValue of %d is out of range for option %s and is "
918+
"ignored! Consult the documentation.\n\033[0m",
919+
v, k.toStdString().c_str());
916920
}

src/settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ class RuntimeCfg : public QObject {
195195
QString toAbsolutePath(bool isCliOpt, QString optionVal);
196196
QString parseExtensions(const QString &optionVal);
197197
QString getAllExtensionsOfPlatform();
198+
void outOfRange(QString &k, int v);
198199

199200
Settings *config;
200201
const QCommandLineParser *parser;

0 commit comments

Comments
 (0)