Fraxinus  16.5.0-fx-rc1
An IGT application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cxBrowserWidget.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) 2008-2014, SINTEF Department of Medical Technology
5 All rights reserved.
6 
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 
10 1. Redistributions of source code must retain the above copyright notice,
11  this list of conditions and the following disclaimer.
12 
13 2. Redistributions in binary form must reproduce the above copyright notice,
14  this list of conditions and the following disclaimer in the documentation
15  and/or other materials provided with the distribution.
16 
17 3. Neither the name of the copyright holder nor the names of its contributors
18  may be used to endorse or promote products derived from this software
19  without specific prior written permission.
20 
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 =========================================================================*/
32 #include "cxBrowserWidget.h"
33 
34 #include <QTreeView>
35 #include "cxTreeItemModel.h"
36 #include "cxLogger.h"
37 #include <QSplitter>
38 #include <QMenu>
39 #include <QLabel>
40 #include "cxTreeNode.h"
41 #include "cxPopupToolbarWidget.h"
42 #include <QWidgetAction>
43 #include <QCheckBox>
44 #include "boost/bind.hpp"
45 #include "cxTreeRepository.h"
46 #include "cxProfile.h"
48 #include "cxDataSelectWidget.h"
49 
50 namespace cx
51 {
52 
53 BrowserWidget::BrowserWidget(QWidget* parent, VisServicesPtr services) :
54  BaseWidget(parent, "BrowserWidget", "Browser"),
55  mServices(services),
56  mModel(NULL)
57 {
58  mOptions = profile()->getXmlSettings().descend(this->objectName());
59  this->setModified();
60 }
61 
62 void BrowserWidget::createGUI()
63 {
64  QVBoxLayout* layout = new QVBoxLayout(this);
65  layout->setMargin(0);
66  layout->setSpacing(0);
67 
68  mModel = new TreeItemModel(mOptions.descend("model"), mServices, this);
69  connect(mModel, &TreeItemModel::modelAboutToBeReset, this, &BrowserWidget::setModified);
70  connect(mModel, &TreeItemModel::currentItemChanged, this, &BrowserWidget::onCurrentItemChanged);
71  connect(mModel, &TreeItemModel::loaded, this, &BrowserWidget::onLoaded);
72 
73  //layout
74  mTreeView = new QTreeView(this);
75 // mTreeView->setRootIsDecorated(false);
76 // mTreeView->setTreePosition(1);
77  mTreeView->setModel(mModel);
78  connect(mTreeView.data(), &QTreeView::collapsed, this, &BrowserWidget::onNodeCollapsed);
79  connect(mTreeView.data(), &QTreeView::expanded, this, &BrowserWidget::onNodeExpanded);
80  mModel->setSelectionModel(mTreeView->selectionModel());
81 
82  mPopupWidget = new PopupToolbarWidget(this);
83  connect(mPopupWidget, &PopupToolbarWidget::popup, this, &BrowserWidget::onPopup);
84  layout->addWidget(mPopupWidget);
85  mPopupWidget->setPopupVisible(this->getShowToolbarOption().readValue(QString::number(false)).toInt());
86 
87  mPropertiesWidget = new ReplacableContentWidget(this);
88  mPropertiesWidget->setWidget(new QLabel("no\nproperties\nselected"));
89 
90  mSplitter = new ControllableSplitter(mOptions.descend("splitter"), this);
91  layout->addWidget(mSplitter, 1);
92  mSplitter->addLeftWidget(mTreeView, "browser");
93  mSplitter->addRightWidget(mPropertiesWidget, "properties");
94 
95  this->createButtonWidget(mPopupWidget->getToolbar());
96 }
97 
98 void BrowserWidget::onNodeCollapsed(const QModelIndex & index)
99 {
100  mExpanded.removeAll(mModel->getNodeFromIndex(index)->getUid());
101 }
102 
103 void BrowserWidget::onNodeExpanded(const QModelIndex & index)
104 {
105  QString uid = mModel->getNodeFromIndex(index)->getUid();
106  if (!mExpanded.contains(uid))
107  mExpanded.push_back(uid);
108 }
109 
110 void BrowserWidget::onPopup()
111 {
112  this->getShowToolbarOption().writeValue(QString::number(mPopupWidget->popupIsVisible()));
113 }
114 
116 {
117 }
118 
120 {
121  if (!mModel)
122  this->createGUI();
123  mPopupWidget->refresh();
124 // CX_LOG_CHANNEL_DEBUG("CA") << "BrowserWidget::prePaintEvent() modified";
125  mModel->update();
126  this->resetView();
127 }
128 
129 void BrowserWidget::updateNodeName()
130 {
132 
133  if (mName->actions().empty())
134  mName->addAction(node->getIcon(), QLineEdit::LeadingPosition);
135  else
136  mName->actions().front()->setIcon(node->getIcon());
137 
138 
139  mName->setText(node->getName());
140 // mName->addAction(node->getIcon(), QLineEdit::LeadingPosition);
141 
142  int height = mName->height();
143 
144  QFontMetrics fm(QFont("", 0));
145  mName->setFixedSize(fm.width(mName->text())+height*2, height);
146 
147 // this->adjustSize();
148 }
149 
150 
151 void BrowserWidget::createButtonWidget(QWidget* widget)
152 {
153  QHBoxLayout* buttonLayout = new QHBoxLayout(widget);
154  buttonLayout->setMargin(0);
155  buttonLayout->setSpacing(0);
156 
157  StringListSelectWidget* visibility = new StringListSelectWidget(this, mModel->repo()->getVisibilityProperty());
158  visibility->showLabel(false);
159  visibility->setIcon(QIcon(":/icons/open_icon_library/arrange_vertical.png"));
160  buttonLayout->addWidget(visibility);
161 
162  LabeledComboBoxWidget* mode = new LabeledComboBoxWidget(this, mModel->repo()->getModeProperty());
163  mode->showLabel(false);
164  buttonLayout->addSpacing(8);
165  buttonLayout->addWidget(mode);
166  buttonLayout->setStretch(buttonLayout->count()-1, 0);
167 
168  StringListSelectWidget* columns = new StringListSelectWidget(this, mModel->getShowColumnsProperty());
169  columns->showLabel(false);
170  columns->setIcon(QIcon(":/icons/open_icon_library/arrange_horizontal.png"));
171  buttonLayout->addWidget(columns);
172 
173  buttonLayout->addSpacing(8);
174 
175  // everything being added after this will be aligned to the right side
176  buttonLayout->addStretch(1);
177 
178  mRemoveButton = new EraseDataToolButton(this);
179  connect(mRemoveButton, &EraseDataToolButton::eraseData, this, &BrowserWidget::eraseCurrentNode);
180  buttonLayout->addWidget(mRemoveButton);
181 
182  mName = new QLineEdit;
183  mName->setReadOnly(true);
184  buttonLayout->addWidget(mName);
185 
186  QToolButton* button;
187  button = new CXSmallToolButton();
188  button->setDefaultAction(mSplitter->getMoveLeftAction());
189  buttonLayout->addWidget(button);
190 
191  button = new CXSmallToolButton();
192  button->setDefaultAction(mSplitter->getMoveRightAction());
193  buttonLayout->addWidget(button);
194 }
195 
196 XmlOptionItem BrowserWidget::getShowToolbarOption()
197 {
198  return XmlOptionItem("show_toolbar", mOptions.getElement());
199 }
200 
201 void BrowserWidget::expandDefault(QModelIndex index)
202 {
203  TreeNodePtr node = mModel->getNodeFromIndex(index);
204  if (!node->isDefaultExpanded())
205  return;
206 
207  mTreeView->expand(index);
208 
209  int rc = mModel->rowCount(index);
210  for (int r=0; r<rc; ++r)
211  {
212  QModelIndex child = mModel->index(r, 0, index);
213  this->expandDefault(child);
214  }
215 }
216 
217 void BrowserWidget::expandRestore(QModelIndex index)
218 {
219  TreeNodePtr node = mModel->getNodeFromIndex(index);
220  if (index.isValid() && !mExpanded.contains(node->getUid()))
221  return;
222 // CX_LOG_CHANNEL_DEBUG("CA") << " expandRestore " << node->getUid();
223 
224  mTreeView->expand(index);
225 
226  int rc = mModel->rowCount(index);
227  for (int r=0; r<rc; ++r)
228  {
229  QModelIndex child = mModel->index(r, 0, index);
230  this->expandRestore(child);
231  }
232 }
233 
234 bool BrowserWidget::setCurrentNode(QString uid, QModelIndex index)
235 {
236  TreeNodePtr node = mModel->getNodeFromIndex(index);
237 // CX_LOG_CHANNEL_DEBUG("CA") << " setCurrentNode: inspecting node " << node->getUid();
238 
239  if (node && (node->getUid()==uid))
240  {
241 // CX_LOG_CHANNEL_DEBUG("CA") << " setCurrentNode: HIT, setting current index " << node->getUid();
242 // boost::function<void()> f =
243 // boost::bind(&QItemSelectionModel::setCurrentIndex,
244 // mTreeView->selectionModel(),
245 // index,
246 // QItemSelectionModel::Current);
247 // QTimer::singleShot(0, f);
248  mTreeView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select);
249 // mTreeView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Current);
250  return true;
251  }
252 
253  int rc = mModel->rowCount(index);
254  for (int r=0; r<rc; ++r)
255  {
256  QModelIndex child = mModel->index(r, 0, index);
257  if (this->setCurrentNode(uid, child))
258  return true;
259  }
260  return false;
261 }
262 
264 {
265  mTreeView->setRootIsDecorated(mModel->repo()->getMode()!="spaces");
266 
267  if (mExpanded.empty())
268  {
269  this->expandDefault(QModelIndex());
270 // CX_LOG_CHANNEL_DEBUG("CA") << "===BrowserWidget:: rebuild default()";
271 
272  for (unsigned i=0; i<mModel->columnCount(); ++i)
273  mTreeView->resizeColumnToContents(i);
274  }
275  else
276  {
277 // CX_LOG_CHANNEL_DEBUG("CA") << "===BrowserWidget::reset content() ";// << mExpanded.join("\n ");
278  this->expandRestore(QModelIndex());
279  }
280 
281 // CX_LOG_CHANNEL_DEBUG("CA") << "===BrowserWidget::setCurrentNode " << mActiveNodeUid;
282  this->setCurrentNode(mActiveNodeUid, QModelIndex());
283 
284 //. mActiveNodeUid = node->getUid();
285 }
286 
287 void BrowserWidget::onLoaded()
288 {
289  mExpanded.clear();
290  this->setModified();
291 }
292 
293 void BrowserWidget::onCurrentItemChanged()
294 {
295 // CX_LOG_CHANNEL_DEBUG("CA") << " *********** BrowserWidget::onCurrentItemChanged()";
296 
298 
299  if (node->getUid() == mActiveNodeUid)
300  return;
301  if (node->getUid() == mModel->repo()->getTopNode()->getUid())
302  return;
303 
304  mRemoveButton->setEnabled(node && node->isRemovable());
305  this->updateNodeName();
306 
307  if (node)
308  {
309  mActiveNodeUid = node->getUid();
310 // CX_LOG_CHANNEL_DEBUG("CA") << " store CurrentNode " << mActiveNodeUid;
311  QWidget* widget = node->createPropertiesWidget();
312  mPropertiesWidget->setWidget(widget);
313 // CX_LOG_CHANNEL_DEBUG("CA") << "mPropertiesWidget: " << mPropertiesWidget->parent();
314 // if (widget)
315 // CX_LOG_CHANNEL_DEBUG("CA") << " : " << widget->parent();
316  }
317 }
318 
319 void BrowserWidget::eraseCurrentNode()
320 {
322  if (!node)
323  return;
324 
325  node->remove();
326 }
327 
328 }//end namespace cx
TreeItemModel * mModel
void currentItemChanged()
boost::shared_ptr< TreeNode > TreeNodePtr
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:176
BrowserWidget(QWidget *parent, VisServicesPtr services)
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:62
TreeRepositoryPtr repo()
TreeNodePtr getCurrentItem()
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const
void addLeftWidget(QWidget *widget, QString name)
QDomElement getElement()
return the current element
virtual void prePaintEvent()
virtual QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const
QPointer< QTreeView > mTreeView
void writeValue(const QString &val)
Interface for QWidget which handles widgets uniformly for the system.
Definition: cxBaseWidget.h:108
void eraseData()
indicates that erase has been requested by user.
void setSelectionModel(QItemSelectionModel *selectionModel)
void popup(bool show)
TreeNodePtr getNodeFromIndex(const QModelIndex &index)
StringListPropertyPtr getShowColumnsProperty()
virtual int rowCount(const QModelIndex &parent=QModelIndex()) const
void addRightWidget(QWidget *widget, QString name)
XmlOptionFile descend(QString element) const
step one level down in the xml tree