当前位置: 首页 > news >正文

Qt 收藏夹书签管理

Qt 收藏夹书签管理,对浏览器导出的标准书签html文件进行正则解析数据提取,对书签时间戳进行易读的格式转换,收藏夹层级树形显示,表格显示书签层级、名称、链接、日期的详细数据,右键菜单提供复制链接和浏览器打开的功能,支持按名称、链接、日期范围进行筛选,支持两个层级解析,层级内目录名不能重名。

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QDir>
#include <QFileInfo>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QTreeWidgetItem>
#include <QTableWidget>
#include <QMenu>
#include <QClipboard>
#include <QDesktopServices>
#include <QTimer>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);QFont font;font.setPixelSize(16);setFont(font);setWindowTitle(QStringLiteral("收藏夹管理"));ui->treeWidget->setHeaderHidden(true);ui->treeWidget->setFixedWidth(200);connect(ui->treeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(showData(QTreeWidgetItem*,int)));QStringList headers;headers << QStringLiteral("层级") << QStringLiteral("名称") << QStringLiteral("链接") << QStringLiteral("日期");initTableWidget(ui->tableWidget, headers);ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);connect(ui->tableWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(menuDisplayed(QPoint)));ui->dateEdit_start->setCalendarPopup(true);ui->dateEdit_end->setCalendarPopup(true);ui->dateEdit_start->setDate(QDate::currentDate().addDays(-7));ui->dateEdit_end->setDate(QDate::currentDate());ui->dateEdit_start->setMinimumDate(QDate(2000, 1, 1));ui->dateEdit_end->setMinimumDate(QDate(2000, 1, 1));ui->dateEdit_start->setMaximumDate(QDate::currentDate());ui->dateEdit_end->setMaximumDate(QDate::currentDate());ui->lineEdit_keyword->setFixedWidth(200);connect(ui->lineEdit_keyword, SIGNAL(returnPressed()), this, SLOT(on_pushButton_keyword_clicked()));
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::initTableWidget(QTableWidget *tableWidget, QStringList headers)
{tableWidget->setColumnCount(headers.size());tableWidget->setHorizontalHeaderLabels(headers);tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);tableWidget->verticalHeader()->setVisible(false);tableWidget->horizontalHeader()->setHighlightSections(false);tableWidget->setFrameShape(QFrame::NoFrame);tableWidget->setShowGrid(true);tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);tableWidget->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeToContents);for (int i = 0; i < headers.size(); ++i){tableWidget->horizontalHeaderItem(i)->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);}tableWidget->setItemDelegate(new NoFocusDelegate());
}void MainWindow::dataTableWidget(QTableWidget *tableWidget, QList<HREFData> dataLst)
{if (dataLst.isEmpty()){return;}int rowCount = tableWidget->rowCount();int newCount = dataLst.size();if (newCount > rowCount){for (int row = rowCount; row < newCount; ++row){tableWidget->insertRow(row);for (int i = 0; i < 4; ++i){QTableWidgetItem *item = new QTableWidgetItem();tableWidget->setItem(row, i, item);}}}else if (newCount < rowCount){for (int row = rowCount; row > newCount; --row){tableWidget->removeRow(row - 1);}}for (int i = 0; i < newCount; ++i){HREFData data = dataLst.at(i);tableWidget->item(i, 0)->setText(data.Tag);tableWidget->item(i, 1)->setText(data.Name);tableWidget->item(i, 2)->setText(data.Href);tableWidget->item(i, 3)->setText(data.Date);tableWidget->item(i, 1)->setToolTip(data.Name);tableWidget->item(i, 2)->setToolTip(data.Href);}
}void MainWindow::menuDisplayed(const QPoint &pos)
{QTableWidgetItem *item = ui->tableWidget->itemAt(pos);if (item != nullptr){QMenu *menu = new QMenu(ui->tableWidget);QAction *copyHref = new QAction(QStringLiteral("复制链接"), ui->tableWidget);connect(copyHref, SIGNAL(triggered(bool)), this, SLOT(copyHref()));QAction *openHref = new QAction(QStringLiteral("浏览器打开"), ui->tableWidget);connect(openHref, SIGNAL(triggered(bool)), this, SLOT(openHref()));menu->addAction(copyHref);menu->addAction(openHref);menu->exec(QCursor::pos());delete copyHref;delete openHref;delete menu;}
}void MainWindow::copyHref()
{QApplication::clipboard()->setText(ui->tableWidget->item(ui->tableWidget->currentRow(), 2)->text());
}void MainWindow::openHref()
{QDesktopServices::openUrl(QUrl(ui->tableWidget->item(ui->tableWidget->currentRow(), 2)->text()));
}void MainWindow::on_pushButton_clicked()
{QString filestr = QFileDialog::getOpenFileName(this, QStringLiteral("打开收藏夹文件"), ".", "*.html");if (!filestr.isEmpty()){QFile file(filestr);file.open(QIODevice::ReadOnly);QString tt = file.readAll();file.close();QStringList lst = tt.split("\r\n");static QRegularExpression reTag("\">(.+)</H3>");static QRegularExpression reTagModified("LAST_MODIFIED=\"(.+)\"");QString tagName;QString tagModified;QString level_1 = "    <";QString level_2 = "        <";mTagLst.clear();foreach (QString str, lst){if (str.contains("<H3")){if (str.startsWith(level_1)){tagName = reTag.match(str).captured(1);tagModified = QDateTime::fromTime_t(reTagModified.match(str).captured(1).toInt()).toString("yyyy-MM-dd hh:mm:ss");mTagLst.append(QStringLiteral("%1/%2").arg(tagName).arg(tagModified));}else if (str.startsWith(level_2)){QString tmp = tagName;mTagLst.append(QStringLiteral("%1/%2").arg(tmp + "/" + reTag.match(str).captured(1)).arg(QDateTime::fromTime_t(reTagModified.match(str).captured(1).toInt()).toString("yyyy-MM-dd hh:mm:ss")));}}}static QRegularExpression re(" ICON=\"(.+)\"");static QRegularExpression reBookName("\">(.+)</A>");static QRegularExpression reBookHref("HREF=\"(.+?)\"");static QRegularExpression reBookDate("ADD_DATE=\"(.+?)\"");QRegularExpressionMatch rematch;mTagHrefMap.clear();QString curTag;int curLevel = 0;QString level_0_href = "    <";QString level_1_href = "        <";QString level_2_href = "            <";foreach (QString tag, mTagLst){QList<HREFData> tmp;mTagHrefMap.insert(tag, tmp);}foreach (QString str, lst){if (str.contains("HREF")){rematch = re.match(str);QString line = str;if (rematch.hasMatch()){line = str.replace(rematch.captured(0), "");}HREFData data;data.Name = reBookName.match(line).captured(1);data.Href = reBookHref.match(line).captured(1);data.Date = QDateTime::fromTime_t(reBookDate.match(line).captured(1).toInt()).toString("yyyy-MM-dd hh:mm:ss");QString week;switch (QDate::fromString(data.Date.split(" ")[0], "yyyy-MM-dd").dayOfWeek()){case Qt::Monday:week = QStringLiteral("一");break;case Qt::Tuesday:week = QStringLiteral("二");break;case Qt::Wednesday:week = QStringLiteral("三");break;case Qt::Thursday:week = QStringLiteral("四");break;case Qt::Friday:week = QStringLiteral("五");break;case Qt::Saturday:week = QStringLiteral("六");break;case Qt::Sunday:week = QStringLiteral("日");break;}data.Date = data.Date + "/" + week;QString tag;if (curLevel == 1){if (str.startsWith(level_1_href)){tag = curTag;}}else if (curLevel == 2){if (str.startsWith(level_2_href)){tag = curTag;}else if (str.startsWith(level_1_href)){QString key = curTag.split("/")[0];foreach (QString tmp, mTagLst){lst = tmp.split("/");if ((lst.size() == 2) && (lst[0] == key)){curTag = tmp;curLevel = 1;tag = curTag;break;}}}}if (str.startsWith(level_0_href)){tag = mTagLst[0];}QStringList lst = tag.split("/");QString level;if (lst.size() == 2){level = lst[0].replace("&amp;", "&");}else if (lst.size() == 3){level = lst[0].replace("&amp;", "&") + "/" + lst[1].replace("&amp;", "&");}data.Tag = level;QList<HREFData> hrefLst = mTagHrefMap.value(tag);hrefLst.append(data);mTagHrefMap.insert(tag, hrefLst);}else if (str.contains("<H3")){tagName = reTag.match(str).captured(1);foreach (QString tag, mTagLst){QStringList lst = tag.split("/");if (lst.size() == 2){if (lst[0] == tagName){curTag = tag;curLevel = 1;break;}}else if (lst.size() == 3){if (lst[1] == tagName){curTag = tag;curLevel = 2;break;}}}}}for (int i = ui->treeWidget->topLevelItemCount() - 1; i >= 0; --i){delete ui->treeWidget->takeTopLevelItem(i);}QList<QTreeWidgetItem *> topLst;foreach (QString tag, mTagLst){QStringList lst = tag.split("/");if (lst.size() == 2){QTreeWidgetItem *item = new QTreeWidgetItem;item->setText(0, lst[0].replace("&amp;", "&"));item->setData(0, Qt::UserRole, tag);item->setToolTip(0, lst[1]);ui->treeWidget->insertTopLevelItem(ui->treeWidget->topLevelItemCount(), item);topLst.append(item);}else if (lst.size() == 3){foreach (QTreeWidgetItem *top, topLst){if (top->text(0) == lst[0].replace("&amp;", "&")){QTreeWidgetItem *item = new QTreeWidgetItem(top);item->setText(0, lst[1].replace("&amp;", "&"));item->setData(0, Qt::UserRole, tag);item->setToolTip(0, lst[2]);break;}}}}ui->treeWidget->expandAll();}
}void MainWindow::showData(QTreeWidgetItem *item, int column)
{Q_UNUSED(column);QString tmp = item->data(0, Qt::UserRole).toString();if (tmp != mCurTagData){mCurTagData = tmp;dataTableWidget(ui->tableWidget, mTagHrefMap.value(mCurTagData));}
}void MainWindow::on_pushButton_date_clicked()
{if (ui->dateEdit_start->date() > ui->dateEdit_end->date() || mTagLst.isEmpty()){return;}QDate startDate = ui->dateEdit_start->date();QDate endDate = ui->dateEdit_end->date();QString tmp = QStringLiteral("%1;%2").arg(startDate.toString("yyyy-MM-dd")).arg(endDate.toString("yyyy-MM-dd"));if (mCurTagData == tmp){return;}QList<HREFData> retLst;foreach (QString tag, mTagLst){QList<HREFData> dataLst = mTagHrefMap.value(tag);foreach (HREFData data, dataLst){QDate date = QDate::fromString(data.Date.split(" ")[0], "yyyy-MM-dd");if ((date >= startDate) && (date <= endDate)){retLst.append(data);}}}if (!retLst.isEmpty()){mCurTagData = tmp;dataTableWidget(ui->tableWidget, retLst);}
}void MainWindow::on_pushButton_keyword_clicked()
{if (ui->lineEdit_keyword->text().isEmpty() || mTagLst.isEmpty()){return;}QString keyword = ui->lineEdit_keyword->text();if (mCurTagData == keyword){return;}QList<HREFData> retLst;foreach (QString tag, mTagLst){QList<HREFData> dataLst = mTagHrefMap.value(tag);foreach (HREFData data, dataLst){if (data.Name.contains(keyword) || data.Href.contains(keyword)){retLst.append(data);}}}if (!retLst.isEmpty()){mCurTagData = keyword;dataTableWidget(ui->tableWidget, retLst);}
}

http://www.xdnf.cn/news/1072225.html

相关文章:

  • cocos creator 3.8 - 精品源码 - 挪车超人(挪车消消乐)
  • ADVANCED INTELLIGENT SYSTEMS 东京大学仿生人类手指机器人,实现“皮肤”补水!
  • 【AI智能体】Dify 核心组件从使用到实战操作详解
  • web网页开发,在线%健身俱乐部管理%系统demo,基于vs2022,vscode,html,css,vue,c#,net,aspnet,api,mysql
  • 【面板数据】省级电商指数与地级市电子商务交易额数据集(1990-2022年)
  • 车载诊断架构 --- 非易失性存储器(NVM)相关设置项
  • 学习使用dotnet-dump工具分析.net内存转储文件(1)
  • 提示词工程(Prompt Engineering)
  • 校验和(checksum)不匹配
  • SRS WebRTC 入门
  • 基于LQR控制器的六自由度四旋翼无人机模型simulink建模与仿真
  • java nio 所有影响 plc 的方法一览表
  • 如何让ChatGPT模仿人类写作,降低AIGC率?
  • 我的世界模组开发进阶教程——机械动力的数据生成(2)
  • 动态规划---子序列专题
  • 【驱动设计的硬件基础】CPLD和FPGA
  • 华为云Flexus+DeepSeek征文|基于Dify构建AI资讯语音播报工作流
  • Java 大视界 -- Java 大数据机器学习模型在金融市场高频交易策略优化与风险控制中的应用(327)
  • zookeeper Curator(1):认识zookeeper和操作命令
  • 信号处理学习——文献精读与code复现之TFN——嵌入时频变换的可解释神经网络(上)
  • 设计模式之抽象工厂模式
  • ​​Git提交代码Commit消息企业级规范
  • mongodb生产备份工具PBM
  • 学习设计模式《十五》——模板方法模式
  • SpringBoot 防刷 重复提交问题 重复点击问题 注解 RequestParam RequestBody
  • clion与keil分别配置项目宏定义
  • Python打卡:Day39
  • MySQL 连接指定端口后,为什么实际仍是 3306?
  • 什么是故障注入测试
  • 智能助手(利用GPT搭建智能系统)