From 2ef42184c223c73fa67e7a9a1b1c94ebfce68427 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20M=C3=B6ller?= Date: Fri, 19 Oct 2012 15:23:14 +0000 Subject: [PATCH] add context menu refs #1148 git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@15702 383ad7c9-94d9-4d36-a494-682f7c89f535 --- CMakeLists.txt | 4 +- MaterialPicker.cc | 272 ++++++++++++++++++++++++++++++++++++---------- MaterialPicker.hh | 40 ++++++- 3 files changed, 252 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8cb806a..ee452c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,5 @@ include (plugin) -openflipper_plugin (INSTALLDATA Icons) +openflipper_plugin (INCDIRS ${CMAKE_BINARY_DIR}/ACG + INSTALLDATA Icons) +add_dependencies(Plugin-MaterialPicker ACG OpenFlipper) diff --git a/MaterialPicker.cc b/MaterialPicker.cc index 45906c1..8df4bfd 100644 --- a/MaterialPicker.cc +++ b/MaterialPicker.cc @@ -45,6 +45,7 @@ #include #include +#include #include //------------------------------------------------------------------------------ @@ -55,8 +56,12 @@ MaterialPicker::MaterialPicker() pickMaterialButton_(0), fillMaterialButton_(0), materialListWidget_(0), + materialStrings_(), + shortKeyRow_(), + materialNode_(), pickMaterial_(false), fillMaterial_(false) + { } @@ -84,11 +89,10 @@ void MaterialPicker::initializePlugin() { materialListWidget_ = new QListWidget(toolBox); //load saved materials - materialString_ = OpenFlipperSettings().value(propName_, QStringList()).toStringList(); - - for (int i = 0; i < materialString_.size(); ++i) + materialStrings_ = OpenFlipperSettings().value(propName_, QStringList()).toStringList(); + for (int i = 0; i < materialStrings_.size(); ++i) { - QStringList savedString = materialString_[i].split(";"); + QStringList savedString = materialStrings_[i].split(";"); std::stringstream stream; MaterialInfo materialInfo; stream << savedString[1].toStdString(); @@ -119,21 +123,20 @@ void MaterialPicker::initializePlugin() { stream >> materialInfo.reflectance; stream.str(""); stream.clear(); - int key; if (savedString.size() < 9) savedString.push_back(QString::number(Qt::Key_unknown)); stream << savedString[8].toStdString(); - stream >> key; + stream >> materialInfo.key; - if (key != Qt::Key_unknown) - shortKeyRow_[key] = materialListWidget_->count(); + if (materialInfo.key != Qt::Key_unknown) + shortKeyRow_[materialInfo.key] = materialListWidget_->count(); - materialListWidget_->addItem( savedString[0] ); + materialListWidget_->addItem( itemName(savedString[0],materialInfo.key) ); materialList_.push_back(materialInfo); } //if material was saved, set first as current - if (materialString_.size()) + if (materialStrings_.size()) materialListWidget_->setCurrentItem(materialListWidget_->item(0)); else fillMaterialButton_->setEnabled(false); @@ -157,9 +160,11 @@ void MaterialPicker::initializePlugin() { connect(fillMaterialButton_, SIGNAL(clicked()), this, SLOT(slotFillMaterialMode())); connect(clearListButton, SIGNAL(clicked()), this, SLOT(clearList())); connect(materialListWidget_, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(editMode(QListWidgetItem*))); - connect(materialListWidget_,SIGNAL(itemChanged ( QListWidgetItem*)), this, SLOT(saveNewName(QListWidgetItem*))); + connect(materialListWidget_->itemDelegate(), SIGNAL(closeEditor(QWidget*, QAbstractItemDelegate::EndEditHint)),this,SLOT(saveNewName(QWidget*, QAbstractItemDelegate::EndEditHint))); connect(removeItemButton, SIGNAL(clicked()), this, SLOT(slotRemoveCurrentItem())); + connect(materialListWidget_,SIGNAL(customContextMenuRequested(const QPoint&)),this,SLOT(createContextMenu(const QPoint&))); + materialListWidget_->setContextMenuPolicy(Qt::CustomContextMenu); QIcon* toolIcon = new QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"material_picker.png"); emit addToolbox( tr("Material Picker"), toolBox, toolIcon); } @@ -170,8 +175,8 @@ void MaterialPicker::removeItem(QListWidgetItem* _item) unsigned index = materialListWidget_->row(_item); materialListWidget_->takeItem(index); materialList_.erase(materialList_.begin()+index); - materialString_.erase(materialString_.begin()+index); - OpenFlipperSettings().setValue(propName_, materialString_); + materialStrings_.erase(materialStrings_.begin()+index); + OpenFlipperSettings().setValue(propName_, materialStrings_); fillMaterialButton_->setEnabled(materialListWidget_->count()); } @@ -180,8 +185,8 @@ void MaterialPicker::removeItem(QListWidgetItem* _item) void MaterialPicker::clearList() { materialListWidget_->clear(); materialList_.clear(); - materialString_.clear(); - OpenFlipperSettings().setValue(propName_, materialString_); + materialStrings_.clear(); + OpenFlipperSettings().setValue(propName_, materialStrings_); fillMaterialButton_->setEnabled(false); } @@ -220,9 +225,8 @@ void MaterialPicker::slotFillMaterialMode() { void MaterialPicker::pluginsInitialized() { emit addPickMode(pickModeName_); - emit registerKey (Qt::Key_1, Qt::ControlModifier, tr("Material 1"), false); - emit registerKey (Qt::Key_2, Qt::ControlModifier, tr("Material 2"), false); - emit registerKey (Qt::Key_3, Qt::ControlModifier, tr("Material 3"), false); + for (unsigned i = 0; i < supportedKeys_; ++i) + emit registerKey (Qt::Key_1+i, Qt::ControlModifier, QString(tr("Material %1")).arg(i+1), false); } //------------------------------------------------------------------------------ @@ -256,36 +260,27 @@ void MaterialPicker::slotMouseEvent(QMouseEvent* _event) { materialInfo.shininess = material->shininess(); materialInfo.reflectance = material->reflectance(); - int key = Qt::Key_unknown; - if (shortKeyRow_.size() < 3) + materialInfo.key = Qt::Key_unknown; + if (shortKeyRow_.size() < supportedKeys_) { - shortKeyRow_[Qt::Key_1+shortKeyRow_.size()] = materialListWidget_->count(); - key = Qt::Key_1+shortKeyRow_.size(); + materialInfo.key = Qt::Key_1+shortKeyRow_.size(); + shortKeyRow_[materialInfo.key] = materialListWidget_->count(); } // update list widget and material list QString name = QString("material id: %1").arg(material->id()); - materialListWidget_->addItem( name ); + materialListWidget_->addItem( itemName(name,materialInfo.key) ); materialListWidget_->setCurrentItem( materialListWidget_->item(materialListWidget_->count() - 1) ); materialList_.push_back(materialInfo); - //save new material - std::stringstream stream; - stream << name.toStdString(); - stream << ";" << materialInfo.color_material; - stream << ";" << materialInfo.base_color; - stream << ";" << materialInfo.ambient_color; - stream << ";" << materialInfo.diffuse_color; - stream << ";" << materialInfo.specular_color; - stream << ";" << materialInfo.shininess; - stream << ";" << materialInfo.reflectance; - stream << ";" << key; - - QString materialString = stream.str().c_str(); - materialString_.push_back(materialString); + //save material + QString matStr = materialString(materialInfo,name); + materialStrings_.push_back(matStr); + OpenFlipperSettings().setValue(propName_, materialStrings_); + fillMaterialButton_->setEnabled(true); - OpenFlipperSettings().setValue(propName_, materialString_); + OpenFlipperSettings().setValue(propName_, materialStrings_); } // apply material from current item in list widget to picked object @@ -315,30 +310,62 @@ void MaterialPicker::slotMouseEvent(QMouseEvent* _event) { //------------------------------------------------------------------------------ +void MaterialPicker::editModeCurrent() +{ + editMode(materialListWidget_->currentItem()); +} + +//------------------------------------------------------------------------------ void MaterialPicker::editMode(QListWidgetItem* _item) { _item->setFlags(_item->flags() | Qt::ItemIsEditable); materialListWidget_->editItem(_item); + _item->setText( plainName(_item->text(),materialListWidget_->row(_item))); } //------------------------------------------------------------------------------ -void MaterialPicker::saveNewName(QListWidgetItem* _item) +void MaterialPicker::saveNewName ( QWidget * _editor, QAbstractItemDelegate::EndEditHint _hint ) +{ + saveNewName(materialListWidget_->currentItem()); +} +//------------------------------------------------------------------------------ +QString MaterialPicker::plainName(const QString &string, int index) +{ + if (materialList_[index].key == Qt::Key_unknown) + return string; + QString str(string); + return str.remove(0,4); +} +//------------------------------------------------------------------------------ +void MaterialPicker::saveNewName (QListWidgetItem* _item) { unsigned index = materialListWidget_->row(_item); - QString str = materialString_[index]; + QString str = materialStrings_[index]; QStringList strList = str.split(";"); //pass name strList[0] = _item->text(); + //highlight hotkey support + if (materialList_[index].key != Qt::Key_unknown) + _item->setText( itemName(strList[0], materialList_[index].key) ); + //create new String to save str = ""; for (int i = 0; i < strList.size()-1; ++i) str += strList[i] + ";"; str += strList[strList.size()-1]; - materialString_[index] = str; - OpenFlipperSettings().setValue(propName_, materialString_); + materialStrings_[index] = str; + OpenFlipperSettings().setValue(propName_, materialStrings_); +} +//------------------------------------------------------------------------------ +QString MaterialPicker::itemName(const QString &_name, int _key) +{ + if (_key == Qt::Key_unknown) + return _name; + return QString(tr("(%1) ")).arg(QString::number(_key-Qt::Key_1+1)) +_name; } + //------------------------------------------------------------------------------ void MaterialPicker::slotPickModeChanged(const std::string& _mode) { @@ -346,28 +373,155 @@ void MaterialPicker::slotPickModeChanged(const std::string& _mode) { fillMaterialButton_->setChecked( _mode == pickModeName_ && fillMaterial_ ); } +//------------------------------------------------------------------------------ void MaterialPicker::slotKeyEvent(QKeyEvent* _event) { - if (_event->key() == Qt::Key_1 && _event->modifiers() == Qt::ControlModifier) - { - if (shortKeyRow_.find(Qt::Key_1) == shortKeyRow_.end()) - return; - slotFillMaterialMode(); - materialListWidget_->setCurrentRow(shortKeyRow_[Qt::Key_1]); - } - if (_event->key() == Qt::Key_2 && _event->modifiers() == Qt::ControlModifier) + for (unsigned i = 0; i < supportedKeys_; ++i) { - if (shortKeyRow_.find(Qt::Key_2) == shortKeyRow_.end()) - return; - slotFillMaterialMode(); - materialListWidget_->setCurrentRow(shortKeyRow_[Qt::Key_2]); + int key = Qt::Key_1+i; + if (_event->key() == key && _event->modifiers() == Qt::ControlModifier) + { + if (shortKeyRow_.find(key) == shortKeyRow_.end()) + return; + slotFillMaterialMode(); + materialListWidget_->setCurrentRow(shortKeyRow_[key]); + } } - if (_event->key() == Qt::Key_3 && _event->modifiers() == Qt::ControlModifier) +} +//------------------------------------------------------------------------------ +void MaterialPicker::changeHotKey(const int &_key) +{ + std::map::iterator iter = shortKeyRow_.find(_key); + if (iter == shortKeyRow_.end()) + return; + + size_t oldIndex = iter->second; + QListWidgetItem* oldItem = materialListWidget_->item(oldIndex); + //remove name + oldItem->setText( plainName(oldItem->text(),oldIndex) ); + materialList_[oldIndex].key = Qt::Key_unknown; //unregister key after rename, otherwise the renaming will fail + materialStrings_[oldIndex] = materialString(materialList_[oldIndex],oldItem->text()); + saveNewName(oldItem); + + //set the new item (save and hint) + size_t newIndex = materialListWidget_->currentRow(); + QListWidgetItem* newItem = materialListWidget_->item(newIndex); + materialList_[newIndex].key = _key; + + materialStrings_[newIndex] = materialString(materialList_[newIndex],newItem->text()); + saveNewName(newItem); + + shortKeyRow_[_key] = newIndex; +} +//------------------------------------------------------------------------------ +QString MaterialPicker::materialString(const MaterialInfo& _mat, const QString &_name) +{ + std::stringstream stream; + stream << _name.toStdString(); + stream << ";" << _mat.color_material; + stream << ";" << _mat.base_color; + stream << ";" << _mat.ambient_color; + stream << ";" << _mat.diffuse_color; + stream << ";" << _mat.specular_color; + stream << ";" << _mat.shininess; + stream << ";" << _mat.reflectance; + stream << ";" << _mat.key; + + return QString(stream.str().c_str()); +} +//------------------------------------------------------------------------------ +void MaterialPicker::slotMaterialProperties() +{ + if (materialNode_) + return; + + QListWidgetItem* item = materialListWidget_->currentItem(); + materialListWidget_->setDisabled(true); + + materialNode_.reset(new MaterialNode()); + int row = materialListWidget_->currentRow(); + materialNode_->colorMaterial(materialList_[row].color_material); + materialNode_->set_base_color(materialList_[row].base_color); + materialNode_->set_ambient_color(materialList_[row].ambient_color); + materialNode_->set_diffuse_color(materialList_[row].diffuse_color); + materialNode_->set_specular_color(materialList_[row].specular_color); + materialNode_->set_shininess(materialList_[row].shininess); + materialNode_->set_reflectance(materialList_[row].reflectance); + + ACG::QtWidgets::QtMaterialDialog* dialog = new ACG::QtWidgets::QtMaterialDialog( 0, materialNode_.get() ); + + dialog->setWindowFlags(dialog->windowFlags() | Qt::WindowStaysOnTopHint); + + connect(dialog,SIGNAL(finished(int)),this,SLOT(slotEnableListWidget(int))); + connect(dialog,SIGNAL(accepted()),this,SLOT(slotSaveAll())); + + dialog->setWindowIcon( QIcon(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"datacontrol-material.png")); + + dialog->show(); + +} +//------------------------------------------------------------------------------ +void MaterialPicker::slotSaveAll() +{ + if (materialNode_) + { + int index = materialListWidget_->currentRow(); + // store the material information + MaterialInfo materialInfo; + materialInfo.color_material = materialNode_->colorMaterial(); + materialInfo.base_color = materialNode_->base_color(); + materialInfo.ambient_color = materialNode_->ambient_color(); + materialInfo.diffuse_color = materialNode_->diffuse_color(); + materialInfo.specular_color = materialNode_->specular_color(); + materialInfo.shininess = materialNode_->shininess(); + materialInfo.reflectance = materialNode_->reflectance(); + materialInfo.key = materialList_[index].key; + QString name = plainName(materialListWidget_->currentItem()->text(),materialListWidget_->currentRow()); + materialStrings_[index] = materialString(materialInfo,name); + materialList_[index] = materialInfo; + OpenFlipperSettings().setValue(propName_, materialStrings_); + } + OpenFlipperSettings().setValue(propName_, materialStrings_); +} + +//------------------------------------------------------------------------------ +void MaterialPicker::slotEnableListWidget(int _save){ + materialListWidget_->setEnabled(true); + if (_save == QDialog::Accepted) + slotSaveAll(); + materialNode_.reset(); +} + +//------------------------------------------------------------------------------ +void MaterialPicker::createContextMenu(const QPoint& _point) +{ + QMenu *menu = new QMenu(materialListWidget_); + + QAction* action = menu->addAction(tr("Rename")); + connect(action,SIGNAL(triggered(bool)),this,SLOT(editModeCurrent())); + action = menu->addAction(tr("Material Properties")); + QIcon icon; + icon.addFile(OpenFlipper::Options::iconDirStr()+OpenFlipper::Options::dirSeparator()+"datacontrol-material.png"); + action->setIcon(icon); + action->setEnabled(true); + connect(action,SIGNAL(triggered(bool)),this,SLOT(slotMaterialProperties())); + + menu->addSeparator(); + + QSignalMapper* signalMapper = new QSignalMapper(menu); + for (unsigned i = 0; i < supportedKeys_; ++i) { - if (shortKeyRow_.find(Qt::Key_3) == shortKeyRow_.end()) - return; - slotFillMaterialMode(); - materialListWidget_->setCurrentRow(shortKeyRow_[Qt::Key_3]); + QAction* action = menu->addAction(tr("Key %1").arg(i+1)); + connect(action,SIGNAL(triggered(bool)),signalMapper,SLOT(map())); + signalMapper->setMapping(action,Qt::Key_1+i); + std::map::iterator iter = shortKeyRow_.find(Qt::Key_1+i); + if (iter != shortKeyRow_.end() && iter->second == static_cast(materialListWidget_->currentRow())) + action->setDisabled(true); } + + connect(signalMapper, SIGNAL(mapped(const int &)),this, SLOT(changeHotKey(const int &))); + menu->exec(materialListWidget_->mapToGlobal(_point),0); + + } Q_EXPORT_PLUGIN2( materialPicker , MaterialPicker ); diff --git a/MaterialPicker.hh b/MaterialPicker.hh index 021a5ce..78e1c4a 100644 --- a/MaterialPicker.hh +++ b/MaterialPicker.hh @@ -53,6 +53,7 @@ #include #include +#include class MaterialPicker : public QObject, BaseInterface, MouseInterface, PickingInterface, ToolboxInterface, KeyInterface @@ -100,24 +101,34 @@ private: ACG::Vec4f specular_color; float shininess; double reflectance; + int key; }; const std::string pickModeName_; const QString propName_; + static const unsigned supportedKeys_ = 3; QPushButton* pickMaterialButton_; QPushButton* fillMaterialButton_; - QListWidget* materialListWidget_; - QStringList materialString_;//hold materials as a String (saves/load the material at the beginning) + //all these lists are synchronized: + QListWidget* materialListWidget_; QVector materialList_; + QStringList materialStrings_;//hold materials as a String (saves/load the material at the beginning) + + //key = hotKey, value = index for lists std::map shortKeyRow_; + ptr::shared_ptr materialNode_; + /// stores the state of the pick material button bool pickMaterial_; /// stores the state of the fill material button bool fillMaterial_; +private: + QString itemName(const QString &_name, int _key); + private slots: void initializePlugin(); @@ -133,13 +144,34 @@ private slots: /// items can be renamed by double clicking them void editMode(QListWidgetItem* _item); - /// saves the new material name - void saveNewName(QListWidgetItem* _item); + void editModeCurrent(); + + /// saves the new material name with hotkey hint + void saveNewName ( QWidget * _editor, QAbstractItemDelegate::EndEditHint _hint ); + void saveNewName (QListWidgetItem* _item); + + /// returns the plain name of the material without hotkey hint (if setted) + QString plainName(const QString &string, int index); + + /// returns a formatted string for saving + QString materialString(const MaterialInfo& _mat, const QString &_name); void clearList(); void removeItem(QListWidgetItem* _item); + /// creates context menu on current item (current is the item at mouse position) + void createContextMenu(const QPoint& _point); + + /// change specified HotKey to current item + void changeHotKey(const int &_key); + + void slotMaterialProperties(); + + void slotEnableListWidget(int _save); + + void slotSaveAll(); + public slots: QString version(){ return QString("1.0"); } }; -- GitLab