Code::Blocks  SVN r11506
projectlayoutloader.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  *
5  * $Revision: 10874 $
6  * $Id: projectlayoutloader.cpp 10874 2016-07-16 20:00:28Z jenslody $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/sdk/projectlayoutloader.cpp $
8  */
9 
10 #include "sdk_precomp.h"
11 
12 #ifndef CB_PRECOMP
13  #include <wx/confbase.h>
14  #include <wx/fileconf.h>
15  #include <wx/intl.h>
16  #include "manager.h"
17  #include "configmanager.h"
18  #include "projectmanager.h"
19  #include "logmanager.h"
20  #include "editormanager.h"
21  #include "cbeditor.h"
22  #include "cbproject.h"
23 #endif
24 
25 #include "projectlayoutloader.h"
26 #include "annoyingdialog.h"
27 #include <tinyxml.h>
28 #include "tinywxuni.h"
29 
31  : m_pProject(project),
32  m_TopProjectFile(nullptr)
33 {
34  //ctor
35 }
36 
38 {
39  //dtor
40 }
41 
42 // IMPORTANT! We have to be careful of what to unicode and what not to.
43 // TinyXML must use NON-unicode strings!
44 
45 bool ProjectLayoutLoader::Open(const wxString& filename)
46 {
47  TiXmlDocument doc;
48  if (!TinyXML::LoadDocument(filename, &doc))
49  return false;
50 
53  if (!pMan || !pMsg)
54  return false;
55 
56  TiXmlElement* root;
57  TiXmlElement* elem;
58  wxString fname;
59  ProjectFile* pf;
60 
61  root = doc.FirstChildElement("CodeBlocks_layout_file");
62  if (!root)
63  {
64  // old tag
65  root = doc.FirstChildElement("Code::Blocks_layout_file");
66  if (!root)
67  {
68  pMsg->DebugLog(_T("Not a valid Code::Blocks layout file..."));
69  return false;
70  }
71  }
72 
73  int major = 0;
74  int minor = 0;
75 
76  TiXmlElement* version = root->FirstChildElement("FileVersion");
77  // don't show messages if we 're running a batch build (i.e. no gui)
78  if (!Manager::IsBatchBuild() && version)
79  {
80  version->QueryIntAttribute("major", &major);
81  version->QueryIntAttribute("minor", &minor);
82 
84  {
85  pMsg->DebugLog(F(_T("Project layout file version is > %d.%d. Trying to load..."), PROJECT_LAYOUT_FILE_VERSION_MAJOR, PROJECT_LAYOUT_FILE_VERSION_MINOR));
86  AnnoyingDialog dlg(_("Project layout file format is newer/unknown"),
87  F(_("This project layout file was saved with a newer version of Code::Blocks.\n"
88  "Will try to load, but you might see unexpected results.\n"
89  "In this case close the project, delete %s and reopen the project."),filename.wx_str()),
92  dlg.ShowModal();
93  }
94  else
95  {
96  // use one message for all changes
97  wxString msg;
98  wxString warn_msg;
99 
100  if (major == 0 && minor == 0)
101  {
102  msg << _("0.0 (unversioned) to 1.0:\n");
103  msg << _(" * save editor-pane layout and order.\n");
104  msg << _("\n");
105  }
106 
107  if (!msg.IsEmpty())
108  {
109  msg.Prepend(wxString::Format(_("Project layout file format is older (%d.%d) than the current format (%d.%d).\n"
110  "The file will automatically be upgraded on close.\n"
111  "But please read the following list of changes, as some of them\n"
112  "might not automatically convert existing (old) settings.\n"
113  "If you don't understand what a change means, you probably don't\n"
114  "use that feature so you don't have to worry about it.\n\n"
115  "List of changes:\n"),
116  major,
117  minor,
120  AnnoyingDialog dlg(_("Project layout file format changed"),
121  msg,
124  dlg.ShowModal();
125  }
126 
127  if (!warn_msg.IsEmpty())
128  {
129  warn_msg.Prepend(_("!!! WARNING !!!\n\n"));
130  AnnoyingDialog dlg(_("Project layout file upgrade warning"),
131  warn_msg,
134  dlg.ShowModal();
135  }
136  }
137  }
138 
139  elem = root->FirstChildElement("ActiveTarget");
140  if (elem)
141  {
142  if (elem->Attribute("name"))
143  m_pProject->SetActiveBuildTarget(cbC2U(elem->Attribute("name")));
144  }
145 
146  elem = root->FirstChildElement("File");
147  if (!elem)
148  {
149  //pMsg->DebugLog(_T("No 'File' element in file..."));
150  return false;
151  }
152 
153  while (elem)
154  {
155  //pMsg->DebugLog(elem->Value());
156  fname = cbC2U(elem->Attribute("name"));
157  if (fname.IsEmpty())
158  {
159  //pMsg->DebugLog(_T("'File' node exists, but no filename?!?"));
160  pf = nullptr;
161  }
162  else
163  pf = m_pProject->GetFileByFilename(fname);
164 
165  if (pf)
166  {
167  pf->editorOpen = false;
169  pf->editorSplitActive = 1;
170  pf->editorZoom = 0;
171  pf->editorPos = 0;
172  pf->editorTopLine = 0;
173  pf->editorZoom_2 = 0;
174  pf->editorPos_2 = 0;
175  pf->editorTopLine_2 = 0;
176  int getInt = 0; // used to fetch int values
177 
178  if (elem->QueryIntAttribute("open", &getInt) == TIXML_SUCCESS)
179  pf->editorOpen = getInt != 0;
180  if (elem->QueryIntAttribute("top", &getInt) == TIXML_SUCCESS)
181  {
182  if (getInt)
183  m_TopProjectFile = pf;
184  }
185  if (elem->QueryIntAttribute("tabpos", &getInt) == TIXML_SUCCESS)
186  pf->editorTabPos = getInt;
187  if (elem->QueryIntAttribute("split", &getInt) == TIXML_SUCCESS)
188  pf->editorSplit = getInt;
189  if (elem->QueryIntAttribute("active", &getInt) == TIXML_SUCCESS)
190  pf->editorSplitActive = getInt;
191  if (elem->QueryIntAttribute("splitpos", &getInt) == TIXML_SUCCESS)
192  pf->editorSplitPos = getInt;
193  if (elem->QueryIntAttribute("zoom_1", &getInt) == TIXML_SUCCESS)
194  pf->editorZoom = getInt;
195  if (elem->QueryIntAttribute("zoom_2", &getInt) == TIXML_SUCCESS)
196  pf->editorZoom_2 = getInt;
197 
198  TiXmlElement* cursor = elem->FirstChildElement("Cursor");
199  if (cursor)
200  {
201  cursor = cursor->FirstChildElement();
202  if (cursor)
203  {
204  if (cursor->QueryIntAttribute("position", &getInt) == TIXML_SUCCESS)
205  pf->editorPos = getInt;
206  if (cursor->QueryIntAttribute("topLine", &getInt) == TIXML_SUCCESS)
207  pf->editorTopLine = getInt;
208  if (pf->editorSplit != cbEditor::stNoSplit)
209  {
210  cursor = cursor->NextSiblingElement();
211  if (cursor)
212  {
213  if (cursor->QueryIntAttribute("position", &getInt) == TIXML_SUCCESS)
214  pf->editorPos_2 = getInt;
215  if (cursor->QueryIntAttribute("topLine", &getInt) == TIXML_SUCCESS)
216  pf->editorTopLine_2 = getInt;
217  }
218  }
219  }
220  }
221 
222  TiXmlElement* folding = elem->FirstChildElement("Folding");
223  if (folding)
224  {
225  folding = folding->FirstChildElement();
226  while (folding)
227  {
228  if (folding->QueryIntAttribute("line", &getInt) == TIXML_SUCCESS)
229  pf->editorFoldLinesArray.Add(getInt);
230 
231  folding = folding->NextSiblingElement();
232  }
233  }
234  }
235  elem = elem->NextSiblingElement();
236  }
237 
238  if ( (major >= 1)
239  && (Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/enable_editor_layout"), false)) )
240  {
241  elem = root->FirstChildElement("EditorTabsLayout");
242  if (elem)
243  m_NotebookLayout = cbC2U(elem->Attribute("layout"));
244  }
245 
246  return true;
247 }
248 
249 bool ProjectLayoutLoader::Save(const wxString& filename)
250 {
251  const char* ROOT_TAG = "CodeBlocks_layout_file";
252 
253  TiXmlDocument doc;
254  doc.SetCondenseWhiteSpace(false);
255  doc.InsertEndChild(TiXmlDeclaration("1.0", "UTF-8", "yes"));
256  TiXmlElement* rootnode = static_cast<TiXmlElement*>(doc.InsertEndChild(TiXmlElement(ROOT_TAG)));
257  if (!rootnode)
258  return false;
259 
260  rootnode->InsertEndChild(TiXmlElement("FileVersion"));
261  rootnode->FirstChildElement("FileVersion")->SetAttribute("major", PROJECT_LAYOUT_FILE_VERSION_MAJOR);
262  rootnode->FirstChildElement("FileVersion")->SetAttribute("minor", PROJECT_LAYOUT_FILE_VERSION_MINOR);
263 
264  TiXmlElement* tgtidx = static_cast<TiXmlElement*>(rootnode->InsertEndChild(TiXmlElement("ActiveTarget")));
265  tgtidx->SetAttribute("name", cbU2C(m_pProject->GetActiveBuildTarget()));
266 
267  ProjectFile* active = nullptr;
269  if (ed)
270  active = ed->GetProjectFile();
271 
272  for (FilesList::iterator it = m_pProject->GetFilesList().begin(); it != m_pProject->GetFilesList().end(); ++it)
273  {
274  ProjectFile* f = *it;
275 
276  if (f->editorOpen || f->editorPos || f->editorPos_2 || f->editorTopLine || f->editorTopLine_2 || f->editorTabPos)
277  {
278  TiXmlElement* node = static_cast<TiXmlElement*>(rootnode->InsertEndChild(TiXmlElement("File")));
279  node->SetAttribute("name", cbU2C(f->relativeFilename));
280  node->SetAttribute("open", f->editorOpen);
281  node->SetAttribute("top", (f == active));
282  node->SetAttribute("tabpos", f->editorTabPos);
283  node->SetAttribute("split", f->editorSplit);
284  node->SetAttribute("active", f->editorSplitActive);
285  node->SetAttribute("splitpos", f->editorSplitPos);
286  node->SetAttribute("zoom_1", f->editorZoom);
287  node->SetAttribute("zoom_2", f->editorZoom_2);
288 
289 
290  TiXmlElement* cursor = static_cast<TiXmlElement*>(node->InsertEndChild(TiXmlElement("Cursor")));
291  TiXmlElement* cursor_1 = static_cast<TiXmlElement*>(cursor->InsertEndChild(TiXmlElement("Cursor1")));
292  cursor_1->SetAttribute("position", f->editorPos);
293  cursor_1->SetAttribute("topLine", f->editorTopLine);
294 
296  {
297  TiXmlElement* cursor_2 = static_cast<TiXmlElement*>(cursor->InsertEndChild(TiXmlElement("Cursor2")));
298  cursor_2->SetAttribute("position", f->editorPos_2);
299  cursor_2->SetAttribute("topLine", f->editorTopLine_2);
300  }
301 
302  if (f->editorFoldLinesArray.GetCount() > 0)
303  {
304  TiXmlElement* folding = static_cast<TiXmlElement*>(node->InsertEndChild(TiXmlElement("Folding")));
305  for (unsigned int i = 0; i < f->editorFoldLinesArray.GetCount(); i++)
306  {
307  TiXmlElement* line = static_cast<TiXmlElement*>(folding->InsertEndChild(TiXmlElement("Collapse")));
308  line->SetAttribute("line", f->editorFoldLinesArray[i]);
309  }
310  }
311  }
312  }
313  const wxArrayString& en = m_pProject->ExpandedNodes();
314  for (unsigned int i = 0; i < en.GetCount(); ++i)
315  {
316  if (!en[i].IsEmpty())
317  {
318  TiXmlElement* node = static_cast<TiXmlElement*>(rootnode->InsertEndChild(TiXmlElement("Expand")));
319  node->SetAttribute("folder", cbU2C(en[i]));
320  }
321  }
322 
323  if (Manager::Get()->GetConfigManager(_T("app"))->ReadBool(_T("/environment/enable_editor_layout"), false))
324  {
325  TiXmlElement *el =
326  static_cast<TiXmlElement*>(
327  rootnode->InsertEndChild( TiXmlElement("EditorTabsLayout") ) );
328  el->SetAttribute("layout", cbU2C( Manager::Get()->GetEditorManager()->GetNotebook()->SavePerspective(m_pProject->GetTitle()) ));
329  }
330  // else ?!
331 
332  return cbSaveTinyXMLDocument(&doc, filename);
333 }
ProjectFile * GetFileByFilename(const wxString &filename, bool isRelative=true, bool isUnixFilename=false)
Access a file of the project.
Definition: cbproject.cpp:1049
wxString F(const wxChar *msg,...)
sprintf-like function
Definition: logmanager.h:20
int editorTabPos
The position of the editor-tab for this file.
Definition: projectfile.h:178
#define PROJECT_LAYOUT_FILE_VERSION_MAJOR
wxString relativeFilename
The relative (to the project) filename of this file.
Definition: projectfile.h:131
const int version
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
virtual FilesList & GetFilesList()
Provides an easy way to iterate all the files belonging in this target.
Definition: cbproject.h:685
int editorSplitActive
Last active splitview (1 or 2).
Definition: projectfile.h:154
int editorPos_2
The last known caret position in an editor for this file (right/bottom control if split)...
Definition: projectfile.h:169
bool Open(const wxString &filename)
#define PROJECT_LAYOUT_FILE_VERSION_MINOR
#define _T(string)
bool LoadDocument(const wxString &filename, TiXmlDocument *doc)
Definition: tinywxuni.cpp:13
int editorZoom
The zoom-factor of the editor for this file (left/top control if split).
Definition: projectfile.h:166
Represents a file in a Code::Blocks project.
Definition: projectfile.h:39
int editorPos
The last known caret position in an editor for this file (left/top control if split).
Definition: projectfile.h:160
ProjectFile * m_TopProjectFile
EditorManager * GetEditorManager() const
Definition: manager.cpp:434
DLLIMPORT const wxWX2MBbuf cbU2C(const wxString &str)
Return multibyte (C string) representation of the string.
Definition: globals.cpp:743
int editorSplitPos
Last splitter position.
Definition: projectfile.h:157
ProjectManager * GetProjectManager() const
Functions returning pointers to the respective sub-manager instances.
Definition: manager.cpp:429
int editorTopLine
The last known caret line in an editor for this file (left/top control if split). ...
Definition: projectfile.h:163
Represents a Code::Blocks project.
Definition: cbproject.h:96
const wxString & GetActiveBuildTarget() const
Definition: cbproject.cpp:1373
const wxArrayString & ExpandedNodes()
Convenience function for remembering the project&#39;s tree state when refreshing it. ...
Definition: cbproject.h:445
null_pointer_t nullptr
Definition: nullptr.cpp:16
DLLIMPORT wxString cbC2U(const char *str)
Return str as a proper unicode-compatible string.
Definition: globals.cpp:733
virtual const wxString & GetTitle() const
Read the target&#39;s title.
int editorSplit
Split type of the editor as int.
Definition: projectfile.h:151
cbEditor * GetBuiltinActiveEditor()
Definition: editormanager.h:95
static bool IsBatchBuild()
Definition: manager.h:66
LogManager * GetLogManager() const
Definition: manager.cpp:439
const wxStringCharType * wx_str() const
int editorTopLine_2
The last known caret line in an editor for this file(right/bottom control if split).
Definition: projectfile.h:172
ProjectLayoutLoader(cbProject *project)
bool editorOpen
If true, the file is open inside an editor.
Definition: projectfile.h:148
const wxString & _(const wxString &string)
wxArtID wxART_WARNING
A file editor.
Definition: cbeditor.h:43
bool IsEmpty() const
The entry point singleton for working with projects.
void DebugLog(const wxString &msg, Logger::level lv=Logger::info)
Definition: logmanager.h:146
int ShowModal() override
wxString & Prepend(const wxString &str)
int editorZoom_2
The zoom-factor of the editor for this file(right/bottom control if split).
Definition: projectfile.h:175
size_t GetCount() const
ProjectFile * GetProjectFile() const
Read the ProjectFile pointer associated with this editor.
Definition: cbeditor.h:123
wxArrayInt editorFoldLinesArray
Fold lines.
Definition: projectfile.h:181
DLLIMPORT bool cbSaveTinyXMLDocument(TiXmlDocument *doc, const wxString &filename)
Saves a TinyXML document correctly, even if the path contains unicode characters. ...
Definition: globals.cpp:727
wxArtID wxART_INFORMATION
static wxString Format(const wxString &format,...)
bool Save(const wxString &filename)
Dialog that contains a "Don&#39;t annoy me" checkbox.
bool SetActiveBuildTarget(const wxString &name)
Set the active build target.
Definition: cbproject.cpp:1355