mirror of
https://github.com/ModOrganizer2/modorganizer-installer_manual.git
synced 2026-07-27 14:03:56 -07:00
Format files and add .gitattributes and .clang-format.
This commit is contained in:
@@ -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']
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+178
-187
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user