support Universal Entry

`Ctrl+G` to call out the Universal Entry.
This commit is contained in:
Le Tan 2018-03-28 19:35:38 +08:00
parent 29977cff87
commit d421a8577c
12 changed files with 225 additions and 42 deletions

View File

@ -300,6 +300,8 @@ FlashPage=Ctrl+Alt+L
OpenViaDefaultProgram=F12
; Full screen
FullScreen=F11
; Universal Entry
UniversalEntry=Ctrl+G
[captain_mode_shortcuts]
; Define shortcuts in Captain mode here.

View File

@ -117,7 +117,8 @@ SOURCES += main.cpp\
vsearcher.cpp \
vsearch.cpp \
vsearchresulttree.cpp \
vsearchengine.cpp
vsearchengine.cpp \
vuniversalentry.cpp
HEADERS += vmainwindow.h \
vdirectorytree.h \
@ -224,7 +225,8 @@ HEADERS += vmainwindow.h \
vsearchresulttree.h \
isearchengine.h \
vsearchconfig.h \
vsearchengine.h
vsearchengine.h \
vuniversalentry.h
RESOURCES += \
vnote.qrc \

View File

@ -29,10 +29,10 @@ VCaptain::VCaptain(QWidget *p_parent)
// Register Captain mode leader key.
// This can fix the Input Method blocking issue.
QShortcut *shortcut = new QShortcut(QKeySequence(g_config->getShortcutKeySequence("CaptainMode")),
m_captainModeShortcut = new QShortcut(QKeySequence(g_config->getShortcutKeySequence("CaptainMode")),
this);
shortcut->setContext(Qt::ApplicationShortcut);
connect(shortcut, &QShortcut::activated,
m_captainModeShortcut->setContext(Qt::ApplicationShortcut);
connect(m_captainModeShortcut, &QShortcut::activated,
this, &VCaptain::trigger);
// Register Navigation mode as Captain mode target.
@ -280,3 +280,8 @@ bool VCaptain::handleKeyPressCaptainMode(int p_key,
return true;
}
void VCaptain::setCaptainModeEnabled(bool p_enabled)
{
m_captainModeShortcut->setEnabled(p_enabled);
}

View File

@ -43,6 +43,8 @@ public:
void *p_target,
CaptainFunc p_func);
void setCaptainModeEnabled(bool p_enabled);
signals:
// Emit when mode changed.
void captainModeChanged(bool p_captainMode);
@ -171,6 +173,8 @@ private:
// Ignore focus change during handling Captain and Navigation target actions.
bool m_ignoreFocusChange;
QShortcut *m_captainModeShortcut;
};
inline void VCaptain::setMode(CaptainMode p_mode)
@ -182,5 +186,4 @@ inline bool VCaptain::checkMode(CaptainMode p_mode) const
{
return m_mode == p_mode;
}
#endif // VCAPTAIN_H

View File

@ -1105,3 +1105,14 @@ void VEditArea::handleFileTimerTimeout()
}
}
}
QRect VEditArea::editAreaRect() const
{
QRect rt = rect();
int nrWin = splitter->count();
if (nrWin > 0) {
rt.setTopLeft(QPoint(0, getWindow(0)->tabBarHeight()));
}
return rt;
}

View File

@ -83,6 +83,9 @@ public:
// Record a closed file in the stack.
void recordClosedFile(const VFileSessionInfo &p_file);
// Return the rect not containing the tab bar.
QRect editAreaRect() const;
signals:
// Emit when current window's tab status updated.
void tabStatusUpdated(const VEditTabInfo &p_info);

View File

@ -1191,3 +1191,8 @@ void VEditWindow::tabRequestToClose(VEditTab *p_tab)
p_tab->deleteLater();
}
}
int VEditWindow::tabBarHeight() const
{
return tabBar()->height();
}

View File

@ -83,6 +83,8 @@ public:
// Auto save file.
void saveAll();
int tabBarHeight() const;
protected:
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;

View File

@ -39,6 +39,7 @@
#include "vcart.h"
#include "dialog/vexportdialog.h"
#include "vsearcher.h"
#include "vuniversalentry.h"
extern VConfigManager *g_config;
@ -64,7 +65,8 @@ VMainWindow::VMainWindow(VSingleInstanceGuard *p_guard, QWidget *p_parent)
m_guard(p_guard),
m_windowOldState(Qt::WindowNoState),
m_requestQuit(false),
m_printer(NULL)
m_printer(NULL),
m_ue(NULL)
{
qsrand(QDateTime::currentDateTime().toTime_t());
@ -145,7 +147,7 @@ void VMainWindow::registerCaptainAndNavigationTargets()
m_captain->registerNavigationTarget(notebookSelector);
m_captain->registerNavigationTarget(directoryTree);
m_captain->registerNavigationTarget(m_fileList);
m_captain->registerNavigationTarget(editArea);
m_captain->registerNavigationTarget(m_editArea);
m_captain->registerNavigationTarget(m_toolBox);
m_captain->registerNavigationTarget(outline);
m_captain->registerNavigationTarget(m_snippetList);
@ -205,11 +207,11 @@ void VMainWindow::setupUI()
m_fileList = new VFileList();
m_fileList->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
editArea = new VEditArea();
editArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
m_findReplaceDialog = editArea->getFindReplaceDialog();
m_fileList->setEditArea(editArea);
directoryTree->setEditArea(editArea);
m_editArea = new VEditArea();
m_editArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
m_findReplaceDialog = m_editArea->getFindReplaceDialog();
m_fileList->setEditArea(m_editArea);
directoryTree->setEditArea(m_editArea);
// Main Splitter
m_mainSplitter = new QSplitter();
@ -217,7 +219,7 @@ void VMainWindow::setupUI()
m_mainSplitter->addWidget(directoryPanel);
m_mainSplitter->addWidget(m_fileList);
setTabOrder(directoryTree, m_fileList->getContentWidget());
m_mainSplitter->addWidget(editArea);
m_mainSplitter->addWidget(m_editArea);
m_mainSplitter->setStretchFactor(0, 0);
m_mainSplitter->setStretchFactor(1, 0);
m_mainSplitter->setStretchFactor(2, 1);
@ -226,10 +228,10 @@ void VMainWindow::setupUI()
connect(directoryTree, &VDirectoryTree::currentDirectoryChanged,
m_fileList, &VFileList::setDirectory);
connect(directoryTree, &VDirectoryTree::directoryUpdated,
editArea, &VEditArea::handleDirectoryUpdated);
m_editArea, &VEditArea::handleDirectoryUpdated);
connect(notebookSelector, &VNotebookSelector::notebookUpdated,
editArea, &VEditArea::handleNotebookUpdated);
m_editArea, &VEditArea::handleNotebookUpdated);
connect(notebookSelector, &VNotebookSelector::notebookCreated,
directoryTree, [this](const QString &p_name, bool p_import) {
Q_UNUSED(p_name);
@ -239,16 +241,16 @@ void VMainWindow::setupUI()
});
connect(m_fileList, &VFileList::fileClicked,
editArea, &VEditArea::openFile);
m_editArea, &VEditArea::openFile);
connect(m_fileList, &VFileList::fileCreated,
editArea, &VEditArea::openFile);
m_editArea, &VEditArea::openFile);
connect(m_fileList, &VFileList::fileUpdated,
editArea, &VEditArea::handleFileUpdated);
connect(editArea, &VEditArea::tabStatusUpdated,
m_editArea, &VEditArea::handleFileUpdated);
connect(m_editArea, &VEditArea::tabStatusUpdated,
this, &VMainWindow::handleAreaTabStatusUpdated);
connect(editArea, &VEditArea::statusMessage,
connect(m_editArea, &VEditArea::statusMessage,
this, &VMainWindow::showStatusMessage);
connect(editArea, &VEditArea::vimStatusUpdated,
connect(m_editArea, &VEditArea::vimStatusUpdated,
this, &VMainWindow::handleVimStatusUpdated);
connect(m_findReplaceDialog, &VFindReplaceDialog::findTextChanged,
this, &VMainWindow::handleFindDialogTextChanged);
@ -705,7 +707,7 @@ void VMainWindow::initFileToolBar(QSize p_iconSize)
VUtils::fixTextWithCaptainShortcut(m_discardExitAct, "DiscardAndRead");
m_discardExitAct->setStatusTip(tr("Discard changes and exit edit mode"));
connect(m_discardExitAct, &QAction::triggered,
editArea, &VEditArea::readFile);
m_editArea, &VEditArea::readFile);
updateEditReadAct(NULL);
@ -720,7 +722,7 @@ void VMainWindow::initFileToolBar(QSize p_iconSize)
}
connect(saveNoteAct, &QAction::triggered,
editArea, &VEditArea::saveFile);
m_editArea, &VEditArea::saveFile);
newRootDirAct->setEnabled(false);
newNoteAct->setEnabled(false);
@ -778,7 +780,7 @@ void VMainWindow::initHelpMenu()
this, [this](){
QString docFile = VUtils::getDocFile(VNote::c_markdownGuideDocFile);
VFile *file = vnote->getOrphanFile(docFile, false, true);
editArea->openFile(file, OpenFileMode::Read);
m_editArea->openFile(file, OpenFileMode::Read);
});
QAction *docAct = new QAction(tr("&Documentation"), this);
@ -1306,12 +1308,12 @@ void VMainWindow::initToolsDock()
// Outline tree.
outline = new VOutline(this);
connect(editArea, &VEditArea::outlineChanged,
connect(m_editArea, &VEditArea::outlineChanged,
outline, &VOutline::updateOutline);
connect(editArea, &VEditArea::currentHeaderChanged,
connect(m_editArea, &VEditArea::currentHeaderChanged,
outline, &VOutline::updateCurrentHeader);
connect(outline, &VOutline::outlineItemActivated,
editArea, &VEditArea::scrollToHeader);
m_editArea, &VEditArea::scrollToHeader);
// Snippets.
m_snippetList = new VSnippetList(this);
@ -2196,7 +2198,7 @@ void VMainWindow::closeEvent(QCloseEvent *event)
QVector<VFileSessionInfo> fileInfos;
QVector<VEditTabInfo> tabs;
if (saveOpenedNotes) {
tabs = editArea->getAllTabsInfo();
tabs = m_editArea->getAllTabsInfo();
fileInfos.reserve(tabs.size());
@ -2215,7 +2217,7 @@ void VMainWindow::closeEvent(QCloseEvent *event)
}
}
if (!editArea->closeAllFiles(false)) {
if (!m_editArea->closeAllFiles(false)) {
// Fail to close all the opened files, cancel closing app.
event->ignore();
return;
@ -2380,7 +2382,7 @@ void VMainWindow::handleFindDialogTextChanged(const QString &p_text, uint /* p_o
void VMainWindow::openFindDialog()
{
m_findReplaceDialog->openDialog(editArea->getSelectedText());
m_findReplaceDialog->openDialog(m_editArea->getSelectedText());
}
void VMainWindow::viewSettings()
@ -2392,7 +2394,7 @@ void VMainWindow::viewSettings()
void VMainWindow::closeCurrentFile()
{
if (m_curFile) {
editArea->closeFile(m_curFile, false);
m_editArea->closeFile(m_curFile, false);
}
}
@ -2454,7 +2456,7 @@ void VMainWindow::shortcutsHelp()
{
QString docFile = VUtils::getDocFile(VNote::c_shortcutsDocFile);
VFile *file = vnote->getOrphanFile(docFile, false, true);
editArea->openFile(file, OpenFileMode::Read);
m_editArea->openFile(file, OpenFileMode::Read);
}
void VMainWindow::printNote()
@ -2549,7 +2551,7 @@ bool VMainWindow::tryOpenInternalFile(const QString &p_filePath)
VFile *file = vnote->getInternalFile(p_filePath);
if (file) {
editArea->openFile(file, OpenFileMode::Read);
m_editArea->openFile(file, OpenFileMode::Read);
return true;
}
}
@ -2572,7 +2574,7 @@ void VMainWindow::openFiles(const QStringList &p_files,
file = vnote->getOrphanFile(p_files[i], true);
}
editArea->openFile(file, p_mode, p_forceMode);
m_editArea->openFile(file, p_mode, p_forceMode);
}
}
@ -2667,7 +2669,7 @@ void VMainWindow::openStartupPages()
{
QVector<VFileSessionInfo> files = g_config->getLastOpenedFiles();
qDebug() << "open" << files.size() << "last opened files";
editArea->openFiles(files);
m_editArea->openFiles(files);
break;
}
@ -2788,7 +2790,7 @@ bool VMainWindow::closeFileByCaptain(void *p_target, void *p_data)
VMainWindow *obj = static_cast<VMainWindow *>(p_target);
obj->closeCurrentFile();
QWidget *nextFocus = obj->editArea->getCurrentTab();
QWidget *nextFocus = obj->m_editArea->getCurrentTab();
if (nextFocus) {
nextFocus->setFocus();
} else {
@ -2846,6 +2848,15 @@ void VMainWindow::initShortcuts()
connect(closeNoteShortcut, &QShortcut::activated,
this, &VMainWindow::closeCurrentFile);
}
keySeq = g_config->getShortcutKeySequence("UniversalEntry");
qDebug() << "set UniversalEntry shortcut to" << keySeq;
if (!keySeq.isEmpty()) {
QShortcut *ueShortcut = new QShortcut(QKeySequence(keySeq), this);
ueShortcut->setContext(Qt::WidgetWithChildrenShortcut);
connect(ueShortcut, &QShortcut::activated,
this, &VMainWindow::activateUniversalEntry);
}
}
void VMainWindow::openFlashPage()
@ -3091,10 +3102,10 @@ void VMainWindow::toggleEditReadMode()
if (m_curTab->isEditMode()) {
// Save changes and read.
editArea->saveAndReadFile();
m_editArea->saveAndReadFile();
} else {
// Edit.
editArea->editFile();
m_editArea->editFile();
}
}
@ -3154,3 +3165,34 @@ VNotebook *VMainWindow::getCurrentNotebook() const
{
return notebookSelector->currentNotebook();
}
void VMainWindow::activateUniversalEntry()
{
if (!m_ue) {
m_ue = new VUniversalEntry(this);
m_ue->hide();
m_ue->setWindowFlags(Qt::Popup
| Qt::FramelessWindowHint
| Qt::NoDropShadowWindowHint);
connect(m_ue, &VUniversalEntry::exited,
this, [this]() {
m_captain->setCaptainModeEnabled(true);
});
}
m_captain->setCaptainModeEnabled(false);
// Move it to the top left corner of edit area.
QPoint topLeft = m_editArea->mapToGlobal(QPoint(0, 0));
QRect eaRect = m_editArea->editAreaRect();
topLeft += eaRect.topLeft();
// Use global position.
m_ue->move(topLeft);
eaRect.moveTop(0);
m_ue->setAvailableRect(eaRect);
m_ue->show();
m_ue->raise();
}

View File

@ -41,6 +41,7 @@ class VSnippetList;
class VCart;
class VSearcher;
class QPrinter;
class VUniversalEntry;
enum class PanelViewState
{
@ -182,6 +183,9 @@ private slots:
void toggleEditReadMode();
// Activate Universal Entry.
void activateUniversalEntry();
protected:
void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;
@ -231,6 +235,7 @@ private:
void initEditorLineNumberMenu(QMenu *p_menu);
void initEditorStyleMenu(QMenu *p_emnu);
void updateWindowTitle(const QString &str);
void initVimCmd();
@ -323,7 +328,7 @@ private:
// Move directory and file panel in one compact vertical split.
QSplitter *m_naviSplitter;
VEditArea *editArea;
VEditArea *m_editArea;
QDockWidget *m_toolDock;
@ -433,6 +438,8 @@ private:
QPrinter *m_printer;
VUniversalEntry *m_ue;
// Interval of the shared memory timer in ms.
static const int c_sharedMemTimerInterval;
};
@ -444,7 +451,7 @@ inline VFileList *VMainWindow::getFileList() const
inline VEditArea *VMainWindow::getEditArea() const
{
return editArea;
return m_editArea;
}
inline VCaptain *VMainWindow::getCaptain() const

58
src/vuniversalentry.cpp Normal file
View File

@ -0,0 +1,58 @@
#include "vuniversalentry.h"
#include <QVBoxLayout>
#include <QLabel>
#include <QDebug>
#include <QHideEvent>
#include <QShowEvent>
#include "vlineedit.h"
#include "utils/vutils.h"
#define MINIMUM_WIDTH 200
VUniversalEntry::VUniversalEntry(QWidget *p_parent)
: QWidget(p_parent),
m_availableRect(0, 0, MINIMUM_WIDTH, MINIMUM_WIDTH)
{
m_minimumWidth = MINIMUM_WIDTH * VUtils::calculateScaleFactor() + 0.5;
setupUI();
}
void VUniversalEntry::setupUI()
{
m_cmdEdit = new VLineEdit(this);
m_cmdEdit->setPlaceholderText(tr("Welcome to Universal Entry"));
m_layout = new QVBoxLayout();
m_layout->addWidget(m_cmdEdit);
m_layout->setContentsMargins(0, 0, 0, 0);
setLayout(m_layout);
setMinimumWidth(m_minimumWidth);
}
void VUniversalEntry::hideEvent(QHideEvent *p_event)
{
QWidget::hideEvent(p_event);
emit exited();
}
void VUniversalEntry::showEvent(QShowEvent *p_event)
{
QWidget::showEvent(p_event);
m_cmdEdit->setFocus();
m_cmdEdit->selectAll();
}
void VUniversalEntry::setAvailableRect(const QRect &p_rect)
{
m_availableRect = p_rect;
if (m_availableRect.width() < m_minimumWidth) {
m_availableRect.setWidth(m_minimumWidth);
}
}

43
src/vuniversalentry.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef VUNIVERSALENTRY_H
#define VUNIVERSALENTRY_H
#include <QWidget>
#include <QRect>
class VLineEdit;
class QVBoxLayout;
class QHideEvent;
class QShowEvent;
class VUniversalEntry : public QWidget
{
Q_OBJECT
public:
explicit VUniversalEntry(QWidget *p_parent = nullptr);
// Set the availabel width and height.
void setAvailableRect(const QRect &p_rect);
signals:
// Exit Universal Entry.
void exited();
protected:
void hideEvent(QHideEvent *p_event) Q_DECL_OVERRIDE;
void showEvent(QShowEvent *p_event) Q_DECL_OVERRIDE;
private:
void setupUI();
VLineEdit *m_cmdEdit;
QVBoxLayout *m_layout;
// Rect availabel for the UE to use.
QRect m_availableRect;
int m_minimumWidth;
};
#endif // VUNIVERSALENTRY_H