/* * Copyright (C) 2017 KeePassXC Team * Copyright (C) 2011 Felix Geyer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 or (at your option) * version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "FilePath.h" #include #include #include #include #include "config-keepassx.h" #include "core/Config.h" #include "core/Global.h" #include "gui/MainWindow.h" FilePath* FilePath::m_instance(nullptr); QString FilePath::dataPath(const QString& name) { if (name.isEmpty() || name.startsWith('/')) { return m_dataPath + name; } else { return m_dataPath + "/" + name; } } QString FilePath::pluginPath(const QString& name) { QStringList pluginPaths; QDir buildDir(QCoreApplication::applicationDirPath() + "/autotype"); const QStringList buildDirEntryList = buildDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); for (const QString& dir : buildDirEntryList) { pluginPaths << QCoreApplication::applicationDirPath() + "/autotype/" + dir; } // for TestAutoType pluginPaths << QCoreApplication::applicationDirPath() + "/../src/autotype/test"; #if defined(Q_OS_MACOS) && defined(WITH_APP_BUNDLE) pluginPaths << QCoreApplication::applicationDirPath() + "/../PlugIns"; #endif pluginPaths << QCoreApplication::applicationDirPath(); QString configuredPluginDir = KEEPASSX_PLUGIN_DIR; if (configuredPluginDir != ".") { if (QDir(configuredPluginDir).isAbsolute()) { pluginPaths << configuredPluginDir; } else { QString relativePluginDir = QString("%1/../%2").arg(QCoreApplication::applicationDirPath(), configuredPluginDir); pluginPaths << QDir(relativePluginDir).canonicalPath(); QString absolutePluginDir = QString("%1/%2").arg(KEEPASSX_PREFIX_DIR, configuredPluginDir); pluginPaths << QDir(absolutePluginDir).canonicalPath(); } } QStringList dirFilter; dirFilter << QString("*%1*").arg(name); for (const QString& path : asConst(pluginPaths)) { const QStringList fileCandidates = QDir(path).entryList(dirFilter, QDir::Files); for (const QString& file : fileCandidates) { QString filePath = path + "/" + file; if (QLibrary::isLibrary(filePath)) { return filePath; } } } return QString(); } QString FilePath::wordlistPath(const QString& name) { return dataPath("wordlists/" + name); } QIcon FilePath::applicationIcon() { return icon("apps", "keepassxc", false); } QIcon FilePath::trayIcon() { return useDarkIcon() ? icon("apps", "keepassxc-dark", false) : icon("apps", "keepassxc", false); } QIcon FilePath::trayIconLocked() { return icon("apps", "keepassxc-locked", false); } QIcon FilePath::trayIconUnlocked() { return useDarkIcon() ? icon("apps", "keepassxc-dark", false) : icon("apps", "keepassxc-unlocked", false); } QIcon FilePath::icon(const QString& category, const QString& name, bool recolor) { QString combinedName = category + "/" + name; QIcon icon = m_iconCache.value(combinedName); if (!icon.isNull()) { return icon; } if (icon.isNull()) { const QList pngSizes = {16, 22, 24, 32, 48, 64, 128}; QString filename; for (int size : pngSizes) { filename = QString("%1/icons/application/%2x%2/%3.png").arg(m_dataPath, QString::number(size), combinedName); if (QFile::exists(filename)) { icon.addFile(filename, QSize(size, size)); } } filename = QString("%1/icons/application/scalable/%2.svg").arg(m_dataPath, combinedName); if (QFile::exists(filename) && getMainWindow() && recolor) { QPalette palette = getMainWindow()->palette(); QFile f(filename); QIcon scalable(filename); QPixmap pixmap = scalable.pixmap({128, 128}); auto mask = QBitmap::fromImage(pixmap.toImage().createAlphaMask()); pixmap.fill(palette.color(QPalette::WindowText)); pixmap.setMask(mask); icon.addPixmap(pixmap, QIcon::Mode::Normal); pixmap.fill(palette.color(QPalette::HighlightedText)); pixmap.setMask(mask); icon.addPixmap(pixmap, QIcon::Mode::Selected); pixmap.fill(palette.color(QPalette::Disabled, QPalette::WindowText)); pixmap.setMask(mask); icon.addPixmap(pixmap, QIcon::Mode::Disabled); #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) icon.setIsMask(true); #endif } else if (QFile::exists(filename)) { icon.addFile(filename); } } m_iconCache.insert(combinedName, icon); return icon; } QIcon FilePath::onOffIcon(const QString& category, const QString& name, bool recolor) { QString combinedName = category + "/" + name; QString cacheName = "onoff/" + combinedName; QIcon icon = m_iconCache.value(cacheName); if (!icon.isNull()) { return icon; } QIcon on = FilePath::icon(category, name + "-on", recolor); for (const auto& size : on.availableSizes()) { icon.addPixmap(on.pixmap(size, QIcon::Mode::Normal), QIcon::Mode::Normal, QIcon::On); icon.addPixmap(on.pixmap(size, QIcon::Mode::Selected), QIcon::Mode::Selected, QIcon::On); icon.addPixmap(on.pixmap(size, QIcon::Mode::Disabled), QIcon::Mode::Disabled, QIcon::On); } QIcon off = FilePath::icon(category, name + "-off", recolor); for (const auto& size : off.availableSizes()) { icon.addPixmap(off.pixmap(size, QIcon::Mode::Normal), QIcon::Mode::Normal, QIcon::Off); icon.addPixmap(off.pixmap(size, QIcon::Mode::Selected), QIcon::Mode::Selected, QIcon::Off); icon.addPixmap(off.pixmap(size, QIcon::Mode::Disabled), QIcon::Mode::Disabled, QIcon::Off); } m_iconCache.insert(cacheName, icon); return icon; } FilePath::FilePath() { const QString appDirPath = QCoreApplication::applicationDirPath(); bool isDataDirAbsolute = QDir::isAbsolutePath(KEEPASSX_DATA_DIR); Q_UNUSED(isDataDirAbsolute); if (false) { } #ifdef QT_DEBUG else if (testSetDir(QString(KEEPASSX_SOURCE_DIR) + "/share")) { } #endif #if defined(Q_OS_UNIX) && !(defined(Q_OS_MACOS) && defined(WITH_APP_BUNDLE)) else if (isDataDirAbsolute && testSetDir(KEEPASSX_DATA_DIR)) { } else if (!isDataDirAbsolute && testSetDir(QString("%1/../%2").arg(appDirPath, KEEPASSX_DATA_DIR))) { } else if (!isDataDirAbsolute && testSetDir(QString("%1/%2").arg(KEEPASSX_PREFIX_DIR, KEEPASSX_DATA_DIR))) { } #endif #if defined(Q_OS_MACOS) && defined(WITH_APP_BUNDLE) else if (testSetDir(appDirPath + "/../Resources")) { } #endif #ifdef Q_OS_WIN else if (testSetDir(appDirPath + "/share")) { } #endif // Last ditch test when running in the build directory (mainly for travis tests) else if (testSetDir(QString(KEEPASSX_SOURCE_DIR) + "/share")) { } if (m_dataPath.isEmpty()) { qWarning("FilePath::DataPath: can't find data dir"); } else { m_dataPath = QDir::cleanPath(m_dataPath); } } bool FilePath::testSetDir(const QString& dir) { if (QFile::exists(dir + "/icons/database/C00_Password.png")) { m_dataPath = dir; return true; } else { return false; } } bool FilePath::useDarkIcon() { return config()->get("GUI/DarkTrayIcon").toBool(); } FilePath* FilePath::instance() { if (!m_instance) { m_instance = new FilePath(); } return m_instance; }