NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
packagedialog.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2019 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19#include "packagedialog.hpp"
20#include "../compositions/grouppanel.hpp"
21#include "../globals.hpp"
22#include "../../kernel/core/ui/language.hpp"
23#include "../../kernel/core/ui/winlayout.hpp"
24#include "../../kernel/core/utils/tools.hpp"
25#include "../../kernel/core/utils/tinyxml2.h"
26#include "../../kernel/core/procedure/dependency.hpp"
27#include "../../kernel/core/procedure/includer.hpp"
28#include "../../kernel/core/io/styledtextfile.hpp"
29#include "../../common/vcsmanager.hpp"
30#include "../../common/filerevisions.hpp"
31#include "../../common/datastructures.h"
32
33#include <set>
34#include <memory>
35
36#define INCLUDEDOCS "_doctemplate"
37#define DOCFILE "_docfile"
38
39extern Language _guilang;
40
41
42BEGIN_EVENT_TABLE(PackageDialog, wxDialog)
50 EVT_PG_CHANGED(-1, PackageDialog::OnPropGridChange)
51 EVT_CLOSE(PackageDialog::OnClose)
53
54
55
63PackageDialog::PackageDialog(wxWindow* parent, NumeReTerminal* terminal, IconManager* icons) : wxDialog(parent, wxID_ANY, _guilang.get("GUI_PKGDLG_HEAD") + " [New Project]", wxDefaultPosition, wxSize(600*g_pixelScale, 800*g_pixelScale), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
64{
65 m_packageProperties = nullptr;
66 m_fileList = nullptr;
67 m_terminal = terminal;
68 m_icons = icons;
69 m_isAutoIncrement = false;
70
71 wxBoxSizer* vsizer = new wxBoxSizer(wxVERTICAL);
72
73 // Create new grouped panel for this dialog
74 GroupPanel* panel = new GroupPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxBORDER_STATIC);
75
76 // Create the properties group
77 wxStaticBoxSizer* group = panel->createGroup(_guilang.get("GUI_PKGDLG_PROPERTIES"));
78
79 // Create a property grid containing the package
80 // properties
81 m_packageProperties = new wxPropertyGrid(group->GetStaticBox(), wxID_ANY, wxDefaultPosition, wxSize(-1, 260*g_pixelScale), wxPG_THEME_BORDER | wxPG_TOOLTIPS | wxPG_SPLITTER_AUTO_CENTER);
82 m_packageProperties->Append(new wxPropertyCategory(_guilang.get("GUI_PKGDLG_GENERAL_CATEGORY")));
83 m_packageProperties->Append(new wxStringProperty(_guilang.get("GUI_PKGDLG_PACKAGENAME"), "-name"));
84 m_packageProperties->Append(new wxStringProperty(_guilang.get("GUI_PKGDLG_AUTHOR"), "-author"));
85 m_packageProperties->Append(new wxStringProperty(_guilang.get("GUI_PKGDLG_VERSION"), "-version", "<AUTO>"));
86
87 wxArrayString flags;
88 flags.Add("ENABLE_DEFAULTS");
89 flags.Add("ENABLE_FULL_LOGGING");
90 flags.Add("DISABLE_SCREEN_OUTPUT");
91 m_packageProperties->Append(new wxEnumProperty(_guilang.get("GUI_PKGDLG_FLAGS"), "-flags", flags));
92
93 wxArrayString type;
94 type.Add("TYPE_PACKAGE");
95 type.Add("TYPE_PLUGIN");
96 type.Add("TYPE_PLUGIN_WITH_RETURN_VALUE");
97 type.Add("TYPE_GUI_PLUGIN");
98 m_packageProperties->Append(new wxEnumProperty(_guilang.get("GUI_PKGDLG_TYPE"), "-type", type));
99
100 // Add a license field
101 wxArrayString license;
102 license.Add("Apache-2.0");
103 license.Add("BSD-2-Clause");
104 license.Add("BSD-3-Clause");
105 license.Add("CC-BY-4.0");
106 license.Add("CC-BY-ND-4.0");
107 license.Add("CC-BY-SA-4.0");
108 license.Add("CC-BY-SA-ND-4.0");
109 license.Add("EPL-2.0");
110 license.Add("GPL-2.0-only");
111 license.Add("GPL-2.0-or-later");
112 license.Add("GPL-3.0-only");
113 license.Add("GPL-3.0-or-later");
114 license.Add("LGPL-2.0-only");
115 license.Add("LGPL-2.0-or-later");
116 license.Add("LGPL-3.0-only");
117 license.Add("LGPL-3.0-or-later");
118 license.Add("MIT");
119 license.Add("MPL-2.0");
120 m_packageProperties->Append(new wxEditEnumProperty(_guilang.get("GUI_PKGDLG_LICENSE"), "-license", license, wxArrayInt(), license[0]));
121 m_packageProperties->Append(new wxLongStringProperty(_guilang.get("GUI_PKGDLG_PLUGINDESC"), "-desc"));
122 m_packageProperties->Append(new wxLongStringProperty(_guilang.get("GUI_PKGDLG_KEYWORDS"), "-keywords"));
123 m_packageProperties->Append(new wxLongStringProperty(_guilang.get("GUI_PKGDLG_CHANGESLOG"), "-changelog"));
124 m_packageProperties->Append(new wxStringProperty(_guilang.get("GUI_PKGDLG_DEPENDENCIES"), "-requirepackages"));
125
126 // Add a validator to the package command to enssure that the user
127 // only uses alphanumeric characters as command string
128 wxPGProperty* pluginsCategory = m_packageProperties->Append(new wxPropertyCategory(_guilang.get("GUI_PKGDLG_PLUGIN_CATEGORY")));
129 m_packageProperties->Append(new wxStringProperty(_guilang.get("GUI_PKGDLG_PLUGINCOMMAND"), "-plugincommand"));
130 m_packageProperties->SetPropertyValidator("-plugincommand", wxTextValidator(wxFILTER_ALPHANUMERIC));
131 m_packageProperties->Append(new wxStringProperty(_guilang.get("GUI_PKGDLG_PLUGINMENUENTRY"), "-pluginmenuentry"));
132 m_packageProperties->SetPropertyValidator("-pluginmenuentry", wxTextValidator(wxFILTER_ASCII));
133
134 m_packageProperties->Append(new wxStringProperty(_guilang.get("GUI_PKGDLG_PLUGINMAIN"), "-pluginmain"));
135
136 wxPGProperty* docsCategory = m_packageProperties->Append(new wxPropertyCategory(_guilang.get("GUI_PKGDLG_DOCS_CATEGORY")));
137 m_packageProperties->Append(new wxBoolProperty(_guilang.get("GUI_PKGDLG_INCLUDEDOCUMENTATION"), INCLUDEDOCS));
138 wxFileProperty* docfile = new wxFileProperty(_guilang.get("GUI_PKGDLG_DOCUMENTATION"), DOCFILE);
139 docfile->SetAttribute(wxPG_FILE_DIALOG_STYLE, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
140 docfile->SetAttribute(wxPG_FILE_WILDCARD, "Doc files (*.xml,*.nhlp)|*.xml;*.nhlp|Text files (*.txt)|*.txt|All files (*.*)|*.*");
141 docfile->SetAttribute(wxPG_FILE_DIALOG_TITLE, _guilang.get("GUI_DLG_OPEN"));
142 m_packageProperties->Append(docfile);
143
144 // Apply some general settings to the whole property grid
145 m_packageProperties->SetPropertyAttributeAll(wxPG_BOOL_USE_CHECKBOX, true);
146 m_packageProperties->SetValidationFailureBehavior(wxPG_VFB_MARK_CELL | wxPG_VFB_STAY_IN_PROPERTY);
147
148 // Fold the non-general categories
149 m_packageProperties->Collapse(wxPGPropArg(pluginsCategory));
150 m_packageProperties->Collapse(wxPGPropArg(docsCategory));
151
152 group->Add(m_packageProperties, 1, wxEXPAND | wxALL, 5);
153
154 // Create the files group
155 group = panel->createGroup(_guilang.get("GUI_PKGDLG_FILES"));
156
157 // Add a special horizontal sizer for the buttons
158 wxBoxSizer* buttonSizer = panel->createGroup(wxHORIZONTAL, group);
159
160 // Create the add, remove and autodetect buttons
161 panel->CreateButton(group->GetStaticBox(), buttonSizer, _guilang.get("GUI_PKGDLG_ADDFILES"), ID_PKGDLG_ADD);
162 panel->CreateButton(group->GetStaticBox(), buttonSizer, _guilang.get("GUI_PKGDLG_REMOVEFILES"), ID_PKGDLG_REMOVE);
163 panel->CreateButton(group->GetStaticBox(), buttonSizer, _guilang.get("GUI_PKGDLG_AUTODETECTFILES"), ID_PKGDLG_AUTODETECT);
164
165 // Create a list view for the files and add the image list
166 // to display the file icons
167 m_fileList = panel->CreateListView(group->GetStaticBox(), group, wxLC_LIST | wxLC_ALIGN_LEFT, wxSize(-1, 330*g_pixelScale));
168 m_fileList->SetImageList(icons->GetImageList(), wxIMAGE_LIST_SMALL);
169
170 // Create a special horizontal sizer for the project buttons
171 wxBoxSizer* projectButtonSizer = panel->createGroup(wxHORIZONTAL);
172
173 // Create the project buttons
174 panel->CreateButton(panel, projectButtonSizer, _guilang.get("GUI_PKGDLG_SAVE_PROJECT"), ID_PKGDLG_SAVEPROJECT);
175 panel->CreateButton(panel, projectButtonSizer, _guilang.get("GUI_PKGDLG_LOAD_PROJECT"), ID_PKGDLG_LOADPROJECT);
176 panel->CreateButton(panel, projectButtonSizer, _guilang.get("GUI_PKGDLG_CREATE_PACKAGE"), ID_PKGDLG_CREATEPACKAGE);
177 panel->CreateButton(panel, projectButtonSizer, _guilang.get("GUI_BUTTON_CANCEL"), ID_PKGDLG_ABORT);
178
179 // Activate scroll bars
180 panel->SetScrollbars(0, 20, 0, 200);
181
182 // Add the panel to the vertical sizer of the dialog
183 vsizer->Add(panel, 1, wxEXPAND, 0);
184
185 SetSizer(vsizer);
186}
187
188
197void PackageDialog::OnAutoDetect(wxCommandEvent& event)
198{
199 try
200 {
202 }
203 catch (...)
204 {
205 EndModal(wxID_CANCEL);
206 throw;
207 }
208}
209
210
219void PackageDialog::OnAddItems(wxCommandEvent& event)
220{
221 // Create a file dialog focused on procedure files. The user may
222 // select multiple files
223 wxFileDialog dlg(this, _guilang.get("GUI_PKGDLG_SELECT_FILES"), m_terminal->getPathSettings()[PROCPATH], wxEmptyString,
224 _guilang.get("GUI_FILTER_INSTALLABLES") + " (*.nprc, *.nlyt)|*.nprc;*.nlyt|"
225 + _guilang.get("COMMON_FILETYPE_NPRC") + " (*.nprc)|*.nprc|"
226 + _guilang.get("COMMON_FILETYPE_NLYT") + " (*.nlyt)|*.nlyt|"
227 + _guilang.get("COMMON_FILETYPE_NSCR") + " (*.nscr)|*.nscr",
228 wxFD_MULTIPLE);
229
230 if (dlg.ShowModal() == wxID_OK)
231 {
232 wxArrayString files;
233 dlg.GetPaths(files);
234
235 // Insert the selected items, if they're not already part
236 // of the files set
237 for (size_t i = 0; i < files.size(); i++)
238 {
239 if (m_fileList->FindItem(-1, replacePathSeparator(files[i].ToStdString()), false) == -1)
240 {
241 wxString sExt = files[i].substr(files[i].rfind('.'));
242 m_fileList->InsertItem(m_fileList->GetItemCount(), replacePathSeparator(files[i].ToStdString()), m_icons->GetIconIndex(sExt));
243 }
244 }
245
246 markUnsaved();
247 }
248}
249
250
259void PackageDialog::OnRemoveItems(wxCommandEvent& event)
260{
261 long selected = m_fileList->GetFirstSelected();
262
263 // Remove all selected items
264 while (m_fileList->GetItemCount() && m_fileList->GetSelectedItemCount() && selected != -1)
265 {
266 m_fileList->DeleteItem(selected);
267 selected = m_fileList->GetFirstSelected();
268 }
269
270 markUnsaved();
271}
272
273
282void PackageDialog::OnLoadProjectFile(wxCommandEvent& event)
283{
284 if (!isSaved())
285 {
286 int res = wxMessageBox(_guilang.get("GUI_UNSAVEDFILE_CLOSE"), _guilang.get("GUI_SAVE_QUESTION"), wxYES_NO);
287
288 if (res == wxYES)
289 {
290 wxFileDialog dialog(this, _guilang.get("GUI_DLG_SAVE"), m_terminal->getPathSettings()[SCRIPTPATH] + "/packages", getPackageIdentifier() + ".npkp", _guilang.get("GUI_FILTER_NPKP") + " (*.npkp)|*.npkp", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
291
292 if (dialog.ShowModal() == wxID_OK)
293 saveProjectFile(dialog.GetPath());
294 }
295 }
296
297 wxFileDialog dialog(this, _guilang.get("GUI_DLG_OPEN"), m_terminal->getPathSettings()[SCRIPTPATH] + "/packages", wxEmptyString, _guilang.get("GUI_FILTER_NPKP") + " (*.npkp)|*.npkp", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
298
299 if (dialog.ShowModal() == wxID_OK)
300 loadProjectFile(dialog.GetPath());
301}
302
303
312void PackageDialog::OnSaveProjectFile(wxCommandEvent& event)
313{
314 wxFileDialog dialog(this, _guilang.get("GUI_DLG_SAVE"), m_terminal->getPathSettings()[SCRIPTPATH] + "/packages", getPackageIdentifier() + ".npkp", _guilang.get("GUI_FILTER_NPKP") + " (*.npkp)|*.npkp", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
315
316 if (dialog.ShowModal() == wxID_OK)
317 saveProjectFile(dialog.GetPath());
318}
319
320
330void PackageDialog::OnCreatePackage(wxCommandEvent& event)
331{
332 SaveOnClose();
333 EndModal(wxID_OK);
334}
335
336
345void PackageDialog::OnAbort(wxCommandEvent& event)
346{
347 SaveOnClose();
348 EndModal(wxID_CANCEL);
349}
350
351
360void PackageDialog::OnPropGridChange(wxPropertyGridEvent& event)
361{
362 if (isSaved())
363 SetTitle(GetTitle().insert(GetTitle().find("[")+1, "*"));
364
365 event.GetProperty()->SetTextColour(*wxRED);
366}
367
368
377void PackageDialog::OnClose(wxCloseEvent& event)
378{
379 SaveOnClose();
380 EndModal(wxCANCEL);
381}
382
383
393{
394 if (!isSaved())
395 {
396 int res = wxMessageBox(_guilang.get("GUI_UNSAVEDFILE_CLOSE"), _guilang.get("GUI_SAVE_QUESTION"), wxYES_NO);
397
398 if (res == wxYES)
399 {
400 wxFileDialog dialog(this, _guilang.get("GUI_DLG_SAVE"), m_terminal->getPathSettings()[SCRIPTPATH] + "/packages", getPackageIdentifier() + ".npkp", _guilang.get("GUI_FILTER_NPKP") + " (*.npkp)|*.npkp", wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
401
402 if (dialog.ShowModal() == wxID_OK)
403 saveProjectFile(dialog.GetPath());
404 }
405 }
406}
407
408
418static void resolveIncludes(std::set<std::string>& fileSet)
419{
420 std::vector<std::string> vIncludes;
421
422 for (auto iter = fileSet.begin(); iter != fileSet.end(); ++iter)
423 {
424 StyledTextFile depFile(*iter);
425 std::string sSearchPath = depFile.getFileName();
426 sSearchPath.erase(sSearchPath.find_last_of("/\\"));
427
428 for (int i = 0; i < depFile.getLinesCount(); i++)
429 {
431 {
432 Includer incl(depFile.getStrippedLine(i), sSearchPath);
433 vIncludes.push_back(incl.getIncludedFileName());
434 }
435 }
436 }
437
438 for (const auto& incl : vIncludes)
439 fileSet.insert(incl);
440}
441
442
453void PackageDialog::autoDetect(const wxArrayString& mainfiles)
454{
455 // Create a set (forces unique names)
456 std::set<std::string> fileSet;
457
458 // Call followBranch() for every file name in the array
459 // of strings (except of layout files)
460 for (size_t i = 0; i < mainfiles.size(); i++)
461 {
462 if (mainfiles[i].substr(0, 4) == "(!) ")
463 continue;
464
465 if (mainfiles[i].rfind(".nlyt") == std::string::npos)
466 followBranch(replacePathSeparator(mainfiles[i].ToStdString()), fileSet);
467 else
468 findLayoutDependencies(replacePathSeparator(mainfiles[i].ToStdString()), fileSet);
469 }
470
471 resolveIncludes(fileSet);
472
473 // Insert only unique file names into the list view
474 for (auto iter = fileSet.begin(); iter != fileSet.end(); ++iter)
475 {
476 if (m_fileList->FindItem(-1, *iter, false) == -1)
477 {
478 std::string sExt = (*iter).substr((*iter).rfind('.'));
479 m_fileList->InsertItem(m_fileList->GetItemCount(), *iter, m_icons->GetIconIndex(sExt));
480 }
481 }
482
483 markUnsaved();
484}
485
486
497void PackageDialog::followBranch(const std::string& sFile, std::set<std::string>& fileSet)
498{
499 // Add the current file to the set
500 fileSet.insert(sFile);
501
502 // Get a reference to the procedure library
503 // and calculate the dependencies of the current file
506
507 // If the returned dependencies are not already part of
508 // the set, call this function recursively using the dependencies,
509 // which are not part of the set yet
510 for (auto iter = dep->getDependencyMap().begin(); iter != dep->getDependencyMap().end(); ++iter)
511 {
512 for (auto listiter = iter->second.begin(); listiter != iter->second.end(); ++listiter)
513 {
514 if (fileSet.find(listiter->getFileName()) == fileSet.end())
515 followBranch(listiter->getFileName(), fileSet);
516 }
517 }
518}
519
520
531void PackageDialog::findLayoutDependencies(const std::string& sFile, std::set<std::string>& fileSet)
532{
533 // Get a list of all event procedures
534 std::vector<std::string> vProcs = getEventProcedures(sFile);
535
536 // Get the tree for every not already examined
537 // procedure
538 for (size_t i = 0; i < vProcs.size(); i++)
539 {
540 if (fileSet.find(vProcs[i]) == fileSet.end())
541 followBranch(vProcs[i], fileSet);
542 }
543}
544
545
554void PackageDialog::loadProjectFile(const wxString& filename)
555{
556 tinyxml2::XMLDocument project;
557 project.LoadFile(filename.c_str());
558 tinyxml2::XMLElement* root = project.FirstChildElement("project");
559 bool allFilesFound = true;
560
561 // Ensure that the file is readable and that the version
562 // is known
563 if (!root || !root->Attribute("version.npkp", "1"))
564 return;
565
566 tinyxml2::XMLElement* info = root->FirstChildElement("info");
567 tinyxml2::XMLElement* files = root->FirstChildElement("files");
568
569 if (!info || !files)
570 return;
571
572 m_isAutoIncrement = false;
573
574 // Get an iterator for the properties grid and iterate
575 // through it
576 for (auto iter = m_packageProperties->GetIterator(); !iter.AtEnd(); iter++)
577 {
578 wxPGProperty* prop = *iter;
579 prop->SetTextColour(*wxBLACK);
580 tinyxml2::XMLElement* infoitem = info->FirstChildElement(prop->GetName().substr(1).c_str());
581
582 if (!infoitem || !infoitem->GetText())
583 continue;
584
585 if (prop->GetName() == "-version")
586 {
587 if (infoitem->BoolAttribute("autoincrement"))
588 {
589 prop->SetValueFromString(incrementVersion(infoitem->GetText()));
590 prop->SetTextColour(*wxRED);
591 m_isAutoIncrement = true;
592 continue;
593 }
594 }
595 else if (prop->GetName() == DOCFILE && !fileExists(infoitem->GetText()))
596 {
597 allFilesFound = false;
598 continue;
599 }
600
601 prop->SetValueFromString(infoitem->GetText());
602 }
603
604 m_fileList->DeleteAllItems();
605
607
608 // Load all files to the table
609 while (file)
610 {
611 if (!fileExists(file->GetText()))
612 {
613 allFilesFound = false;
614
615 m_fileList->InsertItem(m_fileList->GetItemCount(), "(!) " + std::string(file->GetText()), m_icons->GetIconIndex(""));
616 }
617 else
618 {
619 std::string sExt = file->GetText();
620 sExt = sExt.substr(sExt.rfind('.'));
621
622 m_fileList->InsertItem(m_fileList->GetItemCount(), file->GetText(), m_icons->GetIconIndex(sExt));
623 }
624
625
626 file = file->NextSiblingElement();
627 }
628
629 // Update the window title to reflect the loaded project
630 wxFileName fname(filename);
631 SetTitle(_guilang.get("GUI_PKGDLG_HEAD") + " [" + fname.GetFullName() + "]");
632
634 markUnsaved();
635
636 if (!allFilesFound)
637 wxMessageBox(_guilang.get("GUI_PKGDLG_NOTALLFILESFOUND"), _guilang.get("GUI_PKGDLG_NOTALLFILESFOUND_HEAD"), wxOK, this);
638}
639
640
649void PackageDialog::saveProjectFile(const wxString& filename)
650{
651 VersionControlSystemManager manager(static_cast<NumeReWindow*>(GetParent()));
652 std::unique_ptr<FileRevisions> revisions(manager.getRevisions(filename));
653
654 // Ensure that the revisions are complete
655 if (revisions.get())
656 {
657 if (!revisions->getRevisionCount() && wxFileExists(filename))
658 {
659 wxFile tempfile(filename);
660 wxString contents;
661 tempfile.ReadAll(&contents);
662 revisions->addRevision(contents);
663 }
664 }
665
666 tinyxml2::XMLDocument project;
667 tinyxml2::XMLElement* root = project.NewElement("project");
668 tinyxml2::XMLElement* info = project.NewElement("info");
669 tinyxml2::XMLElement* files = project.NewElement("files");
670
671 root->SetAttribute("version.npkp", "1");
672 root->SetAttribute("version.numere", sVersion.c_str());
673
674 project.InsertFirstChild(root);
675 root->InsertFirstChild(info);
676 root->InsertEndChild(files);
677
678 // Get an iterator for the properties grid and iterate
679 // through it
680 for (auto iter = m_packageProperties->GetIterator(); !iter.AtEnd(); iter++)
681 {
682 wxPGProperty* prop = *iter;
683 prop->SetTextColour(*wxBLACK);
684 tinyxml2::XMLElement* infoitem = project.NewElement(prop->GetName().substr(1).c_str());
685
686 if (prop->GetName() == "-version" && (prop->GetValueAsString() == "<AUTO>" || m_isAutoIncrement))
687 {
688 if (prop->GetValueAsString() == "<AUTO>")
689 infoitem->SetText("0.0.1");
690 else
691 infoitem->SetText(prop->GetValueAsString().ToStdString().c_str());
692
693 infoitem->SetAttribute("autoincrement", true);
694 }
695 else
696 infoitem->SetText(prop->GetValueAsString().ToStdString().c_str());
697
698 info->InsertEndChild(infoitem);
699 }
700
701 files->SetAttribute("count", m_fileList->GetItemCount());
702
703 // Write all files to the project file
704 for (int i = 0; i < m_fileList->GetItemCount(); i++)
705 {
706 tinyxml2::XMLElement* file = project.NewElement("file");
707 std::string sFile = m_fileList->GetItemText(i).ToStdString();
708
709 if (sFile.substr(0, 4) == "(!) ")
710 sFile.erase(0, 4);
711
712 file->SetText(sFile.c_str());
713 files->InsertEndChild(file);
714 }
715
716 project.SaveFile(filename.c_str());
717
718 // Read the written XML file and store it in
719 // the list of revisions
720 if (revisions.get())
721 {
722 if (wxFileExists(filename))
723 {
724 wxFile tempfile(filename);
725 wxString contents;
726 tempfile.ReadAll(&contents);
727 revisions->addRevision(contents);
728 }
729 }
730
731 wxFileName fname(filename);
732
733 // Update the window title to reflect the loaded project
734 SetTitle(_guilang.get("GUI_PKGDLG_HEAD") + " [" + fname.GetFullName() + "]");
735}
736
737
745{
746 if (isSaved())
747 SetTitle(GetTitle().insert(GetTitle().find("[")+1, "*"));
748}
749
750
759{
760 return GetTitle().find("[*") == std::string::npos;
761}
762
763
774void PackageDialog::setMainFile(const wxString& mainfile)
775{
776 if (mainfile.rfind(".nlyt") == std::string::npos)
777 m_fileList->InsertItem(m_fileList->GetItemCount(), replacePathSeparator(mainfile.ToStdString()), m_icons->GetIconIndex(".nprc"));
778 else
779 m_fileList->InsertItem(m_fileList->GetItemCount(), replacePathSeparator(mainfile.ToStdString()), m_icons->GetIconIndex(".nlyt"));
780
781 markUnsaved();
782}
783
784
795{
796 wxArrayString stringArray;
797
798 for (int i = 0; i < m_fileList->GetItemCount(); i++)
799 {
800 stringArray.Add(m_fileList->GetItemText(i));
801 }
802
803 return stringArray;
804}
805
806
816{
817 wxString installInfo = "\t<info>\r\n";
818
819 // Has the user selected a plugin type as package type?
820 bool isplugin = isPlugin();
821
822 // Get an iterator for the properties grid and iterate
823 // through it
824 for (auto iter = m_packageProperties->GetIterator(); !iter.AtEnd(); iter++)
825 {
826 wxPGProperty* prop = *iter;
827
828 // "-type" and "-flag" don't need quoation marks
829 if (prop->GetName() == "-type" || prop->GetName() == "-flags")
830 {
831 installInfo += "\t\t" + prop->GetName() + "=" + prop->GetValueAsString() + "\r\n";
832 continue;
833 }
834 else if ((prop->GetName().substr(0, 7) == "-plugin" && (!isplugin || !prop->GetValueAsString().length())) || prop->GetName()[0] != '-')
835 continue;
836 else if (prop->GetName() == "-name")
837 {
838 installInfo += "\t\t-name=\"" + getPackageName() + "\"\r\n";
839 continue;
840 }
841 else if (prop->GetName() == "-version" && prop->GetValueAsString() == "<AUTO>")
842 {
843 installInfo += "\t\t-version=\"0.0.1\"\r\n";
844 continue;
845 }
846 else if (prop->GetName() == "-requirepackages" && !prop->GetValueAsString().length())
847 continue;
848
849 // Add the current property to the set
850 wxString value = prop->GetValueAsString();
851 value.Replace("\"", "\\\"");
852 installInfo += "\t\t" + prop->GetName() + "=\"" + value + "\"\r\n";
853 }
854
855 // Add the require version property to the current install
856 // information
857 installInfo += "\t\t-requireversion=\"" + sVersion.substr(0, sVersion.find(' ')) + "\"\r\n";
858 installInfo += "\t<endinfo>\r\n";
859
860 return installInfo;
861}
862
863
872{
873 wxString name = m_packageProperties->GetPropertyByName("-name")->GetValueAsString();
874
875 // Fallback name, if nothing set
876 if (!name.length())
877 return "newpackage";
878
879 return name;
880}
881
882
893{
894 // Get the name and transform it to lower case letters
895 std::string identifier = getPackageName().ToStdString();
896 identifier = toLowerCase(identifier);
897
898 // Replace every non-alphanumeric character with an underscore
899 for (size_t i = 0; i < identifier.length(); i++)
900 {
901 if (!isalnum(identifier[i]) && identifier[i] != '_')
902 identifier[i] = '_';
903 }
904
905 if (isPlugin())
906 return "plgn_" + identifier;
907
908 return "pkg_" + identifier;
909}
910
911
920{
921 if (m_packageProperties->GetPropertyByName("-version")->GetValueAsString() == "<AUTO>")
922 return "0.0.1";
923
924 return m_packageProperties->GetPropertyByName("-version")->GetValueAsString();
925}
926
935{
936 return m_packageProperties->GetPropertyByName(DOCFILE)->GetValueAsString();
937}
938
939
948{
949 return m_packageProperties->GetPropertyByName(INCLUDEDOCS)->GetValue().GetBool();
950}
951
952
962{
963 return m_packageProperties->GetPropertyByName("-type")->GetValueAsString().find("PLUGIN") != std::string::npos;
964}
965
966
967
968
const std::string sVersion
std::string toLowerCase(const std::string &)
Converts uppercase to lowercase letters.
double g_pixelScale
This class handles the dependencies of the current procedure file (passed as pointer to a ProcedureEl...
Definition: dependency.hpp:81
std::map< std::string, DependencyList > & getDependencyMap()
Definition: dependency.hpp:98
This class simplifies the creation of simple windows and creates a common layout among all windows.
Definition: grouppanel.hpp:188
wxListView * CreateListView(wxWindow *parent, wxSizer *sizer, int nStyle=wxLC_REPORT, wxSize size=wxDefaultSize, int id=wxID_ANY)
This member function creates the layout for a listview control.
Definition: grouppanel.cpp:376
wxStaticBoxSizer * createGroup(const wxString &sGroupName, int orient=wxVERTICAL, wxWindow *parent=nullptr, wxSizer *sizer=nullptr, int expand=0)
Member function to create a group (a static box with a label) in the panel.
Definition: grouppanel.cpp:161
wxButton * CreateButton(wxWindow *parent, wxSizer *sizer, const wxString &description, int id=wxID_ANY, int alignment=wxALIGN_CENTER_VERTICAL)
This member function creates the layout for a button.
Definition: grouppanel.cpp:447
int GetIconIndex(wxString iconInfo)
This class represents a file, which can be included into other files using the @ syntax.
Definition: includer.hpp:32
std::string getIncludedFileName() const
Returns the embedded file name.
Definition: includer.cpp:300
static bool is_including_syntax(const std::string &sLine)
Static member function which determines, whether the passed line is actually a including syntax.
Definition: includer.cpp:318
This class handles the internal language system and returns the language strings of the selected lang...
Definition: language.hpp:38
std::string get(const std::string &sMessage, const std::vector< std::string > &vTokens) const
This member function returns the language string for the passed language identifier and replaces all ...
Definition: language.cpp:292
ProcedureLibrary & getProcedureLibrary()
Definition: kernel.hpp:321
The terminal class for the GUI. It's a specialisation of the GenericTerminal.
Definition: terminal.hpp:46
NumeReKernel & getKernel()
Definition: terminal.hpp:192
std::vector< std::string > getPathSettings()
Returns the standard paths as a STL vector.
Definition: terminal.cpp:185
This class is the actual NumeRe main frame. The application's logic is implemented here.
Definition: NumeReWindow.h:177
This class represents a dialog for creating a package from a set of procedures.
wxArrayString getProcedures()
This member function will create a string array containing the procedure files, which are currently p...
void loadProjectFile(const wxString &filename)
Loads a NumeRe package project file to memory and updates the UI correspondingly.
void OnRemoveItems(wxCommandEvent &event)
This is the event handler for the remove files button.
void OnClose(wxCloseEvent &event)
Event handler, which is called, when the user closes the dialog.
void OnAutoDetect(wxCommandEvent &event)
This is the event handler for the autodetect button.
void saveProjectFile(const wxString &filename)
Saves a prepared package configuration as a NumeRe package project file to the HDD.
wxListView * m_fileList
wxPropertyGrid * m_packageProperties
wxString getPackageIdentifier()
This member function returns the package identifier, which is constructed from the name and only cont...
IconManager * m_icons
void setMainFile(const wxString &mainfile)
This function can be used to insert the current mainfile to the dialog. Used by the main window,...
wxString getInstallInfo()
This member function will create the install information section of the package based upon the setted...
bool includeDocs()
This member function returns whether the user selected the "include docs" property.
void autoDetect(const wxArrayString &mainfiles)
This function autodetects the dependencies of the passed files by calling the PackageDialog::followBr...
void OnLoadProjectFile(wxCommandEvent &event)
Button event handler to load an existing project file.
void findLayoutDependencies(const std::string &sFile, std::set< std::string > &fileSet)
This member function uses the event procedures of a window layout file to create a dependency tree fo...
void OnCreatePackage(wxCommandEvent &event)
Called upon clicking on "Create package" button. Will ask for saving the project.
void OnAddItems(wxCommandEvent &event)
This is the event handler for the add files button.
void OnAbort(wxCommandEvent &event)
Called upon clicking on "Cancel" button. Will ask for saving the project.
NumeReTerminal * m_terminal
void followBranch(const std::string &sFile, std::set< std::string > &fileSet)
This function will recursively call itself to detect a whole branch of file dependencies.
void markUnsaved()
Marks the current project as modified.
wxString getPackageName()
This member function returns the name of the package, as been set by the user.
void OnPropGridChange(wxPropertyGridEvent &event)
Event handler for all property grid changes.
bool isSaved()
Returns true, if the current project is in a saved state.
void SaveOnClose()
Evaluates, whether the current project has been saved and prompt the user a saving dialog,...
void OnSaveProjectFile(wxCommandEvent &event)
Button event handler to save a prepared package setting to a project file.
wxString getPackageVersion()
Returns the version of the defined package as a simple string.
bool isPlugin()
This member function returns, whether the user selected a plugin type as install type.
wxString getDocFile()
Returns the user-chosen documentation file.
Dependencies * getDependencies()
This member function returns the first-level dependencies of the current procedure file....
This class manages all already read and possibly pre-parsed procedure files for easier and faster acc...
ProcedureElement * getProcedureContents(const std::string &sProcedureFileName)
Returns the ProcedureElement pointer to the desired procedure file. It also creates the element,...
This class represents a text file in memory (e.g. a code file). This class will try to lex the loaded...
std::string getStrippedLine(size_t line) const
Returns the selected line (without the line termination characters and without any comments).
int getLinesCount() const
Returns the number of lines in the current loaded file.
std::string getFileName() const
Returns the filename of the respresented file in memory.
FileRevisions * getRevisions(const wxString &currentFile)
This method returns the file revisions as pointer.
Definition: vcsmanager.cpp:68
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:2312
XMLElement * NewElement(const char *name)
Definition: tinyxml2.cpp:2239
XMLError SaveFile(const char *filename, bool compact=false)
Definition: tinyxml2.cpp:2385
const char * GetText() const
Definition: tinyxml2.cpp:1656
void SetAttribute(const char *name, const char *value)
Sets the named attribute to value.
Definition: tinyxml2.h:1465
void SetText(const char *inText)
Definition: tinyxml2.cpp:1675
const char * Attribute(const char *name, const char *value=0) const
Definition: tinyxml2.cpp:1595
bool BoolAttribute(const char *name, bool defaultValue=false) const
See IntAttribute()
Definition: tinyxml2.cpp:1635
const XMLElement * NextSiblingElement(const char *name=0) const
Get the next (right) sibling element of this node, with an optionally supplied name.
Definition: tinyxml2.cpp:1018
const XMLElement * FirstChildElement(const char *name=0) const
Definition: tinyxml2.cpp:994
XMLNode * InsertFirstChild(XMLNode *addThis)
Definition: tinyxml2.cpp:925
XMLNode * InsertEndChild(XMLNode *addThis)
Definition: tinyxml2.cpp:895
@ SCRIPTPATH
@ PROCPATH
@ ID_PKGDLG_REMOVE
@ ID_PKGDLG_ADD
@ ID_PKGDLG_SAVEPROJECT
@ ID_PKGDLG_ABORT
@ ID_PKGDLG_LOADPROJECT
@ ID_PKGDLG_CREATEPACKAGE
@ ID_PKGDLG_AUTODETECT
std::string replacePathSeparator(const std::string &)
This function replaces the Windows style path sparators to UNIX style.
bool fileExists(const string &)
This function checks, whether the file with the passed file name exists.
Definition: tools.cpp:2500
std::string get(const std::string &sUrl, const std::string &sUserName, const std::string &sPassWord)
Get the contents of a URL.
Definition: http.cpp:251
#define INCLUDEDOCS
Language _guilang
static void resolveIncludes(std::set< std::string > &fileSet)
Static function to resolve the includes in the passed set and add them to the set afterwards.
#define DOCFILE
char name[32]
Definition: resampler.cpp:371
std::string incrementVersion(std::string _sVer)
Increments a MAJOR.MINOR.BUILD version string by one build count.
Definition: tools.cpp:3991
END_EVENT_TABLE()
std::vector< std::string > getEventProcedures(const std::string &sLayoutFile)
Examines a window layout file and searches for all event handler procedures. Returns their correspond...
Definition: winlayout.cpp:723