OpenWalnut  1.5.0dev
WQtNetworkEditorProjectFileIO.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 <string>
27 
28 #include <boost/regex.hpp>
29 #include <boost/tokenizer.hpp>
30 
31 #include "core/common/WLogger.h"
32 #include "core/common/WStringUtils.h"
33 #include "core/kernel/WProjectFile.h"
34 #include "core/kernel/WKernel.h"
35 #include "core/kernel/WModuleContainer.h"
36 #include "core/kernel/WModule.h"
37 
38 #include "WQtNetworkEditor.h"
39 #include "WQtNetworkItemGrid.h"
40 #include "WQtNetworkEditorProjectFileIO.h"
41 
44  m_networkEditor( ne ),
45  m_networkScale( 1.0 )
46 {
47  // initialize members
48  // We want to set the layout before actually starting the network.
49  setApplyOrder( PRE_MODULES );
50 }
51 
53 {
54  // cleanup
55 }
56 
58 {
59  // Nothing special. Simply create new instance.
61  p->setProject( project );
62  return p;
63 }
64 
65 /**
66  * Interpret a string as a ";"- separated sequence of doubles.
67  *
68  * \param seq the sequence
69  * \param size the number of ints needed
70  * \param loaded will contain the number of ints really loaded.
71  *
72  * \return the values
73  */
74 int* parseIntSequence( std::string seq, int size, int& loaded ) // NOLINT: yes it is a non const ref.
75 {
76  // parse the string
77  // -> tokenize it and fill pointer appropriately
78  typedef boost::tokenizer<boost::char_separator< char > > tokenizer;
79  boost::char_separator< char > sep( ";" ); // separate by ;
80  tokenizer tok( seq, sep );
81 
82  // each value must be stored at the proper position
83  int* values = new int[ size ];
84  int i = 0;
85  loaded = 0;
86  for( tokenizer::iterator it = tok.begin(); ( it != tok.end() ) && ( i < size ); ++it )
87  {
88  values[ i ] = string_utils::fromString< int >( ( *it ) );
89  ++i;
90  ++loaded;
91  }
92 
93  // finally, set the values
94  return values;
95 }
96 
97 bool WQtNetworkEditorProjectFileIO::parse( std::string line, unsigned int lineNumber )
98 {
99  static const boost::regex networkCoordRe( "^ *QT5GUI_NETWORK:([0-9]*)=(.*)$" );
100  static const boost::regex networkFlagsRe( "^ *QT5GUI_NETWORK_Flags:([0-9]*)=(.*)$" );
101  static const boost::regex networkScaleRe( "^ *QT5GUI_NETWORK_Scale:(.*)$" );
102 
103  // use regex to parse it
104  boost::smatch matches; // the list of matches
105  if( boost::regex_match( line, matches, networkCoordRe ) )
106  {
107  // network editor coordinate
108  // matches[1] is the ID of the module
109  // matches[2] is the network coordinate
110  wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Network \"" << matches[2] << "\" with module ID " << matches[1];
111 
112  unsigned int id = string_utils::fromString< unsigned int >( matches[1] );
113  int loaded = 0;
114  int* coordRaw = parseIntSequence( string_utils::toString( matches[2] ), 4, loaded );
115 
116  if( loaded == 2 ) // loaded coords
117  {
118  // store. Applied later.
119  m_networkCoords[ id ] = QPoint( coordRaw[0], coordRaw[1] );
120  }
121 
122  return true;
123  }
124  else if( boost::regex_match( line, matches, networkFlagsRe ) )
125  {
126  // network editor coordinate
127  // matches[1] is the ID of the module
128  // matches[2] is the network coordinate
129  wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Network Flags\"" << matches[2] << "\" with module ID " << matches[1];
130 
131  unsigned int id = string_utils::fromString< unsigned int >( matches[1] );
132  int loaded = 0;
133  int* coordRaw = parseIntSequence( string_utils::toString( matches[2] ), 4, loaded );
134 
135  if( loaded == 2 ) // loaded flags
136  {
137  // store. Applied later.
138  m_networkFlags[ id ] = QPoint( coordRaw[0], coordRaw[1] );
139  }
140 
141  return true;
142  }
143  else if( boost::regex_match( line, matches, networkScaleRe ) )
144  {
145  wlog::debug( "Project Loader [Parser]" ) << "Line " << lineNumber << ": Network Scale " << matches[1];
146  m_networkScale = string_utils::fromString< double >( matches[1] );
147 
148  return true;
149  }
150 
151  return false;
152 }
153 
155 {
156  // apply changes
157 
158  // get bounding box
159  QPoint bbTL; // top left
160  QPoint bbBR; // bottom right
161  for( ModuleNetworkCoordinates::const_iterator it = m_networkCoords.begin(); it != m_networkCoords.end(); ++it )
162  {
163  // init first element
164  if( it == m_networkCoords.begin() )
165  {
166  bbTL = ( *it ).second;
167  bbBR = ( *it ).second;
168  }
169  else
170  {
171  // min/max
172  bbTL.rx() = std::min( bbTL.x(), ( *it ).second.x() );
173  bbTL.ry() = std::min( bbTL.y(), ( *it ).second.y() );
174  bbBR.rx() = std::max( bbBR.x(), ( *it ).second.x() );
175  bbBR.ry() = std::max( bbBR.y(), ( *it ).second.y() );
176  }
177  }
178 
179  // request a reserved grid zone:
180  // NOTE: future possibility?!
181  // unsigned int reservedAreadID = m_networkEditor->getLayout()->reserveRect( bbTL, bbBR );
182 
183  // get next free column
184  int firstFree = m_networkEditor->getLayout()->getGrid()->getFirstFreeColumn();
185 
186  // iterate our list.
187  for( ModuleNetworkCoordinates::const_iterator it = m_networkCoords.begin(); it != m_networkCoords.end(); ++it )
188  {
189  // map the ID to a real module
190  WModule::SPtr module = getProject()->mapToModule( ( *it ).first );
191  if( module )
192  {
193  // register in network editor instance as a default position
194  // ensure that the coordinates where relative to the top-left item. Although this is done by the writing code, we should assume someone
195  // has modified the file. Why? One of the primary directives for the project file IO classes is to be fault tolerant.
196  // NOTE: usually bbTL should be 0,0
197  QPoint p = ( *it ).second - bbTL;
198  p.rx() += firstFree;
200  }
201  }
202 
203  for( ModuleNetworkCoordinates::const_iterator it = m_networkFlags.begin(); it != m_networkFlags.end(); ++it )
204  {
205  // map the ID to a real module
206  WModule::SPtr module = getProject()->mapToModule( ( *it ).first );
207  if( module )
208  {
209  // register in network editor instance as a default flag
210  // NOTE: we where lazy and used QPoint for storing both bools
211  QPoint p = ( *it ).second;
212  m_networkEditor->getLayout()->setModuleDefaultFlags( module, static_cast< bool >( p.x() ),
213  static_cast< bool >( p.y() ) );
214  }
215  }
216 
218 }
219 
220 void WQtNetworkEditorProjectFileIO::save( std::ostream& output ) // NOLINT
221 {
222  output << "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
223  "// QtGUI Network Information" << std::endl <<
224  "//////////////////////////////////////////////////////////////////////////////////////////////////////////////////" << std::endl <<
225  std::endl;
226 
227  // write the relative grid positions of each module
229 
230  // IMPORTANT: we store relative coordinates. So we need the bounding rect to get relative coords
231  QPoint bb = grid->getGridBoundingRect().topLeft();
232 
233  // iterate each module:
234  // Grab container and lock
236  // Iterate
237  for( WModuleContainer::ModuleConstIterator iter = container->get().begin(); iter != container->get().end(); ++iter )
238  {
239  // a module has its own project file specific ID:
240  unsigned int id = getProject()->mapFromModule( *iter );
241 
242  // get the graphical item for this module
244 
245  // as grid for position
246  if( grid->isInGrid( item ) )
247  {
248  QPoint p = grid->whereIs( item );
249 
250  // NOTE: we write relative coordinates! So subtract bounding box top-left corner from each coordinate.
251  output << "QT5GUI_NETWORK:" << id << "=" << p.x() - bb.x() << ";" << p.y() - bb.y() << std::endl;
252  output << "QT5GUI_NETWORK_Flags:" << id << "=" << item->wasLayedOut() << ";" << item->wasManuallyPlaced() << std::endl;
253  }
254  // else: not in grid. We do not save info for this module
255  }
256 
257  output << "QT5GUI_NETWORK_Scale:" << m_networkEditor->getView()->transform().m11() << std::endl;
258 }
static WKernel * getRunningKernel()
Returns pointer to the currently running kernel.
Definition: WKernel.cpp:117
std::shared_ptr< WModuleContainer > getRootContainer() const
Returns the root module container.
Definition: WKernel.cpp:127
ModuleContainerType::const_iterator ModuleConstIterator
The const iterator type of the container.
std::shared_ptr< WModule > SPtr
Shared pointer to a WModule.
Definition: WModule.h:106
A base class for all parts of OpenWalnut which can be serialized to a project file.
void setApplyOrder(ApplyOrder order)
Set the order of calls to "done".
WProjectFile * getProject() const
The project using this parser.
std::shared_ptr< WProjectFileIO > SPtr
Abbreviation for a shared pointer.
Class loading project files.
Definition: WProjectFile.h:50
std::shared_ptr< WModule > mapToModule(unsigned int id) const
Map a given project file ID to a module.
unsigned int mapFromModule(std::shared_ptr< WModule > module) const
Map a given module to project file ID.
virtual bool parse(std::string line, unsigned int lineNumber)
This method parses the specified line and interprets it.
ModuleNetworkCoordinates m_networkCoords
The mapping of network coordinates for each module.
WQtNetworkEditorProjectFileIO(WQtNetworkEditor *ne)
Default constructor.
virtual SPtr clone(WProjectFile *project) const
Create a clone of the IO.
ModuleNetworkFlags m_networkFlags
Keep flags.
virtual void save(std::ostream &output)
Saves the state to the specified stream.
virtual void done()
Called whenever the end of the project file has been reached.
WQtNetworkEditor * m_networkEditor
The network editor to use.
Container widget to hold the WQtNetworkScene.
WQtNetworkItem * findItemByModule(std::shared_ptr< WModule > module)
Simple search the WQtNetworkItem that belongs to the WModule.
WQtNetworkEditorView * getView()
Get the view handling the scene.
WQtNetworkSceneLayout * getLayout()
Get the layouter of the scene.
Implement a virtual grid for placing QGraphicsItems.
virtual QPoint whereIs(QGraphicsItem *item)
Find the position of the specified item.
virtual bool isInGrid(QGraphicsItem *item)
Check whether the item is managed in the grid.
virtual QRect getGridBoundingRect() const
Returns the boundaries in grid coordinates.
int getFirstFreeColumn() const
Return the index of the first empty column.
This class represents a WModule as QGraphicsItem and contains a reference to its in- and outports.
bool wasLayedOut() const
Checks whether the item was layed out earlier.
bool wasManuallyPlaced() const
Item was placed by hand.
void setModuleDefaultFlags(WModule::SPtr module, bool layedOut, bool manuallyLayedOut)
Set a default flag combination for the given module.
WQtNetworkItemGrid * getGrid() const
Get the grid used for the layout.
void setModuleDefaultPosition(WModule::SPtr module, QPoint coord)
Set a default position for a given module.
std::shared_ptr< WSharedObjectTicketRead< ModuleContainerType > > ReadTicket
Type for read tickets.
Definition: WSharedObject.h:65
std::string toString(const T &value)
Convert a given value to a string.
Definition: WStringUtils.h:120
WStreamedLogger debug(const std::string &source)
Logging a debug message.
Definition: WLogger.h:331