CustusX  2023.01.05-dev+develop.0da12
An IGT application
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) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 #include "cxBrowserWidget.h"
12 
13 #include <QTreeView>
14 #include "cxTreeItemModel.h"
15 #include "cxLogger.h"
16 #include <QSplitter>
17 #include <QMenu>
18 #include <QLabel>
19 #include "cxTreeNode.h"
20 #include "cxPopupToolbarWidget.h"
21 #include <QWidgetAction>
22 #include <QCheckBox>
23 #include "boost/bind.hpp"
24 #include "cxTreeRepository.h"
25 #include "cxProfile.h"
27 #include "cxDataSelectWidget.h"
28 
29 namespace cx
30 {
31 
32 BrowserWidget::BrowserWidget(QWidget* parent, VisServicesPtr services) :
33  BaseWidget(parent, "BrowserWidget", "Browser"),
34  mServices(services),
35  mModel(NULL)
36 {
37  mOptions = profile()->getXmlSettings().descend(this->objectName());
38  this->setModified();
39 }
40 
41 void BrowserWidget::createGUI()
42 {
43  QVBoxLayout* layout = new QVBoxLayout(this);
44  layout->setMargin(0);
45  layout->setSpacing(0);
46 
47  mModel = new TreeItemModel(mOptions.descend("model"), mServices, this);
48  connect(mModel, &TreeItemModel::modelAboutToBeReset, this, &BrowserWidget::setModified);
49  connect(mModel, &TreeItemModel::currentItemChanged, this, &BrowserWidget::onCurrentItemChanged);
50  connect(mModel, &TreeItemModel::loaded, this, &BrowserWidget::onLoaded);
51 
52  //layout
53  mTreeView = new QTreeView(this);
54 // mTreeView->setRootIsDecorated(false);
55 // mTreeView->setTreePosition(1);
56  mTreeView->setModel(mModel);
57  connect(mTreeView.data(), &QTreeView::collapsed, this, &BrowserWidget::onNodeCollapsed);
58  connect(mTreeView.data(), &QTreeView::expanded, this, &BrowserWidget::onNodeExpanded);
59  mModel->setSelectionModel(mTreeView->selectionModel());
60 
61  mPopupWidget = new PopupToolbarWidget(this);
62  connect(mPopupWidget, &PopupToolbarWidget::popup, this, &BrowserWidget::onPopup);
63  layout->addWidget(mPopupWidget);
64  mPopupWidget->setPopupVisible(this->getShowToolbarOption().readValue(QString::number(false)).toInt());
65 
66  mPropertiesWidget = new ReplacableContentWidget(this);
67  mPropertiesWidget->setWidgetDeleteOld(new QLabel("no\nproperties\nselected"));
68 
69  mSplitter = new ControllableSplitter(mOptions.descend("splitter"), this);
70  layout->addWidget(mSplitter, 1);
71  mSplitter->addLeftWidget(mTreeView, "browser");
72  mSplitter->addRightWidget(mPropertiesWidget, "properties");
73 
74  this->createButtonWidget(mPopupWidget->getToolbar());
75 }
76 
77 void BrowserWidget::onNodeCollapsed(const QModelIndex & index)
78 {
79  mExpanded.removeAll(mModel->getNodeFromIndex(index)->getUid());
80 }
81 
82 void BrowserWidget::onNodeExpanded(const QModelIndex & index)
83 {
84  QString uid = mModel->getNodeFromIndex(index)->getUid();
85  if (!mExpanded.contains(uid))
86  mExpanded.push_back(uid);
87 }
88 
89 void BrowserWidget::onPopup()
90 {
91  this->getShowToolbarOption().writeValue(QString::number(mPopupWidget->popupIsVisible()));
92 }
93 
95 {
96 }
97 
99 {
100  if (!mModel)
101  this->createGUI();
102  mPopupWidget->refresh();
103 // CX_LOG_CHANNEL_DEBUG("CA") << "BrowserWidget::prePaintEvent() modified";
104  mModel->update();
105  this->resetView();
106 }
107 
108 void BrowserWidget::updateNodeName()
109 {
111 
112  if (mName->actions().empty())
113  mName->addAction(node->getIcon(), QLineEdit::LeadingPosition);
114  else
115  mName->actions().front()->setIcon(node->getIcon());
116 
117 
118  mName->setText(node->getName());
119 // mName->addAction(node->getIcon(), QLineEdit::LeadingPosition);
120 
121  int height = mName->height();
122 
123  QFontMetrics fm(QFont("", 0));
124  mName->setFixedSize(fm.width(mName->text())+height*2, height);
125 
126 // this->adjustSize();
127 }
128 
129 
130 void BrowserWidget::createButtonWidget(QWidget* widget)
131 {
132  QHBoxLayout* buttonLayout = new QHBoxLayout(widget);
133  buttonLayout->setMargin(0);
134  buttonLayout->setSpacing(0);
135 
136  StringListSelectWidget* visibility = new StringListSelectWidget(this, mModel->repo()->getVisibilityProperty());
137  visibility->showLabel(false);
138  visibility->setIcon(QIcon(":/icons/open_icon_library/arrange_vertical.png"));
139  buttonLayout->addWidget(visibility);
140 
141  LabeledComboBoxWidget* mode = new LabeledComboBoxWidget(this, mModel->repo()->getModeProperty());
142  mode->showLabel(false);
143  buttonLayout->addSpacing(8);
144  buttonLayout->addWidget(mode);
145  buttonLayout->setStretch(buttonLayout->count()-1, 0);
146 
148  columns->showLabel(false);
149  columns->setIcon(QIcon(":/icons/open_icon_library/arrange_horizontal.png"));
150  buttonLayout->addWidget(columns);
151 
152  buttonLayout->addSpacing(8);
153 
154  // everything being added after this will be aligned to the right side
155  buttonLayout->addStretch(1);
156 
157  mRemoveButton = new EraseDataToolButton(this);
158  connect(mRemoveButton, &EraseDataToolButton::eraseData, this, &BrowserWidget::eraseCurrentNode);
159  buttonLayout->addWidget(mRemoveButton);
160 
161  mName = new QLineEdit;
162  mName->setReadOnly(true);
163  buttonLayout->addWidget(mName);
164 
165  QToolButton* button;
166  button = new CXSmallToolButton();
167  button->setDefaultAction(mSplitter->getMoveLeftAction());
168  buttonLayout->addWidget(button);
169 
170  button = new CXSmallToolButton();
171  button->setDefaultAction(mSplitter->getMoveRightAction());
172  buttonLayout->addWidget(button);
173 }
174 
175 XmlOptionItem BrowserWidget::getShowToolbarOption()
176 {
177  return XmlOptionItem("show_toolbar", mOptions.getElement());
178 }
179 
180 void BrowserWidget::expandDefault(QModelIndex index)
181 {
182  TreeNodePtr node = mModel->getNodeFromIndex(index);
183  if (!node->isDefaultExpanded())
184  return;
185 
186  mTreeView->expand(index);
187 
188  int rc = mModel->rowCount(index);
189  for (int r=0; r<rc; ++r)
190  {
191  QModelIndex child = mModel->index(r, 0, index);
192  this->expandDefault(child);
193  }
194 }
195 
196 void BrowserWidget::expandRestore(QModelIndex index)
197 {
198  TreeNodePtr node = mModel->getNodeFromIndex(index);
199  if (index.isValid() && !mExpanded.contains(node->getUid()))
200  return;
201 // CX_LOG_CHANNEL_DEBUG("CA") << " expandRestore " << node->getUid();
202 
203  mTreeView->expand(index);
204 
205  int rc = mModel->rowCount(index);
206  for (int r=0; r<rc; ++r)
207  {
208  QModelIndex child = mModel->index(r, 0, index);
209  this->expandRestore(child);
210  }
211 }
212 
213 bool BrowserWidget::setCurrentNode(QString uid, QModelIndex index)
214 {
215  TreeNodePtr node = mModel->getNodeFromIndex(index);
216 // CX_LOG_CHANNEL_DEBUG("CA") << " setCurrentNode: inspecting node " << node->getUid();
217 
218  if (node && (node->getUid()==uid))
219  {
220 // CX_LOG_CHANNEL_DEBUG("CA") << " setCurrentNode: HIT, setting current index " << node->getUid();
221 // boost::function<void()> f =
222 // boost::bind(&QItemSelectionModel::setCurrentIndex,
223 // mTreeView->selectionModel(),
224 // index,
225 // QItemSelectionModel::Current);
226 // QTimer::singleShot(0, f);
227  mTreeView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Select);
228 // mTreeView->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Current);
229  return true;
230  }
231 
232  int rc = mModel->rowCount(index);
233  for (int r=0; r<rc; ++r)
234  {
235  QModelIndex child = mModel->index(r, 0, index);
236  if (this->setCurrentNode(uid, child))
237  return true;
238  }
239  return false;
240 }
241 
243 {
244  mTreeView->setRootIsDecorated(mModel->repo()->getMode()!="spaces");
245 
246  if (mExpanded.empty())
247  {
248  this->expandDefault(QModelIndex());
249 // CX_LOG_CHANNEL_DEBUG("CA") << "===BrowserWidget:: rebuild default()";
250 
251  for (unsigned i=0; i<mModel->columnCount(); ++i)
252  mTreeView->resizeColumnToContents(i);
253  }
254  else
255  {
256 // CX_LOG_CHANNEL_DEBUG("CA") << "===BrowserWidget::reset content() ";// << mExpanded.join("\n ");
257  this->expandRestore(QModelIndex());
258  }
259 
260 // CX_LOG_CHANNEL_DEBUG("CA") << "===BrowserWidget::setCurrentNode " << mActiveNodeUid;
261  this->setCurrentNode(mActiveNodeUid, QModelIndex());
262 
263 //. mActiveNodeUid = node->getUid();
264 }
265 
266 void BrowserWidget::onLoaded()
267 {
268  mExpanded.clear();
269  this->setModified();
270 }
271 
272 void BrowserWidget::onCurrentItemChanged()
273 {
274 // CX_LOG_CHANNEL_DEBUG("CA") << " *********** BrowserWidget::onCurrentItemChanged()";
275 
277 
278  if (node->getUid() == mActiveNodeUid)
279  return;
280  if (node->getUid() == mModel->repo()->getTopNode()->getUid())
281  return;
282 
283  mRemoveButton->setEnabled(node && node->isRemovable());
284  this->updateNodeName();
285 
286  if (node)
287  {
288  mActiveNodeUid = node->getUid();
289 // CX_LOG_CHANNEL_DEBUG("CA") << " store CurrentNode " << mActiveNodeUid;
290  boost::shared_ptr<QWidget> widget = node->createPropertiesWidget();
291  mPropertiesWidget->setWidget(widget);
292 // CX_LOG_CHANNEL_DEBUG("CA") << "mPropertiesWidget: " << mPropertiesWidget->parent();
293 // if (widget)
294 // CX_LOG_CHANNEL_DEBUG("CA") << " : " << widget->parent();
295  }
296 }
297 
298 void BrowserWidget::eraseCurrentNode()
299 {
301  if (!node)
302  return;
303 
304  node->remove();
305 }
306 
307 }//end namespace cx
TreeItemModel * mModel
void currentItemChanged()
boost::shared_ptr< TreeNode > TreeNodePtr
cxResource_EXPORT ProfilePtr profile()
Definition: cxProfile.cpp:160
BrowserWidget(QWidget *parent, VisServicesPtr services)
boost::shared_ptr< class VisServices > VisServicesPtr
Definition: cxMainWindow.h:40
TreeRepositoryPtr repo()
TreeNodePtr getCurrentItem()
Composite widget for string list selection.
virtual int columnCount(const QModelIndex &parent=QModelIndex()) const
Composite widget for string selection.
void addLeftWidget(QWidget *widget, QString name)
QDomElement getElement()
return the current element
Helper class for storing one string value in an xml document.
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:88
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
Namespace for all CustusX production code.