mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 13:59:52 +08:00
308 lines
7.9 KiB
C++
308 lines
7.9 KiB
C++
#include <QtWidgets>
|
|
#include "veditarea.h"
|
|
#include "veditwindow.h"
|
|
#include "vedittab.h"
|
|
#include "vnote.h"
|
|
#include "vconfigmanager.h"
|
|
|
|
VEditArea::VEditArea(VNote *vnote, QWidget *parent)
|
|
: QWidget(parent), vnote(vnote), curWindowIndex(0)
|
|
{
|
|
setupUI();
|
|
}
|
|
|
|
void VEditArea::setupUI()
|
|
{
|
|
splitter = new QSplitter(this);
|
|
|
|
// Add a window
|
|
insertSplitWindow(0);
|
|
setCurrentWindow(0, true);
|
|
|
|
QHBoxLayout *mainLayout = new QHBoxLayout();
|
|
mainLayout->addWidget(splitter);
|
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
setLayout(mainLayout);
|
|
}
|
|
|
|
void VEditArea::insertSplitWindow(int idx)
|
|
{
|
|
VEditWindow *win = new VEditWindow(vnote);
|
|
splitter->insertWidget(idx, win);
|
|
connect(win, &VEditWindow::tabStatusChanged,
|
|
this, &VEditArea::curTabStatusChanged);
|
|
connect(win, &VEditWindow::requestSplitWindow,
|
|
this, &VEditArea::handleSplitWindowRequest);
|
|
connect(win, &VEditWindow::requestRemoveSplit,
|
|
this, &VEditArea::handleRemoveSplitRequest);
|
|
connect(win, &VEditWindow::getFocused,
|
|
this, &VEditArea::handleWindowFocused);
|
|
connect(win, &VEditWindow::outlineChanged,
|
|
this, &VEditArea::handleOutlineChanged);
|
|
connect(win, &VEditWindow::curHeaderChanged,
|
|
this, &VEditArea::handleCurHeaderChanged);
|
|
|
|
int nrWin = splitter->count();
|
|
if (nrWin == 1) {
|
|
// Disable removing split
|
|
win->setRemoveSplitEnable(false);
|
|
} else {
|
|
// Enable removing split
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
getWindow(i)->setRemoveSplitEnable(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void VEditArea::removeSplitWindow(VEditWindow *win)
|
|
{
|
|
if (!win) {
|
|
return;
|
|
}
|
|
win->hide();
|
|
// Should be deleted later
|
|
win->deleteLater();
|
|
|
|
int nrWin = splitter->count();
|
|
if (nrWin == 2) {
|
|
// Disable removing split
|
|
getWindow(0)->setRemoveSplitEnable(false);
|
|
getWindow(1)->setRemoveSplitEnable(false);
|
|
} else {
|
|
// Enable removing split
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
getWindow(i)->setRemoveSplitEnable(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
// A given file can be opened in multiple split windows. A given file could be
|
|
// opened at most in one tab inside a window.
|
|
void VEditArea::openFile(QJsonObject fileJson)
|
|
{
|
|
if (fileJson.isEmpty()) {
|
|
return;
|
|
}
|
|
|
|
QString notebook = fileJson["notebook"].toString();
|
|
QString relativePath = fileJson["relative_path"].toString();
|
|
int mode = OpenFileMode::Read;
|
|
if (fileJson.contains("mode")) {
|
|
mode = fileJson["mode"].toInt();
|
|
}
|
|
|
|
qDebug() << "open notebook" << notebook << "path" << relativePath << mode;
|
|
|
|
// Find if it has been opened already
|
|
int winIdx, tabIdx;
|
|
bool setFocus = false;
|
|
auto tabs = findTabsByFile(notebook, relativePath);
|
|
if (!tabs.empty()) {
|
|
// Current window first
|
|
winIdx = tabs[0].first;
|
|
tabIdx = tabs[0].second;
|
|
for (int i = 0; i < tabs.size(); ++i) {
|
|
if (tabs[i].first == curWindowIndex) {
|
|
winIdx = tabs[i].first;
|
|
tabIdx = tabs[i].second;
|
|
break;
|
|
}
|
|
}
|
|
setFocus = true;
|
|
goto out;
|
|
}
|
|
|
|
// Open it in current window
|
|
winIdx = curWindowIndex;
|
|
tabIdx = openFileInWindow(winIdx, notebook, relativePath, mode);
|
|
|
|
out:
|
|
setCurrentTab(winIdx, tabIdx, setFocus);
|
|
}
|
|
|
|
QVector<QPair<int, int> > VEditArea::findTabsByFile(const QString ¬ebook, const QString &relativePath)
|
|
{
|
|
QVector<QPair<int, int> > tabs;
|
|
int nrWin = splitter->count();
|
|
for (int winIdx = 0; winIdx < nrWin; ++winIdx) {
|
|
VEditWindow *win = getWindow(winIdx);
|
|
int tabIdx = win->findTabByFile(notebook, relativePath);
|
|
if (tabIdx != -1) {
|
|
QPair<int, int> match;
|
|
match.first = winIdx;
|
|
match.second = tabIdx;
|
|
tabs.append(match);
|
|
}
|
|
}
|
|
return tabs;
|
|
}
|
|
|
|
int VEditArea::openFileInWindow(int windowIndex, const QString ¬ebook, const QString &relativePath,
|
|
int mode)
|
|
{
|
|
Q_ASSERT(windowIndex < splitter->count());
|
|
VEditWindow *win = getWindow(windowIndex);
|
|
return win->openFile(notebook, relativePath, mode);
|
|
}
|
|
|
|
void VEditArea::setCurrentTab(int windowIndex, int tabIndex, bool setFocus)
|
|
{
|
|
VEditWindow *win = getWindow(windowIndex);
|
|
win->setCurrentIndex(tabIndex);
|
|
|
|
setCurrentWindow(windowIndex, setFocus);
|
|
}
|
|
|
|
void VEditArea::setCurrentWindow(int windowIndex, bool setFocus)
|
|
{
|
|
if (curWindowIndex == windowIndex) {
|
|
goto out;
|
|
}
|
|
qDebug() << "current window" << windowIndex;
|
|
curWindowIndex = windowIndex;
|
|
if (setFocus) {
|
|
getWindow(windowIndex)->focusWindow();
|
|
}
|
|
|
|
out:
|
|
// Update status
|
|
updateWindowStatus();
|
|
}
|
|
|
|
void VEditArea::updateWindowStatus()
|
|
{
|
|
VEditWindow *win = getWindow(curWindowIndex);
|
|
win->requestUpdateTabStatus();
|
|
win->requestUpdateOutline();
|
|
win->requestUpdateCurHeader();
|
|
}
|
|
|
|
void VEditArea::closeFile(QJsonObject fileJson)
|
|
{
|
|
if (fileJson.isEmpty()) {
|
|
return;
|
|
}
|
|
QString notebook = fileJson["notebook"].toString();
|
|
QString relativePath = fileJson["relative_path"].toString();
|
|
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
VEditWindow *win = getWindow(i);
|
|
win->closeFile(notebook, relativePath);
|
|
}
|
|
}
|
|
|
|
void VEditArea::editFile()
|
|
{
|
|
VEditWindow *win = getWindow(curWindowIndex);
|
|
win->editFile();
|
|
}
|
|
|
|
void VEditArea::saveFile()
|
|
{
|
|
VEditWindow *win = getWindow(curWindowIndex);
|
|
win->saveFile();
|
|
}
|
|
|
|
void VEditArea::readFile()
|
|
{
|
|
VEditWindow *win = getWindow(curWindowIndex);
|
|
win->readFile();
|
|
}
|
|
|
|
void VEditArea::saveAndReadFile()
|
|
{
|
|
VEditWindow *win = getWindow(curWindowIndex);
|
|
win->saveAndReadFile();
|
|
}
|
|
|
|
void VEditArea::handleNotebookRenamed(const QVector<VNotebook> ¬ebooks,
|
|
const QString &oldName, const QString &newName)
|
|
{
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
VEditWindow *win = getWindow(i);
|
|
win->handleNotebookRenamed(notebooks, oldName, newName);
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleSplitWindowRequest(VEditWindow *curWindow)
|
|
{
|
|
if (!curWindow) {
|
|
return;
|
|
}
|
|
int idx = splitter->indexOf(curWindow);
|
|
qDebug() << "window" << idx << "requests split itself";
|
|
insertSplitWindow(++idx);
|
|
setCurrentWindow(idx, true);
|
|
}
|
|
|
|
void VEditArea::handleRemoveSplitRequest(VEditWindow *curWindow)
|
|
{
|
|
if (!curWindow) {
|
|
return;
|
|
}
|
|
int idx = splitter->indexOf(curWindow);
|
|
|
|
removeSplitWindow(curWindow);
|
|
|
|
if (idx >= splitter->count()) {
|
|
idx = splitter->count() - 1;
|
|
}
|
|
|
|
// At least one split window left
|
|
Q_ASSERT(idx >= 0);
|
|
setCurrentWindow(idx, true);
|
|
}
|
|
|
|
void VEditArea::mousePressEvent(QMouseEvent *event)
|
|
{
|
|
return;
|
|
qDebug() << "VEditArea press event" << event;
|
|
QPoint pos = event->pos();
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
VEditWindow *win = getWindow(i);
|
|
if (win->geometry().contains(pos, true)) {
|
|
setCurrentWindow(i, true);
|
|
break;
|
|
}
|
|
}
|
|
QWidget::mousePressEvent(event);
|
|
}
|
|
|
|
void VEditArea::handleWindowFocused()
|
|
{
|
|
QObject *winObject = sender();
|
|
int nrWin = splitter->count();
|
|
for (int i = 0; i < nrWin; ++i) {
|
|
if (splitter->widget(i) == winObject) {
|
|
setCurrentWindow(i, false);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleOutlineChanged(const VToc &toc)
|
|
{
|
|
QObject *winObject = sender();
|
|
if (splitter->widget(curWindowIndex) == winObject) {
|
|
emit outlineChanged(toc);
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleCurHeaderChanged(const VAnchor &anchor)
|
|
{
|
|
QObject *winObject = sender();
|
|
if (splitter->widget(curWindowIndex) == winObject) {
|
|
emit curHeaderChanged(anchor);
|
|
}
|
|
}
|
|
|
|
void VEditArea::handleOutlineItemActivated(const VAnchor &anchor)
|
|
{
|
|
// Notice current window
|
|
getWindow(curWindowIndex)->scrollCurTab(anchor);
|
|
}
|