File indexing completed on 2024-04-21 05:51:40

0001 /*
0002  *  SPDX-FileCopyrightText: 2002-2003 Jesper K. Pedersen <blackie@kde.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-only
0005  **/
0006 
0007 #include "userdefinedregexps.h"
0008 
0009 #include <QAction>
0010 #include <QDir>
0011 #include <QHeaderView>
0012 #include <QMenu>
0013 #include <QTextStream>
0014 #include <QVBoxLayout>
0015 
0016 #include <KLocalizedString>
0017 #include <KMessageBox>
0018 #include <QInputDialog>
0019 #include <QStandardPaths>
0020 
0021 #include "compoundregexp.h"
0022 #include "widgetfactory.h"
0023 
0024 UserDefinedRegExps::UserDefinedRegExps(QWidget *parent, const QString &title)
0025     : QDockWidget(title, parent)
0026 {
0027     QWidget *top = new QWidget(this);
0028     QVBoxLayout *lay = new QVBoxLayout(top);
0029     lay->setContentsMargins(0, 0, 0, 0);
0030 
0031     // QLabel* label = new QLabel( i18n("Compound regular expression:"), top );
0032 
0033     // This is to avoid that the label set the minimum width for the window.
0034     // label->setMinimumSize(1,0);
0035     // lay->addWidget(label);
0036 
0037     _userDefined = new QTreeWidget(top /*, "UserDefinedRegExps::_userDefined"*/);
0038     //_userDefined->addColumn( QString() );
0039     _userDefined->header()->hide();
0040     _userDefined->setRootIsDecorated(true);
0041     _userDefined->setContextMenuPolicy(Qt::CustomContextMenu);
0042     lay->addWidget(_userDefined);
0043     setWidget(top);
0044     slotPopulateUserRegexps();
0045 
0046     connect(_userDefined, &QTreeWidget::itemClicked, this, &UserDefinedRegExps::slotLoad);
0047     connect(_userDefined, &QWidget::customContextMenuRequested, this, &UserDefinedRegExps::slotContextMenuTriggered);
0048 }
0049 
0050 void UserDefinedRegExps::slotPopulateUserRegexps()
0051 {
0052     _userDefined->clear();
0053     _regExps.clear();
0054 
0055     createItems(i18n("User Defined"), WidgetWinItem::path(), true);
0056 
0057     const QStringList dirs =
0058         QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("kregexpeditor/predefined/"), QStandardPaths::LocateDirectory);
0059 
0060     for (QStringList::ConstIterator it1 = dirs.constBegin(); it1 != dirs.constEnd(); ++it1) {
0061         QDir dir(*it1, QString(), QDir::Name, QDir::Dirs);
0062         QStringList subdirs = dir.entryList();
0063         for (QStringList::iterator it2 = subdirs.begin(); it2 != subdirs.end(); ++it2) {
0064             if (*it2 == QStringLiteral(".") || *it2 == QStringLiteral("..")) {
0065                 continue;
0066             }
0067             createItems(*it2, *it1 + QLatin1Char('/') + *it2, false);
0068         }
0069     }
0070 }
0071 
0072 void UserDefinedRegExps::createItems(const QString &_title, const QString &dir, bool usersRegExp)
0073 {
0074     QString title = _title;
0075     if (_title == QLatin1String("general")) {
0076         title = i18n("general");
0077     }
0078 
0079     QTreeWidgetItem *lvItem = new QTreeWidgetItem((QTreeWidget *)nullptr, QStringList(title));
0080     lvItem->setExpanded(true);
0081     _userDefined->addTopLevelItem(lvItem);
0082 
0083     QDir directory(dir);
0084     QStringList files = directory.entryList(QStringList(QStringLiteral("*.regexp")));
0085     for (QStringList::Iterator it = files.begin(), total = files.end(); it != total; ++it) {
0086         const QString fileName = dir + QLatin1Char('/') + *it;
0087 
0088         QFile file(fileName);
0089         if (!file.open(QIODevice::ReadOnly)) {
0090             KMessageBox::error(this, i18n("Could not open file for reading: %1", fileName));
0091             continue;
0092         }
0093 
0094         QTextStream stream(&file);
0095         QString data = stream.readAll();
0096         file.close();
0097 
0098         RegExp *regexp = WidgetFactory::createRegExp(data);
0099         if (!regexp) {
0100             KMessageBox::error(this, i18n("File %1 containing user defined regular expression contained an error", fileName));
0101             continue;
0102         }
0103 
0104         new WidgetWinItem(*it, regexp, usersRegExp, lvItem);
0105 
0106         // Inserth the regexp into the list of compound regexps
0107         if (regexp->type() == RegExp::COMPOUND) {
0108             CompoundRegExp *cregexp = dynamic_cast<CompoundRegExp *>(regexp);
0109             if (cregexp && cregexp->allowReplace()) {
0110                 _regExps.append(cregexp);
0111             }
0112         }
0113     }
0114 }
0115 
0116 const QList<CompoundRegExp *> UserDefinedRegExps::regExps() const
0117 {
0118     return _regExps;
0119 }
0120 
0121 void UserDefinedRegExps::slotUnSelect()
0122 {
0123     _userDefined->clearSelection();
0124 }
0125 
0126 void UserDefinedRegExps::slotLoad(QTreeWidgetItem *item)
0127 {
0128     if (!item || !dynamic_cast<WidgetWinItem *>(item)) {
0129         // Mouse pressed outside a widget.
0130         return;
0131     }
0132 
0133     WidgetWinItem *wwi = dynamic_cast<WidgetWinItem *>(item);
0134     if (wwi) {
0135         Q_EMIT load(wwi->regExp());
0136     }
0137 }
0138 
0139 void UserDefinedRegExps::slotContextMenuTriggered(const QPoint &pos)
0140 {
0141     QMenu menu;
0142     QAction *deleteAction = menu.addAction(i18n("Delete"), this, &UserDefinedRegExps::slotDeleteUserRegexp);
0143     QAction *renameAction = menu.addAction(i18n("Rename"), this, &UserDefinedRegExps::slotRenameUserRegexp);
0144 
0145     QTreeWidgetItem *item = _userDefined->itemAt(pos);
0146 
0147     if (!item || !dynamic_cast<WidgetWinItem *>(item)) {
0148         // menu not selected on an item
0149         deleteAction->setEnabled(false);
0150         renameAction->setEnabled(false);
0151     } else {
0152         // Only allow rename and delete of users own regexps.
0153         WidgetWinItem *winItem = dynamic_cast<WidgetWinItem *>(item);
0154         if (winItem) {
0155             if (!winItem->isUsersRegExp()) {
0156                 deleteAction->setEnabled(false);
0157                 renameAction->setEnabled(false);
0158             } else {
0159                 QVariant var = QVariant::fromValue<void *>((void *)(winItem));
0160                 deleteAction->setData(var);
0161                 renameAction->setData(var);
0162             }
0163         }
0164     }
0165 
0166     menu.exec(_userDefined->mapToGlobal(pos));
0167 }
0168 
0169 void UserDefinedRegExps::slotSelectNewAction()
0170 {
0171     slotUnSelect();
0172 }
0173 
0174 void UserDefinedRegExps::slotRenameUserRegexp()
0175 {
0176     QAction *const action = qobject_cast<QAction *>(sender());
0177     Q_ASSERT(action);
0178 
0179     WidgetWinItem *winItem = static_cast<WidgetWinItem *>(action->data().value<void *>());
0180     Q_ASSERT(winItem);
0181 
0182     QString oldName = winItem->name();
0183 
0184     QString txt = QInputDialog::getText(this, i18n("Rename Item"), i18n("New name:"), QLineEdit::Normal, oldName);
0185 
0186     if (!txt.isNull() && oldName != txt) {
0187         const QString fileName = WidgetWinItem::path() + QLatin1Char('/') + txt + QStringLiteral(".regexp");
0188         QFileInfo finfo(fileName);
0189         if (finfo.exists()) {
0190             int answer = KMessageBox::warningTwoActions(this,
0191                                                         i18n("<p>Overwrite named regular expression <b>%1</b>?</p>", txt),
0192                                                         QString(),
0193                                                         KStandardGuiItem::overwrite(),
0194                                                         KGuiItem(i18n("Do Not Overwrite")));
0195             if (answer != KMessageBox::PrimaryAction) {
0196                 return;
0197             }
0198 
0199             // An item with this name already exists.
0200             delete winItem;
0201         } else {
0202             winItem->setName(txt);
0203         }
0204         QDir dir;
0205         dir.remove(fileName);
0206     }
0207 }
0208 
0209 void UserDefinedRegExps::slotDeleteUserRegexp()
0210 {
0211     QAction *const action = qobject_cast<QAction *>(sender());
0212     Q_ASSERT(action);
0213 
0214     WidgetWinItem *winItem = static_cast<WidgetWinItem *>(action->data().value<void *>());
0215     Q_ASSERT(winItem);
0216 
0217     QFile file(winItem->fileName());
0218     Q_ASSERT(file.exists());
0219 
0220     file.remove();
0221     delete winItem;
0222 }
0223 
0224 WidgetWinItem::WidgetWinItem(const QString &fileName, RegExp *regexp, bool usersRegExp, QTreeWidgetItem *parent)
0225     : QTreeWidgetItem(parent)
0226     , _regexp(regexp)
0227     , _usersRegExp(usersRegExp)
0228 {
0229     int index = fileName.lastIndexOf(QLatin1String(".regexp"));
0230     _name = fileName.left(index);
0231 
0232     setText(0, _name);
0233 }
0234 
0235 WidgetWinItem::~WidgetWinItem()
0236 {
0237     delete _regexp;
0238 }
0239 
0240 QString WidgetWinItem::fileName() const
0241 {
0242     return path() + QLatin1Char('/') + _name + QStringLiteral(".regexp");
0243 }
0244 
0245 RegExp *WidgetWinItem::regExp() const
0246 {
0247     return _regexp;
0248 }
0249 
0250 QString WidgetWinItem::name() const
0251 {
0252     return _name;
0253 }
0254 
0255 void WidgetWinItem::setName(const QString &nm)
0256 {
0257     _name = nm;
0258     setText(0, nm);
0259 }
0260 
0261 QString WidgetWinItem::path()
0262 {
0263     const QString regexppath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + QStringLiteral("KRegExpEditor/");
0264     QDir().mkpath(regexppath);
0265     return regexppath;
0266 }
0267 
0268 #include "moc_userdefinedregexps.cpp"