/* dtkComposerSearchDialog.cpp --- * * Author: Julien Wintz * Copyright (C) 2008-2011 - Julien Wintz, Inria. * Created: Mon Nov 5 16:41:00 2012 (+0100) * Version: $Id: af5575ce30cc5f39006a3d1733b26568ab5e644d $ * Last-Updated: ven. oct. 18 14:09:05 2013 (+0200) * By: Nicolas Niclausse * Update #: 292 */ /* Commentary: * */ /* Change log: * */ #include "dtkComposerNode.h" #include "dtkComposerScene.h" #include "dtkComposerSceneNode.h" #include "dtkComposerSceneNodeComposite.h" #include "dtkComposerSceneNodeControl.h" #include "dtkComposerSearchDialog.h" #include "dtkComposerView.h" // ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// class dtkComposerSearchDialogPrivate { public: void populate(dtkComposerSceneNode *node); void sortCombo(QComboBox *combo); public: void update(void); public: dtkComposerScene *scene; dtkComposerView *view; public: QPushButton *find_button; QPushButton *next_button; QPushButton *more_button; QComboBox *node_combo; QComboBox *type_combo; QTextEdit *info; public: QHash > nodes; QHash > types; public: QList result; public: int index; }; void dtkComposerSearchDialogPrivate::populate(dtkComposerSceneNode *node) { if (!node->title().isEmpty()) { this->node_combo->addItem(node->title()); this->nodes[node->title()] << node; this->nodes["*"] << node; } if (node->wrapee()) { this->type_combo->addItem(node->wrapee()->type()); this->types[node->wrapee()->type()] << node; this->types["*"] << node; } if (dtkComposerSceneNodeComposite *composite = dynamic_cast(node)) foreach (dtkComposerSceneNode *child, composite->nodes()) this->populate(child); if (dtkComposerSceneNodeControl *control = dynamic_cast(node)) foreach (dtkComposerSceneNodeComposite *block, control->blocks()) this->populate(block); } void dtkComposerSearchDialogPrivate::sortCombo(QComboBox *combo) { QSortFilterProxyModel *proxy = new QSortFilterProxyModel(combo); proxy->setSourceModel(combo->model()); combo->model()->setParent(proxy); combo->setModel(proxy); combo->model()->sort(0); } void dtkComposerSearchDialogPrivate::update(void) { // dialog display QString contents = QString("Found %1 nodes satisfyng the following criteria:\n" "- title: %2\n" "- type: %3\n" "\n" "Currently highlighting node %4 over %1") .arg(this->result.count()) .arg(this->node_combo->currentText()) .arg(this->type_combo->currentText()) .arg(this->index + 1); this->info->setText(contents); // scene display if (this->scene) this->scene->clearSelection(); if (!this->result.count()) return; dtkComposerSceneNode *node = this->result.at(this->index); if (!node) return; node->setSelected(true); // view display if (this->view) this->view->centerOn(node->pos()); } // ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// dtkComposerSearchDialog::dtkComposerSearchDialog(dtkComposerView *parent) : QDialog(parent), d(new dtkComposerSearchDialogPrivate) { d->scene = NULL; d->view = parent; d->node_combo = new QComboBox(this); d->node_combo->setEditable(true); d->type_combo = new QComboBox(this); d->type_combo->setEditable(true); d->info = new QTextEdit(this); d->info->setVisible(false); QDialogButtonBox *box = new QDialogButtonBox(this); d->find_button = box->addButton("Find", QDialogButtonBox::ActionRole); d->find_button->setDefault(true); d->next_button = box->addButton("Next", QDialogButtonBox::ActionRole); d->next_button->setDefault(false); d->next_button->setEnabled(false); d->more_button = box->addButton("More", QDialogButtonBox::ActionRole); d->more_button->setCheckable(true); QFormLayout *layout = new QFormLayout(this); layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); layout->addRow("Title", d->node_combo); layout->addRow("Type", d->type_combo); layout->addWidget(box); layout->addWidget(d->info); QAction *search_next_action = new QAction("Find next", this); search_next_action->setShortcut(QKeySequence::FindNext); this->addAction(search_next_action); this->setStyleSheet("background: none;"); this->setWindowTitle("Search"); connect(d->find_button, SIGNAL(clicked()), this, SLOT(find())); connect(d->next_button, SIGNAL(clicked()), this, SLOT(next())); connect(d->more_button, SIGNAL(clicked()), this, SLOT(more())); connect(d->node_combo, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(clear())); connect(d->node_combo, SIGNAL(editTextChanged(const QString&)), this, SLOT(clear())); connect(search_next_action, SIGNAL(triggered()), this, SLOT(next())); } dtkComposerSearchDialog::~dtkComposerSearchDialog(void) { delete d; d = NULL; } void dtkComposerSearchDialog::setScene(dtkComposerScene *scene) { d->scene = scene; QString node = d->node_combo->currentText(); QString type = d->type_combo->currentText(); d->nodes.clear(); d->types.clear(); d->node_combo->clear(); d->node_combo->addItem("*"); d->type_combo->clear(); d->type_combo->addItem("*"); d->populate(scene->root()); d->sortCombo(d->node_combo); d->sortCombo(d->type_combo); if (!node.isEmpty()) d->node_combo->setEditText(node); if (!type.isEmpty()) d->type_combo->setEditText(type); d->find_button->setDefault(true); d->next_button->setEnabled(false); d->next_button->setDefault(false); } void dtkComposerSearchDialog::find(void) { d->result.clear(); QString node = d->node_combo->currentText(); QString type = d->type_combo->currentText(); QSet result = d->nodes[node] & d->types[type]; d->result = result.toList(); d->index = 0; d->find_button->setDefault(false); d->find_button->setEnabled(false); d->next_button->setEnabled(true); d->next_button->setDefault(true); d->update(); } void dtkComposerSearchDialog::next(void) { if (!d->result.count()) return; d->index = (d->index + 1) % d->result.count(); d->update(); } void dtkComposerSearchDialog::more(void) { d->info->setVisible(!d->info->isVisible()); } void dtkComposerSearchDialog::clear(void) { d->find_button->setDefault(true); d->find_button->setEnabled(true); d->next_button->setEnabled(false); d->next_button->setDefault(false); }