1 #include "infocreator.hpp"
2 
3 #include <algorithm>
4 
5 #include <QLabel>
6 #include <QUuid>
7 
8 #include <components/misc/stringops.hpp>
9 
10 #include "../../model/doc/document.hpp"
11 
12 #include "../../model/world/data.hpp"
13 #include "../../model/world/commands.hpp"
14 #include "../../model/world/columns.hpp"
15 #include "../../model/world/idtable.hpp"
16 #include "../../model/world/idcompletionmanager.hpp"
17 
18 #include "../widget/droplineedit.hpp"
19 
getId() const20 std::string CSVWorld::InfoCreator::getId() const
21 {
22     std::string id = Misc::StringUtils::lowerCase (mTopic->text().toUtf8().constData());
23 
24     std::string unique = QUuid::createUuid().toByteArray().data();
25 
26     unique.erase (std::remove (unique.begin(), unique.end(), '-'), unique.end());
27 
28     unique = unique.substr (1, unique.size()-2);
29 
30     return id + '#' + unique;
31 }
32 
configureCreateCommand(CSMWorld::CreateCommand & command) const33 void CSVWorld::InfoCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
34 {
35     CSMWorld::IdTable& table = dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId()));
36 
37     CSMWorld::CloneCommand* cloneCommand = dynamic_cast<CSMWorld::CloneCommand*> (&command);
38     if (getCollectionId() == CSMWorld::UniversalId::Type_TopicInfos)
39     {
40         if (!cloneCommand)
41         {
42             command.addValue (table.findColumnIndex(CSMWorld::Columns::ColumnId_Topic), mTopic->text());
43             command.addValue (table.findColumnIndex(CSMWorld::Columns::ColumnId_Rank), -1);
44             command.addValue (table.findColumnIndex(CSMWorld::Columns::ColumnId_Gender), -1);
45             command.addValue (table.findColumnIndex(CSMWorld::Columns::ColumnId_PcRank), -1);
46         }
47         else
48         {
49             cloneCommand->setOverrideValue(table.findColumnIndex(CSMWorld::Columns::ColumnId_Topic), mTopic->text());
50         }
51     }
52     else
53     {
54         if (!cloneCommand)
55         {
56             command.addValue (table.findColumnIndex(CSMWorld::Columns::ColumnId_Journal), mTopic->text());
57         }
58         else
59             cloneCommand->setOverrideValue(table.findColumnIndex(CSMWorld::Columns::ColumnId_Journal), mTopic->text());
60     }
61 }
62 
InfoCreator(CSMWorld::Data & data,QUndoStack & undoStack,const CSMWorld::UniversalId & id,CSMWorld::IdCompletionManager & completionManager)63 CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack,
64     const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager)
65 : GenericCreator (data, undoStack, id)
66 {
67     // Determine if we're dealing with topics or journals.
68     CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Topic;
69     QString labelText = "Topic";
70     if (getCollectionId().getType() == CSMWorld::UniversalId::Type_JournalInfos)
71     {
72         displayType = CSMWorld::ColumnBase::Display_Journal;
73         labelText = "Journal";
74     }
75 
76     QLabel *label = new QLabel (labelText, this);
77     insertBeforeButtons (label, false);
78 
79     // Add topic/journal ID input with auto-completion.
80     // Only existing topic/journal IDs are accepted so no ID validation is performed.
81     mTopic = new CSVWidget::DropLineEdit(displayType, this);
82     mTopic->setCompleter(completionManager.getCompleter(displayType).get());
83     insertBeforeButtons (mTopic, true);
84 
85     setManualEditing (false);
86 
87     connect (mTopic, SIGNAL (textChanged (const QString&)), this, SLOT (topicChanged()));
88     connect (mTopic, SIGNAL (returnPressed()), this, SLOT (inputReturnPressed()));
89 }
90 
cloneMode(const std::string & originId,const CSMWorld::UniversalId::Type type)91 void CSVWorld::InfoCreator::cloneMode (const std::string& originId,
92     const CSMWorld::UniversalId::Type type)
93 {
94     CSMWorld::IdTable& infoTable =
95         dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId()));
96 
97     int topicColumn = infoTable.findColumnIndex (
98         getCollectionId().getType()==CSMWorld::UniversalId::Type_TopicInfos ?
99         CSMWorld::Columns::ColumnId_Topic : CSMWorld::Columns::ColumnId_Journal);
100 
101     mTopic->setText (
102         infoTable.data (infoTable.getModelIndex (originId, topicColumn)).toString());
103 
104     GenericCreator::cloneMode (originId, type);
105 }
106 
reset()107 void CSVWorld::InfoCreator::reset()
108 {
109     mTopic->setText ("");
110     GenericCreator::reset();
111 }
112 
getErrors() const113 std::string CSVWorld::InfoCreator::getErrors() const
114 {
115     // We ignore errors from GenericCreator here, because they can never happen in an InfoCreator.
116     std::string errors;
117 
118     std::string topic = mTopic->text().toUtf8().constData();
119 
120     if ((getCollectionId().getType()==CSMWorld::UniversalId::Type_TopicInfos ?
121         getData().getTopics() : getData().getJournals()).searchId (topic)==-1)
122     {
123         errors += "Invalid Topic ID";
124     }
125 
126     return errors;
127 }
128 
focus()129 void CSVWorld::InfoCreator::focus()
130 {
131     mTopic->setFocus();
132 }
133 
topicChanged()134 void CSVWorld::InfoCreator::topicChanged()
135 {
136     update();
137 }
138 
makeCreator(CSMDoc::Document & document,const CSMWorld::UniversalId & id) const139 CSVWorld::Creator *CSVWorld::InfoCreatorFactory::makeCreator(CSMDoc::Document& document,
140                                                              const CSMWorld::UniversalId& id) const
141 {
142     return new InfoCreator(document.getData(),
143                            document.getUndoStack(),
144                            id,
145                            document.getIdCompletionManager());
146 }
147