- fix: gliches in UI's left panel in some OS

- fix: correctly restore project layout when reopen it
  - fix: correctly handle rename unit
  - refactor: use filename as the primary key for project unit
This commit is contained in:
Roy Qu 2022-10-08 23:30:30 +08:00
parent 592d6bba32
commit 1e5a130def
9 changed files with 287 additions and 273 deletions

View File

@ -1,7 +1,9 @@
Red Panda C++ Version 1.5
- fix: project files that lies in project include folder is wrongly openned in Read-only mode
- enhancement: add/new/remove project files won't rebuild project tree
- enhancement: add/new/remove/rename project files won't rebuild project tree
- fix: gliches in UI's left panel in some OS
- fix: correctly restore project layout when reopen it
Red Panda C++ Version 1.4

View File

@ -336,8 +336,8 @@ bool Editor::saveAs(const QString &name, bool fromProject){
}
// Update project information
if (mInProject && pMainWindow->project() && !fromProject) {
int unitId = pMainWindow->project()->findUnitId(newName);
if (unitId<0) {
PProjectUnit unit = pMainWindow->project()->findUnit(newName);
if (!unit) {
mInProject = false;
}
}

View File

@ -169,10 +169,8 @@ bool EditorList::closeEditor(Editor* editor, bool transferFocus, bool force) {
// }
if (editor->inProject() && pMainWindow->project()) {
int unitId = pMainWindow->project()->findUnitId(editor);
if (unitId>=0) {
pMainWindow->project()->closeUnit(unitId);
}
PProjectUnit unit = pMainWindow->project()->findUnit(editor);
pMainWindow->project()->closeUnit(unit);
} else {
if (pSettings->history().addToOpenedFiles(editor->filename())) {
pMainWindow->rebuildOpenedFileHisotryMenu();

View File

@ -2224,6 +2224,10 @@ void MainWindow::loadLastOpens()
QByteArray encoding = unit ? unit->encoding() :
(pSettings->editor().autoDetectFileEncoding()? ENCODING_AUTO_DETECT : pSettings->editor().defaultEncoding());
Editor * editor = mEditorList->newEditor(editorFilename, encoding, inProject,false,page);
if (inProject && editor) {
mProject->loadUnitLayout(editor);
}
// if (mProject) {
// mProject->associateEditorToUnit(editor,unit);
// }
@ -2943,15 +2947,13 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos)
bool onRoot = false;
bool folderEmpty = false;
bool multiSelection = ui->projectView->selectionModel()->selectedRows().count()>1;
int unitIndex = -1;
QModelIndex current = mProjectProxyModel->mapToSource(ui->projectView->selectionModel()->currentIndex());
if (current.isValid() && mProject) {
ProjectModelNode * node = static_cast<ProjectModelNode*>(current.internalPointer());
PProjectModelNode pNode = mProject->pointerToNode(node);
if (pNode) {
unitIndex = pNode->unitIndex;
onFolder = (unitIndex<0);
onUnit = (unitIndex >= 0);
onFolder = (!pNode->isUnit);
onUnit = (pNode->isUnit);
onRoot = false;
if (onFolder && !onRoot) {
folderEmpty = pNode->children.isEmpty();
@ -3022,11 +3024,11 @@ void MainWindow::onProjectViewContextMenu(const QPoint &pos)
}
QModelIndex realIndex = mProjectProxyModel->mapToSource(index);
ProjectModelNode * node = static_cast<ProjectModelNode*>(realIndex.internalPointer());
if (!node || node->unitIndex<0) {
if (!node || !node->isUnit) {
shouldAdd=false;
break;
}
PProjectUnit pUnit=mProject->findUnitById(node->unitIndex);
PProjectUnit pUnit=node->pUnit.lock();
if (mProject->model()->iconProvider()->VCSRepository()->isFileInRepository(
pUnit->fileName()
)
@ -3893,7 +3895,7 @@ void MainWindow::onProjectRemoveFolder()
PProjectModelNode folderNode = mProject->pointerToNode(node);
if (!folderNode)
return;
if (folderNode->unitIndex>=0)
if (folderNode->isUnit)
return;
mProject->removeFolder(folderNode);
mProject->saveOptions();
@ -3919,7 +3921,7 @@ void MainWindow::onProjectAddFolder()
PProjectModelNode folderNode = mProject->pointerToNode(node);
if (!folderNode)
folderNode = mProject->rootNode();
if (folderNode->unitIndex>=0)
if (folderNode->isUnit)
return;
QString s=tr("New folder");
int i=1;
@ -4267,6 +4269,7 @@ void MainWindow::closeProject(bool refreshEditor)
auto action3 = finally([this]{
mEditorList->endUpdate();
});
mProject->closeAllUnits();
mProject.reset();
if (!mQuitting && refreshEditor) {
@ -4294,9 +4297,8 @@ void MainWindow::updateProjectView()
if (mProjectProxyModel->sourceModel()!=mProject->model()) {
mProjectProxyModel->setSourceModel(mProject->model());
mProjectProxyModel->sort(0);
// connect(mProject->model(), &ProjectModel::dataChanged,
// this, &MainWindow::invalidateProjectProxyModel);
// connect(mProject->model(), &ProjectModel::rowsRemoved,
connect(mProject.get(), &Project::nodeRenamed,
this, &MainWindow::onProjectViewNodeRenamed);
// this, &MainWindow::invalidateProjectProxyModel);
// connect(mProject->model(), &ProjectModel::rowsInserted,
// this, &MainWindow::invalidateProjectProxyModel);
@ -5760,8 +5762,9 @@ void MainWindow::on_projectView_doubleClicked(const QModelIndex &index)
ProjectModelNode * node = static_cast<ProjectModelNode*>(sourceIndex.internalPointer());
if (!node)
return;
if (node->unitIndex>=0) {
mProject->openUnit(node->unitIndex);
if (node->isUnit) {
PProjectUnit unit = node->pUnit.lock();
mProject->openUnit(unit);
}
}
@ -5967,7 +5970,8 @@ void MainWindow::on_actionRemove_from_project_triggered()
PProjectModelNode folderNode = mProject->pointerToNode(node);
if (!folderNode)
continue;
mProject->removeUnit(folderNode->unitIndex, true, removeFile);
PProjectUnit unit = folderNode->pUnit.lock();
mProject->removeUnit(unit, true, removeFile);
};
ui->projectView->selectionModel()->clearSelection();
mProject->saveAll();
@ -6159,7 +6163,7 @@ void MainWindow::newProjectUnitFile()
}
PProjectModelNode pNode = mProject->pointerToNode(node);
while (pNode && pNode->unitIndex>0) {
while (pNode && pNode->isUnit) {
pNode = pNode->parent.lock();
}
@ -6235,13 +6239,8 @@ void MainWindow::newProjectUnitFile()
setProjectViewCurrentUnit(newUnit);
// mProject->rebuildNodes();
mProject->saveAll();
// updateProjectView();
// idx = newUnit->id;
Editor * editor = mProject->openUnit(newUnit->id(), false);
//editor->setUseCppSyntax(mProject->options().useGPP);
//editor->setModified(true);
Editor * editor = mProject->openUnit(newUnit, false);
if (editor)
editor->activate();
QString branch;
@ -6311,6 +6310,11 @@ void MainWindow::setProjectViewCurrentUnit(std::shared_ptr<ProjectUnit> unit) {
}
}
void MainWindow::onProjectViewNodeRenamed()
{
updateProjectView();
}
void MainWindow::setProjectViewCurrentNode(PProjectModelNode node)
{
if (node) {
@ -7576,8 +7580,8 @@ void MainWindow::on_actionGit_Add_Files_triggered()
PProjectModelNode folderNode = mProject->pointerToNode(node);
if (!folderNode)
continue;
if (folderNode->unitIndex>=0) {
PProjectUnit unit = mProject->findUnitById(folderNode->unitIndex);
if (folderNode->isUnit) {
PProjectUnit unit = folderNode->pUnit.lock();
QFileInfo info(unit->fileName());
QString output;
vcsManager.add(info.absolutePath(),info.fileName(),output);

View File

@ -276,6 +276,7 @@ private:
void setProjectViewCurrentUnit(std::shared_ptr<ProjectUnit> unit);
private slots:
void onProjectViewNodeRenamed();
void setDockExplorerToArea(const Qt::DockWidgetArea &area);
void setDockMessagesToArea(const Qt::DockWidgetArea &area);
void updateVCSActions();

View File

@ -473,12 +473,15 @@
<enum>QTabWidget::West</enum>
</property>
<property name="currentIndex">
<number>1</number>
<number>4</number>
</property>
<property name="usesScrollButtons">
<bool>true</bool>
</property>
<widget class="QWidget" name="tabFiles">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<attribute name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/018-copy.png</normaloff>:/icons/images/newlook24/018-copy.png</iconset>
@ -561,6 +564,9 @@
</layout>
</widget>
<widget class="QWidget" name="tabProject">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<attribute name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/049-newproj.png</normaloff>:/icons/images/newlook24/049-newproj.png</iconset>
@ -612,6 +618,9 @@
</layout>
</widget>
<widget class="QWidget" name="tabWatch">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<attribute name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/088-watch.png</normaloff>:/icons/images/newlook24/088-watch.png</iconset>
@ -654,6 +663,9 @@
</layout>
</widget>
<widget class="QWidget" name="tabStructure">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<attribute name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/087-update.png</normaloff>:/icons/images/newlook24/087-update.png</iconset>
@ -693,6 +705,9 @@
</layout>
</widget>
<widget class="QWidget" name="tabProblemSet">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<attribute name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/014-compopt.png</normaloff>:/icons/images/newlook24/014-compopt.png</iconset>

View File

@ -36,6 +36,9 @@
#include <QDirIterator>
#include <QMimeDatabase>
#include <QDesktopServices>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include "customfileiconprovider.h"
#include <QMimeData>
#include "settings.h"
@ -193,22 +196,19 @@ void Project::open()
newUnit->setEncoding(ENCODING_AUTO_DETECT);
}
newUnit->setNew(false);
newUnit->setParent(this);
PProjectModelNode parentNode;
if (mOptions.modelType==ProjectModelType::FileSystem) {
parentNode = getParentFileSystemFolderNode(newUnit->fileName());
} else {
parentNode = getCustomeFolderNodeFromName(newUnit->folder());
}
PProjectModelNode node = makeNewFileNode(extractFileName(newUnit->fileName()),
newUnit->id(),
PProjectModelNode node = makeNewFileNode(newUnit,
newUnit->priority(),
parentNode
);
newUnit->setNode(node);
mUnits.insert(newUnit->id(),newUnit);
mUnits.insert(newUnit->fileName(),newUnit);
}
//rebuildNodes();
}
void Project::setFileName(QString value)
@ -242,7 +242,7 @@ PProjectModelNode Project::makeNewFolderNode(
if (newParent) {
node->level = newParent->level+1;
}
node->unitIndex = -1;
node->isUnit=false;
node->priority = priority;
node->folderNodeType = nodeType;
QModelIndex parentIndex=mModel.getNodeIndex(newParent.get());
@ -251,18 +251,19 @@ PProjectModelNode Project::makeNewFolderNode(
return node;
}
PProjectModelNode Project::makeNewFileNode(const QString &fileName, int unitId,int priority, PProjectModelNode newParent)
PProjectModelNode Project::makeNewFileNode(PProjectUnit unit,int priority, PProjectModelNode newParent)
{
PProjectModelNode node = std::make_shared<ProjectModelNode>();
if (!newParent) {
newParent = mRootNode;
}
node->parent = newParent;
node->text = fileName;
node->text = extractFileName(unit->fileName());
if (newParent) {
node->level = newParent->level+1;
}
node->unitIndex = unitId;
node->isUnit = true;
node->pUnit = unit;
node->priority = priority;
node->folderNodeType = ProjectModelNodeType::File;
@ -277,7 +278,7 @@ PProjectModelNode Project::makeProjectNode()
PProjectModelNode node = std::make_shared<ProjectModelNode>();
node->text = mName;
node->level = 0;
node->unitIndex = -1;
node->isUnit = false;
node->folderNodeType = ProjectModelNodeType::Folder;
return node;
}
@ -290,7 +291,7 @@ PProjectUnit Project::newUnit(PProjectModelNode parentNode, const QString& custo
if (!parentNode)
parentNode = mRootNode; // project root node
if (parentNode->unitIndex>=0) { //it's a file
if (parentNode->isUnit) { //it's a file
parentNode = mRootNode;
}
QString s;
@ -313,11 +314,9 @@ PProjectUnit Project::newUnit(PProjectModelNode parentNode, const QString& custo
newUnit->setFileName(s);
newUnit->setNew(true);
newUnit->setFolder(getNodePath(parentNode));
PProjectModelNode node = makeNewFileNode(extractFileName(newUnit->fileName()),
newUnit->id(),newUnit->priority(),parentNode);
node->unitIndex = newUnit->id();
PProjectModelNode node = makeNewFileNode(newUnit,newUnit->priority(),parentNode);
newUnit->setNode(node);
mUnits.insert(newUnit->id(), newUnit);
mUnits.insert(newUnit->fileName(), newUnit);
//parentNode.Expand(True);
switch(getFileType(customFileName)) {
@ -349,12 +348,7 @@ PProjectUnit Project::newUnit(PProjectModelNode parentNode, const QString& custo
return newUnit;
}
Editor *Project::openUnit(int index, bool forceOpen)
{
PProjectUnit unit = mUnits.value(index,PProjectUnit());
if (!unit)
return nullptr;
Editor* Project::openUnit(PProjectUnit& unit, bool forceOpen) {
if (!unit->fileName().isEmpty() && fileExists(unit->fileName())) {
if (getFileType(unit->fileName())==FileType::Other) {
@ -375,22 +369,16 @@ Editor *Project::openUnit(int index, bool forceOpen)
if (editor) {
editor->setInProject(true);
//unit->setEncoding(encoding);
editor->activate();
loadUnitLayout(editor);
editor->activate();
return editor;
}
}
return nullptr;
}
Editor *Project::openUnit(PProjectEditorLayout editorLayout)
Editor *Project::openUnit(PProjectUnit &unit, const PProjectEditorLayout &layout)
{
if (!editorLayout)
return nullptr;
PProjectUnit unit = findUnit(editorLayout->filename);
if (!unit)
return nullptr;
if (!unit->fileName().isEmpty() && fileExists(unit->fileName())) {
if (getFileType(unit->fileName())==FileType::Other) {
return nullptr;
@ -407,26 +395,28 @@ Editor *Project::openUnit(PProjectEditorLayout editorLayout)
editor = mEditorList->newEditor(unit->fileName(), encoding, true, unit->isNew());
if (editor) {
editor->setInProject(true);
//unit->setEncoding(encoding);
editor->setCaretY(layout->caretY);
editor->setCaretX(layout->caretX);
editor->setTopLine(layout->topLine);
editor->setLeftChar(layout->leftChar);
editor->activate();
editor->setTopLine(editorLayout->topLine);
editor->setLeftChar(editorLayout->leftChar);
editor->setCaretX(editorLayout->caretX);
editor->setCaretY(editorLayout->caretY);
return editor;
}
}
return nullptr;
}
Editor *Project::unitEditor(const PProjectUnit &unit) const
{
if (!unit)
return nullptr;
return mEditorList->getOpenedEditorByFilename(unit->fileName());
}
Editor *Project::unitEditor(const ProjectUnit *unit) const
{
if (!unit)
return nullptr;
return mEditorList->getOpenedEditorByFilename(unit->fileName());
}
@ -456,13 +446,11 @@ void Project::rebuildNodes()
QFileInfo fileInfo(pUnit->fileName());
pUnit->setNode(
makeNewFileNode(
fileInfo.fileName(),
pUnit->id(),
pUnit,
pUnit->priority(),
getCustomeFolderNodeFromName(pUnit->folder())
)
);
pUnit->node()->priority = pUnit->priority();
}
break;
case ProjectModelType::FileSystem:
@ -472,26 +460,22 @@ void Project::rebuildNodes()
QFileInfo fileInfo(pUnit->fileName());
pUnit->setNode(
makeNewFileNode(
fileInfo.fileName(),
pUnit->id(),
pUnit,
pUnit->priority(),
getParentFileSystemFolderNode(
pUnit->fileName())
)
);
pUnit->node()->priority = pUnit->priority();
}
break;
}
mModel.endUpdate();
emit nodesChanged();
}
bool Project::removeUnit(int id, bool doClose , bool removeFile)
bool Project::removeUnit(PProjectUnit& unit, bool doClose , bool removeFile)
{
PProjectUnit unit = findUnitById(id);
if (!unit)
return false;
@ -514,20 +498,20 @@ bool Project::removeUnit(int id, bool doClose , bool removeFile)
PProjectModelNode node = unit->node();
PProjectModelNode parentNode = node->parent.lock();
if (!parentNode) {
mUnits.remove(unit->id());
mUnits.remove(unit->fileName());
return true;
}
int row = parentNode->children.indexOf(unit->node());
if (row<0) {
mUnits.remove(unit->id());
mUnits.remove(unit->fileName());
return true;
}
QModelIndex parentIndex = mModel.getNodeIndex(parentNode.get());
mModel.removeRow(row,parentIndex);
mUnits.remove(unit->id());
mUnits.remove(unit->fileName());
//remove empty parent node
PProjectModelNode currentNode = parentNode;
@ -558,7 +542,7 @@ bool Project::removeFolder(PProjectModelNode node)
return false;
// Check if this is actually a folder
if (node->unitIndex>=0 || node->level<1)
if (node->isUnit || node->level<1)
return false;
// Let this function call itself
@ -594,7 +578,7 @@ void Project::saveAll()
void Project::saveLayout()
{
SimpleIni layIni;
QJsonObject jsonRoot;
QHash<QString,int> editorOrderSet;
// Write list of open project files
int order=0;
@ -611,52 +595,61 @@ void Project::saveLayout()
// Remember what files were visible
mEditorList->getVisibleEditors(e, e2);
if (e)
layIni.SetValue("Editors","Focused", e->filename().toUtf8());
jsonRoot["focused"]=e->filename();
QJsonArray jsonLayouts;
// save editor info
foreach (const PProjectUnit& unit,mUnits) {
Editor* editor = unitEditor(unit);
if (editor) {
QByteArray groupName = QString("E_%1").arg(editor->filename()).toUtf8();
layIni.SetLongValue(groupName,"CursorCol", editor->caretX());
layIni.SetLongValue(groupName,"CursorRow", editor->caretY());
layIni.SetLongValue(groupName,"TopLine", editor->topLine());
layIni.SetLongValue(groupName,"LeftChar", editor->leftChar());
QJsonObject jsonLayout;
jsonLayout["filename"]=unit->fileName();
jsonLayout["caretX"]=editor->caretX();
jsonLayout["caretY"]=editor->caretY();
jsonLayout["topLine"]=editor->topLine();
jsonLayout["leftChar"]=editor->leftChar();
int order=editorOrderSet.value(editor->filename(),-1);
if (order>=0) {
layIni.SetLongValue(groupName,"Order",order);
jsonLayout["order"]=order;
}
jsonLayouts.append(jsonLayout);
}
}
// remove old data from project file
// SimpleIni ini;
// ini.LoadFile(filename().toLocal8Bit());
// groupName = toByteArray(QString("Unit%1").arg(i+1));
// ini.Delete(groupName,"Open");
// ini.Delete(groupName,"Top");
// ini.Delete(groupName,"CursorCol");
// ini.Delete(groupName,"CursorRow");
// ini.Delete(groupName,"TopLine");
// ini.Delete(groupName,"LeftChar");
// ini.SaveFile(filename().toLocal8Bit());
jsonRoot["editorLayouts"]=jsonLayouts;
QString jsonFilename=changeFileExt(filename(), "layout");
QFile file(jsonFilename);
if (file.open(QFile::WriteOnly|QFile::Truncate)) {
QJsonDocument doc(jsonRoot);
file.write(doc.toJson(QJsonDocument::Indented));
file.close();
} else {
throw FileError(QObject::tr("Can't open file '%1' for write.")
.arg(jsonFilename));
}
layIni.SaveFile(changeFileExt(filename(), "layout").toLocal8Bit());
}
void Project::renameUnit(int idx, const QString &sFileName)
void Project::renameUnit(PProjectUnit& unit, const QString &sFileName)
{
PProjectUnit unit = findUnitById(idx);
if (!unit)
return;
if (sFileName.compare(unit->fileName(),PATH_SENSITIVITY)==0)
return;
if (fileExists(unit->fileName())) {
unit->setNew(false);
}
Editor * editor=unitEditor(unit);
if (editor) {
//prevent recurse
editor->saveAs(sFileName,true);
}
unit->setNew(false);
unit->setFileName(sFileName);
removeUnit(unit,false,false);
PProjectModelNode parentNode = unit->node()->parent.lock();
unit = addUnit(sFileName,parentNode);
setModified(true);
emit nodeRenamed();
}
bool Project::saveUnits()
@ -725,18 +718,9 @@ bool Project::saveUnits()
return true;
}
PProjectUnit Project::findUnitById(int id)
{
return mUnits.value(id,PProjectUnit());
}
PProjectUnit Project::findUnit(const QString &filename)
{
foreach(PProjectUnit unit, mUnits) {
if (QString::compare(unit->fileName(),filename, PATH_SENSITIVITY)==0)
return unit;
}
return PProjectUnit();
return mUnits.value(filename,PProjectUnit());
}
PProjectUnit Project::findUnit(const Editor *editor)
@ -854,6 +838,9 @@ bool Project::assignTemplate(const std::shared_ptr<ProjectTemplate> aTemplate, b
if (!aTemplate) {
return true;
}
mModel.beginUpdate();
mRootNode = makeProjectNode();
mOptions = aTemplate->options();
mOptions.compilerSet = pSettings->compilerSets().defaultIndex();
mOptions.isCpp = useCpp;
@ -921,7 +908,7 @@ bool Project::assignTemplate(const std::shared_ptr<ProjectTemplate> aTemplate, b
}
}
}
rebuildNodes();
mModel.endUpdate();
return true;
}
@ -1188,17 +1175,16 @@ PProjectUnit Project::addUnit(const QString &inFileName, PProjectModelNode paren
newUnit->setCompileCpp(false);
newUnit->setLink(false);
}
if (mOptions.modelType == ProjectModelType::FileSystem)
newUnit->setFolder(getNodePath(parentNode));
newUnit->setPriority(1000);
newUnit->setOverrideBuildCmd(false);
newUnit->setBuildCmd("");
PProjectModelNode node = makeNewFileNode(extractFileName(newUnit->fileName()),
newUnit->id(),
PProjectModelNode node = makeNewFileNode(newUnit,
newUnit->priority(), parentNode);
node->unitIndex = newUnit->id();
newUnit->setNode(node);
mUnits.insert(newUnit->id(),newUnit);
mUnits.insert(newUnit->fileName(),newUnit);
setModified(true);
return newUnit;
@ -1487,6 +1473,17 @@ void Project::buildPrivateResource(bool forceSave)
stringsToFile(contents,hFile);
}
void Project::closeAllUnits()
{
foreach (PProjectUnit unit, mUnits) {
Editor * editor = unitEditor(unit);
if (editor) {
editor->setInProject(false);
mEditorList->forceCloseEditor(editor);
}
}
}
void Project::checkProjectFileForUpdate(SimpleIni &ini)
{
bool cnvt = false;
@ -1537,10 +1534,10 @@ void Project::checkProjectFileForUpdate(SimpleIni &ini)
QMessageBox::Ok);
}
void Project::closeUnit(int id)
void Project::closeUnit(PProjectUnit& unit)
{
PProjectUnit unit = findUnitById(id);
Editor * editor =unitEditor(unit);
saveLayout();
Editor * editor = unitEditor(unit);
if (editor) {
editor->setInProject(false);
mEditorList->forceCloseEditor(editor);
@ -1563,12 +1560,14 @@ void Project::createFolderNodes()
node = makeNewFolderNode(s.mid(0,i),node);
else
node = findnode;
node->unitIndex = -1;
if (!node->isUnit) {
qDebug()<<"node "<<node->text<<"is not a folder:"<<s;
node = mRootNode;
}
s.remove(0,i+1);
i = s.indexOf('/');
}
node = makeNewFolderNode(s, node);
node->unitIndex = -1;
mCustomFolderNodes.append(node);
}
}
@ -1715,11 +1714,11 @@ QString Project::getNodePath(PProjectModelNode node)
if (!node)
return result;
if (node->unitIndex>=0) // not a folder
if (node->isUnit) // not a folder
return result;
PProjectModelNode p = node;
while (p && p->unitIndex==-1 && p!=mRootNode) {
while (p && !p->isUnit && p!=mRootNode) {
if (!result.isEmpty())
result = p->text + "/" + result;
else
@ -1729,11 +1728,6 @@ QString Project::getNodePath(PProjectModelNode node)
return result;
}
int Project::getUnitFromString(const QString &s)
{
return findUnitId(s);
}
PProjectModelNode Project::getParentFileSystemFolderNode(const QString &filename)
{
QFileInfo fileInfo(filename);
@ -1763,40 +1757,50 @@ void Project::incrementBuildNumber()
PProjectUnit Project::loadLayout()
{
SimpleIni layIni;
SI_Error error = layIni.LoadFile(changeFileExt(filename(), "layout").toLocal8Bit());
if (error!=SI_OK)
QString jsonFilename = changeFileExt(filename(), "layout");
qDebug()<<"read file"<<jsonFilename;
QFile file(jsonFilename);
if (!file.open(QIODevice::ReadOnly))
return PProjectUnit();
QString focusedFilename = fromByteArray(layIni.GetValue("Editors","Focused"));
//TopRight := layIni.ReadInteger('Editors', 'FocusedRight', -1);
QByteArray content = file.readAll();
QJsonParseError parseError;
QJsonDocument doc(QJsonDocument::fromJson(content,&parseError));
file.close();
if (parseError.error!=QJsonParseError::NoError)
return PProjectUnit();
QJsonObject jsonRoot=doc.object();
QJsonArray jsonLayouts=jsonRoot["editorLayouts"].toArray();
QHash<int,PProjectEditorLayout> opennedMap;
SimpleIni::TNamesDepend sections;
layIni.GetAllSections(sections);
QSet<QString> sectionNames;
for(const SimpleIni::Entry& entry:sections) {
QString key(entry.pItem);
sectionNames.insert(key);
}
foreach (PProjectUnit unit,mUnits) {
QByteArray groupName = QString("E_%1").arg(unit->fileName()).toUtf8();
if (sectionNames.contains(groupName)) {
for (int i=0;i<jsonLayouts.size();i++) {
QJsonObject jsonLayout = jsonLayouts[i].toObject();
QString unitFilename = jsonLayout["filename"].toString();
if (mUnits.contains(unitFilename)) {
PProjectEditorLayout editorLayout = std::make_shared<ProjectEditorLayout>();
editorLayout->filename=unit->fileName();
editorLayout->topLine=layIni.GetLongValue(groupName,"TopLine");
editorLayout->leftChar=layIni.GetLongValue(groupName,"LeftChar");
editorLayout->caretX=layIni.GetLongValue(groupName,"CursorCol");
editorLayout->caretY=layIni.GetLongValue(groupName,"CursorRow");
int order = layIni.GetLongValue(groupName,"Order",-1);
editorLayout->filename=unitFilename;
editorLayout->topLine=jsonLayout["topLine"].toInt();
editorLayout->leftChar=jsonLayout["leftChar"].toInt();
editorLayout->caretX=jsonLayout["caretX"].toInt();
editorLayout->caretY=jsonLayout["caretY"].toInt();
int order = jsonLayout["order"].toInt(-1);
if (order>=0)
opennedMap.insert(order,editorLayout);
}
}
for (int i=0;i<mUnits.count();i++) {
PProjectEditorLayout editorLayout = opennedMap.value(i,PProjectEditorLayout());
if (editorLayout) {
openUnit(editorLayout);
PProjectUnit unit = findUnit(editorLayout->filename);
openUnit(unit,editorLayout);
}
}
QString focusedFilename = jsonRoot["focused"].toString();
if (!focusedFilename.isEmpty()) {
PProjectUnit unit = findUnit(focusedFilename);
if (unit) {
Editor * editor = unitEditor(unit);
@ -1804,6 +1808,8 @@ PProjectUnit Project::loadLayout()
editor->activate();
}
return unit;
}
return PProjectUnit();
}
void Project::loadOptions(SimpleIni& ini)
@ -2050,16 +2056,37 @@ void Project::loadUnitLayout(Editor *e)
{
if (!e)
return;
SimpleIni layIni;
SI_Error error;
error = layIni.LoadFile(changeFileExt(filename(), "layout").toLocal8Bit());
if (error != SI_Error::SI_OK)
QString jsonFilename = changeFileExt(filename(), "layout");
QFile file(jsonFilename);
if (!file.open(QIODevice::ReadOnly))
return;
QByteArray groupName = (QString("E_%1").arg(e->filename())).toUtf8();
e->setCaretY(layIni.GetLongValue(groupName,"CursorRow",1));
e->setCaretX(layIni.GetLongValue(groupName,"CursorCol",1));
e->setTopLine(layIni.GetLongValue(groupName,"TopLine",1));
e->setLeftChar(layIni.GetLongValue(groupName,"LeftChar",1));
QByteArray content = file.readAll();
QJsonParseError parseError;
QJsonDocument doc{QJsonDocument::fromJson(content,&parseError)};
file.close();
if (parseError.error!=QJsonParseError::NoError)
return;
QJsonObject jsonRoot=doc.object();
QJsonArray jsonLayouts=jsonRoot["editorLayouts"].toArray();
QHash<int,PProjectEditorLayout> opennedMap;
for (int i=0;i<jsonLayouts.size();i++) {
QJsonObject jsonLayout = jsonLayouts[i].toObject();
QString unitFilename = jsonLayout["filename"].toString();
if (unitFilename.compare(e->filename(),PATH_SENSITIVITY)==0) {
qDebug()<<i<<unitFilename<<e->filename();
e->setCaretY(jsonLayout["caretY"].toInt());
e->setCaretX(jsonLayout["caretX"].toInt());
e->setTopLine(jsonLayout["topLine"].toInt());
e->setLeftChar(jsonLayout["leftChar"].toInt());
return;
}
}
}
PCppParser Project::cppParser()
@ -2067,23 +2094,6 @@ PCppParser Project::cppParser()
return mParser;
}
int Project::findUnitId(const QString &fileName) const
{
QDir dir(directory());
foreach (const PProjectUnit& unit, mUnits) {
if (dir.absoluteFilePath(fileName) == dir.absoluteFilePath(unit->fileName()))
return unit->id();
}
return -1;
}
int Project::findUnitId(const Editor *editor) const
{
if (!editor)
return -1;
return findUnitId(editor->filename());
}
void Project::removeFolderRecurse(PProjectModelNode node)
{
if (!node)
@ -2092,13 +2102,13 @@ void Project::removeFolderRecurse(PProjectModelNode node)
for (int i=node->children.count()-1;i>=0;i++) {
PProjectModelNode childNode = node->children[i];
// Remove folder inside folder
if (childNode->unitIndex<0 && childNode->level>0) {
if (!childNode->isUnit && childNode->level>0) {
removeFolderRecurse(childNode);
// Or remove editors at this level
} else if (childNode->unitIndex >= 0 && childNode->level > 0) {
} else if (childNode->isUnit && childNode->level > 0) {
// Remove editor in folder from project
int editorIndex = childNode->unitIndex;
if (!removeUnit(editorIndex,true))
PProjectUnit unit = childNode->pUnit.lock();
if (!removeUnit(unit,true))
return;
}
}
@ -2113,7 +2123,7 @@ void Project::updateFolderNode(PProjectModelNode node)
{
for (int i=0;i<node->children.count();i++){
PProjectModelNode child = node->children[i];
if (child->unitIndex<0) {
if (!child->isUnit) {
mFolders.append(getNodePath(child));
updateFolderNode(child);
}
@ -2162,6 +2172,18 @@ QStringList Project::binDirs()
return lst;
}
void Project::renameFolderNode(PProjectModelNode node, const QString newName)
{
if (!node)
return;
if (node->isUnit)
return;
node->text = newName;
updateFolders();
setModified(true);
emit nodeRenamed();
}
EditorList *Project::editorList() const
{
return mEditorList;
@ -2214,14 +2236,11 @@ const QString &Project::filename() const
return mFilename;
}
int ProjectUnit::mIdGenerator=0;
ProjectUnit::ProjectUnit(Project* parent)
{
mNode = nullptr;
mParent = parent;
mFileMissing = false;
mId=mIdGenerator++;
mPriority=0;
}
@ -2230,11 +2249,6 @@ Project *ProjectUnit::parent() const
return mParent;
}
void ProjectUnit::setParent(Project* newParent)
{
mParent = newParent;
}
const QString &ProjectUnit::fileName() const
{
return mFileName;
@ -2416,16 +2430,6 @@ void ProjectUnit::setFileMissing(bool newDontSave)
mFileMissing = newDontSave;
}
int ProjectUnit::id() const
{
return mId;
}
void ProjectUnit::setId(int newId)
{
mId = newId;
}
ProjectModel::ProjectModel(Project *project, QObject *parent):
QAbstractItemModel(parent),
mProject(project)
@ -2547,8 +2551,10 @@ QVariant ProjectModel::data(const QModelIndex &index, int role) const
return p->text;
} else if (role == Qt::DecorationRole) {
QIcon icon;
if (p->unitIndex>=0) {
icon = mIconProvider->icon(mProject->findUnitById(p->unitIndex)->fileName());
if (p->isUnit) {
PProjectUnit unit = p->pUnit.lock();
if (unit)
icon = mIconProvider->icon(unit->fileName());
} else {
if (p == mProject->rootNode().get()) {
QString branch;
@ -2585,12 +2591,12 @@ Qt::ItemFlags ProjectModel::flags(const QModelIndex &index) const
return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsEditable;
if (mProject && mProject->modelType() == ProjectModelType::FileSystem) {
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
if (p->unitIndex>=0)
if (p->isUnit)
flags.setFlag(Qt::ItemIsEditable);
return flags;
} else {
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
if (p->unitIndex<0) {
if (!p->isUnit) {
flags.setFlag(Qt::ItemIsDropEnabled);
flags.setFlag(Qt::ItemIsDragEnabled,false);
}
@ -2615,10 +2621,10 @@ bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int
emit dataChanged(index,index);
return true;
}
int idx = node->unitIndex;
if (idx >= 0) {
PProjectUnit unit = node->pUnit.lock();
if (unit) {
//change unit name
PProjectUnit unit = mProject->findUnitById(idx);
QString newName = value.toString().trimmed();
if (newName.isEmpty())
return false;
@ -2642,9 +2648,9 @@ bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int
mProject->editorList()->closeEditor(e);
// Remove it from the current project...
int projindex = mProject->findUnitId(newName);
if (projindex>=0) {
mProject->removeUnit(projindex,false);
PProjectUnit unit = mProject->findUnit(newName);
if (unit) {
mProject->removeUnit(unit,false);
}
// All references to the file are removed. Delete the file from disk
@ -2674,17 +2680,13 @@ bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int
QMessageBox::Ok);
return false;
}
mProject->renameUnit(idx,newName);
mProject->renameUnit(unit,newName);
// Add new filename to file minitor
mProject->fileSystemWatcher()->addPath(newName);
//suffix changed
if (mProject && mProject->modelType() == ProjectModelType::FileSystem
&& QFileInfo(oldName).suffix()!=QFileInfo(newName).suffix()) {
mProject->rebuildNodes();
} else
emit dataChanged(index,index);
mProject->saveAll();
return true;
} else {
//change folder name
@ -2693,10 +2695,11 @@ bool ProjectModel::setData(const QModelIndex &index, const QVariant &value, int
return false;
if (newName == node->text)
return false;
node->text = newName;
mProject->updateFolders();
mProject->saveAll();
mProject->renameFolderNode(node,newName);
emit dataChanged(index,index);
mProject->saveAll();
return true;
}
@ -2767,7 +2770,7 @@ bool ProjectModel::canDropMimeData(const QMimeData * data, Qt::DropAction action
// }
ProjectModelNode* p= static_cast<ProjectModelNode*>(idx.internalPointer());
PProjectModelNode node = mProject->pointerToNode(p);
if (node->unitIndex>=0)
if (node->isUnit)
return false;
QByteArray encoded = data->data(format);
QDataStream stream(&encoded, QIODevice::ReadOnly);
@ -2835,8 +2838,8 @@ bool ProjectModel::dropMimeData(const QMimeData *data, Qt::DropAction action, in
beginInsertRows(newParentIndex,node->children.count(),node->children.count());
droppedNode->parent = node;
node->children.append(droppedNode);
if (droppedNode->unitIndex>=0) {
PProjectUnit unit = mProject->findUnitById(droppedNode->unitIndex);
if (droppedNode->isUnit) {
PProjectUnit unit = droppedNode->pUnit.lock();
unit->setFolder(mProject->getNodePath(node));
}
endInsertRows();
@ -2863,8 +2866,10 @@ QMimeData *ProjectModel::mimeData(const QModelIndexList &indexes) const
for (; it != indexes.end(); ++it) {
stream << (qint32)((*it).row()) << (qint32)((*it).column()) << (quintptr)((*it).internalPointer());
ProjectModelNode* p = static_cast<ProjectModelNode*>((*it).internalPointer());
if (p && p->unitIndex>=0) {
urls.append(QUrl::fromLocalFile(mProject->findUnitById(p->unitIndex)->fileName()));
if (p && p->isUnit) {
PProjectUnit unit = p->pUnit.lock();
if (unit)
urls.append(QUrl::fromLocalFile(unit->fileName()));
}
}
if (!urls.isEmpty())
@ -2893,9 +2898,9 @@ bool ProjectModelSortFilterProxy::lessThan(const QModelIndex &source_left, const
return true;
if (!pRight)
return false;
if (pLeft->unitIndex<0 && pRight->unitIndex>=0)
if (!pLeft->isUnit && pRight->isUnit)
return true;
if (pLeft->unitIndex>=0 && pRight->unitIndex<0)
if (pLeft->isUnit && !pRight->isUnit)
return false;
if (pLeft->priority!=pRight->priority)
return pLeft->priority>pRight->priority;

View File

@ -44,12 +44,15 @@ struct ProjectModelItemRecord {
QString fullPath;
};
class ProjectUnit;
struct ProjectModelNode;
using PProjectModelNode = std::shared_ptr<ProjectModelNode>;
struct ProjectModelNode {
QString text;
std::weak_ptr<ProjectModelNode> parent;
int unitIndex;
bool isUnit;
std::weak_ptr<ProjectUnit> pUnit;
int priority;
QList<PProjectModelNode> children;
ProjectModelNodeType folderNodeType;
@ -71,7 +74,6 @@ class ProjectUnit {
public:
explicit ProjectUnit(Project* parent);
Project* parent() const;
void setParent(Project* newParent);
const QString &fileName() const;
void setFileName(QString newFileName);
bool isNew() const;
@ -102,10 +104,6 @@ public:
bool FileMissing() const;
void setFileMissing(bool newDontSave);
int id() const;
void setId(int newId);
private:
Project* mParent;
QString mFileName;
@ -120,8 +118,6 @@ private:
QByteArray mEncoding;
PProjectModelNode mNode;
bool mFileMissing;
int mId;
static int mIdGenerator;
};
using PProjectUnit = std::shared_ptr<ProjectUnit>;
@ -206,46 +202,37 @@ public:
PProjectModelNode parentNode);
QString folder();
void buildPrivateResource(bool forceSave=false);
void closeUnit(int id);
void closeAllUnits();
void closeUnit(PProjectUnit& unit);
PProjectUnit doAutoOpen();
bool fileAlreadyExists(const QString& s);
QString getNodePath(PProjectModelNode node);
int getUnitFromString(const QString& s);
void incrementBuildNumber();
PProjectUnit newUnit(PProjectModelNode parentNode,
const QString& customFileName="");
Editor* openUnit(int index, bool forceOpen=true);
Editor* openUnit(PProjectEditorLayout editorLayout);
Editor* openUnit(PProjectUnit& unit, bool forceOpen=true);
Editor* openUnit(PProjectUnit& unit, const PProjectEditorLayout& layout);
Editor* unitEditor(const PProjectUnit& unit) const;
Editor* unitEditor(const ProjectUnit* unit) const;
Editor* unitEditor(int id) const {
PProjectUnit unit=mUnits.value(id,PProjectUnit());
if (!unit)
return nullptr;
return unitEditor(unit);
}
QList<PProjectUnit> unitList();
PProjectModelNode pointerToNode(ProjectModelNode * p, PProjectModelNode parent=PProjectModelNode());
void rebuildNodes();
bool removeUnit(int id, bool doClose, bool removeFile = false);
bool removeUnit(PProjectUnit& unit, bool doClose, bool removeFile = false);
bool removeFolder(PProjectModelNode node);
void resetParserProjectFiles();
void saveAll(); // save [Project] and all [UnitX]
void saveLayout(); // save all [UnitX]
void saveOptions();
void renameUnit(int idx, const QString& sFileName);
void renameUnit(PProjectUnit& unit, const QString& sFileName);
bool saveUnits();
PProjectUnit findUnitById(int id);
PProjectUnit findUnit(const QString& filename);
PProjectUnit findUnit(const Editor* editor);
int findUnitId(const QString& fileName) const;
int findUnitId(const Editor* editor) const;
void associateEditor(Editor* editor);
void associateEditorToUnit(Editor* editor, PProjectUnit unit);
bool setCompileOption(const QString &key, const QString &value);
@ -283,9 +270,12 @@ public:
QStringList binDirs();
void renameFolderNode(PProjectModelNode node, const QString newName);
void loadUnitLayout(Editor *e);
signals:
void nodesChanged();
void nodeRenamed();
void modifyChanged(bool value);
private:
void checkProjectFileForUpdate(SimpleIni& ini);
void createFolderNodes();
@ -296,7 +286,6 @@ private:
PProjectModelNode getCustomeFolderNodeFromName(const QString& name);
void loadOptions(SimpleIni& ini);
PProjectUnit loadLayout();
void loadUnitLayout(Editor *e);
PProjectModelNode makeNewFolderNode(
const QString& folderName,
@ -304,8 +293,8 @@ private:
ProjectModelNodeType nodeType=ProjectModelNodeType::Folder,
int priority=0);
PProjectModelNode makeNewFileNode(
const QString& fileName,
int unitId,
//const QString& fileName,
PProjectUnit unit,
int priority,
PProjectModelNode newParent);
PProjectModelNode makeProjectNode();
@ -315,7 +304,7 @@ private:
void updateCompilerSetType();
private:
QHash<int,PProjectUnit> mUnits;
QHash<QString,PProjectUnit> mUnits;
ProjectOptions mOptions;
QString mFilename;
QString mName;

View File

@ -47,7 +47,7 @@ void ProjectFilesWidget::doSave()
{
for (int i=0;i<mUnits.count();i++) {
PProjectUnit unitCopy = mUnits[i];
PProjectUnit unit = pMainWindow->project()->findUnitById(unitCopy->id());
PProjectUnit unit = pMainWindow->project()->findUnit(unitCopy->fileName());
unit->setPriority(unitCopy->priority());
unit->setCompile(unitCopy->compile());
unit->setLink(unitCopy->link());
@ -70,11 +70,13 @@ PProjectUnit ProjectFilesWidget::currentUnit()
ProjectModelNode* node = static_cast<ProjectModelNode*>(index.internalPointer());
if (!node)
return PProjectUnit();
int idx = node->unitIndex;
if (idx>=0) {
foreach (PProjectUnit unit, mUnits) {
if (unit->id() == idx)
return unit;
if (!node->isUnit)
return PProjectUnit();
PProjectUnit unit=node->pUnit.lock();
if (unit) {
foreach (PProjectUnit tmpUnit, mUnits) {
if (tmpUnit->fileName() == unit->fileName())
return tmpUnit;
}
}
return PProjectUnit();
@ -88,7 +90,6 @@ void ProjectFilesWidget::copyUnits()
mUnits.clear();
foreach (const PProjectUnit& unit, project->unitList()) {
PProjectUnit unitCopy = std::make_shared<ProjectUnit>(project.get());
unitCopy->setId(unit->id());
unitCopy->setPriority(unit->priority());
unitCopy->setCompile(unit->compile());
unitCopy->setLink(unit->link());
@ -145,9 +146,8 @@ void ProjectFilesWidget::on_treeProject_doubleClicked(const QModelIndex &index)
disableFileOptions();
return;
}
int i = node->unitIndex;
if (i>=0) {
PProjectUnit unit = mUnits[i];
PProjectUnit unit = node->pUnit.lock();
if (unit) {
ui->grpFileOptions->setEnabled(true);
ui->spinPriority->setValue(unit->priority());
ui->chkCompile->setChecked(unit->compile());