Merge branch 'release/2.5.1' into develop

This commit is contained in:
Janek Bevendorff 2019-11-06 10:09:28 +01:00
commit eed935c923
23 changed files with 108 additions and 47 deletions

View File

@ -438,6 +438,14 @@ if(UNIX)
int main() { prctl(PR_SET_DUMPABLE, 0); return 0; }" int main() { prctl(PR_SET_DUMPABLE, 0); return 0; }"
HAVE_PR_SET_DUMPABLE) HAVE_PR_SET_DUMPABLE)
check_cxx_source_compiles("#include <malloc.h>
int main() { return 0; }"
HAVE_MALLOC_H)
check_cxx_source_compiles("#include <malloc.h>
int main() { malloc_usable_size(NULL, 0); return 0; }"
HAVE_MALLOC_USABLE_SIZE)
check_cxx_source_compiles("#include <sys/resource.h> check_cxx_source_compiles("#include <sys/resource.h>
int main() { int main() {
struct rlimit limit; struct rlimit limit;

View File

@ -182,6 +182,10 @@ an error if no TOTP is configured for the entry.
Shows the named attributes. This option can be specified more than once, Shows the named attributes. This option can be specified more than once,
with each attribute shown one-per-line in the given order. If no attributes are with each attribute shown one-per-line in the given order. If no attributes are
specified and \fI-t\fP is not specified, a summary of the default attributes is given. specified and \fI-t\fP is not specified, a summary of the default attributes is given.
Protected attributes will be displayed in clear text if specified explicitly by this option.
.IP "-s, --show-protected"
Shows the protected attributes in clear text.
.IP "-t, --totp" .IP "-t, --totp"
Also shows the current TOTP, reporting an error if no TOTP is configured for Also shows the current TOTP, reporting an error if no TOTP is configured for

View File

@ -33,5 +33,9 @@ endif()
set(QM_FILES ${QM_FILES} ${QTBASE_TRANSLATIONS}) set(QM_FILES ${QM_FILES} ${QTBASE_TRANSLATIONS})
install(FILES ${QM_FILES} DESTINATION ${DATA_INSTALL_DIR}/translations) install(FILES ${QM_FILES} DESTINATION ${DATA_INSTALL_DIR}/translations)
# Add keepassx_en.qm as a fallback for uncommon english locales
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/keepassx_en_US.qm DESTINATION ${DATA_INSTALL_DIR}/translations RENAME keepassx_en.qm)
add_custom_target(translations DEPENDS ${QM_FILES}) add_custom_target(translations DEPENDS ${QM_FILES})
add_dependencies(${PROGNAME} translations) add_dependencies(${PROGNAME} translations)

View File

@ -46,7 +46,7 @@ Clip::Clip()
int Clip::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<QCommandLineParser> parser) int Clip::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<QCommandLineParser> parser)
{ {
const QStringList args = parser->positionalArguments(); const QStringList args = parser->positionalArguments();
QString entryPath = args.at(1); const QString& entryPath = args.at(1);
QString timeout; QString timeout;
if (args.size() == 3) { if (args.size() == 3) {
timeout = args.at(2); timeout = args.at(2);

View File

@ -60,8 +60,8 @@ int Import::execute(const QStringList& arguments)
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly); TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);
const QStringList args = parser->positionalArguments(); const QStringList args = parser->positionalArguments();
const QString xmlExportPath = args.at(0); const QString& xmlExportPath = args.at(0);
const QString dbPath = args.at(1); const QString& dbPath = args.at(1);
if (QFileInfo::exists(dbPath)) { if (QFileInfo::exists(dbPath)) {
errorTextStream << QObject::tr("File %1 already exists.").arg(dbPath) << endl; errorTextStream << QObject::tr("File %1 already exists.").arg(dbPath) << endl;

View File

@ -60,7 +60,7 @@ int List::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
QString groupPath = args.at(1); const QString& groupPath = args.at(1);
Group* group = database->rootGroup()->findGroupByPath(groupPath); Group* group = database->rootGroup()->findGroupByPath(groupPath);
if (!group) { if (!group) {
errorTextStream << QObject::tr("Cannot find group %1.").arg(groupPath) << endl; errorTextStream << QObject::tr("Cannot find group %1.").arg(groupPath) << endl;

View File

@ -40,7 +40,7 @@ int Locate::executeWithDatabase(QSharedPointer<Database> database, QSharedPointe
{ {
const QStringList args = parser->positionalArguments(); const QStringList args = parser->positionalArguments();
QString searchTerm = args.at(1); const QString& searchTerm = args.at(1);
TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly); TextStream outputTextStream(Utils::STDOUT, QIODevice::WriteOnly);
TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly); TextStream errorTextStream(Utils::STDERR, QIODevice::WriteOnly);

View File

@ -31,6 +31,11 @@ const QCommandLineOption Show::TotpOption = QCommandLineOption(QStringList() <<
<< "totp", << "totp",
QObject::tr("Show the entry's current TOTP.")); QObject::tr("Show the entry's current TOTP."));
const QCommandLineOption Show::ProtectedAttributesOption =
QCommandLineOption(QStringList() << "s"
<< "show-protected",
QObject::tr("Show the protected attributes in clear text."));
const QCommandLineOption Show::AttributesOption = QCommandLineOption( const QCommandLineOption Show::AttributesOption = QCommandLineOption(
QStringList() << "a" QStringList() << "a"
<< "attributes", << "attributes",
@ -46,6 +51,7 @@ Show::Show()
description = QObject::tr("Show an entry's information."); description = QObject::tr("Show an entry's information.");
options.append(Show::TotpOption); options.append(Show::TotpOption);
options.append(Show::AttributesOption); options.append(Show::AttributesOption);
options.append(Show::ProtectedAttributesOption);
positionalArguments.append({QString("entry"), QObject::tr("Name of the entry to show."), QString("")}); positionalArguments.append({QString("entry"), QObject::tr("Name of the entry to show."), QString("")});
} }
@ -57,6 +63,7 @@ int Show::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
const QStringList args = parser->positionalArguments(); const QStringList args = parser->positionalArguments();
const QString& entryPath = args.at(1); const QString& entryPath = args.at(1);
bool showTotp = parser->isSet(Show::TotpOption); bool showTotp = parser->isSet(Show::TotpOption);
bool showProtectedAttributes = parser->isSet(Show::ProtectedAttributesOption);
QStringList attributes = parser->values(Show::AttributesOption); QStringList attributes = parser->values(Show::AttributesOption);
Entry* entry = database->rootGroup()->findEntryByPath(entryPath); Entry* entry = database->rootGroup()->findEntryByPath(entryPath);
@ -78,16 +85,20 @@ int Show::executeWithDatabase(QSharedPointer<Database> database, QSharedPointer<
// Iterate over the attributes and output them line-by-line. // Iterate over the attributes and output them line-by-line.
bool sawUnknownAttribute = false; bool sawUnknownAttribute = false;
for (const QString& attribute : asConst(attributes)) { for (const QString& attributeName : asConst(attributes)) {
if (!entry->attributes()->contains(attribute)) { if (!entry->attributes()->contains(attributeName)) {
sawUnknownAttribute = true; sawUnknownAttribute = true;
errorTextStream << QObject::tr("ERROR: unknown attribute %1.").arg(attribute) << endl; errorTextStream << QObject::tr("ERROR: unknown attribute %1.").arg(attributeName) << endl;
continue; continue;
} }
if (showAttributeNames) { if (showAttributeNames) {
outputTextStream << attribute << ": "; outputTextStream << attributeName << ": ";
}
if (entry->attributes()->isProtected(attributeName) && showAttributeNames && !showProtectedAttributes) {
outputTextStream << "PROTECTED" << endl;
} else {
outputTextStream << entry->resolveMultiplePlaceholders(entry->attributes()->value(attributeName)) << endl;
} }
outputTextStream << entry->resolveMultiplePlaceholders(entry->attributes()->value(attribute)) << endl;
} }
if (showTotp) { if (showTotp) {

View File

@ -29,6 +29,7 @@ public:
static const QCommandLineOption TotpOption; static const QCommandLineOption TotpOption;
static const QCommandLineOption AttributesOption; static const QCommandLineOption AttributesOption;
static const QCommandLineOption ProtectedAttributesOption;
}; };
#endif // KEEPASSXC_SHOW_H #endif // KEEPASSXC_SHOW_H

View File

@ -23,8 +23,10 @@
#include <malloc/malloc.h> #include <malloc/malloc.h>
#elif defined(Q_OS_FREEBSD) #elif defined(Q_OS_FREEBSD)
#include <malloc_np.h> #include <malloc_np.h>
#else #elif defined(HAVE_MALLOC_H)
#include <malloc.h> #include <malloc.h>
#else
#include <stdlib.h>
#endif #endif
#if defined(NDEBUG) && !defined(__cpp_sized_deallocation) #if defined(NDEBUG) && !defined(__cpp_sized_deallocation)
@ -64,7 +66,7 @@ void operator delete(void* ptr) noexcept
::operator delete(ptr, _msize(ptr)); ::operator delete(ptr, _msize(ptr));
#elif defined(Q_OS_MACOS) #elif defined(Q_OS_MACOS)
::operator delete(ptr, malloc_size(ptr)); ::operator delete(ptr, malloc_size(ptr));
#elif defined(Q_OS_UNIX) #elif defined(HAVE_MALLOC_USABLE_SIZE)
::operator delete(ptr, malloc_usable_size(ptr)); ::operator delete(ptr, malloc_usable_size(ptr));
#else #else
// whatever OS this is, give up and simply free stuff // whatever OS this is, give up and simply free stuff

View File

@ -158,7 +158,7 @@ bool Database::open(const QString& filePath, QSharedPointer<const CompositeKey>
m_initialized = true; m_initialized = true;
emit databaseOpened(); emit databaseOpened();
m_fileWatcher->start(canonicalFilePath()); m_fileWatcher->start(canonicalFilePath(), 30, 1);
setEmitModified(true); setEmitModified(true);
return true; return true;
@ -234,7 +234,7 @@ bool Database::saveAs(const QString& filePath, QString* error, bool atomic, bool
bool ok = performSave(canonicalFilePath, error, atomic, backup); bool ok = performSave(canonicalFilePath, error, atomic, backup);
if (ok) { if (ok) {
setFilePath(filePath); setFilePath(filePath);
m_fileWatcher->start(canonicalFilePath); m_fileWatcher->start(canonicalFilePath, 30, 1);
} else { } else {
// Saving failed, don't rewatch file since it does not represent our database // Saving failed, don't rewatch file since it does not represent our database
markAsModified(); markAsModified();

View File

@ -42,7 +42,7 @@ FileWatcher::FileWatcher(QObject* parent)
m_fileIgnoreDelayTimer.setSingleShot(true); m_fileIgnoreDelayTimer.setSingleShot(true);
} }
void FileWatcher::start(const QString& filePath, int checksumInterval) void FileWatcher::start(const QString& filePath, int checksumIntervalSeconds, int checksumSizeKibibytes)
{ {
stop(); stop();
@ -63,8 +63,14 @@ void FileWatcher::start(const QString& filePath, int checksumInterval)
m_fileWatcher.addPath(filePath); m_fileWatcher.addPath(filePath);
m_filePath = filePath; m_filePath = filePath;
// Handle file checksum
m_fileChecksumSizeBytes = checksumSizeKibibytes * 1024;
m_fileChecksum = calculateChecksum(); m_fileChecksum = calculateChecksum();
m_fileChecksumTimer.start(checksumInterval); if (checksumIntervalSeconds > 0) {
m_fileChecksumTimer.start(checksumIntervalSeconds * 1000);
}
m_ignoreFileChange = false; m_ignoreFileChange = false;
} }
@ -131,9 +137,12 @@ QByteArray FileWatcher::calculateChecksum()
QFile file(m_filePath); QFile file(m_filePath);
if (file.open(QFile::ReadOnly)) { if (file.open(QFile::ReadOnly)) {
QCryptographicHash hash(QCryptographicHash::Sha256); QCryptographicHash hash(QCryptographicHash::Sha256);
if (hash.addData(&file)) { if (m_fileChecksumSizeBytes > 0) {
return hash.result(); hash.addData(file.read(m_fileChecksumSizeBytes));
} else {
hash.addData(&file);
} }
return hash.result();
} }
return {}; return {};
} }

View File

@ -30,7 +30,7 @@ class FileWatcher : public QObject
public: public:
explicit FileWatcher(QObject* parent = nullptr); explicit FileWatcher(QObject* parent = nullptr);
void start(const QString& path, int checksumInterval = 1000); void start(const QString& path, int checksumIntervalSeconds = 0, int checksumSizeKibibytes = -1);
void stop(); void stop();
bool hasSameFileChecksum(); bool hasSameFileChecksum();
@ -56,6 +56,7 @@ private:
QTimer m_fileChangeDelayTimer; QTimer m_fileChangeDelayTimer;
QTimer m_fileIgnoreDelayTimer; QTimer m_fileIgnoreDelayTimer;
QTimer m_fileChecksumTimer; QTimer m_fileChecksumTimer;
int m_fileChecksumSizeBytes;
bool m_ignoreFileChange; bool m_ignoreFileChange;
}; };

View File

@ -90,7 +90,7 @@ void IconDownloader::setUrl(const QString& entryUrl)
// searching for a match with the returned address(es). // searching for a match with the returned address(es).
bool hostIsIp = false; bool hostIsIp = false;
QList<QHostAddress> hostAddressess = QHostInfo::fromName(fullyQualifiedDomain).addresses(); QList<QHostAddress> hostAddressess = QHostInfo::fromName(fullyQualifiedDomain).addresses();
for (auto addr : hostAddressess) { for (const auto& addr : hostAddressess) {
if (addr.toString() == fullyQualifiedDomain) { if (addr.toString() == fullyQualifiedDomain) {
hostIsIp = true; hostIsIp = true;
} }

View File

@ -341,6 +341,8 @@ OpVaultReader::decodeB64CompositeKeys(const QString& b64, const QByteArray& encK
result->errorStr = tr("Unable to decode masterKey: %1").arg(keyKey01.errorString()); result->errorStr = tr("Unable to decode masterKey: %1").arg(keyKey01.errorString());
return result; return result;
} }
delete result;
const QByteArray keyKey = keyKey01.getClearText(); const QByteArray keyKey = keyKey01.getClearText();
return decodeCompositeKeys(keyKey); return decodeCompositeKeys(keyKey);

View File

@ -75,3 +75,10 @@ YubiKey::ChallengeResult YubiKey::challenge(int slot, bool mayBlock, const QByte
return ERROR; return ERROR;
} }
bool YubiKey::checkSlotIsBlocking(int slot, QString& errorMessage)
{
Q_UNUSED(slot);
Q_UNUSED(errorMessage);
return false;
}

View File

@ -55,6 +55,10 @@ int main(int argc, char** argv)
#endif #endif
#endif #endif
#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
QGuiApplication::setDesktopFileName("org.keepassxc.KeePassXC.desktop");
#endif
Application app(argc, argv); Application app(argc, argv);
Application::setApplicationName("keepassxc"); Application::setApplicationName("keepassxc");
Application::setApplicationVersion(KEEPASSXC_VERSION); Application::setApplicationVersion(KEEPASSXC_VERSION);

View File

@ -87,17 +87,7 @@ macro(add_unit_test)
endif() endif()
endmacro(add_unit_test) endmacro(add_unit_test)
set(TEST_LIBRARIES set(TEST_LIBRARIES keepassx_core Qt5::Test)
keepassx_core
${keepassxcbrowser_LIB}
${autotype_LIB}
Qt5::Core
Qt5::Concurrent
Qt5::Widgets
Qt5::Test
${GCRYPT_LIBRARIES}
${GPGERROR_LIBRARIES}
${ZLIB_LIBRARIES})
set(testsupport_SOURCES set(testsupport_SOURCES
modeltest.cpp modeltest.cpp
@ -108,10 +98,6 @@ set(testsupport_SOURCES
add_library(testsupport STATIC ${testsupport_SOURCES}) add_library(testsupport STATIC ${testsupport_SOURCES})
target_link_libraries(testsupport Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Test) target_link_libraries(testsupport Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Test)
if(YUBIKEY_FOUND)
set(TEST_LIBRARIES ${TEST_LIBRARIES} ${YUBIKEY_LIBRARIES})
endif()
add_unit_test(NAME testgroup SOURCES TestGroup.cpp add_unit_test(NAME testgroup SOURCES TestGroup.cpp
LIBS testsupport ${TEST_LIBRARIES}) LIBS testsupport ${TEST_LIBRARIES})

View File

@ -21,9 +21,9 @@
#include "core/Bootstrap.h" #include "core/Bootstrap.h"
#include "core/Config.h" #include "core/Config.h"
#include "core/Global.h" #include "core/Global.h"
#include "core/PasswordGenerator.h"
#include "core/Tools.h" #include "core/Tools.h"
#include "crypto/Crypto.h" #include "crypto/Crypto.h"
#include "keys/drivers/YubiKey.h"
#include "format/Kdbx3Reader.h" #include "format/Kdbx3Reader.h"
#include "format/Kdbx3Writer.h" #include "format/Kdbx3Writer.h"
#include "format/Kdbx4Reader.h" #include "format/Kdbx4Reader.h"
@ -1682,14 +1682,15 @@ void TestCli::testShow()
QCOMPARE(m_stdoutFile->readAll(), QCOMPARE(m_stdoutFile->readAll(),
QByteArray("Title: Sample Entry\n" QByteArray("Title: Sample Entry\n"
"UserName: User Name\n" "UserName: User Name\n"
"Password: Password\n" "Password: PROTECTED\n"
"URL: http://www.somesite.com/\n" "URL: http://www.somesite.com/\n"
"Notes: Notes\n")); "Notes: Notes\n"));
qint64 pos = m_stdoutFile->pos(); qint64 pos = m_stdoutFile->pos();
Utils::Test::setNextPassword("a"); Utils::Test::setNextPassword("a");
showCmd.execute({"show", m_dbFile->fileName(), "-q", "/Sample Entry"}); showCmd.execute({"show", "-s", m_dbFile->fileName(), "/Sample Entry"});
m_stdoutFile->seek(pos); m_stdoutFile->seek(pos);
m_stdoutFile->readLine(); // skip password prompt
QCOMPARE(m_stdoutFile->readAll(), QCOMPARE(m_stdoutFile->readAll(),
QByteArray("Title: Sample Entry\n" QByteArray("Title: Sample Entry\n"
"UserName: User Name\n" "UserName: User Name\n"
@ -1697,6 +1698,17 @@ void TestCli::testShow()
"URL: http://www.somesite.com/\n" "URL: http://www.somesite.com/\n"
"Notes: Notes\n")); "Notes: Notes\n"));
pos = m_stdoutFile->pos();
Utils::Test::setNextPassword("a");
showCmd.execute({"show", m_dbFile->fileName(), "-q", "/Sample Entry"});
m_stdoutFile->seek(pos);
QCOMPARE(m_stdoutFile->readAll(),
QByteArray("Title: Sample Entry\n"
"UserName: User Name\n"
"Password: PROTECTED\n"
"URL: http://www.somesite.com/\n"
"Notes: Notes\n"));
pos = m_stdoutFile->pos(); pos = m_stdoutFile->pos();
Utils::Test::setNextPassword("a"); Utils::Test::setNextPassword("a");
showCmd.execute({"show", "-a", "Title", m_dbFile->fileName(), "/Sample Entry"}); showCmd.execute({"show", "-a", "Title", m_dbFile->fileName(), "/Sample Entry"});
@ -1704,6 +1716,13 @@ void TestCli::testShow()
m_stdoutFile->readLine(); // skip password prompt m_stdoutFile->readLine(); // skip password prompt
QCOMPARE(m_stdoutFile->readAll(), QByteArray("Sample Entry\n")); QCOMPARE(m_stdoutFile->readAll(), QByteArray("Sample Entry\n"));
pos = m_stdoutFile->pos();
Utils::Test::setNextPassword("a");
showCmd.execute({"show", "-a", "Password", m_dbFile->fileName(), "/Sample Entry"});
m_stdoutFile->seek(pos);
m_stdoutFile->readLine(); // skip password prompt
QCOMPARE(m_stdoutFile->readAll(), QByteArray("Password\n"));
pos = m_stdoutFile->pos(); pos = m_stdoutFile->pos();
Utils::Test::setNextPassword("a"); Utils::Test::setNextPassword("a");
showCmd.execute({"show", "-a", "Title", "-a", "URL", m_dbFile->fileName(), "/Sample Entry"}); showCmd.execute({"show", "-a", "Title", "-a", "URL", m_dbFile->fileName(), "/Sample Entry"});

View File

@ -111,7 +111,7 @@ void TestCsvParser::testEmptySimple()
out << ""; out << "";
QVERIFY(parser->parse(file.data())); QVERIFY(parser->parse(file.data()));
t = parser->getCsvTable(); t = parser->getCsvTable();
QVERIFY(t.size() == 0); QVERIFY(t.isEmpty());
} }
void TestCsvParser::testEmptyQuoted() void TestCsvParser::testEmptyQuoted()
@ -120,7 +120,7 @@ void TestCsvParser::testEmptyQuoted()
out << "\"\""; out << "\"\"";
QVERIFY(parser->parse(file.data())); QVERIFY(parser->parse(file.data()));
t = parser->getCsvTable(); t = parser->getCsvTable();
QVERIFY(t.size() == 0); QVERIFY(t.isEmpty());
} }
void TestCsvParser::testEmptyNewline() void TestCsvParser::testEmptyNewline()
@ -129,14 +129,14 @@ void TestCsvParser::testEmptyNewline()
out << "\"\n\""; out << "\"\n\"";
QVERIFY(parser->parse(file.data())); QVERIFY(parser->parse(file.data()));
t = parser->getCsvTable(); t = parser->getCsvTable();
QVERIFY(t.size() == 0); QVERIFY(t.isEmpty());
} }
void TestCsvParser::testEmptyFile() void TestCsvParser::testEmptyFile()
{ {
QVERIFY(parser->parse(file.data())); QVERIFY(parser->parse(file.data()));
t = parser->getCsvTable(); t = parser->getCsvTable();
QVERIFY(t.size() == 0); QVERIFY(t.isEmpty());
} }
void TestCsvParser::testNewline() void TestCsvParser::testNewline()
@ -281,7 +281,7 @@ void TestCsvParser::testEmptyReparsing()
parser->parse(nullptr); parser->parse(nullptr);
QVERIFY(parser->reparse()); QVERIFY(parser->reparse());
t = parser->getCsvTable(); t = parser->getCsvTable();
QVERIFY(t.size() == 0); QVERIFY(t.isEmpty());
} }
void TestCsvParser::testReparsing() void TestCsvParser::testReparsing()

View File

@ -296,7 +296,7 @@ void TestEntryModel::testProxyModel()
QSignalSpy spyColumnRemove(modelProxy, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int))); QSignalSpy spyColumnRemove(modelProxy, SIGNAL(columnsAboutToBeRemoved(QModelIndex, int, int)));
modelProxy->hideColumn(0, true); modelProxy->hideColumn(0, true);
QCOMPARE(modelProxy->columnCount(), 12); QCOMPARE(modelProxy->columnCount(), 12);
QVERIFY(spyColumnRemove.size() >= 1); QVERIFY(!spyColumnRemove.isEmpty());
int oldSpyColumnRemoveSize = spyColumnRemove.size(); int oldSpyColumnRemoveSize = spyColumnRemove.size();
modelProxy->hideColumn(0, true); modelProxy->hideColumn(0, true);
@ -318,7 +318,7 @@ void TestEntryModel::testProxyModel()
QSignalSpy spyColumnInsert(modelProxy, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int))); QSignalSpy spyColumnInsert(modelProxy, SIGNAL(columnsAboutToBeInserted(QModelIndex, int, int)));
modelProxy->hideColumn(0, false); modelProxy->hideColumn(0, false);
QCOMPARE(modelProxy->columnCount(), 13); QCOMPARE(modelProxy->columnCount(), 13);
QVERIFY(spyColumnInsert.size() >= 1); QVERIFY(!spyColumnInsert.isEmpty());
int oldSpyColumnInsertSize = spyColumnInsert.size(); int oldSpyColumnInsertSize = spyColumnInsert.size();
modelProxy->hideColumn(0, false); modelProxy->hideColumn(0, false);

View File

@ -1070,7 +1070,7 @@ void TestGroup::testHierarchy()
QVERIFY(hierarchy.contains("group3")); QVERIFY(hierarchy.contains("group3"));
hierarchy = group3->hierarchy(0); hierarchy = group3->hierarchy(0);
QVERIFY(hierarchy.size() == 0); QVERIFY(hierarchy.isEmpty());
hierarchy = group3->hierarchy(1); hierarchy = group3->hierarchy(1);
QVERIFY(hierarchy.size() == 1); QVERIFY(hierarchy.size() == 1);

View File

@ -16,5 +16,8 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
add_unit_test(NAME testgui SOURCES TestGui.cpp ../util/TemporaryFile.cpp LIBS ${TEST_LIBRARIES}) add_unit_test(NAME testgui SOURCES TestGui.cpp ../util/TemporaryFile.cpp LIBS ${TEST_LIBRARIES})
add_unit_test(NAME testguibrowser SOURCES TestGuiBrowser.cpp ../util/TemporaryFile.cpp LIBS ${TEST_LIBRARIES})
add_unit_test(NAME testguipixmaps SOURCES TestGuiPixmaps.cpp LIBS ${TEST_LIBRARIES}) add_unit_test(NAME testguipixmaps SOURCES TestGuiPixmaps.cpp LIBS ${TEST_LIBRARIES})
if(WITH_XC_BROWSER)
add_unit_test(NAME testguibrowser SOURCES TestGuiBrowser.cpp ../util/TemporaryFile.cpp LIBS ${TEST_LIBRARIES})
endif()