Add Duplicate button to Execute Macro dialog

With the Duplicate button a macro is duplicated with a new name, e.g. duplicate a macro named "MyMacro.FCMacro" and you get a new duplicate file named "MyMacro@001.FCMacro", but the user has opportunity to override the new name with a name of his own or to cancel the operation.

Functionality is similar to already existing ability to create copies of the .FCStd file, only for macros, and this must be done manually for each new file.  Will be useful to coders mostly.  Expected use case could be to save a history of the macro periodically as changes are made or perhaps to duplicate the macro first, and then make changes to the duplicate, eventually replacing the original once satisfied with the changes.

New code is based largely on existing code from rename operation, but with QFile.copy() instead of QFile.rename() used, along with other changes needed, such as generating the new suggested filenames.

link to forum discussion and demonstration video:
https://forum.freecadweb.org/viewtopic.php?f=8&p=254014&sid=98243801791920b69086a3fcd4699e34#p254014

Not sure how to make the Duplicate button label text translate when changing languages.
This commit is contained in:
Mark Ganson TheMarkster
2018-09-02 13:10:22 -05:00
committed by Yorik van Havre
parent 299f68cda6
commit 43d16fc87a
3 changed files with 107 additions and 4 deletions

View File

@@ -166,9 +166,6 @@
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="mode" >
<enum>Gui::FileChooser::Directory</enum>
</property>
</widget>
</item>
</layout>
@@ -264,6 +261,16 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="duplicateButton">
<property name="text">
<string>Duplicate</string>
</property>
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
@@ -309,9 +316,9 @@
<tabstop>deleteButton</tabstop>
<tabstop>editButton</tabstop>
<tabstop>renameButton</tabstop>
<tabstop>duplicateButton</tabstop>
<tabstop>addonsButton</tabstop>
<tabstop>fileChooser</tabstop>
</tabstops>
<resources/>
<connections>

View File

@@ -139,6 +139,7 @@ void DlgMacroExecuteImp::on_userMacroListBox_currentItemChanged(QTreeWidgetItem*
createButton->setEnabled(true);
editButton->setEnabled(true);
renameButton->setEnabled(true);
duplicateButton->setEnabled(true);
}
else {
executeButton->setEnabled(false);
@@ -146,6 +147,7 @@ void DlgMacroExecuteImp::on_userMacroListBox_currentItemChanged(QTreeWidgetItem*
createButton->setEnabled(true);
editButton->setEnabled(false);
renameButton->setEnabled(false);
duplicateButton->setEnabled(false);
}
}
@@ -159,6 +161,7 @@ void DlgMacroExecuteImp::on_systemMacroListBox_currentItemChanged(QTreeWidgetIte
createButton->setEnabled(false);
editButton->setEnabled(true); //look but don't touch
renameButton->setEnabled(false);
duplicateButton->setEnabled(false);
}
else {
executeButton->setEnabled(false);
@@ -166,6 +169,7 @@ void DlgMacroExecuteImp::on_systemMacroListBox_currentItemChanged(QTreeWidgetIte
createButton->setEnabled(false);
editButton->setEnabled(false);
renameButton->setEnabled(false);
duplicateButton->setEnabled(false);
}
}
@@ -181,6 +185,7 @@ void DlgMacroExecuteImp::on_tabMacroWidget_currentChanged(int index)
createButton->setEnabled(true);
editButton->setEnabled(true);
renameButton->setEnabled(true);
duplicateButton->setEnabled(true);
}
else {
executeButton->setEnabled(false);
@@ -188,6 +193,7 @@ void DlgMacroExecuteImp::on_tabMacroWidget_currentChanged(int index)
createButton->setEnabled(true);
editButton->setEnabled(false);
renameButton->setEnabled(false);
duplicateButton->setEnabled(false);
}
}
else { //index==1 system-wide
@@ -199,6 +205,7 @@ void DlgMacroExecuteImp::on_tabMacroWidget_currentChanged(int index)
createButton->setEnabled(false);
editButton->setEnabled(true); //but you can't save it
renameButton->setEnabled(false);
duplicateButton->setEnabled(false);
}
else {
executeButton->setEnabled(false);
@@ -206,6 +213,7 @@ void DlgMacroExecuteImp::on_tabMacroWidget_currentChanged(int index)
createButton->setEnabled(false);
editButton->setEnabled(false);
renameButton->setEnabled(false);
duplicateButton->setEnabled(false);
}
}
@@ -438,6 +446,93 @@ void DlgMacroExecuteImp::on_renameButton_clicked()
}
}
}
/**Duplicates selected macro
* New file has same name as original but with "@" and 3-digit number appended
* Begins with "@001" and increments until available name is found
* "MyMacro.FCMacro" becomes "MyMacro@001.FCMacro"
* "MyMacro@002.FCMacro.py" becomes "MyMacro@003.FCMacro.py" unless there is
* no already existing "MyMacro@001.FCMacro.py"
*/
void DlgMacroExecuteImp::on_duplicateButton_clicked()
{
QDir dir;
QTreeWidgetItem* item = 0;
int index = tabMacroWidget->currentIndex();
if (index == 0) { //user-specific
item = userMacroListBox->currentItem();
dir.setPath(this->macroPath);
}
if (!item){
return;
}
QString oldName = item->text(0);
QFileInfo oldfi(dir, oldName);
QFile oldfile(oldfi.absoluteFilePath());
QString completeSuffix = oldfi.completeSuffix(); //everything after the first "."
QString baseName = oldfi.baseName(); //everything before first "."
QString neutralSymbol = QString::fromStdString("@");
QString last3 = baseName.right(3);
bool ok = true; //was conversion to int successful?
int nLast3 = last3.toInt(&ok);
last3 = QString::fromStdString("001"); //increment beginning with 001 no matter what
if (ok ){
//last3 were all digits, so we strip them from the base name
if (baseName.size()>3){ //if <= 3 leave be (e.g. 2.py becomes 2@001.py)
baseName = baseName.left(baseName.size()-3); //strip digits
if (baseName.endsWith(neutralSymbol)){
baseName = baseName.left(baseName.size()-1); //trim the "@", will be added back later
}
}
}
//at this point baseName = the base name without any digits, e.g. "MyMacro"
//neutralSymbol = "@"
//last3 is a string representing 3 digits, always "001" at this time
//completeSuffix = FCMacro or py or FCMacro.py or else suffix will become FCMacro below
QString oldNameDigitized = baseName+neutralSymbol+last3+QString::fromStdString(".")+completeSuffix;
QFileInfo fi(dir, oldNameDigitized);
// increment until we find available name with smallest digits
// test from "001" through "999", then give up and let user enter name of choice
while (fi.exists()) {
nLast3 = last3.toInt()+1;
if (nLast3 >=1000){ //avoid infinite loop, 999 files will have to be enough
break;
}
last3 = QString::number(nLast3);
while (last3.size()<3){
last3.prepend(QString::fromStdString("0")); //pad 0's if needed
}
oldNameDigitized = baseName+neutralSymbol+last3+QString::fromStdString(".")+completeSuffix;
fi = QFileInfo(dir,oldNameDigitized);
}
// give user a chance to pick a different name from digitized name suggested
QString fn = QInputDialog::getText(this, tr("Duplicate Macro"),
tr("Enter new name:"), QLineEdit::Normal, oldNameDigitized, 0);
if (!fn.isEmpty() && fn != oldName) {
QString suffix = QFileInfo(fn).suffix().toLower();
if (suffix != QLatin1String("fcmacro") && suffix != QLatin1String("py")){
fn += QLatin1String(".FCMacro");
}
QFileInfo fi(dir, fn);
// check again if new name exists in case user changed it
if (fi.exists()) {
QMessageBox::warning(this, tr("Existing file"),
tr("'%1'\n already exists.").arg(fi.absoluteFilePath()));
}
else if (!oldfile.copy(fi.absoluteFilePath())) {
QMessageBox::warning(this, tr("Duplicate Failed"),
tr("Failed to duplicate to '%1'.\nPerhaps a file permission error?").arg(fi.absoluteFilePath()));
}
this->fillUpList(); //repopulate list to show new file
}
}
/**
* convenience link button to open tools -> addon manager
* from within macro dialog

View File

@@ -51,6 +51,7 @@ public Q_SLOTS:
void on_deleteButton_clicked();
void on_editButton_clicked();
void on_renameButton_clicked();
void on_duplicateButton_clicked();
void on_addonsButton_clicked();
protected Q_SLOTS: