OpenWalnut  1.5.0dev
WQtColormapper.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <algorithm>
26 #include <iostream>
27 #include <map>
28 #include <memory>
29 #include <set>
30 #include <string>
31 #include <vector>
32 
33 #include <QApplication>
34 #include <QListWidgetItem>
35 #include <QScrollArea>
36 #include <QVBoxLayout>
37 #include <QWidgetAction>
38 #include <QtCore/QList>
39 #include <boost/bind/bind.hpp>
40 
41 #include "../WMainWindow.h"
42 #include "../WQtGui.h"
43 #include "../events/WEventTypes.h"
44 #include "../events/WUpdateTextureSorterEvent.h"
45 #include "../guiElements/WScaleLabel.h"
46 #include "WPropertyBoolWidget.h"
47 #include "WPropertyDoubleWidget.h"
48 #include "WQtColormapper.h"
49 #include "WQtPropertyGroupWidget.h"
50 #include "core/common/WAssert.h"
51 #include "core/dataHandler/WDataHandler.h"
52 #include "core/dataHandler/WDataSet.h"
53 #include "core/dataHandler/exceptions/WDHNoSuchSubject.h"
54 #include "core/graphicsEngine/WGEColormapping.h"
55 #include "core/graphicsEngine/WGETexture.h"
56 
58  : WQtDockWidget( "Colormaps", parent )
59 {
60  setObjectName( "Colormapper Dock" );
61 
62  m_textureListWidget = new QListWidget( this );
63  m_textureListWidget->setToolTip( "List of available colormaps. Only the upper <b>"
64  + QString().setNum( WGETexture3D::MAX_NUMBER_OF_TEXTURES )
65  + "</b> textures will be applied." );
66  this->setAllowedAreas( Qt::AllDockWidgetAreas );
67  this->setFeatures( QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable );
68  m_textureListWidget->setDragDropMode( QAbstractItemView::InternalMove );
69 
70  // be notified when moving items around
71  connect( m_textureListWidget->model(), SIGNAL( rowsMoved( const QModelIndex&, int, int, const QModelIndex&, int ) ),
72  this, SLOT( rowsMoved( const QModelIndex&, int, int, const QModelIndex&, int ) ) );
73 
74 
75  QWidget* panel = new QWidget( this );
76 
77  m_layout = new QVBoxLayout();
78  m_layout->setContentsMargins( 0, 0, 0, 0 );
79 
80  // create the move-up/down buttons
81  QAction* downAction = new QAction( WQtGui::getMainWindow()->getIconManager()->getIcon( "go-down" ), "Move selected colormap down.", this );
82  connect( downAction, SIGNAL( triggered() ), this, SLOT( moveItemDown() ) );
83 
84  QAction* upAction = new QAction( WQtGui::getMainWindow()->getIconManager()->getIcon( "go-up" ), "Move selected colormap up.", this );
85  connect( upAction, SIGNAL( triggered() ), this, SLOT( moveItemUp() ) );
86 
87  QAction* bottomAction = new QAction( WQtGui::getMainWindow()->getIconManager()->getIcon( "go-bottom" ), "Move selected colormap to the bottom.",
88  this );
89  connect( bottomAction, SIGNAL( triggered() ), this, SLOT( moveItemBottom() ) );
90 
91  QAction* topAction = new QAction( WQtGui::getMainWindow()->getIconManager()->getIcon( "go-top" ), "Move selected colormap to the top.", this );
92  connect( topAction, SIGNAL( triggered() ), this, SLOT( moveItemTop() ) );
93 
94  addTitleAction( bottomAction );
95  addTitleAction( downAction );
96  addTitleAction( upAction );
97  addTitleAction( topAction );
98 
99  m_layout->addWidget( m_textureListWidget );
100 
101  connect( m_textureListWidget, SIGNAL( itemClicked( QListWidgetItem* ) ), this, SLOT( handleTextureClicked() ) );
102 
103  panel->setLayout( m_layout );
104  setWidget( panel );
105 
106  // get the proper subscriptions to the colormapper signals.
107  std::shared_ptr< WGEColormapping > p = WGEColormapping::instance();
109  static_cast< WGEColormapping::TextureRegisterHandler >( boost::bind( &WQtColormapper::pushUpdateEvent, this ) ) );
111  static_cast< WGEColormapping::TextureDeregisterHandler >( boost::bind( &WQtColormapper::pushUpdateEvent, this ) ) );
112  m_replaceConnection = p->subscribeSignal( WGEColormapping::Replaced,
113  static_cast< WGEColormapping::TextureReplaceHandler >( boost::bind( &WQtColormapper::pushUpdateEvent, this ) ) );
114  m_sortConnection = p->subscribeSignal( WGEColormapping::Sorted,
115  static_cast< WGEColormapping::TextureSortHandler>( boost::bind( &WQtColormapper::pushUpdateEvent, this ) ) );
116 }
117 
119 {
120  m_registerConnection.disconnect();
121  m_deregisterConnection.disconnect();
122  m_sortConnection.disconnect();
123 }
124 
125 WQtColormapper::WQtTextureListItem::WQtTextureListItem( const osg::ref_ptr< WGETexture3D > texture, WQtColormapper* /*cmapper*/,
126  QListWidget* parent ):
127  QListWidgetItem( parent ),
128  m_texture( texture ),
129  m_parent( parent )
130 {
131  // only show the filename. If the name is not a filename, the texture name is used directly
132  std::vector< std::string > names = string_utils::tokenize( texture->name()->get().c_str(), "/" );
133  QString name = QString::fromStdString( texture->name()->get() );
134  if( names.size() )
135  {
136  name = QString::fromStdString( names.back() );
137  }
138 
139  // create nice widget
140  m_itemWidget = new QWidget( m_parent );
141  QHBoxLayout* containerLayout = new QHBoxLayout();
142  m_itemWidget->setLayout( containerLayout );
143 
144  // active property
145  WPropertyBoolWidget* active = new WPropertyBoolWidget( m_texture->active(), NULL, m_itemWidget );
146  active->setToolTip( "Turn this texture on or off. A turned off texture is completely invisible." );
147 
148  // create a slider for the for the texture
149  QWidget* labelContainer = new QWidget( m_itemWidget );
150  QHBoxLayout* labelContainerLayout = new QHBoxLayout();
151  labelContainer->setLayout( labelContainerLayout );
152 
153  WPropertyStringWidget* nameLabel = new WPropertyStringWidget( m_texture->name(), NULL, m_itemWidget );
154  nameLabel->setToolTip( "The name of this texture. This usually is the name of the file it was loaded from." );
155  nameLabel->forceInformationMode();
156  nameLabel->disableTextInteraction();
157 
158  labelContainerLayout->addWidget( nameLabel );
159 
160  // alpha property
161  WPropertyDoubleWidget* alpha = new WPropertyDoubleWidget( m_texture->alpha(), NULL, m_itemWidget );
162  alpha->setToolTip( "Change transparency of a texture. The higher this value, the more opaque is the texture. "
163  "This is very useful for mixing several datasets." );
164 
165  // create a button for opening the texture props
166 
167  // first, create a property group widget and an according widget action
168  QScrollArea* sa = new QScrollArea( m_itemWidget );
170  m_texture->getProperties(), QString::fromStdString( "Configure Colormap" ), 0, sa
171  );
172  sa->setWidget( props );
173 
174  // create widget action
175  QWidgetAction* propAction = new QWidgetAction( m_itemWidget );
176  propAction->setDefaultWidget( sa );
177 
178  // add it into an menu
179  QMenu* propActionMenu = new QMenu();
180  propActionMenu->addAction( propAction );
181 
182  // tool button
183  QToolButton* propActionBtn = new QToolButton( m_itemWidget );
184  propActionBtn->setPopupMode( QToolButton::InstantPopup );
185  propActionBtn->setMenu( propActionMenu );
186  propActionBtn->setIcon( WQtGui::getMainWindow()->getIconManager()->getIcon( "configure" ) );
187  propActionBtn->setToolButtonStyle( Qt::ToolButtonIconOnly );
188  propActionBtn->setContentsMargins( 0, 0, 0, 0 );
189  propActionBtn->setAutoRaise( true );
190  propActionBtn->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
191  propActionBtn->setToolTip( "Show all the configuration options for this texture and its colormap." );
192 
193  QLabel* grabWidget = new QLabel( m_itemWidget );
194  grabWidget->setPixmap( WQtGui::getMainWindow()->getIconManager()->getIcon( "touchpoint_small" ).pixmap( 24, 32 ) );
195  grabWidget->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
196  grabWidget->setFixedWidth( 24 );
197  grabWidget->setToolTip( "Drag and drop these textures to change their composition ordering." );
198 
199  // style
200  QPalette palette;
201  QColor defaultCol = palette.window().color();
202 
203  // label color
204  QColor labelCol = defaultCol.darker( 115 );
205  // property color
206  QColor propertyCol = defaultCol;
207 
208  propActionBtn->setStyleSheet( "background-color:" + propertyCol.name() + ";" );
209  active->setStyleSheet( "background-color:" + labelCol.name() + ";" );
210  alpha->setStyleSheet( "#ControlPanelPropertyWidget{ background-color:" + propertyCol.name() + ";}" );
211  nameLabel->setStyleSheet( "background-color:" + labelCol.name() + ";border:none;" );
212  labelContainer->setStyleSheet( "background-color:" + labelCol.name() + ";" );
213 
214  // fill layout
215  containerLayout->addWidget( grabWidget );
216  containerLayout->addWidget( active );
217  containerLayout->addWidget( labelContainer );
218  containerLayout->addWidget( alpha );
219  containerLayout->addWidget( propActionBtn );
220 
221  // compact layout
222  containerLayout->setContentsMargins( 0, 2, 0, 2 );
223  containerLayout->setSpacing( 0 );
224  labelContainerLayout->setContentsMargins( 2, 2, 0, 2 );
225  labelContainerLayout->setSpacing( 0 );
226 
227  // prefer stretching the label
228  containerLayout->setStretchFactor( active, 0 );
229  containerLayout->setStretchFactor( grabWidget, 0 );
230  containerLayout->setStretchFactor( labelContainer, 100 );
231  containerLayout->setStretchFactor( alpha, 75 );
232  containerLayout->setStretchFactor( propActionBtn, 0 );
233 
234  // widget size constraints and policies
235  m_itemWidget->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );
236 }
237 
239 {
240  // cleanup
241 }
242 
243 const osg::ref_ptr< WGETexture3D > WQtColormapper::WQtTextureListItem::getTexture() const
244 {
245  return m_texture;
246 }
247 
249 {
250  return m_itemWidget;
251 }
252 
254 {
255  // create a new event for this and insert it into event queue
256  QCoreApplication::postEvent( this, new WUpdateTextureSorterEvent() );
257 }
258 
260 {
261  // a texture added/removed/sorted/moved
262  if( event->type() == WQT_UPDATE_TEXTURE_SORTER_EVENT )
263  {
264  update();
265  return true;
266  }
267 
268  return WQtDockWidget::event( event );
269 }
270 
272 {
273  std::shared_ptr< WGEColormapping > cm = WGEColormapping::instance();
274 
276 
277  // we need to store the last selected texture if there was any
278  osg::ref_ptr< WGETexture3D > lastSelected;
279  WQtTextureListItem* item = dynamic_cast< WQtTextureListItem* >( m_textureListWidget->item( m_textureListWidget->currentIndex().row() ) );
280  if( item )
281  {
282  lastSelected = item->getTexture();
283  }
284 
285  // remove all items and rebuild list.
286  m_textureListWidget->clear();
287  for( WGEColormapping::TextureConstIterator iter = r->get().begin(); iter != r->get().end(); ++iter )
288  {
289  WQtTextureListItem* item = new WQtTextureListItem( *iter, this, m_textureListWidget );
290  QWidget* widget = item->getWidget();
291 
292  m_textureListWidget->addItem( item ); // the list widget removes the item (and frees the reference to the texture pointer).
293  item->setSizeHint( QSize( 0, widget->sizeHint().height() ) );
294  m_textureListWidget->setItemWidget( item, widget );
295 
296  // is the item the texture that has been selected previously?
297  if( item->getTexture() == lastSelected )
298  {
299  m_textureListWidget->setCurrentItem( item );
300  }
301  }
302 }
303 
305 {
306  // maybe someone is interested in this signal:
308  static_cast< WQtTextureListItem* >( m_textureListWidget->item( m_textureListWidget->currentIndex().row() ) )->getTexture()
309  );
310 }
311 
313 {
314  std::shared_ptr< WGEColormapping > cm = WGEColormapping::instance();
315  WQtTextureListItem* item = dynamic_cast< WQtTextureListItem* >( m_textureListWidget->item( m_textureListWidget->currentIndex().row() ) );
316  if( item )
317  {
318  cm->moveDown( item->getTexture() );
319  }
320 }
321 
323 {
324  std::shared_ptr< WGEColormapping > cm = WGEColormapping::instance();
325  WQtTextureListItem* item = dynamic_cast< WQtTextureListItem* >( m_textureListWidget->item( m_textureListWidget->currentIndex().row() ) );
326  if( item )
327  {
328  cm->moveUp( item->getTexture() );
329  }
330 }
331 
333 {
334  std::shared_ptr< WGEColormapping > cm = WGEColormapping::instance();
335  WQtTextureListItem* item = dynamic_cast< WQtTextureListItem* >( m_textureListWidget->item( m_textureListWidget->currentIndex().row() ) );
336  if( item )
337  {
338  cm->moveToBottom( item->getTexture() );
339  }
340 }
341 
343 {
344  std::shared_ptr< WGEColormapping > cm = WGEColormapping::instance();
345  WQtTextureListItem* item = dynamic_cast< WQtTextureListItem* >( m_textureListWidget->item( m_textureListWidget->currentIndex().row() ) );
346  if( item )
347  {
348  cm->moveToTop( item->getTexture() );
349  }
350 }
351 
352 void WQtColormapper::selectTexture( std::shared_ptr< WDataSet > dataSet )
353 {
354  // simply check each item against the texture in the specified dataset
355  for( int i = 0; i < m_textureListWidget->count(); ++i )
356  {
357  WQtTextureListItem* item = dynamic_cast< WQtTextureListItem* >( m_textureListWidget->item( i ) );
358  if( item && dataSet->isTexture() && ( item->getTexture() == dataSet->getTexture() ) )
359  {
360  m_textureListWidget->setCurrentItem( item );
361  }
362  }
363 }
364 
365 void WQtColormapper::rowsMoved( const QModelIndex& sourceParent, int sourceStart, int sourceEnd,
366  const QModelIndex& destinationParent, int destinationRow )
367 {
368  WAssert( sourceStart == sourceEnd, "Multiple texture items selected. This should not be the case." );
369  WAssert( sourceParent == destinationParent, "Source and target parent are not the same. This should not be the case." );
370 
371  // just utilize WGEColormapper for this:
372  std::shared_ptr< WGEColormapping > cm = WGEColormapping::instance();
373  WQtTextureListItem* item = dynamic_cast< WQtTextureListItem* >( m_textureListWidget->item( m_textureListWidget->currentIndex().row() ) );
374  if( item )
375  {
376  cm->moveTo( item->getTexture(), destinationRow );
377  }
378 }
379 
TextureRegisterHandler TextureDeregisterHandler
The type of handler used for being notified about removed textures.
boost::function< void(void) > TextureSortHandler
The type of handler called whenever the texture list got resorted.
boost::function< void(osg::ref_ptr< WGETexture3D >, osg::ref_ptr< WGETexture3D >) > TextureReplaceHandler
The type of handler used for being notified about replaced textures.
static std::shared_ptr< WGEColormapping > instance()
Returns instance of the module factory to use to create modules.
@ Deregistered
texture got removed
@ Registered
texture got added
@ Sorted
texture list was resorted
@ Replaced
texture got replaced
TextureContainerType::ConstIterator TextureConstIterator
Const iterator to access the texture list.
boost::function< void(osg::ref_ptr< WGETexture3D >) > TextureRegisterHandler
The type of handler used for being notified about added textures.
static std::size_t const MAX_NUMBER_OF_TEXTURES
We support only 8 textures because some known hardware does not support more texture coordinates.
Definition: WGETexture.h:66
Implements a property widget for WPropBool.
Implements a property widget for WPropDouble.
Implements a property widget for WPropString.
void disableTextInteraction(bool disable=true)
Disable the ability to select text.
void forceInformationMode(bool force=true)
Force the widget to use the information widgets.
This class represents a texture item in the list widget.
const osg::ref_ptr< WGETexture3D > getTexture() const
Returns the associated texture.
const osg::ref_ptr< WGETexture3D > m_texture
The texture that gets handled.
virtual ~WQtTextureListItem()
Destructor.
QWidget * m_itemWidget
Widget representing the item.
QWidget * getWidget() const
Create a new widget for this item.
QListWidget * m_parent
Parent list.
WQtTextureListItem(const osg::ref_ptr< WGETexture3D > texture, WQtColormapper *cmapper, QListWidget *parent=0)
Creates new instance of list item.
This widget controls the colormapper of openwalnut.
void moveItemUp()
change order of items, move currently selected item up
WQtColormapper(QWidget *parent=0)
Default constructor.
QListWidget * m_textureListWidget
pointer to the tree widget
QVBoxLayout * m_layout
Layout of the widget.
void update()
Update the list view from the list of data sets.
void selectTexture(std::shared_ptr< WDataSet > dataSet)
Select a certain texture in the texture sorter belonging to the specified dataset.
virtual bool event(QEvent *event)
Custom event dispatcher.
boost::signals2::connection m_replaceConnection
Connection of the WGEColormapping signal "replaced" to the member function pushUpdateEvent.
void moveItemTop()
change order of items, move currently selected item to top
boost::signals2::connection m_deregisterConnection
Connection of the WGEColormapping signal "deregistered" to the member function pushUpdateEvent.
virtual ~WQtColormapper()
Destructor.
void moveItemBottom()
change order of items, move currently selected item to bottom
boost::signals2::connection m_sortConnection
Connection of the WGEColormapping signal "Sort" to the member function pushUpdateEvent.
void textureSelectionChanged(osg::ref_ptr< WGETexture3D > texture)
Indicates that a texture has been clicked and return the texture.
void handleTextureClicked()
Handles a click to a texture in the list.
void pushUpdateEvent()
Called by the colormapper causing an update event being pushed to the event queue.
void rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
A item was moved into another row.
void moveItemDown()
change order of items, move currently selected item down
boost::signals2::connection m_registerConnection
Connection of the WGEColormapping signal "registered" to the member function pushUpdateEvent.
Advanced QDockWidget.
Definition: WQtDockWidget.h:50
virtual void addTitleAction(QAction *action, bool instantPopup=false)
Add the given action to the titlebar.
static WMainWindow * getMainWindow()
Returns the current main window instance or NULL if not existent.
Definition: WQtGui.cpp:88
static QWidget * createPropertyGroupBox(QWidget *widget, bool asScrollArea=false, QWidget *parent=NULL, const QString &title="", int nestingLevel=0)
This function creates the fancy box around your specified group widget.
std::shared_ptr< WSharedObjectTicketRead< T > > ReadTicket
Type for read tickets.
Definition: WSharedObject.h:65
Event signalling a new module has been associated with the root container in the kernel.
std::vector< std::string > tokenize(const std::string &source, const std::string &delim=WHITESPACE, bool compress=true)
Splits the given string into a vector of strings (so called tokens).