File indexing completed on 2022-11-22 12:51:03

0001 /*
0002     SPDX-FileCopyrightText: 2007, 2008 Carsten Niehaus <cniehaus@kde.org>
0003     SPDX-FileCopyrightText: 2006 Georges Khaznadar <georgesk@debian.org>
0004     SPDX-FileCopyrightText: 2006, 2007 Jerome Pansanel <j.pansanel@pansanel.net>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "obconverter.h"
0010 
0011 // Qt includes
0012 #include <QDialogButtonBox>
0013 #include <QFileDialog>
0014 #include <QProcess>
0015 #include <QPushButton>
0016 #include <QRegularExpression>
0017 #include <QUrl>
0018 #include <QVBoxLayout>
0019 #include <QVector>
0020 
0021 // KDE includes
0022 #include <kwidgetsaddons_version.h>
0023 #include <KGuiItem>
0024 #include <KHelpClient>
0025 #include <KLocalizedString>
0026 #include <KMessageBox>
0027 using namespace std;
0028 using namespace OpenBabel;
0029 
0030 KOpenBabel::KOpenBabel(QWidget *parent)
0031     : QDialog(parent)
0032 {
0033     setWindowTitle(i18nc("@title:window", "OpenBabel Frontend"));
0034     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Close);
0035     QWidget *mainWidget = new QWidget(this);
0036     QVBoxLayout *mainLayout = new QVBoxLayout;
0037     setLayout(mainLayout);
0038     mainLayout->addWidget(mainWidget);
0039     QPushButton *user1Button = new QPushButton;
0040     buttonBox->addButton(user1Button, QDialogButtonBox::ActionRole);
0041     connect(buttonBox, &QDialogButtonBox::rejected, this, &KOpenBabel::reject);
0042     connect(user1Button, &QPushButton::clicked, this, &KOpenBabel::slotConvert);
0043     connect(buttonBox, &QDialogButtonBox::helpRequested, this, &KOpenBabel::slotHelpRequested);
0044 
0045     user1Button->setDefault(true);
0046 
0047     OBConvObject = new OBConversion();
0048 
0049     ui.setupUi(mainWidget);
0050 
0051     KGuiItem::assign(user1Button, KGuiItem(i18n("Convert")));
0052     mainLayout->addWidget(buttonBox);
0053 
0054     setupWindow();
0055 }
0056 
0057 KOpenBabel::~KOpenBabel()
0058 {
0059     delete OBConvObject;
0060     OBConvObject = nullptr;
0061 }
0062 
0063 void KOpenBabel::setupWindow()
0064 {
0065     // Set multiple selection possible
0066     ui.FileListView->setSelectionMode(QAbstractItemView::SelectionMode(3));
0067 
0068     // Creating the main layout
0069     QStringList InputType;
0070     vector<string> InputFormat = OBConvObject->GetSupportedInputFormat();
0071     for (vector<string>::iterator it = InputFormat.begin(); it != InputFormat.end(); ++it) {
0072         InputType << QString((*it).c_str());
0073     }
0074     ui.InputTypeComboBox->addItems(InputType);
0075 
0076     QStringList OutputType;
0077     vector<string> OutputFormat = OBConvObject->GetSupportedOutputFormat();
0078     for (vector<string>::iterator it = OutputFormat.begin(); it != OutputFormat.end(); ++it) {
0079         OutputType << QString((*it).c_str());
0080     }
0081     ui.OutputTypeComboBox->addItems(OutputType);
0082 
0083     // Create connection
0084     connect(ui.addFileButton, &QAbstractButton::clicked, this, &KOpenBabel::slotAddFile);
0085 
0086     connect(ui.deleteFileButton, &QAbstractButton::clicked, this, &KOpenBabel::slotDeleteFile);
0087 
0088     connect(ui.selectAllFileButton, &QAbstractButton::clicked, this, &KOpenBabel::slotSelectAll);
0089 
0090     connect(ui.FileListView, &QListWidget::itemSelectionChanged, this, &KOpenBabel::slotGuessInput);
0091 }
0092 
0093 void KOpenBabel::slotAddFile()
0094 {
0095     QStringList InputType;
0096     vector<string> InputFormat = OBConvObject->GetSupportedInputFormat();
0097     for (vector<string>::iterator it = InputFormat.begin(); it != InputFormat.end(); ++it) {
0098         InputType << QString((*it).c_str());
0099     }
0100     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0101     // InputType is now something like this:                                                                                    //
0102     // "acr -- ACR format [Read-only]", "alc -- Alchemy format", "arc -- Accelrys/MSI Biosym/Insight II CAR format [Read-only]" //
0103     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0104 
0105     QStringList tmpList = InputType;
0106     tmpList.replaceInStrings(QRegularExpression("^"), QStringLiteral("*."));
0107     tmpList.replaceInStrings(QRegularExpression("(.*) -- (.*)"), "\\2(\\1)");
0108     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0109     // tmpList is now something like this:                                                                                      //
0110     // "ACR format [Read-only] (*.acr)", "Alchemy format (*.alc)"                                                                   //
0111     //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0112 
0113     QList<QUrl> fl = QFileDialog::getOpenFileUrls(
0114         this,
0115         i18n("Open Molecule File"),
0116         QUrl(),
0117         i18n("All Files") + QStringLiteral("(*);;") + tmpList.join(QLatin1String(";;")) // add all possible extensions like "*.cml *.mol"
0118     );
0119 
0120     foreach (const QUrl &u, fl) {
0121         new QListWidgetItem(u.toDisplayString(), ui.FileListView);
0122     }
0123 }
0124 
0125 void KOpenBabel::slotSelectAll()
0126 {
0127     ui.FileListView->selectAll();
0128 }
0129 
0130 void KOpenBabel::slotDeleteFile()
0131 {
0132     QList<QListWidgetItem *> p = ui.FileListView->selectedItems();
0133     foreach (QListWidgetItem *item, p) {
0134         delete item;
0135     }
0136 }
0137 
0138 void KOpenBabel::slotGuessInput()
0139 {
0140     QList<QListWidgetItem *> p = ui.FileListView->selectedItems();
0141     bool first = true;
0142     QString suffix;
0143     if (p.count()) {
0144         foreach (QListWidgetItem *item, p) {
0145             if (first) {
0146                 first = false;
0147                 suffix = item->text().remove(QRegularExpression("^.*\\."));
0148             } else {
0149                 if (item->text().remove(QRegularExpression("^.*\\.")) == suffix) {
0150                     continue;
0151                 } else {
0152                     // All the file types are not same, set type to default
0153                     ui.InputTypeComboBox->setCurrentIndex(0);
0154                     return;
0155                 }
0156             }
0157         }
0158     }
0159     for (int i = 0; i < ui.InputTypeComboBox->count(); ++i) {
0160         if (ui.InputTypeComboBox->itemText(i).indexOf(QRegularExpression('^' + suffix + " --")) >= 0) {
0161             ui.InputTypeComboBox->setCurrentIndex(i);
0162             return;
0163         }
0164     }
0165     // The suffix has not been found, set type to default
0166     ui.InputTypeComboBox->setCurrentIndex(0);
0167 }
0168 
0169 void KOpenBabel::slotConvert()
0170 {
0171     QString iformat = ui.InputTypeComboBox->currentText();
0172     QString oformat = ui.OutputTypeComboBox->currentText();
0173     iformat = iformat.remove(QRegularExpression(" --.*"));
0174     oformat = oformat.remove(QRegularExpression(" --.*"));
0175 
0176     QList<QListWidgetItem *> p = ui.FileListView->selectedItems();
0177     if (p.count() == 0) {
0178         KMessageBox::error(this, i18n("You must select some files first."), i18n("No files selected"));
0179         return;
0180     }
0181     QListIterator<QListWidgetItem *> it(p);
0182     QStringList cmdList; // Full command
0183     QVector<QStringList> cmdArgList; // Arguments only
0184     foreach (QListWidgetItem *item, p) {
0185         QString ifname = QUrl(item->text()).toLocalFile();
0186         QString ofname = ifname;
0187         ofname = ofname.remove(QRegularExpression("\\.([^\\.]*$)"));
0188         ofname = ofname + QStringLiteral(".") + oformat;
0189 
0190         bool proceed = true;
0191 
0192         if (QFile::exists(ofname)) {
0193             // something named ofname already exists
0194             switch (KMessageBox::warningContinueCancel(this,
0195                                                        i18n("The file %1 already exists. Do you want to overwrite if possible?", ofname),
0196                                                        i18n("The File %1 Already Exists -- KOpenBabel", ofname))) {
0197             case KMessageBox::Cancel:
0198                 proceed = false;
0199                 break;
0200             default:
0201                 break;
0202             }
0203         }
0204         if (proceed) {
0205             QStringList arguments;
0206             arguments << QStringLiteral("-i") + iformat << ifname << QStringLiteral("-o") + oformat << ofname;
0207             cmdArgList.append(arguments);
0208             cmdList.append(QStringLiteral("babel ") + arguments.join(QStringLiteral(" ")));
0209         }
0210     }
0211     if (cmdArgList.count() > 0) {
0212 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0)
0213         switch (KMessageBox::questionTwoActions(this,
0214 #else
0215         switch (KMessageBox::questionYesNo(this,
0216 #endif
0217             cmdList.join(QStringLiteral("\n")),
0218             i18n("Is it okay to run these commands? -- KOpenBabel"),
0219             KGuiItem(i18n("Convert")),
0220             KStandardGuiItem::cancel())) {
0221 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0)
0222         case KMessageBox::PrimaryAction:
0223 #else
0224         case KMessageBox::Yes:
0225 #endif
0226             foreach (const QStringList &s, cmdArgList) {
0227                 QProcess::startDetached(QStringLiteral("babel"), s);
0228             }
0229             break;
0230         default:
0231             break;
0232         }
0233     }
0234 }
0235 
0236 void KOpenBabel::slotHelpRequested()
0237 {
0238     KHelpClient::invokeHelp(QStringLiteral("commands"), QStringLiteral("kalzium"));
0239 }
0240 
0241 void KOpenBabel::addFile(const QString &filename)
0242 {
0243     ui.FileListView->addItem(filename);
0244 }