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