refactor: VNotebookSelector

Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
Le Tan 2016-12-05 21:50:16 +08:00
parent 9a197b5087
commit e32ee1fa90
9 changed files with 291 additions and 70 deletions

View File

@ -36,18 +36,16 @@ QDockWidget::close-button:hover, QDockWidget::float-button:hover {
background-color: @hover-color; background-color: @hover-color;
} }
/* QComboBox */ /* QComboBox#NotebookSelector */
QComboBox[OnMainWindow="true"] { QComboBox#NotebookSelector {
border: 1px solid grey; border: 1px solid grey;
background-color: @base-background; background-color: @base-background;
} font-size: 14px;
QComboBox[OnMainWindow="true"]:on { /* shift the text when the popup opens */
padding-top: 3px; padding-top: 3px;
padding-left: 4px; padding-bottom: 3px;
} }
QComboBox[OnMainWindow="true"]::drop-down { QComboBox#NotebookSelector::drop-down {
subcontrol-origin: padding; subcontrol-origin: padding;
subcontrol-position: top right; subcontrol-position: top right;
width: 20px; width: 20px;
@ -55,24 +53,23 @@ QComboBox[OnMainWindow="true"]::drop-down {
background: transparent; background: transparent;
} }
QComboBox[OnMainWindow="true"]::down-arrow { QComboBox#NotebookSelector::down-arrow {
image: url(:/resources/icons/arrow_dropdown.svg); image: url(:/resources/icons/arrow_dropdown.svg);
width: 20px; width: 20px;
} }
QComboBox[OnMainWindow="true"]::down-arrow:on { /* shift the arrow when popup is open */ QComboBox#NotebookSelector QListWidget {
top: 1px; border: 1px solid grey;
left: 1px; background-color: @base-background;
font-size: 14px;
} }
QComboBox[OnMainWindow="true"]::item { QComboBox#NotebookSelector QListWidget::item {
padding-left: 20px; padding-top: 5px;
border: none; padding-bottom: 5px;
height: 20px;
} }
QComboBox[OnMainWindow="true"]::item:selected { QComboBox#NotebookSelector QListWidget::item:hover {
padding-left: 20px;
border: none;
background-color: @hover-color; background-color: @hover-color;
} }
/* End QComboBox#NotebookSelector */

View File

@ -45,7 +45,8 @@ SOURCES += main.cpp\
vsingleinstanceguard.cpp \ vsingleinstanceguard.cpp \
vdirectory.cpp \ vdirectory.cpp \
vfile.cpp \ vfile.cpp \
vnotebookselector.cpp vnotebookselector.cpp \
vnofocusitemdelegate.cpp
HEADERS += vmainwindow.h \ HEADERS += vmainwindow.h \
vdirectorytree.h \ vdirectorytree.h \
@ -79,7 +80,8 @@ HEADERS += vmainwindow.h \
vsingleinstanceguard.h \ vsingleinstanceguard.h \
vdirectory.h \ vdirectory.h \
vfile.h \ vfile.h \
vnotebookselector.h vnotebookselector.h \
vnofocusitemdelegate.h
RESOURCES += \ RESOURCES += \
vnote.qrc vnote.qrc

View File

@ -80,30 +80,14 @@ QWidget *VMainWindow::setupDirectoryPanel()
notebookLabel = new QLabel(tr("Notebook")); notebookLabel = new QLabel(tr("Notebook"));
directoryLabel = new QLabel(tr("Directory")); directoryLabel = new QLabel(tr("Directory"));
newNotebookBtn = new QPushButton(QIcon(":/resources/icons/create_notebook.svg"), "");
newNotebookBtn->setToolTip(tr("Create a new notebook"));
newNotebookBtn->setProperty("OnMainWindow", true);
deleteNotebookBtn = new QPushButton(QIcon(":/resources/icons/delete_notebook.svg"), "");
deleteNotebookBtn->setToolTip(tr("Delete current notebook"));
deleteNotebookBtn->setProperty("OnMainWindow", true);
notebookInfoBtn = new QPushButton(QIcon(":/resources/icons/notebook_info.svg"), "");
notebookInfoBtn->setToolTip(tr("View and edit current notebook's information"));
notebookInfoBtn->setProperty("OnMainWindow", true);
notebookSelector = new VNotebookSelector(vnote); notebookSelector = new VNotebookSelector(vnote);
notebookSelector->setProperty("OnMainWindow", true); notebookSelector->setObjectName("NotebookSelector");
notebookSelector->setSizeAdjustPolicy(QComboBox::AdjustToContents); notebookSelector->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
directoryTree = new VDirectoryTree(vnote); directoryTree = new VDirectoryTree(vnote);
QHBoxLayout *nbBtnLayout = new QHBoxLayout;
nbBtnLayout->addWidget(notebookLabel);
nbBtnLayout->addStretch();
nbBtnLayout->addWidget(newNotebookBtn);
nbBtnLayout->addWidget(deleteNotebookBtn);
nbBtnLayout->addWidget(notebookInfoBtn);
nbBtnLayout->setContentsMargins(0, 0, 0, 0);
QVBoxLayout *nbLayout = new QVBoxLayout; QVBoxLayout *nbLayout = new QVBoxLayout;
nbLayout->addLayout(nbBtnLayout); nbLayout->addWidget(notebookLabel);
nbLayout->addWidget(notebookSelector); nbLayout->addWidget(notebookSelector);
nbLayout->addWidget(directoryLabel); nbLayout->addWidget(directoryLabel);
nbLayout->addWidget(directoryTree); nbLayout->addWidget(directoryTree);
@ -117,13 +101,6 @@ QWidget *VMainWindow::setupDirectoryPanel()
connect(notebookSelector, &VNotebookSelector::curNotebookChanged, connect(notebookSelector, &VNotebookSelector::curNotebookChanged,
this, &VMainWindow::handleCurrentNotebookChanged); this, &VMainWindow::handleCurrentNotebookChanged);
connect(newNotebookBtn, &QPushButton::clicked,
notebookSelector, &VNotebookSelector::newNotebook);
connect(deleteNotebookBtn, SIGNAL(clicked(bool)),
notebookSelector, SLOT(deleteNotebook()));
connect(notebookInfoBtn, SIGNAL(clicked(bool)),
notebookSelector, SLOT(editNotebookInfo()));
connect(directoryTree, &VDirectoryTree::currentDirectoryChanged, connect(directoryTree, &VDirectoryTree::currentDirectoryChanged,
this, &VMainWindow::handleCurrentDirectoryChanged); this, &VMainWindow::handleCurrentDirectoryChanged);
return nbContainer; return nbContainer;

View File

@ -74,9 +74,6 @@ private:
QLabel *notebookLabel; QLabel *notebookLabel;
QLabel *directoryLabel; QLabel *directoryLabel;
VNotebookSelector *notebookSelector; VNotebookSelector *notebookSelector;
QPushButton *newNotebookBtn;
QPushButton *deleteNotebookBtn;
QPushButton *notebookInfoBtn;
VFileList *fileList; VFileList *fileList;
VDirectoryTree *directoryTree; VDirectoryTree *directoryTree;
QSplitter *mainSplitter; QSplitter *mainSplitter;

View File

@ -0,0 +1,17 @@
#include "vnofocusitemdelegate.h"
VNoFocusItemDelegate::VNoFocusItemDelegate(QWidget *parent)
: QStyledItemDelegate(parent)
{
}
void VNoFocusItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItem itemOp(option);
if (itemOp.state & QStyle::State_HasFocus) {
itemOp.state ^= QStyle::State_HasFocus;
}
QStyledItemDelegate::paint(painter, itemOp, index);
}

View File

@ -0,0 +1,15 @@
#ifndef VNOFOCUSITEMDELEGATE_H
#define VNOFOCUSITEMDELEGATE_H
#include <QStyledItemDelegate>
class VNoFocusItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit VNoFocusItemDelegate(QWidget *parent = 0);
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const Q_DECL_OVERRIDE;
};
#endif // VNOFOCUSITEMDELEGATE_H

View File

@ -59,10 +59,11 @@ void VNotebook::deleteNotebook(VNotebook *p_notebook)
if (!p_notebook) { if (!p_notebook) {
return; return;
} }
QString path = p_notebook->getPath();
p_notebook->close(); p_notebook->close();
delete p_notebook; delete p_notebook;
QString path = p_notebook->getPath();
QDir dir(path); QDir dir(path);
if (!dir.removeRecursively()) { if (!dir.removeRecursively()) {
qWarning() << "failed to delete" << path; qWarning() << "failed to delete" << path;

View File

@ -1,6 +1,9 @@
#include "vnotebookselector.h" #include "vnotebookselector.h"
#include <QDebug> #include <QDebug>
#include <QJsonObject> #include <QJsonObject>
#include <QListWidget>
#include <QAction>
#include <QMenu>
#include "vnotebook.h" #include "vnotebook.h"
#include "vconfigmanager.h" #include "vconfigmanager.h"
#include "dialog/vnewnotebookdialog.h" #include "dialog/vnewnotebookdialog.h"
@ -10,15 +13,48 @@
#include "utils/vutils.h" #include "utils/vutils.h"
#include "vnote.h" #include "vnote.h"
#include "veditarea.h" #include "veditarea.h"
#include "vnofocusitemdelegate.h"
extern VConfigManager vconfig; extern VConfigManager vconfig;
const int VNotebookSelector::c_notebookStartIdx = 1;
VNotebookSelector::VNotebookSelector(VNote *vnote, QWidget *p_parent) VNotebookSelector::VNotebookSelector(VNote *vnote, QWidget *p_parent)
: QComboBox(p_parent), m_vnote(vnote), m_notebooks(m_vnote->getNotebooks()), : QComboBox(p_parent), m_vnote(vnote), m_notebooks(m_vnote->getNotebooks()),
m_editArea(NULL) m_editArea(NULL), m_lastValidIndex(-1)
{ {
m_listWidget = new QListWidget(this);
m_listWidget->setItemDelegate(new VNoFocusItemDelegate(this));
m_listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_listWidget, &QListWidget::customContextMenuRequested,
this, &VNotebookSelector::requestPopupListContextMenu);
setModel(m_listWidget->model());
setView(m_listWidget);
m_listWidget->viewport()->installEventFilter(this);
initActions();
connect(this, SIGNAL(currentIndexChanged(int)), connect(this, SIGNAL(currentIndexChanged(int)),
this, SLOT(handleCurIndexChanged(int))); this, SLOT(handleCurIndexChanged(int)));
connect(this, SIGNAL(activated(int)),
this, SLOT(handleItemActivated(int)));
}
void VNotebookSelector::initActions()
{
m_deleteNotebookAct = new QAction(QIcon(":/resources/icons/delete_notebook.svg"),
tr("&Delete"), this);
m_deleteNotebookAct->setStatusTip(tr("Delete current notebook"));
connect(m_deleteNotebookAct, SIGNAL(triggered(bool)),
this, SLOT(deleteNotebook()));
m_notebookInfoAct = new QAction(QIcon(":/resources/icons/notebook_info.svg"),
tr("&Info"));
m_notebookInfoAct->setStatusTip(tr("View and edit current notebook's information"));
connect(m_notebookInfoAct, SIGNAL(triggered(bool)),
this, SLOT(editNotebookInfo()));
} }
void VNotebookSelector::updateComboBox() void VNotebookSelector::updateComboBox()
@ -28,42 +64,99 @@ void VNotebookSelector::updateComboBox()
disconnect(this, SIGNAL(currentIndexChanged(int)), disconnect(this, SIGNAL(currentIndexChanged(int)),
this, SLOT(handleCurIndexChanged(int))); this, SLOT(handleCurIndexChanged(int)));
clear(); clear();
m_listWidget->clear();
insertAddNotebookItem();
for (int i = 0; i < m_notebooks.size(); ++i) { for (int i = 0; i < m_notebooks.size(); ++i) {
addItem(QIcon(":/resources/icons/notebook_item.svg"), m_notebooks[i]->getName()); addNotebookItem(m_notebooks[i]->getName());
} }
setCurrentIndex(-1); setCurrentIndex(-1);
connect(this, SIGNAL(currentIndexChanged(int)), connect(this, SIGNAL(currentIndexChanged(int)),
this, SLOT(handleCurIndexChanged(int))); this, SLOT(handleCurIndexChanged(int)));
if (m_notebooks.isEmpty() && index != -1) { if (m_notebooks.isEmpty()) {
index = -1; vconfig.setCurNotebookIndex(-1);
vconfig.setCurNotebookIndex(index); setCurrentIndex(0);
} else {
setCurrentIndexNotebook(index);
} }
setCurrentIndex(index);
qDebug() << "notebooks" << m_notebooks.size() << "current index" << index; qDebug() << "notebooks" << m_notebooks.size() << "current index" << index;
} }
void VNotebookSelector::setCurrentIndexNotebook(int p_index)
{
if (p_index > -1) {
p_index += c_notebookStartIdx;
}
setCurrentIndex(p_index);
}
void VNotebookSelector::insertAddNotebookItem()
{
QListWidgetItem *item = new QListWidgetItem();
item->setIcon(QIcon(":/resources/icons/create_notebook.svg"));
item->setText("Add Notebook");
QFont font;
font.setItalic(true);
item->setData(Qt::FontRole, font);
item->setToolTip(tr("Create or import a notebook."));
m_listWidget->insertItem(0, item);
}
void VNotebookSelector::handleCurIndexChanged(int p_index) void VNotebookSelector::handleCurIndexChanged(int p_index)
{ {
qDebug() << "current index changed" << p_index; qDebug() << "current index changed" << p_index << "startIdx" << c_notebookStartIdx;
VNotebook *nb = NULL; VNotebook *nb = NULL;
if (p_index > -1) { if (p_index > -1) {
nb = m_notebooks[p_index]; if (p_index < c_notebookStartIdx) {
// Click a special action item.
if (m_listWidget->count() == c_notebookStartIdx) {
// There is no regular notebook item. Just let it be selected.
p_index = -1;
} else {
// handleItemActivated() will handle the logics.
return;
}
} else {
int nbIdx = p_index - c_notebookStartIdx;
Q_ASSERT(nbIdx >= 0);
nb = m_notebooks[nbIdx];
}
} }
m_lastValidIndex = p_index;
QString tooltip;
if (p_index > -1) {
p_index -= c_notebookStartIdx;
tooltip = nb->getName();
}
setToolTip(tooltip);
vconfig.setCurNotebookIndex(p_index); vconfig.setCurNotebookIndex(p_index);
emit curNotebookChanged(nb); emit curNotebookChanged(nb);
} }
void VNotebookSelector::handleItemActivated(int p_index)
{
if (p_index > -1 && p_index < c_notebookStartIdx) {
// Click a special action item
if (m_lastValidIndex > -1) {
setCurrentIndex(m_lastValidIndex);
}
newNotebook();
}
}
void VNotebookSelector::update() void VNotebookSelector::update()
{ {
updateComboBox(); updateComboBox();
} }
void VNotebookSelector::newNotebook() bool VNotebookSelector::newNotebook()
{ {
QString info; QString info;
QString defaultName("new_notebook"); QString defaultName("new_notebook");
QString defaultPath; QString defaultPath;
do { do {
VNewNotebookDialog dialog(tr("Create notebook"), info, defaultName, VNewNotebookDialog dialog(tr("Create notebook"), info, defaultName,
defaultPath, this); defaultPath, this);
@ -77,9 +170,11 @@ void VNotebookSelector::newNotebook()
continue; continue;
} }
createNotebook(name, path); createNotebook(name, path);
return true;
} }
break; break;
} while (true); } while (true);
return false;
} }
VNotebook *VNotebookSelector::findNotebook(const QString &p_name) VNotebook *VNotebookSelector::findNotebook(const QString &p_name)
@ -98,14 +193,22 @@ void VNotebookSelector::createNotebook(const QString &p_name, const QString &p_p
m_notebooks.append(nb); m_notebooks.append(nb);
vconfig.setNotebooks(m_notebooks); vconfig.setNotebooks(m_notebooks);
addItem(QIcon(":/resources/icons/notebook_item.svg"), nb->getName()); addNotebookItem(nb->getName());
setCurrentIndex(m_notebooks.size() - 1); setCurrentIndexNotebook(m_notebooks.size() - 1);
} }
void VNotebookSelector::deleteNotebook() void VNotebookSelector::deleteNotebook()
{ {
int curIndex = currentIndex(); QList<QListWidgetItem *> items = m_listWidget->selectedItems();
VNotebook *notebook = m_notebooks[curIndex]; if (items.isEmpty()) {
return;
}
Q_ASSERT(items.size() == 1);
QListWidgetItem *item = items[0];
int index = indexOfListItem(item);
VNotebook *notebook = getNotebookFromComboIndex(index);
Q_ASSERT(notebook);
QString curName = notebook->getName(); QString curName = notebook->getName();
QString curPath = notebook->getPath(); QString curPath = notebook->getPath();
@ -126,7 +229,7 @@ void VNotebookSelector::deleteNotebook(VNotebook *p_notebook)
m_notebooks.remove(idx); m_notebooks.remove(idx);
vconfig.setNotebooks(m_notebooks); vconfig.setNotebooks(m_notebooks);
removeItem(idx); removeNotebookItem(idx);
VNotebook::deleteNotebook(p_notebook); VNotebook::deleteNotebook(p_notebook);
} }
@ -141,11 +244,18 @@ int VNotebookSelector::indexOfNotebook(const VNotebook *p_notebook)
return -1; return -1;
} }
void VNotebookSelector::editNotebookInfo() void VNotebookSelector::editNotebookInfo()
{ {
int curIndex = currentIndex(); QList<QListWidgetItem *> items = m_listWidget->selectedItems();
Q_ASSERT(curIndex > -1); if (items.isEmpty()) {
VNotebook *notebook = m_notebooks[curIndex]; return;
}
Q_ASSERT(items.size() == 1);
QListWidgetItem *item = items[0];
int index = indexOfListItem(item);
VNotebook *notebook = getNotebookFromComboIndex(index);
QString info; QString info;
QString curName = notebook->getName(); QString curName = notebook->getName();
QString defaultPath = notebook->getPath(); QString defaultPath = notebook->getPath();
@ -164,10 +274,72 @@ void VNotebookSelector::editNotebookInfo()
continue; continue;
} }
notebook->rename(name); notebook->rename(name);
setItemText(curIndex, name); updateComboBoxItem(index, name);
vconfig.setNotebooks(m_notebooks); vconfig.setNotebooks(m_notebooks);
emit notebookUpdated(notebook); emit notebookUpdated(notebook);
} }
break; break;
} while (true); } while (true);
} }
void VNotebookSelector::addNotebookItem(const QString &p_name)
{
QListWidgetItem *item = new QListWidgetItem(m_listWidget);
item->setText(p_name);
item->setToolTip(p_name);
item->setIcon(QIcon(":/resources/icons/notebook_item.svg"));
}
void VNotebookSelector::removeNotebookItem(int p_index)
{
QListWidgetItem *item = m_listWidget->item(p_index + c_notebookStartIdx);
m_listWidget->removeItemWidget(item);
delete item;
}
void VNotebookSelector::updateComboBoxItem(int p_index, const QString &p_name)
{
QListWidgetItem *item = m_listWidget->item(p_index);
item->setText(p_name);
item->setToolTip(p_name);
}
void VNotebookSelector::requestPopupListContextMenu(QPoint p_pos)
{
QModelIndex index = m_listWidget->indexAt(p_pos);
if (!index.isValid() || index.row() < c_notebookStartIdx) {
return;
}
QListWidgetItem *item = m_listWidget->itemAt(p_pos);
Q_ASSERT(item);
m_listWidget->clearSelection();
item->setSelected(true);
QMenu menu(this);
menu.addAction(m_deleteNotebookAct);
menu.addAction(m_notebookInfoAct);
menu.exec(m_listWidget->mapToGlobal(p_pos));
}
bool VNotebookSelector::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::MouseButtonRelease) {
if (static_cast<QMouseEvent *>(event)->button() == Qt::RightButton) {
return true;
}
}
return QComboBox::eventFilter(watched, event);
}
int VNotebookSelector::indexOfListItem(const QListWidgetItem *p_item)
{
int nrItems = m_listWidget->count();
for (int i = 0; i < nrItems; ++i) {
if (m_listWidget->item(i) == p_item) {
return i;
}
}
return -1;
}

View File

@ -8,6 +8,9 @@
class VNotebook; class VNotebook;
class VNote; class VNote;
class VEditArea; class VEditArea;
class QListWidget;
class QAction;
class QListWidgetItem;
class VNotebookSelector : public QComboBox class VNotebookSelector : public QComboBox
{ {
@ -23,23 +26,51 @@ signals:
void notebookUpdated(const VNotebook *p_notebook); void notebookUpdated(const VNotebook *p_notebook);
public slots: public slots:
void newNotebook(); bool newNotebook();
void deleteNotebook(); void deleteNotebook();
void editNotebookInfo(); void editNotebookInfo();
protected:
bool eventFilter(QObject *watched, QEvent *event) Q_DECL_OVERRIDE;
private slots: private slots:
void handleCurIndexChanged(int p_index); void handleCurIndexChanged(int p_index);
void handleItemActivated(int p_index);
void requestPopupListContextMenu(QPoint p_pos);
private: private:
void initActions();
void updateComboBox(); void updateComboBox();
VNotebook *findNotebook(const QString &p_name); VNotebook *findNotebook(const QString &p_name);
// Return the index of @p_notebook in m_noteboks.
int indexOfNotebook(const VNotebook *p_notebook); int indexOfNotebook(const VNotebook *p_notebook);
void createNotebook(const QString &p_name, const QString &p_path); void createNotebook(const QString &p_name, const QString &p_path);
void deleteNotebook(VNotebook *p_notebook); void deleteNotebook(VNotebook *p_notebook);
void addNotebookItem(const QString &p_name);
// @p_index is the index of m_notebooks, NOT of QComboBox.
void removeNotebookItem(int p_index);
// @p_index is the index of QComboBox.
void updateComboBoxItem(int p_index, const QString &p_name);
void insertAddNotebookItem();
// @p_index is the index of m_notebooks.
void setCurrentIndexNotebook(int p_index);
int indexOfListItem(const QListWidgetItem *p_item);
// @p_index is the idnex of QComboBox.
inline VNotebook *getNotebookFromComboIndex(int p_index);
VNote *m_vnote; VNote *m_vnote;
QVector<VNotebook *> &m_notebooks; QVector<VNotebook *> &m_notebooks;
VEditArea *m_editArea; VEditArea *m_editArea;
QListWidget *m_listWidget;
int m_lastValidIndex;
// Actions
QAction *m_deleteNotebookAct;
QAction *m_notebookInfoAct;
// We will add several special action item in the combobox. This is the start index
// of the real notebook items related to m_notebooks.
static const int c_notebookStartIdx;
}; };
inline void VNotebookSelector::setEditArea(VEditArea *p_editArea) inline void VNotebookSelector::setEditArea(VEditArea *p_editArea)
@ -47,4 +78,16 @@ inline void VNotebookSelector::setEditArea(VEditArea *p_editArea)
m_editArea = p_editArea; m_editArea = p_editArea;
} }
inline VNotebook *VNotebookSelector::getNotebookFromComboIndex(int p_index)
{
if (p_index < c_notebookStartIdx) {
return NULL;
}
int nbIdx = p_index - c_notebookStartIdx;
if (nbIdx >= m_notebooks.size()) {
return NULL;
}
return m_notebooks[nbIdx];
}
#endif // VNOTEBOOKSELECTOR_H #endif // VNOTEBOOKSELECTOR_H