Merge branch 'calamares' into fix-keyboardq
This commit is contained in:
commit
4f0d6a8f25
4
CHANGES
4
CHANGES
@ -10,7 +10,9 @@ website will have to do for older versions.
|
|||||||
# 3.2.33 (unreleased) #
|
# 3.2.33 (unreleased) #
|
||||||
|
|
||||||
This release contains contributions from (alphabetically by first name):
|
This release contains contributions from (alphabetically by first name):
|
||||||
- No external contributors yet
|
- Anke Boersma
|
||||||
|
- Andrius Štikonas
|
||||||
|
- Gaël PORTAY
|
||||||
|
|
||||||
## Core ##
|
## Core ##
|
||||||
- Calamares now sets the C++ standard for compilation to C++17; this
|
- Calamares now sets the C++ standard for compilation to C++17; this
|
||||||
|
@ -271,6 +271,7 @@ flavoredWidget( Calamares::Branding::PanelFlavor flavor,
|
|||||||
case Calamares::Branding::PanelFlavor::None:
|
case Calamares::Branding::PanelFlavor::None:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Adds widgets to @p layout if they belong on this @p side
|
/** @brief Adds widgets to @p layout if they belong on this @p side
|
||||||
|
@ -139,6 +139,7 @@ PartitionSize::toBytes( qint64 totalSectors, qint64 sectorSize ) const
|
|||||||
case SizeUnit::GiB:
|
case SizeUnit::GiB:
|
||||||
return toBytes();
|
return toBytes();
|
||||||
}
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64
|
qint64
|
||||||
@ -175,7 +176,7 @@ PartitionSize::toBytes( qint64 totalBytes ) const
|
|||||||
case SizeUnit::GiB:
|
case SizeUnit::GiB:
|
||||||
return toBytes();
|
return toBytes();
|
||||||
}
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64
|
qint64
|
||||||
@ -206,6 +207,7 @@ PartitionSize::toBytes() const
|
|||||||
case SizeUnit::GiB:
|
case SizeUnit::GiB:
|
||||||
return CalamaresUtils::GiBtoBytes( static_cast< unsigned long long >( value() ) );
|
return CalamaresUtils::GiBtoBytes( static_cast< unsigned long long >( value() ) );
|
||||||
}
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -231,6 +233,7 @@ PartitionSize::operator<( const PartitionSize& other ) const
|
|||||||
case SizeUnit::GiB:
|
case SizeUnit::GiB:
|
||||||
return ( toBytes() < other.toBytes() );
|
return ( toBytes() < other.toBytes() );
|
||||||
}
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -256,6 +259,7 @@ PartitionSize::operator>( const PartitionSize& other ) const
|
|||||||
case SizeUnit::GiB:
|
case SizeUnit::GiB:
|
||||||
return ( toBytes() > other.toBytes() );
|
return ( toBytes() > other.toBytes() );
|
||||||
}
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -281,6 +285,7 @@ PartitionSize::operator==( const PartitionSize& other ) const
|
|||||||
case SizeUnit::GiB:
|
case SizeUnit::GiB:
|
||||||
return ( toBytes() == other.toBytes() );
|
return ( toBytes() == other.toBytes() );
|
||||||
}
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Partition
|
} // namespace Partition
|
||||||
|
@ -52,6 +52,7 @@ yamlToVariant( const YAML::Node& node )
|
|||||||
case YAML::NodeType::Undefined:
|
case YAML::NodeType::Undefined:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
24
src/modules/keyboard/AdditionalLayoutInfo.h
Normal file
24
src/modules/keyboard/AdditionalLayoutInfo.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2020 Artem Grinev <agrinev@manjaro.org>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* Calamares is Free Software: see the License-Identifier above.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEYBOARD_ADDITIONAL_LAYOUT_INFO_H
|
||||||
|
#define KEYBOARD_ADDITIONAL_LAYOUT_INFO_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
struct AdditionalLayoutInfo {
|
||||||
|
QString additionalLayout;
|
||||||
|
QString additionalVariant;
|
||||||
|
|
||||||
|
QString groupSwitcher;
|
||||||
|
|
||||||
|
QString vconsoleKeymap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -49,6 +49,100 @@ xkbmap_layout_args( const QString& layout, const QString& variant )
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline QStringList
|
||||||
|
xkbmap_layout_args( const QStringList& layouts, const QStringList& variants, const QString& switchOption = "grp:alt_shift_toggle")
|
||||||
|
{
|
||||||
|
if ( layouts.size() != variants.size() )
|
||||||
|
{
|
||||||
|
cError() << "Number of layouts and variants must be equal (empty string should be used if there is no corresponding variant)";
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList r{ "-layout", layouts.join( "," ) };
|
||||||
|
|
||||||
|
if ( !variants.isEmpty() )
|
||||||
|
{
|
||||||
|
r << "-variant" << variants.join( "," );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !switchOption.isEmpty())
|
||||||
|
{
|
||||||
|
r << "-option" << switchOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns group-switch setxkbd option if set
|
||||||
|
* or an empty string otherwise
|
||||||
|
*/
|
||||||
|
static inline QString
|
||||||
|
xkbmap_query_grp_option()
|
||||||
|
{
|
||||||
|
QProcess setxkbmapQuery;
|
||||||
|
setxkbmapQuery.start( "setxkbmap", { "-query" } );
|
||||||
|
setxkbmapQuery.waitForFinished();
|
||||||
|
|
||||||
|
QString outputLine;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
outputLine = setxkbmapQuery.readLine();
|
||||||
|
}
|
||||||
|
while( setxkbmapQuery.canReadLine() && !outputLine.startsWith("options:") );
|
||||||
|
|
||||||
|
if( !outputLine.startsWith( "options:" ) )
|
||||||
|
{
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = outputLine.indexOf( "grp:" );
|
||||||
|
|
||||||
|
if( index == -1 )
|
||||||
|
{
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
//it's either in the end of line or before the other option so \s or ,
|
||||||
|
int lastIndex = outputLine.indexOf( QRegExp( "[\\s,]" ), index );
|
||||||
|
|
||||||
|
return outputLine.mid( index, lastIndex-1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
AdditionalLayoutInfo Config::getAdditionalLayoutInfo( const QString &layout )
|
||||||
|
{
|
||||||
|
QFile layoutTable( ":/non-ascii-layouts" );
|
||||||
|
|
||||||
|
if( !layoutTable.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
|
||||||
|
cError() << "Non-ASCII layout table could not be opened";
|
||||||
|
return AdditionalLayoutInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString tableLine;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
tableLine = layoutTable.readLine();
|
||||||
|
}
|
||||||
|
while( layoutTable.canReadLine() && !tableLine.startsWith( layout ) );
|
||||||
|
|
||||||
|
if( !tableLine.startsWith( layout ) )
|
||||||
|
{
|
||||||
|
return AdditionalLayoutInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList tableEntries = tableLine.split( " ", SplitSkipEmptyParts );
|
||||||
|
|
||||||
|
AdditionalLayoutInfo r;
|
||||||
|
|
||||||
|
r.additionalLayout = tableEntries[1];
|
||||||
|
r.additionalVariant = tableEntries[2] == "-" ? "" : tableEntries[2];
|
||||||
|
|
||||||
|
r.vconsoleKeymap = tableEntries[3];
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
Config::Config( QObject* parent )
|
Config::Config( QObject* parent )
|
||||||
: QObject( parent )
|
: QObject( parent )
|
||||||
, m_keyboardModelsModel( new KeyboardModelsModel( this ) )
|
, m_keyboardModelsModel( new KeyboardModelsModel( this ) )
|
||||||
@ -82,8 +176,35 @@ Config::Config( QObject* parent )
|
|||||||
}
|
}
|
||||||
|
|
||||||
connect( &m_setxkbmapTimer, &QTimer::timeout, this, [=] {
|
connect( &m_setxkbmapTimer, &QTimer::timeout, this, [=] {
|
||||||
QProcess::execute( "setxkbmap", xkbmap_layout_args( m_selectedLayout, m_selectedVariant ) );
|
m_additionalLayoutInfo = getAdditionalLayoutInfo( m_selectedLayout );
|
||||||
cDebug() << "xkbmap selection changed to: " << m_selectedLayout << '-' << m_selectedVariant;
|
|
||||||
|
if ( !m_additionalLayoutInfo.additionalLayout.isEmpty() )
|
||||||
|
{
|
||||||
|
m_additionalLayoutInfo.groupSwitcher = xkbmap_query_grp_option();
|
||||||
|
|
||||||
|
if( m_additionalLayoutInfo.groupSwitcher.isEmpty() )
|
||||||
|
{
|
||||||
|
m_additionalLayoutInfo.groupSwitcher = "grp:alt_shift_toggle";
|
||||||
|
}
|
||||||
|
|
||||||
|
QProcess::execute( "setxkbmap", xkbmap_layout_args(
|
||||||
|
{ m_additionalLayoutInfo.additionalLayout, m_selectedLayout },
|
||||||
|
{ m_additionalLayoutInfo.additionalVariant, m_selectedVariant },
|
||||||
|
m_additionalLayoutInfo.groupSwitcher )
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cDebug() << "xkbmap selection changed to: " << m_selectedLayout << '-' << m_selectedVariant
|
||||||
|
<< "(added " << m_additionalLayoutInfo.additionalLayout << "-"
|
||||||
|
<< m_additionalLayoutInfo.additionalVariant << " since current layout is not ASCII-capable)";
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QProcess::execute( "setxkbmap", xkbmap_layout_args( m_selectedLayout, m_selectedVariant ) );
|
||||||
|
cDebug() << "xkbmap selection changed to: " << m_selectedLayout << '-' << m_selectedVariant;
|
||||||
|
}
|
||||||
m_setxkbmapTimer.disconnect( this );
|
m_setxkbmapTimer.disconnect( this );
|
||||||
} );
|
} );
|
||||||
m_setxkbmapTimer.start( QApplication::keyboardInputInterval() );
|
m_setxkbmapTimer.start( QApplication::keyboardInputInterval() );
|
||||||
@ -222,6 +343,7 @@ Config::createJobs()
|
|||||||
Calamares::Job* j = new SetKeyboardLayoutJob( m_selectedModel,
|
Calamares::Job* j = new SetKeyboardLayoutJob( m_selectedModel,
|
||||||
m_selectedLayout,
|
m_selectedLayout,
|
||||||
m_selectedVariant,
|
m_selectedVariant,
|
||||||
|
m_additionalLayoutInfo,
|
||||||
m_xOrgConfFileName,
|
m_xOrgConfFileName,
|
||||||
m_convertedKeymapPath,
|
m_convertedKeymapPath,
|
||||||
m_writeEtcDefaultKeyboard );
|
m_writeEtcDefaultKeyboard );
|
||||||
@ -372,6 +494,13 @@ Config::finalize()
|
|||||||
{
|
{
|
||||||
gs->insert( "keyboardLayout", m_selectedLayout );
|
gs->insert( "keyboardLayout", m_selectedLayout );
|
||||||
gs->insert( "keyboardVariant", m_selectedVariant ); //empty means default variant
|
gs->insert( "keyboardVariant", m_selectedVariant ); //empty means default variant
|
||||||
|
|
||||||
|
if ( !m_additionalLayoutInfo.additionalLayout.isEmpty() )
|
||||||
|
{
|
||||||
|
gs->insert( "keyboardAdditionalLayout", m_additionalLayoutInfo.additionalLayout);
|
||||||
|
gs->insert( "keyboardAdditionalLayout", m_additionalLayoutInfo.additionalVariant);
|
||||||
|
gs->insert( "keyboardVConsoleKeymap", m_additionalLayoutInfo.vconsoleKeymap );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIXME: also store keyboard model for something?
|
//FIXME: also store keyboard model for something?
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "Job.h"
|
#include "Job.h"
|
||||||
#include "KeyboardLayoutModel.h"
|
#include "KeyboardLayoutModel.h"
|
||||||
|
#include "AdditionalLayoutInfo.h"
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
@ -41,6 +42,8 @@ public:
|
|||||||
|
|
||||||
void setConfigurationMap( const QVariantMap& configurationMap );
|
void setConfigurationMap( const QVariantMap& configurationMap );
|
||||||
|
|
||||||
|
static AdditionalLayoutInfo getAdditionalLayoutInfo( const QString& layout );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void guessLayout( const QStringList& langParts );
|
void guessLayout( const QStringList& langParts );
|
||||||
void updateVariants( const QPersistentModelIndex& currentItem, QString currentVariant = QString() );
|
void updateVariants( const QPersistentModelIndex& currentItem, QString currentVariant = QString() );
|
||||||
@ -52,6 +55,10 @@ private:
|
|||||||
QString m_selectedLayout;
|
QString m_selectedLayout;
|
||||||
QString m_selectedModel;
|
QString m_selectedModel;
|
||||||
QString m_selectedVariant;
|
QString m_selectedVariant;
|
||||||
|
|
||||||
|
// Layout (and corresponding info) added if current one doesn't support ASCII (e.g. Russian or Japanese)
|
||||||
|
AdditionalLayoutInfo m_additionalLayoutInfo;
|
||||||
|
|
||||||
QTimer m_setxkbmapTimer;
|
QTimer m_setxkbmapTimer;
|
||||||
|
|
||||||
// From configuration
|
// From configuration
|
||||||
|
@ -30,9 +30,10 @@
|
|||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
|
||||||
|
|
||||||
SetKeyboardLayoutJob::SetKeyboardLayoutJob( const QString& model,
|
SetKeyboardLayoutJob::SetKeyboardLayoutJob(const QString& model,
|
||||||
const QString& layout,
|
const QString& layout,
|
||||||
const QString& variant,
|
const QString& variant,
|
||||||
|
const AdditionalLayoutInfo& additionalLayoutInfo,
|
||||||
const QString& xOrgConfFileName,
|
const QString& xOrgConfFileName,
|
||||||
const QString& convertedKeymapPath,
|
const QString& convertedKeymapPath,
|
||||||
bool writeEtcDefaultKeyboard )
|
bool writeEtcDefaultKeyboard )
|
||||||
@ -40,6 +41,7 @@ SetKeyboardLayoutJob::SetKeyboardLayoutJob( const QString& model,
|
|||||||
, m_model( model )
|
, m_model( model )
|
||||||
, m_layout( layout )
|
, m_layout( layout )
|
||||||
, m_variant( variant )
|
, m_variant( variant )
|
||||||
|
, m_additionalLayoutInfo( additionalLayoutInfo )
|
||||||
, m_xOrgConfFileName( xOrgConfFileName )
|
, m_xOrgConfFileName( xOrgConfFileName )
|
||||||
, m_convertedKeymapPath( convertedKeymapPath )
|
, m_convertedKeymapPath( convertedKeymapPath )
|
||||||
, m_writeEtcDefaultKeyboard( writeEtcDefaultKeyboard )
|
, m_writeEtcDefaultKeyboard( writeEtcDefaultKeyboard )
|
||||||
@ -250,19 +252,32 @@ SetKeyboardLayoutJob::writeX11Data( const QString& keyboardConfPath ) const
|
|||||||
" Identifier \"system-keyboard\"\n"
|
" Identifier \"system-keyboard\"\n"
|
||||||
" MatchIsKeyboard \"on\"\n";
|
" MatchIsKeyboard \"on\"\n";
|
||||||
|
|
||||||
if ( !m_layout.isEmpty() )
|
|
||||||
{
|
|
||||||
stream << " Option \"XkbLayout\" \"" << m_layout << "\"\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( !m_model.isEmpty() )
|
if ( m_additionalLayoutInfo.additionalLayout.isEmpty() )
|
||||||
{
|
{
|
||||||
stream << " Option \"XkbModel\" \"" << m_model << "\"\n";
|
if ( !m_layout.isEmpty() )
|
||||||
}
|
{
|
||||||
|
stream << " Option \"XkbLayout\" \"" << m_layout << "\"\n";
|
||||||
|
}
|
||||||
|
|
||||||
if ( !m_variant.isEmpty() )
|
if ( !m_variant.isEmpty() )
|
||||||
|
{
|
||||||
|
stream << " Option \"XkbVariant\" \"" << m_variant << "\"\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
stream << " Option \"XkbVariant\" \"" << m_variant << "\"\n";
|
if ( !m_layout.isEmpty() )
|
||||||
|
{
|
||||||
|
stream << " Option \"XkbLayout\" \"" << m_additionalLayoutInfo.additionalLayout << "," << m_layout << "\"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !m_variant.isEmpty() )
|
||||||
|
{
|
||||||
|
stream << " Option \"XkbVariant\" \"" << m_additionalLayoutInfo.additionalVariant << "," << m_variant << "\"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
stream << " Option \"XkbOptions\" \"" << m_additionalLayoutInfo.groupSwitcher << "\"\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
stream << "EndSection\n";
|
stream << "EndSection\n";
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#define SETKEYBOARDLAYOUTJOB_H
|
#define SETKEYBOARDLAYOUTJOB_H
|
||||||
|
|
||||||
#include "Job.h"
|
#include "Job.h"
|
||||||
|
#include "AdditionalLayoutInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SetKeyboardLayoutJob : public Calamares::Job
|
class SetKeyboardLayoutJob : public Calamares::Job
|
||||||
@ -21,6 +23,7 @@ public:
|
|||||||
SetKeyboardLayoutJob( const QString& model,
|
SetKeyboardLayoutJob( const QString& model,
|
||||||
const QString& layout,
|
const QString& layout,
|
||||||
const QString& variant,
|
const QString& variant,
|
||||||
|
const AdditionalLayoutInfo& additionaLayoutInfo,
|
||||||
const QString& xOrgConfFileName,
|
const QString& xOrgConfFileName,
|
||||||
const QString& convertedKeymapPath,
|
const QString& convertedKeymapPath,
|
||||||
bool writeEtcDefaultKeyboard );
|
bool writeEtcDefaultKeyboard );
|
||||||
@ -38,6 +41,7 @@ private:
|
|||||||
QString m_model;
|
QString m_model;
|
||||||
QString m_layout;
|
QString m_layout;
|
||||||
QString m_variant;
|
QString m_variant;
|
||||||
|
AdditionalLayoutInfo m_additionalLayoutInfo;
|
||||||
QString m_xOrgConfFileName;
|
QString m_xOrgConfFileName;
|
||||||
QString m_convertedKeymapPath;
|
QString m_convertedKeymapPath;
|
||||||
const bool m_writeEtcDefaultKeyboard;
|
const bool m_writeEtcDefaultKeyboard;
|
||||||
|
@ -2,5 +2,6 @@
|
|||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
<file>kbd-model-map</file>
|
<file>kbd-model-map</file>
|
||||||
<file>images/restore.png</file>
|
<file>images/restore.png</file>
|
||||||
|
<file>non-ascii-layouts</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
4
src/modules/keyboard/non-ascii-layouts
Normal file
4
src/modules/keyboard/non-ascii-layouts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# Layouts stored here need additional layout (usually us) to provide ASCII support for user
|
||||||
|
|
||||||
|
#layout additional-layout additional-variant vconsole-keymap
|
||||||
|
ru us - ruwin_alt_sh-UTF-8
|
@ -3,5 +3,6 @@
|
|||||||
<file alias="kbd-model-map">../keyboard/kbd-model-map</file>
|
<file alias="kbd-model-map">../keyboard/kbd-model-map</file>
|
||||||
<file alias="images/restore.png">../keyboard/images/restore.png</file>
|
<file alias="images/restore.png">../keyboard/images/restore.png</file>
|
||||||
<file>keyboardq.qml</file>
|
<file>keyboardq.qml</file>
|
||||||
|
<file alias="non-ascii-layouts">../keyboard/non-ascii-layouts</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -43,6 +43,7 @@ Config::status() const
|
|||||||
case Status::FailedNetworkError:
|
case Status::FailedNetworkError:
|
||||||
return tr( "Network Installation. (Disabled: Unable to fetch package lists, check your network connection)" );
|
return tr( "Network Installation. (Disabled: Unable to fetch package lists, check your network connection)" );
|
||||||
}
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,6 +110,7 @@ PackageChooserViewStep::isNextEnabled() const
|
|||||||
// exactly one OR one or more
|
// exactly one OR one or more
|
||||||
return m_widget->hasSelection();
|
return m_widget->hasSelection();
|
||||||
}
|
}
|
||||||
|
__builtin_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user