| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343 |
- #include "viewwindow.h"
- #include <QVBoxLayout>
- #include <QAction>
- #include <QTimer>
- #include <QMenu>
- #include <QToolBar>
- #include <QDebug>
- #include <QToolButton>
- #include <QFileInfo>
- #include <QDragEnterEvent>
- #include <QApplication>
- #include <QFocusEvent>
- #include <QShortcut>
- #include <QWheelEvent>
- #include <QWidgetAction>
- #include <QActionGroup>
- #include "toolbarhelper.h"
- #include "vnotex.h"
- #include <utils/iconutils.h>
- #include <utils/utils.h>
- #include <utils/widgetutils.h>
- #include <core/configmgr.h>
- #include <core/editorconfig.h>
- #include <imagehost/imagehostmgr.h>
- #include "messageboxhelper.h"
- #include "editreaddiscardaction.h"
- #include "viewsplit.h"
- #include "attachmentpopup.h"
- #include "tagpopup.h"
- #include "outlinepopup.h"
- #include "dragdropareaindicator.h"
- #include "attachmentdragdropareaindicator.h"
- #include "exception.h"
- #include "findandreplacewidget.h"
- #include "editors/statuswidget.h"
- #include "propertydefs.h"
- #include "floatingwidget.h"
- #include "widgetsfactory.h"
- using namespace vnotex;
- QIcon ViewWindow::s_savedIcon;
- QIcon ViewWindow::s_modifiedIcon;
- ViewWindow::ViewWindow(QWidget *p_parent)
- : QFrame(p_parent)
- {
- setupUI();
- initIcons();
- setupShortcuts();
- // Need to use this global-wise way, especially for the WebView.
- connect(qApp, &QApplication::focusChanged,
- this, [this](QWidget *p_old, QWidget *p_now) {
- if (p_now == this || isAncestorOf(p_now)) {
- bool hadFocus = p_old && (p_old == this || isAncestorOf(p_old));
- if (!hadFocus) {
- emit focused(this);
- }
- }
- });
- m_syncBufferContentTimer = new QTimer(this);
- m_syncBufferContentTimer->setSingleShot(true);
- m_syncBufferContentTimer->setInterval(500);
- connect(m_syncBufferContentTimer, &QTimer::timeout,
- this, [this]() {
- Q_ASSERT(getBuffer());
- if (getBuffer()->getRevision() != m_bufferRevision) {
- syncEditorFromBufferContent();
- }
- });
- }
- ViewWindow::~ViewWindow()
- {
- Q_ASSERT(!m_buffer);
- if (m_statusWidget) {
- m_statusWidget->setParent(nullptr);
- }
- }
- void ViewWindow::setupUI()
- {
- m_mainLayout = new QVBoxLayout(this);
- m_mainLayout->setSpacing(0);
- m_mainLayout->setContentsMargins(0, 0, 0, 0);
- m_topLayout = new QVBoxLayout();
- m_topLayout->setContentsMargins(0, 0, 0, 0);
- m_topLayout->setSpacing(0);
- m_mainLayout->addLayout(m_topLayout, 0);
- m_bottomLayout = new QVBoxLayout();
- m_bottomLayout->setContentsMargins(0, 0, 0, 0);
- m_bottomLayout->setSpacing(0);
- m_mainLayout->addLayout(m_bottomLayout, 0);
- }
- void ViewWindow::initIcons()
- {
- if (!s_savedIcon.isNull()) {
- return;
- }
- const auto &themeMgr = VNoteX::getInst().getThemeMgr();
- const QString savedIconName("buffer.svg");
- const QString unsavedIconFg("base#icon#warning#fg");
- s_savedIcon = IconUtils::fetchIcon(themeMgr.getIconFile(savedIconName));
- s_modifiedIcon = IconUtils::fetchIcon(themeMgr.getIconFile(savedIconName),
- themeMgr.paletteColor(unsavedIconFg));
- }
- Buffer *ViewWindow::getBuffer() const
- {
- return m_buffer;
- }
- void ViewWindow::handleBufferChanged(const QSharedPointer<FileOpenParameters> &p_paras)
- {
- auto buffer = getBuffer();
- if (buffer) {
- connect(buffer, &Buffer::modified,
- this, &ViewWindow::statusChanged);
- // To make it convenient to disconnect, do not connect directly to
- // the timer.
- connect(buffer, &Buffer::contentsChanged,
- this, [this]() {
- m_syncBufferContentTimer->start();
- });
- connect(buffer, &Buffer::nameChanged,
- this, &ViewWindow::nameChanged);
- connect(buffer, &Buffer::attachmentChanged,
- this, &ViewWindow::attachmentChanged);
- connect(buffer, &Buffer::autoSaved,
- this, [this]() {
- executeHook(FileOpenParameters::PostSave);
- });
- }
- m_sessionEnabled = p_paras->m_sessionEnabled;
- m_openParas = p_paras;
- handleBufferChangedInternal(p_paras);
- emit bufferChanged();
- }
- void ViewWindow::attachToBuffer(Buffer *p_buffer, const QSharedPointer<FileOpenParameters> &p_paras)
- {
- Q_ASSERT(p_buffer);
- Q_ASSERT(m_buffer != p_buffer);
- detachFromBuffer();
- m_buffer = p_buffer;
- m_buffer->attachViewWindow(this);
- handleBufferChanged(p_paras);
- if (m_buffer->getAttachViewWindowCount() == 1) {
- QTimer::singleShot(1000, this, &ViewWindow::checkBackupFileOfPreviousSession);
- }
- }
- void ViewWindow::detachFromBuffer(bool p_quiet)
- {
- if (!m_buffer) {
- return;
- }
- detachFromBufferInternal();
- disconnect(this, 0, m_buffer, 0);
- disconnect(m_buffer, 0, this, 0);
- m_buffer->detachViewWindow(this);
- m_buffer = nullptr;
- if (!p_quiet) {
- handleBufferChanged(nullptr);
- }
- }
- QIcon ViewWindow::getIcon() const
- {
- if (m_buffer) {
- return m_buffer->isModified() ? s_modifiedIcon : s_savedIcon;
- } else {
- return s_savedIcon;
- }
- }
- QString ViewWindow::getName() const
- {
- if (m_buffer) {
- return m_buffer->getName();
- } else {
- return tr("[No Buffer]");
- }
- }
- ViewSplit *ViewWindow::getViewSplit() const
- {
- return m_viewSplit;
- }
- void ViewWindow::setViewSplit(ViewSplit *p_split)
- {
- m_viewSplit = p_split;
- }
- QString ViewWindow::getTitle() const
- {
- if (m_buffer) {
- return m_buffer->getPath();
- } else {
- return tr("[No Buffer]");
- }
- }
- void ViewWindow::setCentralWidget(QWidget *p_widget)
- {
- Q_ASSERT(!m_centralWidget);
- m_centralWidget = p_widget;
- // Insert after top layout.
- m_mainLayout->insertWidget(1, m_centralWidget, 1);
- setFocusProxy(m_centralWidget);
- m_centralWidget->show();
- }
- void ViewWindow::replaceCentralWidget(QWidget *p_widget)
- {
- Q_ASSERT(m_centralWidget);
- m_mainLayout->replaceWidget(m_centralWidget, p_widget);
- m_centralWidget = p_widget;
- setFocusProxy(m_centralWidget);
- m_centralWidget->show();
- }
- void ViewWindow::addTopWidget(QWidget *p_widget)
- {
- m_topLayout->addWidget(p_widget);
- }
- void ViewWindow::addBottomWidget(QWidget *p_widget)
- {
- if (m_statusWidgetInBottomLayout) {
- m_bottomLayout->insertWidget(m_bottomLayout->count() - 1, p_widget);
- } else {
- m_bottomLayout->addWidget(p_widget);
- }
- }
- void ViewWindow::setStatusWidget(const QSharedPointer<StatusWidget> &p_widget)
- {
- m_statusWidget = p_widget;
- m_bottomLayout->addWidget(p_widget.data());
- p_widget->show();
- m_statusWidgetInBottomLayout = true;
- }
- QSharedPointer<QWidget> ViewWindow::statusWidget()
- {
- return m_statusWidget;
- }
- void ViewWindow::setStatusWidgetVisible(bool p_visible)
- {
- if (m_statusWidget) {
- if (p_visible) {
- // Need to add it to the right layout again since global status widget will set it as
- // a child of the main status bar.
- setStatusWidget(m_statusWidget);
- } else {
- m_statusWidget->hide();
- m_statusWidgetInBottomLayout = false;
- }
- }
- }
- QAction *ViewWindow::addAction(QToolBar *p_toolBar, ViewWindowToolBarHelper::Action p_action)
- {
- QAction *act = nullptr;
- switch (p_action) {
- case ViewWindowToolBarHelper::Save:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- connect(this, &ViewWindow::statusChanged,
- this, [this, act]() {
- auto buffer = getBuffer();
- act->setEnabled(buffer ? !buffer->isReadOnly() && buffer->isModified() : false);
- });
- connect(act, &QAction::triggered,
- this, [this]() {
- if (Normal != checkFileMissingOrChangedOutside()) {
- return;
- }
- save(false);
- });
- break;
- }
- case ViewWindowToolBarHelper::EditReadDiscard:
- {
- // A combined button with Edit/Read/Discard.
- Q_ASSERT(!m_editReadDiscardAct);
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- m_editReadDiscardAct = dynamic_cast<EditReadDiscardAction *>(act);
- connect(this, &ViewWindow::modeChanged,
- this, [this]() {
- updateEditReadDiscardActionState(m_editReadDiscardAct);
- });
- connect(m_editReadDiscardAct, QOverload<EditReadDiscardAction::Action>::of(&EditReadDiscardAction::triggered),
- this, [this](EditReadDiscardAction::Action p_act) {
- switch (p_act) {
- case EditReadDiscardAction::Action::Edit:
- edit();
- break;
- case EditReadDiscardAction::Action::Read:
- read(true);
- break;
- case EditReadDiscardAction::Action::Discard:
- read(false);
- break;
- }
- });
- break;
- }
- case ViewWindowToolBarHelper::ViewMode:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- connect(this, &ViewWindow::bufferChanged,
- this, [this, act]() {
- act->setEnabled(getBuffer());
- });
- auto toolBtn = dynamic_cast<QToolButton *>(p_toolBar->widgetForAction(act));
- Q_ASSERT(toolBtn);
- auto menu = WidgetsFactory::createMenu(p_toolBar);
- toolBtn->setMenu(menu);
- connect(menu, &QMenu::aboutToShow,
- this, [this, menu]() {
- updateViewModeMenu(menu);
- });
- break;
- }
- case ViewWindowToolBarHelper::TypeHeading:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- connect(this, &ViewWindow::modeChanged,
- this, [this, act]() {
- act->setEnabled(inModeCanInsert() && getBuffer() && !getBuffer()->isReadOnly());
- });
- auto toolBtn = dynamic_cast<QToolButton *>(p_toolBar->widgetForAction(act));
- Q_ASSERT(toolBtn);
- // MUST use the menu for the event. QToolButton won't trigger the event
- // if we call action->trigger().
- connect(toolBtn->menu(), &QMenu::triggered,
- this, [this](QAction *p_act) {
- TypeAction action = static_cast<TypeAction>(TypeAction::Heading1 + p_act->data().toInt() - 1);
- handleTypeAction(action);
- });
- break;
- }
- case ViewWindowToolBarHelper::TypeBold:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeItalic:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeStrikethrough:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeUnorderedList:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeOrderedList:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeTodoList:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeCheckedTodoList:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeCode:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeCodeBlock:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeMath:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeMathBlock:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeQuote:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeLink:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeImage:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeTable:
- Q_FALLTHROUGH();
- case ViewWindowToolBarHelper::TypeMark:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- connect(this, &ViewWindow::modeChanged,
- this, [this, act]() {
- act->setEnabled(inModeCanInsert() && getBuffer() && !getBuffer()->isReadOnly());
- });
- connect(act, &QAction::triggered,
- this, [this, p_action]() {
- handleTypeAction(toolBarActionToTypeAction(p_action));
- });
- break;
- }
- case ViewWindowToolBarHelper::Attachment:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- auto popup = static_cast<AttachmentPopup *>(static_cast<QToolButton *>(p_toolBar->widgetForAction(act))->menu());
- connect(this, &ViewWindow::bufferChanged,
- this, [this, act, popup]() {
- auto buffer = getBuffer();
- act->setEnabled(buffer ? buffer->isAttachmentSupported() : false);
- act->setIcon(getAttachmentIcon(buffer));
- popup->setBuffer(buffer);
- });
- connect(this, &ViewWindow::attachmentChanged,
- this, [this, act]() {
- act->setIcon(getAttachmentIcon(getBuffer()));
- });
- break;
- }
- case ViewWindowToolBarHelper::Tag:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- auto popup = static_cast<TagPopup *>(static_cast<QToolButton *>(p_toolBar->widgetForAction(act))->menu());
- connect(this, &ViewWindow::bufferChanged,
- this, [this, act, popup]() {
- auto buffer = getBuffer();
- act->setEnabled(buffer ? buffer->isTagSupported() : false);
- popup->setBuffer(buffer);
- });
- break;
- }
- case ViewWindowToolBarHelper::Outline:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- auto popup = static_cast<OutlinePopup *>(static_cast<QToolButton *>(p_toolBar->widgetForAction(act))->menu());
- popup->setOutlineProvider(getOutlineProvider());
- break;
- }
- case ViewWindowToolBarHelper::FindAndReplace:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- connect(act, &QAction::triggered,
- this, [this]() {
- if (findAndReplaceWidgetVisible()) {
- const auto focusWidget = QApplication::focusWidget();
- if (m_findAndReplace == focusWidget || m_findAndReplace->isAncestorOf(focusWidget)) {
- hideFindAndReplaceWidget();
- } else {
- showFindAndReplaceWidget();
- }
- } else {
- showFindAndReplaceWidget();
- }
- });
- break;
- }
- case ViewWindowToolBarHelper::SectionNumber:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- connect(this, &ViewWindow::modeChanged,
- this, [this, act]() {
- act->setEnabled(inModeCanInsert() && getBuffer() && !getBuffer()->isReadOnly());
- });
- auto toolBtn = dynamic_cast<QToolButton *>(p_toolBar->widgetForAction(act));
- Q_ASSERT(toolBtn);
- connect(toolBtn->menu(), &QMenu::triggered,
- this, [this](QAction *p_act) {
- OverrideState state = static_cast<OverrideState>(p_act->data().toInt());
- handleSectionNumberOverride(state);
- });
- break;
- }
- case ViewWindowToolBarHelper::InplacePreview:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- break;
- }
- case ViewWindowToolBarHelper::ImageHost:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- connect(this, &ViewWindow::modeChanged,
- this, [this, act]() {
- act->setEnabled(inModeCanInsert() && getBuffer() && !getBuffer()->isReadOnly());
- });
- auto toolBtn = dynamic_cast<QToolButton *>(p_toolBar->widgetForAction(act));
- Q_ASSERT(toolBtn);
- m_imageHostMenu = toolBtn->menu();
- Q_ASSERT(m_imageHostMenu);
- updateImageHostMenu();
- connect(m_imageHostMenu, &QMenu::triggered,
- this, [this](QAction *p_act) {
- handleImageHostChanged(p_act->data().toString());
- });
- connect(&ImageHostMgr::getInst(), &ImageHostMgr::imageHostChanged,
- this, &ViewWindow::updateImageHostMenu);
- break;
- }
- case ViewWindowToolBarHelper::Debug:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- connect(act, &QAction::triggered,
- this, &ViewWindow::toggleDebug);
- break;
- }
- case ViewWindowToolBarHelper::Print:
- {
- act = ViewWindowToolBarHelper::addAction(p_toolBar, p_action);
- connect(act, &QAction::triggered,
- this, &ViewWindow::print);
- break;
- }
- default:
- Q_ASSERT(false);
- break;
- }
- return act;
- }
- const QIcon &ViewWindow::getAttachmentIcon(Buffer *p_buffer) const
- {
- static QIcon emptyIcon = ToolBarHelper::generateIcon("attachment_editor.svg");
- static QIcon fullIcon = ToolBarHelper::generateIcon("attachment_full_editor.svg");
- if (p_buffer && p_buffer->hasAttachment()) {
- return fullIcon;
- } else {
- return emptyIcon;
- }
- }
- bool ViewWindow::saveInternal(bool p_force)
- {
- if (m_buffer) {
- auto code = m_buffer->save(p_force);
- if (code == Buffer::OperationCode::Success) {
- setModified(false);
- return true;
- }
- return false;
- }
- return true;
- }
- bool ViewWindow::aboutToClose(bool p_force)
- {
- if (!aboutToCloseInternal(p_force)) {
- return false;
- }
- if (m_buffer) {
- m_buffer->syncContent(this);
- if (m_buffer->getAttachViewWindowCount() == 1) {
- // Update the buffer state.
- m_buffer->checkFileExistsOnDisk();
- m_buffer->checkFileChangedOutside();
- if (m_buffer->isModified()) {
- if (p_force) {
- // Just discard.
- m_buffer->discard();
- } else {
- // Check file missing or changed outside.
- int ret = checkFileMissingOrChangedOutside();
- switch (ret) {
- case Normal:
- Q_FALLTHROUGH();
- case SavedOrReloaded:
- break;
- case Discarded:
- m_buffer->discard();
- break;
- default:
- return false;
- }
- if (m_buffer->isModified()) {
- // Ask to save changes.
- ret = MessageBoxHelper::questionSaveDiscardCancel(MessageBoxHelper::Question,
- tr("Save changes before closing note (%1)?").arg(m_buffer->getName()),
- tr("Note path (%1).").arg(m_buffer->getPath()),
- "",
- this);
- switch (ret) {
- case QMessageBox::Save:
- {
- if (!save(false)) {
- return false;
- }
- break;
- }
- case QMessageBox::Discard:
- m_buffer->discard();
- break;
- case QMessageBox::Cancel:
- Q_FALLTHROUGH();
- default:
- return false;
- }
- }
- }
- }
- }
- detachFromBuffer(true);
- }
- return true;
- }
- ViewWindowMode ViewWindow::getMode() const
- {
- return m_mode;
- }
- bool ViewWindow::reload()
- {
- if (m_buffer) {
- auto code = m_buffer->reload();
- if (code == Buffer::OperationCode::Success) {
- setModified(false);
- return true;
- }
- return false;
- }
- return true;
- }
- void ViewWindow::discardChangesAndRead()
- {
- auto buffer = getBuffer();
- Q_ASSERT(buffer);
- buffer->syncContent(this);
- if (buffer->isModified()) {
- // Ask to save changes.
- int ret = MessageBoxHelper::questionSaveDiscardCancel(MessageBoxHelper::Question,
- tr("Discard changes to note (%1)?").arg(buffer->getName()),
- tr("Note path (%1).").arg(buffer->getPath()),
- "",
- this);
- switch (ret) {
- case QMessageBox::Save:
- // Save and read.
- if (!save(false)) {
- return;
- }
- break;
- case QMessageBox::Discard:
- // Reload buffer and read.
- if (!reload()) {
- return;
- }
- break;
- case QMessageBox::Cancel:
- Q_FALLTHROUGH();
- default:
- return;
- }
- }
- setMode(ViewWindowMode::Read);
- }
- bool ViewWindow::inModeCanInsert() const
- {
- return m_mode == ViewWindowMode::Edit;
- }
- void ViewWindow::handleTypeAction(TypeAction p_action)
- {
- Q_UNUSED(p_action);
- Q_ASSERT(false);
- }
- void ViewWindow::handleSectionNumberOverride(OverrideState p_state)
- {
- Q_UNUSED(p_state);
- Q_ASSERT(false);
- }
- void ViewWindow::handleImageHostChanged(const QString &p_hostName)
- {
- Q_UNUSED(p_hostName);
- Q_ASSERT(false);
- }
- QString ViewWindow::selectedText() const
- {
- return QString();
- }
- ViewWindow::TypeAction ViewWindow::toolBarActionToTypeAction(ViewWindowToolBarHelper::Action p_action)
- {
- Q_ASSERT(p_action >= ViewWindowToolBarHelper::Action::TypeBold
- && p_action <= ViewWindowToolBarHelper::Action::TypeMax);
- return static_cast<TypeAction>(TypeAction::Bold + (p_action - ViewWindowToolBarHelper::Action::TypeBold));
- }
- void ViewWindow::detachFromBufferInternal()
- {
- }
- void ViewWindow::checkBackupFileOfPreviousSession()
- {
- Q_ASSERT(m_buffer);
- const auto &backupFile = m_buffer->getBackupFileOfPreviousSession();
- if (backupFile.isEmpty()) {
- return;
- }
- qDebug() << "checkBackupFileOfPreviousSession" << backupFile;
- // Ask to whether save or discard backup file.
- const auto fileModifiedTime = Utils::dateTimeString(QFileInfo(m_buffer->getContentPath()).lastModified());
- const auto backupFileModifiedTime = Utils::dateTimeString(QFileInfo(backupFile).lastModified());
- int ret = MessageBoxHelper::questionYesNoCancel(MessageBoxHelper::Warning,
- tr("Found backup file (%1) of file (%2). Do you want to recover from backup file?").arg(backupFile, m_buffer->getPath()),
- tr("'Yes' to recover from backup file, 'No' to discard it, and 'Cancel' to exit."),
- tr("It may be caused by crash while editing this file before.\n\n"
- "File last modified time: %1\n"
- "Backup file last modified time: %2").arg(fileModifiedTime, backupFileModifiedTime),
- this);
- switch (ret) {
- case QMessageBox::Yes:
- m_buffer->recoverFromBackupFileOfPreviousSession();
- break;
- case QMessageBox::No:
- // Simply delete the backup file.
- m_buffer->discardBackupFileOfPreviousSession();
- break;
- case QMessageBox::Cancel:
- Q_FALLTHROUGH();
- default:
- // Close ViewWindow.
- Q_ASSERT(m_viewSplit);
- emit m_viewSplit->viewWindowCloseRequested(this);
- break;
- }
- }
- DragDropAreaIndicator *ViewWindow::getAttachmentDragDropArea()
- {
- if (!m_attachmentDragDropIndicator) {
- m_attachmentDragDropIndicatorInterface.reset(new AttachmentDragDropAreaIndicator(this));
- m_attachmentDragDropIndicator = new DragDropAreaIndicator(m_attachmentDragDropIndicatorInterface.data(),
- tr("Drag And Drop Files To Attach"),
- this);
- m_attachmentDragDropIndicator->hide();
- addTopWidget(m_attachmentDragDropIndicator);
- }
- return m_attachmentDragDropIndicator;
- }
- void ViewWindow::addToolBar(QToolBar *p_bar)
- {
- Q_ASSERT(!m_toolBar && !m_attachmentDragDropIndicator);
- m_toolBar = p_bar;
- addTopWidget(p_bar);
- p_bar->setAcceptDrops(true);
- // Enable Drag&Drop on it.
- p_bar->installEventFilter(this);
- }
- bool ViewWindow::eventFilter(QObject *p_obj, QEvent *p_event)
- {
- if (p_obj == m_toolBar) {
- switch (p_event->type()) {
- case QEvent::DragEnter:
- if (m_buffer && m_buffer->isAttachmentSupported() && AttachmentDragDropAreaIndicator::isAccepted(dynamic_cast<QDragEnterEvent *>(p_event))) {
- getAttachmentDragDropArea()->show();
- }
- break;
- case QEvent::HoverLeave:
- if (m_attachmentDragDropIndicator) {
- m_attachmentDragDropIndicator->hide();
- }
- break;
- default:
- break;
- }
- }
- return QFrame::eventFilter(p_obj, p_event);
- }
- bool ViewWindow::aboutToCloseInternal(bool p_force)
- {
- Q_UNUSED(p_force);
- return true;
- }
- QSharedPointer<OutlineProvider> ViewWindow::getOutlineProvider()
- {
- return nullptr;
- }
- int ViewWindow::checkFileMissingOrChangedOutside()
- {
- if (!m_buffer) {
- return Normal;
- }
- if (!m_buffer->checkFileExistsOnDisk()) {
- int ret = MessageBoxHelper::questionSaveDiscardCancel(MessageBoxHelper::Warning,
- tr("File is missing on disk (%1).").arg(m_buffer->getPath()),
- tr("Do you want to force to save the buffer to the file?"),
- tr("The file may be deleted from outside. Please choose to save the buffer to a new file or just discard it."),
- this);
- switch (ret) {
- case QMessageBox::Save:
- if (!save(true)) {
- return Failed;
- } else {
- m_fileChangeCheckEnabled = true;
- return SavedOrReloaded;
- }
- break;
- case QMessageBox::Discard:
- return Discarded;
- default:
- return Failed;
- }
- } else if (m_buffer->checkFileChangedOutside()) {
- int ret = QMessageBox::Discard;
- if (!(getWindowFlags() & WindowFlag::AutoReload)) {
- ret = MessageBoxHelper::questionSaveDiscardCancel(MessageBoxHelper::Warning,
- tr("File is changed from outside (%1).").arg(m_buffer->getPath()),
- tr("Do you want to save the buffer to the file to override, or discard the buffer?"),
- tr("The file is changed from outside. Please choose to save the buffer to the file or "
- "just discard the buffer and reload the file."),
- this);
- }
- switch (ret) {
- case QMessageBox::Save:
- if (!save(true)) {
- return Failed;
- } else {
- m_fileChangeCheckEnabled = true;
- return SavedOrReloaded;
- }
- case QMessageBox::Discard:
- if (!reload()) {
- // Return Discarded here to let ViewWindow be closed.
- return Discarded;
- } else {
- return SavedOrReloaded;
- }
- default:
- return Failed;
- }
- }
- m_fileChangeCheckEnabled = true;
- return Normal;
- }
- void ViewWindow::checkFileMissingOrChangedOutsidePeriodically()
- {
- if (m_fileChangeCheckEnabled) {
- // Disable it first.
- m_fileChangeCheckEnabled = false;
- int ret = checkFileMissingOrChangedOutside();
- m_fileChangeCheckEnabled = ret != Discarded;
- }
- }
- bool ViewWindow::save(bool p_force)
- {
- if (!p_force && !m_buffer->isModified()) {
- return true;
- }
- if (m_buffer->isReadOnly()) {
- MessageBoxHelper::notify(MessageBoxHelper::Warning,
- tr("This is a read-only note (%1), on which modification is not allowed.").arg(m_buffer->getName()),
- tr("Please save your changes to another note."),
- "",
- this);
- return false;
- }
- if (!saveInternal(p_force)) {
- MessageBoxHelper::notify(MessageBoxHelper::Warning,
- tr("Failed to save note (%1).").arg(m_buffer->getName()),
- tr("Please check the file (%1) and try it again.").arg(m_buffer->getPath()),
- tr("Maybe the file is occupied by another service temporarily."),
- this);
- return false;
- }
- executeHook(FileOpenParameters::PostSave);
- return true;
- }
- void ViewWindow::executeHook(FileOpenParameters::Hook p_hook) const
- {
- if (m_openParas && m_openParas->m_hooks[p_hook]) {
- m_openParas->m_hooks[p_hook]();
- }
- }
- void ViewWindow::updateEditReadDiscardActionState(EditReadDiscardAction *p_act)
- {
- switch (getMode()) {
- case ViewWindowMode::Read:
- p_act->setState(BiAction::State::Default);
- break;
- default:
- p_act->setState(BiAction::State::Alternative);
- break;
- }
- }
- void ViewWindow::setupShortcuts()
- {
- const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
- // FindNext.
- {
- auto shortcut = WidgetUtils::createShortcut(editorConfig.getShortcut(EditorConfig::FindNext), this, Qt::WidgetWithChildrenShortcut);
- if (shortcut) {
- connect(shortcut, &QShortcut::activated,
- this, [this]() {
- findNextOnLastFind(true);
- });
- }
- }
- // FindPrevious.
- {
- auto shortcut = WidgetUtils::createShortcut(editorConfig.getShortcut(EditorConfig::FindPrevious), this, Qt::WidgetWithChildrenShortcut);
- if (shortcut) {
- connect(shortcut, &QShortcut::activated,
- this, [this]() {
- findNextOnLastFind(false);
- });
- }
- }
- // ApplySnippet.
- {
- auto shortcut = WidgetUtils::createShortcut(editorConfig.getShortcut(EditorConfig::ApplySnippet), this, Qt::WidgetWithChildrenShortcut);
- if (shortcut) {
- connect(shortcut, &QShortcut::activated,
- this, [this]() {
- applySnippet();
- });
- }
- }
- }
- void ViewWindow::wheelEvent(QWheelEvent *p_event)
- {
- if (p_event->modifiers() & Qt::ControlModifier) {
- QPoint angle = p_event->angleDelta();
- if (!angle.isNull() && (angle.y() != 0)) {
- // Zoom in/out current tab.
- zoom(angle.y() > 0);
- }
- p_event->accept();
- return;
- }
- QFrame::wheelEvent(p_event);
- }
- void ViewWindow::showZoomFactor(qreal p_factor)
- {
- showMessage(tr("Zoomed: %1%").arg(p_factor * 100));
- }
- void ViewWindow::showZoomDelta(int p_delta)
- {
- showMessage(tr("Zoomed: %1%2").arg(p_delta > 0 ? "+" : "").arg(p_delta));
- }
- void ViewWindow::showFindAndReplaceWidget()
- {
- if (!m_findAndReplace) {
- m_findAndReplace = new FindAndReplaceWidget(this);
- m_mainLayout->addWidget(m_findAndReplace);
- // Connect it to slots.
- connect(m_findAndReplace, &FindAndReplaceWidget::findTextChanged,
- this, &ViewWindow::handleFindTextChanged);
- connect(m_findAndReplace, &FindAndReplaceWidget::findNextRequested,
- this, &ViewWindow::findNext);
- connect(m_findAndReplace, &FindAndReplaceWidget::replaceRequested,
- this, &ViewWindow::replace);
- connect(m_findAndReplace, &FindAndReplaceWidget::replaceAllRequested,
- this, &ViewWindow::replaceAll);
- connect(m_findAndReplace, &FindAndReplaceWidget::closed,
- this, [this]() {
- setFocus();
- handleFindAndReplaceWidgetClosed();
- });
- connect(m_findAndReplace, &FindAndReplaceWidget::opened,
- this, &ViewWindow::handleFindAndReplaceWidgetOpened);
- }
- m_findAndReplace->open(selectedText());
- }
- void ViewWindow::hideFindAndReplaceWidget()
- {
- if (m_findAndReplace) {
- m_findAndReplace->close();
- }
- }
- void ViewWindow::keyPressEvent(QKeyEvent *p_event)
- {
- switch (p_event->key()) {
- case Qt::Key_Escape:
- if (findAndReplaceWidgetVisible()) {
- hideFindAndReplaceWidget();
- return;
- }
- break;
- default:
- break;
- }
- QFrame::keyPressEvent(p_event);
- }
- bool ViewWindow::findAndReplaceWidgetVisible() const
- {
- return m_findAndReplace && m_findAndReplace->isVisible();
- }
- void ViewWindow::handleFindTextChanged(const QString &p_text, FindOptions p_options)
- {
- Q_UNUSED(p_text);
- Q_UNUSED(p_options);
- }
- void ViewWindow::handleFindNext(const QStringList &p_texts, FindOptions p_options)
- {
- Q_UNUSED(p_texts);
- Q_UNUSED(p_options);
- }
- void ViewWindow::handleReplace(const QString &p_text, FindOptions p_options, const QString &p_replaceText)
- {
- Q_UNUSED(p_text);
- Q_UNUSED(p_options);
- Q_UNUSED(p_replaceText);
- }
- void ViewWindow::handleReplaceAll(const QString &p_text, FindOptions p_options, const QString &p_replaceText)
- {
- Q_UNUSED(p_text);
- Q_UNUSED(p_options);
- Q_UNUSED(p_replaceText);
- }
- void ViewWindow::handleFindAndReplaceWidgetClosed()
- {
- }
- void ViewWindow::handleFindAndReplaceWidgetOpened()
- {
- }
- void ViewWindow::findNextOnLastFind(bool p_forward)
- {
- // Check if need to update the find info.
- if (m_findAndReplace && m_findAndReplace->isVisible()) {
- m_findInfo.m_texts = QStringList(m_findAndReplace->getFindText());
- m_findInfo.m_options = m_findAndReplace->getOptions();
- }
- if (m_findInfo.m_texts.isEmpty()) {
- return;
- }
- if (p_forward) {
- handleFindNext(m_findInfo.m_texts, m_findInfo.m_options & ~FindOption::FindBackward);
- } else {
- handleFindNext(m_findInfo.m_texts, m_findInfo.m_options | FindOption::FindBackward);
- }
- }
- void ViewWindow::findNext(const QString &p_text, FindOptions p_options)
- {
- const QStringList texts(p_text);
- m_findInfo.m_texts = texts;
- m_findInfo.m_options = p_options;
- handleFindNext(texts, p_options);
- }
- void ViewWindow::replace(const QString &p_text, FindOptions p_options, const QString &p_replaceText)
- {
- m_findInfo.m_texts = QStringList(p_text);
- m_findInfo.m_options = p_options;
- handleReplace(p_text, p_options, p_replaceText);
- }
- void ViewWindow::replaceAll(const QString &p_text, FindOptions p_options, const QString &p_replaceText)
- {
- m_findInfo.m_texts = QStringList(p_text);
- m_findInfo.m_options = p_options;
- handleReplaceAll(p_text, p_options, p_replaceText);
- }
- void ViewWindow::showFindResult(const QStringList &p_texts, int p_totalMatches, int p_currentMatchIndex)
- {
- if (p_totalMatches == 0) {
- showMessage(tr("Pattern not found: %1%2").arg(p_texts.isEmpty() ? QString() : p_texts[0],
- p_texts.size() > 1 ? tr(" [+]"): QString()));
- } else {
- showMessage(tr("Match found: %1/%2").arg(p_currentMatchIndex + 1).arg(p_totalMatches));
- }
- }
- void ViewWindow::showReplaceResult(const QString &p_text, int p_totalReplaces)
- {
- if (p_totalReplaces == 0) {
- showMessage(tr("Pattern not found: %1").arg(p_text));
- } else {
- showMessage(tr("Replaced %n match(es)", "", p_totalReplaces));
- }
- }
- void ViewWindow::showMessage(const QString p_msg)
- {
- if (m_statusWidget) {
- m_statusWidget->showMessage(p_msg);
- } else {
- VNoteX::getInst().showStatusMessageShort(p_msg);
- }
- }
- void ViewWindow::edit()
- {
- int ret = checkFileMissingOrChangedOutside();
- if (Normal != ret && SavedOrReloaded != ret) {
- // Recover the icon of the action.
- updateEditReadDiscardActionState(m_editReadDiscardAct);
- return;
- }
- setMode(ViewWindowMode::Edit);
- setFocus();
- }
- void ViewWindow::read(bool p_save)
- {
- int ret = checkFileMissingOrChangedOutside();
- if (Normal != ret && SavedOrReloaded != ret) {
- // Recover the icon of the action.
- updateEditReadDiscardActionState(m_editReadDiscardAct);
- return;
- }
- if (p_save) {
- if (save(false)) {
- setMode(ViewWindowMode::Read);
- }
- } else {
- discardChangesAndRead();
- }
- setFocus();
- }
- QToolBar *ViewWindow::createToolBar(QWidget *p_parent)
- {
- auto toolBar = new QToolBar(p_parent);
- toolBar->setProperty(PropertyDefs::c_viewWindowToolBar, true);
- const auto &editorConfig = ConfigMgr::getInst().getEditorConfig();
- const int iconSize = editorConfig.getToolBarIconSize();
- toolBar->setIconSize(QSize(iconSize, iconSize));
- /*
- // The extension button of tool bar.
- auto extBtn = toolBar->findChild<QToolButton *>(QLatin1String("qt_toolbar_ext_button"));
- Q_ASSERT(extBtn);
- */
- return toolBar;
- }
- ViewWindowSession ViewWindow::saveSession() const
- {
- ViewWindowSession session;
- if (m_buffer) {
- session.m_bufferPath = m_buffer->getPath();
- session.m_readOnly = m_buffer->isReadOnly();
- }
- session.m_viewWindowMode = getMode();
- return session;
- }
- ViewWindow::WindowFlags ViewWindow::getWindowFlags() const
- {
- return m_flags;
- }
- void ViewWindow::setWindowFlags(WindowFlags p_flags)
- {
- m_flags = p_flags;
- }
- QVariant ViewWindow::showFloatingWidget(FloatingWidget *p_widget)
- {
- // Show the widget through a QWidgetAction in menu.
- QMenu menu;
- auto act = new QWidgetAction(&menu);
- // @act will own @p_widget.
- act->setDefaultWidget(p_widget);
- menu.addAction(act);
- p_widget->setMenu(&menu);
- menu.exec(getFloatingWidgetPosition());
- return p_widget->result();
- }
- QPoint ViewWindow::getFloatingWidgetPosition()
- {
- return mapToGlobal(QPoint(5, 5));
- }
- void ViewWindow::updateImageHostMenu()
- {
- Q_ASSERT(m_imageHostMenu);
- m_imageHostMenu->clear();
- if (m_imageHostActionGroup) {
- m_imageHostActionGroup->deleteLater();
- }
- m_imageHostActionGroup = new QActionGroup(m_imageHostMenu);
- auto act = m_imageHostActionGroup->addAction(tr("Local"));
- act->setCheckable(true);
- m_imageHostMenu->addAction(act);
- act->setChecked(true);
- const auto &hosts = ImageHostMgr::getInst().getImageHosts();
- auto curHost = ImageHostMgr::getInst().getDefaultImageHost();
- for (const auto &host : hosts) {
- auto act = m_imageHostActionGroup->addAction(host->getName());
- act->setCheckable(true);
- act->setData(host->getName());
- m_imageHostMenu->addAction(act);
- if (curHost == host) {
- act->setChecked(true);
- }
- }
- handleImageHostChanged(curHost ? curHost->getName() : nullptr);
- }
- void ViewWindow::updateLastFindInfo(const QStringList &p_texts, FindOptions p_options)
- {
- m_findInfo.m_texts = p_texts;
- m_findInfo.m_options = p_options;
- }
- bool ViewWindow::isSessionEnabled() const
- {
- return m_sessionEnabled;
- }
- void ViewWindow::toggleDebug()
- {
- qWarning() << "debug is not supported";
- }
- void ViewWindow::updateViewModeMenu(QMenu *p_menu)
- {
- p_menu->clear();
- auto act = p_menu->addAction(tr("View Mode Not Supported"));
- act->setEnabled(false);
- }
- void ViewWindow::print()
- {
- qWarning() << "print is not supported";
- }
|