1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-03 16:39:41 +00:00

Merge branch 'master' of https://github.com/OpenMW/openmw into osg

Conflicts:
	apps/opencs/CMakeLists.txt
	apps/opencs/model/doc/document.cpp
	apps/opencs/model/doc/document.hpp
This commit is contained in:
scrawl 2015-06-07 15:23:54 +02:00
commit e66e9916db
40 changed files with 570 additions and 44 deletions

View file

@ -490,7 +490,7 @@ bool Launcher::MainDialog::writeSettings()
// Game settings // Game settings
QFile file(userPath + QString("openmw.cfg")); QFile file(userPath + QString("openmw.cfg"));
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
// File cannot be opened or created // File cannot be opened or created
QMessageBox msgBox; QMessageBox msgBox;
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
@ -503,10 +503,8 @@ bool Launcher::MainDialog::writeSettings()
return false; return false;
} }
QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-8"));
mGameSettings.writeFile(stream); mGameSettings.writeFileWithComments(file);
file.close(); file.close();
// Graphics settings // Graphics settings
@ -525,6 +523,7 @@ bool Launcher::MainDialog::writeSettings()
return false; return false;
} }
QTextStream stream(&file);
stream.setDevice(&file); stream.setDevice(&file);
stream.setCodec(QTextCodec::codecForName("UTF-8")); stream.setCodec(QTextCodec::codecForName("UTF-8"));

View file

@ -26,6 +26,7 @@ opencs_units_noqt (model/world
universalid record commands columnbase scriptcontext cell refidcollection universalid record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection
idcompletionmanager
) )
opencs_hdrs_noqt (model/world opencs_hdrs_noqt (model/world
@ -68,12 +69,12 @@ opencs_units (view/world
opencs_units_noqt (view/world opencs_units_noqt (view/world
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
scripthighlighter idvalidator dialoguecreator scripthighlighter idvalidator dialoguecreator idcompletiondelegate
) )
opencs_units (view/widget opencs_units (view/widget
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton
scenetooltoggle2 scenetooltoggle2 completerpopup
) )
opencs_units (view/render opencs_units (view/render

View file

@ -2256,7 +2256,7 @@ CSMDoc::Document::Document (const VFS::Manager* vfs, const Files::ConfigurationM
mSavingOperation (*this, mProjectPath, encoding), mSavingOperation (*this, mProjectPath, encoding),
mSaving (&mSavingOperation), mSaving (&mSavingOperation),
mResDir(resDir), mResDir(resDir),
mRunner (mProjectPath) mRunner (mProjectPath), mIdCompletionManager(mData)
{ {
if (mContentFiles.empty()) if (mContentFiles.empty())
throw std::runtime_error ("Empty content file sequence"); throw std::runtime_error ("Empty content file sequence");
@ -2484,3 +2484,8 @@ void CSMDoc::Document::progress (int current, int max, int type)
{ {
emit progress (current, max, type, 1, this); emit progress (current, max, type, 1, this);
} }
CSMWorld::IdCompletionManager &CSMDoc::Document::getIdCompletionManager()
{
return mIdCompletionManager;
}

View file

@ -13,6 +13,7 @@
#include <components/to_utf8/to_utf8.hpp> #include <components/to_utf8/to_utf8.hpp>
#include "../world/data.hpp" #include "../world/data.hpp"
#include "../world/idcompletionmanager.hpp"
#include "../tools/tools.hpp" #include "../tools/tools.hpp"
@ -68,6 +69,8 @@ namespace CSMDoc
Blacklist mBlacklist; Blacklist mBlacklist;
Runner mRunner; Runner mRunner;
CSMWorld::IdCompletionManager mIdCompletionManager;
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is // It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is
// using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late. // using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late.
QUndoStack mUndoStack; QUndoStack mUndoStack;
@ -145,6 +148,8 @@ namespace CSMDoc
QTextDocument *getRunLog(); QTextDocument *getRunLog();
CSMWorld::IdCompletionManager &getIdCompletionManager();
signals: signals:
void stateChanged (int state, CSMDoc::Document *document); void stateChanged (int state, CSMDoc::Document *document);

View file

@ -65,6 +65,8 @@ bool CSMWorld::ColumnBase::isId (Display display)
Display_JournalInfo, Display_JournalInfo,
Display_Scene, Display_Scene,
Display_GlobalVariable, Display_GlobalVariable,
Display_BodyPart,
Display_Enchantment,
Display_Script, Display_Script,
Display_Mesh, Display_Mesh,

View file

@ -74,6 +74,8 @@ namespace CSMWorld
Display_JournalInfo, Display_JournalInfo,
Display_Scene, Display_Scene,
Display_GlobalVariable, Display_GlobalVariable,
Display_BodyPart,
Display_Enchantment,
//CONCRETE TYPES ENDS HERE //CONCRETE TYPES ENDS HERE
Display_Integer, Display_Integer,

View file

@ -709,7 +709,7 @@ namespace CSMWorld
struct SleepListColumn : public Column<ESXRecordT> struct SleepListColumn : public Column<ESXRecordT>
{ {
SleepListColumn() SleepListColumn()
: Column<ESXRecordT> (Columns::ColumnId_SleepEncounter, ColumnBase::Display_String) : Column<ESXRecordT> (Columns::ColumnId_SleepEncounter, ColumnBase::Display_CreatureLevelledList)
{} {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
@ -735,7 +735,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct TextureColumn : public Column<ESXRecordT> struct TextureColumn : public Column<ESXRecordT>
{ {
TextureColumn() : Column<ESXRecordT> (Columns::ColumnId_Texture, ColumnBase::Display_String) {} TextureColumn() : Column<ESXRecordT> (Columns::ColumnId_Texture, ColumnBase::Display_Texture) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -1269,7 +1269,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct TrapColumn : public Column<ESXRecordT> struct TrapColumn : public Column<ESXRecordT>
{ {
TrapColumn() : Column<ESXRecordT> (Columns::ColumnId_Trap, ColumnBase::Display_String) {} TrapColumn() : Column<ESXRecordT> (Columns::ColumnId_Trap, ColumnBase::Display_Spell) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -1294,7 +1294,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct FilterColumn : public Column<ESXRecordT> struct FilterColumn : public Column<ESXRecordT>
{ {
FilterColumn() : Column<ESXRecordT> (Columns::ColumnId_Filter, ColumnBase::Display_String) {} FilterColumn() : Column<ESXRecordT> (Columns::ColumnId_Filter, ColumnBase::Display_Filter) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -1497,7 +1497,10 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct TopicColumn : public Column<ESXRecordT> struct TopicColumn : public Column<ESXRecordT>
{ {
TopicColumn (bool journal) : Column<ESXRecordT> (journal ? Columns::ColumnId_Journal : Columns::ColumnId_Topic, ColumnBase::Display_String) {} TopicColumn (bool journal)
: Column<ESXRecordT> (journal ? Columns::ColumnId_Journal : Columns::ColumnId_Topic,
journal ? ColumnBase::Display_Journal : ColumnBase::Display_Topic)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -1527,7 +1530,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct ActorColumn : public Column<ESXRecordT> struct ActorColumn : public Column<ESXRecordT>
{ {
ActorColumn() : Column<ESXRecordT> (Columns::ColumnId_Actor, ColumnBase::Display_String) {} ActorColumn() : Column<ESXRecordT> (Columns::ColumnId_Actor, ColumnBase::Display_Npc) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -1830,7 +1833,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct ModelColumn : public Column<ESXRecordT> struct ModelColumn : public Column<ESXRecordT>
{ {
ModelColumn() : Column<ESXRecordT> (Columns::ColumnId_Model, ColumnBase::Display_String) {} ModelColumn() : Column<ESXRecordT> (Columns::ColumnId_Model, ColumnBase::Display_Mesh) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -2158,7 +2161,9 @@ namespace CSMWorld
struct EffectTextureColumn : public Column<ESXRecordT> struct EffectTextureColumn : public Column<ESXRecordT>
{ {
EffectTextureColumn (Columns::ColumnId columnId) EffectTextureColumn (Columns::ColumnId columnId)
: Column<ESXRecordT> (columnId, ColumnBase::Display_Texture) : Column<ESXRecordT> (columnId,
columnId == Columns::ColumnId_Particle ? ColumnBase::Display_Texture
: ColumnBase::Display_Icon)
{ {
assert (this->mColumnId==Columns::ColumnId_Icon || assert (this->mColumnId==Columns::ColumnId_Icon ||
this->mColumnId==Columns::ColumnId_Particle); this->mColumnId==Columns::ColumnId_Particle);

View file

@ -115,7 +115,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
index = mFactions.getColumns()-1; index = mFactions.getColumns()-1;
mFactions.addAdapter (std::make_pair(&mFactions.getColumn(index), new FactionReactionsAdapter ())); mFactions.addAdapter (std::make_pair(&mFactions.getColumn(index), new FactionReactionsAdapter ()));
mFactions.getNestableColumn(index)->addColumn( mFactions.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_Faction, ColumnBase::Display_String)); new NestedChildColumn (Columns::ColumnId_Faction, ColumnBase::Display_Faction));
mFactions.getNestableColumn(index)->addColumn( mFactions.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_FactionReaction, ColumnBase::Display_Integer)); new NestedChildColumn (Columns::ColumnId_FactionReaction, ColumnBase::Display_Integer));
@ -135,7 +135,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
index = mRaces.getColumns()-1; index = mRaces.getColumns()-1;
mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new SpellListAdapter<ESM::Race> ())); mRaces.addAdapter (std::make_pair(&mRaces.getColumn(index), new SpellListAdapter<ESM::Race> ()));
mRaces.getNestableColumn(index)->addColumn( mRaces.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_String)); new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_Spell));
// Race attributes // Race attributes
mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceAttributes)); mRaces.addColumn (new NestedParentColumn<ESM::Race> (Columns::ColumnId_RaceAttributes));
index = mRaces.getColumns()-1; index = mRaces.getColumns()-1;
@ -180,7 +180,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
index = mRegions.getColumns()-1; index = mRegions.getColumns()-1;
mRegions.addAdapter (std::make_pair(&mRegions.getColumn(index), new RegionSoundListAdapter ())); mRegions.addAdapter (std::make_pair(&mRegions.getColumn(index), new RegionSoundListAdapter ()));
mRegions.getNestableColumn(index)->addColumn( mRegions.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_SoundName, ColumnBase::Display_String)); new NestedChildColumn (Columns::ColumnId_SoundName, ColumnBase::Display_Sound));
mRegions.getNestableColumn(index)->addColumn( mRegions.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_SoundChance, ColumnBase::Display_Integer)); new NestedChildColumn (Columns::ColumnId_SoundChance, ColumnBase::Display_Integer));
@ -196,7 +196,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mBirthsigns.addAdapter (std::make_pair(&mBirthsigns.getColumn(index), mBirthsigns.addAdapter (std::make_pair(&mBirthsigns.getColumn(index),
new SpellListAdapter<ESM::BirthSign> ())); new SpellListAdapter<ESM::BirthSign> ()));
mBirthsigns.getNestableColumn(index)->addColumn( mBirthsigns.getNestableColumn(index)->addColumn(
new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_String)); new NestedChildColumn (Columns::ColumnId_SpellId, ColumnBase::Display_Spell));
mSpells.addColumn (new StringIdColumn<ESM::Spell>); mSpells.addColumn (new StringIdColumn<ESM::Spell>);
mSpells.addColumn (new RecordStateColumn<ESM::Spell>); mSpells.addColumn (new RecordStateColumn<ESM::Spell>);

View file

@ -0,0 +1,110 @@
#include "idcompletionmanager.hpp"
#include <boost/make_shared.hpp>
#include <QCompleter>
#include "../../view/widget/completerpopup.hpp"
#include "data.hpp"
#include "idtablebase.hpp"
namespace
{
std::map<CSMWorld::ColumnBase::Display, CSMWorld::UniversalId::Type> generateModelTypes()
{
std::map<CSMWorld::ColumnBase::Display, CSMWorld::UniversalId::Type> types;
types[CSMWorld::ColumnBase::Display_BodyPart ] = CSMWorld::UniversalId::Type_BodyPart;
types[CSMWorld::ColumnBase::Display_Cell ] = CSMWorld::UniversalId::Type_Cell;
types[CSMWorld::ColumnBase::Display_Class ] = CSMWorld::UniversalId::Type_Class;
types[CSMWorld::ColumnBase::Display_CreatureLevelledList] = CSMWorld::UniversalId::Type_Referenceable;
types[CSMWorld::ColumnBase::Display_Creature ] = CSMWorld::UniversalId::Type_Referenceable;
types[CSMWorld::ColumnBase::Display_Enchantment ] = CSMWorld::UniversalId::Type_Enchantment;
types[CSMWorld::ColumnBase::Display_Faction ] = CSMWorld::UniversalId::Type_Faction;
types[CSMWorld::ColumnBase::Display_GlobalVariable ] = CSMWorld::UniversalId::Type_Global;
types[CSMWorld::ColumnBase::Display_Icon ] = CSMWorld::UniversalId::Type_Icon;
types[CSMWorld::ColumnBase::Display_Mesh ] = CSMWorld::UniversalId::Type_Mesh;
types[CSMWorld::ColumnBase::Display_Miscellaneous ] = CSMWorld::UniversalId::Type_Referenceable;
types[CSMWorld::ColumnBase::Display_Npc ] = CSMWorld::UniversalId::Type_Referenceable;
types[CSMWorld::ColumnBase::Display_Race ] = CSMWorld::UniversalId::Type_Race;
types[CSMWorld::ColumnBase::Display_Region ] = CSMWorld::UniversalId::Type_Region;
types[CSMWorld::ColumnBase::Display_Referenceable ] = CSMWorld::UniversalId::Type_Referenceable;
types[CSMWorld::ColumnBase::Display_Script ] = CSMWorld::UniversalId::Type_Script;
types[CSMWorld::ColumnBase::Display_Skill ] = CSMWorld::UniversalId::Type_Skill;
types[CSMWorld::ColumnBase::Display_Sound ] = CSMWorld::UniversalId::Type_Sound;
types[CSMWorld::ColumnBase::Display_SoundRes ] = CSMWorld::UniversalId::Type_SoundRes;
types[CSMWorld::ColumnBase::Display_Spell ] = CSMWorld::UniversalId::Type_Spell;
types[CSMWorld::ColumnBase::Display_Static ] = CSMWorld::UniversalId::Type_Referenceable;
types[CSMWorld::ColumnBase::Display_Texture ] = CSMWorld::UniversalId::Type_Texture;
types[CSMWorld::ColumnBase::Display_Weapon ] = CSMWorld::UniversalId::Type_Referenceable;
return types;
}
typedef std::map<CSMWorld::ColumnBase::Display,
CSMWorld::UniversalId::Type>::const_iterator ModelTypeConstIterator;
}
const std::map<CSMWorld::ColumnBase::Display, CSMWorld::UniversalId::Type>
CSMWorld::IdCompletionManager::sCompleterModelTypes = generateModelTypes();
std::vector<CSMWorld::ColumnBase::Display> CSMWorld::IdCompletionManager::getDisplayTypes()
{
std::vector<CSMWorld::ColumnBase::Display> types;
ModelTypeConstIterator current = sCompleterModelTypes.begin();
ModelTypeConstIterator end = sCompleterModelTypes.end();
for (; current != end; ++current)
{
types.push_back(current->first);
}
return types;
}
CSMWorld::IdCompletionManager::IdCompletionManager(CSMWorld::Data &data)
{
generateCompleters(data);
}
bool CSMWorld::IdCompletionManager::hasCompleterFor(CSMWorld::ColumnBase::Display display) const
{
return mCompleters.find(display) != mCompleters.end();
}
boost::shared_ptr<QCompleter> CSMWorld::IdCompletionManager::getCompleter(CSMWorld::ColumnBase::Display display)
{
if (!hasCompleterFor(display))
{
throw std::logic_error("This column doesn't have an ID completer");
}
return mCompleters[display];
}
void CSMWorld::IdCompletionManager::generateCompleters(CSMWorld::Data &data)
{
ModelTypeConstIterator current = sCompleterModelTypes.begin();
ModelTypeConstIterator end = sCompleterModelTypes.end();
for (; current != end; ++current)
{
QAbstractItemModel *model = data.getTableModel(current->second);
CSMWorld::IdTableBase *table = dynamic_cast<CSMWorld::IdTableBase *>(model);
if (table != NULL)
{
int idColumn = table->searchColumnIndex(CSMWorld::Columns::ColumnId_Id);
if (idColumn != -1)
{
boost::shared_ptr<QCompleter> completer = boost::make_shared<QCompleter>(table);
completer->setCompletionColumn(idColumn);
// The completion role must be Qt::DisplayRole to get the ID values from the model
completer->setCompletionRole(Qt::DisplayRole);
completer->setCaseSensitivity(Qt::CaseInsensitive);
QAbstractItemView *popup = new CSVWidget::CompleterPopup();
completer->setPopup(popup); // The completer takes ownership of the popup
completer->setMaxVisibleItems(10);
mCompleters[current->first] = completer;
}
}
}
}

View file

@ -0,0 +1,41 @@
#ifndef CSM_WORLD_IDCOMPLETIONMANAGER_HPP
#define CSM_WORLD_IDCOMPLETIONMANAGER_HPP
#include <vector>
#include <map>
#include <boost/shared_ptr.hpp>
#include "columnbase.hpp"
#include "universalid.hpp"
class QCompleter;
namespace CSMWorld
{
class Data;
/// \brief Creates and stores all ID completers
class IdCompletionManager
{
static const std::map<ColumnBase::Display, UniversalId::Type> sCompleterModelTypes;
std::map<ColumnBase::Display, boost::shared_ptr<QCompleter> > mCompleters;
// Don't allow copying
IdCompletionManager(const IdCompletionManager &);
IdCompletionManager &operator = (const IdCompletionManager &);
void generateCompleters(Data &data);
public:
static std::vector<ColumnBase::Display> getDisplayTypes();
IdCompletionManager(Data &data);
bool hasCompleterFor(ColumnBase::Display display) const;
boost::shared_ptr<QCompleter> getCompleter(ColumnBase::Display display);
};
}
#endif

View file

@ -33,6 +33,9 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const
if (index.row() < 0 || index.column() < 0) if (index.row() < 0 || index.column() < 0)
return QVariant(); return QVariant();
if (role==ColumnBase::Role_Display)
return QVariant(mIdCollection->getColumn(index.column()).mDisplayType);
if (role==ColumnBase::Role_ColumnId) if (role==ColumnBase::Role_ColumnId)
return QVariant (getColumnId (index.column())); return QVariant (getColumnId (index.column()));
@ -84,6 +87,9 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value
Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const
{ {
if (!index.isValid())
return 0;
Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
if (mIdCollection->getColumn (index.column()).isUserEditable()) if (mIdCollection->getColumn (index.column()).isUserEditable())

View file

@ -21,6 +21,18 @@ void CSMWorld::IdTableProxyModel::updateColumnMap()
} }
} }
bool CSMWorld::IdTableProxyModel::filterAcceptsColumn (int sourceColumn, const QModelIndex& sourceParent)
const
{
int flags =
sourceModel()->headerData (sourceColumn, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt();
if (flags & CSMWorld::ColumnBase::Flag_Table)
return true;
else
return false;
}
bool CSMWorld::IdTableProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) bool CSMWorld::IdTableProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent)
const const
{ {

View file

@ -24,8 +24,6 @@ namespace CSMWorld
void updateColumnMap(); void updateColumnMap();
bool filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const;
public: public:
IdTableProxyModel (QObject *parent = 0); IdTableProxyModel (QObject *parent = 0);
@ -39,6 +37,10 @@ namespace CSMWorld
protected: protected:
bool lessThan(const QModelIndex &left, const QModelIndex &right) const; bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
virtual bool filterAcceptsRow (int sourceRow, const QModelIndex& sourceParent) const;
virtual bool filterAcceptsColumn (int sourceColumn, const QModelIndex& sourceParent) const;
}; };
} }

View file

@ -35,28 +35,29 @@ QVariant CSMWorld::IdTree::data (const QModelIndex & index, int role) const
if (!index.isValid()) if (!index.isValid())
return QVariant(); return QVariant();
if ((role!=Qt::DisplayRole && role!=Qt::EditRole) || index.row() < 0 || index.column() < 0)
return QVariant();
if (index.internalId() != 0) if (index.internalId() != 0)
{ {
std::pair<int, int> parentAddress(unfoldIndexAddress(index.internalId())); std::pair<int, int> parentAddress(unfoldIndexAddress(index.internalId()));
const NestableColumn *parentColumn = mNestedCollection->getNestableColumn(parentAddress.second);
if (role == Qt::EditRole && if (role == ColumnBase::Role_Display)
!mNestedCollection->getNestableColumn(parentAddress.second)->nestedColumn(index.column()).isEditable()) return parentColumn->nestedColumn(index.column()).mDisplayType;
{
if (role == ColumnBase::Role_ColumnId)
return parentColumn->nestedColumn(index.column()).mColumnId;
if (role == Qt::EditRole && !parentColumn->nestedColumn(index.column()).isEditable())
return QVariant();
if (role != Qt::DisplayRole && role != Qt::EditRole)
return QVariant(); return QVariant();
}
return mNestedCollection->getNestedData(parentAddress.first, return mNestedCollection->getNestedData(parentAddress.first,
parentAddress.second, index.row(), index.column()); parentAddress.second, index.row(), index.column());
} }
else else
{ {
if (role==Qt::EditRole && !idCollection()->getColumn (index.column()).isEditable()) return IdTable::data(index, role);
return QVariant();
return idCollection()->getData (index.row(), index.column());
} }
} }
@ -79,6 +80,9 @@ QVariant CSMWorld::IdTree::nestedHeaderData(int section, int subSection, Qt::Ori
if (role==ColumnBase::Role_Display) if (role==ColumnBase::Role_Display)
return parentColumn->nestedColumn(subSection).mDisplayType; return parentColumn->nestedColumn(subSection).mDisplayType;
if (role==ColumnBase::Role_ColumnId)
return parentColumn->nestedColumn(subSection).mColumnId;
return QVariant(); return QVariant();
} }

View file

@ -99,7 +99,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
EnchantableColumns enchantableColumns (inventoryColumns); EnchantableColumns enchantableColumns (inventoryColumns);
mColumns.push_back (RefIdColumn (Columns::ColumnId_Enchantment, ColumnBase::Display_String)); mColumns.push_back (RefIdColumn (Columns::ColumnId_Enchantment, ColumnBase::Display_Enchantment));
enchantableColumns.mEnchantment = &mColumns.back(); enchantableColumns.mEnchantment = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_EnchantmentPoints, ColumnBase::Display_Integer)); mColumns.push_back (RefIdColumn (Columns::ColumnId_EnchantmentPoints, ColumnBase::Display_Integer));
enchantableColumns.mEnchantmentPoints = &mColumns.back(); enchantableColumns.mEnchantmentPoints = &mColumns.back();
@ -135,7 +135,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
new NestedInventoryRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature))); new NestedInventoryRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature)));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), inventoryMap)); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), inventoryMap));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_Referenceable));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer)); new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer));
@ -150,7 +150,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
new NestedSpellRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature))); new NestedSpellRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature)));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), spellsMap)); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), spellsMap));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_SpellId, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_SpellId, CSMWorld::ColumnBase::Display_Spell));
// Nested table // Nested table
mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcDestinations, mColumns.push_back(RefIdColumn (Columns::ColumnId_NpcDestinations,
@ -163,7 +163,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
new NestedTravelRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature))); new NestedTravelRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature)));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), destMap)); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), destMap));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_DestinationCell, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_DestinationCell, CSMWorld::ColumnBase::Display_Cell));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PosX, CSMWorld::ColumnBase::Display_Float)); new RefIdColumn (Columns::ColumnId_PosX, CSMWorld::ColumnBase::Display_Float));
mColumns.back().addColumn( mColumns.back().addColumn(
@ -289,7 +289,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
new NestedInventoryRefIdAdapter<ESM::Container> (UniversalId::Type_Container))); new NestedInventoryRefIdAdapter<ESM::Container> (UniversalId::Type_Container)));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), contMap)); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), contMap));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_InventoryItemId, CSMWorld::ColumnBase::Display_Referenceable));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer)); new RefIdColumn (Columns::ColumnId_ItemCount, CSMWorld::ColumnBase::Display_Integer));
@ -301,7 +301,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
creatureColumns.mSoul = &mColumns.back(); creatureColumns.mSoul = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_Scale, ColumnBase::Display_Float)); mColumns.push_back (RefIdColumn (Columns::ColumnId_Scale, ColumnBase::Display_Float));
creatureColumns.mScale = &mColumns.back(); creatureColumns.mScale = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_OriginalCreature, ColumnBase::Display_String)); mColumns.push_back (RefIdColumn (Columns::ColumnId_OriginalCreature, ColumnBase::Display_Creature));
creatureColumns.mOriginal = &mColumns.back(); creatureColumns.mOriginal = &mColumns.back();
mColumns.push_back ( mColumns.push_back (
RefIdColumn (Columns::ColumnId_CombatState, ColumnBase::Display_Integer)); RefIdColumn (Columns::ColumnId_CombatState, ColumnBase::Display_Integer));
@ -409,10 +409,10 @@ CSMWorld::RefIdCollection::RefIdCollection()
mColumns.push_back (RefIdColumn (Columns::ColumnId_Faction, ColumnBase::Display_Faction)); mColumns.push_back (RefIdColumn (Columns::ColumnId_Faction, ColumnBase::Display_Faction));
npcColumns.mFaction = &mColumns.back(); npcColumns.mFaction = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::Columnid_Hair, ColumnBase::Display_String)); mColumns.push_back (RefIdColumn (Columns::Columnid_Hair, ColumnBase::Display_BodyPart));
npcColumns.mHair = &mColumns.back(); npcColumns.mHair = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_Head, ColumnBase::Display_String)); mColumns.push_back (RefIdColumn (Columns::ColumnId_Head, ColumnBase::Display_BodyPart));
npcColumns.mHead = &mColumns.back(); npcColumns.mHead = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_Female, ColumnBase::Display_Boolean)); mColumns.push_back (RefIdColumn (Columns::ColumnId_Female, ColumnBase::Display_Boolean));
@ -539,9 +539,9 @@ CSMWorld::RefIdCollection::RefIdCollection()
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PartRefType, CSMWorld::ColumnBase::Display_PartRefType)); new RefIdColumn (Columns::ColumnId_PartRefType, CSMWorld::ColumnBase::Display_PartRefType));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PartRefMale, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_PartRefMale, CSMWorld::ColumnBase::Display_BodyPart));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PartRefFemale, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_PartRefFemale, CSMWorld::ColumnBase::Display_BodyPart));
LevListColumns levListColumns (baseColumns); LevListColumns levListColumns (baseColumns);
@ -556,7 +556,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
new NestedLevListRefIdAdapter<ESM::ItemLevList> (UniversalId::Type_ItemLevelledList))); new NestedLevListRefIdAdapter<ESM::ItemLevList> (UniversalId::Type_ItemLevelledList)));
mNestedAdapters.push_back (std::make_pair(&mColumns.back(), levListMap)); mNestedAdapters.push_back (std::make_pair(&mColumns.back(), levListMap));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_LevelledItemId, CSMWorld::ColumnBase::Display_String)); new RefIdColumn (Columns::ColumnId_LevelledItemId, CSMWorld::ColumnBase::Display_Referenceable));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_LevelledItemLevel, CSMWorld::ColumnBase::Display_Integer)); new RefIdColumn (Columns::ColumnId_LevelledItemLevel, CSMWorld::ColumnBase::Display_Integer));

View file

@ -1,6 +1,7 @@
#include "viewmanager.hpp" #include "viewmanager.hpp"
#include <vector>
#include <map> #include <map>
#include <QApplication> #include <QApplication>
@ -10,12 +11,14 @@
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
#include "../../model/world/columns.hpp" #include "../../model/world/columns.hpp"
#include "../../model/world/universalid.hpp" #include "../../model/world/universalid.hpp"
#include "../../model/world/idcompletionmanager.hpp"
#include "../world/util.hpp" #include "../world/util.hpp"
#include "../world/enumdelegate.hpp" #include "../world/enumdelegate.hpp"
#include "../world/vartypedelegate.hpp" #include "../world/vartypedelegate.hpp"
#include "../world/recordstatusdelegate.hpp" #include "../world/recordstatusdelegate.hpp"
#include "../world/idtypedelegate.hpp" #include "../world/idtypedelegate.hpp"
#include "../world/idcompletiondelegate.hpp"
#include "../../model/settings/usersettings.hpp" #include "../../model/settings/usersettings.hpp"
@ -60,6 +63,14 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType, mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType,
new CSVWorld::IdTypeDelegateFactory()); new CSVWorld::IdTypeDelegateFactory());
std::vector<CSMWorld::ColumnBase::Display> idCompletionColumns = CSMWorld::IdCompletionManager::getDisplayTypes();
for (std::vector<CSMWorld::ColumnBase::Display>::const_iterator current = idCompletionColumns.begin();
current != idCompletionColumns.end();
++current)
{
mDelegateFactories->add(*current, new CSVWorld::IdCompletionDelegateFactory());
}
struct Mapping struct Mapping
{ {
CSMWorld::ColumnBase::Display mDisplay; CSMWorld::ColumnBase::Display mDisplay;

View file

@ -0,0 +1,28 @@
#include "completerpopup.hpp"
CSVWidget::CompleterPopup::CompleterPopup(QWidget *parent)
: QListView(parent)
{
setEditTriggers(QAbstractItemView::NoEditTriggers);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setSelectionBehavior(QAbstractItemView::SelectRows);
setSelectionMode(QAbstractItemView::SingleSelection);
}
int CSVWidget::CompleterPopup::sizeHintForRow(int row) const
{
if (model() == NULL)
{
return -1;
}
if (row < 0 || row >= model()->rowCount())
{
return -1;
}
ensurePolished();
QModelIndex index = model()->index(row, modelColumn());
QStyleOptionViewItem option = viewOptions();
QAbstractItemDelegate *delegate = itemDelegate(index);
return delegate->sizeHint(option, index).height();
}

View file

@ -0,0 +1,17 @@
#ifndef CSV_WIDGET_COMPLETERPOPUP_HPP
#define CSV_WIDGET_COMPLETERPOPUP_HPP
#include <QListView>
namespace CSVWidget
{
class CompleterPopup : public QListView
{
public:
CompleterPopup(QWidget *parent = 0);
virtual int sizeHintForRow(int row) const;
};
}
#endif

View file

@ -0,0 +1,39 @@
#include "idcompletiondelegate.hpp"
#include "../../model/world/idcompletionmanager.hpp"
CSVWorld::IdCompletionDelegate::IdCompletionDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document& document,
QObject *parent)
: CommandDelegate(dispatcher, document, parent)
{}
QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
return createEditor(parent, option, index, getDisplayTypeFromIndex(index));
}
QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index,
CSMWorld::ColumnBase::Display display) const
{
if (!index.data(Qt::EditRole).isValid() && !index.data(Qt::DisplayRole).isValid())
{
return NULL;
}
CSMWorld::IdCompletionManager &completionManager = getDocument().getIdCompletionManager();
DropLineEdit *editor = new DropLineEdit(parent);
editor->setCompleter(completionManager.getCompleter(display).get());
return editor;
}
CSVWorld::CommandDelegate *CSVWorld::IdCompletionDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document& document,
QObject *parent) const
{
return new IdCompletionDelegate(dispatcher, document, parent);
}

View file

@ -0,0 +1,36 @@
#ifndef CSV_WORLD_IDCOMPLETIONDELEGATE_HPP
#define CSV_WORLD_IDCOMPLETIONDELEGATE_HPP
#include "util.hpp"
namespace CSVWorld
{
/// \brief Enables the Id completion for a column
class IdCompletionDelegate : public CommandDelegate
{
public:
IdCompletionDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document& document,
QObject *parent);
virtual QWidget *createEditor (QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
virtual QWidget *createEditor (QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index,
CSMWorld::ColumnBase::Display display) const;
};
class IdCompletionDelegateFactory : public CommandDelegateFactory
{
public:
virtual CommandDelegate *makeDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document& document,
QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
};
}
#endif

View file

@ -111,6 +111,12 @@ CSMDoc::Document& CSVWorld::CommandDelegate::getDocument() const
return mDocument; return mDocument;
} }
CSMWorld::ColumnBase::Display CSVWorld::CommandDelegate::getDisplayTypeFromIndex(const QModelIndex &index) const
{
int rawDisplay = index.data(CSMWorld::ColumnBase::Role_Display).toInt();
return static_cast<CSMWorld::ColumnBase::Display>(rawDisplay);
}
void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model, void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const const QModelIndex& index) const
{ {
@ -146,7 +152,17 @@ void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemMode
QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option,
const QModelIndex& index) const const QModelIndex& index) const
{ {
return createEditor (parent, option, index, CSMWorld::ColumnBase::Display_None); CSMWorld::ColumnBase::Display display = getDisplayTypeFromIndex(index);
// This createEditor() method is called implicitly from tables.
// For boolean values in tables use the default editor (combobox).
// Checkboxes is looking ugly in the table view.
// TODO: Find a better solution?
if (display == CSMWorld::ColumnBase::Display_Boolean)
{
return QStyledItemDelegate::createEditor(parent, option, index);
}
return createEditor (parent, option, index, display);
} }
QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option, QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleOptionViewItem& option,

View file

@ -124,6 +124,8 @@ namespace CSVWorld
CSMDoc::Document& getDocument() const; CSMDoc::Document& getDocument() const;
CSMWorld::ColumnBase::Display getDisplayTypeFromIndex(const QModelIndex &index) const;
virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model, virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model,
const QModelIndex& index) const; const QModelIndex& index) const;

View file

@ -130,6 +130,7 @@ namespace MWGui
mSortModel = new SortFilterItemModel(model); mSortModel = new SortFilterItemModel(model);
mSortModel->setFilter(SortFilterItemModel::Filter_OnlyIngredients); mSortModel->setFilter(SortFilterItemModel::Filter_OnlyIngredients);
mItemView->setModel (mSortModel); mItemView->setModel (mSortModel);
mItemView->resetScrollBars();
mNameEdit->setCaption(""); mNameEdit->setCaption("");

View file

@ -114,6 +114,7 @@ void CompanionWindow::openCompanion(const MWWorld::Ptr& npc)
mModel = new CompanionItemModel(npc); mModel = new CompanionItemModel(npc);
mSortModel = new SortFilterItemModel(mModel); mSortModel = new SortFilterItemModel(mModel);
mItemView->setModel(mSortModel); mItemView->setModel(mSortModel);
mItemView->resetScrollBars();
setTitle(npc.getClass().getName(npc)); setTitle(npc.getClass().getName(npc));
} }

View file

@ -151,6 +151,7 @@ namespace MWGui
mSortModel = new SortFilterItemModel(mModel); mSortModel = new SortFilterItemModel(mModel);
mItemView->setModel (mSortModel); mItemView->setModel (mSortModel);
mItemView->resetScrollBars();
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton); MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton);

View file

@ -39,6 +39,7 @@ namespace MWGui
mModel = new InventoryItemModel(container); mModel = new InventoryItemModel(container);
mSortModel = new SortFilterItemModel(mModel); mSortModel = new SortFilterItemModel(mModel);
mItemView->setModel(mSortModel); mItemView->setModel(mSortModel);
mItemView->resetScrollBars();
} }
void ItemSelectionDialog::setCategory(int category) void ItemSelectionDialog::setCategory(int category)

View file

@ -128,6 +128,11 @@ void ItemView::update()
layoutWidgets(); layoutWidgets();
} }
void ItemView::resetScrollBars()
{
mScrollView->setViewOffset(MyGUI::IntPoint(0, 0));
}
void ItemView::onSelectedItem(MyGUI::Widget *sender) void ItemView::onSelectedItem(MyGUI::Widget *sender)
{ {
ItemModel::ModelIndex index = (*sender->getUserData<std::pair<ItemModel::ModelIndex, ItemModel*> >()).first; ItemModel::ModelIndex index = (*sender->getUserData<std::pair<ItemModel::ModelIndex, ItemModel*> >()).first;

View file

@ -30,6 +30,8 @@ namespace MWGui
void update(); void update();
void resetScrollBars();
private: private:
virtual void initialiseOverride(); virtual void initialiseOverride();

View file

@ -114,6 +114,8 @@ void MerchantRepair::onMouseWheel(MyGUI::Widget* _sender, int _rel)
void MerchantRepair::open() void MerchantRepair::open()
{ {
center(); center();
// Reset scrollbars
mList->setViewOffset(MyGUI::IntPoint(0, 0));
} }
void MerchantRepair::exit() void MerchantRepair::exit()

View file

@ -546,6 +546,7 @@ namespace MWGui
WindowModal::open(); WindowModal::open();
mMagicList->setModel(new SpellModel(MWBase::Environment::get().getWorld()->getPlayerPtr())); mMagicList->setModel(new SpellModel(MWBase::Environment::get().getWorld()->getPlayerPtr()));
mMagicList->resetScrollbars();
} }
void MagicSelectionDialog::onModelIndexSelected(SpellModel::ModelIndex index) void MagicSelectionDialog::onModelIndexSelected(SpellModel::ModelIndex index)

View file

@ -44,6 +44,8 @@ Recharge::Recharge()
void Recharge::open() void Recharge::open()
{ {
center(); center();
// Reset scrollbars
mView->setViewOffset(MyGUI::IntPoint(0, 0));
} }
void Recharge::exit() void Recharge::exit()

View file

@ -36,6 +36,8 @@ Repair::Repair()
void Repair::open() void Repair::open()
{ {
center(); center();
// Reset scrollbars
mRepairView->setViewOffset(MyGUI::IntPoint(0, 0));
} }
void Repair::exit() void Repair::exit()

View file

@ -6,6 +6,7 @@
#include <MyGUI_ListBox.h> #include <MyGUI_ListBox.h>
#include <MyGUI_ScrollView.h> #include <MyGUI_ScrollView.h>
#include <MyGUI_Gui.h> #include <MyGUI_Gui.h>
#include <MyGUI_TabControl.h>
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/math/common_factor_rt.hpp> #include <boost/math/common_factor_rt.hpp>
@ -159,6 +160,7 @@ namespace MWGui
setTitle("#{sOptions}"); setTitle("#{sOptions}");
getWidget(mSettingsTab, "SettingsTab");
getWidget(mOkButton, "OkButton"); getWidget(mOkButton, "OkButton");
getWidget(mResolutionList, "ResolutionList"); getWidget(mResolutionList, "ResolutionList");
getWidget(mFullscreenButton, "FullscreenButton"); getWidget(mFullscreenButton, "FullscreenButton");
@ -196,6 +198,7 @@ namespace MWGui
mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SettingsWindow::onWindowResize); mMainWidget->castType<MyGUI::Window>()->eventWindowChangeCoord += MyGUI::newDelegate(this, &SettingsWindow::onWindowResize);
mSettingsTab->eventTabChangeSelect += MyGUI::newDelegate(this, &SettingsWindow::onTabChanged);
mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked);
mTextureFilteringButton->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringChanged); mTextureFilteringButton->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringChanged);
mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled);
@ -260,6 +263,11 @@ namespace MWGui
mControllerSwitch->setStateSelected(false); mControllerSwitch->setStateSelected(false);
} }
void SettingsWindow::onTabChanged(MyGUI::TabControl* /*_sender*/, size_t /*index*/)
{
resetScrollbars();
}
void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender)
{ {
exit(); exit();
@ -454,6 +462,7 @@ namespace MWGui
mKeyboardSwitch->setStateSelected(true); mKeyboardSwitch->setStateSelected(true);
mControllerSwitch->setStateSelected(false); mControllerSwitch->setStateSelected(false);
updateControlsBox(); updateControlsBox();
resetScrollbars();
} }
void SettingsWindow::onControllerSwitchClicked(MyGUI::Widget* _sender) void SettingsWindow::onControllerSwitchClicked(MyGUI::Widget* _sender)
@ -464,6 +473,7 @@ namespace MWGui
mKeyboardSwitch->setStateSelected(false); mKeyboardSwitch->setStateSelected(false);
mControllerSwitch->setStateSelected(true); mControllerSwitch->setStateSelected(true);
updateControlsBox(); updateControlsBox();
resetScrollbars();
} }
void SettingsWindow::updateControlsBox() void SettingsWindow::updateControlsBox()
@ -558,6 +568,7 @@ namespace MWGui
void SettingsWindow::open() void SettingsWindow::open()
{ {
updateControlsBox (); updateControlsBox ();
resetScrollbars();
} }
void SettingsWindow::exit() void SettingsWindow::exit()
@ -569,4 +580,10 @@ namespace MWGui
{ {
updateControlsBox(); updateControlsBox();
} }
void SettingsWindow::resetScrollbars()
{
mResolutionList->setScrollPosition(0);
mControlsBox->setViewOffset(MyGUI::IntPoint(0, 0));
}
} }

View file

@ -22,6 +22,7 @@ namespace MWGui
void updateControlsBox(); void updateControlsBox();
protected: protected:
MyGUI::TabControl* mSettingsTab;
MyGUI::Button* mOkButton; MyGUI::Button* mOkButton;
// graphics // graphics
@ -49,6 +50,7 @@ namespace MWGui
MyGUI::Button* mControllerSwitch; MyGUI::Button* mControllerSwitch;
bool mKeyboardMode; //if true, setting up the keyboard. Otherwise, it's controller bool mKeyboardMode; //if true, setting up the keyboard. Otherwise, it's controller
void onTabChanged(MyGUI::TabControl* _sender, size_t index);
void onOkButtonClicked(MyGUI::Widget* _sender); void onOkButtonClicked(MyGUI::Widget* _sender);
void onFpsToggled(MyGUI::Widget* _sender); void onFpsToggled(MyGUI::Widget* _sender);
void onTextureFilteringChanged(MyGUI::ComboBox* _sender, size_t pos); void onTextureFilteringChanged(MyGUI::ComboBox* _sender, size_t pos);
@ -72,6 +74,9 @@ namespace MWGui
void apply(); void apply();
void configureWidgets(MyGUI::Widget* widget); void configureWidgets(MyGUI::Widget* widget);
private:
void resetScrollbars();
}; };
} }

View file

@ -550,6 +550,7 @@ namespace MWGui
++i; ++i;
} }
mAvailableEffectsList->adjustSize (); mAvailableEffectsList->adjustSize ();
mAvailableEffectsList->scrollToTop();
for (std::vector<short>::const_iterator it = knownEffects.begin(); it != knownEffects.end(); ++it) for (std::vector<short>::const_iterator it = knownEffects.begin(); it != knownEffects.end(); ++it)
{ {

View file

@ -311,4 +311,8 @@ namespace MWGui
mScrollView->setViewOffset(MyGUI::IntPoint(0, static_cast<int>(mScrollView->getViewOffset().top + _rel*0.3f))); mScrollView->setViewOffset(MyGUI::IntPoint(0, static_cast<int>(mScrollView->getViewOffset().top + _rel*0.3f)));
} }
void SpellView::resetScrollbars()
{
mScrollView->setViewOffset(MyGUI::IntPoint(0, 0));
}
} }

View file

@ -51,6 +51,8 @@ namespace MWGui
virtual void setSize(const MyGUI::IntSize& _value); virtual void setSize(const MyGUI::IntSize& _value);
virtual void setCoord(const MyGUI::IntCoord& _value); virtual void setCoord(const MyGUI::IntCoord& _value);
void resetScrollbars();
private: private:
MyGUI::ScrollView* mScrollView; MyGUI::ScrollView* mScrollView;

View file

@ -136,6 +136,7 @@ namespace MWGui
mTradeModel = new TradeItemModel(new ContainerItemModel(itemSources, worldItems), mPtr); mTradeModel = new TradeItemModel(new ContainerItemModel(itemSources, worldItems), mPtr);
mSortModel = new SortFilterItemModel(mTradeModel); mSortModel = new SortFilterItemModel(mTradeModel);
mItemView->setModel (mSortModel); mItemView->setModel (mSortModel);
mItemView->resetScrollBars();
updateLabels(); updateLabels();

View file

@ -1,6 +1,7 @@
#include "gamesettings.hpp" #include "gamesettings.hpp"
#include "launchersettings.hpp" #include "launchersettings.hpp"
#include <QTextCodec>
#include <QTextStream> #include <QTextStream>
#include <QDir> #include <QDir>
#include <QString> #include <QString>
@ -173,6 +174,138 @@ bool Config::GameSettings::writeFile(QTextStream &stream)
return true; return true;
} }
// Policy:
//
// - Always ignore a line beginning with '#' or empty lines
//
// - If a line in file exists with matching key and first part of value (before ',',
// '\n', etc) also matches, then replace the line with that of mUserSettings.
// - else remove line (TODO: maybe replace the line with '#' in front instead?)
//
// - If there is no corresponding line in file, add at the end
//
bool Config::GameSettings::writeFileWithComments(QFile &file)
{
QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-8"));
// slurp
std::vector<QString> fileCopy;
QString line = stream.readLine();
while (!line.isNull())
{
fileCopy.push_back(line);
line = stream.readLine();
}
stream.seek(0);
// empty file, no comments to keep
if (fileCopy.empty())
return writeFile(stream);
// Temp copy of settings to save, but with the keys appended with the first part of the value
//
// ATTENTION!
//
// A hack to avoid looping through each line, makes use of the fact that fallbacks values
// are comma separated.
QMap<QString, QString> userSettingsCopy;
QRegExp settingRegex("^([^=]+)\\s*=\\s*([^,]+)(.*)$");
QString settingLine;
QMap<QString, QString>::const_iterator settingsIter = mUserSettings.begin();
for (; settingsIter != mUserSettings.end(); ++settingsIter)
{
settingLine = settingsIter.key()+"="+settingsIter.value();
if (settingRegex.indexIn(settingLine) != -1)
{
userSettingsCopy[settingRegex.cap(1)+"="+settingRegex.cap(2)] =
(settingRegex.captureCount() < 3) ? "" : settingRegex.cap(3);
}
}
QString keyVal;
for (std::vector<QString>::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter)
{
// skip empty or comment lines
if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#")))
continue;
// look for a key in the line
if (settingRegex.indexIn(*iter) == -1 || settingRegex.captureCount() < 2)
{
// no key or first part of value found in line, replace with a null string which
// will be remved later
*iter = QString();
continue;
}
// look for a matching key in user settings
keyVal = settingRegex.cap(1)+"="+settingRegex.cap(2);
QMap<QString, QString>::iterator it = userSettingsCopy.find(keyVal);
if (it == userSettingsCopy.end())
{
// no such key+valStart, replace with a null string which will be remved later
*iter = QString();
}
else
{
*iter = QString(it.key()+it.value());
userSettingsCopy.erase(it);
}
}
// write the new config file
QString key;
QString value;
for (std::vector<QString>::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter)
{
if ((*iter).isNull())
continue;
// Below is based on readFile() code, if that changes corresponding change may be
// required (for example duplicates may be inserted if the rules don't match)
if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#")))
{
stream << *iter << "\n";
continue;
}
if (settingRegex.indexIn(*iter) == -1 || settingRegex.captureCount() < 2)
continue;
// Quote paths with spaces
key = settingRegex.cap(1);
value = settingRegex.cap(2)+settingRegex.cap(3);
if (key == QLatin1String("data")
|| key == QLatin1String("data-local")
|| key == QLatin1String("resources"))
{
if (value.contains(QChar(' ')))
{
value.remove(QChar('\"')); // Remove quotes
stream << key << "=\"" << value << "\"\n";
continue;
}
}
stream << key << "=" << value << "\n";
}
if (!userSettingsCopy.empty())
{
stream << "# new entries" << "\n";
QMap<QString, QString>::const_iterator it = userSettingsCopy.begin();
for (; it != userSettingsCopy.end(); ++it)
{
stream << it.key() << it.value() << "\n";
}
}
file.resize(file.pos());
return true;
}
bool Config::GameSettings::hasMaster() bool Config::GameSettings::hasMaster()
{ {
bool result = false; bool result = false;

View file

@ -4,6 +4,7 @@
#include <QTextStream> #include <QTextStream>
#include <QStringList> #include <QStringList>
#include <QString> #include <QString>
#include <QFile>
#include <QMap> #include <QMap>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
@ -66,6 +67,7 @@ namespace Config
bool readUserFile(QTextStream &stream); bool readUserFile(QTextStream &stream);
bool writeFile(QTextStream &stream); bool writeFile(QTextStream &stream);
bool writeFileWithComments(QFile &file);
void setContentList(const QStringList& fileNames); void setContentList(const QStringList& fileNames);
QStringList getContentList() const; QStringList getContentList() const;