9#include <QWidgetAction> 
   10#include <QDesktopServices> 
   16#include <QLoggingCategory> 
   18#include <QApplication> 
   20#include <QMimeDatabase> 
   23#include <QTextDocument> 
   27#include "RabbitCommonDir.h" 
   28#include "UndoCommand.h" 
   29#include "FileBroserTreeView.h" 
   30#include "FileBrowser.h" 
   32static Q_LOGGING_CATEGORY(log, 
"RabbitCommon.Browser.File")
 
   36    , m_pUndoStack(
nullptr)
 
   42    , m_pTextEdit(
nullptr)
 
   43    , m_pHiddenFile(
nullptr)
 
   44    , m_pAssociated(
nullptr)
 
   45    , m_pOrientation(
nullptr)
 
   48    setAttribute(Qt::WA_DeleteOnClose);
 
   49    setWindowTitle(tr(
"File browser"));
 
   50    setWindowIcon(QIcon::fromTheme(
"browser"));
 
   52    QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
 
   53                  QSettings::IniFormat);
 
   59        rect = parent->frameGeometry();
 
   61        QScreen* pScreen = QApplication::primaryScreen();
 
   63            rect = pScreen->geometry();
 
   65    rect.setLeft((rect.width() - nWidth) / 2);
 
   66    rect.setTop((rect.height() - nHeight) / 2);
 
   67    rect.setWidth(nWidth);
 
   68    rect.setHeight(nHeight);
 
   71    QVBoxLayout* pLayout = 
new QVBoxLayout(
this);
 
   74        m_pModel = 
new QFileSystemModel(
this);
 
   83        m_pSpliter = 
new QSplitter(
this);
 
   84        if(!m_pSpliter) 
break;
 
   87        m_pTree->setAutoScroll(
true);
 
   99        m_pTable = 
new QTableView(m_pSpliter);
 
  101        m_pTextEdit = 
new QTextEdit(m_pSpliter);
 
  104        QToolBar* pToolBar = 
new QToolBar(
this);
 
  105        szTitle = tr(
"Close");
 
  106        QAction* pAction = pToolBar->addAction(QIcon::fromTheme(
"window-close"),
 
  107                                       szTitle, 
this, &CFileBrowser::close);
 
  108        pAction->setStatusTip(szTitle);
 
  110        m_pUndoStack = 
new QUndoStack(
this);
 
  111        if(!m_pUndoStack) 
break;
 
  113        QList<QAction*> lstUndo;
 
  114        pAction = m_pUndoStack->createUndoAction(
this);
 
  115        pAction->setIcon(QIcon::fromTheme(
"edit-undo"));
 
  117        pAction = m_pUndoStack->createRedoAction(
this);
 
  118        pAction->setIcon(QIcon::fromTheme(
"edit-redo"));
 
  120        pToolBar->addActions(lstUndo);
 
  156        pToolBar->addAction(QIcon::fromTheme(
"go-up"), tr(
"Up folder"),
 
  159            QModelIndex index = m_pTree->currentIndex();
 
  160            szDir = m_pModel->filePath(index);
 
  163                szDir = szDir + QDir::separator() + 
"..";
 
  166                szDir = fi.absolutePath();
 
  168            qDebug(log) << 
"Dir" << szDir;
 
  169            auto i = m_pModel->index(szDir);
 
  172                m_pUndoStack->push(
new CChange(i, 
this));
 
  173                m_pTree->setCurrentIndex(i);
 
  175                m_pTree->doItemsLayout();
 
  176                m_pTree->scrollTo(i);
 
  180        szTitle = tr(
"Option");
 
  181        QToolButton* pButtonOption = 
new QToolButton(pToolBar);
 
  182        pButtonOption->setIcon(QIcon::fromTheme(
"emblem-system"));
 
  183        pButtonOption->setStatusTip(szTitle);
 
  184        pButtonOption->setPopupMode(QToolButton::InstantPopup);
 
  185        QMenu* pMenuOption = 
new QMenu(szTitle, pButtonOption);
 
  186        pButtonOption->setMenu(pMenuOption);
 
  187        pToolBar->addWidget(pButtonOption);
 
  189        szTitle = tr(
"Hidden file");
 
  190        m_pHiddenFile = pMenuOption->addAction(
 
  193                bool checked = m_pHiddenFile->isChecked();
 
  195                    m_pModel->setFilter(m_pModel->filter() | QDir::Hidden);
 
  197                    m_pModel->setFilter(m_pModel->filter() & (~QDir::Hidden));
 
  198                QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
 
  199                              QSettings::IniFormat);
 
  200                set.setValue(GetSetPrefix() + 
"/HiddenFile", checked);
 
  202        check = set.value(GetSetPrefix() + 
"/HiddenFile", check).toBool();
 
  203        m_pHiddenFile->setStatusTip(szTitle);
 
  204        m_pHiddenFile->setToolTip(szTitle);
 
  205        m_pHiddenFile->setCheckable(
true);
 
  206        m_pHiddenFile->setChecked(check);
 
  208            m_pModel->setFilter(m_pModel->filter() | QDir::Hidden);
 
  210            m_pModel->setFilter(m_pModel->filter() & (~QDir::Hidden));
 
  212        szTitle = tr(
"Open with the System Associated Program");
 
  213        m_pAssociated = pMenuOption->addAction(
 
  214            szTitle, 
this, [&](){
 
  215                QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
 
  216                              QSettings::IniFormat);
 
  217                set.setValue(GetSetPrefix() + 
"/SystemAssociatedProgram", m_pAssociated->isChecked());
 
  219        m_pAssociated->setStatusTip(szTitle);
 
  220        m_pAssociated->setToolTip(szTitle);
 
  221        m_pAssociated->setCheckable(
true);
 
  222        m_pAssociated->setChecked(
 
  224                   GetSetPrefix() + 
"/SystemAssociatedProgram",
 
  225                   m_pAssociated->isChecked()).toBool());
 
  227        szTitle = tr(
"Horizontal");
 
  228        m_pOrientation = pMenuOption->addAction(
 
  229            szTitle, 
this, [&](){
 
  230                bool checked = m_pOrientation->isChecked();
 
  232                    m_pSpliter->setOrientation(Qt::Horizontal);
 
  234                    m_pSpliter->setOrientation(Qt::Vertical);
 
  235                QSettings set(RabbitCommon::CDir::Instance()->GetFileUserConfigure(),
 
  236                              QSettings::IniFormat);
 
  237                set.setValue(GetSetPrefix() + 
"/Spliter/Horizontal", checked);
 
  239        m_pOrientation->setStatusTip(szTitle);
 
  240        m_pOrientation->setToolTip(szTitle);
 
  241        m_pOrientation->setCheckable(
true);
 
  242#if defined(Q_OS_ANDROID) 
  247        check = set.value(GetSetPrefix() + 
"/Spliter/Horizontal", check).toBool();
 
  248        m_pOrientation->setChecked(check);
 
  250            m_pSpliter->setOrientation(Qt::Horizontal);
 
  252            m_pSpliter->setOrientation(Qt::Vertical);
 
  254        QComboBox* pUrl = 
new QComboBox(pToolBar);
 
  255        pUrl->setEditable(
true);
 
  256        pUrl->setSizePolicy(QSizePolicy::Policy::Expanding,
 
  257                            QSizePolicy::Policy::Preferred);
 
  259            pUrl, &QComboBox::currentTextChanged, 
this,
 
  260            [&](
const QString &szText) {
 
  261                qDebug(log) << 
"QComboBox::currentTextChanged";
 
  262                QComboBox* pUrl = qobject_cast<QComboBox*>(sender());
 
  264                QModelIndex index = m_pModel->index(szText);
 
  265                if(index.isValid()) {
 
  266                    m_pUndoStack->push(
new CChange(index, 
this));
 
  267                    m_pTree->setCurrentIndex(index);
 
  269                    m_pTree->doItemsLayout();
 
  270                    m_pTree->scrollTo(index);
 
  271                    int index = pUrl->findText(szText);
 
  273                        pUrl->addItem(szText);
 
  277        pToolBar->addWidget(pUrl);
 
  279        pLayout->addWidget(pToolBar);
 
  280        pLayout->addWidget(m_pSpliter);
 
  292            m_pTree->setModel(m_pModel);
 
  293            m_pTree->setHeaderHidden(
true);
 
  295            m_pTree->header()->hideSection(1);
 
  296            m_pTree->header()->hideSection(2);
 
  297            m_pTree->header()->hideSection(3);
 
  298            m_pSpliter->addWidget(m_pTree);
 
  312                m_pTree, &QTreeView::clicked,
 
  313                this, [&](
const QModelIndex& index){
 
  314                    m_pUndoStack->push(
new CChange(index, 
this));
 
  319                m_pTree, &QTreeView::doubleClicked,
 
  320                this, [&](
const QModelIndex &index) {
 
  322                        QString szFile = m_pModel->filePath(index);
 
  323                        emit sigDoubleClicked(szFile, m_pModel->isDir(index));
 
  324                        if(m_pModel->isDir(index)) {
 
  332            check = connect(m_pTree, &CFileBroserTreeView::sigChanged,
 
  333                            this, &CFileBrowser::sigChanged);
 
  338            m_pSpliter->addWidget(m_pList);
 
  339            m_pList->setModel(m_pModel);
 
  344            m_pSpliter->addWidget(m_pTable);
 
  345            m_pTable->setModel(m_pModel);
 
  346            m_pTable->setShowGrid(
false);
 
  347            m_pTable->verticalHeader()->hide();
 
  349                m_pTable, &QTableView::clicked,
 
  350                this, [&](
const QModelIndex &index) {
 
  352                        m_pUndoStack->push(
new CChange(index, 
this));
 
  353                        QString szDir = m_pModel->filePath(index);
 
  354                        m_pTree->setCurrentIndex(index);
 
  355                        m_pTree->expand(index);
 
  356                        if(m_pModel->isDir(index)) {
 
  357                            m_pModel->setRootPath(szDir);
 
  358                            m_pTable->setRootIndex(m_pModel->index(szDir));
 
  359                            if(!m_pTextEdit->isHidden())
 
  362#
if defined(Q_OS_ANDROID)
 
  370            check = connect(m_pTable, &QTableView::doubleClicked,
 
  371                            this, [&](
const QModelIndex &index){
 
  372                QString szFile = m_pModel->filePath(index);
 
  374                emit sigDoubleClicked(szFile, m_pModel->isDir(index));
 
  381            m_pSpliter->addWidget(m_pTextEdit);
 
  405CFileBrowser::~CFileBrowser()
 
  407    qDebug(log) << 
"CFileBrowser::~CFileBrowser()";
 
  412    auto index = m_pModel->setRootPath(dir);
 
  413    m_pTree->setRootIndex(index);
 
 
  418    return m_pModel->rootPath();
 
 
  421QString CFileBrowser::GetSetPrefix()
 
  423    QString szPrefix(
"FileBrowser");
 
  424    if(!this->objectName().isEmpty())
 
  425        szPrefix = szPrefix + 
"/" + this->objectName();
 
  429QString CFileBrowser::readFile(
const QString &filePath)
 
  433    if (filePath.isEmpty())
 
  436    QFile file(filePath);
 
  438    static const QMimeDatabase db;
 
  439    const QMimeType mime = db.mimeTypeForFile(QFileInfo(file));
 
  440    qDebug(log) << mime << filePath;
 
  442    if(mime.name() ==
"application/x-executable")
 
  444        if(QProcess::startDetached(filePath))
 
  447            qCritical(log) << 
"Start fail:" << filePath;
 
  448    } 
else if(mime.name().contains(
"image", Qt::CaseInsensitive)) {
 
  450        if(img.load(filePath)) {
 
  451            QTextCursor cursor = m_pTextEdit->textCursor();
 
  452            QTextDocument *document = m_pTextEdit->document();
 
  455                document->addResource(
 
  456                    QTextDocument::ImageResource, QUrl(
"image"), img);
 
  458            cursor.insertImage(
"image");
 
  461            qCritical(log) << 
"Error: load image" << filePath;
 
  463        if (file.size() >= 2000000)
 
  464            return tr(
"File size is too big.\nYou can read files up to %1 MB.").arg(2);
 
  467        const auto mimeTypesForFile = mime.parentMimeTypes();
 
  468        for (
const auto &m : mimeTypesForFile) {
 
  469            qDebug(log) << 
"m" << m;
 
  470            if (m.contains(
"text", Qt::CaseInsensitive)
 
  471                || mime.comment().contains(
"text", Qt::CaseInsensitive)) {
 
  472                if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
 
  473                    return tr(
"Error opening the File!");
 
  475                QTextStream stream(&file);
 
  476                return stream.readAll();
 
  480    return tr(
"Filetype ") + mime.name() + 
" not supported!";
 
  483int CFileBrowser::ShowFile(
const QString &szFile)
 
  485    if(m_pAssociated->isChecked()) {
 
  486        QUrl url = QUrl::fromLocalFile(szFile);
 
  487        if(QDesktopServices::openUrl(url))
 
  491    QString szText = readFile(szFile);
 
  492    if(!szText.isEmpty())
 
  493        m_pTextEdit->setText(szText);
 
  494    if(m_pTextEdit->isHidden())
 
  499void CFileBrowser::slotClicked(
const QModelIndex &index)
 
  501    qDebug(log) << 
"CFileBrowser::slotClicked" << index;
 
  503        if(m_pModel->isDir(index)) {
 
  504            m_pTable->setRootIndex(index);
 
  510#if defined(Q_OS_ANDROID) 
  511        QString szFile = m_pModel->filePath(index);
 
  517CDlgFileBrowser::CDlgFileBrowser(QWidget *parent) : QDialog(parent)
 
  518    ,m_pFileBrowser(nullptr)
 
  521    setWindowIcon(m_pFileBrowser->windowIcon());
 
  522    setWindowTitle(m_pFileBrowser->windowTitle());
 
  524    bool check = connect(m_pFileBrowser, SIGNAL(destroyed(QObject*)),
 
  525                         this, SLOT(close()));
 
  528    QHBoxLayout *layout = 
new QHBoxLayout(
this);
 
  529    layout->addWidget(m_pFileBrowser);
 
  530    layout->setContentsMargins(0, 0, 0, 0);
 
void setRootPath(const QString dir)
Set root path.
 
QString rootPath() const
Get root path.