mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 22:09:52 +08:00
274 lines
7.1 KiB
C++
274 lines
7.1 KiB
C++
#include "vopenedlistmenu.h"
|
|
#include <QActionGroup>
|
|
#include <QAction>
|
|
#include <QFont>
|
|
#include <QVector>
|
|
#include <QTimer>
|
|
#include <QString>
|
|
#include <QStyleFactory>
|
|
#include <QWidgetAction>
|
|
#include <QLabel>
|
|
|
|
#include "veditwindow.h"
|
|
#include "vnotefile.h"
|
|
#include "vedittab.h"
|
|
#include "vdirectory.h"
|
|
#include "utils/vutils.h"
|
|
#include "vbuttonmenuitem.h"
|
|
#include "utils/vimnavigationforwidget.h"
|
|
|
|
static const int c_cmdTime = 1 * 1000;
|
|
|
|
static bool fileComp(const VOpenedListMenu::ItemInfo &a,
|
|
const VOpenedListMenu::ItemInfo &b)
|
|
{
|
|
QString notebooka, notebookb;
|
|
if (a.file->getType() == FileType::Note) {
|
|
notebooka = dynamic_cast<const VNoteFile *>(a.file)->getNotebookName().toLower();
|
|
} else {
|
|
notebooka = "EXTERNAL_FILES";
|
|
}
|
|
|
|
if (b.file->getType() == FileType::Note) {
|
|
notebookb = dynamic_cast<const VNoteFile *>(b.file)->getNotebookName().toLower();
|
|
} else {
|
|
notebookb = "EXTERNAL_FILES";
|
|
}
|
|
|
|
if (notebooka < notebookb) {
|
|
return true;
|
|
} else if (notebooka > notebookb) {
|
|
return false;
|
|
} else {
|
|
QString patha = a.file->fetchBasePath();
|
|
QString pathb = b.file->fetchBasePath();
|
|
#if defined(Q_OS_WIN)
|
|
patha = patha.toLower();
|
|
pathb = pathb.toLower();
|
|
#endif
|
|
if (patha == pathb) {
|
|
return a.index < b.index;
|
|
} else {
|
|
return patha < pathb;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOpenedListMenu::VOpenedListMenu(VEditWindow *p_editWin)
|
|
: QMenu(p_editWin),
|
|
m_editWin(p_editWin),
|
|
m_cmdNum(0),
|
|
m_accepted(false)
|
|
{
|
|
setToolTipsVisible(true);
|
|
|
|
m_cmdTimer = new QTimer(this);
|
|
m_cmdTimer->setSingleShot(true);
|
|
m_cmdTimer->setInterval(c_cmdTime);
|
|
connect(m_cmdTimer, &QTimer::timeout,
|
|
this, &VOpenedListMenu::cmdTimerTimeout);
|
|
|
|
connect(this, &QMenu::aboutToShow,
|
|
this, &VOpenedListMenu::updateOpenedList);
|
|
connect(this, &QMenu::triggered,
|
|
this, &VOpenedListMenu::handleItemTriggered);
|
|
}
|
|
|
|
void VOpenedListMenu::updateOpenedList()
|
|
{
|
|
// Regenerate the opened list.
|
|
m_seqActionMap.clear();
|
|
clear();
|
|
m_accepted = false;
|
|
|
|
int curTab = m_editWin->currentIndex();
|
|
int nrTab = m_editWin->count();
|
|
QVector<ItemInfo> files(nrTab);
|
|
for (int i = 0; i < nrTab; ++i) {
|
|
files[i].file = m_editWin->getTab(i)->getFile();
|
|
files[i].index = i;
|
|
}
|
|
|
|
Q_ASSERT(!files.isEmpty());
|
|
|
|
std::sort(files.begin(), files.end(), fileComp);
|
|
|
|
QString notebook;
|
|
const VDirectory *directory = NULL;
|
|
for (int i = 0; i < nrTab; ++i) {
|
|
QPointer<VFile> file = files[i].file;
|
|
int index = files[i].index;
|
|
|
|
// Whether add separator.
|
|
QString curNotebook;
|
|
const VDirectory *curDirectory = NULL;
|
|
if (file->getType() == FileType::Note) {
|
|
const VNoteFile *tmpFile = dynamic_cast<const VNoteFile *>((VFile *)file);
|
|
curNotebook = tmpFile->getNotebookName();
|
|
curDirectory = tmpFile->getDirectory();
|
|
} else {
|
|
curNotebook = "EXTERNAL_FILES";
|
|
}
|
|
|
|
QString separatorText;
|
|
if (curNotebook != notebook
|
|
|| curDirectory != directory) {
|
|
notebook = curNotebook;
|
|
directory = curDirectory;
|
|
QString dirName;
|
|
if (directory) {
|
|
dirName = directory->getName();
|
|
}
|
|
|
|
if (dirName.isEmpty()) {
|
|
separatorText = QString("[%1]").arg(notebook);
|
|
} else {
|
|
separatorText = QString("[%1] %2").arg(notebook).arg(dirName);
|
|
}
|
|
|
|
// Add label as separator.
|
|
QWidgetAction *wact = new QWidgetAction(this);
|
|
QLabel *label = new QLabel(separatorText);
|
|
label->setProperty("MenuSeparator", true);
|
|
wact->setDefaultWidget(label);
|
|
wact->setSeparator(true);
|
|
addAction(wact);
|
|
}
|
|
|
|
// Append the separator text to the end of the first item as well.
|
|
QWidgetAction *wact = new QWidgetAction(this);
|
|
wact->setData(QVariant::fromValue(file));
|
|
VButtonMenuItem *w = new VButtonMenuItem(wact,
|
|
m_editWin->tabIcon(index),
|
|
m_editWin->tabText(index),
|
|
separatorText,
|
|
this);
|
|
w->setToolTip(generateDescription(file));
|
|
wact->setDefaultWidget(w);
|
|
|
|
if (index == curTab) {
|
|
QFont boldFont = w->font();
|
|
boldFont.setBold(true);
|
|
w->setFont(boldFont);
|
|
|
|
w->setFocus();
|
|
}
|
|
|
|
addAction(wact);
|
|
m_seqActionMap[index + c_tabSequenceBase] = wact;
|
|
}
|
|
}
|
|
|
|
QString VOpenedListMenu::generateDescription(const VFile *p_file) const
|
|
{
|
|
if (!p_file) {
|
|
return "";
|
|
}
|
|
|
|
// [Notebook]path
|
|
if (p_file->getType() == FileType::Note) {
|
|
const VNoteFile *tmpFile = dynamic_cast<const VNoteFile *>(p_file);
|
|
return QString("[%1] %2").arg(tmpFile->getNotebookName()).arg(tmpFile->fetchPath());
|
|
} else {
|
|
return QString("%1").arg(p_file->fetchPath());
|
|
}
|
|
}
|
|
|
|
void VOpenedListMenu::handleItemTriggered(QAction *p_action)
|
|
{
|
|
if (p_action) {
|
|
QPointer<VFile> file = p_action->data().value<QPointer<VFile>>();
|
|
if (file) {
|
|
m_accepted = true;
|
|
emit fileTriggered(file);
|
|
}
|
|
}
|
|
|
|
hide();
|
|
}
|
|
|
|
void VOpenedListMenu::keyPressEvent(QKeyEvent *p_event)
|
|
{
|
|
if (VimNavigationForWidget::injectKeyPressEventForVim(this,
|
|
p_event)) {
|
|
m_cmdTimer->stop();
|
|
m_cmdNum = 0;
|
|
return;
|
|
}
|
|
|
|
int key = p_event->key();
|
|
switch (key) {
|
|
case Qt::Key_0:
|
|
case Qt::Key_1:
|
|
case Qt::Key_2:
|
|
case Qt::Key_3:
|
|
case Qt::Key_4:
|
|
case Qt::Key_5:
|
|
case Qt::Key_6:
|
|
case Qt::Key_7:
|
|
case Qt::Key_8:
|
|
case Qt::Key_9:
|
|
{
|
|
addDigit(key - Qt::Key_0);
|
|
return;
|
|
}
|
|
|
|
default:
|
|
m_cmdTimer->stop();
|
|
m_cmdNum = 0;
|
|
break;
|
|
}
|
|
|
|
QMenu::keyPressEvent(p_event);
|
|
}
|
|
|
|
void VOpenedListMenu::cmdTimerTimeout()
|
|
{
|
|
if (m_cmdNum > 0) {
|
|
triggerItem(m_cmdNum);
|
|
m_cmdNum = 0;
|
|
}
|
|
}
|
|
|
|
void VOpenedListMenu::addDigit(int p_digit)
|
|
{
|
|
V_ASSERT(p_digit >= 0 && p_digit <= 9);
|
|
m_cmdTimer->stop();
|
|
m_cmdNum = m_cmdNum * 10 + p_digit;
|
|
|
|
int totalItem = m_seqActionMap.size();
|
|
// Try to trigger it ASAP.
|
|
if (m_cmdNum > 0) {
|
|
if (getNumOfDigit(m_cmdNum) == getNumOfDigit(totalItem)) {
|
|
triggerItem(m_cmdNum);
|
|
m_cmdNum = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
m_cmdTimer->start();
|
|
}
|
|
|
|
int VOpenedListMenu::getNumOfDigit(int p_num)
|
|
{
|
|
int nrDigit = 1;
|
|
while (true) {
|
|
p_num /= 10;
|
|
if (p_num == 0) {
|
|
return nrDigit;
|
|
} else {
|
|
++nrDigit;
|
|
}
|
|
}
|
|
}
|
|
|
|
void VOpenedListMenu::triggerItem(int p_seq)
|
|
{
|
|
auto it = m_seqActionMap.find(p_seq);
|
|
if (it != m_seqActionMap.end()) {
|
|
QAction *act = it.value();
|
|
act->trigger();
|
|
hide();
|
|
}
|
|
}
|