/*************************************************************************** * Copyright (c) 2004 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include # include # include # include # include # include # include # include # include # include # include #endif #include "DlgActionsImp.h" #include "ui_DlgActions.h" #include "Action.h" #include "Application.h" #include "Command.h" #include "BitmapFactory.h" #include "Widgets.h" #include "ui_DlgChooseIcon.h" using namespace Gui::Dialog; /* TRANSLATOR Gui::Dialog::DlgCustomActionsImp */ /** * Constructs a DlgCustomActionsImp which is a child of 'parent', with the * name 'name' and widget flags set to 'f' * * The dialog will by default be modeless, unless you set 'modal' to * true to construct a modal dialog. */ DlgCustomActionsImp::DlgCustomActionsImp( QWidget* parent ) : CustomizeActionPage(parent) , ui(new Ui_DlgCustomActions) , bShown(false) { ui->setupUi(this); // search for all macros std::string cMacroPath = App::GetApplication(). GetParameterGroupByPath("User parameter:BaseApp/Preferences/Macro") ->GetASCII("MacroPath",App::Application::getUserMacroDir().c_str()); QDir d(QString::fromUtf8(cMacroPath.c_str()), QLatin1String("*.FCMacro *.py")); for (unsigned int i=0; iactionMacros->insertItem(0,d[i],QVariant(false)); QString systemMacroDirStr = QString::fromUtf8(App::GetApplication().getHomePath()) + QString::fromUtf8("Macro"); d = QDir(systemMacroDirStr, QLatin1String("*.FCMacro *.py")); if (d.exists()) { for (unsigned int i=0; iactionMacros->insertItem(0,d[i],QVariant(true)); } } QStringList labels; labels << tr("Icons") << tr("Macros"); ui->actionListWidget->setHeaderLabels(labels); ui->actionListWidget->header()->hide(); ui->actionListWidget->setIconSize(QSize(32, 32)); #if QT_VERSION >= 0x050000 ui->actionListWidget->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); #else ui->actionListWidget->header()->setResizeMode(0, QHeaderView::ResizeToContents); #endif showActions(); } /** Destroys the object and frees any allocated resources */ DlgCustomActionsImp::~DlgCustomActionsImp() { } /** * Displays this page. If no macros were found a message box * appears. */ void DlgCustomActionsImp::showEvent(QShowEvent* e) { QWidget::showEvent(e); if (ui->actionMacros->count() == 0 && bShown == false) { bShown = true; QMessageBox::warning(this, tr("No macro"),tr("No macros found.")); } } bool DlgCustomActionsImp::event(QEvent* e) { bool ok = QWidget::event(e); if (e->type() == QEvent::ParentChange || e->type() == QEvent::ParentAboutToChange) { QWidget* topLevel = this->parentWidget(); while (topLevel && !topLevel->inherits("QDialog")) topLevel = topLevel->parentWidget(); if ( topLevel ) { int index = topLevel->metaObject()->indexOfSignal( QMetaObject::normalizedSignature("addMacroAction(const QByteArray&)") ); if ( index >= 0 ) { if ( e->type() == QEvent::ParentChange ) { connect(this, SIGNAL(addMacroAction( const QByteArray& )), topLevel, SIGNAL(addMacroAction( const QByteArray& ))); connect(this, SIGNAL(removeMacroAction( const QByteArray& )), topLevel, SIGNAL(removeMacroAction( const QByteArray& ))); connect(this, SIGNAL(modifyMacroAction( const QByteArray& )), topLevel, SIGNAL(modifyMacroAction( const QByteArray& ))); } else { disconnect(this, SIGNAL(addMacroAction( const QByteArray& )), topLevel, SIGNAL(addMacroAction( const QByteArray& ))); disconnect(this, SIGNAL(removeMacroAction( const QByteArray& )), topLevel, SIGNAL(removeMacroAction( const QByteArray& ))); disconnect(this, SIGNAL(modifyMacroAction( const QByteArray& )), topLevel, SIGNAL(modifyMacroAction( const QByteArray& ))); } } } } return ok; } void DlgCustomActionsImp::onAddMacroAction(const QByteArray&) { // does nothing } void DlgCustomActionsImp::onRemoveMacroAction(const QByteArray&) { // does nothing } void DlgCustomActionsImp::onModifyMacroAction(const QByteArray&) { // does nothing } void DlgCustomActionsImp::showActions() { CommandManager& rclMan = Application::Instance->commandManager(); std::vector aclCurMacros = rclMan.getGroupCommands("Macros"); for (std::vector::iterator it = aclCurMacros.begin(); it != aclCurMacros.end(); ++it) { QTreeWidgetItem* item = new QTreeWidgetItem(ui->actionListWidget); QByteArray actionName = (*it)->getName(); item->setData(1, Qt::UserRole, actionName); item->setText(1, QString::fromUtf8((*it)->getMenuText())); item->setSizeHint(0, QSize(32, 32)); if ( (*it)->getPixmap() ) item->setIcon(0, BitmapFactory().pixmap((*it)->getPixmap())); } } void DlgCustomActionsImp::on_actionListWidget_itemActivated(QTreeWidgetItem *item) { if (!item) return; // no valid item // search for the command in the manager and if necessary in the temporary created ones QByteArray actionName = item->data(1, Qt::UserRole).toByteArray(); CommandManager& rclMan = Application::Instance->commandManager(); Command* pCmd = rclMan.getCommandByName(actionName.constData()); MacroCommand* pScript = dynamic_cast(pCmd); // if valid command if ( pScript ) { bool bFound = false; QString scriptName = QString::fromUtf8(pScript->getScriptName()); for (int i = 0; iactionMacros->count(); i++) { if (ui->actionMacros->itemText(i).startsWith(scriptName, Qt::CaseSensitive)) { bFound = true; ui->actionMacros->setCurrentIndex(i); break; } } if (!bFound) { QMessageBox::critical(this, tr("Macro not found"), tr("Sorry, couldn't find macro file '%1'.").arg(scriptName)); } // fill up labels with the command's data ui->actionWhatsThis -> setText(QString::fromUtf8(pScript->getWhatsThis())); ui->actionMenu -> setText(QString::fromUtf8(pScript->getMenuText())); ui->actionToolTip -> setText(QString::fromUtf8(pScript->getToolTipText())); ui->actionStatus -> setText(QString::fromUtf8(pScript->getStatusTip())); ui->actionAccel -> setText(QString::fromLatin1(pScript->getAccel())); ui->pixmapLabel->clear(); m_sPixmap.clear(); const char* name = pScript->getPixmap(); if (name && std::strlen(name) > 2) { QPixmap p = Gui::BitmapFactory().pixmap(pScript->getPixmap()); ui->pixmapLabel->setPixmap(p); m_sPixmap = QString::fromUtf8(name); // can also be a path } } } void DlgCustomActionsImp::on_buttonAddAction_clicked() { if (ui->actionMacros-> currentText().isEmpty()) { QMessageBox::warning(this, tr("Empty macro"),tr("Please specify the macro first.")); return; } if (ui->actionMenu->text().isEmpty()) { QMessageBox::warning(this, tr("Empty text"),tr("Please specify the menu text first.")); return; } // search for the command in the manager QByteArray actionName = newActionName().toLatin1(); CommandManager& rclMan = Application::Instance->commandManager(); MacroCommand* macro = new MacroCommand(actionName, ui->actionMacros->itemData(ui->actionMacros->currentIndex()).toBool()); rclMan.addCommand( macro ); // add new action QTreeWidgetItem* item = new QTreeWidgetItem(ui->actionListWidget); item->setData(1, Qt::UserRole, actionName); item->setText(1, ui->actionMenu->text()); item->setSizeHint(0, QSize(32, 32)); #if QT_VERSION >= QT_VERSION_CHECK(5,15,0) item->setIcon(0, ui->pixmapLabel->pixmap(Qt::ReturnByValue)); #else if (ui->pixmapLabel->pixmap()) item->setIcon(0, *ui->pixmapLabel->pixmap()); #endif // Convert input text into utf8 if (!ui->actionWhatsThis->text().isEmpty()) macro->setWhatsThis(ui->actionWhatsThis->text().toUtf8()); ui->actionWhatsThis->clear(); if (!ui->actionMacros-> currentText().isEmpty()) macro->setScriptName(ui->actionMacros->currentText().toUtf8()); if (!ui->actionMenu->text().isEmpty()) macro->setMenuText(ui->actionMenu->text().toUtf8()); ui->actionMenu->clear(); if (!ui->actionToolTip->text().isEmpty()) macro->setToolTipText(ui->actionToolTip->text().toUtf8()); ui->actionToolTip->clear(); if (!ui->actionStatus->text().isEmpty()) macro->setStatusTip(ui->actionStatus->text().toUtf8()); ui->actionStatus->clear(); if (!m_sPixmap.isEmpty()) macro->setPixmap(m_sPixmap.toLatin1()); ui->pixmapLabel->clear(); m_sPixmap.clear(); if (!ui->actionAccel->text().isEmpty()) { macro->setAccel(ui->actionAccel->text().toLatin1()); } ui->actionAccel->clear(); // emit signal to notify the container widget addMacroAction(actionName); } void DlgCustomActionsImp::on_buttonReplaceAction_clicked() { QTreeWidgetItem* item = ui->actionListWidget->currentItem(); if (!item) { QMessageBox::warning(this, tr("No item selected"),tr("Please select a macro item first.")); return; } if (ui->actionMenu->text().isEmpty()) { QMessageBox::warning(this, tr("Empty text"),tr("Please specify the menu text first.")); return; } // search for the command in the manager QByteArray actionName = item->data(1, Qt::UserRole).toByteArray(); item->setText(1, ui->actionMenu->text()); CommandManager& rclMan = Application::Instance->commandManager(); Command* pCmd = rclMan.getCommandByName(actionName.constData()); MacroCommand* macro = dynamic_cast(pCmd); if (!macro) return; if (!ui->actionWhatsThis->text().isEmpty()) macro->setWhatsThis(ui->actionWhatsThis->text().toUtf8()); ui->actionWhatsThis->clear(); if (!ui->actionMacros-> currentText().isEmpty()) macro->setScriptName(ui->actionMacros->currentText().toUtf8()); if (!ui->actionMenu->text().isEmpty()) macro->setMenuText(ui->actionMenu->text().toUtf8()); ui->actionMenu->clear(); if (!ui->actionToolTip->text().isEmpty()) macro->setToolTipText(ui->actionToolTip->text().toUtf8()); ui->actionToolTip->clear(); if (!ui->actionStatus->text().isEmpty()) macro->setStatusTip(ui->actionStatus->text().toUtf8()); ui->actionStatus->clear(); if (!m_sPixmap.isEmpty()) macro->setPixmap(m_sPixmap.toLatin1()); ui->pixmapLabel->clear(); m_sPixmap.clear(); if (!ui->actionAccel->text().isEmpty()) { macro->setAccel(ui->actionAccel->text().toLatin1()); } ui->actionAccel->clear(); // check whether the macro is already in use Action* action = macro->getAction(); if (action) { // does all the text related stuff action->setText(QString::fromUtf8(macro->getMenuText())); action->setToolTip(QString::fromUtf8(macro->getToolTipText())); action->setWhatsThis(QString::fromUtf8(macro->getWhatsThis())); action->setStatusTip(QString::fromUtf8(macro->getStatusTip())); if (macro->getPixmap()) action->setIcon(Gui::BitmapFactory().pixmap(macro->getPixmap())); action->setShortcut(QString::fromLatin1(macro->getAccel())); QString accel = action->shortcut().toString(QKeySequence::NativeText); if (!accel.isEmpty()) { // show shortcut inside tooltip QString ttip = QString::fromLatin1("%1 (%2)") .arg(action->toolTip(), accel); action->setToolTip(ttip); // show shortcut inside status tip QString stip = QString::fromLatin1("(%1)\t%2") .arg(accel, action->statusTip()); action->setStatusTip(stip); } } // emit signal to notify the container widget modifyMacroAction(actionName); // call this at the end because it internally invokes the highlight method if (macro->getPixmap()) item->setIcon(0, Gui::BitmapFactory().pixmap(macro->getPixmap())); } void DlgCustomActionsImp::on_buttonRemoveAction_clicked() { // remove item from list view QTreeWidgetItem* item = ui->actionListWidget->currentItem(); if (!item) return; int current = ui->actionListWidget->indexOfTopLevelItem(item); ui->actionListWidget->takeTopLevelItem(current); QByteArray actionName = item->data(1, Qt::UserRole).toByteArray(); delete item; // if the command is registered in the manager just remove it CommandManager& rclMan = Application::Instance->commandManager(); std::vector aclCurMacros = rclMan.getGroupCommands("Macros"); for (std::vector::iterator it2 = aclCurMacros.begin(); it2!= aclCurMacros.end(); ++it2) { if (actionName == (*it2)->getName()) { // emit signal to notify the container widget removeMacroAction(actionName); // remove from manager and delete it immediately rclMan.removeCommand(*it2); break; } } } IconDialog::IconDialog(QWidget* parent) : QDialog(parent), ui(new Ui_DlgChooseIcon) { ui->setupUi(this); ui->listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // signals and slots connections connect(ui->listWidget, SIGNAL(itemClicked (QListWidgetItem *)), this, SLOT(accept())); connect(ui->addButton, SIGNAL(clicked()), this, SLOT(onAddIconPath())); QListWidgetItem* item; QStringList names = BitmapFactory().findIconFiles(); for (QStringList::Iterator it = names.begin(); it != names.end(); ++it) { item = new QListWidgetItem(ui->listWidget); //item->setIcon(QIcon(*it)); item->setIcon(QIcon(BitmapFactory().pixmap((const char*)it->toUtf8()))); item->setText(QFileInfo(*it).baseName()); item->setToolTip(*it); } } IconDialog::~IconDialog() { delete ui; } QListWidgetItem* IconDialog::currentItem() const { return ui->listWidget->currentItem(); } void IconDialog::resizeEvent(QResizeEvent*) { ui->listWidget->setFlow(QListView::LeftToRight); } void IconDialog::onAddIconPath() { // Add the user defined paths Base::Reference group = App::GetApplication().GetParameterGroupByPath ("User parameter:BaseApp/Preferences/Bitmaps"); std::vector paths = group->GetASCIIs("CustomPath"); QStringList pathList; for (std::vector::iterator it = paths.begin(); it != paths.end(); ++it) pathList << QString::fromUtf8(it->c_str()); IconFolders dlg(pathList, this); dlg.setWindowTitle(tr("Icon folders")); if (dlg.exec()) { QStringList paths = dlg.getPaths(); // Write to user config group->Clear(); int index=0; for (QStringList::iterator it = paths.begin(); it != paths.end(); ++it, ++index) { std::stringstream str; str << "CustomPath" << index; group->SetASCII(str.str().c_str(), (const char*)it->toUtf8()); } QStringList search = BitmapFactory().getPaths(); for (QStringList::iterator it = search.begin(); it != search.end(); ++it) { *it = QDir::toNativeSeparators(*it); } for (QStringList::iterator it = paths.begin(); it != paths.end(); ++it) { if (search.indexOf(*it) < 0) { QStringList filters; QList formats = QImageReader::supportedImageFormats(); for (QList::iterator jt = formats.begin(); jt != formats.end(); ++jt) filters << QString::fromLatin1("*.%1").arg(QString::fromLatin1(*jt).toLower()); QDir d(*it); d.setNameFilters(filters); QFileInfoList fi = d.entryInfoList(); for (QFileInfoList::iterator jt = fi.begin(); jt != fi.end(); ++jt) { QListWidgetItem* item; QString file = jt->absoluteFilePath(); item = new QListWidgetItem(ui->listWidget); item->setIcon(QIcon(file)); item->setText(jt->baseName()); item->setToolTip(file); } BitmapFactory().addPath(*it); } } } } void DlgCustomActionsImp::on_buttonChoosePixmap_clicked() { // create a dialog showing all pixmaps Gui::Dialog::IconDialog dlg(this); dlg.setModal(true); dlg.exec(); ui->pixmapLabel->clear(); m_sPixmap.clear(); if (dlg.result() == QDialog::Accepted) { QListWidgetItem* item = dlg.currentItem(); if (item) { m_sPixmap = item->text(); ui->pixmapLabel->setPixmap(item->icon().pixmap(QSize(32,32))); } } } QString DlgCustomActionsImp::newActionName() { int id = 0; QString sName; bool bUsed; CommandManager& rclMan = Application::Instance->commandManager(); std::vector aclCurMacros = rclMan.getGroupCommands("Macros"); do { bUsed = false; sName = QString::fromLatin1("Std_Macro_%1").arg( id++ ); std::vector::iterator it; for ( it = aclCurMacros.begin(); it!= aclCurMacros.end(); ++it ) { if (sName == QLatin1String((*it)->getName())) { bUsed = true; break; } } } while ( bUsed ); return sName; } void DlgCustomActionsImp::changeEvent(QEvent *e) { if (e->type() == QEvent::LanguageChange) { ui->retranslateUi(this); ui->actionListWidget->clear(); showActions(); ui->actionAccel->setText(qApp->translate("Gui::AccelLineEdit", "none")); } QWidget::changeEvent(e); } IconFolders::IconFolders(const QStringList& paths, QWidget* parent) : QDialog(parent), restart(false), maxLines(10) { resize(600,400); QDialogButtonBox* buttonBox = new QDialogButtonBox(this); buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); gridLayout = new QGridLayout(); QGridLayout* mainLayout = new QGridLayout(this); mainLayout->addLayout(gridLayout, 0, 0, 1, 1); QSpacerItem* verticalSpacer = new QSpacerItem(20, 108, QSizePolicy::Minimum, QSizePolicy::Expanding); mainLayout->addItem(verticalSpacer, 1, 0, 1, 1); mainLayout->addWidget(buttonBox, 2, 0, 1, 1); // Add the user defined paths int numPaths = static_cast(paths.size()); int maxRow = this->maxLines; for (int row=0; rowsetReadOnly(true); gridLayout->addWidget(edit, row, 0, 1, 1); QPushButton* removeButton = new QPushButton(this); removeButton->setIcon(BitmapFactory().iconFromTheme("list-remove")); gridLayout->addWidget(removeButton, row, 1, 1, 1); if (row < numPaths) { edit->setText(paths[row]); } else { edit->hide(); removeButton->hide(); } buttonMap.append(qMakePair(edit, removeButton)); connect(removeButton, SIGNAL(clicked()), this, SLOT(removeFolder())); } textLabel = new QLabel(this); textLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum); textLabel->setText(tr("Add or remove custom icon folders")); addButton = new QPushButton(this); addButton->setIcon(BitmapFactory().iconFromTheme("list-add")); gridLayout->addWidget(textLabel, maxRow, 0, 1, 1); gridLayout->addWidget(addButton, maxRow, 1, 1, 1); connect(addButton, SIGNAL(clicked()), this, SLOT(addFolder())); if (numPaths >= this->maxLines) addButton->setDisabled(true); } IconFolders::~IconFolders() { } void IconFolders::addFolder() { int countHidden = -1; QStringList paths; for (QList< QPair >::iterator it = buttonMap.begin(); it != buttonMap.end(); ++it) { if (it->first->isHidden()) { countHidden++; if (countHidden == 0) { QString dir = QFileDialog::getExistingDirectory(this, IconDialog::tr("Add icon folder"), QString()); if (!dir.isEmpty() && paths.indexOf(dir) < 0) { QLineEdit* edit = it->first; edit->setVisible(true); edit->setText(dir); QPushButton* removeButton = it->second; removeButton->setVisible(true); } } } else { paths << QDir::toNativeSeparators(it->first->text()); } } if (countHidden <= 0) { addButton->setDisabled(true); } } void IconFolders::removeFolder() { if (!restart) { restart = true; QMessageBox::information(this, tr("Remove folder"), tr("Removing a folder only takes effect after an application restart.")); } addButton->setEnabled(true); QPushButton* remove = static_cast(sender()); QLineEdit* edit = 0; for (QList< QPair >::iterator it = buttonMap.begin(); it != buttonMap.end(); ++it) { if (it->second == remove) { edit = it->first; } else if (edit) { // move up the text of the line edits edit->setText(it->first->text()); if (it->first->isVisible()) { edit = it->first; remove = it->second; } else { edit->hide(); remove->hide(); break; } } } } QStringList IconFolders::getPaths() const { QStringList paths; for (QList< QPair >::const_iterator it = buttonMap.begin(); it != buttonMap.end(); ++it) { if (!it->first->isHidden()) { paths << QDir::toNativeSeparators(it->first->text()); } else { break; } } return paths; } #include "moc_DlgActionsImp.cpp"