diff --git a/src/src.pro b/src/src.pro index 4152078a..8ddb744f 100644 --- a/src/src.pro +++ b/src/src.pro @@ -36,7 +36,6 @@ SOURCES += main.cpp\ vmarkdownconverter.cpp \ dialog/vnotebookinfodialog.cpp \ dialog/vdirinfodialog.cpp \ - vfilelistpanel.cpp \ dialog/vfileinfodialog.cpp HEADERS += vmainwindow.h \ @@ -64,7 +63,6 @@ HEADERS += vmainwindow.h \ vmarkdownconverter.h \ dialog/vnotebookinfodialog.h \ dialog/vdirinfodialog.h \ - vfilelistpanel.h \ dialog/vfileinfodialog.h RESOURCES += \ diff --git a/src/vfilelist.cpp b/src/vfilelist.cpp index ee0478d2..0dadb506 100644 --- a/src/vfilelist.cpp +++ b/src/vfilelist.cpp @@ -3,18 +3,52 @@ #include "vfilelist.h" #include "vconfigmanager.h" #include "dialog/vnewfiledialog.h" +#include "dialog/vfileinfodialog.h" #include "vnote.h" VFileList::VFileList(VNote *vnote, QWidget *parent) - : QListWidget(parent), vnote(vnote) + : QWidget(parent), vnote(vnote) { - setContextMenuPolicy(Qt::CustomContextMenu); + setupUI(); initActions(); +} - connect(this, &VFileList::customContextMenuRequested, +void VFileList::setupUI() +{ + newFileBtn = new QPushButton(QIcon(":/resources/icons/create_note.png"), ""); + newFileBtn->setToolTip(tr("Create a new note")); + deleteFileBtn = new QPushButton(QIcon(":/resources/icons/delete_note.png"), ""); + deleteFileBtn->setToolTip(tr("Delete current note")); + fileInfoBtn = new QPushButton(QIcon(":/resources/icons/note_info.png"), ""); + fileInfoBtn->setToolTip(tr("View and edit current note's information")); + + fileList = new QListWidget(this); + fileList->setContextMenuPolicy(Qt::CustomContextMenu); + + QHBoxLayout *topLayout = new QHBoxLayout; + topLayout->addStretch(); + topLayout->addWidget(newFileBtn); + topLayout->addWidget(deleteFileBtn); + topLayout->addWidget(fileInfoBtn); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->addLayout(topLayout); + mainLayout->addWidget(fileList); + + // Signals + connect(newFileBtn, &QPushButton::clicked, + this, &VFileList::onNewFileBtnClicked); + connect(deleteFileBtn, &QPushButton::clicked, + this, &VFileList::onDeleteFileBtnClicked); + connect(fileInfoBtn, &QPushButton::clicked, + this, &VFileList::onFileInfoBtnClicked); + + connect(fileList, &QListWidget::customContextMenuRequested, this, &VFileList::contextMenuRequested); - connect(this, &VFileList::itemClicked, + connect(fileList, &QListWidget::itemClicked, this, &VFileList::handleItemClicked); + + setLayout(mainLayout); } void VFileList::initActions() @@ -32,6 +66,7 @@ void VFileList::initActions() void VFileList::setDirectory(QJsonObject dirJson) { + fileList->clear(); if (dirJson.isEmpty()) { clearDirectoryInfo(); return; @@ -59,7 +94,6 @@ void VFileList::clearDirectoryInfo() void VFileList::updateFileList() { - clear(); QString path = QDir(rootPath).filePath(relativePath); if (!QDir(path).exists()) { @@ -91,6 +125,54 @@ void VFileList::updateFileList() } } +void VFileList::onNewFileBtnClicked() +{ + if (relativePath.isEmpty()) { + return; + } + newFile(); +} + +void VFileList::onDeleteFileBtnClicked() +{ + QListWidgetItem *curItem = fileList->currentItem(); + if (!curItem) { + return; + } + deleteFile(); +} + +void VFileList::onFileInfoBtnClicked() +{ + QListWidgetItem *curItem = fileList->currentItem(); + if (!curItem) { + return; + } + QJsonObject curItemJson = curItem->data(Qt::UserRole).toJsonObject(); + Q_ASSERT(!curItemJson.isEmpty()); + QString curItemName = curItemJson["name"].toString(); + + QString info; + QString defaultName = curItemName; + + do { + VFileInfoDialog dialog(tr("Note Information"), info, defaultName, this); + if (dialog.exec() == QDialog::Accepted) { + QString name = dialog.getNameInput(); + if (name == curItemName) { + return; + } + if (isConflictNameWithExisting(name)) { + info = "Name already exists.\nPlease choose another name:"; + defaultName = name; + continue; + } + renameFile(curItem, name); + } + break; + } while (true); +} + QListWidgetItem* VFileList::insertFileListItem(QJsonObject fileJson, bool atFront) { Q_ASSERT(!fileJson.isEmpty()); @@ -98,23 +180,23 @@ QListWidgetItem* VFileList::insertFileListItem(QJsonObject fileJson, bool atFron item->setData(Qt::UserRole, fileJson); if (atFront) { - insertItem(0, item); + fileList->insertItem(0, item); } else { - addItem(item); + fileList->addItem(item); } // Qt seems not to update the QListWidget correctly. Manually force it to repaint. - update(); + fileList->update(); qDebug() << "add new list item:" << fileJson["name"].toString(); return item; } void VFileList::removeFileListItem(QListWidgetItem *item) { - setCurrentRow(-1); - removeItemWidget(item); + fileList->setCurrentRow(-1); + fileList->removeItemWidget(item); delete item; // Qt seems not to update the QListWidget correctly. Manually force it to repaint. - update(); + fileList->update(); } void VFileList::newFile() @@ -133,9 +215,9 @@ void VFileList::newFile() } QListWidgetItem *newItem = createFileAndUpdateList(name); if (newItem) { - setCurrentItem(newItem); + fileList->setCurrentItem(newItem); // Qt seems not to update the QListWidget correctly. Manually force it to repaint. - update(); + fileList->update(); // Open this file in edit mode QJsonObject itemJson = newItem->data(Qt::UserRole).toJsonObject(); @@ -152,7 +234,7 @@ void VFileList::newFile() void VFileList::deleteFile() { - QListWidgetItem *curItem = currentItem(); + QListWidgetItem *curItem = fileList->currentItem(); Q_ASSERT(curItem); QJsonObject curItemJson = curItem->data(Qt::UserRole).toJsonObject(); QString curItemName = curItemJson["name"].toString(); @@ -175,7 +257,7 @@ void VFileList::deleteFile() void VFileList::contextMenuRequested(QPoint pos) { - QListWidgetItem *item = itemAt(pos); + QListWidgetItem *item = fileList->itemAt(pos); QMenu menu(this); if (notebook.isEmpty()) { @@ -186,14 +268,14 @@ void VFileList::contextMenuRequested(QPoint pos) menu.addAction(deleteFileAct); } - menu.exec(mapToGlobal(pos)); + menu.exec(fileList->mapToGlobal(pos)); } bool VFileList::isConflictNameWithExisting(const QString &name) { - int nrChild = this->count(); + int nrChild = fileList->count(); for (int i = 0; i < nrChild; ++i) { - QListWidgetItem *item = this->item(i); + QListWidgetItem *item = fileList->item(i); QJsonObject itemJson = item->data(Qt::UserRole).toJsonObject(); Q_ASSERT(!itemJson.isEmpty()); if (itemJson["name"].toString() == name) { @@ -288,7 +370,7 @@ void VFileList::handleItemClicked(QListWidgetItem *currentItem) return; } // Qt seems not to update the QListWidget correctly. Manually force it to repaint. - update(); + fileList->update(); QJsonObject itemJson = currentItem->data(Qt::UserRole).toJsonObject(); Q_ASSERT(!itemJson.isEmpty()); itemJson["notebook"] = notebook; @@ -365,3 +447,57 @@ void VFileList::handleDirectoryRenamed(const QString ¬ebook, relativePath = newRelativePath; } } + +void VFileList::renameFile(QListWidgetItem *item, const QString &newName) +{ + if (!item) { + return; + } + QJsonObject itemJson = item->data(Qt::UserRole).toJsonObject(); + Q_ASSERT(!itemJson.isEmpty()); + QString name = itemJson["name"].toString(); + QString path = QDir(rootPath).filePath(relativePath); + QFile file(QDir(path).filePath(name)); + QString newFilePath(QDir(path).filePath(newName)); + Q_ASSERT(file.exists()); + if (!file.rename(newFilePath)) { + qWarning() << "error: fail to rename file" << name << "under" << path; + QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), QString("Could not rename note \"%1\" under \"%2\".") + .arg(name).arg(path), QMessageBox::Ok, this); + msgBox.setInformativeText(QString("Please check if there already exists a file named \"%1\".").arg(newName)); + msgBox.exec(); + return; + } + + // Update directory's config file + QJsonObject dirJson = VConfigManager::readDirectoryConfig(path); + Q_ASSERT(!dirJson.isEmpty()); + QJsonArray fileArray = dirJson["files"].toArray(); + int index = 0; + for (index = 0; index < fileArray.size(); ++index) { + QJsonObject tmp = fileArray[index].toObject(); + if (tmp["name"].toString() == name) { + tmp["name"] = newName; + fileArray[index] = tmp; + break; + } + } + Q_ASSERT(index != fileArray.size()); + dirJson["files"] = fileArray; + if (!VConfigManager::writeDirectoryConfig(path, dirJson)) { + qWarning() << "error: fail to rename file" + << name << "to" << newName; + file.rename(name); + return; + } + + // Update item + itemJson["name"] = newName; + item->setData(Qt::UserRole, itemJson); + item->setText(newName); + + QString oldPath = QDir::cleanPath(QDir(relativePath).filePath(name)); + QString newPath = QDir::cleanPath(QDir(relativePath).filePath(newName)); + qDebug() << "file renamed" << oldPath << "to" << newPath; + emit fileRenamed(notebook, oldPath, newPath); +} diff --git a/src/vfilelist.h b/src/vfilelist.h index 790f8a25..4b4a169b 100644 --- a/src/vfilelist.h +++ b/src/vfilelist.h @@ -1,7 +1,7 @@ #ifndef VFILELIST_H #define VFILELIST_H -#include +#include #include #include #include @@ -9,8 +9,11 @@ class QAction; class VNote; +class QListWidget; +class QListWidgetItem; +class QPushButton; -class VFileList : public QListWidget +class VFileList : public QWidget { Q_OBJECT public: @@ -21,10 +24,15 @@ signals: void fileClicked(QJsonObject fileJson); void fileDeleted(QJsonObject fileJson); void fileCreated(QJsonObject fileJson); + void fileRenamed(const QString ¬ebook, const QString &oldPath, + const QString &newPath); private slots: void contextMenuRequested(QPoint pos); void handleItemClicked(QListWidgetItem *currentItem); + void onNewFileBtnClicked(); + void onDeleteFileBtnClicked(); + void onFileInfoBtnClicked(); public slots: void setDirectory(QJsonObject dirJson); @@ -36,6 +44,7 @@ public slots: void deleteFile(); private: + void setupUI(); void updateFileList(); QListWidgetItem *insertFileListItem(QJsonObject fileJson, bool atFront = false); void removeFileListItem(QListWidgetItem *item); @@ -45,6 +54,7 @@ private: void deleteFileAndUpdateList(QListWidgetItem *item); void clearDirectoryInfo(); inline QString getDirectoryName(); + void renameFile(QListWidgetItem *item, const QString &newName); VNote *vnote; QString notebook; @@ -53,6 +63,11 @@ private: // Used for cache QString rootPath; + QListWidget *fileList; + QPushButton *newFileBtn; + QPushButton *deleteFileBtn; + QPushButton *fileInfoBtn; + // Actions QAction *newFileAct; QAction *deleteFileAct; diff --git a/src/vfilelistpanel.cpp b/src/vfilelistpanel.cpp deleted file mode 100644 index 24cf99e8..00000000 --- a/src/vfilelistpanel.cpp +++ /dev/null @@ -1,232 +0,0 @@ -#include -#include "vfilelistpanel.h" -#include "vfilelist.h" -#include "dialog/vfileinfodialog.h" -#include "vnotebook.h" -#include "vnote.h" -#include "vconfigmanager.h" - -VFileListPanel::VFileListPanel(VNote *vnote, QWidget *parent) - : QWidget(parent), vnote(vnote) -{ - setupUI(); -} - -void VFileListPanel::setupUI() -{ - newFileBtn = new QPushButton(QIcon(":/resources/icons/create_note.png"), ""); - newFileBtn->setToolTip(tr("Create a new note")); - deleteFileBtn = new QPushButton(QIcon(":/resources/icons/delete_note.png"), ""); - deleteFileBtn->setToolTip(tr("Delete current note")); - fileInfoBtn = new QPushButton(QIcon(":/resources/icons/note_info.png"), ""); - fileInfoBtn->setToolTip(tr("View and edit current note's information")); - - fileList = new VFileList(vnote); - - QHBoxLayout *topLayout = new QHBoxLayout; - topLayout->addStretch(); - topLayout->addWidget(newFileBtn); - topLayout->addWidget(deleteFileBtn); - topLayout->addWidget(fileInfoBtn); - - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addLayout(topLayout); - mainLayout->addWidget(fileList); - - // Signals - connect(fileList, &VFileList::fileClicked, - this, &VFileListPanel::fileClicked); - connect(fileList, &VFileList::fileDeleted, - this, &VFileListPanel::fileDeleted); - connect(fileList, &VFileList::fileCreated, - this, &VFileListPanel::fileCreated); - - connect(newFileBtn, &QPushButton::clicked, - this, &VFileListPanel::onNewFileBtnClicked); - connect(deleteFileBtn, &QPushButton::clicked, - this, &VFileListPanel::onDeleteFileBtnClicked); - connect(fileInfoBtn, &QPushButton::clicked, - this, &VFileListPanel::onFileInfoBtnClicked); - - setLayout(mainLayout); -} - -void VFileListPanel::setDirectory(QJsonObject dirJson) -{ - if (dirJson.isEmpty()) { - clearDirectoryInfo(); - fileList->setDirectory(dirJson); - return; - } - - notebook = dirJson["notebook"].toString(); - relativePath = dirJson["relative_path"].toString(); - rootPath = ""; - const QVector ¬ebooks = vnote->getNotebooks(); - for (int i = 0; i < notebooks.size(); ++i) { - if (notebooks[i].getName() == notebook) { - rootPath = notebooks[i].getPath(); - break; - } - } - Q_ASSERT(!rootPath.isEmpty()); - - fileList->setDirectory(dirJson); -} - -void VFileListPanel::clearDirectoryInfo() -{ - notebook = relativePath = rootPath = ""; - fileList->clear(); -} - -void VFileListPanel::handleNotebookRenamed(const QVector ¬ebooks, - const QString &oldName, const QString &newName) -{ - if (oldName == notebook) { - // Update treePath (though treePath actually will not be changed) - notebook = newName; - rootPath.clear(); - const QVector ¬ebooks = vnote->getNotebooks(); - for (int i = 0; i < notebooks.size(); ++i) { - if (notebooks[i].getName() == notebook) { - rootPath = notebooks[i].getPath(); - break; - } - } - Q_ASSERT(!rootPath.isEmpty()); - } - fileList->handleNotebookRenamed(notebooks, oldName, newName); -} - -void VFileListPanel::handleDirectoryRenamed(const QString ¬ebook, - const QString &oldRelativePath, const QString &newRelativePath) -{ - if (notebook == this->notebook - && oldRelativePath == relativePath) { - relativePath = newRelativePath; - } - fileList->handleDirectoryRenamed(notebook, oldRelativePath, - newRelativePath); -} - -bool VFileListPanel::importFile(const QString &name) -{ - return fileList->importFile(name); -} - -void VFileListPanel::onNewFileBtnClicked() -{ - if (relativePath.isEmpty()) { - return; - } - fileList->newFile(); -} - -void VFileListPanel::onDeleteFileBtnClicked() -{ - QListWidgetItem *curItem = fileList->currentItem(); - if (!curItem) { - return; - } - fileList->deleteFile(); -} - -void VFileListPanel::onFileInfoBtnClicked() -{ - QListWidgetItem *curItem = fileList->currentItem(); - if (!curItem) { - return; - } - QJsonObject curItemJson = curItem->data(Qt::UserRole).toJsonObject(); - Q_ASSERT(!curItemJson.isEmpty()); - QString curItemName = curItemJson["name"].toString(); - - QString info; - QString defaultName = curItemName; - - do { - VFileInfoDialog dialog(tr("Note Information"), info, defaultName, this); - if (dialog.exec() == QDialog::Accepted) { - QString name = dialog.getNameInput(); - if (name == curItemName) { - return; - } - if (isConflictNameWithExisting(name)) { - info = "Name already exists.\nPlease choose another name:"; - defaultName = name; - continue; - } - renameFile(curItem, name); - } - break; - } while (true); -} - -bool VFileListPanel::isConflictNameWithExisting(const QString &name) -{ - int nrChild = fileList->count(); - for (int i = 0; i < nrChild; ++i) { - QListWidgetItem *item = fileList->item(i); - QJsonObject itemJson = item->data(Qt::UserRole).toJsonObject(); - Q_ASSERT(!itemJson.isEmpty()); - if (itemJson["name"].toString() == name) { - return true; - } - } - return false; -} - -void VFileListPanel::renameFile(QListWidgetItem *item, const QString &newName) -{ - if (!item) { - return; - } - QJsonObject itemJson = item->data(Qt::UserRole).toJsonObject(); - Q_ASSERT(!itemJson.isEmpty()); - QString name = itemJson["name"].toString(); - QString path = QDir(rootPath).filePath(relativePath); - QFile file(QDir(path).filePath(name)); - QString newFilePath(QDir(path).filePath(newName)); - Q_ASSERT(file.exists()); - if (!file.rename(newFilePath)) { - qWarning() << "error: fail to rename file" << name << "under" << path; - QMessageBox msgBox(QMessageBox::Warning, tr("Warning"), QString("Could not rename note \"%1\" under \"%2\".") - .arg(name).arg(path), QMessageBox::Ok, this); - msgBox.setInformativeText(QString("Please check if there already exists a file named \"%1\".").arg(newName)); - msgBox.exec(); - return; - } - - // Update directory's config file - QJsonObject dirJson = VConfigManager::readDirectoryConfig(path); - Q_ASSERT(!dirJson.isEmpty()); - QJsonArray fileArray = dirJson["files"].toArray(); - int index = 0; - for (index = 0; index < fileArray.size(); ++index) { - QJsonObject tmp = fileArray[index].toObject(); - if (tmp["name"].toString() == name) { - tmp["name"] = newName; - fileArray[index] = tmp; - break; - } - } - Q_ASSERT(index != fileArray.size()); - dirJson["files"] = fileArray; - if (!VConfigManager::writeDirectoryConfig(path, dirJson)) { - qWarning() << "error: fail to rename file" - << name << "to" << newName; - file.rename(name); - return; - } - - // Update item - itemJson["name"] = newName; - item->setData(Qt::UserRole, itemJson); - item->setText(newName); - - QString oldPath = QDir::cleanPath(QDir(relativePath).filePath(name)); - QString newPath = QDir::cleanPath(QDir(relativePath).filePath(newName)); - qDebug() << "file renamed" << oldPath << "to" << newPath; - emit fileRenamed(notebook, oldPath, newPath); -} diff --git a/src/vfilelistpanel.h b/src/vfilelistpanel.h deleted file mode 100644 index 48ad86af..00000000 --- a/src/vfilelistpanel.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef VFILELISTPANEL_H -#define VFILELISTPANEL_H - -#include -#include -#include -#include -#include -#include -#include "vnotebook.h" - -class VNote; -class VFileList; -class QPushButton; -class QListWidgetItem; - -class VFileListPanel : public QWidget -{ - Q_OBJECT -public: - VFileListPanel(VNote *vnote, QWidget *parent = 0); - bool importFile(const QString &name); - -signals: - void fileClicked(QJsonObject fileJson); - void fileDeleted(QJsonObject fileJson); - void fileCreated(QJsonObject fileJson); - void fileRenamed(const QString ¬ebook, const QString &oldPath, - const QString &newPath); - -public slots: - void setDirectory(QJsonObject dirJson); - void handleNotebookRenamed(const QVector ¬ebooks, const QString &oldName, - const QString &newName); - void handleDirectoryRenamed(const QString ¬ebook, const QString &oldRelativePath, - const QString &newRelativePath); - -private slots: - void onNewFileBtnClicked(); - void onDeleteFileBtnClicked(); - void onFileInfoBtnClicked(); - -private: - void setupUI(); - bool isConflictNameWithExisting(const QString &name); - void renameFile(QListWidgetItem *item, const QString &newName); - void clearDirectoryInfo(); - inline QString getDirectoryName(); - - VNote *vnote; - QString notebook; - // Current directory's relative path - QString relativePath; - // Used for cache - QString rootPath; - - VFileList *fileList; - QPushButton *newFileBtn; - QPushButton *deleteFileBtn; - QPushButton *fileInfoBtn; -}; - -inline QString VFileListPanel::getDirectoryName() -{ - if (relativePath.isEmpty()) { - return ""; - } - return QFileInfo(QDir::cleanPath(relativePath)).fileName(); -} -#endif // VFILELISTPANEL_H diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp index 3e6d58c7..fb512d62 100644 --- a/src/vmainwindow.cpp +++ b/src/vmainwindow.cpp @@ -2,7 +2,7 @@ #include "vmainwindow.h" #include "vdirectorytree.h" #include "vnote.h" -#include "vfilelistpanel.h" +#include "vfilelist.h" #include "vtabwidget.h" #include "vconfigmanager.h" #include "dialog/vnewnotebookdialog.h" @@ -75,8 +75,8 @@ void VMainWindow::setupUI() nbContainer->setLayout(nbLayout); nbContainer->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding); - fileListPanel = new VFileListPanel(vnote); - fileListPanel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding); + fileList = new VFileList(vnote); + fileList->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding); // Editor tab widget tabs = new VTabWidget(vnote); @@ -86,7 +86,7 @@ void VMainWindow::setupUI() // Main Splitter mainSplitter = new QSplitter(); mainSplitter->addWidget(nbContainer); - mainSplitter->addWidget(fileListPanel); + mainSplitter->addWidget(fileList); mainSplitter->addWidget(tabs); mainSplitter->setStretchFactor(0, 1); mainSplitter->setStretchFactor(1, 1); @@ -97,17 +97,17 @@ void VMainWindow::setupUI() SLOT(setCurNotebookIndex(int))); connect(vnote, &VNote::notebooksRenamed, - fileListPanel, &VFileListPanel::handleNotebookRenamed); + fileList, &VFileList::handleNotebookRenamed); connect(directoryTree, &VDirectoryTree::currentDirectoryChanged, - fileListPanel, &VFileListPanel::setDirectory); + fileList, &VFileList::setDirectory); connect(directoryTree, &VDirectoryTree::directoryRenamed, - fileListPanel, &VFileListPanel::handleDirectoryRenamed); + fileList, &VFileList::handleDirectoryRenamed); - connect(fileListPanel, &VFileListPanel::fileClicked, + connect(fileList, &VFileList::fileClicked, tabs, &VTabWidget::openFile); - connect(fileListPanel, &VFileListPanel::fileDeleted, + connect(fileList, &VFileList::fileDeleted, tabs, &VTabWidget::closeFile); - connect(fileListPanel, &VFileListPanel::fileCreated, + connect(fileList, &VFileList::fileCreated, tabs, &VTabWidget::openFile); connect(newNotebookBtn, &QPushButton::clicked, @@ -454,7 +454,7 @@ void VMainWindow::importNoteFromFile() QStringList failedFiles; for (int i = 0; i < files.size(); ++i) { - bool ret = fileListPanel->importFile(files[i]); + bool ret = fileList->importFile(files[i]); if (!ret) { failedFiles.append(files[i]); } diff --git a/src/vmainwindow.h b/src/vmainwindow.h index 2e518fec..7736d3d2 100644 --- a/src/vmainwindow.h +++ b/src/vmainwindow.h @@ -16,7 +16,7 @@ class QAction; class QPushButton; class VNotebook; class QActionGroup; -class VFileListPanel; +class VFileList; class VMainWindow : public QMainWindow { @@ -70,7 +70,7 @@ private: QPushButton *newRootDirBtn; QPushButton *deleteDirBtn; QPushButton *dirInfoBtn; - VFileListPanel *fileListPanel; + VFileList *fileList; VDirectoryTree *directoryTree; VTabWidget *tabs; QSplitter *mainSplitter;