14#include <config-libkleo.h>
16#include "keyselectiondialog.h"
18#include "keylistview.h"
19#include "progressdialog.h"
21#include <libkleo/compat.h>
22#include <libkleo/compliance.h>
23#include <libkleo/dn.h>
24#include <libkleo/formatting.h>
26#include <kleo_ui_debug.h>
29#include <KConfigGroup>
30#include <KLocalizedString>
32#include <KSharedConfig>
34#include <QGpgME/KeyListJob>
36#include <QApplication>
38#include <QDialogButtonBox>
46#include <QRegularExpression>
51#include <gpgme++/key.h>
52#include <gpgme++/keylistresult.h>
60static bool checkKeyUsage(
const GpgME::Key &key,
unsigned int keyUsage,
QString *statusString =
nullptr)
62 auto setStatusString = [statusString](
const QString &
status) {
68 if (keyUsage & KeySelectionDialog::ValidKeys) {
69 if (key.isInvalid()) {
70 if (key.keyListMode() & GpgME::Validate) {
71 qCDebug(KLEO_UI_LOG) <<
"key is invalid";
72 setStatusString(
i18n(
"The key is not valid."));
75 qCDebug(KLEO_UI_LOG) <<
"key is invalid - ignoring";
78 if (key.isExpired()) {
79 qCDebug(KLEO_UI_LOG) <<
"key is expired";
80 setStatusString(
i18n(
"The key is expired."));
82 }
else if (key.isRevoked()) {
83 qCDebug(KLEO_UI_LOG) <<
"key is revoked";
84 setStatusString(
i18n(
"The key is revoked."));
86 }
else if (key.isDisabled()) {
87 qCDebug(KLEO_UI_LOG) <<
"key is disabled";
88 setStatusString(
i18n(
"The key is disabled."));
93 if (keyUsage & KeySelectionDialog::EncryptionKeys && !Kleo::keyHasEncrypt(key)) {
94 qCDebug(KLEO_UI_LOG) <<
"key can't encrypt";
95 setStatusString(
i18n(
"The key is not designated for encryption."));
98 if (keyUsage & KeySelectionDialog::SigningKeys && !Kleo::keyHasSign(key)) {
99 qCDebug(KLEO_UI_LOG) <<
"key can't sign";
100 setStatusString(
i18n(
"The key is not designated for signing."));
103 if (keyUsage & KeySelectionDialog::CertificationKeys && !Kleo::keyHasCertify(key)) {
104 qCDebug(KLEO_UI_LOG) <<
"key can't certify";
105 setStatusString(
i18n(
"The key is not designated for certifying."));
108 if (keyUsage & KeySelectionDialog::AuthenticationKeys && !Kleo::keyHasAuthenticate(key)) {
109 qCDebug(KLEO_UI_LOG) <<
"key can't authenticate";
110 setStatusString(
i18n(
"The key is not designated for authentication."));
114 if (keyUsage & KeySelectionDialog::SecretKeys && !(keyUsage & KeySelectionDialog::PublicKeys) && !key.hasSecret()) {
115 qCDebug(KLEO_UI_LOG) <<
"key isn't secret";
116 setStatusString(
i18n(
"The key is not secret."));
120 if (keyUsage & KeySelectionDialog::TrustedKeys && key.protocol() == GpgME::OpenPGP &&
124 std::vector<GpgME::UserID> uids = key.userIDs();
125 for (std::vector<GpgME::UserID>::const_iterator it = uids.begin(); it != uids.end(); ++it) {
126 if (!it->isRevoked() && it->validity() >= GpgME::UserID::Marginal) {
127 setStatusString(
i18n(
"The key can be used."));
131 qCDebug(KLEO_UI_LOG) <<
"key has no UIDs with validity >= Marginal";
132 setStatusString(
i18n(
"The key is not trusted enough."));
138 setStatusString(
i18n(
"The key can be used."));
142static bool checkKeyUsage(
const std::vector<GpgME::Key> &keys,
unsigned int keyUsage)
144 for (
auto it = keys.begin(); it != keys.end(); ++it) {
145 if (!checkKeyUsage(*it, keyUsage)) {
155class ColumnStrategy :
public KeyListView::ColumnStrategy
158 ColumnStrategy(
unsigned int keyUsage);
160 QString title(
int col)
const override;
161 int width(
int col,
const QFontMetrics &fm)
const override;
163 QString text(
const GpgME::Key &key,
int col)
const override;
164 QString accessibleText(
const GpgME::Key &key,
int column)
const override;
165 QString toolTip(
const GpgME::Key &key,
int col)
const override;
166 QIcon icon(
const GpgME::Key &key,
int col)
const override;
169 const QIcon mKeyGoodPix, mKeyBadPix, mKeyUnknownPix, mKeyValidPix;
170 const unsigned int mKeyUsage;
178ColumnStrategy::ColumnStrategy(
unsigned int keyUsage)
179 : KeyListView::ColumnStrategy()
180 , mKeyGoodPix(iconPath(QStringLiteral(
"key_ok")))
181 , mKeyBadPix(iconPath(QStringLiteral(
"key_bad")))
182 , mKeyUnknownPix(iconPath(QStringLiteral(
"key_unknown")))
183 , mKeyValidPix(iconPath(QStringLiteral(
"key")))
184 , mKeyUsage(keyUsage)
187 qCWarning(KLEO_UI_LOG) <<
"KeySelectionDialog: keyUsage == 0. You want to use AllKeys instead.";
191QString ColumnStrategy::title(
int col)
const
195 return i18n(
"Key ID");
197 return i18n(
"User ID");
203int ColumnStrategy::width(
int col,
const QFontMetrics &fm)
const
206 static const char hexchars[] =
"0123456789ABCDEF";
208 for (
unsigned int i = 0; i < 16; ++i) {
211 return 8 * maxWidth + 2 * 16 ;
213 return KeyListView::ColumnStrategy::width(col, fm);
216QString ColumnStrategy::text(
const GpgME::Key &key,
int col)
const
221 return Formatting::prettyID(key.keyID());
223 return xi18n(
"<placeholder>unknown</placeholder>");
227 const char *uid = key.userID(0).id();
228 if (key.protocol() == GpgME::OpenPGP) {
239QString ColumnStrategy::accessibleText(
const GpgME::Key &key,
int col)
const
244 return Formatting::accessibleHexID(key.keyID());
253QString ColumnStrategy::toolTip(
const GpgME::Key &key,
int)
const
255 const char *uid = key.userID(0).id();
256 const char *fpr = key.primaryFingerprint();
257 const char *issuer = key.issuerName();
258 const GpgME::Subkey subkey = key.subkey(0);
259 const QString expiry = Formatting::expirationDateString(subkey);
260 const QString creation = Formatting::creationDateString(subkey);
262 if (!checkKeyUsage(key, mKeyUsage, &keyStatusString)) {
267 QString html = QStringLiteral(
"<qt><p style=\"style='white-space:pre'\">");
268 if (key.protocol() == GpgME::OpenPGP) {
271 html +=
i18n(
"S/MIME key for <b>%1</b>", uid ?
DN(uid).prettyDN() :
i18n(
"unknown"));
273 html += QStringLiteral(
"</p><table>");
276 html += QStringLiteral(
"<tr><td align=\"right\"><b>%1: </b></td><td>%2</td></tr>").
arg(name, value);
281 if (key.protocol() != GpgME::OpenPGP) {
282 addRow(
i18nc(
"Key issuer",
"Issuer"), issuer ?
DN(issuer).prettyDN() :
i18n(
"unknown"));
284 addRow(
i18nc(
"Key status",
"Status"), keyStatusString);
285 if (DeVSCompliance::isActive()) {
286 addRow(
i18nc(
"Compliance of key",
"Compliance"), DeVSCompliance::name(key.isDeVs()));
288 html += QStringLiteral(
"</table></qt>");
293QIcon ColumnStrategy::icon(
const GpgME::Key &key,
int col)
const
299 if (!(key.keyListMode() & GpgME::Validate)) {
300 return mKeyUnknownPix;
303 if (!checkKeyUsage(key, mKeyUsage)) {
307 if (key.protocol() == GpgME::CMS) {
311 switch (key.userID(0).validity()) {
313 case GpgME::UserID::Unknown:
314 case GpgME::UserID::Undefined:
315 return mKeyUnknownPix;
316 case GpgME::UserID::Never:
318 case GpgME::UserID::Marginal:
319 case GpgME::UserID::Full:
320 case GpgME::UserID::Ultimate: {
321 if (DeVSCompliance::isActive() && !key.isDeVs()) {
331static const int sCheckSelectionDelay = 250;
333KeySelectionDialog::KeySelectionDialog(
QWidget *parent, Options options)
335 , mOpenPGPBackend(QGpgME::openpgp())
336 , mSMIMEBackend(QGpgME::smime())
339 qCDebug(KLEO_UI_LOG) <<
"mTruncated:" << mTruncated <<
"mSavedOffsetY:" << mSavedOffsetY;
343KeySelectionDialog::KeySelectionDialog(
const QString &title,
345 const std::vector<GpgME::Key> &selectedKeys,
346 unsigned int keyUsage,
347 bool extendedSelection,
352 , mSelectedKeys(selectedKeys)
353 , mKeyUsage(keyUsage)
355 setWindowTitle(title);
357 init(rememberChoice, extendedSelection, text,
QString());
360KeySelectionDialog::KeySelectionDialog(
const QString &title,
363 const std::vector<GpgME::Key> &selectedKeys,
364 unsigned int keyUsage,
365 bool extendedSelection,
370 , mSelectedKeys(selectedKeys)
371 , mKeyUsage(keyUsage)
372 , mSearchText(initialQuery)
373 , mInitialQuery(initialQuery)
375 setWindowTitle(title);
377 init(rememberChoice, extendedSelection, text, initialQuery);
380KeySelectionDialog::KeySelectionDialog(
const QString &title,
383 unsigned int keyUsage,
384 bool extendedSelection,
389 , mKeyUsage(keyUsage)
390 , mSearchText(initialQuery)
391 , mInitialQuery(initialQuery)
393 setWindowTitle(title);
395 init(rememberChoice, extendedSelection, text, initialQuery);
398void KeySelectionDialog::setUpUI(Options options,
const QString &initialQuery)
406 mCheckSelectionTimer =
new QTimer(
this);
407 mStartSearchTimer =
new QTimer(
this);
410 mainLayout->addWidget(page);
411 mainLayout->addWidget(buttonBox);
416 mTextLabel =
new QLabel(page);
430 searchExternalPB->
hide();
437 le->setClearButtonEnabled(
true);
438 le->setText(initialQuery);
443 hlay->addWidget(lbSearchFor);
444 hlay->addWidget(le, 1);
452 mKeyListView =
new KeyListView(
new ColumnStrategy(mKeyUsage),
nullptr, page);
459 if (options & ExtendedSelection) {
464 if (options & RememberChoice) {
465 mRememberCB =
new QCheckBox(
i18nc(
"@option:check",
"&Remember choice"), page);
468 i18n(
"<qt><p>If you check this box your choice will "
469 "be stored and you will not be asked again."
474 slotCheckSelection();
478 connect(mKeyListView, &KeyListView::doubleClicked,
this, &KeySelectionDialog::slotTryOk);
479 connect(mKeyListView, &KeyListView::contextMenu,
this, &KeySelectionDialog::slotRMB);
481 if (options & RereadKeys) {
486 if (options & ExternalCertificateManager) {
490 slotStartCertificateManager();
501 dialogSize = dialogConfig.readEntry(
"Dialog size", dialogSize);
510void KeySelectionDialog::init(
bool rememberChoice,
bool extendedSelection,
const QString &text,
const QString &initialQuery)
512 Options options = {RereadKeys, ExternalCertificateManager};
513 options.setFlag(ExtendedSelection, extendedSelection);
514 options.setFlag(RememberChoice, rememberChoice);
516 setUpUI(options, initialQuery);
519 if (mKeyUsage & OpenPGPKeys) {
520 mOpenPGPBackend = QGpgME::openpgp();
522 if (mKeyUsage & SMIMEKeys) {
523 mSMIMEBackend = QGpgME::smime();
529KeySelectionDialog::~KeySelectionDialog()
533 dialogConfig.writeEntry(
"Dialog size",
size());
534 dialogConfig.writeEntry(
"header", mKeyListView->
header()->
saveState());
538void KeySelectionDialog::setText(
const QString &text)
544void KeySelectionDialog::setKeys(
const std::vector<GpgME::Key> &keys)
546 for (
const GpgME::Key &key : keys) {
547 mKeyListView->slotAddKey(key);
551void KeySelectionDialog::connectSignals()
553 if (mKeyListView->isMultiSelection()) {
557 qOverload<KeyListViewItem *>(&KeyListView::selectionChanged),
559 qOverload<KeyListViewItem *>(&KeySelectionDialog::slotCheckSelection));
563void KeySelectionDialog::disconnectSignals()
565 if (mKeyListView->isMultiSelection()) {
569 qOverload<KeyListViewItem *>(&KeyListView::selectionChanged),
571 qOverload<KeyListViewItem *>(&KeySelectionDialog::slotCheckSelection));
575const GpgME::Key &KeySelectionDialog::selectedKey()
const
577 static const GpgME::Key null = GpgME::Key::null;
578 if (mKeyListView->isMultiSelection() || !mKeyListView->selectedItem()) {
581 return mKeyListView->selectedItem()->key();
584QString KeySelectionDialog::fingerprint()
const
589QStringList KeySelectionDialog::fingerprints()
const
592 for (
auto it = mSelectedKeys.begin(); it != mSelectedKeys.end(); ++it) {
593 if (
const char *fpr = it->primaryFingerprint()) {
600QStringList KeySelectionDialog::pgpKeyFingerprints()
const
603 for (
auto it = mSelectedKeys.begin(); it != mSelectedKeys.end(); ++it) {
604 if (it->protocol() == GpgME::OpenPGP) {
605 if (
const char *fpr = it->primaryFingerprint()) {
613QStringList KeySelectionDialog::smimeFingerprints()
const
616 for (
auto it = mSelectedKeys.begin(); it != mSelectedKeys.end(); ++it) {
617 if (it->protocol() == GpgME::CMS) {
618 if (
const char *fpr = it->primaryFingerprint()) {
626void KeySelectionDialog::slotRereadKeys()
628 mKeyListView->clear();
637 if (mOpenPGPBackend) {
638 startKeyListJobForBackend(mOpenPGPBackend, std::vector<GpgME::Key>(),
false );
641 startKeyListJobForBackend(mSMIMEBackend, std::vector<GpgME::Key>(),
false );
644 if (mListJobCount == 0) {
647 i18n(
"No backends found for listing keys. "
648 "Check your installation."),
649 i18nc(
"@title:window",
"Key Listing Failed"));
654void KeySelectionDialog::slotStartCertificateManager(
const QString &query)
659 args << QStringLiteral(
"--search") <<
query;
662 if (
exec.isEmpty()) {
663 qCWarning(KLEO_UI_LOG) <<
"Could not find kleopatra executable in PATH";
665 i18n(
"Could not start certificate manager; "
666 "please check your installation."),
667 i18nc(
"@title:window",
"Certificate Manager Error"));
670 qCDebug(KLEO_UI_LOG) <<
"\nslotStartCertManager(): certificate manager started.";
674#ifndef __KLEO_UI_SHOW_KEY_LIST_ERROR_H__
675#define __KLEO_UI_SHOW_KEY_LIST_ERROR_H__
676static void showKeyListError(
QWidget *parent,
const GpgME::Error &err)
680 "<qt><p>An error occurred while fetching "
681 "the keys from the backend:</p>"
682 "<p><b>%1</b></p></qt>",
683 Formatting::errorAsString(err));
691struct ExtractFingerprint {
692 QString operator()(
const GpgME::Key &key)
699void KeySelectionDialog::startKeyListJobForBackend(
const QGpgME::Protocol *backend,
const std::vector<GpgME::Key> &keys,
bool validate)
702 QGpgME::KeyListJob *job = backend->keyListJob(
false,
false, validate);
707 connect(job, &QGpgME::KeyListJob::result,
this, &KeySelectionDialog::slotKeyListResult);
709 connect(job, &QGpgME::KeyListJob::nextKey, mKeyListView, &KeyListView::slotRefreshKey);
711 connect(job, &QGpgME::KeyListJob::nextKey, mKeyListView, &KeyListView::slotAddKey);
715 std::transform(keys.begin(), keys.end(), std::back_inserter(fprs), ExtractFingerprint());
716 const GpgME::Error err = job->start(fprs, mKeyUsage & SecretKeys && !(mKeyUsage & PublicKeys));
719 return showKeyListError(
this, err);
722#ifndef LIBKLEO_NO_PROGRESSDIALOG
724 (void)
new ProgressDialog(job, validate ?
i18n(
"Checking selected keys...") :
i18n(
"Fetching keys..."),
this);
729static void selectKeys(KeyListView *klv,
const std::vector<GpgME::Key> &selectedKeys)
732 if (selectedKeys.empty()) {
735 for (
auto it = selectedKeys.begin(); it != selectedKeys.end(); ++it) {
736 if (KeyListViewItem *item = klv->itemByFingerprint(it->primaryFingerprint())) {
737 item->setSelected(
true);
742void KeySelectionDialog::slotKeyListResult(
const GpgME::KeyListResult &res)
745 showKeyListError(
this, res.error());
746 }
else if (res.isTruncated()) {
750 if (--mListJobCount > 0) {
754 if (mTruncated > 0) {
756 i18np(
"<qt>One backend returned truncated output.<p>"
757 "Not all available keys are shown</p></qt>",
758 "<qt>%1 backends returned truncated output.<p>"
759 "Not all available keys are shown</p></qt>",
761 i18n(
"Key List Result"));
764 mKeyListView->flushKeys();
767 mListJobCount = mTruncated = 0;
768 mKeysToCheck.clear();
770 selectKeys(mKeyListView, mSelectedKeys);
776 slotSelectionChanged();
783void KeySelectionDialog::slotSelectionChanged()
785 qCDebug(KLEO_UI_LOG) <<
"KeySelectionDialog::slotSelectionChanged()";
790 mCheckSelectionTimer->
start(sCheckSelectionDelay);
795struct AlreadyChecked {
796 bool operator()(
const GpgME::Key &key)
const
798 return key.keyListMode() & GpgME::Validate;
803void KeySelectionDialog::slotCheckSelection(KeyListViewItem *item)
805 qCDebug(KLEO_UI_LOG) <<
"KeySelectionDialog::slotCheckSelection()";
807 mCheckSelectionTimer->
stop();
809 mSelectedKeys.clear();
811 if (!mKeyListView->isMultiSelection()) {
813 mSelectedKeys.push_back(item->key());
817 for (KeyListViewItem *it = mKeyListView->firstChild(); it; it = it->nextSibling()) {
818 if (it->isSelected()) {
819 mSelectedKeys.push_back(it->key());
823 mKeysToCheck.clear();
824 std::remove_copy_if(mSelectedKeys.begin(), mSelectedKeys.end(), std::back_inserter(mKeysToCheck), AlreadyChecked());
825 if (mKeysToCheck.empty()) {
826 mOkButton->
setEnabled(!mSelectedKeys.empty() && checkKeyUsage(mSelectedKeys, mKeyUsage));
831 startValidatingKeyListing();
834void KeySelectionDialog::startValidatingKeyListing()
836 if (mKeysToCheck.empty()) {
847 std::vector<GpgME::Key> smime;
848 std::vector<GpgME::Key> openpgp;
849 for (std::vector<GpgME::Key>::const_iterator it = mKeysToCheck.begin(); it != mKeysToCheck.end(); ++it) {
850 if (it->protocol() == GpgME::OpenPGP) {
851 openpgp.push_back(*it);
853 smime.push_back(*it);
857 if (!openpgp.empty()) {
858 Q_ASSERT(mOpenPGPBackend);
859 startKeyListJobForBackend(mOpenPGPBackend, openpgp,
true );
861 if (!smime.empty()) {
862 Q_ASSERT(mSMIMEBackend);
863 startKeyListJobForBackend(mSMIMEBackend, smime,
true );
866 Q_ASSERT(mListJobCount > 0);
869bool KeySelectionDialog::rememberSelection()
const
871 return mRememberCB && mRememberCB->
isChecked();
874void KeySelectionDialog::slotRMB(KeyListViewItem *item,
const QPoint &p)
880 mCurrentContextMenuItem = item;
883 menu.
addAction(
i18n(
"Recheck Key"),
this, &KeySelectionDialog::slotRecheckKey);
887void KeySelectionDialog::slotRecheckKey()
889 if (!mCurrentContextMenuItem || mCurrentContextMenuItem->key().isNull()) {
893 mKeysToCheck.clear();
894 mKeysToCheck.push_back(mCurrentContextMenuItem->key());
897void KeySelectionDialog::slotTryOk()
899 if (!mSelectedKeys.empty() && checkKeyUsage(mSelectedKeys, mKeyUsage)) {
904void KeySelectionDialog::slotOk()
906 if (mCheckSelectionTimer->
isActive()) {
907 slotCheckSelection();
911 if (!mSelectedKeys.empty() && checkKeyUsage(mSelectedKeys, mKeyUsage)) {
915 mStartSearchTimer->
stop();
919void KeySelectionDialog::slotCancel()
921 mCheckSelectionTimer->
stop();
922 mStartSearchTimer->
stop();
926void KeySelectionDialog::slotSearch(
const QString &text)
932void KeySelectionDialog::slotSearch()
935 mStartSearchTimer->
start(sCheckSelectionDelay);
938void KeySelectionDialog::slotFilter()
947 if (keyIdRegExp.match(mSearchText).hasMatch()) {
950 filterByKeyID(mSearchText.
mid(2));
953 filterByKeyIDOrUID(mSearchText);
957 filterByUID(mSearchText);
961void KeySelectionDialog::filterByKeyID(
const QString &keyID)
963 Q_ASSERT(keyID.
length() <= 16);
968 for (KeyListViewItem *item = mKeyListView->firstChild(); item; item = item->nextSibling()) {
980 const std::vector<GpgME::UserID> uids = item->key().userIDs();
981 for (
auto it = uids.begin(); it != uids.end(); ++it) {
989void KeySelectionDialog::filterByKeyIDOrUID(
const QString &str)
996 for (KeyListViewItem *item = mKeyListView->firstChild(); item; item = item->nextSibling()) {
1001void KeySelectionDialog::filterByUID(
const QString &str)
1008 for (KeyListViewItem *item = mKeyListView->firstChild(); item; item = item->nextSibling()) {
1009 item->
setHidden(!anyUIDMatches(item, rx));
1013void KeySelectionDialog::showAllItems()
1015 for (KeyListViewItem *item = mKeyListView->firstChild(); item; item = item->nextSibling()) {
1020#include "moc_keyselectiondialog.cpp"
static KSharedConfig::Ptr openStateConfig(const QString &fileName=QString())
A progress dialog for Kleo::Jobs.
Q_SCRIPTABLE CaptureState status()
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString xi18n(const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
void init(KXmlGuiWindow *window, KGameDifficulty *difficulty=nullptr)
void information(QWidget *parent, const QString &text, const QString &title=QString(), const QString &dontShowAgainName=QString(), Options options=Notify)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
void setSelectionMode(QAbstractItemView::SelectionMode mode)
void addLayout(QLayout *layout, int stretch)
bool isEmpty() const const
virtual QSize sizeHint() const const override
QRect boundingRect(QChar ch) const const
void linkActivated(const QString &link)
void setBuddy(QWidget *buddy)
void setText(const QString &)
void setWordWrap(bool on)
void setContentsMargins(const QMargins &margins)
void textChanged(const QString &text)
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
void setObjectName(QAnyStringView name)
bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
QRegularExpressionMatch match(QStringView subjectView, qsizetype offset, MatchType matchType, MatchOptions matchOptions) const const
QString anchoredPattern(QStringView expression)
QString escape(QStringView str)
bool hasMatch() const const
QString findExecutable(const QString &executableName, const QStringList &paths)
QString locate(StandardLocation type, const QString &fileName, LocateOptions options)
QString arg(Args &&... args) const const
QString fromLatin1(QByteArrayView str)
QString fromUtf8(QByteArrayView str)
bool isEmpty() const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString toUpper() const const
QString trimmed() const const
QTestData & addRow(const char *format,...)
bool isActive() const const
void setSingleShot(bool singleShot)
void setRootIsDecorated(bool show)
void setSortingEnabled(bool enable)
QString text(int column) const const