Browse Source

frontend: Adjust missing files dialog

Warchamp7 8 months ago
parent
commit
36e3489d86

+ 6 - 15
frontend/dialogs/OBSMissingFiles.cpp

@@ -25,12 +25,6 @@
 
 #include "moc_OBSMissingFiles.cpp"
 
-// TODO: Fix redefinition error of due to clash with enums defined in importer code.
-enum MissingFilesRole { EntryStateRole = Qt::UserRole, NewPathsToProcessRole };
-
-// TODO: Fix redefinition error of due to clash with enums defined in importer code.
-enum MissingFilesColumn { Source, OriginalPath, NewPath, State, Count };
-
 OBSMissingFiles::OBSMissingFiles(obs_missing_files_t *files, QWidget *parent)
 	: QDialog(parent),
 	  filesModel(new MissingFilesModel),
@@ -41,17 +35,14 @@ OBSMissingFiles::OBSMissingFiles(obs_missing_files_t *files, QWidget *parent)
 	ui->setupUi(this);
 
 	ui->tableView->setModel(filesModel);
-	ui->tableView->setItemDelegateForColumn(MissingFilesColumn::OriginalPath,
-						new MissingFilesPathItemDelegate(false, ""));
 	ui->tableView->setItemDelegateForColumn(MissingFilesColumn::NewPath,
 						new MissingFilesPathItemDelegate(true, ""));
-	ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeMode::Stretch);
-	ui->tableView->horizontalHeader()->setSectionResizeMode(MissingFilesColumn::Source,
-								QHeaderView::ResizeMode::ResizeToContents);
-	ui->tableView->horizontalHeader()->setMaximumSectionSize(width() / 3);
-	ui->tableView->horizontalHeader()->setSectionResizeMode(MissingFilesColumn::State,
-								QHeaderView::ResizeMode::ResizeToContents);
+	ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeMode::ResizeToContents);
+	ui->tableView->horizontalHeader()->setMaximumSectionSize(width() / 4);
+	ui->tableView->horizontalHeader()->setSectionResizeMode(MissingFilesColumn::NewPath,
+								QHeaderView::ResizeMode::Stretch);
 	ui->tableView->setEditTriggers(QAbstractItemView::EditTrigger::CurrentChanged);
+	ui->tableView->setWordWrap(false);
 
 	ui->warningIcon->setPixmap(filesModel->warningIcon.pixmap(QSize(32, 32)));
 
@@ -126,7 +117,7 @@ void OBSMissingFiles::browseFolders()
 
 	if (dir != "") {
 		dir += "/";
-		filesModel->fileCheckLoop(filesModel->files, dir, true);
+		filesModel->findAllFilesInPath(dir, true);
 	}
 }
 

+ 8 - 2
frontend/forms/OBSMissingFiles.ui

@@ -6,10 +6,16 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>666</width>
-    <height>310</height>
+    <width>700</width>
+    <height>320</height>
    </rect>
   </property>
+  <property name="minimumSize">
+   <size>
+    <width>700</width>
+    <height>320</height>
+   </size>
+  </property>
   <property name="windowTitle">
    <string>MissingFiles</string>
   </property>

+ 77 - 43
frontend/utility/MissingFilesModel.cpp

@@ -24,12 +24,6 @@
 
 #include "moc_MissingFilesModel.cpp"
 
-// TODO: Fix redefinition error of due to clash with enums defined in importer code.
-enum MissingFilesRole { EntryStateRole = Qt::UserRole, NewPathsToProcessRole };
-
-// TODO: Fix redefinition error of due to clash with enums defined in importer code.
-enum MissingFilesColumn { Source, OriginalPath, NewPath, State, Count };
-
 MissingFilesModel::MissingFilesModel(QObject *parent) : QAbstractTableModel(parent)
 {
 	QStyle *style = QApplication::style();
@@ -160,86 +154,126 @@ Qt::ItemFlags MissingFilesModel::flags(const QModelIndex &index) const
 	return flags;
 }
 
-void MissingFilesModel::fileCheckLoop(QList<MissingFileEntry> files, QString path, bool skipPrompt)
+void MissingFilesModel::findAllFilesInPath(const QString &path, bool skipPrompt)
+{
+	allFilesFound = false;
+	fileCheckLoop(path, skipPrompt, 0);
+}
+
+void MissingFilesModel::fileCheckLoop(const QString &path, bool skipPrompt, int depth)
 {
-	loop = false;
-	QUrl url = QUrl().fromLocalFile(path);
+	if (allFilesFound) {
+		return;
+	}
+
+	if (files.length() == found()) {
+		allFilesFound = true;
+		return;
+	}
+
+	recursionLevel += 1;
+	QUrl url = QUrl::fromLocalFile(path);
 	QString dir = url.toDisplayString(QUrl::RemoveScheme | QUrl::RemoveFilename | QUrl::PreferLocalFile);
 
 	bool prompted = skipPrompt;
+	int depthWithoutFileMatch = depth + 1;
 
-	for (int i = 0; i < files.length(); i++) {
-		if (files[i].state != MissingFilesState::Missing)
+	int loopIndex = -1;
+	for (const MissingFileEntry &file : files) {
+		loopIndex++;
+
+		if (file.state != MissingFilesState::Missing) {
 			continue;
+		}
 
-		QUrl origFile = QUrl().fromLocalFile(files[i].originalPath);
+		QUrl origFile = QUrl::fromLocalFile(file.originalPath);
 		QString filename = origFile.fileName();
 		QString testFile = dir + filename;
 
 		if (os_file_exists(testFile.toStdString().c_str())) {
+			depthWithoutFileMatch = 0;
+
 			if (!prompted) {
 				QMessageBox::StandardButton button =
 					QMessageBox::question(nullptr, QTStr("MissingFiles.AutoSearch"),
 							      QTStr("MissingFiles.AutoSearchText"));
 
-				if (button == QMessageBox::No)
+				if (button == QMessageBox::No) {
 					break;
+				}
 
 				prompted = true;
 			}
-			QModelIndex in = index(i, MissingFilesColumn::NewPath);
-			setData(in, testFile, 0);
+			QModelIndex in = index(loopIndex, MissingFilesColumn::NewPath);
+			setData(in, testFile, Qt::DisplayRole);
+		}
+	}
+
+	if (depthWithoutFileMatch <= 2) {
+		os_dir_t *folder = os_opendir(dir.toStdString().c_str());
+		struct os_dirent *ent;
+		while ((ent = os_readdir(folder)) != NULL) {
+			if (!ent->directory || *ent->d_name == '.')
+				continue;
+
+			QString directoryPath = dir + QString(ent->d_name) + "/";
+			fileCheckLoop(directoryPath, true, depthWithoutFileMatch);
 		}
+
+		os_closedir(folder);
 	}
-	loop = true;
+	recursionLevel -= 1;
 }
 
 bool MissingFilesModel::setData(const QModelIndex &index, const QVariant &value, int role)
 {
 	bool success = false;
 
+	int row = index.row();
+	QString valueString = value.toString();
+
 	if (role == MissingFilesRole::NewPathsToProcessRole) {
 		QStringList list = value.toStringList();
 
-		int row = index.row() + 1;
-		beginInsertRows(QModelIndex(), row, row);
+		int newRow = row + 1;
+		beginInsertRows(QModelIndex(), newRow, newRow);
 
 		MissingFileEntry entry;
 		entry.originalPath = list[0].replace("\\", "/");
 		entry.source = list[1];
 
-		files.insert(row, entry);
-		row++;
+		files.insert(newRow, entry);
 
 		endInsertRows();
 
 		success = true;
-	} else {
-		QString path = value.toString();
-		if (index.column() == MissingFilesColumn::NewPath) {
-			files[index.row()].newPath = value.toString();
-			QString fileName = QUrl(path).fileName();
-			QString origFileName = QUrl(files[index.row()].originalPath).fileName();
-
-			if (path.isEmpty()) {
-				files[index.row()].state = MissingFilesState::Missing;
-			} else if (path.compare(QTStr("MissingFiles.Clear")) == 0) {
-				files[index.row()].state = MissingFilesState::Cleared;
-			} else if (fileName.compare(origFileName) == 0) {
-				files[index.row()].state = MissingFilesState::Found;
-
-				if (loop)
-					fileCheckLoop(files, path, false);
-			} else {
-				files[index.row()].state = MissingFilesState::Replaced;
-
-				if (loop)
-					fileCheckLoop(files, path, false);
+	} else if (index.column() == MissingFilesColumn::NewPath && files[row].newPath != valueString) {
+		QString path = valueString;
+		files[row].newPath = valueString;
+		QString fileName = QUrl(path).fileName();
+		QString origFileName = QUrl(files[row].originalPath).fileName();
+
+		if (path.isEmpty()) {
+			files[row].state = MissingFilesState::Missing;
+		} else if (path.compare(QTStr("MissingFiles.Clear")) == 0) {
+			files[row].state = MissingFilesState::Cleared;
+		} else if (fileName.compare(origFileName) == 0) {
+			files[row].state = MissingFilesState::Found;
+
+			if (recursionLevel == 0) {
+				findAllFilesInPath(path, false);
 			}
+		} else {
+			files[row].state = MissingFilesState::Replaced;
 
-			emit dataChanged(index, index);
-			success = true;
+			if (recursionLevel == 0) {
+				findAllFilesInPath(path, false);
+			}
 		}
+
+		emit dataChanged(index, index);
+
+		success = true;
 	}
 
 	return success;

+ 10 - 2
frontend/utility/MissingFilesModel.hpp

@@ -20,6 +20,12 @@
 #include <QAbstractTableModel>
 #include <QIcon>
 
+// TODO: Fix redefinition error of due to clash with enums defined in importer code.
+enum MissingFilesRole { EntryStateRole = Qt::UserRole, NewPathsToProcessRole };
+
+// TODO: Fix redefinition error of due to clash with enums defined in importer code.
+enum MissingFilesColumn { Source, OriginalPath, NewPath, State, Count };
+
 enum MissingFilesState { Missing, Found, Replaced, Cleared };
 
 Q_DECLARE_METATYPE(MissingFilesState);
@@ -40,7 +46,8 @@ public:
 	Qt::ItemFlags flags(const QModelIndex &index) const;
 	bool setData(const QModelIndex &index, const QVariant &value, int role);
 
-	bool loop = true;
+	bool allFilesFound = false;
+	int recursionLevel = 0;
 
 	QIcon warningIcon;
 
@@ -56,5 +63,6 @@ private:
 
 	QList<MissingFileEntry> files;
 
-	void fileCheckLoop(QList<MissingFileEntry> files, QString path, bool skipPrompt);
+	void findAllFilesInPath(const QString &path, bool skipPrompt);
+	void fileCheckLoop(const QString &path, bool skipPrompt, int depth);
 };

+ 6 - 0
frontend/utility/MissingFilesPathItemDelegate.cpp

@@ -124,6 +124,12 @@ void MissingFilesPathItemDelegate::paint(QPainter *painter, const QStyleOptionVi
 	QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &localOption, painter);
 }
 
+void MissingFilesPathItemDelegate::initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const
+{
+	QStyledItemDelegate::initStyleOption(option, index);
+	option->textElideMode = Qt::ElideMiddle;
+}
+
 void MissingFilesPathItemDelegate::handleBrowse(QWidget *container)
 {
 

+ 3 - 0
frontend/utility/MissingFilesPathItemDelegate.hpp

@@ -33,6 +33,9 @@ public:
 	virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
 			   const QModelIndex &index) const override;
 
+protected:
+	void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override;
+
 private:
 	bool isOutput;
 	QString defaultPath;