Merge branch 'master' into filter
Conflicts: apps/opencs/model/world/universalid.cpp apps/opencs/view/doc/view.cpp apps/opencs/view/world/subviews.cppactorid
commit
adb05737ee
@ -0,0 +1,81 @@
|
||||
|
||||
#include "cellcreator.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QSpinBox>
|
||||
#include <QLabel>
|
||||
|
||||
std::string CSVWorld::CellCreator::getId() const
|
||||
{
|
||||
if (mType->currentIndex()==0)
|
||||
return GenericCreator::getId();
|
||||
|
||||
std::ostringstream stream;
|
||||
|
||||
stream << "#" << mX->value() << " " << mY->value();
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
CSVWorld::CellCreator::CellCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id)
|
||||
: GenericCreator (data, undoStack, id)
|
||||
{
|
||||
mY = new QSpinBox (this);
|
||||
mY->setVisible (false);
|
||||
mY->setMinimum (std::numeric_limits<int>::min());
|
||||
mY->setMaximum (std::numeric_limits<int>::max());
|
||||
connect (mY, SIGNAL (valueChanged (int)), this, SLOT (valueChanged (int)));
|
||||
insertAtBeginning (mY, true);
|
||||
|
||||
mYLabel = new QLabel ("Y", this);
|
||||
mYLabel->setVisible (false);
|
||||
insertAtBeginning (mYLabel, false);
|
||||
|
||||
mX = new QSpinBox (this);
|
||||
mX->setVisible (false);
|
||||
mX->setMinimum (std::numeric_limits<int>::min());
|
||||
mX->setMaximum (std::numeric_limits<int>::max());
|
||||
connect (mX, SIGNAL (valueChanged (int)), this, SLOT (valueChanged (int)));
|
||||
insertAtBeginning (mX, true);
|
||||
|
||||
mXLabel = new QLabel ("X", this);
|
||||
mXLabel->setVisible (false);
|
||||
insertAtBeginning (mXLabel, false);
|
||||
|
||||
mType = new QComboBox (this);
|
||||
|
||||
mType->addItem ("Interior Cell");
|
||||
mType->addItem ("Exterior Cell");
|
||||
|
||||
connect (mType, SIGNAL (currentIndexChanged (int)), this, SLOT (setType (int)));
|
||||
|
||||
insertAtBeginning (mType, false);
|
||||
}
|
||||
|
||||
void CSVWorld::CellCreator::reset()
|
||||
{
|
||||
mX->setValue (0);
|
||||
mY->setValue (0);
|
||||
mType->setCurrentIndex (0);
|
||||
GenericCreator::reset();
|
||||
}
|
||||
|
||||
void CSVWorld::CellCreator::setType (int index)
|
||||
{
|
||||
setManualEditing (index==0);
|
||||
mXLabel->setVisible (index==1);
|
||||
mX->setVisible (index==1);
|
||||
mYLabel->setVisible (index==1);
|
||||
mY->setVisible (index==1);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void CSVWorld::CellCreator::valueChanged (int index)
|
||||
{
|
||||
update();
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
#ifndef CSV_WORLD_CELLCREATOR_H
|
||||
#define CSV_WORLD_CELLCREATOR_H
|
||||
|
||||
class QLabel;
|
||||
class QSpinBox;
|
||||
class QComboBox;
|
||||
|
||||
#include "genericcreator.hpp"
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class CellCreator : public GenericCreator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QComboBox *mType;
|
||||
QLabel *mXLabel;
|
||||
QSpinBox *mX;
|
||||
QLabel *mYLabel;
|
||||
QSpinBox *mY;
|
||||
|
||||
protected:
|
||||
|
||||
virtual std::string getId() const;
|
||||
|
||||
public:
|
||||
|
||||
CellCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id);
|
||||
|
||||
virtual void reset();
|
||||
|
||||
private slots:
|
||||
|
||||
void setType (int index);
|
||||
|
||||
void valueChanged (int index);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,13 @@
|
||||
|
||||
#include "creator.hpp"
|
||||
|
||||
CSVWorld::Creator:: ~Creator() {}
|
||||
|
||||
CSVWorld::CreatorFactoryBase::~CreatorFactoryBase() {}
|
||||
|
||||
|
||||
CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator (CSMWorld::Data& data,
|
||||
QUndoStack& undoStack, const CSMWorld::UniversalId& id) const
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
#ifndef CSV_WORLD_CREATOR_H
|
||||
#define CSV_WORLD_CREATOR_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QUndoStack;
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class Data;
|
||||
class UniversalId;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
/// \brief Record creator UI base class
|
||||
class Creator : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Creator();
|
||||
|
||||
virtual void reset() = 0;
|
||||
|
||||
virtual void setEditLock (bool locked) = 0;
|
||||
|
||||
signals:
|
||||
|
||||
void done();
|
||||
|
||||
void requestFocus (const std::string& id);
|
||||
///< Request owner of this creator to focus the just created \a id. The owner may
|
||||
/// ignore this request.
|
||||
};
|
||||
|
||||
/// \brief Base class for Creator factory
|
||||
class CreatorFactoryBase
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~CreatorFactoryBase();
|
||||
|
||||
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const = 0;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
///
|
||||
/// \note The function can return a 0-pointer, which means no UI for creating/deleting
|
||||
/// records should be provided.
|
||||
};
|
||||
|
||||
/// \brief Creator factory that does not produces any creator
|
||||
class NullCreatorFactory : public CreatorFactoryBase
|
||||
{
|
||||
public:
|
||||
|
||||
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
///
|
||||
/// \note The function always returns 0.
|
||||
};
|
||||
|
||||
template<class CreatorT>
|
||||
class CreatorFactory : public CreatorFactoryBase
|
||||
{
|
||||
public:
|
||||
|
||||
virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const;
|
||||
///< The ownership of the returned Creator is transferred to the caller.
|
||||
///
|
||||
/// \note The function can return a 0-pointer, which means no UI for creating/deleting
|
||||
/// records should be provided.
|
||||
};
|
||||
|
||||
template<class CreatorT>
|
||||
Creator *CreatorFactory<CreatorT>::makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id) const
|
||||
{
|
||||
return new CreatorT (data, undoStack, id);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,135 @@
|
||||
|
||||
#include "genericcreator.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QLineEdit>
|
||||
#include <QUndoStack>
|
||||
|
||||
#include "../../model/world/commands.hpp"
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/idtable.hpp"
|
||||
|
||||
#include "idvalidator.hpp"
|
||||
|
||||
void CSVWorld::GenericCreator::update()
|
||||
{
|
||||
mErrors = getErrors();
|
||||
|
||||
mCreate->setToolTip (QString::fromUtf8 (mErrors.c_str()));
|
||||
mId->setToolTip (QString::fromUtf8 (mErrors.c_str()));
|
||||
|
||||
mCreate->setEnabled (mErrors.empty() && !mLocked);
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::setManualEditing (bool enabled)
|
||||
{
|
||||
mId->setVisible (enabled);
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::insertAtBeginning (QWidget *widget, bool stretched)
|
||||
{
|
||||
mLayout->insertWidget (0, widget, stretched ? 1 : 0);
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::insertBeforeButtons (QWidget *widget, bool stretched)
|
||||
{
|
||||
mLayout->insertWidget (mLayout->count()-2, widget, stretched ? 1 : 0);
|
||||
}
|
||||
|
||||
std::string CSVWorld::GenericCreator::getId() const
|
||||
{
|
||||
return mId->text().toUtf8().constData();
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const {}
|
||||
|
||||
const CSMWorld::Data& CSVWorld::GenericCreator::getData() const
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
|
||||
CSMWorld::Data& CSVWorld::GenericCreator::getData()
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
|
||||
CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id)
|
||||
: mData (data), mUndoStack (undoStack), mListId (id), mLocked (false)
|
||||
{
|
||||
mLayout = new QHBoxLayout;
|
||||
mLayout->setContentsMargins (0, 0, 0, 0);
|
||||
|
||||
mId = new QLineEdit;
|
||||
mId->setValidator (new IdValidator (this));
|
||||
mLayout->addWidget (mId, 1);
|
||||
|
||||
mCreate = new QPushButton ("Create");
|
||||
mLayout->addWidget (mCreate);
|
||||
|
||||
QPushButton *cancelButton = new QPushButton ("Cancel");
|
||||
mLayout->addWidget (cancelButton);
|
||||
|
||||
setLayout (mLayout);
|
||||
|
||||
connect (cancelButton, SIGNAL (clicked (bool)), this, SIGNAL (done()));
|
||||
connect (mCreate, SIGNAL (clicked (bool)), this, SLOT (create()));
|
||||
|
||||
connect (mId, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&)));
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::setEditLock (bool locked)
|
||||
{
|
||||
mLocked = locked;
|
||||
update();
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::reset()
|
||||
{
|
||||
mId->setText ("");
|
||||
update();
|
||||
}
|
||||
|
||||
std::string CSVWorld::GenericCreator::getErrors() const
|
||||
{
|
||||
std::string errors;
|
||||
|
||||
std::string id = getId();
|
||||
|
||||
if (id.empty())
|
||||
{
|
||||
errors = "Missing ID";
|
||||
}
|
||||
else if (mData.hasId (id))
|
||||
{
|
||||
errors = "ID is already in use";
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::textChanged (const QString& text)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void CSVWorld::GenericCreator::create()
|
||||
{
|
||||
if (!mLocked)
|
||||
{
|
||||
std::string id = getId();
|
||||
|
||||
std::auto_ptr<CSMWorld::CreateCommand> command (new CSMWorld::CreateCommand (
|
||||
dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel (mListId)), id));
|
||||
|
||||
configureCreateCommand (*command);
|
||||
|
||||
mUndoStack.push (command.release());
|
||||
|
||||
emit done();
|
||||
emit requestFocus (id);
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
#ifndef CSV_WORLD_GENERICCREATOR_H
|
||||
#define CSV_WORLD_GENERICCREATOR_H
|
||||
|
||||
class QPushButton;
|
||||
class QLineEdit;
|
||||
class QHBoxLayout;
|
||||
|
||||
#include "creator.hpp"
|
||||
|
||||
#include "../../model/world/universalid.hpp"
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class CreateCommand;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class GenericCreator : public Creator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
CSMWorld::Data& mData;
|
||||
QUndoStack& mUndoStack;
|
||||
CSMWorld::UniversalId mListId;
|
||||
QPushButton *mCreate;
|
||||
QLineEdit *mId;
|
||||
std::string mErrors;
|
||||
QHBoxLayout *mLayout;
|
||||
bool mLocked;
|
||||
|
||||
protected:
|
||||
|
||||
void update();
|
||||
|
||||
virtual void setManualEditing (bool enabled);
|
||||
///< Enable/disable manual ID editing (enabled by default).
|
||||
|
||||
void insertAtBeginning (QWidget *widget, bool stretched);
|
||||
|
||||
void insertBeforeButtons (QWidget *widget, bool stretched);
|
||||
|
||||
virtual std::string getId() const;
|
||||
|
||||
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
|
||||
|
||||
const CSMWorld::Data& getData() const;
|
||||
|
||||
CSMWorld::Data& getData();
|
||||
|
||||
public:
|
||||
|
||||
GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id);
|
||||
|
||||
virtual void setEditLock (bool locked);
|
||||
|
||||
virtual void reset();
|
||||
|
||||
virtual std::string getErrors() const;
|
||||
///< Return formatted error descriptions for the current state of the creator. if an empty
|
||||
/// string is returned, there is no error.
|
||||
|
||||
|
||||
private slots:
|
||||
|
||||
void textChanged (const QString& text);
|
||||
|
||||
void create();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,26 @@
|
||||
|
||||
#include "idvalidator.hpp"
|
||||
|
||||
bool CSVWorld::IdValidator::isValid (const QChar& c, bool first) const
|
||||
{
|
||||
if (c.isLetter() || c=='_')
|
||||
return true;
|
||||
|
||||
if (!first && (c.isDigit() || c.isSpace()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
CSVWorld::IdValidator::IdValidator (QObject *parent) : QValidator (parent) {}
|
||||
|
||||
QValidator::State CSVWorld::IdValidator::validate (QString& input, int& pos) const
|
||||
{
|
||||
bool first = true;
|
||||
|
||||
for (QString::const_iterator iter (input.begin()); iter!=input.end(); ++iter, first = false)
|
||||
if (!isValid (*iter, first))
|
||||
return QValidator::Invalid;
|
||||
|
||||
return QValidator::Acceptable;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
#ifndef CSV_WORLD_IDVALIDATOR_H
|
||||
#define CSV_WORLD_IDVALIDATOR_H
|
||||
|
||||
#include <QValidator>
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class IdValidator : public QValidator
|
||||
{
|
||||
private:
|
||||
|
||||
bool isValid (const QChar& c, bool first) const;
|
||||
|
||||
public:
|
||||
|
||||
IdValidator (QObject *parent = 0);
|
||||
|
||||
virtual State validate (QString& input, int& pos) const;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,43 @@
|
||||
|
||||
#include "referenceablecreator.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QLabel>
|
||||
|
||||
#include "../../model/world/universalid.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
|
||||
void CSVWorld::ReferenceableCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
|
||||
{
|
||||
command.setType (
|
||||
static_cast<CSMWorld::UniversalId::Type> (mType->itemData (mType->currentIndex()).toInt()));
|
||||
}
|
||||
|
||||
CSVWorld::ReferenceableCreator::ReferenceableCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id)
|
||||
: GenericCreator (data, undoStack, id)
|
||||
{
|
||||
QLabel *label = new QLabel ("Type", this);
|
||||
insertBeforeButtons (label, false);
|
||||
|
||||
std::vector<CSMWorld::UniversalId::Type> types = CSMWorld::UniversalId::listReferenceableTypes();
|
||||
|
||||
mType = new QComboBox (this);
|
||||
|
||||
for (std::vector<CSMWorld::UniversalId::Type>::const_iterator iter (types.begin());
|
||||
iter!=types.end(); ++iter)
|
||||
{
|
||||
CSMWorld::UniversalId id (*iter, "");
|
||||
|
||||
mType->addItem (QIcon (id.getIcon().c_str()), id.getTypeName().c_str(),
|
||||
static_cast<int> (id.getType()));
|
||||
}
|
||||
|
||||
insertBeforeButtons (mType, false);
|
||||
}
|
||||
|
||||
void CSVWorld::ReferenceableCreator::reset()
|
||||
{
|
||||
mType->setCurrentIndex (0);
|
||||
GenericCreator::reset();
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
#ifndef CSV_WORLD_REFERENCEABLECREATOR_H
|
||||
#define CSV_WORLD_REFERENCEABLECREATOR_H
|
||||
|
||||
class QComboBox;
|
||||
|
||||
#include "genericcreator.hpp"
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class ReferenceableCreator : public GenericCreator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QComboBox *mType;
|
||||
|
||||
private:
|
||||
|
||||
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
|
||||
|
||||
public:
|
||||
|
||||
ReferenceableCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id);
|
||||
|
||||
virtual void reset();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,70 @@
|
||||
|
||||
#include "referencecreator.hpp"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
|
||||
std::string CSVWorld::ReferenceCreator::getId() const
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
void CSVWorld::ReferenceCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
|
||||
{
|
||||
/// \todo avoid using hard-coded column numbers
|
||||
command.addValue (2, mCell->text());
|
||||
}
|
||||
|
||||
CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id)
|
||||
: GenericCreator (data, undoStack, id)
|
||||
{
|
||||
QLabel *label = new QLabel ("Cell", this);
|
||||
insertBeforeButtons (label, false);
|
||||
|
||||
mCell = new QLineEdit (this);
|
||||
insertBeforeButtons (mCell, true);
|
||||
|
||||
setManualEditing (false);
|
||||
|
||||
connect (mCell, SIGNAL (textChanged (const QString&)), this, SLOT (cellChanged()));
|
||||
}
|
||||
|
||||
void CSVWorld::ReferenceCreator::reset()
|
||||
{
|
||||
mCell->setText ("");
|
||||
mId = getData().getReferences().getNewId();
|
||||
GenericCreator::reset();
|
||||
}
|
||||
|
||||
std::string CSVWorld::ReferenceCreator::getErrors() const
|
||||
{
|
||||
std::string errors = GenericCreator::getErrors();
|
||||
|
||||
std::string cell = mCell->text().toUtf8().constData();
|
||||
|
||||
if (cell.empty())
|
||||
{
|
||||
if (!errors.empty())
|
||||
errors += "<br>";
|
||||
|
||||
errors += "Missing Cell ID";
|
||||
}
|
||||
else if (getData().getCells().searchId (cell)==-1)
|
||||
{
|
||||
if (!errors.empty())
|
||||
errors += "<br>";
|
||||
|
||||
errors += "Invalid Cell ID";
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
void CSVWorld::ReferenceCreator::cellChanged()
|
||||
{
|
||||
update();
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
#ifndef CSV_WORLD_REFERENCECREATOR_H
|
||||
#define CSV_WORLD_REFERENCECREATOR_H
|
||||
|
||||
#include "genericcreator.hpp"
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class ReferenceCreator : public GenericCreator
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QLineEdit *mCell;
|
||||
std::string mId;
|
||||
|
||||
private:
|
||||
|
||||
virtual std::string getId() const;
|
||||
|
||||
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
|
||||
|
||||
public:
|
||||
|
||||
ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack,
|
||||
const CSMWorld::UniversalId& id);
|
||||
|
||||
virtual void reset();
|
||||
|
||||
virtual std::string getErrors() const;
|
||||
///< Return formatted error descriptions for the current state of the creator. if an empty
|
||||
/// string is returned, there is no error.
|
||||
|
||||
private slots:
|
||||
|
||||
void cellChanged();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,156 @@
|
||||
|
||||
#include "tablebottombox.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <QStatusBar>
|
||||
#include <QStackedLayout>
|
||||
#include <QLabel>
|
||||
|
||||
#include "creator.hpp"
|
||||
|
||||
void CSVWorld::TableBottomBox::updateStatus()
|
||||
{
|
||||
if (mShowStatusBar)
|
||||
{
|
||||
static const char *sLabels[4] = { "record", "deleted", "touched", "selected" };
|
||||
static const char *sLabelsPlural[4] = { "records", "deleted", "touched", "selected" };
|
||||
|
||||
std::ostringstream stream;
|
||||
|
||||
bool first = true;
|
||||
|
||||
for (int i=0; i<4; ++i)
|
||||
{
|
||||
if (mStatusCount[i]>0)
|
||||
{
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
stream << ", ";
|
||||
|
||||
stream
|
||||
<< mStatusCount[i] << ' '
|
||||
<< (mStatusCount[i]==1 ? sLabels[i] : sLabelsPlural[i]);
|
||||
}
|
||||
}
|
||||
|
||||
mStatus->setText (QString::fromUtf8 (stream.str().c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory,
|
||||
CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, QWidget *parent)
|
||||
: QWidget (parent), mShowStatusBar (false), mCreating (false)
|
||||
{
|
||||
for (int i=0; i<4; ++i)
|
||||
mStatusCount[i] = 0;
|
||||
|
||||
setVisible (false);
|
||||
|
||||
mLayout = new QStackedLayout;
|
||||
mLayout->setContentsMargins (0, 0, 0, 0);
|
||||
|
||||
mStatus = new QLabel;
|
||||
|
||||
mStatusBar = new QStatusBar;
|
||||
|
||||
mStatusBar->addWidget (mStatus);
|
||||
|
||||
mLayout->addWidget (mStatusBar);
|
||||
|
||||
setLayout (mLayout);
|
||||
|
||||
mCreator = creatorFactory.makeCreator (data, undoStack, id);
|
||||
|
||||
mLayout->addWidget (mCreator);
|
||||
|
||||
connect (mCreator, SIGNAL (done()), this, SLOT (createRequestDone()));
|
||||
|
||||
connect (mCreator, SIGNAL (requestFocus (const std::string&)),
|
||||
this, SIGNAL (requestFocus (const std::string&)));
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::setEditLock (bool locked)
|
||||
{
|
||||
if (mCreator)
|
||||
mCreator->setEditLock (locked);
|
||||
}
|
||||
|
||||
CSVWorld::TableBottomBox::~TableBottomBox()
|
||||
{
|
||||
delete mCreator;
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::setStatusBar (bool show)
|
||||
{
|
||||
if (show!=mShowStatusBar)
|
||||
{
|
||||
setVisible (show || mCreating);
|
||||
|
||||
mShowStatusBar = show;
|
||||
|
||||
if (show)
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
bool CSVWorld::TableBottomBox::canCreateAndDelete() const
|
||||
{
|
||||
return mCreator;
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::createRequestDone()
|
||||
{
|
||||
if (!mShowStatusBar)
|
||||
setVisible (false);
|
||||
else
|
||||
updateStatus();
|
||||
|
||||
mLayout->setCurrentWidget (mStatusBar);
|
||||
|
||||
mCreating = false;
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::selectionSizeChanged (int size)
|
||||
{
|
||||
if (mStatusCount[3]!=size)
|
||||
{
|
||||
mStatusCount[3] = size;
|
||||
updateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::tableSizeChanged (int size, int deleted, int modified)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (mStatusCount[0]!=size)
|
||||
{
|
||||
mStatusCount[0] = size;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (mStatusCount[1]!=deleted)
|
||||
{
|
||||
mStatusCount[1] = deleted;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (mStatusCount[2]!=modified)
|
||||
{
|
||||
mStatusCount[2] = modified;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
updateStatus();
|
||||
}
|
||||
|
||||
void CSVWorld::TableBottomBox::createRequest()
|
||||
{
|
||||
mCreator->reset();
|
||||
mLayout->setCurrentWidget (mCreator);
|
||||
setVisible (true);
|
||||
mCreating = true;
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
#ifndef CSV_WORLD_BOTTOMBOX_H
|
||||
#define CSV_WORLD_BOTTOMBOX_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QLabel;
|
||||
class QStackedLayout;
|
||||
class QStatusBar;
|
||||
class QUndoStack;
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class Data;
|
||||
class UniversalId;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
{
|
||||
class CreatorFactoryBase;
|
||||
class Creator;
|
||||
|
||||
class TableBottomBox : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
bool mShowStatusBar;
|
||||
QLabel *mStatus;
|
||||
QStatusBar *mStatusBar;
|
||||
int mStatusCount[4];
|
||||
Creator *mCreator;
|
||||
bool mCreating;
|
||||
QStackedLayout *mLayout;
|
||||
|
||||
private:
|
||||
|
||||
// not implemented
|
||||
TableBottomBox (const TableBottomBox&);
|
||||
TableBottomBox& operator= (const TableBottomBox&);
|
||||
|
||||
void updateStatus();
|
||||
|
||||
public:
|
||||
|
||||
TableBottomBox (const CreatorFactoryBase& creatorFactory, CSMWorld::Data& data,
|
||||
QUndoStack& undoStack, const CSMWorld::UniversalId& id, QWidget *parent = 0);
|
||||
|
||||
virtual ~TableBottomBox();
|
||||
|
||||
void setEditLock (bool locked);
|
||||
|
||||
void setStatusBar (bool show);
|
||||
|
||||
bool canCreateAndDelete() const;
|
||||
///< Is record creation and deletion supported?
|
||||
///
|
||||
/// \note The BotomBox does not partake in the deletion of records.
|
||||
|
||||
signals:
|
||||
|
||||
void requestFocus (const std::string& id);
|
||||
///< Request owner of this box to focus the just created \a id. The owner may
|
||||
/// ignore this request.
|
||||
|
||||
private slots:
|
||||
|
||||
void createRequestDone();
|
||||
///< \note This slot being called does not imply success.
|
||||
|
||||
public slots:
|
||||
|
||||
void selectionSizeChanged (int size);
|
||||
|
||||
void tableSizeChanged (int size, int deleted, int modified);
|
||||
///< \param size Number of not deleted records
|
||||
/// \param deleted Number of deleted records
|
||||
/// \param modified Number of added and modified records
|
||||
|
||||
void createRequest();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,115 @@
|
||||
#include "sdlwindowhelper.hpp"
|
||||
|
||||
#include <OgreStringConverter.h>
|
||||
#include <OgreRoot.h>
|
||||
|
||||
#include <SDL_syswm.h>
|
||||
#include <SDL_endian.h>
|
||||
|
||||
namespace SFO
|
||||
{
|
||||
|
||||
SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h,
|
||||
const std::string& title, bool fullscreen, Ogre::NameValuePairList params)
|
||||
: mSDLWindow(window)
|
||||
{
|
||||
//get the native whnd
|
||||
struct SDL_SysWMinfo wmInfo;
|
||||
SDL_VERSION(&wmInfo.version);
|
||||
|
||||
if (SDL_GetWindowWMInfo(mSDLWindow, &wmInfo) == -1)
|
||||
throw std::runtime_error("Couldn't get WM Info!");
|
||||
|
||||
Ogre::String winHandle;
|
||||
|
||||
switch (wmInfo.subsystem)
|
||||
{
|
||||
#ifdef WIN32
|
||||
case SDL_SYSWM_WINDOWS:
|
||||
// Windows code
|
||||
winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.win.window);
|
||||
break;
|
||||
#elif __MACOSX__
|
||||
case SDL_SYSWM_COCOA:
|
||||
//required to make OGRE play nice with our window
|
||||
params.insert(std::make_pair("macAPI", "cocoa"));
|
||||
params.insert(std::make_pair("macAPICocoaUseNSView", "true"));
|
||||
|
||||
winHandle = Ogre::StringConverter::toString(WindowContentViewHandle(wmInfo));
|
||||
break;
|
||||
#else
|
||||
case SDL_SYSWM_X11:
|
||||
winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.x11.window);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
throw std::runtime_error("Unexpected WM!");
|
||||
break;
|
||||
}
|
||||
|
||||
/// \todo externalWindowHandle is deprecated according to the source code. Figure out a way to get parentWindowHandle
|
||||
/// to work properly. On Linux/X11 it causes an occasional GLXBadDrawable error.
|
||||
params.insert(std::make_pair("externalWindowHandle", winHandle));
|
||||
|
||||
mWindow = Ogre::Root::getSingleton().createRenderWindow(title, w, h, fullscreen, ¶ms);
|
||||
}
|
||||
|
||||
void SDLWindowHelper::setWindowIcon(const std::string &name)
|
||||
{
|
||||
Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().load(name, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
|
||||
if (texture.isNull())
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Window icon not found: " << name;
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
Ogre::Image image;
|
||||
texture->convertToImage(image);
|
||||
|
||||
SDL_Surface* surface = SDL_CreateRGBSurface(0,texture->getWidth(),texture->getHeight(),32,0xFF000000,0x00FF0000,0x0000FF00,0x000000FF);
|
||||
|
||||
//copy the Ogre texture to an SDL surface
|
||||
for(size_t x = 0; x < texture->getWidth(); ++x)
|
||||
{
|
||||
for(size_t y = 0; y < texture->getHeight(); ++y)
|
||||
{
|
||||
Ogre::ColourValue clr = image.getColourAt(x, y, 0);
|
||||
|
||||
//set the pixel on the SDL surface to the same value as the Ogre texture's
|
||||
int bpp = surface->format->BytesPerPixel;
|
||||
/* Here p is the address to the pixel we want to set */
|
||||
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
|
||||
Uint32 pixel = SDL_MapRGBA(surface->format, clr.r*255, clr.g*255, clr.b*255, clr.a*255);
|
||||
switch(bpp) {
|
||||
case 1:
|
||||
*p = pixel;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
*(Uint16 *)p = pixel;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
|
||||
p[0] = (pixel >> 16) & 0xff;
|
||||
p[1] = (pixel >> 8) & 0xff;
|
||||
p[2] = pixel & 0xff;
|
||||
} else {
|
||||
p[0] = pixel & 0xff;
|
||||
p[1] = (pixel >> 8) & 0xff;
|
||||
p[2] = (pixel >> 16) & 0xff;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
*(Uint32 *)p = pixel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SetWindowIcon(mSDLWindow, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
#ifndef SDL4OGRE_SDLWINDOWHELPER_H
|
||||
#define SDL4OGRE_SDLWINDOWHELPER_H
|
||||
|
||||
#include <OgreRenderWindow.h>
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class RenderWindow;
|
||||
}
|
||||
struct SDL_Window;
|
||||
|
||||
namespace SFO
|
||||
{
|
||||
|
||||
/// @brief Creates an Ogre window from an SDL window and allows setting an Ogre texture as window icon
|
||||
class SDLWindowHelper
|
||||
{
|
||||
public:
|
||||
SDLWindowHelper (SDL_Window* window, int w, int h, const std::string& title, bool fullscreen, Ogre::NameValuePairList params);
|
||||
void setWindowIcon(const std::string& name);
|
||||
Ogre::RenderWindow* getWindow() { return mWindow; }
|
||||
|
||||
private:
|
||||
Ogre::RenderWindow* mWindow;
|
||||
SDL_Window* mSDLWindow;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue