26 #include <QCloseEvent>
27 #include <QFileDialog>
28 #include <QInputDialog>
31 #include <QMessageBox>
34 #include <boost/property_tree/ptree.hpp>
35 #include <boost/property_tree/xml_parser.hpp>
46 QString
const PTreeEditor::g_caption(
"PTree Editor");
47 QString
const PTreeEditor::g_caption_with_file(
"PTree Editor: %1");
49 PTreeEditor::PTreeEditor(
QWidget* parent)
53 setWindowTitle(g_caption);
57 setCentralWidget(ptree_view);
63 statusbar =
new QStatusBar(
this);
64 statusbar->clearMessage();
65 setStatusBar(statusbar);
68 action_new =
new QAction(QIcon::fromTheme(
"document-new"),
"&New...",
this);
69 action_open =
new QAction(QIcon::fromTheme(
"document-open"),
"&Open...",
this);
70 action_save =
new QAction(QIcon::fromTheme(
"document-save"),
"&Save",
this);
71 action_save_as =
new QAction(QIcon::fromTheme(
"document-save-as"),
"Save &As...",
this);
72 action_close =
new QAction(
"&Close",
this);
73 action_quit =
new QAction(QIcon::fromTheme(
"application-exit"),
"&Quit",
this);
74 action_view_toolbar =
new QAction(
"&Toolbar",
this);
75 action_view_statusbar =
new QAction(
"&Statusbar",
this);
76 action_fullscreen =
new QAction(QIcon::fromTheme(
"view-fullscreen"),
"&Fullscreen",
this);
77 action_about =
new QAction(
"&About",
this);
79 action_save->setEnabled(
false);
80 action_save_as->setEnabled(
false);
81 action_close->setEnabled(
false);
83 action_view_toolbar->setCheckable(
true);
84 action_view_statusbar->setCheckable(
true);
85 action_fullscreen->setCheckable(
true);
86 action_view_toolbar->setChecked(
true);
87 action_view_statusbar->setChecked(
true);
88 action_fullscreen->setChecked(
false);
90 action_new->setShortcut(QKeySequence(
"Ctrl+N"));
91 action_open->setShortcut(QKeySequence(
"Ctrl+O"));
92 action_save->setShortcut(QKeySequence(
"Ctrl+S"));
93 action_save_as->setShortcut(QKeySequence(
"Shift+Ctrl+S"));
94 action_close->setShortcut(QKeySequence(
"Ctrl+W"));
95 action_quit->setShortcut(QKeySequence(
"Ctrl+Q"));
96 action_fullscreen->setShortcut(QKeySequence(
"F11"));
99 QAction* action_undo = ptree_view->GetUndoAction();
100 QAction* action_redo = ptree_view->GetRedoAction();
101 QAction* action_cut = ptree_view->GetCutAction();
102 QAction* action_copy = ptree_view->GetCopyAction();
103 QAction* action_paste = ptree_view->GetPasteAction();
104 QAction* action_find = ptree_view->GetFindDialogAction();
105 QAction* action_clear_highlight = ptree_view->GetClearHighlightAction();
106 QAction* action_insert_before = ptree_view->GetInsertBeforeAction();
107 QAction* action_insert_child = ptree_view->GetInsertChildAction();
108 QAction* action_move_up = ptree_view->GetMoveUpAction();
109 QAction* action_move_down = ptree_view->GetMoveDownAction();
110 QAction* action_remove = ptree_view->GetRemoveAction();
111 QAction* action_expand_all = ptree_view->GetExpandAllAction();
112 QAction* action_expand_none = ptree_view->GetExpandNoneAction();
119 menu_file->addAction(action_new);
120 menu_file->addAction(action_open);
121 menu_file->addSeparator();
122 menu_file->addAction(action_save);
123 menu_file->addAction(action_save_as);
124 menu_file->addSeparator();
125 menu_file->addAction(action_close);
126 menu_file->addAction(action_quit);
127 menu->addMenu(menu_file);
130 menu_edit->addAction(action_undo);
131 menu_edit->addAction(action_redo);
132 menu_edit->addSeparator();
133 menu_edit->addAction(action_cut);
134 menu_edit->addAction(action_copy);
135 menu_edit->addAction(action_paste);
136 menu->addMenu(menu_edit);
139 menu_item->addAction(action_insert_before);
140 menu_item->addAction(action_insert_child);
141 menu_item->addSeparator();
142 menu_item->addAction(action_move_up);
143 menu_item->addAction(action_move_down);
144 menu_item->addSeparator();
145 menu_item->addAction(action_remove);
146 menu->addMenu(menu_item);
149 menu_view->addAction(action_expand_all);
150 menu_view->addAction(action_expand_none);
151 menu_view->addSeparator();
152 menu_view->addAction(action_view_toolbar);
153 menu_view->addAction(action_view_statusbar);
154 menu_view->addSeparator();
155 menu_view->addAction(action_fullscreen);
156 menu->addMenu(menu_view);
158 QMenu* menu_search =
new QMenu(
"&Search", menu);
159 menu_search->addAction(action_find);
160 menu_search->addSeparator();
161 menu_search->addAction(action_clear_highlight);
162 menu->addMenu(menu_search);
165 menu_help->addAction(action_about);
166 menu->addMenu(menu_help);
169 toolbar =
new QToolBar(
this);
170 toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
171 toolbar->setMovable(
false);
172 toolbar->addAction(action_new);
173 toolbar->addAction(action_open);
174 toolbar->addAction(action_save);
175 toolbar->addSeparator();
176 toolbar->addAction(action_undo);
177 toolbar->addAction(action_redo);
178 toolbar->addSeparator();
179 toolbar->addAction(action_find);
180 toolbar->addSeparator();
181 toolbar->addAction(action_fullscreen);
184 connect(action_new, SIGNAL(triggered()),
this, SLOT(SLOT_New()));
185 connect(action_open, SIGNAL(triggered()),
this, SLOT(SLOT_OpenDialog()));
186 connect(action_save, SIGNAL(triggered()),
this, SLOT(SLOT_Save()));
187 connect(action_save_as, SIGNAL(triggered()),
this, SLOT(SLOT_SaveAsDialog()));
188 connect(action_close, SIGNAL(triggered()),
this, SLOT(SLOT_PromptClose()));
189 connect(action_quit, SIGNAL(triggered()),
this, SLOT(close()));
190 connect(action_view_toolbar, SIGNAL(toggled(
bool)), toolbar, SLOT(setVisible(
bool)));
191 connect(action_view_statusbar, SIGNAL(toggled(
bool)), statusbar, SLOT(setVisible(
bool)));
192 connect(action_fullscreen, SIGNAL(toggled(
bool)),
this, SLOT(SLOT_SetFullscreenMode(
bool)));
193 connect(action_about, SIGNAL(triggered()),
this, SLOT(SLOT_AboutDialog()));
194 connect(ptree_view, SIGNAL(CleanChanged(
bool)),
this, SLOT(SLOT_SetClean(
bool)));
195 connect(ptree_view, SIGNAL(StatusChanged(QString
const &)), statusbar, SLOT(showMessage(QString
const &)));
198 void PTreeEditor::closeEvent(QCloseEvent *event)
200 if (PromptClose(
this)) {
207 void PTreeEditor::InternalForceClose() {
209 ptree_view->setModel(
nullptr);
211 ptree_model =
nullptr;
213 action_save->setEnabled(
false);
214 action_save_as->setEnabled(
false);
215 action_close->setEnabled(
false);
216 setWindowTitle(g_caption);
220 bool PTreeEditor::InternalIsClean()
const
222 return !IsOpened() || ptree_view->IsClean();
225 bool PTreeEditor::InternalSave()
227 if (opened_path.empty())
228 return SLOT_SaveAsDialog();
230 return SavePath(opened_path);
233 bool PTreeEditor::IsOpened()
const {
237 bool PTreeEditor::OpenPath(
string const& path)
241 if (!PromptClose()) {
246 QString filename = QString::fromStdString(path).split(
"/").last();
249 read_xml(path, root_pt, trim_whitespace);
253 if (root_pt.empty()) {
254 QMessageBox::warning(
this, QString(
"Could not open file ") + filename, QString(
"File is empty!"));
257 string default_subtree;
258 for (
auto child : root_pt) {
259 if (child.first ==
"<xmlcomment>")
261 default_subtree = child.first;
263 string const subtree = QInputDialog::getText(
this,
"",
"Please specify path of subtree to edit:",
264 QLineEdit::Normal, QString::fromStdString(default_subtree), &ok).toStdString();
266 edit_pt = root_pt.get_child(subtree);
269 setWindowTitle(g_caption_with_file.arg(QString::fromStdString(path)));
270 subtree_key = subtree;
272 ptree_view->setModel(ptree_model);
274 action_close->setEnabled(
true);
275 action_save_as->setEnabled(
true);
281 catch (xml_parser_error& e) {
282 QMessageBox::warning(
this, QString(
"Could not open file ") + filename,
283 QString(
"Exception xml_parser_error ") + e.what());
285 catch (ptree_bad_path& e) {
286 QMessageBox::warning(
this, QString(
"Could not open file ") + filename,
287 QString(
"Exception ptree_bad_path ") + e.what());
289 catch (ptree_bad_data& e) {
290 QMessageBox::warning(
this, QString(
"Could not open file ") + filename,
291 QString(
"Exception ptree_bad_data ") + e.what());
296 void PTreeEditor::SLOT_AboutDialog()
298 const QString app_name =
"PTree Editor";
299 const QString about =
"<h3>PTree editor</h3>\
300 <p>(c) 2012, <a href=\"http://www.comp.ua.ac.be/\">J. Broeckhove</a> <i>et al.</i><br>\
301 <a href=\"http://www.comp.ua.ac.be\">Computational Modeling and Programming</a><br>\
302 Universiteit Antwerpen, Belgium.</p>";
304 QMessageBox::about(
this,app_name, about);
307 void PTreeEditor::SLOT_New()
315 string const subtree =
316 QInputDialog::getText(
this,
"New...",
"Root element:",
317 QLineEdit::Normal,
"vleaf_sim", &ok).toStdString();
320 edit_pt.add_child(
"<xmlcomment>", ptree(
"File created by simPT Ptree Editor."));
325 setWindowTitle(g_caption_with_file.arg(
"Untitled"));
326 subtree_key = subtree;
328 ptree_view->setModel(ptree_model);
330 action_close->setEnabled(
true);
331 action_save->setEnabled(
true);
332 action_save_as->setEnabled(
true);
336 void PTreeEditor::SLOT_OpenDialog()
338 QFileDialog* fd =
new QFileDialog(
this,
"Open", QString(),
"Ptree files (*.xml)");
339 fd->setFilter(QDir::Hidden);
340 fd->setFileMode(QFileDialog::AnyFile);
341 fd->setAcceptMode(QFileDialog::AcceptOpen);
343 if (fd->exec() == QDialog::Accepted) {
344 QStringList files = fd->selectedFiles();
346 if (!files.empty()) {
347 filename = files.first();
351 QFileInfo fi(filename);
352 if (!QFile::exists(filename) && QFile::exists(filename +
".xml")) {
356 OpenPath(filename.toStdString());
360 void PTreeEditor::SLOT_PromptClose()
389 void PTreeEditor::SLOT_Save()
394 bool PTreeEditor::SLOT_SaveAsDialog()
396 QFileDialog* fd =
new QFileDialog(
this,
"Save As", QString(),
"XML files (*.xml)");
397 fd->setFileMode(QFileDialog::AnyFile);
398 fd->setAcceptMode(QFileDialog::AcceptSave);
400 if (fd->exec() == QDialog::Accepted) {
401 QStringList files = fd->selectedFiles();
404 filename = files.first();
405 QFileInfo fi(filename);
406 if (fi.suffix().isEmpty())
409 return SavePath(filename.toStdString());
415 bool PTreeEditor::SavePath(std::string
const& path)
419 ptree param_pt = ptree_model->Store();
420 root_pt.put_child(subtree_key, param_pt);
421 write_xml(path, root_pt, std::locale(), XmlWriterSettings::GetTab());
423 catch (xml_parser_error & e) {
424 QMessageBox::warning(
this,
"Could not save to file", QString(
"Exception xml_parser_error ") + e.what());
428 ptree_view->SetClean();
430 setWindowTitle(g_caption_with_file.arg(QString::fromStdString(opened_path)));
436 void PTreeEditor::SLOT_SetClean(
bool clean)
438 if (!opened_path.empty()) {
439 action_save->setEnabled(!clean);
443 void PTreeEditor::SLOT_SetFullscreenMode(
bool checked)
446 setWindowState(windowState() | Qt::WindowFullScreen);
448 setWindowState(windowState() & ~Qt::WindowFullScreen);
see the online Qt documentation
Namespace for miscellaneous utilities.
HasUnsavedChanges with the ability of displaying a "save-discard-cancel" dialog to the user before cl...
Namespace for SimPT shell package.
Namespace for graphical interface classes.
Qt model reflecting hierarchical structure of a ptree.
see the online Qt documentation
TreeView widget that presents an editable ptree to the user.
see the online Qt documentation
Interface for PTreeEditor.
see the online Qt documentation
Interface for PTreeModel.
Xml writer settings class.