2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
2011-08-16 18:55:23 +02:00
|
|
|
|
|
|
|
|
#include "fileutils.h"
|
|
|
|
|
|
2022-11-24 17:38:36 +01:00
|
|
|
#include "coreconstants.h"
|
|
|
|
|
#include "documentmanager.h"
|
|
|
|
|
#include "editormanager/editormanager.h"
|
|
|
|
|
#include "foldernavigationwidget.h"
|
|
|
|
|
#include "icore.h"
|
|
|
|
|
#include "iversioncontrol.h"
|
|
|
|
|
#include "messagemanager.h"
|
|
|
|
|
#include "navigationwidget.h"
|
|
|
|
|
#include "vcsmanager.h"
|
|
|
|
|
|
2021-10-28 15:54:24 +02:00
|
|
|
#include <utils/commandline.h>
|
2017-01-11 13:55:31 +01:00
|
|
|
#include <utils/environment.h>
|
2012-12-20 17:14:18 +01:00
|
|
|
#include <utils/hostosinfo.h>
|
2021-10-28 15:54:24 +02:00
|
|
|
#include <utils/qtcprocess.h>
|
2022-01-25 09:32:43 +01:00
|
|
|
#include <utils/terminalcommand.h>
|
2020-05-08 18:06:26 +02:00
|
|
|
#include <utils/textfileformat.h>
|
2012-12-20 17:14:18 +01:00
|
|
|
#include <utils/unixutils.h>
|
2011-08-16 18:55:23 +02:00
|
|
|
|
2012-12-20 17:14:18 +01:00
|
|
|
#include <QApplication>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDir>
|
|
|
|
|
#include <QFileInfo>
|
|
|
|
|
#include <QMessageBox>
|
2012-12-20 17:14:18 +01:00
|
|
|
#include <QPushButton>
|
2020-05-08 18:06:26 +02:00
|
|
|
#include <QRegularExpression>
|
|
|
|
|
#include <QTextStream>
|
|
|
|
|
#include <QTextCodec>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QWidget>
|
2011-08-16 18:55:23 +02:00
|
|
|
|
2022-01-25 09:32:43 +01:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
2012-12-20 17:14:18 +01:00
|
|
|
using namespace Utils;
|
2011-08-16 18:55:23 +02:00
|
|
|
|
2012-12-20 17:14:18 +01:00
|
|
|
namespace Core {
|
2011-08-16 18:55:23 +02:00
|
|
|
|
|
|
|
|
// Show error with option to open settings.
|
2012-12-20 17:14:18 +01:00
|
|
|
static void showGraphicalShellError(QWidget *parent, const QString &app, const QString &error)
|
2011-08-16 18:55:23 +02:00
|
|
|
{
|
|
|
|
|
const QString title = QApplication::translate("Core::Internal",
|
|
|
|
|
"Launching a file browser failed");
|
|
|
|
|
const QString msg = QApplication::translate("Core::Internal",
|
|
|
|
|
"Unable to start the file manager:\n\n%1\n\n").arg(app);
|
|
|
|
|
QMessageBox mbox(QMessageBox::Warning, title, msg, QMessageBox::Close, parent);
|
|
|
|
|
if (!error.isEmpty())
|
|
|
|
|
mbox.setDetailedText(QApplication::translate("Core::Internal",
|
2014-04-17 14:09:47 +02:00
|
|
|
"\"%1\" returned the following error:\n\n%2").arg(app, error));
|
2014-02-20 14:52:10 +01:00
|
|
|
QAbstractButton *settingsButton = mbox.addButton(Core::ICore::msgShowOptionsDialog(),
|
2011-08-16 18:55:23 +02:00
|
|
|
QMessageBox::ActionRole);
|
|
|
|
|
mbox.exec();
|
2015-02-23 11:07:38 +01:00
|
|
|
if (mbox.clickedButton() == settingsButton)
|
2015-08-14 13:25:31 +02:00
|
|
|
ICore::showOptionsDialog(Constants::SETTINGS_ID_INTERFACE, parent);
|
2011-08-16 18:55:23 +02:00
|
|
|
}
|
|
|
|
|
|
2021-08-12 12:05:37 +02:00
|
|
|
void FileUtils::showInGraphicalShell(QWidget *parent, const FilePath &pathIn)
|
2011-08-16 18:55:23 +02:00
|
|
|
{
|
2021-08-12 12:05:37 +02:00
|
|
|
const QFileInfo fileInfo = pathIn.toFileInfo();
|
2011-08-16 18:55:23 +02:00
|
|
|
// Mac, Windows support folder or file.
|
2012-12-20 17:14:18 +01:00
|
|
|
if (HostOsInfo::isWindowsHost()) {
|
2019-05-28 13:49:26 +02:00
|
|
|
const FilePath explorer = Environment::systemEnvironment().searchInPath(QLatin1String("explorer.exe"));
|
2012-12-20 17:14:18 +01:00
|
|
|
if (explorer.isEmpty()) {
|
|
|
|
|
QMessageBox::warning(parent,
|
|
|
|
|
QApplication::translate("Core::Internal",
|
|
|
|
|
"Launching Windows Explorer Failed"),
|
|
|
|
|
QApplication::translate("Core::Internal",
|
|
|
|
|
"Could not find explorer.exe in path to launch Windows Explorer."));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
QStringList param;
|
2021-08-12 12:05:37 +02:00
|
|
|
if (!pathIn.isDir())
|
2012-12-20 17:14:18 +01:00
|
|
|
param += QLatin1String("/select,");
|
2016-06-23 12:39:44 +02:00
|
|
|
param += QDir::toNativeSeparators(fileInfo.canonicalFilePath());
|
2021-08-25 13:51:49 +02:00
|
|
|
QtcProcess::startDetached({explorer, param});
|
2012-12-20 17:14:18 +01:00
|
|
|
} else if (HostOsInfo::isMacHost()) {
|
2022-01-18 15:37:42 +01:00
|
|
|
QtcProcess::startDetached({"/usr/bin/open", {"-R", fileInfo.canonicalFilePath()}});
|
2012-12-20 17:14:18 +01:00
|
|
|
} else {
|
|
|
|
|
// we cannot select a file here, because no file browser really supports it...
|
|
|
|
|
const QString folder = fileInfo.isDir() ? fileInfo.absoluteFilePath() : fileInfo.filePath();
|
|
|
|
|
const QString app = UnixUtils::fileBrowser(ICore::settings());
|
2021-05-06 13:07:36 +02:00
|
|
|
QStringList browserArgs = ProcessArgs::splitArgs(
|
2020-11-16 13:22:56 +01:00
|
|
|
UnixUtils::substituteFileBrowserParameters(app, folder));
|
|
|
|
|
QString error;
|
|
|
|
|
if (browserArgs.isEmpty()) {
|
|
|
|
|
error = QApplication::translate("Core::Internal",
|
|
|
|
|
"The command for file browser is not set.");
|
|
|
|
|
} else {
|
|
|
|
|
QProcess browserProc;
|
|
|
|
|
browserProc.setProgram(browserArgs.takeFirst());
|
|
|
|
|
browserProc.setArguments(browserArgs);
|
|
|
|
|
const bool success = browserProc.startDetached();
|
|
|
|
|
error = QString::fromLocal8Bit(browserProc.readAllStandardError());
|
|
|
|
|
if (!success && error.isEmpty())
|
|
|
|
|
error = QApplication::translate("Core::Internal",
|
|
|
|
|
"Error while starting file browser.");
|
|
|
|
|
}
|
|
|
|
|
if (!error.isEmpty())
|
2012-12-20 17:14:18 +01:00
|
|
|
showGraphicalShellError(parent, app, error);
|
2011-08-16 18:55:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-28 15:54:24 +02:00
|
|
|
void FileUtils::showInFileSystemView(const FilePath &path)
|
|
|
|
|
{
|
|
|
|
|
QWidget *widget
|
|
|
|
|
= NavigationWidget::activateSubWidget(FolderNavigationWidgetFactory::instance()->id(),
|
|
|
|
|
Side::Left);
|
|
|
|
|
if (auto *navWidget = qobject_cast<FolderNavigationWidget *>(widget))
|
|
|
|
|
navWidget->syncWithFilePath(path);
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-25 09:32:43 +01:00
|
|
|
static void startTerminalEmulator(const QString &workingDir, const Environment &env)
|
|
|
|
|
{
|
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
|
STARTUPINFO si;
|
|
|
|
|
ZeroMemory(&si, sizeof(si));
|
|
|
|
|
si.cb = sizeof(si);
|
|
|
|
|
|
|
|
|
|
PROCESS_INFORMATION pinfo;
|
|
|
|
|
ZeroMemory(&pinfo, sizeof(pinfo));
|
|
|
|
|
|
2022-01-26 17:01:22 +01:00
|
|
|
static const auto quoteWinCommand = [](const QString &program) {
|
|
|
|
|
const QChar doubleQuote = QLatin1Char('"');
|
|
|
|
|
|
|
|
|
|
// add the program as the first arg ... it works better
|
|
|
|
|
QString programName = program;
|
|
|
|
|
programName.replace(QLatin1Char('/'), QLatin1Char('\\'));
|
|
|
|
|
if (!programName.startsWith(doubleQuote) && !programName.endsWith(doubleQuote)
|
|
|
|
|
&& programName.contains(QLatin1Char(' '))) {
|
|
|
|
|
programName.prepend(doubleQuote);
|
|
|
|
|
programName.append(doubleQuote);
|
|
|
|
|
}
|
|
|
|
|
return programName;
|
|
|
|
|
};
|
2022-08-24 14:55:41 +02:00
|
|
|
const QString cmdLine = quoteWinCommand(qtcEnvironmentVariable("COMSPEC"));
|
2022-01-25 09:32:43 +01:00
|
|
|
// cmdLine is assumed to be detached -
|
|
|
|
|
// https://blogs.msdn.microsoft.com/oldnewthing/20090601-00/?p=18083
|
|
|
|
|
|
|
|
|
|
const QString totalEnvironment = env.toStringList().join(QChar(QChar::Null)) + QChar(QChar::Null);
|
|
|
|
|
LPVOID envPtr = (env != Environment::systemEnvironment())
|
|
|
|
|
? (WCHAR *)(totalEnvironment.utf16()) : nullptr;
|
|
|
|
|
|
|
|
|
|
const bool success = CreateProcessW(0, (WCHAR *)cmdLine.utf16(),
|
|
|
|
|
0, 0, FALSE, CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT,
|
|
|
|
|
envPtr, workingDir.isEmpty() ? 0 : (WCHAR *)workingDir.utf16(),
|
|
|
|
|
&si, &pinfo);
|
|
|
|
|
|
|
|
|
|
if (success) {
|
|
|
|
|
CloseHandle(pinfo.hThread);
|
|
|
|
|
CloseHandle(pinfo.hProcess);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
const TerminalCommand term = TerminalCommand::terminalEmulator();
|
|
|
|
|
QProcess process;
|
|
|
|
|
process.setProgram(term.command);
|
|
|
|
|
process.setArguments(ProcessArgs::splitArgs(term.openArgs));
|
|
|
|
|
process.setProcessEnvironment(env.toProcessEnvironment());
|
|
|
|
|
process.setWorkingDirectory(workingDir);
|
|
|
|
|
process.startDetached();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-02 18:02:10 +02:00
|
|
|
void FileUtils::openTerminal(const FilePath &path)
|
2018-08-31 10:54:47 +02:00
|
|
|
{
|
|
|
|
|
openTerminal(path, Environment::systemEnvironment());
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-02 18:02:10 +02:00
|
|
|
void FileUtils::openTerminal(const FilePath &path, const Environment &env)
|
2011-08-16 18:55:23 +02:00
|
|
|
{
|
2021-08-02 18:02:10 +02:00
|
|
|
const QFileInfo fileInfo = path.toFileInfo();
|
2022-01-25 09:32:43 +01:00
|
|
|
const QString workingDir = QDir::toNativeSeparators(fileInfo.isDir() ?
|
|
|
|
|
fileInfo.absoluteFilePath() :
|
|
|
|
|
fileInfo.absolutePath());
|
|
|
|
|
startTerminalEmulator(workingDir, env);
|
2011-08-16 18:55:23 +02:00
|
|
|
}
|
|
|
|
|
|
2013-09-24 12:12:09 +03:00
|
|
|
QString FileUtils::msgFindInDirectory()
|
|
|
|
|
{
|
|
|
|
|
return QApplication::translate("Core::Internal", "Find in This Directory...");
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-17 17:33:47 +02:00
|
|
|
QString FileUtils::msgFileSystemAction()
|
|
|
|
|
{
|
|
|
|
|
return QApplication::translate("Core::Internal", "Show in File System View");
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-16 18:55:23 +02:00
|
|
|
QString FileUtils::msgGraphicalShellAction()
|
|
|
|
|
{
|
2012-12-20 17:14:18 +01:00
|
|
|
if (HostOsInfo::isWindowsHost())
|
|
|
|
|
return QApplication::translate("Core::Internal", "Show in Explorer");
|
|
|
|
|
if (HostOsInfo::isMacHost())
|
|
|
|
|
return QApplication::translate("Core::Internal", "Show in Finder");
|
2011-11-15 10:19:20 +01:00
|
|
|
return QApplication::translate("Core::Internal", "Show Containing Folder");
|
2011-08-16 18:55:23 +02:00
|
|
|
}
|
|
|
|
|
|
2019-04-26 20:47:23 +02:00
|
|
|
QString FileUtils::msgTerminalHereAction()
|
2011-08-16 18:55:23 +02:00
|
|
|
{
|
2012-12-20 17:14:18 +01:00
|
|
|
if (HostOsInfo::isWindowsHost())
|
|
|
|
|
return QApplication::translate("Core::Internal", "Open Command Prompt Here");
|
2011-11-15 10:19:20 +01:00
|
|
|
return QApplication::translate("Core::Internal", "Open Terminal Here");
|
2011-08-16 18:55:23 +02:00
|
|
|
}
|
2012-05-24 23:04:29 +04:00
|
|
|
|
2019-04-26 20:47:23 +02:00
|
|
|
QString FileUtils::msgTerminalWithAction()
|
|
|
|
|
{
|
|
|
|
|
if (HostOsInfo::isWindowsHost())
|
2020-03-17 16:30:38 +01:00
|
|
|
return QApplication::translate("Core::Internal", "Open Command Prompt With",
|
|
|
|
|
"Opens a submenu for choosing an environment, such as \"Run Environment\"");
|
|
|
|
|
return QApplication::translate("Core::Internal", "Open Terminal With",
|
|
|
|
|
"Opens a submenu for choosing an environment, such as \"Run Environment\"");
|
2019-04-26 20:47:23 +02:00
|
|
|
}
|
|
|
|
|
|
2020-09-03 17:51:23 +02:00
|
|
|
void FileUtils::removeFiles(const FilePaths &filePaths, bool deleteFromFS)
|
2012-07-18 13:41:13 +04:00
|
|
|
{
|
|
|
|
|
// remove from version control
|
2020-09-03 17:51:23 +02:00
|
|
|
VcsManager::promptToDelete(filePaths);
|
|
|
|
|
|
|
|
|
|
if (!deleteFromFS)
|
|
|
|
|
return;
|
2012-07-18 13:41:13 +04:00
|
|
|
|
|
|
|
|
// remove from file system
|
2020-09-03 17:51:23 +02:00
|
|
|
for (const FilePath &fp : filePaths) {
|
|
|
|
|
QFile file(fp.toString());
|
|
|
|
|
if (!file.exists()) // could have been deleted by vc
|
|
|
|
|
continue;
|
|
|
|
|
if (!file.remove()) {
|
2020-12-01 13:02:12 +01:00
|
|
|
MessageManager::writeDisrupting(
|
2021-03-18 11:20:36 +01:00
|
|
|
QCoreApplication::translate("Core::Internal", "Failed to remove file \"%1\".")
|
2020-12-01 13:02:12 +01:00
|
|
|
.arg(fp.toUserOutput()));
|
2012-07-18 13:41:13 +04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-11 14:34:34 +02:00
|
|
|
bool FileUtils::renameFile(const FilePath &orgFilePath, const FilePath &newFilePath,
|
2020-05-08 18:06:26 +02:00
|
|
|
HandleIncludeGuards handleGuards)
|
2012-05-24 23:04:29 +04:00
|
|
|
{
|
|
|
|
|
if (orgFilePath == newFilePath)
|
|
|
|
|
return false;
|
|
|
|
|
|
2021-06-11 14:34:34 +02:00
|
|
|
FilePath dir = orgFilePath.absolutePath();
|
2021-07-30 16:46:27 +02:00
|
|
|
IVersionControl *vc = VcsManager::findVersionControlForDirectory(dir);
|
2012-05-24 23:04:29 +04:00
|
|
|
|
|
|
|
|
bool result = false;
|
2012-12-20 17:14:18 +01:00
|
|
|
if (vc && vc->supportsOperation(IVersionControl::MoveOperation))
|
2021-07-29 09:31:09 +02:00
|
|
|
result = vc->vcsMove(orgFilePath, newFilePath);
|
2012-05-24 23:04:29 +04:00
|
|
|
if (!result) // The moving via vcs failed or the vcs does not support moving, fall back
|
2021-09-13 16:39:39 +02:00
|
|
|
result = orgFilePath.renameFile(newFilePath);
|
2012-05-24 23:04:29 +04:00
|
|
|
if (result) {
|
2014-11-16 10:52:41 +02:00
|
|
|
DocumentManager::renamedFile(orgFilePath, newFilePath);
|
2021-12-08 16:26:32 +01:00
|
|
|
updateHeaderFileGuardIfApplicable(orgFilePath, newFilePath, handleGuards);
|
2022-11-24 17:38:36 +01:00
|
|
|
}
|
2021-12-08 16:26:32 +01:00
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FileUtils::updateHeaderFileGuardIfApplicable(const Utils::FilePath &oldFilePath,
|
|
|
|
|
const Utils::FilePath &newFilePath,
|
|
|
|
|
HandleIncludeGuards handleGuards)
|
|
|
|
|
{
|
|
|
|
|
if (handleGuards == HandleIncludeGuards::No)
|
|
|
|
|
return;
|
|
|
|
|
const bool headerUpdateSuccess = updateHeaderFileGuardAfterRename(newFilePath.toString(),
|
|
|
|
|
oldFilePath.baseName());
|
|
|
|
|
if (headerUpdateSuccess)
|
|
|
|
|
return;
|
|
|
|
|
MessageManager::writeDisrupting(
|
2020-12-01 13:02:12 +01:00
|
|
|
QCoreApplication::translate("Core::FileUtils",
|
2020-05-08 18:06:26 +02:00
|
|
|
"Failed to rename the include guard in file \"%1\".")
|
2021-12-08 16:26:32 +01:00
|
|
|
.arg(newFilePath.toUserOutput()));
|
2012-05-24 23:04:29 +04:00
|
|
|
}
|
2012-12-20 17:14:18 +01:00
|
|
|
|
2020-05-08 18:06:26 +02:00
|
|
|
bool FileUtils::updateHeaderFileGuardAfterRename(const QString &headerPath,
|
|
|
|
|
const QString &oldHeaderBaseName)
|
|
|
|
|
{
|
|
|
|
|
bool ret = true;
|
|
|
|
|
QFile headerFile(headerPath);
|
|
|
|
|
if (!headerFile.open(QFile::ReadOnly | QFile::Text))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
QRegularExpression guardConditionRegExp(
|
|
|
|
|
QString("(#ifndef)(\\s*)(_*)%1_H(_*)(\\s*)").arg(oldHeaderBaseName.toUpper()));
|
|
|
|
|
QRegularExpression guardDefineRegexp, guardCloseRegExp;
|
|
|
|
|
QRegularExpressionMatch guardConditionMatch, guardDefineMatch, guardCloseMatch;
|
|
|
|
|
int guardStartLine = -1;
|
|
|
|
|
int guardCloseLine = -1;
|
|
|
|
|
|
2022-11-24 17:38:36 +01:00
|
|
|
const QByteArray data = headerFile.readAll();
|
2020-05-08 18:06:26 +02:00
|
|
|
headerFile.close();
|
|
|
|
|
|
2022-11-24 17:38:36 +01:00
|
|
|
auto headerFileTextFormat = Utils::TextFileFormat::detect(data);
|
|
|
|
|
if (!headerFileTextFormat.codec)
|
|
|
|
|
headerFileTextFormat.codec = EditorManager::defaultTextCodec();
|
|
|
|
|
QString stringContent;
|
|
|
|
|
if (!headerFileTextFormat.decode(data, &stringContent))
|
|
|
|
|
return false;
|
|
|
|
|
QTextStream inStream(&stringContent);
|
2020-05-08 18:06:26 +02:00
|
|
|
int lineCounter = 0;
|
|
|
|
|
QString line;
|
|
|
|
|
while (!inStream.atEnd()) {
|
|
|
|
|
// use trimmed line to get rid from the maunder leading spaces
|
|
|
|
|
inStream.readLineInto(&line);
|
|
|
|
|
line = line.trimmed();
|
|
|
|
|
if (line == QStringLiteral("#pragma once")) {
|
|
|
|
|
// if pragma based guard found skip reading the whole file
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (guardStartLine == -1) {
|
|
|
|
|
// we are still looking for the guard condition
|
|
|
|
|
guardConditionMatch = guardConditionRegExp.match(line);
|
|
|
|
|
if (guardConditionMatch.hasMatch()) {
|
|
|
|
|
guardDefineRegexp.setPattern(QString("(#define\\s*%1)%2(_H%3\\s*)")
|
|
|
|
|
.arg(guardConditionMatch.captured(3),
|
|
|
|
|
oldHeaderBaseName.toUpper(),
|
|
|
|
|
guardConditionMatch.captured(4)));
|
|
|
|
|
// read the next line for the guard define
|
|
|
|
|
line = inStream.readLine();
|
|
|
|
|
if (!inStream.atEnd()) {
|
|
|
|
|
guardDefineMatch = guardDefineRegexp.match(line);
|
|
|
|
|
if (guardDefineMatch.hasMatch()) {
|
|
|
|
|
// if a proper guard define present in the next line store the line number
|
|
|
|
|
guardCloseRegExp
|
|
|
|
|
.setPattern(
|
|
|
|
|
QString("(#endif\\s*)(\\/\\/|\\/\\*)(\\s*%1)%2(_H%3\\s*)((\\*\\/)?)")
|
|
|
|
|
.arg(
|
|
|
|
|
guardConditionMatch.captured(3),
|
|
|
|
|
oldHeaderBaseName.toUpper(),
|
|
|
|
|
guardConditionMatch.captured(4)));
|
|
|
|
|
guardStartLine = lineCounter;
|
|
|
|
|
lineCounter++;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// it the line after the guard opening is not something what we expect
|
|
|
|
|
// then skip the whole guard replacing process
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// guard start found looking for the guard closing endif
|
|
|
|
|
guardCloseMatch = guardCloseRegExp.match(line);
|
|
|
|
|
if (guardCloseMatch.hasMatch()) {
|
|
|
|
|
guardCloseLine = lineCounter;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lineCounter++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (guardStartLine != -1) {
|
|
|
|
|
// At least the guard have been found ->
|
|
|
|
|
// copy the contents of the header to a temporary file with the updated guard lines
|
|
|
|
|
inStream.seek(0);
|
|
|
|
|
|
|
|
|
|
QFileInfo fi(headerFile);
|
|
|
|
|
const auto guardCondition = QString("#ifndef%1%2%3_H%4%5").arg(
|
|
|
|
|
guardConditionMatch.captured(2),
|
|
|
|
|
guardConditionMatch.captured(3),
|
|
|
|
|
fi.baseName().toUpper(),
|
|
|
|
|
guardConditionMatch.captured(4),
|
|
|
|
|
guardConditionMatch.captured(5));
|
|
|
|
|
// guardDefineRegexp.setPattern(QString("(#define\\s*%1)%2(_H%3\\s*)")
|
|
|
|
|
const auto guardDefine = QString("%1%2%3").arg(
|
|
|
|
|
guardDefineMatch.captured(1),
|
|
|
|
|
fi.baseName().toUpper(),
|
|
|
|
|
guardDefineMatch.captured(2));
|
|
|
|
|
const auto guardClose = QString("%1%2%3%4%5%6").arg(
|
|
|
|
|
guardCloseMatch.captured(1),
|
|
|
|
|
guardCloseMatch.captured(2),
|
|
|
|
|
guardCloseMatch.captured(3),
|
|
|
|
|
fi.baseName().toUpper(),
|
|
|
|
|
guardCloseMatch.captured(4),
|
|
|
|
|
guardCloseMatch.captured(5));
|
|
|
|
|
|
|
|
|
|
QFile tmpHeader(headerPath + ".tmp");
|
|
|
|
|
if (tmpHeader.open(QFile::WriteOnly)) {
|
|
|
|
|
const auto lineEnd =
|
|
|
|
|
headerFileTextFormat.lineTerminationMode
|
|
|
|
|
== Utils::TextFileFormat::LFLineTerminator
|
|
|
|
|
? QStringLiteral("\n") : QStringLiteral("\r\n");
|
2020-09-07 12:28:32 +02:00
|
|
|
// write into temporary string,
|
|
|
|
|
// after that write with codec into file (QTextStream::setCodec is gone in Qt 6)
|
|
|
|
|
QString outString;
|
|
|
|
|
QTextStream outStream(&outString);
|
2020-05-08 18:06:26 +02:00
|
|
|
int lineCounter = 0;
|
|
|
|
|
while (!inStream.atEnd()) {
|
|
|
|
|
inStream.readLineInto(&line);
|
|
|
|
|
if (lineCounter == guardStartLine) {
|
|
|
|
|
outStream << guardCondition << lineEnd;
|
|
|
|
|
outStream << guardDefine << lineEnd;
|
|
|
|
|
inStream.readLine();
|
|
|
|
|
lineCounter++;
|
|
|
|
|
} else if (lineCounter == guardCloseLine) {
|
|
|
|
|
outStream << guardClose << lineEnd;
|
|
|
|
|
} else {
|
|
|
|
|
outStream << line << lineEnd;
|
|
|
|
|
}
|
|
|
|
|
lineCounter++;
|
|
|
|
|
}
|
2022-11-24 17:38:36 +01:00
|
|
|
tmpHeader.write(headerFileTextFormat.codec->fromUnicode(outString));
|
2020-05-08 18:06:26 +02:00
|
|
|
tmpHeader.close();
|
|
|
|
|
} else {
|
|
|
|
|
// if opening the temp file failed report error
|
|
|
|
|
ret = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ret && guardStartLine != -1) {
|
|
|
|
|
// if the guard was found (and updated updated properly) swap the temp and the target file
|
|
|
|
|
ret = QFile::remove(headerPath);
|
|
|
|
|
if (ret)
|
|
|
|
|
ret = QFile::rename(headerPath + ".tmp", headerPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-20 17:14:18 +01:00
|
|
|
} // namespace Core
|