Skip to content

Commit

Permalink
Ability to disable loading certain file extensions.
Browse files Browse the repository at this point in the history
  • Loading branch information
jdpurcell committed Nov 24, 2023
1 parent 2bb3329 commit 1b26365
Show file tree
Hide file tree
Showing 9 changed files with 208 additions and 45 deletions.
2 changes: 0 additions & 2 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,6 @@ void MainWindow::settingsUpdated()
#ifdef COCOA_LOADED
// titlebaralwaysdark
QVCocoaFunctions::setVibrancy(settingsManager.getBoolean("titlebaralwaysdark"), windowHandle());
// quitonlastwindow
qvApp->setQuitOnLastWindowClosed(settingsManager.getBoolean("quitonlastwindow"));
#endif

//slideshow timer
Expand Down
52 changes: 37 additions & 15 deletions src/qvapplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ QVApplication::QVApplication(int &argc, char **argv) : QApplication(argc, argv)
// Connections
connect(this, &QGuiApplication::commitDataRequest, this, &QVApplication::onCommitDataRequest, Qt::DirectConnection);
connect(this, &QCoreApplication::aboutToQuit, this, &QVApplication::onAboutToQuit);
connect(&settingsManager, &SettingsManager::settingsUpdated, this, &QVApplication::settingsUpdated);
connect(&actionManager, &ActionManager::recentsMenuUpdated, this, &QVApplication::recentsMenuUpdated);
connect(&updateChecker, &UpdateChecker::checkedUpdates, this, &QVApplication::checkedUpdates);

Expand All @@ -25,7 +26,7 @@ QVApplication::QVApplication(int &argc, char **argv) : QApplication(argc, argv)
QIcon::setFallbackSearchPaths(QIcon::fallbackSearchPaths() << "/usr/share/pixmaps");
#endif

defineFilterLists();
settingsUpdated();

// Check for updates
// TODO: move this to after first window show event
Expand Down Expand Up @@ -58,9 +59,6 @@ QVApplication::QVApplication(int &argc, char **argv) : QApplication(argc, argv)
#ifdef COCOA_LOADED
QVCocoaFunctions::setUserDefaults();
#endif
#ifdef Q_OS_MACOS
setQuitOnLastWindowClosed(getSettingsManager().getBoolean("quitonlastwindow"));
#endif

// Block any erroneous icons from showing up on mac and windows
// (this is overridden in some cases)
Expand Down Expand Up @@ -318,48 +316,72 @@ void QVApplication::hideIncompatibleActions()
#endif
}

void QVApplication::settingsUpdated()
{
auto &settingsManager = qvApp->getSettingsManager();

QString disabledFileExtensionsStr = settingsManager.getString("disabledfileextensions");
disabledFileExtensions = Qv::listToSet(!disabledFileExtensionsStr.isEmpty() ? disabledFileExtensionsStr.split(';') : QStringList());

#ifdef Q_OS_MACOS
setQuitOnLastWindowClosed(settingsManager.getBoolean("quitonlastwindow"));
#endif

defineFilterLists();
}

void QVApplication::defineFilterLists()
{
allFileExtensionList.clear();
nameFilterList.clear();
fileExtensionSet.clear();
mimeTypeNameSet.clear();

const auto &byteArrayFormats = QImageReader::supportedImageFormats();

auto filterString = tr("Supported Images") + " (";
filterList.reserve(byteArrayFormats.size()-1);
fileExtensionList.reserve(byteArrayFormats.size()-1);
fileExtensionSet.reserve(byteArrayFormats.size()-1);

const auto addExtension = [&](const QString &extension) {
allFileExtensionList << extension;
if (disabledFileExtensions.contains(extension))
return;
filterString += "*" + extension + " ";
fileExtensionSet << extension;
};

// Build the filterlist, filterstring, and filterregexplist in one loop
// Build extension and filter lists
for (const auto &byteArray : byteArrayFormats)
{
const auto fileExtension = "." + QString::fromUtf8(byteArray);
// Qt 5.15 seems to have added pdf support for QImageReader but it is super broken in qView
if (fileExtension == ".pdf")
continue;

filterList << "*" + fileExtension;
filterString += "*" + fileExtension + " ";
fileExtensionList << fileExtension;
addExtension(fileExtension);

// If we support jpg, we actually support the jfif, jfi, and jpe file extensions too almost certainly.
if (fileExtension == ".jpg")
{
filterList << "*.jpe" << "*.jfi" << "*.jfif";
filterString += "*.jpe *.jfi *.jfif ";
fileExtensionList << ".jpe" << ".jfi" << ".jfif";
addExtension(".jpe");
addExtension(".jfi");
addExtension(".jfif");
}
}
filterString.chop(1);
filterString += ")";

// Build mime type list
const auto &byteArrayMimeTypes = QImageReader::supportedMimeTypes();
mimeTypeNameList.reserve(byteArrayMimeTypes.size()-1);
mimeTypeNameSet.reserve(byteArrayMimeTypes.size()-1);
for (const auto &byteArray : byteArrayMimeTypes)
{
// Qt 5.15 seems to have added pdf support for QImageReader but it is super broken in qView
const QString mime = QString::fromUtf8(byteArray);
if (mime == "application/pdf")
continue;

mimeTypeNameList << mime;
mimeTypeNameSet << mime;
}

// Build name filter list for file dialogs
Expand Down
18 changes: 12 additions & 6 deletions src/qvapplication.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,21 @@ class QVApplication : public QApplication

void hideIncompatibleActions();

void settingsUpdated();

void defineFilterLists();

QMenuBar *getMenuBar() const { return menuBar; }

const QStringList &getFilterList() const { return filterList; }
const QSet<QString> &getDisabledFileExtensions() const { return disabledFileExtensions; }

const QStringList &getAllFileExtensionList() const { return allFileExtensionList; }

const QStringList &getNameFilterList() const { return nameFilterList; }

const QStringList &getFileExtensionList() const { return fileExtensionList; }
const QSet<QString> &getFileExtensionSet() const { return fileExtensionSet; }

const QStringList &getMimeTypeNameList() const { return mimeTypeNameList; }
const QSet<QString> &getMimeTypeNameSet() const { return mimeTypeNameSet; }

const SettingsManager &getSettingsManager() const { return settingsManager; }
SettingsManager &getSettingsManager() { return settingsManager; }
Expand Down Expand Up @@ -120,10 +124,12 @@ protected slots:

QMenuBar *menuBar;

QStringList filterList;
QSet<QString> disabledFileExtensions;

QStringList allFileExtensionList;
QStringList nameFilterList;
QStringList fileExtensionList;
QStringList mimeTypeNameList;
QSet<QString> fileExtensionSet;
QSet<QString> mimeTypeNameSet;

// This order is very important
SettingsManager settingsManager;
Expand Down
18 changes: 6 additions & 12 deletions src/qvimagecore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,30 +248,24 @@ QList<QVImageCore::CompatibleFile> QVImageCore::getCompatibleFiles(const QString
QList<CompatibleFile> fileList;

QMimeDatabase mimeDb;
const auto &extensions = qvApp->getFileExtensionList();
const auto &mimeTypes = qvApp->getMimeTypeNameList();
const auto &extensions = qvApp->getFileExtensionSet();
const auto &disabledExtensions = qvApp->getDisabledFileExtensions();
const auto &mimeTypes = qvApp->getMimeTypeNameSet();

QMimeDatabase::MatchMode mimeMatchMode = allowMimeContentDetection ? QMimeDatabase::MatchDefault : QMimeDatabase::MatchExtension;

const QFileInfoList currentFolder = QDir(dirPath).entryInfoList(QDir::Files | QDir::Hidden, QDir::Unsorted);
for (const QFileInfo &fileInfo : currentFolder)
{
bool matched = false;
const QString absoluteFilePath = fileInfo.absoluteFilePath();
const QString fileName = fileInfo.fileName();
for (const QString &extension : extensions)
{
if (fileName.endsWith(extension, Qt::CaseInsensitive))
{
matched = true;
break;
}
}
const QString suffix = fileInfo.suffix().toLower();
bool matched = !suffix.isEmpty() && extensions.contains("." + suffix);
QString mimeType;
if (!matched || sortMode == Qv::SortMode::Type)
{
mimeType = mimeDb.mimeTypeForFile(absoluteFilePath, mimeMatchMode).name();
matched |= mimeTypes.contains(mimeType);
matched |= mimeTypes.contains(mimeType) && (suffix.isEmpty() || !disabledExtensions.contains("." + suffix));
}
if (matched)
{
Expand Down
13 changes: 13 additions & 0 deletions src/qvnamespace.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#ifndef QVNAMESPACE_H
#define QVNAMESPACE_H

#include <QSet>
#include <QString>

namespace Qv
{
inline constexpr int SessionStateVersion = 1;
Expand Down Expand Up @@ -104,6 +107,16 @@ namespace Qv
WhenOpeningImages = 2
};

inline QSet<QString> listToSet(const QStringList &list)
{
return QSet<QString>{list.begin(), list.end()};
}

inline QStringList setToList(const QSet<QString> &set)
{
return QStringList(set.begin(), set.end());
}

inline bool scrollActionIsSelfCompatible(const ViewportScrollAction action)
{
return
Expand Down
77 changes: 67 additions & 10 deletions src/qvoptionsdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ QVOptionsDialog::QVOptionsDialog(QWidget *parent) :
connect(ui->titlebarComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &QVOptionsDialog::titlebarComboBoxCurrentIndexChanged);
connect(ui->windowResizeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &QVOptionsDialog::windowResizeComboBoxCurrentIndexChanged);
connect(ui->langComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &QVOptionsDialog::languageComboBoxCurrentIndexChanged);
connect(ui->formatsTable, &QTableWidget::itemChanged, this, &QVOptionsDialog::formatsItemChanged);

populateCategories();
populateComboBoxes();
Expand Down Expand Up @@ -92,6 +93,7 @@ QVOptionsDialog::QVOptionsDialog(QWidget *parent) :

syncSettings(false, true);
syncShortcuts();
syncFormats();
updateButtonBox();

isInitialLoad = false;
Expand Down Expand Up @@ -121,6 +123,7 @@ void QVOptionsDialog::modifySetting(QString key, QVariant value)
void QVOptionsDialog::saveSettings()
{
QSettings settings;

settings.beginGroup("options");

const auto keys = transientSettings.keys();
Expand All @@ -130,7 +133,10 @@ void QVOptionsDialog::saveSettings()
settings.setValue(key, value);
}

settings.setValue("disabledfileextensions", Qv::setToList(transientDisabledFileExtensions).join(';'));

settings.endGroup();

settings.beginGroup("shortcuts");

const auto &shortcutsList = qvApp->getShortcutManager().getShortcutsList();
Expand Down Expand Up @@ -406,6 +412,38 @@ void QVOptionsDialog::shortcutCellDoubleClicked(int row, int column)
shortcutDialog->open();
}

void QVOptionsDialog::syncFormats(bool defaults)
{
if (defaults)
transientDisabledFileExtensions.clear();
else
transientDisabledFileExtensions = qvApp->getDisabledFileExtensions();

QStringList extensions = qvApp->getAllFileExtensionList();
extensions.sort(Qt::CaseInsensitive);

isLoadingFormats = true;

ui->formatsTable->setRowCount(extensions.length());

for (int i = 0; i < extensions.length(); i++)
{
const QString &extension = extensions.value(i);
const bool isDisabled = transientDisabledFileExtensions.contains(extension);

auto *extensionItem = new QTableWidgetItem();
extensionItem->setText(extension);
ui->formatsTable->setItem(i, 0, extensionItem);

auto *enabledItem = new QTableWidgetItem();
enabledItem->setCheckState(isDisabled ? Qt::Unchecked : Qt::Checked);
enabledItem->setData(Qt::UserRole, extension);
ui->formatsTable->setItem(i, 1, enabledItem);
}

isLoadingFormats = false;
}

void QVOptionsDialog::buttonBoxClicked(QAbstractButton *button)
{
auto role = ui->buttonBox->buttonRole(button);
Expand All @@ -419,15 +457,16 @@ void QVOptionsDialog::buttonBoxClicked(QAbstractButton *button)
{
syncSettings(true);
syncShortcuts(true);
syncFormats(true);
}
}

void QVOptionsDialog::updateButtonBox()
{
QPushButton *defaultsButton = ui->buttonBox->button(QDialogButtonBox::RestoreDefaults);
QPushButton *applyButton = ui->buttonBox->button(QDialogButtonBox::Apply);
defaultsButton->setEnabled(false);
applyButton->setEnabled(false);
bool anyUnsaved = false;
bool anyNonDefault = false;

// settings
const QList<QString> settingKeys = transientSettings.keys();
Expand All @@ -437,10 +476,8 @@ void QVOptionsDialog::updateButtonBox()
const auto &savedValue = qvApp->getSettingsManager().getSetting(key);
const auto &defaultValue = qvApp->getSettingsManager().getSetting(key, true);

if (transientValue != savedValue)
applyButton->setEnabled(true);
if (transientValue != defaultValue)
defaultsButton->setEnabled(true);
anyUnsaved |= transientValue != savedValue;
anyNonDefault |= transientValue != defaultValue;
}

// shortcuts
Expand All @@ -451,11 +488,16 @@ void QVOptionsDialog::updateButtonBox()
QStringList savedValue = shortcutsList.value(i).shortcuts;
QStringList defaultValue = shortcutsList.value(i).defaultShortcuts;

if (transientValue != savedValue)
applyButton->setEnabled(true);
if (transientValue != defaultValue)
defaultsButton->setEnabled(true);
anyUnsaved |= transientValue != savedValue;
anyNonDefault |= transientValue != defaultValue;
}

// formats
anyUnsaved |= transientDisabledFileExtensions != qvApp->getDisabledFileExtensions();
anyNonDefault |= !transientDisabledFileExtensions.isEmpty();

applyButton->setEnabled(anyUnsaved);
defaultsButton->setEnabled(anyNonDefault);
}

void QVOptionsDialog::bgColorButtonClicked()
Expand Down Expand Up @@ -539,6 +581,7 @@ void QVOptionsDialog::populateCategories()
addItem(u'\ue429', tr("Miscellaneous"));
addItem(u'\ue312', tr("Shortcuts"));
addItem(u'\ue323', tr("Mouse"));
addItem(u'\ue87b', tr("Formats"));
ui->categoryList->setFixedWidth(ui->categoryList->sizeHintForColumn(0) + ui->categoryList->frameWidth() + listRightPadding);
}

Expand Down Expand Up @@ -574,6 +617,20 @@ void QVOptionsDialog::languageComboBoxCurrentIndexChanged(int index)
}
}

void QVOptionsDialog::formatsItemChanged(QTableWidgetItem *item)
{
if (isLoadingFormats)
return;

const QString extension = item->data(Qt::UserRole).toString();
if (item->checkState() == Qt::Unchecked)
transientDisabledFileExtensions.insert(extension);
else
transientDisabledFileExtensions.remove(extension);

updateButtonBox();
}

void QVOptionsDialog::middleButtonModeChanged()
{
const bool isClick = ui->middleButtonModeClickRadioButton->isChecked();
Expand Down
Loading

0 comments on commit 1b26365

Please sign in to comment.