在QT5窗口菜单中实现最近打开的文件功能

首先来看下效果:

 点击这些最近的文件能马上打开,比如点击SS.stp:

关键代码:

新建一个类,类名为RecentFiles,继承QObject,具体的.h文件(RecentFiles.h)如下,读者可以自行理解:


#ifndef RECENTFILES_H
#define RECENTFILES_H

#include <QObject>
#include <QStringList>
#include <QMainWindow>
#include <QSettings>

class QMenu;
class QAction;

#define recentFileCount "OCCADrecentFiles/numOfRecentFiles"
#define recentFileListId "OCCADrecentFiles/fileList"

/**
 * @brief The RecentFiles class manages a list of recently accessed files.
 *
 * It handles user-settable number of most recently accessed files, provides
 * a sub-menu that allows the user to select recently used files for opening.
 */
class RecentFiles : public QObject
{
    Q_OBJECT
public:
    explicit RecentFiles(QMainWindow *parent=NULL); /* Parent mainwindow, just for proper heirarchy, not actually used outside QObject constr */
    ~RecentFiles();

    /// Inserts the sub-menu into another Menu
    ///  param menu   The parent menu where the sub-menu should be inserted
    ///  param text   Text of menu item after which Recent menu is inserted
    void attachToMenuAfterItem(QMenu *menu, QString text, const char *slotName);

    QStringList getRecentFiles() const;                     ///< application calls this to get list of recent files
    void        setMostRecentFile(const QString fileName);  ///< called when each new file is opened
    QString     strippedName(const QString &fullFileName);  ///< returns filename from full path

    void        setMenuEnabled(bool tf);

    /// returns how many recent files are being remenbered.  see setNumOfRecentFiles()
    int         numberOfRecentFilesToSave();

    static const int MaxRecentFiles = 6;  ///< Max number of names we keep.

public slots:
    /// The application can set the number of recent files retained/reported here
    void setNumOfRecentFiles(int n);

signals:
    void openFile(QString fileName); ///< emitted when user selects item from "Open Recent" sub-menu
    void newMaxFilesShown(int);     ///< tells observers that the number of recent files being remembered has changed.

private slots:
    void openRecentFile(); ///< menu items signal this when user selects item from "Open Recent" sub-menu

private:
    void purgeMissingFilesFromList(QStringList &recentFileList);
    void updateRecentFiles(QSettings &settings);  ///< call this with each new filename

    QMenu *m_recentMenu;
    QAction *m_recentMenuTriggeredAction;
    QAction *m_recentFileActions[MaxRecentFiles]; ///< QActions created in file menu for storing recent files
};

#endif // RECENTFILES_H


 


对应的.cpp文件如下:


#include "RecentFiles.h"
#include <QAction>
#include <QApplication>
#include <QDir>
#include <QFileInfo>
#include <QFile>
#include <QMenu>
#include <QString>
#include <QStringList>
#include <QSettings>
#include <QRegExp>

QString sanitizedFileName(const QString &name)
{
    QString clean = name;
    return clean.replace(QRegExp("[^A-Za-z0-9]"), QString("_"));
}

RecentFiles::RecentFiles(QMainWindow *parent)
    : QObject(parent)
    , m_recentMenu(new QMenu(parent))
    , m_recentMenuTriggeredAction(NULL)

{
    // create the sub-menu
    m_recentMenu->setTitle("Open Recent...");
    m_recentMenu->setObjectName("RecentMenu");

    // create an action for all possible entries in the sub-menu
    for (int i = 0; i < MaxRecentFiles; i++) {
        m_recentFileActions[i] = new QAction(m_recentMenu);
        m_recentFileActions[i]->setText("---");
        m_recentFileActions[i]->setVisible(false);
        connect(m_recentFileActions[i], SIGNAL(triggered()),
            this, SLOT(openRecentFile()));
        m_recentMenu->addAction(m_recentFileActions[i]);
    }

    // Set some defaults
    QSettings settings;

    if (!settings.value(recentFileCount).isValid())
        settings.setValue(recentFileCount, QVariant(4));

    // If there are no recent files, initialize an empty list
    if (!settings.allKeys().contains(recentFileListId)) {
        settings.setValue(recentFileListId, QVariant(QStringList()));
    }

    updateRecentFiles(settings);
}
RecentFiles::~RecentFiles()
{
    // delete m_recentMenu; // might be bad because parent menu will delete.
    m_recentMenu = (QMenu *)NULL;
}
//在menu菜单项下插图一个text名称的菜单项,并且这个菜单关联slotname响应
void RecentFiles::attachToMenuAfterItem(QMenu *menu,         /* menu that "Recent" sub-menu should be inserted into */
    QString text,        /* Action in menu after which Recent menu should be inserted */
    const char * slotName)
{
    QList<QAction *> actionList = menu->actions();

    int indexOfItemToFollow = 0;
    for (; indexOfItemToFollow < actionList.size(); indexOfItemToFollow++) {
        QAction *act = actionList.at(indexOfItemToFollow);
        if (!act->text().compare(text)) {
            break;
        }
    }


    int indexOfItemToPreceed = indexOfItemToFollow + 1;
    if (indexOfItemToPreceed >= actionList.size()) {
        // append to end of menu
        m_recentMenuTriggeredAction = menu->addMenu(m_recentMenu);
        m_recentMenuTriggeredAction->setObjectName("recentMenuAction");
    }
    else {
        // insert into menu
        QAction *before = actionList.at(indexOfItemToPreceed);
        m_recentMenuTriggeredAction = menu->insertMenu(before, m_recentMenu);
        m_recentMenuTriggeredAction->setObjectName("recentMenuAction");
        menu->insertSeparator(before);
    }

    connect(this, SIGNAL(openFile(QString)), parent(), slotName);

}

void RecentFiles::openRecentFile()
{
    QAction *action = qobject_cast<QAction *>(sender());
    if (action)
        emit openFile(action->data().toString());
}

void RecentFiles::purgeMissingFilesFromList(QStringList &recentFileList)
{
    for (QMutableStringListIterator i(recentFileList); i.hasNext();) {
        QString fileName = i.next(); // stash filename and advance iterator
        if (!QFile::exists(fileName)) {
            i.remove(); // removes item last jumped by i.next()
        }
    }
}

QString RecentFiles::strippedName(const QString &fullFileName)
{
    return QFileInfo(fullFileName).fileName();
}

void RecentFiles::setMenuEnabled(bool tf)
{
    m_recentMenuTriggeredAction->setEnabled(tf);
}

int RecentFiles::numberOfRecentFilesToSave()
{
    QSettings settings;

    return settings.value(recentFileCount).toInt();
}

void RecentFiles::setMostRecentFile(const QString fileName)
{
    if (fileName.isEmpty())
        return;

    QSettings settings;
    QStringList recentFileList = settings.value(recentFileListId).toStringList();

    recentFileList.removeAll(fileName);
    recentFileList.prepend(fileName);
    settings.setValue(recentFileListId, QVariant(recentFileList));

    updateRecentFiles(settings);

    qApp->setProperty("currentDirectory",
        QVariant(
        QFileInfo(fileName)
        .absoluteDir()
        .absolutePath()
        ));
}

void RecentFiles::setNumOfRecentFiles(int n)
{
    QSettings settings;

    settings.setValue(recentFileCount, QVariant(n));

    updateRecentFiles(settings);

    // So a preference panel can be updated to show new value...
    emit newMaxFilesShown(n);
}


QStringList RecentFiles::getRecentFiles() const
{
    QSettings settings;

    QStringList recentFileList = settings.value(recentFileListId).toStringList();
    return recentFileList;
}

void RecentFiles::updateRecentFiles(QSettings &settings)
{
    int numOfRecentFiles = settings.value(recentFileCount, QVariant(4)).toInt();

    QStringList MyRecentFileList = settings.value(recentFileListId).toStringList();
    purgeMissingFilesFromList(MyRecentFileList);
    settings.setValue(recentFileListId, QVariant(MyRecentFileList));

    // If there are no recent files, then the menu item (that would show the list)
    // should not be visible.
    if (m_recentMenuTriggeredAction) {
        if (numOfRecentFiles == 0) {
            m_recentMenuTriggeredAction->setVisible(false);
        }
        else {
            m_recentMenuTriggeredAction->setVisible(true);
        }
    }

    for (int j = 0; j < MaxRecentFiles; ++j) {
        if (j < MyRecentFileList.count() && j < numOfRecentFiles) {
            QString text = strippedName(MyRecentFileList[j]);
            m_recentFileActions[j]->setText(text);
            m_recentFileActions[j]->setData(MyRecentFileList[j]);
            m_recentFileActions[j]->setObjectName(sanitizedFileName(text));

            m_recentFileActions[j]->setVisible(true);
        }
        else {
            m_recentFileActions[j]->setVisible(false);
        }
    }

    for (int j = numOfRecentFiles; j < MyRecentFileList.count(); j++)
        m_recentFileActions[j]->setVisible(false);

    getRecentFiles();
}


 


关于怎么使用的问题,就我的程序上来说,需要在Mainwindow上进行操作,因此我需要在Mainwindow上增加如下代码:

构造函数中:

m_recentFiles(this);

m_recentFiles.attachToMenuAfterItem(ui.menu_F, "Export...", SLOT(openFile(QString)));//在Export菜单项下插入
 m_recentFiles.setNumOfRecentFiles(8);//最多显示最近的8个文件

在打开文件函数中添加如下代码:

QSettings settings;
QFileInfo fi(filename);
 settings.setValue("currentDirectory", fi.absolutePath());
 m_recentFiles.setMostRecentFile(filename);

如果需要点击这些最近的文件后打开,需要实现openFile(QString filename)函数,这个可以根据自己的情况就行了,我的实现是:


//最近文档打开接口
void OCCAD::openFile(QString filename)
{
    QFormDoc *Temp = FindMdiChild(filename);
    //判断文件是否已经打开
    if (!Temp)
    {//文件还没打开
        QFormDoc *formDoc = FindEmptyFile();
        if (formDoc)
        {//还有空的文档,直接写入空文档
            setActiveSubWindow(formDoc);
            formDoc->loadFromFile(filename);
            formDoc->setcurrFileName(filename);
            formDoc->showMaximized(); //默认全屏显示
            formDoc->Fill_View_style();
            formDoc->show();
            //
            CurrOperation = "OPEN";
            CreateModelNode();
            CreateNodeWithModelType(filename, formDoc);
            //
            QSettings settings;
            QFileInfo fi(filename);
            settings.setValue("currentDirectory", fi.absolutePath());
            m_recentFiles.setMostRecentFile(filename);
        }
        else
        {
            //没有空窗口,新建一个并显示到这个新窗口中
            formDoc = new QFormDoc(this);
            ui.mdiArea->addSubWindow(formDoc);
            setActiveSubWindow(formDoc);
            formDoc->loadFromFile(filename);
            formDoc->showMaximized(); //默认全屏显示
            formDoc->Fill_View_style();
            formDoc->show();
            //
            CurrOperation = "OPEN";
            CreateModelNode();
            CreateNodeWithModelType(filename, formDoc);
            //
            QSettings settings;
            QFileInfo fi(filename);
            settings.setValue("currentDirectory", fi.absolutePath());
            m_recentFiles.setMostRecentFile(filename);
        }
    }
    else
    {//文件已经打开,置顶这个窗口
        Temp->activateWindow();
        Temp->showMaximized(); //默认全屏显示
    }

}


QT4下我测试的时候好像没问题,但是在QT5下工作不正常,后面看了下官网的资料:

因此,我在主函数中加入了这三句代码,之后能工作正常:

QCoreApplication::setOrganizationName("OCSOFT");
QCoreApplication::setOrganizationDomain("OCSOFT.COM");
QCoreApplication::setApplicationName("OCCAD V1.0");

 

后记: 到此,在QT窗口菜单中实现最近打开的文件功能已经完成。如果有什么写错的地方,请联系我修改 QQ:1623451686。

 

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值