基于Qt/C++的ProjectExplorer实现


我在写MarkdownOne的时候, 需要有一个类似各大IDE都有的ProjectExplorer这样的东西. 我需要的功能比较简单, 就是显示外加一些简单操作而已. 因为自己平日里爱极了QtCreator这个IDE, 它的ProjectExplorer是相当赞的. 于是一开始我就想反正QtCreator是插件机制的各个模块之间应该耦合度比较低, 直接看它的源码下一些功夫应该可以把这部分给抠出来. 但是打开QtCreator1.0的源码看的时候, 发现比我预想的要复杂, 并不是一时半会儿就能搞定的. 还是自己写吧, 反正要的功能也不多, 自己实现也还算简单, 无非数据, 显示, 操作, 这三样还有个专业术语MVC.实现效果如下(红色区域部分):


 

因为目录结构其实是一个树形结构, 那么在显示方面, 当属TreeView了. 而Model呢, 自己递归遍历目录生成对应的数据, 也简单, 但除了自己实现之外还有更简洁的东西, Qt为我们提供了QFileSystemModel. 而在Qt里面没有Control的概念而是用Delegate来代替, 反正也差不多. 在这里ProjectExplorerView, ProjectExplorerModel, ProjectExplorerItemDelegate 分别继承于QTreeView,QFileSystemModel和QStyledItemDelegate.

在这其中, 其实ProjectExplorerView不是必须的, 因为QTreeView已经可以满足我们的需求, 这样做把一些内部实现放到了派生类中, 用户不必关心这些细节, 以方便以后再其他地方重复利用, 代码比较简单, 不废话了上代码:

//ProjectExplorerView.h


#ifndef PROJECTEXPLORERVIEW_H
#define PROJECTEXPLORERVIEW_H

#include <QTreeView>

class ProjectExplorerModel;
class ProjectExplorerItemMenu;
class ProjectExplorerMenu;

class ProjectExplorerView : public QTreeView
{
 Q_OBJECT
public:
 explicit ProjectExplorerView(QWidget *parent = 0);

 /**
  * @brief setRootPath Sets the directory that is being watched by the model to newPath
  * @param path
  */
 void setRootPath(const QString &path);

signals:
 void signalDoubleClickedFile(const QString &filePath);
 void signalDoubleClickedDir(const QString &dirPath);

public slots:

protected:
 void mousePressEvent(QMouseEvent *event);

private:
 void initSetting();
 void initData();
 void initGui();

private:
 ProjectExplorerModel *pModel_;
 ProjectExplorerItemMenu *pItemMenu_;
 ProjectExplorerMenu *pMenu_;
};

#endif // PROJECTEXPLORERVIEW_H

//ProjectExplorerView.cpp

#include "ProjectExplorerView.h"

#include <QDebug>
#include <QFileInfo>
#include <QModelIndex>
#include <QMouseEvent>

#include "ProjectExplorerItemDelegate.h"
#include "ProjectExplorerModel.h"

#include "ProjectExplorerItemMenu.h"
#include "ProjectExplorerMenu.h"

ProjectExplorerView::ProjectExplorerView(QWidget *parent)
 : QTreeView(parent)
 , pModel_(NULL)
 , pItemMenu_(NULL)
 , pMenu_(NULL)
{
 initSetting();
 initData();
 initGui();
}

void ProjectExplorerView::setRootPath(const QString &path)
{
 pModel_->setRootPath(path);
 this->setRootIndex(pModel_->index(path));
}

void ProjectExplorerView::mousePressEvent(QMouseEvent *event)
{
 if(event->buttons() == Qt::RightButton)
 {
  QModelIndex index = indexAt(event->pos());
  if(!index.isValid())
  {
  qDebug() << "点了空白处";
  pMenu_->move(event->globalPos());
  pMenu_->show();
  }
  else
  {
  pItemMenu_->move(event->globalPos());
  qDebug() << pModel_->fileName(index);
  pItemMenu_->show();
  }

  event->accept();
  return;
 }

 event->ignore();
 return QTreeView::mousePressEvent(event);
}

void ProjectExplorerView::initSetting()
{
 //this->setAccessibleName("Name");
 //按键响应编辑
 this->setEditTriggers(QAbstractItemView::EditKeyPressed);//只响应键盘的编辑事件
 //this->setContextMenuPolicy(Qt::CustomContextMenu);
}

void ProjectExplorerView::initData()
{
 pModel_ = new ProjectExplorerModel(this);
 this->setModel(pModel_);
 connect(this, &ProjectExplorerView::doubleClicked, [=](const QModelIndex &index){
  QString path = pModel_->filePath(index);
  QFileInfo info(path);
  if(info.isDir())
  {
  Q_EMIT signalDoubleClickedDir(path);
  }
  else if(info.isFile())
  {
  Q_EMIT signalDoubleClickedFile(path);
  }
  else if(info.isSymLink())
  {
  QString source = info.symLinkTarget();
  qDebug() << "这个快捷方式是? " << source;

  }
  else
  {
  qDebug() << "这是毛? " << info.path();
  }
 });

 pMenu_ = new ProjectExplorerMenu(this);
 pItemMenu_ = new ProjectExplorerItemMenu(this);

 this->setItemDelegate(new ProjectExplorerItemDelegate());
}

void ProjectExplorerView::initGui()
{

}

或许一些也学Qt的小伙伴看到这一串代码中connect那一部分有点懵

connect(this, &ProjectExplorerView::doubleClicked, [=](const QModelIndex &index){
  QString path = pModel_->filePath(index);
  QFileInfo info(path);
  if(info.isDir())
  {
  Q_EMIT signalDoubleClickedDir(path);
  }
  else if(info.isFile())
  {
  Q_EMIT signalDoubleClickedFile(path);
  }
  else if(info.isSymLink())
  {
  QString source = info.symLinkTarget();
  qDebug() << "这个快捷方式是? " << source;

  }
  else
  {
  qDebug() << "这是毛? " << info.path();
  }
 });

更多详情见请继续阅读下一页的精彩内容:

Qt 的详细介绍:请点这里
Qt 的下载地址:请点这里

推荐阅读:

Ubuntu 环境下Gtk与QT编译环境安装与配置

Linux系统下QT环境搭建

Ubuntu下QT控制台程序无法运行的解决方案以及XTerm的配置方法

Ubuntu 10.04下QT4.7.4移植详解

  • 1
  • 2
  • 3
  • 下一页

相关内容