Qtで開いたファイルパスを履歴保存して、メニューに表示・ファイルを開く
今回は前回作成した
をベースに、開いたファイルの履歴保存とメニューに『最近開いたファイル』として一覧表示の機能を追加します。
ファイルの履歴機能は、多くのアプリが実装していますが、メニュー処理にちょっとしたコツがあります。
履歴は最大20ファイルで。開いたファイルが履歴に存在していたら、古い方を削除します。
また、表示しているファイルパスは省略していない手抜きです(^^ゞ
記事後半でソース・リソース等一式のZIPファイルがダウンロードできます。
また、Ubuntu 18.04 LTS で作成しています。
今回は mainwindow.cpp と mainwindow.h のみ張り付けます。
履歴保存・取得は、appinitdata.cpp で行っていますが、あえて掲載するほどでもないので、ZIPファイルをダウンロードして確認してください。
mainwindow.h
#ifndef APPINITDATA_H #define APPINITDATA_H #include <QMainWindow> #include <QApplication> #include <QFileInfo> #include <QSettings> class appInitData { public: appInitData(); void set_appInitDatas(QWidget *p_win, QString m_sid); void get_appInitDatas(QWidget *p_win, QString m_sid); bool m_bbyteArray; QString m_byteArray_name; QByteArray m_byteArray; QString m_sLastopenPath; // history QStringList m_listOpenedHistory; void set_OpenedHistory(QString strFilepath); void get_OpenedHistory(); private: QString m_SettingsFile; QString m_OrganizationName; }; #endif // APPINITDATA_H
mainwindow.cpp
<feff>#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // get init appInit.m_byteArray_name = "treeWidget_playlist"; appInit.get_appInitDatas(this->window(), "MAIN"); appInit.get_OpenedHistory(); setMenu_Recently_files(); // setting status bar ui->statusBar->addWidget(label_MessageBar_normal); label_MessageBar_normal->setText(tr("File not selected")); // setting treeWidget_playlist QStringList list_label; list_label << tr("tag") << tr("value"); ui->treeWidget_playlist->header()->setSectionResizeMode(QHeaderView::Interactive); ui->treeWidget_playlist->setHeaderLabels(list_label); if (appInit.m_bbyteArray) ui->treeWidget_playlist->header()->restoreState(appInit.m_byteArray); // etc init editing_Filepath = appInit.m_sLastopenPath; setAcceptDrops(true); } MainWindow::~MainWindow() { // set init appInit.m_byteArray_name = "treeWidget_playlist"; appInit.m_byteArray = ui->treeWidget_playlist->header()->saveState(); appInit.m_bbyteArray = true; if (editing_Filepath.length() == 0) appInit.m_sLastopenPath = ""; else{ QFileInfo fi = QFileInfo(editing_Filepath); if (fi.isFile()) appInit.m_sLastopenPath = QFileInfo(editing_Filepath).path(); else appInit.m_sLastopenPath = editing_Filepath; } appInit.set_appInitDatas(this->window(), "MAIN"); delete ui; } /* from main */ void MainWindow::setParam_readfile(QString param) { if (param.length() > 0){ QString suffix = QFileInfo(param).suffix(); if (suffix.toLower() == "xspf"){ param_readfile = param; //open_PlayLlist_file(param); QTimer::singleShot(200, this, SLOT(getParamFile())); } else{ QMessageBox msgBox; msgBox.setText("The file specified in the parameter is not a file with the XSPF extension."); msgBox.exec(); } } } void MainWindow::getParamFile() { open_PlayLlist_file(param_readfile); } /* Menu actions */ void MainWindow::on_action_Quit_triggered() { this->close(); } void MainWindow::on_action_Open_triggered() { QString init_path; if (editing_Filepath.length() > 3){ QFileInfo fi = QFileInfo(editing_Filepath); if (fi.isFile()) init_path = QFileInfo(editing_Filepath).path(); else init_path = editing_Filepath; } else init_path = QStandardPaths::standardLocations(QStandardPaths::MoviesLocation)[0]; QString filename = QFileDialog::getOpenFileName( this, tr("Open Playlist file"), init_path, tr("Playlist File (*.xspf);;ALL file (*.*)")); if (filename.length()==0){ this->statusBar()->showMessage(tr("select : Canseled"),3000); return; } open_PlayLlist_file(filename); } void MainWindow::open_PlayLlist_file(QString filename) { editing_Filepath = filename; //label_MessageBar_normal->setText(editing_Filepath); this->statusBar()->showMessage(tr("select : ")+filename,3000); XML_tree_open(); label_MessageBar_normal->setText(editing_Filepath); } void MainWindow::on_action_Save_triggered() { } void MainWindow::on_action_SaveAS_triggered() { } void MainWindow::on_action_New_triggered() { set_NewData(); label_MessageBar_normal->setText("( new file )"); } void MainWindow::on_action_About_triggered() { aboutDialog *pdialog = new aboutDialog(this); pdialog->exec(); delete pdialog; } // set menu from opened history void MainWindow::setMenu_Recently_files() { // check on first creation if (action_Recently_file_Group == nullptr){ // first creation action_Recently_file_Group = new QActionGroup(this); // create 20 actions for (int ni = 0;ni < 20;ni++){ QAction* paction = new QAction("filepath", action_Recently_file_Group); paction->setVisible(false); ui->menu_Recently_files->addAction(paction); } connect(action_Recently_file_Group, SIGNAL(triggered(QAction*)), this, SLOT(onaction_Recently_file_Group_triggered(QAction*)) ); } else{ // hide all actions QList<QAction *> list_action = action_Recently_file_Group->actions(); foreach(QAction *paction, list_action){ paction->setVisible(false); } } // set filepath in m_listOpenedHistory to display QList<QAction *> list_action = action_Recently_file_Group->actions(); int nlist = 0; foreach (QString filepath, appInit.m_listOpenedHistory){ list_action[nlist]->setText(filepath); list_action[nlist]->setVisible(true); nlist++; } } // triggered sub menu of Recently files void MainWindow::onaction_Recently_file_Group_triggered(QAction *paction) { // opens open_PlayLlist_file(paction->text()); } /************************************************************ new settings for TreeWidget ************************************************************/ void MainWindow::set_NewData() { ui->treeWidget_playlist->clear(); QStringList liststr; liststr << "playlist version" << "1"; QTreeWidgetItem *ptree_top = new QTreeWidgetItem(liststr, 0); ptree_top->setToolTip(0,tr("attibute in playlist")); ui->treeWidget_playlist->addTopLevelItem(ptree_top); liststr.clear(); liststr << "title" << ""; QTreeWidgetItem *ptree_item_1 = new QTreeWidgetItem(liststr, 0); ptree_item_1->setFlags(Qt::ItemIsEditable|Qt::ItemIsEnabled); ptree_top->addChild(ptree_item_1); liststr.clear(); liststr << "<trackList>" << ""; QTreeWidgetItem *ptree_item_tracklist = new QTreeWidgetItem(liststr, 0); ptree_top->addChild(ptree_item_tracklist); liststr.clear(); liststr << "<track>" << ""; QTreeWidgetItem *ptree_item_track = new QTreeWidgetItem(liststr, 0); ptree_item_tracklist->addChild(ptree_item_track); liststr.clear(); liststr << "title" << ""; QTreeWidgetItem *ptree_item_detail_title = new QTreeWidgetItem(liststr, 0); ptree_item_detail_title->setFlags(Qt::ItemIsEditable|Qt::ItemIsEnabled); ptree_item_track->addChild(ptree_item_detail_title); liststr.clear(); liststr << "location" << ""; QTreeWidgetItem *ptree_item_detail_location = new QTreeWidgetItem(liststr, 0); ptree_item_detail_location->setFlags(Qt::ItemIsEditable|Qt::ItemIsEnabled); ptree_item_track->addChild(ptree_item_detail_location); ui->treeWidget_playlist->expandAll(); } /************************************************************ Get Playlist and Set TreeWidget ************************************************************/ /* functions */ void MainWindow::XML_tree_open() { clearFileinfo(); ui->treeWidget_playlist->clear(); QFile file(editing_Filepath); if (!file.open(QFile::ReadOnly | QFile::Text)) { QMessageBox::warning(this, tr("PLeditor"), tr("Cannot read file %1:\n%2.") .arg(editing_Filepath) .arg(file.errorString())); this->statusBar()->showMessage(tr("Cannot open file : ")+editing_Filepath, 3000); return; } XML_tree_read(&file); // set open file history appInit.set_OpenedHistory(editing_Filepath); setMenu_Recently_files(); } bool MainWindow::XML_tree_read(QIODevice *device) { QString errorStr; int errorLine; int errorColumn; if (!domDocument.setContent( device, true, &errorStr, &errorLine,&errorColumn)) { QMessageBox::information(window(), tr("PLeditor"), tr("Parse error at line %1, column %2:\n%3") .arg(errorLine) .arg(errorColumn) .arg(errorStr)); this->statusBar()->showMessage( tr("Parse error in file : ")+editing_Filepath, 3000); return false; } QDomElement root = domDocument.documentElement(); if (root.tagName() != "playlist") { QMessageBox::information(window(), tr("PLeditor"), tr("The file is not an playlist file.")); this->statusBar()->showMessage( tr("not an playlist : ")+editing_Filepath, 3000); return false; } else if (root.hasAttribute("version") && root.attribute("version") != "1") { QMessageBox::information(window(), tr("PLeditor"), tr("The file is not an playlist version 1 " "file.")); this->statusBar()->showMessage( tr("not an playlist version: ")+editing_Filepath, 3000); return false; } QStringList liststr; QDomNamedNodeMap attrMap = root.attributes(); liststr << "playlist "+attrMap.item(0).toAttr().name() << attrMap.item(0).toAttr().value(); QTreeWidgetItem *ptree_item = new QTreeWidgetItem(liststr, 0); ptree_item->setToolTip(0,tr("attibute in playlist")); ui->treeWidget_playlist->addTopLevelItem(ptree_item); // playlist attribute int attrCount = attrMap.length(); for(int i = 0; i < attrCount; ++i){ QDomAttr attr = attrMap.item(i).toAttr(); } // in playlist-tag parsePlaylistElement(ptree_item,root); // in tracklist m_nTrack_cnt = 0; // Loops in a track list QDomElement child = root.firstChildElement("trackList"); while (!child.isNull()) { liststr.clear(); liststr << "<tracklist>" << ""; QTreeWidgetItem *ptree_item_tracklist = new QTreeWidgetItem(liststr, 0); ptree_item_tracklist->setToolTip(0,tr("tracklist")); ptree_item->addChild(ptree_item_tracklist); // Loops in a track QDomElement child2 = child.firstChildElement("track"); while (!child2.isNull()) { liststr.clear(); liststr << "<track>" << ""; QTreeWidgetItem *ptree_item_track = new QTreeWidgetItem(liststr, 0); ptree_item_track->setToolTip(0,tr("track")); ptree_item_tracklist->addChild(ptree_item_track); // in track parseTrackElement(ptree_item_track,child2); m_nTrack_cnt++; child2 = child2.nextSiblingElement("track"); } child = child.nextSiblingElement("tracklist"); } ui->treeWidget_playlist->expandAll(); if (m_nTrack_cnt == 0){ this->statusBar()->showMessage( tr("Track was not found : ")+editing_Filepath, 10000); } else { this->statusBar()->showMessage( QString::number(m_nTrack_cnt)+tr(" tracks found : ")+editing_Filepath, 10000); } setFileinfo(); return true; } // Elements other than track list void MainWindow::parsePlaylistElement(QTreeWidgetItem *ptree_playlist,const QDomElement &root) { QStringList liststr; QDomNode node = root.firstChild(); while (!node.isNull()) { if (node.isElement()) { QDomElement element = node.toElement(); if (element.tagName() != "trackList"){ liststr.clear(); liststr << element.tagName() << element.text(); QTreeWidgetItem *ptree_playlist_element = new QTreeWidgetItem(liststr, 0); ptree_playlist_element->setFlags(Qt::ItemIsEditable|Qt::ItemIsEnabled); ptree_playlist->addChild(ptree_playlist_element); } } node = node.nextSibling(); } } // Elements in a track void MainWindow::parseTrackElement(QTreeWidgetItem *ptree_track,const QDomElement &element) { QStringList liststr; QDomElement child = element.firstChildElement(); while (!child.isNull()) { QString tag_name = child.tagName(); QString value = child.text(); if (QUrl(value).isLocalFile()){ value = QUrl(value).toLocalFile(); } QString str= tag_name+","+value; liststr.clear(); liststr << tag_name << value; QTreeWidgetItem *ptree_track_item = new QTreeWidgetItem(liststr, 0); ptree_track_item->setFlags(Qt::ItemIsEditable|Qt::ItemIsEnabled); ptree_track->addChild(ptree_track_item); child = child.nextSiblingElement(); } } // file info void MainWindow::clearFileinfo() { ui->label_track_cnt->setText(""); ui->label_update_date->setText(""); } void MainWindow::setFileinfo() { ui->label_track_cnt->setText(QString::number(m_nTrack_cnt)+ " tracks"); QFileInfo fi = QFileInfo(editing_Filepath); ui->label_update_date->setText("(last-modified) "+fi.lastModified().toString("yyyy/MM/dd HH:mm:ss")); } /************************************************************ drop processing from an external file ************************************************************/ void MainWindow::dragEnterEvent(QDragEnterEvent *e) { if (e->mimeData()->hasUrls()) { e->acceptProposedAction(); } } void MainWindow::dropEvent(QDropEvent *e) { if (e->mimeData()->hasUrls()) { QString suffix = QFileInfo(e->mimeData()->text().trimmed()).suffix(); if (suffix.toLower() == "xspf"){ open_PlayLlist_file(QUrl(e->mimeData()->text().trimmed()).toLocalFile()); } } }
A.『最近開いたファイル』の中に、ファイルパス(Action)を設定
起動時およびXSPFファイルの読み込み完了時に
void setMenu_Recently_files();
を呼び出します。
この関数内で、取得済のファイルパスの履歴リスト (QStringList)を使って、『最近開いたファイル』の中にその履歴をaction登録します。
(1) 最初の呼び出し時に
QActionGroup
を作成し、
20個の Action を作成します。
20個は保存する最大のオープン履歴数です。
QActionGroup (各20個のaction) のトリガーは
void onaction_Recently_file_Group_triggered(QAction*)
に接続するように設定します。
(2) 次回以降は、履歴actionを一旦すべて非表示設定します。
(3) 履歴リストをループ処理で、ファイルパスを設定、表示状態に変更します。
B.ファイルパスの Action トリガーを処理
void onaction_Recently_file_Group_triggered(QAction*)
でクリックされた履歴の QAtion* を受け取ります。
actionに設定されているテキストをそのまま、オープンするファイルとして処理します。
ちょいテク
今回、QActionGroupをトリガーとしました。
triggered(QAction*)
トリガーの送信先を1つにすることで、今回のようにまとめて処理できます。
action のテキストをデータとして扱いましたが、
dataメンバーを使えば、より現実的な処理ができます。
また、QAction 個別にトリガーを設定した場合、
triggered()
となり、個別の処理がやりやすくなります
処理の方法によって、どの種類の triggered を使うか決めると良いでしょう。
他のクラスファイルやリソースファイルなどはZIPファイルをダウンロードして確認してください。
ZIP-file (73KB) download from Google DRIVE
空いた時間を見つけながら作成しているので、バグ等があってもご愛嬌でお願いします。(簡単なデバックと動作テストしかしていません)
今回は表示だけですが、最終的にはエディターとなる予定です (^^♪
また、区切りの良いタイミングで公開しますので、気長にお待ちくださいw
「Qt Quick」アプリケーション開発 (I・O BOOKS)
- 作者: 村上信昌,吉川武宏
- 出版社/メーカー: 工学社
- 発売日: 2018/10/01
- メディア: 単行本
- この商品を含むブログを見る
Qtプログラミング入門―使いやすいフレームワークを基礎から解説 (I・O BOOKS)
- 作者: 津田伸秀
- 出版社/メーカー: 工学社
- 発売日: 2011/12/01
- メディア: 単行本
- 購入: 1人 クリック: 4回
- この商品を含むブログ (9件) を見る
- 作者: ダニエルソーリン,Daniel Solin,アットコム
- 出版社/メーカー: ピアソンエデュケーション
- 発売日: 2001/05
- メディア: 単行本
- 購入: 1人 クリック: 9回
- この商品を含むブログ (2件) を見る