Format files and add .gitattributes and .clang-format.

This commit is contained in:
Mikaël Capelle
2024-06-09 13:56:50 +02:00
parent fed6ac72b4
commit 1d3cd89fc8
8 changed files with 1253 additions and 1187 deletions
+41
View File
@@ -0,0 +1,41 @@
---
# We'll use defaults from the LLVM style, but with 4 columns indentation.
BasedOnStyle: LLVM
IndentWidth: 2
---
Language: Cpp
DeriveLineEnding: false
UseCRLF: true
DerivePointerAlignment: false
PointerAlignment: Left
AlignConsecutiveAssignments: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: Empty
AlwaysBreakTemplateDeclarations: Yes
AccessModifierOffset: -2
AlignTrailingComments: true
SpacesBeforeTrailingComments: 2
NamespaceIndentation: Inner
MaxEmptyLinesToKeep: 1
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: false
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: true
ColumnLimit: 88
ForEachMacros: ['Q_FOREACH', 'foreach']
+7
View File
@@ -0,0 +1,7 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.cpp text eol=crlf
*.h text eol=crlf
+484 -468
View File
File diff suppressed because it is too large Load Diff
+178 -187
View File
@@ -1,187 +1,178 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer 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 3 of the License, or
(at your option) any later version.
Mod Organizer 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 Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ARCHIVETREE_H
#define ARCHIVETREE_H
#include <QTreeWidget>
#include "ifiletree.h"
class ArchiveTreeWidget;
// custom tree widget that holds a shared pointer to the file tree entry
// they represent
//
class ArchiveTreeWidgetItem : public QTreeWidgetItem {
public:
ArchiveTreeWidgetItem(QString dataName);
ArchiveTreeWidgetItem(std::shared_ptr<MOBase::FileTreeEntry> entry);
public:
// populate this tree widget item if it has not been populated yet
// or if force is true
//
void populate(bool force = false);
// check if this item has already been populated
//
bool isPopulated() const { return m_Populated; }
// replace the entry corresponding to this item
//
void setEntry(std::shared_ptr<MOBase::FileTreeEntry> entry) {
m_Entry = entry;
}
// retrieve the entry corresponding to this item
//
std::shared_ptr<MOBase::FileTreeEntry> entry() const {
return m_Entry;
}
// overriden method to avoid propagating dataChanged events
//
void setData(int column, int role, const QVariant& value) override;
ArchiveTreeWidgetItem* parent() const {
return static_cast<ArchiveTreeWidgetItem*>(QTreeWidgetItem::parent());
}
ArchiveTreeWidgetItem* child(int index) const {
return static_cast<ArchiveTreeWidgetItem*>(QTreeWidgetItem::child(index));
}
protected:
std::shared_ptr<MOBase::FileTreeEntry> m_Entry;
bool m_Populated = false;
friend class ArchiveTreeWidget;
};
// Qt tree widget used to display the content of an archive in the manual installation
// dialog
class ArchiveTreeWidget : public QTreeWidget
{
Q_OBJECT
public:
explicit ArchiveTreeWidget(QWidget* parent = 0);
void setup(QString dataFolderName);
public:
// set the data root widget
//
void setDataRoot(ArchiveTreeWidgetItem* const root);
// create a directory under the given tree item, without
// performing any check
//
ArchiveTreeWidgetItem* addDirectory(ArchiveTreeWidgetItem* treeItem, QString name);
// return the root of the tree (the item corresponding to <data>)
//
ArchiveTreeWidgetItem* root() const { return m_ViewRoot; }
signals:
// emitted when the tree has been modified
//
void treeChanged();
public slots:
protected:
// detach the entry of this item from its parent, and recursively detach
// all of its parent if they become
//
void detachParents(ArchiveTreeWidgetItem* item);
// re-attach the entry of this item to its parent, and recursively attach
// all of its parent if they were empty (and thus detached)
//
void attachParents(ArchiveTreeWidgetItem* item);
// recursively re-insert all the entries below the given item in their
// corresponding parents
//
// this method does not recurse in items that have not been populated yet
//
void recursiveInsert(ArchiveTreeWidgetItem* item);
// recursively detach all the entries below the given item from their
// corresponding parents
//
// this method does not recurse in items that have not been populated yet
//
void recursiveDetach(ArchiveTreeWidgetItem* item);
// slot that trigger the given item to be populated if it has not already
// been
//
void populateItem(QTreeWidgetItem* item);
// move the source under the target
//
void moveItem(ArchiveTreeWidgetItem* source, ArchiveTreeWidgetItem* target);
// called when the state of the item changed - unlike the standard QTreeWidget,
// this is only called for the actual item, not its parent/children
//
void onTreeCheckStateChanged(ArchiveTreeWidgetItem* item);
void dragEnterEvent(QDragEnterEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
void dropEvent(QDropEvent *event) override;
private:
bool testMovePossible(ArchiveTreeWidgetItem* source, ArchiveTreeWidgetItem* target);
// refresh the given item (after a drop)
//
void refreshItem(ArchiveTreeWidgetItem* item);
// the widget item that emitted the dataChanged event
ArchiveTreeWidgetItem* m_Emitter = nullptr;
// IMPORTANT: if you intend to work on this and understand this, read the detailed
// explanation at the beginning of the archivetree.cpp file
//
// - the data root is the real widget of the current data, this widget
// is not the real root that is added to the tree
// - the view root is the actual tree in the widget (should be const but cannot be since
// the parent tree cannot be consstructed in the member initializer list)
//
ArchiveTreeWidgetItem* m_DataRoot;
ArchiveTreeWidgetItem* m_ViewRoot;
friend class ArchiveTreeWidgetItem;
};
#endif // ARCHIVETREE_H
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer 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 3 of the License, or
(at your option) any later version.
Mod Organizer 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 Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ARCHIVETREE_H
#define ARCHIVETREE_H
#include <QTreeWidget>
#include "ifiletree.h"
class ArchiveTreeWidget;
// custom tree widget that holds a shared pointer to the file tree entry
// they represent
//
class ArchiveTreeWidgetItem : public QTreeWidgetItem
{
public:
ArchiveTreeWidgetItem(QString dataName);
ArchiveTreeWidgetItem(std::shared_ptr<MOBase::FileTreeEntry> entry);
public:
// populate this tree widget item if it has not been populated yet
// or if force is true
//
void populate(bool force = false);
// check if this item has already been populated
//
bool isPopulated() const { return m_Populated; }
// replace the entry corresponding to this item
//
void setEntry(std::shared_ptr<MOBase::FileTreeEntry> entry) { m_Entry = entry; }
// retrieve the entry corresponding to this item
//
std::shared_ptr<MOBase::FileTreeEntry> entry() const { return m_Entry; }
// overriden method to avoid propagating dataChanged events
//
void setData(int column, int role, const QVariant& value) override;
ArchiveTreeWidgetItem* parent() const
{
return static_cast<ArchiveTreeWidgetItem*>(QTreeWidgetItem::parent());
}
ArchiveTreeWidgetItem* child(int index) const
{
return static_cast<ArchiveTreeWidgetItem*>(QTreeWidgetItem::child(index));
}
protected:
std::shared_ptr<MOBase::FileTreeEntry> m_Entry;
bool m_Populated = false;
friend class ArchiveTreeWidget;
};
// Qt tree widget used to display the content of an archive in the manual installation
// dialog
class ArchiveTreeWidget : public QTreeWidget
{
Q_OBJECT
public:
explicit ArchiveTreeWidget(QWidget* parent = 0);
void setup(QString dataFolderName);
public:
// set the data root widget
//
void setDataRoot(ArchiveTreeWidgetItem* const root);
// create a directory under the given tree item, without
// performing any check
//
ArchiveTreeWidgetItem* addDirectory(ArchiveTreeWidgetItem* treeItem, QString name);
// return the root of the tree (the item corresponding to <data>)
//
ArchiveTreeWidgetItem* root() const { return m_ViewRoot; }
signals:
// emitted when the tree has been modified
//
void treeChanged();
public slots:
protected:
// detach the entry of this item from its parent, and recursively detach
// all of its parent if they become
//
void detachParents(ArchiveTreeWidgetItem* item);
// re-attach the entry of this item to its parent, and recursively attach
// all of its parent if they were empty (and thus detached)
//
void attachParents(ArchiveTreeWidgetItem* item);
// recursively re-insert all the entries below the given item in their
// corresponding parents
//
// this method does not recurse in items that have not been populated yet
//
void recursiveInsert(ArchiveTreeWidgetItem* item);
// recursively detach all the entries below the given item from their
// corresponding parents
//
// this method does not recurse in items that have not been populated yet
//
void recursiveDetach(ArchiveTreeWidgetItem* item);
// slot that trigger the given item to be populated if it has not already
// been
//
void populateItem(QTreeWidgetItem* item);
// move the source under the target
//
void moveItem(ArchiveTreeWidgetItem* source, ArchiveTreeWidgetItem* target);
// called when the state of the item changed - unlike the standard QTreeWidget,
// this is only called for the actual item, not its parent/children
//
void onTreeCheckStateChanged(ArchiveTreeWidgetItem* item);
void dragEnterEvent(QDragEnterEvent* event) override;
void dragMoveEvent(QDragMoveEvent* event) override;
void dropEvent(QDropEvent* event) override;
private:
bool testMovePossible(ArchiveTreeWidgetItem* source, ArchiveTreeWidgetItem* target);
// refresh the given item (after a drop)
//
void refreshItem(ArchiveTreeWidgetItem* item);
// the widget item that emitted the dataChanged event
ArchiveTreeWidgetItem* m_Emitter = nullptr;
// IMPORTANT: if you intend to work on this and understand this, read the detailed
// explanation at the beginning of the archivetree.cpp file
//
// - the data root is the real widget of the current data, this widget
// is not the real root that is added to the tree
// - the view root is the actual tree in the widget (should be const but cannot be
// since
// the parent tree cannot be consstructed in the member initializer list)
//
ArchiveTreeWidgetItem* m_DataRoot;
ArchiveTreeWidgetItem* m_ViewRoot;
friend class ArchiveTreeWidgetItem;
};
#endif // ARCHIVETREE_H
+215 -193
View File
@@ -1,193 +1,215 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer 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 3 of the License, or
(at your option) any later version.
Mod Organizer 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 Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "installdialog.h"
#include "ui_installdialog.h"
#include "report.h"
#include "utility.h"
#include "log.h"
#include <QMenu>
#include <QCompleter>
#include <QInputDialog>
#include <QMetaType>
#include <QMessageBox>
using namespace MOBase;
InstallDialog::InstallDialog(std::shared_ptr<IFileTree> tree, const GuessedValue<QString> &modName, std::shared_ptr<const MOBase::ModDataChecker> modDataChecker, const QString& dataName, QWidget *parent)
: TutorableDialog("InstallDialog", parent),
ui(new Ui::InstallDialog),
m_Checker(modDataChecker),
m_DataFolderName(dataName)
{
ui->setupUi(this);
for (auto iter = modName.variants().begin(); iter != modName.variants().end(); ++iter) {
ui->nameCombo->addItem(*iter);
}
ui->nameCombo->setCurrentIndex(ui->nameCombo->findText(modName));
ui->nameCombo->completer()->setCaseSensitivity(Qt::CaseSensitive);
m_ProblemLabel = ui->problemLabel;
m_Tree = ui->treeContent;
m_TreeRoot = new ArchiveTreeWidgetItem(tree);
m_Tree->setup(m_DataFolderName);
connect(m_Tree, &ArchiveTreeWidget::treeChanged, [this] { updateProblems(); });
m_Tree->setDataRoot(m_TreeRoot);
}
InstallDialog::~InstallDialog()
{
delete ui;
}
QString InstallDialog::getModName() const
{
return ui->nameCombo->currentText();
}
/**
* @brief Retrieve the user-modified directory structure.
*
* @return the new tree represented by this dialog, which can be a new
* tree or a subtree of the original tree.
**/
std::shared_ptr<MOBase::IFileTree> InstallDialog::getModifiedTree() const {
return m_Tree->root()->entry()->astree();
}
bool InstallDialog::testForProblem()
{
if (!m_Checker) {
return true;
}
return m_Checker->dataLooksValid(m_Tree->root()->entry()->astree()) == ModDataChecker::CheckReturn::VALID;
}
void InstallDialog::updateProblems()
{
if (!m_Checker) {
m_Tree->setStyleSheet("QTreeWidget { border: none; }");
m_ProblemLabel->setText(tr("Cannot check the content of <%1>.").arg(m_DataFolderName));
m_ProblemLabel->setToolTip(tr("The plugin for the current game does not provide a way to check the content of <%1>.").arg(m_DataFolderName));
m_ProblemLabel->setStyleSheet("color: darkYellow;");
}
else if (testForProblem()) {
m_Tree->setStyleSheet("QTreeWidget { border: 1px solid darkGreen; border-radius: 2px; }");
m_ProblemLabel->setText(tr("The content of <%1> looks valid.").arg(m_DataFolderName));
m_ProblemLabel->setToolTip(tr("The content of <%1> seems valid for the current game.").arg(m_DataFolderName));
m_ProblemLabel->setStyleSheet("color: darkGreen;");
} else {
m_Tree->setStyleSheet("QTreeWidget { border: 1px solid red; border-radius: 2px; }");
m_ProblemLabel->setText(tr("The content of <%1> does not look valid.").arg(m_DataFolderName));
m_ProblemLabel->setToolTip(tr("The content of <%1> is probably not valid for the current game.").arg(m_DataFolderName));
m_ProblemLabel->setStyleSheet("color: red;");
}
}
void InstallDialog::createDirectoryUnder(ArchiveTreeWidgetItem* item)
{
// Should never happen if we customize the context menu depending
// on the item:
if (!item->entry()->isDir()) {
reportError(tr("Cannot create directory under a file."));
return;
}
// Retrieve the directory:
auto fileTree = item->entry()->astree();
bool ok = false;
QString result = QInputDialog::getText(this, tr("Enter a directory name"), tr("Name"),
QLineEdit::Normal, QString(), &ok);
result = result.trimmed();
if (ok && !result.isEmpty()) {
// If a file with this name already exists:
if (fileTree->exists(result)) {
reportError(tr("A directory or file with that name already exists."));
return;
}
item->setExpanded(true);
auto* newItem = m_Tree->addDirectory(item, result);
m_Tree->scrollToItem(newItem);
}
}
void InstallDialog::on_treeContent_customContextMenuRequested(QPoint pos)
{
ArchiveTreeWidgetItem* selectedItem = static_cast<ArchiveTreeWidgetItem*>(m_Tree->itemAt(pos));
if (selectedItem == nullptr) {
return;
}
QMenu menu;
if (selectedItem != m_Tree->root() && selectedItem->entry()->isDir()) {
menu.addAction(tr("Set as <%1> directory").arg(m_DataFolderName), [this, selectedItem]() { m_Tree->setDataRoot(selectedItem); });
}
if (m_Tree->root()->entry() != m_TreeRoot->entry()) {
menu.addAction(tr("Unset <%1> directory").arg(m_DataFolderName), [this]() { m_Tree->setDataRoot(m_TreeRoot); });
}
// Add a separator if not empty:
if (!menu.isEmpty()) {
menu.addSeparator();
}
if (selectedItem->entry()->isDir()) {
menu.addAction(tr("Create directory..."), [this, selectedItem]() { createDirectoryUnder(selectedItem); });
}
else {
menu.addAction(tr("&Open"), [this, selectedItem]() {
emit openFile(selectedItem->entry().get());
});
}
menu.exec(m_Tree->mapToGlobal(pos));
}
void InstallDialog::on_okButton_clicked()
{
if (!testForProblem()) {
if (QMessageBox::question(this, tr("Continue?"),
tr("This mod was probably NOT set up correctly, most likely it will NOT work. "
"You should first correct the directory layout using the content-tree."),
QMessageBox::Ignore | QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Cancel) {
return;
}
}
this->accept();
}
void InstallDialog::on_cancelButton_clicked()
{
this->reject();
}
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer 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 3 of the License, or
(at your option) any later version.
Mod Organizer 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 Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "installdialog.h"
#include "ui_installdialog.h"
#include "log.h"
#include "report.h"
#include "utility.h"
#include <QCompleter>
#include <QInputDialog>
#include <QMenu>
#include <QMessageBox>
#include <QMetaType>
using namespace MOBase;
InstallDialog::InstallDialog(
std::shared_ptr<IFileTree> tree, const GuessedValue<QString>& modName,
std::shared_ptr<const MOBase::ModDataChecker> modDataChecker,
const QString& dataName, QWidget* parent)
: TutorableDialog("InstallDialog", parent), ui(new Ui::InstallDialog),
m_Checker(modDataChecker), m_DataFolderName(dataName)
{
ui->setupUi(this);
for (auto iter = modName.variants().begin(); iter != modName.variants().end();
++iter) {
ui->nameCombo->addItem(*iter);
}
ui->nameCombo->setCurrentIndex(ui->nameCombo->findText(modName));
ui->nameCombo->completer()->setCaseSensitivity(Qt::CaseSensitive);
m_ProblemLabel = ui->problemLabel;
m_Tree = ui->treeContent;
m_TreeRoot = new ArchiveTreeWidgetItem(tree);
m_Tree->setup(m_DataFolderName);
connect(m_Tree, &ArchiveTreeWidget::treeChanged, [this] {
updateProblems();
});
m_Tree->setDataRoot(m_TreeRoot);
}
InstallDialog::~InstallDialog()
{
delete ui;
}
QString InstallDialog::getModName() const
{
return ui->nameCombo->currentText();
}
/**
* @brief Retrieve the user-modified directory structure.
*
* @return the new tree represented by this dialog, which can be a new
* tree or a subtree of the original tree.
**/
std::shared_ptr<MOBase::IFileTree> InstallDialog::getModifiedTree() const
{
return m_Tree->root()->entry()->astree();
}
bool InstallDialog::testForProblem()
{
if (!m_Checker) {
return true;
}
return m_Checker->dataLooksValid(m_Tree->root()->entry()->astree()) ==
ModDataChecker::CheckReturn::VALID;
}
void InstallDialog::updateProblems()
{
if (!m_Checker) {
m_Tree->setStyleSheet("QTreeWidget { border: none; }");
m_ProblemLabel->setText(
tr("Cannot check the content of <%1>.").arg(m_DataFolderName));
m_ProblemLabel->setToolTip(tr("The plugin for the current game does not provide a "
"way to check the content of <%1>.")
.arg(m_DataFolderName));
m_ProblemLabel->setStyleSheet("color: darkYellow;");
} else if (testForProblem()) {
m_Tree->setStyleSheet(
"QTreeWidget { border: 1px solid darkGreen; border-radius: 2px; }");
m_ProblemLabel->setText(
tr("The content of <%1> looks valid.").arg(m_DataFolderName));
m_ProblemLabel->setToolTip(
tr("The content of <%1> seems valid for the current game.")
.arg(m_DataFolderName));
m_ProblemLabel->setStyleSheet("color: darkGreen;");
} else {
m_Tree->setStyleSheet("QTreeWidget { border: 1px solid red; border-radius: 2px; }");
m_ProblemLabel->setText(
tr("The content of <%1> does not look valid.").arg(m_DataFolderName));
m_ProblemLabel->setToolTip(
tr("The content of <%1> is probably not valid for the current game.")
.arg(m_DataFolderName));
m_ProblemLabel->setStyleSheet("color: red;");
}
}
void InstallDialog::createDirectoryUnder(ArchiveTreeWidgetItem* item)
{
// Should never happen if we customize the context menu depending
// on the item:
if (!item->entry()->isDir()) {
reportError(tr("Cannot create directory under a file."));
return;
}
// Retrieve the directory:
auto fileTree = item->entry()->astree();
bool ok = false;
QString result = QInputDialog::getText(this, tr("Enter a directory name"), tr("Name"),
QLineEdit::Normal, QString(), &ok);
result = result.trimmed();
if (ok && !result.isEmpty()) {
// If a file with this name already exists:
if (fileTree->exists(result)) {
reportError(tr("A directory or file with that name already exists."));
return;
}
item->setExpanded(true);
auto* newItem = m_Tree->addDirectory(item, result);
m_Tree->scrollToItem(newItem);
}
}
void InstallDialog::on_treeContent_customContextMenuRequested(QPoint pos)
{
ArchiveTreeWidgetItem* selectedItem =
static_cast<ArchiveTreeWidgetItem*>(m_Tree->itemAt(pos));
if (selectedItem == nullptr) {
return;
}
QMenu menu;
if (selectedItem != m_Tree->root() && selectedItem->entry()->isDir()) {
menu.addAction(tr("Set as <%1> directory").arg(m_DataFolderName),
[this, selectedItem]() {
m_Tree->setDataRoot(selectedItem);
});
}
if (m_Tree->root()->entry() != m_TreeRoot->entry()) {
menu.addAction(tr("Unset <%1> directory").arg(m_DataFolderName), [this]() {
m_Tree->setDataRoot(m_TreeRoot);
});
}
// Add a separator if not empty:
if (!menu.isEmpty()) {
menu.addSeparator();
}
if (selectedItem->entry()->isDir()) {
menu.addAction(tr("Create directory..."), [this, selectedItem]() {
createDirectoryUnder(selectedItem);
});
} else {
menu.addAction(tr("&Open"), [this, selectedItem]() {
emit openFile(selectedItem->entry().get());
});
}
menu.exec(m_Tree->mapToGlobal(pos));
}
void InstallDialog::on_okButton_clicked()
{
if (!testForProblem()) {
if (QMessageBox::question(
this, tr("Continue?"),
tr("This mod was probably NOT set up correctly, most likely it will NOT "
"work. "
"You should first correct the directory layout using the content-tree."),
QMessageBox::Ignore | QMessageBox::Cancel,
QMessageBox::Cancel) == QMessageBox::Cancel) {
return;
}
}
this->accept();
}
void InstallDialog::on_cancelButton_clicked()
{
this->reject();
}
+126 -126
View File
@@ -1,126 +1,126 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer 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 3 of the License, or
(at your option) any later version.
Mod Organizer 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 Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INSTALLDIALOG_H
#define INSTALLDIALOG_H
#include "archivetree.h"
#include "tutorabledialog.h"
#include <guessedvalue.h>
#include <ifiletree.h>
#include <iplugingame.h>
#include <moddatachecker.h>
#include <QDialog>
#include <QUuid>
#include <QTreeWidgetItem>
#include <QProgressDialog>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
namespace Ui {
class InstallDialog;
}
/**
* a dialog presented to manually define how a mod is to be installed. It provides
* a tree view of the file contents that can modified directly
**/
class InstallDialog : public MOBase::TutorableDialog
{
Q_OBJECT
public:
/**
* @brief Create a new install dialog for the given tree. The tree
* is "own" by the dialog, i.e., any change made by the user is immediately
* reflected to the given tree, except for the changes to the root.
*
* @param tree Tree structure describing the original archive structure.
* @param modName Name of the mod. The name can be modified through the dialog.
* @param modDataChecker The mod data checker to use to check.
* @param dataName The name of the data folder for the game.
* @param parent Parent widget.
**/
explicit InstallDialog(std::shared_ptr<MOBase::IFileTree> tree, const MOBase::GuessedValue<QString> &modName, std::shared_ptr<const MOBase::ModDataChecker> modDataChecker, const QString& dataName, QWidget *parent = 0);
~InstallDialog();
/**
* @brief retrieve the (modified) mod name
*
* @return updated mod name
**/
QString getModName() const;
/**
* @brief Retrieve the user-modified directory structure.
*
* @return the new tree represented by this dialog, which can be a new
* tree or a subtree of the original tree.
**/
std::shared_ptr<MOBase::IFileTree> getModifiedTree() const;
signals:
/**
* @brief Signal emitted when user request the file corresponding
* to the given entry to be opened.
*
* @param entry Entry corresponding to the file to open.
*/
void openFile(const MOBase::FileTreeEntry *entry);
private:
bool testForProblem();
void updateProblems();
void createDirectoryUnder(ArchiveTreeWidgetItem* treeItem);
private slots:
// Automatic slots that are directly bound to the UI:
void on_treeContent_customContextMenuRequested(QPoint pos);
void on_cancelButton_clicked();
void on_okButton_clicked();
private:
Ui::InstallDialog *ui;
std::shared_ptr<const MOBase::ModDataChecker> m_Checker;
// Name of the "data" directory:
QString m_DataFolderName;
// the tree root is the initial root that will never change (should be const
// but cannot be since the parent tree cannot be constructed in the member
// initializer list)
//
// the tree root is not actually added to the tree, but is used to maintain
// the state of the tree and not lose entries when unsetting data root
//
ArchiveTreeWidget *m_Tree;
ArchiveTreeWidgetItem* m_TreeRoot;
QLabel *m_ProblemLabel;
};
#endif // INSTALLDIALOG_H
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer 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 3 of the License, or
(at your option) any later version.
Mod Organizer 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 Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INSTALLDIALOG_H
#define INSTALLDIALOG_H
#include "archivetree.h"
#include "tutorabledialog.h"
#include <guessedvalue.h>
#include <ifiletree.h>
#include <iplugingame.h>
#include <moddatachecker.h>
#include <QDialog>
#include <QProgressDialog>
#include <QTreeWidgetItem>
#include <QUuid>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
namespace Ui
{
class InstallDialog;
}
/**
* a dialog presented to manually define how a mod is to be installed. It provides
* a tree view of the file contents that can modified directly
**/
class InstallDialog : public MOBase::TutorableDialog
{
Q_OBJECT
public:
/**
* @brief Create a new install dialog for the given tree. The tree
* is "own" by the dialog, i.e., any change made by the user is immediately
* reflected to the given tree, except for the changes to the root.
*
* @param tree Tree structure describing the original archive structure.
* @param modName Name of the mod. The name can be modified through the dialog.
* @param modDataChecker The mod data checker to use to check.
* @param dataName The name of the data folder for the game.
* @param parent Parent widget.
**/
explicit InstallDialog(std::shared_ptr<MOBase::IFileTree> tree,
const MOBase::GuessedValue<QString>& modName,
std::shared_ptr<const MOBase::ModDataChecker> modDataChecker,
const QString& dataName, QWidget* parent = 0);
~InstallDialog();
/**
* @brief retrieve the (modified) mod name
*
* @return updated mod name
**/
QString getModName() const;
/**
* @brief Retrieve the user-modified directory structure.
*
* @return the new tree represented by this dialog, which can be a new
* tree or a subtree of the original tree.
**/
std::shared_ptr<MOBase::IFileTree> getModifiedTree() const;
signals:
/**
* @brief Signal emitted when user request the file corresponding
* to the given entry to be opened.
*
* @param entry Entry corresponding to the file to open.
*/
void openFile(const MOBase::FileTreeEntry* entry);
private:
bool testForProblem();
void updateProblems();
void createDirectoryUnder(ArchiveTreeWidgetItem* treeItem);
private slots:
// Automatic slots that are directly bound to the UI:
void on_treeContent_customContextMenuRequested(QPoint pos);
void on_cancelButton_clicked();
void on_okButton_clicked();
private:
Ui::InstallDialog* ui;
std::shared_ptr<const MOBase::ModDataChecker> m_Checker;
// Name of the "data" directory:
QString m_DataFolderName;
// the tree root is the initial root that will never change (should be const
// but cannot be since the parent tree cannot be constructed in the member
// initializer list)
//
// the tree root is not actually added to the tree, but is used to maintain
// the state of the tree and not lose entries when unsetting data root
//
ArchiveTreeWidget* m_Tree;
ArchiveTreeWidgetItem* m_TreeRoot;
QLabel* m_ProblemLabel;
};
#endif // INSTALLDIALOG_H
+130 -138
View File
@@ -1,138 +1,130 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer 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 3 of the License, or
(at your option) any later version.
Mod Organizer 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 Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "installermanual.h"
#include <igamefeatures.h>
#include <utility.h>
#include <iinstallationmanager.h>
#include <iplugingame.h>
#include <moddatachecker.h>
#include <QtPlugin>
#include <QDialog>
#include <Shellapi.h>
#include "installdialog.h"
using namespace MOBase;
InstallerManual::InstallerManual()
: m_MOInfo(nullptr)
{
}
bool InstallerManual::init(IOrganizer* moInfo)
{
m_MOInfo = moInfo;
return true;
}
QString InstallerManual::name() const
{
return "Manual Installer";
}
QString InstallerManual::localizedName() const
{
return tr("Manual Installer");
}
QString InstallerManual::author() const
{
return "Tannin, Holt59";
}
QString InstallerManual::description() const
{
return tr("Fallback installer for mods that can be extracted but can't be handled by another installer");
}
VersionInfo InstallerManual::version() const
{
return VersionInfo(1, 0, 1, VersionInfo::RELEASE_FINAL);
}
QList<PluginSetting> InstallerManual::settings() const
{
return QList<PluginSetting>();
}
unsigned int InstallerManual::priority() const
{
return 0;
}
bool InstallerManual::isManualInstaller() const
{
return true;
}
bool InstallerManual::isArchiveSupported(std::shared_ptr<const MOBase::IFileTree>) const
{
return true;
}
void InstallerManual::openFile(const FileTreeEntry* entry)
{
QString tempName = manager()->extractFile(entry->shared_from_this());
SHELLEXECUTEINFOW execInfo;
memset(&execInfo, 0, sizeof(SHELLEXECUTEINFOW));
execInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
execInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
execInfo.lpVerb = L"open";
std::wstring fileNameW = ToWString(tempName);
execInfo.lpFile = fileNameW.c_str();
execInfo.nShow = SW_SHOWNORMAL;
if (!::ShellExecuteExW(&execInfo)) {
qCritical("failed to spawn %s: %d", qUtf8Printable(tempName), ::GetLastError());
}
}
IPluginInstaller::EInstallResult InstallerManual::install(
GuessedValue<QString>& modName, std::shared_ptr<MOBase::IFileTree>& tree, QString&, int&)
{
qDebug("offering installation dialog");
InstallDialog dialog(tree, modName, m_MOInfo->gameFeatures()->gameFeature<ModDataChecker>(),
m_MOInfo->managedGame()->dataDirectory().dirName().toLower(), parentWidget());
connect(&dialog, &InstallDialog::openFile, this, &InstallerManual::openFile);
if (dialog.exec() == QDialog::Accepted) {
modName.update(dialog.getModName(), GUESS_USER);
// TODO probably more complicated than necessary
tree = dialog.getModifiedTree();
return IPluginInstaller::RESULT_SUCCESS;
}
else {
return IPluginInstaller::RESULT_CANCELED;
}
}
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
Q_EXPORT_PLUGIN2(installerManual, InstallerManual)
#endif
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer 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 3 of the License, or
(at your option) any later version.
Mod Organizer 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 Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#include "installermanual.h"
#include <igamefeatures.h>
#include <iinstallationmanager.h>
#include <iplugingame.h>
#include <moddatachecker.h>
#include <utility.h>
#include <QDialog>
#include <QtPlugin>
#include <Shellapi.h>
#include "installdialog.h"
using namespace MOBase;
InstallerManual::InstallerManual() : m_MOInfo(nullptr) {}
bool InstallerManual::init(IOrganizer* moInfo)
{
m_MOInfo = moInfo;
return true;
}
QString InstallerManual::name() const
{
return "Manual Installer";
}
QString InstallerManual::localizedName() const
{
return tr("Manual Installer");
}
QString InstallerManual::author() const
{
return "Tannin, Holt59";
}
QString InstallerManual::description() const
{
return tr("Fallback installer for mods that can be extracted but can't be handled by "
"another installer");
}
VersionInfo InstallerManual::version() const
{
return VersionInfo(1, 0, 1, VersionInfo::RELEASE_FINAL);
}
QList<PluginSetting> InstallerManual::settings() const
{
return QList<PluginSetting>();
}
unsigned int InstallerManual::priority() const
{
return 0;
}
bool InstallerManual::isManualInstaller() const
{
return true;
}
bool InstallerManual::isArchiveSupported(std::shared_ptr<const MOBase::IFileTree>) const
{
return true;
}
void InstallerManual::openFile(const FileTreeEntry* entry)
{
QString tempName = manager()->extractFile(entry->shared_from_this());
SHELLEXECUTEINFOW execInfo;
memset(&execInfo, 0, sizeof(SHELLEXECUTEINFOW));
execInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
execInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
execInfo.lpVerb = L"open";
std::wstring fileNameW = ToWString(tempName);
execInfo.lpFile = fileNameW.c_str();
execInfo.nShow = SW_SHOWNORMAL;
if (!::ShellExecuteExW(&execInfo)) {
qCritical("failed to spawn %s: %d", qUtf8Printable(tempName), ::GetLastError());
}
}
IPluginInstaller::EInstallResult
InstallerManual::install(GuessedValue<QString>& modName,
std::shared_ptr<MOBase::IFileTree>& tree, QString&, int&)
{
qDebug("offering installation dialog");
InstallDialog dialog(
tree, modName, m_MOInfo->gameFeatures()->gameFeature<ModDataChecker>(),
m_MOInfo->managedGame()->dataDirectory().dirName().toLower(), parentWidget());
connect(&dialog, &InstallDialog::openFile, this, &InstallerManual::openFile);
if (dialog.exec() == QDialog::Accepted) {
modName.update(dialog.getModName(), GUESS_USER);
// TODO probably more complicated than necessary
tree = dialog.getModifiedTree();
return IPluginInstaller::RESULT_SUCCESS;
} else {
return IPluginInstaller::RESULT_CANCELED;
}
}
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
Q_EXPORT_PLUGIN2(installerManual, InstallerManual)
#endif
+72 -75
View File
@@ -1,75 +1,72 @@
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer 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 3 of the License, or
(at your option) any later version.
Mod Organizer 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 Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INSTALLERMANUAL_H
#define INSTALLERMANUAL_H
#include <imoinfo.h>
#include <iplugininstallersimple.h>
class InstallerManual : public MOBase::IPluginInstallerSimple
{
Q_OBJECT
Q_INTERFACES(MOBase::IPlugin MOBase::IPluginInstaller MOBase::IPluginInstallerSimple)
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
Q_PLUGIN_METADATA(IID "org.tannin.InstallerManual" FILE "installermanual.json")
#endif
public:
InstallerManual();
virtual bool init(MOBase::IOrganizer* moInfo) override;
virtual QString name() const override;
virtual QString localizedName() const override;
virtual QString author() const override;
virtual QString description() const override;
virtual MOBase::VersionInfo version() const override;
virtual QList<MOBase::PluginSetting> settings() const override;
virtual unsigned int priority() const;
virtual bool isManualInstaller() const;
virtual bool isArchiveSupported(std::shared_ptr<const MOBase::IFileTree> tree) const;
virtual EInstallResult install(MOBase::GuessedValue<QString> &modName, std::shared_ptr<MOBase::IFileTree> &tree,
QString &version, int &modID);
private:
bool isSimpleArchiveTopLayer(const std::shared_ptr<const MOBase::IFileTree> tree) const;
std::shared_ptr<const MOBase::IFileTree> getSimpleArchiveBase(const std::shared_ptr<const MOBase::IFileTree> tree) const;
private slots:
/**
* @brief Opens a file from the archive in the (system-)default editor/viewer.
*
* @param entry Entry corresponding to the file to open.
*/
void openFile(const MOBase::FileTreeEntry* entry);
private:
const MOBase::IOrganizer *m_MOInfo;
};
#endif // INSTALLERMANUAL_H
/*
Copyright (C) 2012 Sebastian Herbord. All rights reserved.
This file is part of Mod Organizer.
Mod Organizer 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 3 of the License, or
(at your option) any later version.
Mod Organizer 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 Mod Organizer. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INSTALLERMANUAL_H
#define INSTALLERMANUAL_H
#include <imoinfo.h>
#include <iplugininstallersimple.h>
class InstallerManual : public MOBase::IPluginInstallerSimple
{
Q_OBJECT
Q_INTERFACES(MOBase::IPlugin MOBase::IPluginInstaller MOBase::IPluginInstallerSimple)
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
Q_PLUGIN_METADATA(IID "org.tannin.InstallerManual" FILE "installermanual.json")
#endif
public:
InstallerManual();
virtual bool init(MOBase::IOrganizer* moInfo) override;
virtual QString name() const override;
virtual QString localizedName() const override;
virtual QString author() const override;
virtual QString description() const override;
virtual MOBase::VersionInfo version() const override;
virtual QList<MOBase::PluginSetting> settings() const override;
virtual unsigned int priority() const;
virtual bool isManualInstaller() const;
virtual bool isArchiveSupported(std::shared_ptr<const MOBase::IFileTree> tree) const;
virtual EInstallResult install(MOBase::GuessedValue<QString>& modName,
std::shared_ptr<MOBase::IFileTree>& tree,
QString& version, int& modID);
private:
bool
isSimpleArchiveTopLayer(const std::shared_ptr<const MOBase::IFileTree> tree) const;
std::shared_ptr<const MOBase::IFileTree>
getSimpleArchiveBase(const std::shared_ptr<const MOBase::IFileTree> tree) const;
private slots:
/**
* @brief Opens a file from the archive in the (system-)default editor/viewer.
*
* @param entry Entry corresponding to the file to open.
*/
void openFile(const MOBase::FileTreeEntry* entry);
private:
const MOBase::IOrganizer* m_MOInfo;
};
#endif // INSTALLERMANUAL_H