File indexing completed on 2024-04-28 05:38:15
0001 /*************************************************************************** 0002 * Copyright (C) 2009 by Renaud Guezennec * 0003 * https://rolisteam.org/contact * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 0021 #include "userlistview.h" 0022 0023 #include <QColorDialog> 0024 #include <QDebug> 0025 #include <QDrag> 0026 #include <QHeaderView> 0027 #include <QMenu> 0028 #include <QMouseEvent> 0029 #include <QPainter> 0030 #include <memory> 0031 0032 #include "controller/view_controller/imageselectorcontroller.h" 0033 #include "rwidgets/dialogs/imageselectordialog.h" 0034 #include "userlistview.h" 0035 #include "worker/iohelper.h" 0036 #include "worker/utilshelper.h" 0037 0038 #include "controller/playercontroller.h" 0039 #include "data/character.h" 0040 #include "data/rolisteammimedata.h" 0041 #include "model/characterstatemodel.h" 0042 #include "model/playermodel.h" 0043 #include "preferences/preferencesmanager.h" 0044 #include <QInputDialog> 0045 0046 UserListView::UserListView(QWidget* parent) : QTreeView(parent) 0047 { 0048 setHeaderHidden(true); 0049 0050 // set action 0051 m_addAvatarAct= std::make_unique<QAction>(tr("Set Avatar..."), this); 0052 m_removeAvatarAct= std::make_unique<QAction>(tr("Remove..."), this); 0053 m_changeName= std::make_unique<QAction>(tr("Edit name"), this); 0054 m_changeColor= std::make_unique<QAction>(tr("Change color…"), this); 0055 0056 connect(m_addAvatarAct.get(), &QAction::triggered, this, &UserListView::addAvatar); 0057 connect(m_removeAvatarAct.get(), &QAction::triggered, this, &UserListView::deleteAvatar); 0058 connect(m_changeName.get(), &QAction::triggered, this, [this]() { edit(currentIndex()); }); 0059 connect(m_changeColor.get(), &QAction::triggered, this, &UserListView::editCurrentItemColor); 0060 0061 setIconSize(QSize(64, 64)); 0062 0063 std::vector<std::tuple<QString, QString, Type>> propertyList 0064 = {{"healthPoints", tr("Health Points"), Integer}, {"maxHP", tr("Health Points Maximum"), Integer}, 0065 {"minHP", tr("Health Points Minimum"), Integer}, {"distancePerTurn", tr("Distance per turn"), Real}, 0066 {"initCommand", tr("Initiative Command"), String}, {"hasInitiative", tr("Has initiative"), Boolean}, 0067 {"lifeColor", tr("Life bar color"), Color}}; 0068 0069 for(auto propertyName : propertyList) 0070 { 0071 auto act= new QAction(std::get<1>(propertyName), this); 0072 std::pair<QString, Type> pair(std::get<0>(propertyName), std::get<2>(propertyName)); 0073 if(std::get<2>(propertyName) == Boolean) 0074 act->setCheckable(true); 0075 0076 QVariant var; 0077 var.setValue(pair); 0078 act->setData(var); 0079 connect(act, &QAction::triggered, this, &UserListView::setPropertyValue); 0080 m_propertyActions.push_back(act); 0081 } 0082 } 0083 0084 void UserListView::setPlayerController(PlayerController* ctrl) 0085 { 0086 m_ctrl= ctrl; 0087 } 0088 0089 void UserListView::setState() 0090 { 0091 auto act= qobject_cast<QAction*>(sender()); 0092 if(nullptr == act) 0093 return; 0094 0095 auto index= currentIndex(); 0096 auto stateId= act->data().toString(); 0097 /*auto state= Character::getStateFromIndex(stateIdx); 0098 auto person= static_cast<Person*>(index.internalPointer()); 0099 auto tmpPlayer= dynamic_cast<Character*>(person); 0100 0101 if(nullptr == tmpPlayer || nullptr == state) 0102 return;*/ 0103 0104 model()->setData(index, stateId, PlayerModel::CharacterStateIdRole); 0105 0106 // tmpPlayer->setStateId(stateId); 0107 } 0108 0109 void UserListView::setPropertyValue() 0110 { 0111 auto act= qobject_cast<QAction*>(sender()); 0112 if(nullptr == act) 0113 return; 0114 0115 auto index= currentIndex(); 0116 QVariant value= act->data(); 0117 auto pair= value.value<std::pair<QString, Type>>(); 0118 auto person= static_cast<Person*>(index.internalPointer()); 0119 auto tmpperso= dynamic_cast<Character*>(person); 0120 0121 if(nullptr == tmpperso) 0122 return; 0123 0124 auto formerVal= tmpperso->property(pair.first.toLocal8Bit()); 0125 QVariant var; 0126 bool ok; 0127 0128 switch(pair.second) 0129 { 0130 case Boolean: 0131 var= !formerVal.toBool(); 0132 ok= true; 0133 break; 0134 case Integer: 0135 var= QInputDialog::getInt(this, tr("Get value for %1 property").arg(pair.first), tr("Value:"), 0136 formerVal.toInt(), -2147483647, 2147483647, 1, &ok); 0137 break; 0138 case Real: 0139 var= QInputDialog::getDouble(this, tr("Get value for %1 property").arg(pair.first), tr("Value:"), 0140 formerVal.toDouble(), -2147483647, 2147483647, 1, &ok); 0141 break; 0142 case String: 0143 var= QInputDialog::getText(this, tr("Get value for %1 property").arg(pair.first), tr("Value:"), 0144 QLineEdit::Normal, formerVal.toString(), &ok); 0145 break; 0146 case Color: 0147 var= QColorDialog::getColor(formerVal.value<QColor>(), this); 0148 ok= true; 0149 break; 0150 } 0151 0152 if(!ok) 0153 return; 0154 0155 tmpperso->setProperty(pair.first.toLocal8Bit(), var); 0156 } 0157 0158 void UserListView::mouseDoubleClickEvent(QMouseEvent* event) 0159 { 0160 QModelIndex tmp= indexAt(event->pos()); 0161 int indentationValue= indentation(); 0162 int icon= 0; 0163 if(iconSize().isValid()) 0164 icon= iconSize().width(); 0165 else 0166 icon= indentationValue; 0167 0168 if(tmp.isValid()) 0169 { 0170 event->pos(); 0171 int depth= 1; 0172 while(tmp.parent().isValid()) 0173 { 0174 depth++; 0175 tmp= tmp.parent(); 0176 } 0177 if((depth * indentationValue < event->pos().x()) && ((depth)*indentationValue + icon >= event->pos().x())) 0178 { 0179 editCurrentItemColor(); 0180 } 0181 else 0182 QTreeView::mouseDoubleClickEvent(event); 0183 } 0184 else 0185 QTreeView::mouseDoubleClickEvent(event); 0186 } 0187 0188 void UserListView::contextMenuEvent(QContextMenuEvent* e) 0189 { 0190 QModelIndex index= indexAt(e->pos()); 0191 if(!index.isValid()) 0192 return; 0193 0194 setCurrentIndex(index); 0195 0196 auto tmpperso= index.data(PlayerModel::PersonPtrRole).value<Person*>(); 0197 0198 auto flags= index.flags(); 0199 0200 if(!(flags & Qt::ItemIsEditable) || tmpperso == nullptr) 0201 return; 0202 0203 auto uuid= tmpperso->uuid(); 0204 auto charact= dynamic_cast<Character*>(tmpperso); 0205 QMenu popMenu(this); 0206 0207 /*if(nullptr != charact) 0208 { 0209 auto initCmd= charact->getInitCommand(); 0210 if(!initCmd.isEmpty()) 0211 { 0212 //auto act= popMenu.addAction(tr("Roll initiative")); 0213 connect(act, &QAction::triggered, this, [this, initCmd, charact]() { 0214 if(m_diceParser->parseLine(initCmd)) 0215 { 0216 m_diceParser->start(); 0217 auto valueList= m_diceParser->getSumOfDiceResult(); 0218 if(valueList.isEmpty()) 0219 return; 0220 0221 charact->setInitiativeScore(static_cast<int>(valueList.first())) 0222 } 0223 }); 0224 } 0225 }*/ 0226 0227 popMenu.addAction(m_changeName.get()); 0228 popMenu.addAction(m_changeColor.get()); 0229 popMenu.addSeparator(); 0230 popMenu.addAction(m_addAvatarAct.get()); 0231 popMenu.addAction(m_removeAvatarAct.get()); 0232 popMenu.addSeparator(); 0233 if(nullptr != charact) 0234 { 0235 popMenu.addSeparator(); 0236 auto menu= popMenu.addMenu(tr("Set Property")); 0237 for(auto pro : m_propertyActions) 0238 { 0239 if(pro->isCheckable()) 0240 { 0241 auto data= pro->data().value<std::pair<QString, Type>>(); 0242 pro->setChecked(tmpperso->property(data.first.toLocal8Bit()).toBool()); 0243 } 0244 menu->addAction(pro); 0245 } 0246 0247 auto stateModel= m_ctrl->characterStateModel(); 0248 if(stateModel) 0249 { 0250 auto stateMenu= popMenu.addMenu(tr("State")); 0251 for(int i= 0; i < stateModel->rowCount(); ++i) 0252 { 0253 auto label= stateModel->index(i, 0).data(CharacterStateModel::LABEL).toString(); 0254 auto id= stateModel->index(i, 0).data(CharacterStateModel::ID).toString(); 0255 0256 auto act= stateMenu->addAction(label); 0257 act->setCheckable(true); 0258 auto stateIdPerson= charact->stateId(); 0259 act->setChecked(id == stateIdPerson); 0260 act->setData(id); 0261 connect(act, &QAction::triggered, this, &UserListView::setState); 0262 } 0263 0264 popMenu.addSeparator(); 0265 } 0266 auto actionList= charact->actionList(); 0267 if(!actionList.isEmpty()) 0268 { 0269 auto actionMenu= popMenu.addMenu(tr("Action")); 0270 for(auto action : actionList) 0271 { 0272 auto act= actionMenu->addAction(action->name()); 0273 connect(act, &QAction::triggered, this, 0274 [this, &action, uuid]() { emit runDiceForCharacter(action->command(), uuid); }); 0275 } 0276 } 0277 0278 auto shapeList= charact->shapeList(); 0279 if(!shapeList.isEmpty()) 0280 { 0281 auto shapeMenu= popMenu.addMenu(tr("Shape")); 0282 for(auto shape : shapeList) 0283 { 0284 auto act= shapeMenu->addAction(shape->name()); 0285 act->setCheckable(true); 0286 act->setChecked(charact->currentShape() == shape); 0287 connect(act, &QAction::triggered, this, 0288 [&charact, shape]() 0289 { 0290 if(charact->currentShape() == shape) 0291 charact->setCurrentShape(nullptr); 0292 else 0293 charact->setCurrentShape(shape); 0294 }); 0295 } 0296 } 0297 } 0298 popMenu.exec(e->globalPos()); 0299 } 0300 0301 void UserListView::addAvatar() 0302 { 0303 /// @TODO: Here! options manager is required to get access to the photo directory 0304 PreferencesManager* m_preferencesManager= PreferencesManager::getInstance(); 0305 QString directory("."); 0306 if(nullptr != m_preferencesManager) 0307 { 0308 directory= m_preferencesManager->value("imageDirectory", QDir::homePath()).toString(); 0309 } 0310 ImageSelectorController ctrl(false, ImageSelectorController::All, ImageSelectorController::Square); 0311 ImageSelectorDialog dialog(&ctrl, this); 0312 if(QDialog::Accepted != dialog.exec()) 0313 return; 0314 0315 QModelIndex index= currentIndex(); 0316 auto data= ctrl.finalImageData(); 0317 if(!index.isValid() || data.isEmpty()) 0318 return; 0319 0320 Person* tmpperso= static_cast<Person*>(index.internalPointer()); 0321 if(tmpperso) 0322 tmpperso->setAvatar(data); 0323 } 0324 0325 void UserListView::deleteAvatar() 0326 { 0327 QModelIndex index= currentIndex(); 0328 if(index.isValid()) 0329 { 0330 Person* tmpperso= static_cast<Person*>(index.internalPointer()); 0331 if(tmpperso) 0332 tmpperso->setAvatar({}); 0333 } 0334 } 0335 void UserListView::editCurrentItemColor() 0336 { 0337 QModelIndex index= currentIndex(); 0338 0339 if(!index.isValid()) 0340 return; 0341 0342 QVariant valueVar= index.data(Qt::DecorationRole); 0343 0344 QColor color= QColorDialog::getColor(valueVar.value<QColor>(), this); 0345 0346 if(color.isValid()) 0347 { 0348 model()->setData(index, QVariant(color), Qt::DecorationRole); 0349 } 0350 } 0351 0352 void UserListView::mouseMoveEvent(QMouseEvent* event) 0353 { 0354 QModelIndex tmp= indexAt(event->pos()); 0355 0356 QTreeView::mousePressEvent(event); 0357 0358 if((event->buttons() == Qt::LeftButton) && (tmp.isValid())) 0359 { 0360 Person* tmpperso= static_cast<Person*>(tmp.internalPointer()); 0361 if(nullptr != tmpperso) 0362 { 0363 QDrag* drag= new QDrag(this); 0364 RolisteamMimeData* mimeData= new RolisteamMimeData(); 0365 0366 mimeData->setPerson(tmpperso); 0367 drag->setMimeData(mimeData); 0368 drag->setPixmap(helper::utils::roundCornerImage(IOHelper::dataToPixmap(tmpperso->avatar()))); 0369 drag->exec(); 0370 } 0371 } 0372 } 0373 /*QPixmap UserListView::generateAvatar(Person* p) 0374 { 0375 int diameter= 80; 0376 QPixmap img(diameter, diameter); 0377 img.fill(Qt::transparent); 0378 QPainter painter(&img); 0379 QBrush brush; 0380 if(p->avatar().isNull()) 0381 { 0382 painter.setPen(p->getColor()); 0383 brush.setColor(p->getColor()); 0384 brush.setStyle(Qt::SolidPattern); 0385 } 0386 else 0387 { 0388 QImage img= IOHelper::dataToImage(p->avatar()); 0389 brush.setTextureImage(img.scaled(diameter, diameter)); 0390 } 0391 0392 painter.setBrush(brush); 0393 painter.drawRoundedRect(0, 0, diameter, diameter, diameter / 10, diameter / 10); 0394 0395 return img; 0396 }*/