27 #include <boost/property_tree/ptree.hpp>
28 #include <boost/property_tree/xml_parser.hpp>
42 using namespace Ws::Event;
48 shared_ptr<WorkspaceQtModel> WorkspaceQtModel::Create(
const shared_ptr<IWorkspace>& w,
49 Controller::ProjectController* c,
52 auto result = shared_ptr<WorkspaceQtModel>(
new WorkspaceQtModel(w, c, parent));
55 auto handler = bind(&WorkspaceQtModel::ListenWorkspaceEvent, result.get(), _1);
56 w->
Subject<Ws::Event::WorkspaceChanged, std::weak_ptr<const void>>::Register(result, handler);
59 auto it = result->m_root->workspace.children.begin();
60 for (
auto& project : *w) {
61 auto handler = bind(&WorkspaceQtModel::ListenProjectEvent, result.get(), *it, _1);
62 project.second->Subject<Ws::Event::ProjectChanged, std::weak_ptr<const void>>::Register(result, handler);
69 WorkspaceQtModel::WorkspaceQtModel(
const shared_ptr<IWorkspace>& w,
70 Controller::ProjectController* c,
74 m_project_controller(c)
78 for (
auto& project : *m_workspace) {
79 auto project_item =
new Item(m_root->workspace.children.size(), project.first, project.second.Project());
80 for (
auto& file : *(project.second)) {
81 auto file_item =
new Item(project_item->project.children.size(), file.first, project_item, file.second);
82 project_item->project.children.push_back(file_item);
84 m_root->workspace.children.push_back(project_item);
88 WorkspaceQtModel::~WorkspaceQtModel()
95 bool WorkspaceQtModel::Close()
97 return m_project_controller->PromptClose();
100 bool WorkspaceQtModel::Close(
const QModelIndex& index)
102 if (!index.isValid()) {
103 throw Exception(
"WorkspaceQtModel::Close> Invalid index given!");
106 if (IsOpened(index)) {
107 return m_project_controller->PromptClose();
110 return (
bool) m_project_controller;
117 case Ws::Event::WorkspaceChanged::Type::ProjectAdded:
120 const string name = e.
GetName();
123 auto project_it = m_workspace->Find(name);
126 int row = FindProjectRowInsert(project_it);
130 Item* project_item =
new Item(row, project_it->first, project_it->second.Project());
131 m_root->workspace.children[row] = project_item;
134 project_it->second->Subject<
Ws::Event::ProjectChanged, std::weak_ptr<const void>>::Register(shared_from_this(), bind(&WorkspaceQtModel::ListenProjectEvent,
this, project_item, _1));
137 for (
auto& file : *(project_it->second)) {
138 auto file_item =
new Item(project_item->project.children.size(), file.first, project_item, file.second);
139 project_item->project.children.push_back(file_item);
143 auto index = createIndex(row, 0, project_item);
144 emit dataChanged(index, index);
148 case Ws::Event::WorkspaceChanged::Type::ProjectRenamed:
157 int old_row = FindProjectRow(old_name);
161 auto new_it = m_workspace->Find(new_name);
162 int new_row = FindProjectRowInsert(new_it);
166 Item* new_item =
new Item(new_row, new_it->first, new_it->second.Project());
167 m_root->workspace.children[new_row] = new_item;
170 new_it->second->Subject<Ws::Event::ProjectChanged, std::weak_ptr<const void>>::Register(shared_from_this(), bind(&WorkspaceQtModel::ListenProjectEvent,
this, new_item, _1));
173 for (
auto& file : *(new_it->second)) {
174 auto file_item =
new Item(new_item->project.children.size(), file.first, new_item, file.second);
175 new_item->project.children.push_back(file_item);
179 auto new_index = createIndex(new_row, 0, new_item);
180 emit dataChanged(new_index, new_index);
184 case Ws::Event::WorkspaceChanged::Type::ProjectRemoved:
192 int row = FindProjectRow(name);
202 void WorkspaceQtModel::ListenProjectEvent(Item* project_item,
const Ws::Event::ProjectChanged& e)
206 case Ws::Event::ProjectChanged::Type::LeafAdded:
209 const string name = e.GetName();
212 auto file_it = project_item->project.obj->Find(name);
215 int row = FindFileRowInsert(project_item, file_it);
216 insertRow(row, index(project_item->row, 0));
219 Item* file_item =
new Item(row, file_it->first, project_item, file_it->second);
220 project_item->project.children[row] = file_item;
223 auto index = createIndex(row, 0, file_item);
224 emit dataChanged(index, index);
228 case Ws::Event::ProjectChanged::Type::LeafRemoved:
231 const string name = e.GetName();
234 int row = FindFileRow(project_item, name);
235 removeRow(row, index(project_item->row, 0));
244 vector<QAction*> WorkspaceQtModel::GetContextMenuActions(
const QModelIndex& index)
const
246 if (!index.isValid()) {
247 throw Exception(
"WorkspaceQtModel::GetContextMenuActions> Invalid index given!");
249 Item* item =
static_cast<Item*
>(index.internalPointer());
253 return item->project.obj->GetContextMenuActions();
255 return item->file.obj->GetContextMenuActions();
257 throw Exception(
"WorkspaceQtModel::GetContextMenuActions() should only be called on items of ProjectType or FileType.");
261 string const& WorkspaceQtModel::GetName(QModelIndex
const& index)
const
263 if (!index.isValid()) {
264 throw Exception(
"WorkspaceQtModel::GetName> Invalid index given!");
266 Item* item =
static_cast<Item*
>(index.internalPointer());
270 return item->project.name;
272 return item->file.name;
274 throw Exception(
"WorkspaceQtModel::GetName() should only be called on items of ProjectType or FileType.");
278 WorkspaceQtModel::ItemType WorkspaceQtModel::GetType(QModelIndex
const& index)
const
280 if (!index.isValid()) {
281 throw Exception(
"WorkspaceQtModel::GetType> Invalid index given!");
283 return static_cast<Item*
>(index.internalPointer())->type;
286 int WorkspaceQtModel::FindProjectRow(
const string& name)
288 auto& children = m_root->workspace.children;
289 for (
auto it = children.begin(); it != children.end(); it++) {
290 if ((*it)->project.name == name) {
291 return it - children.begin();
297 int WorkspaceQtModel::FindProjectRowInsert(IWorkspace::ConstProjectIterator project_it)
299 auto next_it = project_it;
301 if (next_it == m_workspace->end()) {
302 return m_root->workspace.children.size();
304 return FindProjectRow(next_it->first);
308 int WorkspaceQtModel::FindFileRow(Item* project_item,
const string& name)
310 auto& children = project_item->project.children;
311 for (
auto it = children.begin(); it != children.end(); it++) {
312 if ((*it)->file.name == name) {
313 return it - children.begin();
319 int WorkspaceQtModel::FindFileRowInsert(Item* project_item, IProject::ConstFileIterator file_it)
321 auto next_it = file_it;
323 if (next_it == project_item->project.obj->end()) {
324 return project_item->project.children.size();
326 return FindFileRow(project_item, next_it->first);
330 bool WorkspaceQtModel::IsOpened(
const QModelIndex& index)
const
332 Item* item =
static_cast<Item*
>(index.internalPointer());
333 switch (item->type) {
335 if (item->project.obj->IsOpened()) {
340 if (item->file.parent->project.obj->IsOpened()) {
351 bool WorkspaceQtModel::Open(
const QModelIndex& index)
353 if (!index.isValid()) {
354 throw Exception(
"WorkspaceQtModel::Open> Invalid index given!");
357 if (!m_project_controller->PromptClose())
360 Item* item =
static_cast<Item*
>(index.internalPointer());
361 switch (item->type) {
364 Ws::IWorkspace::ProjectIterator it_p = m_workspace->Find(item->project.name);
365 auto project = it_p->second.Project();
367 return m_project_controller->Set(item->project.name, project);
371 Item* project_item = item->file.parent;
372 Ws::IWorkspace::ProjectIterator it_p = m_workspace->Find(project_item->project.name);
373 auto project = it_p->second.Project();
374 project->Open(item->file.name);
375 return m_project_controller->Set(project_item->project.name, project);
386 int WorkspaceQtModel::columnCount(QModelIndex
const& )
const
391 QVariant WorkspaceQtModel::data(QModelIndex
const& index,
int role)
const
393 if (index.isValid()) {
394 Item* item =
static_cast<Item*
>(index.internalPointer());
396 bool opened = IsOpened(index);
398 switch (item->type) {
400 if (role == Qt::DisplayRole) {
401 return QString::fromStdString(item->project.name);
402 }
else if (role == Qt::DecorationRole) {
404 return QIcon::fromTheme(
"folder-open");
406 return QIcon::fromTheme(
"folder");
408 }
else if (role == Qt::FontRole) {
416 if (role == Qt::DisplayRole) {
417 return QString::fromStdString(item->file.name);
418 }
else if (role == Qt::DecorationRole) {
419 return QIcon::fromTheme(
"text-x-generic");
420 }
else if (role == Qt::FontRole) {
434 Qt::ItemFlags WorkspaceQtModel::flags(QModelIndex
const & index)
const
436 Qt::ItemFlags flag = 0;
437 if (index.isValid()) {
438 flag = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
443 QVariant WorkspaceQtModel::headerData(
int , Qt::Orientation ,
int )
const
448 QModelIndex WorkspaceQtModel::index(
int row,
int column, QModelIndex
const& parent)
const
450 if (!hasIndex(row, column, parent)) {
451 return QModelIndex();
455 if (!parent.isValid()) {
456 parent_item = m_root;
458 parent_item =
static_cast<Item*
>(parent.internalPointer());
461 switch (parent_item->type) {
463 return createIndex(row, column, parent_item->workspace.children[row]);
465 return createIndex(row, column, parent_item->project.children[row]);
467 return QModelIndex();
471 bool WorkspaceQtModel::insertRow(
int row, QModelIndex
const& parent)
473 return insertRows(row, 1, parent);
476 bool WorkspaceQtModel::insertRows(
int row,
int count, QModelIndex
const& parent)
479 if (parent.isValid()) {
480 item =
static_cast<Item*
>(parent.internalPointer());
489 vector<Item*>* children =
nullptr;
491 switch (item->type) {
493 children = &item->workspace.children;
496 children = &item->project.children;
503 if (row > (
int) children->size()) {
507 beginInsertRows(parent, row, row + count - 1);
508 for (
int i = 0; i < count; i++) {
509 children->insert(children->begin() + row + i, 0);
512 for (
int i = row + count; i < static_cast<int>(children->size()); i++) {
513 (*children)[i]->row += count;
520 QModelIndex WorkspaceQtModel::parent(QModelIndex
const& index)
const
522 if (!index.isValid()) {
523 return QModelIndex();
525 Item* child =
static_cast<Item*
>(index.internalPointer());
526 if (child->type == FileType) {
527 Item* project = child->file.parent;
528 auto it = find(m_root->workspace.children.begin(), m_root->workspace.children.end(), project);
529 return createIndex(it - m_root->workspace.children.begin(), 0, project);
531 return QModelIndex();
535 bool WorkspaceQtModel::removeRow(
int row, QModelIndex
const& parent)
537 return removeRows(row, 1, parent);
540 bool WorkspaceQtModel::removeRows(
int row,
int count, QModelIndex
const& parent)
543 if (parent.isValid()) {
544 item =
static_cast<Item*
>(parent.internalPointer());
552 vector<Item*>* children =
nullptr;
554 switch (item->type) {
556 children = &item->workspace.children;
559 children = &item->project.children;
565 if (row + count > (
int) children->size()) {
569 beginRemoveRows(parent, row, row + count - 1);
570 for (
int i = 0; i < count; i++) {
571 delete (*children)[row + i];
572 children->erase(children->begin() + row + i);
579 int WorkspaceQtModel::rowCount(QModelIndex
const& parent)
const
582 if (!parent.isValid()) {
585 item =
static_cast<Item*
>(parent.internalPointer());
587 switch (item->type) {
589 return item->workspace.children.size();
591 return item->project.children.size();
see the online Qt documentation
Namespace for miscellaneous utilities.
Interface for WorkspaceQtModel.
Extremely simple Exception root class.
Event used to inform some observer that the workspace has changed.
Interface for IWorkspace.
Type GetType() const
Get type.
Event used to inform some observer that a project has changed.
const std::string GetOldName() const
In case type is ProjectRenamed, get old name of renamed project.
Subject in Observer pattern.
Header file for Exception class.
see the online Qt documentation
Namespace for generic graphical shell for simulators.
const std::string GetName() const
In case type is ProjectAdded or ProjectRemoved, get name of project.
const std::string GetNewName() const
In case type is ProjectRenamed, get new name of renamed project.