Merge branch 'translation-debugging'

Better support for ad-hoc translation loading. Use -T to load
local translations independent of the -d flag.
This commit is contained in:
Adriaan de Groot 2020-02-05 17:52:19 +01:00
commit 5d25719918
10 changed files with 187 additions and 175 deletions

View File

@ -42,12 +42,17 @@
#include <QScreen>
#include <QTimer>
/// @brief Convenience for "are the settings in debug mode"
static bool
isDebug()
{
return Calamares::Settings::instance() && Calamares::Settings::instance()->debugMode();
}
CalamaresApplication::CalamaresApplication( int& argc, char* argv[] )
: QApplication( argc, argv )
, m_mainwindow( nullptr )
, m_moduleManager( nullptr )
, m_debugMode( false )
{
// Setting the organization name makes the default cache
// directory -- where Calamares stores logs, for instance --
@ -59,8 +64,6 @@ CalamaresApplication::CalamaresApplication( int& argc, char* argv[] )
setApplicationName( QStringLiteral( CALAMARES_APPLICATION_NAME ) );
setApplicationVersion( QStringLiteral( CALAMARES_VERSION ) );
CalamaresUtils::installTranslator( QLocale::system(), QString(), this );
QFont f = font();
CalamaresUtils::setDefaultFontSize( f.pointSize() );
}
@ -73,15 +76,20 @@ CalamaresApplication::init()
cDebug() << "Calamares version:" << CALAMARES_VERSION;
cDebug() << " languages:" << QString( CALAMARES_TRANSLATION_LANGUAGES ).replace( ";", ", " );
setQuitOnLastWindowClosed( false );
if ( !Calamares::Settings::instance() )
{
cError() << "Must create Calamares::Settings before the application.";
::exit( 1 );
}
initQmlPath();
initSettings();
initBranding();
CalamaresUtils::installTranslator( QLocale::system(), QString(), this );
setQuitOnLastWindowClosed( false );
setWindowIcon( QIcon( Calamares::Branding::instance()->imagePath( Calamares::Branding::ProductIcon ) ) );
cDebug() << "STARTUP: initQmlPath, initSettings, initBranding done";
cDebug() << "STARTUP: initSettings, initQmlPath, initBranding done";
initModuleManager(); //also shows main window
@ -103,20 +111,6 @@ CalamaresApplication::instance()
}
void
CalamaresApplication::setDebug( bool enabled )
{
m_debugMode = enabled;
}
bool
CalamaresApplication::isDebug()
{
return m_debugMode;
}
CalamaresWindow*
CalamaresApplication::mainWindow()
{
@ -152,35 +146,6 @@ qmlDirCandidates( bool assumeBuilddir )
}
static QStringList
settingsFileCandidates( bool assumeBuilddir )
{
static const char settings[] = "settings.conf";
QStringList settingsPaths;
if ( CalamaresUtils::isAppDataDirOverridden() )
{
settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings );
}
else
{
if ( assumeBuilddir )
{
settingsPaths << QDir::current().absoluteFilePath( settings );
}
if ( CalamaresUtils::haveExtraDirs() )
for ( auto s : CalamaresUtils::extraConfigDirs() )
{
settingsPaths << ( s + settings );
}
settingsPaths << CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/settings.conf"; // String concat
settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings );
}
return settingsPaths;
}
static QStringList
brandingFileCandidates( bool assumeBuilddir, const QString& brandingFilename )
{
@ -246,49 +211,6 @@ CalamaresApplication::initQmlPath()
}
void
CalamaresApplication::initSettings()
{
QStringList settingsFileCandidatesByPriority = settingsFileCandidates( isDebug() );
QFileInfo settingsFile;
bool found = false;
foreach ( const QString& path, settingsFileCandidatesByPriority )
{
QFileInfo pathFi( path );
if ( pathFi.exists() && pathFi.isReadable() )
{
settingsFile = pathFi;
found = true;
break;
}
}
if ( !found || !settingsFile.exists() || !settingsFile.isReadable() )
{
cError() << "Cowardly refusing to continue startup without settings."
<< Logger::DebugList( settingsFileCandidatesByPriority );
if ( CalamaresUtils::isAppDataDirOverridden() )
{
cError() << "FATAL: explicitly configured application data directory is missing settings.conf";
}
else
{
cError() << "FATAL: none of the expected configuration file paths exist.";
}
::exit( EXIT_FAILURE );
}
auto* settings = new Calamares::Settings( settingsFile.absoluteFilePath(), isDebug(), this ); // Creates singleton
if ( settings->modulesSequence().count() < 1 )
{
cError() << "FATAL: no sequence set.";
::exit( EXIT_FAILURE );
}
}
void
CalamaresApplication::initBranding()
{

View File

@ -49,16 +49,6 @@ public:
void init();
static CalamaresApplication* instance();
/**
* @brief setDebug controls whether debug mode is enabled
*/
void setDebug( bool enabled );
/**
* @brief isDebug returns true if running in debug mode, otherwise false.
*/
bool isDebug();
/**
* @brief mainWindow returns the Calamares application main window.
*/
@ -70,16 +60,14 @@ private slots:
void initFailed( const QStringList& l );
private:
// Initialization steps happen in this order
void initQmlPath();
void initSettings();
void initBranding();
void initModuleManager();
void initJobQueue();
CalamaresWindow* m_mainwindow;
Calamares::ModuleManager* m_moduleManager;
bool m_debugMode;
};
#endif // CALAMARESAPPLICATION_H

View File

@ -20,9 +20,10 @@
#include "CalamaresApplication.h"
#include "CalamaresConfig.h"
#include "Settings.h"
#include "utils/Dirs.h"
#include "utils/Logger.h"
#include "utils/Retranslator.h"
#include "3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h"
@ -35,6 +36,21 @@
#include <QDebug>
#include <QDir>
static unsigned int
debug_level( QCommandLineParser& parser, QCommandLineOption& levelOption )
{
bool ok = true;
int l = parser.value( levelOption ).toInt( &ok );
if ( !ok || ( l < 0 ) )
{
return Logger::LOGVERBOSE;
}
else
{
return static_cast< unsigned int >( l ); // l >= 0
}
}
static void
handle_args( CalamaresApplication& a )
{
@ -42,6 +58,9 @@ handle_args( CalamaresApplication& a )
"Also look in current directory for configuration. Implies -D8." );
QCommandLineOption debugLevelOption(
QStringLiteral( "D" ), "Verbose output for debugging purposes (0-8).", "level" );
QCommandLineOption debugTxOption( QStringList { "T", "debug-translation" },
"Also look in the current directory for translation." );
QCommandLineOption configOption(
QStringList { "c", "config" }, "Configuration directory to use, for testing purposes.", "config" );
QCommandLineOption xdgOption( QStringList { "X", "xdg-config" }, "Use XDG_{CONFIG,DATA}_DIRS as well." );
@ -55,29 +74,11 @@ handle_args( CalamaresApplication& a )
parser.addOption( debugLevelOption );
parser.addOption( configOption );
parser.addOption( xdgOption );
parser.addOption( debugTxOption );
parser.process( a );
a.setDebug( parser.isSet( debugOption ) );
if ( parser.isSet( debugOption ) )
{
Logger::setupLogLevel( Logger::LOGVERBOSE );
}
else if ( parser.isSet( debugLevelOption ) )
{
bool ok = true;
int l = parser.value( debugLevelOption ).toInt( &ok );
unsigned int dlevel = 0;
if ( !ok || ( l < 0 ) )
{
dlevel = Logger::LOGVERBOSE;
}
else
{
dlevel = static_cast< unsigned int >( l ); // l >= 0
}
Logger::setupLogLevel( dlevel );
}
Logger::setupLogLevel( parser.isSet( debugOption ) ? Logger::LOGVERBOSE : debug_level( parser, debugLevelOption ) );
if ( parser.isSet( configOption ) )
{
CalamaresUtils::setAppDataDir( QDir( parser.value( configOption ) ) );
@ -86,6 +87,9 @@ handle_args( CalamaresApplication& a )
{
CalamaresUtils::setXdgDirs();
}
CalamaresUtils::setAllowLocalTranslation( parser.isSet( debugOption ) || parser.isSet( debugTxOption ) );
Calamares::Settings::init( parser.isSet( debugOption ) );
a.init();
}
int
@ -113,14 +117,11 @@ main( int argc, char* argv[] )
// TODO: umount anything in /tmp/calamares-... as an emergency save function
#endif
handle_args( a );
KDSingleApplicationGuard guard( KDSingleApplicationGuard::AutoKillOtherInstances );
int returnCode = 0;
if ( guard.isPrimaryInstance() )
{
a.init();
returnCode = a.exec();
handle_args( a );
return a.exec();
}
else
{
@ -135,7 +136,6 @@ main( int argc, char* argv[] )
{
qDebug() << " " << i.isValid() << i.pid() << i.arguments();
}
return 69; // EX_UNAVAILABLE on FreeBSD
}
return returnCode;
}

View File

@ -225,7 +225,7 @@ main( int argc, char* argv[] )
return 1;
}
std::unique_ptr< Calamares::Settings > settings_p( new Calamares::Settings( QString(), true ) );
std::unique_ptr< Calamares::Settings > settings_p( Calamares::Settings::init( QString() ) );
std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) );
QMainWindow* mw = nullptr;

View File

@ -21,6 +21,7 @@
#include "Settings.h"
#include "CalamaresConfig.h"
#include "utils/Dirs.h"
#include "utils/Logger.h"
#include "utils/Yaml.h"
@ -193,8 +194,8 @@ interpretSequence( const YAML::Node& node, Settings::ModuleSequence& moduleSeque
}
}
Settings::Settings( const QString& settingsFilePath, bool debugMode, QObject* parent )
: QObject( parent )
Settings::Settings( const QString& settingsFilePath, bool debugMode )
: QObject()
, m_debug( debugMode )
, m_doChroot( true )
, m_promptInstall( false )
@ -265,37 +266,93 @@ Settings::brandingComponentName() const
return m_brandingComponentName;
}
bool
Settings::showPromptBeforeExecution() const
static QStringList
settingsFileCandidates( bool assumeBuilddir )
{
return m_promptInstall;
static const char settings[] = "settings.conf";
QStringList settingsPaths;
if ( CalamaresUtils::isAppDataDirOverridden() )
{
settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings );
}
else
{
if ( assumeBuilddir )
{
settingsPaths << QDir::current().absoluteFilePath( settings );
}
if ( CalamaresUtils::haveExtraDirs() )
for ( auto s : CalamaresUtils::extraConfigDirs() )
{
settingsPaths << ( s + settings );
}
settingsPaths << CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/settings.conf"; // String concat
settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings );
}
return settingsPaths;
}
bool
Settings::debugMode() const
Settings*
Settings::init( bool debugMode )
{
return m_debug;
if ( s_instance )
{
cWarning() << "Calamares::Settings already created";
return s_instance;
}
QStringList settingsFileCandidatesByPriority = settingsFileCandidates( debugMode );
QFileInfo settingsFile;
bool found = false;
foreach ( const QString& path, settingsFileCandidatesByPriority )
{
QFileInfo pathFi( path );
if ( pathFi.exists() && pathFi.isReadable() )
{
settingsFile = pathFi;
found = true;
break;
}
}
if ( !found || !settingsFile.exists() || !settingsFile.isReadable() )
{
cError() << "Cowardly refusing to continue startup without settings."
<< Logger::DebugList( settingsFileCandidatesByPriority );
if ( CalamaresUtils::isAppDataDirOverridden() )
{
cError() << "FATAL: explicitly configured application data directory is missing settings.conf";
}
else
{
cError() << "FATAL: none of the expected configuration file paths exist.";
}
::exit( EXIT_FAILURE );
}
auto* settings = new Calamares::Settings( settingsFile.absoluteFilePath(), debugMode ); // Creates singleton
if ( settings->modulesSequence().count() < 1 )
{
cError() << "FATAL: no sequence set.";
::exit( EXIT_FAILURE );
}
return settings;
}
bool
Settings::doChroot() const
Settings*
Settings::init( const QString& path )
{
return m_doChroot;
if ( s_instance )
{
cWarning() << "Calamares::Settings already created";
return s_instance;
}
return new Calamares::Settings( path, true );
}
bool
Settings::disableCancel() const
{
return m_disableCancel;
}
bool
Settings::disableCancelDuringExec() const
{
return m_disableCancelDuringExec;
}
} // namespace Calamares

View File

@ -35,11 +35,14 @@ namespace Calamares
class DLLEXPORT Settings : public QObject
{
Q_OBJECT
explicit Settings( const QString& settingsFilePath, bool debugMode );
public:
explicit Settings( const QString& settingsFilePath, bool debugMode, QObject* parent = nullptr );
static Settings* instance();
/// @brief Find a settings.conf, following @p debugMode
static Settings* init( bool debugMode );
/// @brief Explicif filename, debug is always true (for testing)
static Settings* init( const QString& filename );
QStringList modulesSearchPaths() const;
using InstanceDescription = QMap< QString, QString >;
@ -51,11 +54,31 @@ public:
QString brandingComponentName() const;
bool showPromptBeforeExecution() const;
/** @brief Is this a debugging run?
*
* Returns true if Calamares is in debug mode. In debug mode,
* modules and settings are loaded from more locations, to help
* development and debugging.
*/
bool debugMode() const { return m_debug; }
bool debugMode() const;
/** @brief Distinguish "install" from "OEM" modes.
*
* Returns true in "install" mode, which is where actions happen
* in a chroot -- the target system, which exists separately from
* the source system. In "OEM" mode, returns false and most actions
* apply to the *current* (host) system.
*/
bool doChroot() const { return m_doChroot; }
bool doChroot() const;
/** @brief Global setting of prompt-before-install.
*
* Returns true when the configuration is such that the user
* should be prompted one-last-time before any action is taken
* that really affects the machine.
*/
bool showPromptBeforeExecution() const { return m_promptInstall; }
/** @brief Distinguish between "install" and "setup" modes.
*
* This influences user-visible strings, for instance using the
@ -64,9 +87,9 @@ public:
bool isSetupMode() const { return m_isSetupMode; }
/** @brief Global setting of disable-cancel: can't cancel ever. */
bool disableCancel() const;
bool disableCancel() const { return m_disableCancel; }
/** @brief Temporary setting of disable-cancel: can't cancel during exec. */
bool disableCancelDuringExec() const;
bool disableCancelDuringExec() const { return m_disableCancelDuringExec; }
private:
static Settings* s_instance;

View File

@ -19,6 +19,7 @@
#include "Tests.h"
#include "Manager.h"
#include "utils/Logger.h"
#include <QtTest/QtTest>
@ -43,6 +44,9 @@ NetworkTests::testInstance()
void
NetworkTests::testPing()
{
auto& nam = CalamaresUtils::Network::Manager::instance();
QVERIFY( nam.synchronousPing( QUrl( "https://www.kde.org" ) ) );
using namespace CalamaresUtils::Network;
Logger::setupLogLevel( Logger::LOGVERBOSE );
auto& nam = Manager::instance();
auto r = nam.synchronousPing( QUrl( "https://www.kde.org" ), RequestOptions( RequestOptions::FollowRedirect ) );
QVERIFY( r );
}

View File

@ -27,6 +27,8 @@
#include <QEvent>
#include <QTranslator>
static bool s_allowLocalTranslations = false;
/** @brief Helper class for loading translations
*
* This is used by the loadSingletonTranslator() function to hand off
@ -131,7 +133,7 @@ static bool
tryLoad( QTranslator* translator, const QString& prefix, const QString& localeName )
{
// In debug-mode, try loading from the current directory
if ( Calamares::Settings::instance() && Calamares::Settings::instance()->debugMode() && translator->load( prefix + localeName ) )
if ( s_allowLocalTranslations && translator->load( prefix + localeName ) )
{
cDebug() << Logger::SubEntry << "Loaded local translation" << prefix << localeName;
return true;
@ -139,14 +141,15 @@ tryLoad( QTranslator* translator, const QString& prefix, const QString& localeNa
// Or load from appDataDir -- often /usr/share/calamares -- subdirectory land/
QDir localeData( CalamaresUtils::appDataDir() );
if ( localeData.exists() && translator->load( localeData.absolutePath() + QStringLiteral("/lang/") + prefix + localeName) )
if ( localeData.exists()
&& translator->load( localeData.absolutePath() + QStringLiteral( "/lang/" ) + prefix + localeName ) )
{
cDebug() << Logger::SubEntry << "Loaded appdata translation" << prefix << localeName;
return true;
}
// Or from QRC (most common)
if ( translator->load( QStringLiteral( ":/lang/") + prefix + localeName ) )
if ( translator->load( QStringLiteral( ":/lang/" ) + prefix + localeName ) )
{
cDebug() << Logger::SubEntry << "Loaded QRC translation" << prefix << localeName;
return true;
@ -260,5 +263,11 @@ Retranslator::eventFilter( QObject* obj, QEvent* e )
return QObject::eventFilter( obj, e );
}
void
setAllowLocalTranslation( bool allow )
{
s_allowLocalTranslations = allow;
}
} // namespace CalamaresUtils

View File

@ -42,6 +42,15 @@ DLLEXPORT void installTranslator( const QLocale& locale, const QString& branding
DLLEXPORT QString translatorLocaleName();
/** @brief Set @p allow to true to load translations from current dir.
*
* If false, (or never called) the translations are loaded only from
* system locations (the AppData dir) and from QRC (compiled in).
* Enable local translations to test translations stored in the
* current directory.
*/
DLLEXPORT void setAllowLocalTranslation( bool allow );
class Retranslator : public QObject
{
Q_OBJECT

View File

@ -176,7 +176,7 @@ script:
if ( !Calamares::JobQueue::instance() )
(void)new Calamares::JobQueue( nullptr );
if ( !Calamares::Settings::instance() )
(void)new Calamares::Settings( QString(), true );
(void)Calamares::Settings::init( QString() );
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
QVERIFY( gs != nullptr );