diff --git a/src/Gui/Action.cpp b/src/Gui/Action.cpp
index 38bae0cf59..f388e9ee91 100644
--- a/src/Gui/Action.cpp
+++ b/src/Gui/Action.cpp
@@ -44,11 +44,16 @@
#include
#include "Action.h"
#include "Application.h"
+#include "BitmapFactory.h"
#include "Command.h"
#include "DlgUndoRedo.h"
#include "DlgWorkbenchesImp.h"
+#include "Document.h"
+#include "EditorView.h"
#include "FileDialog.h"
+#include "Macro.h"
#include "MainWindow.h"
+#include "PythonEditor.h"
#include "WhatsThis.h"
#include "Widgets.h"
#include "Workbench.h"
@@ -818,6 +823,195 @@ void RecentFilesAction::save()
// --------------------------------------------------------------------
+/* TRANSLATOR Gui::RecentMacrosAction */
+
+RecentMacrosAction::RecentMacrosAction ( Command* pcCmd, QObject * parent )
+ : ActionGroup( pcCmd, parent ), visibleItems(4), maximumItems(20)
+{
+ restore();
+}
+
+RecentMacrosAction::~RecentMacrosAction()
+{
+}
+
+/** Adds the new item to the recent files. */
+void RecentMacrosAction::appendFile(const QString& filename)
+{
+ // restore the list of recent files
+ QStringList files = this->files();
+
+ // if already inside remove and prepend it
+ files.removeAll(filename);
+ files.prepend(filename);
+ setFiles(files);
+ save();
+
+ // update the XML structure and save the user parameter to disk (#0001989)
+ bool saveParameter = App::GetApplication().GetParameterGroupByPath
+ ("User parameter:BaseApp/Preferences/General")->GetBool("SaveUserParameter", true);
+ if (saveParameter) {
+ ParameterManager* parmgr = App::GetApplication().GetParameterSet("User parameter");
+ parmgr->SaveDocument(App::Application::Config()["UserParameter"].c_str());
+ }
+}
+
+/**
+ * Set the list of recent macro files. For each item an action object is
+ * created and added to this action group.
+ */
+void RecentMacrosAction::setFiles(const QStringList& files)
+{
+ ParameterGrp::handle hGrp = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
+ ->GetGroup("Preferences")->GetGroup("RecentMacros");
+ this->shortcut_modifiers = hGrp->GetASCII("ShortcutModifiers","Ctrl+Shift+");
+ this->shortcut_count = std::min(hGrp->GetInt("ShortcutCount",3),9);//max = 9, e.g. Ctrl+Shift+9
+ this->visibleItems = hGrp->GetInt("RecentMacros",12);
+ QList recentFiles = _group->actions();
+
+ int numRecentFiles = std::min(recentFiles.count(), files.count());
+ for (int index = 0; index < numRecentFiles; index++) {
+ QFileInfo fi(files[index]);
+ QString accel = tr(QString::fromLatin1(shortcut_modifiers.c_str())\
+ .append(QString::number(index+1,10)).toStdString().c_str());
+ recentFiles[index]->setText(QString::fromLatin1("%1 %2").arg(index+1).arg(fi.baseName()));
+ recentFiles[index]->setStatusTip(tr("Run macro %1 (Shift+click to edit) shortcut: %2").arg(files[index]).arg(accel));
+ recentFiles[index]->setToolTip(files[index]); // set the full name that we need later for saving
+ recentFiles[index]->setData(QVariant(index));
+ if (index < shortcut_count){
+ recentFiles[index]->setShortcut(accel);
+ }
+ recentFiles[index]->setVisible(true);
+ }
+
+ // if less file names than actions
+ numRecentFiles = std::min(numRecentFiles, this->visibleItems);
+ for (int index = numRecentFiles; index < recentFiles.count(); index++) {
+ recentFiles[index]->setVisible(false);
+ recentFiles[index]->setText(QString());
+ recentFiles[index]->setToolTip(QString());
+ }
+}
+
+/**
+ * Returns the list of defined recent files.
+ */
+QStringList RecentMacrosAction::files() const
+{
+ QStringList files;
+ QList recentFiles = _group->actions();
+ for (int index = 0; index < recentFiles.count(); index++) {
+ QString file = recentFiles[index]->toolTip();
+ if (file.isEmpty())
+ break;
+ files.append(file);
+ }
+
+ return files;
+}
+
+void RecentMacrosAction::activateFile(int id)
+{
+ // restore the list of recent files
+ QStringList files = this->files();
+ if (id < 0 || id >= files.count())
+ return; // no valid item
+
+ QString filename = files[id];
+ QFileInfo fi(filename);
+ if (!fi.exists() || !fi.isFile()) {
+ QMessageBox::critical(getMainWindow(), tr("File not found"), tr("The file '%1' cannot be opened.").arg(filename));
+ files.removeAll(filename);
+ setFiles(files);
+ }
+ else {
+ if (QApplication::keyboardModifiers() == Qt::ShiftModifier){ //open for editing on Shift+click
+ PythonEditor* editor = new PythonEditor();
+ editor->setWindowIcon(Gui::BitmapFactory().iconFromTheme("applications-python"));
+ PythonEditorView* edit = new PythonEditorView(editor, getMainWindow());
+ edit->setDisplayName(PythonEditorView::FileName);
+ edit->open(filename);
+ edit->resize(400, 300);
+ getMainWindow()->addWindow(edit);
+ getMainWindow()->appendRecentMacro(filename);
+ edit->setWindowTitle(fi.fileName());
+ } else { //execute macro on normal (non-shifted) click
+ try {
+ getMainWindow()->appendRecentMacro(fi.filePath());
+ Application::Instance->macroManager()->run(Gui::MacroManager::File, fi.filePath().toUtf8());
+ // after macro run recalculate the document
+ if (Application::Instance->activeDocument())
+ Application::Instance->activeDocument()->getDocument()->recompute();
+ }
+ catch (const Base::SystemExitException&) {
+ // handle SystemExit exceptions
+ Base::PyGILStateLocker locker;
+ Base::PyException e;
+ e.ReportException();
+ }
+ }
+ }
+}
+
+void RecentMacrosAction::resizeList(int size)
+{
+ this->visibleItems = size;
+ int diff = this->visibleItems - this->maximumItems;
+ // create new items if needed
+ for (int i=0; iaddAction(QLatin1String(""))->setVisible(false);
+ setFiles(files());
+}
+
+/** Loads all recent files from the preferences. */
+void RecentMacrosAction::restore()
+{
+ ParameterGrp::handle hGrp = App::GetApplication().GetUserParameter().GetGroup("BaseApp")->GetGroup("Preferences");
+ if (hGrp->HasGroup("RecentMacros")) {
+ hGrp = hGrp->GetGroup("RecentMacros");
+ // we want at least 20 items but we do only show the number of files
+ // that is defined in user parameters
+ this->visibleItems = hGrp->GetInt("RecentMacros", this->visibleItems);
+ this->shortcut_count = hGrp->GetInt("ShortcutCount", 3); // number of shortcuts
+ this->shortcut_modifiers = hGrp->GetASCII("ShortcutModifiers","Ctrl+Shift+");
+ }
+
+ int count = std::max(this->maximumItems, this->visibleItems);
+ for (int i=0; iaddAction(QLatin1String(""))->setVisible(false);
+ std::vector MRU = hGrp->GetASCIIs("MRU");
+ QStringList files;
+ for (std::vector::iterator it = MRU.begin(); it!=MRU.end();++it)
+ files.append(QString::fromUtf8(it->c_str()));
+ setFiles(files);
+}
+
+/** Saves all recent files to the preferences. */
+void RecentMacrosAction::save()
+{
+ ParameterGrp::handle hGrp = App::GetApplication().GetUserParameter().GetGroup("BaseApp")
+ ->GetGroup("Preferences")->GetGroup("RecentMacros");
+ int count = hGrp->GetInt("RecentMacros", this->visibleItems); // save number of files
+ hGrp->Clear();
+
+ // count all set items
+ QList recentFiles = _group->actions();
+ int num = std::min(count, recentFiles.count());
+ for (int index = 0; index < num; index++) {
+ QString key = QString::fromLatin1("MRU%1").arg(index);
+ QString value = recentFiles[index]->toolTip();
+ if (value.isEmpty())
+ break;
+ hGrp->SetASCII(key.toLatin1(), value.toUtf8());
+ }
+
+ hGrp->SetInt("RecentMacros", count); // restore
+ hGrp->SetInt("ShortcutCount", this->shortcut_count);
+ hGrp->SetASCII("ShortcutModifiers",this->shortcut_modifiers.c_str());
+}
+
+// --------------------------------------------------------------------
+
UndoAction::UndoAction (Command* pcCmd,QObject * parent)
: Action(pcCmd, parent)
{
diff --git a/src/Gui/Action.h b/src/Gui/Action.h
index bf72a7f44e..5429db732a 100644
--- a/src/Gui/Action.h
+++ b/src/Gui/Action.h
@@ -210,6 +210,38 @@ private:
int maximumItems; /**< Number of maximum items */
};
+// --------------------------------------------------------------------
+
+/**
+ * The RecentMacrosAction class holds a menu listed with the recent macros
+ * that were executed, edited, or created
+ */
+class GuiExport RecentMacrosAction : public ActionGroup
+{
+ Q_OBJECT
+
+public:
+ RecentMacrosAction (Command* pcCmd, QObject * parent = 0);
+ virtual ~RecentMacrosAction();
+
+ void appendFile(const QString&);
+ void activateFile(int);
+ void resizeList(int);
+
+private:
+ void setFiles(const QStringList&);
+ QStringList files() const;
+ void restore();
+ void save();
+
+private:
+ int visibleItems; /**< Number of visible items */
+ int maximumItems; /**< Number of maximum items */
+ std::string shortcut_modifiers; /**< default = "Ctrl+Shift+" */
+ int shortcut_count; /**< Number of dynamic shortcuts to create -- default = 3*/
+};
+
+
// --------------------------------------------------------------------
/**
diff --git a/src/Gui/CommandStd.cpp b/src/Gui/CommandStd.cpp
index 3e77ddfe6d..ce1bee3d27 100644
--- a/src/Gui/CommandStd.cpp
+++ b/src/Gui/CommandStd.cpp
@@ -172,6 +172,46 @@ Action * StdCmdRecentFiles::createAction(void)
return pcAction;
}
+//===========================================================================
+// Std_RecentMacros
+//===========================================================================
+
+DEF_STD_CMD_C(StdCmdRecentMacros)
+
+StdCmdRecentMacros::StdCmdRecentMacros()
+ :Command("Std_RecentMacros")
+{
+ sGroup = QT_TR_NOOP("Macro");
+ sMenuText = QT_TR_NOOP("Recent macros");
+ sToolTipText = QT_TR_NOOP("Recent macro list");
+ sWhatsThis = "Std_RecentMacros";
+ sStatusTip = QT_TR_NOOP("Recent macro list");
+ eType = NoTransaction;
+}
+
+/**
+ * Opens the recent macro at position \a iMsg in the menu.
+ * If the macro does not exist or cannot be loaded this item is removed
+ * from the list.
+ */
+void StdCmdRecentMacros::activated(int iMsg)
+{
+ RecentMacrosAction* act = qobject_cast(_pcAction);
+ if (act) act->activateFile( iMsg );
+}
+
+/**
+ * Creates the QAction object containing the recent macros.
+ */
+Action * StdCmdRecentMacros::createAction(void)
+{
+ RecentMacrosAction* pcAction = new RecentMacrosAction(this, getMainWindow());
+ pcAction->setObjectName(QLatin1String("recentMacros"));
+ pcAction->setDropDownMenu(true);
+ applyCommandData(this->className(), pcAction);
+ return pcAction;
+}
+
//===========================================================================
// Std_About
//===========================================================================
@@ -766,6 +806,7 @@ void CreateStdCommands(void)
rcCmdMgr.addCommand(new StdCmdCommandLine());
rcCmdMgr.addCommand(new StdCmdWorkbench());
rcCmdMgr.addCommand(new StdCmdRecentFiles());
+ rcCmdMgr.addCommand(new StdCmdRecentMacros());
rcCmdMgr.addCommand(new StdCmdWhatsThis());
rcCmdMgr.addCommand(new StdCmdPythonHelp());
rcCmdMgr.addCommand(new StdCmdOnlineHelp());
diff --git a/src/Gui/DlgMacroExecuteImp.cpp b/src/Gui/DlgMacroExecuteImp.cpp
index 95870d03b6..7e7607768c 100644
--- a/src/Gui/DlgMacroExecuteImp.cpp
+++ b/src/Gui/DlgMacroExecuteImp.cpp
@@ -274,6 +274,7 @@ void DlgMacroExecuteImp::accept()
QFileInfo fi(dir, item->text(0));
try {
+ getMainWindow()->appendRecentMacro(fi.filePath());
Application::Instance->macroManager()->run(Gui::MacroManager::File, fi.filePath().toUtf8());
// after macro run recalculate the document
if (Application::Instance->activeDocument())
@@ -334,6 +335,7 @@ void DlgMacroExecuteImp::on_editButton_clicked()
edit->open(file);
edit->resize(400, 300);
getMainWindow()->addWindow(edit);
+ getMainWindow()->appendRecentMacro(file);
if (mitem->systemWide) {
editor->setReadOnly(true);
@@ -341,7 +343,6 @@ void DlgMacroExecuteImp::on_editButton_clicked()
shownName = QString::fromLatin1("%1[*] - [%2]").arg(item->text(0), tr("Read-only"));
edit->setWindowTitle(shownName);
}
-
close();
}
@@ -380,6 +381,7 @@ void DlgMacroExecuteImp::on_createButton_clicked()
editor->setWindowIcon(Gui::BitmapFactory().iconFromTheme("applications-python"));
PythonEditorView* edit = new PythonEditorView(editor, getMainWindow());
edit->open(fi.absoluteFilePath());
+ getMainWindow()->appendRecentMacro(fi.absoluteFilePath());
edit->setWindowTitle(QString::fromLatin1("%1[*]").arg(fn));
edit->resize(400, 300);
getMainWindow()->addWindow(edit);
diff --git a/src/Gui/DlgSettingsMacro.ui b/src/Gui/DlgSettingsMacro.ui
index b840c608ad..6c03a55f40 100644
--- a/src/Gui/DlgSettingsMacro.ui
+++ b/src/Gui/DlgSettingsMacro.ui
@@ -48,25 +48,21 @@
Macro recording settings
-
+
+ 9
+
+
+ 9
+
+
+ 9
+
+
9
6
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
@@ -76,7 +72,16 @@
6
-
+
+ 11
+
+
+ 11
+
+
+ 11
+
+
11
-
@@ -112,8 +117,8 @@
-
-
-
+
+
FullScript.FCScript
@@ -133,7 +138,16 @@
Gui commands
-
+
+ 11
+
+
+ 11
+
+
+ 11
+
+
11
@@ -186,20 +200,26 @@
Macro path
-
+
+ 11
+
+
+ 11
+
+
+ 11
+
+
11
6
-
-
+
The directory in which the application will search for macros
-
- Gui::FileChooser::Directory
-
MacroPath
@@ -214,10 +234,152 @@
+ -
+
+
+ Recent macros menu
+
+
+
-
+
+
+ Size of recent macro list
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ How many macros should be listed in recent macros list
+
+
+ 12
+
+
+ RecentMacros
+
+
+ RecentMacros
+
+
+
+ -
+
+
+ Shortcut count
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ How many recent macros should have shortcuts
+
+
+ 3
+
+
+ ShortcutCount
+
+
+ RecentMacros
+
+
+
+ -
+
+
+ Keyboard Modifiers
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Keyboard modifiers, default = Ctrl+Shift+
+
+
+ ShortcutModifiers
+
+
+ RecentMacros
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+ Gui::PrefLineEdit
+ QLineEdit
+
+
+
+ Gui::PrefSpinBox
+ QSpinBox
+
+
+
+ Gui::PrefCheckBox
+ QCheckBox
+
+
Gui::FileChooser
QWidget
@@ -228,11 +390,6 @@
Gui::FileChooser
-
- Gui::PrefCheckBox
- QCheckBox
-
-
diff --git a/src/Gui/DlgSettingsMacroImp.cpp b/src/Gui/DlgSettingsMacroImp.cpp
index 1ee3b887fb..5f2548cf8e 100644
--- a/src/Gui/DlgSettingsMacroImp.cpp
+++ b/src/Gui/DlgSettingsMacroImp.cpp
@@ -22,10 +22,11 @@
#include "PreCompiled.h"
-
#include "DlgSettingsMacroImp.h"
#include "ui_DlgSettingsMacro.h"
+#include "Action.h"
#include "Application.h"
+#include "MainWindow.h"
using namespace Gui::Dialog;
@@ -58,6 +59,18 @@ DlgSettingsMacroImp::~DlgSettingsMacroImp()
{
// no need to delete child widgets, Qt does it all for us
}
+/** Sets the size of the recent macros list from the user parameters.
+ * @see RecentMacrosAction
+ * @see StdCmdRecentMacros
+ */
+void DlgSettingsMacroImp::setRecentMacroSize()
+{
+ RecentMacrosAction *recent = getMainWindow()->findChild(QLatin1String("recentMacros"));
+ if (recent) {
+ ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("RecentMacros");
+ recent->resizeList(hGrp->GetInt("RecentMacros", 4));
+ }
+}
void DlgSettingsMacroImp::saveSettings()
{
@@ -68,6 +81,10 @@ void DlgSettingsMacroImp::saveSettings()
ui->PConsoleCheckBox->onSave();
ui->FileLogCheckBox->onSave();
ui->MacroPath_2->onSave();
+ ui->RecentMacros->onSave();
+ ui->ShortcutModifiers->onSave();
+ ui->ShortcutCount->onSave();
+ setRecentMacroSize();
}
void DlgSettingsMacroImp::loadSettings()
@@ -79,6 +96,9 @@ void DlgSettingsMacroImp::loadSettings()
ui->PConsoleCheckBox->onRestore();
ui->FileLogCheckBox->onRestore();
ui->MacroPath_2->onRestore();
+ ui->RecentMacros->onRestore();
+ ui->ShortcutModifiers->onRestore();
+ ui->ShortcutCount->onRestore();
}
/**
diff --git a/src/Gui/DlgSettingsMacroImp.h b/src/Gui/DlgSettingsMacroImp.h
index 325154ec5b..646fad6092 100644
--- a/src/Gui/DlgSettingsMacroImp.h
+++ b/src/Gui/DlgSettingsMacroImp.h
@@ -52,6 +52,7 @@ protected:
private:
std::unique_ptr ui;
+ void setRecentMacroSize();
};
} // namespace Dialog
diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp
index 3b71b43e3d..ba3e169fed 100644
--- a/src/Gui/MainWindow.cpp
+++ b/src/Gui/MainWindow.cpp
@@ -1320,6 +1320,15 @@ void MainWindow::appendRecentFile(const QString& filename)
}
}
+void MainWindow::appendRecentMacro(const QString& filename)
+{
+ RecentMacrosAction *recent = this->findChild
+ (QString::fromLatin1("recentMacros"));
+ if (recent) {
+ recent->appendFile(filename);
+ }
+}
+
void MainWindow::updateActions(bool delay)
{
//make it safe to call before the main window is actually created
diff --git a/src/Gui/MainWindow.h b/src/Gui/MainWindow.h
index c27bc406b5..d704956547 100644
--- a/src/Gui/MainWindow.h
+++ b/src/Gui/MainWindow.h
@@ -118,6 +118,10 @@ public:
* MRU: Appends \a file to the list of recent files.
*/
void appendRecentFile(const QString& filename);
+ /**
+ * MRU: Appends \a macro to the list of recent macros.
+ */
+ void appendRecentMacro(const QString& filename);
/**
* Returns true that the context menu contains the 'Customize...' menu item.
*/
diff --git a/src/Gui/Workbench.cpp b/src/Gui/Workbench.cpp
index 1dd2348aa4..5c0eee3f45 100644
--- a/src/Gui/Workbench.cpp
+++ b/src/Gui/Workbench.cpp
@@ -671,6 +671,7 @@ MenuItem* StdWorkbench::setupMenuBar() const
*macro << "Std_DlgMacroRecord"
<< "Std_MacroStopRecord"
<< "Std_DlgMacroExecute"
+ << "Std_RecentMacros"
<< "Separator"
<< "Std_DlgMacroExecuteDirect"
<< "Std_MacroAttachDebugger"