diff --git a/src/common/util/eventdefinitions.h b/src/common/util/eventdefinitions.h index 285e45ca9..0ddbef114 100644 --- a/src/common/util/eventdefinitions.h +++ b/src/common/util/eventdefinitions.h @@ -127,6 +127,7 @@ OPI_OBJECT(workspace, ) OPI_OBJECT(session, OPI_INTERFACE(readyToSaveSession) + OPI_INTERFACE(sessionStatusChanged) OPI_INTERFACE(sessionLoaded, "session") OPI_INTERFACE(sessionCreated, "session") OPI_INTERFACE(sessionRenamed, "oldName", "newName") diff --git a/src/plugins/core/modules/sessionmanagermodule.cpp b/src/plugins/core/modules/sessionmanagermodule.cpp index d517efd41..50cd5ca9c 100644 --- a/src/plugins/core/modules/sessionmanagermodule.cpp +++ b/src/plugins/core/modules/sessionmanagermodule.cpp @@ -48,6 +48,7 @@ void SessionManagerModule::initInterfaces() sessionSrv->isDefaultSession = std::bind(&SessionManager::isDefaultSession, ins, _1); sessionSrv->isSessionLoading = std::bind(&SessionManager::isSessionLoading, ins); sessionSrv->isDefaultVirgin = std::bind(&SessionManager::isDefaultVirgin, ins); + sessionSrv->markSessionFileDirty = std::bind(&SessionManager::markSessionFileDirty, ins); sessionSrv->sessionFile = std::bind(&SessionManager::sessionFile, ins, _1); } @@ -74,4 +75,8 @@ void SessionManagerModule::initOutputEvents() [](const QString &name) { session.sessionRemoved(name); }); + connect(ins, &SessionManager::sessionStatusChanged, this, + [] { + session.sessionStatusChanged(); + }); } diff --git a/src/plugins/core/session/sessionmanager.cpp b/src/plugins/core/session/sessionmanager.cpp index 5926ece27..c60678ff5 100644 --- a/src/plugins/core/session/sessionmanager.cpp +++ b/src/plugins/core/session/sessionmanager.cpp @@ -105,8 +105,9 @@ SessionManager::SessionManager(QObject *parent) { d->readSettings(); connect(qApp, &QApplication::aboutToQuit, this, [this] { + if (!isSessionLoading() && !isDefaultVirgin()) + saveSession(); d->saveSettings(); - saveSession(); }); } @@ -279,7 +280,7 @@ bool SessionManager::loadSession(const QString &session) return true; } -bool SessionManager::saveSession() +void SessionManager::saveSession() { Q_EMIT readyToSaveSession(); @@ -290,7 +291,7 @@ bool SessionManager::saveSession() settings.setValue(kSessionGroup, iter.key(), iter.value()); } - return true; + d->sessionDateTimes.insert(d->currentSession, QDateTime::currentDateTime()); } bool SessionManager::isDefaultSession(const QString &session) @@ -313,6 +314,15 @@ bool SessionManager::isAutoLoadLastSession() return d->isAutoLoad; } +void SessionManager::markSessionFileDirty() +{ + if (!d->virginSession) + return; + + d->virginSession = false; + Q_EMIT sessionStatusChanged(); +} + QString SessionManager::sessionFile(const QString &session) { QString format = "%1/%2.session"; diff --git a/src/plugins/core/session/sessionmanager.h b/src/plugins/core/session/sessionmanager.h index b0656fdf0..92e663766 100644 --- a/src/plugins/core/session/sessionmanager.h +++ b/src/plugins/core/session/sessionmanager.h @@ -31,17 +31,19 @@ class SessionManager : public QObject QVariant value(const QString &key); bool loadSession(const QString &session); - bool saveSession(); + void saveSession(); bool isDefaultSession(const QString &session); bool isSessionLoading(); bool isDefaultVirgin(); bool isAutoLoadLastSession(); + void markSessionFileDirty(); QString sessionFile(const QString &session); Q_SIGNALS: void readyToSaveSession(); void sessionLoaded(const QString &session); + void sessionStatusChanged(); void sessionCreated(const QString &session); void sessionRenamed(const QString &oldName, const QString &newName); diff --git a/src/plugins/project/transceiver/projectcorereceiver.cpp b/src/plugins/project/transceiver/projectcorereceiver.cpp index 5695dffa9..d59e86740 100644 --- a/src/plugins/project/transceiver/projectcorereceiver.cpp +++ b/src/plugins/project/transceiver/projectcorereceiver.cpp @@ -55,6 +55,8 @@ void ProjectCoreReceiver::processActiveProjectEvent(const dpf::Event &event) void ProjectCoreReceiver::processOpenProjectEvent(const dpf::Event &event) { + auto sessionSrv = dpfGetService(SessionService); + sessionSrv->markSessionFileDirty(); uiController.doSwitch(dpfservice::MWNA_EDIT); auto &ctx = dpfInstance.serviceContext(); ProjectService *projectService = ctx.service(ProjectService::name()); diff --git a/src/plugins/recent/mainframe/itemdelegate.cpp b/src/plugins/recent/mainframe/itemdelegate.cpp index 142cc3e76..3d9d8b11a 100644 --- a/src/plugins/recent/mainframe/itemdelegate.cpp +++ b/src/plugins/recent/mainframe/itemdelegate.cpp @@ -3,7 +3,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "itemdelegate.h" -#include "itemlistview.h" #include #include diff --git a/src/plugins/recent/mainframe/itemlistview.cpp b/src/plugins/recent/mainframe/itemlistview.cpp deleted file mode 100644 index 5eb21fce1..000000000 --- a/src/plugins/recent/mainframe/itemlistview.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "itemlistview.h" -#include "common/common.h" -#include "itemdelegate.h" - -#include -#include - -#include - -#include -#include -#include -#include -#include - -#define INIT_DATA "{\n \"Projects\":[],\n \"Documents\":[]\n}\n" - -ItemListView::ItemListView(QWidget *parent) - : DListView(parent), model(new QStandardItemModel(this)) -{ - setDragDropMode(QAbstractItemView::NoDragDrop); - setSelectionMode(QAbstractItemView::SingleSelection); - setSelectionBehavior(QAbstractItemView::SelectRows); - setEditTriggers(QListView::NoEditTriggers); - setTextElideMode(Qt::ElideMiddle); - setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setAlternatingRowColors(false); - setSelectionRectVisible(true); - setMouseTracking(true); - - setUniformItemSizes(true); - setResizeMode(Fixed); - setOrientation(QListView::TopToBottom, false); - setFrameStyle(QFrame::NoFrame); - setSpacing(0); - setContentsMargins(0, 0, 0, 0); - - setModel(model); - setItemDelegate(new ItemDelegate(this)); -} - -ItemListView::~ItemListView() -{ -} - -void ItemListView::clear() -{ - model->clear(); -} - -void ItemListView::focusOutEvent(QFocusEvent *e) -{ - DListView::clearSelection(); - DListView::focusOutEvent(e); -} - -void ItemListView::mousePressEvent(QMouseEvent *e) -{ - if (e->button() != Qt::LeftButton) - return; - return DListView::mousePressEvent(e); -} diff --git a/src/plugins/recent/mainframe/itemlistview.h b/src/plugins/recent/mainframe/itemlistview.h deleted file mode 100644 index 8caa08398..000000000 --- a/src/plugins/recent/mainframe/itemlistview.h +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef ITEMLISTVIEW_H -#define ITEMLISTVIEW_H - -#include -#include - -DWIDGET_USE_NAMESPACE - -class QStandardItemModel; -class QStandardItem; -class ItemListView : public DListView -{ - Q_OBJECT -public: - explicit ItemListView(QWidget *parent = nullptr); - ~ItemListView() override; - - virtual QString title() = 0; - virtual QString configKey() = 0; - virtual void setItemList(const QVariantList &items) = 0; - virtual QVariantList itemList() const = 0; - virtual void appendItem(const QVariant &item) = 0; - virtual void prependItem(const QVariant &item) = 0; - virtual void clear(); - - void focusOutEvent(QFocusEvent *e) override; - void mousePressEvent(QMouseEvent *e) override; - -protected: - QStandardItemModel *model { nullptr }; -}; - -#endif // ITEMLISTVIEW_H diff --git a/src/plugins/recent/mainframe/recentdisplaywidget.cpp b/src/plugins/recent/mainframe/recentdisplaywidget.cpp index d181521f6..e734fa872 100644 --- a/src/plugins/recent/mainframe/recentdisplaywidget.cpp +++ b/src/plugins/recent/mainframe/recentdisplaywidget.cpp @@ -33,6 +33,8 @@ DWIDGET_USE_NAMESPACE using namespace dpfservice; constexpr char kRecentGroup[] { "Recent" }; +constexpr char kProjects[] { "Projects" }; +constexpr char kDocuments[] { "Documents" }; static RecentDisplayWidget *ins { nullptr }; @@ -41,8 +43,7 @@ class RecentDisplayWidgetPrivate public: explicit RecentDisplayWidgetPrivate(RecentDisplayWidget *qq); - void createProjectWidget(); - void createDocumentWidget(); + void createRecentWidget(); void createSessionWidget(); public: @@ -52,20 +53,12 @@ class RecentDisplayWidgetPrivate QVBoxLayout *vLayoutDoc { nullptr }; QVBoxLayout *vLayoutPro { nullptr }; DWidget *recentOpen { nullptr }; - RecentProjectView *proView { nullptr }; - RecentDocemntView *docView { nullptr }; + RecentListView *recentListView { nullptr }; SessionItemListWidget *sessionListWidget { nullptr }; - QList viewList; DLabel *proLabel { nullptr }; DToolButton *proClear { nullptr }; DDialog *clearProConfirm { nullptr }; - - DLabel *docLabel { nullptr }; - DToolButton *docClear { nullptr }; - DDialog *clearDocConfirm { nullptr }; - DToolButton *sessionSetBtn { nullptr }; - DFrame *navFrame { nullptr }; DFrame *docFrame { nullptr }; DFrame *proFrame { nullptr }; @@ -85,25 +78,25 @@ RecentDisplayWidgetPrivate::RecentDisplayWidgetPrivate(RecentDisplayWidget *qq) sessionSrv = dpfGetService(SessionService); } -void RecentDisplayWidgetPrivate::createProjectWidget() +void RecentDisplayWidgetPrivate::createRecentWidget() { proFrame = new DFrame(q); proFrame->setLineWidth(0); DStyle::setFrameRadius(proFrame, 0); - proView = new RecentProjectView(q); + recentListView = new RecentListView(q); - proLabel = new DLabel(RecentDisplayWidget::tr("Projects"), q); + proLabel = new DLabel(RecentDisplayWidget::tr("Projects And Documents"), q); proLabel->setForegroundRole(QPalette::BrightText); proLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); proLabel->setContentsMargins(10, 5, 0, 10); proClear = new DToolButton(q); proClear->setIcon(QIcon::fromTheme("ide_recent_delete")); - proClear->setToolTip(RecentDisplayWidget::tr("clear all")); + proClear->setToolTip(RecentDisplayWidget::tr("Clear All")); clearProConfirm = new DDialog(q); clearProConfirm->setIcon(QIcon::fromTheme("dialog-warning")); - clearProConfirm->setMessage(RecentDisplayWidget::tr("Confirm to clear the record of the opened project?")); + clearProConfirm->setMessage(RecentDisplayWidget::tr("Confirm to clear the record of the opened projects and documents?")); clearProConfirm->insertButton(0, RecentDisplayWidget::tr("Cancel", "button")); clearProConfirm->insertButton(1, RecentDisplayWidget::tr("Delete", "button"), true, DDialog::ButtonWarning); @@ -116,50 +109,14 @@ void RecentDisplayWidgetPrivate::createProjectWidget() vLayoutPro->setContentsMargins(10, 10, 10, 10); vLayoutPro->addLayout(proHlayout); vLayoutPro->setSpacing(0); - vLayoutPro->addWidget(proView); + vLayoutPro->addWidget(recentListView); proFrame->setLayout(vLayoutPro); } -void RecentDisplayWidgetPrivate::createDocumentWidget() -{ - docFrame = new DFrame(); - docFrame->setLineWidth(0); - DStyle::setFrameRadius(docFrame, 0); - docView = new RecentDocemntView(q); - - docLabel = new DLabel(RecentDisplayWidget::tr("Documents")); - docLabel->setForegroundRole(QPalette::BrightText); - docLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - docLabel->setContentsMargins(10, 5, 0, 10); - - docClear = new DToolButton(q); - docClear->setIcon(QIcon::fromTheme("ide_recent_delete")); - docClear->setToolTip(RecentDisplayWidget::tr("clear all")); - - clearDocConfirm = new DDialog(q); - clearDocConfirm->setIcon(QIcon::fromTheme("dialog-warning")); - clearDocConfirm->setMessage(RecentDisplayWidget::tr("Confirm to clear the record of the opened file?")); - clearDocConfirm->insertButton(0, RecentDisplayWidget::tr("Cancel", "button")); - clearDocConfirm->insertButton(1, RecentDisplayWidget::tr("Delete", "button"), true, DDialog::ButtonWarning); - - QHBoxLayout *docHlayout = new QHBoxLayout; - docHlayout->addWidget(docLabel); - docHlayout->addWidget(docClear); - - DFontSizeManager::instance()->bind(docLabel, DFontSizeManager::T4, QFont::Medium); - vLayoutDoc = new QVBoxLayout(); - vLayoutDoc->setContentsMargins(10, 10, 10, 10); - vLayoutDoc->addLayout(docHlayout); - vLayoutDoc->setSpacing(0); - vLayoutDoc->addWidget(docView); - docFrame->setLayout(vLayoutDoc); -} - void RecentDisplayWidgetPrivate::createSessionWidget() { sessionFrame = new DFrame(q); sessionFrame->setLineWidth(0); - sessionFrame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding); DStyle::setFrameRadius(sessionFrame, 0); sessionListWidget = new SessionItemListWidget(q); @@ -195,9 +152,6 @@ RecentDisplayWidget::RecentDisplayWidget(DWidget *parent) RecentDisplayWidget::~RecentDisplayWidget() { - d->recentSettings.setValue(kRecentGroup, d->proView->configKey(), d->proView->itemList()); - d->recentSettings.setValue(kRecentGroup, d->docView->configKey(), d->docView->itemList()); - delete d; } @@ -210,13 +164,15 @@ RecentDisplayWidget *RecentDisplayWidget::instance() void RecentDisplayWidget::addDocument(const QString &filePath) { - auto itemList = d->docView->itemList(); - if (itemList.contains(filePath)) + if (d->recentListView->contains(filePath)) { + auto itemList = d->recentListView->documentList(); itemList.removeOne(filePath); - itemList.prepend(filePath); - - d->docView->clear(); - d->docView->setItemList(itemList); + itemList.prepend(filePath); + d->recentListView->clearDocuments(); + d->recentListView->setItemList(itemList); + } else { + d->recentListView->prependItem(filePath); + } } void RecentDisplayWidget::addProject(const QString &kitName, @@ -228,13 +184,15 @@ void RecentDisplayWidget::addProject(const QString &kitName, item.insert(kLanguage, language); item.insert(kWorkspace, workspace); - auto itemList = d->proView->itemList(); - if (itemList.contains(item)) + if (d->recentListView->contains(workspace)) { + auto itemList = d->recentListView->projectList(); itemList.removeOne(item); - itemList.prepend(item); - - d->proView->clear(); - d->proView->setItemList(itemList); + itemList.prepend(item); + d->recentListView->clearProjects(); + d->recentListView->setItemList(itemList); + } else { + d->recentListView->prependItem(item); + } } void RecentDisplayWidget::addSession(const QString &session) @@ -252,21 +210,20 @@ void RecentDisplayWidget::updateSessions() d->sessionListWidget->updateSessions(); } -void RecentDisplayWidget::doDoubleClickedProject(const QModelIndex &index) +void RecentDisplayWidget::doDoubleClicked(const QModelIndex &index) { - QString kitName = index.data(RecentProjectView::KitNameRole).toString(); - QString language = index.data(RecentProjectView::LanguageRole).toString(); - QString workspace = index.data(RecentProjectView::WorkspaceRole).toString(); - // "kitName", "language", "workspace" - project.openProject(kitName, language, workspace); - RecentDisplayWidget::addProject(kitName, language, workspace); -} - -void RecentDisplayWidget::doDoubleCliekedDocument(const QModelIndex &index) -{ - QString filePath = index.data(Qt::DisplayRole).toString(); - RecentDisplayWidget::addDocument(filePath); - editor.openFile(QString(), filePath); + if (index.data(RecentListView::IsProject).toBool()) { + QString kitName = index.data(RecentListView::KitNameRole).toString(); + QString language = index.data(RecentListView::LanguageRole).toString(); + QString workspace = index.data(RecentListView::WorkspaceRole).toString(); + // "kitName", "language", "workspace" + project.openProject(kitName, language, workspace); + RecentDisplayWidget::addProject(kitName, language, workspace); + } else { + QString filePath = index.data(Qt::DisplayRole).toString(); + RecentDisplayWidget::addDocument(filePath); + editor.openFile(QString(), filePath); + } } void RecentDisplayWidget::btnOpenFileClicked() @@ -292,7 +249,7 @@ void RecentDisplayWidget::btnNewFileOrProClicked() bool RecentDisplayWidget::isProAndDocNull() { - return d->proView->itemList().isEmpty() && d->docView->itemList().isEmpty(); + return d->recentListView->isEmpty(); } QVariantMap RecentDisplayWidget::parseProjectInfo(const QJsonObject &obj) @@ -313,21 +270,9 @@ QVariantMap RecentDisplayWidget::parseProjectInfo(const QJsonObject &obj) return map; } -void RecentDisplayWidget::clearProList() +void RecentDisplayWidget::clearRecent() { - d->proView->clear(); - d->recentSettings.removeGroup(d->proView->configKey()); - - if (isProAndDocNull()) { - d->nullRecentText->setVisible(true); - d->recentOpen->setVisible(false); - } -} - -void RecentDisplayWidget::clearDocList() -{ - d->docView->clear(); - d->recentSettings.removeGroup(d->docView->configKey()); + d->recentListView->clearAll(); if (isProAndDocNull()) { d->nullRecentText->setVisible(true); @@ -368,19 +313,13 @@ void RecentDisplayWidget::initializeUi() recentTitle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); DFontSizeManager::instance()->bind(recentTitle, DFontSizeManager::T4, QFont::Medium); - d->createDocumentWidget(); - d->createProjectWidget(); + d->createRecentWidget(); d->createSessionWidget(); - QVBoxLayout *sessionDocLayout = new QVBoxLayout; - sessionDocLayout->setSpacing(2); - sessionDocLayout->addWidget(d->docFrame); - sessionDocLayout->addWidget(d->sessionFrame); - QHBoxLayout *proAndDocLayout = new QHBoxLayout(); proAndDocLayout->addWidget(d->proFrame); proAndDocLayout->setSpacing(2); - proAndDocLayout->addLayout(sessionDocLayout); + proAndDocLayout->addWidget(d->sessionFrame); d->recentOpen = new DWidget(this); QVBoxLayout *recentNavLayout = new QVBoxLayout(d->recentOpen); @@ -405,12 +344,8 @@ void RecentDisplayWidget::initializeUi() void RecentDisplayWidget::initConnect() { - QObject::connect(d->proView, &QListView::doubleClicked, - this, &RecentDisplayWidget::doDoubleClickedProject, - Qt::UniqueConnection); - - QObject::connect(d->docView, &QListView::doubleClicked, - this, &RecentDisplayWidget::doDoubleCliekedDocument, + QObject::connect(d->recentListView, &QListView::doubleClicked, + this, &RecentDisplayWidget::doDoubleClicked, Qt::UniqueConnection); QObject::connect(d->btnOpenFile, &DPushButton::clicked, @@ -425,30 +360,24 @@ void RecentDisplayWidget::initConnect() this, &RecentDisplayWidget::btnNewFileOrProClicked, Qt::UniqueConnection); - QObject::connect(d->docClear, &DPushButton::clicked, - d->clearDocConfirm, &DDialog::exec, - Qt::UniqueConnection); - QObject::connect(d->proClear, &DPushButton::clicked, d->clearProConfirm, &DDialog::exec, Qt::UniqueConnection); - QObject::connect(d->clearDocConfirm, &DDialog::buttonClicked, this, [=](int index) { - if (index == 0) - d->clearDocConfirm->reject(); - else if (index == 1) - clearDocList(); - }); - QObject::connect(d->clearProConfirm, &DDialog::buttonClicked, this, [=](int index) { if (index == 0) d->clearProConfirm->reject(); else if (index == 1) - clearProList(); + clearRecent(); }); QObject::connect(d->sessionSetBtn, &DToolButton::clicked, this, [this] { d->sessionSrv->showSessionManager(); }); + QObject::connect(qApp, &QApplication::aboutToQuit, this, [this] { + d->recentSettings.setValue(kRecentGroup, kProjects, d->recentListView->projectList()); + d->recentSettings.setValue(kRecentGroup, kDocuments, d->recentListView->documentList()); + d->recentSettings.sync(); + }); } [[deprecated("-------------存在兼容代码需要删除")]] void RecentDisplayWidget::initData() @@ -464,27 +393,27 @@ void RecentDisplayWidget::initConnect() file.remove(); QVariantList prjList; - QJsonArray prjArray = doc.object().value(d->proView->configKey()).toArray(); + QJsonArray prjArray = doc.object().value(kProjects).toArray(); for (const auto &prj : prjArray) { auto prjObj = prj.toObject(); const auto &info = parseProjectInfo(prjObj); if (!info.isEmpty()) prjList << info; } - d->recentSettings.setValue(kRecentGroup, d->proView->configKey(), prjList); + d->recentSettings.setValue(kRecentGroup, kProjects, prjList); QVariantList docList; - QJsonArray docArray = doc.object().value(d->docView->configKey()).toArray(); + QJsonArray docArray = doc.object().value(kDocuments).toArray(); for (const auto &doc : docArray) { auto filePath = doc.toString(); if (!filePath.isEmpty()) docList << filePath; } - d->recentSettings.setValue(kRecentGroup, d->docView->configKey(), docList); + d->recentSettings.setValue(kRecentGroup, kDocuments, docList); } - d->proView->setItemList(d->recentSettings.value(kRecentGroup, d->proView->configKey()).toList()); - d->docView->setItemList(d->recentSettings.value(kRecentGroup, d->docView->configKey()).toList()); + d->recentListView->setItemList(d->recentSettings.value(kRecentGroup, kProjects).toList()); + d->recentListView->setItemList(d->recentSettings.value(kRecentGroup, kDocuments).toList()); d->sessionListWidget->addSessionList(d->sessionSrv->sessionList()); } diff --git a/src/plugins/recent/mainframe/recentdisplaywidget.h b/src/plugins/recent/mainframe/recentdisplaywidget.h index a18b0cac6..8d64a07d3 100644 --- a/src/plugins/recent/mainframe/recentdisplaywidget.h +++ b/src/plugins/recent/mainframe/recentdisplaywidget.h @@ -29,15 +29,11 @@ public slots: void updateSessions(); private slots: - void doDoubleClickedProject(const QModelIndex &index); - void doDoubleCliekedDocument(const QModelIndex &index); - + void doDoubleClicked(const QModelIndex &index); void btnOpenFileClicked(); void btnOpenProjectClicked(); void btnNewFileOrProClicked(); - - void clearDocList(); - void clearProList(); + void clearRecent(); private: void initializeUi(); diff --git a/src/plugins/recent/mainframe/recentlistview.cpp b/src/plugins/recent/mainframe/recentlistview.cpp index 4d8b4ef4e..cf555a346 100644 --- a/src/plugins/recent/mainframe/recentlistview.cpp +++ b/src/plugins/recent/mainframe/recentlistview.cpp @@ -3,44 +3,94 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "recentlistview.h" +#include "itemdelegate.h" #include +#include + +DWIDGET_USE_NAMESPACE + static QIcon icon(const QString &file) { static DFileIconProvider provider; return provider.icon(QFileInfo(file)); } -RecentProjectView::RecentProjectView(QWidget *parent) - : ItemListView(parent) +RecentListView::RecentListView(QWidget *parent) + : DListView(parent) { + setDragDropMode(QAbstractItemView::NoDragDrop); + setSelectionMode(QAbstractItemView::SingleSelection); + setSelectionBehavior(QAbstractItemView::SelectRows); + setEditTriggers(QListView::NoEditTriggers); + setTextElideMode(Qt::ElideMiddle); + setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setAlternatingRowColors(false); + setSelectionRectVisible(true); + setMouseTracking(true); + + setUniformItemSizes(true); + setResizeMode(Fixed); + setOrientation(QListView::TopToBottom, false); + setFrameStyle(QFrame::NoFrame); + setSpacing(0); + setContentsMargins(0, 0, 0, 0); + + setModel(&model); + setItemDelegate(new ItemDelegate(this)); } -QString RecentProjectView::title() +void RecentListView::setItemList(const QVariantList &items) { - return tr("Projects"); + for (const auto &item : items) + appendItem(item); } -QString RecentProjectView::configKey() +bool RecentListView::contains(const QString &name) const { - return "Projects"; + auto list = model.findItems(name); + return !list.isEmpty(); } -void RecentProjectView::setItemList(const QVariantList &items) +bool RecentListView::isEmpty() const { - clear(); - for (const auto &item : items) { - appendItem(item); + return model.rowCount() == 0; +} + +void RecentListView::clearAll() +{ + model.clear(); +} + +void RecentListView::clearProjects() +{ + for (int i = model.rowCount() - 1; i >= 0; --i) { + const auto &item = model.item(i); + if (item->data(IsProject).toBool()) + model.removeRow(i); } } -QVariantList RecentProjectView::itemList() const +void RecentListView::clearDocuments() +{ + for (int i = model.rowCount() - 1; i >= 0; --i) { + const auto &item = model.item(i); + if (!item->data(IsProject).toBool()) + model.removeRow(i); + } +} + +QVariantList RecentListView::projectList() const { QVariantList itemList; - for (int i = 0; i < model->rowCount(); ++i) { + for (int i = 0; i < model.rowCount(); ++i) { + const auto &item = model.item(i); + if (!item->data(IsProject).toBool()) + continue; + QVariantMap map; - const auto &item = model->item(i); map.insert(kKitName, item->data(KitNameRole)); map.insert(kLanguage, item->data(LanguageRole)); map.insert(kWorkspace, item->data(WorkspaceRole)); @@ -51,23 +101,67 @@ QVariantList RecentProjectView::itemList() const return itemList; } -void RecentProjectView::appendItem(const QVariant &item) +QVariantList RecentListView::documentList() const { - if (!item.canConvert(QMetaType::QVariantMap)) - return; + QVariantList itemList; + for (int i = 0; i < model.rowCount(); ++i) { + const auto &item = model.item(i); + if (item->data(IsProject).toBool()) + continue; + + itemList << item->data(Qt::DisplayRole); + } + + return itemList; +} - model->appendRow(createItem(item)); +void RecentListView::appendItem(const QVariant &item) +{ + if (auto aitem = createItem(item)) { + if (aitem->data(IsProject).toBool()) { + int lastProjectRow = -1; + for (int i = 0; i < model.rowCount(); ++i) { + if (model.item(i)->data(IsProject).toBool()) { + lastProjectRow = i; + break; + } + } + model.insertRow(lastProjectRow + 1, aitem); + } else { + model.appendRow(aitem); + } + } } -void RecentProjectView::prependItem(const QVariant &item) +void RecentListView::prependItem(const QVariant &item) +{ + if (auto aitem = createItem(item)) { + if (aitem->data(IsProject).toBool()) { + model.insertRow(0, aitem); + } else { + int firstDocRow = model.rowCount(); + for (int i = 0; i < model.rowCount(); ++i) { + if (!model.item(i)->data(IsProject).toBool()) { + firstDocRow = i; + break; + } + } + model.insertRow(firstDocRow, aitem); + } + } +} + +DStandardItem *RecentListView::createItem(const QVariant &item) { - if (!item.canConvert(QMetaType::QVariantMap)) - return; + if (item.canConvert(QMetaType::QVariantMap)) + return createProjectItem(item); + else if (item.canConvert(QMetaType::QString)) + return createDocumentItem(item); - model->insertRow(0, createItem(item)); + return nullptr; } -DStandardItem *RecentProjectView::createItem(const QVariant &item) +DStandardItem *RecentListView::createProjectItem(const QVariant &item) { const auto &infoMap = item.toMap(); const auto kitName = infoMap.value(kKitName).toString(); @@ -78,63 +172,30 @@ DStandardItem *RecentProjectView::createItem(const QVariant &item) rowItem->setData(kitName, KitNameRole); rowItem->setData(language, LanguageRole); rowItem->setData(workspace, WorkspaceRole); + rowItem->setData(true, IsProject); QString tipFormat("KitName: %1\nLanguage: %2\nWorkspace: %3"); rowItem->setToolTip(tipFormat.arg(kitName, language, workspace)); return rowItem; } -RecentDocemntView::RecentDocemntView(QWidget *parent) - : ItemListView(parent) +DStandardItem *RecentListView::createDocumentItem(const QVariant &item) { + QString filePath = item.toString(); + auto rowItem = new DStandardItem(icon(filePath), filePath); + rowItem->setData(false, IsProject); + return rowItem; } -QString RecentDocemntView::title() -{ - return tr("Documents"); -} - -QString RecentDocemntView::configKey() -{ - return "Documents"; -} - -void RecentDocemntView::setItemList(const QVariantList &items) -{ - clear(); - for (const auto &item : items) { - appendItem(item); - } -} - -QVariantList RecentDocemntView::itemList() const -{ - QVariantList itemList; - for (int i = 0; i < model->rowCount(); ++i) { - const auto &item = model->item(i); - const auto filePath = item->data(Qt::DisplayRole); - itemList << filePath; - } - - return itemList; -} - -void RecentDocemntView::appendItem(const QVariant &item) +void RecentListView::focusOutEvent(QFocusEvent *e) { - if (!item.canConvert(QMetaType::QString)) - return; - - QString filePath = item.toString(); - auto rowItem = new DStandardItem(icon(filePath), filePath); - model->appendRow(rowItem); + clearSelection(); + DListView::focusOutEvent(e); } -void RecentDocemntView::prependItem(const QVariant &item) +void RecentListView::mousePressEvent(QMouseEvent *e) { - if (!item.canConvert(QMetaType::QString)) + if (e->button() != Qt::LeftButton) return; - - QString filePath = item.toString(); - auto rowItem = new DStandardItem(icon(filePath), filePath); - model->insertRow(0, rowItem); + return DListView::mousePressEvent(e); } diff --git a/src/plugins/recent/mainframe/recentlistview.h b/src/plugins/recent/mainframe/recentlistview.h index 1d6948193..bc480f61e 100644 --- a/src/plugins/recent/mainframe/recentlistview.h +++ b/src/plugins/recent/mainframe/recentlistview.h @@ -5,47 +5,47 @@ #ifndef RECENTLISTVIEW_H #define RECENTLISTVIEW_H -#include "itemlistview.h" +#include +#include + +#include constexpr char kKitName[] { "KitName" }; constexpr char kLanguage[] { "Language" }; constexpr char kWorkspace[] { "Workspace" }; -class RecentProjectView : public ItemListView +class RecentListView : public DTK_WIDGET_NAMESPACE::DListView { Q_OBJECT public: enum ItemRole { KitNameRole = Qt::ItemDataRole::UserRole, LanguageRole, - WorkspaceRole + WorkspaceRole, + IsProject }; - RecentProjectView(QWidget *parent = nullptr); + RecentListView(QWidget *parent = nullptr); - QString title() override; - QString configKey() override; - void setItemList(const QVariantList &items) override; - QVariantList itemList() const override; - void appendItem(const QVariant &item) override; - void prependItem(const QVariant &item) override; + void setItemList(const QVariantList &items); + QVariantList projectList() const; + QVariantList documentList() const; + bool contains(const QString &name) const; + bool isEmpty() const; + void clearAll(); + void clearProjects(); + void clearDocuments(); + void appendItem(const QVariant &item); + void prependItem(const QVariant &item); private: - DStandardItem *createItem(const QVariant &item); -}; + DTK_WIDGET_NAMESPACE::DStandardItem *createItem(const QVariant &item); + DTK_WIDGET_NAMESPACE::DStandardItem *createProjectItem(const QVariant &item); + DTK_WIDGET_NAMESPACE::DStandardItem *createDocumentItem(const QVariant &item); + void focusOutEvent(QFocusEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; -class RecentDocemntView : public ItemListView -{ - Q_OBJECT -public: - RecentDocemntView(QWidget *parent = nullptr); - - QString title() override; - QString configKey() override; - void setItemList(const QVariantList &items) override; - QVariantList itemList() const override; - void appendItem(const QVariant &item) override; - void prependItem(const QVariant &item) override; + QStandardItemModel model; }; #endif // RECENTLISTVIEW_H diff --git a/src/plugins/recent/mainframe/sessionitemwidget.cpp b/src/plugins/recent/mainframe/sessionitemwidget.cpp index 550a470a0..4a05c195e 100644 --- a/src/plugins/recent/mainframe/sessionitemwidget.cpp +++ b/src/plugins/recent/mainframe/sessionitemwidget.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -136,6 +137,11 @@ class SessionItemWidgetPrivate : public QObject DIconButton *renameBtn { nullptr }; DIconButton *removeBtn { nullptr }; DLabel *prjInfoLabel { nullptr }; + + QPropertyAnimation *animation { nullptr }; + ContentBox *contentLoader { nullptr }; + DVBoxWidget *boxWidget { nullptr }; + bool expand { false }; }; SessionItemWidgetPrivate::SessionItemWidgetPrivate(SessionItemWidget *qq) @@ -146,19 +152,52 @@ SessionItemWidgetPrivate::SessionItemWidgetPrivate(SessionItemWidget *qq) void SessionItemWidgetPrivate::initUI() { + q->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); + QVBoxLayout *mainLayout = new QVBoxLayout(q); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->setSpacing(0); + headerLine = new ArrowHeaderLine(q); - headerLine->setExpand(q->expand()); - q->setHeader(headerLine); - q->setContent(createContent()); - q->setSeparatorVisible(false); - q->setExpandedSeparatorVisible(false); + contentLoader = new ContentBox(q); + contentLoader->setFixedHeight(0); + + boxWidget = new DVBoxWidget(q); + auto contentLayout = boxWidget->layout(); + contentLayout->addWidget(createContent()); + + QVBoxLayout *loaderLayout = new QVBoxLayout(contentLoader); + loaderLayout->setMargin(0); + loaderLayout->setSpacing(0); + loaderLayout->addWidget(boxWidget); + loaderLayout->addStretch(); + + animation = new QPropertyAnimation(contentLoader, "height", q); + animation->setDuration(200); + animation->setEasingCurve(QEasingCurve::InSine); + + mainLayout->addWidget(headerLine); + mainLayout->addWidget(contentLoader); } void SessionItemWidgetPrivate::initConnection() { - connect(headerLine, &ArrowHeaderLine::expandChanged, q, [=] { + connect(headerLine, &ArrowHeaderLine::expandChanged, this, [this] { q->setExpand(!q->expand()); }); + connect(boxWidget, &DVBoxWidget::sizeChanged, this, [this] { + if (expand) { + int endHeight = 0; + endHeight = boxWidget->height(); + + animation->setStartValue(contentLoader->height()); + animation->setEndValue(endHeight); + animation->stop(); + animation->start(); + } + }); + connect(animation, &QPropertyAnimation::valueChanged, this, [this] { + q->setFixedHeight(q->sizeHint().height()); + }); connect(headerLine, &ArrowHeaderLine::itemClicked, this, &SessionItemWidgetPrivate::openSession); connect(cloneBtn, &DIconButton::clicked, this, &SessionItemWidgetPrivate::cloneSession); connect(renameBtn, &DIconButton::clicked, this, &SessionItemWidgetPrivate::renameSession); @@ -290,7 +329,7 @@ void SessionItemWidgetPrivate::runInputDialog(const QString &title, const QStrin } SessionItemWidget::SessionItemWidget(QWidget *parent) - : DDrawer(parent), + : DFrame(parent), d(new SessionItemWidgetPrivate(this)) { d->initUI(); @@ -314,8 +353,26 @@ QString SessionItemWidget::sessionName() const void SessionItemWidget::setExpand(bool value) { + if (d->expand == value) + return; + d->headerLine->setExpand(value); - DDrawer::setExpand(value); + d->expand = value; + if (value) { + d->animation->setStartValue(0); + d->animation->setEndValue(d->boxWidget->height()); + } else { + d->animation->setStartValue(d->boxWidget->height()); + d->animation->setEndValue(0); + } + + d->animation->stop(); + d->animation->start(); +} + +bool SessionItemWidget::expand() const +{ + return d->expand; } void SessionItemWidget::updateSession() @@ -348,8 +405,17 @@ void SessionItemWidget::updateSession() void SessionItemWidget::resizeEvent(QResizeEvent *e) { - d->headerLine->setFixedWidth(e->size().width()); - DDrawer::resizeEvent(e); + if (d->contentLoader) + d->contentLoader->setFixedWidth(e->size().width()); + + if (d->headerLine) + d->headerLine->setFixedWidth(e->size().width()); + DFrame::resizeEvent(e); +} + +bool SessionItemWidget::eventFilter(QObject *obj, QEvent *e) +{ + return DFrame::eventFilter(obj, e); } SessionItemListWidget::SessionItemListWidget(QWidget *parent) diff --git a/src/plugins/recent/mainframe/sessionitemwidget.h b/src/plugins/recent/mainframe/sessionitemwidget.h index 96863745c..81abe8705 100644 --- a/src/plugins/recent/mainframe/sessionitemwidget.h +++ b/src/plugins/recent/mainframe/sessionitemwidget.h @@ -12,6 +12,17 @@ #include +class ContentBox : public QWidget +{ + Q_OBJECT + Q_PROPERTY(int height READ height WRITE setFixedHeight) +public: + explicit ContentBox(QWidget *parent = nullptr) + : QWidget(parent) + { + } +}; + class ArrowHeaderLine : public QWidget { Q_OBJECT @@ -37,7 +48,7 @@ class ArrowHeaderLine : public QWidget }; class SessionItemWidgetPrivate; -class SessionItemWidget : public DTK_WIDGET_NAMESPACE::DDrawer +class SessionItemWidget : public DTK_WIDGET_NAMESPACE::DFrame { Q_OBJECT public: @@ -46,11 +57,13 @@ class SessionItemWidget : public DTK_WIDGET_NAMESPACE::DDrawer void setSessionName(const QString &session); QString sessionName() const; - void setExpand(bool value) override; + void setExpand(bool value); + bool expand() const; void updateSession(); private: void resizeEvent(QResizeEvent *e) override; + bool eventFilter(QObject *obj, QEvent *e) override; SessionItemWidgetPrivate *const d; }; diff --git a/src/plugins/recent/transceiver/recentreceiver.cpp b/src/plugins/recent/transceiver/recentreceiver.cpp index 1c2556c41..add23986e 100644 --- a/src/plugins/recent/transceiver/recentreceiver.cpp +++ b/src/plugins/recent/transceiver/recentreceiver.cpp @@ -15,6 +15,7 @@ RecentReceiver::RecentReceiver(QObject *parent) eventHandleMap.insert(session.sessionCreated.name, std::bind(&RecentReceiver::processSessionCreatedEvent, this, _1)); eventHandleMap.insert(session.sessionRemoved.name, std::bind(&RecentReceiver::processSessionRemovedEvent, this, _1)); eventHandleMap.insert(session.sessionLoaded.name, std::bind(&RecentReceiver::processSessionLoadedEvent, this, _1)); + eventHandleMap.insert(session.sessionStatusChanged.name, std::bind(&RecentReceiver::processSessionLoadedEvent, this, _1)); } dpf::EventHandler::Type RecentReceiver::type() diff --git a/src/services/session/sessionservice.cpp b/src/services/session/sessionservice.cpp deleted file mode 100644 index 07d54d158..000000000 --- a/src/services/session/sessionservice.cpp +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. -// -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "sessionservice.h" - -SessionService::SessionService() {} diff --git a/src/services/session/sessionservice.h b/src/services/session/sessionservice.h index 161d24a3c..da718f408 100644 --- a/src/services/session/sessionservice.h +++ b/src/services/session/sessionservice.h @@ -41,11 +41,12 @@ class SERVICE_EXPORT SessionService final : public dpf::PluginService, dpf::Auto DPF_INTERFACE(QVariant, value, const QString &key); DPF_INTERFACE(bool, loadSession, const QString &session); - DPF_INTERFACE(bool, saveSession); + DPF_INTERFACE(void, saveSession); DPF_INTERFACE(bool, isDefaultSession, const QString &session); DPF_INTERFACE(bool, isSessionLoading); DPF_INTERFACE(bool, isDefaultVirgin); + DPF_INTERFACE(void, markSessionFileDirty); DPF_INTERFACE(QString, sessionFile, const QString &session); }; }