tageditor/gui/mainwindow.cpp

588 lines
22 KiB
C++
Raw Permalink Normal View History

2015-09-06 20:20:00 +02:00
#include "./mainwindow.h"
2016-03-03 22:21:15 +01:00
#include "./dbquerywidget.h"
2018-03-07 01:18:01 +01:00
#include "./renamefilesdialog.h"
#include "./settingsdialog.h"
#include "./tageditorwidget.h"
2015-04-22 19:33:53 +02:00
2015-09-06 20:20:00 +02:00
#include "../application/settings.h"
#include "../misc/htmlinfo.h"
2018-03-07 01:18:01 +01:00
#include "../misc/utility.h"
2015-09-06 15:41:17 +02:00
2015-12-05 22:55:05 +01:00
#include "ui_mainwindow.h"
2015-04-22 19:33:53 +02:00
#include "resources/config.h"
#include <tagparser/mediafileinfo.h>
2015-04-22 19:33:53 +02:00
#include <qtutilities/aboutdialog/aboutdialog.h>
2018-03-07 01:18:01 +01:00
#include <qtutilities/misc/conversion.h>
2016-02-05 20:24:03 +01:00
#include <qtutilities/misc/desktoputils.h>
2018-03-07 01:18:01 +01:00
#include <qtutilities/misc/dialogutils.h>
2016-03-10 22:13:43 +01:00
#include <qtutilities/misc/trylocker.h>
2016-02-05 20:24:03 +01:00
#include <c++utilities/conversion/stringconversion.h>
#include <c++utilities/io/path.h>
2015-04-22 19:33:53 +02:00
#include <QCoreApplication>
2015-04-22 19:33:53 +02:00
#include <QFileDialog>
#include <QFileSystemModel>
2018-03-07 01:18:01 +01:00
#include <QMessageBox>
2015-04-22 19:33:53 +02:00
#include <iomanip>
using namespace std;
using namespace Utility;
2019-06-10 22:49:46 +02:00
using namespace QtUtilities;
2018-03-06 23:10:13 +01:00
using namespace TagParser;
2015-04-22 19:33:53 +02:00
namespace QtGui {
2015-07-08 00:21:21 +02:00
/*!
* \brief The LoadingResult enum specifies whether the file could be parsed.
*/
2018-03-07 01:18:01 +01:00
enum LoadingResult : char { ParsingSuccessful, FatalParsingError, IoError };
2015-07-08 00:21:21 +02:00
2015-04-22 19:33:53 +02:00
/*!
* \class QtGui::MainWindow
* \brief The MainWindow class provides the main window of the Tag Editor's Qt GUI.
2015-04-22 19:33:53 +02:00
*/
/*!
* \brief Shortcut to access file operation mutex of TagEditorWidget.
*/
bool MainWindow::fileOperationOngoing() const
{
return m_ui->tagEditorWidget->isFileOperationOngoing();
}
/*!
* \brief Shortcut to access MediaFileInfo of TagEditorWidget.
*/
MediaFileInfo &MainWindow::fileInfo()
{
return m_ui->tagEditorWidget->fileInfo();
}
2015-04-22 19:33:53 +02:00
/*!
* \brief Constructs a new main window.
*/
2018-03-07 01:18:01 +01:00
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent, Qt::Window)
, m_ui(new Ui::MainWindow())
, m_internalFileSelection(false)
, m_aboutDlg(nullptr)
, m_settingsDlg(nullptr)
, m_dbQueryWidget(nullptr)
2015-04-22 19:33:53 +02:00
{
// setup UI
2015-04-22 19:33:53 +02:00
m_ui->setupUi(this);
2023-03-26 22:19:27 +02:00
updateStyleSheet();
2016-03-03 22:21:15 +01:00
2015-04-22 19:33:53 +02:00
// restore geometry and state
2016-10-24 20:15:10 +02:00
const auto &settings = Settings::values();
restoreGeometry(settings.mainWindow.geometry);
restoreState(settings.mainWindow.state);
2016-03-03 22:21:15 +01:00
2015-04-22 19:33:53 +02:00
// setup file model and file tree view
m_fileModel = new QFileSystemModel(this);
m_fileModel->setRootPath(QString());
m_fileFilterModel = new FileFilterProxyModel(this);
2016-01-25 19:23:33 +01:00
m_fileFilterModel->setExtensionsToBeFiltered(QStringList() << QStringLiteral("bak") << QStringLiteral("tmp"));
2015-04-22 19:33:53 +02:00
m_fileFilterModel->setSourceModel(m_fileModel);
2016-10-24 20:15:10 +02:00
m_fileFilterModel->setFilterEnabled(settings.fileBrowser.hideBackupFiles);
2015-04-22 19:33:53 +02:00
m_ui->filesTreeView->sortByColumn(0, Qt::AscendingOrder);
m_ui->filesTreeView->setModel(m_fileFilterModel);
m_ui->filesTreeView->setColumnWidth(0, 300);
2016-03-03 22:21:15 +01:00
2015-04-22 19:33:53 +02:00
// setup path line edit
m_ui->pathLineEdit->setCompletionModel(m_fileModel);
2016-03-03 22:21:15 +01:00
// apply initial file status
handleFileStatusChange(false, false);
2016-03-03 22:21:15 +01:00
// dbquery dock widget
2018-03-07 01:18:01 +01:00
if (settings.dbQuery.widgetShown) {
2016-12-01 22:23:01 +01:00
initDbQueryWidget();
2016-03-03 22:21:15 +01:00
}
2016-09-25 23:59:04 +02:00
// restore locked
2016-10-24 20:15:10 +02:00
setLayoutLocked(settings.mainWindow.layoutLocked);
2016-09-25 23:59:04 +02:00
2015-05-05 23:08:49 +02:00
// connect signals and slots, install event filter
2015-04-22 19:33:53 +02:00
// menu: application
2020-11-25 18:14:40 +01:00
connect(m_ui->actionNew_window, &QAction::triggered, this, &MainWindow::showNewWindow);
2015-04-22 19:33:53 +02:00
connect(m_ui->actionSettings, &QAction::triggered, this, &MainWindow::showSettingsDlg);
connect(m_ui->actionOpen_MusicBrainz_search, &QAction::triggered, this, &MainWindow::toggleDbQueryWidget);
2016-09-25 23:59:04 +02:00
connect(m_ui->lockLayout, &QAction::triggered, this, &MainWindow::toggleLayoutLocked);
2015-04-22 19:33:53 +02:00
connect(m_ui->actionQuit, &QAction::triggered, this, &MainWindow::close);
// menu: file
connect(m_ui->actionOpen, &QAction::triggered, this, &MainWindow::showOpenFileDlg);
connect(m_ui->actionSave, &QAction::triggered, m_ui->tagEditorWidget, &TagEditorWidget::applyEntriesAndSaveChangings);
2016-05-01 20:07:04 +02:00
connect(m_ui->actionSave_as, &QAction::triggered, this, &MainWindow::showSaveAsDlg);
connect(m_ui->actionDelete_all_tags, &QAction::triggered, m_ui->tagEditorWidget, &TagEditorWidget::deleteAllTagsAndSave);
connect(m_ui->actionSave_file_information, &QAction::triggered, m_ui->tagEditorWidget, &TagEditorWidget::saveFileInfo);
connect(m_ui->actionClose, &QAction::triggered, m_ui->tagEditorWidget, &TagEditorWidget::closeFile);
connect(m_ui->actionReload, &QAction::triggered, m_ui->tagEditorWidget, &TagEditorWidget::reparseFile);
2015-10-14 20:15:10 +02:00
connect(m_ui->actionExternalPlayer, &QAction::triggered, this, &MainWindow::spawnExternalPlayer);
2015-04-22 19:33:53 +02:00
// menu: directory
2018-03-07 01:18:01 +01:00
connect(m_ui->actionSelect_next_file, &QAction::triggered, this, static_cast<void (MainWindow::*)(void)>(&MainWindow::selectNextFile));
connect(m_ui->actionSelect_next_file_and_save_current, &QAction::triggered, m_ui->tagEditorWidget, &TagEditorWidget::saveAndShowNextFile);
2015-04-22 19:33:53 +02:00
connect(m_ui->actionRename_files, &QAction::triggered, this, &MainWindow::showRenameFilesDlg);
// menu: help
connect(m_ui->actionAbout, &QAction::triggered, this, &MainWindow::showAboutDlg);
// tag editor widget
2018-03-07 01:18:01 +01:00
connect(m_ui->tagEditorWidget, &TagEditorWidget::nextFileSelected, this, static_cast<void (MainWindow::*)(void)>(&MainWindow::selectNextFile));
connect(m_ui->tagEditorWidget, &TagEditorWidget::fileStatusChanged, this, &MainWindow::handleFileStatusChange);
connect(m_ui->tagEditorWidget, &TagEditorWidget::statusMessage, m_ui->statusBar, &QStatusBar::showMessage);
connect(m_ui->tagEditorWidget, &TagEditorWidget::currentPathChanged, this, &MainWindow::handleCurrentPathChanged);
2015-04-22 19:33:53 +02:00
// misc
connect(m_ui->pathLineEdit, &QLineEdit::textEdited, this, &MainWindow::pathEntered);
connect(m_ui->filesTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::fileSelected);
2018-03-07 01:18:01 +01:00
connect(
m_ui->selectNextCommandLinkButton, &QCommandLinkButton::clicked, this, static_cast<void (MainWindow::*)(void)>(&MainWindow::selectNextFile));
2015-04-22 19:33:53 +02:00
// apply settings
2016-10-24 20:15:10 +02:00
setCurrentDirectory(settings.mainWindow.currentFileBrowserDirectory);
2015-04-22 19:33:53 +02:00
applySettingsFromDialog();
}
/*!
* \brief Destroys the main window.
*/
MainWindow::~MainWindow()
2018-03-07 01:18:01 +01:00
{
}
2015-04-22 19:33:53 +02:00
/*!
* \brief Returns directory the file browser is currently showning.
*/
2016-09-25 23:59:04 +02:00
QString MainWindow::currentDirectory() const
2015-04-22 19:33:53 +02:00
{
return m_ui->pathLineEdit->text();
}
/*!
* \brief Sets the directory the file browser is showing.
2023-05-06 19:30:11 +02:00
* If a file is specified the file will be opened.
2015-04-22 19:33:53 +02:00
*/
void MainWindow::setCurrentDirectory(const QString &path)
{
m_ui->pathLineEdit->editText(path);
}
2016-09-25 23:59:04 +02:00
/*!
* \brief Returns whether the layout is \a locked.
*/
bool MainWindow::isLayoutLocked() const
{
return m_ui->fileSelectionDockWidget->features() == QDockWidget::NoDockWidgetFeatures;
}
/*!
* \brief Sets whether the layout is \a locked.
*/
void MainWindow::setLayoutLocked(bool locked)
{
// lock layout if not already locked
const auto change = locked != isLayoutLocked();
if (locked) {
if (!change) {
return;
2016-09-25 23:59:04 +02:00
}
m_ui->fileSelectionDockWidget->setFeatures(QDockWidget::NoDockWidgetFeatures);
m_ui->dbQueryDockWidget->setFeatures(QDockWidget::NoDockWidgetFeatures);
m_ui->lockLayout->setText(tr("Unlock layout"));
m_ui->lockLayout->setIcon(QIcon::fromTheme(QStringLiteral("unlock")));
return;
}
// unlock layout using different features depending on the platform
#if defined(Q_OS_WINDOWS) || defined(Q_OS_MAC)
constexpr auto features = QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable;
#else
auto features = static_cast<QDockWidget::DockWidgetFeatures>(QDockWidget::DockWidgetMovable);
if (QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) {
// enable floating windows only on non-Wayland platforms as one can never put a floating window back under Wayland
features |= QDockWidget::DockWidgetFloatable;
} else {
// ensure currently floating windows (e.g. from the last X11 session) aren't floating anymore under Wayland
m_ui->fileSelectionDockWidget->setFloating(false);
m_ui->dbQueryDockWidget->setFloating(false);
}
#endif
m_ui->fileSelectionDockWidget->setFeatures(features);
m_ui->dbQueryDockWidget->setFeatures(features | QDockWidget::DockWidgetClosable);
if (change) {
m_ui->lockLayout->setText(tr("Lock layout"));
m_ui->lockLayout->setIcon(QIcon::fromTheme(QStringLiteral("lock")));
2016-09-25 23:59:04 +02:00
}
}
void MainWindow::toggleLayoutLocked()
{
setLayoutLocked(!isLayoutLocked());
}
/*!
* \brief Starts parsing the specified file.
*/
void MainWindow::startParsing(const QString &path)
{
m_ui->tagEditorWidget->startParsing(path, true);
}
2015-04-22 19:33:53 +02:00
/*!
* \brief
* - Saves the applications settings relating the state of the main window.
* - Updates the info webview when the palette changed.
2015-04-22 19:33:53 +02:00
*/
bool MainWindow::event(QEvent *event)
2015-04-22 19:33:53 +02:00
{
2016-10-24 20:15:10 +02:00
auto &settings = Settings::values();
2018-03-07 01:18:01 +01:00
switch (event->type()) {
2023-03-26 22:19:27 +02:00
case QEvent::PaletteChange:
updateStyleSheet();
break;
case QEvent::Close:
if (m_ui->tagEditorWidget->isFileOperationOngoing()) {
event->ignore();
static const auto warning(tr("Unable to close while the file operation is still ongoing."));
QMessageBox::warning(this, QCoreApplication::applicationName(), warning);
return true;
}
// save settings
2016-10-24 20:15:10 +02:00
settings.mainWindow.geometry = saveGeometry();
settings.mainWindow.state = saveState();
settings.mainWindow.currentFileBrowserDirectory = currentDirectory();
settings.mainWindow.layoutLocked = isLayoutLocked();
settings.dbQuery.widgetShown = m_ui->dbQueryDockWidget->isVisible();
break;
2018-03-07 01:18:01 +01:00
default:;
}
return QMainWindow::event(event);
2015-04-22 19:33:53 +02:00
}
/*!
* \brief This private slot is called when the entered text of m_ui->pathLineEdit which represents the current directory changes.
2016-02-05 20:24:03 +01:00
*
2015-04-22 19:33:53 +02:00
* If the text is a valid path the current index of the m_ui->filesTreeView is updated to show the path. This invokes the file
* selected slot.
*/
void MainWindow::pathEntered()
{
const QString path = m_ui->pathLineEdit->text();
2018-03-07 01:18:01 +01:00
if (!path.isEmpty()) {
const QModelIndex index = m_fileFilterModel->mapFromSource(m_fileModel->index(path));
2018-03-07 01:18:01 +01:00
if (index.isValid()) {
2015-04-22 19:33:53 +02:00
m_ui->filesTreeView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect);
2016-02-05 20:24:03 +01:00
m_ui->pathLineEdit->setProperty("classNames", QStringList());
2015-04-22 19:33:53 +02:00
} else {
2018-05-26 22:43:35 +02:00
m_ui->pathLineEdit->setProperty("classNames", QStringList({ QStringLiteral("input-invalid") }));
2015-04-22 19:33:53 +02:00
}
2016-02-05 20:24:03 +01:00
updateStyle(m_ui->pathLineEdit);
2015-04-22 19:33:53 +02:00
}
}
/*!
* \brief This private slot is called when the selected file or directory changes.
*
2015-04-22 19:33:53 +02:00
* If a directory is selected the m_ui->pathLineEdit will be updated.
* If a file is selected it will be opened.
*/
void MainWindow::fileSelected()
{
if (m_internalFileSelection) {
return;
}
const QModelIndexList selectedIndexes = m_ui->filesTreeView->selectionModel()->selectedRows();
if (selectedIndexes.count() != 1) {
return;
}
const QString path(m_fileModel->filePath(m_fileFilterModel->mapToSource(selectedIndexes.at(0))));
const QFileInfo fileInfo(path);
if (fileInfo.isFile()) {
startParsing(path);
m_ui->pathLineEdit->setText(fileInfo.dir().path());
} else if (fileInfo.isDir()) {
m_ui->pathLineEdit->setText(path);
2015-04-22 19:33:53 +02:00
}
m_ui->pathLineEdit->setProperty("classNames", QStringList());
updateStyle(m_ui->pathLineEdit);
2015-04-22 19:33:53 +02:00
}
/*!
* \brief Updates the status of the relevant widgets (enabled/disabled, visible/hidden) according to the
* current "file status" (opened/closed, has tags/no tags).
*/
void MainWindow::handleFileStatusChange(bool opened, bool hasTag)
2015-04-22 19:33:53 +02:00
{
// actions to save, delete, close
2015-04-22 19:33:53 +02:00
m_ui->actionSave->setEnabled(opened);
m_ui->actionDelete_all_tags->setEnabled(hasTag);
m_ui->actionSave_file_information->setEnabled(opened);
2016-05-01 20:07:04 +02:00
m_ui->actionSave_as->setEnabled(opened);
2015-04-22 19:33:53 +02:00
m_ui->actionClose->setEnabled(opened);
m_ui->actionReload->setEnabled(opened);
2015-10-14 20:15:10 +02:00
m_ui->actionExternalPlayer->setEnabled(opened);
2015-07-07 00:46:43 +02:00
// window title
2019-06-10 22:49:46 +02:00
setWindowTitle(generateWindowTitle(opened ? DocumentStatus::Saved : DocumentStatus::NoDocument, m_ui->tagEditorWidget->currentPath()));
2015-04-22 19:33:53 +02:00
}
/*!
* \brief Handles that the current path has changed by the tag editor widget itself.
*/
2016-08-14 22:49:47 +02:00
void MainWindow::handleCurrentPathChanged(const QString &newPath)
2015-04-22 19:33:53 +02:00
{
// ensure the current file is still selected
m_internalFileSelection = true;
2016-08-14 22:49:47 +02:00
const QModelIndex index = m_fileFilterModel->mapFromSource(m_fileModel->index(newPath));
2018-03-07 01:18:01 +01:00
if (index.isValid()) {
m_ui->filesTreeView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect);
2016-08-14 22:49:47 +02:00
m_ui->pathLineEdit->setText(QFileInfo(newPath).dir().path());
m_ui->pathLineEdit->setProperty("classNames", QStringList());
updateStyle(m_ui->pathLineEdit);
2015-04-22 19:33:53 +02:00
}
m_internalFileSelection = false;
// ensure this is the active window
activateWindow();
}
2023-03-26 22:19:27 +02:00
/*!
* \brief Updates the style sheet.
*/
void MainWindow::updateStyleSheet()
{
#ifdef Q_OS_WINDOWS
setStyleSheet(dialogStyleForPalette(palette()) + QStringLiteral("#tagEditorWidget { color: palette(text); background-color: palette(base); }"));
#else
setStyleSheet(dialogStyleForPalette(palette()));
#endif
}
2015-10-14 20:15:10 +02:00
/*!
* \brief Spawns an external player for the current file.
*/
void MainWindow::spawnExternalPlayer()
{
const QString &currentPath = m_ui->tagEditorWidget->currentPath();
2018-03-07 01:18:01 +01:00
if (!currentPath.isEmpty()) {
2019-06-10 22:49:46 +02:00
openLocalFileOrDir(currentPath);
2015-10-14 20:15:10 +02:00
} else {
m_ui->statusBar->showMessage(tr("No file opened."));
}
}
2016-03-03 22:21:15 +01:00
/*!
2016-12-01 22:23:01 +01:00
* \brief Initializes m_dbQueryWidget is not already initialized.
2016-03-03 22:21:15 +01:00
*/
2016-12-01 22:23:01 +01:00
void MainWindow::initDbQueryWidget()
2016-03-03 22:21:15 +01:00
{
2018-03-07 01:18:01 +01:00
if (!m_dbQueryWidget) {
2016-03-03 22:21:15 +01:00
m_ui->dbQueryDockWidget->setWidget(m_dbQueryWidget = new DbQueryWidget(m_ui->tagEditorWidget, this));
2018-03-07 01:18:01 +01:00
connect(m_ui->tagEditorWidget, &TagEditorWidget::tagValuesLoaded, m_dbQueryWidget,
static_cast<void (DbQueryWidget::*)(void)>(&DbQueryWidget::autoInsertMatchingResults), Qt::DirectConnection);
2016-03-03 22:21:15 +01:00
}
2016-12-01 22:23:01 +01:00
}
/*!
* \brief Toggles visibility of the database query widget.
*/
void MainWindow::toggleDbQueryWidget()
{
initDbQueryWidget();
m_ui->dbQueryDockWidget->setVisible(m_ui->dbQueryDockWidget->isHidden());
2016-03-03 22:21:15 +01:00
}
2015-04-22 19:33:53 +02:00
/*!
* \brief Shows the about dialog.
*/
void MainWindow::showAboutDlg()
{
2018-03-07 01:18:01 +01:00
if (!m_aboutDlg) {
m_aboutDlg = new AboutDialog(this, QString(),
QStringLiteral("<p>Developed by " APP_AUTHOR
2022-12-10 12:04:33 +01:00
"<br>Program icon based on icons from <a href=\"https://invent.kde.org/frameworks/breeze-icons\">KDE/Breeze</a> "
"project (copyright © 2014 Uri Herrera <uri_herrera@nitrux.in> and others, see the according "
2022-09-10 16:29:32 +02:00
"<a href=\"" APP_URL "/blob/master/LICENSE.LESSER\">LGPL-3.0 license</a>)"
"<br>Fallback icons from KDE/Breeze as well</p>"),
QString(), QString(), tr("A tag editing utility supporting ID3, MP4 (iTunes style), Vorbis and Matroska tags."),
2018-03-07 01:18:01 +01:00
QImage(QStringLiteral(":/tageditor/icons/hicolor/128x128/apps/tageditor.png")));
2015-04-22 19:33:53 +02:00
}
2018-03-07 01:18:01 +01:00
if (m_aboutDlg->isHidden()) {
2015-04-22 19:33:53 +02:00
m_aboutDlg->show();
} else {
m_aboutDlg->activateWindow();
}
}
2020-11-25 18:14:40 +01:00
/*!
* \brief MainWindow::showNewWindow
*/
void MainWindow::showNewWindow()
{
auto *const newWindow = new MainWindow;
newWindow->setAttribute(Qt::WA_DeleteOnClose);
newWindow->show();
}
2015-04-22 19:33:53 +02:00
/*!
* \brief Shows the settings dialog (modal).
*/
void MainWindow::showSettingsDlg()
{
2018-03-07 01:18:01 +01:00
if (!m_settingsDlg) {
2015-04-22 19:33:53 +02:00
m_settingsDlg = new SettingsDialog(this);
2016-05-26 02:15:41 +02:00
connect(m_settingsDlg, &SettingsDialog::applied, this, &MainWindow::applySettingsFromDialog);
connect(m_settingsDlg, &SettingsDialog::applied, m_ui->tagEditorWidget, &TagEditorWidget::applySettingsFromDialog);
2015-04-22 19:33:53 +02:00
}
2016-05-26 02:15:41 +02:00
m_settingsDlg->exec();
2015-04-22 19:33:53 +02:00
}
/*!
* \brief Shows the "Rename files" dialog (instance of RenameFilesDialog).
*/
void MainWindow::showRenameFilesDlg()
{
2018-03-07 01:18:01 +01:00
if (!m_renameFilesDlg) {
2015-04-22 19:33:53 +02:00
m_renameFilesDlg.reset(new RenameFilesDialog);
}
m_renameFilesDlg->setDirectory(currentDirectory());
2018-03-07 01:18:01 +01:00
if (m_renameFilesDlg->isHidden()) {
2015-04-22 19:33:53 +02:00
m_renameFilesDlg->show();
} else {
m_renameFilesDlg->activateWindow();
}
}
/*!
* \brief Selects the next file.
* \remarks Does nothing if there is currently no file selected.
2015-04-22 19:33:53 +02:00
*/
void MainWindow::selectNextFile()
{
QItemSelectionModel *selectionModel = m_ui->filesTreeView->selectionModel();
2016-06-14 00:52:03 +02:00
const QModelIndexList selectedIndexes = selectionModel->selectedIndexes();
2018-03-07 01:18:01 +01:00
if (!selectedIndexes.isEmpty()) {
selectNextFile(selectionModel, selectedIndexes.at(0), false);
}
}
/*!
* \brief Selects the file next to the file with the specified index.
*
* If \a notDeeper is false, this method will not try to go deeper into
* the file system tree.
*/
void MainWindow::selectNextFile(QItemSelectionModel *selectionModel, const QModelIndex &currentIndex, bool notDeeper)
{
QModelIndex next;
2018-03-07 01:18:01 +01:00
if (!notDeeper && selectionModel->model()->hasChildren(currentIndex)) {
// a directory is selected -> go deeper
2018-03-07 01:18:01 +01:00
if (m_fileFilterModel->canFetchMore(currentIndex)) {
// files and subdirectories have to be fetched
2016-06-14 00:52:03 +02:00
// -> QFileSystemModel seems to fetch files and directories async
// -> hence fetchMore will return immediately
// -> select next file when rowsInserted is emitted
auto conn = make_shared<QMetaObject::Connection>();
2018-03-07 01:18:01 +01:00
*conn = connect(m_fileFilterModel, &QAbstractItemModel::rowsInserted,
[this, selectionModel, currentIndex, conn](const QModelIndex &parent, int, int) {
disconnect(*conn);
if (parent == currentIndex) {
2021-03-20 21:59:49 +01:00
const QModelIndex nextFetched = m_fileFilterModel->index(0, 0, parent);
if (nextFetched.isValid()) {
if (m_ui->filesTreeView->model()->hasChildren(nextFetched)) {
2018-03-07 01:18:01 +01:00
// next item is a directory -> keep on searching
2021-03-20 21:59:49 +01:00
selectNextFile(selectionModel, nextFetched, false);
2018-03-07 01:18:01 +01:00
} else {
m_ui->filesTreeView->selectionModel()->setCurrentIndex(
2021-03-20 21:59:49 +01:00
nextFetched, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
2018-03-07 01:18:01 +01:00
}
2016-03-03 22:21:15 +01:00
} else {
2018-03-07 01:18:01 +01:00
selectNextFile(selectionModel, currentIndex, true);
2016-03-03 22:21:15 +01:00
}
2015-04-22 19:33:53 +02:00
}
2018-03-07 01:18:01 +01:00
});
m_fileModel->fetchMore(m_fileFilterModel->mapToSource(currentIndex));
return;
} else {
// files and subdirectories have been fetched already
2019-05-04 22:17:28 +02:00
next = currentIndex.model()->index(0, currentIndex.column(), currentIndex);
2015-04-22 19:33:53 +02:00
}
}
2018-03-07 01:18:01 +01:00
if (!next.isValid()) {
// not possible to go deeper -> choose next sibling
next = currentIndex.sibling(currentIndex.row() + 1, currentIndex.column());
}
2018-03-07 01:18:01 +01:00
if (!next.isValid()) {
// not possible to choose next sibling -> go higher
const QModelIndex parent = currentIndex.parent();
2018-03-07 01:18:01 +01:00
if (parent.isValid()) {
selectNextFile(selectionModel, parent, true);
return;
2015-04-22 19:33:53 +02:00
}
}
2018-03-07 01:18:01 +01:00
if (next.isValid()) {
if (selectionModel->model()->hasChildren(next)) {
2016-03-03 22:21:15 +01:00
// next item is a directory -> keep on searching
selectNextFile(selectionModel, next, false);
} else {
selectionModel->setCurrentIndex(next, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
}
} else {
showNextFileNotFound();
}
}
void MainWindow::showNextFileNotFound()
{
static const QString errormsg(tr("Unable to show the next file because it can't be found anymore."));
2018-05-26 22:43:35 +02:00
QMessageBox::warning(this, QCoreApplication::applicationName(), errormsg);
m_ui->statusBar->showMessage(errormsg);
2015-04-22 19:33:53 +02:00
}
/*!
* \brief Shows an open file dialog and opens the selected file.
*/
void MainWindow::showOpenFileDlg()
{
2016-05-01 20:07:04 +02:00
const QString path = QFileDialog::getOpenFileName(this, tr("Open file - ") + QCoreApplication::applicationName());
2018-03-07 01:18:01 +01:00
if (!path.isEmpty()) {
2015-07-08 00:21:21 +02:00
startParsing(path);
2015-04-22 19:33:53 +02:00
}
}
2016-05-01 20:07:04 +02:00
/*!
* \brief Shows an save file dialog and triggers saving the changes under the selected location.
*/
void MainWindow::showSaveAsDlg()
{
2018-03-07 01:18:01 +01:00
const QString path
= QFileDialog::getSaveFileName(this, tr("Save changes as - ") + QCoreApplication::applicationName(), m_ui->tagEditorWidget->currentDir());
if (!path.isEmpty()) {
2021-04-23 22:18:30 +02:00
m_ui->tagEditorWidget->fileInfo().setSaveFilePath(std::string(toNativeFileName(path).data()));
2016-05-01 20:07:04 +02:00
m_ui->tagEditorWidget->applyEntriesAndSaveChangings();
}
}
2015-04-22 19:33:53 +02:00
/*!
* \brief Applies settings from Settings namespace. Only settings configurable through the SettingsDialog
* will be applied and not settings like the main window's geometry and state.
*/
void MainWindow::applySettingsFromDialog()
{
2016-10-24 20:15:10 +02:00
auto &settings = Settings::values();
2018-03-07 01:18:01 +01:00
if (m_fileFilterModel->isFilterEnabled() != settings.fileBrowser.hideBackupFiles) {
2015-04-22 19:33:53 +02:00
// check this condition to avoid unnecessary model reset
2016-10-24 20:15:10 +02:00
m_fileFilterModel->setFilterEnabled(settings.fileBrowser.hideBackupFiles);
2016-01-25 19:23:33 +01:00
const QModelIndex index = m_fileFilterModel->mapFromSource(m_fileModel->index(m_ui->pathLineEdit->text()));
2018-03-07 01:18:01 +01:00
if (index.isValid()) {
2015-04-22 19:33:53 +02:00
m_ui->filesTreeView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select);
}
}
2018-03-07 01:18:01 +01:00
if (m_fileModel->isReadOnly() != settings.fileBrowser.readOnly) {
2016-10-24 20:15:10 +02:00
m_fileModel->setReadOnly(settings.fileBrowser.readOnly);
2015-04-22 19:33:53 +02:00
}
}
2018-03-07 01:18:01 +01:00
} // namespace QtGui