File indexing completed on 2024-05-12 15:27:47

0001 /***************************************************************************
0002     File                 : FileInfoDialog.cpp
0003     Project              : LabPlot
0004     Description          : import file data dialog
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2009-2019 Alexander Semke (alexander.semke@web.de)
0007     Copyright            : (C) 2015-2018 Stefan-Gerlach (stefan.gerlach@uni.kn)
0008 
0009  ***************************************************************************/
0010 
0011 /***************************************************************************
0012  *                                                                         *
0013  *  This program is free software; you can redistribute it and/or modify   *
0014  *  it under the terms of the GNU General Public License as published by   *
0015  *  the Free Software Foundation; either version 2 of the License, or      *
0016  *  (at your option) any later version.                                    *
0017  *                                                                         *
0018  *  This program is distributed in the hope that it will be useful,        *
0019  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0020  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0021  *  GNU General Public License for more details.                           *
0022  *                                                                         *
0023  *   You should have received a copy of the GNU General Public License     *
0024  *   along with this program; if not, write to the Free Software           *
0025  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0026  *   Boston, MA  02110-1301  USA                                           *
0027  *                                                                         *
0028  ***************************************************************************/
0029 
0030 #include "FileInfoDialog.h"
0031 #include "backend/datasources/LiveDataSource.h"
0032 #include "backend/datasources/filters/filters.h"
0033 
0034 #include <QDialogButtonBox>
0035 #include <QDir>
0036 #include <QIcon>
0037 #include <QFileInfo>
0038 #include <QProcess>
0039 #include <QVBoxLayout>
0040 #include <QWindow>
0041 
0042 #include <KLocalizedString>
0043 #include <KSharedConfig>
0044 #include <KWindowConfig>
0045 
0046 /*!
0047 \class ImportWidget
0048 \brief Provides a dialog containing the information about the files to be imported.
0049 
0050 \ingroup kdefrontend
0051 */
0052 
0053 FileInfoDialog::FileInfoDialog(QWidget* parent) : QDialog(parent) {
0054     m_textEditWidget.setReadOnly(true);
0055     m_textEditWidget.setLineWrapMode(QTextEdit::NoWrap);
0056     m_textEditWidget.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0057     m_textEditWidget.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0058 
0059     auto* layout = new QVBoxLayout(this);
0060     layout->addWidget(&m_textEditWidget);
0061 
0062     auto* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
0063     connect(buttonBox, &QDialogButtonBox::rejected, this, &FileInfoDialog::reject);
0064     connect(buttonBox, &QDialogButtonBox::accepted, this, &FileInfoDialog::accept);
0065 
0066     layout->addWidget(buttonBox);
0067 
0068     setWindowIcon(QIcon::fromTheme("help-about"));
0069     setWindowTitle(i18nc("@title:window", "File Information"));
0070     setAttribute(Qt::WA_DeleteOnClose);
0071 
0072     setLayout(layout);
0073 
0074     //restore saved settings if available
0075     create(); // ensure there's a window created
0076     KConfigGroup conf(KSharedConfig::openConfig(), "FileInfoDialog");
0077     if (conf.exists()) {
0078         KWindowConfig::restoreWindowSize(windowHandle(), conf);
0079         resize(windowHandle()->size()); // workaround for QTBUG-40584
0080     } else
0081         resize(QSize(300, 200).expandedTo(minimumSize()));
0082 }
0083 
0084 FileInfoDialog::~FileInfoDialog() {
0085     //save current settings
0086     KConfigGroup conf(KSharedConfig::openConfig(), "FileInfoDialog");
0087     KWindowConfig::saveWindowSize(windowHandle(), conf);
0088 }
0089 
0090 void FileInfoDialog::setFiles(QStringList& files) {
0091     QString infoString;
0092 
0093     for (const auto& fileName : files) {
0094         if (fileName.isEmpty())
0095             continue;
0096 
0097         if (!infoString.isEmpty())
0098             infoString += "<br><br><br>";
0099 
0100         infoString += fileInfoString(fileName);
0101     }
0102 
0103     m_textEditWidget.document()->setHtml(infoString);
0104 
0105     //resize to fit the content
0106     QSize size = m_textEditWidget.document()->size().toSize();
0107     m_textEditWidget.setMinimumSize(size.width() + m_textEditWidget.contentsMargins().left() + m_textEditWidget.contentsMargins().right(),
0108                                     size.height() + m_textEditWidget.contentsMargins().top() + m_textEditWidget.contentsMargins().bottom());
0109 }
0110 
0111 /*!
0112     returns a string containing the general information about the file \c name
0113     and some content specific information
0114     (number of columns and lines for ASCII, color-depth for images etc.).
0115  */
0116 QString FileInfoDialog::fileInfoString(const QString& name) const {
0117     QString infoString;
0118     QFileInfo fileInfo;
0119     QString fileTypeString;
0120     QIODevice *file = new QFile(name);
0121 
0122     QString fileName{name};
0123 #ifdef HAVE_WINDOWS
0124     if (name.at(1) != QLatin1Char(':'))
0125 #else
0126     if (name.at(0) != QLatin1String("/"))
0127 #endif
0128         fileName = QDir::homePath() + QLatin1String("/") + name;
0129 
0130     if (!file)
0131         file = new QFile(fileName);
0132 
0133     if (file->open(QIODevice::ReadOnly)) {
0134         QStringList infoStrings;
0135 
0136         infoStrings << "<u><b>" + fileName + "</b></u><br>";
0137 
0138         // File type given by "file"
0139 #ifdef Q_OS_LINUX
0140         auto* proc = new QProcess();
0141         QStringList args;
0142         args << "-b" << fileName;
0143         proc->start( "file", args);
0144 
0145         if (proc->waitForReadyRead(1000) == false)
0146             infoStrings << i18n("Reading from file %1 failed.", fileName);
0147         else {
0148             fileTypeString = proc->readLine();
0149             if (fileTypeString.contains(i18n("cannot open")))
0150                 fileTypeString.clear();
0151             else {
0152                 fileTypeString.remove(fileTypeString.length() - 1, 1);  // remove '\n'
0153             }
0154         }
0155         infoStrings << i18n("<b>File type:</b> %1", fileTypeString);
0156 #endif
0157 
0158         // General:
0159         fileInfo.setFile(fileName);
0160         infoStrings << "<b>" << i18n("General:") << "</b>";
0161 
0162         infoStrings << i18n("Readable: %1", fileInfo.isReadable() ? i18n("yes") : i18n("no"));
0163         infoStrings << i18n("Writable: %1", fileInfo.isWritable() ? i18n("yes") : i18n("no"));
0164         infoStrings << i18n("Executable: %1", fileInfo.isExecutable() ? i18n("yes") : i18n("no"));
0165 
0166 #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
0167         infoStrings << i18n("Birth time: %1", fileInfo.birthTime().toString());
0168         infoStrings << i18n("Last metadata changed: %1", fileInfo.metadataChangeTime().toString());
0169 #else
0170         infoStrings << i18n("Created: %1", fileInfo.created().toString());
0171 #endif
0172         infoStrings << i18n("Last modified: %1", fileInfo.lastModified().toString());
0173         infoStrings << i18n("Last read: %1", fileInfo.lastRead().toString());
0174         infoStrings << i18n("Owner: %1", fileInfo.owner());
0175         infoStrings << i18n("Group: %1", fileInfo.group());
0176         infoStrings << i18n("Size: %1", i18np("%1 cByte", "%1 cBytes", fileInfo.size()));
0177 
0178         // Summary:
0179         infoStrings << "<b>" << i18n("Summary:") << "</b>";
0180         //depending on the file type, generate summary and content information about the file
0181         //TODO: content information (in BNF) for more types
0182         switch (AbstractFileFilter::fileType(fileName)) {
0183         case AbstractFileFilter::FileType::Ascii:
0184             infoStrings << AsciiFilter::fileInfoString(fileName);
0185             break;
0186         case AbstractFileFilter::FileType::Binary:
0187             infoStrings << BinaryFilter::fileInfoString(fileName);
0188             break;
0189         case AbstractFileFilter::FileType::Image:
0190             infoStrings << ImageFilter::fileInfoString(fileName);
0191             break;
0192         case AbstractFileFilter::FileType::HDF5:
0193             infoStrings << HDF5Filter::fileInfoString(fileName);
0194             infoStrings << "<b>" << i18n("Content:") << "</b>";
0195             infoStrings << HDF5Filter::fileDDLString(fileName);
0196             break;
0197         case AbstractFileFilter::FileType::NETCDF:
0198             infoStrings << NetCDFFilter::fileInfoString(fileName);
0199             infoStrings << "<b>" << i18n("Content:") << "</b>";
0200             infoStrings << NetCDFFilter::fileCDLString(fileName);
0201             break;
0202         case AbstractFileFilter::FileType::FITS:
0203             infoStrings << FITSFilter::fileInfoString(fileName);
0204             break;
0205         case AbstractFileFilter::FileType::JSON:
0206             infoStrings << JsonFilter::fileInfoString(fileName);
0207             break;
0208         case AbstractFileFilter::FileType::ROOT:
0209             infoStrings << ROOTFilter::fileInfoString(fileName);
0210             break;
0211         case AbstractFileFilter::FileType::NgspiceRawAscii:
0212         case AbstractFileFilter::FileType::NgspiceRawBinary:
0213             infoStrings << NgspiceRawAsciiFilter::fileInfoString(fileName);
0214             break;
0215         }
0216 
0217 
0218         infoString += infoStrings.join("<br>");
0219 
0220     } else
0221         infoString += i18n("Could not open file %1 for reading.", fileName);
0222 
0223     return infoString;
0224 }