/*
* Copyright (C) Bobbin Robotics, Inc. All Rights Reserved
*
* This source code is protected under international copyright law.
*
* All rights reserved and protected by the copyright holders.
*
* This file is confidential and only available to authorized individuals with
* the permission of the copyright holders. If you encounter this file and do
* not have permission, please contact the copyright holders and delete this
* file.
*
*/
#pragma once
#include <map>
#include <string>
#include <QDialog>
QT_BEGIN_NAMESPACE
class QTextEdit;
class QTabWidget;
QT_END_NAMESPACE
namespace bobbin::open_file_dialog {
class OpenFileDialog : public QDialog {
Q_OBJECT
public:
/** \brief Constructors.*/
explicit OpenFileDialog(QWidget* parent = nullptr);
/** \brief Destructor. */
~OpenFileDialog() = default;
private:
/** \brief Initialize dialog layout.*/
void InitializeDialog();
/** \brief Create a new tab widget when opening a new file.*/
QWidget* CreateFileTabWidget(const QString file_path);
/** \brief Get the text of the currently open tab widget.*/
QTextEdit* GetFileTextEdit(const QString& file_name) const;
/** \brief Open new file and read file text.*/
void OpenAndShowFile();
/** \brief Save file in the same path.*/
void SaveFile();
/** \brief Close file and tab widget.*/
void CloseFile(int index);
/** \brief Get file action icon resource.*/
const std::string GetFileActionIcon(const std::string icon_name) const;
/** \brief Keyboard events that handle events for keyboard triggering.*/
bool eventFilter(QObject* obj, QEvent* e) override;
private:
QTabWidget* file_tab_widget_;
std::map<QString, QString> file_info_map_;
};
} // namespace bobbin::open_file_dialog
.cpp
/*
* Copyright (C) Bobbin Robotics, Inc. All Rights Reserved
*
* This source code is protected under international copyright law.
*
* All rights reserved and protected by the copyright holders.
*
* This file is confidential and only available to authorized individuals with
* the permission of the copyright holders. If you encounter this file and do
* not have permission, please contact the copyright holders and delete this
* file.
*
*/
#include "tools/open_file_dialog/open_file_dialog.h"
#include "common/find_resource.h"
#include <QFile>
#include <QFileDialog>
#include <QFileInfo>
#include <QKeyEvent>
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>
#include <QPushButton>
#include <QTabWidget>
#include <QTextEdit>
#include <QTextStream>
#include <QToolBar>
#include <QVBoxLayout>
namespace bobbin::open_file_dialog {
OpenFileDialog::OpenFileDialog(QWidget* parent) : QDialog(parent) {
InitializeDialog();
}
void OpenFileDialog::InitializeDialog() {
constexpr size_t kDldWidth = 600;
constexpr size_t kDlgHeight = 800;
this->resize(kDldWidth, kDlgHeight);
setWindowTitle(tr("Open File Dialog"));
QVBoxLayout* main_layout = new QVBoxLayout;
this->setLayout(main_layout);
// Menu bar.
QMenuBar* menu_bar_ = new QMenuBar(this);
menu_bar_->setStyleSheet("QMenuBar{font-size: 18px}");
QMenu* file_menu_ = new QMenu(tr("File"), this);
menu_bar_->addMenu(file_menu_);
main_layout->addWidget(menu_bar_);
QAction* open_file_dialog_action = new QAction(tr("Open"));
file_menu_->addAction(open_file_dialog_action);
connect(open_file_dialog_action, &QAction::triggered, this,
&OpenFileDialog::OpenAndShowFile);
QAction* save_file_action = new QAction(tr("Save"));
file_menu_->addAction(save_file_action);
connect(save_file_action, &QAction::triggered, this,
&OpenFileDialog::SaveFile);
QAction* close_file_action = new QAction(tr("Close"));
file_menu_->addAction(close_file_action);
connect(close_file_action, &QAction::triggered, this,
&OpenFileDialog::CloseFile);
// Tool bar.
QToolBar* tool_bar = new QToolBar;
QAction* tool_bar_open_file_dialog_action = new QAction(
QIcon(QString::fromStdString(
GetFileActionIcon("tools/open_file_dialog/open_file.jpg"))),
tr("Open File"));
QAction* tool_bar_save_file_action = new QAction(
QIcon(QString::fromStdString(
GetFileActionIcon("tools/open_file_dialog/save_file.jpg"))),
tr("Save File"));
QAction* tool_bar_close_file_action = new QAction(
QIcon(QString::fromStdString(
GetFileActionIcon("tools/open_file_dialog/close_file.jpeg"))),
tr("Close File"));
tool_bar->addAction(tool_bar_open_file_dialog_action);
tool_bar->addAction(tool_bar_save_file_action);
tool_bar->addAction(tool_bar_close_file_action);
main_layout->addWidget(tool_bar);
connect(tool_bar_open_file_dialog_action, &QAction::triggered, this,
&OpenFileDialog::OpenAndShowFile);
connect(tool_bar_save_file_action, &QAction::triggered, this,
&OpenFileDialog::SaveFile);
connect(tool_bar_close_file_action, &QAction::triggered, this,
&OpenFileDialog::CloseFile);
file_tab_widget_ = new QTabWidget;
file_tab_widget_->setTabPosition(QTabWidget::North);
file_tab_widget_->setTabsClosable(false);
file_tab_widget_->setTabsClosable(true);
main_layout->addWidget(file_tab_widget_);
connect(file_tab_widget_, &QTabWidget::tabCloseRequested, this,
&OpenFileDialog::CloseFile);
}
void OpenFileDialog::OpenAndShowFile() {
const auto file_path =
QFileDialog::getOpenFileName(this, tr("Open File"), tr("."), tr("*"));
if (file_path.isEmpty()) {
QMessageBox::warning(this, tr("warn"), tr("File path is empty!"));
return;
}
const QFileInfo file_info(file_path);
const auto file_name = file_info.fileName();
if (file_info_map_.count(file_name) > 0) {
QMessageBox::warning(this, tr("warn"), tr("The file is already open!"));
return;
}
file_tab_widget_->setCurrentIndex(
file_tab_widget_->addTab(CreateFileTabWidget(file_path), file_name));
file_info_map_[file_name] = file_path;
}
void OpenFileDialog::SaveFile() {
const auto file_name =
file_tab_widget_->tabText(file_tab_widget_->currentIndex());
if (!file_info_map_.count(file_name)) {
QMessageBox::warning(this, tr("warn"), tr("Find file path failed!"));
return;
}
const auto text_edit = GetFileTextEdit(file_name);
if (text_edit == nullptr) {
QMessageBox::warning(this, tr("warn"), tr("Find file path failed!"));
return;
}
QFile file(file_info_map_[file_name]);
if (!file.open(QIODevice::ReadWrite | QFile::Text | QIODevice::Truncate)) {
QMessageBox::warning(this, tr("warn"), tr("Open file failed!"));
return;
}
QTextStream out(&file);
out << text_edit->toPlainText() << endl;
out.flush();
file.close();
}
void OpenFileDialog::CloseFile(int index) {
const auto file_name =
file_tab_widget_->tabText(file_tab_widget_->currentIndex());
if (!file_info_map_.count(file_name)) {
file_info_map_.erase(file_name);
}
file_tab_widget_->removeTab(index);
}
QWidget* OpenFileDialog::CreateFileTabWidget(const QString file_path) {
QWidget* widget = new QWidget;
QVBoxLayout* layout = new QVBoxLayout;
QTextEdit* file_text = new QTextEdit;
const QFileInfo file_info(file_path);
const auto file_name = file_info.fileName();
file_text->setObjectName(file_name);
file_text->setStyleSheet("QTextEdit{font-size: 20px}");
file_text->installEventFilter(this);
layout->addWidget(file_text);
widget->setLayout(layout);
QFile file(file_path);
if (file.open(QIODevice::ReadWrite | QFile::Text)) {
QTextStream in(&file);
file_text->setText(in.readAll());
file.close();
} else {
QMessageBox::warning(this, tr("warn"), tr("Open file failed!"));
}
return widget;
}
QTextEdit* OpenFileDialog::GetFileTextEdit(const QString& file_name) const {
const auto current_widget = file_tab_widget_->currentWidget();
QList<QTextEdit*> text_edits = current_widget->findChildren<QTextEdit*>();
for (auto edit : text_edits) {
if (edit->objectName() == file_name) {
return edit;
}
}
return nullptr;
}
bool OpenFileDialog::eventFilter(QObject* obj, QEvent* e) {
if (e->type() == QEvent::KeyPress) {
QKeyEvent* event = static_cast<QKeyEvent*>(e);
if (event->key() == Qt::Key_S &&
(event->modifiers() & Qt::ControlModifier)) {
SaveFile();
return true;
}
}
return false;
}
const std::string OpenFileDialog::GetFileActionIcon(
const std::string icon_name) const {
return common::FindResourceOrThrow(icon_name);
}
} // namespace bobbin::open_file_dialog