QMainWindow相关的函数。同时,需要在多个插件之间共享历史记录。可以将History类改为一个全局单例,并使用信号槽机制来实现界面跳转。
新的History类代码如下:
class History : public QObject {
Q_OBJECT
public:
static History& instance() {
static History history;
return history;
}
void push(QWidget* widget, const QString& pluginName) {
// 存储界面和对应的QTreeView的选中状态
m_selections[pluginName][widget] = findTreeViewSelection(widget);
QList<QWidget*>& list = m_history[pluginName];
if (list.size() > 0 && list.last() == widget) {
return; // 如果当前界面就是最后一个,则不需要再次添加
}
while (list.size() >= MAX_HISTORY_SIZE) {
QWidget* front = list.first();
list.pop_front();
m_selections[pluginName].remove(front);
}
list.append(widget);
// 发送信号通知其他插件更新历史记录
emit historyChanged(pluginName);
}
QWidget* current(const QString& pluginName) const {
QList<QWidget*> list = m_history.value(pluginName);
if (list.isEmpty()) {
return nullptr;
}
return list.last();
}
bool canGoBack(const QString& pluginName) const {
QList<QWidget*> list = m_history.value(pluginName);
return list.size() > 1;
}
bool canGoForward(const QString& pluginName) const {
QList<QWidget*> list = m_history.value(pluginName);
int currentIndex = list.indexOf(current(pluginName));
return currentIndex >= 0 && currentIndex < list.size() - 1;
}
void goBack(const QString& pluginName) {
if (canGoBack(pluginName)) {
QList<QWidget*>& list = m_history[pluginName];
QWidget* currentWidget = list.takeLast();
m_selections[pluginName][currentWidget] = findTreeViewSelection(currentWidget);
QWidget* prevWidget = list.last();
QTreeView* treeView = findTreeView(prevWidget);
if (treeView && m_selections[pluginName].contains(prevWidget)) {
treeView->selectionModel()->select(m_selections[pluginName][prevWidget], QItemSelectionModel::Select);
}
// 发送信号通知其他插件更新历史记录
emit historyChanged(pluginName);
emit widgetChanged(prevWidget);
}
}
void goForward(const QString& pluginName) {
if (canGoForward(pluginName)) {
QList<QWidget*>& list = m_history[pluginName];
QWidget* currentWidget = list.takeLast();
m_selections[pluginName][currentWidget] = findTreeViewSelection(currentWidget);
QWidget* nextWidget = list.last();
QTreeView* treeView = findTreeView(nextWidget);
if (treeView && m_selections[pluginName].contains(nextWidget)) {
treeView->selectionModel()->select(m_selections[pluginName][nextWidget], QItemSelectionModel::Select);
}
// 发送信号通知其他插件更新历史记录
emit historyChanged(pluginName);
emit widgetChanged(nextWidget);
}
}
void clear(const QString& pluginName) {
QList<QWidget*>& list = m_history[pluginName];
for (QWidget* widget : list) {
m_selections[pluginName].remove(widget);
}
list.clear();
emit historyChanged(pluginName);
}
signals:
void historyChanged(const QString& pluginName); // 历史记录发生变化
void widgetChanged(QWidget* widget); // 界面发生变化
private:
QMap<QString, QList<QWidget*>> m_history;
QMap<QString, QMap<QWidget*, QItemSelection>> m_selections;
static const int MAX_HISTORY_SIZE = 20;
// 查找界面中的QTreeView
QTreeView* findTreeView(QWidget* widget) {
return widget->findChild<QTreeView*>();
}
// 获取QTreeView的选中状态
QItemSelection findTreeViewSelection(QWidget* widget) {
QTreeView* treeView = findTreeView(widget);
if (treeView) {
return treeView->selectionModel()->selection();
}
return QItemSelection();
}
History() {}
History(const History&) = delete;
History& operator=(const History&) = delete;
};
在每个插件的构造函数中,需要将自身加入历史记录,并连接历史记录的信号槽:
class MyPlugin : public QObject {
Q_OBJECT
public:
explicit MyPlugin(QObject* parent = nullptr)
: QObject(parent), m_widget(new QWidget())
{
connect(&History::instance(), &History::widgetChanged, this, &MyPlugin::onWidgetChanged);
// 将当前界面加入历史记录
History::instance().push(m_widget, "MyPlugin");
}
private slots:
void onWidgetChanged(QWidget* widget) {
if (widget == m_widget) {
// 如果当前界面发生变化,则更新对应的界面显示
m_stackedWidget->setCurrentWidget(m_widget);
}
}
private:
QWidget* m_widget;
QStackedWidget* m_stackedWidget;
};
在主窗口中,需要连接历史记录的信号槽,并在回退和前进按钮的槽函数中调用History类对应的函数:
class MainWindow : public QMainWindow {
public:
MainWindow(QWidget* parent = nullptr) : QMainWindow(parent) {
// ...
connect(&History::instance(), &History::historyChanged, this, &MainWindow::onHistoryChanged);
onHistoryChanged("MyPlugin"); // 手动触发第一个插件的历史记录变化信号
// ...
}
private slots:
void goBack() {
History::instance().goBack(m_currentPlugin);
}
void goForward() {
History::instance().goForward(m_currentPlugin);
}
void onHistoryChanged(const QString& pluginName) {
m_currentPlugin = pluginName;
m_backButton->setEnabled(History::instance().canGoBack(pluginName));
m_forwardButton->setEnabled(History::instance().canGoForward(pluginName));
QWidget* currentWidget = History::instance().current(pluginName);
if (currentWidget) {
m_stackedWidget->setCurrentWidget(currentWidget);
}
}
private:
QString m_currentPlugin;
QStackedWidget* m_stackedWidget;
QPushButton* m_backButton;
QPushButton* m_forwardButton;
};