work save: project basicly done

- rename project unit / folder
 - add / remove project folder
 - open project in explorer / terminal
This commit is contained in:
royqh1979@gmail.com 2021-09-18 10:47:35 +08:00
parent f5358f16a7
commit 88ac399b4e
8 changed files with 620 additions and 299 deletions

File diff suppressed because it is too large Load Diff

View File

@ -71,7 +71,8 @@ Editor::Editor(QWidget *parent, const QString& filename,
mCurrentWord(),
mCurrentTipType(TipType::None),
mOldSelectionWord(),
mSelectionWord()
mSelectionWord(),
mSaving(false)
{
mUseCppSyntax = pSettings->editor().defaultFileCpp();
if (mFilename.isEmpty()) {
@ -229,7 +230,9 @@ bool Editor::save(bool force, bool doReparse) {
return true;
}
bool Editor::saveAs(){
bool Editor::saveAs(const QString &name, bool fromProject){
QString newName = name;
if (name.isEmpty()) {
QString selectedFileFilter;
if (pSettings->editor().defaultFileCpp())
selectedFileFilter = pSystemConsts->defaultCPPFileFilter();
@ -241,17 +244,33 @@ bool Editor::saveAs(){
dialog.selectFile(mFilename);
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setOption(QFileDialog::DontConfirmOverwrite,false);
connect(&dialog, &QFileDialog::filterSelected,
[&dialog](const QString &filter){
int pos = filter.indexOf("*.");
if (pos>=0) {
QString suffix;
pos+=2;
while (pos<filter.length()) {
if (filter[pos] == ';' || filter[pos] ==' ' || filter[pos] == ')')
break;
suffix+=filter[pos];
pos++;
}
dialog.setDefaultSuffix(suffix);
}
});
if (!dialog.exec()) {
return false;
}
QString newName = dialog.selectedFiles()[0];
newName = dialog.selectedFiles()[0];
}
// Update project information
if (mInProject && pMainWindow->project()) {
if (mInProject && pMainWindow->project() && !fromProject) {
int unitIndex = pMainWindow->project()->indexInUnits(mFilename);
if (unitIndex>=0) {
pMainWindow->project()->saveUnitAs(unitIndex,newName);
pMainWindow->project()->saveUnitAs(unitIndex,newName,false);
}
}

View File

@ -108,7 +108,7 @@ public:
void saveFile(const QString& filename);
void convertToEncoding(const QByteArray& encoding);
bool save(bool force=false, bool reparse=true);
bool saveAs();
bool saveAs(const QString& name="", bool fromProject = false);
void activate();
QTabWidget* pageControl() noexcept;
@ -228,6 +228,8 @@ private:
QString mOldSelectionWord;
QString mSelectionWord;
bool mSaving;
// QWidget interface
protected:
void wheelEvent(QWheelEvent *event) override;

View File

@ -273,6 +273,8 @@ void MainWindow::updateProjectActions()
ui->actionMakeClean->setEnabled(hasProject);
ui->actionProject_options->setEnabled(hasProject);
ui->actionClose_Project->setEnabled(hasProject);
ui->actionProject_Open_Folder_In_Explorer->setEnabled(hasProject);
ui->actionProject_Open_In_Terminal->setEnabled(hasProject);
updateCompileActions();
}
@ -1478,24 +1480,70 @@ void MainWindow::buildContextMenus()
ui->projectView);
connect(mProject_Rename_Unit, &QAction::triggered,
[this](){
if (ui->projectView->currentIndex().isValid())
ui->projectView->edit(ui->projectView->currentIndex());
});
mProject_Add_Folder = createActionFor(
tr("Add Folder"),
ui->projectView);
connect(mProject_Add_Folder, &QAction::triggered,
[this](){
if (!mProject)
return;
QModelIndex current = ui->projectView->currentIndex();
if (!current.isValid()) {
return;
}
FolderNode * node = static_cast<FolderNode*>(current.internalPointer());
PFolderNode folderNode = mProject->pointerToNode(node);
if (!folderNode)
folderNode = mProject->node();
if (folderNode->unitIndex>=0)
return;
QString s=tr("New folder");
bool ok;
s = QInputDialog::getText(ui->projectView,
tr("Add Folder"),
tr("Folder name:"),
QLineEdit::Normal, s,
&ok).trimmed();
if (ok && !s.isEmpty()) {
QString path = mProject->getFolderPath(folderNode);
if (path.isEmpty()) {
mProject->addFolder(s);
} else {
mProject->addFolder(path + '/' +s);
}
mProject->saveOptions();
}
});
mProject_Rename_Folder = createActionFor(
tr("Rename File"),
tr("Rename Folder"),
ui->projectView);
connect(mProject_Rename_Folder, &QAction::triggered,
[this](){
if (ui->projectView->currentIndex().isValid())
ui->projectView->edit(ui->projectView->currentIndex());
});
mProject_Remove_Folder = createActionFor(
tr("Rename File"),
tr("Remove Folder"),
ui->projectView);
connect(mProject_Remove_Folder, &QAction::triggered,
[this](){
if (!mProject)
return;
QModelIndex current = ui->projectView->currentIndex();
if (!current.isValid()) {
return;
}
FolderNode * node = static_cast<FolderNode*>(current.internalPointer());
PFolderNode folderNode = mProject->pointerToNode(node);
if (!folderNode)
return;
if (folderNode->unitIndex>=0)
return;
mProject->removeFolder(folderNode);
mProject->saveOptions();
});
}
@ -1617,17 +1665,22 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos)
unitIndex = pNode->unitIndex;
onFolder = (unitIndex<0);
onUnit = (unitIndex >= 0);
onRoot = (pNode == mProject->node());
onRoot = false;
if (onFolder && !onRoot) {
folderEmpty = pNode->children.isEmpty();
}
} else {
onFolder = true;
onRoot = true;
}
}
QMenu menu(this);
updateProjectActions();
menu.addAction(ui->actionProject_New_File);
menu.addAction(ui->actionAdd_to_project);
if (!onFolder) {
menu.addAction(ui->actionRemove_from_project);
}
if (onUnit) {
menu.addAction(mProject_Rename_Unit);
}
@ -1642,6 +1695,9 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos)
}
menu.addSeparator();
}
menu.addAction(ui->actionProject_Open_Folder_In_Explorer);
menu.addAction(ui->actionProject_Open_In_Terminal);
menu.addSeparator();
menu.addAction(ui->actionProject_options);
menu.exec(ui->projectView->mapToGlobal(pos));
@ -1818,6 +1874,8 @@ void MainWindow::updateProjectView()
{
if (mProject) {
ui->projectView->setModel(mProject->model());
connect(mProject->model(), &QAbstractItemModel::modelReset,
ui->projectView,&QTreeView::expandAll);
ui->projectView->expandAll();
openCloseLeftPanel(true);
ui->tabProject->setVisible(true);
@ -1944,6 +2002,10 @@ void MainWindow::closeEvent(QCloseEvent *event) {
return ;
}
if (mProject) {
mProject = nullptr;
}
delete mEditorList;
event->accept();
return;
@ -3143,6 +3205,7 @@ void MainWindow::on_actionProject_New_File_triggered()
PProjectUnit newUnit = mProject->newUnit(
mProject->pointerToNode(node) );
idx = mProject->units().count()-1;
mProject->saveUnits();
updateProjectView();
Editor * editor = mProject->openUnit(idx);
editor->setModified(true);
@ -3171,6 +3234,7 @@ void MainWindow::on_actionAdd_to_project_triggered()
mProject->cppParser()->addFileToScan(filename);
}
mProject->rebuildNodes();
mProject->saveUnits();
parseFileList(mProject->cppParser());
updateProjectView();
}
@ -3200,6 +3264,7 @@ void MainWindow::on_actionRemove_from_project_triggered()
}
}
mProject->saveUnits();
mProject->model()->endUpdate();
updateProjectView();
}
@ -3223,3 +3288,19 @@ void MainWindow::on_actionMakeClean_triggered()
mCompilerManager->cleanProject(mProject);
}
void MainWindow::on_actionProject_Open_Folder_In_Explorer_triggered()
{
if (!mProject)
return;
QDesktopServices::openUrl(mProject->directory());
}
void MainWindow::on_actionProject_Open_In_Terminal_triggered()
{
if (!mProject)
return;
openShell(mProject->directory(),"cmd.exe");
}

View File

@ -326,6 +326,10 @@ private slots:
void on_actionMakeClean_triggered();
void on_actionProject_Open_Folder_In_Explorer_triggered();
void on_actionProject_Open_In_Terminal_triggered();
private:
Ui::MainWindow *ui;
EditorList *mEditorList;

View File

@ -109,6 +109,9 @@
</property>
<item>
<widget class="QTreeView" name="projectView">
<property name="editTriggers">
<set>QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
</property>
@ -883,6 +886,10 @@
<addaction name="actionAdd_to_project"/>
<addaction name="actionRemove_from_project"/>
<addaction name="separator"/>
<addaction name="actionProject_Open_Folder_In_Explorer"/>
<addaction name="actionProject_Open_In_Terminal"/>
<addaction name="separator"/>
<addaction name="separator"/>
<addaction name="actionView_Makefile"/>
<addaction name="actionMakeClean"/>
<addaction name="separator"/>
@ -1687,6 +1694,24 @@
<string>Clean</string>
</property>
</action>
<action name="actionProject_Open_Folder_In_Explorer">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/090-explorer.png</normaloff>:/icons/images/newlook24/090-explorer.png</iconset>
</property>
<property name="text">
<string>Open Folder in Explorer</string>
</property>
</action>
<action name="actionProject_Open_In_Terminal">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/030-dos.png</normaloff>:/icons/images/newlook24/030-dos.png</iconset>
</property>
<property name="text">
<string>Open In Terminal</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -124,7 +124,7 @@ void Project::open()
checkProjectFileForUpdate(ini);
int uCount = ini.GetLongValue("Project","UnitCount",0);
//createFolderNodes;
createFolderNodes();
QDir dir(directory());
for (int i=0;i<uCount;i++) {
PProjectUnit newUnit = std::make_shared<ProjectUnit>(this);
@ -454,14 +454,18 @@ void Project::saveLayout()
}
}
void Project::saveUnitAs(int i, const QString &sFileName)
void Project::saveUnitAs(int i, const QString &sFileName, bool syncEditor)
{
if ((i < 0) || (i >= mUnits.count()))
return;
PProjectUnit unit = mUnits[i];
// if (fileExists(unit->fileName())) {
// unit->setNew(false);
// }
if (fileExists(unit->fileName())) {
unit->setNew(false);
}
if (unit->editor() && syncEditor) {
//prevent recurse
unit->editor()->saveAs(sFileName,true);
}
unit->setNew(false);
unit->setFileName(sFileName);
SimpleIni ini;
@ -476,6 +480,11 @@ void Project::saveUnitAs(int i, const QString &sFileName)
sFileName)));
ini.SaveFile(mFilename.toLocal8Bit());
setModified(true);
if (!syncEditor) {
//the call it's from editor, we need to update model
mModel.beginUpdate();
mModel.endUpdate();
}
}
void Project::saveUnitLayout(Editor *e, int index)
@ -1146,7 +1155,7 @@ void Project::createFolderNodes()
else
node = findnode;
node->unitIndex = -1;
s.remove(0,i);
s.remove(0,i+1);
i = s.indexOf('/');
}
node = makeNewFileNode(s, true, node);
@ -1215,9 +1224,11 @@ QString Project::getFolderPath(PFolderNode node)
return result;
PFolderNode p = node;
while (p && p->unitIndex==-1) {
while (p && p->unitIndex==-1 && p!=mNode) {
if (!result.isEmpty())
result = p->text + "/" + result;
else
result = p->text;
p = p->parent.lock();
}
return result;
@ -1476,7 +1487,7 @@ void Project::removeFolderRecurse(PFolderNode node)
void Project::updateFolderNode(PFolderNode node)
{
for (int i=0;i<node->children.count();i++){
PFolderNode child;
PFolderNode child = node->children[i];
if (child->unitIndex<0) {
mFolders.append(getFolderPath(child));
updateFolderNode(child);
@ -1561,7 +1572,12 @@ const QString &ProjectUnit::fileName() const
void ProjectUnit::setFileName(const QString &newFileName)
{
if (mFileName != newFileName) {
mFileName = newFileName;
if (mNode) {
mNode->text = extractFileName(mFileName);
}
}
}
bool ProjectUnit::isNew() const
@ -1789,3 +1805,109 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const
}
return QVariant();
}
Qt::ItemFlags ProjectModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
FolderNode* p = static_cast<FolderNode*>(index.internalPointer());
if (!p)
return Qt::NoItemFlags;
if (p==mProject->node().get())
return Qt::ItemIsEnabled;
return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable;
}
bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid())
return false;
FolderNode* p = static_cast<FolderNode*>(index.internalPointer());
PFolderNode node = mProject->pointerToNode(p);
if (!node)
return false;
if (role == Qt::EditRole) {
if (node == mProject->node())
return false;
int idx = node->unitIndex;
if (idx >= 0) {
//change unit name
PProjectUnit unit = mProject->units()[idx];
QString newName = value.toString().trimmed();
if (newName.isEmpty())
return false;
if (newName == node->text)
return false;
QString oldName = unit->fileName();
QString curDir = extractFilePath(oldName);
newName = QDir(curDir).absoluteFilePath(newName);
// Only continue if the user says so...
if (fileExists(newName) && newName.compare(oldName, PATH_SENSITIVITY)!=0) {
// don't remove when changing case for example
if (QMessageBox::question(pMainWindow,
tr("File exists"),
tr("File '%1' already exists. Delete it now?")
.arg(newName),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No) == QMessageBox::Yes) {
// Close the target file...
Editor * e= pMainWindow->editorList()->getOpenedEditorByFilename(newName);
if (e)
pMainWindow->editorList()->closeEditor(e);
// Remove it from the current project...
int projindex = mProject->indexInUnits(newName);
if (projindex>=0) {
mProject->removeEditor(projindex,false);
}
// All references to the file are removed. Delete the file from disk
if (!QFile::remove(newName)) {
QMessageBox::critical(pMainWindow,
tr("Remove failed"),
tr("Failed to remove file '%1'")
.arg(newName),
QMessageBox::Ok);
return false;
}
} else {
return false;
}
}
// Target filename does not exist anymore. Do a rename
// change name in project file first (no actual file renaming on disk)
mProject->saveUnitAs(idx,newName);
// remove old file from monitor list
pMainWindow->fileSystemWatcher()->removePath(oldName);
// Finally, we can rename without issues
if (!QFile::remove(oldName)){
QMessageBox::critical(pMainWindow,
tr("Remove failed"),
tr("Failed to remove file '%1'")
.arg(oldName),
QMessageBox::Ok);
mProject->saveUnitAs(idx,oldName);
return false;
}
// Add new filename to file minitor
pMainWindow->fileSystemWatcher()->removePath(oldName);
return true;
} else {
//change folder name
QString newName = value.toString().trimmed();
if (newName.isEmpty())
return false;
if (newName == node->text)
return false;
node->text = newName;
mProject->updateFolders();
mProject->saveAll();
return true;
}
}
return false;
}

View File

@ -94,6 +94,8 @@ public:
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
};
class ProjectTemplate;
@ -143,7 +145,7 @@ public:
void saveAll(); // save [Project] and all [UnitX]
void saveLayout(); // save all [UnitX]
void saveOptions();
void saveUnitAs(int i, const QString& sFileName); // save single [UnitX]
void saveUnitAs(int i, const QString& sFileName, bool syncEditor = true); // save single [UnitX]
void saveUnitLayout(Editor* e, int index); // save single [UnitX] cursor positions
bool saveUnits();
void setCompilerOption(const QString& optionString, char value);