1 #include "tablesubview.hpp"
2
3 #include <QVBoxLayout>
4 #include <QEvent>
5 #include <QHeaderView>
6 #include <QApplication>
7 #include <QDesktopWidget>
8 #include <QDropEvent>
9
10 #include "../../model/doc/document.hpp"
11 #include "../../model/world/tablemimedata.hpp"
12
13 #include "../doc/sizehint.hpp"
14 #include "../filter/filterbox.hpp"
15 #include "table.hpp"
16 #include "tablebottombox.hpp"
17 #include "creator.hpp"
18
TableSubView(const CSMWorld::UniversalId & id,CSMDoc::Document & document,const CreatorFactoryBase & creatorFactory,bool sorting)19 CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
20 const CreatorFactoryBase& creatorFactory, bool sorting)
21 : SubView (id)
22 {
23 QVBoxLayout *layout = new QVBoxLayout;
24
25 layout->addWidget (mBottom =
26 new TableBottomBox (creatorFactory, document, id, this), 0);
27
28 layout->insertWidget (0, mTable =
29 new Table (id, mBottom->canCreateAndDelete(), sorting, document), 2);
30
31 mFilterBox = new CSVFilter::FilterBox (document.getData(), this);
32
33 layout->insertWidget (0, mFilterBox);
34
35 CSVDoc::SizeHintWidget *widget = new CSVDoc::SizeHintWidget;
36
37 widget->setLayout (layout);
38
39 setWidget (widget);
40 // prefer height of the screen and full width of the table
41 const QRect rect = QApplication::desktop()->screenGeometry(this);
42 int frameHeight = 40; // set a reasonable default
43 QWidget *topLevel = QApplication::topLevelAt(pos());
44 if (topLevel)
45 frameHeight = topLevel->frameGeometry().height() - topLevel->height();
46 widget->setSizeHint(QSize(mTable->horizontalHeader()->length(), rect.height()-frameHeight));
47
48 connect (mTable, SIGNAL (editRequest (const CSMWorld::UniversalId&, const std::string&)),
49 this, SLOT (editRequest (const CSMWorld::UniversalId&, const std::string&)));
50
51 connect (mTable, SIGNAL (selectionSizeChanged (int)),
52 mBottom, SLOT (selectionSizeChanged (int)));
53 connect (mTable, SIGNAL (tableSizeChanged (int, int, int)),
54 mBottom, SLOT (tableSizeChanged (int, int, int)));
55
56 mTable->tableSizeUpdate();
57 mTable->selectionSizeUpdate();
58 mTable->viewport()->installEventFilter(this);
59 mBottom->installEventFilter(this);
60 mFilterBox->installEventFilter(this);
61
62 if (mBottom->canCreateAndDelete())
63 {
64 connect (mTable, SIGNAL (createRequest()), mBottom, SLOT (createRequest()));
65
66 connect (mTable, SIGNAL (cloneRequest(const CSMWorld::UniversalId&)), this,
67 SLOT(cloneRequest(const CSMWorld::UniversalId&)));
68
69 connect (this, SIGNAL(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)),
70 mBottom, SLOT(cloneRequest(const std::string&, const CSMWorld::UniversalId::Type)));
71
72 connect (mTable, SIGNAL(touchRequest(const std::vector<CSMWorld::UniversalId>&)),
73 mBottom, SLOT(touchRequest(const std::vector<CSMWorld::UniversalId>&)));
74
75 connect (mTable, SIGNAL(extendedDeleteConfigRequest(const std::vector<std::string> &)),
76 mBottom, SLOT(extendedDeleteConfigRequest(const std::vector<std::string> &)));
77 connect (mTable, SIGNAL(extendedRevertConfigRequest(const std::vector<std::string> &)),
78 mBottom, SLOT(extendedRevertConfigRequest(const std::vector<std::string> &)));
79 }
80 connect (mBottom, SIGNAL (requestFocus (const std::string&)),
81 mTable, SLOT (requestFocus (const std::string&)));
82
83 connect (mFilterBox,
84 SIGNAL (recordFilterChanged (std::shared_ptr<CSMFilter::Node>)),
85 mTable, SLOT (recordFilterChanged (std::shared_ptr<CSMFilter::Node>)));
86
87 connect(mFilterBox, SIGNAL(recordDropped(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)),
88 this, SLOT(createFilterRequest(std::vector<CSMWorld::UniversalId>&, Qt::DropAction)));
89
90 connect (mTable, SIGNAL (closeRequest()), this, SLOT (closeRequest()));
91 }
92
setEditLock(bool locked)93 void CSVWorld::TableSubView::setEditLock (bool locked)
94 {
95 mTable->setEditLock (locked);
96 mBottom->setEditLock (locked);
97 }
98
editRequest(const CSMWorld::UniversalId & id,const std::string & hint)99 void CSVWorld::TableSubView::editRequest (const CSMWorld::UniversalId& id, const std::string& hint)
100 {
101 focusId (id, hint);
102 }
103
setStatusBar(bool show)104 void CSVWorld::TableSubView::setStatusBar (bool show)
105 {
106 mBottom->setStatusBar (show);
107 }
108
useHint(const std::string & hint)109 void CSVWorld::TableSubView::useHint (const std::string& hint)
110 {
111 if (hint.empty())
112 return;
113
114 if (hint[0]=='f' && hint.size()>=2)
115 mFilterBox->setRecordFilter (hint.substr (2));
116 }
117
cloneRequest(const CSMWorld::UniversalId & toClone)118 void CSVWorld::TableSubView::cloneRequest(const CSMWorld::UniversalId& toClone)
119 {
120 emit cloneRequest(toClone.getId(), toClone.getType());
121 }
122
createFilterRequest(std::vector<CSMWorld::UniversalId> & types,Qt::DropAction action)123 void CSVWorld::TableSubView::createFilterRequest (std::vector< CSMWorld::UniversalId>& types, Qt::DropAction action)
124 {
125 std::vector<std::pair<std::string, std::vector<std::string> > > filterSource;
126
127 std::vector<std::string> refIdColumns = mTable->getColumnsWithDisplay(CSMWorld::TableMimeData::convertEnums(CSMWorld::UniversalId::Type_Referenceable));
128 bool hasRefIdDisplay = !refIdColumns.empty();
129
130 for (std::vector<CSMWorld::UniversalId>::iterator it(types.begin()); it != types.end(); ++it)
131 {
132 CSMWorld::UniversalId::Type type = it->getType();
133 std::vector<std::string> col = mTable->getColumnsWithDisplay(CSMWorld::TableMimeData::convertEnums(type));
134 if(!col.empty())
135 {
136 filterSource.emplace_back(it->getId(), col);
137 }
138
139 if(hasRefIdDisplay && CSMWorld::TableMimeData::isReferencable(type))
140 {
141 filterSource.emplace_back(it->getId(), refIdColumns);
142 }
143 }
144
145 mFilterBox->createFilterRequest(filterSource, action);
146 }
147
eventFilter(QObject * object,QEvent * event)148 bool CSVWorld::TableSubView::eventFilter (QObject* object, QEvent* event)
149 {
150 if (event->type() == QEvent::Drop)
151 {
152 if (QDropEvent* drop = dynamic_cast<QDropEvent*>(event))
153 {
154 const CSMWorld::TableMimeData* tableMimeData = dynamic_cast<const CSMWorld::TableMimeData*>(drop->mimeData());
155 if (!tableMimeData) // May happen when non-records (e.g. plain text) are dragged and dropped
156 return false;
157
158 bool handled = tableMimeData->holdsType(CSMWorld::UniversalId::Type_Filter);
159 if (handled)
160 {
161 mFilterBox->setRecordFilter(tableMimeData->returnMatching(CSMWorld::UniversalId::Type_Filter).getId());
162 }
163 return handled;
164 }
165 }
166 return false;
167 }
168
requestFocus(const std::string & id)169 void CSVWorld::TableSubView::requestFocus (const std::string& id)
170 {
171 mTable->requestFocus(id);
172 }
173