RedPanda-CPP/RedPandaIDE/editorlist.cpp

507 lines
14 KiB
C++
Raw Normal View History

2021-12-26 23:18:28 +08:00
/*
* Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
2021-04-06 23:10:57 +08:00
#include "editorlist.h"
2021-04-07 21:13:15 +08:00
#include "editor.h"
2021-04-09 10:08:05 +08:00
#include <QMessageBox>
2021-04-07 22:44:08 +08:00
#include <QVariant>
2021-04-09 10:08:05 +08:00
#include <mainwindow.h>
2021-06-23 22:38:02 +08:00
#include <QFileInfo>
2021-08-01 23:24:37 +08:00
#include "settings.h"
2021-09-12 00:17:15 +08:00
#include "project.h"
#include "systemconsts.h"
#include "visithistorymanager.h"
#include <QApplication>
2021-04-06 23:10:57 +08:00
2021-04-07 21:13:15 +08:00
EditorList::EditorList(QTabWidget* leftPageWidget,
QTabWidget* rightPageWidget,
QSplitter* splitter,
QWidget* panel,
QObject* parent):
QObject(parent),
2021-09-12 00:17:15 +08:00
mLayout(LayoutShowType::lstLeft),
2021-04-07 21:13:15 +08:00
mLeftPageWidget(leftPageWidget),
mRightPageWidget(rightPageWidget),
mSplitter(splitter),
mPanel(panel),
mUpdateCount(0)
2021-04-06 23:10:57 +08:00
{
}
2021-04-07 21:13:15 +08:00
Editor* EditorList::newEditor(const QString& filename, const QByteArray& encoding,
Project *pProject, bool newFile,
2021-04-07 21:13:15 +08:00
QTabWidget* page) {
QTabWidget * parentPageControl = nullptr;
if (page == nullptr)
parentPageControl = getNewEditorPageControl();
2021-04-07 21:13:15 +08:00
else
parentPageControl = page;
if (fileExists(filename)) {
pMainWindow->fileSystemWatcher()->addPath(filename);
}
// parentPageControl takes the owner ship
Editor * e = new Editor(parentPageControl,filename,encoding,pProject,newFile,parentPageControl);
connect(e, &Editor::renamed, this, &EditorList::onEditorRenamed);
2021-09-07 16:49:35 +08:00
updateLayout();
2022-02-15 17:22:44 +08:00
connect(e,&Editor::fileSaved,
pMainWindow, &MainWindow::onFileSaved);
2021-09-12 00:17:15 +08:00
return e;
2021-04-07 21:13:15 +08:00
}
2021-04-09 10:08:05 +08:00
QTabWidget* EditorList::getNewEditorPageControl() const {
return getFocusedPageControl();
2021-04-07 21:13:15 +08:00
}
2021-04-09 10:08:05 +08:00
QTabWidget* EditorList::getFocusedPageControl() const {
switch(mLayout) {
case LayoutShowType::lstLeft:
return mLeftPageWidget;
case LayoutShowType::lstRight:
return mRightPageWidget;
case LayoutShowType::lstBoth: {
Editor* rightEditor = dynamic_cast<Editor*>(mRightPageWidget->currentWidget());
if (!rightEditor)
return mLeftPageWidget;
if (rightEditor->hasFocus())
return mRightPageWidget;
Editor *leftEditor = dynamic_cast<Editor*>(mLeftPageWidget->currentWidget());
if (!leftEditor)
return mRightPageWidget;
if (leftEditor->hasFocus())
return mLeftPageWidget;
if (rightEditor->lastFocusOutTime() > leftEditor->lastFocusOutTime())
return mRightPageWidget;
return mLeftPageWidget;
}
default:
return nullptr;
}
2021-04-09 10:08:05 +08:00
}
2021-09-07 16:49:35 +08:00
void EditorList::showLayout(LayoutShowType layout)
{
if (layout == mLayout)
return;
mLayout = layout;
// Apply widths if layout does not change
switch(mLayout) {
case LayoutShowType::lstLeft:
mLeftPageWidget->setVisible(true);
mRightPageWidget->setVisible(false);
break;
case LayoutShowType::lstRight:
mLeftPageWidget->setVisible(false);
mRightPageWidget->setVisible(true);
break;
case LayoutShowType::lstBoth:
mLeftPageWidget->setVisible(true);
mRightPageWidget->setVisible(true);
{
QList<int> sizes=mSplitter->sizes();
int total = sizes[0]+sizes[1];
sizes[0] = total / 2;
sizes[1] = total - sizes[0];
mSplitter->setSizes(sizes);
}
break;
2021-09-07 16:49:35 +08:00
}
}
void EditorList::doRemoveEditor(Editor *e)
{
QTabWidget* parentPage=e->pageControl();
int index = parentPage->indexOf(e);
parentPage->removeTab(index);
pMainWindow->fileSystemWatcher()->removePath(e->filename());
pMainWindow->caretList().removeEditor(e);
pMainWindow->updateCaretActions();
e->setParent(nullptr);
delete e;
}
void EditorList::onEditorRenamed(const QString &oldFilename, const QString &newFilename, bool firstSave)
{
emit editorRenamed(oldFilename, newFilename, firstSave);
}
2021-10-20 18:05:43 +08:00
QTabWidget *EditorList::rightPageWidget() const
{
return mRightPageWidget;
}
QTabWidget *EditorList::leftPageWidget() const
{
return mLeftPageWidget;
}
Editor* EditorList::getEditor(int index, QTabWidget* tabsWidget) const {
2021-04-07 22:44:08 +08:00
QTabWidget* selectedWidget;
if (tabsWidget == nullptr) {
selectedWidget = getFocusedPageControl();
2021-04-07 22:44:08 +08:00
} else {
selectedWidget = tabsWidget;
}
if (!selectedWidget)
return nullptr;
2021-04-07 22:44:08 +08:00
if (index == -1) {
2021-04-09 10:08:05 +08:00
index = selectedWidget->currentIndex();
2021-04-07 22:44:08 +08:00
}
2021-04-09 10:08:05 +08:00
if (index<0 || index >= selectedWidget->count()) {
return nullptr;
2021-04-09 10:08:05 +08:00
}
2021-04-09 17:48:25 +08:00
return (Editor*)selectedWidget->widget(index);
2021-04-07 22:44:08 +08:00
}
bool EditorList::closeEditor(Editor* editor, bool transferFocus, bool force) {
if (editor == nullptr)
2021-04-09 10:08:05 +08:00
return false;
if (force) {
editor->save(true,false);
2021-05-24 00:41:00 +08:00
} else if ( (editor->modified()) && (!editor->empty())) {
2021-04-09 10:08:05 +08:00
// ask user if he wants to save
QMessageBox::StandardButton reply;
reply = QMessageBox::question(editor,QObject::tr("Save"),
QString(QObject::tr("Save changes to %1?")).arg(editor->filename()),
2021-04-09 10:08:05 +08:00
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel);
if (reply == QMessageBox::Cancel) {
return false;
} else if (reply == QMessageBox::Yes) {
if (!editor->save(false,false)) {
return false;
}
}
}
beginUpdate();
// if (transferFocus && (editor->pageControl()->currentWidget()==editor)) {
// //todo: activate & focus the previous editor
// }
2021-04-09 10:08:05 +08:00
2021-09-12 00:17:15 +08:00
if (editor->inProject() && pMainWindow->project()) {
if (fileExists(pMainWindow->project()->directory())) {
PProjectUnit unit = pMainWindow->project()->findUnit(editor);
pMainWindow->project()->closeUnit(unit);
} else {
editor->setProject(nullptr);
}
2021-09-12 00:17:15 +08:00
} else {
if (!editor->isNew() && pMainWindow->visitHistoryManager()->addFile(editor->filename())) {
2021-09-12 00:17:15 +08:00
pMainWindow->rebuildOpenedFileHisotryMenu();
}
editor->clearBreakpoints();
doRemoveEditor(editor);
2021-08-01 23:24:37 +08:00
}
2021-09-12 00:17:15 +08:00
updateLayout();
if (!force && transferFocus) {
2021-09-12 00:17:15 +08:00
editor = getEditor();
if (editor) {
2021-11-01 23:37:54 +08:00
editor->activate();
pMainWindow->updateClassBrowserForEditor(editor);
2022-10-28 09:47:34 +08:00
}
2021-09-12 00:17:15 +08:00
}
editor = getEditor();
if (!editor) {
pMainWindow->updateClassBrowserForEditor(nullptr);
}
emit editorClosed();
endUpdate();
2021-04-07 22:44:08 +08:00
return true;
}
2021-04-09 10:08:05 +08:00
bool EditorList::swapEditor(Editor *editor)
{
Q_ASSERT(editor!=nullptr);
beginUpdate();
auto action = finally([this](){
endUpdate();
});
//remember old index
QTabWidget* fromPageControl = editor->pageControl();
if (fromPageControl == mLeftPageWidget) {
editor->setPageControl(mRightPageWidget);
} else {
editor->setPageControl(mLeftPageWidget);
}
updateLayout();
editor->activate();
return true;
}
void EditorList::saveAll()
{
for (int i=0;i<pageCount();i++) {
Editor * e= (*this)[i];
if (e->modified())
e->save();
}
}
bool EditorList::saveAllForProject()
{
for (int i=0;i<pageCount();i++) {
Editor * e= (*this)[i];
if (e->modified() && e->inProject()) {
if (!e->save())
return false;
}
}
return true;
}
bool EditorList::projectEditorsModified()
{
for (int i=0;i<pageCount();i++) {
Editor * e= (*this)[i];
if (e->modified() && e->inProject()) {
return true;
}
}
return false;
}
void EditorList::clearProjectEditorsModified()
{
for (int i=0;i<pageCount();i++) {
Editor * e= (*this)[i];
if (e->inProject()) {
e->setModified(false);
}
}
}
2021-04-09 10:08:05 +08:00
void EditorList::beginUpdate() {
if (mUpdateCount==0) {
mPanel->setUpdatesEnabled(false);
}
mUpdateCount++;
}
void EditorList::endUpdate() {
mUpdateCount--;
if (mUpdateCount==0) {
mPanel->setUpdatesEnabled(true);
mPanel->update();
}
}
2021-06-07 11:02:03 +08:00
void EditorList::applySettings()
{
for (int i=0;i<mLeftPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mLeftPageWidget->widget(i));
e->applySettings();
}
for (int i=0;i<mRightPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mRightPageWidget->widget(i));
e->applySettings();
}
}
2021-06-20 14:30:47 +08:00
void EditorList::applyColorSchemes(const QString& name)
{
for (int i=0;i<mLeftPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mLeftPageWidget->widget(i));
e->applyColorScheme(name);
}
for (int i=0;i<mRightPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mRightPageWidget->widget(i));
e->applyColorScheme(name);
}
}
bool EditorList::isFileOpened(const QString &fullfilepath) const
2021-06-23 22:38:02 +08:00
{
QFileInfo fileInfo(fullfilepath);
2021-06-23 22:38:02 +08:00
QString filename = fileInfo.absoluteFilePath();
for (int i=0;i<mLeftPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mLeftPageWidget->widget(i));
if (e->filename().compare(filename)==0 || e->filename().compare(fullfilepath)==0)
2021-06-23 22:38:02 +08:00
return true;
}
for (int i=0;i<mRightPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mRightPageWidget->widget(i));
if (e->filename().compare(filename)==0 || e->filename().compare(fullfilepath)==0)
2021-06-23 22:38:02 +08:00
return true;
}
return false;
}
bool EditorList::hasFilename(const QString &filename) const
{
for (int i=0;i<mLeftPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mLeftPageWidget->widget(i));
QFileInfo fileInfo(e->filename());
QString name = fileInfo.fileName();
if (name.compare(filename, PATH_SENSITIVITY)==0 )
return true;
}
for (int i=0;i<mRightPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mRightPageWidget->widget(i));
QFileInfo fileInfo(e->filename());
QString name = fileInfo.fileName();
if (name.compare(filename, PATH_SENSITIVITY)==0 )
return true;
}
return false;
}
int EditorList::pageCount() const
2021-07-26 00:22:08 +08:00
{
return mLeftPageWidget->count()+mRightPageWidget->count();
}
void EditorList::selectNextPage()
{
QTabWidget * pageControl = getFocusedPageControl();
if (pageControl && pageControl->count()>0) {
pageControl->setCurrentIndex(
(pageControl->currentIndex()+1) % pageControl->count()
);
}
}
void EditorList::selectPreviousPage()
{
QTabWidget * pageControl = getFocusedPageControl();
if (pageControl && pageControl->count()>0) {
pageControl->setCurrentIndex(
(pageControl->currentIndex()+pageControl->count()-1) % pageControl->count()
);
}
}
2021-07-26 00:22:08 +08:00
Editor *EditorList::operator[](int index)
{
if (index>=0 && index<mLeftPageWidget->count()) {
return static_cast<Editor*>(mLeftPageWidget->widget(index));
}
index -= mLeftPageWidget->count();
if (index>=0 && index<mRightPageWidget->count()) {
return static_cast<Editor*>(mRightPageWidget->widget(index));
}
return nullptr;
}
2021-04-09 10:08:05 +08:00
bool EditorList::closeAll(bool force) {
// beginUpdate();
// auto end = finally([this] {
// this->endUpdate();
// });
2021-04-09 17:48:25 +08:00
while (mLeftPageWidget->count()>0) {
if (!closeEditor(getEditor(0,mLeftPageWidget),false,force)) {
return false;
}
}
while (mRightPageWidget->count()>0) {
if (!closeEditor(getEditor(0,mRightPageWidget),false,force)) {
return false;
}
}
return true;
2021-04-09 10:08:05 +08:00
}
2021-04-11 21:33:08 +08:00
bool EditorList::closeOthers(Editor *editor)
{
QList<Editor*> editors;
for (int i=0;i<mLeftPageWidget->count();i++) {
editors.append(static_cast<Editor*>(mLeftPageWidget->widget(i)));
}
for (int i=0;i<mRightPageWidget->count();i++) {
editors.append(static_cast<Editor*>(mRightPageWidget->widget(i)));
}
for (Editor* e: editors ) {
if (e!=editor) {
if (!closeEditor(e,false,false)) {
return false;
}
}
}
return true;
}
2021-09-07 16:49:35 +08:00
void EditorList::forceCloseEditor(Editor *editor)
{
beginUpdate();
doRemoveEditor(editor);
2021-09-07 16:49:35 +08:00
// Force layout update when creating, destroying or moving editors
updateLayout();
endUpdate();
emit editorClosed();
2021-09-07 16:49:35 +08:00
}
Editor* EditorList::getOpenedEditorByFilename(QString filename) const
2021-04-11 21:33:08 +08:00
{
if (filename.isEmpty())
return nullptr;
2021-04-11 21:33:08 +08:00
for (int i=0;i<mLeftPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mLeftPageWidget->widget(i));
if (!e)
continue;
if (e->filename().compare(filename, PATH_SENSITIVITY)==0) {
2021-04-11 21:33:08 +08:00
return e;
}
}
for (int i=0;i<mRightPageWidget->count();i++) {
Editor* e = static_cast<Editor*>(mRightPageWidget->widget(i));
if (!e)
continue;
if (e->filename().compare(filename)==0) {
2021-04-11 21:33:08 +08:00
return e;
}
}
return nullptr;
}
2021-04-29 20:54:44 +08:00
bool EditorList::getContentFromOpenedEditor(const QString &filename, QStringList &buffer) const
2021-08-23 10:16:06 +08:00
{
if (pMainWindow->isQuitting())
return false;
2021-08-23 10:16:06 +08:00
Editor * e= getOpenedEditorByFilename(filename);
if (!e)
return false;
buffer = e->contents();
2021-08-23 10:16:06 +08:00
return true;
}
2021-09-07 16:49:35 +08:00
void EditorList::getVisibleEditors(Editor *&left, Editor *&right) const
2021-09-11 09:21:44 +08:00
{
switch(mLayout) {
case LayoutShowType::lstLeft:
left = getEditor(-1,mLeftPageWidget);
right = nullptr;
break;
case LayoutShowType::lstRight:
left = nullptr;
right = getEditor(-1,mRightPageWidget);
break;
case LayoutShowType::lstBoth:
left = getEditor(-1,mLeftPageWidget);
right = getEditor(-1,mRightPageWidget);
break;
}
}
2021-09-07 16:49:35 +08:00
void EditorList::updateLayout()
{
if (mRightPageWidget->count() == 0)
2021-09-07 16:49:35 +08:00
showLayout(LayoutShowType::lstLeft);
else if (mLeftPageWidget->count() ==0)
2021-09-07 16:49:35 +08:00
showLayout(LayoutShowType::lstRight);
else
showLayout(LayoutShowType::lstBoth);
}