- Suche nach toten Funktionen im Projekt - Doppelklick auf Funktion öffnet die Datei mit der Deklaration
302 lines
7.7 KiB
C++
302 lines
7.7 KiB
C++
#include "EditorPanel.h"
|
|
#include "EditorTab.h"
|
|
#include "CodeEditor.h"
|
|
#include "SearchPanel.h"
|
|
#include "FileSearchPanel.h"
|
|
#include "FunctionListDialog.h"
|
|
#include "DeadCodeDialog.h"
|
|
#include "FunctionIndex.h"
|
|
|
|
#include <QFileInfo>
|
|
#include <QFile>
|
|
#include <QTextDocument>
|
|
#include <QTextBlock>
|
|
|
|
EditorPanel::EditorPanel(Settings *settings, QWidget *parent)
|
|
: QWidget(parent)
|
|
, m_settings(settings)
|
|
{
|
|
setupUi();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Setup
|
|
// ---------------------------------------------------------------------------
|
|
void EditorPanel::setupUi()
|
|
{
|
|
m_layout = new QVBoxLayout(this);
|
|
m_layout->setContentsMargins(0, 0, 0, 0);
|
|
m_layout->setSpacing(0);
|
|
|
|
m_tabWidget = new QTabWidget(this);
|
|
m_tabWidget->setTabsClosable(true);
|
|
m_tabWidget->setMovable(true);
|
|
m_tabWidget->setDocumentMode(true);
|
|
|
|
m_searchPanel = new SearchPanel(this);
|
|
m_fileSearch = new FileSearchPanel(this);
|
|
m_funcDialog = new FunctionListDialog(window());
|
|
m_deadCode = new DeadCodeDialog(window());
|
|
m_funcIndex = new FunctionIndex(this);
|
|
|
|
m_layout->addWidget(m_tabWidget, 1);
|
|
m_layout->addWidget(m_searchPanel, 0);
|
|
m_layout->addWidget(m_fileSearch, 0);
|
|
|
|
connect(m_tabWidget, &QTabWidget::tabCloseRequested,
|
|
this, &EditorPanel::onTabCloseRequested);
|
|
|
|
connect(m_tabWidget, &QTabWidget::currentChanged,
|
|
this, &EditorPanel::onCurrentTabChanged);
|
|
|
|
connect(m_fileSearch, &FileSearchPanel::fileLineRequested,
|
|
this, &EditorPanel::goToLine);
|
|
|
|
connect(m_funcDialog, &FunctionListDialog::fileLineRequested,
|
|
this, &EditorPanel::goToLine);
|
|
|
|
connect(m_deadCode, &DeadCodeDialog::fileLineRequested,
|
|
this, &EditorPanel::goToLine);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Hilfsmethoden
|
|
// ---------------------------------------------------------------------------
|
|
EditorTab *EditorPanel::currentTab() const
|
|
{
|
|
return qobject_cast<EditorTab *>(m_tabWidget->currentWidget());
|
|
}
|
|
|
|
int EditorPanel::findTabForFile(const QString &filePath) const
|
|
{
|
|
EditorTab *tab = m_openTabs.value(filePath, nullptr);
|
|
return tab ? m_tabWidget->indexOf(tab) : -1;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Öffentliche Slots
|
|
// ---------------------------------------------------------------------------
|
|
void EditorPanel::openFile(const QString &filePath)
|
|
{
|
|
const int existing = findTabForFile(filePath);
|
|
if (existing != -1)
|
|
{
|
|
m_tabWidget->setCurrentIndex(existing);
|
|
return;
|
|
}
|
|
|
|
EditorTab *tab = new EditorTab(filePath, m_settings, m_tabWidget);
|
|
const int index = m_tabWidget->addTab(tab, tab->fileName());
|
|
m_tabWidget->setCurrentIndex(index);
|
|
m_tabWidget->setTabToolTip(index, filePath);
|
|
m_openTabs.insert(filePath, tab);
|
|
|
|
// FunctionIndex dem Editor mitgeben für Doppelklick-Navigation
|
|
tab->editor()->setFunctionIndex(m_funcIndex);
|
|
|
|
// Doppelklick auf Funktion → zur Definition springen
|
|
connect(tab->editor(), &CodeEditor::navigateToRequested,
|
|
this, &EditorPanel::goToLine);
|
|
|
|
// Änderungsindikator im Tab-Titel (● = ungespeichert)
|
|
connect(tab->editor()->document(), &QTextDocument::modificationChanged,
|
|
this, [this, tab](bool modified)
|
|
{
|
|
const int idx = m_tabWidget->indexOf(tab);
|
|
if (idx == -1)
|
|
{
|
|
return;
|
|
}
|
|
const QString name = QFileInfo(tab->filePath()).fileName();
|
|
m_tabWidget->setTabText(idx, modified ? "● " + name : name);
|
|
});
|
|
|
|
// Tab-Titel nach "Speichern unter" aktualisieren (neuer Dateiname, kein Punkt)
|
|
connect(tab->editor(), &CodeEditor::fileSaved, this, [this, tab](const QString &savedPath)
|
|
{
|
|
const int idx = m_tabWidget->indexOf(tab);
|
|
if (idx != -1)
|
|
{
|
|
m_tabWidget->setTabText(idx, QFileInfo(savedPath).fileName());
|
|
m_tabWidget->setTabToolTip(idx, savedPath);
|
|
}
|
|
emit currentFileSaved(savedPath);
|
|
|
|
// Index und Funktionsliste aktualisieren
|
|
m_funcIndex->refresh();
|
|
if (m_funcDialog->isVisible())
|
|
{
|
|
m_funcDialog->refresh();
|
|
}
|
|
});
|
|
}
|
|
|
|
void EditorPanel::saveCurrentFile()
|
|
{
|
|
if (EditorTab *tab = currentTab())
|
|
{
|
|
tab->save();
|
|
}
|
|
}
|
|
|
|
void EditorPanel::saveCurrentFileAs()
|
|
{
|
|
if (EditorTab *tab = currentTab())
|
|
{
|
|
tab->saveAs();
|
|
}
|
|
}
|
|
|
|
void EditorPanel::saveAllFiles()
|
|
{
|
|
for (int i = 0; i < m_tabWidget->count(); ++i)
|
|
{
|
|
EditorTab *tab = qobject_cast<EditorTab *>(m_tabWidget->widget(i));
|
|
if (tab && tab->isModified())
|
|
{
|
|
tab->save();
|
|
}
|
|
}
|
|
}
|
|
|
|
void EditorPanel::showSearchPanel()
|
|
{
|
|
m_fileSearch->hide();
|
|
m_searchPanel->activate();
|
|
}
|
|
|
|
void EditorPanel::showFileSearchPanel()
|
|
{
|
|
m_searchPanel->hide();
|
|
m_fileSearch->activate();
|
|
}
|
|
|
|
void EditorPanel::showFunctionList()
|
|
{
|
|
m_funcDialog->show();
|
|
m_funcDialog->raise();
|
|
m_funcDialog->activateWindow();
|
|
}
|
|
|
|
void EditorPanel::showDeadCode()
|
|
{
|
|
m_deadCode->show();
|
|
m_deadCode->raise();
|
|
m_deadCode->activateWindow();
|
|
}
|
|
|
|
void EditorPanel::setSearchRoot(const QString &path)
|
|
{
|
|
m_fileSearch->setSearchRoot(path);
|
|
m_funcDialog->setProjectRoot(path);
|
|
m_deadCode->setProjectRoot(path);
|
|
m_funcIndex->setProjectRoot(path);
|
|
}
|
|
|
|
void EditorPanel::goToLine(const QString &filePath, int line)
|
|
{
|
|
// Datei öffnen falls noch nicht geöffnet
|
|
openFile(filePath);
|
|
|
|
EditorTab *tab = m_openTabs.value(filePath, nullptr);
|
|
if (!tab)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_tabWidget->setCurrentWidget(tab);
|
|
|
|
// Zur gewünschten Zeile springen
|
|
CodeEditor *editor = tab->editor();
|
|
QTextBlock block = editor->document()->findBlockByLineNumber(line - 1);
|
|
if (block.isValid())
|
|
{
|
|
QTextCursor cursor(block);
|
|
cursor.movePosition(QTextCursor::StartOfBlock);
|
|
editor->setTextCursor(cursor);
|
|
editor->centerCursor();
|
|
editor->setFocus();
|
|
}
|
|
}
|
|
|
|
QStringList EditorPanel::openFilePaths() const
|
|
{
|
|
QStringList paths;
|
|
for (int i = 0; i < m_tabWidget->count(); ++i)
|
|
{
|
|
EditorTab *tab = qobject_cast<EditorTab *>(m_tabWidget->widget(i));
|
|
if (tab)
|
|
{
|
|
paths.append(tab->filePath());
|
|
}
|
|
}
|
|
return paths;
|
|
}
|
|
|
|
QString EditorPanel::activeFilePath() const
|
|
{
|
|
EditorTab *tab = currentTab();
|
|
return tab ? tab->filePath() : QString();
|
|
}
|
|
|
|
void EditorPanel::restoreSession(const QStringList &files, const QString &activeFile)
|
|
{
|
|
for (const QString &path : files)
|
|
{
|
|
if (QFile::exists(path))
|
|
{
|
|
openFile(path);
|
|
}
|
|
}
|
|
|
|
// Aktiven Tab wiederherstellen
|
|
if (!activeFile.isEmpty())
|
|
{
|
|
const int idx = findTabForFile(activeFile);
|
|
if (idx != -1)
|
|
{
|
|
m_tabWidget->setCurrentIndex(idx);
|
|
}
|
|
}
|
|
}
|
|
|
|
void EditorPanel::undo()
|
|
{
|
|
if (EditorTab *tab = currentTab())
|
|
{
|
|
tab->editor()->undo();
|
|
}
|
|
}
|
|
|
|
void EditorPanel::redo()
|
|
{
|
|
if (EditorTab *tab = currentTab())
|
|
{
|
|
tab->editor()->redo();
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Private Slots
|
|
// ---------------------------------------------------------------------------
|
|
void EditorPanel::onTabCloseRequested(int index)
|
|
{
|
|
EditorTab *tab = qobject_cast<EditorTab *>(m_tabWidget->widget(index));
|
|
if (!tab)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_openTabs.remove(tab->filePath());
|
|
m_tabWidget->removeTab(index);
|
|
tab->deleteLater();
|
|
|
|
m_searchPanel->setEditor(currentTab() ? currentTab()->editor() : nullptr);
|
|
}
|
|
|
|
void EditorPanel::onCurrentTabChanged(int /*index*/)
|
|
{
|
|
EditorTab *tab = currentTab();
|
|
m_searchPanel->setEditor(tab ? tab->editor() : nullptr);
|
|
}
|